liding
2026-09-20 2b2fa317c30ee2de7a8b6f5fc964532031adea66
src/views/business/reportPreparation/index.vue
@@ -4,30 +4,30 @@
      <el-form :model="entity" ref="entity" size="small" :inline="true">
        <el-form-item label="报告编号" prop="code">
          <el-input v-model="entity.code" clearable placeholder="请输入" size="small"
            @keyup.enter.native="refreshTable()"></el-input>
                    @keyup.enter.native="refreshTable()"></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="queryStatus">
          <el-select v-model="entity.queryStatus" clearable size="small" @change="refreshTable()">
            <el-option v-for="(a, i) in queryStatusList" :key="i" :label="a.label" :value="a.value"></el-option>
          </el-select>
        </el-form-item>
<!--        <el-form-item label="报告类型" prop="reportType">-->
<!--          <el-select v-model="entity.reportType" clearable size="small" @change="refreshTable()">-->
<!--            <el-option v-for="item in reportTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option>-->
<!--          </el-select>-->
<!--        </el-form-item>-->
<!--        <el-form-item label="下单类别" prop="typeSource">-->
<!--          <el-select v-model="entity.typeSource" clearable size="small" @change="refreshTable()">-->
<!--            <el-option v-for="(a, i) in typeSourceList" :key="i" :label="a.label" :value="a.value"></el-option>-->
<!--          </el-select>-->
<!--        </el-form-item>-->
<!--        <el-form-item label="物料属性" prop="materialProp">-->
<!--          <el-select clearable size="small" v-model="entity.materialProp" style="width: 100%">-->
<!--            <el-option v-for="dict in dict.type.material_prop_type" :key="dict.value" :label="dict.label"-->
<!--                       :value="dict.value">-->
<!--            </el-option>-->
<!--          </el-select>-->
<!--        </el-form-item>-->
        <!--        <el-form-item label="报告类型" prop="reportType">-->
        <!--          <el-select v-model="entity.reportType" clearable size="small" @change="refreshTable()">-->
        <!--            <el-option v-for="item in reportTypeList" :key="item.value" :label="item.label" :value="item.value"></el-option>-->
        <!--          </el-select>-->
        <!--        </el-form-item>-->
        <!--        <el-form-item label="下单类别" prop="typeSource">-->
        <!--          <el-select v-model="entity.typeSource" clearable size="small" @change="refreshTable()">-->
        <!--            <el-option v-for="(a, i) in typeSourceList" :key="i" :label="a.label" :value="a.value"></el-option>-->
        <!--          </el-select>-->
        <!--        </el-form-item>-->
        <!--        <el-form-item label="物料属性" prop="materialProp">-->
        <!--          <el-select clearable size="small" v-model="entity.materialProp" style="width: 100%">-->
        <!--            <el-option v-for="dict in dict.type.material_prop_type" :key="dict.value" :label="dict.label"-->
        <!--                       :value="dict.value">-->
        <!--            </el-option>-->
        <!--          </el-select>-->
        <!--        </el-form-item>-->
        <el-form-item label="检验类别" prop="orderType">
          <el-select v-model="entity.orderType" clearable size="small" @change="refreshTable()">
            <el-option v-for="(a, i) in orderTypeList" :key="i" :label="a.label" :value="a.value"></el-option>
@@ -45,57 +45,66 @@
    </div>
    <div>
      <lims-table :tableData="valueTableData" :column="column" :page="page" :tableLoading="tableLoading"
        :isSelection="true" :handleSelectionChange="handleChange" :height="'calc(100vh - 290px)'"
        @pagination="pagination" key="valueTableData">
                  :isSelection="true" :handleSelectionChange="handleChange" :height="'calc(100vh - 290px)'"
                  @pagination="pagination" key="valueTableData">
        <div slot="action" slot-scope="scope">
