From 67aebf4dcaa249d99893a88685ea273cc46606f4 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期五, 06 十一月 2026 11:48:19 +0800
Subject: [PATCH] 流程优化

---
 src/views/projectManagement/Management/components/ProjectExecutionPanel.vue |   33 +++++++++++++++++++++++----------
 1 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/src/views/projectManagement/Management/components/ProjectExecutionPanel.vue b/src/views/projectManagement/Management/components/ProjectExecutionPanel.vue
index 9f42356..42001a8 100644
--- a/src/views/projectManagement/Management/components/ProjectExecutionPanel.vue
+++ b/src/views/projectManagement/Management/components/ProjectExecutionPanel.vue
@@ -51,7 +51,7 @@
             <span v-if="data.followWindow?.dueDate">鏈搴旇窡杩涙棩 {{ data.followWindow.dueDate }}锛屽彲濉啓 {{ data.followWindow.windowStart }} 鑷� {{ data.followWindow.windowEnd }}</span>
             <span v-else>棣栨璺熻繘鍙洿鎺ュ~鍐�</span>
           </div>
-          <el-button v-if="!readonly" v-hasPermi="['project:follow:add']" type="primary" @click="openFollow()">濉啓璺熻繘</el-button>
+          <el-button v-if="!readonly && canManageFollow" v-hasPermi="['project:follow:add']" type="primary" @click="openFollow()">濉啓璺熻繘</el-button>
         </div>
         <el-table :data="data.followUps" border>
           <el-table-column prop="followDate" label="璺熻繘鏃ユ湡" width="130" />
@@ -63,7 +63,7 @@
               <span v-else class="empty-file">鏃犻檮浠�</span>
             </template>
           </el-table-column>
-          <el-table-column v-if="!readonly" label="鎿嶄綔" width="140" align="center"><template #default="{ row }"><el-button v-hasPermi="['project:follow:add']" link type="primary" @click="openFollow(row)">缂栬緫</el-button><el-button v-hasPermi="['project:follow:remove']" link type="danger" @click="removeRecord('follow', row)">鍒犻櫎</el-button></template></el-table-column>
+          <el-table-column v-if="!readonly && canManageFollow" label="鎿嶄綔" width="140" align="center"><template #default="{ row }"><el-button v-hasPermi="['project:follow:add']" link type="primary" @click="openFollow(row)">缂栬緫</el-button><el-button v-hasPermi="['project:follow:remove']" link type="danger" @click="removeRecord('follow', row)">鍒犻櫎</el-button></template></el-table-column>
         </el-table>
       </el-tab-pane>
 
@@ -124,7 +124,7 @@
               </el-button>
             </template>
           </el-table-column>
-          <el-table-column v-if="!readonly" label="鎿嶄綔" width="90" align="center"><template #default="{ row }"><el-button v-hasPermi="['project:material:remove']" link type="danger" @click="removeRecord('material', row)">鍒犻櫎</el-button></template></el-table-column>
+          <el-table-column v-if="!readonly" label="鎿嶄綔" width="140" align="center"><template #default="{ row }"><el-button v-hasPermi="['project:material:add']" link type="primary" @click="openMaterial(row)">缂栬緫</el-button><el-button v-hasPermi="['project:material:remove']" link type="danger" @click="removeRecord('material', row)">鍒犻櫎</el-button></template></el-table-column>
         </el-table>
       </el-tab-pane>
 
@@ -160,7 +160,7 @@
         </div>
         <div class="module-grid">
           <el-form-item label="妯″潡鍚嶇О" required><el-input v-model="module.moduleName" :disabled="module.locked" /></el-form-item>
