From 92f2177d06cc67b2055bac0331a85780a086df0b Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期日, 20 九月 2026 19:51:47 +0800
Subject: [PATCH] feat(order): 优化订单管理功能并增加设备绑定支持 - 修改生产日期字段支持清除和显示默认值 - 在标准库中增加设备绑定功能,支持模板与设备关联 - 新增价格字段用于检验项目定价管理 - 增强模板绑定界面,支持多选和设备分配操作
---
src/views/standard/model/index.vue | 12 +++-
.env.development | 4
src/api/standard/standardLibrary.js | 9 +++
src/views/standard/standardLibrary/index.vue | 59 +++++++++++++++----
vue.config.js | 4
src/views/business/productOrder/components/addOrder.vue | 16 ++++-
src/main.js | 8 +-
src/views/business/productOrder/components/printDialog.vue | 4
src/views/business/productOrder/components/addView.vue | 2
src/components/Onlyoffice/onlyoffice.vue | 40 ++++++++++++-
src/views/business/costStatistics/components/viewInfoDia.vue | 9 +--
src/views/business/materialOrderComponents/materialOrder/printDialog.vue | 4
12 files changed, 129 insertions(+), 42 deletions(-)
diff --git a/.env.development b/.env.development
index 8215534..2a82886 100644
--- a/.env.development
+++ b/.env.development
@@ -7,8 +7,8 @@
# LIMS瀹為獙瀹ょ鐞嗙郴缁�/寮�鍙戠幆澧�
VUE_APP_BASE_API = '/dev-api'
-# 鏈湴鐜ip+绔彛
-VUE_APP_BASE_URL = 'http://127.0.0.1:8001/lims'
+# 鏂囦欢璁块棶涓庢櫘閫氭帴鍙g粺涓�璧版湰鍦板紑鍙戜唬鐞�
+VUE_APP_BASE_URL = '/dev-api'
# OnlyOffice 鏂囨。鏈嶅姟鍦板潃锛堥瑙� pdf 鐢紝娌℃湁 http:// 鍓嶇紑浼氬綋鎴愮浉瀵硅矾寰勶級
VUE_APP_ONLYOFFICE_API = 'http://192.168.21.53:9001'
diff --git a/src/api/standard/standardLibrary.js b/src/api/standard/standardLibrary.js
index 73d1965..a380534 100644
--- a/src/api/standard/standardLibrary.js
+++ b/src/api/standard/standardLibrary.js
@@ -140,6 +140,15 @@
return request({ url: "/standardTree/saveTemplateBindings", method: "post", data });
}
+// 鏌ヨ鍙粦瀹氬埌鍘熷璁板綍妯℃澘鐨勮澶�
+export function searchDevices(query) {
+ return request({
+ url: "/deviceScope/search",
+ method: "get",
+ params: query,
+ });
+}
+
// 鑾峰彇鏍囧噯鏂规硶鏋氫妇
export function selectStandardMethods(query) {
return request({
diff --git a/src/components/Onlyoffice/onlyoffice.vue b/src/components/Onlyoffice/onlyoffice.vue
index 1c1e261..cfafc9f 100644
--- a/src/components/Onlyoffice/onlyoffice.vue
+++ b/src/components/Onlyoffice/onlyoffice.vue
@@ -1,6 +1,15 @@
<!--onlyoffice 缂栬緫鍣�-->
<template>
- <div id="vabOnlyOffice"></div>
+ <div class="document-preview">
+ <iframe
+ v-if="isPdf"
+ :key="option.url"
+ :src="option.url"
+ class="native-pdf-preview"
+ title="PDF棰勮"
+ ></iframe>
+ <div v-else id="vabOnlyOffice"></div>
+ </div>
</template>
<script>
@@ -55,6 +64,11 @@
}
};
},
+ computed: {
+ isPdf() {
+ return this.isPdfFile(this.option);
+ }
+ },
created() {
if(this.options){
const option = this.options
@@ -106,10 +120,12 @@
},
async setEditor(option) {
this.destroyEditor();
- // 娌℃湁鏂囨。鍦板潃灏变笉鍒濆鍖栫紪杈戝櫒锛岄伩鍏嶈闂皻鏈姞杞界殑 DocsAPI
- if (!option || !option.url) {
+ // PDF 浣跨敤娴忚鍣ㄥ師鐢熼瑙堬紱鍏朵粬鏂囨。鎵嶅垵濮嬪寲 OnlyOffice銆�
+ if (!option || !option.url || this.isPdfFile(option)) {
return;
}
+ // 绛夊緟 v-else 涓殑 OnlyOffice 瀹瑰櫒瀹屾垚娓叉煋銆�
+ await this.$nextTick();
this.doctype = this.getFileType(option.fileType);
let config = {
document: {
@@ -162,6 +178,14 @@
return;
}
this.docEditor = new window.DocsAPI.DocEditor("vabOnlyOffice", config);
+ },
+ isPdfFile(option) {
+ if (!option) {
+ return false;
+ }
+ const fileType = String(option.fileType || "").toLowerCase();
+ const url = String(option.url || "").split(/[?#]/)[0].toLowerCase();
+ return fileType === "pdf" || url.endsWith(".pdf");
},
getFileType(fileType) {
let docType = "";
@@ -227,6 +251,16 @@
</script>
<style scoped>
+.document-preview,
+.native-pdf-preview,
+#vabOnlyOffice {
+ width: 100%;
+ height: 100%;
+}
+.native-pdf-preview {
+ display: block;
+ border: 0;
+}
html,
body {
height: 100%;
diff --git a/src/main.js b/src/main.js
index 255d118..8cc126f 100644
--- a/src/main.js
+++ b/src/main.js
@@ -65,10 +65,10 @@
Vue.prototype.HaveJson = (val) => {
return JSON.parse(JSON.stringify(val));
};
-// Vue.prototype.javaApi = process.env.NODE_ENV === "production"?"http://192.168.21.53:8001/lims":"http://127.0.0.1:8001/lims";
-// Vue.prototype.javaApi = process.env.VUE_APP_BASE_URL && process.env.NODE_ENV==='production'?process.env.VUE_APP_BASE_URL : "http://127.0.0.1:8001/lims";
-Vue.prototype.javaApi =
- process.env.VUE_APP_BASE_URL || process.env.VUE_APP_BASE_API;
+const apiBase = process.env.VUE_APP_BASE_URL || process.env.VUE_APP_BASE_API;
+Vue.prototype.javaApi = /^https?:\/\//i.test(apiBase)
+ ? apiBase.replace(/\/$/, "")
+ : window.location.origin + "/" + apiBase.replace(/^\/+|\/+$/g, "");
Vue.prototype.checkPermi = checkPermi;
Vue.prototype.uploadHeader = {
Authorization: "Bearer " + getToken(),
diff --git a/src/views/business/costStatistics/components/viewInfoDia.vue b/src/views/business/costStatistics/components/viewInfoDia.vue
index 19d5876..6ea5798 100644
--- a/src/views/business/costStatistics/components/viewInfoDia.vue
+++ b/src/views/business/costStatistics/components/viewInfoDia.vue
@@ -20,12 +20,9 @@
return {
tableData: [],
column: [
- { label: '濮旀墭缂栧彿', prop: 'entrustCode', width: 160 },
- {label: '妫�楠岄」鍒嗙被', prop: 'inspectionItemClass', width: 160},
- {label: '妫�楠岄」', prop: 'inspectionItem', width: 160},
- {label: '妫�楠屽瓙椤�', prop: 'inspectionItemSubclass', width: 160},
- { label: '鏀惰垂鏍囧噯(鍏�/娆�)', prop: 'rates' },
- { label: '鍒嗙粍绯绘暟', prop: 'manHourGroup' },
+ { label: '妫�楠岄」鐩�', prop: 'number', width: 160 },
+ { label: '妯℃澘鍚嶇О', prop: 'name', width: 200 },
+ { label: '浠锋牸(鍏�)', prop: 'price' },
],
viewInfoDia: false,
tableLoading: false,
diff --git a/src/views/business/materialOrderComponents/materialOrder/printDialog.vue b/src/views/business/materialOrderComponents/materialOrder/printDialog.vue
index fe99554..2d39bd1 100644
--- a/src/views/business/materialOrderComponents/materialOrder/printDialog.vue
+++ b/src/views/business/materialOrderComponents/materialOrder/printDialog.vue
@@ -30,7 +30,7 @@
<span class="info">{{ item.partDesc }}</span>
</div>
<div class="item">
- <span class="full-title">濮旀墭鏃ユ湡</span>:
+ <span class="full-title">閫佹牱鏃ユ湡</span>:
<span class="info">{{ item.sendTime }}</span>
</div>
<div class="item">
@@ -93,7 +93,7 @@
<span class="info4">{{ item.partDesc }}</span>
</div>
<div class="item">
- <span class="full-title2">濮旀墭鏃ユ湡</span>:
+ <span class="full-title2">閫佹牱鏃ユ湡</span>:
<span class="info">{{ item.sendTime }}</span>
</div>
<div class="item">
diff --git a/src/views/business/productOrder/components/addOrder.vue b/src/views/business/productOrder/components/addOrder.vue
index f70fb79..7376ef4 100644
--- a/src/views/business/productOrder/components/addOrder.vue
+++ b/src/views/business/productOrder/components/addOrder.vue
@@ -126,7 +126,7 @@
<el-col :span="6">
<el-form-item label="鐢熶骇鏃ユ湡">
<el-date-picker v-model="addObj.productionDate" type="date" value-format="yyyy-MM-dd"
- :disabled="active>1" size="small"/>
+ :disabled="active>1" clearable placeholder="涓嶉�夋嫨鏃舵姤鍛婃樉绀�/" size="small"/>
</el-form-item>
</el-col>
<el-col :span="6">
@@ -853,6 +853,8 @@
quarterItemId: '',
sampleView: '', // 鏍峰搧鍚嶇О锛堟姤鍛婂睍绀哄瓧娈碉級
sampleViewEn: '', // 鏍峰搧鍚嶇О鑻辨枃锛堟姤鍛婂睍绀哄瓧娈碉級
+ productionDate: null,
+ sampleDate: null,
},
addObjRules: { // 琛ㄥ崟鏍¢獙瑙勫垯
orderType: [
@@ -1567,9 +1569,15 @@
},
saveData(sampleList) {
this.saveLoad = true
+ const insOrder = {
+ ...this.addObj,
+ productionDate: this.addObj.productionDate === '/' || !this.addObj.productionDate
+ ? null : this.addObj.productionDate,
+ typeSource: -1,
+ }
if (this.tabIndex == 4 && this.active == 2) {
// 閫�鍥炲悗鎻愪氦
- updateInsOrder({insOrder: this.addObj, sampleProduct: sampleList}).then(res => {
+ updateInsOrder({insOrder, sampleProduct: sampleList}).then(res => {
this.saveLoad = false
this.$message.success('宸叉彁浜�')
this.bsm3Dia = false;
@@ -1579,7 +1587,7 @@
})
} else {
// 甯歌鎻愪氦
- const newJuOrder = {...this.addObj, typeSource: -1}
+ const newJuOrder = {...insOrder}
delete newJuOrder.temperature
delete newJuOrder.humidity
const payload = this.addObj.standardTreeId
@@ -1589,7 +1597,7 @@
sampleCode: this.sampleCode,
templateList: this.boundTemplateList.map((item, index) => ({templateId: item.templateId, sort: index}))
}
- : {insOrder: {...this.addObj, typeSource: -1}, sampleList: sampleList}
+ : {insOrder, sampleList: sampleList}
addInsOrder(payload).then(res => {
this.saveLoad = false
this.$message.success('宸叉彁浜�')
diff --git a/src/views/business/productOrder/components/addView.vue b/src/views/business/productOrder/components/addView.vue
index 1503f96..cd295a3 100644
--- a/src/views/business/productOrder/components/addView.vue
+++ b/src/views/business/productOrder/components/addView.vue
@@ -57,7 +57,7 @@
<el-descriptions-item label="鏍峰搧缂栧彿">{{ sampleCode || '-' }}</el-descriptions-item>
<el-descriptions-item label="鏍峰搧澶栬">{{ addObj.sampleStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="閫佹牱浜�">{{ addObj.prepareUser || '-' }}</el-descriptions-item>
- <el-descriptions-item label="鐢熶骇鏃ユ湡">{{ addObj.productionDate || '-' }}</el-descriptions-item>
+ <el-descriptions-item label="鐢熶骇鏃ユ湡">{{ addObj.productionDate || '/' }}</el-descriptions-item>
<el-descriptions-item label="鐢熶骇鎵瑰彿">{{ addObj.productionBatch || '-' }}</el-descriptions-item>
<el-descriptions-item label="閫佹牱鏃ユ湡">{{ addObj.sampleDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="鑱旂郴鏂瑰紡">{{ addObj.phone || '-' }}</el-descriptions-item>
diff --git a/src/views/business/productOrder/components/printDialog.vue b/src/views/business/productOrder/components/printDialog.vue
index 77a921f..a85c32e 100644
--- a/src/views/business/productOrder/components/printDialog.vue
+++ b/src/views/business/productOrder/components/printDialog.vue
@@ -30,7 +30,7 @@
<span class="info">{{ item.sampleModel }}</span>
</div>
<div class="item">
- <span class="full-title">濮旀墭鏃ユ湡</span>:
+ <span class="full-title">閫佹牱鏃ユ湡</span>:
<span class="info">{{ item.sendTime }}</span>
</div>
<div class="item">
@@ -91,7 +91,7 @@
<span class="info4">{{ item.sampleModel }}</span>
</div>
<div class="item">
- <span class="full-title2">濮旀墭鏃ユ湡</span>:
+ <span class="full-title2">閫佹牱鏃ユ湡</span>:
<span class="info">{{ item.sendTime }}</span>
</div>
<div class="item">
diff --git a/src/views/standard/model/index.vue b/src/views/standard/model/index.vue
index 6d3ce8f..e179b7a 100644
--- a/src/views/standard/model/index.vue
+++ b/src/views/standard/model/index.vue
@@ -27,7 +27,7 @@
<el-dialog :before-close="closeCopyTem" :close-on-click-modal="false" :close-on-press-escape="false"
:visible.sync="isShowCopyTem" :title="title" width="35%" :modal-append-to-body="false">
<el-form ref="copyForm" :model="copyForm" :rules="copyFormRules" label-position="right" label-width="80px">
- <el-form-item label="妯$増缂栧彿" prop="number">
+ <el-form-item label="妫�楠岄」鐩�" prop="number">
<el-input v-model="copyForm.number" clearable size="small"></el-input>
</el-form-item>
<el-form-item label="妯$増鍚嶇О" prop="name">
@@ -35,6 +35,9 @@
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
<el-input v-model="copyForm.remark" clearable size="small"></el-input>
+ </el-form-item>
+ <el-form-item label="浠锋牸(鍏�)" prop="price">
+ <el-input v-model="copyForm.price" clearable size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@@ -79,6 +82,7 @@
number: "",
name: "",
remark: "",
+ price: "",
id: "",
},
copyFormRules: {
@@ -89,9 +93,10 @@
},
tableData: [],
column: [
- { label: "妯℃澘缂栧彿", prop: "number" },
+ { label: "妫�楠岄」鐩�", prop: "number" },
{ label: "妯℃澘鍚嶇О", prop: "name" },
{ label: "澶囨敞", prop: "remark" },
+ { label: "浠锋牸(鍏�)", prop: "price" },
{ label: "鍒涘缓鐢ㄦ埛", prop: "createUserName" },
{ label: "鍒涘缓鏃堕棿", prop: "createTime", width: "160" },
{ label: "鏇存柊鐢ㄦ埛", prop: "updateUserName" },
@@ -216,6 +221,7 @@
name: this.copyForm.name,
number: this.copyForm.number,
remark: this.copyForm.remark,
+ price: this.copyForm.price === "" || this.copyForm.price == null ? null : this.copyForm.price,
};
switch (this.title) {
case "鏂板":
@@ -225,7 +231,7 @@
this.isShowCopyTem = false;
this.submitCopyInfoLoading = false;
this.$message.success("鏂板鎴愬姛");
- this.refreshTable("page");
+ this.getList();
})
.catch((err) => {
console.log("copyTemplate----", err);
diff --git a/src/views/standard/standardLibrary/index.vue b/src/views/standard/standardLibrary/index.vue
index a800e11..464bb37 100644
--- a/src/views/standard/standardLibrary/index.vue
+++ b/src/views/standard/standardLibrary/index.vue
@@ -48,9 +48,21 @@
<p v-if="!templateBindings.length" class="binding-tip">璇蜂负褰撳墠鏍囧噯缁戝畾鍘熷璁板綍妯℃澘銆�</p>
<el-table :data="templateBindings" border size="small">
<el-table-column type="index" label="椤哄簭" width="70" /><el-table-column label="妯℃澘缂栧彿" prop="number" width="180" /><el-table-column label="妯℃澘鍚嶇О" prop="name" /><el-table-column label="妫�娴嬩緷鎹紙妯℃澘澶囨敞锛�" prop="remark" />
+ <el-table-column label="璁惧缁戝畾" min-width="360">
+ <template slot-scope="scope">
+ <el-select v-model="scope.row.deviceIds"
+ :disabled="!checkPermi(['standard:standardLibrary:upStandardProduct'])"
+ multiple filterable clearable size="small"
+ placeholder="璇烽�夋嫨璇ユā鏉跨殑榛樿璁惧" style="width:100%">
+ <el-option v-for="device in deviceOptions" :key="device.id"
+ :label="device.label" :value="device.id" />
+ </el-select>
+ </template>
+ </el-table-column>
<el-table-column v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" label="鎿嶄綔" width="150"><template slot-scope="scope"><el-button type="text" :disabled="scope.$index === 0" @click="moveBinding(scope.$index, -1)">涓婄Щ</el-button><el-button type="text" :disabled="scope.$index === templateBindings.length - 1" @click="moveBinding(scope.$index, 1)">涓嬬Щ</el-button><el-button type="text" @click="removeBinding(scope.$index)">绉婚櫎</el-button></template></el-table-column>
</el-table>
- <el-select v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" v-model="templateToBind" filterable placeholder="閫夋嫨鍘熷璁板綍妯℃澘" size="small" style="width:320px;margin-top:16px" @change="addBinding"><el-option v-for="template in templateList.filter(item => !templateBindings.some(binding => binding.templateId === item.id))" :key="template.id" :label="template.number ? template.number + ' - ' + template.name : template.name" :value="template.id" /></el-select>
+ <el-select v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" v-model="templateToBind" multiple filterable placeholder="閫夋嫨鍘熷璁板綍妯℃澘" size="small" style="width:320px;margin-top:16px"><el-option v-for="template in templateList.filter(item => !templateBindings.some(binding => binding.templateId === item.id))" :key="template.id" :label="template.number ? template.number + ' - ' + template.name : template.name" :value="template.id" /></el-select>
+ <el-button v-if="checkPermi(['standard:standardLibrary:upStandardProduct'])" type="primary" size="small" style="margin-top:16px;margin-left:8px" @click="confirmAddBindings">纭</el-button>
</el-card>
<el-empty v-else description="璇烽�夋嫨浜岀骇鏍囧噯锛岀淮鎶ゅ叾鍘熷璁板綍妯℃澘" />
<div v-if="false">
@@ -322,6 +334,7 @@
getStandardTemplate,
selectTemplateBindings,
saveTemplateBindings,
+ searchDevices,
} from "@/api/standard/standardLibrary";
import bindSupplierDensityDialogAsk from "./components/bindSupplierDensityDialogAsk.vue";
import BatchCopy from "./components/BatchCopy.vue";
@@ -393,7 +406,8 @@
sectionList: [],
templateList: [],
templateBindings: [],
- templateToBind: null,
+ templateToBind: [],
+ deviceOptions: [],
total: 0,
currentPage: 1,
standardId: 0,
@@ -419,6 +433,7 @@
this.selectEnumByCategoryForSonLaboratory();
this.selectEnumByCategoryForsampleType();
this.getStandardTemplate();
+ this.loadDeviceOptions();
this.selectStandardMethodsSec();
this.token = {
token: sessionStorage.getItem("token"),
@@ -977,18 +992,32 @@
this.templateList = res.data;
});
},
- loadTemplateBindings(standardTreeId) {
- selectTemplateBindings({ standardTreeId }).then((res) => {
- this.templateBindings = res.data || [];
- this.templateToBind = null;
+ loadDeviceOptions() {
+ searchDevices({ status: 0 }).then((res) => {
+ this.deviceOptions = (res.data || []).map((device) => ({
+ id: device.id,
+ label: `${device.deviceName}--${device.managementNumber}`,
+ }));
});
},
- addBinding(templateId) {
- const template = this.templateList.find((item) => item.id === templateId);
- if (template && !this.templateBindings.some((item) => item.templateId === templateId)) {
- this.templateBindings.push({ ...template, templateId, sort: this.templateBindings.length });
- }
- this.templateToBind = null;
+ loadTemplateBindings(standardTreeId) {
+ selectTemplateBindings({ standardTreeId }).then((res) => {
+ this.templateBindings = (res.data || []).map((item) => ({
+ ...item,
+ deviceIds: Array.isArray(item.deviceIds) ? [...item.deviceIds] : [],
+ }));
+ this.templateToBind = [];
+ });
+ },
+ confirmAddBindings() {
+ const selectedIds = Array.isArray(this.templateToBind) ? this.templateToBind : [];
+ selectedIds.forEach((templateId) => {
+ const template = this.templateList.find((item) => item.id === templateId);
+ if (template && !this.templateBindings.some((item) => item.templateId === templateId)) {
+ this.templateBindings.push({ ...template, templateId, sort: this.templateBindings.length, deviceIds: [] });
+ }
+ });
+ this.templateToBind = [];
},
removeBinding(index) {
this.templateBindings.splice(index, 1);
@@ -1000,7 +1029,11 @@
},
saveBindings() {
saveTemplateBindings({ standardTreeId: this.selected.id,
- templates: this.templateBindings.map((item, index) => ({ templateId: item.templateId, sort: index }))
+ templates: this.templateBindings.map((item, index) => ({
+ templateId: item.templateId,
+ sort: index,
+ deviceIds: Array.isArray(item.deviceIds) ? [...item.deviceIds] : [],
+ }))
}).then(() => {
this.$message.success("妯℃澘缁戝畾宸蹭繚瀛�");
this.loadTemplateBindings(this.selected.id);
diff --git a/vue.config.js b/vue.config.js
index e11b2a9..3c39cb2 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -36,8 +36,8 @@
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
- // target: `http://36.213.90.123:9015/lims`,
- target: `http://192.168.21.53:9001/lims`,
+ // 鏈湴寮�鍙戠粺涓�璁块棶鏈満鍚庣锛屾姤鍛婃枃浠惰鍙栨湰鏈� wordUrl 鐩綍銆�
+ target: `http://127.0.0.1:9509/lims`,
changeOrigin: true,
pathRewrite: {
["^" + process.env.VUE_APP_BASE_API]: "",
--
Gitblit v1.9.3