Newer
Older
xc-business-system / src / views / business / manager / interchangeReceipt / detail.vue
<!-- 交接单管理详情 -->
<script name="InterchangeReceiptDetail" lang="ts" setup>
import type { Ref } from 'vue'
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules, UploadUserFile } from 'element-plus'
import dayjs from 'dayjs'
import { isKnownHtmlAttr } from '@vue/shared'
import type { IDetailTableList, IList as IOrderList } from '../order/order-interface'
import type { IForm, IList } from './interchangeReceipt-interface'
import selectOrderDialog from './dialog/selectOrderDialog.vue'
import selectEquipmentDialog from './dialog/selectEquipment.vue'
import { getSealInfoList } from '@/api/resource/seal'
import { getDictByCode } from '@/api/system/dict'
import { getUid } from '@/utils/getUid'
import scanSampleDialog from '@/components/ScanSampleDialog/index.vue'
import type { deptType, dictType } from '@/global'
import { useCheckList } from '@/commonMethods/useCheckList'
import { useDoubleClickTableRow, useSetAllRowReadable } from '@/commonMethods/useSetAllRowReadable'
import useUserStore from '@/store/modules/user'
import { listPageApi } from '@/api/system/tool'
import { getOrderDetail } from '@/api/business/manager/order'
import { getAllDeptList, getDept, getDeptTreeList } from '@/api/system/dept'
import {
  addInterchangeReceipt,
  getInterchangeReceiptDetail,
  getStream,
  updateInterchangeReceipt,
} from '@/api/business/manager/interchangeReceipt'
import { getUserList } from '@/api/system/user'
import { toTreeList } from '@/utils/structure'
import canvasDialog from '@/components/canvas/canvasDialog.vue'
import { uploadApi } from '@/api/system/notice'
import { printJSON, printPdf } from '@/utils/printUtils'
const textMap: { [key: string]: string } = {
  edit: '编辑',
  add: '新建',
  detail: '详情',
}// 页面类型字典
const user = useUserStore() // 用户信息
const pageType = ref('add') // 页面类型: add, edit, detail
const infoId = ref('') // id
const pdfStream = ref() as any // pdf流
const ruleFormRef = ref() // 表单ref
// 表单
const form: Ref<IForm> = ref({
  id: '', // 系统编号
  createUserId: '', // 创建人id
  createUserName: '', // 创建人名称
  createTime: '', // 创建时间
  orderNo: '', // 任务单编号
  orderId: '', // 任务单编号
  orderDeliverer: '', // 预计送检人
  customerId: '', // 委托方id
  customerNo: '', // 委托方代码
  customerName: '', // 委托方名称
  orderDelivererTel: '', // 委托方电话
  deptId: '', // 使用部门id
  deptName: '', // 使用部门名称
  requireOverTime: '', // 要求检完时间
  customerAddress: '', // 委托方地址
  isUrgent: '', // 是否加急
  maintainMajor: '', // 检修专业
  measureCompany: '', // 检定校准单位

  interchangeNo: '', // 交接单编号
  interchangeType: '', // 交接单类型 1收入交接单、2归还交接单
  deliverer: '', // 实际送检人
  delivererTel: '', // 实际送检人电话
  delivererDeptId: '', // 送检人/取件人部门id
  delivererDeptName: '', // 送检人/取件人部门名称
  deviceTotal: '', // 设备总量
  printSignature: '', // 打印签字
  signatureTime: '', // 签名时间
})
const rules = reactive<FormRules>({ // 表单验证规则
  orderNo: [{ required: true, message: '任务单编号不能为空', trigger: ['change', 'blur'] }],
  deliverer: [{ required: true, message: '送检人不能为空', trigger: 'blur' }],
  delivererTel: [{ required: true, message: '电话不能为空', trigger: 'change' }],
  delivererDeptId: [{ required: true, message: '送检人/取件人部门名称不能为空', trigger: 'change' }],
  interchangeType: [{ required: true, message: '交接单类型不能为空', trigger: ['change', 'blur'] }],
})

// -------------------------------------------字典------------------------------------------
const isUrgentList = ref<dictType[]>([]) // 是否加急
const userList = ref<{ [key: string]: string }[]>([]) // 用户列表
const interchangeTypeList = ref<{ [key: string]: string }[]>([]) // 交接单类型
const useDeptList = ref<deptType[]>([]) // 所属部门列表
const receiveCompanyList = ref<dictType[]>([]) // 印章
const meterIdentifyDict = ref({}) as any // 计量标识

