From 86c6153f294e61c0ee2268b2651c63313abb56ee Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期四, 15 五月 2025 17:59:23 +0800
Subject: [PATCH] Merge branch 'main' of http://120.76.84.145:10101/gitblit/r/H5/leshan-laboratory

---
 laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue |  772 +++++++++----------
 laboratory/src/views/dataManagement/schemeManagement/list.vue                      |   43 
 laboratory/src/components/DynamicComponent/index.vue                               |  400 ++++++---
 laboratory/src/components/DynamicComponent/service.js                              |    8 
 laboratory/src/components/DynamicComponent/addTableHeader.vue                      |   53 
 laboratory/src/components/DynamicComponent/addTableData.vue                        |   94 +
 laboratory/src/components/AiEditor/index.vue                                       |    1 
 laboratory/src/views/dataManagement/schemeManagement/service.js                    |    2 
 laboratory/src/views/dataManagement/dispatching/list.vue                           |   16 
 laboratory/src/views/dataManagement/schemeManagement/addPlan.vue                   |  771 ++++++++++---------
 laboratory/src/components/SelectMember/service.js                                  |    8 
 laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue           |  178 +++
 laboratory/src/components/SelectMember/index.vue                                   |    5 
 13 files changed, 1,287 insertions(+), 1,064 deletions(-)

diff --git a/laboratory/src/components/AiEditor/index.vue b/laboratory/src/components/AiEditor/index.vue
index 4619576..9433983 100644
--- a/laboratory/src/components/AiEditor/index.vue
+++ b/laboratory/src/components/AiEditor/index.vue
@@ -72,7 +72,6 @@
   },
   mounted() {
     this.initEditor()
-    console.log('editor instance:', this.editor)
   },
   beforeDestroy() {
     this.destroyEditor()
diff --git a/laboratory/src/components/DynamicComponent/addTableData.vue b/laboratory/src/components/DynamicComponent/addTableData.vue
index b8956ac..22fcbb7 100644
--- a/laboratory/src/components/DynamicComponent/addTableData.vue
+++ b/laboratory/src/components/DynamicComponent/addTableData.vue
@@ -62,6 +62,7 @@
                     :disabled="!checkEditPermission(header)"
                   >
                     <i class="el-icon-plus"></i>
+                    <!-- <div slot="tip" class="el-upload__tip">暂未连接服务器,使用默认图片</div> -->
                   </el-upload>
                 </el-form-item>
                 <el-form-item
@@ -143,6 +144,8 @@
 </template>
   
 <script>
+import { listByRole } from './service';
+
 export default {
   name: "AddDialog",
   props: {
@@ -171,13 +174,8 @@
       rules: {},
       photoList: [],
       spectrumList: [],
-      userOptions: [
-        { value: '1', label: '用户1' },
-        { value: '2', label: '用户2' },
-        { value: '3', label: '用户3' },
-        { value: '4', label: '用户4' },
-        { value: '5', label: '用户5' }
-      ]
+      defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
+      userOptions: []
     };
   },
   computed: {
@@ -198,7 +196,6 @@
     visible: {
       handler(newVal) {
         if (newVal) {
-          console.log('弹窗打开,初始化数据');
           this.showHeaderList = JSON.parse(JSON.stringify(this.headerList));
           this.$forceUpdate();
           if (this.isEdit && this.editData) {
@@ -209,8 +206,6 @@
             this.initFormData();
           }
           this.initRules();
-          console.log('初始化后的表单数据:', this.form);
-          console.log('初始化后的校验规则:', this.rules);
         }
       },
     },
@@ -218,7 +213,6 @@
       immediate: true,
       handler(newVal) {
         if (newVal && newVal.length) {
-          console.log('headerList变化,重新初始化');
           if (this.isEdit && this.editData) {
             this.setFormData(this.editData);
           } else {
@@ -228,18 +222,22 @@
         }
       },
     },
-    showHeaderList: {
-      immediate: true,
-      handler(newVal) {
-        if (newVal ) {
-         
-          console.log("222222222222222222", JSON.stringify(newVal));
-          
-        }
-      },
-    },
   },
   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;
@@ -262,7 +260,6 @@
           }
         });
       }
-      console.log('生成的校验规则:', rules);
       this.rules = rules;
     },
     initFormData() {
@@ -286,8 +283,6 @@
       Object.keys(formData).forEach(key => {
         this.$set(this.form, key, formData[key]);
       });
-      
-      console.log('初始化后的表单数据:', this.form);
     },
     setFormData(data) {
       // 设置基础表单数据
@@ -355,23 +350,32 @@
       this.initFormData();
     },
     handleSubmit() {
-      console.log('开始提交表单');
-      console.log('表单数据:', this.form);
-      console.log('校验规则:', this.rules);
       
       this.$refs.form.validate((valid) => {
-        console.log('表单验证结果:', valid);
         if (valid) {
           const submitData = {
             ...this.form,
             photos: this.photoList,
             spectrums: this.spectrumList,
           };
-          console.log('提交数据:', submitData);
+          
+          // 为用户类型字段添加用户完整信息
+          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 {
-          console.log('表单验证失败');
           this.$message.error('请填写必填项');
         }
       });
@@ -381,20 +385,31 @@
       this.$refs.form.validateField("photos");
     },
     handleSpectrumChange(file, fileList) {
-      this.spectrumList = fileList;
+      // 使用默认图片替代实际上传
+      this.spectrumList = [{
+        name: '默认图片.jpg',
+        url: this.defaultImageUrl,
+        status: 'success'
+      }];
+      
+      // 同时更新form中对应的字段值以通过表单验证
+      const imageHeader = this.headerList.find(h => h.type === 'image');
+      if (imageHeader && imageHeader.name) {
+        // 保存图片URL,这样在表格中可以直接使用
+        this.$set(this.form, imageHeader.name, this.defaultImageUrl);
+        console.log('设置图片字段:', imageHeader.name, this.defaultImageUrl);
+      }
+      
       this.$refs.form.validateField("spectrums");
     },
     handleSpectrumRemove(file) {
-      // 处理文件移除逻辑
+      this.spectrumList = [];
     },
 
-    handleIPadSpectrum() {
-      // TODO: 调用 iPad 选择图谱功能
-      console.log("调用 iPad 选择图谱功能");
-    },
   },
   mounted() {
-    console.log("初始headerList:", this.headerList);
+    // 获取用户列表数据
+    this.getUserOptions();
   },
 };
 </script>
@@ -431,7 +446,7 @@
     .form-content {
       flex: 1;
       overflow-y: auto;
-      padding: 0 10px;
+      padding: 10px 10px;
       max-height: calc(90vh - 250px); // 设置内容区域最大高度
 
       &::-webkit-scrollbar {
@@ -447,6 +462,9 @@
         background: #f5f7fa;
       }
     }
+    .el-form-item::after{
+      height: 10px !important;
+    }
   }
 }
 
diff --git a/laboratory/src/components/DynamicComponent/addTableHeader.vue b/laboratory/src/components/DynamicComponent/addTableHeader.vue
index 0623b5d..b8697d9 100644
--- a/laboratory/src/components/DynamicComponent/addTableHeader.vue
+++ b/laboratory/src/components/DynamicComponent/addTableHeader.vue
@@ -1,11 +1,5 @@
 <template>
-  <el-dialog
-    title="新增表头"
-    :visible.sync="dialogVisible"
-    width="30%"
-    :close-on-click-modal="false"
-    @close="handleClose"
-  >
+  <el-dialog title="新增表头" :visible.sync="dialogVisible" width="30%" :close-on-click-modal="false" @close="handleClose">
     <div class="sample-dialog">
       <div class="sample-content">
         <div class="form-content">
@@ -13,43 +7,30 @@
             <el-row :gutter="24">
               <el-col :span="24">
                 <el-form-item label="表头名称" prop="name">
-                  <el-input
-                    v-model="form.name"
-                    style="width: 100%"
-                    placeholder="请输入表头名称"
-                  />
+                  <el-input v-model="form.name" style="width: 100%" placeholder="请输入表头名称" />
                 </el-form-item>
               </el-col>
               <el-col :span="24">
                 <el-form-item label="表头类型" prop="type">
                   <el-radio-group v-model="form.type" style="width: 100%">
-                    <el-radio-button  label="text">文本框</el-radio-button>
+                    <el-radio-button label="text">文本框</el-radio-button>
                     <el-radio-button label="image">图片上传</el-radio-button>
-                    <el-radio-button  label="date">日期选择</el-radio-button>
-                    <el-radio-button  label="user">人员选择</el-radio-button>
+                    <el-radio-button label="date">日期选择</el-radio-button>
+                    <el-radio-button label="user">人员选择</el-radio-button>
                   </el-radio-group>
                 </el-form-item>
               </el-col>
               <el-col :span="24">
                 <el-form-item label="操作权限" prop="role">
                   <el-select v-model="form.role" placeholder="请选择" style="width: 100%" multiple>
-                    <el-option
-                      v-for="item in options"
-                      :key="item.value"
-                      :label="item.label"
-                      :value="item.value"
-                    >
+                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
                     </el-option>
                   </el-select>
                 </el-form-item>
               </el-col>
               <el-col :span="24" v-if="['text', 'date', 'user'].includes(form.type)">
                 <el-form-item label="提示文案" prop="message">
-                  <el-input
-                    v-model="form.message"
-                    style="width: 100%"
-                    placeholder="请输入提示文案"
-                  />
+                  <el-input v-model="form.message" style="width: 100%" placeholder="请输入提示文案" />
                 </el-form-item>
               </el-col>
               <el-col :span="24">
@@ -71,7 +52,7 @@
     </div>
   </el-dialog>
 </template>
