Newer
Older
xc-business-system / src / views / resource / customer / situationReport / edit.vue
dutingting on 3 Jan 23 KB 需求开发+10
<!-- 委托方情况报告详情 -->
<script name="SituationReportDetail" lang="ts" setup>
import { ElLoading, ElMessage, ElMessageBox, dayjs } from 'element-plus'
import type { ICustomerQuestionnaireInfo, IListQuery } from '../questionnaire/customer-questionnaire'
import type { ICustomerSatisfaction, ISituationReportInfo } from './customer-report'
import selectSuggestFormDialog from './dialog/selectSuggestFormDialog.vue'
import type { TableColumn } from '@/components/NormalTable/table_interface'
import type { IDictType } from '@/commonInterface/resource-interface'
import useUserStore from '@/store/modules/user'
import { detailSituationReport, getStream, saveSituationReport, updateSituationReport } from '@/api/resource/situationReport'
import { getDictByCode } from '@/api/system/dict'
import { getQuestionnaireList } from '@/api/resource/questionnaire'
import FilterQuestionnaire from '@/views/resource/common/filterQuestionnaire.vue'
import { calc } from '@/utils/useCalc'
import { exportFile } from '@/utils/exportUtils'
import { printPdf } from '@/utils/printUtils'
import { uniqueArray } from '@/utils/Array'
import { isInteger } from '@/utils/validate'

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

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

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

const reportFormRef = ref()
const refQuestionnaireFilter = ref()

const reportInfo = ref<ISituationReportInfo>({
  id: '',
  customerName: '',
  labCode: '',
  labCodeName: '',
  reportNo: '',
  reportName: '委托方情况报告',
  customerAdvice: '', // 委托方反馈意见
  customerAdviceHandle: '', // 对意见的处理
  conclusion: '实现“委托方满意率高于90%,每年收到委托方投诉不大于2次”的目标',
  createUserId: '',
  createUserName: '',
  createTime: '',
  customerList: [],
  draft: '1', // 1/2是否是草稿箱
  averageScore: '', // 平均分
  totalScore: '', // 总分
  rate: '', // 满意率
  suggestId: '', // 委托方意见登记表id
})

const quesQuery = ref<IListQuery>({
  customerName: '', // 填写单位
  writerName: '',
  writeTimeStart: '',
  writeTimeEnd: '',
  sendTimeStart: '',
  sendTimeEnd: '',
  offset: 1,
  limit: 2000,
})

const reportFormRules = ref({
  labCode: [{ required: true, message: '实验室代码不能为空', trigger: ['change', 'blur'] }],
  customerName: [{ required: true, message: '委托方不能为空', trigger: ['change', 'blur'] }],
  customerAdvice: [{ required: true, message: '委托方反馈意见不能为空', trigger: 'blur' }],
  customerAdviceHandle: [{ required: true, message: '对委托方意见的处理不能为空', trigger: 'blur' }],
  conclusion: [{ required: true, message: '结论不能为空', trigger: 'blur' }],
}) // 表单验证规则

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

const customerListXc = ref<ICustomerSatisfaction[]>([])
const customerListHk = ref<ICustomerSatisfaction[]>([])
const satisfactionColumns = ref<TableColumn[]>([
  { text: '委托方名称', value: 'customerName', align: 'center' },
  { text: '时间', value: 'proposeTime', align: 'center', width: '240' },
  { text: '评分', value: 'score', align: 'center', width: '240' },
])

// -----------------------------------表格操作-----------------------------------------------
const customerSelectedXc = ref<ICustomerSatisfaction[]>([])
const customerSelectedHk = ref<ICustomerSatisfaction[]>([])
// 西昌多选
const xcMultiSelect = (e: any) => {
  customerSelectedXc.value = e
}
// 海口多选
const hkMultiSelect = (e: any) => {
  customerSelectedHk.value = e
}