<!--          <el-button size="small" type="text" @click="viewIssued(scope.row)">查看报告</el-button>-->
          <!--          <el-button size="small" type="text" @click="viewIssued(scope.row)">查看报告</el-button>-->
          <el-upload ref='upload1' style="display: inline;margin: 0 6px" :action="fileAction1 + '?id=' + scope.row.id"
            :auto-upload="true" :before-upload="fileBeforeUpload1" :headers="uploadHeader" :on-error="onError1"
            :on-success="handleSuccessUp1" :show-file-list="false" accept='.doc,.docx'>
                     :auto-upload="true" :before-upload="fileBeforeUpload1" :headers="uploadHeader" :on-error="onError1"
                     :on-success="handleSuccessUp1" :show-file-list="false" accept='.doc,.docx'>
            <el-button size="small" type="text"
              :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName">上传</el-button>
                       :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName">上传
            </el-button>
          </el-upload>
<!--          <el-button type="text" size="small" :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName"-->
<!--            @click="handleRestore(scope.row)">还原</el-button>-->
          <!--          <el-button type="text" size="small" :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName"-->
          <!--            @click="handleRestore(scope.row)">还原</el-button>-->
          <el-button type="text" size="small" @click="sendBackTask(scope.row)">退回任务</el-button>
          <el-button type="text" size="small" :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName"
            @click="sendBackTask(scope.row)">退回任务</el-button>
          <el-button type="text" size="small" :disabled="scope.row.state != 0 || nickName !== scope.row.writeUserName"
            @click="handle(scope.row)">提交</el-button>
                     @click="handle(scope.row)">提交
          </el-button>
          <el-button type="text" size="small"
            :disabled="scope.row.state == null || scope.row.state == 0 || scope.row.isExamine == 1 || nickName !== scope.row.examineUser"
            @click="handleIssued(scope.row)">审核</el-button>
                     :disabled="scope.row.state == null || scope.row.state == 0 || scope.row.isExamine == 1 || nickName !== scope.row.examineUser"
                     @click="handleIssued(scope.row)">审核
          </el-button>
          <el-button type="text" size="small"
            :disabled="scope.row.state == null || scope.row.state == 0 || scope.row.isExamine == 0 || scope.row.isExamine == null || scope.row.isRatify == 1 || nickName !== scope.row.ratifyUser"
            @click="handleApprove(scope.row)">批准</el-button>
                     :disabled="scope.row.state == null || scope.row.state == 0 || scope.row.isExamine == 0 || scope.row.isExamine == null || scope.row.isRatify == 1 || nickName !== scope.row.ratifyUser"
                     @click="handleApprove(scope.row)">批准
          </el-button>
          <el-button style="margin-left: 10px" type="text" size="small"
                     :disabled="!scope.row.url && !scope.row.urlS" @click="download(scope.row)">下载</el-button>
                     :disabled="!scope.row.url && !scope.row.urlS" @click="download(scope.row)">下载
          </el-button>
          <el-button type="text" size="small"
                     :loading="regeneratingReportId === scope.row.id"
                     :disabled="regeneratingReportId === scope.row.id"
                     @click="handleRegenerate(scope.row)">重新生成
          </el-button>
          <el-button type="text" size="small" @click="viewInspectInfo(scope.row)">原始记录</el-button>
          <el-button type="text" size="small" @click="handleFileLook(scope.row)">附件上传</el-button>
        </div>
      </lims-table>
    </div>
    <el-dialog :fullscreen="fullscreen" :modal-append-to-body="false" :visible.sync="claimVisible" title="在线编制"
      width="22cm">
               width="22cm">
      <div class="full-screen">
        <i v-if="!fullscreen" class="el-icon-full-screen" style="cursor: pointer;font-size: 18px"
          @click="fullscreen = true;"></i>
           @click="fullscreen = true;"></i>
        <img v-else alt="" src="@/assets/images/no-full.svg" style="cursor: pointer;" @click="fullscreen = false;">
      </div>
      <Word v-if="claimVisible" ref="Word" :class="{ fullscreen: fullscreen }" :value="value" style="height:70vh" />
      <Word v-if="claimVisible" ref="Word" :class="{ fullscreen: fullscreen }" :value="value" style="height:70vh"/>
      <span slot="footer" class="dialog-footer">
        <el-button @click="claimVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmClaim">确 定</el-button>
      </span>
    </el-dialog>
    <el-dialog :fullscreen="fullscreen" :modal-append-to-body="false" :visible.sync="issuedVisible" title="报告审核"
      width="80vw">
               width="80vw">
      <div class="full-screen">
        <i v-if="!fullscreen" class="el-icon-full-screen" style="cursor: pointer;font-size: 18px"
          @click="fullscreen = true;"></i>
           @click="fullscreen = true;"></i>
        <img v-else alt="" src="@/assets/images/no-full.svg" style="cursor: pointer;" @click="fullscreen = false;">
      </div>
      <div v-if="issuedVisible" style="height: 70vh;">
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;" />
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;"/>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button :disabled="loadingIssued" @click="issuedReasonVisible = true">不通过</el-button>
@@ -105,7 +114,9 @@
    <el-dialog :modal-append-to-body="false" :visible.sync="issuedReasonVisible" title="不通过原因" width="400px">
      <div class="search_thing">
        <div class="search_label">不通过原因:</div>
        <div class="search_input"><el-input v-model="reason" clearable placeholder="请输入" size="small"></el-input></div>
        <div class="search_input">
          <el-input v-model="reason" clearable placeholder="请输入" size="small"></el-input>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button :disabled="loadingIssuedReason" @click="issuedReasonVisible = false">取消</el-button>
