From b3f4499793fa7b21f6c5d1e099d6ed170ecbe47a Mon Sep 17 00:00:00 2001
From: 董国庆 <364620639@qq.com>
Date: 星期四, 15 五月 2025 16:38:45 +0800
Subject: [PATCH] 实验方案管理

---
 laboratory/src/components/DynamicComponent/addTableData.vue                        |   45 ++
 laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue |   34 ++
 laboratory/src/views/dataManagement/schemeManagement/list.vue                      |   29 +
 laboratory/src/views/dataManagement/schemeManagement/addPlan.vue                   |  609 +++++++++++++++++----------------------
 laboratory/src/components/DynamicComponent/index.vue                               |  112 ++++++
 laboratory/src/components/DynamicComponent/service.js                              |    8 
 laboratory/src/components/SelectMember/service.js                                  |    8 
 laboratory/src/components/SelectMember/index.vue                                   |    5 
 8 files changed, 482 insertions(+), 368 deletions(-)

diff --git a/laboratory/src/components/DynamicComponent/addTableData.vue b/laboratory/src/components/DynamicComponent/addTableData.vue
index 95267e6..22fcbb7 100644
--- a/laboratory/src/components/DynamicComponent/addTableData.vue
+++ b/laboratory/src/components/DynamicComponent/addTableData.vue
@@ -144,6 +144,8 @@
 </template>
   
 <script>
+import { listByRole } from './service';
+
 export default {
   name: "AddDialog",
   props: {
@@ -173,13 +175,7 @@
       photoList: [],
       spectrumList: [],
       defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
-      userOptions: [
-        { value: '1', label: '用户1' },
-        { value: '2', label: '用户2' },
-        { value: '3', label: '用户3' },
-        { value: '4', label: '用户4' },
-        { value: '5', label: '用户5' }
-      ]
+      userOptions: []
     };
   },
   computed: {
@@ -228,6 +224,20 @@
     },
   },
   methods: {
+    getUserOptions() {
+      listByRole().then(res => {
+        if (res) {
+          this.userOptions = res.map(user => ({
+            value: user.userId,
+            label: user.nickName || user.userName
+          }));
+        } else {
+          this.$message.error('获取用户列表失败');
+        }
+      }).catch(err => {
+        console.error('获取用户列表失败', err);
+      });
+    },
     checkEditPermission(header) {
       if (!header.role || !Array.isArray(header.role)) {
         return true;
@@ -348,6 +358,21 @@
             photos: this.photoList,
             spectrums: this.spectrumList,
           };
+          
+          // 为用户类型字段添加用户完整信息
+          if (this.headerList && this.headerList.length) {
+            this.headerList.forEach(header => {
+              if (header.type === 'user' && Array.isArray(submitData[header.name])) {
+                // 为每个用户类型字段添加userInfo属性,包含用户完整信息
+                submitData[`${header.name}_userInfo`] = submitData[header.name].map(userId => {
+                  const userInfo = this.userOptions.find(user => user.value === userId);
+                  return userInfo ? userInfo : { value: userId, label: userId };
+                });
+              }
+            });
+          }
+          
+          console.log(submitData,'修改的数据')
           this.$emit("success", submitData);
           this.handleClose();
         } else {
@@ -370,7 +395,9 @@
       // 同时更新form中对应的字段值以通过表单验证
       const imageHeader = this.headerList.find(h => h.type === 'image');
       if (imageHeader && imageHeader.name) {
-        this.$set(this.form, imageHeader.name, '默认图片');
+        // 保存图片URL,这样在表格中可以直接使用
+        this.$set(this.form, imageHeader.name, this.defaultImageUrl);
+        console.log('设置图片字段:', imageHeader.name, this.defaultImageUrl);
       }
       
       this.$refs.form.validateField("spectrums");
@@ -381,6 +408,8 @@
 
   },
   mounted() {
+    // 获取用户列表数据
+    this.getUserOptions();
   },
 };
 </script>
diff --git a/laboratory/src/components/DynamicComponent/index.vue b/laboratory/src/components/DynamicComponent/index.vue
index cd198b6..8faa19a 100644
--- a/laboratory/src/components/DynamicComponent/index.vue
+++ b/laboratory/src/components/DynamicComponent/index.vue
@@ -25,9 +25,27 @@
             <el-button size="mini"  @click="showTableHeaderDialog(idx)">添加表头</el-button>
             <el-button size="mini" type="primary" @click="showAddRowDialog(idx, item.data.headers)">添加数据</el-button>
           </div>
-          <Table :data="item.data.rows" :total="null" :height="null" class="groupTable">
+          <Table :data="item.data.rows" :total="null" :height="null" class="groupTable" :key="item.id + '_' + JSON.stringify(item.data.rows).length">
             <el-table-column v-for="(header, hidx) in item.data.headers" :key="hidx" :label="header.name"
