From 069ef85293bb4baa74dd9251e8b3fd8cc4355410 Mon Sep 17 00:00:00 2001 From: 董国庆 <364620639@qq.com> Date: 星期四, 15 五月 2025 15:21:10 +0800 Subject: [PATCH] 实验方案管理详情和中止 --- laboratory/src/components/DynamicComponent/addTableData.vue | 51 - laboratory/src/views/dataManagement/schemeManagement/components/approvalDialog.vue | 738 ++++++++++------------- laboratory/src/components/AiEditor/index.vue | 1 laboratory/src/views/dataManagement/schemeManagement/service.js | 2 laboratory/src/views/dataManagement/schemeManagement/list.vue | 16 laboratory/src/views/dataManagement/dispatching/list.vue | 16 laboratory/src/views/dataManagement/schemeManagement/addPlan.vue | 428 +++++++++----- laboratory/src/components/DynamicComponent/index.vue | 298 +++++---- laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue | 178 ++++- laboratory/src/components/DynamicComponent/addTableHeader.vue | 53 - 10 files changed, 945 insertions(+), 836 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..95267e6 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 @@ -171,6 +172,7 @@ rules: {}, photoList: [], spectrumList: [], + defaultImageUrl: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg', // 默认图片地址 userOptions: [ { value: '1', label: '用户1' }, { value: '2', label: '用户2' }, @@ -198,7 +200,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 +210,6 @@ this.initFormData(); } this.initRules(); - console.log('初始化后的表单数据:', this.form); - console.log('初始化后的校验规则:', this.rules); } }, }, @@ -218,23 +217,12 @@ immediate: true, handler(newVal) { if (newVal && newVal.length) { - console.log('headerList变化,重新初始化'); if (this.isEdit && this.editData) { this.setFormData(this.editData); } else { this.initFormData(); } this.initRules(); - } - }, - }, - showHeaderList: { - immediate: true, - handler(newVal) { - if (newVal ) { - - console.log("222222222222222222", JSON.stringify(newVal)); - } }, }, @@ -262,7 +250,6 @@ } }); } - console.log('生成的校验规则:', rules); this.rules = rules; }, initFormData() { @@ -286,8 +273,6 @@ Object.keys(formData).forEach(key => { this.$set(this.form, key, formData[key]); }); - - console.log('初始化后的表单数据:', this.form); }, setFormData(data) { // 设置基础表单数据 @@ -355,23 +340,17 @@ 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); this.$emit("success", submitData); this.handleClose(); } else { - console.log('表单验证失败'); this.$message.error('请填写必填项'); } }); @@ -381,20 +360,27 @@ 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) { + this.$set(this.form, imageHeader.name, '默认图片'); + } + this.$refs.form.validateField("spectrums"); }, handleSpectrumRemove(file) { - // 处理文件移除逻辑 + this.spectrumList = []; }, - handleIPadSpectrum() { - // TODO: 调用 iPad 选择图谱功能 - console.log("调用 iPad 选择图谱功能"); - }, }, mounted() { - console.log("初始headerList:", this.headerList); }, }; </script> @@ -431,7 +417,7 @@ .form-content { flex: 1; overflow-y: auto; - padding: 0 10px; + padding: 10px 10px; max-height: calc(90vh - 250px); // 设置内容区域最大高度 &::-webkit-scrollbar { @@ -447,6 +433,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..cd198b6 100644 --- a/laboratory/src/components/DynamicComponent/index.vue +++ b/laboratory/src/components/DynamicComponent/index.vue @@ -4,155 +4,78 @@ <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"> + <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" v-if="dialogCanEdit"> <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 - > + <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 +104,18 @@ participants: { type: Array, default: () => [] + }, + dataSource: { + type: Array, + default: () => [] + }, + editable: { + type: Boolean, + default: true + }, + dialogCanEdit: { + type: Boolean, + default: true } }, data() { @@ -200,12 +135,50 @@ headers: [], form: {}, }, - headerList: [], //编辑的表头列表 + headerList: [], }; + }, + 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: { addComponent(type) { - // 如果是添加自定义表格,需要检查是否已选择实验调度 + if (!this.editable) return; + if (type === "customTable") { if (!this.participants || this.participants.length === 0) { this.$message.warning('请先选择实验调度'); @@ -213,7 +186,7 @@ return; } } - + this.showAddDialog = false; const id = Date.now() + Math.random(); let data = {}; @@ -221,59 +194,53 @@ 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; if (isEdit) { - // 编辑模式 this.components[idx].data.rows[rowIndex] = { ...formData, updateTime: new Date().toLocaleString() }; } else { - // 新增模式 this.components[idx].data.rows.push({ ...formData, updateTime: new Date().toLocaleString() @@ -281,9 +248,13 @@ } this.rowDialog.visible = false; this.rowDialog.form = {}; + this.emitUpdate(); }, removeComponent(idx) { + if (!this.editable) return; + this.components.splice(idx, 1); + this.emitUpdate(); }, showTableHeaderDialog(idx) { this.tableHeaderDialog.visible = true; @@ -291,14 +262,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 +275,6 @@ this.$set(row, data.name, ''); } } else { - // 如果行数据不是对象,转换为对象 const newRow = {}; this.components[idx].data.headers.forEach(header => { if (header.name === data.name) { @@ -319,19 +287,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 +307,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 +321,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 +336,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 +353,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 +365,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 +386,9 @@ } return true; }, + emitUpdate() { + this.$emit('update:dataSource', this.components); + }, }, }; </script> @@ -425,9 +399,11 @@ padding: 20px; margin-top: 37px; } -.has-title{ + +.has-title { margin-top: 0px !important; } + .add-group { display: flex; align-items: center; @@ -445,25 +421,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 +456,7 @@ .el-upload--picture-card { margin: 0; } + .el-upload-list--picture-card .el-upload-list__item { margin: 0 10px 10px 0; } @@ -487,6 +469,7 @@ align-items: center; justify-content: center; flex-direction: column; + .upload-text { font-weight: 400; font-size: 14px; @@ -495,6 +478,7 @@ margin-top: 13px; } } + .uploaf-notice { font-weight: 400; font-size: 14px; @@ -502,17 +486,37 @@ 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; +} </style> 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..969c483 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[0].projectName }}</div> + <div>实验编号:{{ groupTableData[0].experimentCode }}</div> + </div> + <div class="content-box-right"> + <div>项目课题方案编号: {{ groupTableData[0].projectCode }}</div> + <div>实验名称: {{ 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,93 +246,23 @@ taskTableData: [], participantsData: [], selectedParticipants: [], + isEdit: false, // 是否为编辑模式 + editId: null, // 编辑的ID + viewMaterialData: [], // 查看模式的材料数据 + viewEquipmentData: [], // 查看模式的设备数据 }; }, + 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) || []; - }, - handleAddGroup() { - this.$refs.addGroupDialog.open(); - }, - 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) { // 处理实验材料数据 @@ -309,19 +276,19 @@ // 先获取所有动态组件的数据 this.$refs.materialComponent.submit(); this.$refs.equipmentComponent.submit(); - + // 获取所有步骤内容 - 添加错误检查 this.stepList.forEach((step, index) => { const stepContentRef = this.$refs['stepContent' + index]; - console.log('stepContentRef',stepContentRef) + 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) + console.log('材料数据', this.form.experimentMaterial) + console.log('设备数据', this.form.experimentDevice) + console.log('步骤数据', this.form.stepList) // 然后进行表单校验 this.$refs.form.validate((valid) => { @@ -358,7 +325,7 @@ // 提交时间,使用 moment 格式化为指定格式 commitTime: moment().format('YYYY-MM-DD HH:mm:ss'), }; - console.log('formData 提交数据',formData) + console.log('formData 提交数据', formData) // 调用添加接口 add(formData).then(res => { @@ -389,7 +356,7 @@ // 先获取所有动态组件的数据 this.$refs.materialComponent.submit(); this.$refs.equipmentComponent.submit(); - + // 获取所有步骤内容 - 添加错误检查 this.stepList.forEach((step, index) => { const stepContentRef = this.$refs['stepContent' + index]; @@ -490,7 +457,7 @@ this.$refs.addStepDialog.setStepName(this.stepList[index].stepName); }, handleStepContentSubmit(index, content) { - console.log('步骤内容',content) + console.log('步骤内容', content) this.stepList[index].content = content; }, getAllEditorContent() { @@ -616,6 +583,144 @@ }, handleEditMember() { this.$refs.selectMember.open(this.participantsData, this.selectedParticipants); + }, + // 加载编辑数据 + async loadEditData() { + try { + const res = await getDetail({ id: this.editId }); + console.log('编辑数据', res); + if (res) { + const data = res; + + // 填充基本表单数据 + this.form.experimentDate = data.experimentDate; + + // 填充实验调度信息 + if (data.experimentDispatch && data.experimentDispatch.id) { + this.form.dispatchId = data.experimentDispatch.id; + + // 获取组别信息 + try { + const groupRes = await getGroupByDispatchId({ dispatchId: data.experimentDispatch.id }); + if (groupRes) { + this.groupData = groupRes || []; + } + } catch (err) { + console.error('获取组别列表失败:', err); + } + + // 构建调度表格数据 + this.groupTableData = [{ ...data.experimentDispatch }]; + } + + // 填充参与人员 + if (data.experimentSchemePersons) { + this.selectedParticipants = Array.isArray(data.experimentSchemePersons) + ? data.experimentSchemePersons + : JSON.parse(data.experimentSchemePersons || '[]'); + } + + // 填充富文本编辑器内容 + this.editorContents.purpose = data.experimentObjective || ''; + this.editorContents.process = data.experimentParamRoute || ''; + + // 填充实验材料和设备(编辑模式下转换为查看格式) + if (data.experimentMaterial) { + try { + const materialData = typeof data.experimentMaterial === 'string' + ? JSON.parse(data.experimentMaterial) + : data.experimentMaterial; + this.form.experimentMaterial = materialData; + + } catch (err) { + console.error('解析实验材料数据失败:', err); + this.viewMaterialData = []; + } + } + + if (data.experimentDevice) { + try { + const deviceData = typeof data.experimentDevice === 'string' + ? JSON.parse(data.experimentDevice) + : data.experimentDevice; + this.form.experimentDevice = deviceData; + + } catch (err) { + console.error('解析实验设备数据失败:', err); + this.viewEquipmentData = []; + } + } + + // 填充实验步骤(编辑模式下步骤内容也要转换为查看格式) + if (data.experimentStepRecord) { + try { + const stepsData = typeof data.experimentStepRecord === 'string' + ? JSON.parse(data.experimentStepRecord) + : data.experimentStepRecord; + + this.stepList = (stepsData || []).map(step => ({ + stepName: step.stepName, + // 编辑模式下步骤内容转换为查看格式 + content: step.content + })); + } catch (err) { + console.error('解析实验步骤数据失败:', err); + this.stepList = []; + } + } + + // 等待组件渲染完成后设置编辑器内容 + this.$nextTick(() => { + // 设置富文本编辑器内容 + if (this.$refs.purposeEditor) { + this.$refs.purposeEditor.setContent(this.editorContents.purpose); + } + if (this.$refs.processEditor) { + this.$refs.processEditor.setContent(this.editorContents.process); + } + + // 新增模式下设置动态组件的初始数据 + if (!this.isEdit) { + if (this.$refs.materialComponent && this.form.experimentMaterial) { + this.$refs.materialComponent.setInitialData(this.form.experimentMaterial); + } + if (this.$refs.equipmentComponent && this.form.experimentDevice) { + this.$refs.equipmentComponent.setInitialData(this.form.experimentDevice); + } + + // 设置步骤内容的初始数据 + this.stepList.forEach((step, index) => { + const stepContentRef = this.$refs['stepContent' + index]; + if (stepContentRef && step.content) { + const editor = Array.isArray(stepContentRef) ? stepContentRef[0] : stepContentRef; + if (editor && typeof editor.setInitialData === 'function') { + editor.setInitialData(step.content); + } + } + }); + } + }); + + } else { + this.$message.error(res.msg || '获取详情失败'); + // this.$router.go(-1); + } + } catch (error) { + this.$message.error('获取详情失败'); + console.error('获取详情失败:', error); + // this.$router.go(-1); + } + }, + + // 转换数据格式为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 +1031,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..64b6a8c 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("获取方案详情失败"); @@ -762,7 +669,7 @@ } .groupTable { - width: 65%; + width: 85%; padding-left: 40px; } @@ -779,8 +686,8 @@ margin-left: 38px; .member-list-card { - width: 280px; - height: 300px; + width: 340px; + height: 400px; border-radius: 8px; border: 1px solid #dcdfe6; @@ -891,11 +798,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 +816,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..914cff5 100644 --- a/laboratory/src/views/dataManagement/schemeManagement/list.vue +++ b/laboratory/src/views/dataManagement/schemeManagement/list.vue @@ -89,13 +89,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)">编辑</el-button> </template> </template> </el-table-column> @@ -244,17 +244,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