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.

429 lines
13 KiB

<template>
<div>
<Modal v-model="isShowModal" fullscreen class-name="oa-modal" footer-hide title="科室资金执行率明细" :mask-closable="false">
<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.money_total) }}</div>
<div class="card-desc">科室预算金额</div>
</el-card>
</el-col>
</el-row>
<!-- 已执行项目表格 -->
<el-card class="table-container mb-4">
<div class="section-title" style="display:flex;align-items:center;justify-content:space-between;">
<span>资金执行明细</span>
<el-button type="primary" size="mini" @click="exportEnd"></el-button>
</div>
<xy-table ref="xyTable" :list="endList" :table-item="endTable" :height="300">
<template v-slot:status>
<el-table-column header-align="center" label="当前状态" width="120">
<template>
<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 v-if="scope.row.contract_id" type="primary" size="small" @click="showContractDetail(scope.row)"></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" style="display:flex;align-items:center;justify-content:space-between;">
<span>未执行完项目流程中/预算流转中</span>
<el-button type="primary" size="mini" @click="exportPart"></el-button>
</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="showContractDetail(scope.row)"></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" /> -->
<ContractDetailDrawer ref="contractDetailDrawer" :visible.sync="isShowContractDetail" />
</div>
</template>
<script>
import {
endIndex2,
partIndex
} from '@/api/departmentProgress'
// import detail from '../components/detail.vue'
import ContractDetailDrawer from '@/components/contractIntegration/index.vue'
import { getToken } from '@/utils/auth'
export default {
name: 'DepartmentProgressDetail',
components: {
// detail,
ContractDetailDrawer
},
data() {
return {
isShowModal: false,
isShowContractDetail: false,
row: {},
endTotal: 0,
partTotal: 0,
endSelect: {
page: 1,
page_size: 10
},
partSelect: {
page: 1,
page_size: 10
},
endList: [],
partList: [],
endTable: [{
prop: 'model_type_text',
label: '类型',
width: 120,
align: 'center'
}, {
prop: 'name',
label: '关联名称',
width: 240,
align: 'center'
}, {
prop: 'use_money',
label: '使用金额',
width: 240
}, {
prop: 'admin_name',
label: '发起人',
width: 120,
align: 'center'
}, {
prop: 'created_at',
label: '发起时间',
width: 180,
align: 'center',
formatter: (v1, v2, value) => {
return this.formatDateTime(value)
}
}, {
prop: 'status',
label: '状态',
width: 120,
align: 'center'
}],
table: [{
prop: 'name',
label: '项目名称',
// fixed: 'left',
// width: 240,
align: 'left'
}, {
prop: 'department.name',
label: '科室',
width: 240,
align: 'left'
}, {
prop: 'admin.name',
label: '经办人',
width: 100
}, {
prop: 'money',
label: '预算金额',
width: 100,
formatter(v1, v2, value) {
return value || '0.00'
}
}, {
prop: 'funds_count',
label: '发起支付笔数',
width: 100
}, {
prop: 'contract_plan_act_sum',
label: '已确认付款金额',
width: 120,
formatter(v1, v2, value) {
return value || '0.00'
}
}, {
prop: 'status',
label: '当前状态',
export: 'funds_count_text',
width: 120
}]
}
},
watch: {
isShowModal(newval) {
if (newval) {
// Modal opened
} 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 endIndex2({
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
},
showContractDetail(row) {
this.isShowContractDetail = true
this.$nextTick(() => {
this.$refs.contractDetailDrawer.getDetail(row.contract_id)
})
},
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.toFixed(2).toString() + '元' // 小于1万直接返回原数值
} else {
return (num / 10000).toFixed(2) + '万元' // 除以1万并保留两位小数
}
},
formatDateTime(dateStr) {
if (!dateStr) return ''
const date = new Date(dateStr)
const today = new Date()
// 检查是否是今天
const isToday = date.getFullYear() === today.getFullYear() &&
date.getMonth() === today.getMonth() &&
date.getDate() === today.getDate()
if (isToday) {
// 今天显示时分秒
return date.toLocaleTimeString('zh-CN', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
} else {
// 其他日期只显示日期
return date.toLocaleDateString('zh-CN')
}
},
exportEnd() {
const name = this.row ? (this.row.plan_department ? this.row.plan_department.name : '') : ''
const file_name = name + '资金执行明细'
// const export_fields = 'export_fields[name]=项目名称&export_fields[department.name]=科室&export_fields[admin.name]=经办人&export_fields[money]=预算金额&export_fields[funds_count]=发起支付笔数&export_fields[contract_plan_act_sum]=已确认付款金额&export_fields[funds_count_text]=当前状态'
const export_fields = 'export_fields[model_type_text]=类型&export_fields[name]=关联名称&export_fields[use_money]=使用金额&export_fields[created_at]=发起时间&export_fields[funds_count_text]=状态&export_fields[admin_name]=发起人'
window.open(`${process.env.VUE_APP_BASE_API}/api/ht/contract/end-index-v2?token=${getToken()}&is_export=1&page=1&page_size=999&department_id=${this.row.plan_department_id}&${export_fields}&file_name=${file_name}`, '_blank')
},
exportPart() {
const name = this.row ? (this.row.plan_department ? this.row.plan_department.name : '') : ''
const file_name = name + '未执行完项目'
const export_fields = 'export_fields[name]=项目名称&export_fields[department.name]=科室&export_fields[admin.name]=经办人&export_fields[money]=预算金额&export_fields[funds_count]=发起支付笔数&export_fields[contract_plan_act_sum]=已确认付款金额&export_fields[funds_count_text]=当前状态'
window.open(`${process.env.VUE_APP_BASE_API}/api/ht/contract/part-index?token=${getToken()}&is_export=1&page=1&page_size=999&department_id=${this.row.plan_department_id}&${export_fields}&file_name=${file_name}`, '_blank')
}
}
}
</script>
<style scoped lang="scss">
::v-deep .ivu-modal-body {
max-height: none !important;
overflow: scroll!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>