You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

853 lines
23 KiB

2 years ago
<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="16">
<el-card class="box-card" style="margin: 20px 0">
<div slot="header" class="clearfix">
2 years ago
<span>预算总体执行情况</span>
2 years ago
<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
)
}}
3 years ago
</div>
2 years ago
<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>
2 years ago
<div class="progress-card-item__label">执行率</div>
2 years ago
</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>
2 years ago
<el-col :span="7">
2 years ago
<el-card class="box-card" style="margin: 20px 0">
<div class="text item">
<pie-chart :chartData="rptChartData"></pie-chart>
</div>
</el-card>
</el-col>
2 years ago
<el-col :span="1">
<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>
2 years ago
</el-row>
<div class="demo-split">
<Split v-model="split" style="height: 440px">
<template #left>
<div class="demo-split-pane" style="padding-right: 5px">
<div ref="lxHeader" v-if="statistic.departmentList">
<LxHeader
icon="iconfont/icon--kucunguanli"
2 years ago
text="科室执行情况"
2 years ago
:custom="true"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content" />
<slot>
<div style="width: 100%">
<xy-table
:height="380"
: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="`/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"
2 years ago
text="预算类型执行情况"
2 years ago
:custom="true"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content" />
<slot>
<div style="width: 100%">
<xy-table
:height="380"
: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="`/statisticalReport/budgetProgress?typeId=${scope.row.type}`"
>查看
</router-link>
</template>
</el-table-column>
</template>
</xy-table>
</div>
</slot>
</LxHeader>
</div>
</div>
</template>
</Split>
</div>
2 years ago
<Card>
<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 :chart-data="lineChartData"></lineChart>
</Card>
2 years ago
<detailContract ref="detailContract"></detailContract>
2 years ago
<budgetStatic ref="budgetStatic"></budgetStatic>
2 years ago
<carryStatic ref="carryStatic" :departments="statistic.departmentList" :year="select.year"></carryStatic>
2 years ago
</div>
</template>
<script>
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";
2 years ago
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';
2 years ago
import { Message } from "element-ui";
2 years ago
import budgetStatic from '@/views/dashboard/components/budgetStatic.vue'
import lineChart from '@/views/dashboard/components/LineChart.vue'
import carryStatic from '@/views/dashboard/components/carryStatic.vue'
2 years ago
export default {
name: "Manage",
components: {
LxHeader,
Pagination,
detailContract,
PieChart,
2 years ago
budgetStatic,
lineChart,
carryStatic
2 years ago
},
data() {
return {
value2: 12,
split: 0.5,
rptChartData: [],
select: {
year: "",
},
2 years ago
carrySelect: {
month: this.$moment().format('YYYY-MM')
},
lineChartData: {},
2 years ago
statistic: {
departmentList: []
},
2 years ago
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",
},
{
2 years ago
label: "执行情况",
2 years ago
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: 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",
},
{
2 years ago
label: "执行情况",
2 years ago
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();
3 years ago
2 years ago
this.getStatistic();
2 years ago
this.getCarry();
2 years ago
getInfo()
.then((response) => {
console.log(response);
this.user = response;
})
.catch((error) => {});
},
methods: {
2 years ago
async getCarry () {
const res = await carry(this.carrySelect);
this.lineChartData = {
rotate: 54,
xArr: res?.map(i => i.plan_department?.name),
series: [
{
name: `${this.carrySelect.month}计划`,
type: 'bar',
barGap: 0,
emphasis: {
focus: 'series'
},
2 years ago
itemStyle: {
color: '#4d8bdc'
},
2 years ago
data: res?.map(i => {
const { use_money_total,money_total_1 } = i
return Math.round((Number(use_money_total||0) / Number(money_total_1||0)) * 10000) / 100
})
},
{
name: `${this.carrySelect.month}实际`,
type: 'bar',
barGap: 0,
emphasis: {
focus: 'series'
},
2 years ago
itemStyle: {
color: '#7ab384'
},
2 years ago
data: res?.map(i => {
const { use_money_total,money_total_2 } = i
return Math.round((Number(use_money_total||0) / Number(money_total_2||0)) * 10000) / 100
})
},
{
name: `${this.$moment(this.carrySelect.month).add(1,'months').format('YYYY-MM')}计划`,
type: 'bar',
barGap: 0,
emphasis: {
focus: 'series'
},
2 years ago
itemStyle: {
color: '#f7cb56'
},
2 years ago
data: res?.map(i => {
const { use_money_total_next,money_total } = i
return Math.round((Number(use_money_total_next||0) / Number(money_total||0)) * 10000) / 100
})
},
]
};
console.log(res)
},
2 years ago
changeYear(e) {
this.select.year = e;
this.getStatistic();
},
async getStatistic() {
2 years ago
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;
}
2 years ago
this.rptChartData = {
2 years ago
xArr: ["预算未执行金额", "预算已执行金额"],
2 years ago
radiusArr: "50%",
yArr: [
{
2 years ago
value: m3,
name: "预算未执行金额",
2 years ago
label: {
show: false, //这个数据高亮时不显示label就不会显示替遮住第一个数据的label值了
},
emphasis: {
label: {
show: false, //这个数据高亮时不显示label就不会显示替遮住第一个数据的label值了
},
},
3 years ago
},
2 years ago
{ value: user_m, name: "预算已执行金额" },
2 years ago
],
};
},
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;
3 years ago
}
2 years ago
});
},
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);
};
},
},
};
</script>
<style scoped lang="scss">
2 years ago
.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);
}
}
2 years ago
::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;
}
3 years ago
</style>