// 获取字典值
async function getDict() {
  // 计量标识
  const responseEqptMeterIdentify = await getDictByCode('eqptMeterIdentify')
  responseEqptMeterIdentify.data.forEach((item: { name: string; value: string }) => {
    meterIdentifyDict.value[item.value] = item.name
  })

  // 是否加急
  const response = await getDictByCode('isUrgent')
  isUrgentList.value = response.data

  const res = await getDictByCode('interchangeReceiptSealNo')
  receiveCompanyList.value = res.data

  // 获取用户列表
  getUserList({ offset: 1, limit: 999999 }).then((res: any) => {
    userList.value = res.data.rows
  })
  // 交接单类型
  getDictByCode('interchangeType').then((res: any) => {
    interchangeTypeList.value = res.data.filter((item: { name: string }) => item.name === '设备收入交接单' || item.name === '设备归还交接单')
  })
  // 获取部门列表
  // getDeptTreeList().then((res) => {
  //   // 转成树结构
  //   useDeptList.value = toTreeList(res.data.map((item: any) => ({ ...item, label: item.name, value: item.id })))
  // })
  getAllDeptList().then((res) => {
    useDeptList.value = toTreeList(res.data.map((item: any) => ({ ...item, label: item.name, value: item.id }))) as any
  })
}
// -----------------------------------------路由参数----------------------------------------
// 从路由中获取页面类型参数
const $route = useRoute()
if ($route.params && $route.params.type) {
  pageType.value = $route.params.type as string
  if ($route.params.id) {
    infoId.value = $route.params.id as string
  }
}
console.log('页面类型', pageType.value)

// --------------------------------------------选择任务单------------------------------------
const selectOrderRef = ref() // 选择任务单组件ref
// 点击选择任务单
const selectOrder = () => {
  selectOrderRef.value.initDialog()
}
// 选好任务单
const clickConfirmOrder = (val: any) => {
  getOrderDetail({ id: val[0].id }).then((res) => {
    form.value.orderNo = res.data.data.orderNo!// 任务单编号
    form.value.orderId = val[0].id// 任务单id
    form.value.customerId = res.data.data.customerId!// 委托方id
    form.value.customerNo = res.data.data.customerNo!// 委托方代码
    form.value.customerName = res.data.data.customerName!// 委托方名称
    form.value.orderDeliverer = res.data.data.deliverer!// 预计送检人
    form.value.orderDelivererTel = res.data.data.customerPhone!// 委托方电话
    form.value.requireOverTime = res.data.data.requireOverTime!// 要求检完时间
    form.value.customerAddress = res.data.data.customerAddress!// 委托方地址
    // form.value.maintainMajor = res.data.data.maintainMajor!// 检修专业
    form.value.isUrgent = `${res.data.data.isUrgent}` // 是否加急
    form.value.deptId = res.data.data.deptId!// 使用部门id
    form.value.deptName = res.data.data.deptName!// 使用部门名称
    form.value.measureCompany = res.data.data.measureCompany!// 检定校准单位
  })
}
// -------------------------------------------表格------------------------------------------
const list = ref<IDetailTableList[]>([])// 表格数据
const selectEquipmentRef = ref() // 选择设备组件ref
const isMulti = ref(false) // 表格是否多选
const selectIndex = ref(0) // 选择的第几列
const checkoutList = ref<IDetailTableList[]>([]) // 选中的内容
// 表头
const columns = ref([
  { text: '设备名称', value: 'equipmentName', align: 'center', required: true, width: '220' },
  { text: '型号规格', value: 'model', align: 'center', required: false },
  { text: '出厂编号', value: 'manufactureNo', align: 'center', required: false },
  { text: '生产厂家', value: 'manufacturer', align: 'center', required: false },
  { text: '计量标识', value: 'meterIdentifyName', align: 'center', required: false },
  { text: '限用说明', value: 'limitInstruction', align: 'center', required: false },
  { text: '检定有效期', value: 'certificateValid', align: 'center', required: false, width: '120' },
  { text: '附件', value: 'appendixDescn', align: 'center', required: true, width: '220' },
  { text: '特殊要求', value: 'specialRequire', align: 'center', required: true, width: '220' },
  { text: '受检设备状态', value: 'sampleStatusName', align: 'center', required: false },
  { text: '检测完成度', value: 'measureCompletePercent', align: 'center', required: false },
  { text: '检定完成时间', value: 'measureCompleteTime', align: 'center', required: false },
])