// 计算总分、平均分、满意率
const caculate = (list: any = []) => {
  if (!list.length) { return }

  let sum = 0 // 总分
  let ave = 0 // 平均分
  let rate = 0 // 满意率
  list.forEach((item: { score: number }) => {
    sum = Number(calc(Number(item.score), sum, '+'))
  })
  ave = Number(calc(sum, list.length, '/'))

  const above90 = list.filter((item: { score: number }) => item.score >= 90)
  rate = Number(calc(above90.length, list.length, '/'))

  console.log('总分', sum)
  console.log('平均分', isInteger(ave) ? ave : ave.toFixed(2))
  console.log('满意率', isInteger(Number(calc(rate, 100, '*'))) ? `${Number(calc(rate, 100, '*'))}%` : `${Number(calc(rate, 100, '*')).toFixed(2)}%`)
  return {
    sum,
    ave: isInteger(ave) ? ave : ave.toFixed(2),
    rate: isInteger(Number(calc(rate, 100, '*'))) ? `${Number(calc(rate, 100, '*'))}%` : `${Number(calc(rate, 100, '*')).toFixed(2)}%`,
  }
}

// 增加行
const addEditableRow = () => {
  refQuestionnaireFilter.value.showOrHideFilterDialog(true, reportInfo.value.labCode)
}

// 删除行
const delSatisfaction = () => {
  if (customerSelectedXc.value.length === 0 && customerSelectedHk.value.length === 0) {
    ElMessage.warning('请至少选择一行')
    return
  }
  // 前端界面删除
  customerListXc.value = customerListXc.value.filter(item => customerSelectedXc.value.includes(item) === false)
  customerListHk.value = customerListHk.value.filter(item => customerSelectedHk.value.includes(item) === false)

  // 计算总分、平均分、满意率
  const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : []
  const { sum, ave, rate } = caculate(caculateList)!
  reportInfo.value.averageScore = `${ave}`// 平均分
  reportInfo.value.totalScore = `${sum}` // 总分
  reportInfo.value.rate = rate// 满意率
}

// 选好委托方满意度调查表
const questionnaireSelectedHandler = (rows: ICustomerQuestionnaireInfo[]) => {
  refQuestionnaireFilter.value.showOrHideFilterDialog(false)

  rows.forEach((row) => {
    if (row.labCode === 'X') {
      const existList = customerListXc.value.filter(xc => xc.id === row.id)
      if (existList.length === 0) {
        customerListXc.value.push({
          ...row,
          questionnaireId: row.id,
        })
      }
    }
    else if (row.labCode === 'H') {
      const existList = customerListHk.value.filter(hk => hk.id === row.id)
      if (existList.length === 0) {
        customerListHk.value.push({
          ...row,
          questionnaireId: row.id,
        })
      }
    }
  })
  const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : []
  const { sum, ave, rate } = caculate(caculateList)!
  reportInfo.value.averageScore = `${ave}`// 平均分
  reportInfo.value.totalScore = `${sum}` // 总分
  reportInfo.value.rate = rate// 满意率

  // 委托方名称
  reportInfo.value.customerName = uniqueArray(caculateList.map(item => item.customerName)).join(',')
}

// ------------------------------------------------------------------------------------------------------------------

// 根据委托方名称查询满意度调查表
// 暂时不用
const searchQuestionnaire = () => {
  if (reportInfo.value.customerName !== '') {
    reportInfo.value.customerName = reportInfo.value.customerName.replace(',', ',')
    const customerList = reportInfo.value.customerName.split(',')
    customerList.forEach((customer: string) => {
      quesQuery.value.customerName = customer
      getQuestionnaireList(quesQuery.value).then((res) => {
        if (res.code === 200) {
          customerListXc.value = []
          customerListHk.value = []
          res.data.rows.forEach((item: ICustomerQuestionnaireInfo) => {
            if (item.writeStatus === '已提交') {
              if (item.labCode === 'X') {
                customerListXc.value.push({
                  id: item.id,
                  labCode: item.labCode,
                  customerName: item.customerName,
                  proposeTime: item.writeTime,
                })
              }
              else if (item.labCode === 'H') {
                customerListHk.value.push({
                  id: item.id,
                  labCode: item.labCode,
                  customerName: item.customerName,
                  proposeTime: item.writeTime,
                })
              }
            }
          })
        }
      })
    })
  }
}