-              :prop="header.name" />
+              :prop="header.name">
+              <template slot-scope="scope">
+                <!-- 用户类型显示 -->
+                <template v-if="header.type === 'user'">
+                  {{ getUserDisplayText(header.name, scope.row) }}
+                </template>
+                <!-- 图片类型显示 -->
+                <template v-else-if="header.type === 'image'">
+                  <img v-if="scope.row[header.name]" 
+                       :src="scope.row[header.name]" 
+                       alt="头像" 
+                       class="table-image" />
+                </template>
+                <!-- 其他类型 -->
+                <template v-else>
+                  {{ scope.row[header.name] }}
+                </template>
+              </template>
+            </el-table-column>
             <el-table-column label="更新时间" prop="updateTime" min-width="180"></el-table-column>
             <el-table-column  label="操作" min-width="200" v-if="dialogCanEdit">
               <template slot-scope="scope">
@@ -136,6 +154,7 @@
         form: {},
       },
       headerList: [],
+      defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
     };
   },
   watch: {
@@ -176,6 +195,49 @@
     }
   },
   methods: {
+    getUserDisplayText(fieldName, rowData) {
+      // 检查是否有对应的userInfo数据
+      const userInfoKey = `${fieldName}_userInfo`;
+      
+      // 如果没有rowData或fieldName,直接返回空字符串
+      if (!rowData || !fieldName) {
+        return '';
+      }
+      
+      // 情况1: 有_userInfo数据
+      if (rowData[userInfoKey] && Array.isArray(rowData[userInfoKey])) {
+        return rowData[userInfoKey].map(user => user.label || '').join(', ');
+      }
+      
+      // 情况2: 只有用户ID数组
+      if (Array.isArray(rowData[fieldName])) {
+        // 使用participants查找用户信息
+        return rowData[fieldName].map(userId => {
+          const user = this.participants.find(p => p.userId === userId);
+          return user ? (user.nickName || user.userName || userId) : userId;
+        }).join(', ');
+      }
+      
+      // 情况3: 已经是字符串(可能是之前格式化过的)
+      if (typeof rowData[fieldName] === 'string') {
+        return rowData[fieldName];
+      }
+      
+      // 默认返回空字符串
+      return '';
+    },
+    formatUserNames(userArray) {
+      if (!userArray || !Array.isArray(userArray) || userArray.length === 0) {
+        return '';
+      }
+      
+      // 查找参与者列表中的用户,获取昵称并用逗号拼接
+      const userNames = userArray.map(userId => {
+        const user = this.participants.find(p => p.userId === userId);
+        return user ? user.nickName : userId;
+      });
+      return userNames.join(', ');
+    },
     addComponent(type) {
       if (!this.editable) return;
 
@@ -232,23 +294,44 @@
       this.$emit('submit', data);
     },
     confirmAddRow(formData) {
-      if (!this.editable) return;
+      // if (!this.editable) return;
 
       const { idx, rowIndex, isEdit } = this.rowDialog;
+      
+      // 处理formData中的数据,保证用户信息的完整性
+      const processedData = { ...formData };
+      
+      // 调试输出
+      console.log('添加/编辑行数据:', processedData,'isEdit',isEdit);
+      
       if (isEdit) {
-        this.components[idx].data.rows[rowIndex] = {
-          ...formData,
-          updateTime: new Date().toLocaleString()
-        };
+        // Vue无法检测到对象或数组深层属性的变化,使用Vue.set来确保响应式
+        this.$set(
+          this.components[idx].data.rows, 
+          rowIndex, 
+          {
+            ...processedData,
+            updateTime: new Date().toLocaleString()
+          }
+        );
       } else {
+        // 使用数组方法push会被Vue检测到
         this.components[idx].data.rows.push({
-          ...formData,
+          ...processedData,
           updateTime: new Date().toLocaleString()
         });
       }
+      console.log('this.components',this.components);
+      
+      // 手动触发组件更新
+      this.$forceUpdate();
+      // 延迟发送事件,确保数据已更新
+      this.$nextTick(() => {
+        this.emitUpdate();
+      });
+      
       this.rowDialog.visible = false;
       this.rowDialog.form = {};
-      this.emitUpdate();
     },
     removeComponent(idx) {
       if (!this.editable) return;
@@ -387,7 +470,9 @@
       return true;
     },
     emitUpdate() {
-      this.$emit('update:dataSource', this.components);
+      // 先创建新对象,这有助于触发更新
+      const updatedComponents = JSON.parse(JSON.stringify(this.components));
+      this.$emit('update:dataSource', updatedComponents);
     },
   },
 };
@@ -519,4 +604,11 @@
   object-fit: cover;
   border-radius: 8px;
 }
+
+.table-image {
+  width: 50px;
+  height: 50px;
+  object-fit: cover;
+  border-radius: 4px;
+}
 </style>
diff --git a/laboratory/src/components/DynamicComponent/service.js b/laboratory/src/components/DynamicComponent/service.js
new file mode 100644
index 0000000..15f0014
--- /dev/null
+++ b/laboratory/src/components/DynamicComponent/service.js
@@ -0,0 +1,8 @@
+import axios from '@/utils/request';
+
+
+// 获取项目列表 获取用户列表-不分页-根据角色筛选
+export const listByRole = (data) => {
+    return axios.get('/system/user/listByRole', { params:data })
+}
+
diff --git a/laboratory/src/components/SelectMember/index.vue b/laboratory/src/components/SelectMember/index.vue
index 96ca265..621e526 100644
--- a/laboratory/src/components/SelectMember/index.vue
+++ b/laboratory/src/components/SelectMember/index.vue
@@ -59,7 +59,7 @@
 </template>
 
 <script>
