<template> <el-card class="box-card"> <el-table :data="tableData" v-loading="loading" element-loading-text="数据加载中..." :span-method="objectSpanMethod" :border="true" max-height="400px" > <el-table-column label="评价类型" prop="evaluationType" width="100" /> <el-table-column label="类型分值" prop="evaluationTypeScore" width="60" /> <el-table-column label="评价内容" prop="evaluationContent" width="100" /> <el-table-column label="分项分值" prop="evaluationContentScore" width="60" /> <el-table-column label="评价规则" prop="evaluationRule" /> <el-table-column label="细项分值" prop="evaluationRuleScore" width="60"/> <el-table-column label="评估结果" prop="operateList" width="180"> <template #default="{ row }"> <el-radio-group v-model="row.operateInfo.status" :disabled="row.canOperate === 0 || opts.type === 'view'" > <el-radio v-for="item in row.operateInfo.list" :label="item.value" :key="item.value" @click="operateChange(row, item)" > {{ item.label }} </el-radio> </el-radio-group> </template> </el-table-column> <el-table-column label="细项得分" prop="fineScore" fixed="right" width="60"/> <el-table-column label="分项得分" prop="itemizedScore" fixed="right" width="60"/> <el-table-column label="类型得分" prop="typeScore" fixed="right" width="60"/> <el-table-column label="佐证材料" align="center" fixed="right" width="200"> <template #default="{ row }"> <upload :file-list="row.fileSaveRequestList" :disabled="opts.type === 'view'" @success="(file) => { uploadSuccess(file, row) }" > <el-icon :size="20" class="pointer" :class="{ disabled: opts.type === 'view' }"><Upload /></el-icon> </upload> <div class="file-list"> <div class="file" v-for="file in row.fileSaveRequestList" > <span class="ellipsis" :title="file.name" :class="{ disabled: opts.type === 'view' }" @click="handlePreview(file)" >{{ file.name }}</span> <span class="del" @click="removeFile(file, row)" v-if="opts.type !== 'view'">删除</span> </div> </div> </template> </el-table-column> </el-table> </el-card> </template> <script setup> import { onMounted, nextTick } from 'vue' import { getScoreList } from '@/api/preassess/evaluation' import upload from './upload' import useTable from './mixins' const { proxy } = getCurrentInstance(); const props = defineProps({ id: { type: [String, Number], default: '' }, opts: { type: Object, default: () => {} }, projectInfo: { type: Object, default: () => {} } }) const { id, projectInfo, opts } = props const { treeData, loading, tableData, getTreeCurRow, setMergeData, handlePreview, uploadSuccess, removeFile } = useTable(proxy, opts, 'evaluationRule') const getTableList = async () => { const res = await getScoreList(projectInfo.engineeringType) if(res?.code !== 200) return setFields(res.data, '0') setSort(res.data) computedScore(res.data) setMergeData(res.data) treeData.value = res.data nextTick(() => { console.log(tableData.value) }) } const getDetail = (data) => { setFields(data, '0') setSort(data) computedScore(data) setMergeData(data) treeData.value = data } const setFields = (data, level) => { for (const item of data) { item.level = level if(!item.fileSaveRequestList){ item.fileSaveRequestList = [] } switch (level) { case '0': item.sort = item.evaluationTypeRank break; case '1': item.sort = item.evaluationContentRank break; case '2': item.sort = item.evaluationRuleRank if(item.calculateStandard === 'reach'){ if(id){ const operateJson = JSON.parse(item.operateJson) item.operateInfo = operateJson } else { item.operateInfo = { status: '1', list: [ { value: '1', label: '是', score: item.evaluationRuleScore }, { value: '0', label: '否', score: 0 } ] } } } else { const operateJson = JSON.parse(item.operateJson) if(id) { item.operateInfo = operateJson } else { const list = operateJson.map(item => ({ value: item.value, label: item.name, score: item.value })) const scorelist = list.map(item => item.value) const max = Math.max(...scorelist) const maxItem = list.find(it => it.value * 1 === max) item.operateInfo = { status: maxItem.value, list } } } item.operateJson = JSON.stringify(item.operateInfo) 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 computedScore = (data) => { for (const item1 of data) { const children1 = item1.children || [] for (const item2 of children1) { const children2 = item2.children || [] for (const item3 of children2) { item3.evaluationTypeScore = item1.evaluationTypeScore item3.evaluationContentScore = item2.evaluationContentScore if(!id) { item3.fineScore = item3.evaluationRuleScore item3.itemizedScore = item3.evaluationContentScore item3.typeScore = item3.evaluationTypeScore } } } } } const operateChange = (row, item) => { if(row.canOperate === 0 || opts.type === 'view') return const treeDataCurRow = getTreeCurRow(treeData.value, { nodeCode: row.nodeCode }) treeDataCurRow.operateInfo.status = item.value treeDataCurRow.operateJson = JSON.stringify(treeDataCurRow.operateInfo) dynamicComputedScore(row.nodeCode, item.score * 1) } const dynamicComputedScore = (nodeCode, score) => { const treeDataCurRow = getTreeCurRow(treeData.value, { nodeCode }) treeDataCurRow.fineScore = score const treeDataCurParentRow = getTreeCurRow(treeData.value, { nodeCode: treeDataCurRow.parentNodeCode }) const itemizedScore = treeDataCurParentRow.children.reduce((pre, item) => { return pre += item.fineScore * 1 }, 0) treeDataCurParentRow.children.forEach(item => { item.itemizedScore = itemizedScore }); const rootRow = getTreeCurRow(treeData.value, { nodeCode: treeDataCurParentRow.parentNodeCode }) const typeScore = getTypeScore(rootRow.children) for (const item of rootRow.children) { for (const it of item.children) { it.typeScore = typeScore } } } const getTypeScore = (data) => { let typeScore = 0 for (const item of data) { typeScore += item.children.reduce((pre, it) => { return pre += it.fineScore * 1 }, 0) } return typeScore } const getSum = (data) => { let sum = 0 for (const item of data) { const children = item.children || [] for (const it of children) { sum++ if(it.children) { getSum(it.children) } } } return sum } // 表数据合并 const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => { if([0, 1, 9].includes(columnIndex)){ const rowspan = row.length1 - rowIndex === row.sum1 ? row.sum1 : 0 return { rowspan, colspan: 1 } } else if([2, 3, 8].includes(columnIndex)) { const rowspan = row.length2 - rowIndex === row.sum2 ? row.sum2 : 0 return { rowspan, colspan: 1 } } } onMounted(() => { if(!id) getTableList() }) defineExpose({ treeData, getDetail }) </script> <style lang="scss" scoped> .pointer { cursor: pointer; } .disabled { cursor: not-allowed !important; } .file-list { .file { display: flex; align-items: center; } .del { flex-shrink: 0; color: #f56c6c; cursor: pointer; margin-left: 10px; } .disabled { cursor: not-allowed !important; } } .ellipsis { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; cursor: pointer; } </style>