fix
13404089107
2025-06-27 7c11eabfecc120d1ac3db9047d899ca22566c335
fix
6个文件已修改
1个文件已添加
202 ■■■■■ 已修改文件
culture/src/components/SignatureCanvas.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/service.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/strain-library-manage/add.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/strain-library-manage/components/AddRecordDialog.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/strain-library-manage/components/StrainDetail.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
culture/src/components/SignatureCanvas.vue
@@ -1,27 +1,11 @@
<template>
  <el-dialog
    title="确认签字"
    :visible.sync="visible"
    :width="dialogWidth"
    :close-on-click-modal="false"
    custom-class="signature-dialog"
    append-to-body
    @close="$emit('update:visible', false)"
  >
  <el-dialog title="确认签字" :visible.sync="visible" :width="dialogWidth" :close-on-click-modal="false"
    custom-class="signature-dialog" append-to-body @close="$emit('update:visible', false)">
    <div class="signature-container">
      <div class="signature-content">
        <canvas
          ref="signatureCanvas"
          :width="canvasWidth"
          :height="canvasHeight"
          @mousedown="startDrawing"
          @mousemove="draw"
          @mouseup="stopDrawing"
          @mouseleave="stopDrawing"
          @touchstart="handleTouchStart"
          @touchmove="handleTouchMove"
          @touchend="stopDrawing"
        ></canvas>
        <canvas ref="signatureCanvas" :width="canvasWidth" :height="canvasHeight" @mousedown="startDrawing"
          @mousemove="draw" @mouseup="stopDrawing" @mouseleave="stopDrawing" @touchstart="handleTouchStart"
          @touchmove="handleTouchMove" @touchend="stopDrawing"></canvas>
      </div>
      <div class="signature-footer">
        <el-button type="default" @click="clearCanvas">重置</el-button>