// 保存至草稿箱
const saveReportInfo = () => {
  reportInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss') // 创建时间改为提交时间
  const params = {
    ...reportInfo.value,
    draft: '1',
    customerList: reportInfo.value.customerList.map((item: any) => {
      return {
        ...item,
        id: '',
      }
    }),
  }
  saveSituationReport(params).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')
      // 设置返回的委托方id和委托方编号
      reportInfo.value.reportNo = res.data.reportNo
      reportInfo.value.id = res.data.id
      id.value = res.data.id

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

// 编辑
const updateReportInfo = () => {
  updateSituationReport({ ...reportInfo.value, id: id.value }).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('保存成功')
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}

// 提交
const submit = () => {
  const params = {
    ...reportInfo.value,
    draft: '2',
    id: id.value,
    customerList: reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : [],
  }
  updateSituationReport({
    ...params,
    customerList: params.customerList.map((item) => {
      return {
        ...item,
        id: '',
      }
    }),
  }).then((res) => {
    if (res.code === 200) {
      // 提示保存成功
      ElMessage.success('提交成功')
      type.value = 'detail'
      reportInfo.value.draft = '2'
    }
    else {
      // 提示失败信息
      ElMessage.error(`保存失败:${res.message}`)
    }
  })
}

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

  reportInfo.value.customerList = []
  customerListXc.value.forEach((item) => {
    reportInfo.value.customerList.push(item)
  })
  customerListHk.value.forEach((item) => {
    reportInfo.value.customerList.push(item)
  })

  await reportFormRef.value.validate((valid: boolean, fields: any) => {
    if (valid === true) {
      ElMessageBox.confirm(
        '确认保存吗?',
        '提示',
        {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning',
        },
      ).then(() => {
        if (type.value === 'create') {
          saveReportInfo()
        }
        else if (type.value === 'update') {
          updateReportInfo()
        }
      })
    }
  })
}

// 获取西昌实验室情况表、海口实验室情况表
const disSatisfByLabCode = () => {
  detailSituationReport({ id: reportInfo.value.id }).then((res) => {
    if (res.code === 200) {
      customerListXc.value = res.data.xCustomerList
      customerListHk.value = res.data.hCustomerList
      // 计算总分、平均分、满意率
      const caculateList = reportInfo.value.labCode === 'X' ? customerListXc.value : reportInfo.value.labCode === 'H' ? customerListHk.value : []
      const { sum, ave, rate } = caculate(caculateList)!
      reportInfo.value.averageScore = `${ave}`// 平均分
      reportInfo.value.totalScore = `${sum}` // 总分
      reportInfo.value.rate = rate// 满意率
    }
  })
}
// -----------------------------------选择委托方意见登记表---------------------------------------------
const selectSuggestFormRef = ref() // 委托方意见登记表组件ref

// 点击选择委托委托方意见
const handleSelectSuggestForm = () => {
  selectSuggestFormRef.value.initDialog()
}

// 选好委托方意见登记表
const confirmSelectSuggestForm = (val: any) => {
  if (val && val.length) {
    reportInfo.value.customerAdvice = val[0].handleStatusName // 委托方反馈意见
    reportInfo.value.customerAdviceHandle = val[0].suggestContent // 对意见的处理
    reportInfo.value.suggestId = val[0].id // 委托方意见登记表id
  }
}
// --------------------------------------------------------------------------------------------------

const getLabCodeDict = async () => {
  // 缓存中没有则调用接口查询
  await getDictByCode('bizGroupCodeEquipment').then((res) => {
    if (res.code === 200) {
      labCodeDict.value = res.data
    }
  })
}

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

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

  switch (params.type) {
    case 'create' :
      title.value = '委托方情况报告(新增)'

      sessionStorage.removeItem('situationReportInfo')

      reportInfo.value.createUserId = userInfo.id
      reportInfo.value.createUserName = userInfo.name
      reportInfo.value.createTime = dayjs(new Date()).format('YYYY-MM-DD')

      // 新建时部门和实验实验室编辑
      keyFieldsDisable.value = false
      break
    case 'update':
      title.value = '委托方情况报告(编辑)'

      reportInfo.value = JSON.parse(sessionStorage.getItem('situationReportInfo')!)
      reportInfo.value.draft = `${reportInfo.value.draft}`
      disSatisfByLabCode()
      break
    case 'detail':
      title.value = '委托方情况报告(详情)'
      id.value = params.id

      reportInfo.value = JSON.parse(sessionStorage.getItem('situationReportInfo')!)
      reportInfo.value.draft = `${reportInfo.value.draft}`
      disSatisfByLabCode()
      keyFieldsDisable.value = true
      break
    default:
      title.value = ''
      keyFieldsDisable.value = true
      break
  }
}

