From db42d47f5692ef64e5436c5a6d29dcb537b44596 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期一, 26 一月 2026 16:36:13 +0800
Subject: [PATCH] 浪潮对接单点登录:mis调整
---
src/views/oaSystem/projectManagement/components/milestoneList.vue | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 289 insertions(+), 0 deletions(-)
diff --git a/src/views/oaSystem/projectManagement/components/milestoneList.vue b/src/views/oaSystem/projectManagement/components/milestoneList.vue
new file mode 100644
index 0000000..47b0027
--- /dev/null
+++ b/src/views/oaSystem/projectManagement/components/milestoneList.vue
@@ -0,0 +1,289 @@
+// ... existing code ...
+<template>
+ <div class="milestone-list-container">
+ <el-timeline>
+ <el-timeline-item
+ v-for="milestone in milestoneList"
+ :key="milestone.phaseId"
+ :timestamp="milestone.endDate"
+ >
+ <el-card>
+ <template #header>
+ <div class="card-header">
+ <span>{{ milestone.phaseName }}</span>
+ <div class="milestone-actions">
+ <el-button type="text" size="small" @click="handleEdit(milestone)">缂栬緫</el-button>
+ <el-button type="text" size="small" @click="handleDelete(milestone)" danger>鍒犻櫎</el-button>
+ </div>
+ </div>
+ </template>
+ <div class="milestone-content">
+ <p>{{ milestone.description }}</p>
+ <div class="milestone-status">
+ <el-tag :type="getStatusType(milestone.status)">{{ getStatusText(milestone.status) }}</el-tag>
+ </div>
+ </div>
+ </el-card>
+ </el-timeline-item>
+ </el-timeline>
+
+ <!-- 鏃犻噷绋嬬鏃剁殑鎻愮ず -->
+ <div v-if="milestoneList.length === 0" class="empty-tip">
+ <el-empty description="鏆傛棤閲岀▼纰戞暟鎹�" />
+ </div>
+
+ <!-- 缂栬緫閲岀▼纰戝璇濇 -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="'缂栬緫閲岀▼纰�: ' + (form.phaseName || '')"
+ width="600px"
+ :close-on-click-modal="false"
+ >
+ <el-form
+ ref="formRef"
+ :model="form"
+ :rules="rules"
+ label-width="100px"
+ >
+ <el-form-item label="閲岀▼纰戝悕绉�" prop="phaseName">
+ <el-input v-model="form.phaseName" placeholder="璇疯緭鍏ラ噷绋嬬鍚嶇О" />
+ </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-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-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��">
+ <el-option label="鏈紑濮�" value="notStarted" />
+ <el-option label="宸插畬鎴�" value="completed" />
+ <el-option label="宸插欢杩�" value="delayed" />
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitEditForm">纭畾</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, watch, reactive } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import { getProject, listProjectPhase, updateProjectPhase,delProjectPhase } from '@/api/oaSystem/projectManagement';
+
+const props = defineProps({
+ projectId: {
+ type: String,
+ required: true
+ }
+});
+
+const emit = defineEmits(['refresh']);
+
+const milestoneList = ref([]);
+const dialogVisible = ref(false);
+const formRef = ref(null);
+const form = reactive({
+ phaseId: '',
+ phaseName: '',
+ startDate: '',
+ endDate: '',
+ status: 'notStarted',
+ projectId: props.projectId
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = {
+ phaseName: [
+ { required: true, message: '璇疯緭鍏ラ噷绋嬬鍚嶇О', trigger: 'blur' },
+ { min: 2, max: 50, message: '闀垮害鍦� 2 鍒� 50 涓瓧绗�', trigger: 'blur' }
+ ],
+ status: [
+ { required: true, message: '璇烽�夋嫨鐘舵��', trigger: 'change' }
+ ]
+};
+
+// 鑾峰彇閲岀▼纰戝垪琛�
+const getMilestoneList = async () => {
+ try {
+ listProjectPhase(props.projectId).then(res => {
+ milestoneList.value = res.data.rows || res.data;
+ // 鎸夌洰鏍囨棩鏈熸帓搴�
+ // milestoneList.value.sort((a, b) => new Date(a.endDate) - new Date(b.endDate));
+ })
+ } catch (error) {
+ ElMessage.error('鑾峰彇閲岀▼纰戝垪琛ㄥけ璐�');
+ console.error('鑾峰彇閲岀▼纰戝垪琛ㄥけ璐�:', error);
+ }
+};
+
+// 缂栬緫閲岀▼纰�
+const handleEdit = (milestone) => {
+ // 澶嶅埗閲岀▼纰戞暟鎹埌琛ㄥ崟
+ Object.assign(form, {
+ phaseId: milestone.phaseId,
+ phaseName: milestone.phaseName,
+ description: milestone.description,
+ endDate: milestone.endDate,
+ status: milestone.status,
+ projectId: props.projectId
+ });
+ dialogVisible.value = true;
+};
+
+// 鎻愪氦缂栬緫琛ㄥ崟
+const submitEditForm = async () => {
+ try {
+ await formRef.value.validate();
+
+ // 鍙戦�佹洿鏂拌姹�
+ const res = await updateProjectPhase(form);
+
+ if (res.code === 200) {
+ ElMessage.success('閲岀▼纰戠紪杈戞垚鍔�');
+ dialogVisible.value = false;
+ getMilestoneList(); // 鍒锋柊鍒楄〃
+ emit('refresh'); // 閫氱煡鐖剁粍浠跺埛鏂�
+ } else {
+ ElMessage.error(res.msg || '閲岀▼纰戠紪杈戝け璐�');
+ }
+ } catch (error) {
+ if (error.name === 'ValidationError') {
+ // 琛ㄥ崟楠岃瘉澶辫触锛孍lement Plus浼氳嚜鍔ㄦ彁绀�
+ return;
+ }
+ ElMessage.error('閲岀▼纰戠紪杈戝け璐�');
+ console.error('缂栬緫閲岀▼纰戝け璐�:', error);
+ }
+};
+
+// 鍒犻櫎閲岀▼纰�
+const handleDelete = (milestone) => {
+ ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ら噷绋嬬 "${milestone.phaseName}" 鍚楋紵鍒犻櫎鍚庡皢鏃犳硶鎭㈠銆俙,
+ '鍒犻櫎纭',
+ {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }
+ )
+ .then(async () => {
+ try {
+ // 璋冪敤鍒犻櫎API
+ const res = await delProjectPhase(milestone.phaseId);
+
+ if (res.code === 200) {
+ ElMessage.success('閲岀▼纰戝垹闄ゆ垚鍔�');
+ getMilestoneList(); // 鍒锋柊鍒楄〃
+ emit('refresh'); // 閫氱煡鐖剁粍浠跺埛鏂�
+ } else {
+ ElMessage.error(res.msg || '閲岀▼纰戝垹闄ゅけ璐�');
+ }
+ } catch (error) {
+ ElMessage.error('閲岀▼纰戝垹闄ゅけ璐�');
+ console.error('鍒犻櫎閲岀▼纰戝け璐�:', error);
+ }
+ })
+ .catch(() => {
+ // 鐢ㄦ埛鍙栨秷鍒犻櫎
+ ElMessage.info('宸插彇娑堝垹闄�');
+ });
+};
+
+// 鑾峰彇鐘舵�佹爣绛剧被鍨�
+const getStatusType = (status) => {
+ const statusTypeMap = {
+ notStarted: 'info',
+ completed: 'success',
+ delayed: 'danger'
+ };
+ return statusTypeMap[status] || 'default';
+};
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+ const statusTextMap = {
+ notStarted: '鏈紑濮�',
+ completed: '宸插畬鎴�',
+ delayed: '宸插欢杩�'
+ };
+ return statusTextMap[status] || status;
+};
+
+// 鐩戝惉椤圭洰ID鍙樺寲
+watch(() => props.projectId, () => {
+ if (props.projectId) {
+ getMilestoneList();
+ }
+});
+
+// 鍒濆鍖�
+onMounted(() => {
+ if (props.projectId) {
+ getMilestoneList();
+ }
+});
+</script>
+
+<style scoped>
+.milestone-list-container {
+ padding: 10px 0;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.milestone-actions {
+ display: flex;
+ gap: 10px;
+}
+
+.milestone-content {
+ padding: 10px 0;
+}
+
+.milestone-status {
+ margin-top: 10px;
+}
+
+.empty-tip {
+ margin-top: 40px;
+ text-align: center;
+}
+
+.dialog-footer {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+}
+</style>
--
Gitblit v1.9.3