From 71a9eef518f2f2f1a1eb2fb90f2eb8ab7b155bc8 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 08 一月 2026 14:57:56 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_天津军泰伟业' into dev_天津军泰伟业
---
src/views/oaSystem/projectManagement/projectDetail.vue | 868 +++++++++++++++++++++++++++++----------------------------
1 files changed, 448 insertions(+), 420 deletions(-)
diff --git a/src/views/oaSystem/projectManagement/projectDetail.vue b/src/views/oaSystem/projectManagement/projectDetail.vue
index c3b0779..83f3dd8 100644
--- a/src/views/oaSystem/projectManagement/projectDetail.vue
+++ b/src/views/oaSystem/projectManagement/projectDetail.vue
@@ -8,7 +8,8 @@
<span>椤圭洰鍩烘湰淇℃伅</span>
</div>
</template>
- <el-descriptions :column="2" border>
+ <el-descriptions :column="2"
+ border>
<el-descriptions-item label="椤圭洰鍚嶇О">{{ projectInfo.projectName }}</el-descriptions-item>
<el-descriptions-item label="椤圭洰璐熻矗浜�">{{ projectInfo.managerName }}</el-descriptions-item>
<el-descriptions-item label="寮�濮嬫棩鏈�">{{ projectInfo.startDate }}</el-descriptions-item>
@@ -17,12 +18,13 @@
<el-tag :type="getStatusType(projectInfo.status)">{{ getStatusText(projectInfo.status) }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="瀹屾垚搴�">
- <el-progress :percentage="projectInfo.completionRate" :stroke-width="6" />
+ <el-progress :percentage="projectInfo.completionRate"
+ :stroke-width="6" />
</el-descriptions-item>
- <el-descriptions-item label="椤圭洰鎻忚堪" :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="椤圭洰鎻忚堪"
+ :span="2">{{ projectInfo.description || '-' }}</el-descriptions-item>
</el-descriptions>
</el-card>
-
<!-- 椤圭洰杩涘害姒傝 -->
<el-card class="mb20">
<template #header>
@@ -57,7 +59,6 @@
</el-col>
</el-row>
</el-card>
-
<!-- 闃舵鍜屼换鍔$鐞� -->
<!-- <el-card class="mb20">
<template #header>
@@ -68,162 +69,175 @@
</template>
<task-tree :project-id="projectId" @refresh="getProjectDetail" />
</el-card> -->
-
<!-- 閲岀▼纰戠鐞� -->
<el-card class="mb20">
<template #header>
<div class="card-header">
<span>椤圭洰闃舵閲岀▼纰�</span>
- <el-button type="primary" size="small" @click="handleAddMilestone">娣诲姞閲岀▼纰�</el-button>
+ <el-button type="primary"
+ size="small"
+ @click="handleAddMilestone">娣诲姞閲岀▼纰�</el-button>
</div>
</template>
- <milestone-list :project-id="projectId" @refresh="getProjectDetail" :key="`milestone-${refreshProjectId}`"/>
+ <milestone-list :project-id="projectId"
+ @refresh="getProjectDetail"
+ :key="`milestone-${refreshProjectId}`" />
</el-card>
-
<!-- 闃舵鐩爣绠$悊 -->
<el-card>
<template #header>
<div class="card-header">
<span>闃舵浠诲姟</span>
- <el-button type="primary" size="small" @click="handleAddPhaseGoal">娣诲姞闃舵鐩爣</el-button>
+ <el-button type="primary"
+ size="small"
+ @click="handleAddPhaseGoal">娣诲姞闃舵鐩爣</el-button>
</div>
</template>
- <phase-goal-list :project-id="projectId" @refresh="getProjectDetail" @editGoal="handleEditPhaseGoal" :key="`phaseGoal-${refreshProjectId}`"/>
+ <phase-goal-list :project-id="projectId"
+ @refresh="getProjectDetail"
+ @editGoal="handleEditPhaseGoal"
+ :key="`phaseGoal-${refreshProjectId}`" />
</el-card>
-
- <!-- 閲岀▼纰戠鐞嗗脊妗� -->
- <el-dialog :title="title" v-model="open" width="600px" append-to-body>
- <el-form :model="form" ref="formRef" label-width="100px">
- <el-form-item label="椤圭洰闃舵鍚嶇О" prop="phaseName">
- <el-input
- v-model="form.phaseName"
- placeholder="璇疯緭鍏ラ」鐩樁娈靛悕绉�"
- maxlength="50"
- />
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="form.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨寮�濮嬫棩鏈�"
- style="width: 100%"
- />
+ <!-- 閲岀▼纰戠鐞嗗脊妗� -->
+ <el-dialog :title="title"
+ v-model="open"
+ width="600px"
+ append-to-body>
+ <el-form :model="form"
+ ref="formRef"
+ label-width="100px">
+ <el-form-item label="椤圭洰闃舵鍚嶇О"
+ prop="phaseName">
+ <el-input v-model="form.phaseName"
+ placeholder="璇疯緭鍏ラ」鐩樁娈靛悕绉�"
+ maxlength="50" />
</el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="form.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨缁撴潫鏃ユ湡"
- style="width: 100%"
- />
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="寮�濮嬫棩鏈�"
+ prop="startDate">
+ <el-date-picker v-model="form.startDate"
+ type="date"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨寮�濮嬫棩鏈�"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁撴潫鏃ユ湡"
+ prop="endDate">
+ <el-date-picker v-model="form.endDate"
+ type="date"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨缁撴潫鏃ユ湡"
+ style="width: 100%" />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-radio-group v-model="form.status">
+ <el-radio label="notStarted">鏈紑濮�</el-radio>
+ <el-radio label="completed">宸插畬鎴�</el-radio>
+ <el-radio label="delayed">宸插欢杩�</el-radio>
+ </el-radio-group>
</el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="鐘舵��" prop="status">
- <el-radio-group v-model="form.status">
- <el-radio label="notStarted">鏈紑濮�</el-radio>
- <el-radio label="completed">宸插畬鎴�</el-radio>
- <el-radio label="delayed">宸插欢杩�</el-radio>
- </el-radio-group>
- </el-form-item>
- </el-form>
+ </el-form>
<template #footer>
<div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitForm">纭畾</el-button>
<el-button @click="cancel">鍙栨秷</el-button>
- <el-button type="primary" @click="submitForm">纭畾</el-button>
</div>
</template>
</el-dialog>
-
<!-- 闃舵浠诲姟绠$悊寮规 -->
- <el-dialog :title="goalTitle" v-model="goalOpen" width="600px" append-to-body>
- <el-form :model="goalForm" ref="goalFormRef" label-width="100px">
- <el-form-item label="鎵�灞為樁娈�" prop="phaseId">
- <el-select v-model="goalForm.phaseId" placeholder="璇烽�夋嫨鎵�灞為樁娈�">
- <el-option
- v-for="phase in phaseList"
- :key="phase.phaseId"
- :label="phase.phaseName"
- :value="phase.phaseId"
- />
+ <el-dialog :title="goalTitle"
+ v-model="goalOpen"
+ width="600px"
+ append-to-body>
+ <el-form :model="goalForm"
+ ref="goalFormRef"
+ label-width="100px">
+ <el-form-item label="鎵�灞為樁娈�"
+ prop="phaseId">
+ <el-select v-model="goalForm.phaseId"
+ placeholder="璇烽�夋嫨鎵�灞為樁娈�">
+ <el-option v-for="phase in phaseList"
+ :key="phase.phaseId"
+ :label="phase.phaseName"
+ :value="phase.phaseId" />
</el-select>
</el-form-item>
- <el-form-item label="鐩爣鍚嶇О" prop="taskName">
- <el-input
- v-model="goalForm.taskName"
- placeholder="璇疯緭鍏ョ洰鏍囧悕绉�"
- maxlength="50"
- />
+ <el-form-item label="鐩爣鍚嶇О"
+ prop="taskName">
+ <el-input v-model="goalForm.taskName"
+ placeholder="璇疯緭鍏ョ洰鏍囧悕绉�"
+ maxlength="50" />
</el-form-item>
- <el-form-item label="鐩爣鍊�" prop="targetValue">
- <el-input-number
- v-model="goalForm.targetValue"
- :min="0"
- :precision="2"
- placeholder="璇疯緭鍏ョ洰鏍囧��"
- style="width: 100%"
- />
+ <el-form-item label="鐩爣鍊�"
+ prop="targetValue">
+ <el-input-number v-model="goalForm.targetValue"
+ :min="0"
+ :precision="2"
+ placeholder="璇疯緭鍏ョ洰鏍囧��"
+ style="width: 100%" />
</el-form-item>
- <el-form-item label="褰撳墠鍊�" prop="currentValue">
- <el-input-number
- v-model="goalForm.currentValue"
- :min="0"
- :precision="2"
- placeholder="璇疯緭鍏ュ綋鍓嶅��"
- style="width: 100%"
- />
+ <el-form-item label="褰撳墠鍊�"
+ prop="currentValue">
+ <el-input-number v-model="goalForm.currentValue"
+ :min="0"
+ :precision="2"
+ placeholder="璇疯緭鍏ュ綋鍓嶅��"
+ style="width: 100%" />
</el-form-item>
- <el-form-item label="鍗曚綅" prop="unit">
- <el-input
- v-model="goalForm.unit"
- placeholder="璇疯緭鍏ュ崟浣�"
- maxlength="10"
- />
+ <el-form-item label="鍗曚綅"
+ prop="unit">
+ <el-input v-model="goalForm.unit"
+ placeholder="璇疯緭鍏ュ崟浣�"
+ maxlength="10" />
</el-form-item>
- <el-form-item label="浠诲姟瀹屾垚鏃ユ湡" prop="targetDate">
- <el-date-picker
- v-model="goalForm.targetDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
+ <el-form-item label="浠诲姟瀹屾垚鏃ユ湡"
+ prop="targetDate">
+ <el-date-picker v-model="goalForm.targetDate"
+ type="date"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨鐩爣鏃ユ湡"
+ style="width: 100%" />
</el-form-item>
- <el-form-item label="寮�濮嬫棩鏈�" prop="startDate">
- <el-date-picker
- v-model="goalForm.startDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
+ <el-form-item label="寮�濮嬫棩鏈�"
+ prop="startDate">
+ <el-date-picker v-model="goalForm.startDate"
+ type="date"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨鐩爣鏃ユ湡"
+ style="width: 100%" />
</el-form-item>
- <el-form-item label="缁撴潫鏃ユ湡" prop="endDate">
- <el-date-picker
- v-model="goalForm.endDate"
- type="date"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- placeholder="閫夋嫨鐩爣鏃ユ湡"
- style="width: 100%"
- />
+ <el-form-item label="缁撴潫鏃ユ湡"
+ prop="endDate">
+ <el-date-picker v-model="goalForm.endDate"
+ type="date"
+ format="YYYY-MM-DD"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨鐩爣鏃ユ湡"
+ style="width: 100%" />
</el-form-item>
- <el-form-item label="鐘舵��" prop="status">
- <el-select v-model="goalForm.status" placeholder="璇烽�夋嫨鐘舵��">
- <el-option label="鏈紑濮�" value="notStarted" />
- <el-option label="杩涜涓�" value="inProgress" />
- <el-option label="宸插畬鎴�" value="completed" />
- <el-option label="宸插欢杩�" value="delayed" />
+ <el-form-item label="鐘舵��"
+ prop="status">
+ <el-select v-model="goalForm.status"
+ placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="鏈紑濮�"
+ value="notStarted" />
+ <el-option label="杩涜涓�"
+ value="inProgress" />
+ <el-option label="宸插畬鎴�"
+ value="completed" />
+ <el-option label="宸插欢杩�"
+ value="delayed" />
</el-select>
</el-form-item>
<!-- <el-form-item label="瀹屾垚搴�" prop="completionRate">
@@ -239,8 +253,9 @@
</el-form>
<template #footer>
<div class="dialog-footer">
+ <el-button type="primary"
+ @click="submitGoalForm">纭畾</el-button>
<el-button @click="cancelGoal">鍙栨秷</el-button>
- <el-button type="primary" @click="submitGoalForm">纭畾</el-button>
</div>
</template>
</el-dialog>
@@ -248,318 +263,331 @@
</template>
<script setup>
-import { ref, reactive, onMounted, watch } from 'vue';
-import { useRoute, useRouter } from 'vue-router';
-import { ElMessage } from 'element-plus';
-import TaskTree from './components/taskTree.vue';
-import MilestoneList from './components/milestoneList.vue';
-import ProjectForm from './components/projectForm.vue';
-import PhaseGoalList from './components/phaseGoalList.vue';
-import { getProject, addProjectPhase, listProjectPhase, addProjectTask, updateProjectTask } from '@/api/oaSystem/projectManagement';
+ import { ref, reactive, onMounted, watch } from "vue";
+ import { useRoute, useRouter } from "vue-router";
+ import { ElMessage } from "element-plus";
+ import TaskTree from "./components/taskTree.vue";
+ import MilestoneList from "./components/milestoneList.vue";
+ import ProjectForm from "./components/projectForm.vue";
+ import PhaseGoalList from "./components/phaseGoalList.vue";
+ import {
+ getProject,
+ addProjectPhase,
+ listProjectPhase,
+ addProjectTask,
+ updateProjectTask,
+ } from "@/api/oaSystem/projectManagement";
-const route = useRoute();
-const router = useRouter();
-const open = ref(false);
-const title = ref('');
-const projectFormRef = ref();
-const formRef = ref();
-// 椤圭洰ID
-// 鍦ㄥ叾浠杛ef瀹氫箟闄勮繎娣诲姞
-const refreshProjectId = ref(0);
+ const route = useRoute();
+ const router = useRouter();
+ const open = ref(false);
+ const title = ref("");
+ const projectFormRef = ref();
+ const formRef = ref();
+ // 椤圭洰ID
+ // 鍦ㄥ叾浠杛ef瀹氫箟闄勮繎娣诲姞
+ const refreshProjectId = ref(0);
-const projectId = ref(route.params.projectId);
+ const projectId = ref(route.params.projectId);
-// 椤圭洰淇℃伅
-const projectInfo = reactive({
- projectId: '',
- projectName: '',
- description: '',
- startDate: '',
- endDate: '',
- managerId: '',
- managerName: '',
- status: 'planning',
- completionRate: 0
-});
+ // 椤圭洰淇℃伅
+ const projectInfo = reactive({
+ projectId: "",
+ projectName: "",
+ description: "",
+ startDate: "",
+ endDate: "",
+ managerId: "",
+ managerName: "",
+ status: "planning",
+ completionRate: 0,
+ });
-// 缁熻淇℃伅
-const statistics = reactive({
- totalPhases: 0,
- totalTasks: 0,
- completedTasks: 0
-});
-const form = reactive({
- phaseId: '',
- phaseName: '',
- startDate: '',
- endDate: '',
- status: 'planning',
- oaProjectId: projectId.value,
-})
+ // 缁熻淇℃伅
+ const statistics = reactive({
+ totalPhases: 0,
+ totalTasks: 0,
+ completedTasks: 0,
+ });
+ const form = reactive({
+ phaseId: "",
+ phaseName: "",
+ startDate: "",
+ endDate: "",
+ status: "planning",
+ oaProjectId: projectId.value,
+ });
-// 闃舵鐩爣鐩稿叧
-const goalOpen = ref(false);
-const goalTitle = ref('');
-const goalFormRef = ref();
-const phaseList = ref([]);
-const goalForm = reactive({
- taskId: '',
- phaseId: '',
- taskName: '',
- targetValue: 100,
- currentValue: 0,
- unit: '%',
- targetDate: '',
- startDate: '',
- endDate: '',
- status: 'notStarted',
- completionRate: 0
-});
+ // 闃舵鐩爣鐩稿叧
+ const goalOpen = ref(false);
+ const goalTitle = ref("");
+ const goalFormRef = ref();
+ const phaseList = ref([]);
+ const goalForm = reactive({
+ taskId: "",
+ phaseId: "",
+ taskName: "",
+ targetValue: 100,
+ currentValue: 0,
+ unit: "%",
+ targetDate: "",
+ startDate: "",
+ endDate: "",
+ status: "notStarted",
+ completionRate: 0,
+ });
-// 鑾峰彇椤圭洰璇︽儏
-const getProjectDetail = async () => {
- try {
- getProject().then((res)=>{
- console.log("椤圭洰璇︽儏",res)
- const projectData = res.data[projectId.value];
- // 鏇存柊椤圭洰淇℃伅
- Object.assign(projectInfo, projectData);
-
- // 鏇存柊缁熻淇℃伅
- updateStatistics(projectData);
+ // 鑾峰彇椤圭洰璇︽儏
+ const getProjectDetail = async () => {
+ try {
+ getProject().then(res => {
+ console.log("椤圭洰璇︽儏", res);
+ const projectData = res.data[projectId.value];
+ // 鏇存柊椤圭洰淇℃伅
+ Object.assign(projectInfo, projectData);
- // 寮哄埗鏇存柊DOM浠ョ‘淇濆瓙缁勪欢鑳芥纭埛鏂�
- // 杩欓噷閫氳繃瑙﹀彂refreshProjectId浜嬩欢鏉ュ己鍒跺埛鏂板瓙缁勪欢
- refreshProjectId.value++;
- })
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰璇︽儏澶辫触');
- console.error('鑾峰彇椤圭洰璇︽儏澶辫触:', error);
- }
-};
+ // 鏇存柊缁熻淇℃伅
+ updateStatistics(projectData);
-// 鏇存柊缁熻淇℃伅
-const updateStatistics = (projectData) => {
- // 杩欓噷鍋囪projectData涓寘鍚簡缁熻淇℃伅
- // 濡傛灉娌℃湁锛岄渶瑕佸崟鐙姹傜粺璁℃暟鎹�
- statistics.totalPhases = projectData.phases ? projectData.phases.length : 0;
- statistics.totalTasks = projectData.tasks ? projectData.tasks.length : 0;
- statistics.completedTasks = projectData.tasks ?
- projectData.tasks.filter(task => task.status === 'completed').length : 0;
-};
+ // 寮哄埗鏇存柊DOM浠ョ‘淇濆瓙缁勪欢鑳芥纭埛鏂�
+ // 杩欓噷閫氳繃瑙﹀彂refreshProjectId浜嬩欢鏉ュ己鍒跺埛鏂板瓙缁勪欢
+ refreshProjectId.value++;
+ });
+ } catch (error) {
+ ElMessage.error("鑾峰彇椤圭洰璇︽儏澶辫触");
+ console.error("鑾峰彇椤圭洰璇︽儏澶辫触:", error);
+ }
+ };
-// 鑾峰彇椤圭洰闃舵鍒楄〃
-const getPhaseList = async () => {
- try {
- const { data } = await listProjectPhase(projectId.value);
- phaseList.value = data.rows || data;
- } catch (error) {
- ElMessage.error('鑾峰彇椤圭洰闃舵鍒楄〃澶辫触');
- console.error('鑾峰彇椤圭洰闃舵鍒楄〃澶辫触:', error);
- }
-};
+ // 鏇存柊缁熻淇℃伅
+ const updateStatistics = projectData => {
+ // 杩欓噷鍋囪projectData涓寘鍚簡缁熻淇℃伅
+ // 濡傛灉娌℃湁锛岄渶瑕佸崟鐙姹傜粺璁℃暟鎹�
+ statistics.totalPhases = projectData.phases ? projectData.phases.length : 0;
+ statistics.totalTasks = projectData.tasks ? projectData.tasks.length : 0;
+ statistics.completedTasks = projectData.tasks
+ ? projectData.tasks.filter(task => task.status === "completed").length
+ : 0;
+ };
-// 璁$畻瀹屾垚搴�
-const calculateCompletionRate = () => {
- if (goalForm.targetValue > 0) {
- goalForm.completionRate = Math.min(Math.round((goalForm.currentValue / goalForm.targetValue) * 100), 100);
- } else {
- goalForm.completionRate = 0;
- }
-};
+ // 鑾峰彇椤圭洰闃舵鍒楄〃
+ const getPhaseList = async () => {
+ try {
+ const { data } = await listProjectPhase(projectId.value);
+ phaseList.value = data.rows || data;
+ } catch (error) {
+ ElMessage.error("鑾峰彇椤圭洰闃舵鍒楄〃澶辫触");
+ console.error("鑾峰彇椤圭洰闃舵鍒楄〃澶辫触:", error);
+ }
+ };
-// 娣诲姞闃舵
-const handleAddPhase = () => {
- // resetForm();
- ElMessage.info('娣诲姞闃舵鍔熻兘寰呭疄鐜�');
-};
-
-// 娣诲姞閲岀▼纰�
-const handleAddMilestone = () => {
- resetForm();
- open.value = true;
- title.value = '鏂板椤圭洰闃舵';
-};
-
-// 娣诲姞闃舵浠诲姟
-const handleAddPhaseGoal = () => {
- goalForm.taskId = '';
- goalForm.phaseId = '';
- goalForm.taskName = '';
- goalForm.targetValue = 0;
- goalForm.currentValue = 0;
- goalForm.unit = '%';
- goalForm.targetDate = '';
- goalForm.startDate = '';
- goalForm.endDate = '';
- goalForm.status = 'notStarted';
- goalForm.completionRate = 0;
- if (goalFormRef.value) {
- goalFormRef.value.resetFields();
- }
- getPhaseList();
- goalTitle.value = '鏂板闃舵鐩爣';
- goalOpen.value = true;
-};
-
-// 鎻愪氦琛ㄥ崟
-const submitForm = async () => {
- try {
- await formRef.value.validate();
-
- if (form.phaseId) {
- // await updateProject(form);
- // ElMessage.success('淇敼椤圭洰闃舵鎴愬姛');
+ // 璁$畻瀹屾垚搴�
+ const calculateCompletionRate = () => {
+ if (goalForm.targetValue > 0) {
+ goalForm.completionRate = Math.min(
+ Math.round((goalForm.currentValue / goalForm.targetValue) * 100),
+ 100
+ );
} else {
- console.log("form",form);
- await addProjectPhase(form);
- ElMessage.success('鏂板椤圭洰闃舵鎴愬姛');
+ goalForm.completionRate = 0;
+ }
+ };
+
+ // 娣诲姞闃舵
+ const handleAddPhase = () => {
+ // resetForm();
+ ElMessage.info("娣诲姞闃舵鍔熻兘寰呭疄鐜�");
+ };
+
+ // 娣诲姞閲岀▼纰�
+ const handleAddMilestone = () => {
+ resetForm();
+ open.value = true;
+ title.value = "鏂板椤圭洰闃舵";
+ };
+
+ // 娣诲姞闃舵浠诲姟
+ const handleAddPhaseGoal = () => {
+ goalForm.taskId = "";
+ goalForm.phaseId = "";
+ goalForm.taskName = "";
+ goalForm.targetValue = 0;
+ goalForm.currentValue = 0;
+ goalForm.unit = "%";
+ goalForm.targetDate = "";
+ goalForm.startDate = "";
+ goalForm.endDate = "";
+ goalForm.status = "notStarted";
+ goalForm.completionRate = 0;
+ if (goalFormRef.value) {
+ goalFormRef.value.resetFields();
+ }
+ getPhaseList();
+ goalTitle.value = "鏂板闃舵鐩爣";
+ goalOpen.value = true;
+ };
+
+ // 鎻愪氦琛ㄥ崟
+ const submitForm = async () => {
+ try {
+ await formRef.value.validate();
+
+ if (form.phaseId) {
+ // await updateProject(form);
+ // ElMessage.success('淇敼椤圭洰闃舵鎴愬姛');
+ } else {
+ console.log("form", form);
+ await addProjectPhase(form);
+ ElMessage.success("鏂板椤圭洰闃舵鎴愬姛");
+ getProjectDetail();
+ }
+ open.value = false;
+ } catch (error) {
+ console.error("鎻愪氦琛ㄥ崟澶辫触:", error);
+ }
+ };
+
+ // 鎻愪氦闃舵浠诲姟琛ㄥ崟
+ const submitGoalForm = async () => {
+ try {
+ await goalFormRef.value.validate();
+ calculateCompletionRate();
+
+ const goalData = {
+ ...goalForm,
+ oaProjectId: projectId.value,
+ };
+
+ if (goalForm.taskId) {
+ await updateProjectTask(goalData);
+ ElMessage.success("淇敼闃舵鐩爣鎴愬姛");
+ } else {
+ await addProjectTask(goalData);
+ ElMessage.success("鏂板闃舵鐩爣鎴愬姛");
+ }
+ // 璋冪敤getProjectDetail鍒锋柊鎵�鏈夌浉鍏虫暟鎹�
+ getProjectDetail();
+ goalOpen.value = false;
+ } catch (error) {
+ console.error("鎻愪氦闃舵鐩爣琛ㄥ崟澶辫触:", error);
+ }
+ };
+
+ // 閲嶇疆閲岀▼纰戣〃鍗�
+ const resetForm = () => {
+ form.phaseId = "";
+ form.phaseName = "";
+ form.startDate = "";
+ form.endDate = "";
+ form.status = "planning";
+ form.oaProjectId = projectId.value;
+ if (formRef.value) {
+ formRef.value.resetFields();
+ }
+ };
+
+ // 鍙栨秷闃舵浠诲姟鎿嶄綔
+ const cancelGoal = () => {
+ goalOpen.value = false;
+ };
+
+ // 鍙栨秷鎿嶄綔
+ const cancel = () => {
+ open.value = false;
+ };
+ // 缂栬緫闃舵浠诲姟
+ const handleEditPhaseGoal = async goal => {
+ // 澶嶅埗鐩爣鏁版嵁鍒拌〃鍗�
+ Object.assign(goalForm, goal);
+
+ // 鑾峰彇椤圭洰闃舵鍒楄〃
+ await getPhaseList();
+
+ // 鎵撳紑缂栬緫寮圭獥
+ goalTitle.value = "缂栬緫闃舵鐩爣";
+ goalOpen.value = true;
+ };
+ // 鑾峰彇鐘舵�佹爣绛剧被鍨�
+ const getStatusType = status => {
+ const statusTypeMap = {
+ planning: "info",
+ inProgress: "primary",
+ completed: "success",
+ paused: "warning",
+ };
+ return statusTypeMap[status] || "default";
+ };
+
+ // 鑾峰彇鐘舵�佹枃鏈�
+ const getStatusText = status => {
+ const statusTextMap = {
+ planning: "瑙勫垝涓�",
+ inProgress: "杩涜涓�",
+ completed: "宸插畬鎴�",
+ paused: "宸叉殏鍋�",
+ };
+ return statusTextMap[status] || status;
+ };
+
+ // 鐩戝惉璺敱鍙傛暟鍙樺寲
+ watch(
+ () => route.params.projectId,
+ newProjectId => {
+ // console.log('璺敱鍙傛暟鍙樺寲:', projectId);
+ if (newProjectId) {
+ projectId.value = newProjectId;
+ getProjectDetail();
+ }
+ }
+ );
+
+ // 鐩戝惉褰撳墠鍊煎拰鐩爣鍊煎彉鍖栵紝閲嶆柊璁$畻瀹屾垚搴�
+ watch(
+ () => [goalForm.currentValue, goalForm.targetValue],
+ () => {
+ calculateCompletionRate();
+ }
+ );
+
+ // 鍒濆鍖�
+ onMounted(() => {
+ if (projectId.value) {
getProjectDetail();
}
- open.value = false;
- } catch (error) {
- console.error('鎻愪氦琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 鎻愪氦闃舵浠诲姟琛ㄥ崟
-const submitGoalForm = async () => {
- try {
- await goalFormRef.value.validate();
- calculateCompletionRate();
-
- const goalData = {
- ...goalForm,
- oaProjectId: projectId.value
- };
-
- if (goalForm.taskId) {
- await updateProjectTask(goalData);
- ElMessage.success('淇敼闃舵鐩爣鎴愬姛');
-
- } else {
- await addProjectTask(goalData);
- ElMessage.success('鏂板闃舵鐩爣鎴愬姛');
-
- }
- // 璋冪敤getProjectDetail鍒锋柊鎵�鏈夌浉鍏虫暟鎹�
- getProjectDetail();
- goalOpen.value = false;
-
- } catch (error) {
- console.error('鎻愪氦闃舵鐩爣琛ㄥ崟澶辫触:', error);
- }
-};
-
-// 閲嶇疆閲岀▼纰戣〃鍗�
-const resetForm = () => {
- form.phaseId = '';
- form.phaseName = '';
- form.startDate = '';
- form.endDate = '';
- form.status = 'planning';
- form.oaProjectId = projectId.value;
- if (formRef.value) {
- formRef.value.resetFields();
- }
-};
-
-// 鍙栨秷闃舵浠诲姟鎿嶄綔
-const cancelGoal = () => {
- goalOpen.value = false;
-};
-
-// 鍙栨秷鎿嶄綔
-const cancel = () => {
- open.value = false;
-};
-// 缂栬緫闃舵浠诲姟
-const handleEditPhaseGoal = async (goal) => {
- // 澶嶅埗鐩爣鏁版嵁鍒拌〃鍗�
- Object.assign(goalForm, goal);
-
- // 鑾峰彇椤圭洰闃舵鍒楄〃
- await getPhaseList();
-
- // 鎵撳紑缂栬緫寮圭獥
- goalTitle.value = '缂栬緫闃舵鐩爣';
- goalOpen.value = true;
-};
-// 鑾峰彇鐘舵�佹爣绛剧被鍨�
-const getStatusType = (status) => {
- const statusTypeMap = {
- planning: 'info',
- inProgress: 'primary',
- completed: 'success',
- paused: 'warning'
- };
- return statusTypeMap[status] || 'default';
-};
-
-// 鑾峰彇鐘舵�佹枃鏈�
-const getStatusText = (status) => {
- const statusTextMap = {
- planning: '瑙勫垝涓�',
- inProgress: '杩涜涓�',
- completed: '宸插畬鎴�',
- paused: '宸叉殏鍋�'
- };
- return statusTextMap[status] || status;
-};
-
-// 鐩戝惉璺敱鍙傛暟鍙樺寲
-watch(() => route.params.projectId, (newProjectId) => {
- // console.log('璺敱鍙傛暟鍙樺寲:', projectId);
- if (newProjectId) {
- projectId.value = newProjectId;
- getProjectDetail();
- }
-});
-
-// 鐩戝惉褰撳墠鍊煎拰鐩爣鍊煎彉鍖栵紝閲嶆柊璁$畻瀹屾垚搴�
-watch(() => [goalForm.currentValue, goalForm.targetValue], () => {
- calculateCompletionRate();
-});
-
-// 鍒濆鍖�
-onMounted(() => {
- if (projectId.value) {
- getProjectDetail();
- }
-});
+ });
</script>
<style scoped>
-.app-container {
- padding: 20px;
-}
+ .app-container {
+ padding: 20px;
+ }
-.card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
+ .card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
-.progress-item {
- text-align: center;
- padding: 20px;
- background-color: #f5f7fa;
- border-radius: 8px;
-}
+ .progress-item {
+ text-align: center;
+ padding: 20px;
+ background-color: #f5f7fa;
+ border-radius: 8px;
+ }
-.progress-title {
- font-size: 14px;
- color: #606266;
- margin-bottom: 10px;
-}
+ .progress-title {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 10px;
+ }
-.progress-number {
- font-size: 24px;
- font-weight: bold;
- color: #409eff;
-}
+ .progress-number {
+ font-size: 24px;
+ font-weight: bold;
+ color: #409eff;
+ }
-.mb20 {
- margin-bottom: 20px;
-}
+ .mb20 {
+ margin-bottom: 20px;
+ }
</style>
--
Gitblit v1.9.3