From 0402000a602338a8a2717cab38e3ff086dbba802 Mon Sep 17 00:00:00 2001 From: lion <120344285@qq.com> Date: Thu, 4 Dec 2025 11:58:35 +0800 Subject: [PATCH] genggai --- src/api/dashboard/notice.js | 8 + src/views/contractDetails/index.vue | 16 +- src/views/dashboard/index.vue | 425 ++++++++++++++++++------ src/views/departmentPlanMoney/index.vue | 2 +- 4 files changed, 332 insertions(+), 119 deletions(-) diff --git a/src/api/dashboard/notice.js b/src/api/dashboard/notice.js index babfe43..5652f52 100644 --- a/src/api/dashboard/notice.js +++ b/src/api/dashboard/notice.js @@ -59,3 +59,11 @@ export function contractDetailDepartment(params) { params }) } + +export function nopayTotal(params) { + return request({ + method: 'get', + url: '/api/admin/notice/nopay-total', + params + }) +} diff --git a/src/views/contractDetails/index.vue b/src/views/contractDetails/index.vue index d83d6cc..0e1e38f 100644 --- a/src/views/contractDetails/index.vue +++ b/src/views/contractDetails/index.vue @@ -4,7 +4,7 @@ - +
查询 重置 @@ -97,10 +97,10 @@ - - @@ -331,7 +446,7 @@ - +
预算类型执行情况 -
+
-
+
- + 部门预算计划金额 + @@ -408,6 +524,10 @@ + + + + @@ -415,15 +535,19 @@ import { parseTime, moneyFormatter } from "@/utils/index"; import { Message } from "element-ui"; import * as echarts from "echarts"; -import { getNotice, readNotice, statistic, carry,contractDetailDepartment } from "@/api/dashboard/notice"; +import { getNotice, readNotice, statistic, carry, contractDetailDepartment, nopayTotal } from "@/api/dashboard/notice"; import detailContract from "@/views/contract/components/detailContract"; import lineChart from '@/views/dashboard/components/LineChart.vue'; - +import budgetStatic from '@/views/dashboard/components/budgetStatic.vue'; +import carryStatic from '@/views/dashboard/components/carryStatic.vue'; +import { getparameter } from '@/api/system/dictionary' export default { name: "Dashboard", components: { detailContract, - lineChart + lineChart, + budgetStatic, + carryStatic }, data() { return { @@ -444,52 +568,11 @@ export default { }, // 合同统计 - contractStats: [ - { - department: "行政科室", - gov_goods: 1, - gov_service: 1, - gov_project: 1, - small_goods: 1, - small_service: 1, - small_project: 1, - month_total: 1, - year_total: 1, - }, - { - department: "质量保证科室", - gov_goods: 5, - gov_service: 5, - gov_project: 5, - small_goods: 5, - small_service: 5, - small_project: 5, - month_total: 5, - year_total: 5, - }, - { - department: "水环境监测科", - gov_goods: 1, - gov_service: 1, - gov_project: 1, - small_goods: 1, - small_service: 1, - small_project: 1, - month_total: 1, - year_total: 1, - }, - { - department: "大气环境监测科", - gov_goods: 3, - gov_service: 3, - gov_project: 3, - small_goods: 3, - small_service: 3, - small_project: 3, - month_total: 3, - year_total: 3, - }, - ], + purchaseType: [], + contractStats: [], + + // 合同到期待办清单 + contractDueList: [], // 项目支出 @@ -607,14 +690,25 @@ export default { }; }, - computed: {}, + computed: { + allowAuth() { + return this.$store.state.user.min_allow_level !== 2; + }, + authShowStatic() { + return this.$store.state.user.myroles?.find(i => i.name === "首页统计"); + } + }, created() { this.currentYear = new Date().getFullYear().toString(); + this.getContractSignDimension().then(() => { + this.getContractDetailDepartment(); + }); this.getNotices(); this.getStatistic(); this.getCarry(); - this.getContractDetailDepartment() + this.getContractDueList(); + this.getNopayTotal(); }, mounted() { @@ -622,6 +716,20 @@ export default { }, methods: { + // 跳转部门预算计划金额 + goDepPlanMoney() { + this.$router.push('/contract/departmentPlanMoney/index'); + }, + // 获取未支付合计 + async getNopayTotal() { + const res = await nopayTotal(); + console.log(res); + }, + // 获取合同签订统计 维度 + async getContractSignDimension() { + const res = await getparameter({ number: 'purchase_type' }); + this.purchaseType = res?.detail || []; + }, // 格式化金额 formatMoney(amount) { if (!amount) return "0.00"; @@ -638,6 +746,24 @@ export default { return parseTime(new Date(cellValue), "{y}-{m}-{d}"); }, + // 格式化日期 + formatDate(date) { + if (!date) return ''; + return parseTime(new Date(date), "{y}-{m}-{d}"); + }, + + // 格式化金额(带¥符号和千分位) + formatMoneyWithSymbol(row, column, cellValue) { + if (cellValue === null || cellValue === undefined || cellValue === '') { + return '¥ 0'; + } + const value = Number(cellValue); + if (isNaN(value)) { + return '¥ 0'; + } + return `¥ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','); + }, + // 类型格式化 typeFormatter(row, column, cellValue) { return cellValue === 1 ? "合同流程" : "付款计划"; @@ -669,9 +795,9 @@ export default { // 执行率计算 toper(m1, m2, m3) { - if (m2 != 0) { + if (m2 != 0) { return ((m3 / m2) * 100).toFixed(2); - } else if (m1 != 0) { + } else if (m1 != 0) { return ((m3 / m1) * 100).toFixed(2); } else { return 0; @@ -717,13 +843,62 @@ export default { Message.error("标记已读失败"); } }, - // 合同签订 - async getContractDetailDepartment(row) { + // 合同签订统计 + async getContractDetailDepartment() { try { const res = await contractDetailDepartment(); - console.log(res); + const data = res?.data || res || []; + + // 按 sortnumber 从小到大排序 + const sortedData = data.sort((a, b) => { + const sortA = a.sortnumber || 0; + const sortB = b.sortnumber || 0; + return sortA - sortB; + }); + + // 转换为表格数据格式 + this.contractStats = sortedData.map(item => { + const rowData = { + department: item.name || '', + month_total: item.month_total || 0, + year_total: item.year_total || 0 + }; + + // 处理采购类型数据 + if (item.purchase_type_list && Array.isArray(item.purchase_type_list)) { + item.purchase_type_list.forEach(purchaseType => { + const purchaseTypeId = purchaseType.id; + // 货物 (type 2) + rowData[`purchase_${purchaseTypeId}_type_2`] = purchaseType.huowu_total || 0; + // 服务 (type 1) + rowData[`purchase_${purchaseTypeId}_type_1`] = purchaseType.fuwu_total || 0; + // 工程 (type 3) + rowData[`purchase_${purchaseTypeId}_type_3`] = purchaseType.gongcheng_total || 0; + }); + } + + return rowData; + }); + } catch (error) { + console.error("获取合同签订统计失败:", error); + Message.error("获取合同签订统计失败"); + } + }, + // 获取合同到期待办清单 + async getContractDueList() { + try { + const res = await nopayTotal(); + const data = res?.data || res || []; + this.contractDueList = data + .filter((i) => i.money != 0) + .sort((a, b) => { + return ( + new Date(a.end_date).getTime() - new Date(b.end_date).getTime() + ); + }); } catch (error) { - console.error("获取合同签订失败:", error); + console.error("获取合同到期待办清单失败:", error); + Message.error("获取合同到期待办清单失败"); } }, // 表格合计 @@ -781,13 +956,13 @@ export default { let m2 = row?.money_total_2; let m1 = row?.money_total_1; let m3 = row?.use_money_total; - let per = 0; + let per = 0; - if (m2 != 0) { - per = ((m3 / m2) * 100).toFixed(2); - } else if (m1 != 0) { - per = ((m3 / m1) * 100).toFixed(2); - } + if (m2 != 0) { + per = ((m3 / m2) * 100).toFixed(2); + } else if (m1 != 0) { + per = ((m3 / m1) * 100).toFixed(2); + } return Number(per); }, @@ -803,9 +978,9 @@ export default { let m3 = row.use_money_total; let per = 0; - if (m2 != 0) { + if (m2 != 0) { per = ((m3 / m2) * 100).toFixed(2); - } else if (m1 != 0) { + } else if (m1 != 0) { per = ((m3 / m1) * 100).toFixed(2); } return Number(per); @@ -827,7 +1002,7 @@ export default { if (item && Number(item.value) !== 0) { constData.push(1); showData.push(item); - } else { + } else { constData.push(1); showData.push(null); } @@ -872,11 +1047,11 @@ export default { let nextPlan = res?.map(i => { const { plan_rate_next, use_money_total, paid_plan_total_next } = i; let nextPlan_total = Number(paid_plan_total_next || 0) + Number(use_money_total || 0); - return { + return { value: this.formatResult(plan_rate_next), money: parseFloat(nextPlan_total).toFixed(2) - }; - }); + }; + }); let barWidth = 23; let constData1 = []; @@ -1160,7 +1335,7 @@ export default { border: 1px solid #ebeef5; border-bottom: none; font-size: 12px; - font-weight: 600; + font-weight: 600; color: #606266; position: sticky; top: 0; @@ -1170,20 +1345,20 @@ export default { display: flex; align-items: center; justify-content: center; - text-align: center; + text-align: center; } } .todo-body { - flex: 1; + flex: 1; border: 1px solid #ebeef5; border-top: none; overflow-y: auto; max-height: 180px; .todo-row { - display: flex; - align-items: center; + display: flex; + align-items: center; padding: 8px 12px; border-bottom: 1px solid #ebeef5; font-size: 12px; @@ -1193,7 +1368,7 @@ export default { border-bottom: none; } - &:hover { + &:hover { background-color: #f5f7fa; } @@ -1220,8 +1395,8 @@ export default { height: 100%; .budget-stats-horizontal { - display: flex; - justify-content: space-between; + display: flex; + justify-content: space-between; align-items: flex-start; height: 100%; gap: 15px; @@ -1239,11 +1414,11 @@ export default { } .budget-item-content { - display: flex; - flex-direction: column; - align-items: center; + display: flex; + flex-direction: column; + align-items: center; justify-content: center; - text-align: center; + text-align: center; } .budget-icon { @@ -1256,7 +1431,7 @@ export default { margin: 0 auto 10px; i { - font-size: 20px; + font-size: 20px; color: white; } @@ -1439,7 +1614,7 @@ export default { } .expense-label { - margin-top: 10px; + margin-top: 10px; font-size: 12px; color: #909399; } @@ -1577,4 +1752,34 @@ export default { } } } + +// 统计按钮样式 +.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); + } +} diff --git a/src/views/departmentPlanMoney/index.vue b/src/views/departmentPlanMoney/index.vue index 47d6835..ab36aef 100644 --- a/src/views/departmentPlanMoney/index.vue +++ b/src/views/departmentPlanMoney/index.vue @@ -51,7 +51,7 @@ style="width: 100%" > - +