Newer
Older
xc-business-system / src / views / resource / outsideService / consumable / storeDetail.vue
tanyue on 23 Oct 2023 20 KB 20231023 物资入库单
<!-- 物资入库单 详情 -->
<script name="ConsumableStoreDetail" lang="ts" setup>
import { ElMessage, ElMessageBox, dayjs } from 'element-plus'
import type { IConsumableStore, IConsumableStoreGoods } from './consumable-interface'
import StoreDetailDialog from './storeDetailDialog.vue'
import ApprovalDialog from '@/views/resource/common/approvalDialog.vue'
import type { IDictType } from '@/commonInterface/resource-interface'
import { SCHEDULE } from '@/utils/scheduleDict'
import { detailConsumableStore, draftDeleteStore, failUpdateConsumableStore, refuseApprovalStore, revokeApprovalStore, saveConsumableStore, submitConsumableStore, updateConsumableStore } from '@/api/resource/supplierConsumable'
import ApprovalRecordTable from '@/components/ApprovalRecord/ApprovalRecordTable.vue'
import useUserStore from '@/store/modules/user'
import { getDictByCode } from '@/api/system/dict'
import { useCheckList } from '@/commonMethods/useCheckList'

// 变量
// 从路由中传过来的参数
const type = ref<string>('')
const id = ref<string>('')
const status = ref<string>('')

// 关键字段是否可以编辑
const keyFieldsDisable = ref<boolean>(true)

const userInfo = useUserStore()
const route = useRoute()
const router = useRouter()
const title = ref('')

const radioItems = ref([
  { name: '基本信息', value: 'consumable-store-basic' },
  { name: '审批详情', value: 'consumable-store-approval' },
])
const current = ref('')
const currentLabel = ref('')

// 子组件
const approvalDialog = ref()
const consumableStoreRef = ref()
const refStoreDetailDialog = ref()

const consumableStore = ref<IConsumableStore>({
  id: '',
  labCode: '',
  groupCode: '',
  warehouseNo: '',
  warehouseName: '物资入库单',
  createDeptId: '',
  createUserId: '', // 保管员
  createTime: '',
  warehouseDetailList: [],
  approvalStatus: '',
  approvalStatusName: '',
  processId: '',
  taskId: '',
})

const goodsList = ref<Array<IConsumableStoreGoods>>([])
const goodsColumns = [
  { text: '名称', value: 'goodsName', align: 'center', width: '240', required: true },
  { text: '规格型号', value: 'goodsModel', align: 'center', width: '240', required: true },
  { text: '数量及单位', value: 'amount', align: 'center', width: '240', required: true },
  { text: '单价', value: 'unitPrice', align: 'center', width: '180' },
  { text: '金额', value: 'price', align: 'center', width: '180', required: true },
  { text: '备注', value: 'remark', align: 'center' },
] // 表头

const storeRules = ref({
  labCode: [{ required: true, message: '实验室代码不能为空,请选择', trigger: ['change', 'blur'] }],
  groupCode: [{ required: true, message: '组别代码不能为空,请选择', trigger: ['change', 'blur'] }],
}) // 表单验证规则

// 是否显示相关按钮
const saveButtVisable = ref<boolean>(false) // 是否显示 保存 按钮
const submitButtVisable = ref<boolean>(false) // 是否显示 提交 按钮
const flowButtsVisable = ref<boolean>(false) // 是否显示 同意和拒绝 按钮
const cancelButtVisable = ref<boolean>(false) // 是否显示 取消 按钮
const deleteButtVisable = ref<boolean>(false) // 是否显示 删除 按钮
const editButtVisable = ref<boolean>(false) // 是否显示 编辑 按钮

// 字典值
const labCodeDict = ref<IDictType[]>([])
const groupCodeDict = ref<IDictType[]>([])

const recordSelected = ref<IConsumableStoreGoods[]>([])