-import { getRoleList, getUserList } from './service'
+import { getRoleList, getUserList, listByRole } from './service'
 export default {
     props: {
         projectId: {
@@ -118,7 +118,8 @@
             if (this.projectId) {
                 params.projectId = this.projectId;
                 // TODO: 这里需要替换为新的接口调用
-                // const res = await getProjectUserList(params);
+                const res = await listByRole(params);
+                this.tableData = res.records;
             } else {
                 const res = await getUserList(params);
                 this.tableData = res.records;
diff --git a/laboratory/src/components/SelectMember/service.js b/laboratory/src/components/SelectMember/service.js
index cf0bc1e..c733e22 100644
--- a/laboratory/src/components/SelectMember/service.js
+++ b/laboratory/src/components/SelectMember/service.js
@@ -13,4 +13,10 @@
 // 角色列表不分页
 export const getRoleList = (data) => {
     return axios.post('/system/role/listNotPage', { ...data })
-}
\ No newline at end of file
+}
+
+// 获取项目列表 获取用户列表-不分页-根据角色筛选
+export const listByRole = (data) => {
+    return axios.get('/system/user/listByRole', { params:data })
+}
+
diff --git a/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue b/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
index 969c483..ef3538f 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
@@ -70,12 +70,12 @@
           </div>
           <div class="content-box">
             <div class="content-box-left">
-              <div>项目课题方案名称:{{ groupTableData[0].projectName }}</div>
-              <div>实验编号:{{ groupTableData[0].experimentCode }}</div>
+              <div>项目课题方案名称:{{ groupTableData && groupTableData.length > 0 ? groupTableData[0].projectName : '' }}</div>
+              <div>实验编号:{{ groupTableData && groupTableData.length > 0 ? groupTableData[0].experimentCode : '' }}</div>
             </div>
             <div class="content-box-right">
-              <div>项目课题方案编号: {{ groupTableData[0].projectCode }}</div>
-              <div>实验名称: {{ groupTableData[0].experimentName }}</div>
+              <div>项目课题方案编号: {{ groupTableData && groupTableData.length > 0 ? groupTableData[0].projectCode : '' }}</div>
+              <div>实验名称: {{ groupTableData && groupTableData.length > 0 ? groupTableData[0].experimentName : '' }}</div>
             </div>
           </div>
         </div>
@@ -250,6 +250,19 @@
       editId: null, // 编辑的ID
       viewMaterialData: [], // 查看模式的材料数据
       viewEquipmentData: [], // 查看模式的设备数据
+      // 状态映射表
+      statusTypeMap: {
+        "-1": "info",
+        "1": "warning",
+        "2": "success",
+        "3": "info"
+      },
+      statusTextMap: {
+        "-1": "草稿箱",
+        "1": "待确认",
+        "2": "已确认",
+        "3": "已封存"
+      }
     };
   },
   async created() {
@@ -261,182 +274,39 @@
     }
   },
   methods: {
+    // ===== 人员相关方法 =====
     addMember() {
       this.$refs.selectMember.open(this.participantsData, []);
     },
-    handleMaterialSubmit(data) {
-      // 处理实验材料数据
-      this.form.experimentMaterial = data;
+    handleMemberSubmit(selectedMembers) {
+      this.selectedParticipants = selectedMembers;
+      this.$refs.selectMember.close();
     },
-    handleEquipmentSubmit(data) {
-      // 处理实验设备数据
-      this.form.experimentDevice = data;
+    handleEditMember() {
+      this.$refs.selectMember.open(this.participantsData, this.selectedParticipants);
     },
-    handleSave() {
-      // 先获取所有动态组件的数据
-      this.$refs.materialComponent.submit();
-      this.$refs.equipmentComponent.submit();
-
-      // 获取所有步骤内容 - 添加错误检查
-      this.stepList.forEach((step, index) => {
-        const stepContentRef = this.$refs['stepContent' + index];
-        console.log('stepContentRef', stepContentRef)
-        const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef;
-        if (editor && typeof editor.submit === 'function') {
-          editor.submit();
-        }
-      });
-      console.log('材料数据', this.form.experimentMaterial)
-      console.log('设备数据', this.form.experimentDevice)
-      console.log('步骤数据', this.form.stepList)
-
-      // 然后进行表单校验
-      this.$refs.form.validate((valid) => {
-        if (valid && this.validateContent()) {
-          // 构建提交数据
-          const formData = {
-            ...this.form,
-            // 实验日期,使用 moment 格式化为指定格式
-            experimentDate: moment(this.form.experimentDate).format('YYYY-MM-DD HH:mm:ss'),
-            // 实验调度ID,从选中的调度数据中获取
-            dispatchId: this.groupTableData[0]?.id,
-            // 实验设备,转换为JSON字符串
-            experimentDevice: this.form.experimentDevice,
-            // 实验材料,转换为JSON字符串
-            experimentMaterial: this.form.experimentMaterial,
-            // 实验目的,从富文本编辑器获取内容
-            experimentObjective: this.$refs.purposeEditor.getContent(),
-            // 工艺参数及路线,从富文本编辑器获取内容
-            experimentParamRoute: this.$refs.processEditor.getContent(),
-            // 实验方案人员,包含用户ID、昵称和角色类型
-            experimentSchemePersons: this.selectedParticipants.map(person => ({
-              userId: person.userId,    // 用户ID
-              nickName: person.nickName, // 用户昵称
-              roleType: person.roleType,  // 角色类型
-              commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
-            })),
-            // 实验步骤记录,转换为JSON字符串,包含步骤名称和内容
-            experimentStepRecord: this.stepList.map(step => ({
-              stepName: step.stepName,  // 步骤名称
-              content: step.content     // 步骤内容
-            })),
-            // 状态:1=已发送
-            status: 1,
-            // 提交时间,使用 moment 格式化为指定格式
-            commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
-          };
-          console.log('formData 提交数据', formData)
-
-          // 调用添加接口
-          add(formData).then(res => {
-            if (res.code === 200) {
-              this.$message.success('保存成功');
-              this.$router.go(-1)
-              // 可以在这里添加跳转逻辑
-            } else {
-              this.$message.error(res.msg || '保存失败');
-            }
-          }).catch(err => {
-            this.$message.error('保存失败');
-            console.error('保存失败:', err);
-          });
-        } else {
-          // 获取第一个错误字段
-          const firstError = this.$refs.form.fields.find(field => field.validateState === 'error');
-          if (firstError) {
-            // 滚动到错误字段
-            this.$nextTick(() => {
-              firstError.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
-            });
-          }
-        }
-      });
-    },
-    handleSaveDraft() {
-      // 先获取所有动态组件的数据
-      this.$refs.materialComponent.submit();
-      this.$refs.equipmentComponent.submit();
-
-      // 获取所有步骤内容 - 添加错误检查
-      this.stepList.forEach((step, index) => {
-        const stepContentRef = this.$refs['stepContent' + index];
-        if (stepContentRef && typeof stepContentRef.submit === 'function') {
-          stepContentRef.submit();
-        }
-      });
-
-      // 然后进行表单校验
-      this.$refs.form.validate((valid) => {
-        if (valid && this.validateContent()) {
-          // 构建草稿数据
-          const formData = {
-            ...this.form,
-            // 实验日期,使用 moment 格式化为指定格式
-            experimentDate: moment(this.form.experimentDate).format('YYYY-MM-DD HH:mm:ss'),
-            // 实验调度ID,从选中的调度数据中获取
-            dispatchId: this.groupTableData[0]?.id,
-            // 实验设备,转换为JSON字符串
-            experimentDevice: JSON.stringify(this.form.experimentDevice),
-            // 实验材料,转换为JSON字符串
-            experimentMaterial: JSON.stringify(this.form.experimentMaterial),
-            // 实验目的,从富文本编辑器获取内容
-            experimentObjective: this.$refs.purposeEditor.getContent(),
-            // 工艺参数及路线,从富文本编辑器获取内容
-            experimentParamRoute: this.$refs.processEditor.getContent(),
-            // 实验方案人员,包含用户ID、昵称和角色类型
-            experimentSchemePersons: this.selectedParticipants.map(person => ({
-              userId: person.userId,    // 用户ID
-              nickName: person.nickName, // 用户昵称
-              roleType: person.roleType  // 角色类型
-            })),
-            // 实验步骤记录,转换为JSON字符串,包含步骤名称和内容
-            experimentStepRecord: JSON.stringify(this.stepList.map(step => ({
-              stepName: step.stepName,  // 步骤名称
-              content: step.content     // 步骤内容
-            }))),
-            // 状态:-1=草稿箱
-            status: -1,
-            // 提交时间,使用 moment 格式化为指定格式
-            commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
-          };
-
-          // 调用添加接口
-          add(formData).then(res => {
-            if (res.code === 200) {
-              this.$message.success('草稿保存成功');
-              // 可以在这里添加跳转逻辑
-            } else {
-              this.$message.error(res.msg || '草稿保存失败');
-            }
-          }).catch(err => {
-            this.$message.error('草稿保存失败');
-            console.error('草稿保存失败:', err);
-          });
-        } else {
-          // 获取第一个错误字段
-          const firstError = this.$refs.form.fields.find(field => field.validateState === 'error');
-          if (firstError) {
-            // 滚动到错误字段
-            this.$nextTick(() => {
-              firstError.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
-            });
-          }
-        }
-      });
-    },
+    
+    // ===== 步骤相关方法 =====
     handleAddStep() {
       this.$refs.addStepDialog.open();
     },
     handleStepSubmit(stepData) {
       if (this.editingStepIndex > -1) {
+        // 编辑现有步骤
         this.stepList[this.editingStepIndex].stepName = stepData.stepName;
         this.editingStepIndex = -1;
       } else {
+        // 添加新步骤
         this.stepList.push({
           stepName: stepData.stepName,
           content: null,
         });
       }
+    },
+    handleEditStep(index) {
+      this.editingStepIndex = index;
+      this.$refs.addStepDialog.open(true);
+      this.$refs.addStepDialog.setStepName(this.stepList[index].stepName);
     },
     handleDeleteStep(index) {
       this.$confirm("确认删除该步骤吗?删除后步骤内容将无法恢复", "警告", {
@@ -451,14 +321,108 @@
         })
         .catch(() => { });
     },
-    handleEditStep(index) {
-      this.editingStepIndex = index;
-      this.$refs.addStepDialog.open(true);
-      this.$refs.addStepDialog.setStepName(this.stepList[index].stepName);
-    },
     handleStepContentSubmit(index, content) {
-      console.log('步骤内容', content)
       this.stepList[index].content = content;
+    },
+    
+    // ===== 材料设备相关方法 =====
+    handleMaterialSubmit(data) {
+      this.form.experimentMaterial = data;
+    },
+    handleEquipmentSubmit(data) {
+      this.form.experimentDevice = data;
+    },
+    
+    // ===== 保存提交相关方法 =====
+    handleSave() {
+      this.submitData(1);
+    },
+    handleSaveDraft() {
+      this.submitData(-1);
+    },
+    submitData(status) {
+      // 先获取所有动态组件的数据
+      this.$refs.materialComponent.submit();
+      this.$refs.equipmentComponent.submit();
+
+      // 获取所有步骤内容
+      const stepContentRefs = Object.keys(this.$refs)
+        .filter(key => key.startsWith('stepContent'))
+        .map(key => this.$refs[key]);
+      
+      stepContentRefs.forEach((ref) => {
+        const editor = Array.isArray(ref) ? ref[0] : ref;
+        if (editor && typeof editor.submit === 'function') {
+          editor.submit();
+        }
+      });
+
+      // 进行表单校验
+      this.$refs.form.validate((valid) => {
+        if (valid && this.validateContent()) {
+          // 获取富文本编辑器内容
+          const experimentObjective = this.$refs.purposeEditor.getContent();
+          const experimentParamRoute = this.$refs.processEditor.getContent();
+          
+          // 构建实验步骤记录数据
+          const experimentStepRecord = this.stepList.map(step => ({
+            stepName: step.stepName,
+            content: step.content
+          }));
+          
+          // 构建提交数据
+          const formData = {
+            ...this.form,
+            experimentDate: moment(this.form.experimentDate).format('YYYY-MM-DD HH:mm:ss'),
+            dispatchId: this.groupTableData && this.groupTableData.length > 0 ? this.groupTableData[0]?.id : '',
+            experimentObjective,
+            experimentParamRoute,
+            experimentSchemePersons: this.selectedParticipants.map(person => ({
+              userId: person.userId,
+              nickName: person.nickName,
+              roleType: person.roleType,
+              commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
+            })),
+            status,
+            commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
+          };
+          
+          // 统一转换JSON字符串
+          formData.experimentStepRecord = JSON.stringify(experimentStepRecord);
+          formData.experimentDevice = JSON.stringify(this.form.experimentDevice);
+          formData.experimentMaterial = JSON.stringify(this.form.experimentMaterial);
+          
+          // 编辑模式下添加id参数
+          if (this.isEdit && this.editId) {
+            formData.id = this.editId;
+          }
+          
+          // 根据是否为编辑模式调用不同接口
+          const apiCall = this.isEdit ? update(formData) : add(formData);
+          
+          apiCall.then(res => {
+            if (res.code === 200) {
+              this.$message.success(status === 1 ? '保存成功' : '草稿保存成功');
+              if (status === 1) {
+                this.$router.go(-1);
+              }
+            } else {
+              this.$message.error(res.msg || (status === 1 ? '保存失败' : '草稿保存失败'));
+            }
+          }).catch(err => {
+            this.$message.error(status === 1 ? '保存失败' : '草稿保存失败');
+            console.error(status === 1 ? '保存失败:' : '草稿保存失败:', err);
+          });
+        } else {
+          // 获取第一个错误字段并滚动到该位置
+          const firstError = this.$refs.form.fields.find(field => field.validateState === 'error');
+          if (firstError) {
+            this.$nextTick(() => {
+              firstError.$el.scrollIntoView({ behavior: 'smooth', block: 'center' });
+            });
+          }
+        }
+      });
     },
     getAllEditorContent() {
       return {
@@ -467,37 +431,37 @@
       };
     },
     validateContent() {
-      // // 校验实验调度
-      // if (!this.groupTableData || this.groupTableData.length === 0) {
-      //   this.$message.error("请选择实验调度");
-      //   return false;
-      // }
+      // 校验实验调度
+      if (!this.groupTableData || this.groupTableData.length === 0) {
+        this.$message.error("请选择实验调度");
+        return false;
+      }
 
-      // // 校验实验日期
-      // if (!this.form.experimentDate) {
-      //   this.$message.error("请填写实验日期");
-      //   return false;
-      // }
+      // 校验实验日期
+      if (!this.form.experimentDate) {
+        this.$message.error("请填写实验日期");
+        return false;
+      }
 
-      // // 校验参与人员
-      // if (!this.selectedParticipants || this.selectedParticipants.length === 0) {
-      //   this.$message.error("请选择参与人员");
-      //   return false;
-      // }
+      // 校验参与人员
+      if (!this.selectedParticipants || this.selectedParticipants.length === 0) {
+        this.$message.error("请选择参与人员");
+        return false;
+      }
 
-      // // 校验实验目的
-      // const purpose = this.$refs.purposeEditor.getContent();
-      // if (!purpose || purpose === '<p></p>' || purpose.trim() === '<p></p>') {
-      //   this.$message.error("请填写实验目的");
-      //   return false;
-      // }
+      // 校验实验目的
+      const purpose = this.$refs.purposeEditor.getContent();
+      if (!purpose || purpose === '<p></p>' || purpose.trim() === '<p></p>') {
+        this.$message.error("请填写实验目的");
+        return false;
+      }
 
-      // // 校验工艺参数及路线
-      // const process = this.$refs.processEditor.getContent();
-      // if (!process || process === '<p></p>' || process.trim() === '<p></p>') {
-      //   this.$message.error("请填写工艺参数及路线");
-      //   return false;
-      // }
+      // 校验工艺参数及路线
+      const process = this.$refs.processEditor.getContent();
+      if (!process || process === '<p></p>' || process.trim() === '<p></p>') {
+        this.$message.error("请填写工艺参数及路线");
+        return false;
+      }
 
       // 校验实验材料
       if (!this.form.experimentMaterial) {
@@ -518,11 +482,10 @@
       }
 
       // 校验每个步骤是否都有内容
-      for (let i = 0; i < this.stepList.length; i++) {
-        if (!this.stepList[i].content) {
-          this.$message.error(`请完善第${i + 1}个步骤的内容`);
-          return false;
-        }
+      const invalidStep = this.stepList.findIndex(step => !step.content);
+      if (invalidStep !== -1) {
+        this.$message.error(`请完善第${invalidStep + 1}个步骤的内容`);
+        return false;
       }
 
       return true;
@@ -531,26 +494,14 @@
       this.$router.push("/dataManagement/scheme-management/stop-experiment");
     },
     getStatusType(status) {
-      const statusMap = {
-        "-1": "info",
-        "1": "warning",
-        "2": "success",
-        "3": "info"
-      };
-      return statusMap[status] || "info";
+      return this.statusTypeMap[status] || "info";
     },
     getStatusText(status) {
-      const statusMap = {
-        "-1": "草稿箱",
-        "1": "待确认",
-        "2": "已确认",
-        "3": "已封存"
-      };
-      return statusMap[status] || "未知";
+      return this.statusTextMap[status] || "未知";
     },
     handleSchedulingSubmit(data) {
-      this.groupTableData = data;
-      if (data && data.length > 0) {
+      this.groupTableData = data || [];
+      if (data && data.length > 0 && data[0].id) {
         getGroupByDispatchId({ dispatchId: data[0].id }).then(res => {
           if (res) {
             this.groupData = res || [];
@@ -577,141 +528,115 @@
     handleSchedulingClose() {
       this.showScheduling = false;
     },
-    handleMemberSubmit(selectedMembers) {
-      this.selectedParticipants = selectedMembers;
-      this.$refs.selectMember.close();
-    },
-    handleEditMember() {
-      this.$refs.selectMember.open(this.participantsData, this.selectedParticipants);
-    },
-    // 加载编辑数据
+    // ===== 数据加载方法 =====
     async loadEditData() {
       try {
         const res = await getDetail({ id: this.editId });
-        console.log('编辑数据', res);
-        if (res) {
-          const data = res;
-
-          // 填充基本表单数据
-          this.form.experimentDate = data.experimentDate;
-
-          // 填充实验调度信息
-          if (data.experimentDispatch && data.experimentDispatch.id) {
-            this.form.dispatchId = data.experimentDispatch.id;
-
-            // 获取组别信息
-            try {
-              const groupRes = await getGroupByDispatchId({ dispatchId: data.experimentDispatch.id });
-              if (groupRes) {
-                this.groupData = groupRes || [];
-              }
-            } catch (err) {
-              console.error('获取组别列表失败:', err);
-            }
-
-            // 构建调度表格数据
-            this.groupTableData = [{ ...data.experimentDispatch }];
-          }
-
-          // 填充参与人员
-          if (data.experimentSchemePersons) {
-            this.selectedParticipants = Array.isArray(data.experimentSchemePersons)
-              ? data.experimentSchemePersons
-              : JSON.parse(data.experimentSchemePersons || '[]');
-          }
-
-          // 填充富文本编辑器内容
-          this.editorContents.purpose = data.experimentObjective || '';
-          this.editorContents.process = data.experimentParamRoute || '';
-
-          // 填充实验材料和设备(编辑模式下转换为查看格式)
-          if (data.experimentMaterial) {
-            try {
-              const materialData = typeof data.experimentMaterial === 'string'
-                ? JSON.parse(data.experimentMaterial)
-                : data.experimentMaterial;
-              this.form.experimentMaterial = materialData;
-
-            } catch (err) {
-              console.error('解析实验材料数据失败:', err);
-              this.viewMaterialData = [];
-            }
-          }
-
-          if (data.experimentDevice) {
-            try {
-              const deviceData = typeof data.experimentDevice === 'string'
-                ? JSON.parse(data.experimentDevice)
-                : data.experimentDevice;
-              this.form.experimentDevice = deviceData;
-
-            } catch (err) {
-              console.error('解析实验设备数据失败:', err);
-              this.viewEquipmentData = [];
-            }
-          }
-
-          // 填充实验步骤(编辑模式下步骤内容也要转换为查看格式)
-          if (data.experimentStepRecord) {
-            try {
-              const stepsData = typeof data.experimentStepRecord === 'string'
-                ? JSON.parse(data.experimentStepRecord)
-                : data.experimentStepRecord;
-
-              this.stepList = (stepsData || []).map(step => ({
-                stepName: step.stepName,
-                // 编辑模式下步骤内容转换为查看格式
-                content: step.content
-              }));
-            } catch (err) {
-              console.error('解析实验步骤数据失败:', err);
-              this.stepList = [];
-            }
-          }
-
-          // 等待组件渲染完成后设置编辑器内容
-          this.$nextTick(() => {
-            // 设置富文本编辑器内容
-            if (this.$refs.purposeEditor) {
-              this.$refs.purposeEditor.setContent(this.editorContents.purpose);
-            }
-            if (this.$refs.processEditor) {
-              this.$refs.processEditor.setContent(this.editorContents.process);
-            }
-
-            // 新增模式下设置动态组件的初始数据
-            if (!this.isEdit) {
-              if (this.$refs.materialComponent && this.form.experimentMaterial) {
-                this.$refs.materialComponent.setInitialData(this.form.experimentMaterial);
-              }
-              if (this.$refs.equipmentComponent && this.form.experimentDevice) {
-                this.$refs.equipmentComponent.setInitialData(this.form.experimentDevice);
-              }
-
-              // 设置步骤内容的初始数据
-              this.stepList.forEach((step, index) => {
-                const stepContentRef = this.$refs['stepContent' + index];
-                if (stepContentRef && step.content) {
-                  const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef;
-                  if (editor && typeof editor.setInitialData === 'function') {
-                    editor.setInitialData(step.content);
-                  }
-                }
-              });
-            }
-          });
-
-        } else {
-          this.$message.error(res.msg || '获取详情失败');
-          // this.$router.go(-1);
+        if (!res) {
+          this.$message.error('获取详情失败');
+          return;
         }
+        
+        console.log('编辑数据', res);
+        const data = res;
+
+        // 填充基本表单数据
+        this.form.experimentDate = data.experimentDate;
+
+        // 填充实验调度信息
+        if (data.experimentDispatch?.id) {
+          this.form.dispatchId = data.experimentDispatch.id;
+          this.groupTableData = [{ ...data.experimentDispatch }];
+          
+          // 获取组别信息
+          try {
+            const groupRes = await getGroupByDispatchId({ dispatchId: data.experimentDispatch.id });
+            this.groupData = groupRes || [];
+          } catch (err) {
+            console.error('获取组别列表失败:', err);
+          }
+        }
+
+        // 填充参与人员
+        this.selectedParticipants = Array.isArray(data.experimentSchemePersons)
+          ? data.experimentSchemePersons
+          : JSON.parse(data.experimentSchemePersons || '[]');
+
+        // 填充富文本编辑器内容
+        this.editorContents.purpose = data.experimentObjective || '';
+        this.editorContents.process = data.experimentParamRoute || '';
+
+        // 填充实验材料和设备
+        try {
+          this.form.experimentMaterial = typeof data.experimentMaterial === 'string'
+            ? JSON.parse(data.experimentMaterial)
+            : data.experimentMaterial;
+        } catch (err) {
+          console.error('解析实验材料数据失败:', err);
+          this.form.experimentMaterial = [];
+        }
+
+        try {
+          this.form.experimentDevice = typeof data.experimentDevice === 'string'
+            ? JSON.parse(data.experimentDevice)
+            : data.experimentDevice;
+        } catch (err) {
+          console.error('解析实验设备数据失败:', err);
+          this.form.experimentDevice = [];
+        }
+
+        // 填充实验步骤
+        try {
+          const stepsData = typeof data.experimentStepRecord === 'string'
+            ? JSON.parse(data.experimentStepRecord)
+            : data.experimentStepRecord;
+
+          this.stepList = (stepsData || []).map(step => ({
+            stepName: step.stepName,
+            content: step.content
+          }));
+        } catch (err) {
+          console.error('解析实验步骤数据失败:', err);
+          this.stepList = [];
+        }
+
+        // 等待组件渲染完成后设置编辑器内容
+        this.$nextTick(() => {
+          // 设置富文本编辑器内容
+          if (this.$refs.purposeEditor) {
+            this.$refs.purposeEditor.setContent(this.editorContents.purpose);
+          }
+          if (this.$refs.processEditor) {
+            this.$refs.processEditor.setContent(this.editorContents.process);
+          }
+
+          // 设置动态组件的初始数据
+          if (!this.isEdit) {
+            if (this.$refs.materialComponent && this.form.experimentMaterial) {
+              this.$refs.materialComponent.setInitialData(this.form.experimentMaterial);
+            }
+            if (this.$refs.equipmentComponent && this.form.experimentDevice) {
+              this.$refs.equipmentComponent.setInitialData(this.form.experimentDevice);
+            }
+
+            // 设置步骤内容的初始数据
+            this.stepList.forEach((step, index) => {
+              const stepContentRef = this.$refs['stepContent' + index];
+              if (stepContentRef && step.content) {
+                const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef;
+                if (editor?.setInitialData) {
+                  editor.setInitialData(step.content);
+                }
+              }
+            });
+          }
+        });
+
       } catch (error) {
         this.$message.error('获取详情失败');
         console.error('获取详情失败:', error);
-        // this.$router.go(-1);
       }
     },
-
     // 转换数据格式为ViewDynamicComponent需要的格式
     convertToViewFormat(data) {
       if (!data || !Array.isArray(data)) return [];
diff --git a/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue b/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
index 64b6a8c..d3a3873 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
@@ -521,24 +521,54 @@
   border-bottom: 1px solid #e4e7ed;
 }
 
+::v-deep .el-dialog__body {
+  padding: 20px;
+  max-height: 80vh;
+  overflow: hidden;
+}
+
+@media screen and (max-width: 1200px) {
+  ::v-deep .el-dialog__body {
+    max-height: none;
+    overflow: auto;
+  }
+}
+
 .approval-dialog {
   display: flex;
   height: 60vh;
+  padding:20px;
+  overflow: hidden;
+
+  @media screen and (max-width: 1200px) {
+    flex-direction: column;
+    height: auto;
+    
+    .approval-content, .approval-flow {
+      width: 100%;
+      margin-right: 0;
+      margin-bottom: 20px;
+      height: 50vh;
+    }
+  }
 
   .approval-content {
-    flex: 1;
+    flex: 7;
     margin-right: 20px;
     background: #ffffff;
     box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
     border-radius: 10px;
+    overflow-y: auto;
   }
 
   .approval-flow {
+    flex: 3;
+    min-width: 350px;
     padding: 40px 20px;
-    width: 405px;
     background: #ffffff;
     box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
     border-radius: 10px;
+    overflow-y: auto;
 
     .flow-title {
       font-size: 16px;
diff --git a/laboratory/src/views/dataManagement/schemeManagement/list.vue b/laboratory/src/views/dataManagement/schemeManagement/list.vue
index 914cff5..4597a9e 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/list.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/list.vue
@@ -23,6 +23,7 @@
           <el-form-item label="状态:">
             <el-select v-model="form.status" placeholder="请选择">
               <el-option label="全部" value=""></el-option>
+              <el-option label="草稿" :value="-1"></el-option>
               <el-option label="已发送" :value="1"></el-option>
               <el-option label="申请中止待审核" :value="2"></el-option>
               <el-option label="申请中止已通过" :value="3"></el-option>
@@ -95,7 +96,7 @@
 
             <!-- 实验员(5) -->
             <template v-if="userRole == '5'">
-              <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
+              <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == 1">编辑</el-button>
             </template>
           </template>
         </el-table-column>
@@ -156,11 +157,19 @@
   methods: {
     handlePageChange(page) {
       this.form.pageNum = page;
+      // 当处于草稿箱模式时,强制将状态设置为-1
+      if (this.currentType === 'draft') {
+        this.form.status = -1;
+      }
       this.getTableData();
     },
     handleSizeChange(size) {
       this.form.pageSize = size;
       this.form.pageNum = 1;
+      // 当处于草稿箱模式时,强制将状态设置为-1
+      if (this.currentType === 'draft') {
+        this.form.status = -1;
+      }
       this.getTableData();
     },
     resetForm() {
@@ -174,10 +183,18 @@
         pageNum: 1,
         pageSize: 10
       };
+      // 当处于草稿箱模式时,强制将状态设置为-1
+      if (this.currentType === 'draft') {
+        this.form.status = -1;
+      }
       this.getTableData();
     },
     handleSearch() {
       this.form.pageNum = 1;
+      // 当处于草稿箱模式时,强制将状态设置为-1
+      if (this.currentType === 'draft') {
+        this.form.status = -1;
+      }
       this.getTableData();
     },
     getStatusType(status) {
@@ -187,7 +204,8 @@
         '2': "warning",
         '3': "success",
         '4': "danger",
-        '5': "info"
+        '5': "info",
+        '6':'success'
       };
       return statusMap[status] || "info";
     },
@@ -198,7 +216,8 @@
         '2': "申请中止待审核",
         '3': "申请中止已通过",
         '4': "申请中止已驳回",
-        '5': "已封存"
+        '5': "已封存",
+        '6':'实验员已提交'
       };
       return statusMap[status] || "未知";
     },
@@ -219,6 +238,10 @@
     },
     async getTableData() {
       try {
+        // 当处于草稿箱模式时,强制将状态设置为-1
+        if (this.currentType === 'draft') {
+          this.form.status = -1;
+        }
         const { data } = await getList(this.form);
         this.tableData = data.records || [];
         this.total = data.total || 0;

--
Gitblit v1.7.1