| | |
| | | <el-dialog |
| | | title="处理异常反馈" |
| | | :visible.sync="processDialogVisible" |
| | | width="60%" |
| | | width="80%" |
| | | top="6vh" |
| | | center |
| | | > |
| | |
| | | <el-form |
| | | :model="processForm" |
| | | :rules="processRules" |
| | | :validate-on-rule-change="false" |
| | | ref="processForm" |
| | | label-width="100px" |
| | | size="medium" |
| | |
| | | v-model="processForm.handleFlag" |
| | | placeholder="请选择处理状态" |
| | | style="width: 100%" |
| | | @change="handleFlagChange('single', $event)" |
| | | > |
| | | <el-option label="已处理" :value="'1'" /> |
| | | <el-option label="取消处理" :value="'0'" /> |
| | |
| | | placeholder="请选择处理结果" |
| | | style="width: 100%" |
| | | :disabled="processForm.handleFlag !== '1'" |
| | | @change="handleResultChange('single')" |
| | | > |
| | | <el-option label="已解决" value="resolved" /> |
| | | <el-option label="已解释" value="explained" /> |
| | |
| | | v-model="processForm.flowDepts" |
| | | multiple |
| | | filterable |
| | | collapse-tags |
| | | |
| | | placeholder="请选择流转科室" |
| | | style="width: 100%" |
| | | @change="onFlowDeptChange" |
| | |
| | | <el-option |
| | | v-for="dept in deptList" |
| | | :key="dept.deptCode" |
| | | :label="dept.label" |
| | | :label="dept.label + '(' + dept.deptCode + ')'" |
| | | :value="dept.deptCode" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="流转科室code"> |
| | | <el-select |
| | | v-model="processForm.flowDeptCodes" |
| | | multiple |
| | | disabled |
| | | placeholder="选择科室后自动生成" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="code in processForm.flowDeptCodes" |
| | | :key="code" |
| | | :label="code" |
| | | :value="code" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | v-model="processForm.pushUsers" |
| | | multiple |
| | | filterable |
| | | collapse-tags |
| | | |
| | | placeholder="请选择推送负责人" |
| | | style="width: 100%" |
| | | @change="onPushUserChange" |
| | |
| | | width="120" |
| | | align="center" |
| | | /> |
| | | <el-table-column label="是否同意" width="130" align="center"> |
| | | <el-table-column label="是否处理" width="130" align="center"> |
| | | <template slot-scope="scope"> |
| | | <el-select |
| | | v-model="scope.row.agree" |
| | | placeholder="请选择" |
| | | size="mini" |
| | | > |
| | | <el-option label="同意" value="1" /> |
| | | <el-option label="不同意" value="0" /> |
| | | <el-option label="已处理" value="1" /> |
| | | <el-option label="未处理" value="0" /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | > |
| | | <el-form |
| | | :model="batchProcessForm" |
| | | :rules="processRules" |
| | | :rules="batchProcessRules" |
| | | :validate-on-rule-change="false" |
| | | ref="batchProcessForm" |
| | | label-width="100px" |
| | | size="medium" |
| | |
| | | <el-form-item label="处理状态" prop="handleFlag"> |
| | | <el-select |
| | | v-model="batchProcessForm.handleFlag" |
| | | clearable |
| | | placeholder="请选择处理状态" |
| | | style="width: 100%" |
| | | @change="handleFlagChange('batch', $event)" |
| | | > |
| | | <el-option label="已处理" :value="'1'" /> |
| | | <el-option label="取消处理" :value="'0'" /> |
| | |
| | | <el-form-item label="报备科室" prop="ccdepts"> |
| | | <el-select |
| | | v-model="batchProcessForm.ccdepts" |
| | | clearable |
| | | placeholder="请选择报备科室" |
| | | multiple |
| | | filterable |
| | |
| | | <el-form-item label="处理结果" prop="handleresult"> |
| | | <el-select |
| | | v-model="batchProcessForm.handleresult" |
| | | clearable |
| | | placeholder="请选择处理结果" |
| | | style="width: 100%" |
| | | :disabled="batchProcessForm.handleFlag !== '1'" |
| | | @change="handleResultChange('batch')" |
| | | > |
| | | <el-option label="已解决" value="resolved" /> |
| | | <el-option label="已解释" value="explained" /> |
| | |
| | | todeptcode: "", |
| | | handleFlag: "", |
| | | templateType: null, |
| | | scriptids: null, |
| | | scriptids: [], |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }, |
| | |
| | | processed: 0, |
| | | total: 0, |
| | | }, |
| | | processRules: { |
| | | handleFlag: [ |
| | | { required: true, message: "请选择处理状态", trigger: "change" }, |
| | | ], |
| | | handleresult: [ |
| | | { |
| | | required: true, |
| | | message: "请选择处理结果", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (this.processForm.handleFlag === "1" && !value) { |
| | | callback(new Error("请选择处理结果")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | handledesc: [ |
| | | { |
| | | required: true, |
| | | message: "请输入处理说明", |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if ( |
| | | this.processForm.handleFlag === "1" && |
| | | (!value || value.trim().length < 3) |
| | | ) { |
| | | callback(new Error("处理说明至少3个字符")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | // 批量处理对话框 |
| | | batchDialogVisible: false, |
| | |
| | | }, |
| | | |
| | | created() { |
| | | // 从路由参数获取问题ID |
| | | this.filterParams.scriptids = |
| | | this.$route.query.questionId || this.$route.query.questionIds || null; |
| | | // if (this.$route.query.questionId) { |
| | | // } else if (this.$route.query.questionIds) { |
| | | // console.log( |
| | | // this.$route.query.questionIds, |
| | | // "this.$route.query.questionIds" |
| | | // ); |
| | | |
| | | // 从路由参数获取问题ID集合(scriptids 为数组形式) |
| | | this.filterParams.scriptids = this.resolveScriptids(); |
| | | this.filterParams.templateType = Number(this.$route.query.type) || null; |
| | | |
| | | // this.filterParams.scriptid = null; |
| | | // } |
| | | this.hasQualityPermission = this.checkQualityPermission(); |
| | | }, |
| | | |
| | |
| | | this.getUserOptions(); |
| | | }, |
| | | |
| | | computed: { |
| | | // 单条处理表单校验规则 |
| | | processRules() { |
| | | return this.buildProcessRules( |
| | | () => this.processForm.handleFlag, |
| | | () => this.processForm.handleresult |
| | | ); |
| | | }, |
| | | // 批量处理表单校验规则 |
| | | batchProcessRules() { |
| | | return this.buildProcessRules( |
| | | () => this.batchProcessForm.handleFlag, |
| | | () => this.batchProcessForm.handleresult |
| | | ); |
| | | }, |
| | | }, |
| | | |
| | | methods: { |
| | | // 生成处理表单校验规则 |
| | | // 处理结果:处理状态为「已处理」时必填 |
| | | // 处理说明:处理结果为「已解决」时必填,其他情况不必填(但仍可填写) |
| | | buildProcessRules(getFlag, getResult) { |
| | | return { |
| | | handleFlag: [ |
| | | { required: true, message: "请选择处理状态", trigger: "change" }, |
| | | ], |
| | | handleresult: [ |
| | | { |
| | | required: true, |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (getFlag() === "1" && !value) { |
| | | callback(new Error("请选择处理结果")); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | handledesc: [ |
| | | { |
| | | required: true, |
| | | trigger: "blur", |
| | | validator: (rule, value, callback) => { |
| | | if ( |
| | | getResult() === "resolved" && |
| | | (!value || String(value).trim().length < 3) |
| | | ) { |
| | | callback( |
| | | new Error("处理结果为「已解决」时,处理说明至少填写3个字符") |
| | | ); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }; |
| | | }, |
| | | |
| | | // 切换处理状态时:非「已处理」清空从属字段并清掉旧的校验提示 |
| | | // (此时三个控件处于 disabled,用户无法修改,留残值会被提交成脏数据) |
| | | handleFlagChange(type, val) { |
| | | const isBatch = type === "batch"; |
| | | const form = isBatch ? this.batchProcessForm : this.processForm; |
| | | const refName = isBatch ? "batchProcessForm" : "processForm"; |
| | | if (val !== "1") { |
| | | form.ccdepts = []; |
| | | form.handleresult = ""; |
| | | form.handledesc = ""; |
| | | } |
| | | const ref = this.$refs[refName]; |
| | | if (ref) ref.clearValidate(["handleresult", "handledesc"]); |
| | | }, |
| | | |
| | | // 切换处理结果时:只清掉处理说明的旧校验提示,不清空已填内容 |
| | | // (非「已解决」时说明不是必填,但用户仍可自愿填写) |
| | | handleResultChange(type) { |
| | | const refName = type === "batch" ? "batchProcessForm" : "processForm"; |
| | | const ref = this.$refs[refName]; |
| | | if (ref) ref.clearValidate(["handledesc"]); |
| | | }, |
| | | |
| | | // 格式化日期时间 |
| | | formatDateTime(dateTime) { |
| | | if (!dateTime) return ""; |
| | |
| | | }, |
| | | /** 查询用户列表(流转负责人候选) */ |
| | | getUserOptions() { |
| | | listUser({ pageNum: 1, pageSize: 999 }) |
| | | listUser({ pageNum: 1, pageSize: 19999 }) |
| | | .then((res) => { |
| | | if (res.code == 200) { |
| | | this.userList = res.rows || []; |
| | |
| | | }); |
| | | }, |
| | | |
| | | // 解析路由中的 scriptids(兼容数组 / 逗号分隔字符串,统一返回数组) |
| | | resolveScriptids() { |
| | | const raw = this.$route.query.scriptids; |
| | | if (Array.isArray(raw)) return raw; |
| | | if (raw) return String(raw).split(","); |
| | | return []; |
| | | }, |
| | | |
| | | // 构建查询参数 |
| | | buildQueryParams() { |
| | | const params = { |
| | |
| | | params.templateType = this.filterParams.templateType; |
| | | } |
| | | |
| | | // if (this.filterParams.scriptid) { |
| | | // params.scriptid = this.filterParams.scriptid; |
| | | // } |
| | | if (this.filterParams.scriptids) { |
| | | params.scriptids = this.filterParams.scriptids.split(","); |
| | | if (this.filterParams.scriptids && this.filterParams.scriptids.length) { |
| | | params.scriptids = this.filterParams.scriptids; |
| | | } |
| | | |
| | | return params; |
| | |
| | | this.filterParams = { |
| | | todeptcode: "", |
| | | handleFlag: "", |
| | | scriptids: |
| | | this.$route.query.questionId || this.$route.query.questionIds || null, |
| | | scriptids: this.resolveScriptids(), |
| | | templateType: Number(this.$route.query.type) || null, |
| | | |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }; |
| | |
| | | }; |
| | | |
| | | // 控制并发数 |
| | | const CONCURRENT_LIMIT = 10; // 同时最多3个请求 |
| | | const CONCURRENT_LIMIT = 10; // 同时最多 10 个请求 |
| | | const totalCount = this.selectedExceptionIds.length; |
| | | const results = []; |
| | | let successCount = 0; |
| | |
| | | console.error(`处理记录 ${result.id} 失败:`, result.error); |
| | | } |
| | | }); |
| | | // 更新进度 |
| | | this.batchProgress.processed = i + 1; |
| | | this.batchProgress.percentage = Math.round( |
| | | ((i + 1) / totalCount) * 100 |
| | | ); |
| | | // 更新进度:i 是批次起始索引(步长为 CONCURRENT_LIMIT), |
| | | // 必须加上本批实际条数,否则进度只会按批数递增(如 25 条只到 84%) |
| | | this.batchProgress.processed = i + batchIds.length; |
| | | this.batchProgress.percentage = totalCount |
| | | ? Math.round(((i + batchIds.length) / totalCount) * 100) |
| | | : 100; |
| | | // 显示进度 |
| | | console.log( |
| | | `进度: ${Math.min( |