<template> <div class="mark" v-loading.fullscreen.lock="loading" element-loading-text="加载中..." element-loading-background="rgba(0, 0, 0, 0.6)" > <el-page-header class="header" @back="goBack(route, '/preassess/examineManage')"> <template #content> <span class="title">{{ name }}</span> </template> </el-page-header> <div class="body"> <el-form ref="ruleForm" :model="form"> <el-row :gutter="20"> <el-col :span="5"> <el-form-item label="评价规则:" prop="name"> <el-input v-model="form.name" placeholder="请输入评价规则"/> </el-form-item> </el-col> <el-col :span="4"> <el-form-item> <el-button type="primary" icon="Search" @click="search"> 查询</el-button> <el-button icon="Refresh" @click="resetQuery">重置</el-button> </el-form-item> </el-col> <el-col :span="15"> <el-button type="primary" style="float: right;margin-left: 10px;" @click="save" :disabled="type === 'view'" >保存</el-button> <el-button type="primary" style="float: right;margin-left: 10px;" @click="enable" :disabled="type === 'view'" >{{ statusText }}</el-button> <el-button type="primary" icon="Plus" style="float: right" :disabled="type === 'view'" @click="openDialog({}, '0', 'add')" > 新增评价类型</el-button> <upload class="upload" style="float: right" action="/prod-api/sponge/assessTargetConfigGradeItem/exportTargetConfigGradeItem" :data="{ targetId: markId }" :disabled="type === 'view'" @success="(data) => { uploadSuccess(data) }" > <el-button type="primary" icon="Upload" :disabled="type === 'view'" > 导入</el-button> </upload> </el-col> </el-row> </el-form> <el-table ref="tableRef" :data="treeData" stripe :max-height="600" row-key="nodeCode" v-loading="tableLoading" > <el-table-column label="评价类型" prop="evaluationType" width="120px"> <template #default="{ row }"> <span>{{ row.level === '0' ? row.evaluationType : ''}}</span> </template> </el-table-column> <el-table-column label="评价内容" prop="evaluationContent" width="120px"> <template #default="{ row }"> <span>{{ row.level === '1' ? row.evaluationContent : ''}}</span> </template> </el-table-column> <el-table-column label="评价规则" prop="evaluationRule" width="300px"> <template #default="{ row, $index }"> <div v-html="formatSearch(row, $index, row.evaluationRule)" v-if="row.level === '2'"></div> <span v-else></span> </template> </el-table-column> <el-table-column label="分值" prop="score" show-overflow-tooltip width="80px"> <template #default="{ row }"> <span v-if="row.level === '0'">{{ row.evaluationTypeScore }}</span> <span v-else-if="row.level === '1'">{{ row.evaluationContentScore }}</span> <span v-else-if="row.level === '2'">{{ row.evaluationRuleScore }}</span> </template> </el-table-column> <el-table-column label="评价标准" align="center" prop="calculateStandard" show-overflow-tooltip width="80px"> <template #default="{ row }"> <span>{{ calculateStandardText.get(row.calculateStandard) }}</span> </template> </el-table-column> <el-table-column label="是否可操作" align="center" prop="canOperate" width="90px"> <template #default="{ row }"> <el-switch v-model="row.canOperate" :active-value="1" :inactive-value="0" :disabled="row.canOperateDisabled || type === 'view'" @change="(val) => { canOperateChange(row, val) }" /> </template> </el-table-column> <el-table-column label="启用状态" align="center" prop="status" width="90px"> <template #default="{ row }"> <el-switch v-model="row.status" active-value="1" inactive-value="0" @change="(val) => { statusChange(row, val) }" :disabled="row.statusDisabled || type === 'view'" /> </template> </el-table-column> <el-table-column label="启用时间" align="center" prop="enableTime" show-overflow-tooltip width="160px" /> <el-table-column label="停用时间" align="center" prop="stopTime" show-overflow-tooltip width="160px" /> <el-table-column label="修改人" align="center" prop="updateBy" show-overflow-tooltip /> <el-table-column label="修改日期" align="center" prop="updateTime" show-overflow-tooltip width="160px" /> <el-table-column label="排序" align="center" show-overflow-tooltip width="110px" fixed="right"> <template #default="{ row }"> <el-button type="primary" link :disabled="getSortIsDisabled(row, 'ascending') || type === 'view'" @click="ascHandle(row)" >升序</el-button> <el-button type="primary" link :disabled="getSortIsDisabled(row, 'descending') || type === 'view'" @click="descHandle(row)" >降序</el-button> </template> </el-table-column> <el-table-column label="操作" align="center" width="260" fixed="right" > <template #default="{ row }"> <el-button type="primary" link v-if="row.level === '0'" @click="openDialog(row, row.level * 1 + 1 + '', 'add')" :disabled="type === 'view'" >新增评价内容</el-button> <el-button type="primary" link v-if="row.level === '1'" @click="openDialog(row, row.level * 1 + 1 + '', 'add')" :disabled="type === 'view'" >新增评价规则</el-button> <el-button type="primary" link v-if="row.level === '2'" @click="copy(row)" :disabled="type === 'view'" >复制</el-button> <el-button type="primary" link @click="openDialog(row, row.level, 'view')" >查看</el-button> <el-button type="primary" link @click="openDialog(row, row.level, 'edit')" :disabled="type === 'view'" >修改</el-button> <el-button type="danger" link @click="del(row)" :disabled="type === 'view'" >删除</el-button> </template> </el-table-column> </el-table> </div> <el-dialog v-model="visible" :title="`${operateInfo.text}`" :close-on-click-modal="false" :width="operateInfo.width" :before-close="close" class="dialog" > <el-form ref="dialogFormRef" :model="dialogForm" :rules="dialogFormRules" v-if="operateInfo.level" :disabled="operateInfo.type === 'view' || type === 'view'" > <el-row v-if="operateInfo.level === '0'"> <el-col :span="20" :offset="2"> <el-form-item label="评价类型:" prop="evaluationType"> <el-input v-model="dialogForm.evaluationType" placeholder="请输入评价类型"/> </el-form-item> </el-col> </el-row> <el-row :gutter="20" v-if="operateInfo.level === '1'"> <el-col :span="12"> <el-form-item label="评价内容:" prop="evaluationContent"> <el-input v-model="dialogForm.evaluationContent" placeholder="请输入评价内容"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="评价类型:" prop="evaluationType"> <el-input v-model="dialogForm.evaluationType" :disabled="true"/> </el-form-item> </el-col> </el-row> <el-row :gutter="20" v-if="operateInfo.level === '2'"> <el-col :span="12"> <el-form-item label="评价规则:" prop="evaluationRule"> <el-input v-model="dialogForm.evaluationRule" placeholder="请输入评价规则"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="评价标准:" prop="calculateStandard"> <el-select v-model="dialogForm.calculateStandard" placeholder="请选择评价标准" style="width: 100%" > <el-option label="达标" value="reach" /> <el-option label="评级" value="rate" /> </el-select> </el-form-item> </el-col> <el-col :span="12" v-if="dialogForm.calculateStandard === 'reach'"> <el-form-item label="分值:" prop="evaluationRuleScore"> <el-input v-model="dialogForm.evaluationRuleScore" placeholder="请输入分值"/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="评价内容:" prop="evaluationContent"> <el-input v-model="dialogForm.evaluationContent" :disabled="true" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="评价类型:" prop="evaluationType"> <el-input v-model="dialogForm.evaluationType" :disabled="true" /> </el-form-item> </el-col> </el-row> </el-form> <rate ref="rateRef" :type="operateInfo.type" :operateJson="dialogForm.operateJson" v-if="operateInfo.level && dialogForm.calculateStandard === 'rate'" /> <template #footer v-if="operateInfo.type !== 'view'"> <div class="dialog-footer"> <el-button type="primary" @click="submit">保存</el-button> <el-button @click="close">取消</el-button> </div> </template> </el-dialog> </div> </template> <script setup> import { ref, nextTick, onMounted, reactive } from 'vue' import { v4 as uuidv4 } from 'uuid' import useUserStore from "@/store/modules/user" import { getAssessTargetConfigGradeItem, assessTargetConfigGradeItemBatchUpdate, assessTargetConfigOpen, assessTargetConfigClose } from '@/api/preassess/examineManage.js' import { optTextMap } from '@/utils/map' import { inheritAttr } from '@/utils/v3' import { numberValidate } from '../validate' import useTable from '../mixins' import rate from './rate.vue' import upload from '../upload.vue' const route = useRoute(); const { proxy } = getCurrentInstance(); const { markId } = route.params let { type, status, name, engineeringType } = route.query const statusText = ref(status ==='1' ? '停用' : '启用') const { form, treeData, visible, curRow, operateInfo, getTreeCurRow, search, resetQuery, goBack, close, statusChange, setStatusDisabled, canOperateChange, setCanOperateDisabled, getSortIsDisabled, copy, del, ascHandle, descHandle, formatSearch, computedScore, expand, checkData } = useTable(proxy, uuidv4) const dialogForm = reactive({ evaluationType: '', evaluationContent: '', evaluationRule: '', evaluationRuleScore: '', calculateStandard: '', operateJson: '' }) const loading = ref(false) const tableLoading = ref(false) const dialogFormRules = reactive({ evaluationType: [ { required: true, trigger: "blur", message: "评价类型不能为空" } ], evaluationContent: [ { required: true, trigger: "blur", message: "评价内容不能为空" } ], evaluationRule: [ { required: true, trigger: "blur", message: "评价规则不能为空" } ], calculateStandard: [ { required: true, trigger: "blur", message: "评价标准不能为空" } ], evaluationRuleScore: [ { required: true, trigger: "blur", validator: numberValidate } ], }) const calculateStandardText = new Map([ ['acc', '累加'], ['reach', '达标'], ['rate', '评级'] ]) const operateMap = new Map([ ['0', { width: '24%', text: '评价类型' }], ['1', { width: '48%',text: '评价内容' }], ['2', { width: '48%',text: '评价规则' }], ]) const openDialog = (row, level, type) => { console.log(row) curRow.value = row operateInfo.level = level operateInfo.type = type operateInfo.text = optTextMap.get(type) + operateMap.get(level).text operateInfo.width = operateMap.get(level).width visible.value = true nextTick(() => { setDialogForm(row, level, type) }) } const setDialogForm = (row, level, type) => { inheritAttr(row, dialogForm) switch (level) { case '1': dialogForm.evaluationType = row.evaluationType break; case '2': dialogForm.evaluationType = row.evaluationType dialogForm.evaluationContent = row.evaluationContent default: break; } if(type === 'add'){ dialogForm.calculateStandard = '' dialogForm.operateJson = '' } } const submit = () => { console.log(operateInfo, dialogForm) proxy.$refs.dialogFormRef.validate((valid) => { if(valid){ const treeDataCurRow = getTreeCurRow(treeData.value, curRow.value) const row = { assessTargetConfigId: markId, evaluationType: '', evaluationTypeScore: '', evaluationContent: '', evaluationContentScore: '', evaluationRule: '', evaluationRuleScore: '', calculateStandard: '', canOperate: '0', enableTime: '', stopTime: proxy.moment().format("YYYY-MM-DD HH:mm:ss"), updateBy: useUserStore().name, updateTime: proxy.moment().format("YYYY-MM-DD HH:mm:ss"), status: '0', parentNodeCode: '0', operateJson: '' } if(operateInfo.type === 'add'){ row.nodeCode = uuidv4() row.level = operateInfo.level switch (operateInfo.level) { case '0': row.evaluationType = dialogForm.evaluationType // row.evaluationTypeScore = dialogForm.evaluationTypeScore row.calculateStandard = 'acc' row.statusDisabled = false treeData.value.unshift(row) row.sort = treeData.value.length break; case '1': row.evaluationType = dialogForm.evaluationType row.evaluationContent = dialogForm.evaluationContent // row.evaluationContentScore = dialogForm.evaluationContentScore row.calculateStandard = 'acc' row.parentNodeCode = curRow.value.nodeCode row.statusDisabled = curRow.value.status === '0' if(!treeDataCurRow.children) treeDataCurRow.children = [] row.sort = treeDataCurRow.children.length + 1 treeDataCurRow.children.unshift(row) break; case '2': if(dialogForm.calculateStandard === 'rate') { const list = proxy.$refs.rateRef.rateTableData if(!list?.length) return proxy.$modal.msgError('请至少添加一条评级规则') const scorelist = list.map(it => it.value * 1) row.evaluationRuleScore = Math.max(...scorelist) + '' row.operateJson = JSON.stringify(list) } else { row.operateJson = '' row.evaluationRuleScore = dialogForm.evaluationRuleScore } row.evaluationType = dialogForm.evaluationType row.evaluationContent = dialogForm.evaluationContent row.evaluationRule = dialogForm.evaluationRule row.calculateStandard = dialogForm.calculateStandard row.parentNodeCode = curRow.value.nodeCode row.statusDisabled = curRow.value.status === '0' if(!treeDataCurRow.children) treeDataCurRow.children = [] row.sort = treeDataCurRow.children.length + 1 treeDataCurRow.children.unshift(row) //计算分值 computedScore(treeDataCurRow.nodeCode) break; default: break; } nextTick(() => { proxy.$refs.tableRef.toggleRowExpansion(treeDataCurRow, true) }) } else if(operateInfo.type === 'edit'){ switch (operateInfo.level) { case '0': treeDataCurRow.evaluationType = dialogForm.evaluationType if(treeDataCurRow?.children?.length){ for (const item of treeDataCurRow.children) { item.evaluationType = treeDataCurRow.evaluationType if(item?.children?.length){ for (const it of item.children) { it.evaluationType = treeDataCurRow.evaluationType } } } } // treeDataCurRow.evaluationTypeScore = dialogForm.evaluationTypeScore break; case '1': treeDataCurRow.evaluationContent = dialogForm.evaluationContent if(treeDataCurRow?.children?.length){ for (const item of treeDataCurRow.children) { item.evaluationContent = treeDataCurRow.evaluationContent } } // treeDataCurRow.evaluationContentScore = dialogForm.evaluationContentScore break; case '2': if(dialogForm.calculateStandard === 'rate') { const list = proxy.$refs.rateRef.rateTableData if(!list?.length) return proxy.$modal.msgError('请至少添加一条评级规则') const scorelist = list.map(it => it.value * 1) treeDataCurRow.evaluationRuleScore = Math.max(...scorelist) + '' treeDataCurRow.operateJson = JSON.stringify(list) } else { treeDataCurRow.operateJson = '' treeDataCurRow.evaluationRuleScore = dialogForm.evaluationRuleScore } treeDataCurRow.evaluationRule = dialogForm.evaluationRule treeDataCurRow.calculateStandard = dialogForm.calculateStandard //计算分值 computedScore(treeDataCurRow.parentNodeCode) break; default: break; } } close() } }) } const getTableData = async () => { tableLoading.value = true const res = await getAssessTargetConfigGradeItem(markId) tableLoading.value = false if(res?.code !== 200) return treeData.value = res?.data || [] setFields(treeData.value, '0') setSort(treeData.value) setCanOperateDisabled(treeData.value) setStatusDisabled(treeData.value) nextTick(() => { expand() }) console.log(treeData.value) } const setFields = (data, level) => { for (const item of data) { item.level = level switch (level) { case '0': item.sort = item.evaluationTypeRank break; case '1': item.sort = item.evaluationContentRank break; case '2': item.sort = item.evaluationRuleRank break; default: break; } if(item.children) { setFields(item.children, level * 1 + 1 + '') } } } const setSort = (data) => { data.sort((a, b) => { return b.sort - a.sort }) for (const item of data) { if(item.children) { setSort(item.children) } } } const save = async () => { loading.value = true const params = JSON.parse(JSON.stringify(treeData.value)) const flag = checkData(params) if(flag) return proxy.$modal.msgError('表格数据至少要填写到评价规则') setParams(params) console.log(params) const res = await assessTargetConfigGradeItemBatchUpdate(params) loading.value = false if(res?.code !== 200) return proxy.$modal.msgSuccess('操作成功!') } const setParams = (data) => { for (const item of data) { if(item.level === '0'){ item.evaluationTypeRank = item.sort } else if(item.level === '1') { item.evaluationContentRank = item.sort } else if(item.level === '2') { item.evaluationRuleRank = item.sort } if(item.children) { setParams(item.children) } } } const enable = () => { proxy.$modal .confirm(`是否确认${statusText.value}?`) .then(async () => { let method = status === '1' ? assessTargetConfigClose : assessTargetConfigOpen const formData = new FormData() formData.append('id', markId) formData.append('engineeringType', engineeringType) formData.append('assessType', 'score') const res = await method(formData) if(res?.code !== 200) return proxy.$modal.msgSuccess('操作成功!') if(status === '1'){ status = '0' statusText.value = '启用' } else { status = '1' statusText.value = '停用' } }) .catch(() => {}); } const uploadSuccess = (data) => { console.log(data) if(data) getTableData() } onMounted(() => { getTableData() }) </script> <style lang="scss" scoped> .mark { padding: 10px; height: 92vh; overflow-y: hidden; .header { padding: 10px; border-radius: 4px; box-shadow: 0px 0px 12px rgba(0, 0, 0, .12); border: 1px solid #e4e7ed; margin-bottom: 10px; .title { font-size: 16px; } ::v-deep(.el-page-header__header) { .el-page-header__left { .el-page-header__back { .el-page-header__icon { font-size: 20px; font-weight: 700; } .el-page-header__title { font-size: 16px; } } } } } .body { height: calc(100% - 74px); overflow: auto; overflow-x: hidden; background-color: #fff; border-radius: 4px; box-shadow: 0px 0px 12px rgba(0, 0, 0, .12); border: 1px solid #e4e7ed; padding: 20px; ::v-deep(.el-table) { .light { background-color: rgb(252, 247, 0); } } } } ::v-deep(.dialog) { .el-dialog__body { padding-bottom: 20px !important; .el-form { .el-form-item { .el-form-item__label { width: 80px; word-break: keep-all; white-space: nowrap; } } } } .el-dialog__footer { padding-top: 0 !important; } } </style>