Newer
Older
xc-business-system / src / views / resource / person / train / detail.vue
<!-- 训练登记表详情 -->
<script name="TrainDetail" lang="ts" setup>
import { ElMessage, ElMessageBox, dayjs } from 'element-plus'
import type { IStaffBasicInfo } from '../register/person-regitster'
import type { IStaffListQuery, ITrainInfo } from './train-interface'
import FilterRegistedStaff from '@/views/resource/common/filterRegistedStaff.vue'
import { addTrainInfo, getTrainStaffList, updateTrainInfo } from '@/api/resource/train'
import type { TableColumn } from '@/components/NormalTable/table_interface'
import type { IDictType } from '@/commonInterface/resource-interface'

const type = ref<string>('')
const id = ref<string>('')

const route = useRoute()
const router = useRouter()

// 字典值
const trainSiteDict = ref<Array<IDictType>>([]) // 训练地点 HK / XC
const trainGroupDict = ref<Array<IDictType>>([]) // 培训部门
const trainContentDict = ref<Array<IDictType>>([]) // 培训内容
const trainWayDict = ref<Array<IDictType>>([]) // 培训方式

const staffListQuery = ref<IStaffListQuery>({
  id: '',
  limit: 1200,
  offset: 1,
})

const trainInfo = ref<ITrainInfo>({
  id: '',
  trainNo: '',
  trainSite: '',
  trainSiteName: '',
  trainGroupArray: [],
  trainGroup: '',
  trainGroupName: '',
  trainContent: '',
  trainContentName: '',
  trainWay: '',
  trainWayName: '',
  dutyLeader: '',
  trainType: '',
  trainText: '',
  trainDate: '',
  trainLocation: '',
  shouldAttendCount: undefined,
  actualAttendCount: undefined,
  attendRate: '',
  score: '',
  consume: '',
  remark: '',
  trainName: '训练登记表',
  createTime: '',
  staffList: [],
})
const trainStaffList = ref<Array<IStaffBasicInfo>>([])

const basicFormRef = ref()
const staffFormRef = ref()
const refFilterStaff = ref()

const trainBasicRules = ref({
  trainSite: [{ required: true, message: '训练场地不能为空,请选择', trigger: ['change', 'blur'] }],
  trainGroup: [{ required: true, message: '培训部门不能为空,请选择', trigger: ['change', 'blur'] }],
  trainContent: [{ required: true, message: '培训内容不能为空,请选择', trigger: ['change', 'blur'] }],
  trainWay: [{ required: true, message: '培训方式不能为空,请选择', trigger: ['change', 'blur'] }],
  dutyLeader: [{ required: true, message: '值班领导不能为空', trigger: 'blur' }],
  trainType: [{ required: true, message: '训练类别不能为空', trigger: 'blur' }],
  trainText: [{ required: true, message: '训练内容不能为空', trigger: 'blur' }],
  trainDate: [{ required: true, message: '训练时间不能为空', trigger: 'blur' }],
  trainLocation: [{ required: true, message: '训练地点不能为空', trigger: 'blur' }],
  shouldAttendCount: [{ required: true, message: '应训人数不能为空', trigger: ['blur', 'change'] }],
  actualAttendCount: [{ required: true, message: '实训人数不能为空', trigger: ['blur', 'change'] }],
  score: [{ required: true, message: '训练效果不能为空', trigger: 'blur' }],
  consume: [{ required: true, message: '消耗不能为空', trigger: 'blur' }],
}) // 表单验证规则

const staffColumns = ref<Array<TableColumn>>([
  { text: '人员编号', value: 'staffNo', align: 'center', width: '160' },
  { text: '姓名', value: 'staffName', align: 'center', width: '150' },
  { text: '工作部门', value: 'deptName', align: 'center' },
  { text: '岗位', value: 'station', align: 'center' },
  { text: '人员类别', value: 'staffTypeName', align: 'center', width: '150' },
  { text: '效果(成绩)', value: 'staffScore', align: 'center', width: '150' },
]) // 表头

// 表格被选中的行
const staffSelected = ref<IStaffBasicInfo[]>([])

// 逻辑
// 关闭
const resetForm = () => {
  sessionStorage.removeItem('trainInfo')
  router.go(-1)
}

const staffMultiSelect = (e: any) => {
  staffSelected.value = e
}

// 新增训练登记表
const addTrainAndStaffList = () => {
  trainInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')

  addTrainInfo(trainInfo.value).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')

      type.value = 'detail'
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}
// 编辑登记表
const updateTrainAndStaffList = () => {
  updateTrainInfo(trainInfo.value).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')

      type.value = 'detail'
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}

