| src/api/lims/instrument.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/instrumentCalibration.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/judgmentStandard.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/reagent.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/reagentRecord.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/testItem.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/api/lims/unit.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/lims/resourceManagement/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/lims/systemConfig/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/lims/instrument.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // 仪å¨è®¾å¤æ¥å£ import request from '@/utils/request' // å页æ¥è¯¢ä»ªå¨è®¾å¤ export function listInstrument(query) { return request({ url: '/lims/instrument/listPage', method: 'get', params: query }) } // æ¥è¯¢ä»ªå¨è®¾å¤è¯¦ç» export function getInstrument(id) { return request({ url: '/lims/instrument/' + id, method: 'get' }) } // æ°å¢ä»ªå¨è®¾å¤ export function addInstrument(data) { return request({ url: '/lims/instrument/add', method: 'post', data: data }) } // ä¿®æ¹ä»ªå¨è®¾å¤ export function updateInstrument(data) { return request({ url: '/lims/instrument/update', method: 'post', data: data }) } // å é¤ä»ªå¨è®¾å¤ export function delInstrument(ids) { return request({ url: '/lims/instrument/delete', method: 'delete', data: ids }) } src/api/lims/instrumentCalibration.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // æ ¡åè®°å½æ¥å£ import request from '@/utils/request' // å页æ¥è¯¢æ ¡åè®°å½ export function listInstrumentCalibration(query) { return request({ url: '/lims/instrumentCalibration/listPage', method: 'get', params: query }) } // æ¥è¯¢æ ¡åè®°å½è¯¦ç» export function getInstrumentCalibration(id) { return request({ url: '/lims/instrumentCalibration/' + id, method: 'get' }) } // æ°å¢æ ¡åè®°å½ export function addInstrumentCalibration(data) { return request({ url: '/lims/instrumentCalibration/add', method: 'post', data: data }) } // ä¿®æ¹æ ¡åè®°å½ export function updateInstrumentCalibration(data) { return request({ url: '/lims/instrumentCalibration/update', method: 'post', data: data }) } // å 餿 ¡åè®°å½ export function delInstrumentCalibration(ids) { return request({ url: '/lims/instrumentCalibration/delete', method: 'delete', data: ids }) } src/api/lims/judgmentStandard.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // å¤å®æ åæ¥å£ import request from '@/utils/request' // å页æ¥è¯¢å¤å®æ å export function listJudgmentStandard(query) { return request({ url: '/lims/judgmentStandard/listPage', method: 'get', params: query }) } // æ¥è¯¢å¤å®æ åè¯¦ç» export function getJudgmentStandard(id) { return request({ url: '/lims/judgmentStandard/' + id, method: 'get' }) } // æ°å¢å¤å®æ å export function addJudgmentStandard(data) { return request({ url: '/lims/judgmentStandard/add', method: 'post', data: data }) } // ä¿®æ¹å¤å®æ å export function updateJudgmentStandard(data) { return request({ url: '/lims/judgmentStandard/update', method: 'post', data: data }) } // å é¤å¤å®æ å export function delJudgmentStandard(ids) { return request({ url: '/lims/judgmentStandard/delete', method: 'delete', data: ids }) } src/api/lims/reagent.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // è¯åèææ¥å£ import request from '@/utils/request' // å页æ¥è¯¢è¯åèæ export function listReagent(query) { return request({ url: '/lims/reagent/listPage', method: 'get', params: query }) } // æ¥è¯¢è¯åèæè¯¦ç» export function getReagent(id) { return request({ url: '/lims/reagent/' + id, method: 'get' }) } // æ°å¢è¯åèæ export function addReagent(data) { return request({ url: '/lims/reagent/add', method: 'post', data: data }) } // ä¿®æ¹è¯åèæ export function updateReagent(data) { return request({ url: '/lims/reagent/update', method: 'post', data: data }) } // å é¤è¯åèæ export function delReagent(ids) { return request({ url: '/lims/reagent/delete', method: 'delete', data: ids }) } src/api/lims/reagentRecord.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // åºå ¥åºæµæ°´æ¥å£ import request from '@/utils/request' // å页æ¥è¯¢åºå ¥åºæµæ°´ export function listReagentRecord(query) { return request({ url: '/lims/reagentRecord/listPage', method: 'get', params: query }) } // æ¥è¯¢åºå ¥åºæµæ°´è¯¦ç» export function getReagentRecord(id) { return request({ url: '/lims/reagentRecord/' + id, method: 'get' }) } // æ°å¢åºå ¥åºæµæ°´ export function addReagentRecord(data) { return request({ url: '/lims/reagentRecord/add', method: 'post', data: data }) } // ä¿®æ¹åºå ¥åºæµæ°´ export function updateReagentRecord(data) { return request({ url: '/lims/reagentRecord/update', method: 'post', data: data }) } // å é¤åºå ¥åºæµæ°´ export function delReagentRecord(ids) { return request({ url: '/lims/reagentRecord/delete', method: 'delete', data: ids }) } src/api/lims/testItem.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // æ£æµé¡¹ç®æ¥å£ import request from '@/utils/request' // å页æ¥è¯¢æ£æµé¡¹ç® export function listTestItem(query) { return request({ url: '/lims/testItem/listPage', method: 'get', params: query }) } // æ¥è¯¢æ£æµé¡¹ç®è¯¦ç» export function getTestItem(id) { return request({ url: '/lims/testItem/' + id, method: 'get' }) } // æ°å¢æ£æµé¡¹ç® export function addTestItem(data) { return request({ url: '/lims/testItem/add', method: 'post', data: data }) } // ä¿®æ¹æ£æµé¡¹ç® export function updateTestItem(data) { return request({ url: '/lims/testItem/update', method: 'post', data: data }) } // å 餿£æµé¡¹ç® export function delTestItem(ids) { return request({ url: '/lims/testItem/delete', method: 'delete', data: ids }) } src/api/lims/unit.js
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,46 @@ // 计éå使¥å£ import request from '@/utils/request' // å页æ¥è¯¢è®¡éåä½ export function listUnit(query) { return request({ url: '/lims/unit/listPage', method: 'get', params: query }) } // æ¥è¯¢è®¡éåä½è¯¦ç» export function getUnit(id) { return request({ url: '/lims/unit/' + id, method: 'get' }) } // æ°å¢è®¡éåä½ export function addUnit(data) { return request({ url: '/lims/unit/add', method: 'post', data: data }) } // ä¿®æ¹è®¡éåä½ export function updateUnit(data) { return request({ url: '/lims/unit/update', method: 'post', data: data }) } // å é¤è®¡éåä½ export function delUnit(ids) { return request({ url: '/lims/unit/delete', method: 'delete', data: ids }) } src/views/lims/resourceManagement/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,535 @@ <template> <div class="app-container"> <el-tabs v-model="activeTab" type="border-card"> <!-- ==================== Tab1: 仪å¨è®¾å¤ ==================== --> <el-tab-pane label="仪å¨è®¾å¤" name="instrument"> <div class="search_form"> <div> <span class="search_title">仪å¨ç¼å·ï¼</span> <el-input v-model="insSearch.instrumentCode" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadInstrument" /> <span class="search_title" style="margin-left: 16px">仪å¨åç§°ï¼</span> <el-input v-model="insSearch.instrumentName" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadInstrument" /> <span class="search_title" style="margin-left: 16px">ç¶æï¼</span> <el-select v-model="insSearch.status" style="width: 140px" placeholder="å ¨é¨" clearable @change="loadInstrument"> <el-option label="æ£å¸¸" value="normal" /> <el-option label="ç»´ä¿®ä¸" value="maintenance" /> <el-option label="é²ç½®" value="idle" /> <el-option label="å·²æ¥åº" value="scrapped" /> </el-select> <el-button type="primary" style="margin-left: 10px" @click="loadInstrument">æç´¢</el-button> </div> <div> <el-button type="primary" @click="openInsForm('add')">æ°å¢ä»ªå¨</el-button> <el-button type="success" plain @click="openCalDialog">æ ¡åè®°å½</el-button> <el-button type="danger" plain @click="delInstrument">å é¤</el-button> </div> </div> <div class="table_list"> <PIMTable rowKey="id" :column="insColumns" :tableData="insData" :page="insPage" :isSelection="true" :tableLoading="insLoading" @selection-change="(v) => (insSelected = v)" @pagination="paginationIns" /> </div> </el-tab-pane> <!-- ==================== Tab2: è¯åèæ ==================== --> <el-tab-pane label="è¯åèæ" name="reagent"> <div class="search_form"> <div> <span class="search_title">ç¼å·ï¼</span> <el-input v-model="reSearch.reagentCode" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadReagent" /> <span class="search_title" style="margin-left: 16px">åç§°ï¼</span> <el-input v-model="reSearch.reagentName" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadReagent" /> <span class="search_title" style="margin-left: 16px">ç±»å«ï¼</span> <el-select v-model="reSearch.category" style="width: 140px" placeholder="å ¨é¨" clearable @change="loadReagent"> <el-option label="è¯å" value="reagent" /> <el-option label="èæ" value="consumable" /> <el-option label="æ åå" value="standard" /> <el-option label="è´¨æ§å" value="control" /> </el-select> <el-button type="primary" style="margin-left: 10px" @click="loadReagent">æç´¢</el-button> </div> <div> <el-button type="primary" @click="openReForm('add')">æ°å¢è¯å/èæ</el-button> <el-button type="success" plain @click="openStockDialog('in')">éè´å ¥åº</el-button> <el-button type="warning" plain @click="openStockDialog('out')">é¢ç¨åºåº</el-button> <el-button type="danger" plain @click="delReagent">å é¤</el-button> </div> </div> <div class="table_list"> <PIMTable rowKey="id" :column="reColumns" :tableData="reData" :page="rePage" :isSelection="true" :tableLoading="reLoading" @selection-change="(v) => (reSelected = v)" @pagination="paginationRe" /> </div> </el-tab-pane> </el-tabs> <!-- ==================== 仪å¨è¡¨å ==================== --> <el-dialog v-model="insDialogVisible" :title="insOpType === 'add' ? 'æ°å¢ä»ªå¨' : 'ç¼è¾ä»ªå¨'" width="70%"> <el-form ref="insFormRef" :model="insForm" label-position="top" :rules="insRules"> <el-row :gutter="24"> <el-col :span="12"><el-form-item label="仪å¨ç¼å·" prop="instrumentCode"><el-input v-model="insForm.instrumentCode" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="仪å¨åç§°" prop="instrumentName"><el-input v-model="insForm.instrumentName" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="è§æ ¼åå·"><el-input v-model="insForm.instrumentModel" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="ç产åå"><el-input v-model="insForm.manufacturer" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åºååºåå·"><el-input v-model="insForm.serialNo" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åæ¾ä½ç½®"><el-input v-model="insForm.location" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="è´ç½®æ¥æ"><el-date-picker v-model="insForm.purchaseDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="ä¿ä¿®æªæ¢"><el-date-picker v-model="insForm.warrantyEndDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="ç¶æ"> <el-select v-model="insForm.status" style="width: 100%"> <el-option label="æ£å¸¸" value="normal" /><el-option label="ç»´ä¿®ä¸" value="maintenance" /> <el-option label="é²ç½®" value="idle" /><el-option label="å·²æ¥åº" value="scrapped" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="责任人"><el-input v-model="insForm.responsiblePerson" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="insForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="insDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitIns">ç¡®å®</el-button> </template> </el-dialog> <!-- ==================== è¯å表å ==================== --> <el-dialog v-model="reDialogVisible" :title="reOpType === 'add' ? 'æ°å¢è¯å/èæ' : 'ç¼è¾è¯å/èæ'" width="70%"> <el-form ref="reFormRef" :model="reForm" label-position="top" :rules="reRules"> <el-row :gutter="24"> <el-col :span="12"><el-form-item label="ç¼å·" prop="reagentCode"><el-input v-model="reForm.reagentCode" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åç§°" prop="reagentName"><el-input v-model="reForm.reagentName" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="è§æ ¼"><el-input v-model="reForm.specification" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="ç±»å«"> <el-select v-model="reForm.category" style="width: 100%"> <el-option label="è¯å" value="reagent" /><el-option label="èæ" value="consumable" /> <el-option label="æ åå" value="standard" /><el-option label="è´¨æ§å" value="control" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="计éåä½"><el-input v-model="reForm.unit" placeholder="å¦ g / mL / ç¶" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="ä¾åºå"><el-input v-model="reForm.supplier" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="å卿¡ä»¶"><el-input v-model="reForm.storageCondition" placeholder="å¦ 2-8âé¿å " /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åæ¾ä½ç½®"><el-input v-model="reForm.location" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="å½ååºå"><el-input-number v-model="reForm.currentStock" :precision="4" :min="0" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="å®å ¨åºå"><el-input-number v-model="reForm.safetyStock" :precision="4" :min="0" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="æææè³"><el-date-picker v-model="reForm.expiryDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="reForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="reDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitRe">ç¡®å®</el-button> </template> </el-dialog> <!-- ==================== åºå ¥åºå¼¹çª ==================== --> <el-dialog v-model="stockDialogVisible" :title="stockType === 'in' ? 'éè´å ¥åº' : 'é¢ç¨åºåº'" width="560px"> <el-form :model="stockForm" label-position="top"> <el-form-item label="è¯å/èæ"> <el-select v-model="stockForm.reagentId" style="width: 100%" placeholder="è¯·éæ©" filterable @change="onStockReagentChange"> <el-option v-for="r in reOptions" :key="r.id" :label="`${r.reagentName}ï¼åºå ${r.currentStock ?? 0}${r.unit || ''}ï¼`" :value="r.id" /> </el-select> </el-form-item> <el-row :gutter="16"> <el-col :span="12"><el-form-item label="æ°é"><el-input-number v-model="stockForm.quantity" :precision="4" :min="0.0001" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ¹æ¬¡å·"><el-input v-model="stockForm.batchNo" /></el-form-item></el-col> </el-row> <el-row :gutter="16" v-if="stockType === 'in'"> <el-col :span="12"><el-form-item label="ä¾åºå"><el-input v-model="stockForm.supplier" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åä»·"><el-input-number v-model="stockForm.unitPrice" :precision="4" :min="0" style="width: 100%" /></el-form-item></el-col> </el-row> <el-form-item v-if="stockType === 'out'" label="ç¨é/é¢ç¨äºç±"> <el-input v-model="stockForm.purpose" placeholder="å¦ï¼æ ·ååå¤ç" /> </el-form-item> <el-form-item label="夿³¨"><el-input v-model="stockForm.remark" type="textarea" :rows="2" /></el-form-item> </el-form> <template #footer> <el-button @click="stockDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitStock">ç¡®å®</el-button> </template> </el-dialog> <!-- ==================== æ ¡åè®°å½å¼¹çª ==================== --> <el-dialog v-model="calDialogVisible" title="ä»ªå¨æ ¡å / ç»´æ¤è®°å½" width="80%"> <div style="margin-bottom: 12px; display: flex; justify-content: space-between"> <el-select v-model="calInstrumentId" style="width: 320px" placeholder="éæ©ä»ªå¨æ¥çè®°å½" filterable @change="loadCalibration"> <el-option v-for="i in insOptions" :key="i.id" :label="`${i.instrumentName}ï¼${i.instrumentCode}ï¼`" :value="i.id" /> </el-select> <el-button type="primary" @click="openCalForm('add')" :disabled="!calInstrumentId">æ°å¢è®°å½</el-button> </div> <el-table :data="calData" border size="small" max-height="420"> <el-table-column prop="recordType" label="ç±»å" width="100"> <template #default="{ row }">{{ recordTypeText(row.recordType) }}</template> </el-table-column> <el-table-column prop="calibrationDate" label="æ¬æ¬¡æ¥æ" width="110" /> <el-table-column prop="nextCalibrationDate" label="䏿¬¡å°æ" width="110" /> <el-table-column prop="calibrationOrg" label="æºæ" show-overflow-tooltip /> <el-table-column prop="certificateNo" label="è¯ä¹¦ç¼å·" width="140" show-overflow-tooltip /> <el-table-column prop="calibrationResult" label="ç»æ" width="90"> <template #default="{ row }"> <el-tag :type="row.calibrationResult === 'pass' ? 'success' : row.calibrationResult === 'fail' ? 'danger' : 'warning'" size="small"> {{ resultText(row.calibrationResult) }} </el-tag> </template> </el-table-column> <el-table-column prop="cost" label="è´¹ç¨" width="100" /> <el-table-column prop="executor" label="æ§è¡äºº" width="100" /> <el-table-column label="æä½" width="120" align="center"> <template #default="{ row }"> <el-button link type="primary" @click="openCalForm('edit', row)">ç¼è¾</el-button> <el-button link type="danger" @click="delCalibration(row)">å é¤</el-button> </template> </el-table-column> </el-table> </el-dialog> <!-- ==================== æ ¡åè®°å½è¡¨å ==================== --> <el-dialog v-model="calFormVisible" :title="calOpType === 'add' ? 'æ°å¢æ ¡åè®°å½' : 'ç¼è¾æ ¡åè®°å½'" width="600px"> <el-form :model="calForm" label-position="top"> <el-row :gutter="16"> <el-col :span="12"> <el-form-item label="ç±»å"> <el-select v-model="calForm.recordType" style="width: 100%"> <el-option label="æ ¡å" value="calibration" /><el-option label="ç»´æ¤ä¿å »" value="maintenance" /><el-option label="ç»´ä¿®" value="repair" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="æ¬æ¬¡æ¥æ"><el-date-picker v-model="calForm.calibrationDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="䏿¬¡å°æ"><el-date-picker v-model="calForm.nextCalibrationDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ ¡å/ç»´ä¿æºæ"><el-input v-model="calForm.calibrationOrg" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="è¯ä¹¦ç¼å·"><el-input v-model="calForm.certificateNo" /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="ç»æ"> <el-select v-model="calForm.calibrationResult" style="width: 100%"> <el-option label="åæ ¼" value="pass" /><el-option label="ä¸åæ ¼" value="fail" /><el-option label="ææ¡ä»¶éè¿" value="conditional" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="è´¹ç¨"><el-input-number v-model="calForm.cost" :precision="2" :min="0" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ§è¡äºº"><el-input v-model="calForm.executor" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="calForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="calFormVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitCal">ç¡®å®</el-button> </template> </el-dialog> </div> </template> <script setup> import { ref, reactive, onMounted, getCurrentInstance } from "vue"; import { ElMessage, ElMessageBox } from "element-plus"; import { listInstrument, getInstrument, addInstrument, updateInstrument, delInstrument as apiDelInstrument, } from "@/api/lims/instrument"; import { listInstrumentCalibration, addInstrumentCalibration, updateInstrumentCalibration, delInstrumentCalibration, } from "@/api/lims/instrumentCalibration"; import { listReagent, getReagent, addReagent, updateReagent, delReagent as apiDelReagent, } from "@/api/lims/reagent"; import { addReagentRecord } from "@/api/lims/reagentRecord"; const { proxy } = getCurrentInstance(); const activeTab = ref("instrument"); /* ==================== ä»ªå¨ ==================== */ const insSearch = ref({}); const insData = ref([]); const insSelected = ref([]); const insLoading = ref(false); const insPage = reactive({ pageNum: 1, pageSize: 10, total: 0 }); const insOptions = ref([]); const insColumns = ref([ { label: "仪å¨ç¼å·", prop: "instrumentCode", width: 140 }, { label: "仪å¨åç§°", prop: "instrumentName", width: 180 }, { label: "è§æ ¼åå·", prop: "instrumentModel", width: 150 }, { label: "ç产åå", prop: "manufacturer", width: 150 }, { label: "åæ¾ä½ç½®", prop: "location", width: 130 }, { label: "è´ç½®æ¥æ", prop: "purchaseDate", width: 110 }, { label: "ä¿ä¿®æªæ¢", prop: "warrantyEndDate", width: 110 }, { label: "ç¶æ", prop: "status", width: 90 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 140, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => openInsForm("edit", row) }, { name: "å é¤", type: "text", clickFun: (row) => doDelInstrument([row.id]) }, ], }, ]); const loadInstrument = () => { insLoading.value = true; listInstrument({ ...insSearch.value, ...insPage }).then((res) => { insLoading.value = false; insData.value = res.data.records || []; insPage.total = res.data.total || 0; insOptions.value = insData.value; }).catch(() => (insLoading.value = false)); }; const paginationIns = (p) => { insPage.pageNum = p.pageNum; insPage.pageSize = p.pageSize; loadInstrument(); }; const insDialogVisible = ref(false); const insOpType = ref("add"); const insFormRef = ref(null); const insForm = ref({}); const insRules = { instrumentCode: [{ required: true, message: "请è¾å ¥ä»ªå¨ç¼å·", trigger: "blur" }], instrumentName: [{ required: true, message: "请è¾å ¥ä»ªå¨åç§°", trigger: "blur" }], }; const openInsForm = (type, row) => { insOpType.value = type; insForm.value = { status: "normal" }; if (type === "edit") { getInstrument(row.id).then((res) => { insForm.value = { ...res.data }; }); } insDialogVisible.value = true; }; const submitIns = () => { insFormRef.value.validate((valid) => { if (!valid) return; const fn = insOpType.value === "add" ? addInstrument : updateInstrument; fn(insForm.value).then(() => { ElMessage.success("ä¿åæå"); insDialogVisible.value = false; loadInstrument(); }); }); }; const doDelInstrument = (ids) => { ElMessageBox.confirm(`确认å é¤éä¸ç ${ids.length} æ¡ä»ªå¨è®°å½ï¼`, "æç¤º", { type: "warning" }) .then(() => apiDelInstrument(ids).then(() => { ElMessage.success("å 餿å"); loadInstrument(); })) .catch(() => {}); }; const delInstrument = () => { const ids = insSelected.value.map((r) => r.id); if (!ids.length) return ElMessage.warning("请å éæ©è¦å é¤çè®°å½"); doDelInstrument(ids); }; /* ==================== æ ¡åè®°å½ ==================== */ const calDialogVisible = ref(false); const calInstrumentId = ref(null); const calData = ref([]); const calFormVisible = ref(false); const calOpType = ref("add"); const calForm = ref({}); const openCalDialog = () => { if (!insOptions.value.length) return ElMessage.warning("è¯·å æ°å¢ä»ªå¨"); calInstrumentId.value = insOptions.value[0].id; loadCalibration(); calDialogVisible.value = true; }; const loadCalibration = () => { if (!calInstrumentId.value) return; listInstrumentCalibration({ instrumentId: calInstrumentId.value, pageNum: 1, pageSize: 100 }).then((res) => { calData.value = res.data.records || []; }); }; const openCalForm = (type, row) => { calOpType.value = type; const ins = insOptions.value.find((i) => i.id === calInstrumentId.value) || {}; calForm.value = type === "edit" ? { ...row } : { instrumentId: calInstrumentId.value, instrumentCode: ins.instrumentCode, instrumentName: ins.instrumentName, recordType: "calibration" }; calFormVisible.value = true; }; const submitCal = () => { const fn = calOpType.value === "add" ? addInstrumentCalibration : updateInstrumentCalibration; fn(calForm.value).then(() => { ElMessage.success("ä¿åæå"); calFormVisible.value = false; loadCalibration(); }); }; const delCalibration = (row) => { ElMessageBox.confirm("确认å é¤è¿æ¡è®°å½ï¼", "æç¤º", { type: "warning" }) .then(() => delInstrumentCalibration([row.id]).then(() => { ElMessage.success("å 餿å"); loadCalibration(); })) .catch(() => {}); }; const recordTypeText = (t) => ({ calibration: "æ ¡å", maintenance: "ç»´æ¤ä¿å »", repair: "ç»´ä¿®" }[t] || t || "-"); const resultText = (t) => ({ pass: "åæ ¼", fail: "ä¸åæ ¼", conditional: "ææ¡ä»¶éè¿" }[t] || t || "-"); /* ==================== è¯åèæ ==================== */ const reSearch = ref({}); const reData = ref([]); const reSelected = ref([]); const reLoading = ref(false); const rePage = reactive({ pageNum: 1, pageSize: 10, total: 0 }); const reOptions = ref([]); const reColumns = ref([ { label: "ç¼å·", prop: "reagentCode", width: 130 }, { label: "åç§°", prop: "reagentName", width: 180 }, { label: "è§æ ¼", prop: "specification", width: 130 }, { label: "ç±»å«", prop: "category", width: 100 }, { label: "å½ååºå", prop: "currentStock", width: 110 }, { label: "å®å ¨åºå", prop: "safetyStock", width: 110 }, { label: "åä½", prop: "unit", width: 80 }, { label: "æææè³", prop: "expiryDate", width: 110 }, { label: "åæ¾ä½ç½®", prop: "location", width: 130 }, { label: "ä¾åºå", prop: "supplier", width: 150 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 140, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => openReForm("edit", row) }, { name: "å é¤", type: "text", clickFun: (row) => doDelReagent([row.id]) }, ], }, ]); const loadReagent = () => { reLoading.value = true; listReagent({ ...reSearch.value, ...rePage }).then((res) => { reLoading.value = false; reData.value = res.data.records || []; rePage.total = res.data.total || 0; }).catch(() => (reLoading.value = false)); }; const paginationRe = (p) => { rePage.pageNum = p.pageNum; rePage.pageSize = p.pageSize; loadReagent(); }; const loadReagentOptions = () => { listReagent({ pageNum: 1, pageSize: 500 }).then((res) => { reOptions.value = res.data.records || []; }); }; const reDialogVisible = ref(false); const reOpType = ref("add"); const reFormRef = ref(null); const reForm = ref({}); const reRules = { reagentCode: [{ required: true, message: "请è¾å ¥ç¼å·", trigger: "blur" }], reagentName: [{ required: true, message: "请è¾å ¥åç§°", trigger: "blur" }], }; const openReForm = (type, row) => { reOpType.value = type; reForm.value = { category: "reagent", currentStock: 0, safetyStock: 0 }; if (type === "edit") { getReagent(row.id).then((res) => { reForm.value = { ...res.data }; }); } reDialogVisible.value = true; }; const submitRe = () => { reFormRef.value.validate((valid) => { if (!valid) return; const fn = reOpType.value === "add" ? addReagent : updateReagent; fn(reForm.value).then(() => { ElMessage.success("ä¿åæå"); reDialogVisible.value = false; loadReagent(); loadReagentOptions(); }); }); }; const doDelReagent = (ids) => { ElMessageBox.confirm(`确认å é¤éä¸ç ${ids.length} æ¡è®°å½ï¼`, "æç¤º", { type: "warning" }) .then(() => apiDelReagent(ids).then(() => { ElMessage.success("å 餿å"); loadReagent(); loadReagentOptions(); })) .catch(() => {}); }; const delReagent = () => { const ids = reSelected.value.map((r) => r.id); if (!ids.length) return ElMessage.warning("请å éæ©è¦å é¤çè®°å½"); doDelReagent(ids); }; /* ==================== åºå ¥åº ==================== */ const stockDialogVisible = ref(false); const stockType = ref("in"); const stockForm = ref({}); const stockReagent = ref(null); const openStockDialog = (type) => { stockType.value = type; stockForm.value = { reagentId: null, quantity: null, batchNo: "" }; stockReagent.value = null; loadReagentOptions(); stockDialogVisible.value = true; }; const onStockReagentChange = (id) => { stockReagent.value = reOptions.value.find((r) => r.id === id) || null; }; const submitStock = () => { const f = stockForm.value; if (!f.reagentId) return ElMessage.warning("è¯·éæ©è¯å/èæ"); if (!f.quantity || f.quantity <= 0) return ElMessage.warning("请è¾å ¥æ£ç¡®æ°é"); const re = stockReagent.value || {}; const before = Number(re.currentStock || 0); const qty = Number(f.quantity); if (stockType.value === "out" && qty > before) { return ElMessage.warning(`åºåä¸è¶³ï¼å½ååºå ${before}`); } const after = stockType.value === "in" ? before + qty : before - qty; const payload = { ...f, reagentCode: re.reagentCode, reagentName: re.reagentName, recordType: stockType.value, beforeStock: before, afterStock: after, operateTime: formatNow(), totalAmount: f.unitPrice ? Number(f.unitPrice) * qty : null, }; addReagentRecord(payload).then(() => { // åæ¥æ´æ°å°è´¦åºå updateReagent({ id: re.id, currentStock: after }).then(() => { ElMessage.success(stockType.value === "in" ? "å ¥åºæå" : "åºåºæå"); stockDialogVisible.value = false; loadReagent(); loadReagentOptions(); }); }); }; const formatNow = () => { const d = new Date(); const p = (n) => String(n).padStart(2, "0"); return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`; }; onMounted(() => { loadInstrument(); loadReagent(); loadReagentOptions(); }); </script> <style scoped> .search_form { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; flex-wrap: wrap; gap: 8px; } .search_title { font-size: 14px; color: #606266; } .table_list { margin-top: 8px; } </style> src/views/lims/systemConfig/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,442 @@ <template> <div class="app-container"> <el-tabs v-model="activeTab" type="border-card"> <!-- ==================== Tab1: æ£æµé¡¹ç® ==================== --> <el-tab-pane label="æ£æµé¡¹ç®åº" name="testItem"> <div class="search_form"> <div> <span class="search_title">项ç®ç¼å·ï¼</span> <el-input v-model="itemSearch.itemCode" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadItem" /> <span class="search_title" style="margin-left: 16px">项ç®åç§°ï¼</span> <el-input v-model="itemSearch.itemName" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadItem" /> <span class="search_title" style="margin-left: 16px">ç±»åï¼</span> <el-select v-model="itemSearch.itemType" style="width: 140px" placeholder="å ¨é¨" clearable @change="loadItem"> <el-option label="åå¦åæ" value="chemical" /><el-option label="ç©çæµè¯" value="physical" /> <el-option label="å¾®çç©" value="microbial" /><el-option label="å ¶å®" value="other" /> </el-select> <el-button type="primary" style="margin-left: 10px" @click="loadItem">æç´¢</el-button> </div> <div> <el-button type="primary" @click="openItemForm('add')">æ°å¢é¡¹ç®</el-button> <el-button type="danger" plain @click="delItem">å é¤</el-button> </div> </div> <PIMTable rowKey="id" :column="itemColumns" :tableData="itemData" :page="itemPage" :isSelection="true" :tableLoading="itemLoading" @selection-change="(v) => (itemSelected = v)" @pagination="paginationItem" /> </el-tab-pane> <!-- ==================== Tab2: 计éåä½ ==================== --> <el-tab-pane label="计éåä½åº" name="unit"> <div class="search_form"> <div> <span class="search_title">åä½ç¼ç ï¼</span> <el-input v-model="unitSearch.unitCode" style="width: 160px" placeholder="请è¾å ¥" clearable @change="loadUnit" /> <span class="search_title" style="margin-left: 16px">åä½åç§°ï¼</span> <el-input v-model="unitSearch.unitName" style="width: 160px" placeholder="请è¾å ¥" clearable @change="loadUnit" /> <span class="search_title" style="margin-left: 16px">ç±»åï¼</span> <el-select v-model="unitSearch.unitType" style="width: 150px" placeholder="å ¨é¨" clearable @change="loadUnit"> <el-option label="éé" value="weight" /><el-option label="ä½ç§¯" value="volume" /> <el-option label="é¿åº¦" value="length" /><el-option label="温度" value="temperature" /> <el-option label="æµåº¦" value="concentration" /><el-option label="计æ°" value="count" /> </el-select> <el-button type="primary" style="margin-left: 10px" @click="loadUnit">æç´¢</el-button> </div> <div> <el-button type="primary" @click="openUnitForm('add')">æ°å¢åä½</el-button> <el-button type="danger" plain @click="delUnit">å é¤</el-button> </div> </div> <PIMTable rowKey="id" :column="unitColumns" :tableData="unitData" :page="unitPage" :isSelection="true" :tableLoading="unitLoading" @selection-change="(v) => (unitSelected = v)" @pagination="paginationUnit" /> </el-tab-pane> <!-- ==================== Tab3: å¤å®æ å ==================== --> <el-tab-pane label="å¤å®æ ååº" name="standard"> <div class="search_form"> <div> <span class="search_title">æ åç¼å·ï¼</span> <el-input v-model="stdSearch.standardCode" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadStd" /> <span class="search_title" style="margin-left: 16px">æ ååç§°ï¼</span> <el-input v-model="stdSearch.standardName" style="width: 180px" placeholder="请è¾å ¥" clearable @change="loadStd" /> <el-button type="primary" style="margin-left: 10px" @click="loadStd">æç´¢</el-button> </div> <div> <el-button type="primary" @click="openStdForm('add')">æ°å¢æ å</el-button> <el-button type="danger" plain @click="delStd">å é¤</el-button> </div> </div> <PIMTable rowKey="id" :column="stdColumns" :tableData="stdData" :page="stdPage" :isSelection="true" :tableLoading="stdLoading" @selection-change="(v) => (stdSelected = v)" @pagination="paginationStd" /> </el-tab-pane> </el-tabs> <!-- ==================== æ£æµé¡¹ç®è¡¨å ==================== --> <el-dialog v-model="itemDialogVisible" :title="itemOpType === 'add' ? 'æ°å¢æ£æµé¡¹ç®' : 'ç¼è¾æ£æµé¡¹ç®'" width="70%"> <el-form ref="itemFormRef" :model="itemForm" label-position="top" :rules="itemRules"> <el-row :gutter="24"> <el-col :span="12"><el-form-item label="项ç®ç¼å·" prop="itemCode"><el-input v-model="itemForm.itemCode" placeholder="å¦ PHãCODãSS" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="项ç®åç§°" prop="itemName"><el-input v-model="itemForm.itemName" placeholder="å¦ pHå¼ãåå¦éæ°§é" /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="ç±»å"> <el-select v-model="itemForm.itemType" style="width: 100%"> <el-option label="åå¦åæ" value="chemical" /><el-option label="ç©çæµè¯" value="physical" /> <el-option label="å¾®çç©" value="microbial" /><el-option label="å ¶å®" value="other" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="计éåä½"><el-input v-model="itemForm.unit" placeholder="å¦ mg/Lã%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ£æµæ¹æ³"><el-input v-model="itemForm.method" placeholder="å¦ ç»ççµææ³" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ§è¡æ å"><el-input v-model="itemForm.standard" placeholder="å¦ GB/T 6920-1986" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åæ ¼ä¸é"><el-input-number v-model="itemForm.limitMin" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åæ ¼ä¸é"><el-input-number v-model="itemForm.limitMax" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="itemForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="itemDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitItem">ç¡®å®</el-button> </template> </el-dialog> <!-- ==================== 计éåä½è¡¨å ==================== --> <el-dialog v-model="unitDialogVisible" :title="unitOpType === 'add' ? 'æ°å¢è®¡éåä½' : 'ç¼è¾è®¡éåä½'" width="600px"> <el-form ref="unitFormRef" :model="unitForm" label-position="top" :rules="unitRules"> <el-row :gutter="16"> <el-col :span="12"><el-form-item label="åä½ç¼ç " prop="unitCode"><el-input v-model="unitForm.unitCode" placeholder="å¦ mg" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="åä½åç§°" prop="unitName"><el-input v-model="unitForm.unitName" placeholder="å¦ æ¯«å " /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="ç±»å"> <el-select v-model="unitForm.unitType" style="width: 100%"> <el-option label="éé" value="weight" /><el-option label="ä½ç§¯" value="volume" /> <el-option label="é¿åº¦" value="length" /><el-option label="温度" value="temperature" /> <el-option label="æµåº¦" value="concentration" /><el-option label="计æ°" value="count" /> </el-select> </el-form-item> </el-col> <el-col :span="12"><el-form-item label="åºååä½"><el-input v-model="unitForm.baseUnit" placeholder="å¦ gï¼ééåºåï¼" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ¢ç®ç³»æ°"><el-input-number v-model="unitForm.conversionRate" :precision="6" :min="0" style="width: 100%" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="unitForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="unitDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitUnit">ç¡®å®</el-button> </template> </el-dialog> <!-- ==================== å¤å®æ å表å ==================== --> <el-dialog v-model="stdDialogVisible" :title="stdOpType === 'add' ? 'æ°å¢å¤å®æ å' : 'ç¼è¾å¤å®æ å'" width="70%"> <el-form ref="stdFormRef" :model="stdForm" label-position="top" :rules="stdRules"> <el-row :gutter="24"> <el-col :span="12"><el-form-item label="æ åç¼å·" prop="standardCode"><el-input v-model="stdForm.standardCode" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"><el-form-item label="æ ååç§°" prop="standardName"><el-input v-model="stdForm.standardName" placeholder="请è¾å ¥" /></el-form-item></el-col> <el-col :span="12"> <el-form-item label="å ³èæ£æµé¡¹ç®"> <el-select v-model="stdForm.itemId" style="width: 100%" placeholder="è¯·éæ©" filterable clearable @change="onStdItemChange"> <el-option v-for="i in itemOptions" :key="i.id" :label="`${i.itemName}ï¼${i.itemCode}ï¼`" :value="i.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="å¤å®ç±»å"> <el-select v-model="stdForm.standardType" style="width: 100%"> <el-option label="åºé´ï¼ä¸é~ä¸éï¼" value="range" /><el-option label="ä¸ä½äº" value="min" /> <el-option label="ä¸é«äº" value="max" /><el-option label="çäº" value="equal" /> <el-option label="ç®æ å¼Â±åå·®" value="target" /> </el-select> </el-form-item> </el-col> <el-col :span="8"><el-form-item label="ä¸é"><el-input-number v-model="stdForm.minValue" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="ä¸é"><el-input-number v-model="stdForm.maxValue" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="åä½"><el-input v-model="stdForm.unit" placeholder="å¦ mg/L" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="ç®æ å¼"><el-input-number v-model="stdForm.targetValue" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="å 许åå·®"><el-input-number v-model="stdForm.deviation" :precision="4" style="width: 100%" /></el-form-item></el-col> <el-col :span="8"><el-form-item label="便®æ å"><el-input v-model="stdForm.sourceStandard" placeholder="å¦ GB 5749-2022" /></el-form-item></el-col> <el-col :span="24"><el-form-item label="夿³¨"><el-input v-model="stdForm.remark" type="textarea" :rows="2" /></el-form-item></el-col> </el-row> </el-form> <template #footer> <el-button @click="stdDialogVisible = false">åæ¶</el-button> <el-button type="primary" @click="submitStd">ç¡®å®</el-button> </template> </el-dialog> </div> </template> <script setup> import { ref, reactive, onMounted } from "vue"; import { ElMessage, ElMessageBox } from "element-plus"; import { listTestItem, getTestItem, addTestItem, updateTestItem, delTestItem } from "@/api/lims/testItem"; import { listUnit, getUnit, addUnit, updateUnit, delUnit as apiDelUnit } from "@/api/lims/unit"; import { listJudgmentStandard, getJudgmentStandard, addJudgmentStandard, updateJudgmentStandard, delJudgmentStandard, } from "@/api/lims/judgmentStandard"; const activeTab = ref("testItem"); const itemOptions = ref([]); /* ==================== æ£æµé¡¹ç® ==================== */ const itemSearch = ref({}); const itemData = ref([]); const itemSelected = ref([]); const itemLoading = ref(false); const itemPage = reactive({ pageNum: 1, pageSize: 10, total: 0 }); const itemColumns = ref([ { label: "项ç®ç¼å·", prop: "itemCode", width: 130 }, { label: "项ç®åç§°", prop: "itemName", width: 200 }, { label: "ç±»å", prop: "itemType", width: 110 }, { label: "åä½", prop: "unit", width: 90 }, { label: "æ£æµæ¹æ³", prop: "method", width: 200 }, { label: "æ§è¡æ å", prop: "standard", width: 160 }, { label: "ä¸é", prop: "limitMin", width: 90 }, { label: "ä¸é", prop: "limitMax", width: 90 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 140, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => openItemForm("edit", row) }, { name: "å é¤", type: "text", clickFun: (row) => doDelItem([row.id]) }, ], }, ]); const loadItem = () => { itemLoading.value = true; listTestItem({ ...itemSearch.value, ...itemPage }).then((res) => { itemLoading.value = false; itemData.value = res.data.records || []; itemPage.total = res.data.total || 0; }).catch(() => (itemLoading.value = false)); }; const paginationItem = (p) => { itemPage.pageNum = p.pageNum; itemPage.pageSize = p.pageSize; loadItem(); }; const loadItemOptions = () => { listTestItem({ pageNum: 1, pageSize: 500 }).then((res) => { itemOptions.value = res.data.records || []; }); }; const itemDialogVisible = ref(false); const itemOpType = ref("add"); const itemFormRef = ref(null); const itemForm = ref({}); const itemRules = { itemCode: [{ required: true, message: "请è¾å ¥é¡¹ç®ç¼å·", trigger: "blur" }], itemName: [{ required: true, message: "请è¾å ¥é¡¹ç®åç§°", trigger: "blur" }], }; const openItemForm = (type, row) => { itemOpType.value = type; itemForm.value = { itemType: "chemical" }; if (type === "edit") getTestItem(row.id).then((res) => { itemForm.value = { ...res.data }; }); itemDialogVisible.value = true; }; const submitItem = () => { itemFormRef.value.validate((valid) => { if (!valid) return; const fn = itemOpType.value === "add" ? addTestItem : updateTestItem; fn(itemForm.value).then(() => { ElMessage.success("ä¿åæå"); itemDialogVisible.value = false; loadItem(); loadItemOptions(); }); }); }; const doDelItem = (ids) => { ElMessageBox.confirm(`确认å é¤éä¸ç ${ids.length} æ¡è®°å½ï¼`, "æç¤º", { type: "warning" }) .then(() => delTestItem(ids).then(() => { ElMessage.success("å 餿å"); loadItem(); loadItemOptions(); })) .catch(() => {}); }; const delItem = () => { const ids = itemSelected.value.map((r) => r.id); if (!ids.length) return ElMessage.warning("请å éæ©è®°å½"); doDelItem(ids); }; /* ==================== 计éåä½ ==================== */ const unitSearch = ref({}); const unitData = ref([]); const unitSelected = ref([]); const unitLoading = ref(false); const unitPage = reactive({ pageNum: 1, pageSize: 10, total: 0 }); const unitColumns = ref([ { label: "åä½ç¼ç ", prop: "unitCode", width: 130 }, { label: "åä½åç§°", prop: "unitName", width: 160 }, { label: "ç±»å", prop: "unitType", width: 130 }, { label: "åºååä½", prop: "baseUnit", width: 130 }, { label: "æ¢ç®ç³»æ°", prop: "conversionRate", width: 130 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 140, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => openUnitForm("edit", row) }, { name: "å é¤", type: "text", clickFun: (row) => doDelUnit([row.id]) }, ], }, ]); const loadUnit = () => { unitLoading.value = true; listUnit({ ...unitSearch.value, ...unitPage }).then((res) => { unitLoading.value = false; unitData.value = res.data.records || []; unitPage.total = res.data.total || 0; }).catch(() => (unitLoading.value = false)); }; const paginationUnit = (p) => { unitPage.pageNum = p.pageNum; unitPage.pageSize = p.pageSize; loadUnit(); }; const unitDialogVisible = ref(false); const unitOpType = ref("add"); const unitFormRef = ref(null); const unitForm = ref({}); const unitRules = { unitCode: [{ required: true, message: "请è¾å ¥åä½ç¼ç ", trigger: "blur" }], unitName: [{ required: true, message: "请è¾å ¥åä½åç§°", trigger: "blur" }], }; const openUnitForm = (type, row) => { unitOpType.value = type; unitForm.value = { unitType: "weight", conversionRate: 1 }; if (type === "edit") getUnit(row.id).then((res) => { unitForm.value = { ...res.data }; }); unitDialogVisible.value = true; }; const submitUnit = () => { unitFormRef.value.validate((valid) => { if (!valid) return; const fn = unitOpType.value === "add" ? addUnit : updateUnit; fn(unitForm.value).then(() => { ElMessage.success("ä¿åæå"); unitDialogVisible.value = false; loadUnit(); }); }); }; const doDelUnit = (ids) => { ElMessageBox.confirm(`确认å é¤éä¸ç ${ids.length} æ¡è®°å½ï¼`, "æç¤º", { type: "warning" }) .then(() => apiDelUnit(ids).then(() => { ElMessage.success("å 餿å"); loadUnit(); })) .catch(() => {}); }; const delUnit = () => { const ids = unitSelected.value.map((r) => r.id); if (!ids.length) return ElMessage.warning("请å éæ©è®°å½"); doDelUnit(ids); }; /* ==================== å¤å®æ å ==================== */ const stdSearch = ref({}); const stdData = ref([]); const stdSelected = ref([]); const stdLoading = ref(false); const stdPage = reactive({ pageNum: 1, pageSize: 10, total: 0 }); const stdColumns = ref([ { label: "æ åç¼å·", prop: "standardCode", width: 140 }, { label: "æ ååç§°", prop: "standardName", width: 200 }, { label: "æ£æµé¡¹ç®", prop: "itemName", width: 160 }, { label: "å¤å®ç±»å", prop: "standardType", width: 120 }, { label: "ä¸é", prop: "minValue", width: 100 }, { label: "ä¸é", prop: "maxValue", width: 100 }, { label: "åä½", prop: "unit", width: 90 }, { label: "便®æ å", prop: "sourceStandard", width: 160 }, { dataType: "action", label: "æä½", align: "center", fixed: "right", width: 140, operation: [ { name: "ç¼è¾", type: "text", clickFun: (row) => openStdForm("edit", row) }, { name: "å é¤", type: "text", clickFun: (row) => doDelStd([row.id]) }, ], }, ]); const loadStd = () => { stdLoading.value = true; listJudgmentStandard({ ...stdSearch.value, ...stdPage }).then((res) => { stdLoading.value = false; stdData.value = res.data.records || []; stdPage.total = res.data.total || 0; }).catch(() => (stdLoading.value = false)); }; const paginationStd = (p) => { stdPage.pageNum = p.pageNum; stdPage.pageSize = p.pageSize; loadStd(); }; const stdDialogVisible = ref(false); const stdOpType = ref("add"); const stdFormRef = ref(null); const stdForm = ref({}); const stdRules = { standardCode: [{ required: true, message: "请è¾å ¥æ åç¼å·", trigger: "blur" }], standardName: [{ required: true, message: "请è¾å ¥æ ååç§°", trigger: "blur" }], }; const openStdForm = (type, row) => { stdOpType.value = type; stdForm.value = { standardType: "range" }; if (type === "edit") getJudgmentStandard(row.id).then((res) => { stdForm.value = { ...res.data }; }); stdDialogVisible.value = true; }; const onStdItemChange = (id) => { const it = itemOptions.value.find((i) => i.id === id); if (it) { stdForm.value.itemName = it.itemName; if (!stdForm.value.unit) stdForm.value.unit = it.unit; } }; const submitStd = () => { stdFormRef.value.validate((valid) => { if (!valid) return; const fn = stdOpType.value === "add" ? addJudgmentStandard : updateJudgmentStandard; fn(stdForm.value).then(() => { ElMessage.success("ä¿åæå"); stdDialogVisible.value = false; loadStd(); }); }); }; const doDelStd = (ids) => { ElMessageBox.confirm(`确认å é¤éä¸ç ${ids.length} æ¡è®°å½ï¼`, "æç¤º", { type: "warning" }) .then(() => delJudgmentStandard(ids).then(() => { ElMessage.success("å 餿å"); loadStd(); })) .catch(() => {}); }; const delStd = () => { const ids = stdSelected.value.map((r) => r.id); if (!ids.length) return ElMessage.warning("请å éæ©è®°å½"); doDelStd(ids); }; onMounted(() => { loadItem(); loadItemOptions(); loadUnit(); loadStd(); }); </script> <style scoped> .search_form { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; flex-wrap: wrap; gap: 8px; } .search_title { font-size: 14px; color: #606266; } </style>