|
|
@@ -5,7 +5,7 @@
|
|
|
ref="auditForm"
|
|
|
:model="auditForm"
|
|
|
:rules="rules"
|
|
|
- :disabled="hasTableData"
|
|
|
+ :disabled="isSaved"
|
|
|
>
|
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="8">
|
|
|
@@ -65,20 +65,9 @@
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
- <el-row v-if="!hasTableData" :gutter="20">
|
|
|
- <el-col :span="16">
|
|
|
- <el-form-item label="新模板名称" prop="surveyTemplateName">
|
|
|
- <el-input
|
|
|
- v-model="auditForm.surveyTemplateName"
|
|
|
- placeholder="请输入新的核定表模板名称"
|
|
|
- clearable
|
|
|
- ></el-input>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
</el-form>
|
|
|
<el-button
|
|
|
- v-if="!hasTableData"
|
|
|
+ v-if="!isSaved"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
:loading="loading"
|
|
|
@@ -87,15 +76,15 @@
|
|
|
生成核定表
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="!hasUploadData"
|
|
|
+ v-if="hasTableData && !isSaved"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="handleSaveTemplate"
|
|
|
>
|
|
|
- 保存核定模板
|
|
|
+ 保存模板
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="showButtons"
|
|
|
+ v-if="isSaved"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="handleExportTemplate"
|
|
|
@@ -103,7 +92,7 @@
|
|
|
导出模板
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="showButtons"
|
|
|
+ v-if="isSaved"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="handleImportData"
|
|
|
@@ -111,7 +100,7 @@
|
|
|
导入数据
|
|
|
</el-button>
|
|
|
<el-button
|
|
|
- v-if="showButtons"
|
|
|
+ v-if="isSaved"
|
|
|
type="primary"
|
|
|
size="small"
|
|
|
@click="handleSaveData"
|
|
|
@@ -303,7 +292,7 @@
|
|
|
</template>
|
|
|
</el-table-column> -->
|
|
|
<el-table-column
|
|
|
- v-if="!hasUploadData"
|
|
|
+ v-if="!isSaved && !hasUploadData"
|
|
|
prop="action"
|
|
|
label="操作"
|
|
|
width="100"
|
|
|
@@ -345,6 +334,7 @@
|
|
|
batchSaveOrUpdate,
|
|
|
getCostVerifyTemplate,
|
|
|
clearCostVerifyData,
|
|
|
+ previewCostVerifyTemplate,
|
|
|
} from '@/api/costFormManage'
|
|
|
import {
|
|
|
getlistBySurveyTemplateId,
|
|
|
@@ -408,7 +398,6 @@
|
|
|
// 成本调查表模板列表
|
|
|
surveyFormList: [],
|
|
|
auditForm: {
|
|
|
- surveyTemplateName: '',
|
|
|
surveyTemplateId: '',
|
|
|
templateType: '',
|
|
|
dataTable: '',
|
|
|
@@ -419,10 +408,14 @@
|
|
|
catalogId: [
|
|
|
{ required: true, message: '请输选择监审类别', trigger: 'change' },
|
|
|
],
|
|
|
- surveyTemplateName: [
|
|
|
- { required: true, message: '请输入新的核定表模板名称', trigger: 'blur' },
|
|
|
- ],
|
|
|
},
|
|
|
+ // 当前预览的源模板信息
|
|
|
+ currentPreviewSource: {
|
|
|
+ templateId: '',
|
|
|
+ templateType: ''
|
|
|
+ },
|
|
|
+ // 是否已保存到数据库
|
|
|
+ isSaved: false,
|
|
|
tableHeadersRes: [],
|
|
|
tableDataRes: [],
|
|
|
// 成本审核表格列配置
|
|
|
@@ -430,7 +423,7 @@
|
|
|
// 成本审核数据
|
|
|
costAuditData: [],
|
|
|
project: {},
|
|
|
- // 是否已有上传数据(用于控制“生成核定表”按钮显示隐藏)
|
|
|
+ // 是否已有上传数据(用于控制"生成核定表"按钮显示隐藏)
|
|
|
hasUploadData: false,
|
|
|
// 防重与去重:避免重复请求 getSurveyDetail
|
|
|
echoInProgress: false,
|
|
|
@@ -578,7 +571,7 @@
|
|
|
if (!res || res.code !== 200) return false
|
|
|
const v = res.value || {}
|
|
|
// 若后端返回 code=200 但 value=null:说明任务下尚未生成/绑定模板
|
|
|
- // 此时必须保持空表(不再走任何兜底加载),避免出现“value=null 但仍有表头”的问题
|
|
|
+ // 此时必须保持空表(不再走任何兜底加载),避免出现"value=null 但仍有表头"的问题
|
|
|
if (!res.value) {
|
|
|
if (this.auditForm) {
|
|
|
this.auditForm.surveyTemplateId = ''
|
|
|
@@ -587,8 +580,13 @@
|
|
|
// 保持 templateType 由用户自行选择
|
|
|
}
|
|
|
this.resetAuditTableState()
|
|
|
+ this.isSaved = false
|
|
|
return 'EMPTY'
|
|
|
}
|
|
|
+
|
|
|
+ // 如果获取到了数据,说明该任务已经有核定表了,标记为已保存状态
|
|
|
+ this.isSaved = true
|
|
|
+
|
|
|
// 兼容不同字段命名:createTemplateId/createMode 或 createtemplateid/createmode
|
|
|
const createMode = v.createMode != null ? v.createMode : v.createmode
|
|
|
// 生成模板依赖模型id(用于UI来源选择的回显)
|
|
|
@@ -688,6 +686,61 @@
|
|
|
this.loadHistoryTemplateOptions()
|
|
|
}
|
|
|
},
|
|
|
+ // 点击"生成核定表"按钮,加载数据显示
|
|
|
+ handleGenerateTemplate() {
|
|
|
+ // 校验是否选择了生成方式
|
|
|
+ if (!this.auditForm || !this.auditForm.templateType) {
|
|
|
+ this.$message.error('请先选择核定表生成方式')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验是否选择了源模板
|
|
|
+ const sourceTemplateId = this.auditForm.templateType === '1'
|
|
|
+ ? this.auditForm.dataTable
|
|
|
+ : this.auditForm.historyTemplate
|
|
|
+
|
|
|
+ if (!sourceTemplateId) {
|
|
|
+ this.$message.error('请选择源模板')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加载数据显示
|
|
|
+ this.loadPreviewData(sourceTemplateId, this.auditForm.templateType)
|
|
|
+ },
|
|
|
+ // 加载数据显示(手动触发)
|
|
|
+ async loadPreviewData(templateId, templateType) {
|
|
|
+ try {
|
|
|
+ this.loading = true
|
|
|
+ const taskId = (this.selectedProject && this.selectedProject.taskId) || ''
|
|
|
+
|
|
|
+ // 调用后端预览接口
|
|
|
+ const resp = await previewCostVerifyTemplate({
|
|
|
+ templateId: templateId,
|
|
|
+ catalogId: this.catalogId,
|
|
|
+ taskId: taskId,
|
|
|
+ templateType: templateType
|
|
|
+ })
|
|
|
+
|
|
|
+ if (resp && resp.code === 200 && resp.value) {
|
|
|
+ // 记录当前的源模板
|
|
|
+ this.currentPreviewSource = {
|
|
|
+ templateId: templateId,
|
|
|
+ templateType: templateType
|
|
|
+ }
|
|
|
+
|
|
|
+ // 渲染数据
|
|
|
+ await this.renderPreviewData({
|
|
|
+ headers: resp.value.headers || [],
|
|
|
+ items: resp.value.items || []
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('加载数据失败:', error)
|
|
|
+ this.$message.error('加载数据失败:' + (error.message || '未知错误'))
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
async loadSurveyFormOptions() {
|
|
|
try {
|
|
|
const res = await getActiveCostVerifyFormListByType({
|
|
|
@@ -732,48 +785,62 @@
|
|
|
this.auditFormList = []
|
|
|
}
|
|
|
},
|
|
|
- handleGenerateTemplate() {
|
|
|
- // 先校验是否选择了"核定表生成方式"
|
|
|
- if (!this.auditForm || !this.auditForm.templateType) {
|
|
|
- this.$message.error('请先选择核定表生成方式')
|
|
|
- return
|
|
|
- }
|
|
|
- // 校验是否输入了模板名称
|
|
|
- if (!this.auditForm.surveyTemplateName || !this.auditForm.surveyTemplateName.trim()) {
|
|
|
- this.$message.error('请输入新的核定表模板名称')
|
|
|
- return
|
|
|
- }
|
|
|
- this.$confirm(
|
|
|
- '核定表生成后,不再支持修改生成方式。确定生成模板吗?',
|
|
|
- '提示',
|
|
|
- {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning',
|
|
|
+ async renderPreviewData(data) {
|
|
|
+ // 解析表头
|
|
|
+ const headersRes = { code: 200, value: data.headers }
|
|
|
+ await this.parseAndDisplayTableHeaders(headersRes)
|
|
|
+
|
|
|
+ // 将"单元格列表"转换为"行对象列表"
|
|
|
+ const rowsMap = new Map()
|
|
|
+ const headers = data.headers || []
|
|
|
+
|
|
|
+ // 创建表头名称到字段的映射
|
|
|
+ const nameToHeader = new Map()
|
|
|
+ headers.forEach((h) => {
|
|
|
+ if (h && (h.fieldName || h.label)) {
|
|
|
+ nameToHeader.set(String(h.fieldName || h.label), h)
|
|
|
}
|
|
|
- ).then(() => {
|
|
|
- this.$refs['auditForm'].validate((valid) => {
|
|
|
- if (!valid) {
|
|
|
- this.$message.error('请填写表单数据')
|
|
|
- return
|
|
|
- }
|
|
|
- if (this.auditForm.templateType === '1') {
|
|
|
- if (!this.auditForm.dataTable) {
|
|
|
- this.$message.error('请选择成本调查表模板')
|
|
|
- return
|
|
|
- }
|
|
|
- this.generateFromSurveyTemplate()
|
|
|
- } else if (this.auditForm.templateType === '2') {
|
|
|
- if (!this.auditForm.historyTemplate) {
|
|
|
- this.$message.error('请选择历史核定模板')
|
|
|
- return
|
|
|
- }
|
|
|
- this.generateFromHistoryTemplate()
|
|
|
- } else {
|
|
|
- this.$message.error('请选择模板来源方式')
|
|
|
- }
|
|
|
- })
|
|
|
})
|
|
|
+
|
|
|
+ // 按 rowid 分组
|
|
|
+ data.items.forEach((item) => {
|
|
|
+ const rowId = item.rowid != null ? String(item.rowid) : ''
|
|
|
+ if (!rowId) return
|
|
|
+
|
|
|
+ if (!rowsMap.has(rowId)) {
|
|
|
+ rowsMap.set(rowId, {
|
|
|
+ rowid: rowId,
|
|
|
+ parentid: item.parentid != null ? String(item.parentid) : '-1',
|
|
|
+ orderNum: item.orderNum,
|
|
|
+ id: item.id,
|
|
|
+ surveyTemplateId: item.surveyTemplateId,
|
|
|
+ versionId: item.versionId,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const row = rowsMap.get(rowId)
|
|
|
+ const rkey = item.rkey != null ? String(item.rkey) : ''
|
|
|
+ const rvalue = item.rvalue != null ? String(item.rvalue) : ''
|
|
|
+
|
|
|
+ // 根据 rkey 找到对应的表头
|
|
|
+ const header = nameToHeader.get(rkey)
|
|
|
+ if (header && header.fieldEname) {
|
|
|
+ // 使用 fieldEname 作为属性名
|
|
|
+ row[header.fieldEname] = rvalue
|
|
|
+ // 同时保存中文列名,兼容性
|
|
|
+ row[header.fieldName] = rvalue
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 转换为数组
|
|
|
+ const rowsList = Array.from(rowsMap.values())
|
|
|
+
|
|
|
+ // 解析数据
|
|
|
+ const itemsRes = { code: 200, value: { itemlist: rowsList } }
|
|
|
+ this.parseAndDisplayTableData(itemsRes)
|
|
|
+
|
|
|
+ // 计算核定值
|
|
|
+ this.computeApprovedForAllRows()
|
|
|
},
|
|
|
async generateFromSurveyTemplate() {
|
|
|
try {
|
|
|
@@ -1401,40 +1468,122 @@
|
|
|
}
|
|
|
},
|
|
|
handleSaveTemplate(type) {
|
|
|
- // 显示加载状态
|
|
|
- this.$loading({
|
|
|
+ // 弹窗输入模板名称
|
|
|
+ this.$prompt('请输入新的核定表模板名称', '保存模板', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ inputPattern: /\S+/,
|
|
|
+ inputErrorMessage: '模板名称不能为空',
|
|
|
+ inputPlaceholder: '请输入模板名称'
|
|
|
+ }).then(({ value: templateName }) => {
|
|
|
+ this.saveTemplateWithName(templateName)
|
|
|
+ }).catch(() => {
|
|
|
+ this.$message.info('已取消保存')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async saveTemplateWithName(templateName) {
|
|
|
+ const loading = this.$loading({
|
|
|
lock: true,
|
|
|
- text: '保存数据中...',
|
|
|
+ text: '生成模板中...',
|
|
|
spinner: 'el-icon-loading',
|
|
|
background: 'rgba(0, 0, 0, 0.7)',
|
|
|
})
|
|
|
- // 加上遮罩层
|
|
|
- const headersList = this.tableHeadersRes.map((header, index) => ({
|
|
|
- ...header,
|
|
|
- orderNum: header.orderNum || index + 1,
|
|
|
- }))
|
|
|
- let splitData = this.splitFixedTableDataForSave(this.costAuditData)
|
|
|
- let data = {
|
|
|
- costVerifyTemplateId: this.auditForm.surveyTemplateId,
|
|
|
- headersList: headersList,
|
|
|
- itemsList: splitData,
|
|
|
+
|
|
|
+ try {
|
|
|
+ const taskId = (this.selectedProject && this.selectedProject.taskId) || ''
|
|
|
+
|
|
|
+ // 调用后端生成模板接口(真正保存到数据库)
|
|
|
+ const resp = await this.generateTemplateToDatabase({
|
|
|
+ catalogId: this.catalogId,
|
|
|
+ templatename: templateName,
|
|
|
+ templateId: this.currentPreviewSource.templateId,
|
|
|
+ taskId: taskId,
|
|
|
+ templateType: this.currentPreviewSource.templateType
|
|
|
+ })
|
|
|
+
|
|
|
+ const newTemplateId = resp?.value?.surveyTemplateId || ''
|
|
|
+
|
|
|
+ if (!newTemplateId) {
|
|
|
+ throw new Error('生成模板失败:未返回模板ID')
|
|
|
+ }
|
|
|
+
|
|
|
+ this.$message.success('模板生成成功')
|
|
|
+
|
|
|
+ // 标记为已保存
|
|
|
+ this.isSaved = true
|
|
|
+
|
|
|
+ // 更新当前模板ID
|
|
|
+ this.auditForm.surveyTemplateId = newTemplateId
|
|
|
+
|
|
|
+ // 重新加载数据
|
|
|
+ await this.loadTemplateDataForEdit(newTemplateId)
|
|
|
+
|
|
|
+ // 检查按钮显示权限
|
|
|
+ await this.checkButtonVisibility()
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error('生成模板失败:', error)
|
|
|
+ this.$message.error('生成模板失败:' + (error.message || '未知错误'))
|
|
|
+ } finally {
|
|
|
+ loading.close()
|
|
|
}
|
|
|
- batchSaveOrUpdate(data)
|
|
|
- .then(async (data) => {
|
|
|
- // 关闭加载状态
|
|
|
- this.$loading().close()
|
|
|
- if (type != 'delete') {
|
|
|
- this.$message.success('保存成功')
|
|
|
- await this.checkButtonVisibility()
|
|
|
- this.loadTemplateData()
|
|
|
- // 保存成功后重新检查按钮显示权限
|
|
|
- }
|
|
|
+ },
|
|
|
+ async generateTemplateToDatabase(params) {
|
|
|
+ if (params.templateType === '1') {
|
|
|
+ // 从调查表生成
|
|
|
+ return await generateCostVerifyForm({
|
|
|
+ catalogId: params.catalogId,
|
|
|
+ templatename: params.templatename,
|
|
|
+ templateId: params.templateId,
|
|
|
+ taskId: params.taskId,
|
|
|
})
|
|
|
- .catch((err) => {
|
|
|
- // 关闭加载状态
|
|
|
- this.$loading().close()
|
|
|
- console.log(err)
|
|
|
+ } else {
|
|
|
+ // 从历史核定表生成
|
|
|
+ return await generateCostVerifyFormData({
|
|
|
+ catalogId: params.catalogId,
|
|
|
+ templatename: params.templatename,
|
|
|
+ templateId: params.templateId,
|
|
|
+ taskId: params.taskId,
|
|
|
})
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async saveExistingTemplate(type) {
|
|
|
+ // 显示加载状态
|
|
|
+ const loading = this.$loading({
|
|
|
+ lock: true,
|
|
|
+ text: '保存数据中...',
|
|
|
+ spinner: 'el-icon-loading',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)',
|
|
|
+ })
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 加上遮罩层
|
|
|
+ const headersList = this.tableHeadersRes.map((header, index) => ({
|
|
|
+ ...header,
|
|
|
+ orderNum: header.orderNum || index + 1,
|
|
|
+ }))
|
|
|
+ let splitData = this.splitFixedTableDataForSave(this.costAuditData)
|
|
|
+ let data = {
|
|
|
+ costVerifyTemplateId: this.auditForm.surveyTemplateId,
|
|
|
+ headersList: headersList,
|
|
|
+ itemsList: splitData,
|
|
|
+ }
|
|
|
+
|
|
|
+ await batchSaveOrUpdate(data)
|
|
|
+
|
|
|
+ // 关闭加载状态
|
|
|
+ loading.close()
|
|
|
+ if (type != 'delete') {
|
|
|
+ this.$message.success('保存成功')
|
|
|
+ await this.checkButtonVisibility()
|
|
|
+ this.loadTemplateData && this.loadTemplateData()
|
|
|
+ // 保存成功后重新检查按钮显示权限
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ // 关闭加载状态
|
|
|
+ loading.close()
|
|
|
+ console.log(err)
|
|
|
+ }
|
|
|
},
|
|
|
async handleSaveData() {
|
|
|
const loading = this.$loading({
|