Newer
Older
KaiFengPC / src / views / preassess / evaluation / mark.vue
@zhangdeliang zhangdeliang on 23 May 8 KB 初始化项目
  1. <template>
  2. <el-card class="box-card">
  3. <el-table
  4. :data="tableData"
  5. v-loading="loading"
  6. element-loading-text="数据加载中..."
  7. :span-method="objectSpanMethod"
  8. :border="true"
  9. max-height="400px"
  10. >
  11. <el-table-column label="评价类型" prop="evaluationType" width="100" />
  12. <el-table-column label="类型分值" prop="evaluationTypeScore" width="60" />
  13. <el-table-column label="评价内容" prop="evaluationContent" width="100" />
  14. <el-table-column label="分项分值" prop="evaluationContentScore" width="60" />
  15. <el-table-column label="评价规则" prop="evaluationRule" />
  16. <el-table-column label="细项分值" prop="evaluationRuleScore" width="60" />
  17. <el-table-column label="评估结果" prop="operateList" width="180">
  18. <template #default="{ row }">
  19. <el-radio-group v-model="row.operateInfo.status" :disabled="row.canOperate === 0 || opts.type === 'view'">
  20. <el-radio v-for="item in row.operateInfo.list" :label="item.value" :key="item.value" @click="operateChange(row, item)">
  21. {{ item.label }}
  22. </el-radio>
  23. </el-radio-group>
  24. </template>
  25. </el-table-column>
  26. <el-table-column label="细项得分" prop="fineScore" width="60" />
  27. <el-table-column label="分项得分" prop="itemizedScore" width="60" />
  28. <el-table-column label="类型得分" prop="typeScore" width="60" />
  29. <el-table-column label="佐证材料" width="200">
  30. <template #default="{ row }">
  31. <upload
  32. :file-list="row.fileSaveRequestList"
  33. :disabled="opts.type === 'view'"
  34. @success="
  35. file => {
  36. uploadSuccess(file, row);
  37. }
  38. "
  39. >
  40. <el-icon :size="20" class="pointer" :class="{ disabled: opts.type === 'view' }"><Upload /></el-icon>
  41. </upload>
  42. <div class="file-list">
  43. <div class="file" v-for="file in row.fileSaveRequestList">
  44. <span class="ellipsis" :title="file.name" :class="{ disabled: opts.type === 'view' }" @click="handlePreview(file)">{{
  45. file.name
  46. }}</span>
  47. <span class="del" @click="removeFile(file, row)" v-if="opts.type !== 'view'">删除</span>
  48. </div>
  49. </div>
  50. </template>
  51. </el-table-column>
  52. </el-table>
  53. </el-card>
  54. </template>
  55.  
  56. <script setup>
  57. import { onMounted, nextTick } from 'vue';
  58. import { getScoreList } from '@/api/preassess/evaluation';
  59. import upload from './upload';
  60. import useTable from './mixins';
  61. const { proxy } = getCurrentInstance();
  62.  
  63. const props = defineProps({
  64. id: {
  65. type: [String, Number],
  66. default: '',
  67. },
  68. opts: {
  69. type: Object,
  70. default: () => {},
  71. },
  72. projectInfo: {
  73. type: Object,
  74. default: () => {},
  75. },
  76. });
  77. const { id, projectInfo, opts } = props;
  78. const { treeData, loading, tableData, getTreeCurRow, setMergeData, handlePreview, uploadSuccess, removeFile } = useTable(
  79. proxy,
  80. opts,
  81. 'evaluationRule'
  82. );
  83.  
  84. const getTableList = async () => {
  85. const res = await getScoreList(projectInfo.engineeringType);
  86. if (res?.code !== 200) return;
  87. setFields(res.data, '0');
  88. setSort(res.data);
  89. computedScore(res.data);
  90. setMergeData(res.data);
  91. treeData.value = res.data;
  92. nextTick(() => {
  93. console.log(tableData.value);
  94. });
  95. };
  96.  
  97. const getDetail = data => {
  98. setFields(data, '0');
  99. setSort(data);
  100. computedScore(data);
  101. setMergeData(data);
  102. treeData.value = data;
  103. };
  104.  
  105. const setFields = (data, level) => {
  106. for (const item of data) {
  107. item.level = level;
  108. if (!item.fileSaveRequestList) {
  109. item.fileSaveRequestList = [];
  110. }
  111. switch (level) {
  112. case '0':
  113. item.sort = item.evaluationTypeRank;
  114. break;
  115. case '1':
  116. item.sort = item.evaluationContentRank;
  117. break;
  118. case '2':
  119. item.sort = item.evaluationRuleRank;
  120. if (item.calculateStandard === 'reach') {
  121. if (id) {
  122. const operateJson = JSON.parse(item.operateJson);
  123. item.operateInfo = operateJson;
  124. } else {
  125. item.operateInfo = {
  126. status: '1',
  127. list: [
  128. {
  129. value: '1',
  130. label: '是',
  131. score: item.evaluationRuleScore,
  132. },
  133. {
  134. value: '0',
  135. label: '否',
  136. score: 0,
  137. },
  138. ],
  139. };
  140. }
  141. } else {
  142. const operateJson = JSON.parse(item.operateJson);
  143. if (id) {
  144. item.operateInfo = operateJson;
  145. } else {
  146. const list = operateJson.map(item => ({
  147. value: item.value,
  148. label: item.name,
  149. score: item.value,
  150. }));
  151. const scorelist = list.map(item => item.value);
  152. const max = Math.max(...scorelist);
  153. const maxItem = list.find(it => it.value * 1 === max);
  154. item.operateInfo = {
  155. status: maxItem.value,
  156. list,
  157. };
  158. }
  159. }
  160. item.operateJson = JSON.stringify(item.operateInfo);
  161. break;
  162. default:
  163. break;
  164. }
  165. if (item.children) {
  166. setFields(item.children, level * 1 + 1 + '');
  167. }
  168. }
  169. };
  170.  
  171. const setSort = data => {
  172. data.sort((a, b) => {
  173. return b.sort - a.sort;
  174. });
  175. for (const item of data) {
  176. if (item.children) {
  177. setSort(item.children);
  178. }
  179. }
  180. };
  181.  
  182. // 计算分数
  183. const computedScore = data => {
  184. for (const item1 of data) {
  185. const children1 = item1.children || [];
  186. for (const item2 of children1) {
  187. const children2 = item2.children || [];
  188. for (const item3 of children2) {
  189. item3.evaluationTypeScore = item1.evaluationTypeScore;
  190. item3.evaluationContentScore = item2.evaluationContentScore;
  191. if (!id) {
  192. item3.fineScore = item3.evaluationRuleScore;
  193. item3.itemizedScore = item3.evaluationContentScore;
  194. item3.typeScore = item3.evaluationTypeScore;
  195. }
  196. }
  197. }
  198. }
  199. };
  200.  
  201. const operateChange = (row, item) => {
  202. if (row.canOperate === 0 || opts.type === 'view') return;
  203. const treeDataCurRow = getTreeCurRow(treeData.value, { nodeCode: row.nodeCode });
  204. treeDataCurRow.operateInfo.status = item.value;
  205. treeDataCurRow.operateJson = JSON.stringify(treeDataCurRow.operateInfo);
  206. dynamicComputedScore(row.nodeCode, item.score * 1);
  207. };
  208.  
  209. const dynamicComputedScore = (nodeCode, score) => {
  210. const treeDataCurRow = getTreeCurRow(treeData.value, { nodeCode });
  211. treeDataCurRow.fineScore = score;
  212.  
  213. const treeDataCurParentRow = getTreeCurRow(treeData.value, { nodeCode: treeDataCurRow.parentNodeCode });
  214. const itemizedScore = treeDataCurParentRow.children.reduce((pre, item) => {
  215. return (pre += item.fineScore * 1);
  216. }, 0);
  217. treeDataCurParentRow.children.forEach(item => {
  218. item.itemizedScore = itemizedScore;
  219. });
  220. const rootRow = getTreeCurRow(treeData.value, { nodeCode: treeDataCurParentRow.parentNodeCode });
  221. const typeScore = getTypeScore(rootRow.children);
  222. for (const item of rootRow.children) {
  223. for (const it of item.children) {
  224. it.typeScore = typeScore;
  225. }
  226. }
  227. };
  228.  
  229. const getTypeScore = data => {
  230. let typeScore = 0;
  231. for (const item of data) {
  232. typeScore += item.children.reduce((pre, it) => {
  233. return (pre += it.fineScore * 1);
  234. }, 0);
  235. }
  236. return typeScore;
  237. };
  238.  
  239. const getSum = data => {
  240. let sum = 0;
  241. for (const item of data) {
  242. const children = item.children || [];
  243. for (const it of children) {
  244. sum++;
  245. if (it.children) {
  246. getSum(it.children);
  247. }
  248. }
  249. }
  250. return sum;
  251. };
  252.  
  253. // 表数据合并
  254. const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
  255. if ([0, 1, 9].includes(columnIndex)) {
  256. const rowspan = row.length1 - rowIndex === row.sum1 ? row.sum1 : 0;
  257. return {
  258. rowspan,
  259. colspan: 1,
  260. };
  261. } else if ([2, 3, 8].includes(columnIndex)) {
  262. const rowspan = row.length2 - rowIndex === row.sum2 ? row.sum2 : 0;
  263. return {
  264. rowspan,
  265. colspan: 1,
  266. };
  267. }
  268. };
  269.  
  270. onMounted(() => {
  271. if (!id) getTableList();
  272. });
  273.  
  274. defineExpose({
  275. treeData,
  276. getDetail,
  277. });
  278. </script>
  279.  
  280. <style lang="scss" scoped>
  281. .pointer {
  282. cursor: pointer;
  283. }
  284. .disabled {
  285. cursor: not-allowed !important;
  286. }
  287. .file-list {
  288. .file {
  289. display: flex;
  290. align-items: center;
  291. }
  292. .del {
  293. flex-shrink: 0;
  294. color: #f56c6c;
  295. cursor: pointer;
  296. margin-left: 10px;
  297. }
  298. .disabled {
  299. cursor: not-allowed !important;
  300. }
  301. }
  302. .ellipsis {
  303. overflow: hidden;
  304. white-space: nowrap;
  305. text-overflow: ellipsis;
  306. cursor: pointer;
  307. }
  308. </style>