|
|
|
|
@ -111,8 +111,11 @@
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
|
|
<el-table-column fixed="right" label="操作" width="200">
|
|
|
|
|
<el-table-column fixed="right" label="操作" width="300">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<Button type="primary" @click="openEconomicClassifications(scope.row)" size="small" style="margin-right: 5px;" ghost>
|
|
|
|
|
经济分类
|
|
|
|
|
</Button>
|
|
|
|
|
<Button type="info" @click="edit(scope.row)" size="small" style="margin-right: 5px;" ghost>
|
|
|
|
|
编辑
|
|
|
|
|
</Button>
|
|
|
|
|
@ -232,6 +235,104 @@
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
<!-- 年度经济分类维护 -->
|
|
|
|
|
<el-dialog
|
|
|
|
|
:title="classificationDialogTitle"
|
|
|
|
|
:visible.sync="classificationDialogVisible"
|
|
|
|
|
width="760px"
|
|
|
|
|
append-to-body
|
|
|
|
|
>
|
|
|
|
|
<el-alert
|
|
|
|
|
v-if="!classificationEditable"
|
|
|
|
|
title="该预算年度已关闭,经济分类只能查看,不能修改。"
|
|
|
|
|
type="warning"
|
|
|
|
|
:closable="false"
|
|
|
|
|
show-icon
|
|
|
|
|
style="margin-bottom: 12px;"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<div class="classification-toolbar">
|
|
|
|
|
<el-button type="primary" size="small" :disabled="!classificationEditable" @click="openClassificationForm()">
|
|
|
|
|
新增分类
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="success"
|
|
|
|
|
size="small"
|
|
|
|
|
:disabled="!classificationEditable || classificationItems.length > 0"
|
|
|
|
|
@click="copyPreviousClassifications"
|
|
|
|
|
>
|
|
|
|
|
复制上一年度
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="warning"
|
|
|
|
|
size="small"
|
|
|
|
|
:disabled="!classificationEditable || !classificationOrderDirty"
|
|
|
|
|
:loading="savingClassificationOrder"
|
|
|
|
|
@click="saveClassificationOrder"
|
|
|
|
|
>
|
|
|
|
|
保存排序
|
|
|
|
|
</el-button>
|
|
|
|
|
<span class="classification-count">共 {{ classificationItems.length }} 项</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-table
|
|
|
|
|
v-loading="classificationLoading"
|
|
|
|
|
:data="classificationItems"
|
|
|
|
|
border
|
|
|
|
|
max-height="460"
|
|
|
|
|
empty-text="本年度暂无经济分类,可复制上一年度或手动新增"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="index" label="序号" width="70" align="center" />
|
|
|
|
|
<el-table-column prop="name" label="经济分类名称" min-width="260" />
|
|
|
|
|
<el-table-column prop="sort_order" label="排序" width="90" align="center" />
|
|
|
|
|
<el-table-column label="操作" width="250" align="center">
|
|
|
|
|
<template slot-scope="scope">
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
:disabled="!classificationEditable || scope.$index === 0"
|
|
|
|
|
@click="moveClassification(scope.$index, -1)"
|
|
|
|
|
>
|
|
|
|
|
上移
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="text"
|
|
|
|
|
:disabled="!classificationEditable || scope.$index === classificationItems.length - 1"
|
|
|
|
|
@click="moveClassification(scope.$index, 1)"
|
|
|
|
|
>
|
|
|
|
|
下移
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button type="text" :disabled="!classificationEditable" @click="openClassificationForm(scope.row)">
|
|
|
|
|
编辑
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button type="text" class="danger-text-button" :disabled="!classificationEditable" @click="deleteClassification(scope.row)">
|
|
|
|
|
删除
|
|
|
|
|
</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</el-table-column>
|
|
|
|
|
</el-table>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
|
|
|
|
|
<!-- 新增/编辑经济分类 -->
|
|
|
|
|
<el-dialog
|
|
|
|
|
:title="classificationForm.id ? '编辑经济分类' : '新增经济分类'"
|
|
|
|
|
:visible.sync="classificationFormVisible"
|
|
|
|
|
width="460px"
|
|
|
|
|
append-to-body
|
|
|
|
|
>
|
|
|
|
|
<el-form ref="classificationForm" :model="classificationForm" :rules="classificationRules" label-width="100px">
|
|
|
|
|
<el-form-item label="分类名称" prop="name">
|
|
|
|
|
<el-input v-model.trim="classificationForm.name" maxlength="100" show-word-limit />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<el-form-item label="排序序号" prop="sort_order">
|
|
|
|
|
<el-input-number v-model="classificationForm.sort_order" :min="1" :step="1" style="width: 100%;" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<div slot="footer">
|
|
|
|
|
<el-button @click="classificationFormVisible = false">取消</el-button>
|
|
|
|
|
<el-button type="primary" :loading="savingClassification" @click="submitClassification">确定</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
@ -239,11 +340,16 @@
|
|
|
|
|
import LxHeader from '@/components/LxHeader/index.vue'
|
|
|
|
|
import {
|
|
|
|
|
getBudgetCollectionYearList,
|
|
|
|
|
getBudgetCollectionYearDetail,
|
|
|
|
|
createBudgetCollectionYear,
|
|
|
|
|
updateBudgetCollectionYear,
|
|
|
|
|
deleteBudgetCollectionYear,
|
|
|
|
|
batchDeleteBudgetCollectionYear
|
|
|
|
|
batchDeleteBudgetCollectionYear,
|
|
|
|
|
getYearEconomicClassifications,
|
|
|
|
|
createYearEconomicClassification,
|
|
|
|
|
updateYearEconomicClassification,
|
|
|
|
|
deleteYearEconomicClassification,
|
|
|
|
|
reorderYearEconomicClassifications,
|
|
|
|
|
copyPreviousYearEconomicClassifications
|
|
|
|
|
} from '@/api/budget/budgetCollectionYear.js'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
@ -257,6 +363,29 @@ export default {
|
|
|
|
|
formLabelWidth: '120px',
|
|
|
|
|
loading: false,
|
|
|
|
|
submitting: false,
|
|
|
|
|
classificationDialogVisible: false,
|
|
|
|
|
classificationLoading: false,
|
|
|
|
|
classificationEditable: false,
|
|
|
|
|
classificationYear: null,
|
|
|
|
|
classificationItems: [],
|
|
|
|
|
classificationOrderDirty: false,
|
|
|
|
|
savingClassificationOrder: false,
|
|
|
|
|
classificationFormVisible: false,
|
|
|
|
|
savingClassification: false,
|
|
|
|
|
classificationForm: {
|
|
|
|
|
id: '',
|
|
|
|
|
name: '',
|
|
|
|
|
sort_order: 1
|
|
|
|
|
},
|
|
|
|
|
classificationRules: {
|
|
|
|
|
name: [
|
|
|
|
|
{ required: true, message: '请输入经济分类名称', trigger: 'blur' },
|
|
|
|
|
{ max: 100, message: '经济分类名称不能超过100个字符', trigger: 'blur' }
|
|
|
|
|
],
|
|
|
|
|
sort_order: [
|
|
|
|
|
{ required: true, message: '请输入排序序号', trigger: 'change' }
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
selectedRows: [],
|
|
|
|
|
form: {
|
|
|
|
|
id: '',
|
|
|
|
|
@ -319,6 +448,11 @@ export default {
|
|
|
|
|
computed: {
|
|
|
|
|
dialogTitle() {
|
|
|
|
|
return this.form.id ? '编辑预算采集年份' : '新增预算采集年份'
|
|
|
|
|
},
|
|
|
|
|
classificationDialogTitle() {
|
|
|
|
|
return this.classificationYear
|
|
|
|
|
? `${this.classificationYear.year}年度经济分类`
|
|
|
|
|
: '年度经济分类'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
created() {
|
|
|
|
|
@ -482,6 +616,147 @@ export default {
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async openEconomicClassifications(row) {
|
|
|
|
|
this.classificationYear = { ...row }
|
|
|
|
|
this.classificationDialogVisible = true
|
|
|
|
|
await this.loadEconomicClassifications()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async loadEconomicClassifications() {
|
|
|
|
|
if (!this.classificationYear) return
|
|
|
|
|
this.classificationLoading = true
|
|
|
|
|
try {
|
|
|
|
|
const response = await getYearEconomicClassifications(this.classificationYear.id)
|
|
|
|
|
this.classificationItems = (response.items || []).map(item => ({ ...item }))
|
|
|
|
|
this.classificationEditable = response.editable === true
|
|
|
|
|
this.classificationOrderDirty = false
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
this.classificationItems = []
|
|
|
|
|
} finally {
|
|
|
|
|
this.classificationLoading = false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
openClassificationForm(row) {
|
|
|
|
|
if (!this.classificationEditable) return
|
|
|
|
|
this.classificationForm = row
|
|
|
|
|
? { id: row.id, name: row.name, sort_order: row.sort_order }
|
|
|
|
|
: {
|
|
|
|
|
id: '',
|
|
|
|
|
name: '',
|
|
|
|
|
sort_order: Math.max(0, ...this.classificationItems.map(item => Number(item.sort_order) || 0)) + 1
|
|
|
|
|
}
|
|
|
|
|
this.classificationFormVisible = true
|
|
|
|
|
this.$nextTick(() => this.$refs.classificationForm && this.$refs.classificationForm.clearValidate())
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submitClassification() {
|
|
|
|
|
this.$refs.classificationForm.validate(async valid => {
|
|
|
|
|
if (!valid || !this.classificationYear) return
|
|
|
|
|
this.savingClassification = true
|
|
|
|
|
try {
|
|
|
|
|
const data = {
|
|
|
|
|
name: this.classificationForm.name,
|
|
|
|
|
sort_order: this.classificationForm.sort_order
|
|
|
|
|
}
|
|
|
|
|
if (this.classificationForm.id) {
|
|
|
|
|
await updateYearEconomicClassification(this.classificationYear.id, this.classificationForm.id, data)
|
|
|
|
|
this.$Message.success('经济分类修改成功')
|
|
|
|
|
} else {
|
|
|
|
|
await createYearEconomicClassification(this.classificationYear.id, data)
|
|
|
|
|
this.$Message.success('经济分类新增成功')
|
|
|
|
|
}
|
|
|
|
|
this.classificationFormVisible = false
|
|
|
|
|
await this.loadEconomicClassifications()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
} finally {
|
|
|
|
|
this.savingClassification = false
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
moveClassification(index, offset) {
|
|
|
|
|
const targetIndex = index + offset
|
|
|
|
|
if (targetIndex < 0 || targetIndex >= this.classificationItems.length) return
|
|
|
|
|
const items = [...this.classificationItems]
|
|
|
|
|
const moved = items.splice(index, 1)[0]
|
|
|
|
|
items.splice(targetIndex, 0, moved)
|
|
|
|
|
this.classificationItems = items.map((item, itemIndex) => ({
|
|
|
|
|
...item,
|
|
|
|
|
sort_order: itemIndex + 1
|
|
|
|
|
}))
|
|
|
|
|
this.classificationOrderDirty = true
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
async saveClassificationOrder() {
|
|
|
|
|
if (!this.classificationYear || !this.classificationOrderDirty) return
|
|
|
|
|
this.savingClassificationOrder = true
|
|
|
|
|
try {
|
|
|
|
|
const items = this.classificationItems.map(item => ({ id: item.id, sort_order: item.sort_order }))
|
|
|
|
|
await reorderYearEconomicClassifications(this.classificationYear.id, items)
|
|
|
|
|
this.$Message.success('排序保存成功')
|
|
|
|
|
await this.loadEconomicClassifications()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
} finally {
|
|
|
|
|
this.savingClassificationOrder = false
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
deleteClassification(row) {
|
|
|
|
|
if (!this.classificationYear) return
|
|
|
|
|
this.$confirm(
|
|
|
|
|
`确认删除经济分类“${row.name}”吗?已被预算填报使用的分类不能删除。`,
|
|
|
|
|
'确认删除',
|
|
|
|
|
{
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning',
|
|
|
|
|
closeOnClickModal: false
|
|
|
|
|
}
|
|
|
|
|
).then(async() => {
|
|
|
|
|
try {
|
|
|
|
|
await deleteYearEconomicClassification(this.classificationYear.id, row.id)
|
|
|
|
|
this.$Message.success('删除成功')
|
|
|
|
|
await this.loadEconomicClassifications()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
}
|
|
|
|
|
}).catch(action => {
|
|
|
|
|
if (action !== 'cancel' && action !== 'close') {
|
|
|
|
|
console.error(action)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
copyPreviousClassifications() {
|
|
|
|
|
if (!this.classificationYear) return
|
|
|
|
|
this.$confirm(
|
|
|
|
|
`将最近一个更早年度的全部经济分类复制到${this.classificationYear.year}年度。该操作仅允许在本年度分类为空时执行,是否继续?`,
|
|
|
|
|
'复制上一年度经济分类',
|
|
|
|
|
{
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning',
|
|
|
|
|
closeOnClickModal: false
|
|
|
|
|
}
|
|
|
|
|
).then(async() => {
|
|
|
|
|
try {
|
|
|
|
|
const response = await copyPreviousYearEconomicClassifications(this.classificationYear.id)
|
|
|
|
|
this.$Message.success(`已从${response.source_year}年度复制${response.copied_count}项经济分类`)
|
|
|
|
|
await this.loadEconomicClassifications()
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error)
|
|
|
|
|
}
|
|
|
|
|
}).catch(action => {
|
|
|
|
|
if (action !== 'cancel' && action !== 'close') {
|
|
|
|
|
console.error(action)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
getDefaultForm() {
|
|
|
|
|
return {
|
|
|
|
|
id: '',
|
|
|
|
|
@ -538,6 +813,21 @@ export default {
|
|
|
|
|
padding: 12px 16px 16px 16px; /* 紧凑布局 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.classification-toolbar {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.classification-count {
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
color: #909399;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.danger-text-button {
|
|
|
|
|
color: #f56c6c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.v-table {
|
|
|
|
|
border: 1px solid #e6e6e6;
|
|
|
|
|
}
|
|
|
|
|
@ -572,4 +862,4 @@ export default {
|
|
|
|
|
.el-tag {
|
|
|
|
|
margin-right: 5px;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
</style>
|
|
|
|
|
|