@@ -113,14 +124,14 @@
      </span>
    </el-dialog>
    <el-dialog :fullscreen="fullscreen" :modal-append-to-body="false" :visible.sync="approveVisible" title="报告批准"
      width="80vw">
               width="80vw">
      <div class="full-screen">
        <i v-if="!fullscreen" class="el-icon-full-screen" style="cursor: pointer;font-size: 18px"
          @click="fullscreen = true;"></i>
           @click="fullscreen = true;"></i>
        <img v-else alt="" src="@/assets/images/no-full.svg" style="cursor: pointer;" @click="fullscreen = false;">
      </div>
      <div v-if="approveVisible" style="height: 70vh;">
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;" />
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;"/>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button :disabled="loadingApprove" @click="approveReasonVisible = true">不批准</el-button>
@@ -130,7 +141,9 @@
    <el-dialog :modal-append-to-body="false" :visible.sync="approveReasonVisible" title="不批准原因" width="400px">
      <div class="search_thing">
        <div class="search_label">不批准原因:</div>
        <div class="search_input"><el-input v-model="reason" clearable placeholder="请输入" size="small"></el-input></div>
        <div class="search_input">
          <el-input v-model="reason" clearable placeholder="请输入" size="small"></el-input>
        </div>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button :disabled="loadingApproveReason" @click="approveReasonVisible = false">取消</el-button>
@@ -138,7 +151,7 @@
      </span>
    </el-dialog>
    <el-dialog :close-on-click-modal="false" :visible.sync="addApproverDia" title="指定批准人员" width="400px"
      @close="closeAddApproverDia">
               @close="closeAddApproverDia">
      <div class="body" style="display: flex;padding: 10px;align-items: center;">
        <div class="search_label" style="width: 150px;"><span class="required-span">*</span>批准人:</div>
        <div class="search_input" style="width: 100%;">
@@ -154,7 +167,7 @@
      </span>
    </el-dialog>
    <el-dialog :close-on-click-modal="false" :visible.sync="addVerifyDia" title="指定审核人员" width="400px"
      @close="closeAddVerifyDia">
               @close="closeAddVerifyDia">
      <div class="body" style="display: flex;padding: 10px;align-items: center;">
        <div class="search_label" style="width: 150px;"><span class="required-span">*</span>审核人:</div>
        <div class="search_input" style="width: 100%;">