// 多选发生改变时
const handleSelectionChange = (e: any) => {
  checkoutList.value = e
}

// 点击选择
const selectEquipment = (index: number) => {
  isMulti.value = false
  selectIndex.value = index
  selectEquipmentRef.value.initDialog(isMulti.value, form.value.customerId, form.value.orderId)
}

// 点击批量添加
const multiAdd = () => {
  if (!form.value.orderNo) {
    ElMessage.warning('请先选择任务单')
    return false
  }
  isMulti.value = true
  selectEquipmentRef.value.initDialog(isMulti.value, form.value.customerId, form.value.orderId)
}

// 增加行
const addRow = () => {
  if (!form.value.orderNo) {
    ElMessage.warning('请先选择任务单')
    return false
  }
  const checkResult = useCheckList(list.value, columns.value, '交接单列表') // 检查表格
  if (checkResult) {
    useSetAllRowReadable(list.value)
    list.value.push({
      id: '', // 主键
      equipmentNo: '', // 统一编号
      equipmentName: '', // 设备名称
      model: '', // 型号规格
      appendixDescn: '', // 附件
      appearanceInspect: '', // 外观和功能检查
      specialRequire: '', // 特殊要求
      measureContent: '', // 检校项目
      editable: true,
    })
  }
}

// 选好设备
const clickConfirmEquipment = (val: IDetailTableList[]) => {
  if (isMulti.value) { // 多选
    val.forEach((item: any) => {
      // 只添加列表里不存在的
      const index = list.value.findIndex((i: IDetailTableList) => item.sampleNo === i.equipmentNo)
      if (index === -1) {
        const param = {
          id: '', // 主键
          sampleId: item.sampleId,
          equipmentNo: item.sampleNo, // 统一编号
          equipmentName: item.sampleName, // 设备名称
          model: item.sampleModel, // 型号规格
          manufactureNo: item.manufactureNo, // 出厂编号
          manufacturer: item.manufacturer, // 生产厂家
          meterIdentify: item.meterIdentify, // 计量标识
          meterIdentifyName: meterIdentifyDict.value[item.meterIdentify], // 计量标识
          limitInstruction: item.limitInstruction, // 限用说明
          certificateValid: item.certificateValid, // 检定有效期
          appendixDescn: item.appendixDescn, // 附件
          appearanceInspect: item.appearanceInspect, // 外观和功能检查
          specialRequire: item.specialRequire, // 特殊要求
          measureContent: item.measureContent, // 检校项目
          sampleStatusName: item.sampleStatusName, // 受检设备状态
          measureCompletePercent: item.measureCompletePercent, // 检测完成度
          measureCompleteTime: item.measureCompleteTime, // 检定完成时间
          editable: true,
        }
        list.value.push(param)
      }
    })
  }
  else { // 单选
    const getValue = val[0] as any
    const index = list.value.findIndex((i: IDetailTableList) => val[0].sampleNo === i.equipmentNo)
    if (index !== -1) {
      ElMessage.warning('此设备已添加过')
      return
    }
    const param = {
      id: '', // 主键
      sampleId: getValue.sampleId,
      equipmentNo: getValue.sampleNo, // 统一编号
      equipmentName: getValue.sampleName, // 设备名称
      model: getValue.sampleModel, // 型号规格
      manufactureNo: getValue.manufactureNo, // 出厂编号
      manufacturer: getValue.manufacturer, // 生产厂家
      meterIdentify: getValue.meterIdentify, // 计量标识
      meterIdentifyName: meterIdentifyDict.value[getValue.meterIdentify], // 计量标识
      limitInstruction: getValue.limitInstruction, // 限用说明
      certificateValid: getValue.certificateValid, // 检定有效期
      appendixDescn: getValue.appendixDescn, // 附件
      appearanceInspect: getValue.appearanceInspect, // 外观和功能检查
      specialRequire: getValue.specialRequire, // 特殊要求
      measureContent: getValue.measureContent, // 检校项目
      sampleStatusName: getValue.sampleStatusName, // 受检设备状态
      measureCompletePercent: getValue.measureCompletePercent, // 检测完成度
      measureCompleteTime: getValue.measureCompleteTime, // 检定完成时间
      editable: true,
    }
    list.value.splice(selectIndex.value, 1, param)
  }
}

