|
|
|
@ -58,12 +58,22 @@ |
|
|
|
<LineLabel label="template.dl.dl010.sjxx" /> |
|
|
|
<div class="template-form-item"> |
|
|
|
<div class="sj-operation-btns"> |
|
|
|
<el-button size="small" type="primary">{{ |
|
|
|
$t('template.dl.dl010.xzmb') |
|
|
|
}}</el-button> |
|
|
|
<el-button size="small" type="success">{{ |
|
|
|
$t('template.dl.dl010.dr') |
|
|
|
}}</el-button> |
|
|
|
<el-button |
|
|
|
size="small" |
|
|
|
type="primary" |
|
|
|
@click=" |
|
|
|
() => { |
|
|
|
downloadExcelTemplate(downloadArr) |
|
|
|
} |
|
|
|
" |
|
|
|
>{{ $t('template.dl.dl010.xzmb') }}</el-button |
|
|
|
> |
|
|
|
<el-button |
|
|
|
size="small" |
|
|
|
type="success" |
|
|
|
@click="handleImportExcel" |
|
|
|
>{{ $t('template.dl.dl010.dr') }}</el-button |
|
|
|
> |
|
|
|
</div> |
|
|
|
<CustomTable |
|
|
|
:columns="sjxxColumns" |
|
|
|
@ -85,6 +95,7 @@ |
|
|
|
></TableOpertaionDelete> |
|
|
|
</template> |
|
|
|
</CustomTable> |
|
|
|
<Step :ref="refConf.sjxxStep" :formData="formData.stepData" /> |
|
|
|
</div> |
|
|
|
|
|
|
|
<BaseInfoFormPackage |
|
|
|
@ -97,6 +108,12 @@ |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
<ImportExcelDialog |
|
|
|
ref="ImportExcelDialog" |
|
|
|
@onLoadData="onLoadExcelData" |
|
|
|
:downloadArr="downloadArr" |
|
|
|
@downloadExcelTemplate="downloadExcelTemplate" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -109,11 +126,13 @@ import TableList from '@/components/Template/Table' |
|
|
|
import Step from '@/components/Template/Step' |
|
|
|
import templateMixin from '../../mixins/templateMixin' |
|
|
|
import moment from 'moment' |
|
|
|
import ImportExcelDialog from '../../dialog/ImportExcelDialog' |
|
|
|
|
|
|
|
const refConf = { |
|
|
|
base: 'baseInfoRef', |
|
|
|
sysj: 'sysjTableRef', |
|
|
|
yqsy: 'yqsyTableRef', |
|
|
|
sjxxStep: 'sjxxStepRef', |
|
|
|
sjxx: 'sjxxTableRef', |
|
|
|
remark: 'remarkRef' |
|
|
|
} |
|
|
|
@ -127,7 +146,8 @@ export default { |
|
|
|
TableList, |
|
|
|
Step, |
|
|
|
CustomTable, |
|
|
|
TableOpertaionDelete |
|
|
|
TableOpertaionDelete, |
|
|
|
ImportExcelDialog |
|
|
|
}, |
|
|
|
mixins: [templateMixin], |
|
|
|
props: { |
|
|
|
@ -290,12 +310,6 @@ export default { |
|
|
|
yqsyColumns() { |
|
|
|
return [ |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.yqbh', |
|
|
|
prop: 'yqbh', |
|
|
|
bodyType: 'yq', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.yqmc', |
|
|
|
prop: 'yqmc', |
|
|
|
bodyType: 'input', |
|
|
|
@ -312,6 +326,12 @@ export default { |
|
|
|
disabled: true |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.yqbh', |
|
|
|
prop: 'yqbh', |
|
|
|
bodyType: 'yq', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.xccsjzjdrq', |
|
|
|
prop: 'jzrq', |
|
|
|
bodyType: 'input', |
|
|
|
@ -321,45 +341,69 @@ export default { |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
// 受集信息列表 |
|
|
|
// 采集信息列表 |
|
|
|
sjxxColumns() { |
|
|
|
return [ |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.dwbh', |
|
|
|
prop: 'dwbh', |
|
|
|
bodyType: 'input', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
bodyMaxlength: 50, |
|
|
|
bodyFillType: 'preFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.yslhnzsjyjrl', |
|
|
|
headerSelectKey: 'yslhnUnit', |
|
|
|
headerOptions: this.getDictOptions('business_tjdw'), |
|
|
|
prop: 'yslhnzsjyjrl', |
|
|
|
bodyType: 'inputNumber', |
|
|
|
bodyMaxlength: 10, |
|
|
|
fillType: 'preFill', |
|
|
|
bodyFillType: 'preFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.dwxb', |
|
|
|
prop: 'dwxb', |
|
|
|
bodyType: 'select', |
|
|
|
label: 'template.dl.dl010.sjlhnzsjyjrl', |
|
|
|
headerSelectKey: 'yslhnUnit', |
|
|
|
headerOptions: this.getDictOptions('business_tjdw'), |
|
|
|
prop: 'sjlhnzsjyjrl', |
|
|
|
bodyMaxlength: 10, |
|
|
|
bodyType: 'inputNumber', |
|
|
|
bodyFillType: 'actFill', |
|
|
|
options: this.getDictOptions('sys_user_sex') |
|
|
|
fillType: 'preFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.dwzl', |
|
|
|
prop: 'dwzl', |
|
|
|
bodyType: 'input', |
|
|
|
label: 'template.dl.dl010.sjgs', |
|
|
|
prop: 'sjgs', |
|
|
|
bodyType: 'checkbox', |
|
|
|
checkboxLabel: '', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.xcqkxzjd', |
|
|
|
prop: 'xcqk', |
|
|
|
bodyType: 'input', |
|
|
|
label: 'template.dl.dl010.lx', |
|
|
|
prop: 'lx', |
|
|
|
bodyType: 'checkbox', |
|
|
|
checkboxLabel: '', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.bz', |
|
|
|
prop: 'bz', |
|
|
|
bodyType: 'input', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
label: 'template.dl.dl010.ysjrxq', |
|
|
|
prop: 'ysjrxq', |
|
|
|
bodyType: 'inputNumber', |
|
|
|
bodyFillType: 'preFill', |
|
|
|
bodyMaxlength: 10, |
|
|
|
fillType: 'preFill', |
|
|
|
headerSelectKey: 'yslhnUnit', |
|
|
|
headerOptions: this.getDictOptions('business_tjdw') |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: 'template.dl.dl010.sjsj', |
|
|
|
prop: 'sjsj', |
|
|
|
bodyType: 'input', |
|
|
|
bodyFillType: 'actFill' |
|
|
|
label: 'template.dl.dl010.sjjrxq', |
|
|
|
prop: 'sjjrxq', |
|
|
|
bodyType: 'inputNumber', |
|
|
|
bodyMaxlength: 10, |
|
|
|
bodyFillType: 'actFill', |
|
|
|
fillType: 'preFill', |
|
|
|
headerSelectKey: 'yslhnUnit', |
|
|
|
headerOptions: this.getDictOptions('business_tjdw') |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
@ -367,25 +411,167 @@ export default { |
|
|
|
data() { |
|
|
|
return { |
|
|
|
formData: {}, |
|
|
|
refConf |
|
|
|
refConf, |
|
|
|
downloadArr: ['动物编号', '预设0.9%氯化钠注射液加入量', '预设加入血清'] |
|
|
|
} |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
downloadExcelTemplate(arr) { |
|
|
|
this.exportExcel(arr, '骨髓收集记录表-采集信息导入模板') |
|
|
|
}, |
|
|
|
// 模板导入成功 数据返回 |
|
|
|
onLoadExcelData(excelData) { |
|
|
|
console.log(excelData, 'excelData') |
|
|
|
|
|
|
|
if (excelData.length < 2) { |
|
|
|
this.$message.error('Excel 数据为空') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 第一行是表头 |
|
|
|
const headers = excelData[0] |
|
|
|
|
|
|
|
// 定义表头与字段的映射关系 |
|
|
|
const headerMap = { |
|
|
|
动物编号: 'dwbh', |
|
|
|
'预设0.9%氯化钠注射液加入量': 'yslhnzsjyjrl', |
|
|
|
预设加入血清: 'ysjrxq' |
|
|
|
} |
|
|
|
|
|
|
|
// 创建表头索引映射 |
|
|
|
const headerIndexMap = {} |
|
|
|
headers.forEach((header, index) => { |
|
|
|
const fieldName = headerMap[header] |
|
|
|
if (fieldName) { |
|
|
|
headerIndexMap[fieldName] = index |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
// 验证必需的表头是否存在 |
|
|
|
const requiredFields = ['dwbh', 'yslhnzsjyjrl', 'ysjrxq'] |
|
|
|
const missingFields = requiredFields.filter( |
|
|
|
(field) => headerIndexMap[field] === undefined |
|
|
|
) |
|
|
|
|
|
|
|
if (missingFields.length > 0) { |
|
|
|
const missingHeaders = missingFields.map((field) => { |
|
|
|
return Object.keys(headerMap).find((key) => headerMap[key] === field) |
|
|
|
}) |
|
|
|
this.$message.error( |
|
|
|
`Excel 表头缺少必需列: ${missingHeaders.join('、')}` |
|
|
|
) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
// 移除表头行,处理数据行 |
|
|
|
const dataRows = excelData.slice(1) |
|
|
|
|
|
|
|
// 数据验证函数 |
|
|
|
const validateDwbh = (value) => { |
|
|
|
// 动物编号:限制50字以内 |
|
|
|
if (!value) return '' |
|
|
|
const str = String(value).trim() |
|
|
|
return str.length <= 50 ? str : '' |
|
|
|
} |
|
|
|
|
|
|
|
const validateNumber = (value) => { |
|
|
|
// 数字字段:限制10位数以内的数字 |
|
|
|
if (!value) return '' |
|
|
|
const str = String(value).trim() |
|
|
|
// 匹配数字(可以包含小数点) |
|
|
|
const numberRegex = /^-?\d{1,10}(\.\d+)?$/ |
|
|
|
return numberRegex.test(str) ? str : '' |
|
|
|
} |
|
|
|
|
|
|
|
// 将二维数组转换为对象数组,根据表头映射读取数据并验证 |
|
|
|
const list = dataRows.map((row, index) => { |
|
|
|
const dwbh = validateDwbh(row[headerIndexMap.dwbh]) |
|
|
|
const yslhnzsjyjrl = validateNumber(row[headerIndexMap.yslhnzsjyjrl]) |
|
|
|
const ysjrxq = validateNumber(row[headerIndexMap.ysjrxq]) |
|
|
|
|
|
|
|
// 记录验证失败的行 |
|
|
|
if (!dwbh && row[headerIndexMap.dwbh]) { |
|
|
|
console.warn(`第${index + 2}行:动物编号超过50字,已清空`) |
|
|
|
} |
|
|
|
if (!yslhnzsjyjrl && row[headerIndexMap.yslhnzsjyjrl]) { |
|
|
|
console.warn( |
|
|
|
`第${index + 2}行:预设0.9%氯化钠注射液加入量格式不正确,已清空` |
|
|
|
) |
|
|
|
} |
|
|
|
if (!ysjrxq && row[headerIndexMap.ysjrxq]) { |
|
|
|
console.warn(`第${index + 2}行:预设加入血清格式不正确,已清空`) |
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
dwbh, // 动物编号(验证后) |
|
|
|
yslhnzsjyjrl, // 预设0.9%氯化钠注射液加入量(验证后) |
|
|
|
ysjrxq, // 预设加入血清(验证后) |
|
|
|
sjlhnzsjyjrl: '', // 实际0.9%氯化钠注射液加入量(空) |
|
|
|
sjgs: '', // 收集骨髓(空) |
|
|
|
lx: '', // 离心(空) |
|
|
|
sjjrxq: '' // 实际加入血清(空) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
// 使用 addRows 方法批量添加数据 |
|
|
|
this.$refs[refConf.sjxx].addRows(list) |
|
|
|
// 关闭导入对话框 |
|
|
|
this.$refs.ImportExcelDialog.cancel() |
|
|
|
|
|
|
|
// 提示用户 |
|
|
|
this.$message.success(`成功导入 ${list.length} 条数据`) |
|
|
|
|
|
|
|
// 触发数据更新 |
|
|
|
setTimeout(() => { |
|
|
|
this.justUpdateFilledFormData() |
|
|
|
}, 100) |
|
|
|
}, |
|
|
|
// 导入模板 |
|
|
|
handleImportExcel() { |
|
|
|
this.$refs.ImportExcelDialog.show() |
|
|
|
}, |
|
|
|
// 删除表格行 |
|
|
|
deleteTableRow(rowIndex, refName) { |
|
|
|
this.$refs[refName].deleteRow(rowIndex) |
|
|
|
}, |
|
|
|
// 获取已填写的表单数据 |
|
|
|
getFilledFormData() { |
|
|
|
return this.getFilledFormDataByRefs(refNames) |
|
|
|
const baseData = this.$refs.baseInfoRef.getFilledFormData() |
|
|
|
const sysjData = this.$refs.sysjTableRef.getFilledFormData() |
|
|
|
const yqsyData = this.$refs.yqsyTableRef.getFilledFormData() |
|
|
|
const sjxxStepData = this.$refs.sjxxStepRef.getFilledFormData() |
|
|
|
const sjxxData = this.$refs.sjxxTableRef.getFilledFormData() |
|
|
|
const remarkData = this.$refs.remarkRef.getFilledFormData() |
|
|
|
|
|
|
|
return { |
|
|
|
...baseData, |
|
|
|
...sysjData, |
|
|
|
...yqsyData, |
|
|
|
...sjxxStepData, |
|
|
|
...sjxxData, |
|
|
|
...remarkData |
|
|
|
} |
|
|
|
}, |
|
|
|
// 获取填写完成的表单数据 |
|
|
|
async getFormData() { |
|
|
|
return await this.validFormFields(refNames) |
|
|
|
// 先校验再获取值 |
|
|
|
const validFlag = await this.validFields() |
|
|
|
if (!validFlag) { |
|
|
|
return false |
|
|
|
} |
|
|
|
return this.getFilledFormData() |
|
|
|
}, |
|
|
|
// 只做校验 |
|
|
|
async validFields() { |
|
|
|
return await this.validFormFields(refNames) |
|
|
|
const refsToValidate = [ |
|
|
|
'baseInfoRef', |
|
|
|
'sysjTableRef', |
|
|
|
'yqsyTableRef', |
|
|
|
'sjxxStepRef', |
|
|
|
'sjxxTableRef', |
|
|
|
'remarkRef' |
|
|
|
] |
|
|
|
return await this.validFormFields(refsToValidate) |
|
|
|
}, |
|
|
|
getResource() { |
|
|
|
const sysjStepResource = this.$refs.sysjTableRef.getStepResource() |
|
|
|
|