|
|
<template>
|
|
|
<div class="app-container">
|
|
|
<div
|
|
|
style="display: flex; justify-content: space-between; align-items: center"
|
|
|
>
|
|
|
<span>当前登录人:{{ user.name }} </span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="allowAuth ? 16 : 24">
|
|
|
<el-card v-if="allowAuth" class="box-card" style="margin: 20px 0">
|
|
|
<div slot="header" class="clearfix">
|
|
|
<span>预算总体执行情况</span>
|
|
|
<DatePicker
|
|
|
:value="select.year"
|
|
|
placeholder="选择所属年份"
|
|
|
placement="bottom"
|
|
|
style="width: 130px; float: right"
|
|
|
type="year"
|
|
|
@on-change="changeYear"
|
|
|
></DatePicker>
|
|
|
</div>
|
|
|
<router-link :to="`/statisticalReport/budgetProgress`">
|
|
|
<div class="progress-card">
|
|
|
<div class="progress-card-item">
|
|
|
<div class="progress-card-item__num">
|
|
|
{{
|
|
|
moneyFormat(
|
|
|
statistic.progress ? statistic.progress.money_total_1 : 0
|
|
|
)
|
|
|
}}
|
|
|
</div>
|
|
|
<div class="progress-card-item__label">年初预算合计金额</div>
|
|
|
</div>
|
|
|
<div class="progress-card-item">
|
|
|
<div class="progress-card-item__num">
|
|
|
{{
|
|
|
moneyFormat(
|
|
|
statistic.progress ? statistic.progress.money_total_2 : 0
|
|
|
)
|
|
|
}}
|
|
|
</div>
|
|
|
<div class="progress-card-item__label">调整后预算合计金额</div>
|
|
|
</div>
|
|
|
<div class="progress-card-item">
|
|
|
<div class="progress-card-item__num">
|
|
|
{{
|
|
|
moneyFormat(
|
|
|
statistic.progress
|
|
|
? statistic.progress.use_money_total
|
|
|
: 0
|
|
|
)
|
|
|
}}
|
|
|
</div>
|
|
|
<div class="progress-card-item__label">已支付金额</div>
|
|
|
</div>
|
|
|
<div class="progress-card-item">
|
|
|
<div class="progress-card-item__num">
|
|
|
{{
|
|
|
toper(
|
|
|
statistic.progress ? statistic.progress.money_total_1 : 0,
|
|
|
statistic.progress ? statistic.progress.money_total_2 : 0,
|
|
|
statistic.progress
|
|
|
? statistic.progress.use_money_total
|
|
|
: 0
|
|
|
)
|
|
|
}}%
|
|
|
</div>
|
|
|
<div class="progress-card-item__label">执行率</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</router-link>
|
|
|
</el-card>
|
|
|
|
|
|
<div ref="lxHeader">
|
|
|
<LxHeader
|
|
|
icon="iconfont/icon--kucunguanli"
|
|
|
text="待办事项"
|
|
|
:custom="true"
|
|
|
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
|
|
|
>
|
|
|
<div slot="content" />
|
|
|
<slot>
|
|
|
<div></div>
|
|
|
</slot>
|
|
|
</LxHeader>
|
|
|
</div>
|
|
|
<div class="table-tree">
|
|
|
<el-table
|
|
|
:data="list"
|
|
|
border
|
|
|
class="v-table"
|
|
|
style="width: 100%; margin-bottom: 20px"
|
|
|
>
|
|
|
<el-table-column type="index" label="序号" align="center" />
|
|
|
<el-table-column
|
|
|
prop="type"
|
|
|
width="100"
|
|
|
label="类型"
|
|
|
align="center"
|
|
|
:formatter="typeFormatter"
|
|
|
/>
|
|
|
<el-table-column prop="content" label="内容" align="left" />
|
|
|
<el-table-column
|
|
|
prop="created_at"
|
|
|
width="200"
|
|
|
label="下发时间"
|
|
|
align="center"
|
|
|
:formatter="timeFormatter"
|
|
|
/>
|
|
|
<el-table-column
|
|
|
width="100"
|
|
|
label="状态"
|
|
|
align="center"
|
|
|
prop="read_count"
|
|
|
>
|
|
|
<template slot-scope="{ row, $index }">
|
|
|
<el-link v-if="row.read_count" type="success" :underline="false"
|
|
|
>已读</el-link
|
|
|
>
|
|
|
<Button
|
|
|
v-else
|
|
|
type="error"
|
|
|
size="small"
|
|
|
style="margin-left: 10px"
|
|
|
ghost
|
|
|
@click="readIt(row, $index)"
|
|
|
>未读</Button
|
|
|
>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
width="90"
|
|
|
header-align="center"
|
|
|
label="操作"
|
|
|
align="center"
|
|
|
>
|
|
|
<template slot-scope="{ row, $index }">
|
|
|
<Button
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
style="margin-left: 10px"
|
|
|
ghost
|
|
|
@click="toContract(row)"
|
|
|
>查看</Button
|
|
|
>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
<div style="display: flex; justify-content: flex-end">
|
|
|
<Page :total="total" show-elevator @on-change="pageChange" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
<el-col v-if="allowAuth" :span="authShowStatic ? 7 : 8">
|
|
|
<el-card class="box-card" style="margin: 20px 0">
|
|
|
<div class="text item">
|
|
|
<pie-chart :chartData="rptChartData"></pie-chart>
|
|
|
</div>
|
|
|
</el-card>
|
|
|
</el-col>
|
|
|
|
|
|
<el-col :span="1" v-if="authShowStatic">
|
|
|
<div style="display: flex;flex-direction: column;height: 310px;padding-top: 20px;">
|
|
|
<div class="show-static-btn" @click="$refs['budgetStatic'].show()">
|
|
|
统计查看
|
|
|
<i class="el-icon-d-arrow-left"></i>
|
|
|
</div>
|
|
|
<div class="show-static-btn"
|
|
|
@click="$confirm('选择统计的数据类型','提示',{
|
|
|
confirmButtonText: '预算类型',
|
|
|
cancelButtonText: '部门科室',
|
|
|
showClose: false,
|
|
|
callback:(action, instance) => {
|
|
|
if (action === 'cancel') {
|
|
|
$refs['carryStatic'].setType(1)
|
|
|
$refs['carryStatic'].show()
|
|
|
}
|
|
|
if (action === 'confirm') {
|
|
|
$refs['carryStatic'].setType(2)
|
|
|
$refs['carryStatic'].show()
|
|
|
}
|
|
|
}
|
|
|
})">
|
|
|
执行统计
|
|
|
<i class="el-icon-d-arrow-left"></i>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
|
|
|
<div class="demo-split" v-if="allowAuth">
|
|
|
<Split v-model="split" style="height: 570px">
|
|
|
<template #left>
|
|
|
<div class="demo-split-pane" style="padding-right: 5px">
|
|
|
<div ref="lxHeader" v-if="statistic.departmentList">
|
|
|
<LxHeader
|
|
|
icon="iconfont/icon--kucunguanli"
|
|
|
text="科室执行情况"
|
|
|
:custom="true"
|
|
|
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
|
|
|
>
|
|
|
<div slot="content" />
|
|
|
<slot>
|
|
|
<div style="width: 100%">
|
|
|
<xy-table
|
|
|
:height="488"
|
|
|
:list="statistic.departmentList"
|
|
|
:table-item="departmentTable"
|
|
|
>
|
|
|
<template v-slot:btns>
|
|
|
<el-table-column
|
|
|
:width="80"
|
|
|
fixed="right"
|
|
|
label="操作"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
>
|
|
|
<template slot-scope="scope">
|
|
|
<router-link
|
|
|
:to="`/contract/statisticalReport/budgetProgress?departmentId=${scope.row.plan_department_id}`"
|
|
|
>查看
|
|
|
</router-link>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</template>
|
|
|
</xy-table>
|
|
|
</div>
|
|
|
</slot>
|
|
|
</LxHeader>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<template #right>
|
|
|
<div class="demo-split-pane" style="padding-left: 10px">
|
|
|
<div ref="lxHeader" v-if="statistic.typeList">
|
|
|
<LxHeader
|
|
|
icon="iconfont/icon--kucunguanli"
|
|
|
text="预算类型执行情况"
|
|
|
:custom="true"
|
|
|
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
|
|
|
>
|
|
|
<div slot="content" />
|
|
|
<slot>
|
|
|
<div style="width: 100%">
|
|
|
<xy-table
|
|
|
:height="488"
|
|
|
:list="statistic.typeList"
|
|
|
:table-item="typeTable"
|
|
|
>
|
|
|
<template v-slot:btns>
|
|
|
<el-table-column
|
|
|
:width="80"
|
|
|
fixed="right"
|
|
|
label="操作"
|
|
|
header-align="center"
|
|
|
align="center"
|
|
|
>
|
|
|
<template slot-scope="scope">
|
|
|
<router-link
|
|
|
:to="`/contract/statisticalReport/budgetProgress?typeId=${scope.row.type}`"
|
|
|
>查看
|
|
|
</router-link>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</template>
|
|
|
</xy-table>
|
|
|
</div>
|
|
|
</slot>
|
|
|
</LxHeader>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</Split>
|
|
|
</div>
|
|
|
|
|
|
<Card v-if="allowAuth">
|
|
|
<template #title>
|
|
|
<div style="display: flex;justify-content: space-between;align-items: center;">
|
|
|
<p>各科室预算计划完成对比图</p>
|
|
|
<el-date-picker v-model="carrySelect.month"
|
|
|
format="yyyy-MM"
|
|
|
:clearable="false"
|
|
|
style="width: 140px;"
|
|
|
placeholder="月份"
|
|
|
type="month"
|
|
|
size="small"
|
|
|
@change="e => {
|
|
|
carrySelect.month = $moment(e).format('YYYY-MM');
|
|
|
getCarry();
|
|
|
}"></el-date-picker>
|
|
|
</div>
|
|
|
</template>
|
|
|
<lineChart height="500px" :chart-data="lineChartData"></lineChart>
|
|
|
</Card>
|
|
|
|
|
|
<detailContract ref="detailContract"></detailContract>
|
|
|
|
|
|
<budgetStatic ref="budgetStatic"></budgetStatic>
|
|
|
|
|
|
<carryStatic ref="carryStatic" :departments="statistic.departmentList" :year="select.year"></carryStatic>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import echarts from 'echarts'
|
|
|
import detailContract from "@/views/contract/components/detailContract";
|
|
|
import LxHeader from "@/components/LxHeader/index.vue";
|
|
|
import Pagination from "@/components/Pagination";
|
|
|
import PieChart from "./components/PieChart.vue";
|
|
|
import { adminDepartmentList } from '@/api/system/department';
|
|
|
import { adminUserList, getInfo } from '@/api/user';
|
|
|
import { getNotice, readNotice, statistic, carry } from "@/api/dashboard/notice";
|
|
|
import { parseTime, moneyFormatter } from '@/utils';
|
|
|
import { Message } from "element-ui";
|
|
|
import budgetStatic from '@/views/dashboard/components/budgetStatic.vue'
|
|
|
import lineChart from '@/views/dashboard/components/LineChart.vue'
|
|
|
import carryStatic from '@/views/dashboard/components/carryStatic.vue'
|
|
|
export default {
|
|
|
name: "Manage",
|
|
|
components: {
|
|
|
LxHeader,
|
|
|
Pagination,
|
|
|
detailContract,
|
|
|
PieChart,
|
|
|
budgetStatic,
|
|
|
lineChart,
|
|
|
carryStatic
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
value2: 12,
|
|
|
split: 0.5,
|
|
|
rptChartData: [],
|
|
|
select: {
|
|
|
year: "",
|
|
|
},
|
|
|
carrySelect: {
|
|
|
month: this.$moment().format('YYYY-MM')
|
|
|
},
|
|
|
lineChartData: {},
|
|
|
statistic: {
|
|
|
departmentList: []
|
|
|
},
|
|
|
department_id: [],
|
|
|
userIds: [],
|
|
|
list: [],
|
|
|
total: 0,
|
|
|
pageIndex: 1,
|
|
|
// listQuery: {
|
|
|
// page: 1,
|
|
|
// page_size: 10,
|
|
|
// show_self: 1,
|
|
|
// },
|
|
|
form: {
|
|
|
id: undefined,
|
|
|
},
|
|
|
dialogFormVisible: false,
|
|
|
departmentTree: [],
|
|
|
userList: [],
|
|
|
formLabelWidth: "200px",
|
|
|
user: {},
|
|
|
|
|
|
departmentProgress: [],
|
|
|
departmentTable: [
|
|
|
{
|
|
|
label: "科室",
|
|
|
minWidth: 180,
|
|
|
prop: "plan_department.name",
|
|
|
sortable: false,
|
|
|
align: "left",
|
|
|
fixed: "left",
|
|
|
},
|
|
|
{
|
|
|
label: "执行情况",
|
|
|
sortable: false,
|
|
|
minWidth: 220,
|
|
|
align: "left",
|
|
|
fixed: "right",
|
|
|
customFn: (row) => {
|
|
|
let m2 = row?.money_total_2;
|
|
|
let m1 = row?.money_total_1;
|
|
|
let m3 = row?.use_money_total;
|
|
|
let per = 0;
|
|
|
|
|
|
if (m2 != 0) {
|
|
|
per = ((m3 / m2) * 100).toFixed(2);
|
|
|
} else if (m1 != 0) {
|
|
|
per = ((m3 / m1) * 100).toFixed(2);
|
|
|
}
|
|
|
return (
|
|
|
<div>
|
|
|
<el-progress percentage={Number(per)}> </el-progress>{" "}
|
|
|
</div>
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "年初预算合计金额(元)",
|
|
|
width: 260,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "money_total_1",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "调整后预算合计金额(元)",
|
|
|
width: 260,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "money_total_2",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "年中专项资金(元)",
|
|
|
width: 260,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "middle_fund_total",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "已使用(元)",
|
|
|
width: 120,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "use_money_total",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
typeTable: [
|
|
|
{
|
|
|
label: "预算类别",
|
|
|
width: 100,
|
|
|
prop: "type_text",
|
|
|
sortable: false,
|
|
|
fixed: "left",
|
|
|
},
|
|
|
{
|
|
|
label: "执行情况",
|
|
|
sortable: false,
|
|
|
minWidth: 220,
|
|
|
align: "left",
|
|
|
fixed: "right",
|
|
|
customFn: (row) => {
|
|
|
let m2 = row.money_total_2;
|
|
|
let m1 = row.money_total_1;
|
|
|
let m3 = row.use_money_total;
|
|
|
let per = 0;
|
|
|
|
|
|
if (m2 != 0) {
|
|
|
per = ((m3 / m2) * 100).toFixed(2);
|
|
|
} else if (m1 != 0) {
|
|
|
per = ((m3 / m1) * 100).toFixed(2);
|
|
|
}
|
|
|
return (
|
|
|
<div>
|
|
|
<el-progress percentage={Number(per)}> </el-progress>{" "}
|
|
|
</div>
|
|
|
);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "年初预算合计金额(元)",
|
|
|
width: 260,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "money_total_1",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "调整后预算合计金额(元)",
|
|
|
width: 260,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "money_total_2",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
label: "已使用(元)",
|
|
|
width: 140,
|
|
|
align: "right",
|
|
|
sortable: false,
|
|
|
prop: "use_money_total",
|
|
|
formatter: (cell, data, value) => {
|
|
|
return moneyFormatter(value);
|
|
|
},
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
},
|
|
|
created() {
|
|
|
this.select.year = this.$moment().format("YYYY");
|
|
|
this.getNotices();
|
|
|
|
|
|
this.getStatistic();
|
|
|
this.getCarry();
|
|
|
|
|
|
getInfo()
|
|
|
.then((response) => {
|
|
|
console.log(response);
|
|
|
this.user = response;
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
},
|
|
|
methods: {
|
|
|
async getCarry () {
|
|
|
const res = await carry(this.carrySelect);
|
|
|
|
|
|
//组织数据
|
|
|
let setData = function(data, constData, showData) {
|
|
|
data.filter(function(item) {
|
|
|
if (item) {
|
|
|
constData.push(1);
|
|
|
showData.push(item);
|
|
|
} else {
|
|
|
constData.push(0);
|
|
|
showData.push({
|
|
|
value: 1,
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
borderColor: "rgba(0,0,0,0)",
|
|
|
borderWidth: 2,
|
|
|
color: "rgba(0,0,0,0)",
|
|
|
},
|
|
|
},
|
|
|
});
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
//组织颜色
|
|
|
let setColor = function(colorArr) {
|
|
|
let color = {
|
|
|
type: "linear",
|
|
|
x: 0,
|
|
|
x2: 1,
|
|
|
y: 0,
|
|
|
y2: 0,
|
|
|
/* 此处决定阴暗面 若为横向柱状图则x,y轴调换
|
|
|
x: 0,
|
|
|
x2: 0,
|
|
|
y: 0,
|
|
|
y2: 1, */
|
|
|
colorStops: [{
|
|
|
offset: 0,
|
|
|
color: colorArr[0],
|
|
|
},
|
|
|
{
|
|
|
offset: 0.5,
|
|
|
color: colorArr[0],
|
|
|
},
|
|
|
{
|
|
|
offset: 0.5,
|
|
|
color: colorArr[1],
|
|
|
},
|
|
|
{
|
|
|
offset: 1,
|
|
|
color: colorArr[1],
|
|
|
},
|
|
|
],
|
|
|
};
|
|
|
return color
|
|
|
}
|
|
|
|
|
|
// let curPlan = res?.map(i => {
|
|
|
// const { use_money_total,paid_plan_total,money_total_2 } = i
|
|
|
// return paid_plan_total ? (Math.round((Number(paid_plan_total||0) / Number(money_total_2 ||0)) * 10000) / 100) :
|
|
|
// 0;
|
|
|
// });
|
|
|
// let curAct = res?.map(i => {
|
|
|
// const { use_money_total,money_total_2 } = i
|
|
|
// return Number(money_total_2) ? (Math.round((Number(use_money_total||0) / Number(money_total_2||0)) * 10000) / 100) :
|
|
|
// 0;
|
|
|
// });
|
|
|
// let nextPlan = res?.map(i => {
|
|
|
// const { use_money_total_next,paid_plan_total_next,money_total_2 } = i
|
|
|
// return paid_plan_total_next ? (Math.round((Number(paid_plan_total_next||0) / Number(money_total_2||0)) * 10000) / 100) :
|
|
|
// 0;
|
|
|
// });
|
|
|
let curPlan = res?.map(i => {
|
|
|
const { use_money_total,paid_plan_total,money_total_2,money_total_1 } = i
|
|
|
let curPlan_total = Math.round(Number(paid_plan_total||0)) + Math.round(Number(use_money_total||0))
|
|
|
return {
|
|
|
value:Number(money_total_2) ? ((( curPlan_total / Number(money_total_2 ||0)) * 10000) / 100).toFixed(2) :
|
|
|
((( curPlan_total / Number(money_total_1 ||0)) * 10000) / 100).toFixed(2),
|
|
|
money:paid_plan_total
|
|
|
}
|
|
|
});
|
|
|
|
|
|
let curAct = res?.map(i => {
|
|
|
const { use_money_total,money_total_2,money_total_1 } = i
|
|
|
return {
|
|
|
value:Number(money_total_2) ? (Math.round((Number(use_money_total||0) / Number(money_total_2||0)) * 10000) / 100).toFixed(2) :
|
|
|
(Math.round((Number(use_money_total||0) / Number(money_total_1||0)) * 10000) / 100).toFixed(2),
|
|
|
money:use_money_total
|
|
|
}
|
|
|
});
|
|
|
|
|
|
let nextPlan = res?.map(i => {
|
|
|
const { use_money_total,use_money_total_next,paid_plan_total_next,money_total_2,money_total_1 } = i
|
|
|
if(Number(paid_plan_total_next)===0){
|
|
|
return 0
|
|
|
}
|
|
|
let nextPlan_total = Math.round(Number(paid_plan_total_next||0)) + Math.round(Number(use_money_total||0))
|
|
|
return {
|
|
|
value:Number(money_total_2) ? (((nextPlan_total / Number(money_total_2||0)) * 10000) / 100).toFixed(2) :
|
|
|
(((nextPlan_total / Number(money_total_1||0)) * 10000) / 100).toFixed(2),
|
|
|
money:paid_plan_total_next
|
|
|
}
|
|
|
});
|
|
|
|
|
|
let barWidth = 23;
|
|
|
let constData1 = [];
|
|
|
let showData1 = [];
|
|
|
let constData2 = [];
|
|
|
let showData2 = [];
|
|
|
let constData3 = [];
|
|
|
let showData3 = [];
|
|
|
|
|
|
setData(curPlan, constData1, showData1)
|
|
|
setData(curAct, constData2, showData2)
|
|
|
setData(nextPlan, constData3, showData3)
|
|
|
|
|
|
let colorArr1 = ["#345A8B", "#387ABD", "#398ac4"];
|
|
|
let colorArr2 = ["#51C0DB", "#42D9D6", "#45F5F1"];
|
|
|
let colorArr3 = ['#559372','#7ab798','#9edebc']
|
|
|
let spanColor = ["#345A8B","#51C0DB",'#559372']
|
|
|
|
|
|
let color1 = setColor(colorArr1)
|
|
|
let color2 = setColor(colorArr2)
|
|
|
let color3 = setColor(colorArr3)
|
|
|
|
|
|
this.lineChartData = {
|
|
|
rotate: 54,
|
|
|
xArr: res?.map(i => i.plan_department?.name),
|
|
|
tooltip: {
|
|
|
show:true,
|
|
|
trigger: 'axis', // 触发方式为鼠标悬浮在图形上
|
|
|
formatter: function (params) {
|
|
|
// 自定义悬浮窗的内容和样式
|
|
|
let result = `<div style=" padding: 10px;">`;
|
|
|
// 获取当前悬浮的部门名称
|
|
|
const departmentName = params[0].name;
|
|
|
result += `<div style="font-weight: bold; margin-bottom: 5px;">${departmentName}</div>`;
|
|
|
|
|
|
// 遍历所有参数,找到三个主要柱状图的数据
|
|
|
params.forEach((param,index) => {
|
|
|
// 只处理主要的柱状图数据(z值为1、4、7的系列)
|
|
|
result += `<div style="margin: 3px 0;">
|
|
|
<span style="display: inline-block; width: 10px; height: 10px; background-color: ${spanColor[index]}; margin-right: 5px;"></span>
|
|
|
<span>${param.seriesName}: ${param.value}%-${param.data.money?param.data.money+'元':0+'元'}</span>
|
|
|
</div>`;
|
|
|
});
|
|
|
result += `</div>`;
|
|
|
return result
|
|
|
}
|
|
|
},
|
|
|
series: [
|
|
|
{
|
|
|
z: 1,
|
|
|
type: 'bar',
|
|
|
barWidth: barWidth,
|
|
|
name: `${this.carrySelect.month}计划`,
|
|
|
barGap: "54%", //相邻柱子间距
|
|
|
itemStyle: {
|
|
|
borderRadius: [0, 0, 0, 0],//柱子四周圆角
|
|
|
color: color1//柱子左右颜色(深,浅)
|
|
|
},
|
|
|
data: curPlan, //Y轴上的高度
|
|
|
label: {
|
|
|
show: true,
|
|
|
position: 'top',
|
|
|
textStyle: {//数值样式
|
|
|
fontSize: 12,
|
|
|
color: '#4d8bdc',
|
|
|
},
|
|
|
formatter: params => `${params.value}%`
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 2,
|
|
|
name: `${this.carrySelect.month}计划`,
|
|
|
type: "pictorialBar",
|
|
|
data: constData1,//此数据对应底部组件
|
|
|
symbol: "diamond",//底部组件形状,不写默认为椭圆
|
|
|
symbolOffset: ["-154%", "50%"],//与柱子的偏移角度
|
|
|
symbolSize: [barWidth, 10],//底面[宽,高]
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
color: color1//底面左右颜色(深,浅)
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 3,
|
|
|
name: `${this.carrySelect.month}计划`,
|
|
|
type: "pictorialBar",
|
|
|
symbolPosition: "end",
|
|
|
data: showData1,//此数据对应顶部组件
|
|
|
symbol: "diamond",
|
|
|
symbolOffset: ["-184%", "-50%"],
|
|
|
symbolSize: [barWidth - 4, (10 * (barWidth - 4)) / barWidth],
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
borderColor: colorArr1[2],
|
|
|
borderWidth: 2,
|
|
|
color: colorArr1[2],
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 4,
|
|
|
type: 'bar',
|
|
|
barWidth: barWidth,
|
|
|
name: `${this.carrySelect.month}实际`,
|
|
|
itemStyle: {
|
|
|
borderRadius: [0, 0, 0, 0],
|
|
|
color: color2
|
|
|
},
|
|
|
data: curAct,
|
|
|
label: {
|
|
|
offset:[0,-15],
|
|
|
show: true,
|
|
|
position: 'top',
|
|
|
textStyle: {//数值样式
|
|
|
fontSize: 12,
|
|
|
// color: 'red',
|
|
|
},
|
|
|
formatter: params => `${params.value}%`
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
z: 5,
|
|
|
name: `${this.carrySelect.month}实际`,
|
|
|
type: "pictorialBar",
|
|
|
data: constData2,
|
|
|
symbol: "diamond",
|
|
|
symbolOffset: ["0%", "50%"],
|
|
|
symbolSize: [barWidth, 10], //=========================
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
color: color2
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 6,
|
|
|
name: `${this.carrySelect.month}实际`,
|
|
|
type: "pictorialBar",
|
|
|
symbolPosition: "end",
|
|
|
data: showData2,
|
|
|
symbol: "diamond",
|
|
|
symbolOffset: ["0%", "-50%"],
|
|
|
symbolSize: [barWidth - 4, (10 * (barWidth - 4)) / barWidth],
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
borderColor: colorArr2[2],
|
|
|
borderWidth: 2,
|
|
|
color: colorArr2[2]
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 7,
|
|
|
type: 'bar',
|
|
|
barWidth: barWidth,
|
|
|
name: `${this.$moment(this.carrySelect.month).add(1,'months').format('YYYY-MM')}计划`,
|
|
|
itemStyle: {
|
|
|
borderRadius: [0, 0, 0, 0],
|
|
|
color: color3
|
|
|
},
|
|
|
data: nextPlan,
|
|
|
label: {
|
|
|
show: true,
|
|
|
position: 'top',
|
|
|
textStyle: {//数值样式
|
|
|
fontSize: 12,
|
|
|
color: '#4d8bdc',
|
|
|
},
|
|
|
formatter: params => `${params.value}%`
|
|
|
}
|
|
|
},
|
|
|
{
|
|
|
z: 8,
|
|
|
name: `${this.$moment(this.carrySelect.month).add(1,'months').format('YYYY-MM')}计划`,
|
|
|
type: "pictorialBar",
|
|
|
data: constData3,
|
|
|
symbol: "diamond",
|
|
|
symbolOffset: ["154%", "50%"],
|
|
|
symbolSize: [barWidth, 10],
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
color: color3
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
z: 9,
|
|
|
name: `${this.$moment(this.carrySelect.month).add(1,'months').format('YYYY-MM')}计划`,
|
|
|
type: "pictorialBar",
|
|
|
symbolPosition: "end",
|
|
|
data: showData3,
|
|
|
symbol: "diamond",
|
|
|
symbolOffset: ["191%", "-50%"],
|
|
|
symbolSize: [barWidth - 4, (10 * (barWidth - 4)) / barWidth],
|
|
|
itemStyle: {
|
|
|
normal: {
|
|
|
borderColor: colorArr3[2],
|
|
|
borderWidth: 2,
|
|
|
color: colorArr3[2]
|
|
|
},
|
|
|
},
|
|
|
tooltip: {
|
|
|
show: false,
|
|
|
},
|
|
|
}
|
|
|
]
|
|
|
};
|
|
|
},
|
|
|
|
|
|
changeYear(e) {
|
|
|
this.select.year = e;
|
|
|
this.getStatistic();
|
|
|
},
|
|
|
async getStatistic() {
|
|
|
const res = await statistic(this.select);
|
|
|
console.log(res);
|
|
|
this.statistic = res;
|
|
|
let m2 = res.progress.money_total_2;
|
|
|
let m1 = res.progress.money_total_1;
|
|
|
var user_m = res.progress.use_money_total;
|
|
|
var m3=m1-user_m
|
|
|
if (m2 != 0) {
|
|
|
m3=m2-user_m;
|
|
|
} else if (m1 != 0) {
|
|
|
m3=m1-user_m;
|
|
|
}
|
|
|
this.rptChartData = {
|
|
|
xArr: ["预算未执行金额", "预算已执行金额"],
|
|
|
radiusArr: "50%",
|
|
|
yArr: [
|
|
|
{
|
|
|
value: m3,
|
|
|
name: "预算未执行金额",
|
|
|
label: {
|
|
|
show: false, //这个数据高亮时不显示label,就不会显示替遮住第一个数据的label值了
|
|
|
},
|
|
|
emphasis: {
|
|
|
label: {
|
|
|
show: false, //这个数据高亮时不显示label,就不会显示替遮住第一个数据的label值了
|
|
|
},
|
|
|
},
|
|
|
},
|
|
|
{ value: user_m, name: "预算已执行金额" },
|
|
|
],
|
|
|
};
|
|
|
},
|
|
|
|
|
|
toContract(row) {
|
|
|
this.$refs["detailContract"].getDetail(row.contract_id);
|
|
|
this.$refs["detailContract"].isShowDetail = true;
|
|
|
},
|
|
|
|
|
|
pageChange(e) {
|
|
|
this.pageIndex = e;
|
|
|
this.getNotices();
|
|
|
},
|
|
|
|
|
|
timeFormatter(cell, data, value) {
|
|
|
return parseTime(new Date(value));
|
|
|
},
|
|
|
typeFormatter(cell, data, value) {
|
|
|
return value === 1 ? "合同流程" : "付款计划";
|
|
|
},
|
|
|
toper(m1, m2, m3) {
|
|
|
if (m2 != 0) {
|
|
|
return ((m3 / m2) * 100).toFixed(2);
|
|
|
} else if (m1 != 0) {
|
|
|
return ((m3 / m1) * 100).toFixed(2);
|
|
|
} else return 0;
|
|
|
},
|
|
|
async getNotices() {
|
|
|
const res = await getNotice({
|
|
|
page_size: 10,
|
|
|
page: this.pageIndex,
|
|
|
});
|
|
|
this.list = res.data;
|
|
|
this.total = res.total;
|
|
|
},
|
|
|
|
|
|
filterChildren(data) {
|
|
|
data.forEach((i) => {
|
|
|
if (i.children && i.children.length > 0) {
|
|
|
this.filterChildren(i.children);
|
|
|
} else {
|
|
|
delete i.children;
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
getList() {
|
|
|
index(this.listQuery)
|
|
|
.then((response) => {
|
|
|
this.list = response.data;
|
|
|
this.total = response.total;
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
},
|
|
|
handleFilter() {
|
|
|
this.listQuery.page = 1;
|
|
|
this.getList();
|
|
|
},
|
|
|
readIt(row) {
|
|
|
readNotice({
|
|
|
id: row.id,
|
|
|
}).then((res) => {
|
|
|
Message({
|
|
|
type: "success",
|
|
|
message: "已读",
|
|
|
});
|
|
|
this.getNotices();
|
|
|
});
|
|
|
// show({id: row.id}).then(r => { this.form = r }).catch(error => {})
|
|
|
// this.list[index].is_read = 1
|
|
|
},
|
|
|
save() {
|
|
|
this.$refs["dataForm"].validate((valid) => {
|
|
|
if (valid) {
|
|
|
const tempData = Object.assign({}, this.form);
|
|
|
tempData.admin_id_list = tempData.ids.map((i) => {
|
|
|
return {
|
|
|
admin_id: i,
|
|
|
};
|
|
|
});
|
|
|
if (tempData.id) {
|
|
|
save(tempData)
|
|
|
.then((r) => {
|
|
|
this.saved();
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
} else {
|
|
|
store(tempData)
|
|
|
.then((r) => {
|
|
|
this.saved();
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
saved() {
|
|
|
this.handleFilter();
|
|
|
this.dialogFormVisible = false;
|
|
|
this.$message.success("保存成功");
|
|
|
},
|
|
|
handleDelete(row, index) {
|
|
|
this.$confirm("确定要删除吗?", "提示", {
|
|
|
confirmButtonText: "确定",
|
|
|
cancelButtonText: "取消",
|
|
|
type: "warning",
|
|
|
})
|
|
|
.then(() => {
|
|
|
destroy({
|
|
|
id: row.id,
|
|
|
})
|
|
|
.then((response) => {
|
|
|
this.$message.success("删除成功");
|
|
|
this.getList();
|
|
|
})
|
|
|
.catch((error) => {});
|
|
|
})
|
|
|
.catch(() => {});
|
|
|
},
|
|
|
},
|
|
|
computed: {
|
|
|
moneyFormat () {
|
|
|
return function (price) {
|
|
|
return moneyFormatter(price);
|
|
|
};
|
|
|
},
|
|
|
allowAuth () {
|
|
|
return this.$store.state.user.min_allow_level !== 2
|
|
|
},
|
|
|
authShowStatic () {
|
|
|
return this.$store.state.user.myroles.find(i => i.name === "首页统计")
|
|
|
}
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
<style scoped lang="scss">
|
|
|
::v-deep .el-progress--line {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
}
|
|
|
::v-deep .el-progress__text {
|
|
|
word-break: keep-all;
|
|
|
}
|
|
|
.show-static-btn {
|
|
|
cursor: pointer;
|
|
|
font-size: 15px;
|
|
|
font-weight: 600;
|
|
|
text-align: center;
|
|
|
color: #fff;
|
|
|
background: #4d8bdc;
|
|
|
border-radius: 4px;
|
|
|
border: 1px solid #EBEEF5;
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
transition: all .2s;
|
|
|
flex: 1;
|
|
|
width: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
padding: 0 20px;
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
& + & {
|
|
|
background: darkorange;
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
&:hover {
|
|
|
transform: scale(1.05,1.05);
|
|
|
}
|
|
|
}
|
|
|
::v-deep .el-dialog__body {
|
|
|
padding: 8px 20px;
|
|
|
}
|
|
|
|
|
|
::v-deep .el-col-5 {
|
|
|
width: 20%;
|
|
|
}
|
|
|
|
|
|
::v-deep .el-card__body {
|
|
|
padding: 4px 10px !important;
|
|
|
}
|
|
|
|
|
|
.progress-card {
|
|
|
display: flex;
|
|
|
|
|
|
&-item {
|
|
|
text-align: center;
|
|
|
flex: 1;
|
|
|
|
|
|
&__label {
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
&__num {
|
|
|
font-size: 20px;
|
|
|
font-weight: 600;
|
|
|
|
|
|
padding: 6px 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
<style lang="scss" scoped>
|
|
|
.ivu-btn {
|
|
|
margin-right: 10px;
|
|
|
}
|
|
|
|
|
|
.table-tree {
|
|
|
margin-top: 10px;
|
|
|
}
|
|
|
|
|
|
.v-text {
|
|
|
padding: 8px 0;
|
|
|
border-bottom: 1px solid #eee;
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
.title {
|
|
|
color: #338de3;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.dataGroup {
|
|
|
padding: 10px 0;
|
|
|
}
|
|
|
|
|
|
.grid-content {
|
|
|
border-radius: 5px;
|
|
|
text-align: center;
|
|
|
background: #ffffff;
|
|
|
padding: 15px 0;
|
|
|
|
|
|
p {
|
|
|
line-height: 1.8;
|
|
|
}
|
|
|
|
|
|
p:first-child {
|
|
|
font-weight: 700;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.bg-org {
|
|
|
border: 2px solid #ef6c24;
|
|
|
color: #ef6c24;
|
|
|
}
|
|
|
|
|
|
.bg-blue {
|
|
|
border: 2px solid #0800ff;
|
|
|
color: #0800ff;
|
|
|
}
|
|
|
|
|
|
.bg-green {
|
|
|
border: 2px solid #0f9700;
|
|
|
color: #0f9700;
|
|
|
}
|
|
|
|
|
|
.bg-black {
|
|
|
border: 2px solid #333;
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.bg-pink {
|
|
|
border: 2px solid #ff0000;
|
|
|
color: #ff0000;
|
|
|
}
|
|
|
</style>
|