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.

331 lines
9.8 KiB

<template>
<div>
<Modal fullscreen class-name="oa-modal" footer-hide title="科室资金执行率明细" :mask-closable="false" v-model="isShowModal">
<div class="department-progress-detail">
<el-container>
<el-main>
<!-- 科室标题 -->
<div class="department-title">
<h3>{{row?(row.plan_department?row.plan_department.name:''):''}} - 资金执行率明细</h3>
</div>
<!-- 执行率统计卡片 -->
<el-row :gutter="20" class="mb-4">
<el-col :span="8">
<el-card class="summary-card" shadow="hover">
<div class="card-title">当前执行率</div>
<div class="execution-rate">{{ getCompletionRate(row.rate) }}%</div>
<div class="card-desc">已财务确认的资金比例</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card class="summary-card" shadow="hover">
<div class="card-title">预计执行率</div>
<div class="execution-rate">{{ getCompletionRate(row.rate_end) }}%</div>
<div class="card-desc">全部付款确认后预计的执行率</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card class="summary-card" shadow="hover">
<div class="card-title">预算金额</div>
<div class="execution-rate">{{ formatToWan(row.contract_plan_sum) }}</div>
<div class="card-desc">科室预算金额</div>
</el-card>
</el-col>
</el-row>
<!-- 已执行项目表格 -->
<el-card class="table-container mb-4">
<div class="section-title">已执行项目财务付款确认
</div>
<xy-table ref="xyTable" :list="endList" :table-item="table" :height='300'>
<template v-slot:status>
<el-table-column header-align="center" label="当前状态" width="120">
<template slot-scope="scope">
<el-tag type='success'>已完成</el-tag>
</template>
</el-table-column>
</template>
<template v-slot:btns>
<el-table-column :fixed="$store.getters.device === 'mobile'?false:'right'" header-align="center"
label="操作" width="120">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="getDetail(scope.row,'end')"></el-button>
</template>
</el-table-column>
</template>
</xy-table>
<div style="display: flex; justify-content: flex-end">
<Page :total="endTotal" show-elevator @on-change="endPageChange" />
</div>
</el-card>
<!-- 未执行完项目表格 -->
<el-card class="table-container">
<div class="section-title">未执行完项目流程中/预算流转中
</div>
<xy-table ref="xyTable" :list="partList" :table-item="table" :height='300'>
<template v-slot:status>
<el-table-column header-align="center" label="当前状态" width="120" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.funds_count>0" type='warning'>部分支付中</el-tag>
<el-tag v-else type='warning'>oa流程中</el-tag>
</template>
</el-table-column>
</template>
<template v-slot:btns>
<el-table-column :fixed="$store.getters.device === 'mobile'?false:'right'" header-align="center"
label="操作" width="120" align="center">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="getDetail(scope.row,'part')"></el-button>
</template>
</el-table-column>
</template>
</xy-table>
<div style="display: flex; justify-content: flex-end">
<Page :total="partTotal" show-elevator @on-change="partPageChange" />
</div>
</el-card>
</el-main>
</el-container>
</div>
</Modal>
<detail ref="detail"></detail>
</div>
</template>
<script>
import {
endIndex,
partIndex,
} from "@/api/departmentProgress"
import detail from "../components/detail.vue"
export default {
name: 'DepartmentProgressDetail',
components: {
detail
},
data() {
return {
isShowModal: false,
row: {},
endTotal: 0,
partTotal: 0,
endSelect: {
page: 1,
page_size: 10,
},
partSelect: {
page: 1,
page_size: 10,
},
endList: [],
partList: [],
table: [{
prop: 'name',
label: '项目名称',
// fixed: 'left',
// width: 240,
align: 'left'
}, {
prop: 'department.name',
label: '科室',
width: 240,
}, {
prop: 'admin.name',
label: '经办人',
width: 100,
}, {
prop: 'contract_plan_sum',
label: '预算金额',
width: 100,
formatter(v1, v2, value){
return value ? value: '0.00'
}
}, {
prop: 'funds_count',
label: '发起支付笔数',
width: 100,
}, {
prop: 'contract_plan_act_sum',
label: '已确认付款金额',
width: 120,
formatter(v1, v2, value){
return value ? value: '0.00'
}
}, {
prop: 'status',
label: '当前状态',
width: 120,
}]
}
},
watch: {
isShowModal(newval) {
if (newval) {
} else {
this.row = {}
}
},
row(newval) {
if (newval) {
this.getEndIndex(newval.plan_department_id)
this.getPartIndex(newval.plan_department_id)
}
}
},
methods: {
partPageChange(e) {
this.partSelect.page = e
this.getPartIndex(this.row.plan_department_id)
},
endPageChange(e) {
this.endSelect.page = e
this.getEndIndex(this.row.plan_department_id)
},
async getEndIndex(id) {
const res = await endIndex({
department_id: id,
page: this.endSelect.page,
page_size: this.endSelect.page_size
})
this.endList = res.list.data
this.endTotal = res.list.total
},
async getPartIndex(id) {
const res = await partIndex({
department_id: id,
page: this.partSelect.page,
page_size: this.partSelect.page_size
})
this.partList = res.list.data
this.partTotal = res.list.total
},
getDetail(row,type) {
this.$refs.detail.type = type
this.$refs.detail.detailRow = row
this.$refs.detail.detailDrawerVisible = true
},
getCompletionRate(dept) {
return dept ? Number(dept.toFixed(2)) : 0
},
formatToWan(num) {
if (num === null || num === undefined) return '0元';
num = Number(num);
if (isNaN(num)) return '0元';
if (Math.abs(num) < 10000) {
return num.toString() + '元'; // 小于1万直接返回原数值
} else {
return (num / 10000).toFixed(2) + '万元'; // 除以1万并保留两位小数
}
},
}
}
</script>
<style scoped lang="scss">
::v-deep .ivu-modal-body {
max-height: none !important;
}
.department-progress-detail {
min-height: 100vh;
background: #f4f6fa;
}
.header-bg {
background: linear-gradient(135deg, #4A90E2 0%, #357ABD 100%);
color: white;
padding: 0;
height: 70px;
display: flex;
align-items: center;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 0 30px;
}
.header-title {
font-size: 20px;
font-weight: bold;
}
.header-user {
font-size: 14px;
}
.sidebar {
background-color: #f8f9fa;
min-height: calc(100vh - 70px);
border-right: 1px solid #dee2e6;
}
.department-title {
background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
color: white;
padding: 15px;
border-radius: 10px;
margin-bottom: 20px;
text-align: center;
}
.action-buttons {
margin-bottom: 20px;
text-align: right;
}
.summary-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
text-align: center;
}
.card-title {
font-size: 16px;
margin-bottom: 10px;
}
.execution-rate {
font-size: 32px;
font-weight: bold;
margin-bottom: 5px;
}
.card-desc {
font-size: 13px;
}
.section-title {
background-color: #f8f9fa;
padding: 15px;
margin: 20px 0 15px 0;
border-left: 4px solid #007bff;
border-radius: 5px;
font-size: 16px;
font-weight: bold;
}
.table-container {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
.detail-table {
font-size: 14px;
}
</style>