@@ -173,28 +186,46 @@
    <!--    <ShowInfo v-if="showInfoDialog" ref="showInfoDialog" :showInfoDialog="showInfoDialog"></ShowInfo>-->
    <!--报告查看-->
    <el-dialog :fullscreen="fullscreen" :modal-append-to-body="false" :visible.sync="viewIssuedVisible" title="报告查看"
      width="80vw">
               width="80vw">
      <div class="full-screen">
        <i v-if="!fullscreen" class="el-icon-full-screen" style="cursor: pointer;font-size: 18px"
          @click="fullscreen = true;"></i>
           @click="fullscreen = true;"></i>
        <img v-else alt="" src="@/assets/images/no-full.svg" style="cursor: pointer;" @click="fullscreen = false;">
      </div>
      <div v-if="viewIssuedVisible" style="height: 80vh;">
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;" />
        <onlyoffice ref="onlyoffice" :options="option" style="width: 100%;height: 100%;"/>
      </div>
    </el-dialog>
    <!--附件查看-->
    <el-dialog :visible.sync="filesDialogVisible" title="附件查看" width="80%" @closed="closeFilesLook">
      <div style="margin-bottom: 10px">
        <el-upload ref='upload' :action="fileAction" :auto-upload="true" :before-upload="fileBeforeUpload"
          :data="{ orderId: filesLookInfo.insOrderId }" :headers="uploadHeader" :on-error="onError"
          :on-success="handleSuccessUp" :show-file-list="false"
          accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar' style="width: 80px !important;">
                   :data="{ orderId: filesLookInfo.insOrderId }" :headers="uploadHeader" :on-error="onError"
                   :on-success="handleSuccessUp" :show-file-list="false"
                   accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
                   style="width: 80px !important;">
          <el-button size="small" style="height: 38px" type="primary">附件上传</el-button>
        </el-upload>
      </div>
      <lims-table :tableData="tableDataFile" :column="columnFile" height="600px"
        key="tableDataFile" :tableLoading="tableLoadingFile"></lims-table>
                  key="tableDataFile" :tableLoading="tableLoadingFile"></lims-table>
    </el-dialog>
    <el-dialog title="选择下载报告" :visible.sync="downloadDialogVisible" width="400px"
               :close-on-click-modal="false" @closed="closeDownloadDialog">
      <el-form label-width="90px">
        <el-form-item label="报告类型:">
          <el-radio-group v-model="selectedReportType">
            <el-radio :label="0">检测报告</el-radio>
            <el-radio :label="1" :disabled="!downloadRow || !downloadRow.inspectionUrl">检验报告</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="downloadDialogVisible = false">取 消</el-button>
        <el-button type="primary" :loading="downloadingReportType !== null"
                   :disabled="selectedReportType === null || downloadingReportType !== null"
                   @click="downloadSelectedReport(selectedReportType)">下 载</el-button>
      </span>
    </el-dialog>
  </div>
