27个文件已修改
1个文件已删除
8个文件已添加
5983 ■■■■■ 已修改文件
laboratory/src/components/Table/index.vue 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/router/index.js 68 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/SampleDeliveryRecord/components/receiveConfirmDialog.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue 507 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/SampleDeliveryRecord/list.vue 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/SampleDeliveryRecord/service.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/components/addDialog.vue 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/detail.vue 418 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/list.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/originalRecordTest/service.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/addSample.vue 677 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/components/experimental-scheduling.vue 187 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/components/receiveConfirmDialog.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/list.vue 308 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleManage/service.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue 298 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleRecordList/components/confirmDialog.vue 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleRecordList/components/sampleDialog.vue 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleRecordList/list.vue 285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleRecordList/service.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleSubmissionList/components/receiveConfirmDialog.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleSubmissionList/list.vue 210 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleSubmissionList/service.js 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue 278 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/feasibilityReport/index.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/feasibilityStudy/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/processDevelopment/index.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/processDevelopment/service.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/projectProposalLibrary/add.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/projectProposalLibrary/components/approval/index.vue 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/projectProposalLibrary/index.vue 273 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/projectProposalLibrary/service.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/verificationRelease/add.vue 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/verificationRelease/components/approval/index.vue 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/verificationRelease/index.vue 276 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/views/reportLibrary/verificationRelease/service.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
laboratory/src/components/Table/index.vue
@@ -42,14 +42,14 @@
        }
    },
    methods: {
        toggleRowSelection(row, selected) {
            this.$refs.elTable.toggleRowSelection(row, selected)
            this.$forceUpdate()
        },
        clearSelection() {
            this.$refs.elTable.clearSelection()
            this.$forceUpdate()
        },
        // toggleRowSelection(row, selected) {
        //     this.$refs.elTable.toggleRowSelection(row, selected)
        //     this.$forceUpdate()
        // },
        // clearSelection() {
        //     this.$refs.elTable.clearSelection()
        //     this.$forceUpdate()
        // },
        handleCurrentChange(page) {
            this.$emit('handleCurrentChange', page)
        },
laboratory/src/router/index.js
@@ -23,8 +23,7 @@
    }
 */