// 逻辑
// 详情页的各个tab切换操作
const radioChangeHandler = (newVal: string | number | boolean) => {
  const radioTarget = radioItems.value.filter(item => item.name === newVal)
  if (radioTarget.length > 0) {
    currentLabel.value = radioTarget[0].name
    current.value = radioTarget[0].value
  }
  else {
    currentLabel.value = radioItems.value[0].name
    current.value = radioItems.value[0].value
  }
}

// 将所有流程操作的按钮隐藏
const hideAllOpterationButtons = () => {
  saveButtVisable.value = false
  submitButtVisable.value = false
  flowButtsVisable.value = false
  cancelButtVisable.value = false
  deleteButtVisable.value = false
  editButtVisable.value = false
}

// 根据审批状态显示对应的流程操作按钮
const showOperationButtonByStatus = () => {
  switch (status.value) {
    case '0':
      // 全部:保存按钮可见
      if (type.value === 'update') {
        saveButtVisable.value = true
      }
      else {
        saveButtVisable.value = false
      }
      break

    case '1':
      // 草稿箱:保存、提交按钮可见
      saveButtVisable.value = true
      submitButtVisable.value = true
      break

    case '2':
      // 待审批:同意、拒绝按钮可见
      flowButtsVisable.value = true
      break

    case '3':
      // 审批中:取消按钮可见
      cancelButtVisable.value = true
      break

    case '5':
      // 未通过:编辑 按钮可见
      editButtVisable.value = true
      break

    case '6':
      // 已取消:编辑 删除按钮可见
      editButtVisable.value = true
      deleteButtVisable.value = true
      break

    default:
      // 默认不显示所有的操作按钮
      hideAllOpterationButtons()
      break
  }
}

// 关闭
const resetForm = () => {
  sessionStorage.removeItem('consumableStoreTaskId') // 返回列表时 将缓存中的数据删除
  router.go(-1)
}

// 新增
const addEditableRow = () => {
  refStoreDetailDialog.value.showRecordDialog(true)
}

const delGoodsStoreRecords = () => {
  if (recordSelected.value.length === 0) {
    ElMessage.warning('请至少选择一行')
    return
  }

  goodsList.value = goodsList.value.filter(item => recordSelected.value.includes(item) === false)
}

const storeMultiSelect = (e: any) => {
  recordSelected.value = e
}

// 保存至草稿箱
const saveDraftStore = () => {
  consumableStore.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') // 创建时间改为提交时间
  saveConsumableStore(consumableStore.value).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')
      // 设置返回的id和编号
      consumableStore.value.warehouseNo = res.data.warehouseNo
      consumableStore.value.id = res.data.id
      id.value = res.data.id

      type.value = 'update'
      status.value = '1' // 保存成功后进入草稿箱 为了不显示审批详情
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}
// 编辑草稿箱(不走流程审批)
const updateDraftStore = () => {
  updateConsumableStore(consumableStore.value).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}

// 编辑按钮点击事件处理函数
const editClickedHandler = () => {
  type.value = 'update'
  title.value = '物资入库单(编辑)'

  // 隐藏编辑按钮 显示提交按钮
  editButtVisable.value = false
  submitButtVisable.value = true
}

// 新建时保存后的处理 获取返回的id
const saveButtonHandler = async () => {
  if (!consumableStoreRef) { return }

  if (goodsList.value.length === 0) {
    ElMessage.error('物资明细不能为空,请选择易耗物资及供方')
    return
  }

  if (useCheckList(goodsList.value, goodsColumns, '物资明细') === false) {
    return
  }

  await consumableStoreRef.value.validate((valid: boolean) => {
    if (valid === true) {
      consumableStore.value.warehouseDetailList = goodsList.value

      ElMessageBox.confirm(
        '确认保存吗?',
        '提示',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        },
      ).then(() => {
        if (type.value === 'create') {
          saveDraftStore()
        }
        else if (type.value === 'update') {
          updateDraftStore()
        }
      })
    }
  })
}