-          <el-form-item label="棰勮寮�濮�" required><el-date-picker v-model="module.plannedStartDate" :disabled="module.locked" type="date" value-format="YYYY-MM-DD" style="width:100%" /></el-form-item>
+          <el-form-item label="棰勮寮�濮�" required><el-date-picker v-model="module.plannedStartDate" :disabled="module.locked" :disabled-date="moduleDateDisabled" type="date" value-format="YYYY-MM-DD" style="width:100%" /></el-form-item>
           <el-form-item label="宸ヤ綔閲忓崰姣�" required><el-input-number v-model="module.projectWeight" :disabled="module.locked" :min="0.01" :max="draftWeightMax(moduleIndex)" :precision="2" /><span class="unit">%</span><div class="percent-hint">鍏朵粬妯″潡 {{ otherDraftWeight(moduleIndex) }}%锛屾湰妯″潡鏈�澶� {{ draftWeightMax(moduleIndex) }}%</div></el-form-item>
           <el-form-item label="妯″潡姒傝" required class="summary-item"><el-input v-model="module.summary" :disabled="module.locked" type="textarea" :rows="2" maxlength="1000" show-word-limit /></el-form-item>
           <el-form-item label="妯″潡鎵ц浜�" required class="members-item">
@@ -181,7 +181,7 @@
 
     <el-dialog v-model="followVisible" :title="followForm.id ? '缂栬緫椤圭洰璺熻繘' : '濉啓椤圭洰璺熻繘'" width="650px" destroy-on-close>
       <el-form ref="followFormRef" :model="followForm" :rules="followRules" label-width="90px">
-        <el-form-item label="璺熻繘鏃ユ湡" prop="followDate"><el-date-picker v-model="followForm.followDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item>
+        <el-form-item label="璺熻繘鏃ユ湡" prop="followDate"><el-date-picker v-model="followForm.followDate" :disabled="!!followForm.id" :disabled-date="date => dayjs(date).isAfter(dayjs(), 'day')" type="date" value-format="YYYY-MM-DD" style="width: 100%" /><div v-if="followForm.id" class="percent-hint">鍘嗗彶璺熻繘鏃ユ湡涓嶅彲淇敼锛岄伩鍏嶇牬鍧忓悗缁窡杩涘懆鏈熴��</div></el-form-item>
         <el-form-item label="璺熻繘璇︽儏" prop="detail"><el-input v-model="followForm.detail" type="textarea" :rows="5" maxlength="2000" show-word-limit /></el-form-item>
         <el-form-item label="闄勪欢"><AttachmentUploadFile v-model:file-list="followFiles" :limit="10" /></el-form-item>
       </el-form>
@@ -205,14 +205,14 @@
           </div>
         </el-form-item>
         <el-form-item label="鏈杩涘害" prop="incrementProgress"><el-input-number v-model="reportForm.incrementProgress" :min="0.01" :max="reportIncrementMax" :precision="2" /><span class="unit">%</span><span class="current-progress-hint">{{ reportProgressHint }}</span></el-form-item>
-        <el-form-item label="姹囨姤鏃堕棿" prop="reportDate"><el-date-picker v-model="reportForm.reportDate" :disabled="!!reportForm.id" type="date" value-format="YYYY-MM-DD" style="width: 100%" /><div v-if="reportForm.id" class="percent-hint">缂栬緫宸叉湁姹囨姤鏃朵笉鍏佽璋冩暣鏃堕棿锛屼互淇濊瘉鍘嗗彶杩涘害椤哄簭姝g‘銆�</div></el-form-item>
+        <el-form-item label="姹囨姤鏃堕棿" prop="reportDate"><el-date-picker v-model="reportForm.reportDate" :disabled="!!reportForm.id" :disabled-date="date => dayjs(date).isAfter(dayjs(), 'day')" type="date" value-format="YYYY-MM-DD" style="width: 100%" /><div v-if="reportForm.id" class="percent-hint">缂栬緫宸叉湁姹囨姤鏃朵笉鍏佽璋冩暣鏃堕棿锛屼互淇濊瘉鍘嗗彶杩涘害椤哄簭姝g‘銆�</div></el-form-item>
         <el-form-item label="澶囨敞"><el-input v-model="reportForm.remark" type="textarea" :rows="3" maxlength="2000" show-word-limit /></el-form-item>
         <el-form-item label="鏂囦欢"><AttachmentUploadFile v-model:file-list="reportFiles" :limit="10" /></el-form-item>
       </el-form>
       <template #footer><el-button @click="reportVisible = false">鍙栨秷</el-button><el-button type="primary" :loading="saving" @click="submitReport">{{ reportForm.id ? '淇濆瓨淇敼' : '鎻愪氦姹囨姤' }}</el-button></template>
     </el-dialog>
 
