| | |
| | | <!-- 顶部信息卡片 - 优化排版 --> |
| | | <el-card class="top-card" shadow="never"> |
| | | <el-row :gutter="24" class="top-info-row"> |
| | | <!-- 左列:菌种来源 + 编号 + 名称 --> |
| | | <el-col :span="9" class="info-col"> |
| | | <el-col :span="24" class="info-col source-col"> |
| | | <div class="info-item source-item"> |
| | | <span class="label">菌种来源:</span> |
| | | <el-tooltip |
| | |
| | | <span class="source-text">{{ detail.strainSource || '暂无数据' }}</span> |
| | | </el-tooltip> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="8" class="info-col"> |
| | | <div class="info-item"> |
| | | <span class="label">鉴别菌株编号:</span> |
| | | <span class="value">{{ detail.identifyingStrainCode || '-' }}</span> |
| | |
| | | </div> |
| | | </el-col> |
| | | |
| | | <!-- 中列:验证信息 --> |
| | | <el-col :span="7" class="info-col"> |
| | | <el-col :span="8" class="info-col"> |
| | | <div class="info-item"> |
| | | <span class="label">验证实验编号:</span> |
| | | <span class="value">{{ detail.validationExperimentCode || '-' }}</span> |
| | |
| | | </div> |
| | | </el-col> |
| | | |
| | | <!-- 右列:签名 --> |
| | | <el-col :span="8" class="info-col sign-col"> |
| | | <div class="sign-wrapper"> |
| | | <div class="sign-label-text">菌种实验员签字</div> |
| | |
| | | result: '', |
| | | purpose: [] |
| | | }, |
| | | activeTab: 'conditions', |
| | | rules: { |
| | | result: [ |
| | | { required: true, message: '请输入实验结论', trigger: 'blur' } |
| | |
| | | { conditions: '发酵时间', record: '', workmanship: '' }, |
| | | { conditions: '检测数据及结果', record: '', workmanship: '' } |
| | | ], |
| | | tableData: [ |
| | | { conditions: '平板培养基', record: '', workmanship: '' }, |
| | | { conditions: '培养温度', record: '', workmanship: '' }, |
| | | { conditions: '培养时间', record: '', workmanship: '' }, |
| | | { conditions: '摇瓶培养基', record: '', workmanship: '' }, |
| | | { conditions: '接种量', record: '', workmanship: '' }, |
| | | { conditions: '培养时间', record: '', workmanship: '' }, |
| | | { conditions: '发酵时间', record: '', workmanship: '' }, |
| | | { conditions: '检测数据及结果', record: '', workmanship: '' } |
| | | ], |
| | | tableData: [], |
| | | dialogVisible: false, |
| | | dialogIsEdit: false, |
| | | dialogIsFixed: false, |
| | | dialogValue: {}, |
| | | dialogIndex: null, |
| | | detailDialogVisible: false, |
| | | detailDialogValue: {} |
| | | detailDialogValue: {}, |
| | | |
| | | cacheForm: null, |
| | | cacheFormtableData: null, |
| | | isFirstLoad: true, |
| | | isLoading: false, |
| | | } |
| | | }, |
| | | filters: { |
| | |
| | | return '' |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getDetail() |
| | | // ========== 只使用 activated ========== |
| | | activated() { |
| | | console.log('activated, isFirstLoad:', this.isFirstLoad) |
| | | |
| | | // 1. 首次加载 - 初始化数据并请求 |
| | | if (this.isFirstLoad) { |
| | | this.isFirstLoad = false |
| | | // 初始化表格数据(显示默认行) |
| | | this.tableData = this.initialTableData.map(item => ({ ...item })) |
| | | |
| | | if (this.$route.query.id) { |
| | | this.getDetail() |
| | | } |
| | | return |
| | | } |
| | | |
| | | // 2. 从缓存恢复数据(非首次加载) |
| | | if (this.cacheForm) { |
| | | this.detail = JSON.parse(JSON.stringify(this.cacheForm)) |
| | | this.tableData = JSON.parse(JSON.stringify(this.cacheFormtableData)) |
| | | this.restorePurpose() |
| | | } |
| | | |
| | | // 3. 如果路由参数变化,重新加载数据 |
| | | if (this.$route.query.id && this.detail.id && this.$route.query.id !== String(this.detail.id)) { |
| | | this.getDetail() |
| | | } |
| | | }, |
| | | deactivated() { |
| | | // 缓存当前数据 |
| | | this.cacheForm = JSON.parse(JSON.stringify(this.detail)) |
| | | this.cacheFormtableData = JSON.parse(JSON.stringify(this.tableData)) |
| | | console.log('deactivated - 数据已缓存') |
| | | }, |
| | | // ========== 移除 mounted,或保留仅用于调试 ========== |
| | | mounted() { |
| | | // 不做任何初始化,所有逻辑都在 activated 中 |
| | | console.log('mounted - 仅用于调试,无初始化逻辑') |
| | | }, |
| | | // ========== 方法 ========== |
| | | methods: { |
| | | getFullUrl(url) { |
| | | if (url) { |
| | |
| | | } |
| | | return '' |
| | | }, |
| | | getDetail() { |
| | | detail({ id: this.$route.query.id }).then(res => { |
| | | this.detail = { |
| | | ...res, |
| | | handleSignature: res.handleSignature || '', |
| | | purpose: res.purpose || [] |
| | | } |
| | | }) |
| | | |
| | | restorePurpose() { |
| | | if (!this.detail.purpose) { |
| | | this.detail.purpose = [] |
| | | return |
| | | } |
| | | |
| | | let purposeArray = [] |
| | | if (typeof this.detail.purpose === 'string') { |
| | | purposeArray = this.detail.purpose.split(',').map(item => Number(item.trim())).filter(num => !isNaN(num)) |
| | | } else if (Array.isArray(this.detail.purpose)) { |
| | | purposeArray = this.detail.purpose |
| | | } |
| | | this.detail.purpose = purposeArray |
| | | }, |
| | | |
| | | getDetail() { |
| | | if (this.isLoading) { |
| | | console.log('正在加载中,跳过重复请求') |
| | | return |
| | | } |
| | | |
| | | const id = this.$route.query.id |
| | | if (!id) { |
| | | console.warn('缺少 id 参数') |
| | | return |
| | | } |
| | | |
| | | this.isLoading = true |
| | | console.log('开始请求详情数据, id:', id) |
| | | |
| | | detail({ id }) |
| | | .then(res => { |
| | | console.log('详情数据返回:', res) |
| | | |
| | | const data = res.data || res |
| | | |
| | | // 处理 purpose |
| | | let purposeArray = [] |
| | | if (data.purpose) { |
| | | if (typeof data.purpose === 'string') { |
| | | purposeArray = data.purpose.split(',').map(item => Number(item.trim())).filter(num => !isNaN(num)) |
| | | } else if (Array.isArray(data.purpose)) { |
| | | purposeArray = data.purpose |
| | | } |
| | | } |
| | | |
| | | // 处理 tableData |
| | | const tableList = data.list && data.list.length > 0 ? data.list : this.initialTableData.map(item => ({ ...item })) |
| | | |
| | | // 更新数据 |
| | | this.detail = { |
| | | ...data, |
| | | handleSignature: data.handleSignature || '', |
| | | purpose: purposeArray |
| | | } |
| | | this.tableData = tableList |
| | | |
| | | // 更新缓存 |
| | | this.cacheForm = JSON.parse(JSON.stringify(this.detail)) |
| | | this.cacheFormtableData = JSON.parse(JSON.stringify(this.tableData)) |
| | | }) |
| | | .catch(err => { |
| | | console.error('获取详情失败:', err) |
| | | this.$message.error('加载数据失败,请重试') |
| | | |
| | | // 加载失败时使用初始数据 |
| | | this.tableData = this.initialTableData.map(item => ({ ...item })) |
| | | }) |
| | | .finally(() => { |
| | | this.isLoading = false |
| | | }) |
| | | }, |
| | | |
| | | handleAdd() { |
| | | this.dialogVisible = true |
| | | this.dialogIsEdit = false |
| | |
| | | this.dialogValue = {} |
| | | this.dialogIndex = null |
| | | }, |
| | | |
| | | handleEdit(row) { |
| | | const idx = this.tableData.indexOf(row) |
| | | this.dialogVisible = true |
| | |
| | | this.dialogValue = { ...row } |
| | | this.dialogIndex = idx |
| | | }, |
| | | |
| | | handleDetail(row) { |
| | | this.detailDialogVisible = true |
| | | this.detailDialogValue = { ...row } |
| | | }, |
| | | |
| | | handleSave() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | this.detail.list = this.tableData || [] |
| | | this.detail.purpose = this.detail.purpose.join(',') |
| | | confirm({ ...this.detail }).then(res => { |
| | | const payload = { |
| | | ...this.detail, |
| | | list: this.tableData || [], |
| | | purpose: (this.detail.purpose || []).join(','), |
| | | isDraft: 0 |
| | | } |
| | | confirm(payload).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('保存成功') |
| | | this.$router.back() |
| | | this.cacheForm = null |
| | | this.cacheFormtableData = null |
| | | this.$closeCurrentView('/strain/validation/primitive-cell') |
| | | } else { |
| | | this.$message.error(res.msg) |
| | | this.$message.error(res.msg || '保存失败') |
| | | } |
| | | }) |
| | | } else { |
| | |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | handleDraft() { |
| | | this.$refs.form.validate((valid) => { |
| | | if (valid) { |
| | | //todo 存稿逻辑 |
| | | this.detail.list = this.tableData || [] |
| | | this.detail.purpose = this.detail.purpose.join(',') |
| | | console.log('this.detail: ',this.detail) |
| | | const payload = { |
| | | ...this.detail, |
| | | list: this.tableData || [], |
| | | purpose: (this.detail.purpose || []).join(',') |
| | | } |
| | | |
| | | saveDraft({ ...this.detail }).then(res => { |
| | | saveDraft(payload).then(res => { |
| | | if (res.code == 200) { |
| | | this.$message.success('保存成功') |
| | | this.$router.back() |
| | | this.$message.success('存稿成功') |
| | | this.cacheForm = null |
| | | this.cacheFormtableData = null |
| | | this.$closeCurrentView('/strain/validation/primitive-cell') |
| | | } else { |
| | | this.$message.error(res.msg) |
| | | this.$message.error(res.msg || '存稿失败') |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | handleDialogOk(val) { |
| | | if (this.dialogIsEdit && this.dialogIndex !== null) { |
| | | this.$set(this.tableData, this.dialogIndex, val) |
| | |
| | | this.tableData.push(val) |
| | | } |
| | | }, |
| | | |
| | | getRowClassName({ rowIndex }) { |
| | | return rowIndex < this.initialTableData?.length ? 'fixed-row' : '' |
| | | } |