// 提交按钮
const submitButtonHandler = async () => {
  if (consumableStore.value === null || consumableStore.value.processId === undefined || consumableStore.value.processId === '') {
    // 流程id为空 表示还未进入流程中 直接提交
    ElMessageBox.confirm(`是否提交物资入库单 ${consumableStore.value.warehouseNo}`, '提示', {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning',
    }).then(() => {
      submitConsumableStore({
        formId: SCHEDULE.MATERIAL_RECEIPT_APPROVAL,
        id: consumableStore.value.id,
      }).then((res) => {
        if (res.code === 200) {
          ElMessage.success(`物资入库单 ${consumableStore.value.warehouseNo} 提交成功`)

          type.value = 'detail'
          hideAllOpterationButtons()
        }
        else {
          ElMessage.error(`物资入库单 ${consumableStore.value.warehouseNo} 提交失败:${res.message}`)
        }
      })
    })
  }
  else {
    // 之前已经在流程中的表单 保存提交
    if (goodsList.value.length === 0) {
      ElMessage.error('物资明细不能为空,请选择易耗物资及供方')
      return
    }

    if (useCheckList(goodsList.value, goodsColumns, '物资明细') === false) {
      return
    }

    await consumableStoreRef.value.validate((valid: boolean) => {
      if (valid === true) {
        failUpdateConsumableStore(consumableStore.value).then((res) => {
          if (res.code === 200) {
          // 提示保存成功
            ElMessage.success(`物资入库单 ${consumableStore.value.warehouseNo} 提交成功`)

            type.value = 'detail'
            hideAllOpterationButtons()
          }
          else {
          // 提示失败信息
            ElMessage.error(`物资入库单 ${consumableStore.value.warehouseNo} 提交失败:${res.message}`)
          }
        })
      }
    })
  }
}

// 根据id查询详情
const detailById = async (id: string) => {
  await detailConsumableStore({ id }).then((res) => {
    if (res.code === 200) {
      consumableStore.value = res.data
      goodsList.value = consumableStore.value.warehouseDetailList
      if (consumableStore.value.taskId === '') {
        consumableStore.value.taskId = sessionStorage.getItem('consumableStoreTaskId')!
      }
    }
  })
}

// 流程审批-拒绝
const approvalRefuseHandler = () => {
  approvalDialog.value.initDialog('refuse', consumableStore.value.id, consumableStore.value.taskId, '')
}

// 流程审批-同意
const approvalAgreeHandler = () => {
  approvalDialog.value.initDialog('agree', consumableStore.value.id, consumableStore.value.taskId, '')
}

// 取消流程
const revokeClickedHandler = () => {
  approvalDialog.value.initDialog('revoke', consumableStore.value.id, consumableStore.value.taskId, consumableStore.value.processId)
}

// 删除审批单
const deleteClickedHandler = () => {
  ElMessageBox.confirm(`是否删除审批单 ${consumableStore.value.warehouseNo}`, '提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    draftDeleteStore({ id: id.value }).then((res) => {
      if (res.code === 200) {
        ElMessage.success(`审批单 ${consumableStore.value.warehouseNo} 删除成功`)
        resetForm()
      }
      else {
        ElMessage.error(`审批单 ${consumableStore.value.warehouseNo} 删除失败: ${res.message}`)
      }
    })
  })
}

// 流程审批(同意、拒绝、取消)结束后的操作 将按钮都隐藏(本身就不能编辑了)
const approvalSuccessHandler = (type: string) => {
  if (type === 'agree' || type === 'refuse') {
    flowButtsVisable.value = false
  }
  else if (type === 'revoke') {
    cancelButtVisable.value = false
  }
}

// 取消
const revokeHandler = (param: any) => {
  revokeApprovalStore(param).then((res) => {
    if (res.code === 200) {
      ElMessage.success('流程取消成功')
    }
    else {
      ElMessage.error(`流程取消失败:${res.message}`)
    }
    // 关闭弹窗
    approvalDialog.value.handleClose()

    cancelButtVisable.value = false
  })
}