// 保存基本信息
const saveTrainForm = async () => {
  if (!basicFormRef) { return }

  await basicFormRef.value.validate((valid: boolean, fields: any) => {
    if (valid === true) {
      if (trainInfo.value.staffList !== undefined && trainInfo.value.staffList.length > 0) {
        ElMessageBox.confirm(
          '确认保存吗?',
          '提示',
          {
            confirmButtonText: '确认',
            cancelButtonText: '取消',
            type: 'warning',
          },
        ).then(() => {
          if (type.value === 'create') {
            addTrainAndStaffList()
          }
          else if (type.value === 'update') {
            updateTrainAndStaffList()
          }
        })
      }
      else {
        ElMessage.warning('实训人员不能为空')
      }
    }
  })
}

// 从接口查询
const getActualTrainStaffList = (trainId: string) => {
  staffListQuery.value.id = trainId
  getTrainStaffList(staffListQuery.value).then((res) => {
    if (res.code === 200) {
      trainStaffList.value = res.data.rows

      // 添加staffList
      trainInfo.value.staffList = []
      trainStaffList.value.forEach((item) => {
        trainInfo.value.staffList!.push({
          staffId: item.id!,
          score: item.staffScore!,
        })
      })
    }
  })
}

// 点击增加行按钮 选择人员
const addEditableRow = () => {
  if (trainInfo.value.actualAttendCount === 0 || trainInfo.value.actualAttendCount === null) {
    ElMessage.warning('请先输入实训人数')
  }
  else if (trainInfo.value.actualAttendCount! <= trainStaffList.value.length) {
    ElMessage.warning('实训人员列表总数不能超过实训人数')
  }
  else {
    refFilterStaff.value.showOrHideFilterDialog(true, trainInfo.value.actualAttendCount)
  }
}

// 选定人员
const recordSelectedHandler = (rows: Array<IStaffBasicInfo>) => {
  refFilterStaff.value.showOrHideFilterDialog(false)

  // 没有实训人员列表 则直接添加
  if (trainStaffList.value.length > 0) {
    // 找到已有实训人员列表中不存在的记录 加到新选择的记录中
    const selectedIds = rows.map(item => item.id)
    const notInNew = trainStaffList.value.filter(item => selectedIds.includes(item.id) === false)
    trainStaffList.value = notInNew
  }

  trainStaffList.value = trainStaffList.value.concat(rows)

  trainInfo.value.staffList = []
  trainStaffList.value.forEach((row: IStaffBasicInfo) => {
    trainInfo.value.staffList!.push({
      staffId: row.id!,
      score: row.staffScore!,
    })
  })
}

// 删除实训人员
const delTrainStaffRec = async () => {
  if (staffSelected.value.length === 0) {
    ElMessage.warning('请至少选择一行')
    return
  }

  // 前端界面删除
  trainStaffList.value = trainStaffList.value.filter(item => staffSelected.value.includes(item) === false)

  // 将详情数据中的值也删除
  trainInfo.value.staffList = []

  trainStaffList.value.forEach((row: IStaffBasicInfo) => {
    trainInfo.value.staffList!.push({
      staffId: row.id!,
      score: row.staffScore!,
    })
  })
}

const initDialog = (params: any) => {
  type.value = params.type
  id.value = params.id

  switch (params.type) {
    case 'create' :
      trainInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
      break
    case 'update':
      trainInfo.value = JSON.parse(sessionStorage.getItem('trainInfo')!)
      getActualTrainStaffList(trainInfo.value.id)

      break
    case 'detail':
      trainInfo.value = JSON.parse(sessionStorage.getItem('trainInfo')!)
      getActualTrainStaffList(trainInfo.value.id)

      break
    default:

      break
  }
}

const initDict = () => {
  if (trainSiteDict.value.length === 0) {
    trainSiteDict.value = JSON.parse(sessionStorage.getItem('bizTrainSite')!)
  }

  if (trainGroupDict.value.length === 0) {
    trainGroupDict.value = JSON.parse(sessionStorage.getItem('bizGroupCode')!)
  }

  if (trainContentDict.value.length === 0) {
    trainContentDict.value = JSON.parse(sessionStorage.getItem('bizTrainContent')!)
  }

  if (trainWayDict.value.length === 0) {
    trainWayDict.value = JSON.parse(sessionStorage.getItem('bizTrainWay')!)
  }
}

// 计算参训率
const rate = computed(() => {
  if (trainInfo.value.shouldAttendCount === undefined || trainInfo.value.actualAttendCount === undefined
  || trainInfo.value.shouldAttendCount === 0 || trainInfo.value.actualAttendCount === 0) {
    return '0.00'
  }
  else {
    return ((trainInfo.value.actualAttendCount! / trainInfo.value.shouldAttendCount!) * 100).toFixed(2)
  }
})

