<template> <div> <el-table ref="tableRef" :data="okrList" default-expand-all row-key="id" size="large" @row-click="handleRowClick" @expand-change="handleExpand" > <el-table-column label="目标/关键成果"> <template #default="{ row, $index }"> <span v-if="!expandedRows[row.id]" class="line1" :style="{ top: row.type == '目标' ? '30px' : 0, height: getHeight(row, $index) }" ></span> <span v-if="row.type == '目标'">【目标】{{ row.name }}</span> <template v-else> <span class="line2"></span> <span> 【关键成果】{{ row.channelName }} {{ row.name }} <span v-if="row.resultType == 1">达 {{ row.targetValue }}</span> </span> <div class="flex items-center mt-10px ml-50px"> <span>当前进度:</span> <span v-if="row.isSys || !props.canEdit">{{ row.currentValue }}</span> <el-input v-else-if="row.resultType == 1" v-model="row.currentValue" clearable size="small" style="width: 200px" /> <el-radio-group v-else-if="row.resultType == 2" v-model="row.currentValue" size="small" > <el-radio :value="true">是</el-radio> <el-radio :value="false">否</el-radio> </el-radio-group> </div> </template> </template> </el-table-column> <el-table-column prop="progress" label="进度" width="200px"> <template #default="{ row }"> <el-progress :percentage="row.progress || 0" /> </template> </el-table-column> <el-table-column prop="executorName" label="执行人" width="200px" /> </el-table> </div> </template> <script setup name="OkrTable"> import { updateOkrProgress } from '@/api/okr/okr' const emit = defineEmits(['rowClick']) const props = defineProps({ canEdit: { type: Boolean, default: false } }) const okrList = ref([]) const helpList = ref([]) function prepareData(list) { helpList.value = [] expandedRows.value = {} okrList.value = list.map((item) => { let obj = { id: item.objectiveId, name: item.objectiveName, progress: item.progress, executorName: item.executorName, type: '目标' } helpList.value.push(obj) if (item.keyResults) { obj.children = item.keyResults.map((child) => { let kr = { id: child.keyResultId, keyResultId: child.keyResultId, objectiveId: child.objectiveId, nodeId: child.nodeId, isSys: child.isSys, processId: child.id, name: child.keyResultName, progress: child.progress, executorName: child.executorName, type: '关键成果', resultType: child.resultType, targetValue: child.targetValue } helpList.value.push(kr) return kr }) } return obj }) } defineExpose({ prepareData, updateProcess }) function getHeight(row, index) { if (helpList.value.length - 1 == index || helpList.value[index + 1].type == '目标') { return '22px' } else { return '100%' } } const expandedRows = ref({}) function handleExpand(row, expanded) { expandedRows.value[row.id] = !expanded } function updateProcess(nodeId) { return new Promise((resolve, reject) => { try { let arr = [] okrList.value.map((item) => { arr = [...arr, ...(item.children || []).map((it) => ({ ...it, id: it.processId }))] }) updateOkrProgress({ nodeId, keyResultProgressList: arr }).then((resp) => { resolve(resp) }) } catch (error) { reject(error) } }) } function handleRowClick(row) { emit('rowClick', row) } </script> <style lang="scss" scoped> .line1 { position: absolute; width: 1px; left: 21px; border-left: 1px dashed #ccc; } .line2 { position: absolute; width: 26px; height: 1px; left: 21px; top: 22px; border-bottom: 1px dashed #ccc; &::after { position: absolute; left: 25px; top: -3px; display: block; width: 6px; height: 6px; border-radius: 6px; margin: 0 auto; border: 1px solid #ddd; content: ''; } } </style>