-  
+
 <script>
 export default {
   name: "AddDialog",
@@ -139,15 +120,18 @@
     },
     options() {
       // 将participants转换为select组件需要的格式
-      return this.participants.map(participant => ({
-        value: participant.userId ,
+      let userId = JSON.parse(sessionStorage.getItem('userInfo'))?.userId
+      let nickName = JSON.parse(sessionStorage.getItem('userInfo'))?.nickName
+      let newList = JSON.parse(JSON.stringify(this.participants))
+      newList.push({ userId, nickName })
+      return newList.map(participant => ({
+        value: participant.userId,
         label: participant.nickName
       }));
     }
   },
   mounted() {
     // 组件挂载时的初始化逻辑
-    console.log('组件已挂载');
   },
   methods: {
     setFormData(data) {
@@ -179,7 +163,7 @@
         this.$message.error('请输入提示文案');
         return;
       }
-      
+
       this.$refs.form.validate((valid) => {
         if (valid) {
           const submitData = {
@@ -192,7 +176,7 @@
   },
 };
 </script>
-  
+
 <style scoped lang="less">
 ::v-deep .el-dialog__body {
   padding: 0;
@@ -335,12 +319,15 @@
     .el-upload-list {
       margin-top: 10px;
     }
+
     .el-upload-list__item {
       transition: all 0.3s;
+
       &:hover {
         background-color: #f5f7fa;
       }
     }
+
     .el-upload__tip {
       color: #909399;
       font-size: 12px;
@@ -348,4 +335,4 @@
     }
   }
 }
-</style> 
\ No newline at end of file
+</style>
\ No newline at end of file
diff --git a/laboratory/src/components/DynamicComponent/index.vue b/laboratory/src/components/DynamicComponent/index.vue
index ac328f7..8faa19a 100644
--- a/laboratory/src/components/DynamicComponent/index.vue
+++ b/laboratory/src/components/DynamicComponent/index.vue
@@ -4,155 +4,96 @@
       <div class="add-group">
         <div v-if="title">*</div>
         <span v-if="title">{{ title }}</span>
-        <el-button
-          @click="showAddDialog = true"
-          class="el-icon-plus"
-          type="primary"
-        >
-          添加组件</el-button
-        >
+        <el-button v-if="editable" @click="showAddDialog = true" class="el-icon-plus" type="primary">
+          添加组件</el-button>
       </div>
 
       <!-- 选择组件弹窗 -->
-      <AddComponentDialog
-        :visible="showAddDialog"
-        @confirm="addComponent"
-        @close="showAddDialog = false"
-      />
+      <AddComponentDialog v-if="editable" :visible="showAddDialog" @confirm="addComponent"
+        @close="showAddDialog = false" />
 
       <!-- 动态渲染组件 -->
-      <div
-        v-for="(item, idx) in components"
-        :key="item.id"
-        class="dynamic-component"
-      >
+      <div v-for="(item, idx) in components" :key="item.id" class="dynamic-component">
         <!-- 富文本 -->
         <div v-if="item.type == 'richText'">
-          <AiEditor 
-            :ref="`editor_${item.id}`"
-           :value="item.data.content" 
-            height="200px"
-            placeholder="请输入内容..." 
-          />
+          <AiEditor :ref="`editor_${item.id}`" :value="item.data.content" height="200px" :readOnly="!editable" placeholder="请输入内容..."
+            :disabled="!editable" />
         </div>
         <!-- 自定义表格 -->
         <div v-else-if="item.type == 'customTable'" style="flex: 1">
-          <div class="table-actions">
-            <el-button size="mini" @click="showTableHeaderDialog(idx)"
-              >添加表头</el-button
-            >
-            <el-button
-              size="mini"
-              type="primary"
-              @click="showAddRowDialog(idx, item.data.headers)"
-              >添加数据</el-button
-            >
+          <div v-if="editable" class="table-actions">
+            <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"
-          >
-            <!-- <el-table-column
-              type="index"
-              label="序号"
-              width="80"
-            ></el-table-column> -->
-           
-            <el-table-column
-              v-for="(header, hidx) in item.data.headers"
-              :key="hidx"
-              :label="header.name"
-              :prop="header.name"
-            /> 
-            <el-table-column
-              label="更新时间"
-              prop="updateTime"
-              min-width="180"
-            ></el-table-column>
-            <el-table-column label="操作" min-width="200">
+          <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">
               <template slot-scope="scope">
-                <el-button type="text" @click="handleEditRow(idx, scope.$index)"
-                  >编辑</el-button
-                >
-                <el-button
-                  type="text"
-                  @click="handleDeleteRow(idx, scope.$index)"
-                  >删除</el-button
-                >
+                <!-- 用户类型显示 -->
+                <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">
+                <el-button type="text" @click="handleEditRow(idx, scope.$index)" >编辑</el-button>
+                <el-button type="text" v-if="editable" @click="handleDeleteRow(idx, scope.$index)">删除</el-button>
               </template>
             </el-table-column>
           </Table>
         </div>
         <!-- 文件上传 -->
         <div v-else-if="item.type == 'fileUpload'">
-          <el-upload
-            action="#"
-            :file-list="item.data.fileList"
-            :on-change="(file, fileList) => handleFileChange(idx, fileList)"
-            list-type="text"
-          >
+          <el-upload v-if="editable" action="#" :file-list="item.data.fileList"
+            :on-change="(file, fileList) => handleFileChange(idx, fileList)" list-type="text">
             <el-button size="small" icon="el-icon-upload2">点击上传</el-button>
           </el-upload>
+          <div v-else>
+            <div v-for="file in item.data.fileList" :key="file.uid" class="file-list-item">
+              {{ file.name }}
+            </div>
+          </div>
         </div>
         <!-- 图片上传 -->
         <div v-else-if="item.type == 'imageUpload'">
           <div class="image-upload-container">
-            <el-upload
-              action="#"
-              :file-list="item.data.imageList"
+            <el-upload v-if="editable" action="#" :file-list="item.data.imageList"
               :on-change="(file, fileList) => handleImageChange(idx, fileList)"
-              :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)"
-              :auto-upload="true"
-              :http-request="() => {}"
-              :before-upload="beforeImageUpload"
-              list-type="picture-card"
-              class="image-uploader"
-            >
+              :on-success="(res, file, fileList) => handleImageSuccess(res, file, fileList, idx)" :auto-upload="true"
+              :http-request="() => { }" :before-upload="beforeImageUpload" list-type="picture-card"
+              class="image-uploader">
               <i class="el-icon-plus"></i>
               <div class="upload-text">上传图片</div>
             </el-upload>
+            <div v-else class="image-preview">
+              <img v-for="image in item.data.imageList" :key="image.uid" :src="image.url" class="preview-image" />
+            </div>
             <div class="uploaf-notice">支持.jpg .png格式</div>
           </div>
         </div>
-        <img
-          src="@/assets/public/delete.png"
-          @click="removeComponent(idx)"
-          alt="删除"
-          class="delete-icon"
-        />
+        <img v-if="editable" src="@/assets/public/delete.png" @click="removeComponent(idx)" alt="删除"
+          class="delete-icon" />
       </div>
     </div>
 
-    <!-- 添加表头弹窗 -->
-    <el-dialog
-      :visible.sync="tableHeaderDialog.visible"
-      title="添加表头"
-      width="300px"
-    >
-      <el-input
-        v-model="tableHeaderDialog.header"
-        placeholder="请输入表头"
-      ></el-input>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="tableHeaderDialog.visible = false">取消</el-button>
-        <el-button type="primary" @click="confirmAddHeader">确定</el-button>
-      </span>
-    </el-dialog>
 
-    <addTableHeader
-      :visible.sync="tableHeaderDialog.visible"
-      :participants="participants"
-      @confirm="confirmAddHeader"
-    ></addTableHeader>
-    <addTableData
-      :visible.sync="rowDialog.visible"
-      :headerList="rowDialog.headers"
-      :editData="rowDialog.form"
-      :isEdit="rowDialog.isEdit"
-      @success="confirmAddRow"
-    >
+    <addTableHeader  :visible.sync="tableHeaderDialog.visible" :participants="participants"
+      @confirm="confirmAddHeader"></addTableHeader>
+    <addTableData  :visible.sync="rowDialog.visible" :headerList="rowDialog.headers"
+      :editData="rowDialog.form" :isEdit="rowDialog.isEdit" @success="confirmAddRow">
     </addTableData>
   </div>
 </template>
@@ -181,6 +122,18 @@
     participants: {
       type: Array,
       default: () => []
+    },
+    dataSource: {
+      type: Array,
+      default: () => []
+    },
+    editable: {
+      type: Boolean,
+      default: true
+    },
+    dialogCanEdit: {
+      type: Boolean,
+      default: true
     }
   },
   data() {
@@ -200,12 +153,94 @@
         headers: [],
         form: {},
       },
-      headerList: [], //编辑的表头列表
+      headerList: [],
+      defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址
     };
   },
+  watch: {
+    dataSource: {
+      handler(newVal) {
+        if (newVal) {
+          newVal = newVal.map(component => {
+            let componentData = null;
+
+            switch (component.type) {
+              case 'richText':
+                componentData = { content: component.data }
+                break;
+              case 'customTable':
+                componentData = {
+                  headers: component.data.headers,
+                  rows: component.data.rows
+                };
+                break;
+              case 'fileUpload':
+                componentData = { fileList: component.data };
+                break;
+              case 'imageUpload':
+                componentData = { imageList: component.data };
+                break;
+            }
+            return {
+              type: component.type,
+              id: component.id || Math.random().toString(36).substr(2, 9),
+              data: componentData
+            }
+          })
+        }
+        this.components = newVal ? [...newVal] : [];
+      },
+      immediate: true,
+      deep: true
+    }
+  },
   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;
+
       if (type === "customTable") {
         if (!this.participants || this.participants.length === 0) {
           this.$message.warning('请先选择实验调度');
@@ -213,7 +248,7 @@
           return;
         }
       }
-      
+
       this.showAddDialog = false;
       const id = Date.now() + Math.random();
       let data = {};
@@ -221,69 +256,88 @@
       if (type === "customTable") data = { headers: [], rows: [] };
       if (type === "fileUpload") data = { fileList: [] };
       if (type === "imageUpload") data = { imageList: [] };
-      console.log(type, "111111111111111", this.components);
 
       this.components.push({ id, type, data });