const initDict = () => {
  getLabCodeDict()
}

// 监听 显示中文
watch(() => reportInfo.value.labCode, (newVal) => {
  labCodeDict.value = JSON.parse(sessionStorage.getItem('bizLabCode')!)

  if (labCodeDict.value.length > 0) {
    const targetList = labCodeDict.value.filter(item => item.value === newVal)
    if (targetList.length > 0) {
      reportInfo.value.labCodeName = targetList[0].name
    }
    else {
      reportInfo.value.labCodeName = ''
    }
  }
})

// --------------------------------导出word、pdf、打印----------------------------------------------------
const stream = ref()
const streamNormal = ref(true) // 流是否正常
// 获取流
const fetchStream = async (isPdf = true) => {
  const loading = ElLoading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(255, 255, 255, 0.6)',
  })
  const res = await getStream({ id: id.value, pdf: isPdf })
  stream.value = res.data
  loading.close()
}

// 打印Word
const printToWord = () => {
  fetchStream(false).then(() => {
    if (streamNormal.value) {
      exportFile(stream.value, '委托方意见登记表.doc')
    }
  })
}

// 导出PDF
const printToPDF = () => {
  fetchStream().then(() => {
    if (streamNormal.value) {
      exportFile(new Blob([stream.value]), '委托方意见登记表.pdf')
    }
  })
}

// 打印
const printClickedHandler = () => {
  fetchStream().then(() => {
    if (streamNormal.value) {
      const blobUrl = URL.createObjectURL(stream.value)
      printPdf(blobUrl)
    }
  })
}

// 监听实验室修改, 清空表格
const changeLab = () => {
  customerSelectedXc.value = []
  customerSelectedHk.value = []
  customerListXc.value = []
  customerListHk.value = []
}

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