// 双击行
const rowDbClick = (row: IList) => {
  if (pageType.value !== 'detail') {
    useDoubleClickTableRow(row, list.value)
  }
}

// 删除行
const delRow = () => {
  if (checkoutList.value.length <= 0) {
    ElMessage({
      message: '请选中要删除的行',
      type: 'warning',
    })
  }
  else {
    checkoutList.value.forEach((item: IDetailTableList) => {
      list.value.forEach((element, index) => {
        if (element.equipmentNo === item.equipmentNo) {
          list.value.splice(index, 1)
        }
      })
    })
  }
}

// ---------------------------------------------按钮-------------------------------------------
const $router = useRouter()
// 关闭新增页面的回调
const close = () => {
  $router.back()
}

// 点击保存
const saveForm = (formEl: FormInstance | undefined) => {
  if (!list.value.length) {
    ElMessage.warning('要求交接单列表不能为空')
    return
  }
  const checkResult = useCheckList(list.value, columns.value, '交接单列表') // 检查表格
  if (!checkResult) { return false }
  if (!formEl) { return }
  formEl.validate((valid) => {
    if (valid) {
      ElMessageBox.confirm(
        '确认保存吗?',
        '提示',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        },
      ).then(() => {
        const loading = ElLoading.service({
          lock: true,
          background: 'rgba(255, 255, 255, 0.8)',
        })
        const params = {
          ...form.value,
          delivererTel: form.value.delivererTel, // 委托方电话
          sampleIdList: list.value.map(item => item.sampleId),
          deviceTotal: list.value.length, // 设备总量
          labCode: user.bizLabCode, // 实验室代码
        }
        if (pageType.value === 'edit') { // 编辑
          updateInterchangeReceipt({
            ...params,
            id: infoId.value,
          }).then(() => {
            ElMessage.success('已保存')
            loading.close()
            pageType.value = 'detail'
          }).catch(() => {
            loading.close()
          })
        }
        if (pageType.value === 'add') { // 新建
          addInterchangeReceipt(params).then((res) => {
            ElMessage.success('已保存')
            form.value.interchangeNo = res.data.interchangeNo
            infoId.value = res.data.id
            loading.close()
            pageType.value = 'detail'
          }).catch(() => {
            loading.close()
          })
        }
      })
    }
  })
}
// 点击编辑
const edit = () => {
  pageType.value = 'edit'
}

// ---------------------------------------------扫描--------------------------------------
const scanSampleRef = ref()
// 点击扫描收添加
const scan = () => {
  if (!form.value.orderNo) {
    ElMessage.warning('请先选择任务单')
    return false
  }
  // 参数:不是标签绑定,委托书,业务场景
  scanSampleRef.value.initDialog(false, '5', '', 'list', form.value.customerId)
}
// 扫描结束
const scanOver = (sampleList: any) => {
  if (sampleList.length) {
    list.value = sampleList.map((item: any) => {
      return {
        ...item,
        equipmentNo: item.sampleNo, // 统一编号
        equipmentName: item.sampleName, // 设备名称
        model: item.sampleModel, // 型号规格
        appendixDescn: item.appendixDescn, // 附件
        appearanceInspect: item.appearanceInspect, // 外观和功能检查
        specialRequire: item.specialRequire, // 特殊要求
        measureContent: item.measureContent, // 检校项目
        id: '', // 主键
        sampleId: item.sampleId,
        editable: true,
      }
    })
  }
  scanSampleRef.value.closeDialog()
}
// ------------------------------------------签名签章--------------------------------------------
const minioFileNameSignature = ref() // 签章图片
const minioFileNameAutograph = ref() // 签名图片
const printSignaturePicture = ref() // 打印签字图片

// 签章查询数据
const searchQuerySignature = ref({
  sealNo: '', // 印章编号
  sealName: '', // 印章名
  status: '',
  offset: 1,
  limit: 20,
})
// 签名查询数据
const searchQueryAutograph = ref({
  signNo: '', // 编号
  signName: '', // 名称
  signDirector: '', // 负责人
  signUserId: '', // 用户id
  createStartTime: '',
  createEndTime: '',
  limit: 20,
  offset: 1,
  signType: '',
  ids: [],
})
// 获取签章数据
const getSignatureList = () => {
  searchQuerySignature.value.sealNo = receiveCompanyList.value[0].value as string
  getSealInfoList(searchQuerySignature.value).then((res) => {
    if (res.code === 200) {
      minioFileNameSignature.value = res.data.rows[0].minioFileName
    }
  })
}

