270 lines
6.2 KiB
Vue
270 lines
6.2 KiB
Vue
<template>
|
|
<div class="info-grid" v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])">
|
|
<table class="info-table">
|
|
<tbody>
|
|
<tr>
|
|
<td>项目名称</td>
|
|
<td>{{ nodeInfo.nodeName }}</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td>当前阶段</td>
|
|
<td>
|
|
{{ nodeInfo.currentPhase || '未设置' }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<table class="info-table">
|
|
<tbody>
|
|
<tr>
|
|
<td>项目代号</td>
|
|
<td>{{ nodeInfo.nodeCode }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>仿真专项代表</td>
|
|
<td>{{ nodeInfo.pMemberNames }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="info-grid" v-else>
|
|
<table class="info-table">
|
|
<tbody>
|
|
<tr>
|
|
<td>项目名称</td>
|
|
<td>{{ nodeInfo.nodeName }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>仿真专项代表</td>
|
|
<td>{{ nodeInfo.pMemberNames }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>项目状态</td>
|
|
<td>
|
|
<StatusDot
|
|
:status="projectStatus(nodeInfo.exeStatus)"
|
|
:title="PROJECT_EXE_STATUS.O[nodeInfo.exeStatus]"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>计划开始时间</td>
|
|
<td>{{ nodeInfo.beginTime }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>当前阶段</td>
|
|
<td>
|
|
{{ nodeInfo.currentPhase || '未设置' }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<table class="info-table">
|
|
<tbody>
|
|
<tr>
|
|
<td>项目代号</td>
|
|
<td>{{ nodeInfo.nodeCode }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>创建人</td>
|
|
<td>{{ nodeInfo?.creatorObj?.nickname }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>创建时间</td>
|
|
<td>{{ nodeInfo.createTime }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>计划结束时间</td>
|
|
<td>{{ nodeInfo.endTime }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>备注</td>
|
|
<td>{{ nodeInfo.description }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<!-- <el-descriptions title="" :column="2" border>
|
|
<el-descriptions-item label="项目名称">{{ nodeInfo.nodeName }}</el-descriptions-item>
|
|
<el-descriptions-item label="项目代号">{{ nodeInfo.nodeCode }}</el-descriptions-item>
|
|
<el-descriptions-item label="项目经理">{{ nodeInfo.pMemberNames }}</el-descriptions-item>
|
|
<el-descriptions-item label="创建人">{{ nodeInfo.creator }}</el-descriptions-item>
|
|
<el-descriptions-item label="项目状态">{{ nodeInfo.status }}</el-descriptions-item>
|
|
<el-descriptions-item label="创建时间">{{ nodeInfo.createTime }}</el-descriptions-item>
|
|
<el-descriptions-item label="计划开始时间">{{ nodeInfo.beginTime }}</el-descriptions-item>
|
|
<el-descriptions-item label="计划结束时间">{{ nodeInfo.endTime }}</el-descriptions-item>
|
|
<el-descriptions-item label="当前阶段">{{ nodeInfo.currentPhase }}</el-descriptions-item>
|
|
<el-descriptions-item label="备注">{{ nodeInfo.description }}</el-descriptions-item>
|
|
</el-descriptions> -->
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { getNodeDetailApi } from '@/api/project/node';
|
|
import { onMounted, reactive, watch } from 'vue';
|
|
import { useDict } from '@/utils/useDict';
|
|
import StatusDot from '@/components/common/statusDot/index.vue';
|
|
import { projectStatus } from '@/components/common/statusDot/statusMap';
|
|
import { enableConfigByTenant, TENANT_ENUM } from '@/tenants/tenant';
|
|
|
|
const props = defineProps({
|
|
nodeId: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
});
|
|
|
|
const { PROJECT_EXE_STATUS } = useDict('PROJECT_EXE_STATUS');
|
|
|
|
const emits = defineEmits(['update:projectInfo', 'loaded']);
|
|
const nodeInfo = reactive<any>({
|
|
nodeName: '',
|
|
creator: '',
|
|
creatorObj: '',
|
|
exeStatusName: '',
|
|
exeStatus: '',
|
|
nodeCode: '',
|
|
createTime: '',
|
|
description: '',
|
|
memberList: [],
|
|
pMemberNames: '',
|
|
beginTime: '',
|
|
currentPhase: '',
|
|
endTime: '',
|
|
});
|
|
|
|
const getNodeDetailFun = async () => {
|
|
const res: any = await getNodeDetailApi({ projectNodeId: props.nodeId });
|
|
if (res.code === 200) {
|
|
for (const key in nodeInfo) {
|
|
// if (key === 'exeStatus') {
|
|
// nodeInfo[key] = res.data[key];
|
|
// nodeInfo.exeStatusName = res.data[key];
|
|
// } else {
|
|
nodeInfo[key] = res.data[key];
|
|
// }
|
|
}
|
|
if (Array.isArray(res.data.memberList)) {
|
|
nodeInfo.pMemberNames = res.data.memberList
|
|
.map((item: any) => {
|
|
return item.nickname || item.name || item.realName;
|
|
})
|
|
.join();
|
|
}
|
|
emits('update:projectInfo', res.data);
|
|
}
|
|
};
|
|
|
|
const updateBaseInfo = (info: any) => {
|
|
for (const key in nodeInfo) {
|
|
if (info[key]) {
|
|
nodeInfo[key] = info[key];
|
|
}
|
|
}
|
|
};
|
|
|
|
const refresh = async () => {
|
|
await getNodeDetailFun();
|
|
};
|
|
|
|
onMounted(() => {
|
|
// getNodeDetailFun();
|
|
});
|
|
defineExpose({
|
|
updateBaseInfo,
|
|
refresh,
|
|
});
|
|
watch(
|
|
() => props.nodeId,
|
|
async () => {
|
|
await getNodeDetailFun();
|
|
emits('loaded');
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
</script>
|
|
|
|
<style scoped>
|
|
.info-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 24px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.info-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.info-table tr {
|
|
border-bottom: 1px solid #e9ecef;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.info-table tr:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.info-table tr:hover {
|
|
background-color: rgba(0, 0, 0, 0.02);
|
|
}
|
|
|
|
.info-table td {
|
|
padding: 12px 8px;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.info-table td:first-child {
|
|
width: 120px;
|
|
color: #8d99ae;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.info-table td:nth-child(2) {
|
|
color: #2b2d42;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 4px 12px;
|
|
border-radius: 20px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-3 {
|
|
background-color: rgba(76, 201, 240, 0.1);
|
|
color: #4cc9f0;
|
|
}
|
|
|
|
.status-1 {
|
|
background-color: rgba(67, 97, 238, 0.1);
|
|
color: #4361ee;
|
|
}
|
|
|
|
.status-5 {
|
|
background-color: rgba(248, 37, 133, 0.1);
|
|
color: #f72585;
|
|
}
|
|
|
|
.status-2 {
|
|
background-color: rgba(248, 150, 30, 0.1);
|
|
color: #f8961e;
|
|
}
|
|
.status-0 {
|
|
background-color: rgba(248, 150, 30, 0.1);
|
|
color: #8d99ae;
|
|
}
|
|
|
|
.empty-value {
|
|
color: #8d99ae !important;
|
|
font-style: italic;
|
|
}
|
|
</style>
|