From 0db8c9b94a9ac655549d5eba5c2a6c92ac386c06 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期四, 08 十月 2026 11:20:56 +0800
Subject: [PATCH] 提交最新代码
---
culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue | 4
culture/src/views/system/role/edit.vue | 8
culture/src/views/projectList/editProject.vue | 2
culture/src/views/strain-library/breeding-record/add.vue | 175 +-
culture/src/views/strain-library/breeding-record/index.vue | 4
culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue | 4
culture/src/views/projectList/addProject.vue | 4
culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue | 346 +++--
culture/src/components/SignatureCanvas.vue | 13
culture/src/views/strainReportLibrary/reportLibraryOneThree/components/approval/index.vue | 21
culture/src/router/index.js | 43
culture/src/views/strain-library/validation/primitive-cell/index.vue | 4
culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue | 22
culture/src/utils/view-tabs.js | 67 +
culture/src/views/strainReportLibrary/reportLibraryOne/add.vue | 78 -
laboratory/src/views/dataManagement/suspendExperiment/components/editDialog.vue | 130 ++
culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue | 54
culture/src/views/strain-library/strain-library-manage/add.vue | 2
laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue | 11
laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue | 9
culture/src/views/strainReportLibrary/reportLibraryOneFour/add.vue | 76 -
culture/src/views/strainReportLibrary/reportLibraryOneFour/components/approval/index.vue | 21
culture/src/views/strain-library/main-cell-library/add.vue | 2
culture/src/store/index.js | 10
laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue | 8
culture/src/views/pedigree-chart/add.vue | 174 ++
laboratory/src/views/dataManagement/confirmation-sheet/components/add.vue | 13
culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue | 83 -
laboratory/LICENSE | 20
culture/src/views/pedigree-chart/addProgenitor.vue | 171 ++
culture/src/views/pedigree-chart/index.vue | 14
culture/src/views/strainReportLibrary/reportLibraryOneThree/add.vue | 75 -
culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue | 4
culture/src/views/system/role/add.vue | 8
culture/src/main.js | 10
culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue | 63
culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue | 19
culture/vue.config.js | 6
laboratory/src/views/chemistQa/projectTesting/addDetectionReport.vue | 80 +
culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue | 339 +++--
culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue | 271 +++-
laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue | 10
culture/src/views/strain-library/validation/primitive-cell/add.vue | 54
culture/src/layouts/components/AppContent.vue | 44
culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue | 33
culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue | 272 +++-
culture/src/utils/baseurl.js | 7
culture/src/views/strain-library/production-cell-library/add.vue | 2
culture/src/layouts/components/HeaderNav.vue | 29
laboratory/src/utils/request.js | 3
culture/src/views/strainReportLibrary/reportLibraryOne/index.vue | 4
culture/src/views/strain-library/production-cell-grandson/add.vue | 2
culture/src/views/strain-library/validation/chief-cell/index.vue | 6
culture/src/views/strain-library/validation/chief-cell/add.vue | 54
laboratory/vue.config.js | 4
culture/src/utils/utils.js | 86 +
56 files changed, 2,004 insertions(+), 1,074 deletions(-)
diff --git a/culture/src/components/SignatureCanvas.vue b/culture/src/components/SignatureCanvas.vue
index 46bb6e3..11b773a 100644
--- a/culture/src/components/SignatureCanvas.vue
+++ b/culture/src/components/SignatureCanvas.vue
@@ -16,7 +16,7 @@
</template>
<script>
-import { customUploadRequest } from '@/utils/utils'
+import { customUploadRequest, getUploadedFilePath } from '@/utils/utils'
import {editSignPicture} from './service'
export default {
name: 'SignatureCanvas',
@@ -208,10 +208,13 @@
customUploadRequest({
file,
onSuccess: (res) => {
- // 假设返回的图片路径为 res.url
- const url = res.msg || res.data || res
- editSignPicture({ signPicture: res.msg }).then(res => {
- if (res.code == 200) {
+ const url = getUploadedFilePath(res)
+ if (!url) {
+ this.$message.error('上传接口未返回文件地址')
+ return
+ }
+ editSignPicture({ signPicture: url }).then(result => {
+ if (result.code == 200) {
this.$message.success('签名成功');
this.$emit('confirm', url);
}
diff --git a/culture/src/layouts/components/AppContent.vue b/culture/src/layouts/components/AppContent.vue
index 62372dc..45abca8 100644
--- a/culture/src/layouts/components/AppContent.vue
+++ b/culture/src/layouts/components/AppContent.vue
@@ -1,8 +1,9 @@
<template>
<div @click="foldFun" style="height: 100%;">
- <keep-alive :include="keepAliveList">
- <router-view />
+ <keep-alive ref="keepAlive">
+ <router-view v-if="shouldCacheView" :key="routeCacheKey" />
</keep-alive>
+ <router-view v-if="!shouldCacheView" :key="$route.fullPath" />
</div>
</template>
@@ -15,9 +16,46 @@
}
},
computed: {
- ...mapState(['keepAliveList'])
+ ...mapState(['tagList', 'cachePruneRequest']),
+ activeTag() {
+ return this.tagList.find(tag => {
+ const fullPath = tag.fullPath || this.$router.resolve({
+ path: tag.path,
+ query: tag.query || {}
+ }).route.fullPath
+ return fullPath === this.$route.fullPath
+ })
+ },
+ shouldCacheView() {
+ return Boolean(this.$route.meta.keepAlive || this.$route.meta.hide)
+ },
+ routeCacheKey() {
+ return this.activeTag && this.activeTag.cacheKey
+ ? this.activeTag.cacheKey
+ : (this.$route.query._view || this.$route.fullPath)
+ }
+ },
+ watch: {
+ cachePruneRequest(request) {
+ if (request && request.keys) {
+ request.keys.forEach(key => this.pruneCacheEntry(key))
+ }
+ }
},
methods: {
+ pruneCacheEntry(key) {
+ const keepAlive = this.$refs.keepAlive
+ if (!keepAlive || !keepAlive.cache || !keepAlive.keys) return
+
+ const cached = keepAlive.cache[key]
+ if (cached && cached.componentInstance) {
+ cached.componentInstance.$destroy()
+ }
+ keepAlive.cache[key] = null
+
+ const index = keepAlive.keys.indexOf(key)
+ if (index > -1) keepAlive.keys.splice(index, 1)
+ },
foldFun() {
if (window.innerWidth < 1000) {
this.$store.commit('SET_ISFOLD', true)
diff --git a/culture/src/layouts/components/HeaderNav.vue b/culture/src/layouts/components/HeaderNav.vue
index 0c66d87..1deaf24 100644
--- a/culture/src/layouts/components/HeaderNav.vue
+++ b/culture/src/layouts/components/HeaderNav.vue
@@ -12,8 +12,8 @@
<i @click="clickFold" class="el-icon-s-fold"></i>
<!-- 标签列表 -->
<div class="tag-list-container" @wheel.prevent="handleWheel">
- <div class="tag-list" v-for="tag in tagList" :key="tag.name">
- <div @click="goTag(tag)" :class="{ 'activeTag': tag.path === $route.path }">
+ <div class="tag-list" v-for="tag in tagList" :key="tag.cacheKey || tag.fullPath || tag.path">
+ <div @click="goTag(tag)" :class="{ 'activeTag': getTagFullPath(tag) === $route.fullPath }">
{{ tag.meta.title }}
</div>
<i @click="closeTag(tag)" v-if="tagList.length > 1" class="el-icon-close"></i>
@@ -35,6 +35,7 @@
<script>
import { mapState } from 'vuex'
+import { closeRouteView, getTagFullPath } from '@/utils/view-tabs'
export default {
data() {
return {
@@ -72,22 +73,22 @@
},
// 关闭标签
closeTag(tag) {
- this.$store.commit('SET_TAGLIST', this.tagList.filter(item => item.path !== tag.path))
- // 判断是否是当前标签
- if (tag.path === this.$route.path) {
- // if (this.tagList.length > 1) {
- this.$router.push(this.tagList[this.tagList.length - 1].path)
- // } else {
- // // this.$router.push('/welcome')
- // }
- }
+ closeRouteView({
+ router: this.$router,
+ store: this.$store,
+ route: this.$route,
+ tag
+ })
},
// 跳转标签
goTag(tag) {
- this.$router.push({
+ this.$router.push(tag.fullPath || {
path: tag.path,
- query: tag.query
+ query: tag.query || {}
})
+ },
+ getTagFullPath(tag) {
+ return getTagFullPath(this.$router, tag)
},
handleWheel(e) {
if (this.scrollTimer) {
@@ -259,4 +260,4 @@
}
}
}
-</style>
\ No newline at end of file
+</style>
diff --git a/culture/src/main.js b/culture/src/main.js
index 33131c1..7d28ab3 100644
--- a/culture/src/main.js
+++ b/culture/src/main.js
@@ -21,6 +21,7 @@
import './assets/tailwind.css'
import './styles/element-variables.less'
import { fetchEncryptionKey } from './utils/encryption'
+import { closeRouteView } from './utils/view-tabs'
Vue.config.productionTip = false;
Vue.use(ElementUI, { size: 'small' })
@@ -72,6 +73,15 @@
return height
}
+Vue.prototype.$closeCurrentView = function (fallback) {
+ return closeRouteView({
+ router: this.$router,
+ store: this.$store,
+ route: this.$route,
+ fallback
+ })
+}
+
// 获取加密密钥
// fetchEncryptionKey()
diff --git a/culture/src/router/index.js b/culture/src/router/index.js
index d5365ce..10022be 100644
--- a/culture/src/router/index.js
+++ b/culture/src/router/index.js
@@ -732,6 +732,18 @@
routes,
});
+let tagCacheSequence = 0;
+const createTagCacheKey = (fullPath) => `${fullPath}::${Date.now()}-${tagCacheSequence++}`;
+const getTagFullPath = (tag) => tag.fullPath || router.resolve({
+ path: tag.path,
+ query: tag.query || {},
+}).route.fullPath;
+const getViewIdentity = (path, query = {}) => {
+ const businessQuery = { ...query };
+ delete businessQuery._view;
+ return router.resolve({ path, query: businessQuery }).route.fullPath;
+};
+
// 前置路由拦截器
router.beforeEach((to, from, next) => {
// 设置当前页签名称
@@ -780,18 +792,47 @@
}
}
+ // Hidden business pages are independent tab instances. An existing tab keeps
+ // its _view; entering from a list again creates a clean component instance.
+ const isIndependentView = Boolean(to.meta.hide && !to.meta.oneself);
+ if (isIndependentView && !to.query._view) {
+ const viewIdentity = getViewIdentity(to.path, to.query);
+ const tagList = JSON.parse(sessionStorage.getItem("tagList") || "[]");
+ const staleTags = tagList.filter((tag) =>
+ getViewIdentity(tag.path, tag.query) === viewIdentity
+ );
+
+ if (staleTags.length) {
+ const staleKeys = staleTags.map((tag) => tag.cacheKey || getTagFullPath(tag));
+ const remainingTags = tagList.filter((tag) =>
+ getViewIdentity(tag.path, tag.query) !== viewIdentity
+ );
+ store.commit("SET_TAGLIST", remainingTags);
+ store.commit("PRUNE_VIEW_CACHE", staleKeys);
+ }
+
+ next({
+ path: to.path,
+ query: { ...to.query, _view: `${Date.now()}-${tagCacheSequence++}` },
+ replace: true,
+ });
+ return;
+ }
+
// 设置标签列表
if (!to.meta.hide || !to.meta.oneself) {
let tagList = JSON.parse(sessionStorage.getItem("tagList") || "[]");
// 判断是否存在
- let isExist = tagList.some((item) => item.path === to.path);
+ let isExist = tagList.some((item) => getTagFullPath(item) === to.fullPath);
if (!isExist) {
// 只保存必要的信息
const tagInfo = {
path: to.path,
+ fullPath: to.fullPath,
name: to.name,
meta: to.meta,
query: to.query,
+ cacheKey: createTagCacheKey(to.fullPath),
};
tagList.push(tagInfo);
sessionStorage.setItem("tagList", JSON.stringify(tagList));
diff --git a/culture/src/store/index.js b/culture/src/store/index.js
index 07bb9ce..51771f8 100644
--- a/culture/src/store/index.js
+++ b/culture/src/store/index.js
@@ -2,11 +2,14 @@
import Vuex from 'vuex'
Vue.use(Vuex)
+let cachePruneSequence = 0
+
const store = new Vuex.Store({
state: {
menus: sessionStorage.getItem('menuList') ? JSON.parse(sessionStorage.getItem('menuList')) : [],
keepAliveList: sessionStorage.getItem('keepAliveList') ? JSON.parse(sessionStorage.getItem('keepAliveList')) : [],//缓存页面
tagList: sessionStorage.getItem('tagList') ? JSON.parse(sessionStorage.getItem('tagList')) : [],//标签列表
+ cachePruneRequest: null,
isFold: false,//是否折叠
assay: [
'检验方法正确',
@@ -48,6 +51,13 @@
state.tagList = data;
sessionStorage.setItem('tagList', JSON.stringify(data));
},
+ PRUNE_VIEW_CACHE(state, data) {
+ const keys = (Array.isArray(data) ? data : [data]).filter(Boolean)
+ state.cachePruneRequest = {
+ id: ++cachePruneSequence,
+ keys
+ }
+ },
SET_ISFOLD(state, data) {
state.isFold = data;
},
diff --git a/culture/src/utils/baseurl.js b/culture/src/utils/baseurl.js
index d1b6e8d..2608d69 100644
--- a/culture/src/utils/baseurl.js
+++ b/culture/src/utils/baseurl.js
@@ -1,3 +1,8 @@
+function getProductionFileUrl() {
+ if (typeof window === 'undefined') return '/images/';
+ return `${window.location.protocol}//${window.location.hostname}:11223/images/`;
+}
+
const apiConfig = {
// 开发环境
development: {
@@ -9,7 +14,7 @@
production: {
baseURL: "/culture",
imgUrl: "/culture/open/file/upload",
- showImgUrl:'http://127.0.0.1:11223/images/'
+ showImgUrl: getProductionFileUrl()
},
};
diff --git a/culture/src/utils/utils.js b/culture/src/utils/utils.js
index 2bd2900..5e1f7fd 100644
--- a/culture/src/utils/utils.js
+++ b/culture/src/utils/utils.js
@@ -39,32 +39,81 @@
}
});
};
-// export function getFullUrl(url) {
-// if (!url) return "";
-// if (/^https?:\/\//.test(url)) return url;
-// return getAllocateIp() + url;
-// }
-export function getFullUrl(url) {
- const origin = window.location.origin;
- console.log('图片:', url);
+export function getUploadedFilePath(response) {
+ const payload = response && response.data && typeof response.data === 'object'
+ ? response.data
+ : response;
- if (!url) return "";
- if (/^https?:\/\//.test(url)) return url;
+ if (typeof payload === 'string') return payload.trim();
+ if (!payload || typeof payload !== 'object') return '';
- console.log(origin.replace('8087','11223') + '/images/' + url);
-
- return origin.replace('8087','11223') + '/images/' + url; //todo 具体端口以线上为准
- // return getAllocateIp() + url;
+ const nestedPath = payload.data && typeof payload.data === 'object'
+ ? getUploadedFilePath(payload.data)
+ : '';
+ const candidates = [nestedPath, payload.data, payload.url, payload.fileUrl, payload.path, payload.msg];
+ const successMessages = ['操作成功', '上传成功', 'success', 'ok'];
+ return candidates.find(value => {
+ return typeof value === 'string'
+ && value.trim()
+ && !successMessages.includes(value.trim().toLowerCase());
+ }) || '';
}
+export function normalizeFileList(value) {
+ let files = value;
+ if (typeof files === 'string') {
+ const text = files.trim();
+ if (!text) return [];
+ try {
+ files = JSON.parse(text);
+ } catch (e) {
+ files = [text];
+ }
+ }
+ if (!Array.isArray(files)) files = files ? [files] : [];
+
+ return files.map((file, index) => {
+ const source = typeof file === 'string' ? { url: file } : (file || {});
+ const url = source.url || source.fileUrl || source.path || source.filePath || '';
+ const fallbackName = String(url).split(/[\\/]/).pop() || `附件${index + 1}`;
+ return {
+ ...source,
+ name: source.name || source.fileName || fallbackName,
+ url,
+ uid: source.uid || source.id || `legacy-file-${index}-${url}`
+ };
+ }).filter(file => file.url);
+}
+
+export function getFullUrl(url) {
+ if (!url) return "";
+ const value = String(url).trim().replace(/\\/g, '/');
+ if (/^(data|blob):/.test(value)) return value;
+
+ const isAbsoluteUrl = /^(https?:)?\/\//.test(value);
+ if (isAbsoluteUrl && !/^(https?:)?\/\/(localhost|127\.0\.0\.1)(:\d+)?\//i.test(value)) {
+ return value;
+ }
+
+ const base = getAllocateIp().replace(/\/+$/, '') + '/';
+ let path = value;
+ if (isAbsoluteUrl) {
+ const parsedUrl = new URL(value, window.location.origin);
+ path = `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;
+ }
+ path = path.replace(/^\/+/, '');
+ if (/\/images\/$/.test(base) && path.startsWith('images/')) {
+ path = path.slice('images/'.length);
+ }
+ return base + path;
+}
/**
* 通用文件下载方法
* @param {string} url 文件的下载地址(支持相对和绝对路径)
* @param {string} name 下载保存的文件名(可选)
*/
export function downloadFileByUrl(url, name) {
- console.log('22222222222222222222',url)
if (!url) return;
// 处理相对路径
const fullUrl = getFullUrl(url);
@@ -104,6 +153,9 @@
export function getAllocateIp() {
const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}");
- // return apiConfig.showImgUrl
- return userInfo.allocateIp ? 'http://'+userInfo.allocateIp +':11223/images/' : apiConfig.showImgUrl;
+ const allocateIp = String(userInfo.allocateIp || '').trim();
+ const isLoopback = /^(localhost|127\.0\.0\.1)$/i.test(allocateIp);
+ return allocateIp && !isLoopback
+ ? `http://${allocateIp}:11223/images/`
+ : apiConfig.showImgUrl;
}
diff --git a/culture/src/utils/view-tabs.js b/culture/src/utils/view-tabs.js
new file mode 100644
index 0000000..d7eea97
--- /dev/null
+++ b/culture/src/utils/view-tabs.js
@@ -0,0 +1,67 @@
+export function getTagFullPath(router, tag) {
+ if (tag.fullPath) return tag.fullPath
+ return router.resolve({
+ path: tag.path,
+ query: tag.query || {}
+ }).route.fullPath
+}
+
+function getNavigationTarget(router, remainingTags, fallback) {
+ if (fallback) {
+ const fallbackRoute = router.resolve(fallback).route
+ const matchingTag = remainingTags.slice().reverse().find((tag) => {
+ return router.resolve(getTagFullPath(router, tag)).route.path === fallbackRoute.path
+ })
+ return matchingTag ? getTagFullPath(router, matchingTag) : fallback
+ }
+
+ const target = remainingTags[remainingTags.length - 1]
+ return target ? getTagFullPath(router, target) : null
+}
+
+export function closeRouteView({ router, store, route, tag, fallback }) {
+ const currentRoute = route || router.currentRoute
+ const targetTag = tag || store.state.tagList.find((item) => {
+ return getTagFullPath(router, item) === currentRoute.fullPath
+ })
+ const targetFullPath = targetTag
+ ? getTagFullPath(router, targetTag)
+ : currentRoute.fullPath
+ const remainingTags = store.state.tagList.filter((item) => {
+ return getTagFullPath(router, item) !== targetFullPath
+ })
+ const isActive = targetFullPath === router.currentRoute.fullPath
+ const pruneKey = targetTag && targetTag.cacheKey
+ ? targetTag.cacheKey
+ : targetFullPath
+
+ const removeTagAndPrune = () => {
+ const latestTags = store.state.tagList.filter((item) => {
+ return getTagFullPath(router, item) !== targetFullPath
+ })
+ store.commit('SET_TAGLIST', latestTags)
+ store.commit('PRUNE_VIEW_CACHE', pruneKey)
+ }
+
+ if (!isActive) {
+ removeTagAndPrune()
+ return Promise.resolve()
+ }
+
+ const navigationTarget = getNavigationTarget(router, remainingTags, fallback)
+ if (!navigationTarget) {
+ removeTagAndPrune()
+ return Promise.resolve()
+ }
+
+ return Promise.resolve(router.push(navigationTarget)).then(
+ (result) => {
+ removeTagAndPrune()
+ return result
+ },
+ (error) => {
+ removeTagAndPrune()
+ throw error
+ }
+ )
+}
diff --git a/culture/src/views/pedigree-chart/add.vue b/culture/src/views/pedigree-chart/add.vue
index 0b4be92..42bf693 100644
--- a/culture/src/views/pedigree-chart/add.vue
+++ b/culture/src/views/pedigree-chart/add.vue
@@ -86,22 +86,22 @@
<div class="header">
<div class="title">菌种传代生产谱系图</div>
<div class="option-btn">
- <el-button type="primary" v-if="roleType == 3 || roleType == 1" class="el-icon-plus" @click="addNode" :disabled="editBoolean">
+ <el-button type="primary" v-if="!isReadOnly && (roleType == 3 || roleType == 1)" class="el-icon-plus" @click="addNode" :disabled="editBoolean">
新增</el-button>
- <el-button type="primary" v-if="roleType == 3 || roleType == 1"
+ <el-button type="primary" v-if="!isReadOnly && (roleType == 3 || roleType == 1)"
@click="setGenerationPlan" :disabled="editBoolean">设置传代计划数</el-button>
<el-button type="primary" @click="showDetail">详情</el-button>
- <el-button type="primary" @click="handleEdit" v-if="roleType == 1 || roleType == 3" :disabled="editBoolean">编辑</el-button>
- <el-button type="primary" @click="handleDelete" v-if="roleType == 1 || roleType == 3" :disabled="editBoolean">删除</el-button>
+ <el-button type="primary" @click="handleEdit" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">编辑</el-button>
+ <el-button type="primary" @click="handleDelete" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">删除</el-button>
</div>
</div>
<div class="strain-flow-chart">
- <div id="mountNode"></div>
+ <div ref="mountNode" class="mount-node"></div>
</div>
<!-- v-if="!$route.query.id || (roleType == 1 && $route.query.id)" -->
- <div v-if="roleType == 1 || roleType == 3">
+ <div v-if="!isReadOnly && (roleType == 1 || roleType == 3)">
<el-button type="primary" @click="handleSubmit('1')" style="width: 150px" :disabled="editBoolean">保存</el-button>
<el-button type="primary" @click="handleSubmit('2')" style="width: 150px; margin-left: 20px" :disabled="editBoolean">提交</el-button>
</div>
@@ -112,20 +112,20 @@
</div>
</el-form>
- <ParentForm ref="parentForm" @addNodeSign="addNodeSign" />
- <PlanForm ref="planForm" @addNodeSign="addNodeSign" />
- <AddSublevelForm ref="addSublevelForm" @addNodeSign="addNodeSign" />
- <AddSublevelPlan ref="addSublevelPlan" @addNodeSign="addNodeSign" />
- <ConfirmStorageDialog name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
+ <ParentForm :key="pageInstanceKey" ref="parentForm" @addNodeSign="addNodeSign" />
+ <PlanForm :key="pageInstanceKey" ref="planForm" @addNodeSign="addNodeSign" />
+ <AddSublevelForm :key="pageInstanceKey" ref="addSublevelForm" @addNodeSign="addNodeSign" />
+ <AddSublevelPlan :key="pageInstanceKey" ref="addSublevelPlan" @addNodeSign="addNodeSign" />
+ <ConfirmStorageDialog :key="`signature-${pageInstanceKey}`" name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
@confirm="handleSignatureConfirm" />
<!-- 菌种工程师 -->
- <ConfirmStorageDialog name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
+ <ConfirmStorageDialog :key="`storage-${pageInstanceKey}`" name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
@confirm="handleSignatureConfirm1" />
<!-- 传代数审批 -->
- <ApprovalCount ref="approvalCount" @addNodeSign="sureApprovalCountSign" />
+ <ApprovalCount :key="`approval-${pageInstanceKey}`" ref="approvalCount" @addNodeSign="sureApprovalCountSign" />
- <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
+ <chooseProject :key="`project-${pageInstanceKey}`" @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
</div>
</template>
@@ -212,6 +212,9 @@
nodeType: "", //1母代 2计划数 3子孙代
tableData: [],
cacheData: null, // 👈 添加这一行
+ activeRouteKey: "",
+ graphLoadId: 0,
+ pageInstanceKey: 0,
confirmStorageDialogVisible: false,
storageVisible: false,
editBoolean: false,
@@ -232,6 +235,9 @@
};
},
computed: {
+ isReadOnly() {
+ return this.$route.path.includes('detail') || this.$route.query.mode === 'detail';
+ },
canAddNode() {
// 如果没有节点,可以新增母代
if (this.graphData.nodes.length === 0) {
@@ -245,8 +251,7 @@
},
},
mounted() {
- this.initGraph();
- this.initEvents();
+ this.resetMountNode();
},
deactivated() {
// 缓存数据
@@ -261,11 +266,12 @@
newTotal: this.newTotal,
projectData: JSON.parse(JSON.stringify(this.projectData)),
treeData: JSON.parse(JSON.stringify(this.treeData)),
- nodeTreeStatus: this.nodeTreeStatus
+ nodeTreeStatus: this.nodeTreeStatus,
+ routeKey: this.activeRouteKey
};
},
activated() {
- if (this.cacheData) {
+ if (this.cacheData && this.cacheData.routeKey === this.$route.fullPath) {
// 恢复数据
this.form = JSON.parse(JSON.stringify(this.cacheData.form));
this.graphData = JSON.parse(JSON.stringify(this.cacheData.graphData));
@@ -280,13 +286,17 @@
this.nodeTreeStatus = this.cacheData.nodeTreeStatus || 1;
// 更新图表
+ this.resetMountNode();
if (this.graphData.nodes.length > 0) {
this.updateGraphData();
}
return;
}
+ this.cacheData = null;
if (this.$route.query.id) {
this.reloadData();
+ } else {
+ this.resetPageState();
}
if (this.$route.query.status !== undefined && this.$route.query.status != 1 && this.roleType != 1){
this.editBoolean = true
@@ -298,22 +308,108 @@
'$route': {
immediate: true,
handler(to) {
+ if (!["AddPedigree", "DetailPedigree"].includes(to.name)) {
+ return;
+ }
console.log('变动');
+ const routeKey = to.fullPath;
+ const routeChanged = this.activeRouteKey && this.activeRouteKey !== routeKey;
+ this.activeRouteKey = routeKey;
+ if (routeChanged || !to.query.id) {
+ this.cacheData = null;
+ this.resetPageState();
+ }
if (to.query.id) {
this.reloadData();
}
- this.editBoolean =
- this.roleType != 1 &&
- to.query.status != 1;
+ this.editBoolean = this.shouldDisableEditing(to.query);
}
}
},
beforeDestroy() {
- this.graph?.destroy();
- window.removeEventListener("resize", this.handleResize);
+ this.destroyGraph();
},
methods: {
+ shouldDisableEditing(query = this.$route.query) {
+ const status = query && query.status;
+ return Number(this.roleType) !== 1
+ && status !== undefined
+ && status !== null
+ && status !== ""
+ && Number(status) !== 1;
+ },
+ destroyGraph() {
+ window.removeEventListener("resize", this.handleResize);
+ if (this.graph && !this.graph.get("destroyed")) {
+ this.graph.destroy();
+ }
+ this.graph = null;
+
+ const container = this.$refs.mountNode;
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+ },
+ resetMountNode() {
+ this.destroyGraph();
+ if (!this.$refs.mountNode) return;
+ this.initGraph();
+ this.initEvents();
+ },
+ resetPageState() {
+ this.pageInstanceKey += 1;
+ this.form = {
+ strainSourceStart: "",
+ strainSourceEnd: "",
+ cellBank: "",
+ strainCode: "",
+ strainName: "",
+ remarks: "",
+ };
+ this.projectData = [];
+ this.tableData = [];
+ this.newTableData = [];
+ this.total = 0;
+ this.current = 1;
+ this.size = 10;
+ this.newTotal = 0;
+ this.newCurrent = 1;
+ this.newSize = 10;
+ this.queryForm = { pageSize: 10, pageNum: 1 };
+ this.newQueryForm = { pageSize: 10, pageNum: 1 };
+ this.showChoose = false;
+ this.dialogVisible = false;
+ this.confirmStorageDialogVisible = false;
+ this.storageVisible = false;
+ this.nodeData = {};
+ this.nodeType = "";
+ this.isAddingNode = false;
+ this.showDiscarded = false;
+ this.nodeTreeStatus = 1;
+ this.editBoolean = this.shouldDisableEditing();
+ this.resetGraphData();
+ this.$nextTick(() => {
+ this.$refs.pedigreeForm && this.$refs.pedigreeForm.clearValidate();
+ });
+ },
+ resetGraphData() {
+ this.graphLoadId += 1;
+ this.graphData = {
+ nodes: [],
+ edges: [],
+ };
+ this.treeData = [];
+ this.selectedNode = null;
+ this.nodeCount = 0;
+
+ if (this.graph) {
+ this.graph.changeData({ nodes: [], edges: [] });
+ this.graph.render();
+ }
+ },
getProjectData(data) {
this.projectData = [data]; // 将选中的项目组数据存储到数组中
this.showChoose = false;
@@ -357,13 +453,15 @@
);
if (this.graphData.nodes[nodeIndex - 1].label === "子代") {
this.$refs.addSublevelPlan.openInitData({
+ ...nodeModel.data,
strainSourceStart: this.form.strainSourceStart,
strainCode1: this.form.strainCode,
strainName1: this.form.strainName,
strainSourceEnd: this.form.strainSourceEnd,
confirmTime: this.form.confirmTime,
parentId: nodeModel.id,
- formStatus: "editCount",
+ generationCount: nodeModel.data.generationCount || nodeModel.planCount,
+ formStatus: "edit",
});
} else {
this.$refs.planForm.openInitData({
@@ -372,7 +470,8 @@
strainCode1: this.form.strainCode,
strainName1: this.form.strainName,
...nodeModel.data,
- formStatus: "editCount",
+ generationCount: nodeModel.data.generationCount || nodeModel.planCount,
+ formStatus: "edit",
});
}
}
@@ -551,12 +650,19 @@
}
},
reloadData() {
+ this.resetPageState();
+ this.resetMountNode();
+ const graphLoadId = this.graphLoadId;
+ const routeKey = this.$route.fullPath;
this.getList();
this.getNewList()
if (!this.$route.query.id) {
return
}
getDetail({ id: this.$route.query.id }).then((res) => {
+ if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) {
+ return;
+ }
const nodeMap = new Map();
const calculateLevel = (node) => {
if (node.parentId === "0") return 0;
@@ -628,7 +734,7 @@
// 处理所有节点
const processAllNodes = (nodes) => {
nodes.forEach((node) => {
- if (node.codeStatus == 2 || (node.codeStatus == 1 && this.roleType == 3)) {
+ if (Number(this.roleType) === 2 || node.codeStatus == 2 || (node.codeStatus == 1 && Number(this.roleType) === 3)) {
const processedNode = processNode(node);
this.graphData.nodes.push(processedNode);
@@ -757,7 +863,7 @@
if (res.code == 200) {
this.$message.success("编辑成功");
this.cacheData = null; // 👈 添加这一行
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
}
});
return;
@@ -766,7 +872,7 @@
if (res.code == 200) {
this.$message.success("保存成功");
this.cacheData = null;
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
}
});
}
@@ -776,7 +882,7 @@
// 实现存草稿逻辑
},
handleCancel() {
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
},
handleSignatureConfirm(signatureImage) {
this.confirmStorageDialogVisible = false;
@@ -803,7 +909,8 @@
// 处理提交逻辑
},
initGraph() {
- const container = document.getElementById("mountNode");
+ const container = this.$refs.mountNode;
+ if (!container) return;
const width = container.scrollWidth;
const height = container.scrollHeight || 600;
@@ -942,7 +1049,7 @@
});
this.graph = new G6.Graph({
- container: "mountNode",
+ container,
width,
height,
fitView: true,
@@ -1219,7 +1326,8 @@
},
handleResize() {
if (this.graph) {
- const container = document.getElementById("mountNode");
+ const container = this.$refs.mountNode;
+ if (!container) return;
const width = container.scrollWidth;
const height = container.scrollHeight || 600;
this.graph.changeSize(width, height);
@@ -1825,7 +1933,7 @@
}
}
- #mountNode {
+ .mount-node {
flex: 1;
width: 100%;
min-height: 500px;
diff --git a/culture/src/views/pedigree-chart/addProgenitor.vue b/culture/src/views/pedigree-chart/addProgenitor.vue
index d079324..c1a9b26 100644
--- a/culture/src/views/pedigree-chart/addProgenitor.vue
+++ b/culture/src/views/pedigree-chart/addProgenitor.vue
@@ -69,38 +69,38 @@
<div class="header">
<div class="title">菌种传代生产谱系图</div>
<div class="option-btn">
- <el-button type="primary" class="el-icon-plus" @click="addNode" :disabled="editBoolean" v-if="roleType == 3 || roleType == 1">
+ <el-button type="primary" class="el-icon-plus" @click="addNode" :disabled="editBoolean" v-if="!isReadOnly && (roleType == 3 || roleType == 1)">
<!-- v-if="$route.query.type != 1" -->
新增</el-button>
- <el-button type="primary" v-if="roleType == 3 || roleType == 1" :disabled="editBoolean"
+ <el-button type="primary" v-if="!isReadOnly && (roleType == 3 || roleType == 1)" :disabled="editBoolean"
@click="setGenerationPlan">设置传代计划数</el-button>
<el-button type="primary" @click="showDetail">详情</el-button>
- <el-button type="primary" @click="handleEdit" v-if="roleType == 1 || roleType == 3" :disabled="editBoolean">编辑</el-button>
- <el-button type="primary" @click="handleDelete" v-if="roleType == 1 || roleType == 3" :disabled="editBoolean">删除</el-button>
+ <el-button type="primary" @click="handleEdit" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">编辑</el-button>
+ <el-button type="primary" @click="handleDelete" v-if="!isReadOnly && (roleType == 1 || roleType == 3)" :disabled="editBoolean">删除</el-button>
</div>
</div>
<div class="strain-flow-chart">
- <div id="mountNode"></div>
+ <div ref="mountNode" class="mount-node"></div>
</div>
- <div v-if="roleType == 1 || roleType == 3">
+ <div v-if="!isReadOnly && (roleType == 1 || roleType == 3)">
<el-button type="primary" @click="handleSubmit('1')" style="width: 150px" :disabled="editBoolean">保存</el-button>
<el-button type="primary" @click="handleSubmit('2')" style="width: 150px; margin-left: 20px" :disabled="editBoolean">提交</el-button>
</div>
</div>
</el-form>
- <AddAncestor ref="addAncestor" @addNodeSign="addNodeSign" />
- <PlanForm ref="planForm" @addNodeSign="addNodeSign" />
- <AddSublevelForm ref="addSublevelForm" @addNodeSign="addNodeSign" />
- <ConfirmStorageDialog name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
+ <AddAncestor :key="pageInstanceKey" ref="addAncestor" @addNodeSign="addNodeSign" />
+ <PlanForm :key="pageInstanceKey" ref="planForm" @addNodeSign="addNodeSign" />
+ <AddSublevelForm :key="pageInstanceKey" ref="addSublevelForm" @addNodeSign="addNodeSign" />
+ <ConfirmStorageDialog :key="`signature-${pageInstanceKey}`" name="接种操作人签字" :visible.sync="confirmStorageDialogVisible"
@confirm="handleSignatureConfirm" />
<!-- 菌种工程师 -->
- <ConfirmStorageDialog name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
+ <ConfirmStorageDialog :key="`storage-${pageInstanceKey}`" name="菌种保藏人签字" text="是否确认该项菌种信息入库" :visible.sync="storageVisible"
@confirm="handleSignatureConfirm1" />
<!-- 传代数审批 -->
- <ApprovalCount ref="approvalCount" @addNodeSign="sureApprovalCountSign" />
- <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
+ <ApprovalCount :key="`approval-${pageInstanceKey}`" ref="approvalCount" @addNodeSign="sureApprovalCountSign" />
+ <chooseProject :key="`project-${pageInstanceKey}`" @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
</div>
</template>
@@ -195,9 +195,15 @@
pageSize: 10,
pageNum: 1,
},
+ activeRouteKey: "",
+ graphLoadId: 0,
+ pageInstanceKey: 0,
};
},
computed: {
+ isReadOnly() {
+ return this.$route.path.includes('detail') || this.$route.query.mode === 'detail';
+ },
canAddNode() {
// 如果没有节点,可以新增母代
if (this.graphData.nodes.length === 0) {
@@ -214,36 +220,108 @@
'$route': {
immediate: true,
handler(to) {
+ if (!["AddProgenitor", "DetailProgenitor"].includes(to.name)) {
+ return;
+ }
console.log('变动');
- if (to.query.id) {
+ const routeKey = to.fullPath;
+ const routeChanged = this.activeRouteKey && this.activeRouteKey !== routeKey;
+ this.activeRouteKey = routeKey;
+ if (routeChanged || !to.query.id) {
+ this.resetPageState();
+ }
+ if (this.graph && to.query.id) {
this.reloadData();
}
- this.editBoolean =
- this.roleType != 1 &&
- to.query.status != 1;
+ this.editBoolean = this.shouldDisableEditing(to.query);
}
}
},
- created() {
- if (this.$route.query.status !== undefined && this.$route.query.status != 1 && this.roleType != 1){
- this.editBoolean = true
- }else {
- this.editBoolean = false
- }
+ mounted() {
+ this.resetMountNode();
if (this.$route.query.id) {
this.reloadData();
}
},
- mounted() {
- this.initGraph();
- this.initEvents();
- },
beforeDestroy() {
- this.graph?.destroy();
- window.removeEventListener("resize", this.handleResize);
+ this.destroyGraph();
},
methods: {
+ shouldDisableEditing(query = this.$route.query) {
+ const status = query && query.status;
+ return Number(this.roleType) !== 1
+ && status !== undefined
+ && status !== null
+ && status !== ""
+ && Number(status) !== 1;
+ },
+ destroyGraph() {
+ window.removeEventListener("resize", this.handleResize);
+ if (this.graph && !this.graph.get("destroyed")) {
+ this.graph.destroy();
+ }
+ this.graph = null;
+
+ const container = this.$refs.mountNode;
+ if (container) {
+ while (container.firstChild) {
+ container.removeChild(container.firstChild);
+ }
+ }
+ },
+ resetMountNode() {
+ this.destroyGraph();
+ if (!this.$refs.mountNode) return;
+ this.initGraph();
+ this.initEvents();
+ },
+ resetPageState() {
+ this.pageInstanceKey += 1;
+ this.form = {
+ strainCode: "",
+ strainName: "",
+ generationType: "2",
+ };
+ this.projectData = [];
+ this.tableData = [];
+ this.newTableData = [];
+ this.total = 0;
+ this.current = 1;
+ this.size = 10;
+ this.newTotal = 0;
+ this.newCurrent = 1;
+ this.newSize = 10;
+ this.queryForm = { pageSize: 10, pageNum: 1 };
+ this.newQueryForm = { pageSize: 10, pageNum: 1 };
+ this.showChoose = false;
+ this.dialogVisible = false;
+ this.confirmStorageDialogVisible = false;
+ this.storageVisible = false;
+ this.nodeData = {};
+ this.nodeType = "";
+ this.isAddingNode = false;
+ this.showDiscarded = false;
+ this.editBoolean = this.shouldDisableEditing();
+ this.resetGraphData();
+ this.$nextTick(() => {
+ this.$refs.pedigreeForm && this.$refs.pedigreeForm.clearValidate();
+ });
+ },
+ resetGraphData() {
+ this.graphLoadId += 1;
+ this.graphData = {
+ nodes: [],
+ edges: [],
+ };
+ this.selectedNode = null;
+ this.nodeCount = 0;
+
+ if (this.graph) {
+ this.graph.changeData({ nodes: [], edges: [] });
+ this.graph.render();
+ }
+ },
getProjectData(data) {
this.projectData = [data]; // 将选中的项目组数据存储到数组中
this.showChoose = false;
@@ -479,12 +557,22 @@
}
},
async reloadData() {
+ this.resetPageState();
+ this.resetMountNode();
+ const graphLoadId = this.graphLoadId;
+ const routeKey = this.$route.fullPath;
await this.getList();
await this.getNewList();
+ if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) {
+ return;
+ }
if (!this.$route.query.id) {
return
}
getDetail({ id: this.$route.query.id }).then((res) => {
+ if (graphLoadId !== this.graphLoadId || routeKey !== this.$route.fullPath) {
+ return;
+ }
this.projectData = res.tprojectTeamList
const detailData = res.pedigreeChartParentAllDetailDTO;
// 设置基础表单数据
@@ -496,7 +584,7 @@
// 递归处理节点数据,构建树形结构
function processNode(node, parentType = null) {
// label 逻辑与新增时保持一致
- let roleType= JSON.parse(sessionStorage.getItem("userInfo")).roleType || 1
+ let roleType= Number(JSON.parse(sessionStorage.getItem("userInfo")).roleType || 1)
let label = "";
if (node.type === 2) {
label = "传代计划数";
@@ -526,12 +614,9 @@
}
if (node.children && node.children.length > 0) {
- // 根据子节点的 codeStatus 和 roleType 决定是否处理子节点
- // codeStatus == 2: 处理
- // codeStatus == 1 且 roleType == 3: 处理
- // codeStatus == 1 且 roleType != 3: 不处理(过滤掉)
+ // 审批人需要查看完整谱系,包括仍处于保存状态的节点。
processedNode.children = node.children
- .filter((child) => child.codeStatus == 2 || (child.codeStatus == 1 && roleType == 3))
+ .filter((child) => roleType === 2 || child.codeStatus == 2 || (child.codeStatus == 1 && roleType === 3))
.map((child) => processNode(child, node.type));
}
return processedNode;
@@ -641,7 +726,7 @@
edit({ ...baseData, id: this.$route.query.id }).then((res) => {
if (res.code == 200) {
this.$message.success("编辑成功");
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
}
});
return;
@@ -649,7 +734,7 @@
add(baseData).then((res) => {
if (res.code == 200) {
this.$message.success("保存成功");
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
}
});
}
@@ -659,7 +744,7 @@
// 实现存草稿逻辑
},
handleCancel() {
- this.$router.back();
+ this.$closeCurrentView('/strain/pedigree-vhart');
},
handleSignatureConfirm(signatureImage) {
this.confirmStorageDialogVisible = false;
@@ -1204,7 +1289,8 @@
}
},
initGraph() {
- const container = document.getElementById("mountNode");
+ const container = this.$refs.mountNode;
+ if (!container) return;
const width = container.scrollWidth;
const height = container.scrollHeight || 600;
@@ -1336,7 +1422,7 @@
});
this.graph = new G6.Graph({
- container: "mountNode",
+ container,
width,
height,
fitView: true,
@@ -1600,7 +1686,8 @@
},
handleResize() {
if (this.graph) {
- const container = document.getElementById("mountNode");
+ const container = this.$refs.mountNode;
+ if (!container) return;
const width = container.scrollWidth;
const height = container.scrollHeight || 600;
this.graph.changeSize(width, height);
@@ -1757,7 +1844,7 @@
}
}
- #mountNode {
+ .mount-node {
flex: 1;
width: 100%;
min-height: 500px;
diff --git a/culture/src/views/pedigree-chart/index.vue b/culture/src/views/pedigree-chart/index.vue
index f8fabc3..6cbcc7b 100644
--- a/culture/src/views/pedigree-chart/index.vue
+++ b/culture/src/views/pedigree-chart/index.vue
@@ -81,7 +81,9 @@
<el-table-column label="操作" width="250">
<template slot-scope="scope">
<el-button style="margin-right: 10px" type="text" @click="handleDetail(scope.row)">详情</el-button>
- <el-button style="margin-right: 10px" type="text" v-if="Number(roleType) == 1" @click="handleDetail(scope.row)">编辑</el-button>
+ <el-button style="margin-right: 10px" type="text"
+ v-if="canEdit(scope.row)"
+ @click="handleEdit(scope.row)">编辑</el-button>
<!-- 菌种超级管理员 -->
<el-button type="text" v-if="Number(roleType) == 1" @click="handleDelete(scope.row)">删除</el-button>
</template>
@@ -113,6 +115,7 @@
tableData: [],
total: 0,
roleType: JSON.parse(sessionStorage.getItem('userInfo')).roleType || 1, // 1.超级管理员 2.审批人 3.工程师 4.实验员
+ currentUserName: JSON.parse(sessionStorage.getItem('userInfo')).nickName || '',
// 模拟数据
mockListData: [],
mockDraftData: [],
@@ -221,7 +224,14 @@
// 实现撤销审批逻辑
},
handleEdit(row) {
- // 实现编辑逻辑
+ const path = row.generationType == 1 ? '/strain/add-pedigree' : '/strain/add-progenitor';
+ this.$router.push({ path, query: { id: row.id, mode: 'edit', status: row.status } });
+ },
+ canEdit(row) {
+ if (Number(this.roleType) === 1) return true;
+ return Number(this.roleType) === 3
+ && Number(row.status) === 1
+ && row.createBy === this.currentUserName;
},
handleDelete(row) {
// 实现删除逻辑
diff --git a/culture/src/views/projectList/addProject.vue b/culture/src/views/projectList/addProject.vue
index 64e6d42..b0bddcd 100644
--- a/culture/src/views/projectList/addProject.vue
+++ b/culture/src/views/projectList/addProject.vue
@@ -99,7 +99,7 @@
if (res.code == 200) {
this.$message.success('添加成功');
this.resetForm(); // 添加成功后重置表单
- this.$router.back(); // 跳转到上一个页面
+ this.$closeCurrentView('/projectList/list');
}
}).catch(() => {
this.loading = false; // 失败时也关闭 loading
@@ -308,4 +308,4 @@
width: 220px;
}
}
-</style>
\ No newline at end of file
+</style>
diff --git a/culture/src/views/projectList/editProject.vue b/culture/src/views/projectList/editProject.vue
index 13fae1d..1a7817b 100644
--- a/culture/src/views/projectList/editProject.vue
+++ b/culture/src/views/projectList/editProject.vue
@@ -96,7 +96,7 @@
editProject(data).then(res => {
if (res.code == 200) {
this.$message.success('添加成功')
- this.$router.push({ name: 'ProjectList' })
+ this.$closeCurrentView('/projectList/list')
}
})
}
diff --git a/culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue b/culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue
index 37a23b6..a2194f6 100644
--- a/culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue
+++ b/culture/src/views/strain-library/breeding-record/SlantRecordDialog.vue
@@ -1,15 +1,15 @@
<template>
- <el-dialog :visible.sync="visible" :title="editData ? '编辑培养皿观察记录' : '新增培养皿观察记录'" width="80%" @close="handleClose">
+ <el-dialog :visible.sync="visible" :title="readOnly ? '培养皿观察记录详情' : editData ? '编辑培养皿观察记录' : '新增培养皿观察记录'" width="80%" @close="handleClose">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" label-position="top">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="分离菌落编号" prop="separateColonyCode">
- <el-input :disabled="roleType!=4" v-model="form.separateColonyCode" placeholder="请输入分离菌落编号" />
+ <el-input :disabled="!editable" v-model="form.separateColonyCode" placeholder="请输入分离菌落编号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="形状强壮度排名" prop="strength">
- <el-input :disabled="roleType!=4" v-model="form.strength" placeholder="请输入形状强壮度排名" />
+ <el-input :disabled="!editable" v-model="form.strength" placeholder="请输入形状强壮度排名" />
</el-form-item>
</el-col>
</el-row>
@@ -22,7 +22,7 @@
</el-table-column>
<el-table-column prop="desc" label="形态记录">
<template #default="{ row }">
- <el-input class="el-input-full" style="width: 100%;" :disabled="roleType!=4" v-model="row.desc" placeholder="请输入形态记录"
+ <el-input class="el-input-full" style="width: 100%;" :disabled="!editable" v-model="row.desc" placeholder="请输入形态记录"
@blur="handleDescBlur(row)" />
</template>
</el-table-column>
@@ -36,7 +36,7 @@
:http-request="options => rowHandleUpload(options, row)"
:before-upload="file => rowBeforeUpload(file, row)"
:show-file-list="false"
- :disabled="roleType!=4 || row.uploading"
+ :disabled="!editable || row.uploading"
accept="image/*"
:auto-upload="true"
>
@@ -48,17 +48,17 @@
@click.stop="handlePreview(row, img)"
>
<el-image
- :src="img.url"
- :preview-src-list="row.images.map(i => i.url)"
+ :src="getFullUrl(img.url)"
+ :preview-src-list="row.images.map(i => getFullUrl(i.url))"
:initial-index="idx"
fit="cover"
style="width: 100%; height: 100%;"
@click.stop.native="handlePreview(row, img)"
/>
- <i class="el-icon-delete" v-if="roleType==4" @click.stop="rowHandleRemove(row, img, row.images.filter(f => f !== img))"></i>
+ <i class="el-icon-delete" v-if="editable" @click.stop="rowHandleRemove(row, img, row.images.filter(f => f !== img))"></i>
</div>
<div
- v-if="roleType==4"
+ v-if="editable"
class="upload-thumb upload-btn"
@click.stop="triggerUpload(row.index)"
>
@@ -74,7 +74,7 @@
</template>
</el-table-column>
</el-table>
- <div style="text-align: center;" v-if="roleType==4">
+ <div style="text-align: center;" v-if="editable">
<el-button type="primary" @click="handleOk" :disabled="hasUploading">保存</el-button>
</div>
</el-dialog>
@@ -82,11 +82,15 @@
<script>
import moment from 'moment'
-import { customUploadRequest, getFullUrl } from '@/utils/utils'
+import { customUploadRequest, getFullUrl, getUploadedFilePath, normalizeFileList } from '@/utils/utils'
export default {
name: 'SlantRecordDialog',
props: {
visible: Boolean,
+ readOnly: {
+ type: Boolean,
+ default: false
+ },
editData: {
type: Object,
default: null
@@ -132,7 +136,8 @@
index: index + 1,
desc: record.desc || '',
time: record.time || this.getNowTime(),
- images: record.images || []
+ images: this.normalizeImages(record.images),
+ uploading: false
}))
while (this.tableData.length < 10) {
this.tableData.push({
@@ -203,6 +208,7 @@
}
},
handleOk() {
+ if (!this.editable) return
this.$refs.formRef.validate(valid => {
if (!valid) return
@@ -235,8 +241,15 @@
this.$emit('update:visible', false)
},
rowBeforeUpload(file, row) {
- // 可做校验,暂时直接允许
- return true;
+ if (!file.type || !file.type.startsWith('image/')) {
+ this.$message.error('只能上传图片文件')
+ return false
+ }
+ if (file.size > 10 * 1024 * 1024) {
+ this.$message.error('图片大小不能超过 10MB')
+ return false
+ }
+ return true
},
rowHandleUpload(options, row) {
row.uploading = true;
@@ -244,10 +257,11 @@
customUploadRequest({
file,
onSuccess: (res) => {
- if (res.code === 200) {
+ const uploadedPath = getUploadedFilePath(res)
+ if (uploadedPath) {
const fileObj = {
- name: file.name + new Date().getTime(),
- url: getFullUrl(res.msg || res.data || ''),
+ name: file.name,
+ url: uploadedPath,
uid: new Date().getTime()
};
if (!Array.isArray(row.images)) this.$set(row, 'images', []);
@@ -256,8 +270,8 @@
this.$message.success('文件上传成功');
onSuccess(res);
} else {
- this.$message.error(res.msg || '文件上传失败');
- onError(res);
+ this.$message.error(res && res.msg ? res.msg : '上传接口未返回文件地址');
+ onError(new Error('missing uploaded file path'));
}
row.uploading = false;
},
@@ -277,21 +291,28 @@
this.previewVisible = true
},
handleDescBlur(row) {
- console.log(row)
- if (row.desc) {
+ if (this.editable && row.desc) {
row.time = this.getNowTime()
this.$forceUpdate()
}
},
triggerUpload(index) {
+ if (!this.editable) return
const uploadRef = this.$refs['uploadRef' + index];
if (uploadRef && uploadRef.$el) {
const input = uploadRef.$el.querySelector('input[type=file]');
if (input) input.click();
}
+ },
+ getFullUrl,
+ normalizeImages(images) {
+ return normalizeFileList(images)
}
},
computed: {
+ editable() {
+ return [1, 4].includes(Number(this.roleType)) && !this.readOnly
+ },
hasUploading() {
return this.tableData.some(row => row.uploading)
}
diff --git a/culture/src/views/strain-library/breeding-record/add.vue b/culture/src/views/strain-library/breeding-record/add.vue
index 9c66f5e..f473d51 100644
--- a/culture/src/views/strain-library/breeding-record/add.vue
+++ b/culture/src/views/strain-library/breeding-record/add.vue
@@ -6,7 +6,7 @@
<img src="@/assets/public/headercard.png" />
<div>所属项目组</div>
</div>
- <div class="header-title-right">
+ <div class="header-title-right" v-if="!isReadOnly">
<el-button @click="showChoose = true" class="el-icon-circle-plus-outline" type="primary">
选择项目组</el-button>
</div>
@@ -40,19 +40,19 @@
<el-row v-if="activeTab === 'strain'" :gutter="10">
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
<el-form-item label="菌株编号" prop="strainCode">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.strainCode" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.strainCode" class="w-380"
placeholder="请输入菌株编号" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
<el-form-item label="菌株名称" prop="strainName">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.strainName" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.strainName" class="w-380"
placeholder="请输入菌株名称" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="8" :xl="8">
<el-form-item label="培养基配方" prop="formula">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.formula" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.formula" class="w-380"
placeholder="请输入培养基配方" />
</el-form-item>
</el-col>
@@ -61,18 +61,18 @@
<el-row v-if="activeTab === 'material'" :gutter="10">
<el-col :span="24">
<el-form-item label="来源物资、时间及批号" prop="sourceMaterialTimeBatchNumber">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.sourceMaterialTimeBatchNumber"
+ <el-input :disabled="isReadOnly" v-model="form.sourceMaterialTimeBatchNumber"
placeholder="请输入物资编号" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="培养基配方" prop="formula">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.formula" placeholder="请输入培养基配方" />
+ <el-input :disabled="isReadOnly" v-model="form.formula" placeholder="请输入培养基配方" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="分离菌落编号" prop="separateColonyNumber">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.separateColonyNumber"
+ <el-input :disabled="isReadOnly" v-model="form.separateColonyNumber"
placeholder="请输入分离菌落编号" />
</el-form-item>
</el-col>
@@ -86,19 +86,19 @@
<el-row :gutter="10">
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<el-form-item label="培养基" prop="cultureMedium">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.cultureMedium" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.cultureMedium" class="w-380"
placeholder="请输入培养基" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<el-form-item label="培养温度" prop="temperature">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.temperature" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.temperature" class="w-380"
placeholder="请输入培养温度" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<el-form-item label="需氧类型" prop="aerobicType">
- <el-select :disabled="!!$route.query.isDetail" v-model="form.aerobicType" class="w-380"
+ <el-select :disabled="isReadOnly" v-model="form.aerobicType" class="w-380"
placeholder="请选择需氧类型">
<el-option label="专性需氧" :value="1"></el-option>
<el-option label="专性厌氧" :value="2"></el-option>
@@ -109,7 +109,7 @@
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
<el-form-item label="培养时间" prop="cultureTime">
- <el-input :disabled="!!$route.query.isDetail" v-model="form.cultureTime" class="w-380"
+ <el-input :disabled="isReadOnly" v-model="form.cultureTime" class="w-380"
placeholder="请输入培养时间" />
<!-- <el-date-picker v-model="form.cultureTime" class="w-380" placeholder="请选择培养时间" type="date" value-format="yyyy-MM-dd" /> -->
</el-form-item>
@@ -121,7 +121,7 @@
<div>一、培养皿分离记录</div>
</div>
<div class="header-title-right">
- <el-button @click="handleAddSeparation" v-if="!$route.query.isDetail && [1, 4].includes(roleType)"
+ <el-button @click="handleAddSeparation" v-if="canEditRecord"
class="el-icon-circle-plus-outline" type="primary">
新增培养皿分离记录</el-button>
</div>
@@ -139,12 +139,12 @@
</template>
</el-table-column>
<el-table-column prop="createTime" label="操作时间" />
- <el-table-column prop="address" label="操作">
- <template slot-scope="scope" v-if="[1, 4].includes(roleType)">
+ <el-table-column prop="address" label="操作" v-if="canEditRecord">
+ <template slot-scope="scope">
<el-button type="text" @click="handleEditSeparation(scope.row, scope.$index)"
- v-if="!$route.query.isDetail">编辑</el-button>
+ v-if="canEditRecord">编辑</el-button>
<el-button type="text" @click="handleDeleteSeparation(scope.$index)"
- v-if="!$route.query.isDetail">删除</el-button>
+ v-if="canEditRecord">删除</el-button>
</template>
</el-table-column>
</Table>
@@ -154,7 +154,7 @@
<div>二、培养皿生物学形态观察记录</div>
</div>
<div class="header-title-right">
- <el-button @click="handleAddObservation" v-if="!$route.query.isDetail && [1, 4].includes(roleType)"
+ <el-button @click="handleAddObservation" v-if="canEditRecord"
class="el-icon-circle-plus-outline" type="primary">
新增观察记录</el-button>
</div>
@@ -169,7 +169,7 @@
<!-- <el-button type="text" @click="handleEditObservation(scope.row)" v-if="!$route.query.isDetail">编辑</el-button> -->
<el-button type="text" @click="handleEditObservation(scope.row)">形态记录</el-button>
<el-button type="text" @click="handleDeleteObservation(scope.$index)"
- v-if="!$route.query.isDetail && [1, 4].includes(roleType)">删除</el-button>
+ v-if="canEditRecord">删除</el-button>
</template>
</el-table-column>
</Table>
@@ -179,7 +179,7 @@
<div>三、接种斜面记录</div>
</div>
<div class="header-title-right">
- <el-button @click="handleAddInoculation" v-if="!$route.query.isDetail && [1, 4].includes(roleType)"
+ <el-button @click="handleAddInoculation" v-if="canEditRecord"
class="el-icon-circle-plus-outline" type="primary">
新增斜面记录</el-button>
</div>
@@ -215,15 +215,14 @@
</template>
</el-table-column>
<el-table-column prop="preserveTime" label="入库保藏/废弃时间" />
- <el-table-column label="操作"
- v-if="[1, 3].includes(roleType) && $route.query.isDetail || ([4].includes(roleType))">
+ <el-table-column label="操作" v-if="canEditRecord || canEngineerConfirm">
<template slot-scope="scope">
<el-button type="text" @click="handleEditInoculation(scope.row, scope.$index)"
- v-if="!$route.query.isDetail && [1, 4].includes(roleType)">编辑</el-button>
+ v-if="canEditRecord">编辑</el-button>
<el-button type="text" @click="handleConfirmStorageClick(scope.row, scope.$index)"
- v-if="$route.query.isDetail && [3].includes(roleType) && !scope.row.preserveSignature">确认入库</el-button>
+ v-if="canEngineerConfirm && !scope.row.preserveSignature">确认入库</el-button>
<el-button type="text" @click="handleDeleteInoculation(scope.$index)"
- v-if="!scope.row.preserveSignature && [4].includes(roleType)">删除</el-button>
+ v-if="canEditRecord && !scope.row.preserveSignature">删除</el-button>
</template>
</el-table-column>
</Table>
@@ -233,7 +232,7 @@
<div>四、菌种保藏记录</div>
</div>
<div class="header-title-right">
- <el-button @click="handleAddPreserve" v-if="!$route.query.isDetail && [1, 4].includes(roleType)"
+ <el-button @click="handleAddPreserve" v-if="canEditRecord"
class="el-icon-circle-plus-outline" type="primary">
新增菌种保藏记录</el-button>
</div>
@@ -259,22 +258,21 @@
</template>
</el-table-column>
<el-table-column prop="preserveTime" label="保藏时间" />
- <el-table-column label="操作"
- v-if="[1, 3].includes(roleType) && $route.query.isDetail || ([4].includes(roleType))">
+ <el-table-column label="操作" v-if="canEditRecord || canEngineerConfirm">
<template slot-scope="scope">
<el-button type="text" @click="handleEditPreserve(scope.row, scope.$index)"
- v-if="!$route.query.isDetail && [1, 4].includes(roleType)">编辑</el-button>
+ v-if="canEditRecord">编辑</el-button>
<el-button type="text" @click="handleConfirmPreserve(scope.row, scope.$index)"
- v-if="$route.query.isDetail && [3].includes(roleType) && !scope.row.preserveSignature">确认入库</el-button>
+ v-if="canEngineerConfirm && !scope.row.preserveSignature">确认入库</el-button>
<el-button type="text" @click="handleDeletePreserve(scope.$index)"
- v-if="!scope.row.preserveSignature && [4].includes(roleType)">删除</el-button>
+ v-if="canEditRecord && !scope.row.preserveSignature">删除</el-button>
</template>
</el-table-column>
</Table>
<!-- 弹窗组件 -->
<SeparationRecordDialog :visible.sync="showSeparationDialog" :editData="editSeparationData"
@confirm="handleSeparationConfirm" @close="resetSeparationEdit" />
- <SlantRecordDialog :visible.sync="showObservationDialog" :editData="editObservationData"
+ <SlantRecordDialog :visible.sync="showObservationDialog" :editData="editObservationData" :read-only="isReadOnly"
@ok="handleObservationConfirm" />
<InoculationSlopeRecordDialog :visible.sync="showInoculationDialog" :editData="editInoculationData"
@save="handleInoculationConfirm" />
@@ -284,8 +282,7 @@
@confirm="handleConfirmStorage" />
<ConfirmPreserveDialog :visible.sync="showConfirmPreserveDialog" :editData="editPreserveData"
@confirm="handleConfirmPreserveSubmit" />
- <div class="end-btn" style="margin-top: 20px;"
- v-if="($route.query.isDetail && [4, 3].includes(roleType)) || !$route.query.isDetail && [1, 3, 4].includes(roleType)">
+ <div class="end-btn" style="margin-top: 20px;" v-if="canEditRecord">
<el-button type="primary" v-if="[1, 4].includes(roleType)" @click="handleSubmit(1)">提交</el-button>
<el-button v-if="[1, 4].includes(roleType)" type="primary" @click="handleSubmit(3)">同步给保藏人</el-button>
<el-button v-if="!$route.query.isDetail && roleType != 1" type="default" @click="handleSubmit(2)">存草稿</el-button>
@@ -293,7 +290,7 @@
</el-form>
</Card>
- <chooseProject @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
+ <chooseProject v-if="!isReadOnly" @submit="getProjectData" :show="showChoose" @close="showChoose = false"></chooseProject>
</div>
</template>
<script>
@@ -401,6 +398,17 @@
};
},
computed: {
+ isReadOnly() {
+ return Boolean(this.$route.query.isDetail) || Number(this.form.status) === 1
+ },
+ canEditRecord() {
+ return !this.isReadOnly && [1, 4].includes(this.roleType)
+ },
+ canEngineerConfirm() {
+ return Boolean(this.$route.query.isDetail)
+ && this.roleType === 3
+ && Number(this.form.status) === 2
+ },
totalInoculationCount() {
// 只统计入库(保存)
return this.form.vaccinationSlopes
@@ -455,25 +463,32 @@
}
},
ChangeTab(tab) {
- if (!this.$route.query.id) {
- this.activeTab = tab
- }
+ if (this.isReadOnly) return
+ this.activeTab = tab
+ this.form.preserveSource = tab === 'strain' ? 1 : 2
},
async getDetail() {
- const res = await detail({ id: this.$route.query.id })
+ const response = await detail({ id: this.$route.query.id })
+ const res = response.data || response
if (res.preserveSource == 1) {
this.activeTab = 'strain'
} else {
this.activeTab = 'material'
}
- res.vaccinationSlopes = res.vaccinationSlopes.map(item => {
+ res.vaccinationSlopes = (res.vaccinationSlopes || []).map(item => {
return {
...item,
handleType: item.handleType === 1 ? '保存' : '废弃'
}
})
- this.form = res
- this.projectData = res.tprojectTeamList;
+ this.form = {
+ ...this.form,
+ ...res,
+ observationOfPetriDishes: res.observationOfPetriDishes || [],
+ separationOfCultureDishesList: res.separationOfCultureDishesList || [],
+ culturePreservations: res.culturePreservations || []
+ }
+ this.projectData = res.tprojectTeamList || [];
},
handleSeparationConfirm(data) {
if (this.editSeparationIndex !== null) {
@@ -535,63 +550,45 @@
this.editPreserveData = null;
},
handleSubmit(type) {
- if (this.activeTab === 'material') {
- this.form.preserveSource = 2
- } else {
- this.form.preserveSource = 1
+ if (this.isReadOnly) return
+ if (type === 1) {
+ if (!this.form.id || Number(this.form.status) !== 2) {
+ this.$message.warning('请先同步给保藏人并完成入库确认')
+ return
+ }
+ const hasUnconfirmedSlope = this.form.vaccinationSlopes.some(item => !item.preserveId && !item.preserveSignature)
+ const hasUnconfirmedPreservation = this.form.culturePreservations.some(item => !item.preserveId && !item.preserveSignature)
+ if (hasUnconfirmedSlope || hasUnconfirmedPreservation) {
+ this.$message.warning('存在未确认的接种斜面或菌种保藏记录,不能提交')
+ return
+ }
}
-
- if (type == 1) {
- this.form.status = 1
- } else if (type == 3) {
- this.form.status = 2
- } else {
- this.form.status = 3
- }
-
this.$refs.form.validate(async (valid) => {
if (!valid) return;
try {
- if (this.form.vaccinationSlopes.length > 0) {
- let arr = this.form.vaccinationSlopes
- this.form.vaccinationSlopes = arr.map(item => {
- return {
- ...item,
- handleType: item.handleType === '保存' ? 1 : 2,
- }
- })
+ const status = type === 1 ? 1 : type === 3 ? 2 : 3
+ const payload = {
+ ...this.form,
+ preserveSource: this.activeTab === 'material' ? 2 : 1,
+ status,
+ isDraft: status === 2 ? this.form.isDraft : 0,
+ vaccinationSlopes: (this.form.vaccinationSlopes || []).map(item => ({
+ ...item,
+ handleType: item.handleType === '保存' || item.handleType === 1 ? 1 : 2
+ }))
}
- console.log(this.form, this.form.isDraft);
-
- if (this.form.id && (this.form.isDraft == 0 || this.form.isDraft == null || this.form.isDraft == 1)) {
-
- if (this.form.status != 2) {
- this.form.isDraft == 0
- }
-
- edit(this.form).then(res => {
- if (res.code === 200) {
- this.$message.success('编辑成功');
- this.cacheForm = null
- this.$router.back();
- } else {
- this.$message.error('编辑失败');
- }
- })
+ const request = payload.id ? edit(payload) : add(payload)
+ const res = await request
+ if (res.code === 200) {
+ this.$message.success(payload.id ? '编辑成功' : '添加成功')
+ this.cacheForm = null
+ this.$closeCurrentView('/strain/breeding-record')
} else {
- add(this.form).then(res => {
- if (res.code === 200) {
- this.$message.success('添加成功');
- this.cacheForm = null
- this.$router.back();
- } else {
- this.$message.error('添加失败');
- }
- });
+ this.$message.error(res.msg || (payload.id ? '编辑失败' : '添加失败'))
}
} catch (e) {
- this.$message.error('添加失败');
+ this.$message.error(this.form.id ? '编辑失败' : '添加失败');
}
});
},
diff --git a/culture/src/views/strain-library/breeding-record/index.vue b/culture/src/views/strain-library/breeding-record/index.vue
index edf59a4..280fd38 100644
--- a/culture/src/views/strain-library/breeding-record/index.vue
+++ b/culture/src/views/strain-library/breeding-record/index.vue
@@ -89,14 +89,14 @@
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column prop="status" label="状态">
<template slot-scope="scope">
- {{ scope.row.status === 1 ? '已提交' : scope.row.status === 2 ? '已同步' :'草稿' }}
+ {{ scope.row.status === 1 ? '已提交' : scope.row.status === 2 ? '已同步/未提交' :'草稿' }}
</template>
</el-table-column>
<el-table-column label="操作" width="250">
<template slot-scope="scope">
<el-button style="margin-right: 10px" type="text" @click="handleDetail(scope.row)">详情</el-button>
<el-button style="margin-right: 10px" type="text" @click="handleEdit(scope.row)"
- v-if="([1,4].includes(roleType) && scope.row.status != 1)">编辑</el-button>
+ v-if="[1, 4].includes(roleType) && scope.row.status != 1">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)"
v-if="[1].includes(roleType) || ([1, 4].includes(roleType) && currentType != 'list')">删除</el-button>
</template>
diff --git a/culture/src/views/strain-library/main-cell-library/add.vue b/culture/src/views/strain-library/main-cell-library/add.vue
index af099ab..8a399a7 100644
--- a/culture/src/views/strain-library/main-cell-library/add.vue
+++ b/culture/src/views/strain-library/main-cell-library/add.vue
@@ -366,7 +366,7 @@
this.cacheForm = null
this.displayStrainSeq = null
this.signatureVisible = false;
- this.$router.push({ path: '/strain-library/main-cell-library' });
+ this.$closeCurrentView('/strain-library/main-cell-library');
this.$message.success('操作成功');
} catch (error) {
this.$message.error('操作失败');
diff --git a/culture/src/views/strain-library/production-cell-grandson/add.vue b/culture/src/views/strain-library/production-cell-grandson/add.vue
index 2ad11fe..9568c8a 100644
--- a/culture/src/views/strain-library/production-cell-grandson/add.vue
+++ b/culture/src/views/strain-library/production-cell-grandson/add.vue
@@ -369,7 +369,7 @@
this.displayStrainSeq = null
this.signatureVisible = false;
- this.$router.push({ path: '/strain-library/production-cell-grandson' });
+ this.$closeCurrentView('/strain-library/production-cell-grandson');
this.$message.success('操作成功');
} catch (error) {
this.$message.error('操作失败');
diff --git a/culture/src/views/strain-library/production-cell-library/add.vue b/culture/src/views/strain-library/production-cell-library/add.vue
index 71af3f5..a6df7aa 100644
--- a/culture/src/views/strain-library/production-cell-library/add.vue
+++ b/culture/src/views/strain-library/production-cell-library/add.vue
@@ -370,7 +370,7 @@
this.displayStrainSeq = null
this.signatureVisible = false;
- this.$router.push({ path: '/strain-library/production-cell-library' });
+ this.$closeCurrentView('/strain-library/production-cell-library');
this.$message.success('操作成功');
} catch (error) {
this.$message.error('操作失败');
diff --git a/culture/src/views/strain-library/strain-library-manage/add.vue b/culture/src/views/strain-library/strain-library-manage/add.vue
index e59cce3..08d64ae 100644
--- a/culture/src/views/strain-library/strain-library-manage/add.vue
+++ b/culture/src/views/strain-library/strain-library-manage/add.vue
@@ -402,7 +402,7 @@
this.cacheForm = null
this.displayStrainSeq = null
this.signatureVisible = false;
- this.$router.push({ path: '/strain-library/strain-library-manage' });
+ this.$closeCurrentView('/strain-library/strain-library-manage');
this.$message.success('操作成功');
} catch (error) {
this.$message.error('操作失败');
diff --git a/culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue b/culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue
index 803e2be..c430dbf 100644
--- a/culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/DetailConditionDialog.vue
@@ -1,59 +1,52 @@
<template>
- <el-dialog :close-on-click-modal="false" :visible.sync="visible" width="80%" @open="handleOpen" @close="handleClose">
- <!-- 项目组名称 - 新增 -->
- <div class="project-header">
- <span class="project-label">项目组:</span>
- <span class="project-name">{{ detail.projectName }}</span>
+ <el-dialog :close-on-click-modal="false" :visible.sync="visible"
+ width="88%" top="5vh" custom-class="validation-detail-dialog" @open="handleOpen" @close="handleClose">
+ <div class="validation-overview">
+ <div class="stacked-field">
+ <span class="field-label">菌种来源</span>
+ <div class="value-box multiline-box source-box">{{ detail.strainSource || '-' }}</div>
+ </div>
+ <div class="project-header">
+ <span class="project-label">项目组:</span>
+ <span class="project-name">{{ detail.projectName || '-' }}</span>
+ </div>
+ <div class="detail-panel">
+ <div class="single-field-row">
+ <div class="inline-field code-field">
+ <span class="field-label">鉴别菌株编号</span>
+ <div class="value-box compact-box">{{ detail.identifyingStrainCode || '-' }}</div>
+ </div>
+ </div>
+ <div class="stacked-field name-field">
+ <span class="field-label">鉴别菌株名称</span>
+ <div class="value-box multiline-box">{{ detail.identifyingStrainName || '-' }}</div>
+ </div>
+ <div class="paired-fields">
+ <div class="inline-field">
+ <span class="field-label">验证实验编号</span>
+ <div class="value-box compact-box">{{ detail.validationExperimentCode || '-' }}</div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">实验时间</span>
+ <div class="value-box compact-box">{{ detail.experimentTime | formatDate }}</div>
+ </div>
+ </div>
+ <div class="paired-fields signature-row">
+ <div class="inline-field">
+ <span class="field-label">菌种实验员签字</span>
+ <div class="signature-area">
+ <el-image v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)"
+ :preview-src-list="[getFullUrl(detail.handleSignature)]" fit="contain" alt="菌种实验员签字" />
+ <span v-else class="waiting-text">暂无签名</span>
+ </div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">签字时间</span>
+ <div class="value-box compact-box">{{ detail.handleTime || '-' }}</div>
+ </div>
+ </div>
+ </div>
</div>
- <el-card class="top-card">
- <el-row :gutter="24" class="top-info-row">
- <el-col :span="6" class="info-col">
- <div class="info-item source-item">
- <span class="label">菌种来源:</span>
- <el-tooltip
- :content="detail.strainSource || '暂无数据'"
- placement="top"
- :disabled="!detail.strainSource || detail.strainSource.length < 30"
- popper-class="source-tooltip"
- effect="dark"
- >
- <span class="source-text">{{ detail.strainSource || '暂无数据' }}</span>
- </el-tooltip>
- </div>
- <div class="info-item">
- <span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}
- </div>
- <div class="info-item">
- <span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}
- </div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item">
- <span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}
- </div>
- <div class="info-item">
- <span class="label">实验时间:</span>{{ detail.experimentTime | formatDate }}
- </div>
- <div class="info-item"></div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item sign-label">
- <span class="label">菌种实验员签字</span>
- </div>
- <div class="info-item signature-item">
- <div class="signature-area">
- <el-image style="width: 120px;" v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)" :preview-src-list="[getFullUrl(detail.handleSignature)]" alt="签字" />
- <span v-else class="waiting-text">暂无签名</span>
- </div>
- </div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item">
- <span class="label">签字时间:</span>{{ detail.handleTime }}
- </div>
- </el-col>
- </el-row>
- </el-card>
<div class="section-card" style="margin-top: 24px">
<el-form ref="form" label-width="100px" :model="detail" label-position="top">
<el-form-item label="实验结论" prop="result">
@@ -149,7 +142,7 @@
if(date){
return moment(date).format('YYYY-MM-DD')
}else{
- return ''
+ return '-'
}
},
},
@@ -205,141 +198,170 @@
</script>
<style scoped lang="less">
-.el-dialog__body {
- padding-bottom: 0;
+::v-deep(.validation-detail-dialog) {
+ max-width: 1320px;
}
+.validation-overview {
+ color: #303133;
+ font-size: 15px;
+}
-/* 项目组名称样式 - 新增 */
+.field-label {
+ display: block;
+ margin-bottom: 8px;
+ color: #606266;
+ font-weight: 600;
+ line-height: 22px;
+ white-space: nowrap;
+}
+
+.value-box {
+ min-width: 0;
+ padding: 8px 12px;
+ color: #303133;
+ background: #fff;
+ border: 1px solid #dcdfe6;
+ border-radius: 4px;
+ box-sizing: border-box;
+ line-height: 22px;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+}
+
+.multiline-box {
+ min-height: 72px;
+ white-space: pre-wrap;
+}
+
+.source-box {
+ min-height: 68px;
+}
+
+.validation-overview > .stacked-field {
+ margin: 0 32px;
+}
+
+.validation-overview > .stacked-field .field-label {
+ padding-left: 112px;
+}
+
.project-header {
display: flex;
align-items: center;
justify-content: center;
- padding: 12px 20px;
- margin-bottom: 16px;
- background: linear-gradient(135deg, #f0f7ff 0%, #e8f4fd 100%);
- border: 1px solid #b3d8f0;
- border-radius: 8px;
+ min-height: 52px;
+ padding: 10px 20px;
+ margin: 16px 0;
+ background: #f0f8fb;
+ border: 1px solid #b9dfe6;
+ border-radius: 6px;
+ box-sizing: border-box;
.project-label {
+ margin: 0 8px 0 0;
+ color: #4d5965;
font-size: 16px;
- font-weight: 600;
- color: #2c3e50;
- margin-right: 8px;
}
.project-name {
+ color: #1890ff;
font-size: 18px;
font-weight: 700;
- color: #1890ff;
- letter-spacing: 1px;
+ word-break: break-word;
}
}
-.top-card {
- margin-bottom: 0;
- background: rgba(239, 239, 239, 1);
- border-radius: 16px;
-}
-
-.top-info-row {
- display: flex;
- flex-wrap: wrap;
- align-items: stretch;
- // gap: 16px; // 如需列间距可取消注释
-}
-
-.info-col {
- display: flex;
- flex-direction: column;
- flex: 1 1 220px;
- min-width: 220px;
+.detail-panel {
+ padding: 24px 40px 28px;
+ background: #f3f4f6;
+ border: 1px solid #e2e6eb;
+ border-radius: 6px;
box-sizing: border-box;
- // margin-bottom: 16px; // 如需换行后下方留空可取消注释
}
-.info-item {
+.single-field-row {
display: flex;
- font-size: 15px;
- line-height: 45px;
+ padding-left: 42px;
}
-.label {
- color: #666;
- font-weight: 500;
- flex-shrink: 0;
-}
-
-
-// 或者直接覆盖所有 .el-tooltip__popper
-/deep/ .source-tooltip {
- max-width: 320px !important;
- min-width: 120px !important;
- word-break: break-word;
- line-height: 1.6;
- padding: 10px 14px;
- font-size: 13px;
-}
-
-.source-item {
- flex: 1;
+.inline-field {
+ display: grid;
+ grid-template-columns: 150px minmax(0, 1fr);
+ column-gap: 12px;
+ align-items: center;
min-width: 0;
- .source-text {
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- color: #303133;
- cursor: pointer;
- padding: 0 4px;
-
- &:hover {
- color: #409EFF;
- }
+ .field-label {
+ margin-bottom: 0;
}
}
-.sign-col {
+.code-field {
+ width: 100%;
+ max-width: 416px;
+ grid-template-columns: 160px minmax(0, 1fr);
+}
+
+.compact-box {
+ display: flex;
align-items: center;
- text-align: center;
+ min-height: 40px;
}
-.sign-label {
- justify-content: center;
+.name-field {
+ margin-top: 22px;
}
-.signature-item {
- justify-content: center;
+.name-field .field-label {
+ padding-left: 42px;
+}
+
+.paired-fields {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+ gap: 72px;
+ margin-top: 22px;
+ padding: 0 32px;
+}
+
+.time-field {
+ grid-template-columns: 100px minmax(0, 1fr);
+}
+
+.paired-fields .compact-box,
+.paired-fields .signature-area {
+ width: 100%;
+ max-width: 265px;
+}
+
+.signature-row {
+ align-items: start;
+}
+
+.signature-row .signature-area {
+ max-width: 260px;
}
.signature-area {
- min-height: 80px;
- min-width: 120px;
- background: #f5f7fa;
+ width: 100%;
+ height: 72px;
+ background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
- margin-top: 8px;
+ overflow: hidden;
}
-.signature-area img {
- max-width: 100%;
- max-height: 100%;
- display: block;
+.signature-area .el-image {
+ width: 100%;
+ height: 100%;
}
.waiting-text {
color: #909399;
- font-size: 14px;
-}
-
-.sign-time {
- justify-content: center;
- text-align: center;
- color: #666;
font-size: 14px;
}
@@ -364,8 +386,37 @@
}
@media (max-width: 900px) {
- .info-col {
- height: auto;
+ .detail-panel {
+ padding: 20px;
+ }
+
+ .paired-fields {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ padding: 0;
+ }
+}
+
+@media (max-width: 600px) {
+ .inline-field {
+ display: block;
+ }
+
+ .inline-field .field-label {
+ margin-bottom: 8px;
+ }
+
+ .single-field-row {
+ padding-left: 0;
+ }
+
+ .name-field .field-label,
+ .validation-overview > .stacked-field .field-label {
+ padding-left: 0;
+ }
+
+ .validation-overview > .stacked-field {
+ margin: 0;
}
}
</style>
diff --git a/culture/src/views/strain-library/validation/chief-cell/add.vue b/culture/src/views/strain-library/validation/chief-cell/add.vue
index 9ea09e8..4df9dad 100644
--- a/culture/src/views/strain-library/validation/chief-cell/add.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/add.vue
@@ -26,8 +26,8 @@
</Table>
<el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form">
<div class="form-row">
- <el-form-item label="菌种来源" prop="strainSource">
- <el-input type="textarea" style="width:790px;" v-model="form.strainSource" placeholder="请输入" :rows="3"></el-input>
+ <el-form-item label="菌种来源" prop="strainSource" class="full-width">
+ <el-input type="textarea" v-model="form.strainSource" placeholder="请输入" :rows="3"></el-input>
</el-form-item>
</div>
<div class="form-row three-columns">
@@ -44,12 +44,12 @@
<el-input v-model="form.validationExperimentCode" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="实验时间" prop="experimentTime">
- <el-date-picker :prefix-icon="' '" style="width: 290px;" v-model="form.experimentTime" type="date"
+ <el-date-picker :prefix-icon="' '" style="width: 100%;" v-model="form.experimentTime" type="date"
placeholder="请选择实验时间"></el-date-picker>
</el-form-item>
<div class="form-item-placeholder"></div>
</div>
- <div class="end-btn" style="margin-top: 400px">
+ <div class="end-btn form-actions">
<el-button type="primary" @click="handleSubmit">提交</el-button>
<el-button @click="handleDraft" v-if="roleType != 1">存草稿</el-button>
</div>
@@ -106,17 +106,12 @@
activated() {
if (this.cacheForm) {
this.form = this.cacheForm;
+ return;
}
- if (this.$route.query.id && this.cacheForm) {
- detail({ id: this.$route.query.id }).then(res => {
- if (res) {
- // 这里根据实际接口返回字段做适配
- this.form = res
- this.projectData = res.tprojectTeamList
- }
- })
- }
+ if (this.$route.query.id) {
+ this.loadDetailData();
+ }
},
deactivated() {
this.cacheForm = JSON.parse(JSON.stringify(this.form));
@@ -149,33 +144,38 @@
// 编辑
edit({ ...submitData, id }).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/chief-cell');
});
} else {
// 新增
add(submitData).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/chief-cell');
});
}
} else {
// 存草稿
add(submitData).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/chief-cell');
});
}
},
- mounted() {
+ async loadDetailData() {
const id = this.$route.query.id || this.$route.params.id;
- if (id) {
- // 编辑或详情回显
- detail({ id }).then(res => {
- if (res && res.data) {
- // 这里根据实际接口返回字段做适配
- Object.assign(this.form, res.data);
- }
- });
+ try {
+ const res = await detail({ id });
+ if (!res || !res.id) {
+ throw new Error('未获取到验证资料详情');
+ }
+ this.form = { ...this.form, ...res };
+ this.projectData = Array.isArray(res.tprojectTeamList) ? res.tprojectTeamList : [];
+ } catch (error) {
+ console.error('获取母代菌种库验证资料失败:', error);
+ const message = error instanceof Error && error.message
+ ? error.message
+ : '获取编辑数据失败,请返回列表后重试';
+ this.$message.error(message);
}
}
}
@@ -227,6 +227,10 @@
}
}
+.form-actions {
+ margin-top: 48px;
+}
+
.strain-form {
padding: 0 40px;
diff --git a/culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue b/culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue
index b4f95fd..ff3a6f1 100644
--- a/culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/confirm-detail.vue
@@ -2,8 +2,7 @@
<Card class="confirm-detail-page">
<el-card class="top-card">
<el-row :gutter="24" class="top-info-row">
- <el-col :span="8" class="info-col">
-<!-- <div class="info-item"><span class="label">菌种来源:</span>{{ detail.strainSource }}</div>-->
+ <el-col :span="24" class="info-col source-col">
<div class="info-item source-item">
<span class="label">菌种来源:</span>
<el-tooltip
@@ -16,6 +15,8 @@
<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>{{ detail.identifyingStrainCode }}</div>
<div class="info-item"><span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}</div>
</el-col>
@@ -33,7 +34,7 @@
</div>
</div>
</el-col>
- <el-col :span="6" class="info-col">
+ <el-col :span="8" class="info-col">
<div class="info-item">
<span class="label">签字时间:</span>{{ detail.handleTime }}
</div>
@@ -176,10 +177,17 @@
},
getDetail() {
detail({id: this.$route.query.id}).then(res => {
+ const data = res.data || res
+ const purpose = Array.isArray(data.purpose)
+ ? data.purpose
+ : String(data.purpose || '').split(',').filter(Boolean).map(Number)
this.detail = {
- ...res,
- handleSignature: res.handleSignature || '', // 处理签名为空的情况
- purpose: res.purpose || [] // 处理 purpose 为空的情况
+ ...data,
+ handleSignature: data.handleSignature || '',
+ purpose
+ }
+ if (Array.isArray(data.list) && data.list.length) {
+ this.tableData = data.list.map(item => ({ ...item }))
}
})
},
@@ -205,14 +213,17 @@
handleSave() {
this.$refs.form.validate((valid) => {
if (valid) {
- this.detail.list = this.tableData || []
- this.detail.purpose = this.detail.purpose.join(',')
- this.detail.isDraft = 0
- 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.cacheForm = null
- this.$router.back()
+ this.$closeCurrentView('/strain/validation/chief-cell')
} else {
this.$message.error(res.msg);
}
diff --git a/culture/src/views/strain-library/validation/chief-cell/index.vue b/culture/src/views/strain-library/validation/chief-cell/index.vue
index 8fe3210..3bfe613 100644
--- a/culture/src/views/strain-library/validation/chief-cell/index.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/index.vue
@@ -88,7 +88,7 @@
<template #default="{ row }">
<el-button type="text" v-if="row.status == 1 && roleType == 3"
style="margin-right: 10px;"
- @click="$router.push('/strain/validation/confirm-detail?id=' + row.id)">确认</el-button>
+ @click="$router.push('/strain/validation/confirm-detail-chief?id=' + row.id)">确认</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="roleType == 4"
@click="handleDetail(row)">详情</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="roleType != 4"
@@ -224,6 +224,10 @@
// Implement batch add logic
},
handleEdit(row) {
+ if (Number(this.roleType) === 1) {
+ this.$router.push({ path: "/strain/validation/confirm-detail-chief", query: { id: row.id, mode: 'edit' } });
+ return;
+ }
this.$router.push({
path: "/strain/validation/edit-chief-cell",
query: {
diff --git a/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue b/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
index c60dfaa..07a0c9c 100644
--- a/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
+++ b/culture/src/views/strain-library/validation/chief-cell/primitive-cell-detail-dialog.vue
@@ -1,65 +1,58 @@
<template>
<el-dialog
:visible.sync="visible"
- title="母代菌种库验证资料详情"
- width="650px"
+ width="88%"
+ top="6vh"
+ custom-class="validation-simple-detail-dialog"
:close-on-click-modal="false"
@close="handleClose"
>
- <el-form label-width="120px" label-position="top" class="detail-form">
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="项目组名称">
- <el-input v-model="detail.projectName" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种来源">
- <el-input type="textarea" rows="6" v-model="detail.strainSource" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种编号">
- <el-input v-model="detail.identifyingStrainCode" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="菌种名称">
- <el-input v-model="detail.identifyingStrainName" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="验证实验编号">
- <el-input v-model="detail.validationExperimentCode" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="实验时间">
- <el-input v-model="detail.experimentTime" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
-
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种实验员签字">
- <div class="signature-area">
- <el-image style="width: 120px;" v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)" :preview-src-list="[getFullUrl(detail.handleSignature)]" alt="签字" />
- <span v-else class="waiting-text">暂无签名</span>
- </div>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="签字时间">
- <el-input v-model="detail.handleTime" disabled />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
+ <div class="validation-overview">
+ <div class="stacked-field">
+ <span class="field-label">菌种来源</span>
+ <div class="value-box multiline-box source-box">{{ detail.strainSource || '-' }}</div>
+ </div>
+ <div class="project-header">
+ <span class="project-label">项目组:</span>
+ <span class="project-name">{{ detail.projectName || '-' }}</span>
+ </div>
+ <div class="detail-panel">
+ <div class="single-field-row">
+ <div class="inline-field code-field">
+ <span class="field-label">鉴别菌株编号</span>
+ <div class="value-box compact-box">{{ detail.identifyingStrainCode || '-' }}</div>
+ </div>
+ </div>
+ <div class="stacked-field name-field">
+ <span class="field-label">鉴别菌株名称</span>
+ <div class="value-box multiline-box">{{ detail.identifyingStrainName || '-' }}</div>
+ </div>
+ <div class="paired-fields">
+ <div class="inline-field">
+ <span class="field-label">验证实验编号</span>
+ <div class="value-box compact-box">{{ detail.validationExperimentCode || '-' }}</div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">实验时间</span>
+ <div class="value-box compact-box">{{ detail.experimentTime || '-' }}</div>
+ </div>
+ </div>
+ <div class="paired-fields signature-row">
+ <div class="inline-field">
+ <span class="field-label">菌种实验员签字</span>
+ <div class="signature-area">
+ <el-image v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)"
+ :preview-src-list="[getFullUrl(detail.handleSignature)]" fit="contain" alt="菌种实验员签字" />
+ <span v-else class="waiting-text">暂无签名</span>
+ </div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">签字时间</span>
+ <div class="value-box compact-box">{{ detail.handleTime || '-' }}</div>
+ </div>
+ </div>
+ </div>
+ </div>
</el-dialog>
</template>
@@ -94,27 +87,174 @@
}
</script>
-<style scoped>
-.detail-form {
- margin-top: 10px;
+<style scoped lang="less">
+::v-deep(.validation-simple-detail-dialog) {
+ max-width: 1320px;
+}
+
+.validation-overview {
+ color: #303133;
+ font-size: 15px;
+}
+.field-label {
+ display: block;
+ margin-bottom: 8px;
+ color: #606266;
+ font-weight: 600;
+ line-height: 22px;
+ white-space: nowrap;
+}
+.value-box {
+ min-width: 0;
+ padding: 8px 12px;
+ color: #303133;
+ background: #fff;
+ border: 1px solid #dcdfe6;
+ border-radius: 4px;
+ box-sizing: border-box;
+ line-height: 22px;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+}
+.multiline-box {
+ min-height: 72px;
+ white-space: pre-wrap;
+}
+.source-box {
+ min-height: 68px;
+}
+.validation-overview > .stacked-field {
+ margin: 0 32px;
+}
+.validation-overview > .stacked-field .field-label {
+ padding-left: 112px;
+}
+.project-header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 52px;
+ padding: 10px 20px;
+ margin: 16px 0;
+ background: #f0f8fb;
+ border: 1px solid #b9dfe6;
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+.project-label {
+ margin: 0 8px 0 0;
+ color: #4d5965;
+ font-size: 16px;
+}
+.project-name {
+ color: #1890ff;
+ font-size: 18px;
+ font-weight: 700;
+ word-break: break-word;
+}
+.detail-panel {
+ padding: 24px 40px 28px;
+ background: #f3f4f6;
+ border: 1px solid #e2e6eb;
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+.single-field-row {
+ display: flex;
+ padding-left: 42px;
+}
+.inline-field {
+ display: grid;
+ grid-template-columns: 150px minmax(0, 1fr);
+ column-gap: 12px;
+ align-items: center;
+ min-width: 0;
+}
+.inline-field .field-label {
+ margin-bottom: 0;
+}
+.code-field {
+ width: 100%;
+ max-width: 416px;
+ grid-template-columns: 160px minmax(0, 1fr);
+}
+.compact-box {
+ display: flex;
+ align-items: center;
+ min-height: 40px;
+}
+.name-field {
+ margin-top: 22px;
+}
+.name-field .field-label {
+ padding-left: 42px;
+}
+.paired-fields {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+ gap: 72px;
+ margin-top: 22px;
+ padding: 0 32px;
+}
+.time-field {
+ grid-template-columns: 100px minmax(0, 1fr);
+}
+.paired-fields .compact-box,
+.paired-fields .signature-area {
+ width: 100%;
+ max-width: 265px;
+}
+.signature-row {
+ align-items: start;
+}
+.signature-row .signature-area {
+ max-width: 260px;
}
.signature-area {
- min-height: 120px;
- min-width: 240px;
- background: #f5f7fa;
+ width: 100%;
+ height: 72px;
+ background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
+ overflow: hidden;
}
-.signature-area img {
- max-width: 100%;
- max-height: 100%;
- display: block;
+.signature-area .el-image {
+ width: 100%;
+ height: 100%;
}
.waiting-text {
color: #909399;
font-size: 14px;
}
+@media (max-width: 900px) {
+ .detail-panel {
+ padding: 20px;
+ }
+ .paired-fields {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ padding: 0;
+ }
+}
+@media (max-width: 600px) {
+ .inline-field {
+ display: block;
+ }
+ .inline-field .field-label {
+ margin-bottom: 8px;
+ }
+ .single-field-row {
+ padding-left: 0;
+ }
+ .name-field .field-label,
+ .validation-overview > .stacked-field .field-label {
+ padding-left: 0;
+ }
+ .validation-overview > .stacked-field {
+ margin: 0;
+ }
+}
</style>
diff --git a/culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue b/culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue
index efa0a38..a641d82 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/DetailConditionDialog.vue
@@ -1,59 +1,52 @@
<template>
- <el-dialog :close-on-click-modal="false" :visible.sync="visible" width="80%" @open="handleOpen" @close="handleClose">
- <!-- 项目组名称 - 新增 -->
- <div class="project-header">
- <span class="project-label">项目组:</span>
- <span class="project-name">{{ detail.projectName }}</span>
+ <el-dialog :close-on-click-modal="false" :visible.sync="visible"
+ width="88%" top="5vh" custom-class="validation-detail-dialog" @open="handleOpen" @close="handleClose">
+ <div class="validation-overview">
+ <div class="stacked-field">
+ <span class="field-label">菌种来源</span>
+ <div class="value-box multiline-box source-box">{{ detail.strainSource || '-' }}</div>
+ </div>
+ <div class="project-header">
+ <span class="project-label">项目组:</span>
+ <span class="project-name">{{ detail.projectName || '-' }}</span>
+ </div>
+ <div class="detail-panel">
+ <div class="single-field-row">
+ <div class="inline-field code-field">
+ <span class="field-label">鉴别菌株编号</span>
+ <div class="value-box compact-box">{{ detail.identifyingStrainCode || '-' }}</div>
+ </div>
+ </div>
+ <div class="stacked-field name-field">
+ <span class="field-label">鉴别菌株名称</span>
+ <div class="value-box multiline-box">{{ detail.identifyingStrainName || '-' }}</div>
+ </div>
+ <div class="paired-fields">
+ <div class="inline-field">
+ <span class="field-label">验证实验编号</span>
+ <div class="value-box compact-box">{{ detail.validationExperimentCode || '-' }}</div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">实验时间</span>
+ <div class="value-box compact-box">{{ detail.experimentTime | formatDate }}</div>
+ </div>
+ </div>
+ <div class="paired-fields signature-row">
+ <div class="inline-field">
+ <span class="field-label">菌种实验员签字</span>
+ <div class="signature-area">
+ <el-image v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)"
+ :preview-src-list="[getFullUrl(detail.handleSignature)]" fit="contain" alt="菌种实验员签字" />
+ <span v-else class="waiting-text">暂无签名</span>
+ </div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">签字时间</span>
+ <div class="value-box compact-box">{{ detail.handleTime || '-' }}</div>
+ </div>
+ </div>
+ </div>
</div>
- <el-card class="top-card">
- <el-row :gutter="24" class="top-info-row">
- <el-col :span="6" class="info-col">
- <div class="info-item source-item">
- <span class="label">菌种来源:</span>
- <el-tooltip
- :content="detail.strainSource || '暂无数据'"
- placement="top"
- :disabled="!detail.strainSource || detail.strainSource.length < 30"
- popper-class="source-tooltip"
- effect="dark"
- >
- <span class="source-text">{{ detail.strainSource || '暂无数据' }}</span>
- </el-tooltip>
- </div>
- <div class="info-item">
- <span class="label">鉴别菌株编号:</span>{{ detail.identifyingStrainCode }}
- </div>
- <div class="info-item">
- <span class="label">鉴别菌株名称:</span>{{ detail.identifyingStrainName }}
- </div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item">
- <span class="label">验证实验编号:</span>{{ detail.validationExperimentCode }}
- </div>
- <div class="info-item">
- <span class="label">实验时间:</span>{{ detail.experimentTime | formatDate }}
- </div>
- <div class="info-item"></div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item sign-label">
- <span class="label">菌种实验员签字</span>
- </div>
- <div class="info-item signature-item">
- <div class="signature-area">
- <el-image style="width: 120px;" v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)" :preview-src-list="[getFullUrl(detail.handleSignature)]" alt="签字" />
- <span v-else class="waiting-text">暂无签名</span>
- </div>
- </div>
- </el-col>
- <el-col :span="6" class="info-col">
- <div class="info-item">
- <span class="label">签字时间:</span>{{ detail.handleTime }}
- </div>
- </el-col>
- </el-row>
- </el-card>
<div class="section-card" style="margin-top: 24px">
<el-form ref="form" label-width="100px" :model="detail" label-position="top">
<el-form-item label="实验结论" prop="result">
@@ -146,7 +139,7 @@
if(date){
return moment(date).format('YYYY-MM-DD')
}else{
- return ''
+ return '-'
}
},
},
@@ -197,142 +190,170 @@
</script>
<style scoped lang="less">
-.el-dialog__body {
- padding-bottom: 0;
+::v-deep(.validation-detail-dialog) {
+ max-width: 1320px;
}
-/* 项目组名称样式 - 新增 */
+.validation-overview {
+ color: #303133;
+ font-size: 15px;
+}
+
+.field-label {
+ display: block;
+ margin-bottom: 8px;
+ color: #606266;
+ font-weight: 600;
+ line-height: 22px;
+ white-space: nowrap;
+}
+
+.value-box {
+ min-width: 0;
+ padding: 8px 12px;
+ color: #303133;
+ background: #fff;
+ border: 1px solid #dcdfe6;
+ border-radius: 4px;
+ box-sizing: border-box;
+ line-height: 22px;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+}
+
+.multiline-box {
+ min-height: 72px;
+ white-space: pre-wrap;
+}
+
+.source-box {
+ min-height: 68px;
+}
+
+.validation-overview > .stacked-field {
+ margin: 0 32px;
+}
+
+.validation-overview > .stacked-field .field-label {
+ padding-left: 112px;
+}
+
.project-header {
display: flex;
align-items: center;
justify-content: center;
- padding: 12px 20px;
- margin-bottom: 16px;
- background: linear-gradient(135deg, #f0f7ff 0%, #e8f4fd 100%);
- border: 1px solid #b3d8f0;
- border-radius: 8px;
+ min-height: 52px;
+ padding: 10px 20px;
+ margin: 16px 0;
+ background: #f0f8fb;
+ border: 1px solid #b9dfe6;
+ border-radius: 6px;
+ box-sizing: border-box;
.project-label {
+ margin: 0 8px 0 0;
+ color: #4d5965;
font-size: 16px;
- font-weight: 600;
- color: #2c3e50;
- margin-right: 8px;
}
.project-name {
+ color: #1890ff;
font-size: 18px;
font-weight: 700;
- color: #1890ff;
- letter-spacing: 1px;
+ word-break: break-word;
}
}
-.top-card {
- margin-bottom: 0;
- min-height: 160px;
- overflow-y: auto;
- background: #e3e3e3;
- border-radius: 16px;
-}
-
-.top-info-row {
- display: flex;
- flex-wrap: wrap;
- align-items: stretch;
-}
-
-.info-col {
- display: flex;
- flex-direction: column;
- flex: 1 1 220px;
- min-width: 220px;
+.detail-panel {
+ padding: 24px 40px 28px;
+ background: #f3f4f6;
+ border: 1px solid #e2e6eb;
+ border-radius: 6px;
box-sizing: border-box;
}
-.info-item {
+.single-field-row {
display: flex;
- font-size: 15px;
- line-height: 45px;
+ padding-left: 42px;
+}
+
+.inline-field {
+ display: grid;
+ grid-template-columns: 150px minmax(0, 1fr);
+ column-gap: 12px;
align-items: center;
- min-height: 45px;
-}
-
-.label {
- color: #666;
- font-weight: 500;
- flex-shrink: 0;
- white-space: nowrap;
-}
-
-.source-item {
- flex: 1;
min-width: 0;
- .source-text {
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- color: #303133;
- cursor: pointer;
- padding: 0 4px;
-
- &:hover {
- color: #409EFF;
- }
+ .field-label {
+ margin-bottom: 0;
}
}
-// 或者直接覆盖所有 .el-tooltip__popper
-/deep/ .source-tooltip {
- max-width: 320px !important;
- min-width: 120px !important;
- word-break: break-word;
- line-height: 1.6;
- padding: 10px 14px;
- font-size: 13px;
+.code-field {
+ width: 100%;
+ max-width: 416px;
+ grid-template-columns: 160px minmax(0, 1fr);
}
-.sign-col {
+.compact-box {
+ display: flex;
align-items: center;
- text-align: center;
+ min-height: 40px;
}
-.sign-label {
- justify-content: center;
+.name-field {
+ margin-top: 22px;
}
-.signature-item {
- justify-content: center;
+.name-field .field-label {
+ padding-left: 42px;
+}
+
+.paired-fields {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+ gap: 72px;
+ margin-top: 22px;
+ padding: 0 32px;
+}
+
+.time-field {
+ grid-template-columns: 100px minmax(0, 1fr);
+}
+
+.paired-fields .compact-box,
+.paired-fields .signature-area {
+ width: 100%;
+ max-width: 265px;
+}
+
+.signature-row {
+ align-items: start;
+}
+
+.signature-row .signature-area {
+ max-width: 260px;
}
.signature-area {
- min-height: 80px;
- min-width: 120px;
- background: #f5f7fa;
+ width: 100%;
+ height: 72px;
+ background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
- margin-top: 8px;
+ overflow: hidden;
}
-.signature-area img {
- max-width: 100%;
- max-height: 100%;
- display: block;
+.signature-area .el-image {
+ width: 100%;
+ height: 100%;
}
.waiting-text {
color: #909399;
- font-size: 14px;
-}
-
-.sign-time {
- justify-content: center;
- text-align: center;
- color: #666;
font-size: 14px;
}
@@ -356,17 +377,38 @@
background-color: rgb(228, 248, 250) !important;
}
-::v-deep(.source-tooltip) {
- max-width: 320px !important;
- word-break: break-word;
- line-height: 1.6;
- padding: 10px 14px;
- font-size: 13px;
+@media (max-width: 900px) {
+ .detail-panel {
+ padding: 20px;
+ }
+
+ .paired-fields {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ padding: 0;
+ }
}
-@media (max-width: 900px) {
- .info-col {
- height: auto;
+@media (max-width: 600px) {
+ .inline-field {
+ display: block;
+ }
+
+ .inline-field .field-label {
+ margin-bottom: 8px;
+ }
+
+ .single-field-row {
+ padding-left: 0;
+ }
+
+ .name-field .field-label,
+ .validation-overview > .stacked-field .field-label {
+ padding-left: 0;
+ }
+
+ .validation-overview > .stacked-field {
+ margin: 0;
}
}
</style>
diff --git a/culture/src/views/strain-library/validation/primitive-cell/add.vue b/culture/src/views/strain-library/validation/primitive-cell/add.vue
index d92ae07..13fda62 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/add.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/add.vue
@@ -26,8 +26,8 @@
</Table>
<el-form :model="form" :rules="rules" ref="strainForm" label-position="top" class="strain-form">
<div class="form-row">
- <el-form-item label="菌种来源" prop="strainSource">
- <el-input type="textarea" style="width:790px;" v-model="form.strainSource" placeholder="请输入" :rows="3"></el-input>
+ <el-form-item label="菌种来源" prop="strainSource" class="full-width">
+ <el-input type="textarea" v-model="form.strainSource" placeholder="请输入" :rows="3"></el-input>
</el-form-item>
</div>
<div class="form-row three-columns">
@@ -44,12 +44,12 @@
<el-input v-model="form.validationExperimentCode" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="实验时间" prop="experimentTime">
- <el-date-picker :prefix-icon="' '" style="width: 290px;" v-model="form.experimentTime" type="date"
+ <el-date-picker :prefix-icon="' '" style="width: 100%;" v-model="form.experimentTime" type="date"
placeholder="请选择实验时间"></el-date-picker>
</el-form-item>
<div class="form-item-placeholder"></div>
</div>
- <div class="end-btn" style="margin-top: 400px">
+ <div class="end-btn form-actions">
<el-button type="primary" @click="handleSubmit">提交</el-button>
<el-button @click="handleDraft" v-if="roleType != 1">存草稿</el-button>
</div>
@@ -107,17 +107,12 @@
activated() {
if (this.cacheForm) {
this.form = this.cacheForm;
+ return;
}
- if (this.$route.query.id && !this.cacheForm) {
- detail({ id: this.$route.query.id }).then(res => {
- if (res) {
- // 这里根据实际接口返回字段做适配
- this.form = res
- this.projectData = res.tprojectTeamList
- }
- })
- }
+ if (this.$route.query.id) {
+ this.loadDetailData();
+ }
},
deactivated() {
this.cacheForm = JSON.parse(JSON.stringify(this.form));
@@ -150,33 +145,38 @@
// 编辑
edit({ ...submitData, id }).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/primitive-cell');
});
} else {
// 新增
add(submitData).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/primitive-cell');
});
}
} else {
// 存草稿
add(submitData).then(() => {
this.cacheForm = null
- this.$router.back();
+ this.$closeCurrentView('/strain/validation/primitive-cell');
});
}
},
- mounted() {
+ async loadDetailData() {
const id = this.$route.query.id || this.$route.params.id;
- if (id) {
- // 编辑或详情回显
- detail({ id }).then(res => {
- if (res && res.data) {
- // 这里根据实际接口返回字段做适配
- Object.assign(this.form, res.data);
- }
- });
+ try {
+ const res = await detail({ id });
+ if (!res || !res.id) {
+ throw new Error('未获取到验证资料详情');
+ }
+ this.form = { ...this.form, ...res };
+ this.projectData = Array.isArray(res.tprojectTeamList) ? res.tprojectTeamList : [];
+ } catch (error) {
+ console.error('获取祖代菌种库验证资料失败:', error);
+ const message = error instanceof Error && error.message
+ ? error.message
+ : '获取编辑数据失败,请返回列表后重试';
+ this.$message.error(message);
}
}
}
@@ -228,6 +228,10 @@
}
}
+.form-actions {
+ margin-top: 48px;
+}
+
.strain-form {
padding: 0 40px;
diff --git a/culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue b/culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue
index 3fbebb7..06a82be 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/confirm-detail.vue
@@ -3,8 +3,7 @@
<!-- 顶部信息卡片 - 优化排版 -->
<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
@@ -17,6 +16,9 @@
<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>
@@ -27,8 +29,7 @@
</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>
@@ -43,7 +44,6 @@
</div>
</el-col>
- <!-- 右列:签名 -->
<el-col :span="8" class="info-col sign-col">
<div class="sign-wrapper">
<div class="sign-label-text">菌种实验员签字</div>
@@ -282,24 +282,26 @@
.then(res => {
console.log('详情数据返回:', res)
+ const data = res.data || res
+
// 处理 purpose
let purposeArray = []
- if (res.purpose) {
- if (typeof res.purpose === 'string') {
- purposeArray = res.purpose.split(',').map(item => Number(item.trim())).filter(num => !isNaN(num))
- } else if (Array.isArray(res.purpose)) {
- purposeArray = res.purpose
+ 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 = res.list && res.list.length > 0 ? res.list : this.initialTableData.map(item => ({ ...item }))
+ const tableList = data.list && data.list.length > 0 ? data.list : this.initialTableData.map(item => ({ ...item }))
// 更新数据
this.detail = {
- ...res,
- handleSignature: res.handleSignature || '',
- purpose: purposeArray || []
+ ...data,
+ handleSignature: data.handleSignature || '',
+ purpose: purposeArray
}
this.tableData = tableList
@@ -344,15 +346,18 @@
handleSave() {
this.$refs.form.validate((valid) => {
if (valid) {
- this.detail.list = this.tableData || []
- this.detail.purpose = this.detail.purpose.join(',')
- this.detail.isDraft = 0
- 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.cacheForm = null
this.cacheFormtableData = null
- this.$router.back()
+ this.$closeCurrentView('/strain/validation/primitive-cell')
} else {
this.$message.error(res.msg || '保存失败')
}
@@ -367,15 +372,18 @@
handleDraft() {
this.$refs.form.validate((valid) => {
if (valid) {
- this.detail.list = this.tableData || []
- this.detail.purpose = this.detail.purpose.join(',')
+ 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.cacheForm = null
this.cacheFormtableData = null
- this.$router.back()
+ this.$closeCurrentView('/strain/validation/primitive-cell')
} else {
this.$message.error(res.msg || '存稿失败')
}
diff --git a/culture/src/views/strain-library/validation/primitive-cell/index.vue b/culture/src/views/strain-library/validation/primitive-cell/index.vue
index 889a7a6..87c4cec 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/index.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/index.vue
@@ -205,6 +205,10 @@
// Implement batch add logic
},
handleEdit(row) {
+ if (Number(this.roleType) === 1) {
+ this.$router.push({ path: "/strain/validation/confirm-detail", query: { id: row.id, mode: 'edit' } });
+ return;
+ }
this.$router.push({
path: "/strain/validation/edit-primitive-cell",
query: {
diff --git a/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue b/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
index 2278ddb..4d3ac05 100644
--- a/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
+++ b/culture/src/views/strain-library/validation/primitive-cell/primitive-cell-detail-dialog.vue
@@ -1,64 +1,58 @@
<template>
<el-dialog
:visible.sync="visible"
- title="祖代菌种库验证资料详情"
- width="650px"
+ width="88%"
+ top="6vh"
+ custom-class="validation-simple-detail-dialog"
:close-on-click-modal="false"
@close="handleClose"
>
- <el-form label-width="120px" label-position="top" class="detail-form">
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="项目组名称">
- <el-input v-model="detail.projectName" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种来源">
- <el-input type="textarea" rows="6" v-model="detail.strainSource" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种编号">
- <el-input v-model="detail.identifyingStrainCode" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="菌种名称">
- <el-input v-model="detail.identifyingStrainName" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="验证实验编号">
- <el-input v-model="detail.validationExperimentCode" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="实验时间">
- <el-input v-model="detail.experimentTime" disabled placeholder="请输入" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="24">
- <el-col :span="12">
- <el-form-item label="菌种实验员签字">
- <div class="signature-area">
- <el-image v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)" :preview-src-list="[getFullUrl(detail.handleSignature)]" alt="签字" />
- <span v-else class="waiting-text">暂无签名</span>
- </div>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="签字时间">
- <el-input v-model="detail.handleTime" disabled />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
+ <div class="validation-overview">
+ <div class="stacked-field">
+ <span class="field-label">菌种来源</span>
+ <div class="value-box multiline-box source-box">{{ detail.strainSource || '-' }}</div>
+ </div>
+ <div class="project-header">
+ <span class="project-label">项目组:</span>
+ <span class="project-name">{{ detail.projectName || '-' }}</span>
+ </div>
+ <div class="detail-panel">
+ <div class="single-field-row">
+ <div class="inline-field code-field">
+ <span class="field-label">鉴别菌株编号</span>
+ <div class="value-box compact-box">{{ detail.identifyingStrainCode || '-' }}</div>
+ </div>
+ </div>
+ <div class="stacked-field name-field">
+ <span class="field-label">鉴别菌株名称</span>
+ <div class="value-box multiline-box">{{ detail.identifyingStrainName || '-' }}</div>
+ </div>
+ <div class="paired-fields">
+ <div class="inline-field">
+ <span class="field-label">验证实验编号</span>
+ <div class="value-box compact-box">{{ detail.validationExperimentCode || '-' }}</div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">实验时间</span>
+ <div class="value-box compact-box">{{ detail.experimentTime || '-' }}</div>
+ </div>
+ </div>
+ <div class="paired-fields signature-row">
+ <div class="inline-field">
+ <span class="field-label">菌种实验员签字</span>
+ <div class="signature-area">
+ <el-image v-if="detail.handleSignature" :src="getFullUrl(detail.handleSignature)"
+ :preview-src-list="[getFullUrl(detail.handleSignature)]" fit="contain" alt="菌种实验员签字" />
+ <span v-else class="waiting-text">暂无签名</span>
+ </div>
+ </div>
+ <div class="inline-field time-field">
+ <span class="field-label">签字时间</span>
+ <div class="value-box compact-box">{{ detail.handleTime || '-' }}</div>
+ </div>
+ </div>
+ </div>
+ </div>
</el-dialog>
</template>
@@ -93,27 +87,174 @@
}
</script>
-<style scoped>
-.detail-form {
- margin-top: 10px;
+<style scoped lang="less">
+::v-deep(.validation-simple-detail-dialog) {
+ max-width: 1320px;
+}
+
+.validation-overview {
+ color: #303133;
+ font-size: 15px;
+}
+.field-label {
+ display: block;
+ margin-bottom: 8px;
+ color: #606266;
+ font-weight: 600;
+ line-height: 22px;
+ white-space: nowrap;
+}
+.value-box {
+ min-width: 0;
+ padding: 8px 12px;
+ color: #303133;
+ background: #fff;
+ border: 1px solid #dcdfe6;
+ border-radius: 4px;
+ box-sizing: border-box;
+ line-height: 22px;
+ word-break: break-word;
+ overflow-wrap: anywhere;
+}
+.multiline-box {
+ min-height: 72px;
+ white-space: pre-wrap;
+}
+.source-box {
+ min-height: 68px;
+}
+.validation-overview > .stacked-field {
+ margin: 0 32px;
+}
+.validation-overview > .stacked-field .field-label {
+ padding-left: 112px;
+}
+.project-header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 52px;
+ padding: 10px 20px;
+ margin: 16px 0;
+ background: #f0f8fb;
+ border: 1px solid #b9dfe6;
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+.project-label {
+ margin: 0 8px 0 0;
+ color: #4d5965;
+ font-size: 16px;
+}
+.project-name {
+ color: #1890ff;
+ font-size: 18px;
+ font-weight: 700;
+ word-break: break-word;
+}
+.detail-panel {
+ padding: 24px 40px 28px;
+ background: #f3f4f6;
+ border: 1px solid #e2e6eb;
+ border-radius: 6px;
+ box-sizing: border-box;
+}
+.single-field-row {
+ display: flex;
+ padding-left: 42px;
+}
+.inline-field {
+ display: grid;
+ grid-template-columns: 150px minmax(0, 1fr);
+ column-gap: 12px;
+ align-items: center;
+ min-width: 0;
+}
+.inline-field .field-label {
+ margin-bottom: 0;
+}
+.code-field {
+ width: 100%;
+ max-width: 416px;
+ grid-template-columns: 160px minmax(0, 1fr);
+}
+.compact-box {
+ display: flex;
+ align-items: center;
+ min-height: 40px;
+}
+.name-field {
+ margin-top: 22px;
+}
+.name-field .field-label {
+ padding-left: 42px;
+}
+.paired-fields {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+ gap: 72px;
+ margin-top: 22px;
+ padding: 0 32px;
+}
+.time-field {
+ grid-template-columns: 100px minmax(0, 1fr);
+}
+.paired-fields .compact-box,
+.paired-fields .signature-area {
+ width: 100%;
+ max-width: 265px;
+}
+.signature-row {
+ align-items: start;
+}
+.signature-row .signature-area {
+ max-width: 260px;
}
.signature-area {
- min-height: 120px;
- min-width: 240px;
- background: #f5f7fa;
+ width: 100%;
+ height: 72px;
+ background: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
+ overflow: hidden;
}
-.signature-area img {
- max-width: 100%;
- max-height: 100%;
- display: block;
+.signature-area .el-image {
+ width: 100%;
+ height: 100%;
}
.waiting-text {
color: #909399;
font-size: 14px;
}
+@media (max-width: 900px) {
+ .detail-panel {
+ padding: 20px;
+ }
+ .paired-fields {
+ grid-template-columns: 1fr;
+ gap: 16px;
+ padding: 0;
+ }
+}
+@media (max-width: 600px) {
+ .inline-field {
+ display: block;
+ }
+ .inline-field .field-label {
+ margin-bottom: 8px;
+ }
+ .single-field-row {
+ padding-left: 0;
+ }
+ .name-field .field-label,
+ .validation-overview > .stacked-field .field-label {
+ padding-left: 0;
+ }
+ .validation-overview > .stacked-field {
+ margin: 0;
+ }
+}
</style>
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOne/add.vue b/culture/src/views/strainReportLibrary/reportLibraryOne/add.vue
index c83f700..489bafb 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOne/add.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOne/add.vue
@@ -161,7 +161,7 @@
<script>
import AiEditor from '@/components/AiEditor'
import ChooseProject from '@/components/chooseProject/index.vue'
-import { customUploadRequest, getFullUrl ,downloadFileByUrl,getAllocateIp,isImageFile} from "@/utils/utils";
+import { customUploadRequest, getFullUrl, downloadFileByUrl, getAllocateIp, getUploadedFilePath, isImageFile, normalizeFileList } from "@/utils/utils";
import SelectMember from '@/components/SelectMember'
import { add, getDetail, update } from './service'
@@ -255,6 +255,9 @@
};
},
activated() {
+ if (!["/strainReportLibrary/add", "/strainReportLibrary/detail"].includes(this.$route.path)) {
+ return;
+ }
if (this.cacheData) {
// 恢复表单数据
this.form = JSON.parse(JSON.stringify(this.cacheData.form));
@@ -285,41 +288,6 @@
this.$nextTick(() => {
window.scrollTo(0, 0);
});
-
- if (this.$route.query.id && !this.cacheData) {
- getDetail(this.$route.query.id).then(res => {
- const data = res.data || res;
-
- this.form = {
- ...this.form,
- ...data,
- processData: []
- };
-
- let arr = data.evaluate.split(',')
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
- this.assessmentTable = this.assessmentTable.map((item, index) => {
- item.selectedScore = Number(arr[index])
- return item
- })
-
- this.selectedMember = [{
- nickName: data.experimentName,
- userId: data.experimentId
- }]
-
- this.projectData = data.projectTeam ?
- [{ ...data.projectTeam, staffName: data.projectTeam.staff || '' }] :
- [];
-
- console.log('qwe45645664', this.tableData);
-
-
-
- }).catch(err => {
- this.$message.error('获取详情失败');
- });
- }
},
methods: {
// 👇 添加这个方法
@@ -333,8 +301,8 @@
processData: []
};
- let arr = data.evaluate.split(',')
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
+ const arr = String(data.evaluate || '').split(',')
+ this.fileList = normalizeFileList(data.enclosureUrl)
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index])
return item
@@ -366,11 +334,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -390,11 +356,12 @@
customUploadRequest({
file,
onSuccess: (res) => {
- if (res.code === 200) {
+ const uploadedPath = getUploadedFilePath(res)
+ if (uploadedPath) {
const fileObj = {
id: new Date().getTime(),
reportId: this.$route.query.id ? this.$route.query.id : "",
- fileUrl: res.msg || res.data || "",
+ fileUrl: uploadedPath,
reportType: 2, // 报告类型
fileName: file.name,
fileSize: file.size,
@@ -403,17 +370,15 @@
// 添加到文件列表显示
this.fileList.push({
name: file.name,
- url: getFullUrl(fileObj.fileUrl),
+ url: fileObj.fileUrl,
uid: fileObj.id,
});
- // 添加到表单数据
- this.form.feasibilityReportFiles.push(fileObj);
this.$message.success("文件上传成功");
onSuccess(res);
}else {
- this.$message.error("文件上传失败");
- onError(res.msg);
+ this.$message.error(res && res.msg ? res.msg : "上传接口未返回文件地址");
+ onError(new Error('missing uploaded file path'));
}
},
onError: (err) => {
@@ -427,7 +392,6 @@
const index = this.fileList.findIndex((item) => item.name === file.name);
if (index !== -1) {
this.fileList.splice(index, 1);
- this.form.feasibilityReportFiles.splice(index, 1);
}
},
addData() {
@@ -460,7 +424,7 @@
isDraft: 0,
projectId: this.projectData[0].id,
experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -475,7 +439,7 @@
if (res.code == 200) {
this.$message.success('编辑成功');
this.cacheData = null;
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryOne')
} else {
this.$message.error(res.msg || '编辑失败');
this.submitLoading = false;
@@ -489,7 +453,7 @@
if (res.code == 200) {
this.$message.success('发送成功');
this.cacheData = null;
- this.$router.push('/strainReportLibrary/reportLibraryOne');
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryOne');
} else {
this.$message.error(res.msg || '发送失败');
this.submitLoading = false;
@@ -511,7 +475,7 @@
isDraft: 1,
projectId: this.projectData[0].id,
experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -525,7 +489,8 @@
this.submitLoading = false;
if (res.code == 200) {
this.$message.success('编辑成功');
- this.$router.back()
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryOne')
} else {
this.$message.error(res.msg || '编辑失败');
this.submitLoading = false;
@@ -537,7 +502,8 @@
this.submitLoading = false;
if (res.code == 200) {
this.$message.success('保存成功');
- this.$router.push('/strainReportLibrary/reportLibraryOne');
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryOne');
} else {
this.$message.error(res.msg || '保存失败');
this.submitLoading = false;
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue
index 19c8c3a..aafe84d 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOne/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
- <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
+ <el-dialog :title="dialogTitle" :visible.sync="visible" width="94%" @open="open" :close-on-click-modal="false"
@close="handleClose">
- <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
+ <div class="approval-dialog" :style="{ height: obj?.isDetail ? '68vh' : '60vh' }">
<!-- 左侧审批内容 -->
<div class="approval-content">
<Card class="approval-content-card">
@@ -64,10 +64,8 @@
</div>
</div>
<el-form-item prop="name" style="margin-top: 38px">
- <el-upload action="#" :file-list="fileList" :disabled="roleType == 2" list-type="text"
- :before-upload="beforeUpload" :on-preview="handlePreview">
- <el-button size="small" type="primary" v-if="roleType != 2">点击上传</el-button>
- <div slot="tip" class="el-upload__tip">支持 Word、Excel 和所有图片格式,禁止 PPT、PDF、CAJ</div>
+ <el-upload action="#" :file-list="fileList" disabled list-type="text" :on-preview="handlePreview">
+ <span v-if="!fileList.length">暂无附件</span>
</el-upload>
</el-form-item>
@@ -160,7 +158,7 @@
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
-import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils';
+import { getAllocateIp, getFullUrl, downloadFileByUrl, isImageFile, normalizeFileList } from '@/utils/utils';
export default {
@@ -276,9 +274,9 @@
processData: []
};
- let arr = data.evaluate.split(',')
+ const arr = String(data.evaluate || '').split(',')
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
+ this.fileList = normalizeFileList(data.enclosureUrl)
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index])
@@ -433,11 +431,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOne/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOne/index.vue
index bae629c..726e5f5 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOne/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOne/index.vue
@@ -77,9 +77,9 @@
<el-button type="text" style="margin-right: 10px;" v-if="row.status == 2 && [1, 2].includes(roleType)"
@click="handleEvaluate(row)">评定</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="row.status != 1 || roleType == 3" @click="viewDetail(row)">详情</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && (row.status == 4 || isDraft)"
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && (row.status == 4 || isDraft))"
@click="handleDetail(row)">编辑</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && isDraft" @click="handleDelete(row)">删除</el-button>
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && isDraft)" @click="handleDelete(row)">删除</el-button>
<el-button type="text" v-if="row.status == 1 && roleType == 3&&!isDraft"
@click="handleRevoke(row)">撤销审批</el-button>
</template>
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneFour/add.vue b/culture/src/views/strainReportLibrary/reportLibraryOneFour/add.vue
index 27a4cb9..8bf64b0 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneFour/add.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneFour/add.vue
@@ -160,7 +160,7 @@
import { Card } from 'element-ui';
import AiEditor from '@/components/AiEditor'
import ChooseProject from '@/components/chooseProject/index.vue'
-import { customUploadRequest, getFullUrl ,downloadFileByUrl,getAllocateIp,isImageFile} from "@/utils/utils";
+import { customUploadRequest, getFullUrl, downloadFileByUrl, getAllocateIp, getUploadedFilePath, isImageFile, normalizeFileList } from "@/utils/utils";
import SelectMember from '@/components/SelectMember'
import { add, getDetail, update } from './service'
@@ -246,6 +246,9 @@
},
// 👇 添加这两个钩子
activated() {
+ if (!["/strainReportLibrary/addFour", "/strainReportLibrary/detailFour"].includes(this.$route.path)) {
+ return;
+ }
if (this.cacheData) {
// 恢复表单数据
this.form = JSON.parse(JSON.stringify(this.cacheData.form));
@@ -288,44 +291,6 @@
this.$nextTick(() => {
window.scrollTo(0, 0);
});
- if (this.$route.query.id && !this.cacheData) {
- getDetail(this.$route.query.id).then(res => {
- const data = res.data || res;
- this.form = {
- ...this.form,
- ...data,
- processData: []
- };
-
- // 添加空值判断
- let arr = [];
- if (data.evaluate) {
- arr = data.evaluate.split(',');
- } else {
- // 如果 evaluate 为空,使用默认值(根据你的 assessmentTable 长度)
- arr = this.assessmentTable.map(() => 0);
- }
-
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
- this.assessmentTable = this.assessmentTable.map((item, index) => {
- item.selectedScore = Number(arr[index] ?? 0);
- return item
- })
-
- this.selectedMember = [{
- nickName: data.experimentName,
- userId: data.experimentId
- }]
-
- this.projectData = data.projectTeam ?
- [{ ...data.projectTeam, staffName: data.projectTeam.staff || '' }] :
- [];
-
-
- }).catch(err => {
- this.$message.error('获取详情失败');
- });
- }
},
methods: {
// 👇 添加这个方法
@@ -345,7 +310,7 @@
arr = this.assessmentTable.map(() => 0);
}
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : []);
+ this.fileList = normalizeFileList(data.enclosureUrl);
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index] ?? 0);
@@ -378,11 +343,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -429,11 +392,12 @@
customUploadRequest({
file,
onSuccess: (res) => {
- if (res.code === 200) {
+ const uploadedPath = getUploadedFilePath(res)
+ if (uploadedPath) {
const fileObj = {
id: new Date().getTime(),
reportId: this.$route.query.id ? this.$route.query.id : "",
- fileUrl: res.msg || res.data || "",
+ fileUrl: uploadedPath,
reportType: 2, // 报告类型
fileName: file.name,
fileSize: file.size,
@@ -442,14 +406,15 @@
// 添加到文件列表显示
this.fileList.push({
name: file.name,
- url: getFullUrl(fileObj.fileUrl),
+ url: fileObj.fileUrl,
uid: fileObj.id,
});
- // 添加到表单数据
- this.form.feasibilityReportFiles.push(fileObj);
this.$message.success("文件上传成功");
onSuccess(res);
+ } else {
+ this.$message.error(res && res.msg ? res.msg : "上传接口未返回文件地址");
+ onError(new Error('missing uploaded file path'));
}
},
onError: (err) => {
@@ -463,7 +428,6 @@
const index = this.fileList.findIndex((item) => item.name === file.name);
if (index !== -1) {
this.fileList.splice(index, 1);
- this.form.feasibilityReportFiles.splice(index, 1);
}
},
async addData() {
@@ -496,7 +460,7 @@
isDraft: 0,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -511,7 +475,7 @@
if (res.code == 200) {
this.$message.success('编辑成功');
this.cacheData = null; // 👈 添加这一行
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryFour')
}
}).catch(() => {
this.submitLoading = false;
@@ -523,7 +487,7 @@
if (res.code == 200) {
this.$message.success('发送成功');
this.cacheData = null; // 👈 添加这一行
- this.$router.push('/strainReportLibrary/reportLibraryFour');
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryFour');
}
}).catch(() => {
this.submitLoading = false;
@@ -548,7 +512,7 @@
isDraft: 1,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -563,7 +527,7 @@
if (res.code == 200) {
this.$message.success('编辑成功');
this.cacheData = null; // 👈 添加这一行
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryFour')
}
}).catch(() => {
this.submitLoading = false;
@@ -575,7 +539,7 @@
if (res.code == 200) {
this.$message.success('保存成功');
this.cacheData = null; // 👈 添加这一行
- this.$router.push('/strainReportLibrary/reportLibraryFour');
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryFour');
}
}).catch(() => {
this.draftLoading = false;
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneFour/components/approval/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneFour/components/approval/index.vue
index 87c46e8..e8b562a 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneFour/components/approval/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneFour/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
- <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
+ <el-dialog :title="dialogTitle" :visible.sync="visible" width="94%" @open="open" :close-on-click-modal="false"
@close="handleClose">
- <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
+ <div class="approval-dialog" :style="{ height: obj?.isDetail ? '68vh' : '60vh' }">
<!-- 左侧审批内容 -->
<div class="approval-content">
<Card class="approval-content-card">
@@ -58,9 +58,8 @@
</el-form-item>
<el-form-item prop="name" style="margin-top: 38px">
- <el-upload action="#" :file-list="fileList" disabled list-type="text" :before-upload="beforeUpload" :on-preview="handlePreview">
- <el-button size="small" type="primary" v-if="roleType != 2">点击上传</el-button>
- <div slot="tip" class="el-upload__tip">支持 Word、Excel 和所有图片格式,禁止 PPT、PDF、CAJ</div>
+ <el-upload action="#" :file-list="fileList" disabled list-type="text" :on-preview="handlePreview">
+ <span v-if="!fileList.length">暂无附件</span>
</el-upload>
</el-form-item>
@@ -144,7 +143,7 @@
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">{{ obj.isDetail ? '关闭' : '取 消' }}</el-button>
- <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
+ <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">审核</el-button>
</div>
</el-dialog>
</template>
@@ -153,7 +152,7 @@
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
-import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils';
+import { getAllocateIp, getFullUrl, downloadFileByUrl, isImageFile, normalizeFileList } from '@/utils/utils';
export default {
@@ -292,11 +291,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -319,7 +316,7 @@
};
let arr = (data.evaluate || '').split(',')
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
+ this.fileList = normalizeFileList(data.enclosureUrl)
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index])
return item
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue
index 6d0a6df..fa9ac06 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneFour/index.vue
@@ -76,9 +76,9 @@
<el-button type="text" style="margin-right: 10px;" v-if="row.status == 2 && [1, 2].includes(roleType)"
@click="handleEvaluate(row)">评定</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="row.status != 1 || roleType == 3" @click="viewDetail(row)">详情</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && row.status == 4 || isDraft"
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && (row.status == 4 || isDraft))"
@click="handleDetail(row)">编辑</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && isDraft" @click="handleDelete(row)">删除</el-button>
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && isDraft)" @click="handleDelete(row)">删除</el-button>
<el-button type="text" v-if="row.status == 1 && roleType == 3&&!isDraft"
@click="handleRevoke(row)">撤销审批</el-button>
</template>
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue
index 1596c64..ef4830c 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/add.vue
@@ -159,7 +159,7 @@
<script>
import AiEditor from '@/components/AiEditor'
import ChooseProject from '@/components/chooseProject/index.vue'
-import {customUploadRequest, downloadFileByUrl, getAllocateIp, getFullUrl, isImageFile} from "@/utils/utils";
+import { customUploadRequest, downloadFileByUrl, getAllocateIp, getFullUrl, getUploadedFilePath, isImageFile, normalizeFileList } from "@/utils/utils";
import SelectMember from '@/components/SelectMember'
import {add, getDetail, update} from './service'
@@ -244,6 +244,9 @@
},
// 👇 添加这两个钩子
activated() {
+ if (!["/strainReportLibrary/addTwo", "/strainReportLibrary/detailTwo"].includes(this.$route.path)) {
+ return;
+ }
if (this.cacheData) {
// 恢复表单数据
this.form = JSON.parse(JSON.stringify(this.cacheData.form));
@@ -285,45 +288,6 @@
this.$nextTick(() => {
window.scrollTo(0, 0);
});
- if (this.$route.query.id && !this.cacheData) {
- getDetail(this.$route.query.id).then(res => {
- const data = res.data || res;
- this.form = {
- ...this.form,
- ...data,
- processData: []
- };
-
- // 添加空值判断
- let arr = [];
- if (data.evaluate) {
- arr = data.evaluate.split(',');
- } else {
- // 如果 evaluate 为空,使用默认值(根据你的 assessmentTable 长度)
- arr = this.assessmentTable.map(() => 0);
- }
-
- this.selectedMember = [{
- nickName: data.experimentName,
- userId: data.experimentId
- }]
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
-
- this.assessmentTable = this.assessmentTable.map((item, index) => {
- item.selectedScore = Number(arr[index] ?? 0);
- return item;
- });
-
- this.projectData = data.projectTeam ?
- [{ ...data.projectTeam, staffName: data.projectTeam.staff || '' }] :
- [];
-
-
- }).catch(err => {
- console.log(err)
- this.$message.error('获取详情失败');
- });
- }
},
methods: {
// 👇 添加这个方法
@@ -348,7 +312,7 @@
nickName: data.experimentName,
userId: data.experimentId
}];
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : []);
+ this.fileList = normalizeFileList(data.enclosureUrl);
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index] ?? 0);
@@ -377,11 +341,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -427,11 +389,12 @@
customUploadRequest({
file,
onSuccess: (res) => {
- if (res.code === 200) {
+ const uploadedPath = getUploadedFilePath(res)
+ if (uploadedPath) {
const fileObj = {
id: new Date().getTime(),
reportId: this.$route.query.id ? this.$route.query.id : "",
- fileUrl: res.msg || res.data || "",
+ fileUrl: uploadedPath,
reportType: 2, // 报告类型
fileName: file.name,
fileSize: file.size,
@@ -440,14 +403,15 @@
// 添加到文件列表显示
this.fileList.push({
name: file.name,
- url: getFullUrl(fileObj.fileUrl),
+ url: fileObj.fileUrl,
uid: fileObj.id,
});
- // 添加到表单数据
- this.form.feasibilityReportFiles.push(fileObj);
this.$message.success("文件上传成功");
onSuccess(res);
+ } else {
+ this.$message.error(res && res.msg ? res.msg : "上传接口未返回文件地址");
+ onError(new Error('missing uploaded file path'));
}
},
onError: (err) => {
@@ -461,7 +425,6 @@
const index = this.fileList.findIndex((item) => item.name === file.name);
if (index !== -1) {
this.fileList.splice(index, 1);
- this.form.feasibilityReportFiles.splice(index, 1);
}
},
@@ -497,7 +460,7 @@
isDraft: 0,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -512,8 +475,8 @@
this.loading = false;
if (res.code == 200) {
this.$message.success('编辑成功');
- this.$router.back()
- this.cacheData = null;
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryTwo')
} else {
this.$message.error(res.message || '编辑失败');
}
@@ -528,8 +491,8 @@
this.loading = false;
if (res.code == 200) {
this.$message.success('发送成功');
- this.$router.back()
- this.cacheData = null;
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryTwo')
} else {
this.$message.error(res.message || '发送失败');
}
@@ -557,7 +520,7 @@
isDraft: 1,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -571,7 +534,8 @@
this.loading = false;
if (res.code == 200) {
this.$message.success('编辑成功');
- this.$router.back()
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryTwo')
} else {
this.$message.error(res.message || '编辑失败');
}
@@ -586,7 +550,8 @@
this.loading = false;
if (res.code == 200) {
this.$message.success('保存成功');
- this.$router.back()
+ this.cacheData = null;
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryTwo')
} else {
this.$message.error(res.message || '保存失败');
}
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue
index 50bacef..b6547e2 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
- <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
+ <el-dialog :title="dialogTitle" :visible.sync="visible" width="94%" @open="open" :close-on-click-modal="false"
@close="handleClose">
- <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
+ <div class="approval-dialog" :style="{ height: obj?.isDetail ? '68vh' : '60vh' }">
<!-- 左侧审批内容 -->
<div class="approval-content">
<Card class="approval-content-card">
@@ -64,9 +64,8 @@
</div>
</div>
<el-form-item prop="name" style="margin-top: 38px">
- <el-upload action="#" :file-list="fileList" :disabled="roleType == 2" :before-upload="beforeUpload" :on-preview="handlePreview">
- <el-button size="small" type="primary" v-if="roleType != 2">点击上传</el-button>
- <div slot="tip" class="el-upload__tip">支持 Word、Excel 和所有图片格式,禁止 PPT、PDF、CAJ</div>
+ <el-upload action="#" :file-list="fileList" disabled list-type="text" :on-preview="handlePreview">
+ <span v-if="!fileList.length">暂无附件</span>
</el-upload>
</el-form-item>
@@ -159,7 +158,7 @@
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
-import { getAllocateIp, downloadFileByUrl, isImageFile } from '@/utils/utils';
+import { getAllocateIp, getFullUrl, downloadFileByUrl, isImageFile, normalizeFileList } from '@/utils/utils';
export default {
@@ -297,11 +296,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -324,7 +321,7 @@
};
let arr = (data.evaluate || '').split(',')
- this.fileList = data.enclosureUrl ? JSON.parse(data.enclosureUrl) : []
+ this.fileList = normalizeFileList(data.enclosureUrl)
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index])
return item
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue
index a788eba..ccf74d0 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneTWO/index.vue
@@ -76,9 +76,9 @@
<el-button type="text" style="margin-right: 10px;" v-if="row.status == 2 && [1, 2].includes(roleType)"
@click="handleEvaluate(row)">评定</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="row.status != 1 || roleType == 3" @click="viewDetail(row)">详情</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && row.status == 4 || isDraft"
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && (row.status == 4 || isDraft))"
@click="handleDetail(row)">编辑</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && isDraft" @click="handleDelete(row)">删除</el-button>
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && isDraft)" @click="handleDelete(row)">删除</el-button>
<el-button type="text" v-if="row.status == 1 && roleType == 3&&!isDraft"
@click="handleRevoke(row)">撤销审批</el-button>
</template>
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneThree/add.vue b/culture/src/views/strainReportLibrary/reportLibraryOneThree/add.vue
index 4e07538..6e53e37 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneThree/add.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneThree/add.vue
@@ -158,7 +158,7 @@
<script>
import AiEditor from '@/components/AiEditor'
import ChooseProject from '@/components/chooseProject/index.vue'
-import {customUploadRequest, downloadFileByUrl, getAllocateIp, getFullUrl, isImageFile} from "@/utils/utils";
+import { customUploadRequest, downloadFileByUrl, getAllocateIp, getFullUrl, getUploadedFilePath, isImageFile, normalizeFileList } from "@/utils/utils";
import SelectMember from '@/components/SelectMember'
import {add, getDetail, update} from './service'
@@ -244,6 +244,9 @@
},
// 👇 添加这两个钩子
activated() {
+ if (!["/strainReportLibrary/addThree", "/strainReportLibrary/detailThree"].includes(this.$route.path)) {
+ return;
+ }
if (this.cacheData) {
// 恢复表单数据
this.form = JSON.parse(JSON.stringify(this.cacheData.form));
@@ -285,43 +288,6 @@
this.$nextTick(() => {
window.scrollTo(0, 0);
});
- if (this.$route.query.id && !this.cacheData) {
- getDetail(this.$route.query.id).then(res => {
- const data = res.data || res;
- this.form = {
- ...this.form,
- ...data,
- processData: []
- };
-
- // 添加空值判断
- let arr = [];
- if (data.evaluate) {
- arr = data.evaluate.split(',');
- } else {
- // 如果 evaluate 为空,使用默认值(根据你的 assessmentTable 长度)
- arr = this.assessmentTable.map(() => 0);
- }
-
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
-
- this.assessmentTable = this.assessmentTable.map((item, index) => {
- item.selectedScore = Number(arr[index] ?? 0);
- return item
- })
- this.selectedMember = [{
- nickName: data.experimentName,
- userId: data.experimentId
- }]
- this.projectData = data.projectTeam ?
- [{ ...data.projectTeam, staffName: data.projectTeam.staff || '' }] :
- [];
-
-
- }).catch(err => {
- this.$message.error('获取详情失败');
- });
- }
},
methods: {
// 👇 添加这个方法
@@ -341,7 +307,7 @@
arr = this.assessmentTable.map(() => 0);
}
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : []);
+ this.fileList = normalizeFileList(data.enclosureUrl);
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index] ?? 0);
@@ -374,11 +340,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
@@ -424,11 +388,12 @@
customUploadRequest({
file,
onSuccess: (res) => {
- if (res.code === 200) {
+ const uploadedPath = getUploadedFilePath(res)
+ if (uploadedPath) {
const fileObj = {
id: new Date().getTime(),
reportId: this.$route.query.id ? this.$route.query.id : "",
- fileUrl: res.msg || res.data || "",
+ fileUrl: uploadedPath,
reportType: 2, // 报告类型
fileName: file.name,
fileSize: file.size,
@@ -437,14 +402,15 @@
// 添加到文件列表显示
this.fileList.push({
name: file.name,
- url: getFullUrl(fileObj.fileUrl),
+ url: fileObj.fileUrl,
uid: fileObj.id,
});
- // 添加到表单数据
- this.form.feasibilityReportFiles.push(fileObj);
this.$message.success("文件上传成功");
onSuccess(res);
+ } else {
+ this.$message.error(res && res.msg ? res.msg : "上传接口未返回文件地址");
+ onError(new Error('missing uploaded file path'));
}
},
onError: (err) => {
@@ -458,7 +424,6 @@
const index = this.fileList.findIndex((item) => item.name === file.name);
if (index !== -1) {
this.fileList.splice(index, 1);
- this.form.feasibilityReportFiles.splice(index, 1);
}
},
addData() {
@@ -492,7 +457,7 @@
isDraft: 0,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -508,7 +473,7 @@
if (res.code == 200) {
this.cacheData = null
this.$message.success('编辑成功');
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryThree')
} else {
this.$message.error(res.msg || '编辑失败');
}
@@ -526,7 +491,7 @@
if (res.code == 200) {
this.cacheData = null
this.$message.success('编辑成功');
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryThree')
this.cacheData = null;
}
}).catch(() => {
@@ -539,7 +504,7 @@
if (res.code == 200) {
this.cacheData = null
this.$message.success('发送成功');
- this.$router.push('/strainReportLibrary/reportLibraryThree');
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryThree');
this.cacheData = null;
} else {
this.$message.error(res.msg || '发送失败');
@@ -571,7 +536,7 @@
isDraft: 1,
projectId: this.projectData[0].id,
// experimentId: this.selectedMember[0].userId,
- enclosureUrl: this.fileList.length && JSON.stringify(this.fileList),
+ enclosureUrl: JSON.stringify(this.fileList),
// reportCode: this.form.reportCode,
reportContent: this.$refs.materialEditor.getContent(),
reportName: this.form.reportName,
@@ -585,7 +550,7 @@
if (res.code == 200) {
this.cacheData = null
this.$message.success('保存成功');
- this.$router.back()
+ this.$closeCurrentView('/strainReportLibrary/reportLibraryThree')
} else {
console.log('接口报错', res.msg);
this.$message.error(res.msg || '保存失败');
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneThree/components/approval/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneThree/components/approval/index.vue
index 694f448..61602e3 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneThree/components/approval/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneThree/components/approval/index.vue
@@ -1,7 +1,7 @@
<template>
- <el-dialog :title="dialogTitle" :visible.sync="visible" width="80%" @open="open" po :close-on-click-modal="false"
+ <el-dialog :title="dialogTitle" :visible.sync="visible" width="94%" @open="open" :close-on-click-modal="false"
@close="handleClose">
- <div class="approval-dialog" :style="{ height: obj?.isDetail ? '50vh' : '40vh' }">
+ <div class="approval-dialog" :style="{ height: obj?.isDetail ? '68vh' : '60vh' }">
<!-- 左侧审批内容 -->
<div class="approval-content">
<Card class="approval-content-card">
@@ -64,9 +64,8 @@
</div>
</div>
<el-form-item prop="name" style="margin-top: 38px">
- <el-upload action="#" :file-list="fileList" :disabled="roleType == 2" :before-upload="beforeUpload" :on-preview="handlePreview">
- <el-button size="small" type="primary" v-if="roleType != 2">点击上传</el-button>
- <div slot="tip" class="el-upload__tip">支持 Word、Excel 和所有图片格式,禁止 PPT、PDF、CAJ</div>
+ <el-upload action="#" :file-list="fileList" disabled list-type="text" :on-preview="handlePreview">
+ <span v-if="!fileList.length">暂无附件</span>
</el-upload>
</el-form-item>
@@ -150,7 +149,7 @@
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="handleClose">{{ obj.isDetail ? '关闭' : '取 消' }}</el-button>
- <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">通过</el-button>
+ <el-button type="primary" @click="handleApprove" v-if="!obj.isDetail">审核</el-button>
</div>
</el-dialog>
</template>
@@ -159,7 +158,7 @@
import ApprovalProcess from '@/components/approvalProcess'
import AiEditor from '@/components/AiEditor'
import { getDetail } from '../../service';
-import { customUploadRequest, getFullUrl, downloadFileByUrl, getAllocateIp, isImageFile } from "@/utils/utils";
+import { customUploadRequest, getFullUrl, downloadFileByUrl, getAllocateIp, isImageFile, normalizeFileList } from "@/utils/utils";
export default {
name: "ApprovalDialog",
@@ -272,7 +271,7 @@
};
let arr = (data.evaluate || '').split(',')
- this.fileList = (data.enclosureUrl ? JSON.parse(data.enclosureUrl) : [])
+ this.fileList = normalizeFileList(data.enclosureUrl)
this.assessmentTable = this.assessmentTable.map((item, index) => {
item.selectedScore = Number(arr[index])
return item
@@ -397,11 +396,9 @@
// 图片文件:使用 window.open 预览
if (file.url && file.url.startsWith('http')) {
console.log('图片链接', file.url)
- window.open(file.url, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
} else {
- let newUrl = getAllocateIp() + file.url;
- console.log('图片链接', newUrl)
- window.open(newUrl, '_blank');
+ window.open(getFullUrl(file.url), '_blank');
}
} else {
// 非图片文件:使用下载方式
diff --git a/culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue b/culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue
index 68e15d5..7bf0381 100644
--- a/culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue
+++ b/culture/src/views/strainReportLibrary/reportLibraryOneThree/index.vue
@@ -76,9 +76,9 @@
<el-button type="text" style="margin-right: 10px;" v-if="row.status == 2 && [1, 2].includes(roleType)"
@click="handleEvaluate(row)">评定</el-button>
<el-button type="text" style="margin-right: 10px;" v-if="row.status != 1 || roleType == 3" @click="viewDetail(row)">详情</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && row.status == 4 || isDraft"
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && (row.status == 4 || isDraft))"
@click="handleDetail(row)">编辑</el-button>
- <el-button type="text" style="margin-right: 10px;" v-if="roleType == 3 && isDraft" @click="handleDelete(row)">删除</el-button>
+ <el-button type="text" style="margin-right: 10px;" v-if="roleType == 1 || (roleType == 3 && isDraft)" @click="handleDelete(row)">删除</el-button>
<el-button type="text" v-if="row.status == 1 && roleType == 3&&!isDraft"
@click="handleRevoke(row)">撤销审批</el-button>
</template>
diff --git a/culture/src/views/system/role/add.vue b/culture/src/views/system/role/add.vue
index 2bbc2d2..3f34001 100644
--- a/culture/src/views/system/role/add.vue
+++ b/culture/src/views/system/role/add.vue
@@ -83,7 +83,7 @@
</div>
<div class="btn_box">
- <el-button @click="$router.go(-1)">返回</el-button>
+ <el-button @click="$closeCurrentView('/system/role')">返回</el-button>
<el-button type="primary" @click="onSubmit">保存</el-button>
</div>
</Card>
@@ -158,7 +158,7 @@
obj.roleId = this.$route.query.roleId
edit(obj).then(() => {
this.msgsuccess('保存成功')
- this.$router.go(-1)
+ this.$closeCurrentView('/system/role')
})
} else {
add(obj).then(() => {
@@ -168,7 +168,7 @@
remark: "",
}
this.menu = []
- this.$router.go(-1)
+ this.$closeCurrentView('/system/role')
})
}
}
@@ -400,4 +400,4 @@
font-family: 'Source Han Sans CN Bold Bold';
}
}
-</style>
\ No newline at end of file
+</style>
diff --git a/culture/src/views/system/role/edit.vue b/culture/src/views/system/role/edit.vue
index 0f6351c..dcfbff5 100644
--- a/culture/src/views/system/role/edit.vue
+++ b/culture/src/views/system/role/edit.vue
@@ -83,7 +83,7 @@
</div>
<div class="btn_box">
- <el-button @click="$router.go(-1)">返回</el-button>
+ <el-button @click="$closeCurrentView('/system/role')">返回</el-button>
<el-button type="primary" @click="onSubmit">保存</el-button>
</div>
</Card>
@@ -158,12 +158,12 @@
obj.roleId = this.$route.query.roleId
edit(obj).then(() => {
this.msgsuccess('保存成功')
- this.$router.go(-1)
+ this.$closeCurrentView('/system/role')
})
} else {
add(obj).then(() => {
this.msgsuccess('保存成功')
- this.$router.go(-1)
+ this.$closeCurrentView('/system/role')
})
}
}
@@ -395,4 +395,4 @@
font-family: 'Source Han Sans CN Bold Bold';
}
}
-</style>
\ No newline at end of file
+</style>
diff --git a/culture/vue.config.js b/culture/vue.config.js
index 0ba7571..26abac1 100644
--- a/culture/vue.config.js
+++ b/culture/vue.config.js
@@ -12,7 +12,7 @@
"/api": {
// 设置以什么前缀开头的请求用来代理
// target: "http://221.182.45.100:8081", //要访问的跨域的域名
- target: "http://192.168.110.64:8082",
+ target: "http://localhost:8082",
secure: false, // 使用的是http协议则设置为false,https协议则设置为true
changeOrigin: true, //开启代理
pathRewrite: {
@@ -22,7 +22,7 @@
"/": {
// 设置以什么前缀开头的请求用来代理
// target: "http://221.182.45.100:8081", //要访问的跨域的域名
- target: "http://192.168.110.64:8082",
+ target: "http://localhost:8082",
secure: false, // 使用的是http协议则设置为false,https协议则设置为true
changeOrigin: true, //开启代理
pathRewrite: {
@@ -32,7 +32,7 @@
"/open": {
// 设置以什么前缀开头的请求用来代理
// target: "http://221.182.45.100:8081", //要访问的跨域的域名
- target: "http://192.168.110.64:8082",
+ target: "http://localhost:8082",
secure: false, // 使用的是http协议则设置为false,https协议则设置为true
changeOrigin: true, //开启代理
pathRewrite: {
diff --git a/laboratory/LICENSE b/laboratory/LICENSE
new file mode 100644
index 0000000..8564f29
--- /dev/null
+++ b/laboratory/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 RuoYi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/laboratory/src/utils/request.js b/laboratory/src/utils/request.js
index 44b806c..cf6a4ae 100644
--- a/laboratory/src/utils/request.js
+++ b/laboratory/src/utils/request.js
@@ -14,9 +14,6 @@
config => {
config['headers']['Authorization'] = `${sessionStorage.getItem('token')}`
- // 🔥 关键修改:设置请求头的字符集为UTF-8
- config['headers']['Content-Type'] = 'application/json;charset=UTF-8'
-
// 判断是否需要加密(只对/api开头的请求进行加密)
const needEncrypt = config.url.startsWith('/api');
diff --git a/laboratory/src/views/chemistQa/projectTesting/addDetectionReport.vue b/laboratory/src/views/chemistQa/projectTesting/addDetectionReport.vue
index 46cb5b7..1ba7055 100644
--- a/laboratory/src/views/chemistQa/projectTesting/addDetectionReport.vue
+++ b/laboratory/src/views/chemistQa/projectTesting/addDetectionReport.vue
@@ -1,4 +1,4 @@
-<template>
+<template>
<div class="add-container" :loading="loading">
<Card v-loading="loading">
<div class="header-title" style="width: 100%;">
@@ -126,7 +126,9 @@
{ required: true, message: '请选择检测项', trigger: 'change' }
]
},
- queryForm: {}
+ queryForm: {},
+ loadedItemId: '', // 当前已加载记录关联的检测项id,用于keep-alive重新进入时判断是否变化
+ loadedReportId: '', // 当前已加载记录的id,用于keep-alive重新进入时判断是否变化
}
},
@@ -136,36 +138,62 @@
this.form.commitPersonId = JSON.parse(sessionStorage.getItem('userInfo')).userId
this.form.developDate = new Date().toISOString().split('T')[0];
- // this.form.itemId = this.$route.query.itemId
- if (this.$route.query.itemId) {
- getDetail(this.$route.query.itemId).then(res => {
- if (res) {
- let item = {
- teamName: res.projectTeamVO.teamName,
- teamId: res.teamId,
- remark: res.remark,
-
- itemName: res.itemName,
- itemCode: res.itemCode,
- createBy: res.createBy,
- createTime: res.createTime
- }
- this.form.itemId = this.$route.query.itemId
- this.form.teamId = this.$route.query.teamId
-
- this.tableData = [{ ...item }]
- }
- })
- }
- if (this.$route.query.id) {
- this.getDetail()
- }
+ this.loadRouteData();
+ },
+ activated() {
+ // 页面被 keep-alive 缓存,再次打开其他记录时重新加载,避免显示上一次的旧数据
+ this.loadRouteData();
},
computed: {
...mapState(["tagList", "isFold"]),
},
methods: {
+ loadRouteData() {
+ const routeItemId = this.$route.query.itemId || '';
+ const routeId = this.$route.query.id || '';
+ if (routeItemId === this.loadedItemId && routeId === this.loadedReportId) {
+ return;
+ }
+ this.loadedItemId = routeItemId;
+ this.loadedReportId = routeId;
+ // 重置开发人、日期等默认信息
+ this.form.developPerson = JSON.parse(sessionStorage.getItem('userInfo')).nickName;
+ this.form.developPersonName = JSON.parse(sessionStorage.getItem('userInfo')).nickName;
+ this.form.commitPersonId = JSON.parse(sessionStorage.getItem('userInfo')).userId
+ this.form.developDate = new Date().toISOString().split('T')[0];
+ // 重置表单与文件,防止显示上一次记录的数据
+ this.form.itemId = '';
+ this.form.teamId = '';
+ this.tableData = [];
+ this.fileList = [];
+ this.form.qaReportFiles = [];
+
+ // 此段逻辑从 mounted() 中抽出,路由参数变化时重新加载
+ if (this.$route.query.itemId) {
+ getDetail(this.$route.query.itemId).then(res => {
+ if (res) {
+ let item = {
+ teamName: res.projectTeamVO.teamName,
+ teamId: res.teamId,
+ remark: res.remark,
+
+ itemName: res.itemName,
+ itemCode: res.itemCode,
+ createBy: res.createBy,
+ createTime: res.createTime
+ }
+ this.form.itemId = this.$route.query.itemId
+ this.form.teamId = this.$route.query.teamId
+
+ this.tableData = [{ ...item }]
+ }
+ })
+ }
+ if (this.$route.query.id) {
+ this.getDetail()
+ }
+ },
getDetail() {
getDetailInfo({ id: this.$route.query.id }).then(res => {
if (res) {
diff --git a/laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue b/laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue
index b5e4da4..8e9151b 100644
--- a/laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue
+++ b/laboratory/src/views/dataManagement/SampleDeliveryRecord/deliveryRecord.vue
@@ -259,6 +259,7 @@
showReceivedColumns: false,
schedulingData: [],
schedulingTotal: 0,
+ loadedId: null, // 当前已加载记录的id,用于 keep-alive 重新进入时判断是否需要重新拉取
form: {
sampleCode: "",
id: "",
@@ -296,9 +297,19 @@
const { id } = this.$route.query;
if (id) {
this.form.id = id;
+ this.loadedId = id;
this.getDetailData(id);
}
},
+ activated() {
+ const routeId = this.$route.query.id;
+ // 页面被 keep-alive 缓存,再次打开其他记录时重新加载,避免显示上一次的旧数据
+ if (routeId && routeId !== this.loadedId) {
+ this.loadedId = routeId;
+ this.form.id = routeId;
+ this.getDetailData(routeId);
+ }
+ },
methods: {
async getDetailData(id) {
try {
diff --git a/laboratory/src/views/dataManagement/confirmation-sheet/components/add.vue b/laboratory/src/views/dataManagement/confirmation-sheet/components/add.vue
index 41f094f..a343381 100644
--- a/laboratory/src/views/dataManagement/confirmation-sheet/components/add.vue
+++ b/laboratory/src/views/dataManagement/confirmation-sheet/components/add.vue
@@ -1,4 +1,4 @@
-<template>
+<template>
<Card>
<div class="header-title-left">
<img src="@/assets/public/headercard.png" />
@@ -99,6 +99,7 @@
},
selectedScheduling: null, // 添加选中的实验调度数据
currentTestItem: null, // 当前编辑的检测项
+ sheetId: '', // 当前已加载确认单的id,用于keep-alive重新进入时判断是否需要重新拉取
formData: {
id: '', // 确认单ID
dispatchId: '', // 实验调度ID
@@ -124,9 +125,19 @@
// 判断是否是编辑模式
const id = this.$route.query.id
if (id) {
+ this.sheetId = id
this.getDetailData(id)
}
},
+ activated() {
+ const routeId = this.$route.query.id
+ // 页面被 keep-alive 缓存,再次打开其他确认单时重新加载,避免显示上一次的旧数据
+ if (routeId && routeId !== this.sheetId) {
+ this.sheetId = routeId
+ this.getDetailData(routeId)
+ }
+ // 新增(无id)场景保留用户填写的数据
+ },
// computed: {
// ...mapState(["tagList", "isFold"]),
// },
diff --git a/laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue b/laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue
index 9e50e1d..d829286 100644
--- a/laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue
+++ b/laboratory/src/views/dataManagement/sampleRecordList/changeRecord.vue
@@ -175,6 +175,16 @@
this.getDetailData();
}
},
+ activated() {
+ const routeId = this.$route.query.id;
+ const routeType = this.$route.query.type || 'add';
+ // 页面被 keep-alive 缓存,再次打开其他记录时重新加载,避免显示上一次的旧数据
+ if (routeId && (routeId !== this.id || routeType !== this.type)) {
+ this.id = routeId;
+ this.type = routeType;
+ this.getDetailData();
+ }
+ },
computed: {
...mapState(["tagList", "isFold"]),
},
diff --git a/laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue b/laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue
index 43c7b5e..e554e0b 100644
--- a/laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue
+++ b/laboratory/src/views/dataManagement/sampleSubmissionList/submission.vue
@@ -290,6 +290,14 @@
this.getDetailData();
}
},
+ activated() {
+ const routeId = this.$route.query.id;
+ // 页面被 keep-alive 缓存,再次打开其他记录时重新加载,避免显示上一次的旧数据
+ if (routeId && routeId !== this.id) {
+ this.id = routeId;
+ this.getDetailData();
+ }
+ },
methods: {
getFullUrl,
async getDetailData() {
diff --git a/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue b/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
index 1c7e77f..57641bc 100644
--- a/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
+++ b/laboratory/src/views/dataManagement/schemeManagement/stop-experiment.vue
@@ -144,6 +144,15 @@
this.$message.error('参数错误,缺少实验ID')
}
},
+ activated() {
+ const routeId = this.$route.query.id
+ // 页面被 keep-alive 缓存,再次打开其他实验时重新加载,避免显示上一次的旧数据
+ if (routeId && routeId !== this.id) {
+ this.id = routeId
+ this.getExperimentDetail()
+ this.open()
+ }
+ },
computed: {
...mapState(["tagList", "isFold"]),
},
diff --git a/laboratory/src/views/dataManagement/suspendExperiment/components/editDialog.vue b/laboratory/src/views/dataManagement/suspendExperiment/components/editDialog.vue
new file mode 100644
index 0000000..d056bea
--- /dev/null
+++ b/laboratory/src/views/dataManagement/suspendExperiment/components/editDialog.vue
@@ -0,0 +1,130 @@
+<template>
+ <el-dialog
+ title="编辑中止申请"
+ :visible.sync="dialogVisible"
+ width="700px"
+ :close-on-click-modal="false"
+ @close="handleClose"
+ >
+ <el-form :model="form" :rules="rules" ref="formRef" label-width="140px">
+ <el-form-item label="项目课题方案名称" prop="projectName">
+ <el-input v-model="form.projectName" placeholder="请输入项目课题方案名称" disabled></el-input>
+ </el-form-item>
+<!-- <el-form-item label="实验编号" prop="experimentCode">-->
+<!-- <el-input v-model="form.experimentCode" placeholder="请输入实验编号" disabled></el-input>-->
+<!-- </el-form-item>-->
+ <el-form-item label="实验名称" prop="experimentName">
+ <el-input v-model="form.experimentName" placeholder="请输入实验名称" disabled></el-input>
+ </el-form-item>
+ <el-form-item label="中止原因" prop="stopReason">
+ <ai-editor
+ ref="purposeEditor"
+ :value="form.stopReason"
+ height="400px" placeholder="请输入文字"
+ ></ai-editor>
+ </el-form-item>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="handleClose">取 消</el-button>
+ <el-button type="primary" @click="handleSubmit" :loading="submitting">确 定</el-button>
+ </div>
+ </el-dialog>
+</template>
+
+<script>
+import AiEditor from "@/components/AiEditor/index.vue";
+import {update} from "@/views/dataManagement/schemeManagement/service";
+
+export default {
+ name: "EditDialog",
+ components: {AiEditor},
+ props: {
+ visible: {
+ type: Boolean,
+ default: false,
+ },
+ data: {
+ type: Object,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ dialogVisible: {
+ get() {
+ return this.visible;
+ },
+ set(val) {
+ this.$emit('update:visible', val);
+ }
+ },
+ },
+ watch: {
+ visible: {
+ handler(val) {
+ if (val && this.data) {
+ this.form = {
+ id: this.data.id || '',
+ projectName: this.data.projectName || '',
+ experimentCode: this.data.experimentCode || '',
+ experimentName: this.data.experimentName || '',
+ stopReason: this.data.stopReason || '',
+ };
+ }
+ },
+ immediate: true,
+ },
+ },
+ data() {
+ return {
+ form: {
+ id: '',
+ projectName: '',
+ experimentCode: '',
+ experimentName: '',
+ stopReason: '',
+ },
+ rules: {
+ stopReason: [
+ { required: true, message: '请输入中止原因', trigger: 'blur' }
+ ],
+ },
+ submitting: false,
+ };
+ },
+ methods: {
+ handleClose() {
+ this.$emit('update:visible', false);
+ this.$refs.formRef && this.$refs.formRef.resetFields();
+ },
+ async handleSubmit() {
+ console.log('this.form', this.form)
+ try {
+ await this.$refs.formRef.validate();
+ this.submitting = true;
+ await update(this.form);
+ this.$message.success('编辑成功');
+ this.$emit('success');
+ this.handleClose();
+ } catch (error) {
+ if (error !== 'cancel') {
+ this.$message.error('编辑失败');
+ }
+ } finally {
+ this.submitting = false;
+ }
+ },
+ },
+};
+</script>
+
+<style scoped lang="less">
+.dialog-footer {
+ display: flex;
+ justify-content: center;
+ gap: 20px;
+
+ .el-button {
+ width: 120px;
+ }
+}
+</style>
diff --git a/laboratory/vue.config.js b/laboratory/vue.config.js
index 9a6d28b..329008e 100644
--- a/laboratory/vue.config.js
+++ b/laboratory/vue.config.js
@@ -11,7 +11,7 @@
proxy: {
"/": {
// 设置以什么前缀开头的请求用来代理
- target: "http://192.168.110.188:11221", //要访问的跨域的域名
+ target: "http://192.168.1.2:11221", //要访问的跨域的域名
secure: false, // 使用的是http协议则设置为false,https协议则设置为true
changeOrigin: true, //开启代理
pathRewrite: {
@@ -19,7 +19,7 @@
},
},
"/": { // 设置以什么前缀开头的请求用来代理
- target: "http://192.168.110.188:11221", //要访问的跨域的域名
+ target: "http://192.168.1.2:11221", //要访问的跨域的域名
secure: false, // 使用的是http协议则设置为false,https协议则设置为true
changeOrigin: true, //开启代理
pathRewrite: {
--
Gitblit v1.7.1