<template>
  <app-container>
    <el-form ref="reportFormRef" :model="reportInfo" :rules="reportFormRules" label-position="right" label-width="125px" border stripe>
      <detail-page :title="`${title}`">
        <template #btns>
          <template v-if="type === 'detail'">
            <el-button type="primary" @click="printToWord">
              导出Word
            </el-button>
            <el-button type="primary" @click="printToPDF">
              导出PDF
            </el-button>
            <el-button type="primary" @click="printClickedHandler">
              打印
            </el-button>
          </template>
          <el-button v-if="(type === 'detail' || type === 'update') && reportInfo.draft === '1'" type="primary" @click="submit">
            提交
          </el-button>
          <el-button v-if="type !== 'detail'" type="primary" @click="saveButtonHandler">
            保存
          </el-button>
          <el-button type="info" @click="resetForm()">
            关闭
          </el-button>
        </template>

        <el-row :gutter="24">
          <!-- 第一行 第一列 -->
          <el-col :span="6">
            <el-form-item label="实验室" prop="labCode">
              <el-select v-model="reportInfo.labCode" placeholder="请选择实验室" :disabled="keyFieldsDisable" style="width: 100%;" @change="changeLab">
                <el-option v-for="dict in labCodeDict" :key="dict.id" :label="dict.name" :value="dict.value" />
              </el-select>
              <el-input v-model="reportInfo.labCodeName" type="hidden" />
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="报告单编号">
              <el-input v-model="reportInfo.reportNo" placeholder="系统自动生成" :disabled="true" />
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="拟制人">
              <el-input v-model="reportInfo.createUserId" type="hidden" />
              <el-input v-model="reportInfo.createUserName" :disabled="true" />
            </el-form-item>
          </el-col>

          <el-col :span="6">
            <el-form-item label="拟制时间">
              <el-input v-model="reportInfo.createTime" :disabled="true" />
            </el-form-item>
          </el-col>
        </el-row>
      </detail-page>

      <detail-block title="">
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="委托方名称" prop="customerName">
              <el-input v-model="reportInfo.customerName" placeholder="委托方名称,多个委托方用,隔开" :clearable="true" type="textarea" autosize :disabled="type === 'detail'" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="总分">
              <el-input v-model="reportInfo.totalScore" placeholder="总分" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="平均分">
              <el-input v-model="reportInfo.averageScore" placeholder="平均分" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="满意率">
              <el-input v-model="reportInfo.rate" placeholder="满意率" disabled />
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="24">
          <el-col :span="16">
            <el-form-item label="委托方反馈意见" prop="customerAdvice">
              <!-- <el-input v-model="reportInfo.customerAdvice" placeholder="请输入委托方反馈的意见" :clearable="true" :disabled="type === 'detail'" /> -->
              <el-input v-model="reportInfo.customerAdvice" placeholder="请选择" :disabled="true">
                <template v-if="type !== 'detail'" #append>
                  <el-button :disabled="type === 'detail'" @click="handleSelectSuggestForm">
                    选择
                  </el-button>
                </template>
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>

        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="对意见的处理" prop="customerAdviceHandle">
              <el-input v-model="reportInfo.customerAdviceHandle" placeholder="请输入对委托方意见的处理" :clearable="true" type="textarea" autosize :disabled="type === 'detail'" />
            </el-form-item>
          </el-col>
        </el-row>
      </detail-block>

      <table-container v-if="reportInfo.labCode === 'X'" title="西昌实验室情况">
        <template v-if="type !== 'detail'" #btns-right>
          <el-button type="primary" @click="addEditableRow()">
            批量添加
          </el-button>
          <el-button type="info" @click="delSatisfaction()">
            删除行
          </el-button>
        </template>

        <el-table :data="customerListXc" border style="width: 100%;" @selection-change="xcMultiSelect">
          <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="38" />
          <el-table-column align="center" label="序号" width="80" type="index" />
          <el-table-column
            v-for="item in satisfactionColumns"
            :key="item.value"
            :prop="item.value"
            :label="item.text"
            :width="item.width"
            align="center"
          >
            <template #default="scope">
              <span v-if="!scope.row.editable">{{ scope.row[item.value] }}</span>
              <el-input v-else v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" />
            </template>
          </el-table-column>
        </el-table>
      </table-container>

      <table-container v-if="reportInfo.labCode === 'H'" title="海口实验室情况">
        <template v-if="type !== 'detail'" #btns-right>
          <el-button type="primary" @click="addEditableRow()">
            批量添加
          </el-button>
          <el-button type="info" @click="delSatisfaction()">
            删除行
          </el-button>
        </template>
        <el-table :data="customerListHk" border style="width: 100%;" @selection-change="hkMultiSelect">
          <el-table-column v-if="type !== 'detail'" type="selection" align="center" width="38" />
          <el-table-column align="center" label="序号" width="80" type="index" />
          <el-table-column
            v-for="item in satisfactionColumns"
            :key="item.value"
            :prop="item.value"
            :label="item.text"
            :width="item.width"
            align="center"
          >
            <template #default="scope">
              <span v-if="!scope.row.editable">{{ scope.row[item.value] }}</span>
              <el-input v-else v-model="scope.row[item.value]" :autofocus="true" :placeholder="`${item.text}`" class="input" />
            </template>
          </el-table-column>
        </el-table>
      </table-container>

      <detail-block title="">
        <el-row :gutter="24">
          <el-col :span="24">
            <el-form-item label="结论" prop="conclusion">
              <el-input v-model="reportInfo.conclusion" :clearable="true" :disabled="type === 'detail'" />
            </el-form-item>
          </el-col>
        </el-row>
      </detail-block>
    </el-form>

    <!-- 选择委托方满意度调查表 -->
    <filter-questionnaire ref="refQuestionnaireFilter" @record-selected="questionnaireSelectedHandler" />

    <!-- 选择委托方意见登记表 -->
    <select-suggest-form-dialog ref="selectSuggestFormRef" @confirm="confirmSelectSuggestForm" />
  </app-container>
</template>