From bf0d5e47a21816c440a2850299c8af60d58d1f25 Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期四, 05 三月 2026 16:41:24 +0800
Subject: [PATCH] lims模块
---
src/api/lims/realtimeMonitor.js | 46
src/api/lims/dataInterface.js | 46
src/api/lims/sample.js | 46
src/api/lims/experiment.js | 46
src/views/lims/dataInterfaceManagement/index.vue | 479 +++++++++
src/views/lims/dataCollection/index.vue | 561 +++++++++++
src/views/lims/experimentManagement/index.vue | 526 ++++++++++
src/views/lims/realtimeMonitor/index.vue | 582 +++++++++++
src/api/lims/dataCollection.js | 46
src/views/lims/sampleManagement/index.vue | 539 +++++++++++
10 files changed, 2,917 insertions(+), 0 deletions(-)
diff --git a/src/api/lims/dataCollection.js b/src/api/lims/dataCollection.js
new file mode 100644
index 0000000..595d20f
--- /dev/null
+++ b/src/api/lims/dataCollection.js
@@ -0,0 +1,46 @@
+// 鏁版嵁閲囬泦涓庡鐞嗛〉闈㈡帴鍙�
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ鏁版嵁閲囬泦
+export function listDataCollection(query) {
+ return request({
+ url: '/lims/dataCollection/listPage',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鏁版嵁閲囬泦璇︾粏
+export function getDataCollection(id) {
+ return request({
+ url: '/lims/dataCollection/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板鏁版嵁閲囬泦
+export function addDataCollection(data) {
+ return request({
+ url: '/lims/dataCollection/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼鏁版嵁閲囬泦
+export function updateDataCollection(data) {
+ return request({
+ url: '/lims/dataCollection/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎鏁版嵁閲囬泦
+export function delDataCollection(ids) {
+ return request({
+ url: '/lims/dataCollection/delete',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/lims/dataInterface.js b/src/api/lims/dataInterface.js
new file mode 100644
index 0000000..ff20ba6
--- /dev/null
+++ b/src/api/lims/dataInterface.js
@@ -0,0 +1,46 @@
+// 鏁版嵁鎺ュ彛绠$悊椤甸潰鎺ュ彛
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ鏁版嵁鎺ュ彛
+export function listDataInterface(query) {
+ return request({
+ url: '/lims/dataInterface/listPage',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鏁版嵁鎺ュ彛璇︾粏
+export function getDataInterface(id) {
+ return request({
+ url: '/lims/dataInterface/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板鏁版嵁鎺ュ彛
+export function addDataInterface(data) {
+ return request({
+ url: '/lims/dataInterface/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼鏁版嵁鎺ュ彛
+export function updateDataInterface(data) {
+ return request({
+ url: '/lims/dataInterface/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎鏁版嵁鎺ュ彛
+export function delDataInterface(ids) {
+ return request({
+ url: '/lims/dataInterface/delete',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/lims/experiment.js b/src/api/lims/experiment.js
new file mode 100644
index 0000000..bf3224f
--- /dev/null
+++ b/src/api/lims/experiment.js
@@ -0,0 +1,46 @@
+// 瀹為獙绠$悊椤甸潰鎺ュ彛
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ瀹為獙
+export function listExperiment(query) {
+ return request({
+ url: '/lims/experiment/listPage',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ瀹為獙璇︾粏
+export function getExperiment(id) {
+ return request({
+ url: '/lims/experiment/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板瀹為獙
+export function addExperiment(data) {
+ return request({
+ url: '/lims/experiment/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼瀹為獙
+export function updateExperiment(data) {
+ return request({
+ url: '/lims/experiment/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎瀹為獙
+export function delExperiment(ids) {
+ return request({
+ url: '/lims/experiment/delete',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/lims/realtimeMonitor.js b/src/api/lims/realtimeMonitor.js
new file mode 100644
index 0000000..303fb68
--- /dev/null
+++ b/src/api/lims/realtimeMonitor.js
@@ -0,0 +1,46 @@
+// 瀹炴椂鐩戞帶涓庨璀﹂〉闈㈡帴鍙�
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ鐩戞帶鏁版嵁
+export function listRealtimeMonitor(query) {
+ return request({
+ url: '/lims/realtimeMonitor/listPage',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鐩戞帶鏁版嵁璇︾粏
+export function getRealtimeMonitor(id) {
+ return request({
+ url: '/lims/realtimeMonitor/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板鐩戞帶鏁版嵁
+export function addRealtimeMonitor(data) {
+ return request({
+ url: '/lims/realtimeMonitor/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼鐩戞帶鏁版嵁
+export function updateRealtimeMonitor(data) {
+ return request({
+ url: '/lims/realtimeMonitor/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎鐩戞帶鏁版嵁
+export function delRealtimeMonitor(ids) {
+ return request({
+ url: '/lims/realtimeMonitor/delete',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/api/lims/sample.js b/src/api/lims/sample.js
new file mode 100644
index 0000000..2a221c4
--- /dev/null
+++ b/src/api/lims/sample.js
@@ -0,0 +1,46 @@
+// 鏍峰搧绠$悊椤甸潰鎺ュ彛
+import request from '@/utils/request'
+
+// 鍒嗛〉鏌ヨ鏍峰搧
+export function listSample(query) {
+ return request({
+ url: '/lims/sample/listPage',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ鏍峰搧璇︾粏
+export function getSample(id) {
+ return request({
+ url: '/lims/sample/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板鏍峰搧
+export function addSample(data) {
+ return request({
+ url: '/lims/sample/add',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼鏍峰搧
+export function updateSample(data) {
+ return request({
+ url: '/lims/sample/update',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍒犻櫎鏍峰搧
+export function delSample(ids) {
+ return request({
+ url: '/lims/sample/delete',
+ method: 'delete',
+ data: ids
+ })
+}
diff --git a/src/views/lims/dataCollection/index.vue b/src/views/lims/dataCollection/index.vue
new file mode 100644
index 0000000..02e8a5e
--- /dev/null
+++ b/src/views/lims/dataCollection/index.vue
@@ -0,0 +1,561 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">閲囬泦缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.collectionCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title" style="margin-left: 20px">璁惧鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.deviceName"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ />
+ <span class="search_title" style="margin-left: 20px">閲囬泦鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.collectionStatus"
+ style="width: 150px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ >
+ <el-option label="閲囬泦涓�" value="collecting" />
+ <el-option label="澶勭悊涓�" value="processing" />
+ <el-option label="宸插畬鎴�" value="completed" />
+ <el-option label="澶辫触" value="failed" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板閲囬泦</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鏁版嵁閲囬泦' : '缂栬緫鏁版嵁閲囬泦'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囬泦缂栧彿锛�" prop="collectionCode">
+ <el-input
+ v-model="form.collectionCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁惧鍚嶇О锛�" prop="deviceName">
+ <el-input
+ v-model="form.deviceName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璁惧缂栧彿锛�" prop="deviceCode">
+ <el-input
+ v-model="form.deviceCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏁版嵁绫诲瀷锛�" prop="dataType">
+ <el-select
+ v-model="form.dataType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="娓╁害" value="temperature" />
+ <el-option label="婀垮害" value="humidity" />
+ <el-option label="鍘嬪姏" value="pressure" />
+ <el-option label="娴侀噺" value="flow" />
+ <el-option label="娴撳害" value="concentration" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囬泦鏁板�硷細" prop="collectionValue">
+ <el-input
+ v-model="form.collectionValue"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍗曚綅锛�" prop="unit">
+ <el-select
+ v-model="form.unit"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鎽勬皬搴�(掳C)" value="celsius" />
+ <el-option label="鐧惧垎姣�(%)" value="percent" />
+ <el-option label="甯曟柉鍗�(Pa)" value="pa" />
+ <el-option label="鍗�/鍒嗛挓(L/min)" value="lmin" />
+ <el-option label="姣厠/鍗�(mg/L)" value="mgl" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="閲囬泦鏃堕棿锛�" prop="collectionTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.collectionTime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm:ss"
+ type="datetime"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="閲囬泦鐘舵�侊細" prop="collectionStatus">
+ <el-select
+ v-model="form.collectionStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="閲囬泦涓�" value="collecting" />
+ <el-option label="澶勭悊涓�" value="processing" />
+ <el-option label="宸插畬鎴�" value="completed" />
+ <el-option label="澶辫触" value="failed" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏁版嵁璐ㄩ噺锛�" prop="dataQuality">
+ <el-select
+ v-model="form.dataQuality"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鍚堟牸" value="qualified" />
+ <el-option label="寮傚父" value="abnormal" />
+ <el-option label="寰呮牎楠�" value="pending" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="澶勭悊鏂瑰紡锛�" prop="processMethod">
+ <el-select
+ v-model="form.processMethod"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鑷姩娓呮礂" value="autoClean" />
+ <el-option label="浜哄伐鏍¢獙" value="manualVerify" />
+ <el-option label="鏁版嵁杞崲" value="dataTransform" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鍘熷鏁版嵁锛�" prop="rawData">
+ <el-input
+ v-model="form.rawData"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶勭悊鍚庢暟鎹細" prop="processedData">
+ <el-input
+ v-model="form.processedData"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�" prop="remark">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainer">
+ <el-select
+ v-model="form.maintainer"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintenanceTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+ addDataCollection,
+ delDataCollection,
+ getDataCollection,
+ listDataCollection,
+ updateDataCollection,
+} from "@/api/lims/dataCollection.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+
+const tableColumn = ref([
+ {
+ label: "閲囬泦缂栧彿",
+ prop: "collectionCode",
+ width: 150,
+ },
+ {
+ label: "璁惧鍚嶇О",
+ prop: "deviceName",
+ width: 180,
+ },
+ {
+ label: "璁惧缂栧彿",
+ prop: "deviceCode",
+ width: 150,
+ },
+ {
+ label: "鏁版嵁绫诲瀷",
+ prop: "dataType",
+ width: 120,
+ },
+ {
+ label: "閲囬泦鏁板��",
+ prop: "collectionValue",
+ width: 120,
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ width: 80,
+ },
+ {
+ label: "閲囬泦鏃堕棿",
+ prop: "collectionTime",
+ width: 180,
+ },
+ {
+ label: "閲囬泦鐘舵��",
+ prop: "collectionStatus",
+ width: 100,
+ },
+ {
+ label: "鏁版嵁璐ㄩ噺",
+ prop: "dataQuality",
+ width: 100,
+ },
+ {
+ label: "澶勭悊鏂瑰紡",
+ prop: "processMethod",
+ width: 120,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainer",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ return row.maintainer !== userStore.nickName
+ }
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ collectionCode: "",
+ deviceName: "",
+ collectionStatus: "",
+ },
+ form: {
+ collectionCode: "",
+ deviceName: "",
+ deviceCode: "",
+ dataType: "",
+ collectionValue: "",
+ unit: "",
+ collectionTime: "",
+ collectionStatus: "collecting",
+ dataQuality: "",
+ processMethod: "",
+ rawData: "",
+ processedData: "",
+ remark: "",
+ maintainer: "",
+ maintenanceTime: "",
+ },
+ rules: {
+ collectionCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ deviceName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ deviceCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ dataType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ collectionValue: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ collectionTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ collectionStatus: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ dataQuality: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ processMethod: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintenanceTime: [
+ { required: false, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ listDataCollection({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainer = userStore.nickName;
+ form.value.collectionStatus = "collecting";
+ form.value.maintenanceTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getDataCollection(row.id).then((res) => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+};
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+const submitAdd = () => {
+ addDataCollection(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+const submitEdit = () => {
+ updateDataCollection(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/lims/dataCollection/export", {}, "鏁版嵁閲囬泦涓庡鐞�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delDataCollection(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0");
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/lims/dataInterfaceManagement/index.vue b/src/views/lims/dataInterfaceManagement/index.vue
new file mode 100644
index 0000000..803310e
--- /dev/null
+++ b/src/views/lims/dataInterfaceManagement/index.vue
@@ -0,0 +1,479 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鎺ュ彛鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.interfaceName"
+ style="width: 240px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title" style="margin-left: 20px">璁惧绫诲瀷锛�</span>
+ <el-select
+ v-model="searchForm.deviceType"
+ style="width: 200px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ >
+ <el-option label="浠櫒浠〃" value="instrument" />
+ <el-option label="杞欢绯荤粺" value="software" />
+ <el-option label="浼犳劅鍣�" value="sensor" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板鎺ュ彛</el-button>
+ <!-- <el-button @click="handleOut">瀵煎嚭</el-button> -->
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鏁版嵁鎺ュ彛' : '缂栬緫鏁版嵁鎺ュ彛'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鎺ュ彛鍚嶇О锛�" prop="interfaceName">
+ <el-input
+ v-model="form.interfaceName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎺ュ彛缂栫爜锛�" prop="interfaceCode">
+ <el-input
+ v-model="form.interfaceCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璁惧绫诲瀷锛�" prop="deviceType">
+ <el-select
+ v-model="form.deviceType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="浠櫒浠〃" value="instrument" />
+ <el-option label="杞欢绯荤粺" value="software" />
+ <el-option label="浼犳劅鍣�" value="sensor" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁惧鍚嶇О锛�" prop="deviceName">
+ <el-input
+ v-model="form.deviceName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="杩炴帴鍗忚锛�" prop="protocol">
+ <el-select
+ v-model="form.protocol"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="HTTP" value="http" />
+ <el-option label="TCP" value="tcp" />
+ <el-option label="MQTT" value="mqtt" />
+ <el-option label="Modbus" value="modbus" />
+ <el-option label="OPC UA" value="opcua" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="杩炴帴鍦板潃锛�" prop="connectionUrl">
+ <el-input
+ v-model="form.connectionUrl"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="绔彛鍙凤細" prop="port">
+ <el-input
+ v-model="form.port"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎺ュ彛鐘舵�侊細" prop="status">
+ <el-radio-group v-model="form.status">
+ <el-radio label="1">鍚敤</el-radio>
+ <el-radio label="0">绂佺敤</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="鎺ュ彛鎻忚堪锛�" prop="description">
+ <el-input
+ v-model="form.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainer">
+ <el-select
+ v-model="form.maintainer"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintenanceTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+ addDataInterface,
+ delDataInterface,
+ getDataInterface,
+ listDataInterface,
+ updateDataInterface,
+} from "@/api/lims/dataInterface.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+
+const tableColumn = ref([
+ {
+ label: "鎺ュ彛鍚嶇О",
+ prop: "interfaceName",
+ width: 200,
+ },
+ {
+ label: "鎺ュ彛缂栫爜",
+ prop: "interfaceCode",
+ width: 150,
+ },
+ {
+ label: "璁惧绫诲瀷",
+ prop: "deviceType",
+ width: 120,
+ },
+ {
+ label: "璁惧鍚嶇О",
+ prop: "deviceName",
+ width: 180,
+ },
+ {
+ label: "杩炴帴鍗忚",
+ prop: "protocol",
+ width: 120,
+ },
+ {
+ label: "杩炴帴鍦板潃",
+ prop: "connectionUrl",
+ width: 220,
+ },
+ {
+ label: "绔彛鍙�",
+ prop: "port",
+ width: 100,
+ },
+ {
+ label: "鎺ュ彛鐘舵��",
+ prop: "status",
+ width: 100,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainer",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ return row.maintainer !== userStore.nickName
+ }
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+// 鏁版嵁鎺ュ彛琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ interfaceName: "",
+ deviceType: "",
+ },
+ form: {
+ interfaceName: "",
+ interfaceCode: "",
+ deviceType: "",
+ deviceName: "",
+ protocol: "",
+ connectionUrl: "",
+ port: "",
+ status: "1",
+ description: "",
+ maintainer: "",
+ maintenanceTime: "",
+ },
+ rules: {
+ interfaceName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ interfaceCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ deviceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ deviceName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ protocol: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ connectionUrl: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ port: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ status: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintenanceTime: [
+ { required: false, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ listDataInterface({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainer = userStore.nickName;
+ form.value.status = "1";
+ form.value.maintenanceTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getDataInterface(row.id).then((res) => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ addDataInterface(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鎻愪氦淇敼
+const submitEdit = () => {
+ updateDataInterface(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/lims/dataInterface/export", {}, "鏁版嵁鎺ュ彛绠$悊.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delDataInterface(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0");
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/lims/experimentManagement/index.vue b/src/views/lims/experimentManagement/index.vue
new file mode 100644
index 0000000..01d743b
--- /dev/null
+++ b/src/views/lims/experimentManagement/index.vue
@@ -0,0 +1,526 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">瀹為獙缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.experimentCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title" style="margin-left: 20px">瀹為獙鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.experimentName"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ />
+ <span class="search_title" style="margin-left: 20px">瀹為獙鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.experimentStatus"
+ style="width: 150px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ >
+ <el-option label="璁″垝涓�" value="planned" />
+ <el-option label="杩涜涓�" value="inProgress" />
+ <el-option label="宸插畬鎴�" value="completed" />
+ <el-option label="宸插彇娑�" value="cancelled" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板瀹為獙</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板瀹為獙' : '缂栬緫瀹為獙'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瀹為獙缂栧彿锛�" prop="experimentCode">
+ <el-input
+ v-model="form.experimentCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹為獙鍚嶇О锛�" prop="experimentName">
+ <el-input
+ v-model="form.experimentName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瀹為獙绫诲瀷锛�" prop="experimentType">
+ <el-select
+ v-model="form.experimentType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鍖栧鍒嗘瀽" value="chemicalAnalysis" />
+ <el-option label="鐗╃悊娴嬭瘯" value="physicalTest" />
+ <el-option label="寰敓鐗╂娴�" value="microbialTest" />
+ <el-option label="鎬ц兘娴嬭瘯" value="performanceTest" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹為獙鏍囧噯锛�" prop="experimentStandard">
+ <el-input
+ v-model="form.experimentStandard"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="璁″垝寮�濮嬫棩鏈燂細" prop="planStartDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.planStartDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁″垝缁撴潫鏃ユ湡锛�" prop="planEndDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.planEndDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="瀹為獙璐熻矗浜猴細" prop="responsiblePerson">
+ <el-input
+ v-model="form.responsiblePerson"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹為獙鐘舵�侊細" prop="experimentStatus">
+ <el-select
+ v-model="form.experimentStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="璁″垝涓�" value="planned" />
+ <el-option label="杩涜涓�" value="inProgress" />
+ <el-option label="宸插畬鎴�" value="completed" />
+ <el-option label="宸插彇娑�" value="cancelled" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瀹為獙鐩殑锛�" prop="experimentPurpose">
+ <el-input
+ v-model="form.experimentPurpose"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瀹為獙杩囩▼锛�" prop="experimentProcess">
+ <el-input
+ v-model="form.experimentProcess"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="瀹為獙缁撴灉锛�" prop="experimentResult">
+ <el-input
+ v-model="form.experimentResult"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainer">
+ <el-select
+ v-model="form.maintainer"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintenanceTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+ addExperiment,
+ delExperiment,
+ getExperiment,
+ listExperiment,
+ updateExperiment,
+} from "@/api/lims/experiment.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+
+const tableColumn = ref([
+ {
+ label: "瀹為獙缂栧彿",
+ prop: "experimentCode",
+ width: 150,
+ },
+ {
+ label: "瀹為獙鍚嶇О",
+ prop: "experimentName",
+ width: 180,
+ },
+ {
+ label: "瀹為獙绫诲瀷",
+ prop: "experimentType",
+ width: 120,
+ },
+ {
+ label: "瀹為獙鏍囧噯",
+ prop: "experimentStandard",
+ width: 150,
+ },
+ {
+ label: "璁″垝寮�濮嬫棩鏈�",
+ prop: "planStartDate",
+ width: 120,
+ },
+ {
+ label: "璁″垝缁撴潫鏃ユ湡",
+ prop: "planEndDate",
+ width: 120,
+ },
+ {
+ label: "瀹為獙璐熻矗浜�",
+ prop: "responsiblePerson",
+ width: 120,
+ },
+ {
+ label: "瀹為獙鐘舵��",
+ prop: "experimentStatus",
+ width: 100,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainer",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ return row.maintainer !== userStore.nickName
+ }
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+// 瀹為獙琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ experimentCode: "",
+ experimentName: "",
+ experimentStatus: "",
+ },
+ form: {
+ experimentCode: "",
+ experimentName: "",
+ experimentType: "",
+ experimentStandard: "",
+ planStartDate: "",
+ planEndDate: "",
+ responsiblePerson: "",
+ experimentStatus: "planned",
+ experimentPurpose: "",
+ experimentProcess: "",
+ experimentResult: "",
+ maintainer: "",
+ maintenanceTime: "",
+ },
+ rules: {
+ experimentCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ experimentName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ experimentType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ experimentStandard: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ planStartDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ planEndDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ responsiblePerson: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ experimentStatus: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintenanceTime: [
+ { required: false, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ listExperiment({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainer = userStore.nickName;
+ form.value.experimentStatus = "planned";
+ form.value.maintenanceTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getExperiment(row.id).then((res) => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ addExperiment(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鎻愪氦淇敼
+const submitEdit = () => {
+ updateExperiment(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/lims/experiment/export", {}, "瀹為獙绠$悊.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delExperiment(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0");
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/lims/realtimeMonitor/index.vue b/src/views/lims/realtimeMonitor/index.vue
new file mode 100644
index 0000000..658db2c
--- /dev/null
+++ b/src/views/lims/realtimeMonitor/index.vue
@@ -0,0 +1,582 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鐩戞帶缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.monitorCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title" style="margin-left: 20px">鐩戞帶瀵硅薄锛�</span>
+ <el-input
+ v-model="searchForm.monitorTarget"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ />
+ <span class="search_title" style="margin-left: 20px">棰勮鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.alertStatus"
+ style="width: 150px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ >
+ <el-option label="姝e父" value="normal" />
+ <el-option label="棰勮" value="warning" />
+ <el-option label="鍛婅" value="alert" />
+ <el-option label="宸插鐞�" value="resolved" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板鐩戞帶</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板瀹炴椂鐩戞帶' : '缂栬緫瀹炴椂鐩戞帶'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鐩戞帶缂栧彿锛�" prop="monitorCode">
+ <el-input
+ v-model="form.monitorCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐩戞帶瀵硅薄锛�" prop="monitorTarget">
+ <el-input
+ v-model="form.monitorTarget"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鐩戞帶绫诲瀷锛�" prop="monitorType">
+ <el-select
+ v-model="form.monitorType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="娓╁害鐩戞帶" value="temperature" />
+ <el-option label="婀垮害鐩戞帶" value="humidity" />
+ <el-option label="鍘嬪姏鐩戞帶" value="pressure" />
+ <el-option label="璁惧鐘舵��" value="equipment" />
+ <el-option label="瀹為獙杩囩▼" value="experiment" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐩戞帶鎸囨爣锛�" prop="monitorIndicator">
+ <el-input
+ v-model="form.monitorIndicator"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="褰撳墠鏁板�硷細" prop="currentValue">
+ <el-input
+ v-model="form.currentValue"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍗曚綅锛�" prop="unit">
+ <el-select
+ v-model="form.unit"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鎽勬皬搴�(掳C)" value="celsius" />
+ <el-option label="鐧惧垎姣�(%)" value="percent" />
+ <el-option label="甯曟柉鍗�(Pa)" value="pa" />
+ <el-option label="杞�/鍒嗛挓(rpm)" value="rpm" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="涓婇檺闃堝�硷細" prop="upperLimit">
+ <el-input
+ v-model="form.upperLimit"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="涓嬮檺闃堝�硷細" prop="lowerLimit">
+ <el-input
+ v-model="form.lowerLimit"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="棰勮鐘舵�侊細" prop="alertStatus">
+ <el-select
+ v-model="form.alertStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="姝e父" value="normal" />
+ <el-option label="棰勮" value="warning" />
+ <el-option label="鍛婅" value="alert" />
+ <el-option label="宸插鐞�" value="resolved" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="棰勮绾у埆锛�" prop="alertLevel">
+ <el-select
+ v-model="form.alertLevel"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="涓�鑸�" value="low" />
+ <el-option label="閲嶈" value="medium" />
+ <el-option label="绱ф��" value="high" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鐩戞帶鏃堕棿锛�" prop="monitorTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.monitorTime"
+ value-format="YYYY-MM-DD HH:mm:ss"
+ format="YYYY-MM-DD HH:mm:ss"
+ type="datetime"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="澶勭悊浜猴細" prop="handler">
+ <el-input
+ v-model="form.handler"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="棰勮鎻忚堪锛�" prop="alertDescription">
+ <el-input
+ v-model="form.alertDescription"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶勭悊鎺柦锛�" prop="handleMeasure">
+ <el-input
+ v-model="form.handleMeasure"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�" prop="remark">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainer">
+ <el-select
+ v-model="form.maintainer"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintenanceTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+ addRealtimeMonitor,
+ delRealtimeMonitor,
+ getRealtimeMonitor,
+ listRealtimeMonitor,
+ updateRealtimeMonitor,
+} from "@/api/lims/realtimeMonitor.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+
+const tableColumn = ref([
+ {
+ label: "鐩戞帶缂栧彿",
+ prop: "monitorCode",
+ width: 150,
+ },
+ {
+ label: "鐩戞帶瀵硅薄",
+ prop: "monitorTarget",
+ width: 180,
+ },
+ {
+ label: "鐩戞帶绫诲瀷",
+ prop: "monitorType",
+ width: 120,
+ },
+ {
+ label: "鐩戞帶鎸囨爣",
+ prop: "monitorIndicator",
+ width: 150,
+ },
+ {
+ label: "褰撳墠鏁板��",
+ prop: "currentValue",
+ width: 100,
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ width: 80,
+ },
+ {
+ label: "涓婇檺闃堝��",
+ prop: "upperLimit",
+ width: 100,
+ },
+ {
+ label: "涓嬮檺闃堝��",
+ prop: "lowerLimit",
+ width: 100,
+ },
+ {
+ label: "棰勮鐘舵��",
+ prop: "alertStatus",
+ width: 100,
+ },
+ {
+ label: "棰勮绾у埆",
+ prop: "alertLevel",
+ width: 100,
+ },
+ {
+ label: "鐩戞帶鏃堕棿",
+ prop: "monitorTime",
+ width: 180,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainer",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ return row.maintainer !== userStore.nickName
+ }
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ monitorCode: "",
+ monitorTarget: "",
+ alertStatus: "",
+ },
+ form: {
+ monitorCode: "",
+ monitorTarget: "",
+ monitorType: "",
+ monitorIndicator: "",
+ currentValue: "",
+ unit: "",
+ upperLimit: "",
+ lowerLimit: "",
+ alertStatus: "normal",
+ alertLevel: "",
+ monitorTime: "",
+ alertDescription: "",
+ handler: "",
+ handleMeasure: "",
+ remark: "",
+ maintainer: "",
+ maintenanceTime: "",
+ },
+ rules: {
+ monitorCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ monitorTarget: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ monitorType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ monitorIndicator: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ currentValue: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ upperLimit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ lowerLimit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ alertStatus: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ monitorTime: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintenanceTime: [
+ { required: false, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ listRealtimeMonitor({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainer = userStore.nickName;
+ form.value.alertStatus = "normal";
+ form.value.maintenanceTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getRealtimeMonitor(row.id).then((res) => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+};
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+const submitAdd = () => {
+ addRealtimeMonitor(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+const submitEdit = () => {
+ updateRealtimeMonitor(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/lims/realtimeMonitor/export", {}, "瀹炴椂鐩戞帶涓庨璀�.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delRealtimeMonitor(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0");
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
diff --git a/src/views/lims/sampleManagement/index.vue b/src/views/lims/sampleManagement/index.vue
new file mode 100644
index 0000000..8004754
--- /dev/null
+++ b/src/views/lims/sampleManagement/index.vue
@@ -0,0 +1,539 @@
+<template>
+ <div class="app-container">
+ <div class="search_form">
+ <div>
+ <span class="search_title">鏍峰搧缂栧彿锛�</span>
+ <el-input
+ v-model="searchForm.sampleCode"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ :prefix-icon="Search"
+ />
+ <span class="search_title" style="margin-left: 20px">鏍峰搧鍚嶇О锛�</span>
+ <el-input
+ v-model="searchForm.sampleName"
+ style="width: 200px"
+ placeholder="璇疯緭鍏�"
+ @change="handleQuery"
+ clearable
+ />
+ <span class="search_title" style="margin-left: 20px">鏍峰搧鐘舵�侊細</span>
+ <el-select
+ v-model="searchForm.sampleStatus"
+ style="width: 150px"
+ placeholder="璇烽�夋嫨"
+ clearable
+ @change="handleQuery"
+ >
+ <el-option label="鍦ㄥ簱" value="inStock" />
+ <el-option label="鍑哄簱" value="outStock" />
+ <el-option label="妫�娴嬩腑" value="testing" />
+ <el-option label="宸查攢姣�" value="destroyed" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
+ >鎼滅储</el-button
+ >
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板鏍峰搧</el-button>
+ <el-button @click="handleOut">瀵煎嚭</el-button>
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ ></PIMTable>
+ </div>
+ <el-dialog
+ v-model="dialogFormVisible"
+ :title="operationType === 'add' ? '鏂板鏍峰搧' : '缂栬緫鏍峰搧'"
+ width="70%"
+ @close="closeDia"
+ >
+ <el-form
+ :model="form"
+ label-width="140px"
+ label-position="top"
+ :rules="rules"
+ ref="formRef"
+ >
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧缂栧彿锛�" prop="sampleCode">
+ <el-input
+ v-model="form.sampleCode"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧鍚嶇О锛�" prop="sampleName">
+ <el-input
+ v-model="form.sampleName"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧绫诲瀷锛�" prop="sampleType">
+ <el-select
+ v-model="form.sampleType"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鍘熸枡" value="rawMaterial" />
+ <el-option label="鍗婃垚鍝�" value="semiFinished" />
+ <el-option label="鎴愬搧" value="finishedProduct" />
+ <el-option label="鐣欐牱" value="retainedSample" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧瑙勬牸锛�" prop="specification">
+ <el-input
+ v-model="form.specification"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鍏ュ簱鏃ユ湡锛�" prop="inStockDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.inStockDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀛樺偍浣嶇疆锛�" prop="storageLocation">
+ <el-input
+ v-model="form.storageLocation"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧鏁伴噺锛�" prop="quantity">
+ <el-input
+ v-model="form.quantity"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁¢噺鍗曚綅锛�" prop="unit">
+ <el-select
+ v-model="form.unit"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鍏�(g)" value="g" />
+ <el-option label="鍗冨厠(kg)" value="kg" />
+ <el-option label="姣崌(ml)" value="ml" />
+ <el-option label="鍗�(L)" value="L" />
+ <el-option label="涓�" value="piece" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="鏍峰搧鐘舵�侊細" prop="sampleStatus">
+ <el-select
+ v-model="form.sampleStatus"
+ placeholder="璇烽�夋嫨"
+ clearable
+ style="width: 100%"
+ >
+ <el-option label="鍦ㄥ簱" value="inStock" />
+ <el-option label="鍑哄簱" value="outStock" />
+ <el-option label="妫�娴嬩腑" value="testing" />
+ <el-option label="宸查攢姣�" value="destroyed" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏈夋晥鏈熻嚦锛�" prop="validityDate">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.validityDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="24">
+ <el-form-item label="澶囨敞锛�" prop="remark">
+ <el-input
+ v-model="form.remark"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏�"
+ clearable
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="30">
+ <el-col :span="12">
+ <el-form-item label="缁存姢浜猴細" prop="maintainer">
+ <el-select
+ v-model="form.maintainer"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ >
+ <el-option
+ v-for="item in userList"
+ :key="item.nickName"
+ :label="item.nickName"
+ :value="item.nickName"
+ />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="缁存姢鏃堕棿锛�" prop="maintenanceTime">
+ <el-date-picker
+ style="width: 100%"
+ v-model="form.maintenanceTime"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨"
+ clearable
+ disabled
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭</el-button>
+ <el-button @click="closeDia">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { onMounted, ref, reactive } from "vue";
+import { Search } from "@element-plus/icons-vue";
+import {
+ addSample,
+ delSample,
+ getSample,
+ listSample,
+ updateSample,
+} from "@/api/lims/sample.js";
+import { ElMessageBox } from "element-plus";
+import { userListNoPage } from "@/api/system/user.js";
+import useUserStore from "@/store/modules/user";
+const { proxy } = getCurrentInstance();
+const userStore = useUserStore();
+
+const tableColumn = ref([
+ {
+ label: "鏍峰搧缂栧彿",
+ prop: "sampleCode",
+ width: 150,
+ },
+ {
+ label: "鏍峰搧鍚嶇О",
+ prop: "sampleName",
+ width: 180,
+ },
+ {
+ label: "鏍峰搧绫诲瀷",
+ prop: "sampleType",
+ width: 120,
+ },
+ {
+ label: "鏍峰搧瑙勬牸",
+ prop: "specification",
+ width: 150,
+ },
+ {
+ label: "鍏ュ簱鏃ユ湡",
+ prop: "inStockDate",
+ width: 120,
+ },
+ {
+ label: "瀛樺偍浣嶇疆",
+ prop: "storageLocation",
+ width: 150,
+ },
+ {
+ label: "鏁伴噺",
+ prop: "quantity",
+ width: 100,
+ },
+ {
+ label: "鍗曚綅",
+ prop: "unit",
+ width: 80,
+ },
+ {
+ label: "鏍峰搧鐘舵��",
+ prop: "sampleStatus",
+ width: 100,
+ },
+ {
+ label: "鏈夋晥鏈熻嚦",
+ prop: "validityDate",
+ width: 120,
+ },
+ {
+ label: "缁存姢浜�",
+ prop: "maintainer",
+ },
+ {
+ label: "缁存姢鏃堕棿",
+ prop: "maintenanceTime",
+ width: 100,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: 'right',
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ },
+ disabled: (row) => {
+ return row.maintainer !== userStore.nickName
+ }
+ },
+ ],
+ },
+]);
+const tableData = ref([]);
+const selectedRows = ref([]);
+const userList = ref([]);
+const tableLoading = ref(false);
+const page = reactive({
+ current: 1,
+ size: 100,
+ total: 0,
+});
+
+// 鏍峰搧琛ㄥ崟寮规鏁版嵁
+const operationType = ref("");
+const dialogFormVisible = ref(false);
+const data = reactive({
+ searchForm: {
+ sampleCode: "",
+ sampleName: "",
+ sampleStatus: "",
+ },
+ form: {
+ sampleCode: "",
+ sampleName: "",
+ sampleType: "",
+ specification: "",
+ inStockDate: "",
+ storageLocation: "",
+ quantity: "",
+ unit: "",
+ sampleStatus: "inStock",
+ validityDate: "",
+ remark: "",
+ maintainer: "",
+ maintenanceTime: "",
+ },
+ rules: {
+ sampleCode: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ sampleName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ sampleType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ specification: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ inStockDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ storageLocation: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+ unit: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ sampleStatus: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ validityDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+ maintainer: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ maintenanceTime: [
+ { required: false, message: "璇烽�夋嫨", trigger: "change" },
+ ],
+ },
+});
+const { searchForm, form, rules } = toRefs(data);
+
+// 鏌ヨ鍒楄〃
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+ page.current = 1;
+ getList();
+};
+const pagination = (obj) => {
+ page.current = obj.page;
+ page.size = obj.limit;
+ getList();
+};
+const getList = () => {
+ tableLoading.value = true;
+ listSample({ ...searchForm.value, ...page }).then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records;
+ page.total = res.data.total;
+ });
+};
+// 琛ㄦ牸閫夋嫨鏁版嵁
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+// 鎵撳紑寮规
+const openForm = (type, row) => {
+ operationType.value = type;
+ form.value = {};
+ form.value.maintainer = userStore.nickName;
+ form.value.sampleStatus = "inStock";
+ form.value.maintenanceTime = getCurrentDate();
+ userListNoPage().then((res) => {
+ userList.value = res.data;
+ });
+ if (type === "edit") {
+ getSample(row.id).then((res) => {
+ form.value = { ...res.data };
+ });
+ }
+ dialogFormVisible.value = true;
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = () => {
+ proxy.$refs["formRef"].validate((valid) => {
+ if (valid) {
+ if (operationType.value === "edit") {
+ submitEdit();
+ } else {
+ submitAdd();
+ }
+ }
+ });
+};
+// 鎻愪氦鏂板
+const submitAdd = () => {
+ addSample(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鎻愪氦淇敼
+const submitEdit = () => {
+ updateSample(form.value).then((res) => {
+ proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+ closeDia();
+ getList();
+ });
+};
+// 鍏抽棴寮规
+const closeDia = () => {
+ proxy.resetForm("formRef");
+ dialogFormVisible.value = false;
+};
+// 瀵煎嚭
+const handleOut = () => {
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ proxy.download("/lims/sample/export", {}, "鏍峰搧绠$悊.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+// 鍒犻櫎
+const handleDelete = () => {
+ let ids = [];
+ if (selectedRows.value.length > 0) {
+ // 妫�鏌ユ槸鍚︽湁浠栦汉缁存姢鐨勬暟鎹�
+ const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName);
+ if (unauthorizedData.length > 0) {
+ proxy.$modal.msgWarning("涓嶅彲鍒犻櫎浠栦汉缁存姢鐨勬暟鎹�");
+ return;
+ }
+ ids = selectedRows.value.map((item) => item.id);
+ } else {
+ proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+ return;
+ }
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ })
+ .then(() => {
+ tableLoading.value = true;
+ delSample(ids)
+ .then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ })
+ .finally(() => {
+ tableLoading.value = false;
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
+};
+
+// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
+function getCurrentDate() {
+ const today = new Date();
+ const year = today.getFullYear();
+ const month = String(today.getMonth() + 1).padStart(2, "0");
+ const day = String(today.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
+}
+
+onMounted(() => {
+ getList();
+});
+</script>
+
+<style scoped lang="scss"></style>
--
Gitblit v1.9.3