</template>
@@ -207,19 +238,21 @@
  downloadReport,
  examineReport,
  pageInsReport,
  regenerateReport,
  ratifyReport,
  sendBackTask,
  upReportUrl,
  writeReport,
  reportAllExport
} from "@/api/business/insReport";
import { mapGetters } from "vuex";
import { selectUserCondition } from "@/api/business/inspectionTask";
import {mapGetters} from "vuex";
import {selectUserCondition} from "@/api/business/inspectionTask";
import limsTable from "@/components/Table/lims-table.vue";
import {delFile, downFile, getFileList} from "@/api/business/rawMaterialOrder";
export default {
  name: 'ReportPreparation',
  components: { limsTable, onlyoffice },
  components: {limsTable, onlyoffice},
  dicts: ['material_prop_type'],
  data() {
    return {
@@ -255,6 +288,11 @@
      mutiList: [],
      outLoading: false,
      outExportLoading: false,
      regeneratingReportId: null,
      downloadDialogVisible: false,
      downloadRow: null,
      selectedReportType: 0,
      downloadingReportType: null,
      inLoading: false,
      addApproverDia: false, // 指定审批人员弹框
      approver: '', // 审批人员
@@ -264,19 +302,19 @@
      verifyUser: null, // 审核人员
      loadingVerify: false, // 审核人员
      typeSourceList: [
        { label: '委托下单', value: -1 },
        { label: '外购下单', value: 0 },
        { label: '原材料下单', value: 1 },
        {label: '委托下单', value: -1},
        {label: '外购下单', value: 0},
        {label: '原材料下单', value: 1},
      ],
      orderTypeList: [
        { label: '委托试验', value: 'Customer-ordered test' },
        { label: '抽检', value: '抽检' },
        {label: '委托试验', value: 'Customer-ordered test'},
        {label: '抽检', value: '抽检'},
        // { label: '进厂检验', value: '进厂检验' },
        // { label: '季度检验', value: 'Quarterly inspection' },
      ],
      reportTypeList: [
        { label: '检测报告', value: 0 },
        { label: '检验报告', value: 1 },
        {label: '检测报告', value: 0},
        {label: '检验报告', value: 1},
      ],
      showInfoDialog: false, // 产业链信息查看
      isReport: 1,
@@ -286,9 +324,9 @@
      examine: null,
      viewIssuedVisible: false,
      queryStatusList: [
        { label: '待提交', value: 0 },
        { label: '待审核', value: 1 },
        { label: '待批准', value: 2 },
        {label: '待提交', value: 0},
        {label: '待审核', value: 1},
        {label: '待批准', value: 2},
      ],
      state: 0,
      orderId: 0,
@@ -324,9 +362,9 @@
            }
          }
        },
        { label: '附件名称', prop: 'fileName' },
        { label: '上传人', prop: 'name' },
        { label: '上传时间', prop: 'createTime' },
        {label: '附件名称', prop: 'fileName'},
        {label: '上传人', prop: 'name'},
        {label: '上传时间', prop: 'createTime'},
        {
          dataType: 'action',
          fixed: 'right',
@@ -411,9 +449,9 @@
            return this.orderTypeList.find((m) => m.value == params).type;
          },
        },
        { label: "创建时间", prop: "createTime" },
        { label: "提交人", prop: "writeUserName" },
        { label: "提交时间", prop: "writeTime" },
        {label: "创建时间", prop: "createTime"},
        {label: "提交人", prop: "writeUserName"},
        {label: "提交时间", prop: "writeTime"},
        {
          label: "提交状态",
          prop: "state",
@@ -434,8 +472,8 @@
            }
          },
        },
        { label: "审核人", prop: "examineUser" },
        { label: "审核时间", prop: "examineTime" },
        {label: "审核人", prop: "examineUser"},
        {label: "审核时间", prop: "examineTime"},
        {
          label: "审核状态",
          prop: "isExamine",
@@ -460,9 +498,9 @@
            }
          },
        },
        { label: "审核备注", prop: "examineTell" },
        { label: "批准人", prop: "ratifyUser" },
        { label: "批准时间", prop: "ratifyTime" },
        {label: "审核备注", prop: "examineTell"},
        {label: "批准人", prop: "ratifyUser"},
        {label: "批准时间", prop: "ratifyTime"},
        {
          label: "批准状态",
          prop: "isRatify",
@@ -487,12 +525,12 @@
            }
          },
        },
        { label: "批准备注", prop: "ratifyTell" },
        {label: "批准备注", prop: "ratifyTell"},
        {
          fixed: "right",
          dataType: "slot",
          slot: "action",
          width: '360px',
          width: '440px',
          label: "操作"
        }
      ],
