|
|
<template>
|
|
|
<div class="container">
|
|
|
<!-- 查询配置 -->
|
|
|
<div>
|
|
|
<div ref="lxHeader">
|
|
|
<LxHeader :custom="true" icon="el-icon-s-order" text="执行科室预算分解表提交" style="margin-bottom: 10px; border: 0px;">
|
|
|
<div>
|
|
|
<div class="search-panel">
|
|
|
<div class="filters">
|
|
|
<el-select
|
|
|
v-model="searchFields.year_id"
|
|
|
placeholder="选择预算年度"
|
|
|
style="width: 150px"
|
|
|
@change="load"
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="item in yearOptions"
|
|
|
:key="item.value"
|
|
|
:label="item.year + '年'"
|
|
|
:value="item.value"
|
|
|
/>
|
|
|
</el-select>
|
|
|
|
|
|
<el-select
|
|
|
v-model="searchFields.status"
|
|
|
placeholder="选择状态"
|
|
|
style="width: 150px"
|
|
|
@change="load"
|
|
|
clearable
|
|
|
>
|
|
|
<el-option label="待提交" value="pending" />
|
|
|
<el-option label="已提交" value="submitted" />
|
|
|
<el-option label="已审核" value="reviewed" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="actions">
|
|
|
<Button type="primary" @click="load">查询</Button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</LxHeader>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<!-- 分配给本科室的预算包列表 -->
|
|
|
<el-table
|
|
|
ref="packageTable"
|
|
|
:data="packageData"
|
|
|
:height="tableHeight"
|
|
|
class="v-table"
|
|
|
style="width: 100%; margin-bottom: 20px;"
|
|
|
border
|
|
|
v-loading="loading"
|
|
|
row-key="id"
|
|
|
>
|
|
|
<el-table-column type="index" align="center" label="序号" width="60" />
|
|
|
|
|
|
<el-table-column prop="budget_year" label="预算年度" width="100" align="center">
|
|
|
<template slot-scope="scope">
|
|
|
<el-tag type="primary">
|
|
|
{{ scope.row.budget_year ? scope.row.budget_year.year + '年' : '-' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="parent_name" label="上级包名称" min-width="200">
|
|
|
<template slot-scope="scope">
|
|
|
<span style="color: #909399; font-size: 12px;">
|
|
|
{{ scope.row.top_name || '-' }} - {{ scope.row.parent_name || '-' }}
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="executing_department" label="执行部门" min-width="150">
|
|
|
<template slot-scope="scope">
|
|
|
<span style="color: #606266; font-size: 13px;">
|
|
|
{{ scope.row.department.name || '-' }}
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="allocated_amount" label="分配金额" width="160" align="right">
|
|
|
<template slot-scope="scope">
|
|
|
<span style="color: #409EFF; font-weight: bold;">
|
|
|
{{ formatCurrency(scope.row.allocated_amount) }} 万元
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="submitted_amount" label="提交金额" width="160" align="right">
|
|
|
<template slot-scope="scope">
|
|
|
<span style="color: #67C23A; font-weight: bold;">
|
|
|
{{ formatCurrency(scope.row.submission ? scope.row.submission.total_amount : 0) }} 万元
|
|
|
</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="submission_status" label="提交状态" width="120" align="center">
|
|
|
<template slot-scope="scope">
|
|
|
<el-tag :type="getStatusTagType(scope.row.submission_status)">
|
|
|
{{ getStatusText(scope.row.submission_status) }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column prop="submission_date" label="提交时间" width="180" align="center">
|
|
|
<template slot-scope="scope">
|
|
|
{{ scope.row.submission_date ? formatDate(scope.row.submission_date) : '-' }}
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
|
|
|
<el-table-column fixed="right" label="操作" width="200">
|
|
|
<template slot-scope="scope">
|
|
|
<Button
|
|
|
v-if="!scope.row.submission"
|
|
|
type="primary"
|
|
|
@click="openSubmissionForm(scope.row)"
|
|
|
size="small"
|
|
|
style="margin-right: 5px;"
|
|
|
>
|
|
|
填写分解表
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
v-if="scope.row.submission"
|
|
|
type="warning"
|
|
|
@click="editSubmissionForm(scope.row)"
|
|
|
size="small"
|
|
|
style="margin-right: 5px;"
|
|
|
>
|
|
|
修改分解表
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
v-if="scope.row.submission"
|
|
|
type="info"
|
|
|
@click="viewSubmissionForm(scope.row)"
|
|
|
size="small"
|
|
|
>
|
|
|
查看详情
|
|
|
</Button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
|
|
|
<!-- 分解表填写对话框 -->
|
|
|
<el-dialog
|
|
|
:title="dialogTitle"
|
|
|
:visible.sync="submissionDialogVisible"
|
|
|
width="95%"
|
|
|
:close-on-click-modal="false"
|
|
|
top="5vh"
|
|
|
custom-class="submission-dialog"
|
|
|
>
|
|
|
<budget-submission-form
|
|
|
v-if="submissionDialogVisible"
|
|
|
:package-data="currentPackage"
|
|
|
:mode="submissionMode"
|
|
|
@submit="handleSubmissionSubmit"
|
|
|
@cancel="submissionDialogVisible = false"
|
|
|
/>
|
|
|
</el-dialog>
|
|
|
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import LxHeader from '@/components/LxHeader/index.vue'
|
|
|
import { getBudgetCollectionYearOptions } from '@/api/budget/budgetCollectionYear.js'
|
|
|
import { getDepartmentPackages, submitBudgetDecomposition } from '@/api/budget/departmentSubmission.js'
|
|
|
import BudgetSubmissionForm from './components/BudgetSubmissionForm.vue'
|
|
|
|
|
|
export default {
|
|
|
name: 'DepartmentSubmission',
|
|
|
components: {
|
|
|
LxHeader,
|
|
|
BudgetSubmissionForm
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
loading: false,
|
|
|
tableHeight: 0,
|
|
|
searchFields: {
|
|
|
year_id: '',
|
|
|
status: ''
|
|
|
},
|
|
|
packageData: [],
|
|
|
yearOptions: [],
|
|
|
submissionDialogVisible: false,
|
|
|
currentPackage: null,
|
|
|
submissionMode: 'create' // create, edit, view
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
dialogTitle() {
|
|
|
const titles = {
|
|
|
create: '填写预算分解表',
|
|
|
edit: '修改预算分解表',
|
|
|
view: '查看预算分解表'
|
|
|
}
|
|
|
return titles[this.submissionMode] || '预算分解表'
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
|
this.initLoad()
|
|
|
this.loadYearOptions()
|
|
|
},
|
|
|
methods: {
|
|
|
initLoad() {
|
|
|
const clientHeight = document.documentElement.clientHeight
|
|
|
const lxHeaderHeight = 140
|
|
|
const paginationHeight = 60
|
|
|
const topHeight = 50
|
|
|
const tableHeight = clientHeight - lxHeaderHeight - topHeight - paginationHeight - 20
|
|
|
this.tableHeight = tableHeight
|
|
|
},
|
|
|
|
|
|
async loadYearOptions() {
|
|
|
try {
|
|
|
const response = await getBudgetCollectionYearOptions()
|
|
|
console.log('年度选项接口响应:', response)
|
|
|
|
|
|
if (response) {
|
|
|
let yearData = response
|
|
|
|
|
|
// 如果data是字符串,尝试解析JSON
|
|
|
if (typeof yearData === 'string') {
|
|
|
try {
|
|
|
yearData = JSON.parse(yearData)
|
|
|
} catch (e) {
|
|
|
console.error('解析年度选项JSON失败:', e)
|
|
|
this.$message.error('年度选项数据格式错误')
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (Array.isArray(yearData)) {
|
|
|
this.yearOptions = yearData
|
|
|
console.log('年度选项加载成功:', this.yearOptions)
|
|
|
|
|
|
// 默认选择第一个年度
|
|
|
if (this.yearOptions.length > 0 && !this.searchFields.year_id) {
|
|
|
this.searchFields.year_id = this.yearOptions[0].value
|
|
|
this.$nextTick(() => {
|
|
|
this.load()
|
|
|
})
|
|
|
} else if (this.yearOptions.length === 0) {
|
|
|
this.$message.warning('未找到可用的预算年度,请联系管理员')
|
|
|
}
|
|
|
} else {
|
|
|
console.warn('年度选项数据不是数组格式:', yearData)
|
|
|
this.$message.error('年度选项数据格式错误')
|
|
|
}
|
|
|
} else {
|
|
|
console.warn('年度选项接口响应异常:', response)
|
|
|
this.$message.error('年度选项接口返回格式错误')
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('加载年度选项失败:', error)
|
|
|
this.$message.error('加载年度选项失败,请刷新页面重试')
|
|
|
}
|
|
|
},
|
|
|
|
|
|
async load() {
|
|
|
if (!this.searchFields.year_id) {
|
|
|
this.$message.warning('请选择预算年度')
|
|
|
this.packageData = []
|
|
|
return
|
|
|
}
|
|
|
|
|
|
this.loading = true
|
|
|
try {
|
|
|
const params = {
|
|
|
...this.searchFields
|
|
|
}
|
|
|
|
|
|
const response = await getDepartmentPackages(params)
|
|
|
|
|
|
// 根据后端ApiResponse设计判断:code为0表示成功
|
|
|
if (response) {
|
|
|
this.packageData = Array.isArray(response) ? response : []
|
|
|
} else {
|
|
|
this.packageData = []
|
|
|
this.$message.warning(response.msg || '获取预算包列表失败')
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('获取数据失败:', error)
|
|
|
|
|
|
if (error.response && error.response.data) {
|
|
|
const errorMessage = error.response.data.message || error.response.data.error || '获取数据失败'
|
|
|
this.$message.error(errorMessage)
|
|
|
} else {
|
|
|
this.$message.error('获取数据失败,请检查网络连接')
|
|
|
}
|
|
|
|
|
|
this.packageData = []
|
|
|
} finally {
|
|
|
this.loading = false
|
|
|
}
|
|
|
},
|
|
|
|
|
|
openSubmissionForm(packageItem) {
|
|
|
this.currentPackage = { ...packageItem }
|
|
|
this.submissionMode = 'create'
|
|
|
this.submissionDialogVisible = true
|
|
|
// 增加console.log,输出当前表单数据
|
|
|
console.log('表单数据:', this.currentPackage)
|
|
|
},
|
|
|
|
|
|
editSubmissionForm(packageItem) {
|
|
|
this.currentPackage = { ...packageItem }
|
|
|
this.submissionMode = 'edit'
|
|
|
this.submissionDialogVisible = true
|
|
|
// 增加console.log,输出当前表单数据
|
|
|
console.log('编辑表单数据:', this.currentPackage)
|
|
|
},
|
|
|
|
|
|
viewSubmissionForm(packageItem) {
|
|
|
this.currentPackage = { ...packageItem }
|
|
|
this.submissionMode = 'view'
|
|
|
this.submissionDialogVisible = true
|
|
|
},
|
|
|
|
|
|
async handleSubmissionSubmit(submissionData) {
|
|
|
try {
|
|
|
const response = await submitBudgetDecomposition(submissionData)
|
|
|
if (response && response.id) {
|
|
|
this.$message.success('提交成功')
|
|
|
this.submissionDialogVisible = false
|
|
|
this.load() // 重新加载数据
|
|
|
} else {
|
|
|
this.$message.error(response.msg || '提交失败')
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error('提交失败:', error)
|
|
|
|
|
|
if (error.response && error.response.data && error.response.data.message) {
|
|
|
this.$message.error(error.response.data.message)
|
|
|
} else {
|
|
|
this.$message.error('提交失败')
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
|
|
|
formatCurrency(amount) {
|
|
|
if (amount === null || amount === undefined || amount === '') return '0.0'
|
|
|
const num = Number(amount)
|
|
|
return isFinite(num)
|
|
|
? num.toLocaleString('zh-CN', { minimumFractionDigits: 0, maximumFractionDigits: 0 })
|
|
|
: '0.0'
|
|
|
},
|
|
|
|
|
|
formatDate(dateStr) {
|
|
|
if (!dateStr) return '-'
|
|
|
const date = new Date(dateStr)
|
|
|
return date.toLocaleDateString('zh-CN') + ' ' + date.toLocaleTimeString('zh-CN', {
|
|
|
hour12: false,
|
|
|
hour: '2-digit',
|
|
|
minute: '2-digit'
|
|
|
})
|
|
|
},
|
|
|
|
|
|
getStatusTagType(status) {
|
|
|
const typeMap = {
|
|
|
pending: 'warning',
|
|
|
submitted: 'primary',
|
|
|
reviewed: 'success'
|
|
|
}
|
|
|
return typeMap[status] || 'info'
|
|
|
},
|
|
|
|
|
|
getStatusText(status) {
|
|
|
const textMap = {
|
|
|
pending: '待提交',
|
|
|
submitted: '已提交',
|
|
|
reviewed: '已审核'
|
|
|
}
|
|
|
return textMap[status] || '未知'
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
.container {
|
|
|
padding: 12px 16px 16px 16px;
|
|
|
}
|
|
|
|
|
|
.v-table {
|
|
|
border: 1px solid #e6e6e6;
|
|
|
}
|
|
|
|
|
|
.search-panel {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
gap: 12px;
|
|
|
padding: 12px;
|
|
|
background: #fff;
|
|
|
border: 1px solid #ebeef5;
|
|
|
border-radius: 0;
|
|
|
}
|
|
|
|
|
|
.filters {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 12px;
|
|
|
}
|
|
|
|
|
|
.actions {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
/* 统一表格行高 */
|
|
|
.v-table >>> .el-table__body tr {
|
|
|
height: 50px !important;
|
|
|
}
|
|
|
|
|
|
.v-table >>> .el-table__body tr td {
|
|
|
height: 50px !important;
|
|
|
max-height: 50px !important;
|
|
|
vertical-align: middle !important;
|
|
|
padding: 8px 12px !important;
|
|
|
box-sizing: border-box !important;
|
|
|
}
|
|
|
|
|
|
/* 所有单元格内容的统一处理 */
|
|
|
.v-table >>> .el-table__body tr td .cell {
|
|
|
height: 34px !important;
|
|
|
max-height: 34px !important;
|
|
|
line-height: 18px !important;
|
|
|
overflow: hidden !important;
|
|
|
display: flex !important;
|
|
|
align-items: center !important;
|
|
|
}
|
|
|
|
|
|
/* 确保标签和按钮不会撑开行高 */
|
|
|
.v-table >>> .el-table__body tr td .el-tag {
|
|
|
height: 24px !important;
|
|
|
line-height: 22px !important;
|
|
|
}
|
|
|
|
|
|
.v-table >>> .el-table__body tr td .el-button {
|
|
|
height: 28px !important;
|
|
|
padding: 4px 8px !important;
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
<style>
|
|
|
/* 分解表对话框样式 */
|
|
|
.submission-dialog {
|
|
|
margin-top: 5vh !important;
|
|
|
}
|
|
|
|
|
|
.submission-dialog .el-dialog__body {
|
|
|
padding: 10px 20px !important;
|
|
|
max-height: 80vh;
|
|
|
overflow-y: auto;
|
|
|
}
|
|
|
</style>
|