@@ -32,6 +16,8 @@
</template>
<script>
import { customUploadRequest, getFullUrl } from '@/utils/utils'
import {editSignPicture} from './service'
export default {
  name: 'SignatureCanvas',
  props: {
@@ -91,11 +77,11 @@
      this.context.lineWidth = 2
      this.context.lineCap = 'round'
      this.context.lineJoin = 'round'
      // 清空画布并绘制虚线边框
      this.clearCanvas()
    },
    drawDashedBorder() {
      const ctx = this.context
      ctx.setLineDash([5, 5])
@@ -114,16 +100,16 @@
    draw(event) {
      if (!this.isDrawing) return
      const rect = this.$refs.signatureCanvas.getBoundingClientRect()
      const x = event.clientX - rect.left
      const y = event.clientY - rect.top
      this.context.beginPath()
      this.context.moveTo(this.lastX, this.lastY)
      this.context.lineTo(x, y)
      this.context.stroke()
      this.lastX = x
      this.lastY = y
      this.hasDrawn = true
@@ -141,17 +127,17 @@
    handleTouchMove(event) {
      event.preventDefault()
      if (!this.isDrawing) return
      const touch = event.touches[0]
      const rect = this.$refs.signatureCanvas.getBoundingClientRect()
      const x = touch.clientX - rect.left
      const y = touch.clientY - rect.top
      this.context.beginPath()
      this.context.moveTo(this.lastX, this.lastY)
      this.context.lineTo(x, y)
      this.context.stroke()
      this.lastX = x
      this.lastY = y
      this.hasDrawn = true
@@ -170,7 +156,7 @@
    confirmSignature() {
      const canvas = this.$refs.signatureCanvas
      const ctx = this.context
      // 校验是否签名
      if (this.isCanvasBlank()) {
        this.$message && this.$message.warning('请先确认签名')
@@ -178,24 +164,58 @@
      }
      // 保存当前画布内容
      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
      // 先填充背景色
      ctx.fillStyle = 'rgba(239, 248, 250, 1)'
      ctx.fillRect(0, 0, canvas.width, canvas.height)
      // 创建一个临时画布来保存签名内容
      const tempCanvas = document.createElement('canvas')
      tempCanvas.width = canvas.width
      tempCanvas.height = canvas.height
      const tempCtx = tempCanvas.getContext('2d')
      tempCtx.putImageData(imageData, 0, 0)
      // 将签名内容绘制到主画布上
      ctx.drawImage(tempCanvas, 0, 0)
      // 导出图片
      const signatureImage = canvas.toDataURL('image/png')
      this.$emit('confirm', 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg')
      // 导出图片为base64
      const base64Data = canvas.toDataURL('image/png');
      // base64转blob
      const blob = this.dataURLtoBlob(base64Data);
      // 新增:生成带时间戳的文件名
      const timestamp = Date.now();
      const fileName = `signature_${timestamp}.png`;
      const file = new File([blob], fileName, { type: blob.type });
      // 上传
      customUploadRequest({
        file,
        onSuccess: (res) => {
          // 假设返回的图片路径为 res.url
          const url = res.msg || res.data || res
          editSignPicture({ signPicture: res.msg }).then(res => {
            if (res.code == 200) {
              this.$message.success('签名成功');
              this.$emit('confirm', url);
            }
          })
        },
        onError: (err) => {
          this.$message && this.$message.error ? this.$message.error('上传签名失败') : alert('上传签名失败');
        }
      });
    },
        // 新增:base64转blob
        dataURLtoBlob(dataurl) {
      const arr = dataurl.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },
    // 新增方法:判断画布是否为空白
@@ -215,6 +235,7 @@
  :deep(.el-dialog__body) {
    padding: 0;
  }
  :deep(.el-dialog) {
    margin-top: 10vh !important;
  }
@@ -223,12 +244,12 @@
.signature-container {
  background: #fff;
  border-radius: 4px;
  .signature-content {
    padding: 20px;
    display: flex;
    justify-content: center;
    canvas {
      border-radius: 4px;
      background: rgba(239, 248, 250, 1);
@@ -236,16 +257,17 @@
      height: 100%;
    }
  }
  .signature-footer {
    padding: 20px;
    border-top: 1px solid #dcdfe6;
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    button{
    button {
      width: 150px;
    }
  }
}
</style>
</style>
culture/src/components/service.js
New file
@@ -0,0 +1,10 @@
import axios from '@/utils/request';
// 列表
export const editSignPicture = (data) => {
  console.log(data)
  return axios.post('/api/system/user/editSignPicture', { ...data })
}
export const queryDetail = (data) => {
  return axios.get('/system/user/queryDetail',)
}
culture/src/views/strain-library/strain-library-manage/add.vue
@@ -80,6 +80,7 @@
import SignatureCanvas from '@/components/SignatureCanvas.vue'
import { add, edit, getDetail, addBatch } from './service'
export default {
    name: 'StrainLibraryManageAdd',
    components: {
culture/src/views/strain-library/strain-library-manage/components/AddRecordDialog.vue
@@ -29,7 +29,7 @@
          </template>
          <div class="signature-area" :class="{ 'waiting': !formData.handleSignature }">
            <template v-if="formData.handleSignature">
              <img :src="formData.handleSignature" alt="操作人签字" />
              <el-image :src="getFullUrl(formData.handleSignature)" :preview-src-list="[getFullUrl(formData.handleSignature)]"  alt="操作人签字" />
            </template>
            <template v-else>
              <span class="waiting-text">等待确认</span>
@@ -48,6 +48,7 @@
<script>
import SignatureCanvas from '@/components/SignatureCanvas.vue'
import { getFullUrl } from "@/utils/utils";
export default {
  name: 'AddRecordDialog',
  components: { SignatureCanvas },
@@ -67,6 +68,11 @@
    }
  },
  methods: {
    getFullUrl(url){
      if(url){
        return getFullUrl(url);
      }
    },
    handleClose() {
      this.$emit('update:visible', false)
      this.$emit('close')
culture/src/views/strain-library/strain-library-manage/components/StrainDetail.vue
@@ -1,14 +1,7 @@
<template>
  <div>
    <el-dialog
      :title="`${title}详情`"
      :visible.sync="visible"
      width="70%"
      :close-on-click-modal="false"
      custom-class="strain-detail-dialog"
      @close="$emit('update:visible', false)"
      @opened="fetchDetail"
    >
    <el-dialog :title="`${title}详情`" :visible.sync="visible" width="70%" :close-on-click-modal="false"
      custom-class="strain-detail-dialog" @close="$emit('update:visible', false)" @opened="fetchDetail">
      <div class="strain-info">
        <!-- 第一行信息 -->
        <div class="info-row">
@@ -63,7 +56,7 @@
      </div>
      <div class="record-table">
        <div class="table-title">{{title}}出/入库记录</div>
        <div class="table-title">{{ title }}出/入库记录</div>
        <el-table :data="detail.records" style="width: 100%">
          <el-table-column label="出库/入库">
            <template #default="{ row }">
@@ -71,14 +64,16 @@
            </template>
          </el-table-column>
          <el-table-column prop="boundTime" label="操作时间" />
          <el-table-column prop="handleName" label="操作人签字" >
            <template #default="{row}">
              <img :src="row.handleSignature" v-if="row.handleSignature" alt="签字图片" style="max-width: 100px; max-height: 50px;">
          <el-table-column prop="handleName" label="操作人签字">
            <template #default="{ row }">
              <el-image :src="getFullUrl(row.handleSignature)" :preview-src-list="[getFullUrl(row.handleSignature)]"  v-if="row.handleSignature" alt="签字图片"
                style="max-width: 100px; max-height: 50px;" />
            </template>
          </el-table-column>
          <el-table-column prop="preserveSignature" label="菌种保藏人签字" >
            <template #default="{row}">
              <img :src="row.preserveSignature" v-if="row.preserveSignature" alt="签字图片" style="max-width: 100px; max-height: 50px;">
          <el-table-column prop="preserveSignature" label="菌种保藏人签字">
            <template #default="{ row }">
              <el-image :src="getFullUrl(row.preserveSignature)" :preview-src-list="[getFullUrl(row.preserveSignature)]" v-if="row.preserveSignature" alt="签字图片"
                style="max-width: 100px; max-height: 50px;" />
            </template>
          </el-table-column>
          <el-table-column label="状态">
@@ -90,39 +85,27 @@
          </el-table-column>
          <el-table-column label="操作" width="100">
            <template #default="{ row }">
              <el-button v-if="!row.confirmTime && roleType == 3" style="margin-right: 10px" type="text" @click="handleConfirm(row)">确认</el-button>
              <el-button
                type="text"
                @click="handleView(row)"
                >详情</el-button
              >
              <el-button v-if="!row.confirmTime && roleType == 3" style="margin-right: 10px" type="text"
                @click="handleConfirm(row)">确认</el-button>
              <el-button type="text" @click="handleView(row)">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
        <div class="pagination">
          <el-pagination
            :current-page.sync="currentPage"
            :page-size="10"
            layout="total, prev, pager, next"
            :total="total"
            @current-change="handlePageChange"
          />
          <el-pagination :current-page.sync="currentPage" :page-size="10" layout="total, prev, pager, next"
            :total="total" @current-change="handlePageChange" />
        </div>
      </div>
    </el-dialog>
    <RecordDetailDialog
      :visible="visibleRecordDetailDialog"
      :recordData="recordData"
      @close="handleDialogClose"
      @confirm="handleOutbound"
      :type="dialogType"
    />
    <RecordDetailDialog :visible="visibleRecordDetailDialog" :recordData="recordData" @close="handleDialogClose"
      @confirm="handleOutbound" :type="dialogType" />
  </div>
</template>
<script>
import { getDetailById,confirmWarehousing } from "../service";
import { getDetailById, confirmWarehousing } from "../service";
import { getFullUrl } from "@/utils/utils";
import RecordDetailDialog from "./RecordDetailDialog.vue";
export default {
  components: { RecordDetailDialog },
@@ -160,16 +143,22 @@
  },
  methods: {
    getFullUrl(url){
      if (url) {
        return getFullUrl(url);
      }
    },
    handleDialogClose() {
      this.recordData = {};
      this.visibleRecordDetailDialog = false;
    },
    fetchDetail() {
    this.roleType = JSON.parse(sessionStorage.getItem("userInfo")).roleType;
      this.roleType = JSON.parse(sessionStorage.getItem("userInfo")).roleType;
      this.query.id = this.detail.id;
      getDetailById(this.query).then((res) => {
        console.log('qweqweqwe',res);
        console.log('qweqweqwe', res);
        this.detail.records = res.warehousingList?.records || [];
        this.total = res.warehousingList?.total || 0;
        this.currentPage = res.warehousingList?.current || 1;
@@ -177,7 +166,7 @@
      });
    },
    handleView(row) {
        this.dialogType = "detail";
      this.dialogType = "detail";
      this.recordData = row;
      this.visibleRecordDetailDialog = true;
culture/src/views/strain-library/validation/chief-cell/index.vue
@@ -83,7 +83,7 @@
import PrimitiveCellDetailDialog from "./primitive-cell-detail-dialog.vue";
import DetailConditionDialog from "./DetailConditionDialog.vue";
import EditConditionDialog from "./EditConditionDialog.vue";
import moment from "moment";
import { getList, delOne } from "./service";
export default {
  name: "PrimitiveCell",
@@ -123,6 +123,7 @@
  },
  methods: {
    handleDetail(row) {
      row.experimentTime = moment(row.experimentTime).format('YYYY-MM-DD')
      this.currentDetail = row;
      this.detailVisible = true;
    },
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
@@ -57,6 +57,7 @@
</template>
<script>
export default {
  name: 'PrimitiveCellDetailDialog',
  props: {