+      this.emitUpdate();
     },
     submit() {
-      // 获取所有组件的数据
       const data = this.components.map(component => {
         let componentData = null;
-        
+
         switch (component.type) {
           case 'richText':
             const editorRef = this.$refs[`editor_${component.id}`];
             const editor = Array.isArray(editorRef) ? editorRef[0] : editorRef;
-            console.log('editor ref:', editor);
             const content = editor ? editor.getContent() : '';
             componentData = content && content !== '<p></p>' ? content : '';
             break;
           case 'customTable':
-            // 获取表格数据
             componentData = {
               headers: component.data.headers,
               rows: component.data.rows
             };
             break;
           case 'fileUpload':
-            // 获取文件列表
             componentData = component.data.fileList;
             break;
           case 'imageUpload':
-            // 获取图片列表
             componentData = component.data.imageList;
             break;
         }
-        
+
         return {
           type: component.type,
           data: componentData
         };
       });
 
-      // 触发 submit 事件,将数据传递给父组件
       this.$emit('submit', data);
     },
     confirmAddRow(formData) {
+      // 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 = {};
     },
     removeComponent(idx) {
+      if (!this.editable) return;
+
       this.components.splice(idx, 1);
+      this.emitUpdate();
     },
     showTableHeaderDialog(idx) {
       this.tableHeaderDialog.visible = true;
@@ -291,14 +345,12 @@
       this.tableHeaderDialog.header = "";
     },
     confirmAddHeader(data) {
-      console.log("data", data);
+      if (!this.editable) return;
+
       const { idx } = this.tableHeaderDialog;
-      // 添加新表头
       this.components[idx].data.headers.push({ ...data });
-      
-      // 为已有行数据添加新表头对应的默认值
+
       this.components[idx].data.rows.forEach(row => {
-        // 如果行数据是对象,直接添加新属性
         if (typeof row === 'object' && row !== null) {
           if (data.type === 'user') {
             this.$set(row, data.name, []);
@@ -306,7 +358,6 @@
             this.$set(row, data.name, '');
           }
         } else {
-          // 如果行数据不是对象,转换为对象
           const newRow = {};
           this.components[idx].data.headers.forEach(header => {
             if (header.name === data.name) {
@@ -319,19 +370,18 @@
               newRow[header.name] = row[header.name] || '';
             }
           });
-          // 替换原行数据
           const rowIndex = this.components[idx].data.rows.indexOf(row);
           this.components[idx].data.rows.splice(rowIndex, 1, newRow);
         }
       });
 
-      // 关闭弹窗并重置数据
       this.tableHeaderDialog.visible = false;
       this.tableHeaderDialog = {
         visible: false,
         idx: null,
         header: "",
       };
+      this.emitUpdate();
     },
     showAddRowDialog(idx, headerList) {
       this.headerList = headerList;
@@ -340,7 +390,6 @@
       this.rowDialog.isEdit = false;
       this.rowDialog.headers = this.components[idx].data.headers;
       this.rowDialog.form = {};
-      // 初始化表单数据
       this.rowDialog.headers.forEach((header) => {
         if (header.type === "user") {
           this.rowDialog.form[header.name] = [];
@@ -355,12 +404,13 @@
       this.rowDialog.rowIndex = rowIndex;
       this.rowDialog.isEdit = true;
       this.rowDialog.headers = this.components[idx].data.headers;
-      // 深拷贝行数据,避免直接修改原数据
       this.rowDialog.form = JSON.parse(
         JSON.stringify(this.components[idx].data.rows[rowIndex])
       );
     },
     handleDeleteRow(idx, rowIndex) {
+      if (!this.editable) return;
+
       this.$confirm("确认删除该行数据吗?", "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
@@ -369,11 +419,13 @@
         .then(() => {
           this.components[idx].data.rows.splice(rowIndex, 1);
           this.$message.success("删除成功");
+          this.emitUpdate();
         })
-        .catch(() => {});
+        .catch(() => { });
     },
     handleFileChange(idx, fileList) {
-      // 为每个文件添加默认的URL和名称
+      if (!this.editable) return;
+
       fileList = fileList.map(file => {
         if (!file.url) {
           file.url = 'https://picsum.photos/200/200';
@@ -384,9 +436,11 @@
         return file;
       });
       this.components[idx].data.fileList = fileList;
+      this.emitUpdate();
     },
     handleImageChange(idx, fileList) {
-      // 为每个文件添加默认的URL
+      if (!this.editable) return;
+
       fileList = fileList.map(file => {
         if (!file.url) {
           file.url = 'https://picsum.photos/200/200';
@@ -394,9 +448,9 @@
         return file;
       });
       this.components[idx].data.imageList = fileList;
+      this.emitUpdate();
     },
     handleImageSuccess(res, file, fileList, idx) {
-      // 使用默认图片URL
       file.url = 'https://picsum.photos/200/200';
       this.components[idx].data.imageList = fileList;
     },
@@ -415,6 +469,11 @@
       }
       return true;
     },
+    emitUpdate() {
+      // 先创建新对象,这有助于触发更新
+      const updatedComponents = JSON.parse(JSON.stringify(this.components));
+      this.$emit('update:dataSource', updatedComponents);
+    },
   },
 };
 </script>
@@ -425,9 +484,11 @@
   padding: 20px;
   margin-top: 37px;
 }
-.has-title{
+
+.has-title {
   margin-top: 0px !important;
 }
+
 .add-group {
   display: flex;
   align-items: center;
@@ -445,25 +506,30 @@
     margin: 0 32px 0 8px;
   }
 }
+
 .dynamic-component {
   background: #ffffff;
   padding: 15px 20px;
   display: flex;
   justify-content: space-between;
   margin-bottom: 20px;
+
   .delete-icon {
     width: 16px;
     height: 16px;
     cursor: pointer;
   }
 }
-.image-uploader{
+
+.image-uploader {
   display: flex;
- ::v-deep .el-upload-list__item{
-width: 104px !important;
-height: 104px !important;
+
+  ::v-deep .el-upload-list__item {
+    width: 104px !important;
+    height: 104px !important;
   }
 }
+
 .image-upload-container {
   display: flex;
   flex-wrap: wrap;
@@ -475,6 +541,7 @@
   .el-upload--picture-card {
     margin: 0;
   }
+
   .el-upload-list--picture-card .el-upload-list__item {
     margin: 0 10px 10px 0;
   }
@@ -487,6 +554,7 @@
   align-items: center;
   justify-content: center;
   flex-direction: column;
+
   .upload-text {
     font-weight: 400;
     font-size: 14px;
@@ -495,6 +563,7 @@
     margin-top: 13px;
   }
 }
+
 .uploaf-notice {
   font-weight: 400;
   font-size: 14px;
@@ -502,17 +571,44 @@
   line-height: 22px;
   margin-top: 8px;
 }
+
 .table-actions {
   margin-bottom: 10px;
   display: flex;
   gap: 10px;
 }
+
 .groupTable {
   width: 100%;
   margin-top: 10px;
+
   ::v-deep .el-input__inner {
     width: unset !important;
   }
 }
 
+.file-list-item {
+  padding: 8px 0;
+  border-bottom: 1px solid #eee;
+}
+
+.image-preview {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+}
+
+.preview-image {
+  width: 104px;
+  height: 104px;
+  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/dispatching/list.vue b/laboratory/src/views/dataManagement/dispatching/list.vue
index 11c614f..34edc48 100644
--- a/laboratory/src/views/dataManagement/dispatching/list.vue
+++ b/laboratory/src/views/dataManagement/dispatching/list.vue
@@ -43,22 +43,22 @@
           <div class="flex a-center">
             <div
               class="title"
-              :class="{ active: currentType === 'list' }"
+              :class="{ active: currentType == 'list' }"
               @click="handleTypeChange('list')"
             >
               实验与调度列表
             </div>
             <div
-              v-if="userRole === '3'"
+              v-if="userRole == '3'"
               class="drafts"
-              :class="{ active: currentType === 'draft' }"
+              :class="{ active: currentType == 'draft' }"
               @click="handleTypeChange('draft')"
             >
               草稿箱
             </div>
           </div>
           <el-button 
-            v-if="userRole === '3'"
+            v-if="userRole == '3'"
             @click="handleAddPlan" 
             class="el-icon-plus" 
             type="primary"
@@ -112,7 +112,7 @@
             <template v-if="userRole == '3'">
               <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
               <el-button 
-                v-if="scope.row.status === 1" 
+                v-if="scope.row.status == 1" 
                 type="text" 
                 @click="handleDelete(scope.row)"
               >删除</el-button>
@@ -122,7 +122,7 @@
             <template v-if="userRole == '4' || userRole == '5'">
               <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
               <el-button
-                v-if="scope.row.status === 1"
+                v-if="scope.row.status == 1"
                 type="text"
                 @click="handleConfirm(scope.row)"
               >确认</el-button>
@@ -259,14 +259,14 @@
     },
     handleTypeChange(type) {
       this.currentType = type;
-      this.form.status = type === 'draft' ? '-1' : '';
+      this.form.status = type == 'draft' ? '-1' : '';
       this.form.pageNum = 1;
       this.getTableData();
     },
     getTableData() {
       const params = {
         ...this.form,
-        status: this.currentType === 'draft' ? '-1' : this.form.status
+        status: this.currentType == 'draft' ? '-1' : this.form.status
       };
       getDispatchList(params).then(res => {
         console.log('111111111111',res)
diff --git a/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue b/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
index 23a85df..ef3538f 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/addPlan.vue
@@ -2,70 +2,90 @@
   <Card>
     <template style="position: relative">
       <el-form ref="form" :model="form" :rules="rules" inline label-position="top">
-        <div class="header-title" style="margin-bottom: 38px; justify-content: space-between">
-          <div style="display: flex; align-items: center; gap: 13px">
+        <div v-if="!isEdit">
+          <div class="header-title" style="margin-bottom: 38px">
+            <div style="display: flex; align-items: center; gap: 13px">
+              <div class="header-title-left">
+                <img src="@/assets/public/headercard.png" />
+                <div>所属实验调度</div>
+              </div>
+              <el-button @click="showScheduling = true" class="el-icon-plus" type="primary">
+                选择实验调度</el-button>
+            </div>
+          </div>
+          <!-- //换到详情弹窗 -->
+          <!-- <el-button @click="handleStopExperiment" type="danger">
+            申请终止实验</el-button> -->
+          <Table :data="groupTableData" :total="0" :height="null" class="groupTable">
+            <el-table-column type="index" label="序号" width="80"></el-table-column>
+            <el-table-column prop="projectName" label="所属项目课题方案"></el-table-column>
+            <el-table-column prop="experimentCode" label="实验编号"></el-table-column>
+            <el-table-column prop="experimentName" label="实验名称"></el-table-column>
+            <el-table-column prop="experimentDate" label="通知时间"></el-table-column>
+            <el-table-column prop="experimentStartTime" label="实验开始时间"></el-table-column>
+            <el-table-column prop="experimentEndTime" label="实验结束时间"></el-table-column>
+            <el-table-column prop="participantsName" label="参加人员"></el-table-column>
+            <el-table-column prop="status" label="状态">
+              <template slot-scope="scope">
+                <el-tag :type="getStatusType(scope.row.status)">
+                  {{ getStatusText(scope.row.status) }}
+                </el-tag>
+              </template>
+            </el-table-column>
+          </Table>
+
+          <div class="header-title" style="margin-bottom: 38px">
             <div class="header-title-left">
               <img src="@/assets/public/headercard.png" />
-              <div>所属实验调度</div>
+              <span>基础信息</span>
             </div>
-            <el-button @click="showScheduling = true" class="el-icon-plus" type="primary">
-              选择实验调度</el-button>
           </div>
-          <el-button @click="handleStopExperiment" type="danger">
-            申请终止实验</el-button>
-        </div>
-        <Table :data="groupTableData" :total="0" :height="null" class="groupTable">
-          <el-table-column type="index" label="序号" width="80"></el-table-column>
-          <el-table-column prop="projectName" label="所属项目课题方案"></el-table-column>
-          <el-table-column prop="experimentCode" label="实验编号"></el-table-column>
-          <el-table-column prop="experimentName" label="实验名称"></el-table-column>
-          <el-table-column prop="experimentDate" label="通知时间"></el-table-column>
-          <el-table-column prop="experimentStartTime" label="实验开始时间"></el-table-column>
-          <el-table-column prop="experimentEndTime" label="实验结束时间"></el-table-column>
-          <el-table-column prop="participantsName" label="参加人员"></el-table-column>
-          <el-table-column prop="status" label="状态">
-            <template slot-scope="scope">
-              <el-tag :type="getStatusType(scope.row.status)">
-                {{ getStatusText(scope.row.status) }}
-              </el-tag>
-            </template>
-          </el-table-column>
-        </Table>
 
-        <div class="header-title" style="margin-bottom: 38px">
-          <div class="header-title-left">
-            <img src="@/assets/public/headercard.png" />
-            <span>基础信息</span>
+          <template v-if="groupData && groupData.length > 0">
+            <div class="add-group">
+              <span>组别列表</span>
+            </div>
+
+            <Table :data="groupData" :total="0" :height="null" class="groupTable">
+              <el-table-column type="index" label="序号" width="80"></el-table-column>
+              <el-table-column prop="groupName" label="组别"></el-table-column>
+              <el-table-column prop="remark" label="备注"></el-table-column>
+            </Table>
+          </template>
+
+          <div style="padding-left: 25px;margin-top: 28px;">
+            <el-form-item prop="experimentDate" label="试验日期">
+
+              <el-date-picker v-model="form.experimentDate" type="datetime" :disabled="isEdit" placeholder="选择日期时间">
+              </el-date-picker>
+            </el-form-item>
+          </div>
+        </div>
+        <div v-else>
+          <div class="header-title" style="margin-bottom: 18px">
+            <div class="header-title-left">
+              <img src="@/assets/public/headercard.png" />
+              <div>所属项目课题方案</div>
+            </div>
+          </div>
+          <div class="content-box">
+            <div class="content-box-left">
+              <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 && groupTableData.length > 0 ? groupTableData[0].projectCode : '' }}</div>
+              <div>实验名称: {{ groupTableData && groupTableData.length > 0 ? groupTableData[0].experimentName : '' }}</div>
+            </div>
           </div>
         </div>
 
-        <div class="add-group">
-          <span>组别列表</span>
-          <!-- <el-button type="primary" class="el-icon-plus" @click="handleAddGroup">添加组别</el-button> -->
-        </div>
-
-        <Table :data="groupData" :total="0" :height="null" class="groupTable">
-          <el-table-column type="index" label="序号" width="80"></el-table-column>
-          <el-table-column prop="groupName" label="组别"></el-table-column>
-          <el-table-column prop="remark" label="备注"></el-table-column>
-        </Table>
-
-        <div style="padding-left: 25px;margin-top: 28px;">
-          <el-form-item prop="experimentDate" label="试验日期">
-          
-            <el-date-picker
-      v-model="form.experimentDate"
-      type="datetime"
-      placeholder="选择日期时间">
-    </el-date-picker>
-          </el-form-item>
-        </div>
-
-        <div class="add-group">
+        <div class="add-group" v-if="!isEdit">
           <div>*</div>
           <span>参加人员</span>
-          <el-button type="primary" class="el-icon-plus" @click="addMember">选择参加人员</el-button>
+          <el-button type="primary" class="el-icon-plus" @click="addMember" >选择参加人员</el-button>
         </div>
+        <div class="add-group" v-else><span>实验人员</span> </div>
         <div class="member-list">
           <div class="member-list-card">
             <div class="member-item">
@@ -78,11 +98,23 @@
                 </div>
               </div>
               <div class="member-change">
-                <div class="member-change-btn" @click="handleEditMember">修改</div>
+                <div class="member-change-btn" @click="handleEditMember" v-if="!isEdit">修改</div>
               </div>
             </div>
           </div>
         </div>
+
+        <template v-if="groupData && groupData.length > 0 && isEdit">
+          <div class="add-group">
+            <span>组别列表</span>
+          </div>
+
+          <Table :data="groupData" :total="0" :height="null" class="groupTable">
+            <el-table-column type="index" label="序号" width="80"></el-table-column>
+            <el-table-column prop="groupName" label="组别"></el-table-column>
+            <el-table-column prop="remark" label="备注"></el-table-column>
+          </Table>
+        </template>
 
         <div class="header-title" style="margin-bottom: 38px">
           <div class="header-title-left">
@@ -91,7 +123,8 @@
           </div>
         </div>
         <div class="content-box">
-          <AiEditor ref="purposeEditor" :value="editorContents.purpose" height="200px" placeholder="请输入实验目的..." />
+          <AiEditor ref="purposeEditor" :readOnly="isEdit" :value="editorContents.purpose" height="200px"
+            placeholder="请输入实验目的..." />
         </div>
 
         <div class="header-title" style="margin-bottom: 38px">
@@ -101,7 +134,8 @@
           </div>
         </div>
         <div class="content-box">
-          <AiEditor ref="processEditor" :value="editorContents.process" height="200px" placeholder="请输入工艺参数及路线..." />
+          <AiEditor ref="processEditor" :readOnly="isEdit" :value="editorContents.process" height="200px"
+            placeholder="请输入工艺参数及路线..." />
         </div>
 
         <div class="header-title" style="margin-bottom: 38px">
@@ -110,15 +144,17 @@
             <div>三、实验材料及设备</div>
           </div>
         </div>
-        <DynamicComponent ref="materialComponent" title="实验材料" :participants="participantsData" @submit="handleMaterialSubmit" />
-        <DynamicComponent ref="equipmentComponent" title="实验所用设备" :participants="participantsData" @submit="handleEquipmentSubmit" />
+        <DynamicComponent ref="materialComponent" title="实验材料" :participants="participantsData"
+          @submit="handleMaterialSubmit" :dataSource="form.experimentMaterial" :editable="!isEdit" />
+        <DynamicComponent ref="equipmentComponent" title="实验所用设备" :participants="participantsData"
+          @submit="handleEquipmentSubmit" :dataSource="form.experimentDevice" :editable="!isEdit" />
 
         <div class="header-title" style="margin-bottom: 38px">
           <div class="header-title-left">
             <img src="@/assets/public/headercard.png" />
             <div>四、实验操作步骤记录</div>
           </div>
-          <el-button @click="handleAddStep" class="el-icon-plus" type="primary">
+          <el-button @click="handleAddStep" class="el-icon-plus" type="primary" v-if="!isEdit">
             添加步骤</el-button>
         </div>
 
@@ -128,17 +164,18 @@
               步骤{{ idx + 1 }}:{{ item.stepName }}
             </div>
             <div class="step-list-item-control">
-              <div class="controlBtn edit" @click="handleEditStep(idx)">
+              <div class="controlBtn edit" @click="handleEditStep(idx)" v-if="!isEdit">
                 <img src="@/assets/public/edit.png" alt="编辑" class="edit-icon" />
                 编辑
               </div>
-              <div class="controlBtn delete" @click="handleDeleteStep(idx)">
+              <div class="controlBtn delete" @click="handleDeleteStep(idx)" v-if="!isEdit">
                 <img src="@/assets/public/delete.png" alt="删除" class="delete-icon" />
                 删除
               </div>
             </div>
           </div>
-          <DynamicComponent :ref="'stepContent' + idx" @submit="(content) => handleStepContentSubmit(idx, content)" />
+          <DynamicComponent :ref="'stepContent' + idx" @submit="(content) => handleStepContentSubmit(idx, content)"
+            :dataSource="item.content" :editable="!isEdit" />
         </div>
 
         <div class="add-project-footer">
@@ -159,9 +196,9 @@
 import DynamicComponent from "@/components/DynamicComponent";
 import AddStep from "./components/add-step.vue";
 import AiEditor from "@/components/AiEditor";
-import { getGroupByDispatchId,getParticipantsByDispatchId } from "./service";
+import { getGroupByDispatchId, getParticipantsByDispatchId, getDetail } from "./service";
 import moment from 'moment';
-import { add } from "./service";
+import { add,update } from "./service";
 
 export default {
   name: "AddProject",
@@ -209,267 +246,67 @@
       taskTableData: [],
       participantsData: [],
       selectedParticipants: [],
+      isEdit: false, // 是否为编辑模式
+      editId: null, // 编辑的ID
+      viewMaterialData: [], // 查看模式的材料数据
+      viewEquipmentData: [], // 查看模式的设备数据
+      // 状态映射表
+      statusTypeMap: {
+        "-1": "info",
+        "1": "warning",
+        "2": "success",
+        "3": "info"
+      },
+      statusTextMap: {
+        "-1": "草稿箱",
+        "1": "待确认",
+        "2": "已确认",
+        "3": "已封存"
+      }
     };
   },
+  async created() {
+    // 检查是否为编辑模式
+    if (this.$route.query.type === 'edit' && this.$route.query.id) {
+      this.isEdit = true;
+      this.editId = this.$route.query.id;
+      await this.loadEditData();
+    }
+  },
   methods: {
-    confirmAddRow() {
-      // 处理添加行的逻辑
-      console.log('添加行');
-    },
-    submitForm() {
-      this.$refs.form.validate((valid) => {
-        if (valid) {
-          console.log("submit!");
-        }
-      });
-    },
+    // ===== 人员相关方法 =====
     addMember() {
       this.$refs.selectMember.open(this.participantsData, []);
     },
-    memberList(i) {
-      const roleTypes = {
-        1: '工艺工程师',
-        2: '化验师',
-        3: '实验员'
-      };
-      
-      return this.selectedParticipants.filter(member => member.roleType === i) || [];
+    handleMemberSubmit(selectedMembers) {
+      this.selectedParticipants = selectedMembers;
+      this.$refs.selectMember.close();
     },
-    handleAddGroup() {
-      this.$refs.addGroupDialog.open();
+    handleEditMember() {
+      this.$refs.selectMember.open(this.participantsData, this.selectedParticipants);
     },
-    handleEditGroup(row) {
-      this.$refs.addGroupDialog.open(row);
-    },
-    handleDeleteGroup(row) {
-      this.$confirm("确认删除该组别吗?", "提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning",
-      })
-        .then(() => {
-          const index = this.groupTableData.findIndex((item) => item === row);
-          if (index > -1) {
-            this.groupTableData.splice(index, 1);
-            this.$message.success("删除成功");
-          }
-        })
-        .catch(() => { });
-    },
-    handleGroupSubmit(form) {
-      const index = this.groupTableData.findIndex(
-        (item) => item.groupName === form.groupName
-      );
-      if (index > -1) {
-        this.groupTableData.splice(index, 1, form);
-      } else {
-        this.groupTableData.push(form);
-      }
-    },
-    handleAddTask() {
-      this.$refs.addTaskDialog.open();
-    },
-    handleEditTask(row) {
-      this.$refs.addTaskDialog.open(row);
-    },
-    handleDeleteTask(row) {
-      this.$confirm("确认删除该任务吗?", "提示", {
-        confirmButtonText: "确定",
-        cancelButtonText: "取消",
-        type: "warning",
-      })
-        .then(() => {
-          const index = this.taskTableData.findIndex((item) => item === row);
-          if (index > -1) {
-            this.taskTableData.splice(index, 1);
-            this.$message.success("删除成功");
-          }
-        })
-        .catch(() => { });
-    },
-    handleTaskSubmit(form) {
-      const index = this.taskTableData.findIndex(
-        (item) => item.taskName === form.taskName
-      );
-      if (index > -1) {
-        this.taskTableData.splice(index, 1, form);
-      } else {
-        this.taskTableData.push(form);
-      }
-    },
-    handleMaterialSubmit(data) {
-      // 处理实验材料数据
-      this.form.experimentMaterial = data;
-    },
-    handleEquipmentSubmit(data) {
-      // 处理实验设备数据
-      this.form.experimentDevice = data;
-    },
-    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("确认删除该步骤吗?删除后步骤内容将无法恢复", "警告", {
@@ -484,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 {
@@ -500,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) {
@@ -551,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;
@@ -564,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 || [];
@@ -610,12 +528,124 @@
     handleSchedulingClose() {
       this.showScheduling = false;
     },
-    handleMemberSubmit(selectedMembers) {
-      this.selectedParticipants = selectedMembers;
-      this.$refs.selectMember.close();
+    // ===== 数据加载方法 =====
+    async loadEditData() {
+      try {
+        const res = await getDetail({ id: this.editId });
+        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);
+      }
     },
-    handleEditMember() {
-      this.$refs.selectMember.open(this.participantsData, this.selectedParticipants);
+    // 转换数据格式为ViewDynamicComponent需要的格式
+    convertToViewFormat(data) {
+      if (!data || !Array.isArray(data)) return [];
+
+      return data.map(item => ({
+        id: item.id || Math.random().toString(36).substr(2, 9),
+        type: item.type,
+        data: item.data
+      }));
     },
   },
 };
@@ -926,7 +956,20 @@
 
 .content-box {
   padding: 0 25px;
-  margin-bottom: 30px;
+  margin-bottom: 20px;
   width: 65%;
+  display: flex;
+  .content-box-left{
+    flex: 1;
+    div{
+      padding: 10px 0;
+    }
+  }
+  .content-box-right{
+    flex: 1;
+    div{
+      padding: 10px 0;
+    }
+  }
 }
 </style>
\ No newline at end of file
diff --git a/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue b/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
index d31d6ae..d3a3873 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue
@@ -18,25 +18,34 @@
                 :rules="rules"
                 inline
                 label-position="top"
-                :disabled="type === 'view'"
+                
               >
                 <div class="header-title" style="margin-bottom: 38px">
-                  <div class="header-title-left">
-                    <img src="@/assets/public/headercard.png" />
-                    <div>所属实验调度</div>
+                  <div style="display: flex; align-items: center; gap: 13px">
+                    <div class="header-title-left">
+                      <img src="@/assets/public/headercard.png" />
+                      <div>所属实验调度</div>
+                    </div>
+                    <el-button @click="handleStopExperiment" type="danger">
+                      申请终止实验</el-button>
                   </div>
                 </div>
-                <Table :data="groupTableData" :total="0" :height="null">
-                  <el-table-column
-                    type="index"
-                    label="序号"
-                    width="80"
-                  ></el-table-column>
-                  <el-table-column
-                    prop="groupName"
-                    label="组别"
-                  ></el-table-column>
-                  <el-table-column prop="remark" label="备注"></el-table-column>
+                <Table :data="dispatchData" :total="0" :height="null" class="groupTable">
+                  <el-table-column type="index" label="序号" width="80"></el-table-column>
+                  <el-table-column prop="projectName" label="所属项目课题方案"></el-table-column>
+                  <el-table-column prop="experimentCode" label="实验编号"></el-table-column>
+                  <el-table-column prop="experimentName" label="实验名称"></el-table-column>
+                  <el-table-column prop="experimentDate" label="通知时间"></el-table-column>
+                  <el-table-column prop="experimentStartTime" label="实验开始时间"></el-table-column>
+                  <el-table-column prop="experimentEndTime" label="实验结束时间"></el-table-column>
+                  <el-table-column prop="participantsName" label="参加人员"></el-table-column>
+                  <el-table-column prop="status" label="状态">
+                    <template slot-scope="scope">
+                      <el-tag :type="getStatusType(scope.row.status)">
+                        {{ getStatusText(scope.row.status) }}
+                      </el-tag>
+                    </template>
+                  </el-table-column>
                 </Table>
 
                 <div class="header-title" style="margin-bottom: 38px">
@@ -46,72 +55,37 @@
                   </div>
                 </div>
 
-                <div class="add-group">
-                  <span>组别列表</span>
-                </div>
-                <Table
-                  :data="groupTableData"
-                  :total="0"
-                  :height="null"
-                  class="groupTable"
-                >
-                  <el-table-column
-                    type="index"
-                    label="序号"
-                    width="80"
-                  ></el-table-column>
-                  <el-table-column
-                    prop="groupName"
-                    label="组别"
-                  ></el-table-column>
-                  <el-table-column prop="remark" label="备注"></el-table-column>
-                </Table>
+                <template v-if="groupData && groupData.length > 0">
+                  <div class="add-group">
+                    <span>组别列表</span>
+                  </div>
+                  <Table :data="groupData" :total="0" :height="null" class="groupTable">
+                    <el-table-column type="index" label="序号" width="80"></el-table-column>
+                    <el-table-column prop="groupName" label="组别"></el-table-column>
+                    <el-table-column prop="remark" label="备注"></el-table-column>
+                  </Table>
+                </template>
 
-                <div style="padding-left: 25px; margin-top: 20px">
-                  <el-form-item prop="testTime" label="试验时间">
-                    <el-date-picker
-                      v-model="form.testTime"
-                      type="datetime"
-                      placeholder="选择日期时间"
-                      value-format="yyyy-MM-dd HH:mm:ss"
-                    />
+                <div style="padding-left: 25px;margin-top: 28px;">
+                  <el-form-item prop="experimentDate" label="试验日期">
+                    <el-date-picker  v-model="form.experimentDate" type="datetime" :disabled="true" placeholder="选择日期时间">
+                    </el-date-picker>
                   </el-form-item>
                 </div>
+
                 <div class="add-group">
-                  <div>*</div>
                   <span>实验人员</span>
                 </div>
                 <div class="member-list">
-                  <div v-for="item in 3" :key="item" class="member-list-card">
+                  <div class="member-list-card">
                     <div class="member-item">
-                      <div class="member-title">
-                        {{ ["工艺工程师", "实验员", "化验师"][item - 1] }}
-                      </div>
-                      <div
-                        :class="
-                          item == 1 || item == 2 || item == 3
-                            ? 'member-name-box'
-                            : 'flex1'
-                        "
-                      >
-                        <div
-                          :class="
-                            item == 1 || item == 2 || item == 3
-                              ? 'member-name-box'
-                              : 'member-name-box-2'
-                          "
-                        >
-                          <div
-                            v-for="i in memberList(item)"
-                            :key="i"
-                            class="member-name"
-                          >
-                            张三
+                      <div class="member-title">实验员</div>
+                      <div class="flex">
+                        <div class="member-name-box-2">
+                          <div v-for="i in selectedParticipants" :key="i.id" class="member-name">
+                            {{ i.nickName }}
                           </div>
                         </div>
-                      </div>
-                      <div class="member-change" v-if="type !== 'view'">
-                        <div class="member-change-btn">修改</div>
                       </div>
                     </div>
                   </div>
@@ -123,12 +97,15 @@
                     <div>一、实验目的</div>
                   </div>
                 </div>
-                <AiEditor
-                  ref="purposeEditor"
-                  v-model="form.purpose"
-                  height="200px"
-                  placeholder="请输入实验目的..."
-                />
+                <div class="content-box">
+                  <AiEditor
+                    ref="purposeEditor"
+                    :readOnly="true"
+                    :value="form.experimentObjective"
+                    height="200px"
+                    placeholder="请输入实验目的..."
+                  />
+                </div>
 
                 <div class="header-title" style="margin-bottom: 38px">
                   <div class="header-title-left">
@@ -136,12 +113,15 @@
                     <div>二、工艺参数及路线</div>
                   </div>
                 </div>
-                <AiEditor
-                  ref="processEditor"
-                  v-model="form.process"
-                  height="200px"
-                  placeholder="请输入工艺参数及路线..."
-                />
+                <div class="content-box">
+                  <AiEditor
+                    ref="processEditor"
+                    :readOnly="true"
+                    :value="form.experimentParamRoute"
+                    height="200px"
+                    placeholder="请输入工艺参数及路线..."
+                  />
+                </div>
 
                 <div class="header-title" style="margin-bottom: 38px">
                   <div class="header-title-left">
@@ -149,13 +129,19 @@
                     <div>三、实验材料及设备</div>
                   </div>
                 </div>
-                <ViewDynamicComponent
+                <DynamicComponent
+                  ref="materialComponent"
                   title="实验材料"
-                  :components="form.materialsAndEquipment || []"
+                  :dialogCanEdit="false"
+                  :dataSource="form.experimentMaterial"
+                  :editable="false"
                 />
-                <ViewDynamicComponent
+                <DynamicComponent
+                  ref="equipmentComponent"
                   title="实验所用设备"
-                  :components="form.materialsAndEquipment || []"
+                  :dialogCanEdit="false"
+                  :dataSource="form.experimentDevice"
+                  :editable="false"
                 />
 
                 <div class="header-title" style="margin-bottom: 38px">
@@ -165,15 +151,17 @@
                   </div>
                 </div>
 
-                <div class="step-list" v-for="(item, idx) in form.operationSteps" :key="idx">
+                <div class="step-list" v-for="(item, idx) in stepList" :key="idx">
                   <div class="step-list-item">
                     <div class="step-list-item-title">
                       步骤{{ idx + 1 }}:{{ item.stepName }}
                     </div>
                   </div>
-                  <ViewDynamicComponent
+                  <DynamicComponent
+                  :dialogCanEdit="false"
                     :ref="'stepContent' + idx"
-                    :components="[item]"
+                    :dataSource="item.content"
+                    :editable="false"
                   />
                 </div>
               </el-form>
@@ -181,13 +169,10 @@
           </Card>
         </div>
         <!-- 右侧审批流程 -->
-        <div class="approval-flow" v-if="type === 'view'">
+        <div class="approval-flow" v-if="showApprovalFlow">
           <div class="flow-content">
             <approval-process
-              :status="form.status"
-              :submit-time="form.createTime"
-              :approver="form.approver"
-              :approve-time="form.approveTime"
+              :processData="approvalProcessData"
             />
           </div>
         </div>
@@ -203,15 +188,16 @@
 <script>
 import ApprovalProcess from "@/components/approvalProcess";
 import SignatureCanvas from "@/components/SignatureCanvas.vue";
-import ViewDynamicComponent from "@/components/DynamicComponent/ViewDynamicComponent.vue";
-import AiEditor from "@/components/AiEditor/index.vue";
+import DynamicComponent from "@/components/DynamicComponent";
+import AiEditor from "@/components/AiEditor";
+import { getDetail, getGroupByDispatchId } from "../service";
 
 export default {
   name: "ApprovalDialog",
   components: {
     ApprovalProcess,
     SignatureCanvas,
-    ViewDynamicComponent,
+    DynamicComponent,
     AiEditor,
   },
   props: {
@@ -231,187 +217,43 @@
   data() {
     return {
       form: {
-        planName: "",
-        planCode: "",
-        stage: "",
-        testDate: "",
-        testName: "",
-        testCode: "",
-        testTime: "",
-        creator: "",
-        createTime: "",
-        approvalComment: "",
-        status: "approved",
-        approver: "",
-        approveTime: "",
-        materialsAndEquipment: [
-          {
-            id: 1,
-            type: "richText",
-            data: {
-              content:
-                "<p>1. 实验材料说明</p><p>2. 设备使用说明</p><p>3. 安全注意事项</p>",
-            },
-          },
-          {
-            id: 2,
-            type: "customTable",
-            data: {
-              headers: [
-                { name: "材料名称", type: "text" },
-                { name: "规格", type: "text" },
-                { name: "数量", type: "text" },
-                { name: "用途", type: "text" },
-              ],
-              rows: [
-                {
-                  材料名称: "催化剂A",
-                  规格: "工业级",
-                  数量: "100g",
-                  用途: "反应催化剂",
-                  updateTime: "2024-01-01 12:00:00",
-                },
-                {
-                  材料名称: "溶剂B",
-                  规格: "分析纯",
-                  数量: "500ml",
-                  用途: "反应溶剂",
-                  updateTime: "2024-01-01 12:00:00",
-                },
-              ],
-            },
-          },
-          {
-            id: 3,
-            type: "fileUpload",
-            data: {
-              fileList: [
-                {
-                  name: "材料安全说明书.pdf",
-                  url: "https://example.com/msds.pdf",
-                },
-                {
-                  name: "设备操作手册.docx",
-                  url: "https://example.com/manual.docx",
-                },
-              ],
-            },
-          },
-          {
-            id: 4,
-            type: "imageGallery",
-            data: {
-              images: [
-                {
-                  url: "https://example.com/equipment1.jpg",
-                  title: "实验设备1",
-                  description: "主要反应设备",
-                },
-                {
-                  url: "https://example.com/equipment2.jpg",
-                  title: "实验设备2",
-                  description: "辅助设备",
-                },
-              ],
-            },
-          },
-        ],
-        operationSteps: [
-          {
-            id: 7,
-            type: "richText",
-            data: {
-              content:
-                "<p>1. 准备工作</p><p>2. 设备检查</p><p>3. 实验操作</p><p>4. 数据记录</p>",
-            },
-          },
-          {
-            id: 8,
-            type: "customTable",
-            data: {
-              headers: [
-                { name: "步骤", type: "text" },
-                { name: "操作内容", type: "text" },
-                { name: "操作人", type: "user" },
-                { name: "操作图片", type: "image" },
-              ],
-              rows: [
-                {
-                  步骤: "步骤1",
-                  操作内容: "称取催化剂",
-                  操作人: ["1"],
-                  操作图片: [{ url: "https://example.com/step1.jpg" }],
-                  updateTime: "2024-01-01 12:00:00",
-                },
-                {
-                  步骤: "步骤2",
-                  操作内容: "加入溶剂",
-                  操作人: ["2"],
-                  操作图片: [{ url: "https://example.com/step2.jpg" }],
-                  updateTime: "2024-01-01 12:00:00",
-                },
-              ],
-            },
-          },
-        ],
+        projectName: "", // 项目课题方案名称
+        projectCode: "", // 项目课题方案编号
+        experimentCode: "", // 实验编号
+        experimentName: "", // 实验名称
+        experimentDate: "", // 实验日期
+        experimentMaterial: [], // 实验材料
+        experimentDevice: [], // 实验设备
+        experimentObjective: "", // 实验目的
+        experimentParamRoute: "", // 工艺参数及路线
+        createBy: "", // 创建人
+        createTime: "", // 创建时间
+        status: "", // 状态
+        approver: "", // 审批人
+        approveTime: "", // 审批时间
       },
       rules: {
-        planName: [
-          {
-            required: true,
-            message: "请输入项目课题方案名称",
-            trigger: "blur",
-          },
-        ],
-        planCode: [
-          {
-            required: true,
-            message: "请输入项目课题方案编号",
-            trigger: "blur",
-          },
-        ],
-        stage: [{ required: true, message: "请输入项目阶段", trigger: "blur" }],
-        testDate: [
-          { required: true, message: "请选择试验日期", trigger: "change" },
-        ],
-        testName: [
-          { required: true, message: "请输入实验名称", trigger: "blur" },
-        ],
-        testCode: [
-          { required: true, message: "请输入实验编号", trigger: "blur" },
-        ],
         testTime: [
           { required: true, message: "请选择试验时间", trigger: "change" },
         ],
       },
       imgSrc: "",
       signatureDialogVisible: false,
-      status: "1",
       remark: "",
-      groupTableData: [],
-      taskTableData: [],
+      groupData: [],
+      dispatchData: [], // 实验调度数据
+      stepList: [],
+      selectedParticipants: [], // 实验参与人员
+      showApprovalFlow: false,
+      approvalProcessData: [],
     };
-  },
-  computed: {
-    dialogTitle() {
-      return this.type === "approve" ? "确认实验调度" : "实验调度详情";
-    },
   },
   watch: {
     data: {
       handler(val) {
-        if (val) {
-          // 深拷贝数据,避免直接修改props
-          this.form = JSON.parse(
-            JSON.stringify({
-              ...this.form,
-              ...val,
-              // 确保这些字段存在,如果不存在则使用默认值
-              materialsAndEquipment: val.materialsAndEquipment || [],
-              operationSteps: val.operationSteps || [],
-            })
-          );
-          console.log("接收到的数据:", this.form);
+        if (val && val.id) {
+          // 当接收到数据且有ID时,调用获取详情接口
+          this.getPlanDetail(val.id);
         }
       },
       immediate: true,
@@ -419,28 +261,35 @@
     },
     visible: {
       handler(val) {
-        if (val && this.type === "view") {
-          // 当弹窗打开且是查看模式时,获取详情数据
-          this.getPlanDetail();
+        if (val && this.data && this.data.id) {
+          // 弹窗打开时,确保数据已获取
+          this.getPlanDetail(this.data.id);
         }
       },
       immediate: true,
     },
   },
   methods: {
-    memberList(i) {
-      switch (i) {
-        case 1:
-          return [1];
-        case 2:
-          return [1];
-        case 3:
-          return [1, 2, 3, 4, 5, 6, 7, 8];
-        case 4:
-          return [1, 2, 3, 4, 5, 6, 7, 8];
-        default:
-          break;
-      }
+    handleStopExperiment() {
+      this.$router.push("/dataManagement/scheme-management/stop-experiment?id=" + this.data.id);
+    },
+    getStatusType(status) {
+      const statusMap = {
+        "-1": "info",
+        "1": "warning",
+        "2": "success",
+        "3": "info"
+      };
+      return statusMap[status] || "info";
+    },
+    getStatusText(status) {
+      const statusMap = {
+        "-1": "草稿箱",
+        "1": "待确认",
+        "2": "已确认",
+        "3": "已封存"
+      };
+      return statusMap[status] || "未知";
     },
     handleClose() {
       this.$emit("update:visible", false);
@@ -466,9 +315,6 @@
         status: "rejected",
       });
     },
-    memberList(item) {
-      return item === 1 ? 2 : item === 2 ? 3 : 1;
-    },
     openSignature() {
       this.signatureDialogVisible = true;
     },
@@ -476,129 +322,190 @@
       console.log("imageData imageData", imageData);
       this.signatureDialogVisible = false;
       this.imgSrc = imageData;
-
-      // 这里处理签名确认后的逻辑
-      // this.$confirm('确认该实验调度吗?', '提示', {
-      //   confirmButtonText: '确定',
-      //   cancelButtonText: '取消',
-      //   type: 'warning'
-      // }).then(() => {
-      //   // 这里可以将签名图片数据(imageData)连同其他数据一起提交到后端
-      //   this.$message.success('确认成功');
-      //   this.signatureDialogVisible = false;
-      //   this.getTableData();
-      // }).catch(() => {
-      //   this.signatureDialogVisible = false;
-      // });
     },
     // 获取方案详情
-    async getPlanDetail() {
+    async getPlanDetail(id) {
       try {
-        // TODO: 替换为实际的接口调用
-        // const { data } = await this.$api.getPlanDetail({ planCode: this.data.planCode });
+        const res = await getDetail({ id });
+        if (!res) {
+          this.$message.error('获取方案详情失败');
+          this.handleClose();
+          return;
+        }
+        if(res.stopReason){
+          this.showApprovalFlow = true;
+          //中止实验申请
+        let processData = [];
+         processData.push({
+              type: "primary",
+              mode: "list",
+              fields: [
+                { label: "提交人:", value: res.updateBy || "" },
+                { label: "提交时间:", value: res.createTime || "" },
+              ],
+            });
+            if(res.status==4||res.status==3){
+              processData.push({
+                type:
+                  res.auditStatus === 2
+                    ? "primary"
+                    : res.auditStatus === 3
+                    ? "danger"
+                    : "warning",
+                mode: "list",
+                fields: [
+                  {
+                    label: "审核结果:",
+                    value:
+                      res.auditStatus === 2
+                        ? "通过"
+                        : res.auditStatus === 3
+                        ? "驳回"
+                        : "待审批",
+                  },
+                  { label: "审批意见:", value: res.auditRemark || "" },
+                  { label: "审核人:", value: res.auditPersonName || "" },
+                  { label: "审核时间:", value: res.auditTime || "" },
+                ],
+              });
+            }else{
+              processData.push({
+                type: "warning",
+                mode: "list",
+                fields: [
+                  { label: "等待审核"},
+                ],
+              });
+            }
+            this.approvalProcessData = processData;
+        }
 
-        // 模拟接口返回数据
-        const mockDetailData = {
-          planCode: this.data.planCode,
-          planName: "2024年度实验室设备升级方案",
-          stage: "设备升级实验",
-          testDate: "2024-03-15",
-          testTime: "2024-03-15 14:00:00",
-          tester: "张三",
-          creator: "张三",
-          createTime: "2024-03-15",
-          status: "pending",
-          approver: "李四",
-          approveTime: "2024-03-16",
-          materialsAndEquipment: [
-            {
-              id: 1,
-              type: "richText",
-              data: {
-                content:
-                  "<p>1. 实验材料说明</p><p>2. 设备使用说明</p><p>3. 安全注意事项</p>",
-              },
-            },
-            {
-              id: 2,
-              type: "customTable",
-              data: {
-                headers: [
-                  { name: "材料名称", type: "text" },
-                  { name: "规格", type: "text" },
-                  { name: "数量", type: "text" },
-                  { name: "用途", type: "text" },
-                ],
-                rows: [
-                  {
-                    材料名称: "催化剂A",
-                    规格: "工业级",
-                    数量: "100g",
-                    用途: "反应催化剂",
-                    updateTime: "2024-01-01 12:00:00",
-                  },
-                  {
-                    材料名称: "溶剂B",
-                    规格: "分析纯",
-                    数量: "500ml",
-                    用途: "反应溶剂",
-                    updateTime: "2024-01-01 12:00:00",
-                  },
-                ],
-              },
-            },
-            {
-              id: 3,
-              type: "fileUpload",
-              data: {
-                fileList: [
-                  {
-                    name: "材料安全说明书.pdf",
-                    url: "https://example.com/msds.pdf",
-                  },
-                  {
-                    name: "设备操作手册.docx",
-                    url: "https://example.com/manual.docx",
-                  },
-                ],
-              },
-            },
-            {
-              id: 4,
-              type: "imageUpload",
-              data: {
-                images: [
-                  {
-                    url: "https://example.com/equipment1.jpg",
-                    title: "实验设备1",
-                    description: "主要反应设备",
-                  },
-                  {
-                    url: "https://example.com/equipment2.jpg",
-                    title: "实验设备2",
-                    description: "辅助设备",
-                  },
-                ],
-              },
-            },
-          ],
-          operationSteps: [
-            {
-              id: 4,
-              type: "richText",
-              data: {
-                content:
-                  "<p>1. 准备工作</p><p>2. 设备检查</p><p>3. 实验操作</p><p>4. 数据记录</p>",
-              },
-            },
-          ],
-        };
-
-        // 更新表单数据
+        // 填充基本表单数据
         this.form = {
           ...this.form,
-          ...mockDetailData,
+          projectName: res.projectName,
+          projectCode: res.projectCode,
+          experimentCode: res.experimentCode,
+          experimentName: res.experimentName,
+          experimentDate: res.experimentDate,
+          createBy: res.createBy,
+          createTime: res.createTime,
+          status: res.status,
+          experimentObjective: res.experimentObjective || '',
+          experimentParamRoute: res.experimentParamRoute || '',
         };
+        
+        // 构建实验调度数据
+        if (res.experimentDispatch) {
+          this.dispatchData = [res.experimentDispatch];
+        }
+        
+        // 填充组别数据
+        if (res.dispatchId) {
+          try {
+            const groupRes = await getGroupByDispatchId({ dispatchId: res.dispatchId });
+            if (groupRes) {
+              this.groupData = groupRes || [];
+            }
+          } catch (err) {
+            console.error('获取组别列表失败:', err);
+          }
+        }
+        
+        // 填充实验材料和设备
+        if (res.experimentMaterial) {
+          try {
+            const materialData = typeof res.experimentMaterial === 'string'
+              ? JSON.parse(res.experimentMaterial)
+              : res.experimentMaterial;
+            this.form.experimentMaterial = materialData;
+            
+            // 为DynamicComponent设置初始数据
+            // this.$nextTick(() => {
+            //   if (this.$refs.materialComponent) {
+            //     this.$refs.materialComponent.setInitialData(materialData);
+            //   }
+            // });
+          } catch (err) {
+            console.error('解析实验材料数据失败:', err);
+          }
+        }
+        
+        if (res.experimentDevice) {
+          try {
+            const deviceData = typeof res.experimentDevice === 'string'
+              ? JSON.parse(res.experimentDevice)
+              : res.experimentDevice;
+            this.form.experimentDevice = deviceData;
+            
+            // 为DynamicComponent设置初始数据
+            this.$nextTick(() => {
+              // if (this.$refs.equipmentComponent) {
+              //   this.$refs.equipmentComponent.setInitialData(deviceData);
+              // }
+            });
+          } catch (err) {
+            console.error('解析实验设备数据失败:', err);
+          }
+        }
+        
+        // 填充实验步骤
+        if (res.experimentStepRecord) {
+          try {
+            const stepsData = typeof res.experimentStepRecord === 'string'
+              ? JSON.parse(res.experimentStepRecord)
+              : res.experimentStepRecord;
+            
+            this.stepList = (stepsData || []).map(step => ({
+              stepName: step.stepName,
+              content: step.content
+            }));
+            
+            // 设置步骤内容的初始数据
+            this.$nextTick(() => {
+              // 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);
+              //     }
+              //   }
+              // });
+            });
+          } catch (err) {
+            console.error('解析实验步骤数据失败:', err);
+            this.stepList = [];
+          }
+        }
+        
+        // 设置实验人员
+        if (res.experimentSchemePersons) {
+          try {
+            const participantsData = typeof res.experimentSchemePersons === 'string'
+              ? JSON.parse(res.experimentSchemePersons)
+              : res.experimentSchemePersons;
+              
+            this.selectedParticipants = participantsData || [];
+          } catch (err) {
+            console.error('解析实验人员数据失败:', err);
+            this.selectedParticipants = [];
+          }
+        }
+       
+        
+
+        
+        // 更新编辑器内容
+        this.$nextTick(() => {
+          if (this.$refs.purposeEditor) {
+            this.$refs.purposeEditor.setContent(this.form.experimentObjective);
+          }
+          if (this.$refs.processEditor) {
+            this.$refs.processEditor.setContent(this.form.experimentParamRoute);
+          }
+        });
+        
       } catch (error) {
         console.error("获取方案详情失败:", error);
         this.$message.error("获取方案详情失败");
@@ -614,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;
@@ -762,7 +699,7 @@
 }
 
 .groupTable {
-  width: 65%;
+  width: 85%;
   padding-left: 40px;
 }
 
@@ -779,8 +716,8 @@
   margin-left: 38px;
 
   .member-list-card {
-    width: 280px;
-    height: 300px;
+    width: 340px;
+    height: 400px;
     border-radius: 8px;
     border: 1px solid #dcdfe6;
 
@@ -891,11 +828,13 @@
 .step-list {
   background: #eff8fa;
   padding: 20px;
+  
   .step-list-item {
     display: flex;
     justify-content: space-between;
     padding: 25px;
     background: #ffffff;
+    
     .step-list-item-title {
       font-weight: 500;
       font-size: 14px;
@@ -907,13 +846,24 @@
   }
 }
 
-.dialog-footer {
-  align-items: center;
+.content-box {
+  padding: 0 25px;
+  margin-bottom: 20px;
+  width: 65%;
   display: flex;
-  justify-content: center;
-
-  button {
-    width: 150px;
+  
+  .content-box-left {
+    flex: 1;
+    div {
+      padding: 10px 0;
+    }
+  }
+  
+  .content-box-right {
+    flex: 1;
+    div {
+      padding: 10px 0;
+    }
   }
 }
 </style>
\ No newline at end of file
diff --git a/laboratory/src/views/dataManagement/schemeManagement/list.vue b/laboratory/src/views/dataManagement/schemeManagement/list.vue
index 81ed5ba..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>
@@ -89,13 +90,13 @@
 
             <!-- 工艺工程师(3) -->
             <template v-if="userRole == '3'">
-              <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == '4'">编辑</el-button>
+              <!-- <el-button type="text" @click="handleEdit(scope.row)" >编辑</el-button> -->
               <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
             </template>
 
             <!-- 实验员(5) -->
             <template v-if="userRole == '5'">
-              <el-button type="text" @click="handleEdit(scope.row)" v-if="scope.row.status == '4'">编辑</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;
@@ -244,17 +267,7 @@
     handleDetail(row) {
       this.approvalDialogType = 'view';
       this.approvalDialogVisible = true;
-      this.getPlanDetail(row.id);
-    },
-    async getPlanDetail(id) {
-      try {
-        const { data } = await this.$api.getDetail({ id });
-        this.currentApprovalData = data;
-      } catch (error) {
-        console.error('获取方案详情失败:', error);
-        this.$message.error('获取方案详情失败');
-        this.approvalDialogVisible = false;
-      }
+      this.currentApprovalData = row;
     },
     handleApproveSubmit(data) {
       this.approvalDialogVisible = false;
diff --git a/laboratory/src/views/dataManagement/schemeManagement/service.js b/laboratory/src/views/dataManagement/schemeManagement/service.js
index 90e3a8d..89e2877 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/service.js
+++ b/laboratory/src/views/dataManagement/schemeManagement/service.js
@@ -14,7 +14,7 @@
 }
 //修改
 export const update = (data) => {
-  return axios.post('/api/t-experiment-scheme/update', { ...data })
+  return axios.post('/api/t-experiment-scheme/updateTester', { ...data })
 }
 //删除
 export const deleteById = (data) => {
diff --git a/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue b/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
index 4ed09df..c94ed74 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
@@ -4,33 +4,41 @@
       <div class="header-title">
         <div class="header-title-left">
           <img src="@/assets/public/headercard.png" />
-          <span>所属实验调度</span>
+          <div>所属实验调度</div>
         </div>
       </div>
 
       <div class="table-container">
         <el-table :data="experimentData" border style="width: 100%">
-          <el-table-column prop="name" label="所属项目课题方案" />
-          <el-table-column prop="code" label="实验编号" />
-          <el-table-column prop="title" label="实验主题" />
-          <el-table-column prop="startTime" label="实验开始时间" />
-          <el-table-column prop="endTime" label="实验结束时间" />
-          <el-table-column prop="participants" label="参加人员" />
-          <el-table-column prop="status" label="状态" />
+          <el-table-column type="index" label="序号" width="80"></el-table-column>
+          <el-table-column prop="projectName" label="所属项目课题方案"></el-table-column>
+          <el-table-column prop="experimentCode" label="实验编号"></el-table-column>
+          <el-table-column prop="experimentName" label="实验名称"></el-table-column>
+          <el-table-column prop="experimentDate" label="通知时间"></el-table-column>
+          <el-table-column prop="experimentStartTime" label="实验开始时间"></el-table-column>
+          <el-table-column prop="experimentEndTime" label="实验结束时间"></el-table-column>
+          <el-table-column prop="participantsName" label="参加人员"></el-table-column>
+          <el-table-column prop="status" label="状态">
+            <template slot-scope="scope">
+              <el-tag :type="getStatusType(scope.row.status)">
+                {{ getStatusText(scope.row.status) }}
+              </el-tag>
+            </template>
+          </el-table-column>
         </el-table>
       </div>
 
       <div class="header-title">
         <div class="header-title-left">
           <img src="@/assets/public/headercard.png" />
-          <span>申请说明</span>
+          <div>中止原因说明</div>
         </div>
       </div>
 
       <div class="content-box">
         <AiEditor
           ref="reasonEditor"
-          v-model="editorContent"
+          :value="editorContent"
           height="200px"
           placeholder="请输入申请说明..."
         />
@@ -46,6 +54,9 @@
           :auto-upload="false"
           :on-change="handleFileChange"
           :file-list="fileList"
+          :on-remove="handleFileRemove"
+          multiple
+          :limit="5"
         >
           <el-button size="small" type="primary">选择文件</el-button>
           <div slot="tip" class="el-upload__tip">支持格式:.rar .zip .doc .docx .pdf .jpg...</div>
@@ -54,7 +65,7 @@
 
       <div class="footer-section">
         <div class="footer-content">
-          <el-button type="primary" @click="openSignatureDialog" :disabled="!agreement">提交</el-button>
+          <el-button type="primary" @click="openSignatureDialog" >提交</el-button>
           <el-checkbox v-model="agreement">我确认,已仔细实验说明,准确描述本次实验中止全部情况及原因,特此申请中止本次实验。</el-checkbox>
         </div>
       </div>
@@ -98,6 +109,7 @@
 <script>
 import AiEditor from '@/components/AiEditor'
 import SignatureCanvas from "@/components/SignatureCanvas.vue"
+import { getDetail, applicationTermination } from './service'
 
 export default {
   name: 'StopExperiment',
@@ -107,25 +119,54 @@
   },
   data() {
     return {
-      experimentData: [{
-        name: '金标准研究项',
-        code: 'DD-EX001',
-        title: '金标准研究项',
-        startTime: '2025-1-2 14:50:19',
-        endTime: '2025-02-27',
-        participants: '范兵, 李天霸, 张三, 李四',
-        status: '已确认'
-      }],
+      id: null,
+      experimentData: [],
       editorContent: '',
       fileList: [],
       agreement: false,
       signatureDialogVisible: false,
       signatureCanvasVisible: false,
       imgSrc: "",
+      loading: false
+    }
+  },
+  created() {
+    this.id = this.$route.query.id
+    if (this.id) {
+      this.getExperimentDetail()
+    } else {
+      this.$message.error('参数错误,缺少实验ID')
     }
   },
   methods: {
+    // 获取实验详情
+    async getExperimentDetail() {
+      try {
+        this.loading = true
+        const res = await getDetail({ id: this.id })
+        if (res) {
+          const data = res
+          this.experimentData = [{...data.experimentDispatch}]
+        } else {
+          this.$message.warning('未获取到实验详情')
+        }
+      } catch (error) {
+        console.error('获取实验详情失败:', error)
+        this.$message.error('获取实验详情失败')
+      } finally {
+        this.loading = false
+      }
+    },
     handleFileChange(file, fileList) {
+      // this.fileList = fileList
+      this.fileList = [{uid: Date.now(),
+         name: '实验中止申请表.txt', 
+         raw: file, 
+         size: file.size, 
+         url:'https://example.com/files/default-stop-application.pdf',
+         status: 'success'}]
+    },
+    handleFileRemove(file, fileList) {
       this.fileList = fileList
     },
     getEditorContent() {
@@ -133,17 +174,18 @@
     },
     validateForm() {
       const content = this.getEditorContent()
-      if (!content) {
-        this.$message.error('请填写申请说明')
+      if (!content || content === '<p></p>' || content.trim() === '<p></p>') {
+        this.$message.error('请填写中止原因说明')
         return false
       }
       if (!this.agreement) {
-        this.$message.error('请确认申请说明')
+        this.$message.error('请先勾选确认申请说明')
         return false
       }
       return true
     },
     openSignatureDialog() {
+      if (!this.validateForm()) return
       this.signatureDialogVisible = true
     },
     handleDialogClose() {
@@ -155,24 +197,70 @@
     },
     handleSignatureConfirm(imageData) {
       this.signatureCanvasVisible = false
-      this.imgSrc = imageData
+      // this.imgSrc = imageData
+      this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
     },
-    handleConfirm() {
+    async handleConfirm() {
       if (!this.imgSrc) {
         this.$message.warning("请先完成签名确认")
         return
       }
       if (this.validateForm()) {
-        const formData = {
-          reason: this.getEditorContent(),
-          files: this.fileList,
-          experimentInfo: this.experimentData[0],
-          signature: this.imgSrc
+        try {
+          this.loading = true
+          
+          // 处理多个文件,将文件路径和名称通过逗号拼接
+          let filePaths = '';
+          let fileNames = '';
+          
+          if (this.fileList.length > 0) {
+            // 模拟文件路径
+            filePaths = this.fileList.map(file => file.url).join(',')
+            
+            // 文件名称通过逗号拼接
+            fileNames = this.fileList.map(file => file.name).join(',')
+          }
+          
+          const formData = {
+            id: this.id,                     // 实验方案id
+            stopReason: this.getEditorContent(), // 中止原因
+            commitSign: this.imgSrc,         // 提交签字
+            stopFile: filePaths,             // 中止文件路径,多个文件路径通过逗号拼接
+            stopFileName: fileNames          // 中止文件名称,多个文件名称通过逗号拼接
+          }
+          
+          console.log('提交的数据:', formData)
+          
+          await applicationTermination(formData)
+          this.$message.success('提交成功')
+          this.handleDialogClose()
+          // 提交成功后返回列表页
+          this.$router.go(-1)
+        } catch (error) {
+          console.error('提交失败:', error)
+          this.$message.error('提交失败')
+        } finally {
+          this.loading = false
         }
-        console.log('提交的数据:', formData)
-        this.$message.success('提交成功')
-        this.handleDialogClose()
       }
+    },
+    getStatusType(status) {
+      const statusMap = {
+        "-1": "info",
+        "1": "warning",
+        "2": "success",
+        "3": "info"
+      };
+      return statusMap[status] || "info";
+    },
+    getStatusText(status) {
+      const statusMap = {
+        "-1": "草稿箱",
+        "1": "待确认",
+        "2": "已确认",
+        "3": "已封存"
+      };
+      return statusMap[status] || "未知";
     }
   }
 }
@@ -203,6 +291,20 @@
       line-height: 27px;
       font-family: "Source Han Sans CN Bold Bold";
     }
+    div {
+      flex-shrink: 0;
+      font-weight: bold;
+      font-size: 18px;
+      color: #222222;
+      line-height: 27px;
+      font-family: "Source Han Sans CN Bold Bold";
+
+      &:before {
+        content: "*";
+        color: #f56c6c;
+        margin-right: 4px;
+      }
+    }
   }
 }
 .header-title:first-child {
@@ -228,11 +330,11 @@
     span {
       font-size: 14px;
       color: #222222;
-      &::before {
-        content: "*";
-        color: #f56c6c;
-        margin-right: 4px;
-      }
+      // &::before {
+      //   content: "*";
+      //   color: #f56c6c;
+      //   margin-right: 4px;
+      // }
     }
   }
 

--
Gitblit v1.7.1