// 获取签名数据
const getAutographList = () => {
  searchQueryAutograph.value.signUserId = form.value.createUserId // 创建人的签名
  listPageApi(searchQueryAutograph.value).then((res) => {
    if (res.code === 200) {
      if (res.data.rows.length) {
        minioFileNameAutograph.value = res.data.rows[0].minioFileName
      }
      else {
        minioFileNameAutograph.value = ''
      }
    }
  })
}
// ----------------------------------------------------------------------------------------------
// 获取详细信息
const getInfo = () => {
  const loading = ElLoading.service({
    lock: true,
    background: 'rgba(255, 255, 255, 0.8)',
  })
  getInterchangeReceiptDetail({ id: infoId.value }).then((res) => {
    form.value = res.data
    getAutographList() // 获取签名
    list.value = res.data.sampleList.map((item: { sampleNo: string; meterIdentify: string; sampleName: string; sampleModel: string; certificateValid: string }) => {
      return {
        ...item,
        equipmentNo: item.sampleNo, // 统一编号
        equipmentName: item.sampleName, // 设备名称
        model: item.sampleModel, // 型号规格
        certificateValid: item.certificateValid ? dayjs(item.certificateValid).format('YYYY-MM-DD') : item.certificateValid,
        editable: pageType.value !== 'detail',
        meterIdentifyName: meterIdentifyDict.value[item.meterIdentify], // 计量标识
      }
    }) // 交接单列表
    form.value.isUrgent = `${res.data.isUrgent}`
    clickConfirmOrder([{ id: res.data.orderId }])
    printSignaturePicture.value = res.data.printSignature // 打印签名
    loading.close()
  }).catch(() => {
    loading.close()
  })
}

// 选中使用部门触发
const nodeClick = (data: any) => {
  form.value.delivererDeptName = data.name // 送检人部门名称
}

// -------------------------------------打印签字功能---------------------------------------------------------
const canvasDialogRef = ref() // 画布组件ref

// 点击打印签字
const printSign = () => {
  canvasDialogRef.value.initDialog()
}
function base64toFile(dataurl: string, filename = 'file') {
  const arr = dataurl.split(',')
  const mime = arr[0].match(/:(.*?);/)![1]
  // suffix是该文件的后缀
  const suffix = mime.split('/')[1]
  // atob 对经过 base-64 编码的字符串进行解码
  const bstr = atob(arr[1])
  // n 是解码后的长度
  let n = bstr.length
  // Uint8Array 数组类型表示一个 8 位无符号整型数组 初始值都是 数子0
  const u8arr = new Uint8Array(n)
  // charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  // new File返回File对象 第一个参数是 ArraryBuffer 或 Bolb 或Arrary 第二个参数是文件名
  // 第三个参数是 要放到文件中的内容的 MIME 类型
  return new File([u8arr], `${filename}.${suffix}`, {
    type: mime,
  })
}
// 签字后点击确定
const signPicture = (picture: any) => {
  // 创建formdata对象
  const fd = new FormData()
  fd.append('multipartFile', base64toFile(picture))
  const loading = ElLoading.service({
    lock: true,
    background: 'rgba(255, 255, 255, 0.8)',
  })
  uploadApi(fd).then((res) => {
    if (res.code === 200) {
      ruleFormRef.value?.clearValidate('printSignature')
      form.value.printSignature = res.data[0]
      form.value.signatureTime = dayjs().format('YYYY-MM-DD HH-mm:ss') // 签名时间
      ElMessage.success('上传成功')
      canvasDialogRef.value.close() // 关闭对话框
      // 保存签名
      const params = {
        ...form.value,
        delivererTel: form.value.delivererTel, // 委托方电话
        sampleIdList: list.value.map(item => item.sampleId),
        deviceTotal: list.value.length, // 设备总量
        labCode: user.bizLabCode, // 实验室代码
        id: infoId.value,
      }
      const loading = ElLoading.service({
        lock: true,
        background: 'rgba(255, 255, 255, 0.8)',
      })
      updateInterchangeReceipt(params).then(() => {
        printSignaturePicture.value = res.data[0] // 打印签名
        ElMessage.success('已保存签名')
        loading.close()
        pageType.value = 'detail'
      }).catch(() => {
        loading.close()
      })
    }
    else {
      ElMessage.error(res.message)
      loading.close()
    }
  })
}