// 拒绝
const refuseHandler = (param: any) => {
  refuseApprovalStore(param).then((res) => {
    if (res.code === 200) {
      ElMessage.success('拒绝审批完成')
    }
    else {
      ElMessage.error(`拒绝审批失败:${res.message}`)
    }
    // 关闭弹窗
    approvalDialog.value.handleClose()

    flowButtsVisable.value = false
  })
}

// 添加物资入库记录
const consumableStoreAddHandler = (row: IConsumableStoreGoods) => {
  goodsList.value.push({
    goodsName: row.goodsName,
    goodsModel: row.goodsModel,
    amount: row.amount,
    unitPrice: row.unitPrice,
    price: row.price,
    remark: row.remark,
  })
}

const getLabCodeDict = async () => {
  // 先从缓存中获取
  if (sessionStorage.getItem('bizLabCode') === null || sessionStorage.getItem('bizLabCode') === undefined) {
    // 缓存中没有则调用接口查询
    await getDictByCode('bizLabCode').then((res) => {
      if (res.code === 200) {
        labCodeDict.value = res.data
      }
    })
  }
  else {
    labCodeDict.value = JSON.parse(sessionStorage.getItem('bizLabCode')!)
  }
}

const getGroupCodeDict = async () => {
  // 先从缓存中获取
  if (sessionStorage.getItem('bizGroupCode') === null || sessionStorage.getItem('bizLabbizGroupCodeCode') === undefined) {
    // 缓存中没有则调用接口查询
    await getDictByCode('bizGroupCode').then((res) => {
      if (res.code === 200) {
        groupCodeDict.value = res.data
      }
    })
  }
  else {
    groupCodeDict.value = JSON.parse(sessionStorage.getItem('bizGroupCode')!)
  }
}

const initDict = async () => {
  await getLabCodeDict()
  await getGroupCodeDict()
}

const initDialog = (params: any) => {
  // 从路由中获取参数
  type.value = params.type
  id.value = params.id !== undefined ? params.id : ''
  status.value = params.status !== undefined ? params.status : ''

  // 默认显示第一个tab内容
  current.value = radioItems.value[0].value
  currentLabel.value = radioItems.value[0].name

  switch (params.type) {
    case 'create' :
      title.value = '物资入库单(新增)'
      saveButtVisable.value = true
      submitButtVisable.value = true

      consumableStore.value.createUserId = userInfo.id
      consumableStore.value.createUserName = userInfo.name
      consumableStore.value.createDeptId = userInfo.deptId
      consumableStore.value.createDept = userInfo.deptName
      consumableStore.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')

      keyFieldsDisable.value = false

      break
    case 'update':
      title.value = '物资入库单(编辑)'

      detailById(id.value)

      // 判断显示哪些流程操作按钮
      showOperationButtonByStatus()
      keyFieldsDisable.value = true

      break
    case 'detail':
      title.value = '物资入库单(详情)'
      id.value = params.id

      detailById(id.value)

      // 查看详情时所有的操作按钮都隐藏
      showOperationButtonByStatus()
      keyFieldsDisable.value = true

      break
    default:
      title.value = ''
      break
  }
}

onMounted(() => {
  initDict()
  initDialog(route.query)
})
</script>

