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.

1342 lines
40 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="app-container">
<div>当前登录人{{ user.name }}</div>
<el-card 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.money_total_1) }}
</div>
<div class="progress-card-item__label">年初预算数</div>
</div>
<div class="progress-card-item">
<div class="progress-card-item__num">
{{ moneyFormat(statistic.progress.money_total_2) }}
</div>
<div class="progress-card-item__label">调整后预算数</div>
</div>
<div class="progress-card-item">
<div class="progress-card-item__num">
{{ moneyFormat(statistic.progress.use_money_total) }}
</div>
<div class="progress-card-item__label">已支付金额</div>
</div>
<div class="progress-card-item">
<div class="progress-card-item__num">
{{
toper(
statistic.progress.money_total_1,
statistic.progress.money_total_2,
statistic.progress.use_money_total
)
}}%
</div>
<div class="progress-card-item__label">进展率</div>
</div>
</div>
</router-link>
</el-card>
<div ref="lxHeader">
<LxHeader
icon="md-apps"
text="待办事项"
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>
<div class="demo-split">
<div v-for="(sitem, index) in this.typeList">
<Split v-model="split" style="height: 580px">
<template #left>
<div class="demo-split-pane" style="padding-right: 5px">
<div ref="lxHeader" v-if="sitem[0]">
<LxHeader
icon="md-apps"
:text="sitem[0].type_text"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content">
<xy-table
:height="120"
:list="[sitem[0]]"
:table-item="typeTable"
>
<template v-slot:btns>
<el-table-column
:width="10"
fixed="right"
label="操作"
header-align="center"
align="center"
>
<template slot-scope="scope"> </template>
</el-table-column>
</template>
</xy-table>
</div>
<slot>
<div style="width: 100%">
<xy-table
:height="380"
:list="sitem[0].departments"
: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="sitem[1]">
<LxHeader
icon="md-apps"
:text="sitem[1].type_text"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content">
<xy-table
:height="120"
:list="[sitem[1]]"
:table-item="typeTable"
>
<template v-slot:btns>
<el-table-column
:width="10"
fixed="right"
label="操作"
header-align="center"
align="center"
>
<template slot-scope="scope"> </template>
</el-table-column>
</template>
</xy-table>
</div>
<slot>
<div style="width: 100%">
<xy-table
:height="380"
:list="sitem[1].departments"
: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>
</Split>
</div>
<div ref="lxHeader">
<LxHeader
icon="md-apps"
text="合同签订统计表"
style="margin-bottom: 10px; border: 0px; margin-top: 25px"
>
<div slot="content">
<xy-table
:height="300"
:list="departmentTotal"
:table-item="departmentTotalTable"
>
<template v-slot:btns> </template>
</xy-table>
</div>
<slot> </slot>
</LxHeader>
</div>
<div ref="lxHeader">
<LxHeader
icon="md-apps"
text="合同未付清表"
style="margin-bottom: 10px; border: 0px; margin-top: 25px"
>
<div slot="content">
<xy-table :cell-style="nopayCellStyle" :height="300" :list="nopay" :table-item="nopayTable">
<template v-slot:btns> </template>
</xy-table>
</div>
<slot> </slot>
</LxHeader>
</div>
</div>
<detailContract ref="detailContract"></detailContract>
</div>
</template>
<script>
import detailContract from "@/views/contract/components/detailContract";
import LxHeader from "@/components/LxHeader/index.vue";
import Pagination from "@/components/Pagination";
import { adminDepartmentList } from "@/api/system/department";
import { departmentTotal, nopayTotal } from "@/api/dashboard/notice";
import { adminUserList, getInfo } from "../../api/user.js";
import { getNotice, readNotice, statistic } from "@/api/dashboard/notice";
import { parseTime, moneyFormatter } from "@/utils/index";
import { Message } from "element-ui";
export default {
name: "Manage",
components: {
LxHeader,
Pagination,
detailContract,
},
data() {
return {
nopay: [],
nopayTable: [
{
prop: "name",
label: "合同名称",
width: 280,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 160,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
},
{
prop: "supply",
label: "承包商/供货商",
minWidth: 160,
align:"left"
},
{
label: "服务时间",
width: 240,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
{
label: "已付金额",
width: 160,
prop: "fund_log_total",
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
},
],
departmentTotal: [],
departmentTotalTable: [
{
width: 150,
labelClassName: "spit-cell",
headerFn: (scope) => {
return (
<div style="padding: 10px 0;height: 100%;display: flex;justify-content: space-evenly;text-align: center;">
<span style="align-self: flex-end;">科室</span>
<span style="align-self: flex-start;">类别</span>
</div>
);
},
sortable: false,
prop: "name",
},
{
label: "政府采购",
Fprop: "government",
multiHd: [
{
label: "货物",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.government.huowu}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.government.huowu.length}</a>
</el-popover>
);
},
},
{
label: "服务",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.government.fuwu}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.government.fuwu.length}</a>
</el-popover>
);
},
},
{
label: "工程",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.government.gongchen}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.government.gongchen.length}</a>
</el-popover>
);
},
},
],
},
{
label: "小型项目",
Fprop: "small",
multiHd: [
{
label: "货物",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.small.huowu}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.small.huowu.length}</a>
</el-popover>
);
},
},
{
label: "服务",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.small.fuwu}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.small.fuwu.length}</a>
</el-popover>
);
},
},
{
label: "工程",
width: 100,
sortable: false,
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.small.gongchen}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.small.gongchen.length}</a>
</el-popover>
);
},
},
],
},
{
label: "本月累计签订合同数",
minWidth: 140,
prop: "month_total",
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.month_total}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
align:"left"
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.month_total.length}</a>
</el-popover>
);
},
},
{
label: "本年累计签订合同数",
minWidth: 140,
prop: "year_total",
customFn: (row) => {
return (
<el-popover trigger="click">
<div>
<xy-table
list={row.year_total}
height={300}
table-item={[
{
prop: "name",
label: "合同名称",
width: 180,
align:"left"
},
{
prop: "money",
label: "合同金额",
width: 120,
align: "right",
formatter: (cell, data, value) => {
return `¥ ${value}`.replace(
/\B(?=(\d{3})+(?!\d))/g,
","
);
},
},
{
prop: "supply",
label: "承包商/供货商",
width: 160,
},
{
label: "服务时间",
width: 200,
customFn: (row) => {
return (
<div>
<span>{row.start_date} 至 </span>
<span>{row.end_date}</span>
</div>
);
},
},
]}
scopedSlots={{
btns() {
return "";
},
}}
></xy-table>
</div>
<a slot="reference">{row.year_total.length}</a>
</el-popover>
);
},
},
],
value2: 12,
split: 0.5,
select: {
year: "",
},
statistic: "",
department_id: [],
userIds: [],
list: [],
total: 0,
pageIndex: 1,
// listQuery: {
// page: 1,
// page_size: 10,
// show_self: 1,
// },
form: {
id: undefined,
},
dialogFormVisible: false,
departmentTree: [],
userList: [],
typeList: [],
formLabelWidth: "200px",
user: {},
departmentProgress: [],
departmentTable: [
{
label: "科室",
width: 80,
prop: "name",
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: 160,
align: "right",
sortable: false,
prop: "money_total_1",
formatter: (cell, data, value) => {
return moneyFormatter(value);
},
},
{
label: "调整后预算数(元)",
width: 160,
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: "进展情况",
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: 160,
align: "right",
sortable: false,
prop: "money_total_1",
formatter: (cell, data, value) => {
return moneyFormatter(value);
},
},
{
label: "调整后预算数(元)",
width: 160,
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.getDepartmnetTotal();
this.getNopay();
this.getStatistic();
getInfo()
.then((response) => {
console.log(response);
this.user = response;
})
.catch((error) => {});
},
methods: {
nopayCellStyle ({row}) {
let per = ((((row.fund_log_total) / row.money) || 0) * 100)?.toFixed(2) || 0
let endDay = this.$moment(new Date()).diff(this.$moment(new Date(row.end_date)),'months')
if (per < 100 && endDay >= 6) {
return {
'background': '#ef6256ee',
'color': '#fff'
}
}
},
async getNopay() {
const res = await nopayTotal({
is_auth: 1,
year: this.select.year
});
this.nopay = res;
console.log(222, this.nopay);
},
async getDepartmnetTotal() {
const res = await departmentTotal({
is_auth: 1,
year: this.select.year
});
this.departmentTotal = res;
},
changeYear(e) {
this.select.year = e;
this.getStatistic();
this.getNopay();
this.getDepartmnetTotal()
},
async getStatistic() {
const res = await statistic(this.select);
console.log(res);
this.statistic = res;
if (res.typeList) {
var arr = [];
for (var i = 0; i < res.typeList.length; i = i + 2) {
if (res.typeList[i]) {
res.typeList[i].per = this.getPer(res.typeList[i]);
}
if (res.typeList[i + 1]) {
res.typeList[i + 1].per = this.getPer(res.typeList[i + 1]);
}
arr.push([res.typeList[i], res.typeList[i + 1]]);
}
this.typeList = arr;
}
},
getPer(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 per;
},
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);
};
},
},
};
</script>
<style scoped lang="scss">
::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;
}
}
}
a {
&:hover {
text-decoration: underline;
}
}
</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>
<style>
.spit-cell {
height: 100%;
padding: 0 !important;
box-sizing: border-box;
background: linear-gradient(
29deg,
#0000 0,
#0000 49.5%,
#ebeef5 49.5%,
#ebeef5 50.5%,
#0000 50.5%
);
position: relative;
}
</style>