luojie 2 months ago
parent
commit
07c5d2b51e
7 changed files with 471 additions and 15 deletions
  1. +2
    -1
      package.json
  2. +3
    -1
      src/views/business/comps/template/TemplateTable.vue
  3. +307
    -0
      src/views/business/comps/template/comps/gsp/GSP009.vue
  4. +8
    -2
      src/views/business/comps/template/comps/lba/LBA006.vue
  5. +12
    -3
      src/views/business/comps/template/comps/pcr/PCR002.vue
  6. +97
    -0
      src/views/business/comps/template/dialog/ImportExcelDialog.vue
  7. +42
    -8
      src/views/business/comps/template/mixins/templateMixin.js

+ 2
- 1
package.json View File

@ -54,7 +54,8 @@
"vue-pdf": "^4.3.0",
"vue-router": "3.4.9",
"vuedraggable": "2.24.3",
"vuex": "3.6.0"
"vuex": "3.6.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.6",

+ 3
- 1
src/views/business/comps/template/TemplateTable.vue View File

@ -44,6 +44,7 @@ import Demo from "./comps/sp/Demo.vue";
import GSP002 from "./comps/gsp/GSP002.vue";
import GSP003 from "./comps/gsp/GSP003.vue";
import GSP004 from "./comps/gsp/GSP004.vue";
import GSP009 from "./comps/gsp/GSP009.vue";
import GSP010 from "./comps/gsp/GSP010.vue";
////
@ -82,7 +83,7 @@ export default {
////
MJYLQSQD, SYWZPZJHB, DMYPPZJLB,
//
GSP002, GSP003, GSP004, GSP010,
GSP002, GSP003, GSP004,GSP009, GSP010,
//
SP001, SP003, SP00456,SP007, SP008, SP009, SP010, SP011, SP012, SP013, SP014, SP015, SP016, SP017, SP018,
// PCR
@ -143,6 +144,7 @@ export default {
'GSP004': 'GSP004',
'GSP006': 'GSP002',
'GSP008': 'GSP002',
'GSP009': 'GSP009',
'GSP010': 'GSP010',
'GSP012': 'GSP002',
'GSP013': 'GSP002',

+ 307
- 0
src/views/business/comps/template/comps/gsp/GSP009.vue View File

@ -0,0 +1,307 @@
<!-- 配体结合分析处理记录表 -->
<template>
<div>
<div class="detail-container">
<div class="detail-title"><img src="@/assets/images/detail-title.png">{{ formData.bdmc }}<img src="@/assets/images/detail-title.png" /></div>
<div class="detail-content">
<div class="content">
<BaseInfoFormPackage fieldItemLabel="template.common.baseInfo" label="template.common.baseInfo"
ref="baseInfoRef" :formConfig="baseInfoFormConfig" :formData="formData" />
<LineLabel label="template.lba.lba006.fxxx" />
<div v-if="fillType === 'preFill'" class="mt-20">
<el-button type="primary" @click="handleAddParalle(false)">{{ $t('template.lba.lba004.xz')
}}</el-button>
</div>
<!-- 平行配制区域 -->
<div :label="$t('template.common.pxpz')"
v-for="(paralleConfig, paralleIndex) in formData.paralleConfigs"
:key="'paralle_' + paralleIndex">
<div class="template-form-item">
<div class="config-header-end" v-if="fillType === 'preFill'">
<el-button type="danger" plain @click="deleteParalleConfig(paralleIndex)">{{ $t('template.lba.lba004.sc')}}</el-button>
</div>
<BaseInfoFormPackage @clickable="(e) => handleClickable('paralle', paralleIndex, e)"
:ref="`paralleStepFormPackageRef_${paralleIndex}`" :formConfig="paralleStepFormConfig"
:formData="paralleConfig" :prefixKey="'paralle' + paralleIndex"
:fieldItemLabel="$t('template.lba.lba004.xszj')" />
</div>
</div>
<BaseInfoFormPackage fieldItemLabel="template.common.remark" label="template.common.remark"
ref="remarkRef" :formConfig="remarkConig" :formData="formData" />
</div>
</div>
</div>
<!-- <button @click="onSave">保存</button> -->
</div>
</template>
<script>
import BaseInfoFormPackage from "@/components/Template/BaseInfoFormPackage";
import LineLabel from "@/components/Template/LineLabel";
import TableList from "@/components/Template/Table";
import Step from "@/components/Template/Step";
import templateMixin from "../../mixins/templateMixin";
import { EventBus } from "@/utils/eventBus";
import { uniqeResource,uniqeResourceOne } from "@/utils/calUnitTools";
import { duplicateResource } from "@/utils/index.js";
import { debounce } from 'lodash-es';
import CustomTable from '@/components/Template/CustomTable.vue';
import TableOpertaionDelete from "@/components/Template/operation/TableOpertaionDelete.vue"
export default {
name: "GSP009",
components: { BaseInfoFormPackage, LineLabel, TableList, Step,CustomTable,TableOpertaionDelete },
mixins: [templateMixin],
props: {
fillType: {
type: String,
default: 'preFill',
},
},
computed: {
//
remarkConig() {
return [
{
type: "cellItem",
config: {
remark: {
label: "",
type: "textarea",
fillType: "actFill",
span: 1,
placeholder: 'template.common.remarkPlaceholder',
maxlength: 1000,
rows: 5
}
}
}
]
},
//
baseInfoFormConfig() {
return [
{
type: "cardItem",
config: {
studyMc: {
label: 'template.common.testName',
type: "input",
disabled: true,
},
studySn: {
label: 'template.common.testNumber',
type: "input",
disabled: true,
},
methodCode: {
label: 'template.common.methodCode',
type: "input",
fillType: "actFill",
maxlength: 50
},
versionNum: {
label: 'template.common.versionNumber',
type: "inputNumber",
fillType: "actFill",
prepend: "V",
maxlength: 50
},
}
},
{
type: "conditionItem",
label: 'template.lba.lba006.fxtj',
config: {
act: {
label: 'template.common.actualFill',
type: "select",
fillType: "actFill",
otherCode: "actOther",
multiple: true,
options: this.getDictOptions('business_pztj')
}
}
},
{
type: "cellItem",
label: 'template.lba.lba006.fxsj',
config: {
startDate: {
label: 'template.common.startTime',
type: "input",
},
endDate: {
label: 'template.common.endTime',
type: "input",
},
}
}
]
},
paralleStepFormConfig(){
return [
{
type: 'step',
config: {
jcb: {
label: 'template.lba.lba006.jcb',
type: 'jcb',
fillType: 'actFill',
maxlength: 20
},
jg: {
label: 'template.lba.lba006.jg',
type: "sj",
fillType: "actFill",
otherLabel: " ",
otherCode: "jgOther",
otherMaxlength: 100,
multiple: false,
options: this.getDictOptions('business_lba_jg')
},
ms: {
label: 'template.lba.lba006.sjwjm',
type: 'text',
}
}
}
]
},
},
data() {
return {
formData: {}
};
},
mounted() {
this.handleAddParalle(true);
},
methods: {
//
getFilledFormData() {
const baseData = this.$refs.baseInfoRef.getFilledFormData();
const remarkData = this.$refs.remarkRef.getFilledFormData();
//
const paralleConfigsData = [];
if (this.formData.paralleConfigs && this.formData.paralleConfigs.length > 0) {
for (let i = 0; i < this.formData.paralleConfigs.length; i++) {
const paralleFormData = this.$refs[`paralleStepFormPackageRef_${i}`][0].getFilledFormData();
paralleConfigsData.push({
...paralleFormData,
showParalleConfig: true
});
}
}
return {
...baseData,
...remarkData,
paralleConfigs: paralleConfigsData,
}
},
//
async getFormData() {
//
const validFlag = await this.validFields();
if (!validFlag) {
return false;
}
let content = this.getFilledFormData();
return content
},
//
async validFields() {
//
let refsToValidate = ["baseInfoRef", "remarkRef"];
//
if (this.formData.paralleConfigs && this.formData.paralleConfigs.length > 0) {
for (let i = 0; i < this.formData.paralleConfigs.length; i++) {
refsToValidate.push(`paralleStepFormPackageRef_${i}`);
}
}
return await this.validFormFields(refsToValidate);
},
getResource() {
let content = this.getFilledFormData();
//使
this.resourceTmp = []
this.yqResourceTmp = []
return this.resourceTmp;
},
//
async onSave() {
const formData = this.getStepResource();
console.log(formData, "formData")
},
//
handleAddParalle(init) {
debugger
let isAdd = !init
if(init && (!this.formData.paralleConfigs || this.formData.paralleConfigs.length===0)){
isAdd = true
}
if(isAdd){
//
if (!this.formData.paralleConfigs) {
this.$set(this.formData, 'paralleConfigs', []);
}
//
this.formData.paralleConfigs.push({
showParalleConfig: true
});
}
//todo:
debugger
},
//
deleteParalleConfig(index) {
if(this.formData.paralleConfigs.length===1){
// this.$message.error("1");
return;
}
this.formData.paralleConfigs.splice(index, 1);
},
//
deleteRow(rowIndex, type, configIndex = 0) {
//
if (type === 'ladder') {
const tableRef = this.$refs[`ladderStepTableRef_${configIndex}`];
if (tableRef) {
tableRef.deleteRow(rowIndex);
}
} else if (type === 'paralle') {
const tableRef = this.$refs[`paralleStepTableRef_${configIndex}`];
if (tableRef) {
tableRef[0].deleteRow(rowIndex);
}
}
},
}
};
</script>
<style rel="stylesheet/scss" lang="scss">
.mt-20 {
margin-top: 20px;
}
.print-btn {
margin-bottom: 20px;
}
.config-header-end {
display: flex;
justify-content: flex-end;
align-items: center;
margin-bottom: 15px;
font-weight: bold;
font-size: 16px;
color: #303133;
}
</style>

+ 8
- 2
src/views/business/comps/template/comps/lba/LBA006.vue View File

@ -10,14 +10,18 @@
<LineLabel label="template.lba.lba006.fxxx" />
<div v-if="fillType === 'actFill'" class="mt-20">
<el-button type="primary" @click="handleAddParalle(false)">{{ $t('template.lba.lba004.xz')
}}</el-button>
</div>
<!-- 平行配制区域 -->
<div :label="$t('template.common.pxpz')"
v-for="(paralleConfig, paralleIndex) in formData.paralleConfigs"
:key="'paralle_' + paralleIndex">
<div class="template-form-item">
<div class="config-header-end">
<el-button type="primary" @click="handleAddParalle(false)">{{ $t('template.lba.lba004.xz')}}</el-button>
<div class="config-header-end" v-if="fillType === 'actFill'">
<el-button type="danger" plain @click="deleteParalleConfig(paralleIndex)">{{ $t('template.lba.lba004.sc')}}</el-button>
</div>
<BaseInfoFormPackage @clickable="(e) => handleClickable('paralle', paralleIndex, e)"
@ -242,6 +246,7 @@ export default {
},
//
handleAddParalle(init) {
debugger
let isAdd = !init
if(init && (!this.formData.paralleConfigs || this.formData.paralleConfigs.length===0)){
isAdd = true
@ -256,6 +261,7 @@ export default {
showParalleConfig: true
});
}
debugger
},
//
deleteParalleConfig(index) {

+ 12
- 3
src/views/business/comps/template/comps/pcr/PCR002.vue View File

@ -19,7 +19,8 @@
@onSureModifyRecord="onSureModifyRecord"
@resetRecord="resetRecord"
:formConfig="stepFormConfig" @blur="onHandleBlur" :formData="formData" />
<el-button type="primary">导入模板</el-button>
<el-button type="primary" @click="exportExcel(['a','b','c','d'])">下载模板</el-button>
<el-button type="primary" @click="showImportExcelDialog">导入模板</el-button>
<CustomTable
@blur="onHandleTableBlur"
:ref="`stepTableRef`"
@ -52,6 +53,7 @@
<SelectReagentDialog @submit="onSelectReagentSubmit" ref="selectReagentDialogRef">
</SelectReagentDialog>
<!-- <button @click="onSave">保存</button> -->
<ImportExcelDialog ref="ImportExcelDialog" @onLoadData="onLoadData"/>
</div>
</template>
@ -68,10 +70,10 @@ import SelectReagentDialog from '../../dialog/SelectReagentDialog.vue';
import { getLadderColumnsConfig } from "../../formConfig/PCRTableConfig.js";
import TableOpertaion from "@/components/Template/operation/TableOpertaion.vue"
import { addTj,uniqeResource,uniqeResourceOne,addDecimals } from "@/utils/calUnitTools";
import ImportExcelDialog from '../../dialog/ImportExcelDialog'
export default {
name: "PCR002",
components: { BaseInfoFormPackage, LineLabel, TableList, Step, CustomTable, TableOpertaion, SelectReagentDialog },
components: { ImportExcelDialog, BaseInfoFormPackage, LineLabel, TableList, Step, CustomTable, TableOpertaion, SelectReagentDialog },
mixins: [templateMixin],
props: {
fillType: {
@ -259,6 +261,13 @@ export default {
},
methods: {
showImportExcelDialog() {
this.$refs.ImportExcelDialog.show()
},
onLoadData(excelData) {
console.log('onLoadData')
console.log(excelData)
},
//
onSureModifyRecord(key) {
if (key === "subStartSolution") {//table

+ 97
- 0
src/views/business/comps/template/dialog/ImportExcelDialog.vue View File

@ -0,0 +1,97 @@
<template>
<div>
<!-- 导入excel模板 -->
<el-dialog :close-on-click-modal="false" :close-on-press-escape="false" :title="title" :visible.sync="open"
width="400px" @close="close" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :disabled="upload.isUploading" action=""
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xlsxlsx格式文件</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel">{{ $t('form.cancel') }}</el-button>
<el-button type="primary" @click="save">{{ $t('form.confirm') }}</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import * as XLSX from 'xlsx'
export default {
name: "ImportEccelDialog",
components: {},
data() {
return {
title: this.$t('form.modify'),
open: false,
upload: {
//
isUploading: false,
},
excelData: null,
}
},
computed: {
},
created() {
},
methods: {
show() {
this.open = true
},
cancel() {
this.open = false
},
close() {
if (!this.isChecked) {
this.$emit('cancel')
}
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true
console.log('.....')
},
//
handleFileSuccess(response, file, fileList) {
this.open = false
this.upload.isUploading = false
this.$refs.upload.clearFiles()
},
//
save() {
const file = this.$refs.upload.uploadFiles
if (!file || file.length === 0 || !file[0].name.toLowerCase().endsWith('.xls') && !file[0].name.toLowerCase().endsWith('.xlsx')) {
this.$modal.msgError("请选择后缀为 “xls”或“xlsx”的文件。")
return
}
const reader = new FileReader()
reader.onload = (event) => {
try {
const data = event.target.result
// Excel
const workbook = XLSX.read(data, { type: 'binary' })
//
const firstSheetName = workbook.SheetNames[0]
const worksheet = workbook.Sheets[firstSheetName]
// header:1
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 })
this.excelData = jsonData
this.$emit('onLoadData', this.excelData)
} catch (error) {
console.error('解析失败:', error)
this.$modal.msgError('文件解析失败,请检查格式', error)
}
}
reader.readAsArrayBuffer(file[0].raw);
},
}
}
</script>

+ 42
- 8
src/views/business/comps/template/mixins/templateMixin.js View File

@ -29,7 +29,7 @@ export default {
'business_sp_xskkx', //色谱-编号-稀释可靠性
'business_sp_cbydb', //色谱-编号-储备液对比
'business_pcr_gzy', // PCR-编号-工作液
'business_lba_jg' // LBA006-结果
],
props: {
@ -383,7 +383,7 @@ export default {
subTargetStartSolution,
headerSelectFields
}
arr.forEach((item, rowIndex) => {
this.updateTargetStartSolutionVolume(
item,
@ -471,7 +471,7 @@ export default {
// 实际目标溶液浓度 = 实际源溶液浓度÷(实际终体积÷源溶液加入体积);
const actNd = (
parseFloat(targetAcSolution) / (
parseFloat(actVol)/parseFloat(actStartSolutionVolume)
parseFloat(actVol)/parseFloat(actStartSolutionVolume)
)
).toFixed(precision)
const nd = actNd === 'Infinity' ? 0 : Number(actNd)
@ -492,19 +492,19 @@ export default {
const {subTargetStartSolution,headerSelectFields} = unitParams
const {targetSolutionConcentrationUnit,targetSolutionVolumeUnit,targetStartSolutionVolumeUnit,targetDiluentVolumeUnit} = headerSelectFields
const targetStartVolUnit = targetSolutionConcentrationUnit.split("/")[1];//先按照预设目标溶液浓度的单位标准
if(
isValueEmpty(concentration) ||
isValueEmpty(concentration) ||
isValueEmpty(targetVolume)||
isValueEmpty(subTargetStartSolution)||
isValueEmpty(targetSolutionConcentrationUnit)||
isValueEmpty(targetSolutionVolumeUnit)||
isValueEmpty(targetStartSolutionVolumeUnit)||
isValueEmpty(targetStartSolutionVolumeUnit)||
isValueEmpty(targetDiluentVolumeUnit)
){
return;
}
//将起始溶液浓度转换为和预设目标溶液浓度一样的单位再计算;
//将起始溶液浓度转换为和预设目标溶液浓度一样的单位再计算;
const converStartCon = convertConcentration.convert(volume+subTargetStartSolution,targetSolutionConcentrationUnit)
//将预设目标溶液体积转换为和预设目标溶液浓度单位的分母一样的单位再计算;如:预设目标溶液浓度单位为mg/mL,预设目标溶液体积单位为uL,则将预设目标溶液体积转换为mL
const convertTargetVol = volumeConverter.convert(targetVolume+targetSolutionVolumeUnit,targetStartVolUnit)
@ -526,6 +526,40 @@ export default {
item.targetDiluentVolume = volumeConverter.convert(result1+targetStartSolutionVolumeUnit,targetDiluentVolumeUnit)
// this.$refs.stepTableRef.updateDataSourceByRowIndex(rowIndex, { targetDiluentVolume: result1 });
}
}
},
// 导出excel模板
exportExcel(rows, title) {
let that = this
that.$modal.loading()
var tabelStr =
'<table border="1" class="html-tabel">' +
'<tr style="background:#eee;">'
rows.forEach(item => {
tabelStr = tabelStr + '<th style="text-align: center;">' + item + '</th>'
})
tabelStr = tabelStr + ' </tr><table>'
// Worksheet名
var worksheet = title ? title : '导入模板'
var uri = 'data:application/vnd.ms-excel;base64,'
// 真正要导出(下载)的HTML模板
var exportTemplate = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
<head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
<x:Name>${worksheet}</x:Name>
<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
</x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
</head>
<body>
${tabelStr}
</body>
</html>`
var a = document.createElement('a')
a.download = worksheet + '.xls'
a.href = uri + window.btoa(unescape(encodeURIComponent(exportTemplate)))
a.click()
that.$modal.closeLoading()
},
}
}

Loading…
Cancel
Save