-    <el-dialog v-model="materialVisible" title="涓婁紶椤圭洰璧勬枡" width="650px" destroy-on-close>
+    <el-dialog v-model="materialVisible" :title="materialForm.id ? '缂栬緫椤圭洰璧勬枡' : '涓婁紶椤圭洰璧勬枡'" width="650px" destroy-on-close>
       <el-form ref="materialFormRef" :model="materialForm" :rules="materialRules" label-width="90px">
         <el-form-item label="璧勬枡鍚嶇О" prop="materialName"><el-input v-model="materialForm.materialName" /></el-form-item>
         <el-form-item label="璧勬枡绫诲瀷"><el-select v-model="materialForm.materialType" allow-create filterable clearable style="width: 100%"><el-option v-for="type in ['绔嬮」璧勬枡','寮�鍙戣祫鏂�','鐢虫姤璧勬枡','缁撴灉璧勬枡','楠屾敹璧勬枡','鍏朵粬']" :key="type" :label="type" :value="type" /></el-select></el-form-item>
@@ -261,6 +261,7 @@
 const reportShareRemaining = computed(() => Math.max(0, 100 - Number(reportShareTotal.value)).toFixed(2))
 const followCycleLabel = computed(() => ({ MONTH: '姣忔湀', QUARTER: '姣忓搴�', YEAR: '姣忓勾' }[props.projectInfo?.followCycle] || props.projectInfo?.followCycle || '姣忔湀'))
 const isStarted = computed(() => !!props.projectInfo?.currentPhase && props.projectInfo.currentPhase !== '鏈紑濮�')
+const canManageFollow = computed(() => String(props.projectInfo?.projectLeaderId ?? '') === String(userStore.id ?? ''))
 const memberReportModules = computed(() => data.modules.filter(module =>
   (module.members || []).some(member => String(member.userId) === String(userStore.id))
 ))
@@ -334,7 +335,7 @@
 const reportRules = { moduleId: [{ required: true, message: '璇烽�夋嫨椤圭洰妯″潡', trigger: 'change' }], reportDate: [{ required: true, message: '璇烽�夋嫨姹囨姤鏃堕棿', trigger: 'change' }] }
 const materialVisible = ref(false)
 const materialFormRef = ref()
-const materialForm = reactive({ materialName: '', materialType: '', remark: '' })
+const materialForm = reactive({ id: null, materialName: '', materialType: '', remark: '' })
 const materialFiles = ref([])
 const materialRules = { materialName: [{ required: true, message: '璇疯緭鍏ヨ祫鏂欏悕绉�', trigger: 'blur' }] }
 async function loadUsers() {
@@ -468,7 +469,13 @@
 }
 
 function canEditReport(row) {
-  return memberReportModules.value.some(module => String(module.id) === String(row.moduleId))
+  return (row.reporterIdList || []).some(userId => String(userId) === String(userStore.id))
+}
+
+function moduleDateDisabled(date) {
+  const start = props.projectInfo?.planStartTime
+  const end = props.projectInfo?.planEndTime
+  return (start && dayjs(date).isBefore(dayjs(start), 'day')) || (end && dayjs(date).isAfter(dayjs(end), 'day'))
 }
 
 function reporterShareLimit(index) {
@@ -494,7 +501,13 @@
   finally { saving.value = false }
 }
 
-function openMaterial() { Object.assign(materialForm, { materialName: '', materialType: '', remark: '' }); materialFiles.value = []; materialVisible.value = true }
+function openMaterial(row = null) {
+  Object.assign(materialForm, row
+    ? { id: row.id, materialName: row.materialName || '', materialType: row.materialType || '', remark: row.remark || '' }
+    : { id: null, materialName: '', materialType: '', remark: '' })
+  materialFiles.value = row ? [...(row.attachmentList || [])] : []
+  materialVisible.value = true
+}
 async function submitMaterial() {
   await materialFormRef.value?.validate()
   if (!materialFiles.value.length) return ElMessage.warning('璇蜂笂浼犺嚦灏戜竴涓枃浠�')

--
Gitblit v1.9.3