Browse Source

三级校审复核问题汇总部分代码

徐滕 2 weeks ago
parent
commit
8f09c2786f

+ 45 - 6
src/views/program/registered/ProjectList.vue

@@ -481,6 +481,7 @@ import UserSelect from '@/views/utils/UserTreeSelect'
 // 一级校审修改
 import ProjectThreeAuditFormEditDialog from './ProjectThreeAuditFormEditDialog'
 import InvoiceForm from '@/views/finance/invoice/InvoiceForm'
+import IssueRecordService from '@/api/program/IssueRecordService'
 export default {
 	data() {
 		return {
@@ -549,6 +550,7 @@ export default {
 		// this.processService = new ProcessService()
 		// this.userService = new UserService()
 		this.proofreadIssuedService = new ProofreadIssuedService()
+		this.issueRecordService = new IssueRecordService()
 	},
 	components: {
 		ProjectForm,
@@ -1526,14 +1528,47 @@ export default {
 			}
 			return false
 		},
+		// 检查并显示漏洞提醒
+		checkAndShowReminders(auditLevel, callback) {
+			const currentUserId = this.$store.state.user.id
+			this.issueRecordService.getReminders(currentUserId, auditLevel).then((data) => {
+				if (data && data.length > 0) {
+					let reminderHtml = '<div style="text-align: left;">'
+					data.forEach((item, index) => {
+						reminderHtml += `<p style="margin: 8px 0;"><strong>${index + 1}. ${item.issueName}</strong>(已标记${item.markCount}次,阈值${item.threshold}次)</p>`
+						if (item.suggestion) {
+							reminderHtml += `<p style="margin: 0 0 8px 20px; color: #606266;">建议:${item.suggestion}</p>`
+						}
+					})
+					reminderHtml += '</div>'
+					this.$confirm(reminderHtml, '⚠️ 常见漏洞提醒', {
+						confirmButtonText: '知道了',
+						type: 'warning',
+						dangerouslyUseHTMLString: true,
+						showCancelButton: false,
+						closeOnClickModal: false
+					}).then(() => {
+						callback()
+					}).catch(() => {
+						callback()
+					})
+				} else {
+					callback()
+				}
+			}).catch(() => {
+				callback()
+			})
+		},
 		// 驳回后调整  一级校审
 		adjustFirst(row) {
 			this.programProjectListInfoService.findByIdAudit(row.auditId1).then((data) => {
-				if (data.status !== '4') { // status的值不等于“驳回”,就弹出提示
+				if (data.status !== '4') { // status的值不等于”驳回”,就弹出提示
 					this.$message.error('数据已发生改变或不存在,请刷新数据')
 					this.refreshList()
 				} else {
-					this.todoFirst(row)
+					this.checkAndShowReminders('1', () => {
+						this.todoFirst(row)
+					})
 				}
 			})
 		},
@@ -1583,11 +1618,13 @@ export default {
 		// 驳回后调整  二级校审
 		adjustSecond(row) {
 			this.programProjectListInfoService.findByIdAudit(row.auditId2).then((data) => {
-				if (data.status !== '4') { // status的值不等于“驳回”,就弹出提示
+				if (data.status !== '4') { // status的值不等于”驳回”,就弹出提示
 					this.$message.error('数据已发生改变或不存在,请刷新数据')
 					this.refreshList()
 				} else {
-					this.todoSecond(row)
+					this.checkAndShowReminders('2', () => {
+						this.todoSecond(row)
+					})
 				}
 			})
 		},
@@ -1637,11 +1674,13 @@ export default {
 		// 驳回后调整  三级校审
 		adjustThird(row) {
 			this.programProjectListInfoService.findByIdAudit(row.auditId3).then((data) => {
-				if (data.status !== '4') { // status的值不等于“驳回”,就弹出提示
+				if (data.status !== '4') { // status的值不等于”驳回”,就弹出提示
 					this.$message.error('数据已发生改变或不存在,请刷新数据')
 					this.refreshList()
 				} else {
-					this.todoThird(row)
+					this.checkAndShowReminders('3', () => {
+						this.todoThird(row)
+					})
 				}
 			})
 		},

+ 63 - 3
src/views/program/registered/ProjectThreeAuditFormEditDialog.vue

@@ -166,6 +166,27 @@
             </el-col>
           </el-row>
 
+          <!-- 常见漏洞标记 -->
+          <el-divider content-position="left"><i class="el-icon-warning"></i> 常见漏洞标记(选填)</el-divider>
+          <el-row>
+            <el-col :span="24">
+              <div v-if="commonIssueList.length > 0" style="padding: 0 10px;">
+                <div v-for="(issues, category) in groupedIssues" :key="category" style="margin-bottom: 12px;">
+                  <div style="font-weight: bold; color: #606266; margin-bottom: 6px; font-size: 14px;">{{ category }}</div>
+                  <el-checkbox-group v-model="selectedIssueIds" :disabled="status === 'taskFormDetail' || method === 'view'">
+                    <el-checkbox v-for="issue in issues" :key="issue.id" :label="issue.id"
+                                 style="display: block; margin-bottom: 4px; margin-left: 10px;">
+                      {{ issue.issueName }}
+                      <el-tooltip v-if="issue.issueDesc" :content="issue.issueDesc" placement="top">
+                        <el-icon style="color: #909399; cursor: help;"><info-filled /></el-icon>
+                      </el-tooltip>
+                    </el-checkbox>
+                  </el-checkbox-group>
+                </div>
+              </div>
+              <div v-else style="color: #909399; padding: 10px;">暂无适用的常见漏洞</div>
+            </el-col>
+          </el-row>
 
         </el-form>
         <!--        附件-->
@@ -200,6 +221,9 @@ import ProjectThreeAuditFormDialog from './ProjectThreeAuditFormDialog'
 import UserSelect1 from '@/views/utils/UserTreeSelect'
 import UserSelect2 from '@/views/utils/UserTreeSelect'
 import UserSelect3 from '@/views/utils/UserTreeSelect'
+import CommonIssueService from '@/api/program/CommonIssueService'
+import IssueRecordService from '@/api/program/IssueRecordService'
+import { InfoFilled } from '@element-plus/icons-vue'
 
 export default {
   props: {
@@ -251,12 +275,18 @@ export default {
       programId: '',
       supervisorList: [],
       keyWatch: '',
-      tabName: ''
+      tabName: '',
+      commonIssueList: [],
+      selectedIssueIds: []
     }
   },
   programProjectListInfoService: null,
+  commonIssueService: null,
+  issueRecordService: null,
   created() {
     this.programProjectListInfoService = new ProgramProjectListInfoService()
+    this.commonIssueService = new CommonIssueService()
+    this.issueRecordService = new IssueRecordService()
   },
   computed: {
     bus: {
@@ -267,6 +297,15 @@ export default {
       set(val) {
         this.businessId = val
       }
+    },
+    groupedIssues () {
+      const groups = {}
+      this.commonIssueList.forEach(issue => {
+        const cat = issue.category || '其他'
+        if (!groups[cat]) groups[cat] = []
+        groups[cat].push(issue)
+      })
+      return groups
     }
   },
   watch: {
@@ -300,7 +339,8 @@ export default {
     ProjectThreeAuditFormDialog,
     UserSelect1,
     UserSelect2,
-    UserSelect3
+    UserSelect3,
+    InfoFilled
   },
   methods: {
     getKeyWatch(keyWatch) {
@@ -393,6 +433,11 @@ export default {
           } else {
             this.$refs.uploadComponent.newUpload('view', this.inputForm.workAttachmentDtoList, 'program_audit', 500, null, true, this.$store.state.user.name)
           }
+          // 加载常见漏洞列表
+          this.commonIssueService.getEnabledList(this.inputForm.auditLevel).then((data) => {
+            this.commonIssueList = data || []
+            this.selectedIssueIds = []
+          })
           this.loading = false
         })
       })
@@ -418,7 +463,20 @@ export default {
         this.inputForm.programAuditAssessPeopleDtoList = []
       }
       this.programProjectListInfoService.saveFormThree(this.inputForm).then((data) => {
-        this.$message.success('操作成功')
+        // 保存常见漏洞标记
+        if (this.selectedIssueIds && this.selectedIssueIds.length > 0) {
+          this.issueRecordService.saveRecords({
+            projectId: this.inputForm.programId,
+            auditId: this.inputForm.id,
+            auditLevel: this.inputForm.auditLevel,
+            issueIds: this.selectedIssueIds,
+            targetUserId: this.inputForm.programProjectListInfo.projectManager || this.inputForm.programProjectListInfo.createBy
+          }).then(() => {
+            this.$message.success('操作成功')
+          }).catch(() => {})
+        } else {
+          this.$message.success('操作成功')
+        }
         this.loading = false
         this.$emit('refreshDataList')
         this.close()
@@ -457,6 +515,8 @@ export default {
         auditPeopleList: '',
         auditPeopleListName: ''
       }
+      this.commonIssueList = []
+      this.selectedIssueIds = []
       this.$refs.inputForm.resetFields()
       this.visible = false
     },

+ 149 - 0
src/views/zs/reimbursement/info/ImportDialog.vue

@@ -0,0 +1,149 @@
+<template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
+	<div>
+		<el-dialog :title="title" :close-on-click-modal="false" draggable width="1000px" height="500px" @close="close"
+			append-to-body v-model="visible">
+			<el-form :model="inputForm" ref="inputForm" label-width="135px" @submit.native.prevent>
+				<el-row :gutter="0">
+				</el-row>
+				<el-row :gutter="0">
+					<el-col :span="24">
+						<el-form-item label="附件上传:">
+							<el-upload ref="upload" :on-remove="handleRemove" action="" :limit="1" :auto-upload="false"
+								:on-change="beforeUploadDetail" :show-file-list="true" accept=".xlsx,.xls">
+								<el-button type="primary">点击上传Excel文件</el-button>
+							</el-upload>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button type="warning" @click="downloadTpl()" plain>下载模板</el-button>
+					<el-button @click="close()" icon="el-icon-circle-close">关闭</el-button>
+					<el-button type="primary" icon="el-icon-circle-check" @click="doSubmit()">确定</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+import ReimbursementService from '@/api/zs/reimbursement/ReimbursementService'
+
+export default {
+	name: 'ZsImportDialog',
+	emits: ['refreshDataList', 'import-error'],
+	data() {
+		return {
+			visible: false,
+			title: '',
+			inputForm: {
+				file: []
+			},
+			reimbursementService: null,
+		}
+	},
+	created() {
+		this.reimbursementService = new ReimbursementService()
+	},
+	components: {},
+	methods: {
+		init() {
+			this.visible = true
+			this.title = '中审报销数据导入'
+			this.inputForm = {
+				file: []
+			}
+			this.$forceUpdate()
+		},
+		handleRemove() {
+			this.inputForm.file.pop()
+		},
+		beforeUploadDetail(file) {
+			this.inputForm.file.push(file)
+		},
+		// 下载模板
+		downloadTpl() {
+			const loading = this.$loading({
+				lock: true,
+				text: '模板下载中,请稍后',
+				spinner: 'el-icon-loading',
+				background: 'rgba(255, 255, 255, 0.3)'
+			});
+			this.reimbursementService.importTemplate().then((res) => {
+				this.$utils.downloadExcel(res, '中审报销导入模板.xlsx')
+				loading.close()
+			}).catch(function (err) {
+				loading.close()
+				if (err.response) {
+					console.log(err.response)
+				}
+			})
+		},
+		// 确定导入
+		doSubmit() {
+			if (this.inputForm.file.length == 0) {
+				this.$message.warning('未上传文件,无法提交导入')
+				return
+			}
+			const loading = this.$loading({
+				lock: true,
+				text: '导入中,请稍后',
+				spinner: 'el-icon-loading',
+				background: 'rgba(255, 255, 255, 0.3)'
+			});
+			const formBody = new FormData()
+			formBody.append('file', this.inputForm.file[0].raw)
+
+			this.reimbursementService.importFile(formBody).then((data) => {
+				loading.close()
+				console.log("导入返回数据:", data)
+
+				// 有错误文件 → 通知父页面处理
+				if (data && data.errorFilePath) {
+					this.$emit('import-error', data)
+					if (data.failCount > 0 && data.successCount > 0) {
+						this.$message.warning(`部分导入成功:成功 ${data.successCount} 条,失败 ${data.failCount} 条,请下载查看错误详情`)
+						this.$emit('refreshDataList')
+					} else if (data.failCount > 0) {
+						this.$message.warning(`导入全部失败,共 ${data.failCount} 条,请下载查看错误详情`)
+					}
+					this.close()
+					return
+				}
+
+				this.$message.success(`导入成功!共创建 ${data.successCount} 条报销单(${data.successDetailCount} 条明细)`)
+				this.close()
+				this.$emit('refreshDataList')
+			}).catch(err => {
+				loading.close()
+				let errMsg = (err.response && err.response.data) ? err.response.data : (err.message || '服务异常')
+				if (typeof errMsg === 'string' && errMsg.startsWith('错误: ')) {
+					errMsg = errMsg.substring(4)
+				}
+				this.$message.error('导入失败:' + errMsg)
+			})
+		},
+		close() {
+			this.visible = false
+			this.$refs.inputForm.resetFields()
+			this.$refs.upload.clearFiles()
+			this.inputForm = {
+				file: []
+			}
+		}
+	}
+}
+</script>
+
+<style scoped>
+/deep/ .el-input-number .el-input__inner {
+	text-align: left;
+}
+
+.el-row {
+	display: flex;
+	align-items: center;
+}
+</style>