From 76cbfbad1c4235e2baf3216a8c99781995241429 Mon Sep 17 00:00:00 2001 From: 董国庆 <364620639@qq.com> Date: 星期四, 22 五月 2025 10:32:55 +0800 Subject: [PATCH] 检验报告管理 --- laboratory/src/views/dataManagement/inspectionReport/detail.vue | 248 +++++++++++++++++++-- laboratory/src/views/dataManagement/inspectionReport/service.js | 29 ++ laboratory/src/views/dataManagement/inspectionReport/list.vue | 324 +++++++++++++++++++++------- 3 files changed, 484 insertions(+), 117 deletions(-) diff --git a/laboratory/src/views/dataManagement/inspectionReport/detail.vue b/laboratory/src/views/dataManagement/inspectionReport/detail.vue index b303a1f..913130a 100644 --- a/laboratory/src/views/dataManagement/inspectionReport/detail.vue +++ b/laboratory/src/views/dataManagement/inspectionReport/detail.vue @@ -7,28 +7,29 @@ inline label-position="top" > - - - - - - <div class="header-title" style="margin-bottom: 38px"> + <div class="header-title" style="margin-bottom: 38px"> <div class="header-title-left"> <img src="@/assets/public/headercard.png" /> <div>所属实验调度</div> </div> - <el-button type="primary" class="el-icon-plus" @click="handleAddTask">选择实验调度</el-button> + <el-button type="primary" class="el-icon-plus" @click="handleAddTask" v-if="pageType !== 'view'">选择实验调度</el-button> </div> <Table :data="taskTableData" :total="0" :height="null" class="rwuTable"> - <el-table-column prop="index" label="所属项目课题方案" width="200"></el-table-column> - <el-table-column prop="sampleCode" label="实验编号"></el-table-column> - <el-table-column prop="testData" label="实验名称"></el-table-column> - <el-table-column prop="testData" label="通知时间"></el-table-column> - <el-table-column prop="testData" label="实验开始时间"></el-table-column> - <el-table-column prop="testData" label="实验结束时间"></el-table-column> - <el-table-column prop="testData" label="参加人员"></el-table-column> - <el-table-column prop="testData" label="状态"></el-table-column> + <el-table-column prop="projectName" label="所属项目课题方案" width="200"></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"> <div class="header-title-left"> @@ -36,57 +37,101 @@ <div>本次检验结果总表</div> </div> </div> + <AiEditor + ref="totalResultEditor" + :value="editorContents.totalResult" + height="200px" + style="margin: 20px 0;" + placeholder="请输入本次检验结果总表..." + :readOnly="pageType === 'view'" + /> <div class="header-title"> <div class="header-title-left"> <img src="@/assets/public/headercard.png" /> <span>本次检验结果</span> </div> </div> + <AiEditor + ref="resultEditor" + :value="editorContents.result" + height="200px" + style="margin: 20px 0;" + placeholder="请输入本次检验结果..." + :readOnly="pageType === 'view'" + /> - <div class="add-project-footer"> - <el-button type="primary" class="save-btn">发送</el-button> - <el-button>存草稿</el-button> + <div class="add-project-footer" v-if="pageType !== 'view'"> + <el-button type="primary" class="save-btn" @click="handleSave">发送</el-button> + <el-button @click="handleSaveDraft">存草稿</el-button> </div> </el-form> <!-- 添加检测数据弹窗 --> - <add-dialog + <!-- <add-dialog ref="addDialog" :visible.sync="dialogVisible" @success="handleTaskSubmit" - /> + /> --> + <experimentalScheduling :show="dialogVisible" @close="handleSchedulingClose" @submit="handleSchedulingSubmit" /> </Card> </template> <script> import AddDialog from './components/addDialog.vue' import moment from 'moment' +import experimentalScheduling from "../sampleManage/components/experimental-scheduling.vue"; +import AiEditor from '@/components/AiEditor' +import { getDetail,add,update } from './service' export default { name: "AddProject", components: { - AddDialog + AddDialog, + experimentalScheduling, + AiEditor }, data() { return { dialogVisible: false, isEdit: false, currentEditIndex: -1, + pageType: 'add', // 页面类型:add-新增,edit-编辑,view-详情 form: { - recordNo: '', - testItemName: '', - testItemNo: '', - testMethodName: '', - testMethodNo: '' + id: '', + dispatchId: '', // 实验调度id + testReason: '', // 检验说明 + testResult: '', // 检验结果 + status: 1 // 状态:1=待提交 + }, + editorContents: { + totalResult: '', + result: '' }, rules: { - recordNo: [{ required: true, message: "请输入原始检验记录编号", trigger: "blur" }], - testItemName: [{ required: true, message: "请输入检测项名字", trigger: "blur" }], - testItemNo: [{ required: true, message: "请输入检测项编号", trigger: "blur" }], - testMethodName: [{ required: true, message: "请输入检测方法名字", trigger: "blur" }], - testMethodNo: [{ required: true, message: "请输入检测方法编号", trigger: "blur" }] + dispatchId: [{ required: true, message: "请选择实验调度", trigger: "change" }] }, - taskTableData: [] + taskTableData: [], + // 状态映射表 + statusTypeMap: { + "-1": "info", + "1": "warning", + "2": "success", + "3": "info" + }, + statusTextMap: { + "-1": "草稿箱", + "1": "待确认", + "2": "已确认", + "3": "已封存" + } }; + }, + created() { + // 从路由参数中获取id和type + const { id, type } = this.$route.query; + if (id) { + this.pageType = type || 'view'; + this.getDetail(id); + } }, methods: { handleAddTask() { @@ -209,6 +254,145 @@ }, getPhotoUrls(photos) { return photos.map(photo => photo.url); + }, + handleSchedulingClose() { + this.dialogVisible = false; + }, + handleSchedulingSubmit(data) { + this.taskTableData = data || []; + }, + getStatusType(status) { + return this.statusTypeMap[status] || 'info'; + }, + getStatusText(status) { + return this.statusTextMap[status] || '未知状态'; + }, + // 获取所有编辑器的内容 + getAllEditorContent() { + return { + totalResult: this.$refs.totalResultEditor.getContent(), + result: this.$refs.resultEditor.getContent() + } + }, + // 统一处理方法 + handleSubmit(type) { + // 如果是存草稿,不进行校验 + if (type === 'draft') { + this.submitData(type); + return; + } + + this.$refs.form.validate((valid) => { + if (valid) { + // 获取所有编辑器内容 + const editorContents = this.getAllEditorContent() + + // 检查编辑器内容是否为空 + const emptyFields = [] + + // 判断内容是否为空(排除<p></p>) + const isEmptyContent = (content) => { + return !content || content === '<p></p>' || content.trim() === '<p></p>' + } + + // 检查实验调度是否选择 + if (!this.taskTableData || this.taskTableData.length === 0) { + this.$message.warning('请选择实验调度') + return false + } + + // 检查检验结果总表是否填写 + if (isEmptyContent(editorContents.totalResult)) { + this.$message.warning('请填写本次检验结果总表') + return false + } + + this.submitData(type); + } else { + this.$message.warning('请填写必填项') + return false + } + }) + }, + + // 提交数据 + async submitData(type) { + try { + // 获取所有编辑器内容 + const editorContents = this.getAllEditorContent() + + // 构建提交数据 + const submitData = { + ...this.form, + dispatchId: this.taskTableData[0]?.id || '', + testReason: editorContents.totalResult, + testResult: editorContents.result, + status: type === 'draft' ? -1 : 1 // 草稿箱:-1, 待提交:1 + } + + // 如果是编辑模式,添加id + if (this.pageType === 'edit') { + submitData.id = this.form.id + } + + console.log('提交数据:', submitData) + + // 调用接口 + const request = this.pageType === 'edit' ? update : add + const res = await request(submitData) + + if (res.code === 200) { + const successMsg = type === 'draft' ? '草稿保存成功' : (this.pageType === 'edit' ? '更新成功' : '保存成功') + this.$message.success(successMsg) + this.$router.back() + } else { + const errorMsg = type === 'draft' ? '草稿保存失败' : (this.pageType === 'edit' ? '更新失败' : '保存失败') + this.$message.error(res.msg || errorMsg) + } + } catch (error) { + console.error('保存失败:', error) + const errorMsg = type === 'draft' ? '草稿保存失败' : (this.pageType === 'edit' ? '更新失败' : '保存失败') + this.$message.error(errorMsg) + } + }, + + // 获取详情数据 + async getDetail(id) { + try { + const res = await getDetail({ id }); + if (res) { + const data = res; + // 设置表单数据 + this.form = { + id: data.id, + dispatchId: data.dispatchId, + testReason: data.testReason, + testResult: data.testResult, + status: data.status + }; + // 设置编辑器内容 + this.editorContents = { + totalResult: data.testReason || '', + result: data.testResult || '' + }; + // 设置实验调度数据 + if (data.experimentDispatch) { + this.taskTableData = [data.experimentDispatch]; + } + } + } catch (error) { + console.error('获取详情失败:', error); + this.$message.error('获取详情失败,请重试'); + } + }, + + // 保存 + handleSave() { + this.handleSubmit('save') + }, + // 保存草稿 + handleSaveDraft() { + this.handleSubmit('draft') } } }; diff --git a/laboratory/src/views/dataManagement/inspectionReport/list.vue b/laboratory/src/views/dataManagement/inspectionReport/list.vue index e9d66bb..f00ab07 100644 --- a/laboratory/src/views/dataManagement/inspectionReport/list.vue +++ b/laboratory/src/views/dataManagement/inspectionReport/list.vue @@ -1,16 +1,19 @@ <template> <div class="list"> - <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null"> + <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null" @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange"> <template #search> <el-form :model="form" labelWidth="auto" inline> <el-form-item label="项目课题方案名称:"> - <el-input v-model="form.projectPlan" placeholder="请输入"></el-input> + <el-input v-model="form.projectName" placeholder="请输入"></el-input> </el-form-item> <el-form-item label="所属实验编号:"> - <el-input v-model="form.experimentNo" placeholder="请输入"></el-input> + <el-input v-model="form.experimentCode" placeholder="请输入"></el-input> + </el-form-item> + <el-form-item label="实验名称:"> + <el-input v-model="form.experimentName" placeholder="请输入"></el-input> </el-form-item> <el-form-item label="创建人:"> - <el-input v-model="form.creator" placeholder="请输入"></el-input> + <el-input v-model="form.createBy" placeholder="请输入"></el-input> </el-form-item> <el-form-item label="创建时间:"> <el-date-picker @@ -22,90 +25,167 @@ value-format="yyyy-MM-dd" ></el-date-picker> </el-form-item> - <el-form-item label="实验名称:"> - <el-input v-model="form.experimentName" placeholder="请输入"></el-input> - </el-form-item> <el-form-item label=""> <el-button type="default" @click="resetForm">重置</el-button> - <el-button type="primary" style="margin-left: 10px;" @click="handleSearch">查询</el-button> + <el-button type="primary" @click="handleSearch" style="margin-left: 20px">查询</el-button> </el-form-item> </el-form> </template> <template #setting> - <div class="tableTitle" @click="handleAdd"> + <div class="tableTitle"> <div class="flex a-center"> - <div class="title active">新增检验报告</div> + <div class="title" :class="{ active: activeTab == 'list' }" @click="handleTabChange('list')"> + 检验报告列表 + </div> + <div v-if="isLabTechnician" class="drafts" :class="{ active: activeTab == 'draft' }" @click="handleTabChange('draft')"> + 草稿箱 + </div> </div> + <el-button v-if="isLabTechnician" @click="handleAdd" class="el-icon-plus" type="primary"> + 新增检验报告</el-button> </div> </template> <template #table> - <el-table-column prop="projectPlan" label="所属项目课题方案" ></el-table-column> - <el-table-column prop="experimentNo" label="所属实验编号" ></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="createTime" label="创建时间" ></el-table-column> - <el-table-column prop="creator" label="创建人" ></el-table-column> + <el-table-column prop="createBy" label="创建人" ></el-table-column> <el-table-column prop="status" label="状态" > <template slot-scope="scope"> - <el-tag :type="scope.row.status === '待提交' ? 'warning' : 'success'"> - {{ scope.row.status }} + <el-tag :type="getStatusType(scope.row.status)"> + {{ getStatusText(scope.row.status) }} </el-tag> </template> </el-table-column> - <el-table-column label="操作"> + <el-table-column label="操作" width="250"> <template slot-scope="scope"> - <el-button type="text" @click="handleSubmit(scope.row)">提交</el-button> - <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button> + <!-- 列表状态下的按钮 --> + <template v-if="activeTab == 'list'"> + <!-- 化验师的按钮 --> + <template v-if="isLabTechnician"> + <el-button + v-if="scope.row.status == 1" + type="text" + @click="handleSubmit(scope.row)" + >提交</el-button> + <el-button + type="text" + v-if="scope.row.status == 1" + @click="handleEdit(scope.row)" + >编辑</el-button> + <el-button + type="text" + v-if="scope.row.status == 2" + @click="handleDetail(scope.row)" + >详情</el-button> + </template> + <!-- 其他角色的按钮 --> + <template v-else> + <el-button + type="text" + @click="handleDetail(scope.row)" + >详情</el-button> + </template> + </template> + <!-- 草稿箱状态下的按钮 --> + <template v-else> + <el-button + type="text" + @click="handleEdit(scope.row)" + >编辑</el-button> + <el-button + type="text" + @click="handleDelete(scope.row)" + >删除</el-button> + </template> </template> </el-table-column> </template> </TableCustom> + <ShowDelConfirm + :title="changeStatusTitle" + :tip="changeStatusTip" + :show="changeStatus" + @close="changeStatus = false" + @confirm="handleChangeStatusConfirm" + /> </div> </template> <script> -import store from '../../../store'; +import { getList, update, deleteById,commit } from './service'; +import ShowDelConfirm from "@/components/showDelConfirm/index.vue"; + export default { - name: "OriginalRecordTest", + name: "InspectionReportList", + components: { + ShowDelConfirm + }, data() { return { + activeTab: 'list', form: { - projectPlan: "", - experimentNo: "", - creator: "", + testReason: "", + testResult: "", + createBy: "", createTime: [], - experimentName: "" + startTime: "", + endTime: "", + status: '', + pageNum: 1, + pageSize: 10 }, - tableData: [ - { - id: '1', - projectPlan: '名称名称名称', - experimentNo: '31423764', - experimentName: '名称名称名称', - creator: '张三', - createTime: '2024-01-08', - status: '待提交' - } - ], - total: 5 + tableData: [], + total: 0, + // 确认弹窗相关数据 + changeStatus: false, + changeStatusTitle: "", + changeStatusTip: "", + currentOperationRow: null, + currentOperationType: '' }; + }, + computed: { + isLabTechnician() { + const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}'); + return userInfo.roleType == 4; // 4是化验师 + } }, created() { this.getTableData(); }, methods: { - resetForm() { - this.form = { - projectPlan: "", - experimentNo: "", - creator: "", - createTime: [], - experimentName: "" - }; - }, - handleSearch() { + handleTabChange(tab) { + this.activeTab = tab; + this.form.status = tab == 'draft' ? -1 : ''; this.getTableData(); }, - handleAdd(){ + resetForm() { + this.form = { + testReason: "", + testResult: "", + createBy: "", + createTime: [], + startTime: "", + endTime: "", + status: this.activeTab == 'draft' ? -1 : '', + pageNum: 1, + pageSize: 10 + }; + this.getTableData(); + }, + handleSearch() { + if (this.form.createTime && this.form.createTime.length == 2) { + this.form.startTime = this.form.createTime[0]; + this.form.endTime = this.form.createTime[1]; + } else { + this.form.startTime = ""; + this.form.endTime = ""; + } + this.getTableData(); + }, + handleAdd() { this.$router.push({ path: "/dataManagement/inspectionReport/detail", query: { @@ -123,46 +203,101 @@ }); }, handleSubmit(row) { - this.$confirm('确认提交该检验报告?', '提示', { - confirmButtonText: '确定', - cancelButtonText: '取消', - type: 'warning' - }).then(() => { - // TODO: 调用提交接口 - this.$message({ - type: 'success', - message: '提交成功!' - }); - this.getTableData(); - }).catch(() => { - this.$message({ - type: 'info', - message: '已取消提交' - }); + this.currentOperationRow = row; + this.currentOperationType = 'submit'; + this.changeStatusTitle = "确认提交检测数据结果吗?"; + this.changeStatusTip = "提交后关联的样品信息将不可回溯"; + this.changeStatus = true; + }, + handleDetail(row) { + this.$router.push({ + path: "/dataManagement/inspectionReport/detail", + query: { + id: row.id, + type: 'view' + } }); }, + handleDelete(row) { + this.currentOperationRow = row; + this.currentOperationType = 'delete'; + this.changeStatusTitle = "确认要删除这条信息吗?"; + this.changeStatusTip = "删除后信息无法找回"; + this.changeStatus = true; + }, + handleChangeStatusConfirm() { + if (!this.currentOperationRow) return; + + if (this.currentOperationType == 'submit') { + commit({id:this.currentOperationRow.id}).then(res => { + console.log('2222222',res) + if (res.code == 200) { + this.$message.success('提交成功!'); + this.changeStatus = false; + this.getTableData(); + } else { + this.$message.error(res.msg || '提交失败'); + } + }).catch(() => { + this.$message.error('提交失败'); + }); + } else if (this.currentOperationType == 'delete') { + deleteById({ + id: this.currentOperationRow.id + }).then(() => { + this.$message.success("删除成功"); + this.changeStatus = false; + this.getTableData(); + }).catch(error => { + this.$message.error("删除失败"); + }); + } + }, + getStatusType(status) { + const statusMap = { + '-1': 'info', + '1': 'warning', + '2': 'success' + }; + return statusMap[status] || 'info'; + }, + getStatusText(status) { + const statusMap = { + '-1': '草稿箱', + '1': '待提交', + '2': '已提交' + }; + return statusMap[status] || '未知'; + }, + handleSizeChange(val) { + this.form.pageSize = val; + this.getTableData(); + }, + handleCurrentChange(val) { + this.form.pageNum = val; + this.getTableData(); + }, getTableData() { - this.tableData = [ - { - id: '1', - projectPlan: '名称名称名称', - experimentNo: '31423764', - experimentName: '名称名称名称', - creator: '张三', - createTime: '2024-01-08', - status: '待提交' - }, - { - id: '2', - projectPlan: '项目方案2', - experimentNo: '31423765', - experimentName: '实验名称2', - creator: '李四', - createTime: '2024-01-09', - status: '已提交' + if (this.form.createTime && this.form.createTime.length == 2) { + this.form.startTime = this.form.createTime[0]; + this.form.endTime = this.form.createTime[1]; + } else { + this.form.startTime = ""; + this.form.endTime = ""; + } + + const { createTime, ...requestParams } = this.form; + console.log('requestParams',requestParams) + getList(requestParams).then(res => { + if (res.code == 200) { + this.tableData = res.data.records || []; + this.total = res.data.total || 0; + } else { + this.$message.error(res.msg || '获取列表失败'); } - ]; - this.total = this.tableData.length; + }).catch(() => { + this.$message.error('获取列表失败'); + }); } } }; @@ -172,31 +307,50 @@ .list { height: 100%; } + .flex { display: flex; align-items: center; } + .tableTitle { display: flex; padding-bottom: 20px; justify-content: space-between; align-items: center; - cursor: pointer; + .title { background: #fafafc; border-radius: 8px 8px 0px 0px; border: 1px solid #dcdfe6; padding: 16px 29px; - font-weight: bold; font-size: 18px; color: #606266; width: unset; + cursor: pointer; + transition: all 0.3s ease; + font-weight: 400; } + + .drafts { + padding: 16px 65px; + background: #fafafc; + border-radius: 8px 8px 0px 0px; + border: 1px solid #dcdfe6; + font-weight: 400; + font-size: 18px; + color: #606266; + margin-left: 16px; + cursor: pointer; + transition: all 0.3s ease; + } + .active { color: #049c9a; background: #ffffff; border-radius: 8px 8px 0px 0px; border: 1px solid #049c9a; + font-weight: bold; } } </style> \ No newline at end of file diff --git a/laboratory/src/views/dataManagement/inspectionReport/service.js b/laboratory/src/views/dataManagement/inspectionReport/service.js new file mode 100644 index 0000000..8a76155 --- /dev/null +++ b/laboratory/src/views/dataManagement/inspectionReport/service.js @@ -0,0 +1,29 @@ +import axios from '@/utils/request'; + +// 列表 +export const getList = (data) => { + return axios.post('/api/t-inspection-report/pageList', { ...data }) +} +// 详情 +export const getDetail = (data) => { + return axios.get('/open/t-inspection-report/getDetailById', { params:data }) +} +//新增 +export const add = (data) => { + return axios.post('/api/t-inspection-report/add', { ...data }) +} +//修改 +export const update = (data) => { + return axios.post('/api/t-inspection-report/update', { ...data }) +}//提交 +export const commit = (data) => { + return axios.put('/open/t-inspection-report/commit?id='+data.id) +} +//删除 +export const deleteById = (data) => { + return axios.delete('/open/t-inspection-report/deleteById', { params:data }) +} +//批量删除 +export const deleteByIds = (data) => { + return axios.delete('/open/t-inspection-report/deleteByIds', { params:data }) +} \ No newline at end of file -- Gitblit v1.7.1