515 lines
16 KiB
Vue
515 lines
16 KiB
Vue
<template>
|
||
<div class="gl-page-content-full">
|
||
<!-- 顶部选择器区域 -->
|
||
<div class="top-selector">
|
||
<div class="select-content">
|
||
<el-form :inline="true" class="demo-form-inline">
|
||
<div class="project-name">
|
||
{{ currentProjectInfo.nodeName }}
|
||
{{ currentProjectInfo.nodeCode ? '(' + currentProjectInfo.nodeCode + ')' : '' }}
|
||
</div>
|
||
</el-form>
|
||
|
||
<!-- <el-select v-model="nodeLevel2Uuid" placeholder="节点" style="margin-right: 10px">
|
||
<el-option label="T01" value="T01"></el-option>
|
||
</el-select> -->
|
||
</div>
|
||
<div class="top-icons">
|
||
<el-button link @click="goProjectListFun">返回列表</el-button>
|
||
<el-button
|
||
v-if="isMember"
|
||
:disabled="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.CLOSED"
|
||
icon="setting"
|
||
@click="openEditBasicDialogFun"
|
||
>
|
||
项目设置
|
||
</el-button>
|
||
<el-button
|
||
v-if="isMember"
|
||
:disabled="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.CLOSED"
|
||
icon="operation"
|
||
@click="openEditNodeDialogFun"
|
||
>
|
||
阶段设置
|
||
</el-button>
|
||
<el-button
|
||
v-if="isMember"
|
||
:disabled="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.CLOSED"
|
||
icon="calendar"
|
||
@click="openAddTaskDialogFun"
|
||
>
|
||
仿真策划
|
||
</el-button>
|
||
<el-popconfirm
|
||
v-if="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.COMPLETED"
|
||
title="项目关闭后,项目中的数据就无法再变更,确认是否关闭?"
|
||
@confirm="closeProject"
|
||
>
|
||
<template #reference>
|
||
<el-button icon="Lock">关闭</el-button>
|
||
</template>
|
||
</el-popconfirm>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 标签页区域 -->
|
||
<el-tabs v-model="activeTab" type="card" class="tab-card" @tab-change="tabChangeFun">
|
||
<el-tab-pane label="任务列表" name="taskList">
|
||
<loadcase
|
||
ref="loadcaseRef"
|
||
v-if="displayedTabs.includes('taskList') && projectUuid && isLoadProjectInfo"
|
||
:projectUuid="projectUuid"
|
||
:projectCode="currentProjectInfo.nodeCode"
|
||
:canPushReport="isMember"
|
||
:projectInfo="currentProjectInfo"
|
||
@getPhaseList="getPhaseListFun"
|
||
:currentPhase="currentProjectInfo.currentPhase"
|
||
/>
|
||
</el-tab-pane>
|
||
<!-- <el-tab-pane label="团队成员" name="teamMembers">
|
||
<teamMember
|
||
v-if="displayedTabs.includes('teamMembers') && projectUuid"
|
||
:nodeLevel1Uuid="projectUuid"
|
||
/>
|
||
</el-tab-pane> -->
|
||
|
||
<el-tab-pane :label="$t('项目详情页.项目详情')" name="projectDetail">
|
||
<div class="project-detail-content">
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.基本信息') }}</div>
|
||
<baseInfo
|
||
ref="basePageRef"
|
||
@update:projectInfo="updateProjectInfo"
|
||
@loaded="projectInfoLoadCompleteFun"
|
||
:nodeId="projectUuid"
|
||
/>
|
||
</div>
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.团队成员') }}</div>
|
||
<teamMember v-if="projectUuid" :nodeLevel1Uuid="projectUuid" />
|
||
</div>
|
||
<template v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])">
|
||
<!-- <div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.参与人员') }}</div>
|
||
<teamMember
|
||
v-if="projectUuid"
|
||
type="temporary-add"
|
||
:isMember="isMember"
|
||
:nodeLevel1Uuid="projectUuid"
|
||
/>
|
||
</div> -->
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.方案维护') }}</div>
|
||
<SchemeMaintain ref="schemeMaintainRef" :nodeId="projectUuid" />
|
||
</div>
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.批次信息') }}</div>
|
||
<BatchInfo ref="batchInfoRef" :nodeId="projectUuid" />
|
||
</div>
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.产线信息') }}</div>
|
||
<productionLine ref="productionLineRef" :nodeCode="currentProjectInfo.nodeCode" />
|
||
</div>
|
||
<div class="section-block">
|
||
<div class="section-title">{{ $t('项目详情页.项目参与人员') }}</div>
|
||
<PDT ref="pdtRef" :nodeId="projectUuid" />
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane label="统计分析" name="statisticAnalysis">
|
||
<StatisticAnalysis
|
||
v-if="displayedTabs.includes('statisticAnalysis') && currentProjectInfo.uuid"
|
||
:projectUuid="currentProjectInfo.uuid"
|
||
></StatisticAnalysis>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="项目文件" name="projectFiles">
|
||
<projectFile
|
||
v-if="displayedTabs.includes('projectFiles') && currentProjectInfo.id"
|
||
:projectId="currentProjectInfo.id"
|
||
:projectUuid="currentProjectInfo.uuid"
|
||
:projectName="currentProjectInfo.nodeName"
|
||
:freeze="currentProjectInfo.exeStatus === PROJECT_EXE_STATUS_CODE.CLOSED"
|
||
/>
|
||
</el-tab-pane>
|
||
|
||
<el-tab-pane
|
||
v-if="enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
||
:label="$t('项目详情页.工位时间维护')"
|
||
name="workspaceTime"
|
||
>
|
||
<WorkspaceTime
|
||
v-if="displayedTabs.includes('workspaceTime') && projectUuid"
|
||
:projectUuid="projectUuid"
|
||
:readonly="!isMember"
|
||
:currentPhaseName="currentProjectInfo.currentPhase"
|
||
/>
|
||
</el-tab-pane>
|
||
<el-tab-pane label="文件数据" name="projectData">
|
||
<DataOverView
|
||
v-if="displayedTabs.includes('projectData') && projectUuid"
|
||
:defaultProjectId="projectUuid"
|
||
hideAddBtn
|
||
hideTree
|
||
/>
|
||
</el-tab-pane>
|
||
<el-tab-pane
|
||
label="策划记录"
|
||
name="planningRecord"
|
||
v-if="!enableConfigByTenant([TENANT_ENUM.LYRIC])"
|
||
>
|
||
<planningRecord
|
||
v-if="displayedTabs.includes('planningRecord') && projectUuid"
|
||
:project-info="currentProjectInfo"
|
||
></planningRecord>
|
||
</el-tab-pane>
|
||
<el-tab-pane
|
||
label="任务指标"
|
||
name="proformance"
|
||
v-if="enableConfigByTenant([TENANT_ENUM.BASE])"
|
||
>
|
||
<projectTaskPerformanceList
|
||
v-if="displayedTabs.includes('proformance') && projectUuid"
|
||
:projectUuid="projectUuid"
|
||
></projectTaskPerformanceList>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</div>
|
||
<projectInfoDialog
|
||
:projectId="currentProjectInfo.uuid"
|
||
ref="basePageFormRef"
|
||
v-if="showProjectInfoDialog"
|
||
v-model="showProjectInfoDialog"
|
||
:nodeLevel1List="nodeLevel1List"
|
||
@update:currentProjectBaseInfo="updateCurrentProjectBaseInfo"
|
||
@completeFun="completeFun"
|
||
/>
|
||
<nodeInfoDialog
|
||
ref="nodePageRef"
|
||
v-if="showNodeInfoDialog"
|
||
:nodeLevel1Uuid="projectUuid"
|
||
:projectBeginTime="currentProjectInfo.beginTime"
|
||
:projectEndTime="currentProjectInfo.endTime"
|
||
:projectInfo="currentProjectInfo"
|
||
v-model:showNodeInfoDialog="showNodeInfoDialog"
|
||
dialogType="edit"
|
||
@completeFun="completeFun"
|
||
/>
|
||
<TaskDialog
|
||
v-if="showTaskDialog && isLoadProjectInfo"
|
||
v-model:showTaskDialog="showTaskDialog"
|
||
dialogType="edit"
|
||
:nodeLevel1Name="currentProjectInfo.nodeName"
|
||
:nodeLevel1Info="currentProjectInfo"
|
||
:nodeLevel1Uuid="projectUuid"
|
||
:projectBeginTime="currentProjectInfo.beginTime"
|
||
:projectEndTime="currentProjectInfo.endTime"
|
||
@taskComplete="completeFun"
|
||
:currentPhase="currentProjectInfo.currentPhase"
|
||
/>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { reactive, ref, watch } from 'vue';
|
||
import projectFile from './components/projectFile.vue';
|
||
import teamMember from './components/teamMember.vue';
|
||
import loadcase from './components/loadcase.vue';
|
||
import projectInfoDialog from '@/components/project/projectInfoDialog.vue';
|
||
import nodeInfoDialog from '@/components/project/phaseInfoDialog.vue';
|
||
import TaskDialog from '../projectList/components/taskDialog.vue';
|
||
import baseInfo from './components/baseInfo.vue';
|
||
import { editNodeApi } from '@/api/project/node';
|
||
import { PROJECT_EXE_STATUS_CODE } from '@/utils/enum/project';
|
||
import { ElMessage } from 'element-plus';
|
||
import StatisticAnalysis from './components/statisticAnalysis.vue';
|
||
import SchemeMaintain from '@/tenants/lyric/views/project/schemeMaintain.vue';
|
||
import BatchInfo from '@/tenants/lyric/views/project/batchInfo.vue';
|
||
import productionLine from '@/tenants/lyric/views/project/productionLine.vue';
|
||
import PDT from '@/tenants/lyric/views/project/PDT.vue';
|
||
import WorkspaceTime from '@/tenants/lyric/views/project/workspaceTime.vue';
|
||
import { enableConfigByTenant, TENANT_ENUM } from '@/tenants/tenant';
|
||
import { disposeAsyncPhase } from '@/tenants/lyric/views/project/project';
|
||
import DataOverView from '@/views/data/overview/components/index.vue';
|
||
import planningRecord from './components/planningRecord.vue';
|
||
import projectTaskPerformanceList from './components/projectTaskPerformanceList.vue';
|
||
import { isSimProjectManager } from '@/utils/task';
|
||
import { useRoute } from 'vue-router';
|
||
import { jumpPage } from '@/utils/common';
|
||
// import { queryNodeListApi } from '@/api/project/node';
|
||
// import { NODE_TYPE } from '@/utils/enum/node';
|
||
|
||
const props = defineProps({
|
||
projectUuid: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
});
|
||
|
||
const route = useRoute();
|
||
|
||
const nodeLevel1List = ref<any>([]);
|
||
|
||
// 表单弹窗ref
|
||
const basePageFormRef = ref();
|
||
|
||
// 项目信息界面ref
|
||
const basePageRef = ref();
|
||
|
||
const activeTab = ref('taskList');
|
||
|
||
const listPagePath: any = {
|
||
'0': '/project/allProject',
|
||
'1': '/project/followProject',
|
||
'2': '/project/chargeProject',
|
||
};
|
||
const goProjectListFun = () => {
|
||
const projectType: any = route.query?.projectType || '0';
|
||
jumpPage({
|
||
path: listPagePath[projectType],
|
||
});
|
||
};
|
||
|
||
const showProjectInfoDialog = ref(false);
|
||
// const currentProjectBaseInfo = reactive({
|
||
// id: '',
|
||
// projectName: '项目名称',
|
||
// projectCode: '项目代号',
|
||
// projectType: '项目类型',
|
||
// projectManager: '项目经理',
|
||
// progressStatus: '进行中',
|
||
// currentNode: 'T01',
|
||
// planStartTime: '2024-01-01',
|
||
// planEndTime: '2024-12-31',
|
||
// actualStartTime: '2024-01-05',
|
||
// actualEndTime: '',
|
||
// });
|
||
|
||
const openEditBasicDialogFun = () => {
|
||
showProjectInfoDialog.value = true;
|
||
// setTimeout(() => {
|
||
// nextTick(
|
||
// () => {
|
||
// basePageFormRef.value.setEditForm({ ...currentProjectInfo });
|
||
// const statusList = getProjectExeStatus(currentProjectInfo.exeStatus as PROJECT_EXE_STATUS_CODE);
|
||
// basePageFormRef.value.setOptionsFun('exeStatus', statusList);
|
||
// }
|
||
// );
|
||
// }, 500);
|
||
};
|
||
|
||
const showNodeInfoDialog = ref(false);
|
||
const openEditNodeDialogFun = () => {
|
||
showNodeInfoDialog.value = true;
|
||
};
|
||
|
||
const showTaskDialog = ref(false);
|
||
const openAddTaskDialogFun = async () => {
|
||
if (enableConfigByTenant([TENANT_ENUM.LYRIC])) {
|
||
const isSync = await disposeAsyncPhase(phaseList.value, currentProjectInfo);
|
||
if (isSync) {
|
||
showTaskDialog.value = true;
|
||
}
|
||
}
|
||
if (phaseList.value.length === 0) {
|
||
ElMessage.warning('请先创建阶段');
|
||
return;
|
||
}
|
||
|
||
showTaskDialog.value = true;
|
||
};
|
||
const currentProjectInfo = reactive<any>({
|
||
id: '',
|
||
projectId: '', // EP的项目id
|
||
projectSource: '',
|
||
uuid: '',
|
||
nodeName: '',
|
||
nodeCode: '',
|
||
nodeType: '',
|
||
nodeSubType: '',
|
||
progressStatus: '',
|
||
currentPhase: '',
|
||
beginTime: '',
|
||
endTime: '',
|
||
exeStatus: '',
|
||
actualStartTime: '',
|
||
actualEndTime: '',
|
||
description: '',
|
||
memberList: [],
|
||
});
|
||
|
||
const updateProjectInfo = (projectInfo: any) => {
|
||
for (const key in currentProjectInfo) {
|
||
currentProjectInfo[key] = projectInfo[key];
|
||
}
|
||
};
|
||
|
||
// const getProjectListApi = async() => {
|
||
// const res:any = await queryNodeListApi({ current: 1, size: 999, nodeType: NODE_TYPE.PROJECT });
|
||
// if (res && res.code === 200) {
|
||
// nodeLevel1List.value = res.data.data.map((item: { nodeName: string; uuid: string; }) => {
|
||
// // 赋予projectUuid初始值
|
||
// if (!projectUuid.value) {
|
||
// projectUuid.value = item.uuid;
|
||
// projectName.value = item.nodeName;
|
||
// }
|
||
// return { label: item.nodeName, info: { ...item }, value: item.uuid };
|
||
// });
|
||
// } else {
|
||
// nodeLevel1List.value = [];
|
||
// }
|
||
// };
|
||
|
||
const updateCurrentProjectBaseInfo = (projectInfo: any) => {
|
||
for (const key in currentProjectInfo) {
|
||
currentProjectInfo[key] = projectInfo[key];
|
||
}
|
||
basePageRef.value.updateBaseInfo(projectInfo);
|
||
};
|
||
|
||
const loadcaseRef = ref();
|
||
|
||
const completeFun = async (page: string) => {
|
||
if (page === 'projectBasePage') {
|
||
basePageRef.value.refresh();
|
||
}
|
||
if (page === 'phasePage') {
|
||
// 先刷新阶段信息 (刷新currentProjectInfo.currentPhase)
|
||
await basePageRef.value.refresh();
|
||
loadcaseRef.value.refreshPhaseList();
|
||
}
|
||
if (page === 'taskPlanPage') {
|
||
loadcaseRef.value.getTaskTreeList();
|
||
}
|
||
};
|
||
|
||
const closeProject = async () => {
|
||
const res: any = await editNodeApi({
|
||
editNodeList: [{ uuid: props.projectUuid, exeStatus: PROJECT_EXE_STATUS_CODE.CLOSED }],
|
||
});
|
||
if (res && res.code === 200) {
|
||
ElMessage.success('关闭项目成功!');
|
||
} else {
|
||
ElMessage.error(res.message || '关闭项目失败!');
|
||
}
|
||
};
|
||
|
||
const phaseList = ref<any[]>([]);
|
||
|
||
const getPhaseListFun = (phaseArr: any[]) => {
|
||
phaseList.value = phaseArr;
|
||
};
|
||
|
||
const displayedTabs = ref(['taskList']);
|
||
|
||
const tabChangeFun = (tab: string) => {
|
||
if (!displayedTabs.value.includes(tab)) {
|
||
displayedTabs.value.push(tab);
|
||
}
|
||
};
|
||
const isLoadProjectInfo = ref(false);
|
||
const projectInfoLoadCompleteFun = () => {
|
||
isLoadProjectInfo.value = true;
|
||
};
|
||
|
||
// if (route.query?.nodeId) {
|
||
// projectUuid.value = route.query?.nodeId;
|
||
// projectName.value = route.query?.nodeName;
|
||
// sessionStorage.setItem('projectUuid', projectUuid.value);
|
||
// sessionStorage.setItem('projectName', projectName.value);
|
||
// } else {
|
||
// // 使用上一次查看的项目id
|
||
// if (sessionStorage.getItem('projectUuid')) {
|
||
// projectUuid.value = sessionStorage.getItem('projectUuid');
|
||
// projectName.value = sessionStorage.getItem('projectName');
|
||
// } else {
|
||
// getProjectListApi();
|
||
// }
|
||
// }
|
||
|
||
// 当前用户是不是项目经理
|
||
const isMember = ref(false);
|
||
watch(
|
||
() => currentProjectInfo.memberList,
|
||
(newVal) => {
|
||
isMember.value = isSimProjectManager(newVal);
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.app-container {
|
||
padding: 16px;
|
||
}
|
||
.select-content {
|
||
width: 500px;
|
||
display: flex;
|
||
align-items: center;
|
||
span {
|
||
display: inline-block;
|
||
width: 100px;
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
.top-selector {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.top-icons {
|
||
margin-left: auto;
|
||
// display: flex;
|
||
// gap: 16px;
|
||
.el-icon {
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
.project-name {
|
||
font-size: 16px;
|
||
}
|
||
.node-select {
|
||
width: 120px;
|
||
}
|
||
.el-tabs {
|
||
height: calc(100% - 68px);
|
||
.el-tab-pane {
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.project-detail-content {
|
||
height: 100%;
|
||
overflow-y: auto;
|
||
padding-right: 10px;
|
||
}
|
||
|
||
.section-block {
|
||
margin-bottom: 24px;
|
||
padding-bottom: 20px;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: var(--el-text-color-primary);
|
||
margin-bottom: 12px;
|
||
padding-left: 10px;
|
||
border-left: 3px solid var(--el-color-primary);
|
||
}
|
||
</style>
|
||
|
||
<style lang="scss">
|
||
.tab-card {
|
||
.darg-line {
|
||
display: none !important;
|
||
}
|
||
}
|
||
</style>
|