| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- <template>
- <CustomDialog
- :model-value="modelValue"
- title="费用计算"
- width="600px"
- :before-close="handleClose"
- class="calcCheckItemDialog"
- v-loading="loading"
- >
- <div class="content" v-if="!isManualInput">
- <div class="content-title">
- 用户输入
- </div>
- <el-form ref="enterFormRef" :model="enterForm" :rules="enterFormRules">
- <el-table :data="enterDataList" border>
- <el-table-column label="输入项" prop="name"/>
-
- <el-table-column label="用户输入区" prop="">
- <template #default="{row}">
-
- <el-form-item :prop="row.code">
- <el-input-number v-if="row.valueType === 'number'" v-model="row.inputText" placeholder="请输入" :controls="false"/>
- <el-input v-else v-model="row.inputText" placeholder="请输入"/>
- </el-form-item>
-
- </template>
- </el-table-column>
-
- <el-table-column label="说明" prop="description"/>
- </el-table>
- </el-form>
- <div class="button-box">
- <el-button type="primary" @click="handleCalcFee">费用计算</el-button>
- </div>
- </div>
- <div class="content" v-if="!isManualInput">
- <div class="content-title">
- 自动计算
- </div>
- <el-form ref="outputFormRef" :model="outputForm" :rules="outputFormRules">
- <el-table :data="outputDataList" border>
- <el-table-column label="输出项" prop="name"/>
-
- <el-table-column label="自动计算" prop="">
- <template #default="{row}">
-
- <el-form-item :prop="row.code">
- <el-input v-model="row.inputText" placeholder="请输入"/>
- </el-form-item>
-
- </template>
- </el-table-column>
-
- <el-table-column label="说明" prop="description"/>
- </el-table>
- </el-form>
- </div>
- <div class="content">
- <div class="content-title">
- 项目检验费用
- </div>
- <el-form ref="feeFormRef" :model="feeForm" :rules="feeFormRules" label-width="160px">
- <el-form-item label="自动计算总费用:" prop="" v-if="!isBatch">
- {{ isManualInput ? '项目未设置计算规则,请手动填入实际费用' : feeForm.totalCost }}
- </el-form-item>
- <el-form-item label="历史收费:" prop="">
- {{ templateInfo.fee || 0 }}
- </el-form-item>
- <el-form-item label="实际费用:" prop="actualFee">
- <el-input-number v-model="feeForm.actualFee" :controls="false" :precision="2" :min="0" :step="0.01" style="width: 220px;"/>
- </el-form-item>
- </el-form>
- </div>
- <template #footer>
- <el-button type="primary" @click="handleSave">保存</el-button>
- <el-button type="default" @click="handleClose">取消</el-button>
- </template>
- </CustomDialog>
- <!-- 费用计算模板:不在页面显示 -->
- <Teleport to="body">
- <SpreadDesigner v-if="!isManualInput" ref="spreadDesignerRef" @init="handleDesignerInit"/>
- </Teleport>
- </template>
- <script setup>
- import { nextTick } from 'vue'
- import SpreadDesigner from '@/components/SpreadDesigner/index.vue'
- import CustomDialog from '@/components/CustomDialog/index.vue'
- import { PipeTaskOrderApi } from '@/api/pressure2/pipetaskorder'
- import { buildFileUrl } from '@/utils'
- import axios from 'axios'
- import { is } from '@/utils/is'
- const { queryCheckItemCalcPreFillField } = PipeTaskOrderApi
- import { getPressureReportTemplateInfo } from '@/api/pressure2/reportTemplate'
- const props = defineProps({
- modelValue: {
- type: Boolean,
- required: true
- },
- templateInfo: {
- type: Object,
- required: true,
- default: () => ({})
- },
- equipmentId: {
- type: String
- },
- isBatch: {
- type: Boolean,
- default: false
- }
- })
- const emit = defineEmits(['update:modelValue', 'refresh', 'save'])
- const loading = ref(true)
- const enterFormRef = ref(null)
- const outputFormRef = ref(null)
- const feeFormRef = ref(null)
- const enterForm = ref({})
- const outputForm = ref({})
- const feeForm = ref({
- actualFee: 0,
- totalCost: 0
- })
- const enterFormRules = ref({})
- const outputFormRules = ref({})
- const feeFormRules = ref({})
-
- const enterDataList = ref([])
-
- const outputDataList = ref([])
-
- let designer = null
- const spreadDesignerRef = ref(null)
- // 费用模板初始化
- const handleDesignerInit = async (instance) => {
- designer = instance
- console.log('葡萄城初始化了!!!')
- await handleGetPressureReportTemplateInfo()
- // 加载费用计算模板
- await handleRenderFormulaTemplate()
- // 获取费用计算字段
- if (props.equipmentId) {
- await handleQueryCheckItemCalcPreFillField()
- }
- // 优先从已保存的 feeCalculateJson 中回显实际费用
- feeForm.value = {
- actualFee: feeCalculateJson.value['actualFee'] || combineTemplateInfo.value.fee || 0,
- totalCost: feeCalculateJson.value['totalCost'] || combineTemplateInfo.value.fee || 0
- }
- }
-
- // 获取费用模板信息
- const fetchTemplateData = ref({})
- const combineTemplateInfo = computed(() => ({...props.templateInfo, ...fetchTemplateData.value}))
- const feeCalculateJson = computed(() => !props.templateInfo.feeCalculateJson ? {} : JSON.parse(props.templateInfo.feeCalculateJson))
- // 是否手动录入 true是,false否
- const isManualInput = computed(() => combineTemplateInfo.value.isAutoAmount === '0')
- const handleGetPressureReportTemplateInfo = async () => {
- fetchTemplateData.value = await getPressureReportTemplateInfo({id: props.templateInfo.templateId})
- }
- // 渲染费用计算模板
- const handleRenderFormulaTemplate = async () => {
- const spread = designer?.getWorkbook()
- if(!combineTemplateInfo.value.formulaTemplateUrl) return
- const response = await axios.get(buildFileUrl(combineTemplateInfo.value.formulaTemplateUrl), { responseType: 'blob' })
- const blob = new Blob([response.data], { type: response.headers['content-type'] })
- spread.open(
- blob,
- function () {
- // 让活动工作表的单元格全部失焦
- spread.getActiveSheet().setActiveCell(null);
- console.log('费用计算模板加载成功')
- },
- function () {
- console.log('费用计算模板加载失败')
- }
- )
- }
- const calcFields = ref([])
- const allCalcPreFillFieldKeyValue = ref({})
- const allCalcPreFillField = ref([])
- // 获取费用计算字段
- const handleQueryCheckItemCalcPreFillField = async () => {
- loading.value = true
- try {
- const params = {
- equipId: props.equipmentId,
- templateId: combineTemplateInfo.value.templateId
- }
- const fieldResult = await queryCheckItemCalcPreFillField(params)
- allCalcPreFillField.value = fieldResult
- // 保存所有的输入项
- enterDataList.value = fieldResult.filter(field => field.type === '0').map(field => ({inputText: feeCalculateJson.value[field.code] || field.defaultValue, ...field}))
- // 保存所有的输出项
- outputDataList.value = JSON.parse(JSON.stringify(fieldResult.filter(field => field.type === '1').map(field => ({inputText: feeCalculateJson.value[field.code], ...field}))))
- // 获取所有需要field的code,转成{[code]: ''}格式,set到费用模板中
- allCalcPreFillFieldKeyValue.value = Object.fromEntries(enterDataList.value.map(item => ([item.code, feeCalculateJson.value[item.code] || ''])))
-
- // 检验费用数据回显
- feeForm.value = {
- actualFee: feeCalculateJson.value['actualFee'] || 0,
- totalCost: feeCalculateJson.value['totalCost'] || 0
- }
- } catch(error) {
- console.error('获取费用计算字段报错了', error)
- } finally {
- loading.value = false
- }
- }
- // 自动计算费用
- const handleCalcFee = () => {
- const spread = designer?.getWorkbook()
- const entryData = Object.fromEntries(enterDataList.value.map(item => ([item.code, item.inputText])))
- const combineDataSource = {
- ...allCalcPreFillFieldKeyValue.value,
- ...entryData
- }
- // console.log('combineDataSource', combineDataSource)
- // set数据
- spreadDesignerRef.value.newSetDataSource(combineTemplateInfo.value.bindingPathSchema, combineDataSource)
- // get数据
- nextTick(() => {
- const getDataSource = spreadDesignerRef.value.getDataSource()
- // 输出项的值
- outputDataList.value = outputDataList.value.map(item => {
- if(is(getDataSource[item.code], 'Null') || is(getDataSource[item.code], 'Undefined')) return item
- return {
- ...item,
- inputText: getDataSource[item.code]
- }
- })
- // console.log('输出项', outputDataList.value)
- const totalCostCode = allCalcPreFillField.value.find(x => x.type === '3')?.code || 'totalCost'
- // 自动计算总费用
- feeForm.value.totalCost = getDataSource[totalCostCode]
- feeForm.value.actualFee = getDataSource[totalCostCode]
- })
- }
- // 保存
- const handleSave = () => {
- const inputParams = Object.fromEntries(enterDataList.value.map(item => ([item.code, item.inputText])))
- const outputParams = Object.fromEntries(outputDataList.value.map(item => ([item.code, item.inputText])))
- emit('save', {...props.templateInfo, fee: feeForm.value.actualFee || 0, feeCalculateJson: JSON.stringify({...inputParams, ...feeForm.value, ...outputParams})})
- handleClose()
- }
- // 关闭弹窗
- const handleClose = () => {
- emit('update:modelValue', false)
- }
- </script>
- <style lang="scss" scoped>
- .content-title {
- position: sticky;
- left: 0;
- top: 0;
- display: flex;
- justify-content: flex-start;
- align-items: center;
- width: 100%;
- height: 36px;
- margin-bottom: 16px;
- line-height: 36px;
- background-color: var(--el-color-primary-light-9);
- z-index: 1000;
- &::before {
- content: '';
- height: 70%;
- width: 4px;
- margin-right: 12px;
- background-color: var(--el-color-primary);
- }
- }
- .content {
- position: relative;
- margin-bottom: 16px;
- max-height: 400px;
- overflow-y: auto;
- .button-box {
- position: sticky;
- left: 0;
- bottom: 0;
- background-color: #fff;
- z-index: 1000;
- }
- }
- :deep(.el-input-number) {
- width: 100%;
- .el-input__inner {
- text-align: left;
- }
- }
- .button-box {
- display: flex;
- flex-direction: row;
- justify-content: center;
- padding-top: 16px;
- }
- </style>
- <style lang="scss">
- .calcCheckItemDialog {
- .el-dialog__footer {
- text-align: center;
- }
- }
- </style>
|