// 监听训练场地 显示中文
watch(() => trainInfo.value.trainSite, (newVal) => {
  const targetList = trainSiteDict.value.filter(item => item.value === newVal)
  if (targetList.length > 0) {
    trainInfo.value.trainSiteName = targetList[0].name
  }
  else {
    trainInfo.value.trainSiteName = ''
  }
})

// 监听培训部门 显示中文
watch(() => trainInfo.value.trainGroupArray, (newVal) => {
  if (trainInfo.value.trainGroupArray === undefined) {
    return
  }

  if (newVal?.length === 0) {
    trainInfo.value.trainGroup = ''
    trainInfo.value.trainGroupName = ''
  }
  else {
    let nameStr = ''
    newVal?.forEach((val) => {
      const targetList = trainGroupDict.value.filter(item => item.value === val)
      if (targetList.length > 0) {
        nameStr += `${targetList[0].name}, `
      }
    })

    nameStr = nameStr.substring(0, nameStr.length - 2)

    trainInfo.value.trainGroup = newVal!.toString()
    trainInfo.value.trainGroupName = nameStr
  }
})

// 监听培训内容 显示中文
watch(() => trainInfo.value.trainContent, (newVal) => {
  const targetList = trainContentDict.value.filter(item => item.value === newVal)
  if (targetList.length > 0) {
    trainInfo.value.trainContentName = targetList[0].name
  }
  else {
    trainInfo.value.trainContentName = ''
  }
})

// 监听培训方式 显示中文
watch(() => trainInfo.value.trainWay, (newVal) => {
  const targetList = trainWayDict.value.filter(item => item.value === newVal)
  if (targetList.length > 0) {
    trainInfo.value.trainWayName = targetList[0].name
  }
  else {
    trainInfo.value.trainWayName = ''
  }
})

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