// 点击打印
const print = () => {
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(255, 255, 255, 0.6)',
  })
  getStream({ id: infoId.value, pdf: true }).then((res) => {
    pdfStream.value = new Blob([res.data])
    loading.close()
    const blobUrl = URL.createObjectURL(pdfStream.value)
    printPdf(blobUrl)
  })
}
// ----------------------------------------------------钩子----------------------------------------------------
onMounted(async () => {
  getDict().then(() => {
    if (pageType.value === 'edit' || pageType.value === 'detail') { // 编辑和详情
      getInfo() // 获取详情信息
    }
    else { // 新建
      form.value.createUserId = user.id// 创建人id
      form.value.createUserName = user.name // 创建人
      form.value.createTime = dayjs().format('YYYY-MM-DD HH-mm:ss')// 创建时间
      const orderId = $route.query.orderId as string
      if (orderId) {
        clickConfirmOrder([{ id: orderId }])
      }
      if ($route.query.from === 'sendReceive') { // 从设备收发来
        form.value.interchangeType = $route.query.interchangeType || '' as any // 交接单类型
        list.value = JSON.parse($route.query.equipmentList as any)
        list.value = list.value.map((item: any) => {
          return {
            ...item,
            sampleId: item.sampleId,
            equipmentNo: item.sampleNo, // 统一编号
            equipmentName: item.sampleName, // 设备名称
            model: item.sampleModel, // 型号规格
            manufactureNo: item.manufactureNo, // 出厂编号
            manufacturer: item.manufacturer, // 生产厂家
            meterIdentify: item.meterIdentify, // 计量标识
            meterIdentifyName: meterIdentifyDict.value[item.meterIdentify], // 计量标识
            limitInstruction: item.limitInstruction, // 限用说明
            certificateValid: item.certificateValid, // 检定有效期
            appendixDescn: item.appendixDescn, // 附件
            appearanceInspect: item.appearanceInspect, // 外观和功能检查
            specialRequire: item.specialRequire, // 特殊要求
            measureContent: item.measureContent, // 检校项目
            sampleStatusName: item.sampleStatusName, // 受检设备状态
            measureCompletePercent: item.measureCompletePercent, // 检测完成度
            measureCompleteTime: item.measureCompleteTime, // 检定完成时间
            editable: true,
          }
        })
      }
      getSignatureList() // 获取签章数据
    }
    // nextTick(() => {
    //   getSignatureList() // 获取签章数据
    //   getAutographList() // 获取签名
    // })
  })
})
</script>