@@ -525,7 +563,7 @@
        this.valueTableData = res.data.body.records
      })
    },
    pagination({ page, limit }) {
    pagination({page, limit}) {
      this.page.current = page;
      this.page.size = limit;
      this.refreshTable();
@@ -565,7 +603,7 @@
    // 查询附件查看列表回调
    getFileList() {
      this.tableLoadingFile = true
      getFileList({ insOrderId: this.filesLookInfo.insOrderId,current: -1, size: -1 }).then(res => {
      getFileList({insOrderId: this.filesLookInfo.insOrderId, current: -1, size: -1}).then(res => {
        this.tableLoadingFile = false
        if (res.code === 200) {
          this.tableDataFile = res.data.records
@@ -607,7 +645,7 @@
        type: 'warning'
      }).then(() => {
        this.tableLoadingFile = true
        delFile({ id: row.id }).then(res => {
        delFile({id: row.id}).then(res => {
          this.tableLoadingFile = false
          this.$message.success('删除成功')
          this.getFileList()
@@ -636,7 +674,7 @@
      }
      let str = this.mutiList.map(m => m.id).join(',')
      this.outLoading = true
      downAll({ ids: str }).then(res => {
      downAll({ids: str}).then(res => {
        this.outLoading = false
        this.$download.zip(res.data, '报告.zip');
      }).catch(() => {
@@ -651,7 +689,7 @@
        ...this.entity
      }).then(res => {
        this.outExportLoading = false
        const blob = new Blob([res], { type: 'application/octet-stream' });
        const blob = new Blob([res], {type: 'application/octet-stream'});
        this.$download.saveAs(blob, "报告报表导出.xlsx");
      })
    },
@@ -749,7 +787,28 @@
      }
    },
    download(row) {
      downloadReport(row.id).then(res => {
      this.downloadRow = row
      // 历史数据只有检测报告:直接按检测报告下载,保持原有操作习惯。
      if (!row.inspectionUrl) {
        this.downloadSelectedReport(0)
        return
      }
      this.selectedReportType = 0
      this.downloadDialogVisible = true
    },
    closeDownloadDialog() {
      if (this.downloadingReportType === null) {
        this.downloadRow = null
        this.selectedReportType = 0
      }
    },
    downloadSelectedReport(reportType) {
      if (!this.downloadRow) {
        return
      }
      const row = this.downloadRow
      this.downloadingReportType = reportType
      downloadReport(row.id, reportType).then(res => {
        if (res.type && res.type.includes('application/json')) {
          const reader = new FileReader()
          reader.onload = () => {
@@ -762,11 +821,33 @@
          reader.readAsText(res)
          return
        }
        const reportUrl = row.urlS || row.url || ''
        const reportUrl = reportType === 1 ? row.inspectionUrl : (row.urlS || row.url || '')
        const filename = decodeURIComponent(reportUrl.substring(reportUrl.lastIndexOf('/') + 1)) || `${row.code}.docx`
        this.$download.saveAs(res, filename)
        this.downloadDialogVisible = false
      }).catch(() => {
        this.$message.error('报告下载失败')
      }).finally(() => {
        this.downloadingReportType = null
        if (!this.downloadDialogVisible) {
          this.downloadRow = null
        }
      })
    },
    handleRegenerate(row) {
      this.$confirm('将根据当前原始记录重新生成并覆盖系统报告,是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.regeneratingReportId = row.id
        return regenerateReport(row.id).then(() => {
          this.$message.success('报告重新生成成功')
          this.refreshTable()
        }).finally(() => {
          this.regeneratingReportId = null
        })
      }).catch(() => {
      })
    },
    // 还原操作
@@ -837,7 +918,7 @@
        type: 'warning'
      }).then(() => {
        this.upLoad = true
        sendBackTask({ id: row.id }).then(res => {
        sendBackTask({id: row.id}).then(res => {
          this.upLoad = false
          this.$message.success('退回成功!')
          this.refreshTable('page')
@@ -885,7 +966,7 @@
    },
    // 获取人员列表
    getAuthorizedPerson() {
      selectUserCondition({ type: 1 }).then((res) => {
      selectUserCondition({type: 1}).then((res) => {
        let data = [];
        res.data.forEach((a) => {
          data.push({