<template>
  <app-container>
    <detail-page title="训练登记表">
      <template #btns>
        <el-button v-if="type !== 'detail'" type="primary" @click="saveTrainForm()">
          保存
        </el-button>
        <el-button type="info" @click="resetForm()">
          关闭
        </el-button>
      </template>

      <el-form ref="basicFormRef" :model="trainInfo" :rules="trainBasicRules" label-position="right" :class="[type === 'detail' ? 'isDetail' : '']" label-width="110" border stripe>
        <el-row :gutter="24">
          <!-- 第一行 第一列 -->
          <el-col :span="6">
            <el-form-item label="训练场地" prop="trainSite">
              <el-select v-model="trainInfo.trainSite" style="width: 100%;" placeholder="请选择训练场地" :disabled="type === 'detail'">
                <el-option v-for="site in trainSiteDict" :key="site.id" :value="site.value" :label="site.name" />
              </el-select>
              <el-input v-model="trainInfo.trainSiteName" type="hidden" />
            </el-form-item>

            <el-form-item label="登记表编号">
              <el-input v-model="trainInfo.trainNo" placeholder="请输入训练登记表编号" :clearable="true" :disabled="type === 'detail'" />
            </el-form-item>
            <el-form-item label="训练类别" prop="trainType">
              <el-input v-model="trainInfo.trainType" :clearable="true" placeholder="请输入训练类别" :disabled="type === 'detail'" />
            </el-form-item>
            <el-form-item label="应训人数" prop="shouldAttendCount">
              <el-input-number
                v-model="trainInfo.shouldAttendCount" placeholder="请输入应训人数"
                :min="0" :step="1" controls-position="right" :clearable="true" :disabled="type === 'detail'"
                style="width: 100%;"
              />
            </el-form-item>
          </el-col>

          <!-- 第一行 第二列 -->
          <el-col :span="6">
            <el-form-item label="培训部门" prop="trainGroup">
              <el-select
                v-if="type !== 'detail'"
                v-model="trainInfo.trainGroupArray" style="width: 100%;"
                multiple collapse-tags collapse-tags-tooltip
                placeholder="培训部门,可多选" :disabled="type === 'detail'"
              >
                <el-option v-for="site in trainGroupDict" :key="site.id" :value="site.value" :label="site.name" />
              </el-select>
              <el-input v-model="trainInfo.trainGroup" type="hidden" />
              <el-input v-if="type === 'detail'" v-model="trainInfo.trainGroupName" :disabled="true" />
            </el-form-item>
            <el-form-item label="登记表名称">
              <el-input v-model="trainInfo.trainName" :disabled="true" />
            </el-form-item>
            <el-form-item label="训练内容" prop="trainText">
              <el-input v-model="trainInfo.trainText" :clearable="true" placeholder="请输入训练内容" :disabled="type === 'detail'" />
            </el-form-item>
            <el-form-item label="实训人数" prop="actualAttendCount">
              <el-input-number
                v-model="trainInfo.actualAttendCount" placeholder="请输入实训人数"
                :min="0" :step="1" controls-position="right" :clearable="true" :disabled="type === 'detail'"
                style="width: 100%;"
              />
            </el-form-item>
          </el-col>

          <!-- 第一行 第三列 -->
          <el-col :span="6">
            <el-form-item label="培训内容" prop="trainContent">
              <el-select v-model="trainInfo.trainContent" style="width: 100%;" placeholder="请选择培训内容" :disabled="type === 'detail'">
                <el-option v-for="site in trainContentDict" :key="site.id" :value="site.value" :label="site.name" />
              </el-select>
              <el-input v-model="trainInfo.trainContentName" type="hidden" />
            </el-form-item>
            <el-form-item label="值班领导" prop="dutyLeader">
              <el-input v-model="trainInfo.dutyLeader" :clearable="true" placeholder="请输入值班领导" :disabled="type === 'detail'" />
            </el-form-item>
            <el-form-item label="训练内容" prop="trainDate">
              <el-date-picker
                v-model="trainInfo.trainDate" type="date"
                format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss"
                placeholder="请选择训练时间" :disabled="type === 'detail'" style="width: 100%;"
              />
            </el-form-item>
            <el-form-item label="参训率">
              <el-input v-model="rate" :readonly="true" :disabled="type === 'detail'" placeholder="自动计算">
                <template #append>
                  %
                </template>
              </el-input>
            </el-form-item>
          </el-col>

          <!-- 第一行 第四列 -->
          <el-col :span="6">
            <el-form-item label="培训方式" prop="trainWay">
              <el-select v-model="trainInfo.trainWay" placeholder="请选择培训方式" style="width: 100%;" :clearable="true" :disabled="type === 'detail'">
                <el-option v-for="dict in trainWayDict" :key="dict.id" :label="dict.name" :value="dict.value" />
              </el-select>
              <el-input v-model="trainInfo.trainWayName" type="hidden" />
            </el-form-item>
            <el-form-item label="创建时间">
              <el-input v-model="trainInfo.createTime" :disabled="true" />
            </el-form-item>
            <el-form-item label="训练地点" prop="trainLocation">
              <el-input v-model="trainInfo.trainLocation" :clearable="true" :disabled="type === 'detail'" placeholder="请输入训练地点" />
            </el-form-item>
            <el-form-item label="效果(成绩)" prop="score">
              <el-input v-model="trainInfo.score" :clearable="true" :disabled="type === 'detail'" placeholder="请输入训练效果" />
            </el-form-item>
          </el-col>
        </el-row>

        <!-- 第二行 -->
        <el-row :gutter="24">
          <el-col :span="6">
            <el-form-item label="消耗" prop="consume">
              <el-input v-model="trainInfo.consume" placeholder="请输入消耗" :clearable="true" :disabled="type === 'detail'" />
            </el-form-item>
          </el-col>
          <el-col :span="18">
            <el-form-item label="备注">
              <el-input v-model="trainInfo.remark" placeholder="请输入备注信息" :clearable="true" :disabled="type === 'detail'" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
    </detail-page>

    <el-form ref="staffFormRef" label-position="right" label-width="110px" border stripe>
      <table-container title="实训人员" style="margin-top: 20px;">
        <template v-if="type !== 'detail'" #btns-right>
          <el-button type="primary" @click="addEditableRow">
            增加行
          </el-button>
          <el-button type="info" @click="delTrainStaffRec">
            删除行
          </el-button>
        </template>

        <!-- 表格区域 -->
        <el-table :data="trainStaffList" :columns="staffColumns" border @selection-change="staffMultiSelect">
          <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="40" />
          <el-table-column align="center" label="序号" width="55" type="index" />
          <el-table-column
            v-for="item in staffColumns"
            :key="item.value"
            :prop="item.value"
            :label="item.text"
            align="center"
          >
            <template #header>
              <span>{{ item.text }}</span>
            </template>
          </el-table-column>
        </el-table>
      </table-container>
    </el-form>

    <filter-registed-staff ref="refFilterStaff" @record-selected="recordSelectedHandler" />
  </app-container>
</template>

<style lang="scss" scoped>
.isDetail {
  ::v-deep {
    .el-form-item.is-required:not(.is-no-asterisk) .el-form-item__label-wrap > .el-form-item__label::before,
    .el-form-item.is-required:not(.is-no-asterisk) > .el-form-item__label::before {
      content: "";
      display: none;
    }
  }
}
</style>