<template>
  <app-container>
    <el-form ref="consumableStoreRef" :model="consumableStore" :rules="storeRules" label-position="right" label-width="110px" border stripe>
      <detail-page :title="`${title}`">
        <template #btns>
          <el-button v-if="editButtVisable" type="primary" @click="editClickedHandler()">
            编辑
          </el-button>

          <template v-if="flowButtsVisable">
            <el-button type="primary" @click="approvalAgreeHandler">
              同意
            </el-button>
            <el-button type="danger" @click="approvalRefuseHandler">
              拒绝
            </el-button>
          </template>

          <el-button v-if="submitButtVisable" :disabled="id === ''" type="primary" @click="submitButtonHandler">
            提交
          </el-button>
          <el-button v-if="saveButtVisable" type="primary" @click="saveButtonHandler">
            保存
          </el-button>

          <el-button v-if="deleteButtVisable" type="danger" @click="deleteClickedHandler">
            删除
          </el-button>
          <el-button v-if="cancelButtVisable" type="info" @click="revokeClickedHandler">
            取消
          </el-button>

          <el-button type="info" @click="resetForm()">
            关闭
          </el-button>
        </template>

        <el-radio-group v-model="currentLabel" style="margin-bottom: 20px;" @change="radioChangeHandler">
          <el-radio-button v-for="item in radioItems" :key="item.value" :label="item.name" :disabled="id === ''" />
        </el-radio-group>

        <template v-if="current === 'consumable-store-basic'">
          <el-row :gutter="24">
            <!-- 第一行 第一列 -->
            <el-col :span="6">
              <el-form-item label="实验室代码" prop="labCode">
                <el-select v-model="consumableStore.labCode" placeholder="请选择实验室代码" :disabled="keyFieldsDisable" style="width: 100%;">
                  <el-option v-for="dict in labCodeDict" :key="dict.id" :label="dict.name" :value="dict.value" />
                </el-select>
              </el-form-item>
              <el-form-item label="填制部门">
                <el-input v-model="consumableStore.createDept" :disabled="true" />
                <el-input v-model="consumableStore.createDeptId" type="hidden" />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="组别代码" prop="groupCode">
                <el-select v-model="consumableStore.groupCode" placeholder="请选择组别代码" :disabled="keyFieldsDisable" style="width: 100%;">
                  <el-option v-for="dict in groupCodeDict" :key="dict.id" :label="dict.name" :value="dict.value" />
                </el-select>
              </el-form-item>
              <el-form-item label="填制时间">
                <el-input v-model="consumableStore.createTime" :disabled="true" />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="文件编号">
                <el-input v-model="consumableStore.warehouseNo" placeholder="文件编号,保存后自动生成" :disabled="true" />
              </el-form-item>

              <el-form-item label="保管员">
                <el-input v-model="consumableStore.createUserName" :disabled="true" />
                <el-input v-model="consumableStore.createUserId" type="hidden" />
              </el-form-item>
            </el-col>

            <el-col :span="6">
              <el-form-item label="文件名称">
                <el-input v-model="consumableStore.warehouseName" :disabled="true" />
              </el-form-item>
            </el-col>
          </el-row>
        </template>
      </detail-page>

      <template v-if="current === 'consumable-store-basic'">
        <table-container title="入库单详情">
          <template v-if="type !== 'detail'" #btns-right>
            <el-button type="primary" @click="addEditableRow">
              增加行
            </el-button>
            <el-button type="info" @click="delGoodsStoreRecords">
              删除行
            </el-button>
          </template>

          <!-- 表格区域 -->
          <el-table :data="goodsList" border style="width: 100%;" @selection-change="storeMultiSelect">
            <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="38" />
            <el-table-column align="center" label="序号" width="55" type="index" />
            <el-table-column
              v-for="item in goodsColumns"
              :key="item.value"
              :prop="item.value"
              :label="item.text"
              :width="item.width"
              align="center"
            >
              <template #header>
                <span v-show="item.required && type !== 'detail'" style="color: red;">*</span><span>{{ item.text }}</span>
              </template>
            </el-table-column>
          </el-table>
        </table-container>
      </template>
    </el-form>

    <approval-dialog
      ref="approvalDialog"
      @on-success="approvalSuccessHandler" @on-refuse="refuseHandler" @on-revoke="revokeHandler"
    />

    <store-detail-dialog ref="refStoreDetailDialog" @record-saved="consumableStoreAddHandler" />

    <template v-if="current === 'consumable-store-approval' && status !== '1'">
      <approval-record-table :process-id="consumableStore.processId" />
    </template>
  </app-container>
</template>