董国庆
8 小时以前 76cbfbad1c4235e2baf3216a8c99781995241429
检验报告管理
2个文件已修改
1个文件已添加
601 ■■■■ 已修改文件
laboratory/src/views/dataManagement/inspectionReport/detail.vue 248 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/inspectionReport/list.vue 324 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/inspectionReport/service.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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')
    }
  }
};
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> 
laboratory/src/views/dataManagement/inspectionReport/service.js
New file
@@ -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 })
}