const routes = [
    {
const routes = [{
        path: "/",
        redirect: "/login",
    },
@@ -43,8 +42,7 @@
            title: "系统管理",
        },
        component: Layouts,
        children: [
            {
        children: [{
                path: "user",
                name: "User",
                meta: {
@@ -102,8 +100,7 @@
            title: "项目组管理",
        },
        component: Layouts,
        children: [
            {
        children: [{
                path: "list",
                name: "ProjectList",
                meta: {
@@ -147,8 +144,7 @@
        meta: {
            title: "实验室数据管理",
        },
        children: [
            {
        children: [{
                path: "approvalPlan",
                meta: {
                    title: "项目课题方案审批",
@@ -232,8 +228,7 @@
                    // keepAlive: true,
                },
                component: Parent,
                children: [
                    {
                children: [{
                        path: "manage",
                        meta: {
                            title: "样品管理",
@@ -376,8 +371,7 @@
        meta: {
            title: "专业报告库审批",
        },
        children: [
            {
        children: [{
                path: "feasibilityStudy",
                meta: {
                    title: "可研报告库",
@@ -460,7 +454,7 @@
                component: () => import("../views/reportLibrary/processDevelopment/add.vue"),
            },
            {
                path: "verificationRelease",
@@ -471,12 +465,48 @@
                component: () => import("../views/reportLibrary/verificationRelease/index.vue"),
            },
            {
                path: "addVerificationRelease",
                meta: {
                    title: "新增验证与发布",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/reportLibrary/verificationRelease/add.vue"),
            },
            {
                path: "editVerificationRelease",
                meta: {
                    title: "新增验证与发布",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/reportLibrary/verificationRelease/add.vue"),
            },
            {
                path: "projectProposalLibrary",
                meta: {
                    title: "立项报告库",
                    keepAlive: true,
                },
                component: () => import("../views/reportLibrary/projectProposalLibrary/index.vue"),
            },
            {
                path: "addProjectProposalLibrary",
                meta: {
                    title: "新增立项报告",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/reportLibrary/projectProposalLibrary/add.vue"),
            },
            {
                path: "editProjectProposalLibrary",
                meta: {
                    title: "编辑立项报告",
                    hide: true,
                    keepAlive: true,
                },
                component: () => import("../views/reportLibrary/projectProposalLibrary/add.vue"),
            },
        ],
    },
@@ -486,8 +516,7 @@
        meta: {
            title: "化验师QA专题报告",
        },
        children: [
            {
        children: [{
                path: "projectTesting",
                meta: {
                    title: "项目检测项、检验包列表",
@@ -572,8 +601,7 @@
        meta: {
            title: "工作交付评定",
        },
        children: [
            {
        children: [{
                path: "projectTeamIntegral",
                meta: {
                    title: "项目组总积分",
@@ -741,7 +769,7 @@
    // 排除登录页的校验
    if (to.path === "/login") {
        if (sessionStorage.getItem('token')) {
            next('/system');  // 已登录状态访问登录页时重定向到系统首页
            next('/system'); // 已登录状态访问登录页时重定向到系统首页
            return;
        }
        next();
@@ -751,7 +779,7 @@
    // 登录状态校验
    const isAuthenticated = sessionStorage.getItem('token');
    if (!isAuthenticated) {
        next('/login');  // 未登录用户重定向到登录页
        next('/login'); // 未登录用户重定向到登录页
        return;
    }
@@ -795,4 +823,4 @@
    next()
});
export default router;
export default router;
laboratory/src/views/dataManagement/SampleDeliveryRecord/components/receiveConfirmDialog.vue
File was deleted
laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue
@@ -6,26 +6,21 @@
    </div>
    <Table :data="schedulingData" :total="schedulingTotal" :height="null">
      <template>
        <el-table-column
          prop="planCode"
          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="notifyTime" label="通知时间"></el-table-column>
        <el-table-column
          prop="startTime"
          label="实验开始时间"
        ></el-table-column>
        <el-table-column prop="endTime" label="实验结束时间"></el-table-column>
        <el-table-column prop="participants" label="参加人员"></el-table-column>
        <el-table-column prop="status" label="状态"></el-table-column>
        <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>
      </template>
    </Table>
@@ -34,246 +29,88 @@
      <div class="header-title-left" style="margin-top: 38px">
        <img src="@/assets/public/headercard.png" />
        <span>送样-收样记录</span>
        <el-button
          type="primary"
          class="el-icon-plus"
          @click="showAdditives = !showAdditives"
        >
          {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }}
        <el-button type="primary" class="el-icon-plus" @click="showPendingColumns = !showPendingColumns">
          {{ showPendingColumns ? "收起待收样详情" : "展开待收样详情" }}
        </el-button>
        <el-button type="primary" class="el-icon-plus" @click="showReceivedColumns = !showReceivedColumns">
          {{ showReceivedColumns ? "收起已收样详情" : "展开已收样详情" }}
        </el-button>
      </div>
      <div class="sample-code">
        取样单编号:{{ form.sampleCode || "DD-25010BS01" }}
      </div>
      <div class="sample-code">待收样列表</div>
      <div class="sample-table">
        <Table
          :data="sampleList"
          :total="sampleTotal"
          :height="null"
          style="width: 100%"
        >
      <!-- 待收样列表 -->
      <div class="pending-samples">
        <div class="sub-title">待收样列表</div>
        <Table ref="pendingTable"
          :data="pendingSamples"
          :total="pendingSamplesTotal"
          :height="null">
          <template>
            <el-table-column
              prop="index"
              label="序号"
              width="80"
            ></el-table-column>
            <el-table-column
              prop="processTime"
              label="工艺时间间/h"
              width="120"
            ></el-table-column>
            <el-table-column
              prop="sampleName"
              label="取样名称"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="sampleCode"
              label="取样样品编号"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="temperature"
              label="温度"
              width="100"
            ></el-table-column>
            <el-table-column prop="ph" label="PH" width="100"></el-table-column>
            <el-table-column
              prop="waterAmount"
              label="加水量"
              width="100"
            ></el-table-column>
            <template v-if="showAdditives">
              <el-table-column
                prop="additive1"
                label="加辅1"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive2"
                label="加辅2"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive3"
                label="加辅3"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive4"
                label="加辅4"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive5"
                label="加辅5"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive6"
                label="加辅6"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive7"
                label="加辅7"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive8"
                label="加辅8"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive9"
                label="加辅9"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive10"
                label="加辅10"
                min-width="150"
              ></el-table-column>
            <el-table-column type="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="samplingName" label="取样名称" width="200"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号" width="200"></el-table-column>
            <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
            <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
            <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
            <template v-if="showPendingColumns">
              <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
            </template>
            <el-table-column
              prop="sampleAmount"
              label="取样量"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="sampleTime"
              label="取样时间"
              min-width="150"
            ></el-table-column>
            <el-table-column prop="photo" label="拍照" width="100">
            <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
            <el-table-column prop="receiptsTime" label="收样时间" width="150"></el-table-column>
            <el-table-column prop="receiptsPersonName" label="收样人" width="150"></el-table-column>
            <el-table-column label="状态" prop="status" width="100" fixed="right">
              <template slot-scope="scope">
                <img
                  v-if="scope.row.photo"
                  :src="scope.row.photo"
                  class="sample-photo"
                />
                <span>{{ scope.row.status == '2' ? '待接收' : '已接收' }}</span>
              </template>
            </el-table-column>
            <el-table-column
              prop="operator"
              label="操作人"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="status"
              label="状态"
              width="100"
            ></el-table-column>
          </template>
        </Table>
      </div>
      <div class="received-samples">
        <div style="display: flex; align-items: center">
          <div class="sample-code">已收样列表</div>
          <el-button
            type="primary"
            class="el-icon-plus"
            style="margin-left: 16px"
            @click="showReceivedColumns = !showReceivedColumns"
          >
            {{ showReceivedColumns ? "收起辅料详情" : "展开辅料详情" }}
          </el-button>
        </div>
        <Table
          :data="receivedSamples"
          :total="receivedSamplesTotal"
          :height="null"
          style="width: 100%"
        >
      <!-- 已收样列表 -->
      <div class="received-samples">
        <div class="sub-title">已收样列表</div>
        <Table ref="receivedTable" :data="receivedSamples" :total="receivedSamplesTotal" :height="null">
          <template>
            <el-table-column
              prop="index"
              label="序号"
              width="80"
            ></el-table-column>
            <el-table-column
              prop="sampleName"
              label="取样名称"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="sampleCode"
              label="取样样品编号"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="temperature"
              label="温度"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="waterAmount"
              label="加水量"
              width="100"
            ></el-table-column>
            <el-table-column prop="ph" label="PH" width="100"></el-table-column>
            <el-table-column type="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
            <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
            <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
            <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
            <template v-if="showReceivedColumns">
              <el-table-column
                prop="additive1"
                label="加辅1"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive2"
                label="加辅2"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive3"
                label="加辅3"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive4"
                label="加辅4"
                min-width="150"
              ></el-table-column>
              <el-table-column
                prop="additive5"
                label="加辅5"
                min-width="150"
              ></el-table-column>
              <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
            </template>
            <el-table-column
              prop="sampleAmount"
              label="取样量"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="sendTime"
              label="送样时间"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="sender"
              label="送样人"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="receiveTime"
              label="收样时间"
              min-width="150"
            ></el-table-column>
            <el-table-column
              prop="receiver"
              label="收样人"
              width="100"
            ></el-table-column>
            <el-table-column
              prop="status"
              label="状态"
              width="100"
              fixed="right"
            ></el-table-column>
            <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
            <el-table-column prop="sendTime" label="送样时间" width="150"></el-table-column>
            <el-table-column prop="sendPersonName" label="送样人" width="150"></el-table-column>
            <el-table-column prop="receiptsTime" label="收样时间" width="150"></el-table-column>
            <el-table-column prop="receiptsPersonName" label="收样人" width="150"></el-table-column>
            <el-table-column label="状态" prop="status" width="100" fixed="right">
              <template slot-scope="scope">
                <span>{{ scope.row.status == '3' ? '已接收' : '待接收' }}</span>
              </template>
            </el-table-column>
          </template>
        </Table>
      </div>
@@ -282,104 +119,90 @@
</template>
<script>
import { getDetail } from "../sampleManage/service";
export default {
  name: "SampleSubmission",
  name: "SampleDeliveryRecord",
  data() {
    return {
      showAdditives: true,
      showReceivedColumns: true,
      schedulingData: [
        {
          planCode: "DD-EX001",
          experimentCode: "DD-EX001",
          experimentName: "名称名称名称",
          notifyTime: "2025-1-2 14:50:19",
          startTime: "2025-02-27",
          endTime: "2025-06-06",
          participants: "张弘, 李天浩, 陈三, 李四",
          status: "已确认",
        },
      ],
      schedulingTotal: 1,
      showPendingColumns: false,
      showReceivedColumns: false,
      schedulingData: [],
      schedulingTotal: 0,
      form: {
        sampleCode: "DD-25010BS01",
        sampleCode: "",
        id: "",
      },
      sampleList: [
        {
          index: 1,
          processTime: "2",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "34",
          ph: "34",
          waterAmount: "34",
          additive1: "10g",
          additive2: "5g",
          additive3: "3g",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "34",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo1.jpg",
          operator: "张三",
          status: "待发送",
        },
        {
          index: 2,
          processTime: "4",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "23",
          ph: "23",
          waterAmount: "23",
          additive1: "8g",
          additive2: "4g",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "23",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo2.jpg",
          operator: "李四",
          status: "待接收",
        },
        {
          index: 3,
          processTime: "8",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "23",
          ph: "23",
          waterAmount: "23",
          additive1: "",
          additive2: "",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "23",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo3.jpg",
          operator: "王五",
          status: "已接收",
        },
      ],
      sampleTotal: 3,
      pendingSamples: [],
      pendingSamplesTotal: 0,
      receivedSamples: [],
      receivedSamplesTotal: 0,
      statusTypeMap: {
        "-1": "info",
        "1": "warning",
        "2": "success",
        "3": "info"
      },
      statusTextMap: {
        "-1": "草稿箱",
        "1": "待确认",
        "2": "已确认",
        "3": "已封存"
      },
    };
  },
  created() {
    const { id } = this.$route.query;
    if (id) {
      this.form.id = id;
      this.getDetailData(id);
    }
  },
  methods: {
    async getDetailData(id) {
      try {
        const res = await getDetail({ id });
        if (res) {
          const detail = res;
          this.form = {
            ...this.form,
            ...detail,
            sampleCode: detail.samplingCode,
          };
          if (detail.experimentDispatch) {
            this.schedulingData = [detail.experimentDispatch];
          }
          if (detail.samplingRecordOperations && detail.samplingRecordOperations.length > 0) {
            this.pendingSamples = detail.samplingRecordOperations
              .filter(item => String(item.status) === '2')
              .map(item => ({
                ...item,
                status: String(item.status)
              }));
            this.pendingSamplesTotal = this.pendingSamples.length;
            this.receivedSamples = detail.samplingRecordOperations
              .filter(item => String(item.status) === '3')
              .map(item => ({
                ...item,
                status: String(item.status)
              }));
            this.receivedSamplesTotal = this.receivedSamples.length;
          }
        }
      } catch (error) {
        console.error('获取详情失败:', error);
        this.$message.error('获取详情失败,请重试');
      }
    },
    getStatusType(status) {
      return this.statusTypeMap[status] || 'info';
    },
    getStatusText(status) {
      return this.statusTextMap[status] || '未知状态';
    },
  },
};
</script>
@@ -426,15 +249,17 @@
    margin: 20px 0;
  }
  .table-header {
    margin-bottom: 16px;
    text-align: left;
  .sub-title {
    font-size: 16px;
    font-weight: 500;
    color: #333;
    margin: 20px 0;
    display: inline-block;
  }
  .sample-photo {
    width: 60px;
    height: 60px;
    object-fit: cover;
  .pending-samples,
  .received-samples {
    margin-top: 20px;
  }
}
</style>
laboratory/src/views/dataManagement/SampleDeliveryRecord/list.vue
@@ -1,65 +1,56 @@
<template>
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total">
    <TableCustom :queryForm="form" :height="null" :tableData="tableData" :total="total"
      @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange">
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="项目课题方案名称:">
            <el-input v-model="form.planName" placeholder="请输入"></el-input>
          <el-form-item label="所属项目课题方案:">
            <el-input v-model="form.projectName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="实验编号:">
            <el-input v-model="form.planCode" 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
              v-model="form.createTime"
              v-model="form.timeRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="yyyy-MM-dd"
            ></el-date-picker>
          </el-form-item>
          <el-form-item label="实验名称:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
              @change="handleTimeChange">
            </el-date-picker>
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="primary" @click="handleSearch" style="margin-left: 10px;">查询</el-button>
          </el-form-item>
        </el-form>
      </template>
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center">
            <div class="title">待接收样品列表</div>
            <div class="title active">待接收样品列表</div>
          </div>
        </div>
      </template>
      <template #table>
        <el-table-column
          prop="planName"
          label="所属项目课题方案"
        ></el-table-column>
        <el-table-column prop="experimentNo" label="实验编号"></el-table-column>
        <el-table-column
          prop="experimentName"
          label="实验名称"
        ></el-table-column>
        <el-table-column prop="sampleNo" label="取样单编号"></el-table-column>
        <el-table-column prop="creator" label="创建人"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column
          prop="sampleStatus"
          label="样品总数/待接收/已接收"
        ></el-table-column>
        <el-table-column label="操作" width="100">
        <el-table-column v-for="(column, index) in columns" :key="index" :prop="column.prop"
          :label="column.label"></el-table-column>
        <el-table-column label="样品总数/待送达/待接收/已接收">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row)"
              >详情</el-button
            >
            {{ getSampleStatus(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
          </template>
        </el-table-column>
      </template>
@@ -68,54 +59,33 @@
</template>
<script>
import { getList } from './service'
export default {
  name: "ProjectList",
  data() {
    return {
      form: {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        createBy: "",
        startTime: "",
        endTime: "",
        timeRange: [],
        pageNum: 1,
        pageSize: 10
      },
      tableData: [],
      total: 0,
      // 模拟数据
      mockListData: [
        {
          planCode: "PLAN-2024-001",
          planName: "2024年度实验室设备升级方案",
          stage: "规划阶段",
          creator: "张三",
          createTime: "2024-03-15",
          status: "pending",
          approver: "李四",
          approveTime: "2024-03-16",
        },
        {
          planCode: "PLAN-2024-002",
          planName: "实验室安全管理制度更新方案",
          stage: "实施阶段",
          creator: "王五",
          createTime: "2024-03-14",
          status: "approved",
          approver: "赵六",
          approveTime: "2024-03-15",
        },
        {
          planCode: "PLAN-2024-003",
          planName: "实验室人员培训计划",
          stage: "准备阶段",
          creator: "孙七",
          createTime: "2024-03-13",
          status: "rejected",
          approver: "周八",
          approveTime: "2024-03-14",
        },
      ],
      columns: [
        { prop: 'projectName', label: '所属项目课题方案' },
        { prop: 'experimentCode', label: '实验编号' },
        { prop: 'experimentName', label: '实验名称' },
        { prop: 'samplingCode', label: '取样单编号' },
        { prop: 'createBy', label: '创建人' },
        { prop: 'createTime', label: '创建时间' }
      ]
    };
  },
  created() {
@@ -124,33 +94,91 @@
  methods: {
    resetForm() {
      this.form = {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        createBy: "",
        startTime: "",
        endTime: "",
        timeRange: [],
        pageNum: 1,
        pageSize: 10
      };
      this.handleSearch();
    },
    handleSearch() {
      // 实现查询逻辑
      console.log("查询条件:", this.form);
      this.getTableData();
    handleTimeChange(val) {
      if (val) {
        this.form.startTime = val[0];
        this.form.endTime = val[1];
      } else {
        this.form.startTime = "";
        this.form.endTime = "";
      }
    },
    handleDetail(row) {
    async handleSearch() {
      const params = {
        experimentCode: this.form.experimentCode,
        experimentName: this.form.experimentName,
        projectName: this.form.projectName,
        createBy: this.form.createBy,
        startTime: this.form.startTime,
        endTime: this.form.endTime,
        pageNum: this.form.pageNum,
        pageSize: this.form.pageSize
      };
      try {
        const res = await getList(params)
        this.tableData = res.data.records || [];
        this.total = res.data.total || 0;
      } catch (error) {
        console.error("查询失败:", error);
      }
    },
    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] || '未知';
    },
    handleDetail(id) {
      this.$router.push({
        path: "/dataManagement/delivery",
        query: {
          id: row.id,
          type: "view",
        },
          id: id,
          type: 'detail'
        }
      });
    },
    getTableData() {
      // 获取列表数据
      this.tableData = this.mockListData;
      this.total = this.mockListData.length;
      this.handleSearch();
    },
    handlePageChange(pageNum) {
      this.form.pageNum = pageNum;
      this.getTableData();
    },
    handleSizeChange(pageSize) {
      this.form.pageSize = pageSize;
      this.getTableData();
    },
    getSampleStatus(row) {
      const send = row.sendCount || 0;
      const receive = row.receiveCount || 0;
      const received = row.receivedCount || 0;
      const total = send + receive + received;
      return `${total} / ${send} / ${receive} / ${received}`;
    }
  },
};
</script>
laboratory/src/views/dataManagement/SampleDeliveryRecord/service.js
New file
@@ -0,0 +1,48 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-sampling-record/pageList', { ...data })
}
// 详情
export const getDetail = (data) => {
  return axios.get('/open/t-sampling-record/getDetailById', { params:data })
}
//添加
export const add = (data) => {
  return axios.post('/api/t-sampling-record/add', { ...data })
}
//修改
export const update = (data) => {
  return axios.post('/api/t-sampling-record/update', { ...data })
}
//删除
export const deleteById = (data) => {
  return axios.delete('/open/t-sampling-record/deleteById', { params:data })
}
//批量删除
export const deleteByIds = (data) => {
  return axios.delete('/open/t-sampling-record/deleteByIds', { params:data })
}
// 实验员提交记录
export const commitRecord = (data) => {
  return axios.post('/api/t-sampling-record/commitRecord', { ...data })
}
// 修改取样操作记录
export const updateRecordOperation = (data) => {
  return axios.post('/api/t-sampling-record/updateRecordOperation', { params:data })
}
// 批量收样
export const batchCollectSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchCollectSamples', { params:data })
}
// 批量送样
export const batchSendSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchSendSamples', { ...data })
}
// 获取实验调度列表
export const getDispatchList = (data) => {
  return axios.post('/api/t-experiment-dispatch/pageList', { params:data })
}
laboratory/src/views/dataManagement/originalRecordTest/components/addDialog.vue
@@ -1,6 +1,6 @@
<template>
  <el-dialog
    title="新增检测数据"
    :title="isEdit ? '编辑检测数据' : '新增检测数据'"
    :visible.sync="dialogVisible"
    width="60%"
    :close-on-click-modal="false"
@@ -17,17 +17,17 @@
          >
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="检测样编号" prop="sampleCode">
                <el-form-item label="数据编号" prop="dataCode">
                  <el-input
                    v-model="form.sampleCode"
                    placeholder="请输入检测样编号"
                    v-model="form.dataCode"
                    placeholder="请输入数据编号"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="检测数据" prop="testData">
                <el-form-item label="检测数据" prop="dataTitle">
                  <el-input
                    v-model="form.testData"
                    v-model="form.dataTitle"
                    placeholder="请输入检测数据"
                  />
                </el-form-item>
@@ -36,10 +36,10 @@
            <el-row :gutter="20">
              <el-col :span="24">
                <el-form-item label="检测类型" prop="testTypes">
                  <el-checkbox-group v-model="form.testTypes">
                    <el-checkbox label="photo">拍照</el-checkbox>
                    <el-checkbox label="spectrum">图谱</el-checkbox>
                <el-form-item label="检测类型" prop="dataType">
                  <el-checkbox-group v-model="form.dataType">
                    <el-checkbox label="1">拍照</el-checkbox>
                    <el-checkbox label="2">图谱</el-checkbox>
                  </el-checkbox-group>
                </el-form-item>
              </el-col>
@@ -62,7 +62,6 @@
                    :on-change="handlePhotoChange"
                  >
                    <i class="el-icon-plus"></i>
                    <!-- <div class="el-upload__tip" slot="tip">支持 jpg、png 格式文件</div> -->
                  </el-upload>
                </el-form-item>
              </el-col>
@@ -109,26 +108,32 @@
    visible: {
      type: Boolean,
      default: false
    },
    isEdit: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      isIPad: /iPad/i.test(navigator.userAgent),
      form: {
        sampleCode: "",
        testData: "",
        testTypes: ["photo"], // 默认选中拍照
        dataCode: "",
        dataTitle: "",
        dataType: ["1"],
        dataFiles: "",
        dataPictures: "",
        photos: [],
        spectrums: []
      },
      rules: {
        sampleCode: [
          { required: true, message: "请输入检测样编号", trigger: "blur" }
        dataCode: [
          { required: true, message: "请输入数据编号", trigger: "blur" }
        ],
        testData: [
        dataTitle: [
          { required: true, message: "请输入检测数据", trigger: "blur" }
        ],
        testTypes: [
        dataType: [
          { 
            type: 'array',
            required: true, 
@@ -142,7 +147,7 @@
            message: "请上传检测照片", 
            trigger: "change",
            validator: (rule, value, callback) => {
              if (this.form.testTypes.includes('photo') && (!this.photoList || !this.photoList.length)) {
              if (this.form.dataType.includes('1') && (!this.photoList || !this.photoList.length)) {
                callback(new Error('请上传检测照片'));
              } else {
                callback();
@@ -156,7 +161,7 @@
            message: "请上传检测图谱", 
            trigger: "change",
            validator: (rule, value, callback) => {
              if (this.form.testTypes.includes('spectrum') && (!this.spectrumList || !this.spectrumList.length)) {
              if (this.form.dataType.includes('2') && (!this.spectrumList || !this.spectrumList.length)) {
                callback(new Error('请上传检测图谱'));
              } else {
                callback();
@@ -179,37 +184,52 @@
      }
    },
    showPhotoUpload() {
      return this.form.testTypes.includes('photo');
      return this.form.dataType.includes('1');
    },
    showSpectrumUpload() {
      return this.form.testTypes.includes('spectrum');
      return this.form.dataType.includes('2');
    }
  },
  methods: {
    setFormData(data) {
      console.log('data',data)
      // 设置基础表单数据
      this.form.sampleCode = data.sampleCode;
      this.form.testData = data.testData;
      this.form.testTypes = data.testTypes;
      this.form.dataCode = data.dataCode;
      this.form.dataTitle = data.dataTitle;
      // 处理 dataType,确保它是数组格式
      this.form.dataType = Array.isArray(data.dataType) ? data.dataType : (data.dataType ? data.dataType.split(',') : []);
      // 设置照片列表
      if (data.photos && data.photos.length) {
        this.photoList = data.photos.map(photo => ({
          name: photo.name,
          url: photo.url,
          status: 'success'
        }));
      if (data.dataPictures) {
        try {
          const pictures = typeof data.dataPictures === 'string' ? JSON.parse(data.dataPictures) : data.dataPictures;
          this.photoList = pictures.map(photo => ({
            name: photo.name,
            url: photo.url,
            status: 'success'
          }));
        } catch (e) {
          console.error('解析照片数据失败:', e);
          this.photoList = [];
        }
      } else {
        this.photoList = [];
      }
      // 设置图谱列表
      if (data.spectrums && data.spectrums.length) {
        this.spectrumList = data.spectrums.map(spectrum => ({
          name: spectrum.name,
          url: spectrum.url,
          status: 'success'
        }));
      if (data.dataFiles) {
        try {
          const files = typeof data.dataFiles === 'string' ? JSON.parse(data.dataFiles) : data.dataFiles;
          this.spectrumList = files.map(file => ({
            name: file.name,
            url: file.url,
            status: 'success'
          }));
        } catch (e) {
          console.error('解析图谱数据失败:', e);
          this.spectrumList = [];
        }
      } else {
        this.spectrumList = [];
      }
@@ -225,9 +245,11 @@
      this.photoList = [];
      this.spectrumList = [];
      this.form = {
        sampleCode: "",
        testData: "",
        testTypes: ["photo"],
        dataCode: "",
        dataTitle: "",
        dataType: ["1"],
        dataFiles: "",
        dataPictures: "",
        photos: [],
        spectrums: []
      };
@@ -237,19 +259,33 @@
        if (valid) {
          const submitData = {
            ...this.form,
            photos: this.photoList,
            spectrums: this.spectrumList
            // 确保 dataType 在提交时转换为字符串
            dataType: Array.isArray(this.form.dataType) ? this.form.dataType.join(',') : this.form.dataType,
            dataFiles: JSON.stringify(this.spectrumList),
            dataPictures: JSON.stringify(this.photoList)
          };
          this.$emit("success", submitData);
        }
      });
    },
    handlePhotoChange(file, fileList) {
      this.photoList = fileList;
      // 模拟上传成功
      const mockFile = {
        name: file.name || '测试图片.jpg',
        url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
        status: 'success'
      };
      this.photoList = [...this.photoList, mockFile];
      this.$refs.form.validateField('photos');
    },
    handleSpectrumChange(file, fileList) {
      this.spectrumList = fileList;
      // 模拟上传成功
      const mockFile = {
        name: file.name || '测试图谱.pdf',
        url: 'https://example.com/test.pdf',
        status: 'success'
      };
      this.spectrumList = [...this.spectrumList, mockFile];
      this.$refs.form.validateField('spectrums');
    },
    handleSpectrumRemove(file) {
@@ -257,16 +293,34 @@
    },
    // iPad 相关方法
    handleIPadPhoto() {
      // TODO: 调用 iPad 拍照功能
      console.log('调用 iPad 拍照功能');
      // 模拟 iPad 拍照功能
      const mockFile = {
        name: 'iPad拍照.jpg',
        url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
        status: 'success'
      };
      this.photoList = [...this.photoList, mockFile];
      this.$refs.form.validateField('photos');
    },
    handleIPadUpload() {
      // TODO: 调用 iPad 上传功能
      console.log('调用 iPad 上传功能');
      // 模拟 iPad 上传功能
      const mockFile = {
        name: 'iPad上传图片.jpg',
        url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
        status: 'success'
      };
      this.photoList = [...this.photoList, mockFile];
      this.$refs.form.validateField('photos');
    },
    handleIPadSpectrum() {
      // TODO: 调用 iPad 选择图谱功能
      console.log('调用 iPad 选择图谱功能');
      // 模拟 iPad 选择图谱功能
      const mockFile = {
        name: 'iPad图谱.pdf',
        url: 'https://example.com/test.pdf',
        status: 'success'
      };
      this.spectrumList = [...this.spectrumList, mockFile];
      this.$refs.form.validateField('spectrums');
    }
  }
};
laboratory/src/views/dataManagement/originalRecordTest/detail.vue
@@ -8,9 +8,10 @@
      label-position="top"
    >
      <div style="padding-left: 25px">
        <el-form-item prop="recordNo" label="原始检验记录编号">
          <el-input v-model="form.recordNo" placeholder="请输入" />
        <el-form-item prop="originalCode" label="原始检验记录编号">
          <el-input v-model="form.originalCode" placeholder="请输入" disabled />
        </el-form-item>
      </div>
      <div class="header-title" style="margin-bottom: 38px">
@@ -20,57 +21,93 @@
        </div>
      </div>
      <div style="padding-left: 25px">
        <el-form-item prop="testItemName" label="检测项名字">
          <el-input v-model="form.testItemName" placeholder="请输入" />
        <el-form-item prop="termName" label="检测项名字">
          <el-input v-model="form.termName" placeholder="请输入" disabled />
        </el-form-item>
        <el-form-item prop="testItemNo" label="检测项编号">
          <el-input v-model="form.testItemNo" placeholder="请输入" />
        <el-form-item prop="termCode" label="检测项编号">
          <el-input v-model="form.termCode" placeholder="请输入" disabled />
        </el-form-item>
        <el-form-item prop="testMethodName" label="检测方法名字">
          <el-input v-model="form.testMethodName" placeholder="请输入" />
        <el-form-item prop="termMethod" label="检测方法名字">
          <el-input v-model="form.termMethod" placeholder="请输入" disabled />
        </el-form-item>
        <el-form-item prop="testMethodNo" label="检测方法编号">
          <el-input v-model="form.testMethodNo" placeholder="请输入" />
        <el-form-item prop="termMethodCode" label="检测方法编号">
          <el-input v-model="form.termMethodCode" placeholder="请输入" disabled />
        </el-form-item>
      </div>
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>一 、检测标准</span>
          <div>一 、检测标准</div>
        </div>
      </div>
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>二 、检测仪器</span>
        </div>
      </div>
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>三 、检测试剂</span>
        </div>
      </div>
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>四 、检测步骤</span>
        </div>
      </div>
      <AiEditor
        ref="standardEditor"
        :value="editorContents.termStandard"
        height="200px"
        style="margin: 20px 0;"
        placeholder="请输入检测标准..."
        :readOnly="isDetail"
      />
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>五 、检测数据及参照</span>
          <div>二 、检测仪器</div>
        </div>
        <el-button type="primary" class="el-icon-plus" @click="handleAddTask">添加检测数据</el-button>
      </div>
      <AiEditor
        ref="instrumentEditor"
        :value="editorContents.termInstrument"
        height="200px"
        style="margin: 20px 0;"
        placeholder="请输入检测仪器..."
        :readOnly="isDetail"
      />
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <div>三 、检测试剂</div>
        </div>
      </div>
      <AiEditor
        ref="reagentEditor"
        :value="editorContents.termReagent"
        height="200px"
        style="margin: 20px 0;"
        placeholder="请输入检测试剂..."
        :readOnly="isDetail"
      />
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <div>四 、检测步骤</div>
        </div>
      </div>
      <AiEditor
        ref="stepsEditor"
        :value="editorContents.termStep"
        height="200px"
        style="margin: 20px 0;"
        placeholder="请输入检测步骤..."
        :readOnly="isDetail"
      />
      <div class="header-title" style="margin-bottom: 38px">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <div>五 、检测数据及参照</div>
        </div>
        <el-button v-if="!isDetail" type="primary" class="el-icon-plus" @click="handleAddTask">添加检测数据</el-button>
      </div>
      <Table :data="taskTableData" :total="0" :height="null" class="rwuTable">
        <el-table-column type="index" label="序号" width="80"></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="createTime" label="检测时间" width="180"></el-table-column>
        <el-table-column label="检测图片" width="200">
          <template slot-scope="scope">
            <div class="image-preview" v-if="scope.row.photos && scope.row.photos.length">
@@ -107,8 +144,8 @@
            <span v-else>无图谱</span>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="添加时间" width="180"></el-table-column>
        <el-table-column label="操作" width="150">
        <el-table-column v-if="!isDetail" label="操作" width="150">
          <template slot-scope="scope">
            <el-button type="text" @click="handleEditTask(scope.row)">编辑</el-button>
            <el-button type="text" @click="handleDeleteTask(scope.row)">删除</el-button>
@@ -119,29 +156,38 @@
      <div class="header-title">
        <div class="header-title-left">
          <img src="@/assets/public/headercard.png" />
          <span>六 、检测结果预算</span>
          <div>六 、检测结果运算</div>
        </div>
      </div>
      <AiEditor
        ref="resultCalculationEditor"
        :value="editorContents.termResult"
        height="200px"
        style="margin: 20px 0;"
        placeholder="请输入检测结果运算..."
        :readOnly="isDetail"
      />
      <Table :data="taskTableData" :total="0" :height="null" class="rwuTable">
        <el-table-column type="index" label="序号" width="80"></el-table-column>
        <el-table-column prop="sampleCode" label="检测样编号"></el-table-column>
        <el-table-column prop="testData" label="检测数据"></el-table-column>
        <el-table-column label="检测结果" >
          <template slot-scope="scope">
            <el-input v-model="scope.row.testResult" placeholder="请输入检测结果"></el-input>
            <el-input v-model="scope.row.resultText" placeholder="请输入检测结果" :disabled="isDetail"></el-input>
          </template>
        </el-table-column>
      </Table>
      <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="!isDetail">
        <el-button type="primary" class="save-btn" @click="handleSubmit(false)">填写完毕</el-button>
        <el-button @click="handleSaveDraft">存草稿</el-button>
      </div>
    </el-form>
    <!-- 添加检测数据弹窗 -->
    <add-dialog 
      ref="addDialog"
      :visible.sync="dialogVisible" 
      :is-edit="isEdit"
      @success="handleTaskSubmit" 
    />
  </Card>
@@ -149,36 +195,100 @@
  
<script>
import AddDialog from './components/addDialog.vue'
import AiEditor from '@/components/AiEditor'
import moment from 'moment'
import { getDetail, update } from './service'
export default {
  name: "AddProject",
  components: {
    AddDialog
    AddDialog,
    AiEditor
  },
  data() {
    return {
      dialogVisible: false,
      isEdit: false,
      currentEditIndex: -1,
      isDetail: this.$route.query.type === 'detail',
      form: {
        recordNo: '',
        testItemName: '',
        testItemNo: '',
        testMethodName: '',
        testMethodNo: ''
        id: '',
        originalCode: '',
        termName: '',
        termCode: '',
        termMethod: '',
        termMethodCode: '',
        status: 1,
        termStandard: '',
        termInstrument: '',
        termReagent: '',
        termStep: '',
        termResult: ''
      },
      editorContents: {
        termStandard: '',
        termInstrument: '',
        termReagent: '',
        termStep: '',
        termResult: ''
      },
      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" }]
        termName: [{ required: true, message: "请输入检测项名字", trigger: "blur" }],
        termCode: [{ required: true, message: "请输入检测项编号", trigger: "blur" }],
        experimentName: [{ required: true, message: "请输入检测方法名字", trigger: "blur" }],
        experimentCode: [{ required: true, message: "请输入检测方法编号", trigger: "blur" }]
      },
      taskTableData: []
    };
  },
  methods: {
    // 获取详情
    getDetail() {
      const id = this.$route.query.id;
      if (id) {
        getDetail({ id }).then(res => {
          if (res) {
            const data = res;
            // 设置表单数据
            this.form = {
              ...data,
              termCode: data.testMethodConfirmSheetTerm.termCode || '',
              termName: data.testMethodConfirmSheetTerm.termName || '',
              termMethod: data.testMethodConfirmSheetTerm.termMethod || '',
              termMethodCode: data.testMethodConfirmSheetTerm.termMethodCode || '',
              termStandard: data.termStandard || '',
              termInstrument: data.termInstrument || '',
              termReagent: data.termReagent || '',
              termStep: data.termStep || '',
              termResult: data.termResult || ''
            };
            // 设置编辑器内容
            this.editorContents = {
              termStandard: data.termStandard || '',
              termInstrument: data.termInstrument || '',
              termReagent: data.termReagent || '',
              termStep: data.termStep || '',
              termResult: data.termResult || ''
            };
            // 设置检测数据表格
            if (data.testMethodConfirmSheetOriginalDataList && data.testMethodConfirmSheetOriginalDataList.length > 0) {
              this.taskTableData = data.testMethodConfirmSheetOriginalDataList.map(item => ({
                sampleCode: item.dataCode || '',
                testData: item.dataTitle || '',
                resultText: item.resultText || '',
                photos: item.dataPictures ? item.dataPictures.split(',').map(url => ({ url })) : [],
                spectrums: item.dataFiles ? JSON.parse(item.dataFiles) : [],
                createTime: item.createTime || moment().format('YYYY-MM-DD HH:mm:ss')
              }));
            }
          }
        }).catch(err => {
          console.error('获取详情失败:', err);
          this.$message.error('获取详情失败');
        });
      }
    },
    handleAddTask() {
      this.isEdit = false;
      this.currentEditIndex = -1;
@@ -189,28 +299,22 @@
      this.currentEditIndex = this.taskTableData.findIndex(item => item === row);
      
      const editData = {
        sampleCode: row.sampleCode,
        testData: row.testData,
        testTypes: [],
        dataCode: row.sampleCode,
        dataTitle: row.testData,
        dataType: [],
        dataFiles: '',
        dataPictures: '',
        photos: [],
        spectrums: []
      };
      if (row.photos && row.photos.length > 0) {
        editData.testTypes.push('photo');
        editData.photos = row.photos.map(photo => ({
          name: photo.name,
          url: photo.url,
          raw: null
        }));
        editData.dataType.push('1');
        editData.dataPictures = row.photos;
      }
      if (row.spectrums && row.spectrums.length > 0) {
        editData.testTypes.push('spectrum');
        editData.spectrums = row.spectrums.map(spectrum => ({
          name: spectrum.name,
          url: spectrum.url,
          raw: null
        }));
        editData.dataType.push('2');
        editData.dataFiles = row.spectrums;
      }
      this.$nextTick(() => {
@@ -250,42 +354,16 @@
        .catch(() => {});
    },
    handleTaskSubmit(formData) {
      const photos = formData.photos.map(file => ({
        name: file.name,
        url: file.url || URL.createObjectURL(file.raw)
      }));
      const spectrums = formData.spectrums.map(file => ({
        name: file.name,
        url: file.url || URL.createObjectURL(file.raw)
      }));
      const newData = {
        sampleCode: formData.sampleCode,
        testData: formData.testData,
        testResult: '',
        photos,
        spectrums,
        sampleCode: formData.dataCode,
        testData: formData.dataTitle,
        resultText: this.isEdit && this.currentEditIndex > -1 ? this.taskTableData[this.currentEditIndex].resultText : '',
        photos: formData.dataPictures ? JSON.parse(formData.dataPictures) : [],
        spectrums: formData.dataFiles ? JSON.parse(formData.dataFiles) : [],
        createTime: this.isEdit ? this.taskTableData[this.currentEditIndex].createTime : moment().format('YYYY-MM-DD HH:mm:ss')
      };
      if (this.isEdit && this.currentEditIndex > -1) {
        const oldData = this.taskTableData[this.currentEditIndex];
        if (oldData.photos) {
          oldData.photos.forEach(photo => {
            if (photo.url.startsWith('blob:') && !photos.find(p => p.url === photo.url)) {
              URL.revokeObjectURL(photo.url);
            }
          });
        }
        if (oldData.spectrums) {
          oldData.spectrums.forEach(spectrum => {
            if (spectrum.url.startsWith('blob:') && !spectrums.find(s => s.url === spectrum.url)) {
              URL.revokeObjectURL(spectrum.url);
            }
          });
        }
        this.taskTableData.splice(this.currentEditIndex, 1, newData);
        this.$message.success('更新成功');
      } else {
@@ -299,12 +377,148 @@
    },
    getPhotoUrls(photos) {
      return photos.map(photo => photo.url);
    },
    // 获取所有编辑器的内容
    getAllEditorContent() {
      return {
        termStandard: this.$refs.standardEditor.getContent(),
        termInstrument: this.$refs.instrumentEditor.getContent(),
        termReagent: this.$refs.reagentEditor.getContent(),
        termStep: this.$refs.stepsEditor.getContent(),
        termResult: this.$refs.resultCalculationEditor.getContent()
      }
    },
    // 验证所有编辑器内容
    validateEditors() {
      const editors = {
        termStandard: this.$refs.standardEditor.getContent(),
        termInstrument: this.$refs.instrumentEditor.getContent(),
        termReagent: this.$refs.reagentEditor.getContent(),
        termStep: this.$refs.stepsEditor.getContent(),
        termResult: this.$refs.resultCalculationEditor.getContent()
      };
      // 判断内容是否为空(排除<p></p>)
      const isEmptyContent = (content) => {
        return !content || content === '<p></p>' || content.trim() === '<p></p>';
      };
      const emptyFields = [];
      if (isEmptyContent(editors.termStandard)) emptyFields.push('检测标准');
      if (isEmptyContent(editors.termInstrument)) emptyFields.push('检测仪器');
      if (isEmptyContent(editors.termReagent)) emptyFields.push('检测试剂');
      if (isEmptyContent(editors.termStep)) emptyFields.push('检测步骤');
      if (isEmptyContent(editors.termResult)) emptyFields.push('检测结果运算');
      if (emptyFields.length > 0) {
        this.$message.warning(`请填写${emptyFields.join('、')}`);
        return false;
      }
      return true;
    },
    // 获取编辑器对应的标签名
    getEditorLabel(key) {
      const labels = {
        termStandard: '检测标准',
        termInstrument: '检测仪器',
        termReagent: '检测试剂',
        termStep: '检测步骤',
        termResult: '检测结果运算'
      };
      return labels[key] || '';
    },
    // 验证表格数据
    validateTableData() {
      if (!this.taskTableData || this.taskTableData.length === 0) {
        this.$message.error('请至少添加一条检测数据');
        return false;
      }
      return true;
    },
    // 提交表单
    async handleSubmit(isDraft) {
      try {
        // 如果不是草稿,需要验证所有必填项
        if (!isDraft) {
          // 验证编辑器内容
          if (!this.validateEditors()) {
            return;
          }
          // 验证表格数据
          if (!this.validateTableData()) {
            return;
          }
        }
        // 获取所有编辑器内容
        const editorContents = {
          termStandard: this.$refs.standardEditor.getContent(),
          termInstrument: this.$refs.instrumentEditor.getContent(),
          termReagent: this.$refs.reagentEditor.getContent(),
          termStep: this.$refs.stepsEditor.getContent(),
          termResult: this.$refs.resultCalculationEditor.getContent()
        };
        // 构建提交数据
        const submitData = {
          id: this.form.id,
          status: isDraft ? -1 : 2,
          ...editorContents,
          testMethodConfirmSheetOriginalDataList: this.taskTableData.map(item => ({
            dataCode: item.sampleCode,
            dataTitle: item.testData,
            dataType: item.photos && item.spectrums ? '1,2' :
                     item.photos ? '1' :
                     item.spectrums ? '2' : '',
            dataFiles: JSON.stringify(item.spectrums || []),
            dataPictures: (item.photos || []).map(photo => photo.url).join(','),
            originalId: this.form.id,
            resultText: item.resultText || ''
          }))
        };
        console.log('提交数据:', submitData);
        // 调用更新接口
        const res = await update(submitData);
        if (res.code === 200) {
          // 根据 isDraft 显示不同的成功提示
          if (isDraft) {
            this.$message.success('保存草稿成功');
          } else {
            this.$message.success('填写完毕');
          }
          // 返回上一页
          this.$router.back();
        } else {
          this.$message.error(res.msg || '提交失败');
        }
      } catch (error) {
        console.error('提交失败:', error);
        this.$message.error('提交失败');
      }
    },
    // 存草稿
    handleSaveDraft() {
      this.handleSubmit(true);
    }
  },
  created() {
    this.getDetail();
  }
};
</script>
  
<style scoped lang="less">
.ai-editor-container{
  margin-left: 40px;
  width: 85%;
}
.el-form--inline .el-form-item {
  margin-right: 83px;
}
@@ -315,6 +529,7 @@
  flex-wrap: wrap;
  gap: 13px;
  margin-top: 38px;
  margin-bottom: 38px;
  
  .header-title-left {
    display: flex;
@@ -334,6 +549,19 @@
      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;
      }
    }
  }
}
laboratory/src/views/dataManagement/originalRecordTest/list.vue
@@ -1,13 +1,16 @@
<template>
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null" @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange">
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="项目课题方案名称:">
            <el-input v-model="form.projectName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="所属实验编号:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
            <el-input v-model="form.experimentCode" 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
@@ -17,17 +20,27 @@
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="yyyy-MM-dd"
              :default-time="['00:00:00', '23:59:59']"
              @change="handleDateChange"
            ></el-date-picker>
          </el-form-item>
          <el-form-item label="审批人:">
          <!-- <el-form-item label="审批人:">
            <el-input v-model="form.approver" placeholder="请输入"></el-input>
          </el-form-item> -->
          <el-form-item label="状态:">
            <el-select v-model="form.status" placeholder="请选择">
              <el-option label="全部" value=""></el-option>
              <el-option label="未填写" value="1"></el-option>
              <el-option label="已填写" value="2"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="primary" @click="handleSearch" style="margin-left: 10px;">查询</el-button>
          </el-form-item>
        </el-form>
      </template>
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center">
@@ -36,22 +49,41 @@
        </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="originalCode" 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="creator" label="创建人"></el-table-column>
        <el-table-column prop="termCode" label="检测项编号"></el-table-column>
        <el-table-column prop="termName" label="检测项名称"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column prop="createBy" label="创建人"></el-table-column>
        <!-- <el-table-column prop="termInstrument" label="检测仪器"></el-table-column> -->
        <!-- <el-table-column prop="termReagent" label="检测试剂"></el-table-column> -->
        <!-- <el-table-column prop="termStandard" label="检测标准"></el-table-column> -->
        <!-- <el-table-column prop="termStep" label="检测步骤"></el-table-column> -->
        <!-- <el-table-column prop="termResult" label="检测结果"></el-table-column> -->
        <el-table-column prop="status" label="状态">
          <template slot-scope="scope">
            <el-tag :type="scope.row.status === '已填写' ? 'success' : 'warning'">
              {{ scope.row.status }}
            <el-tag :type="getStatusType(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template slot-scope="scope">
            <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            <template v-if="isLabTechnician">
              <el-button
                type="text"
                @click="handleEdit(scope.row)"
              >编辑</el-button>
            </template>
            <template v-else>
              <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            </template>
          </template>
        </el-table-column>
      </template>
@@ -60,64 +92,36 @@
</template>
<script>
import { getList } from './service';
export default {
  name: "OriginalRecordTest",
  computed: {
    /**
     * 判断当前用户是否为化验师
     * @returns {boolean} 是否为化验师
     */
    isLabTechnician() {
      const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
      return userInfo.roleType == 4; // 4是化验师
    }
  },
  data() {
    return {
      // 查询表单数据
      form: {
        planCode: "",
        creator: "",
        createTime: [],
        approver: ""
        projectName: "", // 项目课题方案名称
        experimentCode: "", // 所属实验编号
        createBy: "", // 创建人
        createTime: [], // 创建时间范围
        startTime: "", // 开始时间
        endTime: "", // 结束时间
        status: "", // 状态
        pageNum: 1, // 当前页码
        pageSize: 10 // 每页条数
      },
      tableData: [
        {
          id: '1',
          projectPlan: 'DD250218-JL01',
          experimentNo: '31423764',
          experimentName: '化学成分分析实验',
          creator: '张三',
          createTime: '2025-1-8 17:56:11',
          status: '未填写'
        },
        {
          id: '2',
          projectPlan: 'DD250218-JL02',
          experimentNo: '31423765',
          experimentName: '物理性能测试实验',
          creator: '李四',
          createTime: '2025-1-8 18:00:00',
          status: '未填写'
        },
        {
          id: '3',
          projectPlan: 'DD250218-JL03',
          experimentNo: '31423766',
          experimentName: '材料强度测试',
          creator: '王五',
          createTime: '2025-1-8 18:30:00',
          status: '已填写'
        },
        {
          id: '4',
          projectPlan: 'DD250218-JL04',
          experimentNo: '31423767',
          experimentName: '耐久性测试实验',
          creator: '赵六',
          createTime: '2025-1-8 19:00:00',
          status: '已填写'
        },
        {
          id: '5',
          projectPlan: 'DD250218-JL05',
          experimentNo: '31423768',
          experimentName: '环境适应性测试',
          creator: '孙七',
          createTime: '2025-1-8 19:30:00',
          status: '未填写'
        }
      ],
      total: 5
      tableData: [], // 表格数据
      total: 0 // 总条数
    };
  },
  created() {
@@ -126,28 +130,92 @@
  methods: {
    resetForm() {
      this.form = {
        planCode: "",
        creator: "",
        projectName: "",
        experimentCode: "",
        createBy: "",
        createTime: [],
        approver: ""
        startTime: "",
        endTime: "",
        status: "",
        pageNum: 1,
        pageSize: 10
      };
    },
    handleSearch() {
      this.form.pageNum = 1;
      this.getTableData();
    },
    handleEdit(row) {
      console.log("编辑数据:", row);
      this.$router.push({
        path: "/dataManagement/originalRecordTest/detail",
        query: {
          id: row.id,
          type: 'edit'
        }
      });
    },
    handleDetail(id) {
      this.$router.push({
        path: "/dataManagement/originalRecordTest/detail",
        query: { id }
        query: {
          id,
          type: 'detail'
        }
      });
    },
    handlePageChange(page) {
      this.form.pageNum = page;
      this.getTableData();
    },
    handleSizeChange(size) {
      this.form.pageSize = size;
      this.form.pageNum = 1;
      this.getTableData();
    },
    handleDateChange(val) {
      if (val) {
        this.form.startTime = val[0];
        this.form.endTime = val[1];
      } else {
        this.form.startTime = "";
        this.form.endTime = "";
      }
    },
    getTableData() {
      // TODO: 调用接口获取数据
    //   this.tableData = [];
    //   this.total = 0;
      const params = {
        pageNum: this.form.pageNum,
        pageSize: this.form.pageSize,
        createBy: this.form.createBy,
        projectName: this.form.projectName,
        experimentCode: this.form.experimentCode,
        status: this.form.status,
        startTime: this.form.startTime,
        endTime: this.form.endTime
      };
      console.log('params',params)
      getList(params).then(res => {
        if (res.code == 200) {
          this.tableData = res.data.records || [];
          this.total = res.data.total || 0;
        }
      });
    },
    getStatusType(status) {
      const statusMap = {
        '-1': 'info',
        '1': 'warning',
        '2': 'success'
      };
      return statusMap[status] || 'info';
    },
    getStatusText(status) {
      const statusMap = {
        '-1': '草稿箱',
        '1': '未填写',
        '2': '已填写'
      };
      return statusMap[status] || '未知';
    }
  }
};
laboratory/src/views/dataManagement/originalRecordTest/service.js
New file
@@ -0,0 +1,15 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-test-method-confirm-sheet-original/pageList', { ...data })
}
// 详情
export const getDetail = (data) => {
  return axios.get('/open/t-test-method-confirm-sheet-original/getDetailById', { params:data })
}
//修改
export const update = (data) => {
  return axios.post('/api/t-test-method-confirm-sheet-original/update', { ...data })
}
laboratory/src/views/dataManagement/sampleManage/addSample.vue
@@ -3,19 +3,26 @@
    <div class="header-title-left">
      <img src="@/assets/public/headercard.png" />
      <div>所属实验调度</div>
      <el-button v-if="isEngineer" @click="showScheduling = true" class="el-icon-plus" type="primary">
      <el-button v-if="isEngineer && pageType !== 'detail'" @click="showScheduling = true" class="el-icon-plus" type="primary">
        选择实验调度</el-button>
    </div>
    <Table :data="schedulingData" :total="schedulingTotal" :height="null">
      <template>
        <el-table-column prop="planCode" label="所属项目课题方案"></el-table-column>
        <el-table-column prop="planName" label="实验编号"></el-table-column>
        <el-table-column prop="planName" label="实验名称"></el-table-column>
        <el-table-column prop="stage" label="通知时间"></el-table-column>
        <el-table-column prop="stage" label="实验开始时间"></el-table-column>
        <el-table-column prop="stage" label="实验结束时间"></el-table-column>
        <el-table-column prop="stage" label="参加人员"></el-table-column>
        <el-table-column prop="creator" label="状态"></el-table-column>
        <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>
      </template>
    </Table>
@@ -38,28 +45,63 @@
      <!-- 待收样列表 -->
      <div class="pending-samples">
        <div class="sub-title">待收样列表</div>
        <el-button type="primary" class="batch-receive" @click="handleBatchReceive">批量接收</el-button>
        <Table :data="pendingSamples" :total="pendingSamplesTotal" :height="null"
          @selection-change="handleSelectionChange">
        <el-button
          type="primary"
          class="batch-receive"
          @click="handleBatchReceive"
          :disabled="selectedSamples.length == 0"
        >批量接收</el-button>
        <Table ref="pendingTable"
          :data="pendingSamples"
          :total="pendingSamplesTotal"
          :height="null"
          :row-key="row => row.id"
          @selection-change="handlePendingSelectionChange">
          <template>
            <el-table-column type="selection" width="55"></el-table-column>
            <el-table-column prop="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="sampleName" label="取样名称"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号"></el-table-column>
            <el-table-column prop="ph" label="PH"></el-table-column>
            <el-table-column prop="sampleAmount" label="取样量"></el-table-column>
            <el-table-column prop="sendTime" label="送样时间"></el-table-column>
            <el-table-column prop="sender" label="送样人"></el-table-column>
            <el-table-column prop="status" label="状态"></el-table-column>
            <el-table-column
              type="selection"
              width="55"
              fixed="left" >
            </el-table-column>
            <el-table-column type="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
            <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
            <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
            <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
            <template v-if="showPendingColumns">
              <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
              <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column>
              <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
            </template>
            <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
            <el-table-column prop="pictures" label="拍照" width="150">
              <template slot-scope="scope">
                <template v-if="scope.row.pictures">
                  <el-image
                    v-for="(url, index) in scope.row.pictures.split(',')"
                    :key="index"
                    src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
                    :preview-src-list="[url]"
                    style="width: 50px; height: 50px;"
                  />
                </template>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column prop="handlePersonName" label="操作人员" width="150"></el-table-column>
            <el-table-column label="状态" prop="status" width="100" fixed="right">
              <template slot-scope="scope">
                <span>{{ scope.row.status == '2' ? '待接收' : '已接收' }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="100" fixed="right">
              <template slot-scope="scope">
                <el-button type="text" @click="handleReceive(scope.row)">接收</el-button>
@@ -68,31 +110,52 @@
          </template>
        </Table>
      </div>
      <!-- 已收样列表 -->
      <div class="received-samples">
        <div class="sub-title">已收样列表</div>
        <Table :data="receivedSamples" :total="receivedSamplesTotal" :height="null">
        <Table ref="receivedTable" :data="receivedSamples" :total="receivedSamplesTotal" :height="null">
          <template>
            <el-table-column prop="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="sampleName" label="取样名称"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号"></el-table-column>
            <el-table-column type="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
            <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
            <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column>
            <el-table-column prop="ph" label="PH"></el-table-column>
            <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
            <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
            <template v-if="showReceivedColumns">
              <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
            </template>
            <el-table-column prop="sampleAmount" label="取样量"></el-table-column>
            <el-table-column prop="sendTime" label="送样时间"></el-table-column>
            <el-table-column prop="sender" label="送样人"></el-table-column>
            <el-table-column prop="receiveTime" label="收样时间"></el-table-column>
            <el-table-column prop="receiver" label="收样人"></el-table-column>
            <el-table-column prop="status" label="状态" fixed="right"></el-table-column>
            <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
            <el-table-column prop="pictures" label="拍照" width="150">
              <template slot-scope="scope">
                <template v-if="scope.row.pictures">
                  <el-image
                    v-for="(url, index) in scope.row.pictures.split(',')"
                    :key="index"
                    src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
                    :preview-src-list="[url]"
                    style="width: 50px; height: 50px;"
                  />
                </template>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column prop="handlePersonName" label="操作人员" width="150"></el-table-column>
            <el-table-column prop="receiveTime" label="收样时间" width="150"></el-table-column>
            <el-table-column prop="receiver" label="收样人" width="150"></el-table-column>
            <el-table-column label="状态" prop="status" width="100" fixed="right">
              <template slot-scope="scope">
                <span>{{ scope.row.status == '3' ? '已接收' : '待接收' }}</span>
              </template>
            </el-table-column>
          </template>
        </Table>
      </div>
@@ -104,55 +167,79 @@
        <img src="@/assets/public/headercard.png" />
        <span>基础信息</span>
      </div>
      <el-form ref="form" :model="form" :rules="rules" inline label-position="top">
      <el-form ref="form" :model="form" :rules="rules" inline label-position="top" v-if="pageType !== 'detail'">
        <el-form-item label="取样单编号" prop="sampleCode">
          <el-input v-model="form.sampleCode" :disabled="true" placeholder="自动生成" />
        </el-form-item>
      </el-form>
      <div>取样单编号:{{ form.sampleCode }}</div>
      <div class="header-title-left" style="margin-top: 38px">
        <img src="@/assets/public/headercard.png" />
        <span>取样操作记录</span>
        <el-button type="primary" class="el-icon-plus" @click="showAddTime = true">
        <el-button v-if="isEngineer && pageType !== 'detail'" type="primary" class="el-icon-plus" @click="showAddTime = true">
          新增工艺时间
        </el-button>
        <el-button type="primary" class="el-icon-plus" @click="showAdditives = !showAdditives">
          {{ showAdditives ? "收起辅料详情" : "展开辅料详情" }}
        </el-button>
      </div>
      <Table :data="sampleData" :total="sampleTotal" :height="null">
      <Table ref="sampleTable" :data="sampleData" :total="sampleTotal" :height="null">
        <template>
          <el-table-column prop="index" label="序号" width="80"></el-table-column>
          <el-table-column prop="processTime" label="工艺时间" width="150"></el-table-column>
          <el-table-column prop="sampleName" label="取样名称" width="150"></el-table-column>
          <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
          <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
          <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
          <el-table-column prop="ph" label="PH" width="150"></el-table-column>
          <el-table-column prop="waterAmount" label="加水量" width="150"></el-table-column>
          <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
          <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
          <template v-if="showAdditives">
            <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column>
            <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column>
            <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column>
            <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column>
            <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column>
            <el-table-column prop="additive6" label="加辅6" width="150"></el-table-column>
            <el-table-column prop="additive7" label="加辅7" width="150"></el-table-column>
            <el-table-column prop="additive8" label="加辅8" width="150"></el-table-column>
            <el-table-column prop="additive9" label="加辅9" width="150"></el-table-column>
            <el-table-column prop="additive10" label="加辅10" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
            <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
            <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
            <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
          </template>
          <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
          <el-table-column prop="sampleTime" label="取样时间" width="150"></el-table-column>
          <el-table-column prop="remark" label="拍照" width="150"></el-table-column>
          <el-table-column prop="operator" label="操作人员" width="150"></el-table-column>
          <el-table-column prop="pictures" label="拍照" width="150">
            <template slot-scope="scope">
              <template v-if="scope.row.pictures">
                <el-image
                  v-for="(url, index) in scope.row.pictures.split(',')"
                  :key="index"
                  :src="url"
                  :preview-src-list="[url]"
                  style="width: 50px; height: 50px;"
                />
              </template>
              <span v-else>-</span>
            </template>
          </el-table-column>
          <el-table-column prop="handlePersonName" label="操作人员" width="150"></el-table-column>
        </template>
      </Table>
      <div class="add-project-footer">
      <div v-if="pageType == 'detail'" style="margin-top: 38px">备注:</div>
      <el-input
        v-if="pageType == 'detail'"
        type="textarea"
        v-model="form.remark"
        placeholder="请输入内容"
        style="margin-top: 10px"
        :disabled="true"
      />
      <div class="add-project-footer" v-if="isEngineer && pageType !== 'detail'">
        <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button>
        <el-button>存草稿</el-button>
        <el-button @click="handleSaveDraft">存草稿</el-button>
      </div>
    </div>
    <experimentalScheduling :show="showScheduling" />
    <experimentalScheduling :show="showScheduling" @close="handleSchedulingClose" @submit="handleSchedulingSubmit" />
    <addTime :show.sync="showAddTime" @confirm="handleAddTime" />
    <receive-confirm-dialog :visible.sync="showReceiveConfirm" :sample-count="selectedSamples.length"
      @confirm="confirmReceive" />
@@ -163,6 +250,7 @@
import experimentalScheduling from "./components/experimental-scheduling.vue";
import addTime from "./components/addTime.vue";
import ReceiveConfirmDialog from "./components/receiveConfirmDialog.vue";
import { add, getDetail, update, batchCollectSamples } from "./service";
export default {
  name: "AddSample",
@@ -181,224 +269,331 @@
      showReceivedColumns: true,
      schedulingData: [],
      schedulingTotal: 0,
      sampleData: [
        {
          index: 1,
          processTime: "2h",
          sampleName: "样品A",
          sampleCode: "SP001",
          temperature: "25℃",
          ph: "7.0",
          waterAmount: "500ml",
          additive1: "10g",
          additive2: "5g",
          additive3: "3g",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "100ml",
          sampleTime: "2024-03-20 10:00:00",
          remark: "",
          operator: "张三",
        },
        {
          index: 2,
          processTime: "4min",
          sampleName: "样品B",
          sampleCode: "SP002",
          temperature: "30℃",
          ph: "6.5",
          waterAmount: "300ml",
          additive1: "8g",
          additive2: "4g",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "50ml",
          sampleTime: "2024-03-20 10:30:00",
          remark: "",
          operator: "李四",
        },
      ],
      sampleTotal: 2,
      sampleData: [],
      sampleTotal: 0,
      form: {
        sampleCode: "",
        dispatchId: "", // 实验调度id
        samplingCode: "", // 取样单编号
        status: 1, // 状态:1=已发送待提交
        samplingRecordOperations: [], // 取样操作记录集合
        remark: "", // 备注,json存储
      },
      rules: {
        sampleCode: [
          { required: true, message: "请输入取样单编号", trigger: "blur" },
        ],
      },
      userRole: "assayer", // engineer默认设置为工程师assayer化验师
      userRole: '', // 修改初始值为空字符串
      // 化验师相关数据
      pendingSamples: [
        {
          index: 1,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "5",
          sampleAmount: "34",
          sendTime: "2025-1-9 15:26:08",
          sender: "李四",
          status: "待接收",
        },
        {
          index: 2,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "6",
          sampleAmount: "23",
          sendTime: "2025-1-9 15:26:08",
          sender: "李四",
          status: "待接收",
        },
        {
          index: 3,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "7",
          sampleAmount: "23",
          sendTime: "2025-1-13 16:38:17",
          sender: "李四",
          status: "待接收",
        },
      ],
      pendingSamplesTotal: 3,
      receivedSamples: [
        {
          index: 1,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "5",
          sampleAmount: "34",
          sendTime: "2025-1-9 15:26:08",
          sender: "李四",
          receiveTime: "2025-1-15 14:00:50",
          receiver: "段向蒙",
          status: "已接收",
        },
        {
          index: 2,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "6",
          sampleAmount: "23",
          sendTime: "2025-1-9 15:26:08",
          sender: "李四",
          receiveTime: "2025-1-15 14:00:50",
          receiver: "傅彦涛",
          status: "已接收",
        },
        {
          index: 3,
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          ph: "7",
          sampleAmount: "23",
          sendTime: "2025-1-13 16:38:17",
          sender: "李四",
          receiveTime: "2025-1-15 14:00:50",
          receiver: "王乐康",
          status: "已接收",
        },
      ],
      receivedSamplesTotal: 3,
      pendingSamples: [],
      pendingSamplesTotal: 0,
      receivedSamples: [],
      receivedSamplesTotal: 0,
      selectedSamples: [],
      // 状态映射表
      statusTypeMap: {
        "-1": "info",
        "1": "warning",
        "2": "success",
        "3": "info"
      },
      statusTextMap: {
        "-1": "草稿箱",
        "1": "待确认",
        "2": "已确认",
        "3": "已封存"
      },
      // 页面类型:add-新增,edit-编辑,detail-详情
      pageType: 'add',
    };
  },
  created() {
    const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
    this.userRole = userInfo.roleType || '';
    // 获取路由参数
    const { id, type } = this.$route.query;
    if (id) {
      this.pageType = type || 'detail';
      this.getDetailData(id);
    }
  },
  computed: {
    isEngineer() {
      return this.userRole === "engineer";
      return this.userRole == '3'; // 工艺工程师
    },
    isAssayer() {
      return this.userRole === "assayer";
      return this.userRole == '4'; // 化验师
    },
  },
  methods: {
    // 获取详情数据
    async getDetailData(id) {
      try {
        const res = await getDetail({ id });
        if (res) {
          const detail = res;
          console.log('获取到的详情数据:', detail);
          // 设置表单数据
          this.form = {
            ...this.form,
            ...detail,
            dispatchId: detail.dispatchId,
            sampleCode: detail.samplingCode,
          };
          // 设置实验调度数据
          if (detail.experimentDispatch) {
            this.schedulingData = [detail.experimentDispatch];
          }
          // 设置取样操作记录
          if (detail.samplingRecordOperations && detail.samplingRecordOperations.length > 0) {
            console.log('原始取样操作记录:', detail.samplingRecordOperations);
            // 如果是化验师角色,需要将数据分为待接收和已接收
            if (this.isAssayer) {
              // 确保status是字符串类型
              this.pendingSamples = detail.samplingRecordOperations
                .filter(item => {
                  const status = String(item.status);
                  console.log('过滤待接收样品:', item.id, status);
                  return status === '2';
                })
                .map(item => ({
                  ...item,
                  status: String(item.status)
                }));
              console.log('处理后的待接收样品:', this.pendingSamples);
              this.pendingSamplesTotal = this.pendingSamples.length;
              this.receivedSamples = detail.samplingRecordOperations
                .filter(item => String(item.status) === '3')
                .map(item => ({
                  ...item,
                  status: String(item.status)
                }));
              this.receivedSamplesTotal = this.receivedSamples.length;
            } else {
              // 工程师角色保持原有逻辑
              this.sampleData = detail.samplingRecordOperations.map((item, index) => ({
                ...item,
                index: index + 1,
                status: String(item.status)
              }));
            }
          }
          // 如果是详情模式,禁用所有输入
          if (this.pageType == 'detail') {
            this.$nextTick(() => {
              const inputs = document.querySelectorAll('input, textarea, select');
              inputs.forEach(input => {
                input.disabled = true;
              });
            });
          }
        }
      } catch (error) {
        console.error('获取详情失败:', error);
        this.$message.error('获取详情失败,请重试');
      }
    },
    handleAddTime(processTime) {
      const newRow = {
        index: this.sampleData.length + 1,
        processTime,
        sampleName: "",
        samplingName: "",
        sampleCode: "",
        temperature: "",
        ph: "",
        waterAmount: "",
        additive1: "",
        additive2: "",
        additive3: "",
        additive4: "",
        additive5: "",
        additive6: "",
        additive7: "",
        additive8: "",
        additive9: "",
        additive10: "",
        samplePh: "",
        waterAddition: "",
        addAuxiliaryOne: "",
        addAuxiliaryTwo: "",
        addAuxiliaryThree: "",
        addAuxiliaryFour: "",
        addAuxiliaryFive: "",
        addAuxiliarySix: "",
        addAuxiliarySeven: "",
        addAuxiliaryEight: "",
        addAuxiliaryNine: "",
        addAuxiliaryTen: "",
        sampleAmount: "",
        sampleTime: "",
        remark: "",
        operator: "",
        pictures: "",
        handlePersonId: "",
        status: 1 // 1=待发送
      };
      this.sampleData.push(newRow);
      this.$message.success("添加工艺时间成功");
    },
    handleSave() {
      this.submitForm();
      // 验证是否选择了实验调度
      if (!this.schedulingData || this.schedulingData.length == 0) {
        this.$message.warning('请选择所属实验调度');
        return;
      }
      // 验证是否有取样操作记录
      if (!this.sampleData || this.sampleData.length == 0) {
        this.$message.warning('请至少添加一条取样操作记录');
        return;
      }
      this.$refs.form.validate(async (valid) => {
        if (valid) {
          try {
            // 获取当前用户信息
            const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
            // 构建提交数据
            const submitData = {
              ...this.form,
              dispatchId: this.schedulingData[0].id,
              status: 1, // 正常保存状态为1
              samplingRecordOperations: this.sampleData.map(item => ({
                ...item,
                handlePersonId: userInfo.userId,
                status: 1 // 1=待发送
              })),
              remark: this.form.remark,
          samplingCode: this.form.sampleCode,
          id: this.form.id,
            };
            // 打印提交数据
            console.log('保存提交数据:',submitData);
            let res;
            if (this.pageType == 'edit') {
              // 编辑模式调用update接口
              res = await update(submitData);
            } else {
              // 新增模式调用add接口
              res = await add(submitData);
            }
            if (res.code == 200) {
              this.$message.success(this.pageType == 'edit' ? '编辑成功' : '保存成功');
              this.$router.go(-1);
            } else {
              this.$message.error(res.msg || (this.pageType == 'edit' ? '编辑失败' : '保存失败'));
            }
          } catch (error) {
            console.error(this.pageType == 'edit' ? '编辑失败:' : '保存失败:', error);
            this.$message.error(this.pageType == 'edit' ? '编辑失败,请重试' : '保存失败,请重试');
          }
        }
      });
    },
    submitForm() {
      // 在这里实现表单提交逻辑
      console.log("提交表单数据");
      this.$message.success("保存成功");
    // 添加存草稿方法
    async handleSaveDraft() {
      try {
        // 获取当前用户信息
        const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
        // 构建提交数据
        const submitData = {
          dispatchId: this.schedulingData?.[0]?.id || '',
          status: -1, // 存草稿状态为-1
          samplingRecordOperations: (this.sampleData || []).map(item => ({
            ...item,
            handlePersonId: userInfo.userId,
            status: 1 // 1=待发送
          })),
          remark: this.form.remark,
          samplingCode: this.form.sampleCode,
          id: this.form.id,
        };
        // 打印提交数据
        console.log('草稿提交数据:', submitData);
        let res;
        if (this.pageType == 'edit') {
          // 编辑模式调用update接口
          res = await update(submitData);
        } else {
          // 新增模式调用add接口
          res = await add(submitData);
        }
        if (res.code == 200) {
          this.$message.success(this.pageType == 'edit' ? '草稿保存成功' : '存草稿成功');
          this.$router.go(-1);
        } else {
          this.$message.error(res.msg || (this.pageType == 'edit' ? '草稿保存失败' : '存草稿失败'));
        }
      } catch (error) {
        console.error(this.pageType == 'edit' ? '草稿保存失败:' : '存草稿失败:', error);
        this.$message.error(this.pageType == 'edit' ? '草稿保存失败,请重试' : '存草稿失败,请重试');
      }
    },
    handleSelectionChange(selection) {
    handlePendingSelectionChange(selection) {
      console.log("pending selection change:", selection);
      console.log("pending samples data:", this.pendingSamples);
      this.selectedSamples = selection;
      // 强制更新视图
      this.$nextTick(() => {
        this.$forceUpdate();
      });
    },
    handleReceive(row) {
      // 清空之前的选择
      this.selectedSamples = [];
      // 设置当前行为选中状态
      this.selectedSamples = [row];
      this.showReceiveConfirm = true;
    },
    handleBatchReceive() {
      if (this.selectedSamples.length === 0) {
      if (this.selectedSamples.length == 0) {
        this.$message.warning("请先选择要接收的样品");
        return;
      }
      this.showReceiveConfirm = true;
    },
    confirmReceive(signature) {
      // 这里处理接收确认逻辑
      const sampleIds = this.selectedSamples.map((item) => item.id);
      console.log("接收样品", { sampleIds, signature });
      // 模拟接收成功
      this.$message.success(`成功接收 ${this.selectedSamples.length} 个样品`);
      // 更新数据
      this.selectedSamples.forEach((sample) => {
        const index = this.pendingSamples.findIndex(
          (item) => item.id === sample.id
        );
        if (index > -1) {
          this.pendingSamples.splice(index, 1);
          this.receivedSamples.unshift({
            ...sample,
            receiveTime: new Date().toLocaleString(),
            receiver: "当前用户",
            status: "已接收",
          });
      // 获取选中样品的ID并拼接
      const recordOperationIds = this.selectedSamples.map(item => item.id).join(',');
      // 调用批量收样接口
      batchCollectSamples({
        receiptsSign: signature,
        recordOperationId: recordOperationIds
      }).then(res => {
        if (res.code == 200) {
          this.$message.success(`成功接收 ${this.selectedSamples.length} 个样品`);
          // 重新获取详情数据
          this.getDetailData(this.form.id);
        } else {
          this.$message.error(res.msg || '收样失败');
        }
      }).catch(error => {
        console.error('收样失败:', error);
        this.$message.error('收样失败,请重试');
      }).finally(() => {
        // 清空选择并关闭弹窗
        this.selectedSamples = [];
        this.showReceiveConfirm = false;
      });
      // 清空选择
      this.selectedSamples = [];
    },
    getStatusType(status) {
      return this.statusTypeMap[status] || 'info';
    },
    getStatusText(status) {
      return this.statusTextMap[status] || '未知状态';
    },
    handleSchedulingClose() {
      this.showScheduling = false;
    },
    handleSchedulingSubmit(data) {
      this.schedulingData = data || [];
    },
    isSelectable(row) {
      console.log('isSelectable row:', row);
      console.log('row status:', row.status, typeof row.status);
      const result = String(row.status) === '2';
      console.log('isSelectable result:', result);
      return result;
    },
  },
};
laboratory/src/views/dataManagement/sampleManage/components/experimental-scheduling.vue
@@ -1,7 +1,12 @@
<template>
    <div>
        <el-dialog title="选择实验调度" :visible.sync="show" width="80%">
            <TableCustom :queryForm="form" :tableData="tableData" :total="total" :height="null">
        <el-dialog title="选择实验调度" :visible.sync="show" width="80%" @close="$emit('close', false)">
            <TableCustom
            :queryForm="form" :tableData="tableData"
            :total="total" :height="null"
             @handleCurrentChange="handleCurrentChange"
             @selection-change="changeSelectedRows"
             @handleSizeChange="handleSizeChange">
                <template #search>
                    <el-form :model="form" label-width="140px" inline>
                        <el-form-item label="所属项目课题方案:">
@@ -10,22 +15,19 @@
                        <el-form-item label="实验编号:">
                            <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-date-picker
                                v-model="form.createTime"
                                type="daterange"
                                range-separator="至"
                                start-placeholder="开始日期"
                                end-placeholder="结束日期"
                                value-format="yyyy-MM-dd">
                            </el-date-picker>
                            <el-date-picker v-model="form.createTime" type="daterange" range-separator="至"
                                start-placeholder="开始日期" end-placeholder="结束日期"
                                value-format="yyyy-MM-dd" @change="handleDateChange"></el-date-picker>
                        </el-form-item>
                        <el-form-item label="状态:">
                            <el-select v-model="form.status" placeholder="请选择">
                                <el-option label="草稿箱" :value="-1"></el-option>
                                <el-option label="待确认" :value="1"></el-option>
                                <el-option label="已确认" :value="2"></el-option>
                                <el-option label="已封存" :value="3"></el-option>
                                <el-option label="全部" value=""></el-option>
                                <el-option label="待确认" value="1"></el-option>
                                <el-option label="已确认" value="2"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="" class="search-btn-box">
@@ -36,84 +38,157 @@
                </template>
                
                <template #table>
                    <el-table-column prop="planCode" label="所属项目课题方案"></el-table-column>
                    <el-table-column prop="planName" label="实验编号"></el-table-column>
                    <el-table-column prop="planName" label="实验名称"></el-table-column>
                    <el-table-column prop="stage" label="通知时间"></el-table-column>
                    <el-table-column prop="stage" label="实验开始时间"></el-table-column>
                    <el-table-column prop="stage" label="实验结束时间"></el-table-column>
                    <el-table-column prop="stage" label="参加人员"></el-table-column>
                    <el-table-column prop="creator" label="状态"></el-table-column>
                    <el-table-column type="selection" width="55"></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>
                </template>
            </TableCustom>
            <span slot="footer" class="dialog-footer">
                <el-button @click="show = false">取 消</el-button>
                <el-button type="primary" @click="show = false">确 定</el-button>
            <span slot="footer" class="select-member-footer">
                <el-button @click="$emit('close', false)">取 消</el-button>
                <el-button type="primary" @click="handleConfirm">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<script>
import { getDispatchList } from '../service';
import { getDispatchList } from "../service";
export default {
    props: ['show'],
    props: {
        show: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            form: {
                projectName: "",
                experimentCode: "",
                createTime: [],
                status: null,
                experimentName: "",
                startTime: "",
                endTime: "",
                status: "",
                pageNum: 1,
                pageSize: 10
            },
            tableData: [],
            total: 0
        };
            total: 0,
            selectedRows: []
        }
    },
    watch: {
        show(val) {
            if (val) {
                this.getTableData();
            }
        }
    },
    methods: {
        handleDateChange(val) {
            if (val) {
                this.form.startTime = val[0];
                this.form.endTime = val[1];
            } else {
                this.form.startTime = "";
                this.form.endTime = "";
            }
        },
        resetForm() {
            this.form = {
                projectName: "",
                experimentCode: "",
                createTime: [],
                status: null,
                experimentName: "",
                startTime: "",
                endTime: "",
                status: "",
                pageNum: 1,
                pageSize: 10
            };
            this.handleSearch();
            this.getTableData();
        },
        async handleSearch() {
            const params = {
                projectName: this.form.projectName,
                experimentCode: this.form.experimentCode,
                startTime: this.form.createTime[0] || null,
                endTime: this.form.createTime[1] || null,
                status: this.form.status,
                pageNum: this.form.pageNum,
                pageSize: this.form.pageSize
        handleSearch() {
            this.form.pageNum = 1;
            this.getTableData();
        },
        getStatusType(status) {
            const statusMap = {
                "-1": "info",
                "1": "warning",
                "2": "success",
                "3": "info"
            };
            try {
                const res = await getDispatchList(params);
                this.tableData = res.records || [];
                this.total = res.total || 0;
            } catch (error) {
                console.error("查询失败:", error);
            return statusMap[status] || "info";
        },
        getStatusText(status) {
            const statusMap = {
                "-1": "草稿箱",
                "1": "待确认",
                "2": "已确认",
                "3": "已封存"
            };
            return statusMap[status] || "未知";
        },
        getTableData() {
            const params = {
                ...this.form
            };
            getDispatchList(params).then(res => {
                console.log('222222222222',res)
                if (res.code==200) {
                    this.tableData = res.data.records || [];
                    this.total = res.data.total || 0;
                }
            });
        },
        handleCurrentChange(val) {
            this.form.pageNum = val;
            this.getTableData();
        },
        handleSizeChange(val) {
            this.form.pageSize = val;
            this.form.pageNum = 1;
            this.getTableData();
        },
        changeSelectedRows(val) {
            console.log('val',val)
            this.selectedRows = val;
        },
        handleCancel() {
            this.$emit('update:show', false);
        },
        handleConfirm() {
            if (!this.selectedRows || this.selectedRows.length === 0) {
                this.$message.warning('请至少选择一条数据');
                return;
            }
            if (this.selectedRows.length != 1) {
                this.$message.warning('请选择一条数据');
                return;
            }
            this.$emit('submit', this.selectedRows);
            this.$emit('close', false);
        }
    }
};
}
</script>
<style lang="less" scoped>
.dialog-footer {
.select-member-footer {
    display: flex;
    justify-content: center;
    gap: 10px;
}
::v-deep .el-range-editor--small {
    line-height: 30px !important;
    justify-content: flex-end;
}
</style>
laboratory/src/views/dataManagement/sampleManage/components/receiveConfirmDialog.vue
@@ -75,7 +75,8 @@
    },
    handleSignatureConfirm(imageData) {
      this.signatureDialogVisible = false;
      this.imgSrc = imageData;
      // this.imgSrc = imageData;
      this.imgSrc = 'https://img.yzcdn.cn/vant/ipad.png';
    },
    handleConfirm() {
      if (!this.imgSrc) {
laboratory/src/views/dataManagement/sampleManage/list.vue
@@ -1,16 +1,13 @@
<template>
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total">
    <TableCustom :queryForm="form" :height="null" :tableData="tableData" :total="total" @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange" >
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="实验编号:">
            <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.projectName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="实验编号:">
            <el-input v-model="form.experimentCode" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="创建时间:">
            <el-date-picker
@@ -24,6 +21,7 @@
          </el-form-item>
          <el-form-item label="状态:">
            <el-select v-model="form.status" placeholder="请选择">
              <el-option label="全部" :value="null"></el-option>
              <el-option label="草稿箱" :value="-1"></el-option>
              <el-option label="已发送待提交" :value="1"></el-option>
              <el-option label="已提交" :value="2"></el-option>
@@ -32,7 +30,7 @@
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="primary" @click="handleSearch" style="margin-left: 10px;">查询</el-button>
          </el-form-item>
        </el-form>
      </template>
@@ -40,17 +38,18 @@
        <div class="tableTitle">
          <div class="flex a-center">
            <div 
            class="title"
              :class="{active:currentType === 'list'}"
              class="title"
              :class="{active:currentType == 'list'}"
              @click="handleTypeChange('list')"
            >取样操作记录列表</div>
            <div 
            class="drafts"
              :class="{active:currentType === 'draft'}"
              v-if="isProcessEngineer"
              class="title"
              :class="{active:currentType == 'draft'}"
              @click="handleTypeChange('draft')"
            >草稿箱</div>
          </div>
          <el-button @click="handleAddSample" class="el-icon-plus" type="primary">
          <el-button v-if="isProcessEngineer" @click="handleAddSample" class="el-icon-plus" type="primary">
            新增取样操作记录</el-button
          >
        </div>
@@ -62,36 +61,45 @@
          :prop="column.prop"
          :label="column.label"
        ></el-table-column>
        <el-table-column label="操作" width="100">
        <el-table-column label="样品总数/待接收/已接收" v-if="isChemist">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            {{ getSampleStatus(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template slot-scope="scope">
            <el-button v-if="currentType == 'list'" type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            <template v-if="currentType == 'draft'">
              <el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
              <el-button type="text" @click="handleDelete(scope.row)" style="color: #F56C6C;">删除</el-button>
            </template>
          </template>
        </el-table-column>
      </template>
    </TableCustom>
    <!-- 审批弹窗 -->
    <approval-dialog
      :visible.sync="approvalDialogVisible"
      :type="approvalDialogType"
      :data="currentApprovalData"
      @approve="handleApproveSubmit"
      @reject="handleRejectSubmit"
    <!-- 删除确认弹窗 -->
    <ShowDelConfirm
      :title="changeStatusTitle"
      :tip="changeStatusTip"
      :show="changeStatus"
      @close="changeStatus = false"
      @confirm="handleChangeStatusConfirm"
    />
  </div>
</template>
<script>
import ApprovalDialog from './components/approvalDialog.vue'
import { getList } from './service'
import ShowDelConfirm from "@/components/showDelConfirm/index.vue";
import { getList, deleteById } from './service'
export default {
  name: "ProjectList",
  components: {
    ApprovalDialog
    ShowDelConfirm
  },
  data() {
    return {
      userRole: 'chemist', // 用户角色
      userRole: '', // 用户角色
      currentType: 'list', // 当前显示类型:list-列表,draft-草稿箱
      form: {
        experimentCode: "",
@@ -104,110 +112,35 @@
      },
      tableData: [],
      total: 0,
      // 确认弹窗相关数据
      changeStatus: false,
      changeStatusTitle: "",
      changeStatusTip: "",
      currentOperationRow: null, // 当前操作的行数据
      // 不同角色的表头配置
      columnConfig: {
        default: [
          { prop: 'projectPlan', label: '所属项目课题方案' },
          { prop: 'experimentNo', label: '实验编号' },
          { prop: 'projectName', label: '所属项目课题方案' },
          { prop: 'experimentCode', label: '实验编号' },
          { prop: 'experimentName', label: '实验名称' },
          { prop: 'sampleNo', label: '取样单编号' },
          { prop: 'creator', label: '创建人' },
          { prop: 'samplingCode', label: '取样单编号' },
          { prop: 'createBy', label: '创建人' },
          { prop: 'createTime', label: '创建时间' },
          { prop: 'sendTo', label: '发送对象' },
          { prop: 'sendTime', label: '发送时间' }
        ],
        chemist: [
          { prop: 'projectPlan', label: '所属项目课题方案' },
          { prop: 'experimentNo', label: '实验编号' },
        '4': [
          { prop: 'projectName', label: '所属项目课题方案' },
          { prop: 'experimentCode', label: '实验编号' },
          { prop: 'experimentName', label: '实验名称' },
          { prop: 'sampleNo', label: '取样单编号' },
          { prop: 'creator', label: '创建人' },
          { prop: 'samplingCode', label: '取样单编号' },
          { prop: 'createBy', label: '创建人' },
          { prop: 'createTime', label: '创建时间' },
          { prop: 'sampleCount', label: '样品总数' },
          { prop: 'receivedCount', label: '待接收' },
          { prop: 'completedCount', label: '已接收' }
          // { prop: 'sampleCount', label: '样品总数' },
          // { prop: 'receivedCount', label: '待接收' },
          // { prop: 'completedCount', label: '已接收' }
        ]
      },
      // 模拟数据
      mockListData: [
        {
          id: '1',
          projectPlan: '2024年度实验室设备性能评估方案',
          experimentNo: 'EXP20240315001',
          experimentName: '设备性能测试实验A',
          sampleNo: 'SAMPLE20240315001',
          creator: '张三',
          createTime: '2024-03-15 09:30:00',
          sendTo: '质检部门',
          sendTime: '2024-03-15 10:00:00',
          sampleCount: 5,
          receivedCount: 2,
          completedCount: 3
        },
        {
          id: '2',
          projectPlan: '新型材料研究项目方案',
          experimentNo: 'EXP20240315002',
          experimentName: '材料强度测试实验',
          sampleNo: 'SAMPLE20240315002',
          creator: '李四',
          createTime: '2024-03-15 11:30:00',
          sendTo: '研发部门',
          sendTime: '2024-03-15 14:00:00',
          sampleCount: 3,
          receivedCount: 1,
          completedCount: 2
        },
        {
          id: '3',
          projectPlan: '环境监测系统优化方案',
          experimentNo: 'EXP20240315003',
          experimentName: '空气质量检测实验',
          sampleNo: 'SAMPLE20240315003',
          creator: '王五',
          createTime: '2024-03-15 15:30:00',
          sendTo: '环境监测组',
          sendTime: '2024-03-15 16:00:00'
        },
        {
          id: '4',
          projectPlan: '生物样本分析项目',
          experimentNo: 'EXP20240315004',
          experimentName: '细胞活性测试',
          sampleNo: 'SAMPLE20240315004',
          creator: '赵六',
          createTime: '2024-03-15 16:30:00',
          sendTo: '生物实验室',
          sendTime: '2024-03-15 17:00:00'
        }
      ],
      mockDraftData: [
        {
          id: '5',
          projectPlan: '化学反应监测方案',
          experimentNo: 'EXP20240316001',
          experimentName: '催化剂效率测试',
          sampleNo: 'SAMPLE20240316001',
          creator: '孙七',
          createTime: '2024-03-16 09:30:00',
          sendTo: '化学实验室',
          sendTime: '2024-03-16 10:00:00'
        },
        {
          id: '6',
          projectPlan: '药物稳定性研究方案',
          experimentNo: 'EXP20240316002',
          experimentName: '药物降解测试',
          sampleNo: 'SAMPLE20240316002',
          creator: '周八',
          createTime: '2024-03-16 11:30:00',
          sendTo: '药物研究部',
          sendTime: '2024-03-16 14:00:00'
        }
      ],
      approvalDialogVisible: false,
      approvalDialogType: 'approve',
      currentApprovalData: null,
      }
    };
  },
  computed: {
@@ -217,7 +150,11 @@
    },
    // 判断是否为化验师角色
    isChemist() {
      return this.userRole === 'chemist';
      return this.userRole == '4';
    },
    // 判断是否为工艺工程师角色
    isProcessEngineer() {
      return this.userRole == '3'; // 假设工艺工程师的角色代码为2
    }
  },
  created() {
@@ -225,11 +162,17 @@
    this.getTableData();
  },
  methods: {
    getSampleStatus(row) {
      const send = row.sendCount || 0;
      const receive = row.receiveCount || 0;
      const received = row.receivedCount || 0;
      const total = send + receive + received;
      return `${total} / ${receive} / ${received}`;
    },
    // 获取用户角色
    async getUserRole() {
      // TODO: 从用户信息或接口中获取角色
      // 示例:this.userRole = await getUserRole();
      this.userRole = 'chemist'; // 临时写死,实际应该从接口获取
    getUserRole() {
      const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}');
      this.userRole = userInfo.roleType || '';
    },
    resetForm() {
      this.form = {
@@ -250,79 +193,44 @@
        projectName: this.form.projectName,
        startTime: this.form.createTime[0] || null,
        endTime: this.form.createTime[1] || null,
        status: this.form.status,
        status: this.currentType == 'draft' ? -1 : this.form.status,
        pageNum: this.form.pageNum,
        pageSize: this.form.pageSize
      };
      try {
        const res = await getList(params)
        this.tableData = res.records || [];
        this.total = res.total || 0;
        this.tableData = res.data.records || [];
        this.total = res.data.total || 0;
      } catch (error) {
        console.error("查询失败:", error);
      }
    },
    getStatusType(status) {
      const statusMap = {
        pending: "warning",
        rejected: "danger",
        approved: "success",
        archived: "info",
        draft: "info"
      };
      return statusMap[status] || "info";
    },
    getStatusText(status) {
      const statusMap = {
        pending: "待审批",
        rejected: "已驳回",
        approved: "已通过",
        archived: "已封存",
        draft: "草稿"
      };
      return statusMap[status] || "未知";
    },
    handleAddSample() {
      this.$router.push({
        path: "/sampleManage/addSample",
      });
    },
    handleApprove(row) {
      this.currentApprovalData = row;
      this.approvalDialogType = 'approve';
      this.approvalDialogVisible = true;
    },
    handleApproveSubmit(data) {
      // 处理审批通过
      console.log('审批通过:', data);
      this.approvalDialogVisible = false;
      this.$message.success('审批通过成功');
      this.getTableData();
    },
    handleRejectSubmit(data) {
      // 处理审批驳回
      console.log('审批驳回:', data);
      this.approvalDialogVisible = false;
      this.$message.success('审批驳回成功');
      this.getTableData();
    },
    handleRevokeApprove(row) {
      // 实现撤销审批逻辑
      console.log("撤销审批数据:", row);
    },
    handleEdit(row) {
      // 实现编辑逻辑
      console.log("编辑数据:", row);
      this.$router.push({
        path: "/sampleManage/addSample",
        query: {
          id: row.id,
          type: 'edit'
        }
      });
    },
    handleDelete(row) {
      // 实现删除逻辑
      console.log("删除数据:", row);
      this.currentOperationRow = row;
      this.changeStatusTitle = "确认要删除这条信息吗?";
      this.changeStatusTip = "删除后信息无法找回";
      this.changeStatus = true;
    },
    handleDetail(id) {
      this.$router.push({
        path: "/sampleManage/addSample",
        query: {
          id: id
          id: id,
          type: 'detail'
        }
      });
    },
@@ -332,6 +240,26 @@
    },
    getTableData() {
      this.handleSearch();
    },
    handlePageChange(pageNum) {
      this.form.pageNum = pageNum;
      this.getTableData();
    },
    handleSizeChange(pageSize) {
      this.form.pageSize = pageSize;
      this.getTableData();
    },
    handleChangeStatusConfirm() {
      // 处理删除逻辑
      deleteById({
        id: this.currentOperationRow.id
      }).then(() => {
        this.$message.success("删除成功");
        this.changeStatus = false;
        this.getTableData();
      }).catch(error => {
        this.$message.error("删除失败");
      });
    },
  },
};
@@ -355,28 +283,22 @@
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #dcdfe6;
    padding: 16px 29px;
    font-weight: bold;
    font-weight: 400;
    font-size: 18px;
    color: #606266;
    width: unset;
    cursor: pointer;
  }
  .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;
  }
  .active{
    color: #049c9a;
    background: #ffffff;
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #049c9a;
    margin-right: 16px;
    &:last-child {
      margin-right: 0;
    }
    &.active {
      color: #049c9a;
      background: #ffffff;
      border-radius: 8px 8px 0px 0px;
      border: 1px solid #049c9a;
      font-weight: bold;
    }
  }
}
</style>
laboratory/src/views/dataManagement/sampleManage/service.js
@@ -2,10 +2,47 @@
// 列表
export const getList = (data) => {
  return axios.post('/t-sampling-record/api/t-sampling-record/pageList', { ...data })
  return axios.post('/api/t-sampling-record/pageList', { ...data })
}
// 详情
export const getDetail = (data) => {
  return axios.get('/open/t-sampling-record/getDetailById', { params:data })
}
//添加
export const add = (data) => {
  return axios.post('/api/t-sampling-record/add', { ...data })
}
//修改
export const update = (data) => {
  return axios.post('/api/t-sampling-record/update', { ...data })
}
//删除
export const deleteById = (data) => {
  return axios.delete('/open/t-sampling-record/deleteById', { params:data })
}
//批量删除
export const deleteByIds = (data) => {
  return axios.delete('/open/t-sampling-record/deleteByIds', { params:data })
}
// 获取实验调度分页列表
// 实验员提交记录
export const commitRecord = (data) => {
  return axios.post('/api/t-sampling-record/commitRecord', { params:data })
}
// 修改取样操作记录
export const updateRecordOperation = (data) => {
  return axios.post('/api/t-sampling-record/updateRecordOperation', { params:data })
}
// 批量收样
export const batchCollectSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchCollectSamples', { ...data })
}
// 批量送样
export const batchSendSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchSendSamples', { params:data })
}
// 获取实验调度列表
export const getDispatchList = (data) => {
  return axios.post('/t-experiment-dispatch/api/t-experiment-dispatch/pageList', { ...data })
}
  return axios.post('/api/t-experiment-dispatch/pageList', { params:data })
}
laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue
@@ -1,10 +1,33 @@
<template>
  <Card>
    <div class="header-title-left">
      <img src="@/assets/public/headercard.png" />
      <div>所属实验调度</div>
    </div>
    <Table :data="schedulingData" :total="0" :height="null">
      <template>
        <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>
      </template>
    </Table>
    <div class="header-title-left" style="margin-top: 38px">
      <img src="@/assets/public/headercard.png" />
      <span>基础信息</span>
    </div>
    <div class="number">取样单编号:213421241</div>
    <div class="number">取样单编号:{{ detailData.samplingCode || '-' }}</div>
    <div class="header-title-left" style="margin-top: 38px">
      <img src="@/assets/public/headercard.png" />
      <span>取样操作记录</span>
@@ -18,109 +41,46 @@
    </div>
    <Table :data="sampleData" :total="sampleTotal" :height="null">
      <template>
        <el-table-column prop="index" label="序号" width="80"></el-table-column>
        <el-table-column
          prop="processTime"
          label="工艺时间"
          width="120"
        ></el-table-column>
        <el-table-column
          prop="sampleName"
          label="取样名称"
          width="150"
        ></el-table-column>
        <el-table-column
          prop="sampleCode"
          label="取样样品编号"
          width="150"
        ></el-table-column>
        <el-table-column
          prop="temperature"
          label="温度"
          width="100"
        ></el-table-column>
        <el-table-column prop="ph" label="PH" width="100"></el-table-column>
        <el-table-column
          prop="waterAmount"
          label="加水量"
          width="100"
        ></el-table-column>
        <el-table-column type="index" label="序号" width="80"></el-table-column>
        <el-table-column prop="processTime" label="工艺时间" width="150"></el-table-column>
        <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
        <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
        <el-table-column prop="temperature" label="温度" width="150"></el-table-column>
        <el-table-column prop="samplePh" label="PH" width="150"></el-table-column>
        <el-table-column prop="waterAddition" label="加水量" width="150"></el-table-column>
        <template v-if="showAdditives">
          <el-table-column
            prop="additive1"
            label="加辅1"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive2"
            label="加辅2"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive3"
            label="加辅3"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive4"
            label="加辅4"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive5"
            label="加辅5"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive6"
            label="加辅6"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive7"
            label="加辅7"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive8"
            label="加辅8"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive9"
            label="加辅9"
            width="150"
          ></el-table-column>
          <el-table-column
            prop="additive10"
            label="加辅10"
            width="150"
          ></el-table-column>
          <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
          <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
          <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
          <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
        </template>
        <el-table-column
          prop="sampleAmount"
          label="取样量"
          width="100"
        ></el-table-column>
        <el-table-column
          prop="sampleTime"
          label="取样时间"
          width="150"
        ></el-table-column>
        <el-table-column
          prop="remark"
          label="拍照"
          width="100"
        ></el-table-column>
        <el-table-column
          prop="operator"
          label="操作人员"
          width="100"
        ></el-table-column>
        <el-table-column prop="sampleAmount" label="取样量" width="150"></el-table-column>
        <el-table-column prop="pictures" label="拍照" width="150">
          <template slot-scope="scope">
            <template v-if="scope.row.pictures">
              <el-image
                v-for="(url, index) in scope.row.pictures.split(',')"
                :key="index"
                :src="url"
                :preview-src-list="[url]"
                style="width: 50px; height: 50px;"
              />
            </template>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <el-table-column prop="handlePersonName" label="操作人员" width="150"></el-table-column>
        <el-table-column
          fixed="right"
          label="操作"
          width="100"
          v-if="type !== 'detail'"
        >
          <template slot-scope="scope">
            <el-button type="text" @click="handleEdit(scope.$index, scope.row)"
@@ -138,13 +98,13 @@
            v-model="form.remark"
            :rows="4"
            placeholder="请输入备注信息"
            :disabled="type === 'detail'"
          ></el-input>
        </el-form-item>
      </el-form>
    </div>
    <div class="add-project-footer">
    <div class="add-project-footer" v-if="type !== 'detail'">
      <el-button type="primary" class="save-btn" @click="handleSave">保存</el-button>
      <el-button>存草稿</el-button>
    </div>
    <sample-dialog
      :visible.sync="showSampleDialog"
@@ -155,6 +115,7 @@
      :visible.sync="showConfirmDialog"
      :form-data="form"
      :sample-data="sampleData"
      :detail-data="detailData"
      @confirm="handleConfirm"
    />
  </Card>
@@ -163,6 +124,8 @@
<script>
import SampleDialog from "./components/sampleDialog.vue";
import ConfirmDialog from './components/confirmDialog.vue';
import { getDetail, add, update, commitRecord } from './service';
import moment from 'moment';
export default {
  name: "ChangeRecord",
@@ -172,66 +135,57 @@
  },
  data() {
    return {
      id: null,
      type: 'add', // add-新增, edit-编辑, detail-详情
      showSampleDialog: false,
      showConfirmDialog: false,
      currentSampleData: {},
      currentEditIndex: -1,
      showAdditives: true,
      sampleData: [
        {
          index: 1,
          processTime: "2h",
          sampleName: "样品A",
          sampleCode: "SP001",
          temperature: "25℃",
          ph: "7.0",
          waterAmount: "500ml",
          additive1: "10g",
          additive2: "5g",
          additive3: "3g",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "100ml",
          sampleTime: "2024-03-20 10:00:00",
          remark: "",
          operator: "张三"
        },
        {
          index: 2,
          processTime: "4min",
          sampleName: "样品B",
          sampleCode: "SP002",
          temperature: "30℃",
          ph: "6.5",
          waterAmount: "300ml",
          additive1: "8g",
          additive2: "4g",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "50ml",
          sampleTime: "2024-03-20 10:30:00",
          remark: "",
          operator: "李四",
        },
      ],
      sampleTotal: 2,
      schedulingData: [],
      sampleData: [],
      sampleTotal: 0,
      detailData: {},
      form: {
        remark: "",
      },
      statusTypeMap: {
        '-1': 'info',
        '1': 'warning',
        '2': 'success',
        '3': 'info'
      },
      statusTextMap: {
        '-1': '草稿箱',
        '1': '待提交',
        '2': '已提交',
        '3': '已封存'
      }
    };
  },
  created() {
    this.id = this.$route.query.id;
    this.type = this.$route.query.type || 'add';
    if (this.id) {
      this.getDetailData();
    }
  },
  methods: {
    async getDetailData() {
      try {
        const res = await getDetail({ id: this.id });
        if (res) {
          this.detailData = res || {};
          this.schedulingData = [this.detailData.experimentDispatch] || [];
          this.sampleData = this.detailData.samplingRecordOperations || [];
          this.sampleTotal = this.sampleData.length;
          this.form.remark = this.detailData.remark || '';
        }
      } catch (error) {
        console.error('获取详情失败:', error);
        this.$message.error('获取详情失败');
      }
    },
    handleEdit(index, row) {
      this.currentEditIndex = index;
      this.currentSampleData = { ...row };
@@ -249,17 +203,47 @@
      this.showSampleDialog = false;
    },
    handleSave() {
      // 检查是否有取样记录
      if (this.sampleData.length === 0) {
        this.$message.warning('请至少添加一条取样记录');
        return;
      }
      // 检查每条记录的必要字段是否填写
      const invalidRecord = this.sampleData.find(record => !record.samplingName);
      if (invalidRecord) {
        this.$message.warning('请确保所有取样记录都填写了完整的取样信息(取样名称、取样编号、温度、PH、加水量、取样量、拍照)');
        return;
      }
      this.showConfirmDialog = true;
    },
    handleConfirm(signature) {
      this.submitForm(signature);
    handleConfirm(params) {
      this.submitForm(params);
    },
    submitForm(signature = null) {
      // 在这里实现表单提交逻辑
      console.log('提交表单数据', { signature });
      this.$message.success('保存成功');
      this.showConfirmDialog = false;
    }
    async submitForm(params) {
      try {
        console.log(params, 'params')
        const res = await commitRecord(params);
        console.log(res, 'res')
        if (res.code === 200) {
          this.$message.success('提交成功');
          this.showConfirmDialog = false;
          this.$router.go(-1);
        } else {
          this.$message.error(res.msg || '提交失败');
        }
      } catch (error) {
        console.error('提交失败:', error);
        this.$message.error('提交失败');
      }
    },
    getStatusType(status) {
      return this.statusTypeMap[status] || 'info';
    },
    getStatusText(status) {
      return this.statusTextMap[status] || '未知状态';
    },
  }
};
</script>
laboratory/src/views/dataManagement/sampleRecordList/components/confirmDialog.vue
@@ -13,23 +13,23 @@
            <div class="sample-info">
              <div class="info-item">
                <span class="label">项目课题方案名称:</span>
                <span class="value">{{ formData.planName }}</span>
                <span class="value">{{ detailData.experimentDispatch?.projectName || '-' }}</span>
              </div>
              <div class="info-item">
                <span class="label">申请项目执行方案编号:</span>
                <span class="value">{{ formData.planName }}</span>
                <span class="value">{{ detailData.experimentDispatch?.experimentCode || '-' }}</span>
              </div>
              <div class="info-item">
                <span class="label">实验编号:</span>
                <span class="value">{{ formData.testCode }}</span>
                <span class="value">{{ detailData.experimentDispatch?.experimentCode || '-' }}</span>
              </div>
              <div class="info-item">
                <span class="label">实验名称:</span>
                <span class="value">{{ formData.testName }}</span>
                <span class="value">{{ detailData.experimentDispatch?.experimentName || '-' }}</span>
              </div>
              <div class="info-item">
                <span class="label">取样单编号:</span>
                <span class="value">{{ formData.sampleCode }}</span>
                <span class="value">{{ detailData.samplingCode || '-' }}</span>
              </div>
            </div>
@@ -57,7 +57,7 @@
                  width="150"
                ></el-table-column>
                <el-table-column
                  prop="sampleName"
                  prop="samplingName"
                  label="取样名称"
                  width="150"
                ></el-table-column>
@@ -72,63 +72,63 @@
                  width="150"
                ></el-table-column>
                <el-table-column
                  prop="ph"
                  prop="samplePh"
                  label="PH"
                  width="150"
                ></el-table-column>
                <el-table-column
                  prop="waterAmount"
                  prop="waterAddition"
                  label="加水量"
                  width="150"
                ></el-table-column>
                <template v-if="showAdditives">
                  <el-table-column
                    prop="additive1"
                    prop="addAuxiliaryOne"
                    label="加辅1"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive2"
                    prop="addAuxiliaryTwo"
                    label="加辅2"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive3"
                    prop="addAuxiliaryThree"
                    label="加辅3"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive4"
                    prop="addAuxiliaryFour"
                    label="加辅4"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive5"
                    prop="addAuxiliaryFive"
                    label="加辅5"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive6"
                    prop="addAuxiliarySix"
                    label="加辅6"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive7"
                    prop="addAuxiliarySeven"
                    label="加辅7"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive8"
                    prop="addAuxiliaryEight"
                    label="加辅8"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive9"
                    prop="addAuxiliaryNine"
                    label="加辅9"
                    width="150"
                  ></el-table-column>
                  <el-table-column
                    prop="additive10"
                    prop="addAuxiliaryTen"
                    label="加辅10"
                    width="150"
                  ></el-table-column>
@@ -139,17 +139,22 @@
                  width="150"
                ></el-table-column>
                <el-table-column
                  prop="sampleTime"
                  label="取样时间"
                  width="150"
                ></el-table-column>
                <el-table-column
                  prop="remark"
                  prop="pictures"
                  label="拍照"
                  width="150"
                ></el-table-column>
                >
                  <template slot-scope="scope">
                    <el-image
                      v-for="(url, index) in scope.row.pictures.split(',')"
                      :key="index"
                      :src="url"
                      :preview-src-list="[url]"
                      style="width: 50px; height: 50px;"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  prop="operator"
                  prop="handlePersonName"
                  fixed="right"
                  label="操作人员"
                  width="150"
@@ -179,9 +184,7 @@
    <div slot="footer" class="dialog-footer select-member-footer">
      <el-button @click="handleClose">取 消</el-button>
      <el-button type="primary" @click="handleConfirm" :disabled="!imgSrc"
        >确 认</el-button
      >
      <el-button type="primary" @click="handleConfirm">确 认</el-button>
    </div>
    <SignatureCanvas
@@ -193,6 +196,7 @@
<script>
import SignatureCanvas from "@/components/SignatureCanvas.vue";
import moment from 'moment';
export default {
  name: "ConfirmDialog",
@@ -212,18 +216,22 @@
      type: Array,
      default: () => [],
    },
    detailData: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      signatureDialogVisible: false,
      imgSrc: "",
      imgSrc: "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
      showAdditives: true,
    };
  },
  methods: {
    handleClose() {
      this.$emit("update:visible", false);
      this.imgSrc = "";
      this.imgSrc = "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg";
    },
    openSignature() {
      this.signatureDialogVisible = true;
@@ -237,7 +245,19 @@
        this.$message.warning("请先完成签名确认");
        return;
      }
      this.$emit("confirm", this.imgSrc);
      const now = new Date().toISOString();
      const params = {
        id: this.detailData.id,
        commitPersonId: this.detailData.commitPersonId,
        commitSign: this.imgSrc,
        commitTime: moment().format('YYYY-MM-DD HH:mm:ss'),
        dispatchId: this.detailData.experimentDispatch?.id,
        samplingCode: this.detailData.samplingCode,
        remark: this.formData.remark,
        samplingRecordOperations: this.sampleData,
        status: 2 // 已提交状态
      };
      this.$emit("confirm", params);
      this.handleClose();
    },
  },
laboratory/src/views/dataManagement/sampleRecordList/components/sampleDialog.vue
@@ -23,9 +23,9 @@
          >
            <el-row :gutter="20">
              <el-col :span="12">
                <el-form-item label="取样名称" prop="sampleName">
                <el-form-item label="取样名称" prop="samplingName">
                  <el-input
                    v-model="form.sampleName"
                    v-model="form.samplingName"
                    placeholder="请输入取样名称"
                  />
                </el-form-item>
@@ -50,17 +50,17 @@
                </el-form-item>
              </el-col>
              <el-col :span="7.5">
                <el-form-item label="PH" prop="ph">
                <el-form-item label="PH" prop="samplePh">
                  <el-input
                    v-model="form.ph"
                    v-model="form.samplePh"
                    placeholder="请输入PH值"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="7.5">
                <el-form-item label="加水量" prop="waterAmount">
                <el-form-item label="加水量" prop="waterAddition">
                  <el-input
                    v-model="form.waterAmount"
                    v-model="form.waterAddition"
                    placeholder="请输入加水量"
                  />
                </el-form-item>
@@ -68,21 +68,21 @@
            </el-row>
            <el-row :gutter="20">
              <el-col :span="4.6" v-for="i in 5" :key="'additive' + i">
                <el-form-item :label="'加辅' + i" :prop="'additive' + i">
                  <el-input v-model="form['additive' + i]" placeholder="请输入" />
              <el-col :span="4.6" v-for="i in 5" :key="'addAuxiliary' + i">
                <el-form-item :label="'加辅' + i" :prop="'addAuxiliary' + (i === 1 ? 'One' : i === 2 ? 'Two' : i === 3 ? 'Three' : i === 4 ? 'Four' : 'Five')">
                  <el-input v-model="form['addAuxiliary' + (i === 1 ? 'One' : i === 2 ? 'Two' : i === 3 ? 'Three' : i === 4 ? 'Four' : 'Five')]" placeholder="请输入" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row :gutter="20">
              <el-col :span="4.6" v-for="i in 5" :key="'additive' + (i + 5)">
              <el-col :span="4.6" v-for="i in 5" :key="'addAuxiliary' + (i + 5)">
                <el-form-item
                  :label="'加辅' + (i + 5)"
                  :prop="'additive' + (i + 5)"
                  :prop="'addAuxiliary' + (i === 1 ? 'Six' : i === 2 ? 'Seven' : i === 3 ? 'Eight' : i === 4 ? 'Nine' : 'Ten')"
                >
                  <el-input
                    v-model="form['additive' + (i + 5)]"
                    v-model="form['addAuxiliary' + (i === 1 ? 'Six' : i === 2 ? 'Seven' : i === 3 ? 'Eight' : i === 4 ? 'Nine' : 'Ten')]"
                    placeholder="请输入"
                  />
                </el-form-item>
@@ -110,7 +110,7 @@
              <el-col :span="24">
                <el-form-item
                  label="拍照"
                  prop="fileList"
                  prop="pictures"
                  :rules="[
                    { required: true, message: '请上传照片', trigger: 'change' },
                  ]"
@@ -121,6 +121,10 @@
                    :file-list="fileList"
                    :auto-upload="false"
                    list-type="picture-card"
                    :on-change="handleChange"
                    :on-remove="handleRemove"
                    :before-upload="beforeUpload"
                    multiple
                  >
                    <i class="el-icon-plus"></i>
                  </el-upload>
@@ -139,6 +143,8 @@
</template>
<script>
import { updateRecordOperation } from '../service'
export default {
  name: "SampleDialog",
  props: {
@@ -155,25 +161,26 @@
    return {
      form: {
        processTime: "",
        sampleName: "",
        samplingName: "",
        sampleCode: "",
        temperature: "",
        ph: "",
        waterAmount: "",
        additive1: "",
        additive2: "",
        additive3: "",
        additive4: "",
        additive5: "",
        additive6: "",
        additive7: "",
        additive8: "",
        additive9: "",
        additive10: "",
        samplePh: "",
        waterAddition: "",
        addAuxiliaryOne: "",
        addAuxiliaryTwo: "",
        addAuxiliaryThree: "",
        addAuxiliaryFour: "",
        addAuxiliaryFive: "",
        addAuxiliarySix: "",
        addAuxiliarySeven: "",
        addAuxiliaryEight: "",
        addAuxiliaryNine: "",
        addAuxiliaryTen: "",
        sampleAmount: "",
        pictures: "",
      },
      rules: {
        sampleName: [
        samplingName: [
          { required: true, message: "请输入取样名称", trigger: "blur" },
        ],
        sampleCode: [
@@ -182,12 +189,13 @@
        temperature: [
          { required: true, message: "请输入温度", trigger: "blur" },
        ],
        ph: [{ required: true, message: "请输入PH值", trigger: "blur" }],
        waterAmount: [
        samplePh: [{ required: true, message: "请输入PH值", trigger: "blur" }],
        waterAddition: [
          { required: true, message: "请输入加水量", trigger: "blur" },
        ],
      },
      fileList: [],
      defaultImage: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
    };
  },
  watch: {
@@ -195,6 +203,14 @@
      handler(val) {
        if (val) {
          this.form = { ...this.form, ...val };
          // 如果有图片数据,设置到fileList中
          if (val.pictures) {
            const imageUrls = val.pictures.split(',');
            this.fileList = imageUrls.map((url, index) => ({
              name: `sample-image-${index + 1}.png`,
              url: url
            }));
          }
        }
      },
      immediate: true,
@@ -206,17 +222,69 @@
      this.form = this.$options.data().form;
      this.fileList = [];
    },
    handleSubmit() {
      this.$refs.form.validate((valid) => {
    // 上传前校验
    beforeUpload(file) {
      const isImage = file.type.startsWith('image/');
      const isLt2M = file.size / 1024 / 1024 < 2;
      if (!isImage) {
        this.$message.error('只能上传图片文件!');
        return false;
      }
      if (!isLt2M) {
        this.$message.error('图片大小不能超过 2MB!');
        return false;
      }
      return true;
    },
    // 文件状态改变时的钩子
    handleChange(file, fileList) {
      this.fileList = fileList;
      // 更新pictures字段
      if (fileList.length === 0) {
        this.form.pictures = this.defaultImage;
      } else {
        const imageUrls = fileList.map(file => file.url || this.defaultImage);
        this.form.pictures = imageUrls.join(',');
      }
    },
    // 移除文件时的钩子
    handleRemove(file, fileList) {
      this.fileList = fileList;
      // 更新pictures字段
      if (fileList.length === 0) {
        this.form.pictures = this.defaultImage;
      } else {
        const imageUrls = fileList.map(file => file.url || this.defaultImage);
        this.form.pictures = imageUrls.join(',');
      }
    },
    async handleSubmit() {
      this.$refs.form.validate(async (valid) => {
        if (valid) {
          const submitData = {
            ...this.form,
            sampleTime: new Date().toISOString(),
            operator: window._userInfo?.name || "",
            handlePersonId: JSON.parse(sessionStorage.getItem('userInfo') || '{}').userId || "",
            handlePersonName: JSON.parse(sessionStorage.getItem('userInfo') || '{}').nickName || "",
            fileList: this.fileList,
          };
          this.$emit("submit", submitData);
          this.handleClose();
          try {
            // 先调用updateRecordOperation接口保存数据
            const res = await updateRecordOperation(submitData);
            if (res.code === 200) {
              // 保存成功,继续执行原来的提交逻辑
              this.$emit("submit", submitData);
              this.handleClose();
            } else {
              this.$message.error(res.msg || '保存失败');
            }
          } catch (error) {
            console.error('保存失败:', error);
            this.$message.error('保存失败,请重试');
          }
        }
      });
    },
laboratory/src/views/dataManagement/sampleRecordList/list.vue
@@ -1,58 +1,53 @@
<template>
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total">
    <TableCustom :queryForm="form" :height="null" :tableData="tableData" :total="total" @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange">
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="所属项目课题方案:">
            <el-input v-model="form.planName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="实验名称:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
            <el-input v-model="form.projectName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="实验编号:">
            <el-input v-model="form.planCode" placeholder="请输入"></el-input>
            <el-input v-model="form.experimentCode" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="创建时间:">
            <el-date-picker
              v-model="form.createTime"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="yyyy-MM-dd"
            ></el-date-picker>
          </el-form-item>
          <el-form-item label="状态:">
            <el-input v-model="form.approver" placeholder="请输入"></el-input>
            <el-select v-model="form.status" placeholder="请选择">
              <el-option label="全部" :value="''"></el-option>
              <el-option label="待提交" :value="1"></el-option>
              <el-option label="已提交" :value="2"></el-option>
              <el-option label="已封存" :value="3"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="primary" @click="handleSearch" style="margin-left: 10px;">查询</el-button>
          </el-form-item>
        </el-form>
      </template>
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center">
            <div
            class="title"
              :class="{active:currentType === 'list'}"
              @click="handleTypeChange('list')"
            >{{ type === 'draft' ? '草稿箱' : '取样操作记录列表' }}</div>
            <div class="title active">取样操作记录列表</div>
          </div>
        </div>
      </template>
      <template #table>
        <el-table-column
          prop="planName"
          label="所属项目课题方案"
          v-for="(column, index) in columns"
          :key="index"
          :prop="column.prop"
          :label="column.label"
        ></el-table-column>
        <el-table-column
          prop="experimentNo"
          label="实验编号"
        ></el-table-column>
        <el-table-column
          prop="experimentName"
          label="实验名称"
        ></el-table-column>
        <el-table-column
          prop="sampleNo"
          label="取样单编号"
        ></el-table-column>
        <el-table-column prop="creator" label="创建人"></el-table-column>
        <el-table-column prop="createTime" label="创建时间"></el-table-column>
        <el-table-column prop="status" label="当前状态">
        <el-table-column prop="status" label="状态">
          <template slot-scope="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
@@ -61,88 +56,41 @@
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template slot-scope="scope">
            <el-button
              type="text"
              @click="handleEdit(scope.row)"
              >编辑</el-button>
            <el-button
              type="text"
              @click="handleDetail(scope.row)"
              >详情</el-button>
            <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
            <el-button type="text" @click="handleEdit(scope.row.id)" v-if="scope.row.status == 1">编辑</el-button>
          </template>
        </el-table-column>
      </template>
    </TableCustom>
    <!-- 审批弹窗 -->
    <!-- <approval-dialog
      :visible.sync="approvalDialogVisible"
      :type="approvalDialogType"
      :data="currentApprovalData"
      @approve="handleApproveSubmit"
      @reject="handleRejectSubmit"
    /> -->
  </div>
</template>
<script>
// import ApprovalDialog from './components/approvalDialog.vue'
import { getList } from './service'
export default {
  name: "ProjectList",
  components: {
    // ApprovalDialog
  },
  data() {
    return {
      type: 'list',
      currentType: 'list',
      form: {
        planName: "",
        planCode: "",
        creator: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        createTime: [],
        approver: "",
        status: "",
        status: '',
        pageNum: 1,
        pageSize: 10
      },
      tableData: [],
      total: 0,
      // 模拟数据
      mockListData: [
        {
          planName: '2024年度实验室设备升级方案',
          experimentNo: '31423764',
          experimentName: '设备性能测试',
          sampleNo: '2024-05-28',
          creator: '刘大大',
          createTime: '2025-1-2 16:27:17',
          status: 'pending'
        }
      ],
      mockDraftData: [
        {
          planCode: 'DRAFT-2024-001',
          planName: '实验室设备采购计划(草稿)',
          stage: '规划阶段',
          creator: '张三',
          createTime: '2024-03-16',
          status: 'draft',
          approver: '',
          approveTime: ''
        },
        {
          planCode: 'DRAFT-2024-002',
          planName: '实验室改造方案(草稿)',
          stage: '准备阶段',
          creator: '李四',
          createTime: '2024-03-15',
          status: 'draft',
          approver: '',
          approveTime: ''
        }
      ],
      approvalDialogVisible: false,
      approvalDialogType: 'approve',
      currentApprovalData: null,
      columns: [
        { prop: 'projectName', label: '所属项目课题方案' },
        { prop: 'experimentCode', label: '实验编号' },
        { prop: 'experimentName', label: '实验名称' },
        { prop: 'samplingCode', label: '取样单编号' },
        { prop: 'createBy', label: '创建人' },
        { prop: 'createTime', label: '创建时间' }
      ]
    };
  },
  created() {
@@ -151,103 +99,82 @@
  methods: {
    resetForm() {
      this.form = {
        planName: "",
        planCode: "",
        creator: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        createTime: [],
        approver: "",
        status: "",
        status: '',
        pageNum: 1,
        pageSize: 10
      };
      this.handleSearch();
    },
    handleSearch() {
      // 实现查询逻辑
      console.log("查询条件:", this.form);
    async handleSearch() {
      const params = {
        experimentCode: this.form.experimentCode,
        experimentName: this.form.experimentName,
        projectName: this.form.projectName,
        startTime: this.form.createTime[0] || null,
        endTime: this.form.createTime[1] || null,
        status: this.form.status,
        pageNum: this.form.pageNum,
        pageSize: this.form.pageSize
      };
      try {
        const res = await getList(params)
        this.tableData = res.data.records || [];
        this.total = res.data.total || 0;
      } catch (error) {
        console.error("查询失败:", error);
      }
    },
    getStatusType(status) {
      const statusMap = {
        pending: "warning",
        rejected: "danger",
        approved: "success",
        archived: "info",
        draft: "info"
        '-1': 'info',
        '1': 'warning',
        '2': 'success',
        '3': 'info'
      };
      return statusMap[status] || "info";
      return statusMap[status] || 'info';
    },
    getStatusText(status) {
      const statusMap = {
        pending: "待审批",
        rejected: "已驳回",
        approved: "已通过",
        archived: "已封存",
        draft: "草稿"
        '-1': '草稿箱',
        '1': '待提交',
        '2': '已提交',
        '3': '已封存'
      };
      return statusMap[status] || "未知";
      return statusMap[status] || '未知';
    },
    handleAddSample() {
      this.$router.push({
        path: "/sampleManage/changeRecord",
      });
    },
    handleApprove(row) {
      this.currentApprovalData = row;
      this.approvalDialogType = 'approve';
      this.approvalDialogVisible = true;
    },
    handleApproveSubmit(data) {
      // 处理审批通过
      console.log('审批通过:', data);
      this.approvalDialogVisible = false;
      this.$message.success('审批通过成功');
      this.getTableData();
    },
    handleRejectSubmit(data) {
      // 处理审批驳回
      console.log('审批驳回:', data);
      this.approvalDialogVisible = false;
      this.$message.success('审批驳回成功');
      this.getTableData();
    },
    handleRevokeApprove(row) {
      // 实现撤销审批逻辑
      console.log("撤销审批数据:", row);
    },
    handleEdit(row) {
    handleDetail(id) {
      this.$router.push({
        path: "/sampleManage/changeRecord",
        query: {
          type: 'edit',
          id: row.id
          id: id,
          type: 'detail'
        }
      });
    },
    handleDelete(row) {
      // 实现删除逻辑
      console.log("删除数据:", row);
    },
    handleDetail(row) {
    handleEdit(id) {
      this.$router.push({
        path: "/sampleManage/changeRecord",
        query: {
          type: 'view',
          id: row.id
          id: id,
          type: 'edit'
        }
      });
    },
    handleTypeChange(type) {
      this.currentType = type;
      this.type = type;
      this.getTableData();
    },
    getTableData() {
      // 根据currentType请求不同的数据
      if (this.currentType === 'list') {
        this.tableData = this.mockListData;
        this.total = this.mockListData.length;
      } else {
        this.tableData = this.mockDraftData;
        this.total = this.mockDraftData.length;
      }
      this.handleSearch();
    },
    handlePageChange(pageNum) {
      this.form.pageNum = pageNum;
      this.getTableData();
    },
    handleSizeChange(pageSize) {
      this.form.pageSize = pageSize;
      this.getTableData();
    }
  },
};
</script>
@@ -270,28 +197,18 @@
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #dcdfe6;
    padding: 16px 29px;
    font-weight: bold;
    font-weight: 400;
    font-size: 18px;
    color: #606266;
    width: unset;
    cursor: pointer;
  }
  .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;
  }
  .active{
    color: #049c9a;
    background: #ffffff;
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #049c9a;
    &.active {
      color: #049c9a;
      background: #ffffff;
      border-radius: 8px 8px 0px 0px;
      border: 1px solid #049c9a;
      font-weight: bold;
    }
  }
}
</style>
laboratory/src/views/dataManagement/sampleRecordList/service.js
New file
@@ -0,0 +1,48 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-sampling-record/pageList', { ...data })
}
// 详情
export const getDetail = (data) => {
  return axios.get('/open/t-sampling-record/getDetailById', { params:data })
}
//添加
export const add = (data) => {
  return axios.post('/api/t-sampling-record/add', { ...data })
}
//修改
export const update = (data) => {
  return axios.post('/api/t-sampling-record/update', { ...data })
}
//删除
export const deleteById = (data) => {
  return axios.delete('/open/t-sampling-record/deleteById', { params:data })
}
//批量删除
export const deleteByIds = (data) => {
  return axios.delete('/open/t-sampling-record/deleteByIds', { params:data })
}
// 实验员提交记录
export const commitRecord = (data) => {
  return axios.post('/api/t-sampling-record/commitRecord', { ...data })
}
// 修改取样操作记录
export const updateRecordOperation = (data) => {
  return axios.post('/api/t-sampling-record/updateRecordOperation', { ...data })
}
// 批量收样
export const batchCollectSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchCollectSamples', { params:data })
}
// 批量送样
export const batchSendSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchSendSamples', { params:data })
}
// 获取实验调度列表
export const getDispatchList = (data) => {
  return axios.post('/api/t-experiment-dispatch/pageList', { params:data })
}
laboratory/src/views/dataManagement/sampleSubmissionList/components/receiveConfirmDialog.vue
@@ -75,14 +75,16 @@
    },
    handleSignatureConfirm(imageData) {
      this.signatureDialogVisible = false;
      this.imgSrc = imageData;
      // this.imgSrc = imageData;
      this.imgSrc = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg';
    },
    handleConfirm() {
      if (!this.imgSrc) {
        this.$message.warning("请先完成签名确认");
        return;
      }
      this.$emit("confirm", this.imgSrc);
      const defaultSignature = 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg';
      this.$emit("confirm", this.imgSrc || defaultSignature);
      this.handleClose();
    },
  },
laboratory/src/views/dataManagement/sampleSubmissionList/list.vue
@@ -1,70 +1,50 @@
<template>
  <div class="list">
    <TableCustom :queryForm="form" :tableData="tableData" :total="total">
    <TableCustom :queryForm="form" :height="null" :tableData="tableData" :total="total"
      @handlePageChange="handlePageChange" @handleSizeChange="handleSizeChange">
      <template #search>
        <el-form :model="form" labelWidth="auto" inline>
          <el-form-item label="所属项目课题方案:">
            <el-input v-model="form.planName" placeholder="请输入"></el-input>
            <el-input v-model="form.projectName" placeholder="请输入"></el-input>
          </el-form-item>
          <el-form-item label="实验编号:">
            <el-input
              v-model="form.planCode"
              placeholder="请输入"
            ></el-input> </el-form-item
          ><el-form-item label="实验名称:">
            <el-input v-model="form.planCode" 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.approver" placeholder="请输入"></el-input>
            <el-select v-model="form.status" placeholder="请选择">
              <el-option label="全部" :value="''"></el-option>
              <el-option label="待提交" :value="1"></el-option>
              <el-option label="已提交" :value="2"></el-option>
              <el-option label="已封存" :value="3"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="">
            <el-button type="default" @click="resetForm">重置</el-button>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button type="primary" @click="handleSearch" style="margin-left: 10px;">查询</el-button>
          </el-form-item>
        </el-form>
      </template>
      <template #setting>
        <div class="tableTitle">
          <div class="flex a-center">
            <div class="title">
              取样操作记录列表
            </div>
            <div class="title active">取样操作记录列表</div>
          </div>
        </div>
      </template>
      <template #table>
        <el-table-column
          prop="planName"
          label="所属项目课题方案"
        ></el-table-column>
        <el-table-column
          prop="experimentNo"
          label="实验编号"
        ></el-table-column>
        <el-table-column
          prop="experimentName"
          label="实验名称"
        ></el-table-column>
        <el-table-column
          prop="sampleNo"
          label="取样单编号"
        ></el-table-column>
        <el-table-column
          prop="creator"
          label="创建人"
        ></el-table-column>
        <el-table-column
          prop="createTime"
          label="创建时间"
        ></el-table-column>
        <el-table-column
          prop="sampleStatus"
          label="样品总数/待送达/待接收/已接收"
        ></el-table-column>
        <el-table-column label="操作" width="100">
        <el-table-column v-for="(column, index) in columns" :key="index" :prop="column.prop"
          :label="column.label"></el-table-column>
        <el-table-column label="样品总数/待送达/待接收/已接收">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
            {{ getSampleStatus(scope.row) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="150">
          <template slot-scope="scope">
            <el-button type="text" @click="handleDetail(scope.row.id)">详情</el-button>
          </template>
        </el-table-column>
      </template>
@@ -82,6 +62,7 @@
<script>
// import ApprovalDialog from './components/approvalDialog.vue'
import { getList } from './service'
export default {
  name: "ProjectList",
@@ -91,48 +72,23 @@
  data() {
    return {
      form: {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        status: '',
        pageNum: 1,
        pageSize: 10
      },
      tableData: [],
      total: 0,
      // 模拟数据
      mockListData: [
        {
          planCode: "PLAN-2024-001",
          planName: "2024年度实验室设备升级方案",
          stage: "规划阶段",
          creator: "张三",
          createTime: "2024-03-15",
          status: "pending",
          approver: "李四",
          approveTime: "2024-03-16",
        },
        {
          planCode: "PLAN-2024-002",
          planName: "实验室安全管理制度更新方案",
          stage: "实施阶段",
          creator: "王五",
          createTime: "2024-03-14",
          status: "approved",
          approver: "赵六",
          approveTime: "2024-03-15",
        },
        {
          planCode: "PLAN-2024-003",
          planName: "实验室人员培训计划",
          stage: "准备阶段",
          creator: "孙七",
          createTime: "2024-03-13",
          status: "rejected",
          approver: "周八",
          approveTime: "2024-03-14",
        },
      ],
      columns: [
        { prop: 'projectName', label: '所属项目课题方案' },
        { prop: 'experimentCode', label: '实验编号' },
        { prop: 'experimentName', label: '实验名称' },
        { prop: 'samplingCode', label: '取样单编号' },
        { prop: 'createBy', label: '创建人' },
        { prop: 'createTime', label: '创建时间' }
      ]
    };
  },
  created() {
@@ -141,33 +97,86 @@
  methods: {
    resetForm() {
      this.form = {
        planName: "",
        planCode: "",
        creator: "",
        createTime: [],
        approver: "",
        status: "",
        experimentCode: "",
        experimentName: "",
        projectName: "",
        status: '',
        pageNum: 1,
        pageSize: 10
      };
      this.handleSearch();
    },
    handleSearch() {
      // 实现查询逻辑
      console.log("查询条件:", this.form);
      this.getTableData();
    async handleSearch() {
      const params = {
        experimentCode: this.form.experimentCode,
        experimentName: this.form.experimentName,
        projectName: this.form.projectName,
        status: this.form.status,
        pageNum: this.form.pageNum,
        pageSize: this.form.pageSize
      };
      try {
        const res = await getList(params)
        this.tableData = res.data.records || [];
        this.total = res.data.total || 0;
      } catch (error) {
        console.error("查询失败:", error);
      }
    },
    handleDetail(row) {
    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] || '未知';
    },
    handleDetail(id) {
      this.$router.push({
        path: "/sampleManage/submission",
        query: {
          id: row.id,
          type: 'view'
          id: id,
          type: 'detail'
        }
      });
    },
    handleEdit(id) {
      this.$router.push({
        path: "/sampleManage/submission",
        query: {
          id: id,
          type: 'edit'
        }
      });
    },
    getTableData() {
      // 获取列表数据
      this.tableData = this.mockListData;
      this.total = this.mockListData.length;
      this.handleSearch();
    },
    handlePageChange(pageNum) {
      this.form.pageNum = pageNum;
      this.getTableData();
    },
    handleSizeChange(pageSize) {
      this.form.pageSize = pageSize;
      this.getTableData();
    },
    getSampleStatus(row) {
      const send = row.sendCount || 0;
      const receive = row.receiveCount || 0;
      const received = row.receivedCount || 0;
      const total = send + receive + received;
      return `${total} / ${send} / ${receive} / ${received}`;
    }
  },
};
</script>
@@ -176,15 +185,18 @@
.list {
  height: 100%;
}
.flex {
  display: flex;
  align-items: center;
}
.tableTitle {
  display: flex;
  padding-bottom: 20px;
  justify-content: space-between;
  align-items: center;
  .title {
    background: #ffffff;
    border-radius: 8px 8px 0px 0px;
laboratory/src/views/dataManagement/sampleSubmissionList/service.js
New file
@@ -0,0 +1,48 @@
import axios from '@/utils/request';
// 列表
export const getList = (data) => {
  return axios.post('/api/t-sampling-record/pageList', { ...data })
}
// 详情
export const getDetail = (data) => {
  return axios.get('/open/t-sampling-record/getDetailById', { params:data })
}
//添加
export const add = (data) => {
  return axios.post('/api/t-sampling-record/add', { ...data })
}
//修改
export const update = (data) => {
  return axios.post('/api/t-sampling-record/update', { ...data })
}
//删除
export const deleteById = (data) => {
  return axios.delete('/open/t-sampling-record/deleteById', { params:data })
}
//批量删除
export const deleteByIds = (data) => {
  return axios.delete('/open/t-sampling-record/deleteByIds', { params:data })
}
// 实验员提交记录
export const commitRecord = (data) => {
  return axios.post('/api/t-sampling-record/commitRecord', { ...data })
}
// 修改取样操作记录
export const updateRecordOperation = (data) => {
  return axios.post('/api/t-sampling-record/updateRecordOperation', { params:data })
}
// 批量收样
export const batchCollectSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchCollectSamples', { params:data })
}
// 批量送样
export const batchSendSamples = (data) => {
  return axios.post('/open/t-sampling-record/batchSendSamples', { ...data })
}
// 获取实验调度列表
export const getDispatchList = (data) => {
  return axios.post('/api/t-experiment-dispatch/pageList', { params:data })
}
laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue
@@ -4,16 +4,22 @@
      <img src="@/assets/public/headercard.png" />
      <div>所属实验调度</div>
    </div>
    <Table :data="schedulingData" :total="schedulingTotal" :height="null">
    <Table :data="schedulingData" :total="0" :height="null" >
      <template>
        <el-table-column prop="planCode" label="所属项目课题方案" width="150"></el-table-column>
        <el-table-column prop="experimentCode" label="实验编号" width="150"></el-table-column>
        <el-table-column prop="experimentName" label="实验名称" width="150"></el-table-column>
        <el-table-column prop="notifyTime" label="通知时间" width="150"></el-table-column>
        <el-table-column prop="startTime" label="实验开始时间" width="150"></el-table-column>
        <el-table-column prop="endTime" label="实验结束时间" width="150"></el-table-column>
        <el-table-column prop="participants" label="参加人员" width="150"></el-table-column>
        <el-table-column prop="status" label="状态" width="100"></el-table-column>
        <el-table-column prop="projectName" label="所属项目课题方案" width="200"></el-table-column>
        <el-table-column prop="experimentCode" label="实验编号" width="200"></el-table-column>
        <el-table-column prop="experimentName" label="实验名称" width="200"></el-table-column>
        <el-table-column prop="experimentDate" label="通知时间" width="200"></el-table-column>
        <el-table-column prop="experimentStartTime" label="实验开始时间" width="200"></el-table-column>
        <el-table-column prop="experimentEndTime" label="实验结束时间" width="200"></el-table-column>
        <el-table-column prop="participantsName" label="参加人员" width="200"></el-table-column>
        <el-table-column prop="status" label="状态" width="150">
          <template slot-scope="scope">
            <el-tag :type="getStatusType(scope.row.status)">
              {{ getStatusText(scope.row.status) }}
            </el-tag>
          </template>
        </el-table-column>
      </template>
    </Table>
@@ -36,40 +42,52 @@
        <div class="table-header">
          <el-button type="primary" class="batch-send" @click="handleBatchSend">批量发送</el-button>
        </div>
        <Table :data="sampleList" :total="sampleTotal" :height="null" @selection-change="handleSelectionChange">
        <Table :data="sampleList" :total="sampleTotal" :height="null"
         @selection-change="handleSelectionChange">
          <template>
            <el-table-column type="selection" width="55"></el-table-column>
            <el-table-column prop="index" label="序号" width="80"></el-table-column>
            <el-table-column prop="processTime" label="工艺时间间/h" width="120"></el-table-column>
            <el-table-column prop="sampleName" label="取样名称" width="150"></el-table-column>
            <el-table-column type="selection" width="55" :selectable="isSelectable"></el-table-column>
            <el-table-column type="index"  label="序号" width="80"></el-table-column>
            <el-table-column prop="processTime" label="工艺时间" width="120"></el-table-column>
            <el-table-column prop="samplingName" label="取样名称" width="150"></el-table-column>
            <el-table-column prop="sampleCode" label="取样样品编号" width="150"></el-table-column>
            <el-table-column prop="temperature" label="温度" width="100"></el-table-column>
            <el-table-column prop="ph" label="PH" width="100"></el-table-column>
            <el-table-column prop="waterAmount" label="加水量" width="100"></el-table-column>
            <el-table-column prop="samplePh" label="PH" width="100"></el-table-column>
            <el-table-column prop="waterAddition" label="加水量" width="100"></el-table-column>
            <template v-if="showAdditives">
              <el-table-column prop="additive1" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="additive2" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="additive3" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="additive4" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="additive5" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="additive6" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="additive7" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="additive8" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="additive9" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="additive10" label="加辅10" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryOne" label="加辅1" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTwo" label="加辅2" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryThree" label="加辅3" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFour" label="加辅4" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryFive" label="加辅5" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySix" label="加辅6" width="150"></el-table-column>
              <el-table-column prop="addAuxiliarySeven" label="加辅7" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryEight" label="加辅8" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryNine" label="加辅9" width="150"></el-table-column>
              <el-table-column prop="addAuxiliaryTen" label="加辅10" width="150"></el-table-column>
            </template>
            <el-table-column prop="sampleAmount" label="取样量" width="100"></el-table-column>
            <el-table-column prop="sampleTime" label="取样时间" width="150"></el-table-column>
            <el-table-column prop="photo" label="拍照" width="100">
            <el-table-column prop="pictures" label="拍照" width="100">
              <template slot-scope="scope">
                <img v-if="scope.row.photo" :src="scope.row.photo" class="sample-photo" />
                <el-image
                  v-for="(url, index) in scope.row.pictures.split(',')"
                  :key="index"
                  :src="url"
                  :preview-src-list="[url]"
                  style="width: 50px; height: 50px;"
                />
              </template>
            </el-table-column>
            <el-table-column prop="operator" label="操作人" width="100"></el-table-column>
            <el-table-column prop="status" label="状态" width="100"></el-table-column>
            <el-table-column prop="handlePersonName" label="操作人员" width="100"></el-table-column>
            <el-table-column prop="status" label="状态" width="100" fixed="right">
              <template slot-scope="scope">
                <el-tag :type="getSampleStatusType(scope.row.status)">
                  {{ getSampleStatusText(scope.row.status) }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="100" fixed="right">
              <template slot-scope="scope">
                <el-button type="text" @click="handleSend(scope.row)" v-if="scope.row.status === '待发送'">发送</el-button>
                <el-button type="text" @click="handleSend(scope.row)" v-if="scope.row.status == '1'">发送</el-button>
              </template>
            </el-table-column>
          </template>
@@ -87,6 +105,7 @@
<script>
import ReceiveConfirmDialog from './components/receiveConfirmDialog.vue'
import { getDetail, commitRecord, batchSendSamples, sendSample } from './service'
export default {
  name: "SampleSubmission",
@@ -95,131 +114,114 @@
  },
  data() {
    return {
      id: null,
      showReceiveConfirm: false,
      showAdditives: true,
      schedulingData: [{
        planCode: 'DD-EX001',
        experimentCode: 'DD-EX001',
        experimentName: '名称名称名称',
        notifyTime: '2025-1-2 14:50:19',
        startTime: '2025-02-27',
        endTime: '2025-06-06',
        participants: '张弘, 李天浩, 陈三, 李四',
        status: '已确认'
      }],
      schedulingTotal: 1,
      schedulingData: [],
      schedulingTotal: 0,
      form: {
        sampleCode: "DD-25010BS01",
        sampleCode: "",
      },
      sampleList: [
        {
          index: 1,
          processTime: "2",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "34",
          ph: "34",
          waterAmount: "34",
          additive1: "10g",
          additive2: "5g",
          additive3: "3g",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "34",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo1.jpg",
          operator: "张三",
          status: "待发送"
        },
        {
          index: 2,
          processTime: "4",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "23",
          ph: "23",
          waterAmount: "23",
          additive1: "8g",
          additive2: "4g",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "23",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo2.jpg",
          operator: "李四",
          status: "待接收"
        },
        {
          index: 3,
          processTime: "8",
          sampleName: "名称名称名称",
          sampleCode: "314234321",
          temperature: "23",
          ph: "23",
          waterAmount: "23",
          additive1: "",
          additive2: "",
          additive3: "",
          additive4: "",
          additive5: "",
          additive6: "",
          additive7: "",
          additive8: "",
          additive9: "",
          additive10: "",
          sampleAmount: "23",
          sampleTime: "2025-1-9 15:26:08",
          photo: "@/assets/sample-photos/photo3.jpg",
          operator: "王五",
          status: "已接收"
        }
      ],
      sampleTotal: 3,
      selectedSamples: []
      sampleList: [],
      sampleTotal: 0,
      selectedSamples: [],
      statusTypeMap: {
        '-1': 'info',
        '1': 'warning',
        '2': 'success',
        '3': 'info'
      },
      statusTextMap: {
        '-1': '草稿箱',
        '1': '待提交',
        '2': '已提交',
        '3': '已封存'
      },
      sampleStatusTypeMap: {
        '1': 'warning',
        '2': 'info',
        '3': 'success'
      },
      sampleStatusTextMap: {
        '1': '待发送',
        '2': '待接收',
        '3': '已接收'
      }
    };
  },
  created() {
    this.id = this.$route.query.id;
    if (this.id) {
      this.getDetailData();
    }
  },
  methods: {
    async getDetailData() {
      try {
        const res = await getDetail({ id: this.id });
        if (res) {
          this.schedulingData = [res.experimentDispatch] || [];
          this.schedulingTotal = this.schedulingData.length;
          this.form.sampleCode = res.samplingCode || '';
          this.sampleList = res.samplingRecordOperations || [];
          this.sampleTotal = this.sampleList.length;
        }
      } catch (error) {
        console.error('获取详情失败:', error);
        this.$message.error('获取详情失败');
      }
    },
    handleSelectionChange(selection) {
      this.selectedSamples = selection;
    },
    handleSend(row) {
    async handleSend(row) {
      this.selectedSamples = [row];
      this.showReceiveConfirm = true;
    },
    handleBatchSend() {
      if (this.selectedSamples.length === 0) {
    async handleBatchSend() {
      if (this.selectedSamples.length == 0) {
        this.$message.warning('请先选择要发送的样品');
        return;
      }
      this.showReceiveConfirm = true;
    },
    confirmSend(signature) {
      // 处理发送确认逻辑
      const sampleIds = this.selectedSamples.map(item => item.id);
      console.log('发送样品', { sampleIds, signature });
      // 更新状态
      this.selectedSamples.forEach(sample => {
        const index = this.sampleList.findIndex(item => item.id === sample.id);
        if (index > -1) {
          this.sampleList[index].status = '待接收';
    async confirmSend(signature) {
      try {
        const recordOperationIds = this.selectedSamples.map(item => item.id).join(',');
        const res = await batchSendSamples({
          recordOperationId: recordOperationIds,
          sendSign: signature
        });
        if (res.code == 200) {
          this.$message.success(`成功发送 ${this.selectedSamples.length} 个样品`);
          this.selectedSamples = [];
          this.showReceiveConfirm = false;
          // 刷新数据
          this.getDetailData();
        } else {
          this.$message.error(res.msg || '发送失败');
        }
      });
      this.$message.success(`成功发送 ${this.selectedSamples.length} 个样品`);
      this.selectedSamples = [];
    }
      } catch (error) {
        console.error('发送失败:', error);
        this.$message.error('发送失败');
      }
    },
    getStatusType(status) {
      return this.statusTypeMap[status] || 'info';
    },
    getStatusText(status) {
      return this.statusTextMap[status] || '未知状态';
    },
    isSelectable(row) {
      return row.status == '1';
    },
    getSampleStatusType(status) {
      return this.sampleStatusTypeMap[status] || 'info';
    },
    getSampleStatusText(status) {
      return this.sampleStatusTextMap[status] || '未知状态';
    },
  }
};
</script>
laboratory/src/views/reportLibrary/feasibilityReport/index.vue
@@ -30,8 +30,10 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></el-option>
                            <el-option label="待评定" value="2"></el-option>
                            <el-option label="已驳回" value="4"></el-option>
                            <el-option label="已评定" value="3"></el-option>
                            <el-option label="已撤回" value="5"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
@@ -175,7 +177,7 @@
        handleRevoke(row) {
            this.rowId = row.id
            this.changeStatusTitle = '确认要撤销审批吗?'
            this.changeStatusTip = '撤销审批后,可研报告将被撤销。'
            this.changeStatusTip = '撤销审批后,可行报告将被撤销。'
            this.changeStatus = true
        },
        handleDelConfirm() {
laboratory/src/views/reportLibrary/feasibilityStudy/index.vue
@@ -30,8 +30,10 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></el-option>
                            <el-option label="待评定" value="2"></el-option>
                            <el-option label="已驳回" value="4"></el-option>
                            <el-option label="已评定" value="3"></el-option>
                            <el-option label="已撤回" value="5"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
laboratory/src/views/reportLibrary/processDevelopment/index.vue
@@ -30,8 +30,10 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></el-option>
                            <el-option label="待评定" value="2"></el-option>
                            <el-option label="已驳回" value="4"></el-option>
                            <el-option label="已评定" value="3"></el-option>
                            <el-option label="已撤回" value="5"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
@@ -148,14 +150,14 @@
        },
        handleEdit(row) {
            this.$router.push({
                path: '/reportLibrary/edit',
                path: '/reportLibrary/editProcessDevelopment',
                query: {
                    id: row.id
                }
            })
        },
        handleAddProject() {
            this.$router.push('/reportLibrary/add')
            this.$router.push('/reportLibrary/addProcessDevelopment')
        },
        changeTab(status) {
            if (status == -1) {
@@ -175,7 +177,7 @@
        handleRevoke(row) {
            this.rowId = row.id
            this.changeStatusTitle = '确认要撤销审批吗?'
            this.changeStatusTip = '撤销审批后,可研报告将被撤销。'
            this.changeStatusTip = '撤销审批后,工艺开发工具将被撤销。'
            this.changeStatus = true
        },
        handleDelConfirm() {
laboratory/src/views/reportLibrary/processDevelopment/service.js
@@ -7,6 +7,7 @@
// 添加
export function addData(data) {
  return axios.post('/api/t-feasibility-study-report/add', { ...data })
}
laboratory/src/views/reportLibrary/projectProposalLibrary/add.vue
New file
@@ -0,0 +1,278 @@
<template>
    <div class="add-container" :loading="loading">
        <Card v-loading="loading">
            <div class="header-title" style="width: 100%;">
                <div class="header-title-left">
                    <img src="@/assets/public/headercard.png" />
                    <div>所属项目组</div>
                </div>
                <div class="header-title-right">
                    <el-button @click="showChoose = true" class="el-icon-circle-plus-outline" type="primary">
                        选择项目组</el-button>
                </div>
            </div>
            <Table :height="null" :data="tableData" :queryForm="queryForm" :total="0">
                <template>
                    <el-table-column prop="teamName" label="项目组名称" />
                    <el-table-column prop="personCharge" label="项目负责人" />
                    <el-table-column prop="staffName" label="项目组成员" />
                    <el-table-column prop="createTime" label="创建时间" />
                </template>
            </Table>
            <el-form ref="form" :model="form" :rules="rules" inline label-position="top" style="margin-top: 38px">
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告编号</div>
                    </div>
                </div>
                <el-form-item prop="reportCode" style="margin-top: 38px">
                    <el-input v-model="form.reportCode" style="width: 100%;" placeholder="请输入报告编号" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告名称</div>
                    </div>
                </div>
                <el-form-item prop="reportName" style="margin-top: 38px">
                    <el-input v-model="form.reportName" style="width: 100%;" placeholder="请输入报告名称" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告正文</div>
                    </div>
                </div>
                <el-form-item prop="reportText" style="margin-top: 38px">
                    <ai-editor ref="materialEditor" :value="form.reportText" style="width: 100%;"
                        placeholder="请输入报告正文" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div class="noRequire">附件</div>
                    </div>
                </div>
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </el-form-item>
                <div class="end-btn" style="margin-top: 38px">
                    <el-button type="primary" @click="submit" :loading="loading">发送</el-button>
                    <el-button type="default" @click="save" :loading="loading">存草稿</el-button>
                </div>
            </el-form>
        </Card>
        <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
    </div>
</template>
<script>
import { Card } from 'element-ui';
import AiEditor from '@/components/AiEditor'
import chooseProject from '@/components/chooseProject'
import { addData, getDetail, editData } from './service'
export default {
    components: {
        AiEditor,
        chooseProject
    },
    data() {
        return {
            loading: false,
            form: {
                reportCode: "",
                reportName: "",
                reportText: ""
            },
            tableData: [],
            fileList: [], // 附件列表
            showChoose: false,
            rules: {
                reportCode: [
                    { required: true, message: '请输入报告编号', trigger: 'blur' }
                ],
                reportName: [
                    { required: true, message: '请输入报告名称', trigger: 'blur' }
                ],
            },
            queryForm: {}
        }
    },
    mounted() {
        if (this.$route.query.id) {
            this.getDetail()
        }
    },
    methods: {
        getDetail() {
            getDetail(this.$route.query.id).then(res => {
                this.form = res
                this.tableData = [{ ...res.projectTeam, staffName: res.staffNames }]
                this.fileList = res.fileList
            })
        },
        //获取选择项目组数据
        getProjectData(data) {
            this.tableData = [data]
            this.$forceUpdate()
            this.showChoose = false
        },
        submit() {
            console.log(this.$refs.materialEditor.getContent());
            if (this.tableData.length == 0) {
                this.$message.error('请选择项目组')
                return
            }
            this.$refs.form.validate((valid) => {
                if (this.$refs.materialEditor.getContent() == '<p></p>') {
                    this.$message.error('请输入报告正文')
                    return
                }
                let data = {
                    ...this.form,
                    status: 1,
                    reportText: this.$refs.materialEditor.getContent(),
                    teamId: this.tableData[0].id
                }
                if (valid) {
                    this.loading = true
                    if (this.$route.query.id) {
                        editData({ ...data, id: this.$route.query.id }).then(res => {
                            if (res.code === 200) {
                                this.$message.success('修改成功')
                                this.$router.back()
                            } else {
                                this.$message.error(res.message)
                            }
                        })
                    } else {
                        addData({ ...data }).then(res => {
                            if (res.code === 200) {
                                this.$message.success('发布成功')
                                this.$router.back()
                            } else {
                                this.$message.error(res.message)
                            }
                        }).finally(() => {
                            this.loading = false
                        })
                    }
                }
            })
        },
        save() {
            this.$refs.form.validate((valid) => {
                let data = {
                    ...this.form,
                    status: -1,
                    reportText: this.$refs.materialEditor.getContent(),
                    teamId: this.tableData[0].id
                }
                delete data.id
                if (valid) {
                    this.loading = true
                    addData({ ...data }).then(res => {
                        if (res.code === 200) {
                            this.$message.success('提交成功')
                            this.$router.back()
                        } else {
                            this.$message.error(res.message)
                        }
                    }).finally(() => {
                        this.loading = false
                    })
                }
            })
        },
    },
}
</script>
<style lang="less" scoped>
.header-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 20px;
    gap: 13px;
    .header-title-left {
        display: flex;
        align-items: center;
        gap: 13px;
        margin-top: 38px;
        img {
            width: 12px;
            height: 19px;
        }
        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;
            }
        }
        .noRequire:before {
            content: unset;
            // color: #f56c6c;
            // margin-right: 4px;
        }
        span {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
        }
    }
    .header-title-left :first-child {
        margin-top: 0;
    }
}
.header-title:first-child {
    .header-title-left {
        margin-top: 0;
    }
}
.end-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    button {
        width: 180px;
        height: 36px;
        // background: #409EFF;
    }
}
</style>
laboratory/src/views/reportLibrary/projectProposalLibrary/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog :title="dialogTitle"  :visible.sync="visible" width="80%" po :close-on-click-modal="false"
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
        @close="handleClose">
        <div class="approval-dialog">
        <div class="approval-dialog" :style="{height: obj.isDetail ? '50vh' : '40vh'}">
            <!-- 左侧审批内容 -->
            <div class="approval-content">
                <Card class="approval-content-card">
@@ -12,13 +12,12 @@
                                <div>所属项目组</div>
                            </div>
                        </div>
                        <Table :height="null" :queryForm="queryForm" :total="0" @currentChange="handleCurrentChange"
                            @sizeChange="handleSizeChange">
                        <Table :height="null" :total="0" :data="tableData">
                            <template>
                                <el-table-column prop="name" label="项目组名称" />
                                <el-table-column prop="age" label="项目负责人" />
                                <el-table-column prop="age" label="项目组成员" />
                                <el-table-column prop="age" label="创建时间" />
                                <el-table-column prop="teamName" label="项目组名称" />
                                <el-table-column prop="personCharge" label="项目负责人" />
                                <el-table-column prop="staffName" label="项目组成员" />
                                <el-table-column prop="createTime" label="创建时间" />
                            </template>
                        </Table>
@@ -31,9 +30,10 @@
                                    <div>报告编号</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportCode" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                    placeholder="请输入报告编号" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -41,9 +41,10 @@
                                    <div>报告名称</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportName" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportName" style="width: 100%;"
                                    placeholder="请输入报告名称" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -51,9 +52,10 @@
                                    <div>报告正文</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportText" style="margin-top: 38px">
                                <ai-editor :readOnly="true" :value="form.reportText" style="width: 100%;"
                                    placeholder="请输入报告正文" />
                            </el-form-item>
                        </el-form>
                    </template>
@@ -63,21 +65,20 @@
            <!-- 右侧审批流程 -->
            <div class="approval-flow">
                <div class="flow-content">
                    <approval-process :status="form.status" :submit-time="form.createTime" :approver="form.approver"
                        :approve-time="form.approveTime" />
                    <approval-process :processData="form.processData" />
                </div>
            </div>
        </div>
        <div class="approval-dialog-approve">
        <div class="approval-dialog-approve" v-if="!obj.isDetail">
            <el-row :span="24">
                <el-col :span="12">
                    <div class="status">
                        <div class="status-title">审批结果</div>
                        <div class="status-content">
                            <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1">
                            <div class="resolve" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                                通过
                            </div>
                            <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                            <div class="reject" :class="status == '3' && 'activeStatus'" @click.stop="status = 3">
                                驳回
                            </div>
                        </div>
@@ -94,8 +95,8 @@
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="handleClose" >取 消</el-button>
            <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">通过</el-button>
            <el-button @click="handleClose">{{obj.isDetail ? '关闭' : '取 消'}}</el-button>
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
        </div>
    </el-dialog>
</template>
@@ -103,6 +104,8 @@
<script>
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
export default {
    name: "ApprovalDialog",
@@ -119,27 +122,33 @@
            type: String,
            default: "approve", // approve-审批,view-查看
        },
        data: {
        obj: {
            type: Object,
            default: () => ({}),
            default: () => { },
        },
    },
    data() {
        return {
            form: {
                planName: "",
                planCode: "",
                stage: "",
                creator: "",
                reportCode: "",
                reportName: "",
                reportText: "",
                teamName: "",
                createBy: "",
                createTime: "",
                status: "",
                approvalComment: "",
                status: "pending",
                approver: "",
                approveTime: ""
                approveTime: "",
                processData: [],
                updateBy: "",
                auditRemark: "",
                auditPersonName: "",
                auditTime: ""
            },
            radio1: 1,
            tableData: [],
            rules: {},
            status: "1",
            status: "2",
            remark: "",
        };
    },
@@ -148,40 +157,81 @@
            return this.type === "approve" ? "审批" : "审批详情";
        },
    },
    watch: {
        data: {
            handler(val) {
                if (val) {
                    this.form = { ...val };
                }
            },
            immediate: true,
        },
    },
    methods: {
        open() {
            if (!this.obj.id) {
                this.$message.error('缺少必要参数');
                return;
            }
            getDetail(this.obj.id).then(res => {
                const data = res.data || res;
                this.form = {
                    ...this.form,
                    ...data,
                    processData: []
                };
                this.tableData = data.projectTeam ?
                    [{ ...data.projectTeam, staffName: data.staffNames || '' }] :
                    [];
                let processData = [];
                // 提交节点
                processData.push({
                    type: "primary",
                    mode: "list",
                    fields: [
                        { label: "提交人:", value: data.updateBy || "" },
                        { label: "提交时间:", value: data.createTime || "" },
                    ]
                });
                if (data.status == 2 || data.status == 3) {
                    processData.push({
                        type: data.status === 2 ? "primary" : "danger",
                        mode: "list",
                        fields: [
                            { label: "审批意见:", value: data.auditRemark || "" },
                            { label: "审核人:", value: data.auditPersonName || "" },
                            { label: "审核时间:", value: data.auditTime || "" },
                        ]
                    });
                } else {
                    processData.push({
                        type: "warning",
                        mode: "list",
                        fields: [
                            { label: "等待审核" },
                        ],
                    });
                }
                this.form.processData = processData;
            }).catch(err => {
                this.$message.error('获取详情失败');
            });
        },
        handleClose() {
            this.$emit("close");
            this.form.approvalComment = "";
        },
        handleApprove() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("approve", {
                ...this.form,
                status: "approved",
                statuss: this.status,
                remark: this.remark
            });
        },
        handleReject() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("reject", {
                ...this.form,
                status: "rejected",
            });
        handleCurrentChange(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.form.pageSize = size
            this.getList()
        },
    },
};
@@ -211,7 +261,7 @@
        background: #ffffff;
        box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
        border-radius: 10px;
        .flow-title {
            font-size: 16px;
            font-weight: bold;
laboratory/src/views/reportLibrary/projectProposalLibrary/index.vue
@@ -1,14 +1,27 @@
<template>
    <div class="list">
        <TableCustom :queryForm="queryForm" :total="total" @currentChange="handleCurrentChange"
            @sizeChange="handleSizeChange">
        <el-card class="header-box" v-if="roleType == 3">
            <div class="box-title">
                <img src="@/assets/public/notice.png" class="header-icon"> <span>设立课题规则</span>
            </div>
            <div class="header-content">
                <p>1、根据可研报告、产品构思设计的工艺研究路线,一条工艺路线设立一个课题。如果一个课题中有多个化合物需要开发研究,则每个化合物作为一个分题;分题归集到该课题中,最终形成课题报告。不同课题报告中的分题不能重复使用。
                </p>
                <p>2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题。</p>
            </div>
        </el-card>
        <TableCustom :tableData="tableData" :height="null" :total="total" @handleCurrentChange="handleCurrentChanges"
            @handleSizeChange="handleSizeChanges">
            <template #search>
                <el-form :model="form" :label-width="auto" inline>
                <el-form :model="form" label-width="auto" inline>
                    <el-form-item label="所属项目组:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.teamName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告名称:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.reportName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告编号:">
                        <el-input v-model="form.reportCode" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="创建日期:">
                        <el-date-picker v-model="form.date" type="daterange" range-separator="至"
@@ -17,42 +30,62 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></el-option>
                            <el-option label="已通过" value="2"></el-option>
                            <el-option label="已驳回" value="3"></el-option>
                            <el-option label="已撤回" value="4"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
                        <el-button type="default">重置</el-button>
                        <el-button type="default" style="margin-right: 10px;">重置</el-button>
                        <el-button type="primary">查询</el-button>
                    </el-form-item>
                </el-form>
            </template>
            <template #setting>
                <div class="table-title">
                    立项报告库
                <el-button v-if="roleType == 3" @click="handleAddProject" class="el-icon-plus" type="primary">
                    新增立项报告库</el-button>
                <div class="table-setting">
                    <div :class="!isDraft ? 'table-title' : 'table-tit'" @click="changeTab('')">
                        立项报告库
                    </div>
                    <div v-if="roleType == 3" :class="!isDraft ? 'table-tit' : 'table-title'" @click="changeTab('-1')">
                        草稿箱
                    </div>
                </div>
            </template>
            <template #table>
                <el-table-column prop="name" label="所属项目组" />
                <el-table-column prop="age" label="报告编号" />
                <el-table-column prop="age" label="报告名称" />
                <el-table-column prop="age" label="创建人" />
                <el-table-column prop="age" label="创建时间" />
                <el-table-column prop="age" label="状态">
                <el-table-column prop="teamName" label="所属项目组" />
                <el-table-column prop="reportCode" label="报告编号" />
                <el-table-column prop="reportName" label="报告名称" />
                <el-table-column prop="createBy" label="创建人" />
                <el-table-column prop="createTime" label="创建时间" />
                <el-table-column prop="status" label="状态" v-if="!isDraft">
                    <template #default="{ row }">
                        <el-tag v-if="row.status == 1" type="success">待审核</el-tag>
                        <el-tag v-else-if="row.status == 0" type="success">已通过</el-tag>
                        <el-tag v-else type="danger">已驳回</el-tag>
                        <el-tag v-if="row.status == 1">待审核</el-tag>
                        <el-tag v-else-if="row.status == 3" type="danger">已驳回</el-tag>
                        <el-tag v-else-if="row.status == 2" type="success">已通过</el-tag>
                        <el-tag v-else-if="row.status == 4" type="info">已撤回</el-tag>
                    </template>
                </el-table-column>
                <el-table-column prop="age" label="操作">
                <el-table-column prop="options" label="操作">
                    <template #default="{ row }">
                        <el-button type="text">审核</el-button>
                        <el-button type="text">详情</el-button>
                        <el-button type="text" @click="handleApproval(row)"
                            v-if="row.status == 1 && [1, 2].includes(roleType)">审核</el-button>
                        <el-button type="text" @click="handleDetail(row)">详情</el-button>
                        <el-button type="text" @click="handleDelete(row)"
                            v-if="[4, 5].includes(row.status) && roleType == 3">删除</el-button>
                        <el-button type="text" @click="handleEdit(row)"
                            v-if="[4, 5].includes(row.status) && roleType == 3">编辑</el-button>
                        <el-button type="text" @click="handleRevoke(row)"
                            v-if="row.status == 1 && roleType == 3">撤销审批</el-button>
                    </template>
                </el-table-column>
            </template>
        </TableCustom>
        <Approval :visible="showApproval" @close="showApproval = false" :obj="rowData" @approve="handleApprove" />
        <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
        <ShowDelConfirm :title="changeStatusTitle" :tip="changeStatusTip" :show="changeStatus"
            @close="changeStatus = false" @confirm="handleChangeStatusConfirm" />
@@ -60,71 +93,209 @@
</template>
<script>
import Approval from './components/approval'
import { getDataList, audit, revokeAudit, deleteData } from './service'
export default {
    name: 'ProjectList',
    components: {
        Approval
    },
    data() {
        return {
            form: {
                name: ''
            },
            showDelConfirm: false,
            rowId: '',
            changeStatus: false,
            showApproval: false,
            changeStatusTitle: '',
            changeStatusTip: '',
            queryForm: {
            tableData: [],
            isDraft: false,
            rowData: {},
            roleType: '', // 1 超级管理员 2 审批人 3 工艺工程师 4化验师 5实验员
            form: {
                pageSize: 10,
                pageNum: 1
                pageNum: 1,
                teamName: '',
                status: '',
                startTime: '',
                reportName: '',
                reportCode: '',
                endTime: '',
                date: ''
            },
            total: 0
        }
    },
    mounted() {
        this.roleType = JSON.parse(sessionStorage.getItem('userInfo'))?.roleType
        this.getList()
    },
    methods: {
        handleAddProject() {
        handleApproval(row) {
            this.rowData = row
            this.showApproval = true
        },
        handleDetail(row) {
            row.isDetail = true
            this.rowData = row
            this.showApproval = true
        },
        handleEdit(row) {
            this.$router.push({
                path: '/projectList/addProject'
                path: '/reportLibrary/editProjectProposalLibrary',
                query: {
                    id: row.id
                }
            })
        },
        handleDel(row) {
        handleAddProject() {
            this.$router.push('/reportLibrary/addProjectProposalLibrary')
        },
        changeTab(status) {
            if (status == -1) {
                this.isDraft = true
                this.form.pageNum = 1
            } else {
                this.form.pageNum = 1
                this.isDraft = false
                this.form.status = status
            }
            this.getList()
        },
        handleDelete(row) {
            this.rowId = row.id
            this.showDelConfirm = true
        },
        handleDelConfirm() {
            this.showDelConfirm = false
            this.msgsuccess('删除成功')
            this.rowId = ''
            this.getList()
        },
        handleChangeStatus(row, status) {
        handleRevoke(row) {
            this.rowId = row.id
            this.changeStatusTitle = status == 1 ? '确认要封存这个项目组吗?' : '确认要解封该项目组吗?'
            this.changeStatusTip = status == 1 ? '封存后项目组内人员看不到数据,审批人仍然可见数据。' : '解封后项目组内人员数据恢复。'
            this.changeStatusTitle = '确认要撤销审批吗?'
            this.changeStatusTip = '撤销审批后,验证与发布将被撤销。'
            this.changeStatus = true
        },
        handleDelConfirm() {
            deleteData({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                this.rowId = ''
                this.getList()
            })
        },
        handleChangeStatusConfirm() {
            this.changeStatus = false
            this.msgsuccess('操作成功')
            this.rowId = ''
            this.changeStatusTitle = ''
            this.changeStatusTip = ''
            revokeAudit({ id: this.rowId }).then(res => {
                this.changeStatus = false
                this.$message.success('操作成功')
                this.rowId = ''
                this.changeStatusTitle = ''
                this.changeStatusTip = ''
                this.getList()
            })
        },
        handleCurrentChanges(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleCurrentChange(page) {
            this.queryForm.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.queryForm.pageSize = size
        handleSizeChanges(size) {
            this.form.pageSize = size
            this.getList()
        },
        getList() {
            let data = {}
            if (this.isDraft) {
                data = {
                    ...this.form,
                    status: -1
                }
            } else {
                data = this.form
            }
            getDataList(data).then(res => {
                if (res.code === 200) {
                    this.tableData = res.data.records || []
                    this.total = res.data.total || 0
                }
            })
        },
        handleApprove(data) {
            let params = {
                id: data.id,
                auditStatus: data.statuss,
                auditRemark: data.remark
            }
            audit({ ...params }).then(res => {
                if (res.code === 200) {
                    this.$message.success('审核成功')
                    this.showApproval = false
                    this.getList()
                }
            })
        }
    }
}
</script>
<style scoped lang="less">
.el-icon-plus {
    margin-bottom: 20px;
}
.header-content {
    font-family: PingFangSC, PingFang SC;
    font-weight: 400;
    font-size: 14px;
    color: rgba(0, 0, 0, 0.88);
    margin-left: 30px;
}
.box-title {
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
    color: #222222;
    line-height: 27px;
    display: flex;
    align-items: center;
}
.header-icon {
    width: 20px;
    height: 20px;
    margin-right: 10px;
}
.header-box {
    border-radius: 16px;
    margin-bottom: 30px;
}
.table-setting {
    display: flex;
    gap: 14px;
}
.table-tit {
    background: #FAFAFC;
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #DCDFE6;
    width: 166px;
    height: 50px;
    background: #FFFFFF;
    border-radius: 8px 8px 0px 0px;
    display: flex;
    align-items: center;
    justify-content: center;
    // margin-bottom: 21px;
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
    color: #606266;
    line-height: 27px;
}
.list {
    height: 100%;
}
@@ -138,7 +309,7 @@
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 21px;
    // margin-bottom: 21px;
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
laboratory/src/views/reportLibrary/projectProposalLibrary/service.js
New file
@@ -0,0 +1,44 @@
import axios from '@/utils/request';
// 查询列表
export function getDataList(data) {
  console.log('data11111111', data);
  return axios.post('/api/t-project-approval-report/pageList', { ...data })
}
// 添加
export function addData(data) {
  console.log('data', data);
  return axios.post('/api/t-project-approval-report/add', { ...data })
}
//修改
export function editData(data) {
  return axios.post('/api/t-project-approval-report/update', { ...data })
}
//获取详情
export function getDetail(id) {
  return axios.get(`/open/t-project-approval-report/getDetailById?id=${id}`)
}
//审核
export function audit(data) {
  return axios.post('/api/t-project-approval-report/auditReport', { ...data })
}
//撤销审批
export function revokeAudit(data) {
  return axios.put(`/open/t-project-approval-report/revokedReport?id=${data.id}`)
}
//删除
export function deleteData(data) {
  return axios.delete(`/open/t-project-approval-report/deleteById?id=${data.id}`)
}
laboratory/src/views/reportLibrary/verificationRelease/add.vue
New file
@@ -0,0 +1,278 @@
<template>
    <div class="add-container" :loading="loading">
        <Card v-loading="loading">
            <div class="header-title" style="width: 100%;">
                <div class="header-title-left">
                    <img src="@/assets/public/headercard.png" />
                    <div>所属项目组</div>
                </div>
                <div class="header-title-right">
                    <el-button @click="showChoose = true" class="el-icon-circle-plus-outline" type="primary">
                        选择项目组</el-button>
                </div>
            </div>
            <Table :height="null" :data="tableData" :queryForm="queryForm" :total="0">
                <template>
                    <el-table-column prop="teamName" label="项目组名称" />
                    <el-table-column prop="personCharge" label="项目负责人" />
                    <el-table-column prop="staffName" label="项目组成员" />
                    <el-table-column prop="createTime" label="创建时间" />
                </template>
            </Table>
            <el-form ref="form" :model="form" :rules="rules" inline label-position="top" style="margin-top: 38px">
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告编号</div>
                    </div>
                </div>
                <el-form-item prop="reportCode" style="margin-top: 38px">
                    <el-input v-model="form.reportCode" style="width: 100%;" placeholder="请输入报告编号" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告名称</div>
                    </div>
                </div>
                <el-form-item prop="reportName" style="margin-top: 38px">
                    <el-input v-model="form.reportName" style="width: 100%;" placeholder="请输入报告名称" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div>报告正文</div>
                    </div>
                </div>
                <el-form-item prop="reportText" style="margin-top: 38px">
                    <ai-editor ref="materialEditor" :value="form.reportText" style="width: 100%;"
                        placeholder="请输入报告正文" />
                </el-form-item>
                <div class="header-title" style="width: 100%;">
                    <div class="header-title-left">
                        <img src="@/assets/public/headercard.png" />
                        <div class="noRequire">附件</div>
                    </div>
                </div>
                <el-form-item prop="name" style="margin-top: 38px">
                    <el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </el-form-item>
                <div class="end-btn" style="margin-top: 38px">
                    <el-button type="primary" @click="submit" :loading="loading">发送</el-button>
                    <el-button type="default" @click="save" :loading="loading">存草稿</el-button>
                </div>
            </el-form>
        </Card>
        <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
    </div>
</template>
<script>
import { Card } from 'element-ui';
import AiEditor from '@/components/AiEditor'
import chooseProject from '@/components/chooseProject'
import { addData, getDetail, editData } from './service'
export default {
    components: {
        AiEditor,
        chooseProject
    },
    data() {
        return {
            loading: false,
            form: {
                reportCode: "",
                reportName: "",
                reportText: ""
            },
            tableData: [],
            fileList: [], // 附件列表
            showChoose: false,
            rules: {
                reportCode: [
                    { required: true, message: '请输入报告编号', trigger: 'blur' }
                ],
                reportName: [
                    { required: true, message: '请输入报告名称', trigger: 'blur' }
                ],
            },
            queryForm: {}
        }
    },
    mounted() {
        if (this.$route.query.id) {
            this.getDetail()
        }
    },
    methods: {
        getDetail() {
            getDetail(this.$route.query.id).then(res => {
                this.form = res
                this.tableData = [{ ...res.projectTeam, staffName: res.staffNames }]
                this.fileList = res.fileList
            })
        },
        //获取选择项目组数据
        getProjectData(data) {
            this.tableData = [data]
            this.$forceUpdate()
            this.showChoose = false
        },
        submit() {
            console.log(this.$refs.materialEditor.getContent());
            if (this.tableData.length == 0) {
                this.$message.error('请选择项目组')
                return
            }
            this.$refs.form.validate((valid) => {
                if (this.$refs.materialEditor.getContent() == '<p></p>') {
                    this.$message.error('请输入报告正文')
                    return
                }
                let data = {
                    ...this.form,
                    status: 1,
                    reportText: this.$refs.materialEditor.getContent(),
                    teamId: this.tableData[0].id
                }
                if (valid) {
                    this.loading = true
                    if (this.$route.query.id) {
                        editData({ ...data, id: this.$route.query.id }).then(res => {
                            if (res.code === 200) {
                                this.$message.success('修改成功')
                                this.$router.back()
                            } else {
                                this.$message.error(res.message)
                            }
                        })
                    } else {
                        addData({ ...data }).then(res => {
                            if (res.code === 200) {
                                this.$message.success('发布成功')
                                this.$router.back()
                            } else {
                                this.$message.error(res.message)
                            }
                        }).finally(() => {
                            this.loading = false
                        })
                    }
                }
            })
        },
        save() {
            this.$refs.form.validate((valid) => {
                let data = {
                    ...this.form,
                    status: -1,
                    reportText: this.$refs.materialEditor.getContent(),
                    teamId: this.tableData[0].id
                }
                delete data.id
                if (valid) {
                    this.loading = true
                    addData({ ...data }).then(res => {
                        if (res.code === 200) {
                            this.$message.success('提交成功')
                            this.$router.back()
                        } else {
                            this.$message.error(res.message)
                        }
                    }).finally(() => {
                        this.loading = false
                    })
                }
            })
        },
    },
}
</script>
<style lang="less" scoped>
.header-title {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    margin-bottom: 20px;
    gap: 13px;
    .header-title-left {
        display: flex;
        align-items: center;
        gap: 13px;
        margin-top: 38px;
        img {
            width: 12px;
            height: 19px;
        }
        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;
            }
        }
        .noRequire:before {
            content: unset;
            // color: #f56c6c;
            // margin-right: 4px;
        }
        span {
            flex-shrink: 0;
            font-weight: bold;
            font-size: 18px;
            color: #222222;
            line-height: 27px;
            font-family: "Source Han Sans CN Bold Bold";
        }
    }
    .header-title-left :first-child {
        margin-top: 0;
    }
}
.header-title:first-child {
    .header-title-left {
        margin-top: 0;
    }
}
.end-btn {
    display: flex;
    align-items: center;
    gap: 10px;
    button {
        width: 180px;
        height: 36px;
        // background: #409EFF;
    }
}
</style>
laboratory/src/views/reportLibrary/verificationRelease/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
    <el-dialog :title="dialogTitle"  :visible.sync="visible" width="80%" po :close-on-click-modal="false"
    <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
        @close="handleClose">
        <div class="approval-dialog">
        <div class="approval-dialog" :style="{height: obj.isDetail ? '50vh' : '40vh'}">
            <!-- 左侧审批内容 -->
            <div class="approval-content">
                <Card class="approval-content-card">
@@ -12,13 +12,12 @@
                                <div>所属项目组</div>
                            </div>
                        </div>
                        <Table :height="null" :queryForm="queryForm" :total="0" @currentChange="handleCurrentChange"
                            @sizeChange="handleSizeChange">
                        <Table :height="null" :total="0" :data="tableData">
                            <template>
                                <el-table-column prop="name" label="项目组名称" />
                                <el-table-column prop="age" label="项目负责人" />
                                <el-table-column prop="age" label="项目组成员" />
                                <el-table-column prop="age" label="创建时间" />
                                <el-table-column prop="teamName" label="项目组名称" />
                                <el-table-column prop="personCharge" label="项目负责人" />
                                <el-table-column prop="staffName" label="项目组成员" />
                                <el-table-column prop="createTime" label="创建时间" />
                            </template>
                        </Table>
@@ -31,9 +30,10 @@
                                    <div>报告编号</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportCode" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportCode" style="width: 100%;"
                                    placeholder="请输入报告编号" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -41,9 +41,10 @@
                                    <div>报告名称</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <el-input v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportName" style="margin-top: 38px">
                                <el-input disabled v-model="form.reportName" style="width: 100%;"
                                    placeholder="请输入报告名称" />
                            </el-form-item>
                            <div class="header-title" style="width: 100%;">
                                <div class="header-title-left">
@@ -51,9 +52,10 @@
                                    <div>报告正文</div>
                                </div>
                            </div>
                            <form-item prop="name" style="margin-top: 38px">
                                <ai-editor v-model="form.name" style="width: 100%;" placeholder="请输入报告编号" />
                            </form-item>
                            <el-form-item prop="reportText" style="margin-top: 38px">
                                <ai-editor :readOnly="true" :value="form.reportText" style="width: 100%;"
                                    placeholder="请输入报告正文" />
                            </el-form-item>
                        </el-form>
                    </template>
@@ -63,21 +65,20 @@
            <!-- 右侧审批流程 -->
            <div class="approval-flow">
                <div class="flow-content">
                    <approval-process :status="form.status" :submit-time="form.createTime" :approver="form.approver"
                        :approve-time="form.approveTime" />
                    <approval-process :processData="form.processData" />
                </div>
            </div>
        </div>
        <div class="approval-dialog-approve">
        <div class="approval-dialog-approve" v-if="!obj.isDetail">
            <el-row :span="24">
                <el-col :span="12">
                    <div class="status">
                        <div class="status-title">审批结果</div>
                        <div class="status-content">
                            <div class="resolve" :class="status == '1' && 'activeStatus'" @click.stop="status = 1">
                            <div class="resolve" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                                通过
                            </div>
                            <div class="reject" :class="status == '2' && 'activeStatus'" @click.stop="status = 2">
                            <div class="reject" :class="status == '3' && 'activeStatus'" @click.stop="status = 3">
                                驳回
                            </div>
                        </div>
@@ -94,8 +95,8 @@
        </div>
        <div slot="footer" class="dialog-footer">
            <el-button @click="handleClose" >取 消</el-button>
            <el-button type="primary" @click="handleApprove" v-if="type === 'approve'">通过</el-button>
            <el-button @click="handleClose">{{obj.isDetail ? '关闭' : '取 消'}}</el-button>
            <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
        </div>
    </el-dialog>
</template>
@@ -103,6 +104,8 @@
<script>
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
export default {
    name: "ApprovalDialog",
@@ -119,27 +122,33 @@
            type: String,
            default: "approve", // approve-审批,view-查看
        },
        data: {
        obj: {
            type: Object,
            default: () => ({}),
            default: () => { },
        },
    },
    data() {
        return {
            form: {
                planName: "",
                planCode: "",
                stage: "",
                creator: "",
                reportCode: "",
                reportName: "",
                reportText: "",
                teamName: "",
                createBy: "",
                createTime: "",
                status: "",
                approvalComment: "",
                status: "pending",
                approver: "",
                approveTime: ""
                approveTime: "",
                processData: [],
                updateBy: "",
                auditRemark: "",
                auditPersonName: "",
                auditTime: ""
            },
            radio1: 1,
            tableData: [],
            rules: {},
            status: "1",
            status: "2",
            remark: "",
        };
    },
@@ -148,40 +157,101 @@
            return this.type === "approve" ? "审批" : "审批详情";
        },
    },
    watch: {
        data: {
            handler(val) {
                if (val) {
                    this.form = { ...val };
                }
            },
            immediate: true,
        },
    },
    methods: {
        open() {
            if (!this.obj.id) {
                this.$message.error('缺少必要参数');
                return;
            }
            getDetail(this.obj.id).then(res => {
                const data = res.data || res;
                this.form = {
                    ...this.form,
                    ...data,
                    processData: []
                };
                this.tableData = data.projectTeam ?
                    [{ ...data.projectTeam, staffName: data.staffNames || '' }] :
                    [];
                let processData = [];
                // 提交节点
                processData.push({
                    type: "primary",
                    mode: "list",
                    fields: [
                        { label: "提交人:", value: data.updateBy || "" },
                        { label: "提交时间:", value: data.createTime || "" },
                    ]
                });
                if (data.status == 2 || data.status == 3) {
                    processData.push({
                        type: data.status === 2 ? "primary" : "danger",
                        mode: "list",
                        fields: [
                            { label: "审批意见:", value: data.auditRemark || "" },
                            { label: "审核人:", value: data.auditPersonName || "" },
                            { label: "审核时间:", value: data.auditTime || "" },
                        ]
                    });
                } else {
                    processData.push({
                        type: "warning",
                        mode: "list",
                        fields: [
                            { label: "等待审核" },
                        ],
                    });
                }
                if (data.status == 2) {
                    processData.push({
                        type: "warning",
                        mode: "list",
                        fields: [{ label: "等待评定" }],
                    });
                }
                if (data.status == 3) {
                    processData.push({
                        type: "success",
                        mode: "list",
                        fields: [
                            { label: "已评定" },
                            { label: "评定人:", value: data.evaluatePersonName || "" },
                            { label: "评定时间:", value: data.evaluateTime || "" }
                        ],
                    });
                }
                this.form.processData = processData;
            }).catch(err => {
                this.$message.error('获取详情失败');
            });
        },
        handleClose() {
            this.$emit("close");
            this.form.approvalComment = "";
        },
        handleApprove() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("approve", {
                ...this.form,
                status: "approved",
                statuss: this.status,
                remark: this.remark
            });
        },
        handleReject() {
            if (!this.form.approvalComment) {
                this.$message.warning("请输入审批意见");
                return;
            }
            this.$emit("reject", {
                ...this.form,
                status: "rejected",
            });
        handleCurrentChange(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.form.pageSize = size
            this.getList()
        },
    },
};
@@ -211,7 +281,7 @@
        background: #ffffff;
        box-shadow: 0px 4px 12px 4px rgba(0, 0, 0, 0.08);
        border-radius: 10px;
        .flow-title {
            font-size: 16px;
            font-weight: bold;
laboratory/src/views/reportLibrary/verificationRelease/index.vue
@@ -1,14 +1,27 @@
<template>
    <div class="list">
        <TableCustom :queryForm="queryForm" :total="total" @currentChange="handleCurrentChange"
            @sizeChange="handleSizeChange">
        <el-card class="header-box" v-if="roleType == 3">
            <div class="box-title">
                <img src="@/assets/public/notice.png" class="header-icon"> <span>设立课题规则</span>
            </div>
            <div class="header-content">
                <p>1、根据可研报告、产品构思设计的工艺研究路线,一条工艺路线设立一个课题。如果一个课题中有多个化合物需要开发研究,则每个化合物作为一个分题;分题归集到该课题中,最终形成课题报告。不同课题报告中的分题不能重复使用。
                </p>
                <p>2、在可行研究阶段,工艺开发升级,重新规划工艺研究路线,则以新规划的工艺路线方案来设定课题。</p>
            </div>
        </el-card>
        <TableCustom :tableData="tableData" :height="null" :total="total" @handleCurrentChange="handleCurrentChanges"
            @handleSizeChange="handleSizeChanges">
            <template #search>
                <el-form :model="form" :label-width="auto" inline>
                <el-form :model="form" label-width="auto" inline>
                    <el-form-item label="所属项目组:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.teamName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告名称:">
                        <el-input v-model="form.name" placeholder="请输入"></el-input>
                        <el-input v-model="form.reportName" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="报告编号:">
                        <el-input v-model="form.reportCode" placeholder="请输入"></el-input>
                    </el-form-item>
                    <el-form-item label="创建日期:">
                        <el-date-picker v-model="form.date" type="daterange" range-separator="至"
@@ -17,42 +30,64 @@
                    <el-form-item label="状态:">
                        <el-select v-model="form.status" placeholder="请选择">
                            <el-option label="待审核" value="1"></el-option>
                            <el-option label="已通过" value="0"></el-option>
                            <el-option label="已驳回" value="2"></el-option>
                            <el-option label="待评定" value="2"></el-option>
                            <el-option label="已驳回" value="4"></el-option>
                            <el-option label="已评定" value="3"></el-option>
                            <el-option label="已撤回" value="5"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="" style="margin-left: 63px;">
                        <el-button type="default">重置</el-button>
                        <el-button type="default" style="margin-right: 10px;">重置</el-button>
                        <el-button type="primary">查询</el-button>
                    </el-form-item>
                </el-form>
            </template>
            <template #setting>
                <div class="table-title">
                    验证与发布
                <el-button v-if="roleType == 3" @click="handleAddProject" class="el-icon-plus" type="primary">
                    新增验证与发布</el-button>
                <div class="table-setting">
                    <div :class="!isDraft ? 'table-title' : 'table-tit'" @click="changeTab('')">
                        验证与发布
                    </div>
                    <div v-if="roleType == 3" :class="!isDraft ? 'table-tit' : 'table-title'" @click="changeTab('-1')">
                        草稿箱
                    </div>
                </div>
            </template>
            <template #table>
                <el-table-column prop="name" label="所属项目组" />
                <el-table-column prop="age" label="报告编号" />
                <el-table-column prop="age" label="报告名称" />
                <el-table-column prop="age" label="创建人" />
                <el-table-column prop="age" label="创建时间" />
                <el-table-column prop="age" label="状态">
                <el-table-column prop="teamName" label="所属项目组" />
                <el-table-column prop="reportCode" label="报告编号" />
                <el-table-column prop="reportName" label="报告名称" />
                <el-table-column prop="createBy" label="创建人" />
                <el-table-column prop="createTime" label="创建时间" />
                <el-table-column prop="status" label="状态" v-if="!isDraft">
                    <template #default="{ row }">
                        <el-tag v-if="row.status == 1" type="success">待审核</el-tag>
                        <el-tag v-else-if="row.status == 0" type="success">已通过</el-tag>
                        <el-tag v-else type="danger">已驳回</el-tag>
                        <el-tag v-if="row.status == 1">待审核</el-tag>
                        <el-tag v-else-if="row.status == 2">待评定</el-tag>
                        <el-tag v-else-if="row.status == 4" type="danger">已驳回</el-tag>
                        <el-tag v-else-if="row.status == 3" type="success">已评定</el-tag>
                        <el-tag v-else-if="row.status == 5" type="info">已撤回</el-tag>
                    </template>
                </el-table-column>
                <el-table-column prop="age" label="操作">
                <el-table-column prop="options" label="操作">
                    <template #default="{ row }">
                        <el-button type="text">审核</el-button>
                        <el-button type="text">详情</el-button>
                        <el-button type="text" @click="handleApproval(row)"
                            v-if="row.status == 1 && [1, 2].includes(roleType)">审核</el-button>
                        <el-button type="text" @click="handleDetail(row)">详情</el-button>
                        <el-button type="text" @click="handleDelete(row)"
                            v-if="[4, 5].includes(row.status) && roleType == 3">删除</el-button>
                        <el-button type="text" @click="handleEdit(row)"
                            v-if="[4, 5].includes(row.status) && roleType == 3">编辑</el-button>
                        <el-button type="text" @click="handleRevoke(row)"
                            v-if="row.status == 1 && roleType == 3">撤销审批</el-button>
                    </template>
                </el-table-column>
            </template>
        </TableCustom>
        <Approval :visible="showApproval" @close="showApproval = false" :obj="rowData" @approve="handleApprove" />
        <ShowDelConfirm :show="showDelConfirm" @close="showDelConfirm = false" @confirm="handleDelConfirm" />
        <ShowDelConfirm :title="changeStatusTitle" :tip="changeStatusTip" :show="changeStatus"
            @close="changeStatus = false" @confirm="handleChangeStatusConfirm" />
@@ -60,71 +95,210 @@
</template>
<script>
import Approval from './components/approval'
import { getDataList, audit, revokeAudit, deleteData } from './service'
export default {
    name: 'ProjectList',
    components: {
        Approval
    },
    data() {
        return {
            form: {
                name: ''
            },
            showDelConfirm: false,
            rowId: '',
            changeStatus: false,
            showApproval: false,
            changeStatusTitle: '',
            changeStatusTip: '',
            queryForm: {
            tableData: [],
            isDraft: false,
            rowData: {},
            roleType: '', // 1 超级管理员 2 审批人 3 工艺工程师 4化验师 5实验员
            form: {
                pageSize: 10,
                pageNum: 1
                pageNum: 1,
                teamName: '',
                status: '',
                startTime: '',
                reportType: 4,
                reportName: '',
                reportCode: '',
                endTime: '',
                date: ''
            },
            total: 0
        }
    },
    mounted() {
        this.roleType = JSON.parse(sessionStorage.getItem('userInfo'))?.roleType
        this.getList()
    },
    methods: {
        handleAddProject() {
        handleApproval(row) {
            this.rowData = row
            this.showApproval = true
        },
        handleDetail(row) {
            row.isDetail = true
            this.rowData = row
            this.showApproval = true
        },
        handleEdit(row) {
            this.$router.push({
                path: '/projectList/addProject'
                path: '/reportLibrary/',
                query: {
                    id: row.id
                }
            })
        },
        handleDel(row) {
        handleAddProject() {
            this.$router.push('/reportLibrary/addProjectProposalLibrary')
        },
        changeTab(status) {
            if (status == -1) {
                this.isDraft = true
                this.form.pageNum = 1
            } else {
                this.form.pageNum = 1
                this.isDraft = false
                this.form.status = status
            }
            this.getList()
        },
        handleDelete(row) {
            this.rowId = row.id
            this.showDelConfirm = true
        },
        handleDelConfirm() {
            this.showDelConfirm = false
            this.msgsuccess('删除成功')
            this.rowId = ''
            this.getList()
        },
        handleChangeStatus(row, status) {
        handleRevoke(row) {
            this.rowId = row.id
            this.changeStatusTitle = status == 1 ? '确认要封存这个项目组吗?' : '确认要解封该项目组吗?'
            this.changeStatusTip = status == 1 ? '封存后项目组内人员看不到数据,审批人仍然可见数据。' : '解封后项目组内人员数据恢复。'
            this.changeStatusTitle = '确认要撤销审批吗?'
            this.changeStatusTip = '撤销审批后,验证与发布将被撤销。'
            this.changeStatus = true
        },
        handleDelConfirm() {
            deleteData({ id: this.rowId }).then(res => {
                this.showDelConfirm = false
                this.$message.success('删除成功')
                this.rowId = ''
                this.getList()
            })
        },
        handleChangeStatusConfirm() {
            this.changeStatus = false
            this.msgsuccess('操作成功')
            this.rowId = ''
            this.changeStatusTitle = ''
            this.changeStatusTip = ''
            revokeAudit({ id: this.rowId }).then(res => {
                this.changeStatus = false
                this.$message.success('操作成功')
                this.rowId = ''
                this.changeStatusTitle = ''
                this.changeStatusTip = ''
                this.getList()
            })
        },
        handleCurrentChanges(page) {
            this.form.pageNum = page
            this.getList()
        },
        handleCurrentChange(page) {
            this.queryForm.pageNum = page
            this.getList()
        },
        handleSizeChange(size) {
            this.queryForm.pageSize = size
        handleSizeChanges(size) {
            this.form.pageSize = size
            this.getList()
        },
        getList() {
            let data = {}
            if (this.isDraft) {
                data = {
                    ...this.form,
                    status: -1
                }
            } else {
                data = this.form
            }
            getDataList(data).then(res => {
                if (res.code === 200) {
                    this.tableData = res.data.records || []
                    this.total = res.data.total || 0
                }
            })
        },
        handleApprove(data) {
            let params = {
                id: data.id,
                auditStatus: data.statuss,
                auditRemark: data.remark
            }
            audit({ ...params }).then(res => {
                if (res.code === 200) {
                    this.$message.success('审核成功')
                    this.showApproval = false
                    this.getList()
                }
            })
        }
    }
}
</script>
<style scoped lang="less">
.el-icon-plus {
    margin-bottom: 20px;
}
.header-content {
    font-family: PingFangSC, PingFang SC;
    font-weight: 400;
    font-size: 14px;
    color: rgba(0, 0, 0, 0.88);
    margin-left: 30px;
}
.box-title {
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
    color: #222222;
    line-height: 27px;
    display: flex;
    align-items: center;
}
.header-icon {
    width: 20px;
    height: 20px;
    margin-right: 10px;
}
.header-box {
    border-radius: 16px;
    margin-bottom: 30px;
}
.table-setting {
    display: flex;
    gap: 14px;
}
.table-tit {
    background: #FAFAFC;
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #DCDFE6;
    width: 166px;
    height: 50px;
    background: #FFFFFF;
    border-radius: 8px 8px 0px 0px;
    display: flex;
    align-items: center;
    justify-content: center;
    // margin-bottom: 21px;
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
    color: #606266;
    line-height: 27px;
}
.list {
    height: 100%;
}
@@ -138,7 +312,7 @@
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 21px;
    // margin-bottom: 21px;
    font-family: SourceHanSansCN, SourceHanSansCN;
    font-weight: bold;
    font-size: 18px;
laboratory/src/views/reportLibrary/verificationRelease/service.js
New file
@@ -0,0 +1,45 @@
import axios from '@/utils/request';
// 查询列表
export function getDataList(data) {
  console.log('data111111', data);
  return axios.post('/api/t-feasibility-study-report/pageList', { ...data })
}
// 添加
export function addData(data) {
  console.log('data', data);
  return axios.post('/api/t-feasibility-study-report/add', { ...data })
}
//修改
export function editData(data) {
  return axios.post('/api/t-feasibility-study-report/update', { ...data })
}
//获取详情
export function getDetail(id) {
  return axios.get(`/open/t-feasibility-study-report/getDetailById?id=${id}`)
}
//审核
export function audit(data) {
  console.log(data)
  return axios.post('/api/t-feasibility-study-report/auditReport', { ...data })
}
//撤销审批
export function revokeAudit(data) {
  return axios.put(`/open/t-feasibility-study-report/revokedReport?id=${data.id}`)
}
//删除
export function deleteData(data) {
  return axios.delete(`/open/t-feasibility-study-report/deleteById?id=${data.id}`)
}