| @ -1,399 +1,332 @@ | |||
| <template> | |||
| <div class="step-container"> | |||
| <el-button v-if = "isShowAddStep()" type="primary" @click="addStep" icon="el-icon-plus">添加步骤</el-button> | |||
| <div class="step-list"> | |||
| <div | |||
| v-for="(step, index) in steps" | |||
| :key="step.id" | |||
| class="step-item" | |||
| > | |||
| <div class="step-content"> | |||
| <span class="step-title">{{ index + 1 }}</span> | |||
| <HandleFormItem | |||
| type = "select" | |||
| placeholder="请选择" | |||
| class="step-type-select" | |||
| :item = "stepSelectConfig" | |||
| v-model="step.type" | |||
| @change="onTypeChange(index)" | |||
| /> | |||
| <!-- 根据步骤类型显示对应的表单 --> | |||
| <component :is="getStepComponent(step.type)" | |||
| :step-data="step.formData" | |||
| @update="onFormUpdate(index, $event)"> | |||
| </component> | |||
| <div class="step-header-item"> | |||
| <el-button | |||
| type="text" | |||
| @click="removeStep(index)" | |||
| icon="el-icon-delete" | |||
| class="delete-btn" | |||
| ></el-button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="step-container"> | |||
| <el-button v-if="isShowAddStep()" type="primary" @click="addStep" icon="el-icon-plus">添加步骤</el-button> | |||
| <div class="step-list"> | |||
| <div v-for="(step, index) in steps" :key="step.id" class="step-item"> | |||
| <div class="step-content"> | |||
| <span class="step-title">{{ index + 1 }}</span> | |||
| <HandleFormItem type="select" placeholder="请选择" class="step-type-select" :item="stepSelectConfig" | |||
| v-model="step.type" @change="onTypeChange(index)" /> | |||
| <!-- 根据步骤类型显示对应的表单 --> | |||
| <component :is="getStepComponent(step.type)" :step-data="step.formData" | |||
| @update="onFormUpdate(index, $event)"> | |||
| </component> | |||
| <div class="step-header-item"> | |||
| <el-button type="text" @click="removeStep(index)" icon="el-icon-delete" | |||
| class="delete-btn"></el-button> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| import ContainerStep from './StepComponents/ContainerStep.vue' | |||
| import CentrifugeStep from './StepComponents/CentrifugeStep.vue' | |||
| import AutoWeighStep from './StepComponents/AutoWeighStep.vue' | |||
| import ManualWeighStep from './StepComponents/ManualWeighStep.vue' | |||
| import AddSolutionStep from './StepComponents/AddSolutionStep.vue' | |||
| import MixStep from './StepComponents/MixStep.vue' | |||
| import UltrasoundStep from './StepComponents/UltrasoundStep.vue' | |||
| import FiltrationStep from './StepComponents/FiltrationStep.vue' | |||
| import PackageStep from './StepComponents/PackageStep.vue' | |||
| import Seal2Step from './StepComponents/Seal2Step.vue' | |||
| import Seal3Step from './StepComponents/Seal3Step.vue' | |||
| import VortexStep from './StepComponents/VortexStep.vue' | |||
| import CoatStep from './StepComponents/CoatStep.vue' | |||
| import StaticStartStep from './StepComponents/StaticStartStep.vue' | |||
| import StaticEndStep from './StepComponents/StaticEndStep.vue' | |||
| import TakePlateStep from './StepComponents/TakePlateStep.vue' | |||
| import HandleFormItem from './HandleFormItem.vue' | |||
| const stepTypes = [ | |||
| { label: '容器选择', value: 'container' }, | |||
| // { label: '离心', value: 'centrifuge' }, | |||
| // { label: '自动称量', value: 'autoWeigh' }, | |||
| // { label: '手动称量', value: 'manualWeigh' }, | |||
| // { label: '加入溶液', value: 'addSolution' }, | |||
| // { label: '混合', value: 'mix' }, | |||
| // { label: '超声', value: 'ultrasound' }, | |||
| // { label: '抽滤', value: 'filtration' }, | |||
| // { label: '分装', value: 'package' }, | |||
| // { label: '封装2管', value: 'seal2' }, | |||
| // { label: '封装3管', value: 'seal3' }, | |||
| // { label: '漩涡混匀', value: 'vortex' }, | |||
| // { label: '包被', value: 'coat' }, | |||
| // { label: '静置开始', value: 'staticStart' }, | |||
| // { label: '静置结束', value: 'staticEnd' }, | |||
| // { label: '取板', value: 'takePlate' } | |||
| ]; | |||
| import HandleFormItem from './HandleFormItem.vue'; | |||
| import Czdd from './StepComponents/ry/czdd.vue';//溶液-操作地点 | |||
| const stepTypes = [ | |||
| { label: '容器选择', value: 'container' }, | |||
| { label: '操作地点', value: 'czdd' }, | |||
| ]; | |||
| export default { | |||
| inject: ['templateFillType'], | |||
| name: 'Step', | |||
| props: { | |||
| formData: { | |||
| type: Array, | |||
| default: () => [] | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| stepSelectConfig:{ | |||
| options: stepTypes, | |||
| fillType:"preFill", | |||
| placeholder:"请选择步骤类型" | |||
| }, | |||
| steps: [], | |||
| stepId: 1, | |||
| componentMap: null | |||
| } | |||
| }, | |||
| computed: { | |||
| stepComponentMap() { | |||
| if (!this.componentMap) { | |||
| this.componentMap = { | |||
| 'container': 'ContainerStep', | |||
| 'centrifuge': 'CentrifugeStep', | |||
| 'autoWeigh': 'AutoWeighStep', | |||
| 'manualWeigh': 'ManualWeighStep', | |||
| 'addSolution': 'AddSolutionStep', | |||
| 'mix': 'MixStep', | |||
| 'ultrasound': 'UltrasoundStep', | |||
| 'filtration': 'FiltrationStep', | |||
| 'package': 'PackageStep', | |||
| 'seal2': 'Seal2Step', | |||
| 'seal3': 'Seal3Step', | |||
| 'vortex': 'VortexStep', | |||
| 'coat': 'CoatStep', | |||
| 'staticStart': 'StaticStartStep', | |||
| 'staticEnd': 'StaticEndStep', | |||
| 'takePlate': 'TakePlateStep' | |||
| } | |||
| } | |||
| return this.componentMap | |||
| } | |||
| }, | |||
| components: { | |||
| HandleFormItem, | |||
| ContainerStep, | |||
| CentrifugeStep, | |||
| AutoWeighStep, | |||
| ManualWeighStep, | |||
| AddSolutionStep, | |||
| MixStep, | |||
| UltrasoundStep, | |||
| FiltrationStep, | |||
| PackageStep, | |||
| Seal2Step, | |||
| Seal3Step, | |||
| VortexStep, | |||
| CoatStep, | |||
| StaticStartStep, | |||
| StaticEndStep, | |||
| TakePlateStep | |||
| }, | |||
| created() { | |||
| // // 初始化步骤数据 | |||
| // if (this.value && this.value.length > 0) { | |||
| // this.steps = this.value.map((step) => ({ | |||
| // id: this.stepId++, | |||
| // type: step.type || '', | |||
| // formData: step.formData || {} | |||
| // })) | |||
| // } else { | |||
| // // 默认添加一个步骤 | |||
| // this.addStep() | |||
| // } | |||
| }, | |||
| watch: { | |||
| steps: { | |||
| handler(newVal) { | |||
| this.$emit('input', newVal.map(step => ({ | |||
| type: step.type, | |||
| formData: step.formData | |||
| }))) | |||
| }, | |||
| deep: true | |||
| }, | |||
| 'formData': { | |||
| handler(newVal) { | |||
| console.log('stepValue', newVal) | |||
| if(!newVal || newVal.length === 0) return | |||
| this.steps = newVal.map((step) => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step | |||
| })) | |||
| }, | |||
| deep: true, | |||
| immediate: true | |||
| } | |||
| }, | |||
| methods: { | |||
| isShowAddStep() { | |||
| return this.templateFillType === 'preFill'; | |||
| }, | |||
| addStep() { | |||
| try { | |||
| this.steps.push({ | |||
| id: this.stepId++, | |||
| type: '', | |||
| formData: {} | |||
| }) | |||
| this.$emit('step-added', this.steps.length) | |||
| } catch (error) { | |||
| console.error('添加步骤失败:', error) | |||
| this.$message.error('添加步骤失败,请重试') | |||
| } | |||
| }, | |||
| removeStep(index) { | |||
| if (this.steps.length > 1) { | |||
| const removedStep = this.steps.splice(index, 1)[0] | |||
| this.$emit('step-removed', { index, step: removedStep, remaining: this.steps.length }) | |||
| } else { | |||
| this.$message.warning('至少需要保留一个步骤') | |||
| } | |||
| }, | |||
| onTypeChange(index) { | |||
| // 切换步骤类型时重置表单数据,并确保数据更新 | |||
| const oldType = this.steps[index].type | |||
| this.$set(this.steps[index], 'formData', {}) | |||
| // 可选:添加类型变化的回调 | |||
| this.$emit('step-type-changed', { | |||
| index, | |||
| newType: this.steps[index].type, | |||
| oldType | |||
| }) | |||
| }, | |||
| onFormUpdate(stepIndex, formData) { | |||
| console.log('stepIndex', stepIndex) | |||
| console.log('formData', formData) | |||
| this.steps[stepIndex].formData = formData | |||
| }, | |||
| getStepComponent(type) { | |||
| // 使用计算属性中的映射,提高性能 | |||
| return this.stepComponentMap[type] | |||
| }, | |||
| // 公共方法:获取所有步骤数据 | |||
| getFormData() { | |||
| return new Promise((resolve, reject) => { | |||
| // 校验所有步骤是否填写完整 | |||
| const validation = this.validateSteps() | |||
| if (!validation.isValid) { | |||
| // this.$message.error(validation.errors[0]) | |||
| reject(validation.errors[0]) | |||
| return | |||
| } | |||
| // 检查是否有步骤数据 | |||
| if (this.steps.length === 0) { | |||
| // this.$message.error(this.$t('template.common.addStepError')) | |||
| reject({errorType:"step"}); | |||
| return | |||
| } | |||
| const stepData = this.steps.map(step => ({ | |||
| type: step.type, | |||
| ...step.formData | |||
| })) | |||
| resolve({stepData}) | |||
| }) | |||
| }, | |||
| // 直接获取表单数据,不做校验 | |||
| getFilledFormData() { | |||
| const stepData = this.steps.map(step => ({ | |||
| type: step.type, | |||
| ...step.formData | |||
| })) | |||
| return {stepData} | |||
| }, | |||
| // 公共方法:设置步骤数据 | |||
| setStepData(data) { | |||
| if (Array.isArray(data)) { | |||
| this.steps = data.map(step => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step.formData || {} | |||
| })) | |||
| } | |||
| }, | |||
| // 公共方法:重置所有步骤 | |||
| resetSteps() { | |||
| this.steps = [{ | |||
| id: this.stepId++, | |||
| type: '', | |||
| formData: {} | |||
| }] | |||
| this.$emit('steps-reset') | |||
| }, | |||
| // 公共方法:获取指定步骤的数据 | |||
| getStepDataByIndex(index) { | |||
| if (index >= 0 && index < this.steps.length) { | |||
| return { | |||
| type: this.steps[index].type, | |||
| formData: this.steps[index].formData | |||
| } | |||
| } | |||
| return null | |||
| }, | |||
| // 公共方法:验证所有步骤 | |||
| validateSteps() { | |||
| const errors = [] | |||
| this.steps.forEach((step, index) => { | |||
| if (!step.type) { | |||
| errors.push(`步骤 ${index + 1}: 请选择步骤类型`) | |||
| } | |||
| // 可以在这里添加更具体的表单验证逻辑 | |||
| }) | |||
| return { | |||
| isValid: errors.length === 0, | |||
| errors | |||
| } | |||
| }, | |||
| // 公共方法:批量导入步骤数据 | |||
| importSteps(stepDataArray) { | |||
| if (Array.isArray(stepDataArray)) { | |||
| this.steps = stepDataArray.map((step, index) => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step.formData || {} | |||
| })) | |||
| this.$emit('steps-imported', this.steps.length) | |||
| } | |||
| }, | |||
| // 公共方法:获取步骤统计信息 | |||
| getStepStatistics() { | |||
| const stats = { | |||
| total: this.steps.length, | |||
| byType: {}, | |||
| filled: 0 | |||
| } | |||
| this.steps.forEach(step => { | |||
| // 统计各类型数量 | |||
| if (step.type) { | |||
| stats.byType[step.type] = (stats.byType[step.type] || 0) + 1 | |||
| } | |||
| // 统计已填写的步骤 | |||
| if (step.type && Object.keys(step.formData).length > 0) { | |||
| stats.filled++ | |||
| } | |||
| }) | |||
| return stats | |||
| } | |||
| }, | |||
| inject: ['templateFillType'], | |||
| name: 'Step', | |||
| props: { | |||
| formData: { | |||
| type: Array, | |||
| default: () => [] | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| stepSelectConfig: { | |||
| options: stepTypes, | |||
| fillType: "preFill", | |||
| placeholder: "请选择步骤类型" | |||
| }, | |||
| steps: [], | |||
| stepId: 1, | |||
| componentMap: null | |||
| } | |||
| }, | |||
| components: { | |||
| HandleFormItem, | |||
| ContainerStep, | |||
| Czdd, | |||
| }, | |||
| computed: { | |||
| stepComponentMap() { | |||
| if (!this.componentMap) { | |||
| this.componentMap = { | |||
| 'container': 'ContainerStep', | |||
| 'czdd': 'Czdd', | |||
| } | |||
| } | |||
| return this.componentMap | |||
| } | |||
| }, | |||
| created() { | |||
| // // 初始化步骤数据 | |||
| // if (this.value && this.value.length > 0) { | |||
| // this.steps = this.value.map((step) => ({ | |||
| // id: this.stepId++, | |||
| // type: step.type || '', | |||
| // formData: step.formData || {} | |||
| // })) | |||
| // } else { | |||
| // // 默认添加一个步骤 | |||
| // this.addStep() | |||
| // } | |||
| }, | |||
| watch: { | |||
| steps: { | |||
| handler(newVal) { | |||
| this.$emit('input', newVal.map(step => ({ | |||
| type: step.type, | |||
| formData: step.formData | |||
| }))) | |||
| }, | |||
| deep: true | |||
| }, | |||
| 'formData': { | |||
| handler(newVal) { | |||
| console.log('stepValue', newVal) | |||
| if (!newVal || newVal.length === 0) return | |||
| this.steps = newVal.map((step) => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step | |||
| })) | |||
| }, | |||
| deep: true, | |||
| immediate: true | |||
| } | |||
| }, | |||
| methods: { | |||
| isShowAddStep() { | |||
| return this.templateFillType === 'preFill'; | |||
| }, | |||
| addStep() { | |||
| try { | |||
| this.steps.push({ | |||
| id: this.stepId++, | |||
| type: '', | |||
| formData: {} | |||
| }) | |||
| this.$emit('step-added', this.steps.length) | |||
| } catch (error) { | |||
| console.error('添加步骤失败:', error) | |||
| this.$message.error('添加步骤失败,请重试') | |||
| } | |||
| }, | |||
| removeStep(index) { | |||
| if (this.steps.length > 1) { | |||
| const removedStep = this.steps.splice(index, 1)[0] | |||
| this.$emit('step-removed', { index, step: removedStep, remaining: this.steps.length }) | |||
| } else { | |||
| this.$message.warning('至少需要保留一个步骤') | |||
| } | |||
| }, | |||
| onTypeChange(index) { | |||
| // 切换步骤类型时重置表单数据,并确保数据更新 | |||
| const oldType = this.steps[index].type | |||
| this.$set(this.steps[index], 'formData', {}) | |||
| // 可选:添加类型变化的回调 | |||
| this.$emit('step-type-changed', { | |||
| index, | |||
| newType: this.steps[index].type, | |||
| oldType | |||
| }) | |||
| }, | |||
| onFormUpdate(stepIndex, formData) { | |||
| console.log('stepIndex', stepIndex) | |||
| console.log('formData', formData) | |||
| this.steps[stepIndex].formData = formData | |||
| }, | |||
| getStepComponent(type) { | |||
| // 使用计算属性中的映射,提高性能 | |||
| return this.stepComponentMap[type] | |||
| }, | |||
| // 公共方法:获取所有步骤数据 | |||
| getFormData() { | |||
| return new Promise((resolve, reject) => { | |||
| // 校验所有步骤是否填写完整 | |||
| const validation = this.validateSteps() | |||
| if (!validation.isValid) { | |||
| // this.$message.error(validation.errors[0]) | |||
| reject(validation.errors[0]) | |||
| return | |||
| } | |||
| // 检查是否有步骤数据 | |||
| if (this.steps.length === 0) { | |||
| // this.$message.error(this.$t('template.common.addStepError')) | |||
| reject({ errorType: "step" }); | |||
| return | |||
| } | |||
| const stepData = this.steps.map(step => ({ | |||
| type: step.type, | |||
| ...step.formData | |||
| })) | |||
| resolve({ stepData }) | |||
| }) | |||
| }, | |||
| // 直接获取表单数据,不做校验 | |||
| getFilledFormData() { | |||
| const stepData = this.steps.map(step => ({ | |||
| type: step.type, | |||
| ...step.formData | |||
| })) | |||
| return { stepData } | |||
| }, | |||
| // 公共方法:设置步骤数据 | |||
| setStepData(data) { | |||
| if (Array.isArray(data)) { | |||
| this.steps = data.map(step => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step.formData || {} | |||
| })) | |||
| } | |||
| }, | |||
| // 公共方法:重置所有步骤 | |||
| resetSteps() { | |||
| this.steps = [{ | |||
| id: this.stepId++, | |||
| type: '', | |||
| formData: {} | |||
| }] | |||
| this.$emit('steps-reset') | |||
| }, | |||
| // 公共方法:获取指定步骤的数据 | |||
| getStepDataByIndex(index) { | |||
| if (index >= 0 && index < this.steps.length) { | |||
| return { | |||
| type: this.steps[index].type, | |||
| formData: this.steps[index].formData | |||
| } | |||
| } | |||
| return null | |||
| }, | |||
| // 公共方法:验证所有步骤 | |||
| validateSteps() { | |||
| const errors = [] | |||
| this.steps.forEach((step, index) => { | |||
| if (!step.type) { | |||
| errors.push(`步骤 ${index + 1}: 请选择步骤类型`) | |||
| } | |||
| // 可以在这里添加更具体的表单验证逻辑 | |||
| }) | |||
| return { | |||
| isValid: errors.length === 0, | |||
| errors | |||
| } | |||
| }, | |||
| // 公共方法:批量导入步骤数据 | |||
| importSteps(stepDataArray) { | |||
| if (Array.isArray(stepDataArray)) { | |||
| this.steps = stepDataArray.map((step, index) => ({ | |||
| id: this.stepId++, | |||
| type: step.type || '', | |||
| formData: step.formData || {} | |||
| })) | |||
| this.$emit('steps-imported', this.steps.length) | |||
| } | |||
| }, | |||
| // 公共方法:获取步骤统计信息 | |||
| getStepStatistics() { | |||
| const stats = { | |||
| total: this.steps.length, | |||
| byType: {}, | |||
| filled: 0 | |||
| } | |||
| this.steps.forEach(step => { | |||
| // 统计各类型数量 | |||
| if (step.type) { | |||
| stats.byType[step.type] = (stats.byType[step.type] || 0) + 1 | |||
| } | |||
| // 统计已填写的步骤 | |||
| if (step.type && Object.keys(step.formData).length > 0) { | |||
| stats.filled++ | |||
| } | |||
| }) | |||
| return stats | |||
| } | |||
| }, | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .step-container { | |||
| box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |||
| margin-top: 24px; | |||
| padding: 24px; | |||
| border-radius: 5px 5px; | |||
| .step-header { | |||
| margin-bottom: 20px; | |||
| padding: 15px; | |||
| background: #f5f7fa; | |||
| border-radius: 6px; | |||
| } | |||
| .step-list { | |||
| .step-item { | |||
| margin-top: 20px; | |||
| border-radius: 6px; | |||
| overflow: hidden; | |||
| .step-title { | |||
| margin-right: 10px; | |||
| } | |||
| .step-type-select{ | |||
| width: 200px; | |||
| margin-right: 10px; | |||
| max-width: 200px; | |||
| } | |||
| .delete-btn { | |||
| color: #f56c6c; | |||
| &:hover { | |||
| color: #f78989; | |||
| } | |||
| &:disabled { | |||
| color: #c0c4cc; | |||
| } | |||
| } | |||
| .step-content { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| } | |||
| } | |||
| box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |||
| margin-top: 24px; | |||
| padding: 24px; | |||
| border-radius: 5px 5px; | |||
| .step-header { | |||
| margin-bottom: 20px; | |||
| padding: 15px; | |||
| background: #f5f7fa; | |||
| border-radius: 6px; | |||
| } | |||
| .step-list { | |||
| .step-item { | |||
| margin-top: 20px; | |||
| border-radius: 6px; | |||
| overflow: hidden; | |||
| .step-title { | |||
| margin-right: 10px; | |||
| } | |||
| .step-type-select { | |||
| width: 200px; | |||
| margin-right: 10px; | |||
| max-width: 200px; | |||
| } | |||
| .delete-btn { | |||
| color: #f56c6c; | |||
| &:hover { | |||
| color: #f78989; | |||
| } | |||
| &:disabled { | |||
| color: #c0c4cc; | |||
| } | |||
| } | |||
| .step-content { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -1,66 +0,0 @@ | |||
| <template> | |||
| <div class="add-solution-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="溶液名称"> | |||
| <el-input v-model="formData.solutionName" placeholder="请输入溶液名称"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="加入体积"> | |||
| <div style="display: flex; gap: 10px;"> | |||
| <el-input v-model="formData.volume" placeholder="体积"></el-input> | |||
| <el-select v-model="formData.unit" style="width: 80px;"> | |||
| <el-option label="μl" value="μl"></el-option> | |||
| <el-option label="ml" value="ml"></el-option> | |||
| <el-option label="l" value="l"></el-option> | |||
| </el-select> | |||
| </div> | |||
| </el-form-item> | |||
| <el-form-item label="浓度"> | |||
| <el-input v-model="formData.concentration" placeholder="请输入浓度"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度(℃)"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="加入速度"> | |||
| <el-select v-model="formData.additionSpeed" placeholder="请选择加入速度"> | |||
| <el-option label="慢速" value="slow"></el-option> | |||
| <el-option label="中速" value="medium"></el-option> | |||
| <el-option label="快速" value="fast"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input v-model="formData.notes" type="textarea" :rows="2"></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'AddSolutionStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| solutionName: '', | |||
| volume: '', | |||
| unit: 'ml', | |||
| concentration: '', | |||
| temperature: '', | |||
| additionSpeed: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,89 +0,0 @@ | |||
| <!-- 自动称重步骤表单 --> | |||
| <template> | |||
| <div class="flex"> | |||
| <div class="form-label">选择</div> | |||
| <HandleFormItem | |||
| class = "w-120" | |||
| :item="fieldConfigs.notes" | |||
| v-model="formData.notes" | |||
| /> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| import HandleFormItem from '../HandleFormItem.vue' | |||
| import Input from '../Input.vue' | |||
| export default { | |||
| name: 'AutoWeighStep', | |||
| components: { | |||
| HandleFormItem, | |||
| Input | |||
| }, | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| targetWeight: '123', | |||
| tolerance: '', | |||
| sampleName: '', | |||
| containerWeight: '', | |||
| notes: '' | |||
| }, | |||
| // 字段配置 | |||
| fieldConfigs: { | |||
| targetWeight: { | |||
| label: '目标重量', | |||
| placeholder: '请输入目标重量', | |||
| maxlength: 50 | |||
| }, | |||
| tolerance: { | |||
| label: '允许误差', | |||
| placeholder: '请输入允许误差', | |||
| maxlength: 20 | |||
| }, | |||
| sampleName: { | |||
| label: '样品名称', | |||
| placeholder: '请输入样品名称', | |||
| maxlength: 100 | |||
| }, | |||
| containerWeight: { | |||
| label: '容器重量', | |||
| placeholder: '请输入容器重量', | |||
| maxlength: 20 | |||
| }, | |||
| notes: { | |||
| label: '备注', | |||
| placeholder: '请输入备注信息', | |||
| maxlength: 500 | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| // 合并传入的数据 | |||
| if (this.stepData) { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| }, | |||
| methods: { | |||
| onFieldChange(field, value) { | |||
| this.formData[field] = value | |||
| }, | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .w-120{ | |||
| width: 120px; | |||
| } | |||
| </style> | |||
| @ -1,62 +0,0 @@ | |||
| <template> | |||
| <div class="centrifuge-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="转速(rpm)"> | |||
| <el-input v-model="formData.speed" placeholder="请输入转速"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="时间(min)"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度(℃)"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="加速度"> | |||
| <el-select v-model="formData.acceleration" placeholder="请选择加速度"> | |||
| <el-option label="慢" value="slow"></el-option> | |||
| <el-option label="中" value="medium"></el-option> | |||
| <el-option label="快" value="fast"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="减速度"> | |||
| <el-select v-model="formData.deceleration" placeholder="请选择减速度"> | |||
| <el-option label="慢" value="slow"></el-option> | |||
| <el-option label="中" value="medium"></el-option> | |||
| <el-option label="快" value="fast"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input v-model="formData.notes" type="textarea" :rows="2"></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'CentrifugeStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| speed: '', | |||
| time: '', | |||
| temperature: '', | |||
| acceleration: '', | |||
| deceleration: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,152 +0,0 @@ | |||
| <template> | |||
| <div class="coat-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="包被物质"> | |||
| <el-input v-model="formData.coatMaterial" placeholder="请输入包被物质名称"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="包被浓度"> | |||
| <el-input v-model="formData.concentration" placeholder="请输入浓度值"> | |||
| <el-select v-model="formData.concentrationUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="mg/ml" value="mg/ml"></el-option> | |||
| <el-option label="μg/ml" value="μg/ml"></el-option> | |||
| <el-option label="ng/ml" value="ng/ml"></el-option> | |||
| <el-option label="%" value="%"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="包被体积"> | |||
| <el-input v-model="formData.volume" placeholder="请输入体积"> | |||
| <el-select v-model="formData.unit" slot="append" style="width: 80px;"> | |||
| <el-option label="ml" value="ml"></el-option> | |||
| <el-option label="μl" value="μl"></el-option> | |||
| <el-option label="l" value="l"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="包被时间"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"> | |||
| <el-select v-model="formData.timeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| <el-option label="d" value="d"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度条件"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="pH值"> | |||
| <el-input-number | |||
| v-model="formData.pH" | |||
| :min="1" | |||
| :max="14" | |||
| :step="0.1" | |||
| :precision="1" | |||
| placeholder="请输入pH值" | |||
| ></el-input-number> | |||
| </el-form-item> | |||
| <el-form-item label="容器类型"> | |||
| <el-select v-model="formData.containerType" placeholder="请选择容器类型"> | |||
| <el-option label="微孔板" value="microplate"></el-option> | |||
| <el-option label="培养皿" value="petriDish"></el-option> | |||
| <el-option label="载玻片" value="slide"></el-option> | |||
| <el-option label="试管" value="testTube"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="包被方法"> | |||
| <el-radio-group v-model="formData.method"> | |||
| <el-radio label="passive">被动吸附</el-radio> | |||
| <el-radio label="active">共价结合</el-radio> | |||
| </el-radio-group> | |||
| </el-form-item> | |||
| <el-form-item label="洗涤步骤"> | |||
| <el-checkbox-group v-model="formData.washSteps"> | |||
| <el-checkbox label="包被前洗涤">包被前洗涤</el-checkbox> | |||
| <el-checkbox label="包被后洗涤">包被后洗涤</el-checkbox> | |||
| <el-checkbox label="封闭前洗涤">封闭前洗涤</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="封闭处理"> | |||
| <el-switch v-model="formData.blocking"></el-switch> | |||
| </el-form-item> | |||
| <el-form-item v-if="formData.blocking" label="封闭剂"> | |||
| <el-input v-model="formData.blockingAgent" placeholder="请输入封闭剂名称"></el-input> | |||
| </el-form-item> | |||
| <el-form-item v-if="formData.blocking" label="封闭时间"> | |||
| <el-input v-model="formData.blockingTime" placeholder="请输入封闭时间"> | |||
| <el-select v-model="formData.blockingTimeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'CoatStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| coatMaterial: '', | |||
| concentration: '', | |||
| concentrationUnit: 'mg/ml', | |||
| volume: '', | |||
| unit: 'ml', | |||
| time: '', | |||
| timeUnit: 'h', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| pH: '', | |||
| containerType: '', | |||
| method: 'passive', | |||
| washSteps: [], | |||
| blocking: false, | |||
| blockingAgent: '', | |||
| blockingTime: '', | |||
| blockingTimeUnit: 'min', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,84 +0,0 @@ | |||
| <template> | |||
| <div class="filtration-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="滤膜类型"> | |||
| <el-select v-model="formData.filterType" placeholder="请选择滤膜类型"> | |||
| <el-option label="0.22μm" value="0.22"></el-option> | |||
| <el-option label="0.45μm" value="0.45"></el-option> | |||
| <el-option label="0.8μm" value="0.8"></el-option> | |||
| <el-option label="1.2μm" value="1.2"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="压力"> | |||
| <el-input v-model="formData.pressure" placeholder="请输入压力值"> | |||
| <el-select v-model="formData.pressureUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="kPa" value="kPa"></el-option> | |||
| <el-option label="bar" value="bar"></el-option> | |||
| <el-option label="psi" value="psi"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="过滤时间"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"> | |||
| <el-select v-model="formData.timeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="s" value="s"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'FiltrationStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| filterType: '', | |||
| pressure: '', | |||
| pressureUnit: 'kPa', | |||
| time: '', | |||
| timeUnit: 'min', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,50 +0,0 @@ | |||
| <template> | |||
| <div class="manual-weigh-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="实际重量(g)"> | |||
| <el-input v-model="formData.actualWeight" placeholder="请输入实际重量"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="目标重量(g)"> | |||
| <el-input v-model="formData.targetWeight" placeholder="请输入目标重量"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="差值(g)"> | |||
| <el-input v-model="formData.difference" placeholder="自动计算"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="样品名称"> | |||
| <el-input v-model="formData.sampleName" placeholder="请输入样品名称"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input v-model="formData.notes" type="textarea" :rows="2"></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'ManualWeighStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| actualWeight: '', | |||
| targetWeight: '', | |||
| difference: '', | |||
| sampleName: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,59 +0,0 @@ | |||
| <template> | |||
| <div class="mix-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="混合方式"> | |||
| <el-select v-model="formData.method" placeholder="请选择混合方式"> | |||
| <el-option label="涡旋混匀" value="vortex"></el-option> | |||
| <el-option label="颠倒混匀" value="invert"></el-option> | |||
| <el-option label="移液器吹打" value="pipette"></el-option> | |||
| <el-option label="磁力搅拌" value="magnetic"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="混合时间(s)"> | |||
| <el-input v-model="formData.time" placeholder="请输入混合时间"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="混合速度"> | |||
| <el-select v-model="formData.speed" placeholder="请选择混合速度"> | |||
| <el-option label="低速" value="low"></el-option> | |||
| <el-option label="中速" value="medium"></el-option> | |||
| <el-option label="高速" value="high"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="温度(℃)"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input v-model="formData.notes" type="textarea" :rows="2"></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'MixStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| method: '', | |||
| time: '', | |||
| speed: '', | |||
| temperature: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,90 +0,0 @@ | |||
| <template> | |||
| <div class="package-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="分装容器"> | |||
| <el-select v-model="formData.containerType" placeholder="请选择分装容器"> | |||
| <el-option label="离心管" value="centrifugeTube"></el-option> | |||
| <el-option label="试管" value="testTube"></el-option> | |||
| <el-option label="样品瓶" value="vial"></el-option> | |||
| <el-option label="微孔板" value="microplate"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="分装数量"> | |||
| <el-input-number | |||
| v-model="formData.quantity" | |||
| :min="1" | |||
| :max="100" | |||
| :step="1" | |||
| ></el-input-number> | |||
| </el-form-item> | |||
| <el-form-item label="每份体积"> | |||
| <el-input v-model="formData.volume" placeholder="请输入体积"> | |||
| <el-select v-model="formData.unit" slot="append" style="width: 80px;"> | |||
| <el-option label="ml" value="ml"></el-option> | |||
| <el-option label="μl" value="μl"></el-option> | |||
| <el-option label="l" value="l"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="分装方式"> | |||
| <el-radio-group v-model="formData.method"> | |||
| <el-radio label="manual">手动分装</el-radio> | |||
| <el-radio label="auto">自动分装</el-radio> | |||
| </el-radio-group> | |||
| </el-form-item> | |||
| <el-form-item label="温度要求"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'PackageStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| containerType: '', | |||
| quantity: 1, | |||
| volume: '', | |||
| unit: 'ml', | |||
| method: 'manual', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,113 +0,0 @@ | |||
| <template> | |||
| <div class="seal2-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="封装方式"> | |||
| <el-select v-model="formData.method" placeholder="请选择封装方式"> | |||
| <el-option label="热封" value="heat"></el-option> | |||
| <el-option label="机械封" value="mechanical"></el-option> | |||
| <el-option label="封膜" value="membrane"></el-option> | |||
| <el-option label="盖子封" value="cap"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="密封材料"> | |||
| <el-select v-model="formData.material" placeholder="请选择密封材料"> | |||
| <el-option label="铝箔" value="aluminum"></el-option> | |||
| <el-option label="塑料膜" value="plastic"></el-option> | |||
| <el-option label="橡胶塞" value="rubber"></el-option> | |||
| <el-option label="螺旋盖" value="screwCap"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="压力参数"> | |||
| <el-input v-model="formData.pressure" placeholder="请输入压力值"> | |||
| <el-select v-model="formData.pressureUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="kPa" value="kPa"></el-option> | |||
| <el-option label="bar" value="bar"></el-option> | |||
| <el-option label="psi" value="psi"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度参数"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="时间参数"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"> | |||
| <el-select v-model="formData.timeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="s" value="s"></el-option> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="封管数量"> | |||
| <el-input-number | |||
| v-model="formData.tubeCount" | |||
| :min="2" | |||
| :max="2" | |||
| :step="1" | |||
| ></el-input-number> | |||
| </el-form-item> | |||
| <el-form-item label="质量检查"> | |||
| <el-checkbox-group v-model="formData.qualityChecks"> | |||
| <el-checkbox label="密封性检查">密封性检查</el-checkbox> | |||
| <el-checkbox label="外观检查">外观检查</el-checkbox> | |||
| <el-checkbox label="标识检查">标识检查</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'Seal2Step', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| method: '', | |||
| material: '', | |||
| pressure: '', | |||
| pressureUnit: 'kPa', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| time: '', | |||
| timeUnit: 's', | |||
| tubeCount: 2, | |||
| qualityChecks: [], | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,114 +0,0 @@ | |||
| <template> | |||
| <div class="seal3-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="封装方式"> | |||
| <el-select v-model="formData.method" placeholder="请选择封装方式"> | |||
| <el-option label="热封" value="heat"></el-option> | |||
| <el-option label="机械封" value="mechanical"></el-option> | |||
| <el-option label="封膜" value="membrane"></el-option> | |||
| <el-option label="盖子封" value="cap"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="密封材料"> | |||
| <el-select v-model="formData.material" placeholder="请选择密封材料"> | |||
| <el-option label="铝箔" value="aluminum"></el-option> | |||
| <el-option label="塑料膜" value="plastic"></el-option> | |||
| <el-option label="橡胶塞" value="rubber"></el-option> | |||
| <el-option label="螺旋盖" value="screwCap"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="压力参数"> | |||
| <el-input v-model="formData.pressure" placeholder="请输入压力值"> | |||
| <el-select v-model="formData.pressureUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="kPa" value="kPa"></el-option> | |||
| <el-option label="bar" value="bar"></el-option> | |||
| <el-option label="psi" value="psi"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度参数"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="时间参数"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"> | |||
| <el-select v-model="formData.timeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="s" value="s"></el-option> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="封管数量"> | |||
| <el-input-number | |||
| v-model="formData.tubeCount" | |||
| :min="3" | |||
| :max="3" | |||
| :step="1" | |||
| ></el-input-number> | |||
| </el-form-item> | |||
| <el-form-item label="质量检查"> | |||
| <el-checkbox-group v-model="formData.qualityChecks"> | |||
| <el-checkbox label="密封性检查">密封性检查</el-checkbox> | |||
| <el-checkbox label="外观检查">外观检查</el-checkbox> | |||
| <el-checkbox label="标识检查">标识检查</el-checkbox> | |||
| <el-checkbox label="批次检查">批次检查</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'Seal3Step', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| method: '', | |||
| material: '', | |||
| pressure: '', | |||
| pressureUnit: 'kPa', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| time: '', | |||
| timeUnit: 's', | |||
| tubeCount: 3, | |||
| qualityChecks: [], | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,144 +0,0 @@ | |||
| <template> | |||
| <div class="static-end-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="实际时间"> | |||
| <el-input v-model="formData.actualDuration" placeholder="请输入实际静置时间"> | |||
| <el-select v-model="formData.actualDurationUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| <el-option label="d" value="d"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="结束时间"> | |||
| <el-date-picker | |||
| v-model="formData.endTime" | |||
| type="datetime" | |||
| placeholder="请选择结束时间" | |||
| format="yyyy-MM-dd HH:mm" | |||
| value-format="yyyy-MM-dd HH:mm:ss" | |||
| ></el-date-picker> | |||
| </el-form-item> | |||
| <el-form-item label="实际温度"> | |||
| <el-input v-model="formData.actualTemperature" placeholder="请输入实际温度"> | |||
| <el-select v-model="formData.actualTemperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="样品状态"> | |||
| <el-select v-model="formData.sampleState" placeholder="请选择样品状态"> | |||
| <el-option label="正常" value="normal"></el-option> | |||
| <el-option label="异常" value="abnormal"></el-option> | |||
| <el-option label="有变化" value="changed"></el-option> | |||
| <el-option label="无变化" value="unchanged"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="观察结果"> | |||
| <el-checkbox-group v-model="formData.observationResults"> | |||
| <el-checkbox label="颜色变化">颜色变化</el-checkbox> | |||
| <el-checkbox label="沉淀形成">沉淀形成</el-checkbox> | |||
| <el-checkbox label="相分离">相分离</el-checkbox> | |||
| <el-checkbox label="结晶">结晶</el-checkbox> | |||
| <el-checkbox label="无异常">无异常</el-checkbox> | |||
| <el-checkbox label="其他">其他</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="容器状态"> | |||
| <el-select v-model="formData.finalContainerState" placeholder="请选择最终容器状态"> | |||
| <el-option label="密封" value="sealed"></el-option> | |||
| <el-option label="半密封" value="semiSealed"></el-option> | |||
| <el-option label="开放" value="open"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="后续处理"> | |||
| <el-checkbox-group v-model="formData.nextSteps"> | |||
| <el-checkbox label="直接进行下一步">直接进行下一步</el-checkbox> | |||
| <el-checkbox label="需要预处理">需要预处理</el-checkbox> | |||
| <el-checkbox label="需要检测">需要检测</el-checkbox> | |||
| <el-checkbox label="需要储存">需要储存</el-checkbox> | |||
| <el-checkbox label="需要转移">需要转移</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="处理结果"> | |||
| <el-radio-group v-model="formData.processResult"> | |||
| <el-radio label="success">静置成功</el-radio> | |||
| <el-radio label="partial">部分成功</el-radio> | |||
| <el-radio label="failed">静置失败</el-radio> | |||
| </el-radio-group> | |||
| </el-form-item> | |||
| <el-form-item v-if="formData.processResult !== 'success'" label="失败原因"> | |||
| <el-input v-model="formData.failureReason" placeholder="请输入失败原因"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="质量评估"> | |||
| <el-rate v-model="formData.qualityScore" show-text></el-rate> | |||
| </el-form-item> | |||
| <el-form-item label="最终观察"> | |||
| <el-input | |||
| v-model="formData.finalObservation" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入最终观察结果" | |||
| ></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'StaticEndStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| actualDuration: '', | |||
| actualDurationUnit: 'h', | |||
| endTime: '', | |||
| actualTemperature: '', | |||
| actualTemperatureUnit: '℃', | |||
| sampleState: '', | |||
| observationResults: [], | |||
| finalContainerState: '', | |||
| nextSteps: [], | |||
| processResult: 'success', | |||
| failureReason: '', | |||
| qualityScore: 5, | |||
| finalObservation: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,142 +0,0 @@ | |||
| <template> | |||
| <div class="static-start-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="静置目的"> | |||
| <el-input v-model="formData.purpose" placeholder="请输入静置目的"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="预计时间"> | |||
| <el-input v-model="formData.duration" placeholder="请输入预计时间"> | |||
| <el-select v-model="formData.durationUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| <el-option label="d" value="d"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度要求"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="容器状态"> | |||
| <el-select v-model="formData.containerState" placeholder="请选择容器状态"> | |||
| <el-option label="密封" value="sealed"></el-option> | |||
| <el-option label="半密封" value="semiSealed"></el-option> | |||
| <el-option label="开放" value="open"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="环境条件"> | |||
| <el-checkbox-group v-model="formData.environmentConditions"> | |||
| <el-checkbox label="避光">避光</el-checkbox> | |||
| <el-checkbox label="恒温">恒温</el-checkbox> | |||
| <el-checkbox label="静置">静置</el-checkbox> | |||
| <el-checkbox label="无震动">无震动</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="静置位置"> | |||
| <el-select v-model="formData.position" placeholder="请选择静置位置"> | |||
| <el-option label="室温" value="roomTemp"></el-option> | |||
| <el-option label="冷藏" value="refrigerated"></el-option> | |||
| <el-option label="冷冻" value="frozen"></el-option> | |||
| <el-option label="恒温箱" value="incubator"></el-option> | |||
| <el-option label="水浴" value="waterBath"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="容器类型"> | |||
| <el-select v-model="formData.containerType" placeholder="请选择容器类型"> | |||
| <el-option label="离心管" value="centrifugeTube"></el-option> | |||
| <el-option label="试管" value="testTube"></el-option> | |||
| <el-option label="烧杯" value="beaker"></el-option> | |||
| <el-option label="培养皿" value="petriDish"></el-option> | |||
| <el-option label="容量瓶" value="volumetricFlask"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="体积范围"> | |||
| <el-input v-model="formData.volume" placeholder="请输入体积"> | |||
| <el-select v-model="formData.volumeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="ml" value="ml"></el-option> | |||
| <el-option label="μl" value="μl"></el-option> | |||
| <el-option label="l" value="l"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="开始时间"> | |||
| <el-date-picker | |||
| v-model="formData.startTime" | |||
| type="datetime" | |||
| placeholder="请选择开始时间" | |||
| format="yyyy-MM-dd HH:mm" | |||
| value-format="yyyy-MM-dd HH:mm:ss" | |||
| ></el-date-picker> | |||
| </el-form-item> | |||
| <el-form-item label="观察记录"> | |||
| <el-checkbox-group v-model="formData.observationRecords"> | |||
| <el-checkbox label="颜色变化">颜色变化</el-checkbox> | |||
| <el-checkbox label="沉淀形成">沉淀形成</el-checkbox> | |||
| <el-checkbox label="相分离">相分离</el-checkbox> | |||
| <el-checkbox label="结晶">结晶</el-checkbox> | |||
| <el-checkbox label="其他">其他</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'StaticStartStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| purpose: '', | |||
| duration: '', | |||
| durationUnit: 'h', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| containerState: '', | |||
| environmentConditions: [], | |||
| position: '', | |||
| containerType: '', | |||
| volume: '', | |||
| volumeUnit: 'ml', | |||
| startTime: '', | |||
| observationRecords: [], | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,147 +0,0 @@ | |||
| <template> | |||
| <div class="take-plate-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="取板目的"> | |||
| <el-input v-model="formData.purpose" placeholder="请输入取板目的"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="微孔板类型"> | |||
| <el-select v-model="formData.plateType" placeholder="请选择微孔板类型"> | |||
| <el-option label="96孔板" value="96well"></el-option> | |||
| <el-option label="48孔板" value="48well"></el-option> | |||
| <el-option label="24孔板" value="24well"></el-option> | |||
| <el-option label="12孔板" value="12well"></el-option> | |||
| <el-option label="6孔板" value="6well"></el-option> | |||
| <el-option label="384孔板" value="384well"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="取板位置"> | |||
| <el-select v-model="formData.location" placeholder="请选择取板位置"> | |||
| <el-option label="培养箱" value="incubator"></el-option> | |||
| <el-option label="冷藏" value="refrigerator"></el-option> | |||
| <el-option label="室温" value="roomTemp"></el-option> | |||
| <el-option label="水浴" value="waterBath"></el-option> | |||
| <el-option label="摇床" value="shaker"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="取板时间"> | |||
| <el-date-picker | |||
| v-model="formData.takeTime" | |||
| type="datetime" | |||
| placeholder="请选择取板时间" | |||
| format="yyyy-MM-dd HH:mm" | |||
| value-format="yyyy-MM-dd HH:mm:ss" | |||
| ></el-date-picker> | |||
| </el-form-item> | |||
| <el-form-item label="板子状态"> | |||
| <el-select v-model="formData.plateState" placeholder="请选择板子状态"> | |||
| <el-option label="正常" value="normal"></el-option> | |||
| <el-option label="有污染" value="contaminated"></el-option> | |||
| <el-option label="干燥" value="dry"></el-option> | |||
| <el-option label="湿润" value="wet"></el-option> | |||
| <el-option label="有沉淀" value="precipitate"></el-option> | |||
| <el-option label="有结晶" value="crystal"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="处理要求"> | |||
| <el-checkbox-group v-model="formData.processRequirements"> | |||
| <el-checkbox label="立即处理">立即处理</el-checkbox> | |||
| <el-checkbox label="室温放置">室温放置</el-checkbox> | |||
| <el-checkbox label="冷藏保存">冷藏保存</el-checkbox> | |||
| <el-checkbox label="冷冻保存">冷冻保存</el-checkbox> | |||
| <el-checkbox label="避光保存">避光保存</el-checkbox> | |||
| <el-checkbox label="需要检测">需要检测</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="取板数量"> | |||
| <el-input-number | |||
| v-model="formData.quantity" | |||
| :min="1" | |||
| :max="10" | |||
| :step="1" | |||
| ></el-input-number> | |||
| </el-form-item> | |||
| <el-form-item label="操作者"> | |||
| <el-input v-model="formData.operator" placeholder="请输入操作者姓名"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="后续处理"> | |||
| <el-radio-group v-model="formData.nextAction"> | |||
| <el-radio label="immediate">立即处理</el-radio> | |||
| <el-radio label="delayed">延迟处理</el-radio> | |||
| <el-radio label="storage">储存待处理</el-radio> | |||
| <el-radio label="discard">丢弃</el-radio> | |||
| </el-radio-group> | |||
| </el-form-item> | |||
| <el-form-item label="质量检查"> | |||
| <el-checkbox-group v-model="formData.qualityChecks"> | |||
| <el-checkbox label="外观检查">外观检查</el-checkbox> | |||
| <el-checkbox label="标识检查">标识检查</el-checkbox> | |||
| <el-checkbox label="完整性检查">完整性检查</el-checkbox> | |||
| <el-checkbox label="污染检查">污染检查</el-checkbox> | |||
| </el-checkbox-group> | |||
| </el-form-item> | |||
| <el-form-item label="特殊要求"> | |||
| <el-input | |||
| v-model="formData.specialRequirements" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入特殊要求或注意事项" | |||
| ></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'TakePlateStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| purpose: '', | |||
| plateType: '', | |||
| location: '', | |||
| takeTime: '', | |||
| plateState: '', | |||
| processRequirements: [], | |||
| quantity: 1, | |||
| operator: '', | |||
| nextAction: 'immediate', | |||
| qualityChecks: [], | |||
| specialRequirements: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,50 +0,0 @@ | |||
| <template> | |||
| <div class="ultrasound-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="功率(%)"> | |||
| <el-input v-model="formData.power" placeholder="请输入功率百分比"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="时间(min)"> | |||
| <el-input v-model="formData.time" placeholder="请输入超声时间"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度(℃)"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="频率(kHz)"> | |||
| <el-input v-model="formData.frequency" placeholder="请输入频率"></el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input v-model="formData.notes" type="textarea" :rows="2"></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'UltrasoundStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| power: '', | |||
| time: '', | |||
| temperature: '', | |||
| frequency: '', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -1,124 +0,0 @@ | |||
| <template> | |||
| <div class="vortex-step"> | |||
| <el-form label-width="120px"> | |||
| <el-form-item label="混匀方式"> | |||
| <el-select v-model="formData.method" placeholder="请选择混匀方式"> | |||
| <el-option label="漩涡混匀" value="vortex"></el-option> | |||
| <el-option label="摇床混匀" value="shaker"></el-option> | |||
| <el-option label="磁力搅拌" value="magnetic"></el-option> | |||
| <el-option label="机械搅拌" value="mechanical"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="混匀时间"> | |||
| <el-input v-model="formData.time" placeholder="请输入时间"> | |||
| <el-select v-model="formData.timeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="s" value="s"></el-option> | |||
| <el-option label="min" value="min"></el-option> | |||
| <el-option label="h" value="h"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="转速设置"> | |||
| <el-input v-model="formData.speed" placeholder="请输入转速"> | |||
| <el-select v-model="formData.speedUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="rpm" value="rpm"></el-option> | |||
| <el-option label="Hz" value="Hz"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="体积范围"> | |||
| <el-input v-model="formData.volume" placeholder="请输入体积"> | |||
| <el-select v-model="formData.unit" slot="append" style="width: 80px;"> | |||
| <el-option label="ml" value="ml"></el-option> | |||
| <el-option label="μl" value="μl"></el-option> | |||
| <el-option label="l" value="l"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="温度控制"> | |||
| <el-input v-model="formData.temperature" placeholder="请输入温度"> | |||
| <el-select v-model="formData.temperatureUnit" slot="append" style="width: 60px;"> | |||
| <el-option label="℃" value="℃"></el-option> | |||
| <el-option label="℉" value="℉"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="容器类型"> | |||
| <el-select v-model="formData.containerType" placeholder="请选择容器类型"> | |||
| <el-option label="离心管" value="centrifugeTube"></el-option> | |||
| <el-option label="试管" value="testTube"></el-option> | |||
| <el-option label="烧杯" value="beaker"></el-option> | |||
| <el-option label="培养皿" value="petriDish"></el-option> | |||
| </el-select> | |||
| </el-form-item> | |||
| <el-form-item label="混匀模式"> | |||
| <el-radio-group v-model="formData.mode"> | |||
| <el-radio label="continuous">连续混匀</el-radio> | |||
| <el-radio label="interval">间歇混匀</el-radio> | |||
| </el-radio-group> | |||
| </el-form-item> | |||
| <el-form-item v-if="formData.mode === 'interval'" label="间歇时间"> | |||
| <el-input v-model="formData.intervalTime" placeholder="请输入间歇时间"> | |||
| <el-select v-model="formData.intervalTimeUnit" slot="append" style="width: 80px;"> | |||
| <el-option label="s" value="s"></el-option> | |||
| <el-option label="min" value="min"></el-option> | |||
| </el-select> | |||
| </el-input> | |||
| </el-form-item> | |||
| <el-form-item label="备注"> | |||
| <el-input | |||
| v-model="formData.notes" | |||
| type="textarea" | |||
| :rows="3" | |||
| placeholder="请输入备注信息" | |||
| ></el-input> | |||
| </el-form-item> | |||
| </el-form> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| name: 'VortexStep', | |||
| props: ['stepData'], | |||
| data() { | |||
| return { | |||
| formData: { | |||
| method: '', | |||
| time: '', | |||
| timeUnit: 's', | |||
| speed: '', | |||
| speedUnit: 'rpm', | |||
| volume: '', | |||
| unit: 'ml', | |||
| temperature: '', | |||
| temperatureUnit: '℃', | |||
| containerType: '', | |||
| mode: 'continuous', | |||
| intervalTime: '', | |||
| intervalTimeUnit: 's', | |||
| notes: '' | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| this.formData = { ...this.formData, ...this.stepData } | |||
| }, | |||
| watch: { | |||
| formData: { | |||
| handler(newVal) { | |||
| this.$emit('update', newVal) | |||
| }, | |||
| deep: true | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| @ -0,0 +1,49 @@ | |||
| <template> | |||
| <StepFormPackage :form-config="formConfig" :form-data = "formData" /> | |||
| </template> | |||
| <script> | |||
| import StepFormPackage from '@/components/Template/StepFormPackage.vue' | |||
| export default { | |||
| components: { | |||
| StepFormPackage | |||
| }, | |||
| computed: { | |||
| formConfig() { | |||
| return [{ | |||
| config:{ | |||
| text1:{ | |||
| label:"选择在", | |||
| type:"text", | |||
| }, | |||
| ddsys:{ | |||
| type:"input", | |||
| fillType:"preFill", | |||
| }, | |||
| yq:{ | |||
| type:"instrument", | |||
| fillType:"actFill", | |||
| }, | |||
| text2:{ | |||
| label:"环境下,操作下述步骤", | |||
| type:"text", | |||
| } | |||
| } | |||
| }] | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| formData: { | |||
| ddsys: "xxx", | |||
| yq: "", | |||
| } | |||
| } | |||
| }, | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| </style> | |||
| @ -0,0 +1,104 @@ | |||
| <template> | |||
| <div> | |||
| <div v-for="(item, index) in formConfig" :key="index" class="step-form-package"> | |||
| <div v-for="(sItem, key) in item.config" class="step-item" :key="key"> | |||
| <template v-if="sItem.type === 'input'"> | |||
| <HandleFormItem class="step-row" :field-item-label="fieldItemLabel" @blur="onBlur(key, $event)" | |||
| :item="sItem" v-model="formFields[key]" :field-key="prefixKey + '_' + key" | |||
| @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false" | |||
| :orange-bg="orangeBgFields[key]" /> | |||
| </template> | |||
| <template v-else-if="sItem.type === 'inputNumber'"> | |||
| <HandleFormItem class="step-row" :field-item-label="fieldItemLabel" :field-key="prefixKey + '_' + key" | |||
| type="inputNumber" @blur="onBlur(key, $event)" :item="sItem" | |||
| @input="onInputNumberChange(key, $event)" v-model="formFields[key]" @copy="onCopy(sItem, key)" | |||
| :error="errors[key]" @update:error="errors[key] = false" :orange-bg="orangeBgFields[key]" /> | |||
| </template> | |||
| <template v-else-if="sItem.type === 'select'"> | |||
| <HandleFormItem class="step-row" :field-item-label="fieldItemLabel" :field-key="prefixKey + '_' + key" | |||
| type="select" @blur="onBlur(key, $event)" :item="sItem" v-model="formFields[key]" | |||
| @copy="onCopy(sItem, key)" :error="errors[key]" @update:error="errors[key] = false" | |||
| :orange-bg="orangeBgFields[key]" /> | |||
| </template> | |||
| <template v-else-if="sItem.type === 'instrument'"> | |||
| <HandleFormItem class="step-row" :field-item-label="fieldItemLabel" :field-key="prefixKey + '_' + key" | |||
| type="clickable" @clickable="handleClickable(sItem, $event)" :error="errors[key]" | |||
| @update:error="errors[key] = false" @resetRecord="resetRecord(key)" :item="getClickableItem(sItem)" | |||
| :value="formFields[key]" /> | |||
| </template> | |||
| <template v-else-if="sItem.type === 'text'"> | |||
| <span>{{ sItem.label }}</span> | |||
| </template> | |||
| <template v-else-if="sItem.type === 'span'"> | |||
| <span>{{ formFields[key] }}</span> | |||
| </template> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </template> | |||
| <script> | |||
| import HandleFormItem from '@/components/Template/HandleFormItem.vue' | |||
| import formPackageMixins from '@/components/Template/mixins/formPackageMixins.js' | |||
| import { isShowOther } from "@/utils/formPackageCommon.js"; | |||
| export default { | |||
| components: { | |||
| HandleFormItem, | |||
| }, | |||
| mixins: [formPackageMixins], | |||
| props: { | |||
| formConfig: { | |||
| type: Array, | |||
| default: [] | |||
| }, | |||
| formData: { | |||
| type: Object, | |||
| value: () => ({}) | |||
| }, | |||
| //主要标识当前表单属于哪个模块,用于传给后端 | |||
| fieldItemLabel: { | |||
| type: String, | |||
| default: "", | |||
| }, | |||
| prefixKey: { | |||
| type: String, | |||
| default: "" | |||
| } | |||
| }, | |||
| data() { | |||
| return { | |||
| formFields: {},//表单绑定字段 | |||
| allFieldsConfig: {},//包含config的所有字段,主要用于校验表单是否填写 | |||
| errors: {},//存储表单错误信息,用于标红提示 | |||
| orangeBgFields: {},// 存储需要橙色背景的字段 | |||
| isShowOther, | |||
| } | |||
| }, | |||
| methods: { | |||
| getClickableItem(sItem) { | |||
| return { | |||
| ...sItem, | |||
| type:"clickable" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .step-form-package { | |||
| display: flex; | |||
| align-items: center; | |||
| font-size: 14px; | |||
| } | |||
| .step-row { | |||
| width: 180px; | |||
| } | |||
| .step-item { | |||
| display: flex; | |||
| align-items: center; | |||
| margin-left: 5px; | |||
| } | |||
| </style> | |||
| @ -0,0 +1,349 @@ | |||
| import { isEqual } from "@/utils/index.js"; | |||
| export default { | |||
| watch: { | |||
| formData: { | |||
| immediate: true, | |||
| deep: true, // 深度监听,以便检测嵌套对象变化 | |||
| handler(v) { | |||
| if (v) { | |||
| this.handleFormField(true); | |||
| } | |||
| } | |||
| }, | |||
| fieldItemLabel: { | |||
| immediate: true, | |||
| deep: true, // 深度监听,以便检测嵌套对象变化 | |||
| handler(v) { | |||
| if (v) { | |||
| console.log(v,"fieldItemLabel") | |||
| } | |||
| } | |||
| }, | |||
| formConfig: { | |||
| immediate: true, | |||
| deep: true, // 深度监听,以便检测嵌套对象变化 | |||
| handler(v) { | |||
| this.handleFormField(); | |||
| } | |||
| } | |||
| }, | |||
| mounted() { | |||
| this.handleFormField(); | |||
| }, | |||
| unmounted() { | |||
| console.log("unmounted") | |||
| this.formFields = {};//清空当前填写的数据 | |||
| }, | |||
| methods: { | |||
| getFillType(type) { | |||
| const typeObj = { | |||
| actFill: "orange-border",//实际填写的边框颜色 | |||
| green: "green-border", | |||
| preFill: "blue-border",//预填写的边框颜色 | |||
| } | |||
| return typeObj[type] || "" | |||
| }, | |||
| onInputNumberChange(key, val) { | |||
| this.formFields[key] = val; | |||
| // 清除该表单项的错误状态 | |||
| if (this.errors[key]) { | |||
| this.$set(this.errors, key, false); | |||
| } | |||
| }, | |||
| //更新表单数据 | |||
| updateFormData(key, value,oldKeys = []) { | |||
| if(oldKeys.length){ | |||
| // 深拷贝当前表单数据,避免直接修改原数据 | |||
| const cloneFormFields = JSON.parse(JSON.stringify(this.formFields)); | |||
| oldKeys.forEach(oldKey => { | |||
| //需要把记录一下被更新的旧值,用于取消的时候回填,主要用于clickable类型 | |||
| this.oldFormFields[oldKey] = cloneFormFields[oldKey]; | |||
| }) | |||
| } | |||
| this.formFields[key] = value; | |||
| // 清除该表单项的错误状态 | |||
| if (this.errors[key]) { | |||
| this.$set(this.errors, key, false); | |||
| } | |||
| }, | |||
| //批量更新表单数据 | |||
| batchUpdateFormData(data) { | |||
| Object.keys(data).forEach(key => { | |||
| this.formFields[key] = data[key]; | |||
| // 清除该表单项的错误状态 | |||
| if (this.errors[key]) { | |||
| this.$set(this.errors, key, false); | |||
| } | |||
| }) | |||
| }, | |||
| handleClickable(sItem, event) { | |||
| console.log("clickable", sItem) | |||
| if (this.templateFillType !== 'actFill') { | |||
| return | |||
| } | |||
| this.$emit("clickable", sItem) | |||
| }, | |||
| //根据span判断一行显示几列 | |||
| getSpanClass(sItem) { | |||
| const spanArr = ["full-row", "", "three-row"] | |||
| if (sItem.span) { | |||
| return spanArr[sItem.span - 1] | |||
| } | |||
| return "" | |||
| }, | |||
| //获取其他下拉框的配置 | |||
| getOtherItem(sItem) { | |||
| return { | |||
| label: sItem.otherLabel ? this.$t(sItem.otherLabel) : this.$t("template.common.other"), | |||
| fillType: sItem.fillType, | |||
| maxlength: sItem.otherMaxlength || 50, | |||
| parentLabel: sItem.label, | |||
| } | |||
| }, | |||
| getClickableItem(sItem) { | |||
| return { | |||
| label: "", | |||
| type: "clickable", | |||
| fillType: sItem.subFillType || sItem.fillType, | |||
| parentLabel: sItem.label, | |||
| } | |||
| }, | |||
| getSubItem(sItem) { | |||
| return { | |||
| label: "", | |||
| options: sItem.subOptions || [], | |||
| fillType: sItem.subFillType || sItem.fillType, | |||
| parentLabel: sItem.label, | |||
| } | |||
| }, | |||
| // 根据formConfig回填form表单数据 | |||
| handleFormField(update = false) { | |||
| const result = {}; | |||
| let config = {}; | |||
| const { formConfig, formData, formFields } = this; | |||
| // 遍历配置 | |||
| formConfig.forEach((item) => { | |||
| if (item.config) { | |||
| // 合并配置项 | |||
| config = { ...config, ...item.config } | |||
| // 处理每个配置项 | |||
| Object.keys(item.config).forEach(key => { | |||
| const currentConfig = item.config[key]; | |||
| let value = formData[key]; | |||
| // 如果formFields中已经有值,保持原值(用户输入或之前设置的值) | |||
| if (formFields[key] !== null && | |||
| formFields[key] !== undefined && | |||
| formFields[key] !== '' | |||
| // typeof formFields[key] !== 'object' | |||
| ) { | |||
| // 保留原值,不使用formData中的值 | |||
| result[key] = formFields[key]; | |||
| } else { | |||
| // 使用formData中的值 | |||
| result[key] = value; | |||
| } | |||
| // 处理特殊字段 - "其他"字段 | |||
| if (currentConfig.otherCode) { | |||
| const { otherCode } = currentConfig; | |||
| //如果是更新的话,优先使用formFields中的值 | |||
| if (update) { | |||
| result[otherCode] = formFields[otherCode] || formData[otherCode] || ''; | |||
| } else { | |||
| result[otherCode] = formData[otherCode] || formFields[otherCode] || ''; | |||
| } | |||
| config[otherCode] = { label: "template.common.other", parentKey: key, type: "input", fillType: currentConfig.fillType } | |||
| } | |||
| if (currentConfig.subKey) { | |||
| const { subKey } = currentConfig; | |||
| if (update) { | |||
| result[subKey] = formFields[subKey] || formData[subKey] || ''; | |||
| } else { | |||
| result[subKey] = formData[subKey] || formFields[subKey] || ''; | |||
| } | |||
| config[subKey] = { label: currentConfig.label, subKey, type: currentConfig.subType, fillType: currentConfig.subFillType || currentConfig.fillType, selectTo: currentConfig.selectTo } | |||
| } | |||
| // 检查compareTo字段 | |||
| if (currentConfig.compareTo && formData[currentConfig.compareTo] && result[key]) { | |||
| const compareToValue = formData[currentConfig.compareTo]; | |||
| const currentValue = result[key]; | |||
| this.compareFieldsIsEqual(currentValue,compareToValue,key) | |||
| } | |||
| }); | |||
| // 处理可能存在的直接otherCode字段 | |||
| if (item.config?.otherCode) { | |||
| config[item.config?.otherCode] = item.config?.otherCode; | |||
| } | |||
| } | |||
| }); | |||
| // 更新表单字段 | |||
| this.formFields = result; | |||
| this.allFieldsConfig = config; | |||
| }, | |||
| //比较值是否相等 | |||
| compareFieldsIsEqual(currentValue,compareToValue,key) { | |||
| if(!currentValue || !compareToValue) return; | |||
| // 如果当前值与compareTo字段的值不相等,则设置橙色背景 | |||
| if (isEqual(currentValue,compareToValue)) { | |||
| // 如果相等,移除橙色背景(如果之前设置了的话) | |||
| this.$set(this.orangeBgFields, key, false); | |||
| } else { | |||
| this.$set(this.orangeBgFields, key, true); | |||
| } | |||
| }, | |||
| //判断是否禁用 | |||
| getDisabled() { | |||
| const { item } = this; | |||
| const { fillType } = item; | |||
| if (item.hasOwnProperty("disabled")) { | |||
| return item.disabled | |||
| } else { | |||
| if (fillType === "actFill") {//当模板状态是实际填写时,只有当fillType是actFill时才能填写 | |||
| return this.templateFillType !== "actFill" | |||
| } else if (fillType === "preFill") {//当模板状态是预填写时,只有当fillType是preFill才能填写 | |||
| return this.templateFillType !== "preFill" | |||
| } else { | |||
| return true | |||
| } | |||
| } | |||
| }, | |||
| // 表单数据校验 | |||
| validateFormData() { | |||
| const { formFields, allFieldsConfig } = this; | |||
| const errors = []; | |||
| // 清空之前的错误状态 | |||
| this.errors = {}; | |||
| for (const key in allFieldsConfig) { | |||
| const o = allFieldsConfig[key]; | |||
| if (o.otherCode) {// | |||
| if (o.type === "select") { | |||
| const isSelectedOther = this.isShowOther(formFields[key]); | |||
| if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 | |||
| formFields[o.otherCode] = ""; | |||
| } | |||
| } else if (o.subType === "select") { | |||
| const isSelectedOther = this.isShowOther(formFields[o.subKey]); | |||
| if (!isSelectedOther) {//如果其他选项没有被选择,清空其他字段 | |||
| formFields[o.otherCode] = ""; | |||
| } | |||
| } | |||
| } | |||
| if (this.isValueEmpty(formFields[key])) { | |||
| // 其他字段需要判断是否显示再校验 | |||
| if (o.label === "template.common.other" && !this.isShowOther(formFields[o.parentKey])) { | |||
| continue | |||
| } | |||
| //span的字段不校验 | |||
| if (o.type === "span") { | |||
| continue | |||
| } | |||
| if (o.fillType === this.templateFillType && !o.disabled) { | |||
| let prefix = ""; | |||
| if (o.type === "input" || o.type === "inputNumber" || o.type === "textarea") { | |||
| prefix = "填写"; | |||
| } else { | |||
| prefix = "选择"; | |||
| } | |||
| const errorItem = { | |||
| field: key, | |||
| label: o.label, | |||
| error: `请${prefix}${o.label}` | |||
| }; | |||
| errors.push(errorItem); | |||
| this.$set(this.errors, key, true); | |||
| } | |||
| } | |||
| } | |||
| return { | |||
| valid: errors.length === 0, | |||
| errors: errors | |||
| }; | |||
| }, | |||
| // 判断值是否为空 | |||
| isValueEmpty(value) { | |||
| if (value === null || value === undefined || value === '') { | |||
| return true; | |||
| } | |||
| if (typeof value === 'string' && value.trim() === '') { | |||
| return true; | |||
| } | |||
| if (Array.isArray(value) && value.length === 0) { | |||
| return true; | |||
| } | |||
| return false; | |||
| }, | |||
| getFormData() { | |||
| // 数据校验 | |||
| const validateResult = this.validateFormData(); | |||
| return new Promise((resolve, reject) => { | |||
| if (validateResult.valid) { | |||
| resolve(this.formFields); | |||
| } else { | |||
| // this.$message.error("表单内容未填完,请填写后再提交"); | |||
| reject(validateResult.errors[0].error); | |||
| } | |||
| }); | |||
| }, | |||
| //直接获取表单数据,不做校验 | |||
| getFilledFormData() { | |||
| return this.formFields; | |||
| }, | |||
| getFormDataByKey(key) { | |||
| return this.formFields[key]; | |||
| }, | |||
| onBlur(key, val) { | |||
| // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色 | |||
| this.onValueChangeCompareTo(key, val); | |||
| this.$emit("blur", { key, value: val, ...this.formFields }); | |||
| }, | |||
| onValueChangeCompareTo(key, val, compKey) { | |||
| // compareTo 功能:当fillType==="actFill"时,判断当前值是否与compareTo字段的值一样,如果不一样则将当前input框的背景色标记成橙色 | |||
| const currentFieldConfig = this.allFieldsConfig[key]; | |||
| if (currentFieldConfig && currentFieldConfig.fillType === "actFill" && (currentFieldConfig.compareTo || compKey)) { | |||
| const compareToKey = compKey || currentFieldConfig.compareTo; | |||
| const compareToValue = this.formFields[compareToKey]; | |||
| this.compareFieldsIsEqual(val,compareToValue,key); | |||
| } | |||
| }, | |||
| onSelectChange(key, val, type) { | |||
| // 获取对应的配置 | |||
| const currentConfig = this.allFieldsConfig[key]; | |||
| if(currentConfig.selectTo){ | |||
| this.formFields[currentConfig.selectTo] = val; | |||
| } | |||
| this.onValueChangeCompareTo(key, val); | |||
| this.formFields[key] = val; | |||
| this.$emit("select", { key, value: val, type }); | |||
| // 清除该表单项的错误状态 | |||
| if (this.errors[key]) { | |||
| this.$set(this.errors, key, false); | |||
| } | |||
| }, | |||
| //复制 | |||
| onCopy(config, key) { | |||
| const { formFields } = this; | |||
| if (config.copyFrom) { | |||
| formFields[key] = formFields[config.copyFrom]; | |||
| this.onBlur(key, formFields[key]); | |||
| } | |||
| }, | |||
| resetRecord(key){ | |||
| this.formFields = {...this.formFields, ...this.oldFormFields} | |||
| }, | |||
| } | |||
| } | |||