master
lion 4 days ago
parent da1982cb2e
commit 0402000a60

@ -59,3 +59,11 @@ export function contractDetailDepartment(params) {
params
})
}
export function nopayTotal(params) {
return request({
method: 'get',
url: '/api/admin/notice/nopay-total',
params
})
}

@ -4,7 +4,7 @@
<el-form :model="searchForm" inline label-width="90px" size="small">
<el-form-item label="合同名称">
<el-input
v-model="searchForm.name"
v-model="searchForm.keyword"
placeholder="请输入合同名称"
clearable
style="width: 200px"
@ -40,7 +40,7 @@
/>
</el-select>
</el-form-item>
<el-form-item label="类型">
<!-- <el-form-item label="类型">
<el-select
v-model="searchForm.type"
placeholder="全部"
@ -54,7 +54,7 @@
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form-item> -->
<div class="filter-actions">
<el-button type="primary" @click="handleSearch"></el-button>
<el-button @click="handleReset"></el-button>
@ -97,10 +97,10 @@
</template>
</el-table-column>
<el-table-column prop="date" label="签订日期" width="120" />
<el-table-column label="执行部门" min-width="140" show-overflow-tooltip>
<template slot-scope="{ row }">
<el-table-column prop="carry_department" label="执行部门" min-width="140" show-overflow-tooltip>
<!-- <template slot-scope="{ row }">
{{ formatDepartment(row.carry_department) }}
</template>
</template> -->
</el-table-column>
<el-table-column label="状态" width="110">
<template slot-scope="{ row }">
@ -401,7 +401,7 @@ export default {
total: 0
},
searchForm: {
name: '',
keyword: '',
contract_type: '',
status: '',
type: ''
@ -555,7 +555,7 @@ export default {
},
handleReset() {
this.searchForm = {
name: '',
keyword: '',
contract_type: '',
status: '',
type: ''

@ -26,7 +26,7 @@
<div class="header-col" style="width: 120px">下发时间</div>
<div class="header-col" style="width: 60px">状态</div>
<div class="header-col" style="width: 60px">操作</div>
</div>
</div>
<!-- 表格内容 -->
<div class="todo-body">
@ -35,13 +35,13 @@
<el-tag size="mini" type="info">{{
typeFormatter(null, null, item.type)
}}</el-tag>
</div>
</div>
<div class="todo-col" style="flex: 1" :title="item.content">
{{ item.content }}
</div>
<div class="todo-col" style="width: 120px">
{{ timeFormatter(null, null, item.created_at) }}
</div>
</div>
<div class="todo-col" style="width: 60px">
<el-tag v-if="item.read_count" type="success" size="mini"
>已读</el-tag
@ -63,13 +63,13 @@
>
</div>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
<!-- 右侧预算执行情况 -->
<el-col :span="12">
<el-col :span="authShowStatic ? 11 : 12">
<el-card class="box-card top-card">
<div slot="header" class="card-header">
<div class="header-left">
@ -204,6 +204,35 @@
</div>
</div>
</el-card>
</el-col>
<!-- 统计按钮区域 -->
<el-col v-if="authShowStatic" :span="1">
<div style="display: flex;flex-direction: column;height: 280px;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>
@ -227,14 +256,14 @@
style="width: 100%"
show-summary
:summary-method="getSummaries"
:max-height="300"
:max-height="400"
:header-cell-style="{
background: '#fafafa',
color: '#606266',
fontWeight: '600',
}"
>
<el-table-column
<el-table-column
label="序号"
type="index"
width="60"
@ -246,29 +275,33 @@
width="120"
align="center"
/>
<el-table-column label="政府采购" align="center">
<el-table-column prop="gov_goods" label="货物" align="center" />
<el-table-column prop="gov_service" label="服务" align="center" />
<el-table-column prop="gov_project" label="工程" align="center" />
</el-table-column>
<el-table-column label="小型项目" align="center">
<el-table-column prop="small_goods" label="货物" align="center" />
<el-table-column
v-for="purchaseTypeItem in purchaseType"
:key="purchaseTypeItem.id || purchaseTypeItem.value"
:label="purchaseTypeItem.value"
align="center"
>
<el-table-column
prop="small_service"
:prop="`purchase_${purchaseTypeItem.id}_type_2`"
label="货物"
align="center"
/>
<el-table-column
:prop="`purchase_${purchaseTypeItem.id}_type_1`"
label="服务"
align="center"
/>
<el-table-column
prop="small_project"
:prop="`purchase_${purchaseTypeItem.id}_type_3`"
label="工程"
align="center"
/>
</el-table-column>
<el-table-column
</el-table-column>
<el-table-column
prop="month_total"
label="本月累计签订合同数"
width="160"
align="center"
align="center"
/>
<el-table-column
prop="year_total"
@ -277,6 +310,88 @@
align="center"
/>
</el-table>
</el-card>
</el-col>
</el-row>
<!-- 合同到期待办清单 -->
<el-row :gutter="20" style="margin-top: 20px">
<el-col :span="24">
<el-card class="box-card">
<div slot="header" class="card-header">
<div class="header-left">
<i
class="el-icon-check"
style="color: #409eff; margin-right: 5px"
></i>
<span>合同到期待办清单</span>
</div>
<div class="header-right">
<i class="el-icon-more"></i>
</div>
</div>
<el-table
:data="contractDueList"
border
style="width: 100%"
:max-height="400"
:header-cell-style="{
background: '#fafafa',
color: '#606266',
fontWeight: '600',
}"
>
<el-table-column
label="序号"
type="index"
width="60"
align="center"
/>
<el-table-column
prop="name"
label="合同名称"
width="280"
align="left"
/>
<el-table-column
prop="money"
label="合同金额"
width="160"
align="right"
:formatter="formatMoneyWithSymbol"
/>
<el-table-column
prop="fund_log_total"
label="已付金额"
width="160"
align="right"
:formatter="formatMoneyWithSymbol"
/>
<el-table-column
prop="supply"
label="承包商/供货商"
min-width="160"
align="left"
/>
<el-table-column
label="服务时间"
width="240"
align="center"
>
<template slot-scope="{ row }">
<span v-if="row.start_date && row.end_date">
{{ formatDate(row.start_date) }} {{ formatDate(row.end_date) }}
</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column
prop="department.name"
label="部门"
width="160"
/>
</el-table>
</el-card>
</el-col>
</el-row>
@ -293,7 +408,7 @@
style="color: #409eff; margin-right: 5px"
></i>
<span>科室执行情况</span>
</div>
</div>
<div class="header-right">
<i class="el-icon-more"></i>
</div>
@ -314,8 +429,8 @@
<el-table-column label="执行情况" width="220" align="left">
<template slot-scope="{ row }">
<el-progress :percentage="calculateExecutionRate(row)" />
</template>
</el-table-column>
</template>
</el-table-column>
<el-table-column prop="money_total_1" label="年初预算合计金额(元)" width="200" align="right" :formatter="moneyFormatter" />
<el-table-column prop="money_total_2" label="调整后预算合计金额(元)" width="220" align="right" :formatter="moneyFormatter" />
<el-table-column prop="middle_fund_total" label="年中专项资金(元)" width="180" align="right" :formatter="moneyFormatter" />
@ -323,7 +438,7 @@
<el-table-column label="操作" width="80" align="center" fixed="right">
<template slot-scope="{ row }">
<el-button type="text" size="mini" @click="viewDepartmentDetail(row)"></el-button>
</template>
</template>
</el-table-column>
</el-table>
</el-card>
@ -331,7 +446,7 @@
<!-- 预算类型执行情况 -->
<el-col :span="12">
<el-card class="box-card">
<el-card class="box-card">
<div slot="header" class="card-header">
<div class="header-left">
<i
@ -339,10 +454,10 @@
style="color: #67c23a; margin-right: 5px"
></i>
<span>预算类型执行情况</span>
</div>
</div>
<div class="header-right">
<i class="el-icon-more"></i>
</div>
</div>
</div>
<el-table
@ -398,7 +513,8 @@
size="small"
@change="handleMonthChange"
/>
</div>
<el-button type="primary" size="small" @click="goDepPlanMoney"></el-button>
</div>
</div>
<lineChart height="500px" :chart-data="lineChartData"></lineChart>
@ -408,6 +524,10 @@
<!-- 合同详情弹窗 -->
<detailContract ref="detailContract"></detailContract>
<!-- 统计组件 -->
<budgetStatic ref="budgetStatic"></budgetStatic>
<carryStatic ref="carryStatic" :departments="statistic.departmentList" :year="currentYear"></carryStatic>
</div>
</template>
@ -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);
}
}
</style>

@ -51,7 +51,7 @@
style="width: 100%"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="plan_department_name" label="预算部门" min-width="160" show-overflow-tooltip />
<el-table-column prop="plan_department.name" label="预算部门" min-width="160" show-overflow-tooltip />
<el-table-column prop="month" label="月份" width="120" />
<el-table-column label="预算金额(元)" width="180" align="right">
<template slot-scope="{ row }">

Loading…
Cancel
Save