<template>
  <app-container>
    <detail-page :title="`交接单管理(${textMap[pageType]})`">
      <template #btns>
        <el-button v-if="pageType === 'detail'" type="warning" @click="printSign">
          打印签字
        </el-button>
        <el-button v-if="pageType === 'detail'" type="primary" @click="print">
          打印
        </el-button>
        <el-button v-if="pageType === 'detail'" type="primary" @click="edit">
          编辑
        </el-button>
        <el-button v-if="pageType !== 'detail'" type="primary" @click="saveForm(ruleFormRef)">
          保存
        </el-button>
        <el-button type="info" @click="close">
          关闭
        </el-button>
      </template>
      <el-form
        ref="ruleFormRef"
        :model="form"
        :label-width="130"
        label-position="right"
        :rules="rules"
      >
        <el-row :gutter="24">
          <el-col :span="6">
            <el-form-item label="系统编号:" prop="id ">
              <el-input
                v-model="form.id"
                :placeholder="pageType === 'detail' ? '' : '系统自动生成'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="创建人:">
              <el-input v-model="form.createUserName" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="创建时间:">
              <el-date-picker
                v-model="form.createTime"
                type="datetime"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
                disabled
                class="full-width-input"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="任务单编号" prop="orderNo">
              <el-input
                v-model="form.orderNo"
                :placeholder="pageType === 'detail' ? '' : '请选择'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              >
                <template v-if="pageType !== 'detail'" #append>
                  <el-button size="small" @click="selectOrder">
                    选择
                  </el-button>
                </template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="委托方" prop="customerName">
              <el-input
                v-model="form.customerName"
                :placeholder="pageType === 'detail' ? ' ' : '委托方'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="使用部门">
              <el-input v-model.trim="form.deptName" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="地址:">
              <el-input
                v-model="form.customerAddress"
                type="textarea"
                :placeholder="pageType === 'detail' ? ' ' : '委托方地址'"
                autosize
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <!-- 委托方电话:从任务单过来 -->
          <el-col :span="6">
            <el-form-item label="电话" prop="orderDelivererTel">
              <el-input
                v-model="form.orderDelivererTel"
                :placeholder="pageType === 'detail' ? '' : '电话'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="送检人:" prop="orderDeliverer">
              <el-input
                v-model="form.orderDeliverer"
                :placeholder="pageType === 'detail' ? ' ' : '送检人'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <!-- <el-col :span="6">
            <el-form-item label="检修专业:" prop="maintainMajor">
              <el-input
                v-model="form.maintainMajor"
                :placeholder="pageType === 'detail' ? ' ' : '检修专业'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col> -->
          <el-col :span="6">
            <el-form-item label="检定(校准)单位:">
              <el-input
                v-model="form.measureCompany"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="是否加急:" prop="isUrgent">
              <el-select v-model="form.isUrgent" :placeholder="pageType === 'detail' ? ' ' : '是否加急'" disabled class="full-width-input">
                <el-option
                  v-for="i in isUrgentList"
                  :key="i.value"
                  :label="i.name"
                  :value="i.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="要求检完时间:" prop="requireOverTime">
              <el-date-picker
                v-model="form.requireOverTime"
                type="datetime"
                :placeholder="pageType === 'detail' ? ' ' : '要求检完时间'"
                class="full-width-input"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="交接单编号:" prop="interchangeNo ">
              <el-input
                v-model="form.interchangeNo"
                :placeholder="pageType === 'detail' ? '' : '系统自动生成'"
                :class="{ 'detail-input': pageType === 'detail' }"
                disabled
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="交接单类型:" prop="interchangeType">
              <el-select
                v-model="form.interchangeType"
                filterable
                :placeholder="pageType === 'detail' ? '' : '请选择交接单类型'"
                :class="{ 'detail-input': pageType === 'detail' }"
                :disabled="pageType === 'detail'"
              >
                <el-option v-for="item in interchangeTypeList" :key="item.id" :label="item.name" :value="item.value" />
              </el-select>
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item :label="form.interchangeType === '2' ? '取件人' : '送检人'" prop="deliverer">
              <!-- <el-select
                v-model="form.deliverer"
                filterable
                :placeholder="pageType === 'detail' ? '' : '请选择送检人'"
                :class="{ 'detail-input': pageType === 'detail' }"
                :disabled="pageType === 'detail'"
              >
                <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
              </el-select> -->
              <el-input
                v-model="form.deliverer"
                :placeholder="pageType === 'detail' ? '' : '请输入送检人'"
                :class="{ 'detail-input': pageType === 'detail' }"
                :disabled="pageType === 'detail'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="送检人/取件人部门" label-width="144" prop="delivererDeptId">
              <el-tree-select
                v-model="form.delivererDeptId"
                style="width: 100%;"
                :data="useDeptList"
                :render-after-expand="false"
                check-strictly
                placeholder="请选择"
                :disabled="pageType === 'detail'"
                @node-click="nodeClick"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="电话" prop="delivererTel">
              <el-input
                v-model="form.delivererTel"
                :placeholder="pageType === 'detail' ? '' : '请输入电话'"
                :class="{ 'detail-input': pageType === 'detail' }"
                :disabled="pageType === 'detail'"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </detail-page>
    <!-- 表格 -->
    <detail-block title="交接单列表">
      <template #subhead>
        <div style="margin-left: 32px;">
          <span style="font-size: 14px;font-weight: 600;">列表设备总量(个):</span>
          <span style="color: red;font-weight: 600;">{{ list.length }}</span>
        </div>
      </template>
      <template #btns>
        <el-button v-if="pageType !== 'detail'" type="primary" @click="scan">
          RFID扫描添加
        </el-button>
        <el-button v-if="pageType !== 'detail'" type="primary" @click="multiAdd">
          批量添加
        </el-button>
        <el-button v-if="pageType !== 'detail'" type="primary" @click="addRow">
          增加行
        </el-button>
        <el-button v-if="pageType !== 'detail'" type="info" @click="delRow">
          删除行
        </el-button>
      </template>
      <el-table
        :data="list"
        border
        style="width: 100%;"
        max-height="600"
        @selection-change="handleSelectionChange"
        @row-dblclick="rowDbClick"
      >
        <el-table-column v-if="pageType !== 'detail'" type="selection" width="38" />
        <el-table-column align="center" label="序号" width="80" type="index" />
        <el-table-column
          v-for="item in columns"
          :key="item.value"
          :prop="item.value"
          :label="item.text"
          :width="item.width"
          show-overflow-tooltip
          align="center"
        >
          <template #header>
            <span v-show="item.required" style="color: red;">*</span><span>{{ item.text }}</span>
          </template>
          <template v-if="pageType !== 'detail'" #default="scope">
            <el-input
              v-if="pageType !== 'detail' && item.value === 'equipmentName'"
              v-model="scope.row[item.value]"
              placeholder="请选择"
              disabled
            >
              <template #append>
                <el-button size="small" @click="selectEquipment(scope.$index)">
                  选择
                </el-button>
              </template>
            </el-input>
            <el-input
              v-if="pageType !== 'detail' && item.value === 'appendixDescn' || item.value === 'specialRequire'"
              v-model="scope.row[item.value]"
              :placeholder="item.text"
              class="full-width-input"
            />
            <span v-if="pageType === 'detail'">{{ scope.row[item.value] }}</span>
          </template>
        </el-table-column>
      </el-table>
    </detail-block>
    <!-- 签章部分 -->
    <div v-if="pageType === 'detail'" class="receipt-signature">
      <!-- <div class="content">
        <span class="title">甲方</span>
        <div class="deliverer-time">
          <span class="text-title">送检人:</span>
          <span class="time">时ㅤ间:</span>
        </div>
      </div> -->
      <div class="content">
        <div class="deliverer-time">
          <div style="display: flex;">
            <span class="text-title">计量站交接人:</span>
            <show-photo
              style="position: absolute;left: 220px; top: -40px;"
              :minio-file-name="minioFileNameAutograph"
              fit="contain"
            />
          </div>
          <div style="margin-top: 30px;">
            <span class="time" style="margin-top: 20px;">时ㅤ间: </span>
            <span class="text">{{ form.createTime }}</span>
          </div>
        </div>
      </div>
      <div class="content">
        <!-- <span class="title">乙方</span> -->
        <div class="deliverer-time">
          <div style="display: flex;">
            <span class="text-title">送检人/取件人:</span>
            <show-photo fit="contain" style="position: absolute;left: 220px; top: -40px;" :minio-file-name="printSignaturePicture" />
          </div>
          <div style="margin-top: 30px;">
            <span class="time" style="margin-top: 20px;">时ㅤ间: </span>
            <span class="text">{{ form.signatureTime }}</span>
            <!-- <show-photo style="position: absolute;left: 360px; top: 1px;" :minio-file-name="minioFileNameSignature" /> -->
          </div>
        </div>
      </div>
    </div>
    <!-- 选择任务单 -->
    <select-order-dialog ref="selectOrderRef" @confirm="clickConfirmOrder" />
    <!-- 选择设备组件 -->
    <select-equipment-dialog ref="selectEquipmentRef" :is-multi="isMulti" @confirm="clickConfirmEquipment" />
    <!-- 扫描 -->
    <scan-sample-dialog ref="scanSampleRef" title="扫描添加设备" @confirm="scanOver" />
    <!-- 画布组件:签字板 -->
    <canvas-dialog ref="canvasDialogRef" @signPicture="signPicture" />
  </app-container>
</template>

<style lang="scss" scoped>
.receipt-signature {
  display: flex;
  justify-content: space-around;
  // padding: 50px 250px 50px 150px;
  padding: 50px;
  font-size: 28px;
  color: #000;
  font-weight: 600;

  .content {
    display: flex;
    position: relative;

    .img {
      position: absolute;
      right: 0;
      top: 0;
      z-index: 2;
    }

    .img-name {
      position: absolute;
      left: 220px;
      top: -30px;
      z-index: 1;
    }

    .title {
      margin-right: 32px;
      letter-spacing: 6px;
    }

    .deliverer-time {
      display: flex;
      flex-direction: column;

      .text-title {
        letter-spacing: 2px;
      }

      .time {
        margin-top: 30px;
        letter-spacing: 2px;
      }

      .text {
        font-size: 24px;
        font-weight: 500;
        margin-left: 10px;
      }
    }
  }
}
</style>