src/api/equipmentManagement/calibration.js
@@ -24,4 +24,12 @@ method: "post", data: query, }); } // å é¤è®°å½ export function ledgerRecordDelete(ids) { return request({ url: "/measuringInstrumentLedgerRecord/delete", method: "delete", data: ids, }); } src/api/equipmentManagement/ledger.js
@@ -42,11 +42,3 @@ method: "get", }); }; // 设å¤å°è´¦å¾è¡¨ export const getAssetInfo = (params) => { return request({ url: "/device/ledger/report/forms", method: "get", params }); } src/api/equipmentManagement/upkeep.js
@@ -70,3 +70,35 @@ method: "delete", }); }; // æ·»å 设å¤ä¿å »å®æ¶ä»»å¡ export const deviceMaintenanceTaskAdd = (params) => { return request({ url: '/deviceMaintenanceTask/add', method: "post", data: params, }); }; // ä¿®æ¹è®¾å¤ä¿å »å®æ¶ä»»å¡ export const deviceMaintenanceTaskEdit = (params) => { return request({ url: '/deviceMaintenanceTask/update', method: "post", data: params, }); }; // 设å¤ä¿å »å®æ¶ä»»å¡å表 export const deviceMaintenanceTaskList = (params) => { return request({ url: '/deviceMaintenanceTask/listPage', method: "get", params: params, }); }; // 设å¤ä¿å »å®æ¶ä»»å¡å表 export const deviceMaintenanceTaskDel = (params) => { return request({ url: '/deviceMaintenanceTask/delete', method: "delete", data: params, }); }; src/api/procurementManagement/procurementLedger.js
@@ -78,4 +78,24 @@ method: "post", data: query, }); } } // ä¿åéè´æ¨¡æ¿ // /purchase/ledger/addPurchaseTemplate export function addPurchaseTemplate(data) { return request({ url: "/purchase/ledger/addPurchaseTemplate", method: "post", data: data, }); } // æ¥è¯¢éè´æ¨¡æ¿ // /purchase/ledger/getPurchaseTemplateList export function getPurchaseTemplateList(query) { return request({ url: "/purchase/ledger/getPurchaseTemplateList", method: "get", params: query, }); } src/utils/index.js
@@ -396,3 +396,16 @@ export function isEqual(obj1, obj2) { return JSON.stringify(obj1) === JSON.stringify(obj2); } /** * è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD * @returns {string} æ ¼å¼åçæ¥æå符串 */ export function getCurrentDate() { const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, '0'); // æä»½ä»0å¼å§ const day = String(today.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } src/views/equipmentManagement/calibration/index.vue
@@ -57,10 +57,10 @@ <script setup> import {onMounted, ref} from "vue"; import {ElMessageBox} from "element-plus"; import {ElMessageBox, ElMessage} from "element-plus"; import useUserStore from "@/store/modules/user.js"; import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; import {ledgerRecordListPage} from "@/api/equipmentManagement/calibration.js"; import {ledgerRecordListPage, ledgerRecordDelete} from "@/api/equipmentManagement/calibration.js"; const { proxy } = getCurrentInstance(); const userStore = useUserStore() @@ -134,6 +134,7 @@ { dataType: "action", label: "æä½", width: 140, align: "center", fixed: 'right', operation: [ @@ -142,7 +143,17 @@ type: "text", clickFun: (row) => { openCalibrationDia("edit", row); } }, }, { name: "å é¤", type: "text", style: { color: "#F56C6C" }, clickFun: (row) => { handleDelete(row); }, }, ], }, @@ -191,6 +202,26 @@ }) } // å é¤è®°å½ const handleDelete = (row) => { ElMessageBox.confirm(`确认å é¤è®¡éå¨å ·ç¼å·ä¸º"${row.code}"çæ£å®è®°å½åï¼`, "å é¤ç¡®è®¤", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { ledgerRecordDelete([row.id]).then(() => { ElMessage.success("å 餿å"); getList(); }).catch(() => { ElMessage.error("å é¤å¤±è´¥"); }); }) .catch(() => { proxy.$modal.msg("已忶å é¤"); }); }; // å¯¼åº const handleOut = () => { ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -1,102 +1,116 @@ <template> <div> <el-dialog :title="operationType === 'add' ? 'æ°å¢å·¡æ£ä»»å¡' : 'ç¼è¾å·¡æ£ä»»å¡'" v-model="dialogVisitable" width="800px" @close="cancel"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> <el-row> <el-col :span="12"> <el-form-item label="设å¤åç§°" prop="taskId"> <el-select v-model="form.taskId" @change="setDeviceModel"> <el-option v-for="(item, index) in deviceOptions" :key="index" :label="item.deviceName" :value="item.id" ></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="å·¡æ£äºº" prop="inspector"> <el-select v-model="form.inspector" placeholder="è¯·éæ©" multiple clearable> <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="夿³¨" prop="remarks"> <el-input v-model="form.remarks" placeholder="请è¾å ¥å¤æ³¨" type="textarea" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> <el-option label="æ¯æ¥" value="DAILY"/> <el-option label="æ¯å¨" value="WEEKLY"/> <el-option label="æ¯æ" value="MONTHLY"/> <!-- <el-option label="å£åº¦" value="QUARTERLY"/> --> </el-select> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> <el-option label="å¨ä¸" value="MON"/> <el-option label="å¨äº" value="TUE"/> <el-option label="å¨ä¸" value="WED"/> <el-option label="å¨å" value="THU"/> <el-option label="å¨äº" value="FRI"/> <el-option label="å¨å " value="SAT"/> <el-option label="卿¥" value="SUN"/> </el-select> <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" style="width: 50%"/> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="DD,HH:mm" value-format="DD,HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="MM,DD,HH:mm" value-format="MM,DD,HH:mm" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button @click="cancel">åæ¶</el-button> <el-button type="primary" @click="submitForm">ä¿å</el-button> </div> </template> </el-dialog> </div> <div> <el-dialog :title="operationType === 'add' ? 'æ°å¢å·¡æ£ä»»å¡' : 'ç¼è¾å·¡æ£ä»»å¡'" v-model="dialogVisitable" width="800px" @close="cancel"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> <el-row> <el-col :span="12"> <el-form-item label="设å¤åç§°" prop="taskId"> <el-select v-model="form.taskId" @change="setDeviceModel" filterable> <el-option v-for="(item, index) in deviceOptions" :key="index" :label="item.deviceName" :value="item.id" ></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="å·¡æ£äºº" prop="inspector"> <el-select v-model="form.inspector" filterable default-first-option :reserve-keyword="false" placeholder="è¯·éæ©" multiple clearable> <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="夿³¨" prop="remarks"> <el-input v-model="form.remarks" placeholder="请è¾å ¥å¤æ³¨" type="textarea" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç»è®°æ¶é´" prop="dateStr"> <el-date-picker v-model="form.dateStr" type="date" placeholder="éæ©ç»è®°æ¥æ" format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width: 100%" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> <el-option label="æ¯æ¥" value="DAILY"/> <el-option label="æ¯å¨" value="WEEKLY"/> <el-option label="æ¯æ" value="MONTHLY"/> <!-- <el-option label="å£åº¦" value="QUARTERLY"/> --> </el-select> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> <el-option label="å¨ä¸" value="MON"/> <el-option label="å¨äº" value="TUE"/> <el-option label="å¨ä¸" value="WED"/> <el-option label="å¨å" value="THU"/> <el-option label="å¨äº" value="FRI"/> <el-option label="å¨å " value="SAT"/> <el-option label="卿¥" value="SUN"/> </el-select> <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" style="width: 50%"/> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="DD,HH:mm" value-format="DD,HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="MM,DD,HH:mm" value-format="MM,DD,HH:mm" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button @click="cancel">åæ¶</el-button> <el-button type="primary" @click="submitForm">ä¿å</el-button> </div> </template> </el-dialog> </div> </template> <script setup> @@ -113,115 +127,117 @@ const operationType = ref('add'); const deviceOptions = ref([]); const data = reactive({ form: { taskId: undefined, taskName: undefined, inspector: '', inspectorIds: '', remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '' }, rules: { taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], inspector: [{ required: true, message: "请è¾å ¥å·¡æ£äºº", trigger: "blur" },], } form: { taskId: undefined, taskName: undefined, inspector: '', inspectorIds: '', remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '', dateStr: '' }, rules: { taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], inspector: [{ required: true, message: "请è¾å ¥å·¡æ£äºº", trigger: "blur" },], dateStr: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }] } }) const { form, rules } = toRefs(data) const userList = ref([]) const loadDeviceName = async () => { const { data } = await getDeviceLedger(); deviceOptions.value = data; const { data } = await getDeviceLedger(); deviceOptions.value = data; }; const setDeviceModel = (id) => { const option = deviceOptions.value.find((item) => item.id === id); if (option) { form.value.taskName = option.deviceName; } const option = deviceOptions.value.find((item) => item.id === id); if (option) { form.value.taskName = option.deviceName; } } // æå¼å¼¹æ¡ const openDialog = async (type, row) => { dialogVisitable.value = true operationType.value = type // é置表å resetForm(); // å è½½ç¨æ·å表 userListNoPageByTenantId().then((res) => { userList.value = res.data; }); // å 载设å¤å表 await loadDeviceName(); if (type === 'edit' && row) { form.value = {...row} form.value.inspector = form.value.inspectorIds.split(',').map(Number) // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ if (form.value.taskId) { setDeviceModel(form.value.taskId); } } dialogVisitable.value = true operationType.value = type // é置表å resetForm(); // å è½½ç¨æ·å表 userListNoPageByTenantId().then((res) => { userList.value = res.data; }); // å 载设å¤å表 await loadDeviceName(); if (type === 'edit' && row) { form.value = {...row} form.value.inspector = form.value.inspectorIds.split(',').map(Number) // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ if (form.value.taskId) { setDeviceModel(form.value.taskId); } } } // å ³éå¯¹è¯æ¡ const cancel = () => { resetForm() dialogVisitable.value = false emit('closeDia') resetForm() dialogVisitable.value = false emit('closeDia') } // é置表å彿° const resetForm = () => { if (proxy.$refs.formRef) { proxy.$refs.formRef.resetFields() } // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® form.value = { taskId: undefined, taskName: undefined, inspector: '', inspectorIds: '', remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '' } if (proxy.$refs.formRef) { proxy.$refs.formRef.resetFields() } // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® form.value = { taskId: undefined, taskName: undefined, inspector: '', inspectorIds: '', remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '' } } // æäº¤è¡¨å const submitForm = () => { proxy.$refs["formRef"].validate(async valid => { if (valid) { try { form.value.inspectorIds = form.value.inspector.join(',') delete form.value.inspector if (form.value.frequencyType === 'WEEKLY') { let frequencyDetail = '' frequencyDetail = form.value.week + ',' + form.value.time form.value.frequencyDetail = frequencyDetail } let res = await userStore.getInfo() form.value.registrantId = res.user.userId await addOrEditTimingTask(form.value) cancel() proxy.$modal.msgSuccess('æäº¤æå') } catch (error) { proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') } } }) proxy.$refs["formRef"].validate(async valid => { if (valid) { try { form.value.inspectorIds = form.value.inspector.join(',') delete form.value.inspector if (form.value.frequencyType === 'WEEKLY') { let frequencyDetail = '' frequencyDetail = form.value.week + ',' + form.value.time form.value.frequencyDetail = frequencyDetail } let res = await userStore.getInfo() form.value.registrantId = res.user.userId await addOrEditTimingTask(form.value) cancel() proxy.$modal.msgSuccess('æäº¤æå') } catch (error) { proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') } } }) } defineExpose({ openDialog }) </script> src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -32,7 +32,7 @@ <!-- ç产å --> <div class="form-container"> <div class="title">ç产å</div> <div class="title">ç产ä¸</div> <!-- å¾çå表 --> <div style="display: flex; flex-wrap: wrap;"> @@ -59,7 +59,7 @@ <!-- ç产é®é¢ --> <div class="form-container"> <div class="title">ç产é®é¢</div> <div class="title">ç产å</div> <!-- å¾çå表 --> <div style="display: flex; flex-wrap: wrap;"> src/views/equipmentManagement/inspectionManagement/index.vue
@@ -1,80 +1,78 @@ <template> <div class="app-container"> <el-form :inline="true" :model="queryParams" class="search-form"> <el-form-item label="æç´¢"> <el-input v-model="queryParams.searchAll" placeholder="请è¾å ¥å ³é®å" clearable :style="{ width: '100%' }" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">æ¥è¯¢</el-button> <el-button @click="resetQuery">éç½®</el-button> </el-form-item> </el-form> <el-card> <div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom: 10px;"> <el-radio-group v-model="activeRadio" @change="radioChange"> <el-radio-button v-for="tab in radios" :key="tab.name" :label="tab.label" :value="tab.name"/> </el-radio-group> <!-- æä½æé®åº --> <el-space v-if="activeRadio !== 'task'"> <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">æ°å»º</el-button> <el-button type="danger" :icon="Delete" @click="handleDelete">å é¤</el-button> <el-button @click="handleOut">导åº</el-button> </el-space> <el-space v-else> <el-button @click="handleOut">导åº</el-button> </el-space> </div> <div> <div> <PIMTable :table-loading="tableLoading" :table-data="tableData" :column="tableColumns" @selection-change="handleSelectionChange" :is-selection="true" :border="true" :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }" > <template #inspector="{ row }"> <div class="person-tags"> <!-- è°è¯ä¿¡æ¯ï¼ä¸çº¿æ¶å é¤ --> <!-- {{ console.log('inspector data:', row.inspector) }} --> <template v-if="row.inspector && row.inspector.length > 0"> <el-tag v-for="(person, index) in row.inspector" :key="index" size="small" type="primary" class="person-tag" > {{ person }} </el-tag> </template> <span v-else class="no-data">--</span> </div> </template> </PIMTable> </div> <pagination v-if="total>0" :page="pageNum" :limit="pageSize" :total="total" @pagination="handlePagination" :layout="'total, prev, pager, next, jumper'" /> </div> </el-card> <form-dia ref="formDia" @closeDia="handleQuery"></form-dia> <view-files ref="viewFiles"></view-files> </div> <div class="app-container"> <el-form :inline="true" :model="queryParams" class="search-form"> <el-form-item label="æç´¢"> <el-input v-model="queryParams.searchAll" placeholder="请è¾å ¥å ³é®å" clearable :style="{ width: '100%' }" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">æ¥è¯¢</el-button> <el-button @click="resetQuery">éç½®</el-button> </el-form-item> </el-form> <el-card> <div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom: 10px;"> <el-radio-group v-model="activeRadio" @change="radioChange"> <el-radio-button v-for="tab in radios" :key="tab.name" :label="tab.label" :value="tab.name"/> </el-radio-group> <!-- æä½æé®åº --> <el-space v-if="activeRadio !== 'task'"> <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">æ°å»º</el-button> <el-button type="danger" :icon="Delete" @click="handleDelete">å é¤</el-button> <el-button @click="handleOut">导åº</el-button> </el-space> <el-space v-else> <el-button @click="handleOut">导åº</el-button> </el-space> </div> <div> <div> <PIMTable :table-loading="tableLoading" :table-data="tableData" :column="tableColumns" @selection-change="handleSelectionChange" :is-selection="true" :border="true" :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }" :page="{ current: pageNum, size: pageSize, total: total, }" @pagination="pagination" > <template #inspector="{ row }"> <div class="person-tags"> <!-- è°è¯ä¿¡æ¯ï¼ä¸çº¿æ¶å é¤ --> <!-- {{ console.log('inspector data:', row.inspector) }} --> <template v-if="row.inspector && row.inspector.length > 0"> <el-tag v-for="(person, index) in row.inspector" :key="index" size="small" type="primary" class="person-tag" > {{ person }} </el-tag> </template> <span v-else class="no-data">--</span> </div> </template> </PIMTable> </div> </div> </el-card> <form-dia ref="formDia" @closeDia="handleQuery"></form-dia> <view-files ref="viewFiles"></view-files> </div> </template> <script setup> @@ -90,9 +88,9 @@ // æ¥å£å¼å ¥ import { delTimingTask, inspectionTaskList, timingTaskList delTimingTask, inspectionTaskList, timingTaskList } from "@/api/inspectionManagement/index.js"; // å ¨å±åé @@ -102,14 +100,14 @@ // æ¥è¯¢åæ° const queryParams = reactive({ searchAll: "", searchAll: "", }); // åéæ¡é ç½® const activeRadio = ref("taskManage"); const radios = reactive([ { name: "taskManage", label: "宿¶ä»»å¡ç®¡ç" }, { name: "task", label: "宿¶ä»»å¡è®°å½" }, { name: "taskManage", label: "宿¶ä»»å¡ç®¡ç" }, { name: "task", label: "宿¶ä»»å¡è®°å½" }, ]); // è¡¨æ ¼æ°æ® @@ -124,234 +122,233 @@ // åé ç½® const columns = ref([ { prop: "taskName", label: "å·¡æ£ä»»å¡åç§°", minWidth: 160 }, { prop: "remarks", label: "夿³¨", minWidth: 150 }, { prop: "inspector", label: "æ§è¡å·¡æ£äºº", minWidth: 150, slot: "inspector" }, { prop: "frequencyType", label: "颿¬¡", minWidth: 150, formatter: (_, __, val) => ({ DAILY: "æ¯æ¥", WEEKLY: "æ¯å¨", MONTHLY: "æ¯æ", QUARTERLY: "å£åº¦" }[val] || "") }, { prop: "frequencyDetail", label: "å¼å§æ¥æä¸æ¶é´", minWidth: 150, formatter: (row, column, cellValue) => { // å 夿æ¯å¦æ¯å符串 if (typeof cellValue !== 'string') return ''; let val = cellValue; const replacements = { MON: 'å¨ä¸', TUE: 'å¨äº', WED: 'å¨ä¸', THU: 'å¨å', FRI: 'å¨äº', SAT: 'å¨å ', SUN: '卿¥' }; // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é 项 return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]); } }, { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, { prop: "createTime", label: "ç»è®°æ¥æ", minWidth: 100 }, { prop: "taskName", label: "å·¡æ£ä»»å¡åç§°", minWidth: 160 }, { prop: "remarks", label: "夿³¨", minWidth: 150 }, { prop: "inspector", label: "æ§è¡å·¡æ£äºº", minWidth: 150, slot: "inspector" }, { prop: "frequencyType", label: "颿¬¡", minWidth: 150, formatData: (cell) => ({ DAILY: "æ¯æ¥", WEEKLY: "æ¯å¨", MONTHLY: "æ¯æ", QUARTERLY: "å£åº¦" }[cell] || "") }, { prop: "frequencyDetail", label: "å¼å§æ¥æä¸æ¶é´", minWidth: 150, formatter: (row, column, cellValue) => { // å 夿æ¯å¦æ¯å符串 if (typeof cellValue !== 'string') return ''; let val = cellValue; const replacements = { MON: 'å¨ä¸', TUE: 'å¨äº', WED: 'å¨ä¸', THU: 'å¨å', FRI: 'å¨äº', SAT: 'å¨å ', SUN: '卿¥' }; // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é 项 return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]); } }, { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, { prop: "dateStr", label: "ç»è®°æ¥æ", minWidth: 100 }, ]); // æä½åé ç½® const getOperationColumn = (operations) => { if (!operations || operations.length === 0) return null; const operationConfig = { label: "æä½", width: 130, fixed: "right", dataType: "action", operation: operations.map(op => { switch (op) { case 'edit': return { name: "ç¼è¾", clickFun: handleAdd, color: "#409EFF" }; case 'viewFile': return { name: "æ¥çéä»¶", clickFun: viewFile, color: "#67C23A" }; default: return null; } }).filter(Boolean) }; return operationConfig; if (!operations || operations.length === 0) return null; const operationConfig = { label: "æä½", width: 130, fixed: "right", dataType: "action", operation: operations.map(op => { switch (op) { case 'edit': return { name: "ç¼è¾", clickFun: handleAdd, color: "#409EFF" }; case 'viewFile': return { name: "æ¥çéä»¶", clickFun: viewFile, color: "#67C23A" }; default: return null; } }).filter(Boolean) }; return operationConfig; }; onMounted(() => { radioChange('taskManage'); radioChange('taskManage'); }); // åéåå const radioChange = (value) => { if (value === "taskManage") { const operationColumn = getOperationColumn(['edit']); tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])]; operationsArr.value = ['edit']; } else if (value === "task") { const operationColumn = getOperationColumn(['viewFile']); tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])]; operationsArr.value = ['viewFile']; } pageNum.value = 1; pageSize.value = 10; getList(); if (value === "taskManage") { const operationColumn = getOperationColumn(['edit']); tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])]; operationsArr.value = ['edit']; } else if (value === "task") { const operationColumn = getOperationColumn(['viewFile']); tableColumns.value = [...columns.value, ...(operationColumn ? [operationColumn] : [])]; operationsArr.value = ['viewFile']; } pageNum.value = 1; pageSize.value = 10; getList(); }; // æ¥è¯¢æä½ const handleQuery = () => { pageNum.value = 1; pageSize.value = 10; getList(); pageNum.value = 1; pageSize.value = 10; getList(); }; // å页å¤ç const handlePagination = (val) => { pageNum.value = val.page; pageSize.value = val.size; const pagination = (obj) => { pageNum.value = obj.page; pageSize.value = obj.limit; getList(); }; // è·ååè¡¨æ°æ® const getList = () => { tableLoading.value = true; const params = { ...queryParams, size: pageSize.value, current: pageNum.value }; let apiCall; if (activeRadio.value === "task") { apiCall = inspectionTaskList(params); } else { apiCall = timingTaskList(params); } apiCall.then(res => { const rawData = res.data.records || []; // å¤ç inspector åæ®µï¼å°å符串转æ¢ä¸ºæ°ç»ï¼éç¨äºæææ åµï¼ tableData.value = rawData.map(item => { const processedItem = { ...item }; // å¤ç inspector åæ®µ if (processedItem.inspector) { if (typeof processedItem.inspector === 'string') { // å符串æéå·åå² processedItem.inspector = processedItem.inspector.split(',').map(s => s.trim()).filter(s => s); } else if (!Array.isArray(processedItem.inspector)) { // éæ°ç»è½¬ä¸ºæ°ç» processedItem.inspector = [processedItem.inspector]; } } else { // 空å¼è®¾ä¸ºç©ºæ°ç» processedItem.inspector = []; } return processedItem; }); total.value = res.data.total || 0; }).finally(() => { tableLoading.value = false; }); tableLoading.value = true; const params = { ...queryParams, size: pageSize.value, current: pageNum.value }; let apiCall; if (activeRadio.value === "task") { apiCall = inspectionTaskList(params); } else { apiCall = timingTaskList(params); } apiCall.then(res => { const rawData = res.data.records || []; // å¤ç inspector åæ®µï¼å°å符串转æ¢ä¸ºæ°ç»ï¼éç¨äºæææ åµï¼ tableData.value = rawData.map(item => { const processedItem = { ...item }; // å¤ç inspector åæ®µ if (processedItem.inspector) { if (typeof processedItem.inspector === 'string') { // å符串æéå·åå² processedItem.inspector = processedItem.inspector.split(',').map(s => s.trim()).filter(s => s); } else if (!Array.isArray(processedItem.inspector)) { // éæ°ç»è½¬ä¸ºæ°ç» processedItem.inspector = [processedItem.inspector]; } } else { // 空å¼è®¾ä¸ºç©ºæ°ç» processedItem.inspector = []; } return processedItem; }); total.value = res.data.total || 0; }).finally(() => { tableLoading.value = false; }); }; // éç½®æ¥è¯¢ const resetQuery = () => { for (const key in queryParams) { if (!["pageNum", "pageSize"].includes(key)) { queryParams[key] = ""; } } handleQuery(); for (const key in queryParams) { if (!["pageNum", "pageSize"].includes(key)) { queryParams[key] = ""; } } handleQuery(); }; // æ°å¢ / ç¼è¾ const handleAdd = (row) => { const type = row ? 'edit' : 'add'; nextTick(() => { formDia.value?.openDialog(type, row); }); const type = row ? 'edit' : 'add'; nextTick(() => { formDia.value?.openDialog(type, row); }); }; // æ¥çéä»¶ const viewFile = (row) => { nextTick(() => { viewFiles.value?.openDialog(row); }); nextTick(() => { viewFiles.value?.openDialog(row); }); }; // å é¤æä½ const handleDelete = () => { if (!selectedRows.value.length) { proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); return; } const deleteIds = selectedRows.value.map(item => item.id); proxy.$modal.confirm('æ¯å¦ç¡®è®¤å 餿鿰æ®é¡¹ï¼').then(() => { return delTimingTask(deleteIds); }).then(() => { proxy.$modal.msgSuccess("å 餿å"); handleQuery(); }).catch(() => {}); if (!selectedRows.value.length) { proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); return; } const deleteIds = selectedRows.value.map(item => item.id); proxy.$modal.confirm('æ¯å¦ç¡®è®¤å 餿鿰æ®é¡¹ï¼').then(() => { return delTimingTask(deleteIds); }).then(() => { proxy.$modal.msgSuccess("å 餿å"); handleQuery(); }).catch(() => {}); }; // å¤éåæ´ const handleSelectionChange = (selection) => { selectedRows.value = selection; selectedRows.value = selection; }; // å¯¼åº const handleOut = () => { ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { // æ ¹æ®å½åéä¸çæ ç¾é¡µè°ç¨ä¸åçå¯¼åºæ¥å£ if (activeRadio.value === "taskManage") { // 宿¶ä»»å¡ç®¡ç proxy.download("/timingTask/export", {}, "宿¶ä»»å¡ç®¡ç.xlsx"); } else if (activeRadio.value === "task") { // 宿¶ä»»å¡è®°å½ proxy.download("/inspectionTask/export", {}, "宿¶ä»»å¡è®°å½.xlsx"); } }) .catch(() => { proxy.$modal.msg("已忶"); }); ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { // æ ¹æ®å½åéä¸çæ ç¾é¡µè°ç¨ä¸åçå¯¼åºæ¥å£ if (activeRadio.value === "taskManage") { // 宿¶ä»»å¡ç®¡ç proxy.download("/timingTask/export", {}, "宿¶ä»»å¡ç®¡ç.xlsx"); } else if (activeRadio.value === "task") { // 宿¶ä»»å¡è®°å½ proxy.download("/inspectionTask/export", {}, "宿¶ä»»å¡è®°å½.xlsx"); } }) .catch(() => { proxy.$modal.msg("已忶"); }); }; </script> <style scoped> .person-tags { display: flex; flex-wrap: wrap; gap: 4px; display: flex; flex-wrap: wrap; gap: 4px; } .person-tag { margin-right: 4px; margin-bottom: 2px; margin-right: 4px; margin-bottom: 2px; } .no-data { color: #909399; font-size: 14px; color: #909399; font-size: 14px; } </style> src/views/equipmentManagement/ledger/Modal.vue
@@ -1,5 +1,5 @@ <template> <el-dialog :title="modalOptions.title" v-model="visible" @close="close"> <el-dialog :title="modalOptions.title" v-model="visible" @close="close" draggable> <Form ref="formRef"></Form> <template #footer> <el-button type="primary" @click="sendForm" :loading="loading"> src/views/equipmentManagement/ledger/index.vue
@@ -82,15 +82,14 @@ </PIMTable> </div> <Modal ref="modalRef" @success="getTableData"></Modal> <el-dialog v-model="qrDialogVisible" title="äºç»´ç " width="300px"> <div style="text-align:center;"> <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> <div style="margin-top:6px;font-size:14px;color:#333;">{{ qrRowData?.deviceName }}</div> <div style="margin:10px 0;"> <el-button type="primary" @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> </div> </div> </el-dialog> <el-dialog v-model="qrDialogVisible" title="äºç»´ç " width="300px" draggable> <div style="text-align:center;"> <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> <div style="margin:10px 0;"> <el-button type="primary" @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> </div> </div> </el-dialog> </div> </template> @@ -300,44 +299,10 @@ }; const downloadQRCode = () => { const name = qrRowData.value?.deviceName || "äºç»´ç "; const img = new Image(); img.src = qrCodeUrl.value; img.onload = () => { const padding = 10; const qrSize = 200; const textHeight = 24; // space for text const width = qrSize + padding * 2; const height = qrSize + padding * 2 + textHeight; const canvas = document.createElement("canvas"); canvas.width = width; canvas.height = height; const ctx = canvas.getContext("2d"); // background ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, width, height); // draw QR centered ctx.drawImage(img, padding, padding, qrSize, qrSize); // draw name centered below ctx.fillStyle = "#333"; ctx.font = "14px Arial"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; const maxTextWidth = width - padding * 2; let displayName = name; // ellipsis if too long while (ctx.measureText(displayName).width > maxTextWidth && displayName.length > 0) { displayName = displayName.slice(0, -1); } if (displayName !== name) displayName = displayName + "â¦"; ctx.fillText(displayName, width / 2, qrSize + padding + textHeight / 2); const dataUrl = canvas.toDataURL("image/png"); const a = document.createElement("a"); a.href = dataUrl; a.download = `${name}.png`; a.click(); }; const a = document.createElement("a"); a.href = qrCodeUrl.value; a.download = `${qrRowData.value.deviceName || "äºç»´ç "}.png`; a.click(); }; onMounted(() => { src/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue
@@ -4,6 +4,7 @@ v-model="dialogFormVisible" title="计éå¨å ·" width="50%" draggable @close="closeDia" > <el-form @@ -67,7 +68,9 @@ <el-select v-model="form.userId" placeholder="è¯·éæ©" disabled filterable default-first-option :reserve-keyword="false" clearable > <el-option @@ -129,6 +132,7 @@ import {getToken} from "@/utils/auth.js"; import {ledgerRecordUpdate, ledgerRecordVerifying} from "@/api/equipmentManagement/calibration.js"; import {delLedgerFile} from "@/api/salesManagement/salesLedger.js"; import { getCurrentDate } from "@/utils/index.js"; const { proxy } = getCurrentInstance() const emit = defineEmits(['close']) const dialogFormVisible = ref(false); @@ -248,14 +252,6 @@ dialogFormVisible.value = false; emit('close') }; // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD function getCurrentDate() { const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ const day = String(today.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; } defineExpose({ openDialog, }); src/views/equipmentManagement/measurementEquipment/components/formDia.vue
@@ -4,6 +4,7 @@ v-model="dialogFormVisible" title="计éå¨å ·" width="50%" draggable @close="closeDia" > <el-form @@ -64,7 +65,9 @@ v-model="form.userId" placeholder="è¯·éæ©" clearable disabled filterable default-first-option :reserve-keyword="false" > <el-option v-for="item in userList" @@ -124,6 +127,7 @@ import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js"; import {getToken} from "@/utils/auth.js"; import {measuringInstrumentAdd, measuringInstrumentUpdate} from "@/api/equipmentManagement/measurementEquipment.js"; import { getCurrentDate } from "@/utils/index.js"; const { proxy } = getCurrentInstance() const emit = defineEmits(['close']) const dialogFormVisible = ref(false); @@ -234,14 +238,6 @@ dialogFormVisible.value = false; emit('close') }; // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD function getCurrentDate() { const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ const day = String(today.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; } defineExpose({ openDialog, }); src/views/equipmentManagement/measurementEquipment/index.vue
@@ -148,13 +148,13 @@ openCalibrationDia("verifying", row); }, }, { name: "éä»¶", type: "text", clickFun: (row) => { openFilesFormDia(row); }, }, // { // name: "éä»¶", // type: "text", // clickFun: (row) => { // openFilesFormDia(row); // }, // }, ], }, ]); @@ -221,12 +221,6 @@ const handleDelete = () => { let ids = []; if (selectedRows.value.length > 0) { // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® const unauthorizedData = selectedRows.value.filter(item => item.userId !== userStore.id); if (unauthorizedData.length > 0) { proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); return; } ids = selectedRows.value.map((item) => item.id); } else { proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); src/views/equipmentManagement/repair/Form/MaintainForm.vue
@@ -6,6 +6,13 @@ <el-form-item label="ç»´ä¿®ç»æ"> <el-input v-model="form.maintenanceResult" placeholder="请è¾å ¥ç»´ä¿®ç»æ" /> </el-form-item> <el-form-item label="æ¥ä¿®ç¶æ"> <el-select v-model="form.status"> <el-option label="å¾ æ¥ä¿®" :value="0"></el-option> <el-option label="å®ç»" :value="1"></el-option> <el-option label="失败" :value="2"></el-option> </el-select> </el-form-item> <el-form-item label="ç»´ä¿®æ¥æ"> <el-date-picker v-model="form.maintenanceTime" @@ -34,6 +41,7 @@ maintenanceName: undefined, // ç»´ä¿®åç§° maintenanceResult: undefined, // ç»´ä¿®ç»æ maintenanceTime: undefined, // ç»´ä¿®æ¥æ status: 0, }); const setForm = (data) => { src/views/equipmentManagement/repair/Form/RepairForm.vue
@@ -3,7 +3,7 @@ <el-row> <el-col :span="12"> <el-form-item label="设å¤åç§°"> <el-select v-model="form.deviceLedgerId" @change="setDeviceModel"> <el-select v-model="form.deviceLedgerId" @change="setDeviceModel" filterable> <el-option v-for="(item, index) in deviceOptions" :key="index" @@ -40,6 +40,19 @@ <el-input v-model="form.repairName" placeholder="请è¾å ¥æ¥ä¿®äºº" /> </el-form-item> </el-col> </el-row> <el-row v-if="id"> <el-col :span="12"> <el-form-item label="æ¥ä¿®ç¶æ"> <el-select v-model="form.status"> <el-option label="å¾ ç»´ä¿®" :value="0"></el-option> <el-option label="å®ç»" :value="1"></el-option> <el-option label="失败" :value="2"></el-option> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="æ éç°è±¡"> <el-input @@ -55,9 +68,12 @@ </template> <script setup> import dayjs from "dayjs"; import useFormData from "@/hooks/useFormData"; import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; import useUserStore from "@/store/modules/user"; const { id } = defineProps(["id"]) defineOptions({ name: "è®¾å¤æ¥ä¿®è¡¨å", @@ -75,9 +91,10 @@ deviceLedgerId: undefined, // 设å¤Id deviceName: undefined, // 设å¤åç§° deviceModel: undefined, // è§æ ¼åå· repairTime: undefined, // æ¥ä¿®æ¥æ repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æï¼é»è®¤å½å¤© repairName: userStore.nickName, // æ¥ä¿®äºº remark: undefined, // æ éç°è±¡ status: 0, // æ¥ä¿®ç¶æ }); const setDeviceModel = (id) => { @@ -96,6 +113,7 @@ form.repairTime = data.repairTime; form.repairName = data.repairName; form.remark = data.remark; form.status = data.status; }; // onMounted(() => { src/views/equipmentManagement/repair/Modal/MaintainModal.vue
@@ -1,5 +1,5 @@ <template> <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr"> <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr" draggable> <MaintainForm ref="maintainFormRef" /> <template #footer> <el-button type="primary" @click="sendForm" :loading="loading"> src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -1,6 +1,6 @@ <template> <el-dialog v-model="visible" :title="modalOptions.title" @close="close"> <RepairForm ref="repairFormRef" /> <el-dialog v-model="visible" :title="modalOptions.title" @close="close" draggable> <RepairForm ref="repairFormRef" :id="id" /> <template #footer> <el-button type="primary" @click="sendForm" :loading="loading"> {{ modalOptions.confirmText }} src/views/equipmentManagement/repair/index.vue
@@ -106,8 +106,9 @@ @pagination="changePage" > <template #statusRef="{ row }"> <el-tag v-if="row.status === 2" type="danger">失败</el-tag> <el-tag v-if="row.status === 1" type="success">å®ç»</el-tag> <el-tag v-if="row.status === 0" type="danger">å¾ ç»´ä¿®</el-tag> <el-tag v-if="row.status === 0" type="warning">å¾ ç»´ä¿®</el-tag> </template> <template #operation="{ row }"> <el-button src/views/equipmentManagement/spareParts/index.vue
@@ -1,48 +1,55 @@ <template> <div class="spare-part-category"> <div class="search_form"> <el-form :inline="true" :model="queryParams" class="search-form"> <el-form-item label="å¤ä»¶åç§°"> <el-input v-model="queryParams.name" placeholder="请è¾å ¥å¤ä»¶åç§°" clearable style="width: 240px" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleQuery">æ¥è¯¢</el-button> <el-button @click="resetQuery">éç½®</el-button> </el-form-item> </el-form> <div> <el-button type="primary" @click="addCategory" >æ°å¢</el-button> </div> </div> <div class="table_list"> <div class="actions"> <el-text class="mx-1" size="large">设å¤åç±»</el-text> <div> <el-button @click="fetchTreeData" :loading="loading">å·æ°</el-button> <el-button type="primary" @click="addCategory" >æ°å¢</el-button> </div> </div> <el-table v-loading="loading" :data="renderTableData" style="width: 100%; margin-top: 10px;" border row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" > <el-table-column prop="name" label="åç±»åç§°" width="450"> <template #default="{ row }"> <span :style="{ paddingLeft: getIndentation(row) + 'px' }"> {{ row.name }} </span> </template> </el-table-column> <el-table-column prop="sparePartsNo" label="åç±»ç¼å·" width="200"></el-table-column> <el-table-column prop="deviceNameStr" label="设å¤åç§°" width="300"></el-table-column> <el-table-column prop="name" label="å¤ä»¶åç§°" width="200"></el-table-column> <el-table-column prop="sparePartsNo" label="å¤ä»¶ç¼å·" width="200"></el-table-column> <el-table-column prop="status" label="ç¶æ" width="100"> <template #default="{ row }"> <el-tag type="success" size="small">{{ row.status }}</el-tag> </template> </el-table-column> <el-table-column prop="description" label="æè¿°" win-width="330"></el-table-column> <el-table-column label="æä½" width="180" fixed="right"> <el-table-column prop="price" label="ä»·æ ¼" width="140"></el-table-column> <el-table-column prop="description" label="æè¿°" width="150"></el-table-column> <el-table-column label="æä½" width="150" fixed="right" align="center"> <template #default="{ row }"> <el-button type="text" size="small" link type="primary" @click="() => editCategory(row)" :disabled="loading" > ç¼è¾ </el-button> <el-button type="text" size="small" link @click="() => deleteCategory(row.id)" style="color: #f56c6c;" :disabled="loading" @@ -55,10 +62,28 @@ </div> <el-dialog title="å类管ç" v-model="dialogVisible" width="60%"> <el-form :model="form" :rules="rules" ref="formRef" label-width="100px"> <el-form-item label="åç±»åç§°" prop="name"> <el-form-item label="设å¤" prop="deviceLedgerIds"> <el-select v-model="form.deviceLedgerIds" placeholder="è¯·éæ©è®¾å¤" filterable default-first-option :reserve-keyword="false" multiple style="width: 100%" > <el-option v-for="(item, index) in deviceOptions" :key="index" :label="item.deviceName" :value="item.id" ></el-option> </el-select> </el-form-item> <el-form-item label="å¤ä»¶åç§°" prop="name"> <el-input v-model="form.name"></el-input> </el-form-item> <el-form-item label="åç±»ç¼å·" prop="sparePartsNo"> <el-form-item label="å¤ä»¶ç¼å·" prop="sparePartsNo"> <el-input v-model="form.sparePartsNo"></el-input> </el-form-item> <el-form-item label="ç¶æ" prop="status"> @@ -70,17 +95,15 @@ <el-form-item label="æè¿°" prop="description"> <el-input v-model="form.description"></el-input> </el-form-item> <el-form-item label="ä¸çº§åç±»" prop="parentId"> <el-select v-model="form.parentId" placeholder="è¯·éæ©ä¸çº§åç±»"> <el-option label="æ ä¸çº§åç±»" :value="null"></el-option> <el-option v-for="(item, index) in categories" :key="index" :label="item.name" :value="item.id" ></el-option> </el-select> <el-form-item label="ä»·æ ¼" prop="price"> <el-input-number v-model="form.price" placeholder="请è¾å ¥ä»·æ ¼" :min="0" :step="0.01" :precision="2" style="width: 100%" ></el-input-number> </el-form-item> </el-form> <template #footer> @@ -96,7 +119,8 @@ <script setup> import { ref, computed, onMounted, reactive, watch } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus'; import { getSparePartsList, addSparePart, editSparePart, delSparePart,getSparePartsTree } from "@/api/equipmentManagement/spareParts"; import { getSparePartsList, addSparePart, editSparePart, delSparePart } from "@/api/equipmentManagement/spareParts"; import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; // å è½½ç¶æ const loading = ref(false); @@ -111,8 +135,14 @@ // const renderTableData = computed(() => buildTree(categories.value)); const renderTableData = ref([]); const operationType = ref('add') // 设å¤é项 const deviceOptions = ref([]); // 表åå¼ç¨ const formRef = ref(null); // æ¥è¯¢åæ° const queryParams = reactive({ name: '' }); // è¡¨åæ°æ® const form = reactive({ id:'', @@ -120,19 +150,34 @@ sparePartsNo: '', status: '', description: '', parentId: null deviceLedgerIds: [], price: null }); // 表åéªè¯è§å const rules = reactive({ name: [ { required: true, message: '请è¾å ¥åç±»åç§°', trigger: 'blur' } { required: true, message: '请è¾å ¥å¤ä»¶åç§°', trigger: 'blur' } ], sparePartsNo: [ { required: true, message: '请è¾å ¥åç±»ç¼å·', trigger: 'blur' } { required: true, message: '请è¾å ¥å¤ä»¶ç¼å·', trigger: 'blur' } ], status: [ { required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' } ], deviceLedgerIds: [ { required: true, message: 'è¯·éæ©è®¾å¤', trigger: 'change', validator: (rule, value, callback) => { if (operationType.value === 'add' && (!value || value.length === 0)) { callback(new Error('è¯·éæ©è®¾å¤')); } else { callback(); } } } ] }); // è·å缩è¿é @@ -159,54 +204,80 @@ }); return result; }; //è·åæ å½¢ç»æ const fetchTreeData = async () => { fetchCategories(); // è·ååè¡¨æ°æ® const fetchListData = async () => { loading.value = true; try { const res = await getSparePartsTree(); if (res.code === 200) { renderTableData.value = res.data; } else { ElMessage.error(res.message || 'è·ååç±»å表失败'); const params = {}; if (queryParams.name) { params.name = queryParams.name; } }catch (error) { ElMessage.error('è·ååç±»å表失败'); const res = await getSparePartsList(params); if (res.code === 200) { renderTableData.value = res.data.records || []; categories.value = res.data.records || []; } } catch (error) { loading.value = false; } finally { loading.value = false; } } // è·ååç±»å表 const fetchCategories = async () => { loading.value = true; // æ¥è¯¢ const handleQuery = () => { fetchListData(); } // éç½®æ¥è¯¢ const resetQuery = () => { queryParams.name = ''; fetchListData(); } // å 载设å¤å表ï¼å¨æå¼å¼¹æ¡æ¶è°ç¨ï¼ const loadDeviceName = async () => { try { const res = await getSparePartsList(); if (res.code === 200) { categories.value = res.data.records; } else { ElMessage.error(res.message || 'è·ååç±»å表失败'); } const { data } = await getDeviceLedger(); deviceOptions.value = data || []; } catch (error) { ElMessage.error('è·ååç±»å表失败'); } finally { loading.value = false; ElMessage.error('è·å设å¤å表失败'); } }; // æ°å¢åç±» const addCategory = () => { const addCategory = async () => { await loadDeviceName(); form.id = ''; form.name = ''; form.sparePartsNo = ''; form.status = ''; form.description = ''; form.parentId = null; form.deviceLedgerIds = []; form.price = null; operationType.value = 'add' dialogVisible.value = true; console.log('dialogVisible æ´æ°ä¸º', dialogVisible.value); }; // ç¼è¾åç±» const editCategory = (row) => { const editCategory = async (row) => { await loadDeviceName(); Object.assign(form, row); // 妿å端è¿åçæ¯ deviceIds å符串ï¼éè¦è½¬æ¢ä¸ºæ°ç» if (row.deviceIds && typeof row.deviceIds === 'string') { // ç¡®ä¿IDç±»åä¸è®¾å¤é项ä¸çIDç±»åä¸è´ const deviceIdsArray = row.deviceIds.split(',').map(id => id.trim()).filter(id => id); // å¦æè®¾å¤é项ä¸çIDæ¯æ°åç±»åï¼å转æ¢ä¸ºæ°å if (deviceOptions.value.length > 0 && typeof deviceOptions.value[0].id === 'number') { form.deviceLedgerIds = deviceIdsArray.map(id => Number(id)).filter(id => !isNaN(id)); } else { form.deviceLedgerIds = deviceIdsArray; } } else if (row.deviceIds && Array.isArray(row.deviceIds)) { form.deviceLedgerIds = row.deviceIds; } else { form.deviceLedgerIds = []; } operationType.value = 'edit' dialogVisible.value = true; }; @@ -223,7 +294,7 @@ const res = await delSparePart(id); if (res.code === 200) { ElMessage.success('å 餿å'); fetchTreeData(); fetchListData(); } else { ElMessage.error(res.message || 'å é¤å¤±è´¥'); } @@ -242,19 +313,31 @@ try { await formRef.value.validate(); formLoading.value = true; // æå»ºæäº¤æ°æ® const submitData = { ...form, deviceIds: form.deviceLedgerIds && form.deviceLedgerIds.length > 0 ? form.deviceLedgerIds.join(',') : '' }; // å é¤ä¸éè¦çåæ®µ delete submitData.deviceLedgerIds; if (operationType.value === 'edit') { let res = await editSparePart(form); let res = await editSparePart(submitData); if (res.code === 200) { ElMessage.success('ç¼è¾æå'); dialogVisible.value = false; fetchTreeData(); } } else { let res = await addSparePart(form); if (res.code === 200) { ElMessage.success('ç¼è¾æå'); dialogVisible.value = false; fetchTreeData(); fetchListData(); } } else { let res = await addSparePart(submitData); if (res.code === 200) { ElMessage.success('æ°å¢æå'); dialogVisible.value = false; fetchListData(); } } } catch (error) { @@ -264,10 +347,9 @@ } }; // ç»ä»¶æè½½æ¶è·ååç±»å表 // ç»ä»¶æè½½æ¶è·ååè¡¨æ°æ® onMounted(() => { fetchCategories(); fetchTreeData(); fetchListData(); }); </script> @@ -275,43 +357,13 @@ .spare-part-category { padding: 20px; } .search_form { display: flex; align-items: flex-start; justify-content: space-between; } .table_list { margin-top: unset; } .actions { display: flex; justify-content: space-between; margin-bottom: 10px; align-items: center; } /* åµå¥æ å½¢ç»ææ ·å¼ */ .nested-tree-node { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 0 4px; height: 30px; line-height: 30px; } .category-code { color: #606266; font-size: 12px; margin-left: 8px; } .tree-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; } /* è¡¨æ ¼æ ·å¼è°æ´ */ .el-table { font-size: 14px; } .el-table__header-wrapper th { @@ -321,22 +373,6 @@ .el-table__row:hover > td { background-color: #fafafa; } /* åµå¥æ å½¢ç»æç¹å®æ ·å¼ */ .nested-tree { background-color: transparent; } .nested-tree .el-tree-node__content { height: auto; background-color: transparent; } /* æç´¢æ¡æ ·å¼è°æ´ */ .actions .el-input { margin-right: 10px; width: 200px; } /* æé®ç»æ ·å¼ */ @@ -354,64 +390,5 @@ .nested-tree .el-tree-node__expand-icon { font-size: 12px; margin-right: 4px; } /* ç©ºç¶ææ ·å¼ */ .el-table .cell:empty::before { content: '-'; color: #c0c4cc; } /* å±å¼/æå åè½æ ·å¼ */ .expand-icon { display: inline-block; width: 20px; height: 20px; text-align: center; line-height: 20px; cursor: pointer; font-size: 12px; color: #909399; } .expand-icon.expanded { color: #409eff; } /* å±å¼å å®¹æ ·å¼ */ .expand-content { padding: 10px 20px; } /* å级å å®¹æ ·å¼ */ .child-content { padding-left: 40px; } /* æ ååç±»æç¤ºæ ·å¼ */ .no-children { padding: 10px 20px; color: #909399; font-size: 14px; } /* ç¡®ä¿å±å¼çè¡¨æ ¼æ ·å¼æ£ç¡® */ .el-table .el-table__expanded-cell { background-color: #fafafa; } /* å±å¼çåè¡¨æ ¼æ ·å¼ */ .el-table .el-table { border-top: none; border-bottom: none; } /* å±å¼çåè¡¨æ ¼åå æ ¼æ ·å¼ */ .expand-content .el-table__body-wrapper .el-table__row { background-color: #ffffff; } .expand-content .el-table__body-wrapper .el-table__row:hover > td { background-color: #fafafa; } </style> src/views/equipmentManagement/upkeep/Form/MaintenanceForm.vue
@@ -17,11 +17,22 @@ style="width: 100%" /> </el-form-item> <el-form-item label="ä¿å »ç¶æ"> <el-select v-model="form.status"> <el-option label="å¾ ä¿å »" :value="0"></el-option> <el-option label="å®ç»" :value="1"></el-option> <el-option label="失败" :value="2"></el-option> </el-select> </el-form-item> <el-form-item label="ä¿å »ç»æ"> <el-select v-model="form.maintenanceResult" placeholder="è¯·éæ©ä¿å »ç»æ"> <!-- <el-select v-model="form.maintenanceResult" placeholder="è¯·éæ©ä¿å »ç»æ"> <el-option label="å®å¥½" :value="1"></el-option> <el-option label="ç»´ä¿®" :value="0"></el-option> </el-select> </el-select> --> <el-input v-model="form.maintenanceResult" placeholder="请è¾å ¥ä¿å »ç»æ" type="text" /> </el-form-item> </el-form> </template> @@ -40,6 +51,7 @@ maintenanceActuallyName: undefined, // å®é ä¿å »äºº maintenanceActuallyTime: undefined, // å®é ä¿å »æ¥æ maintenanceResult: undefined, // ä¿å »ç»æ status: 0, // ä¿å »ç¶æ }); const setForm = (data) => { src/views/equipmentManagement/upkeep/Form/PlanForm.vue
@@ -5,6 +5,9 @@ v-model="form.deviceLedgerId" @change="setDeviceModel" placeholder="è¯·éæ©è®¾å¤" filterable default-first-option :reserve-keyword="false" > <el-option v-for="(item, index) in deviceOptions" @@ -20,6 +23,30 @@ placeholder="请è¾å ¥è§æ ¼åå·" disabled /> </el-form-item> <el-form-item label="å½å ¥äºº"> <el-select v-model="form.createUser" placeholder="è¯·éæ©" filterable default-first-option :reserve-keyword="false" clearable > <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> </el-select> </el-form-item> <el-form-item v-if="id" label="ä¿ä¿®ç¶æ"> <el-select v-model="form.status"> <el-option label="å¾ ä¿ä¿®" :value="0"></el-option> <el-option label="å®ç»" :value="1"></el-option> <el-option label="失败" :value="2"></el-option> </el-select> </el-form-item> <el-form-item label="计åä¿å »æ¥æ"> <el-date-picker @@ -40,6 +67,7 @@ import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; import { onMounted } from "vue"; import dayjs from "dayjs"; import { userListNoPage } from "@/api/system/user.js"; defineOptions({ name: "计å表å", @@ -51,11 +79,15 @@ deviceOptions.value = data; }; const { id } = defineProps(['id']); const { form, resetForm } = useFormData({ deviceLedgerId: undefined, // 设å¤Id deviceName: undefined, // 设å¤åç§° deviceModel: undefined, // è§æ ¼åå· maintenancePlanTime: undefined, // 计åä¿å »æ¥æ createUser: undefined, // å½å ¥äºº status: 0, //ä¿ä¿®ç¶æ }); const setDeviceModel = (id) => { @@ -75,15 +107,23 @@ form.deviceLedgerId = data.deviceLedgerId; form.deviceName = data.deviceName; form.deviceModel = data.deviceModel; form.createUser = Number(data.createUser); form.status = data.status; form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format( "YYYY-MM-DD HH:mm:ss" ); }; // ç¨æ·å表 const userList = ref([]); const loadForm = () => {}; onMounted(() => { loadDeviceName(); userListNoPage().then((res) => { userList.value = res.data; }); }); defineExpose({ src/views/equipmentManagement/upkeep/Modal/MaintenanceModal.vue
@@ -1,5 +1,5 @@ <template> <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr"> <el-dialog v-model="visible" :title="modalOptions.title" direction="ltr" draggable> <MaintenanceForm ref="maintenanceFormRef" /> <template #footer> <el-button type="primary" @click="sendForm" :loading="loading"> src/views/equipmentManagement/upkeep/Modal/PlanModal.vue
@@ -3,9 +3,10 @@ v-model="visible" :title="modalOptions.title" width="30%" draggable @close="close" > <PlanForm ref="planFormRef"></PlanForm> <PlanForm ref="planFormRef" :id="id"></PlanForm> <template #footer> <el-button type="primary" @click="sendForm" :loading="loading"> {{ modalOptions.confirmText }} src/views/equipmentManagement/upkeep/Modal/formDia.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,304 @@ <template> <div> <el-dialog :title="operationType === 'add' ? 'æ°å¢ä¿å »ä»»å¡' : 'ç¼è¾ä¿å »ä»»å¡'" v-model="dialogVisitable" width="800px" @close="cancel"> <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> <el-row> <el-col :span="12"> <el-form-item label="设å¤åç§°" prop="taskId"> <el-select v-model="form.taskId" @change="setDeviceModel" filterable> <el-option v-for="(item, index) in deviceOptions" :key="index" :label="item.deviceName" :value="item.id" ></el-option> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="è§æ ¼åå·"> <el-input v-model="form.deviceModel" placeholder="请è¾å ¥è§æ ¼åå·" disabled /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="å½å ¥äºº" prop="inspector"> <el-select v-model="form.inspector" filterable default-first-option :reserve-keyword="false" placeholder="è¯·éæ©" clearable > <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç»è®°æ¶é´" prop="registrationDate"> <el-date-picker v-model="form.registrationDate" type="date" placeholder="éæ©ç»è®°æ¥æ" format="YYYY-MM-DD" value-format="YYYY-MM-DD" style="width: 100%" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="ä»»å¡é¢ç" prop="frequencyType"> <el-select v-model="form.frequencyType" placeholder="è¯·éæ©" clearable> <el-option label="æ¯æ¥" value="DAILY"/> <el-option label="æ¯å¨" value="WEEKLY"/> <el-option label="æ¯æ" value="MONTHLY"/> <el-option label="å£åº¦" value="QUARTERLY"/> </el-select> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-time-picker v-model="form.frequencyDetail" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-select v-model="form.week" placeholder="è¯·éæ©" clearable style="width: 50%"> <el-option label="å¨ä¸" value="MON"/> <el-option label="å¨äº" value="TUE"/> <el-option label="å¨ä¸" value="WED"/> <el-option label="å¨å" value="THU"/> <el-option label="å¨äº" value="FRI"/> <el-option label="å¨å " value="SAT"/> <el-option label="卿¥" value="SUN"/> </el-select> <el-time-picker v-model="form.time" placeholder="éæ©æ¶é´" format="HH:mm" value-format="HH:mm" style="width: 50%"/> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="DD,HH:mm" value-format="DD,HH:mm" /> </el-form-item> </el-col> <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> <el-form-item label="æ¥æ" prop="frequencyDetail"> <el-date-picker v-model="form.frequencyDetail" type="datetime" clearable placeholder="éæ©å¼å§æ¥æ" format="MM,DD,HH:mm" value-format="MM,DD,HH:mm" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="夿³¨" prop="remarks"> <el-input v-model="form.remarks" placeholder="请è¾å ¥å¤æ³¨" type="textarea" /> </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="cancel">åæ¶</el-button> </div> </template> </el-dialog> </div> </template> <script setup> import { reactive, ref, getCurrentInstance, toRefs } from "vue"; import {userListNoPageByTenantId} from "@/api/system/user.js"; import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep"; import { getCurrentDate } from "@/utils/index.js"; import useUserStore from "@/store/modules/user.js"; const { proxy } = getCurrentInstance() const emit = defineEmits() const dialogVisitable = ref(false); const operationType = ref('add'); const deviceOptions = ref([]); const userStore = useUserStore(); const data = reactive({ form: { taskId: undefined, taskName: undefined, // å½å ¥äººï¼åéä¸ä¸ªç¨æ· id inspector: undefined, remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '', deviceModel: undefined, // è§æ ¼åå· registrationDate: '' }, rules: { taskId: [{ required: true, message: "è¯·éæ©è®¾å¤", trigger: "change" },], inspector: [{ required: true, message: "è¯·éæ©å½å ¥äºº", trigger: "blur" },], registrationDate: [{ required: true, message: "è¯·éæ©ç»è®°æ¶é´", trigger: "change" }] } }) const { form, rules } = toRefs(data) const userList = ref([]) const loadDeviceName = async () => { const { data } = await getDeviceLedger(); deviceOptions.value = data; }; // éæ©è®¾å¤æ¶ï¼å填设å¤åç§°(taskName)åè§æ ¼åå·(deviceModel) const setDeviceModel = (id) => { const option = deviceOptions.value.find((item) => item.id === id); if (option) { form.value.taskId = option.id; form.value.taskName = option.deviceName; form.value.deviceModel = option.deviceModel; } } // æå¼å¼¹æ¡ const openDialog = async (type, row) => { dialogVisitable.value = true operationType.value = type // é置表å resetForm(); // å è½½ç¨æ·å表 userListNoPageByTenantId().then((res) => { userList.value = res.data; }); // å 载设å¤å表 await loadDeviceName(); if (type === 'edit' && row) { form.value = { ...row } // ç¼è¾æ¶ç¨æ¥å£è¿åç registrantId åæ¾å½å ¥äºº if (row.registrantId) { form.value.inspector = row.registrantId } // 妿æè®¾å¤IDï¼èªå¨è®¾ç½®è®¾å¤ä¿¡æ¯ if (form.value.taskId) { setDeviceModel(form.value.taskId); } } else if (type === 'add') { // æ°å¢æ¶è®¾ç½®ç»è®°æ¥æä¸ºå½å¤© form.value.registrationDate = getCurrentDate(); // æ°å¢æ¶è®¾ç½®å½å ¥äººä¸ºå½åç»å½è´¦æ· form.value.inspector = userStore.id; } } // å ³éå¯¹è¯æ¡ const cancel = () => { resetForm() dialogVisitable.value = false emit('closeDia') } // é置表å彿° const resetForm = () => { if (proxy.$refs.formRef) { proxy.$refs.formRef.resetFields() } // éç½®è¡¨åæ°æ®ç¡®ä¿è®¾å¤ä¿¡æ¯æ£ç¡®éç½® form.value = { taskId: undefined, taskName: undefined, inspector: undefined, inspector: undefined, remarks: '', frequencyType: '', frequencyDetail: '', week: '', time: '', deviceModel: undefined, registrationDate: '' } } // æäº¤è¡¨å const submitForm = () => { proxy.$refs["formRef"].validate(async valid => { if (valid) { try { const payload = { ...form.value } // ä¸åååç«¯ä¼ ä¿å »äººå段ï¼ä» ä½¿ç¨æ¥å£è¦æ±ç registrant / registrantId // æ ¹æ®éæ©çâå½å ¥äººâ设置 registrant / registrantId if (payload.inspector) { const selectedUser = userList.value.find( (u) => String(u.userId) === String(payload.inspector) ) if (selectedUser) { payload.registrantId = selectedUser.userId payload.registrant = selectedUser.nickName } } delete payload.inspector delete payload.inspectorIds if (payload.frequencyType === 'WEEKLY') { let frequencyDetail = '' frequencyDetail = payload.week + ',' + payload.time payload.frequencyDetail = frequencyDetail } // å½å ¥æ¥æï¼ç´æ¥ä½¿ç¨è¡¨åéç registrationDate åæ®µ // ä¸äºé»è®¤ç¶æå段 if (payload.status === undefined || payload.status === null || payload.status === '') { payload.status = '0' // é»è®¤ç¶æï¼å¯æå®é æä¸¾è°æ´ } payload.active = true payload.deleted = 0 if (operationType.value === 'edit') { await deviceMaintenanceTaskEdit(payload) } else { await deviceMaintenanceTaskAdd(payload) } cancel() proxy.$modal.msgSuccess('æäº¤æå') } catch (error) { proxy.$modal.msgError('æäº¤å¤±è´¥ï¼è¯·éè¯') } } }) } defineExpose({ openDialog }) </script> <style scoped> </style> src/views/equipmentManagement/upkeep/index.vue
@@ -1,78 +1,165 @@ <template> <div class="app-container"> <el-form :model="filters" :inline="true"> <el-form-item label="设å¤åç§°"> <el-input v-model="filters.deviceName" style="width: 240px" placeholder="请è¾å ¥è®¾å¤åç§°" clearable :prefix-icon="Search" @change="getTableData" /> </el-form-item> <el-form-item label="计åä¿å »æ¥æ"> <el-date-picker v-model="filters.maintenancePlanTime" type="date" placeholder="è¯·éæ©è®¡åä¿å »æ¥æ" size="default" @change="(date) => handleDateChange(date,2)" /> </el-form-item> <el-form-item label="å®é ä¿å »æ¥æ"> <el-date-picker v-model="filters.maintenanceActuallyTime" type="date" placeholder="è¯·éæ©å®é ä¿å »æ¥æ" size="default" @change="(date) => handleDateChange(date,1)" /> </el-form-item> <el-form-item label="å®é ä¿å »äºº"> <el-input v-model="filters.maintenanceActuallyName" style="width: 240px" placeholder="请è¾å ¥å®é ä¿å »äºº" clearable :prefix-icon="Search" @change="getTableData" /> </el-form-item> <el-form-item> <el-button type="primary" @click="getTableData">æç´¢</el-button> <el-button @click="resetFilters">éç½®</el-button> </el-form-item> </el-form> <div class="table_list"> <div class="actions"> <el-text class="mx-1" size="large">设å¤ä¿å »</el-text> <div> <el-button type="primary" icon="Plus" :disabled="multipleList.length !== 1" @click="addMaintain" > æ°å¢ä¿å » </el-button> <el-button type="success" icon="Van" @click="addPlan"> æ°å¢è®¡å </el-button> <el-button @click="handleOut"> å¯¼åº </el-button> <el-button type="danger" icon="Delete" :disabled="multipleList.length <= 0" @click="delRepairByIds(multipleList.map((item) => item.id))" > æ¹éå é¤ </el-button> <el-tabs v-model="activeTab" @tab-change="handleTabChange"> <!-- 宿¶ä»»å¡ç®¡çtab --> <el-tab-pane label="宿¶ä»»å¡ç®¡ç" name="scheduled"> <div class="search_form"> <el-form :model="scheduledFilters" :inline="true"> <el-form-item label="ä»»å¡åç§°"> <el-input v-model="scheduledFilters.taskName" style="width: 240px" placeholder="请è¾å ¥ä»»å¡åç§°" clearable :prefix-icon="Search" @change="getScheduledTableData" /> </el-form-item> <el-form-item label="ä»»å¡ç¶æ"> <el-select v-model="scheduledFilters.status" placeholder="è¯·éæ©ä»»å¡ç¶æ" clearable style="width: 200px"> <el-option label="å¯ç¨" value="1" /> <el-option label="åç¨" value="0" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="getScheduledTableData">æç´¢</el-button> <el-button @click="resetScheduledFilters">éç½®</el-button> </el-form-item> </el-form> </div> </div> <PIMTable <div class="table_list"> <div class="actions"> <el-text class="mx-1" size="large">宿¶ä»»å¡ç®¡ç</el-text> <div> <el-button type="primary" icon="Plus" @click="addScheduledTask"> æ°å¢ä»»å¡ </el-button> <el-button type="danger" icon="Delete" :disabled="scheduledMultipleList.length <= 0" @click="delScheduledTaskByIds(scheduledMultipleList.map((item) => item.id))" > æ¹éå é¤ </el-button> </div> </div> <PIMTable rowKey="id" isSelection :column="scheduledColumns" :tableData="scheduledDataList" :page="{ current: scheduledPagination.currentPage, size: scheduledPagination.pageSize, total: scheduledPagination.total, }" @selection-change="handleScheduledSelectionChange" @pagination="changeScheduledPage" > <template #statusRef="{ row }"> <el-tag v-if="row.status === 1" type="success">å¯ç¨</el-tag> <el-tag v-if="row.status === 0" type="danger">åç¨</el-tag> </template> <template #operation="{ row }"> <el-button type="primary" text icon="editPen" @click="editScheduledTask(row)" > ç¼è¾ </el-button> <el-button type="danger" text icon="delete" @click="delScheduledTaskByIds(row.id)" > å é¤ </el-button> </template> </PIMTable> </div> </el-tab-pane> <!-- ä»»å¡è®°å½tabï¼å设å¤ä¿å »é¡µé¢ï¼ --> <el-tab-pane label="ä»»å¡è®°å½" name="record"> <div class="search_form"> <el-form :model="filters" :inline="true"> <el-form-item label="设å¤åç§°"> <el-input v-model="filters.deviceName" style="width: 240px" placeholder="请è¾å ¥è®¾å¤åç§°" clearable :prefix-icon="Search" @change="getTableData" /> </el-form-item> <el-form-item label="计åä¿å »æ¥æ"> <el-date-picker v-model="filters.maintenancePlanTime" type="date" placeholder="è¯·éæ©è®¡åä¿å »æ¥æ" size="default" @change="(date) => handleDateChange(date,2)" /> </el-form-item> <el-form-item label="å®é ä¿å »æ¥æ"> <el-date-picker v-model="filters.maintenanceActuallyTime" type="date" placeholder="è¯·éæ©å®é ä¿å »æ¥æ" size="default" @change="(date) => handleDateChange(date,1)" /> </el-form-item> <el-form-item label="å®é ä¿å »äºº"> <el-input v-model="filters.maintenanceActuallyName" style="width: 240px" placeholder="请è¾å ¥å®é ä¿å »äºº" clearable :prefix-icon="Search" @change="getTableData" /> </el-form-item> <el-form-item> <el-button type="primary" @click="getTableData">æç´¢</el-button> <el-button @click="resetFilters">éç½®</el-button> </el-form-item> </el-form> </div> <div class="table_list"> <div class="actions"> <el-text class="mx-1" size="large">ä»»å¡è®°å½</el-text> <div> <el-button type="primary" icon="Plus" :disabled="multipleList.length !== 1" @click="addMaintain" > æ°å¢ä¿å » </el-button> <el-button type="success" icon="Van" @click="addPlan"> æ°å¢è®¡å </el-button> <el-button @click="handleOut"> å¯¼åº </el-button> <el-button type="danger" icon="Delete" :disabled="multipleList.length <= 0" @click="delRepairByIds(multipleList.map((item) => item.id))" > æ¹éå é¤ </el-button> </div> </div> <PIMTable rowKey="id" isSelection :column="columns" @@ -86,16 +173,12 @@ @pagination="changePage" > <template #maintenanceResultRef="{ row }"> <el-tag v-if="row.maintenanceResult === 1" type="success"> å®å¥½ </el-tag> <el-tag v-if="row.maintenanceResult === 0" type="danger"> ç»´ä¿® </el-tag> <div>{{ row.maintenanceResult || '-' }}</div> </template> <template #statusRef="{ row }"> <el-tag v-if="row.status === 2" type="danger">失败</el-tag> <el-tag v-if="row.status === 1" type="success">å®ç»</el-tag> <el-tag v-if="row.status === 0" type="danger">å¾ ä¿å »</el-tag> <el-tag v-if="row.status === 0" type="warning">å¾ ä¿å »</el-tag> </template> <template #operation="{ row }"> <el-button @@ -116,189 +199,369 @@ </el-button> </template> </PIMTable> </div> </div> </el-tab-pane> </el-tabs> <PlanModal ref="planModalRef" @ok="getTableData" /> <MaintenanceModal ref="maintainModalRef" @ok="getTableData" /> <MaintenanceModal ref="maintainModalRef" @ok="getTableData" /> <FormDia ref="formDiaRef" @closeDia="getScheduledTableData" /> </div> </template> <script setup> import { usePaginationApi } from "@/hooks/usePaginationApi"; import { getUpkeepPage, delUpkeep } from "@/api/equipmentManagement/upkeep"; import { onMounted, getCurrentInstance } from "vue"; import PlanModal from "./Modal/PlanModal.vue"; import MaintenanceModal from "./Modal/MaintenanceModal.vue"; import dayjs from "dayjs"; import { ElMessageBox, ElMessage } from "element-plus"; import { ref, onMounted, reactive, getCurrentInstance, nextTick } from 'vue' import { Search } from '@element-plus/icons-vue' import { ElMessage, ElMessageBox } from 'element-plus' import PlanModal from './Modal/PlanModal.vue' import MaintenanceModal from './Modal/MaintenanceModal.vue' import FormDia from './Modal/formDia.vue' import { getUpkeepPage, delUpkeep, deviceMaintenanceTaskList, deviceMaintenanceTaskDel, } from '@/api/equipmentManagement/upkeep' import dayjs from 'dayjs' defineOptions({ name: "设å¤ä¿å »", }); const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance(); // Tabç¸å ³ const activeTab = ref('scheduled') // 计åå¼¹çªæ§å¶å¨ const planModalRef = ref(); const planModalRef = ref() // ä¿å »å¼¹çªæ§å¶å¨ const maintainModalRef = ref(); const maintainModalRef = ref() // 宿¶ä»»å¡å¼¹çªæ§å¶å¨ const formDiaRef = ref() // è¡¨æ ¼å¤éæ¡éä¸é¡¹ const multipleList = ref([]); // ä»»å¡è®°å½tabï¼å设å¤ä¿å »é¡µé¢ï¼ç¸å ³åé const filters = reactive({ deviceName: '', maintenancePlanTime: '', maintenanceActuallyTime: '', maintenanceActuallyName: '', }) // å¤éååä»ä¹ const handleSelectionChange = (selectionList) => { multipleList.value = selectionList; }; const dataList = ref([]) const pagination = ref({ currentPage: 1, pageSize: 10, total: 0, }) const multipleList = ref([]) // è¡¨æ ¼é©å const { filters, columns, dataList, pagination, getTableData, resetFilters, onCurrentChange, } = usePaginationApi(getUpkeepPage, { deviceName: undefined, maintenancePlanTime: undefined, maintenanceActuallyTime: undefined, maintenanceActuallyName: undefined, }, [ { label: "设å¤åç§°", align: "center", prop: "deviceName", }, { label: "è§æ ¼åå·", align: "center", prop: "deviceModel", }, { label: "计åä¿å »æ¥æ", align: "center", prop: "maintenancePlanTime", formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"), }, { label: "å½å ¥äºº", align: "center", prop: "createUserName", }, { label: "å½å ¥æ¥æ", align: "center", prop: "createTime", formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"), width: 200, }, { label: "å®é ä¿å »äºº", align: "center", prop: "maintenanceActuallyName", }, { label: "å®é ä¿å »æ¥æ", align: "center", prop: "maintenanceActuallyTime", formatData: (cell) => cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-", }, { label: "ä¿å »ç»æ", align: "center", prop: "maintenanceResult", dataType: "slot", slot: "maintenanceResultRef", }, { label: "ç¶æ", align: "center", prop: "status", dataType: "slot", slot: "statusRef", }, { fixed: "right", label: "æä½", dataType: "slot", slot: "operation", align: "center", width: "200px", }, ]); // type == 1å®é ä¿å »æ¶é´ 2计åä¿å »æ¶é´ const handleDateChange = (value,type) => { filters.maintenanceActuallyTimeReq = null filters.maintenancePlanTimeReq = null if(type === 1){ if (value) { filters.maintenanceActuallyTimeReq = dayjs(value).format("YYYY-MM-DD"); } }else{ if (value) { filters.maintenancePlanTimeReq = dayjs(value).format("YYYY-MM-DD"); } // 宿¶ä»»å¡ç®¡çtabç¸å ³åé const scheduledFilters = reactive({ taskName: '', status: '', }) const scheduledDataList = ref([]) const scheduledPagination = reactive({ currentPage: 1, pageSize: 10, total: 0, }) const scheduledMultipleList = ref([]) // 宿¶ä»»å¡ç®¡çè¡¨æ ¼åé ç½® const scheduledColumns = ref([ { prop: "taskName", label: "设å¤åç§°"}, { label: "è§æ ¼åå·", prop: "deviceModel", }, { prop: "frequencyType", label: "颿¬¡", minWidth: 150, // PIMTable 使ç¨çæ¯ formatDataï¼è䏿¯ Element-Plus ç formatter formatData: (cell) => ({ DAILY: "æ¯æ¥", WEEKLY: "æ¯å¨", MONTHLY: "æ¯æ", QUARTERLY: "å£åº¦" }[cell] || "") }, { prop: "frequencyDetail", label: "å¼å§æ¥æä¸æ¶é´", minWidth: 150, // åæ ·æ¹ç¨ formatDataï¼PIMTable å é¨ä¼æåå æ ¼å¼ä¼ è¿æ¥ formatData: (cell) => { if (typeof cell !== 'string') return ''; let val = cell; const replacements = { MON: 'å¨ä¸', TUE: 'å¨äº', WED: 'å¨ä¸', THU: 'å¨å', FRI: 'å¨äº', SAT: 'å¨å ', SUN: '卿¥' }; // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é 项 return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]); } }, { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, { prop: "registrationDate", label: "ç»è®°æ¥æ", minWidth: 100 }, { fixed: "right", label: "æä½", dataType: "slot", slot: "operation", align: "center", width: "200px", }, ]) // ä»»å¡è®°å½è¡¨æ ¼åé ç½®ï¼å设å¤ä¿å »è¡¨æ ¼åï¼ const columns = ref([ { label: "设å¤åç§°", align: "center", prop: "deviceName", }, { label: "è§æ ¼åå·", align: "center", prop: "deviceModel", }, { label: "计åä¿å »æ¥æ", align: "center", prop: "maintenancePlanTime", formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"), }, { label: "å½å ¥äºº", align: "center", prop: "createUserName", }, // { // label: "å½å ¥æ¥æ", // align: "center", // prop: "createTime", // formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"), // width: 200, // }, { label: "å®é ä¿å »äºº", align: "center", prop: "maintenanceActuallyName", }, { label: "å®é ä¿å »æ¥æ", align: "center", prop: "maintenanceActuallyTime", formatData: (cell) => cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-", }, { label: "ä¿å »ç»æ", align: "center", prop: "maintenanceResult", dataType: "slot", slot: "maintenanceResultRef", }, { label: "ç¶æ", align: "center", prop: "status", dataType: "slot", slot: "statusRef", }, { fixed: "right", label: "æä½", dataType: "slot", slot: "operation", align: "center", width: "200px", }, ]) // Tab忢å¤ç const handleTabChange = (tabName) => { if (tabName === 'record') { getTableData() } else if (tabName === 'scheduled') { getScheduledTableData() } getTableData(); }; } // æ°å¢ä¿å » const addMaintain = () => { const row = multipleList.value[0]; maintainModalRef.value.open(row.id, row); }; // æ°å¢è®¡å const addPlan = () => { planModalRef.value.openModal(); }; // ç¼è¾è®¡å const editPlan = (id) => { planModalRef.value.openEdit(id); }; const changePage = ({ page, limit }) => { pagination.currentPage = page; pagination.pageSize = limit; onCurrentChange(page); }; // åè¡å é¤ const delRepairByIds = async (ids) => { ElMessageBox.confirm("确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?", "è¦å", { confirmButtonText: "ç¡®å®", cancelButtonText: "åæ¶", type: "warning", }).then(async () => { const { code } = await delUpkeep(ids); if (code === 200) { ElMessage.success("å 餿å"); getTableData(); // 宿¶ä»»å¡ç®¡çç¸å ³æ¹æ³ const getScheduledTableData = async () => { try { const params = { current: scheduledPagination.currentPage, size: scheduledPagination.pageSize, taskName: scheduledFilters.taskName || undefined, status: scheduledFilters.status || undefined, } }); }; const { code, data } = await deviceMaintenanceTaskList(params) if (code === 200) { scheduledDataList.value = data?.records || [] scheduledPagination.total = data?.total || 0 } } catch (error) { ElMessage.error('è·å宿¶ä»»å¡å表失败') } } // å¯¼åº const resetScheduledFilters = () => { scheduledFilters.taskName = '' scheduledFilters.status = '' getScheduledTableData() } const handleScheduledSelectionChange = (selection) => { scheduledMultipleList.value = selection } const changeScheduledPage = (page) => { scheduledPagination.currentPage = page.page scheduledPagination.pageSize = page.limit getScheduledTableData() } const addScheduledTask = () => { nextTick(() => { formDiaRef.value?.openDialog('add'); }); } const editScheduledTask = (row) => { if (row) { nextTick(() => { formDiaRef.value?.openDialog('edit', row); }); } } const delScheduledTaskByIds = async (ids) => { try { await ElMessageBox.confirm('ç¡®å®å é¤éä¸ç宿¶ä»»å¡åï¼', 'æç¤º', { type: 'warning', }) const payload = Array.isArray(ids) ? ids : [ids] await deviceMaintenanceTaskDel(payload) ElMessage.success('å é¤å®æ¶ä»»å¡æå') getScheduledTableData() } catch (error) { // ç¨æ·åæ¶å é¤ } } const handleScheduledOut = () => { ElMessage.info('导åºå®æ¶ä»»å¡åè½å¾ å®ç°') } // ä»»å¡è®°å½ç¸å ³æ¹æ³ï¼å设å¤ä¿å »é¡µé¢æ¹æ³ï¼ const getTableData = async () => { try { const params = { current: pagination.value.currentPage, size: pagination.value.pageSize, deviceName: filters.deviceName || undefined, maintenancePlanTime: filters.maintenancePlanTime ? dayjs(filters.maintenancePlanTime).format('YYYY-MM-DD') : undefined, maintenanceActuallyTime: filters.maintenanceActuallyTime ? dayjs(filters.maintenanceActuallyTime).format('YYYY-MM-DD') : undefined, maintenanceActuallyName: filters.maintenanceActuallyName || undefined, } const { code, data } = await getUpkeepPage(params) if (code === 200) { dataList.value = data.records pagination.value.total = data.total } } catch (error) { console.log(error); } } const resetFilters = () => { filters.deviceName = '' filters.maintenancePlanTime = '' filters.maintenanceActuallyTime = '' filters.maintenanceActuallyName = '' getTableData() } const handleSelectionChange = (selection) => { multipleList.value = selection } const changePage = (page) => { pagination.value.currentPage = page.page pagination.value.pageSize = page.limit getTableData() } const addMaintain = () => { const row = multipleList.value[0] maintainModalRef.value.open(row.id, row) } const addPlan = () => { planModalRef.value.openModal() } const editPlan = (id) => { planModalRef.value.openEdit(id) } const delRepairByIds = async (ids) => { try { await ElMessageBox.confirm('确认å é¤ä¿å »æ°æ®, æ¤æä½ä¸å¯é?', 'è¦å', { confirmButtonText: 'ç¡®å®', cancelButtonText: 'åæ¶', type: 'warning', }) const { code } = await delUpkeep(ids) if (code === 200) { ElMessage.success('å 餿å') getTableData() } } catch (error) { // ç¨æ·åæ¶å é¤ } } const handleOut = () => { ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", ElMessageBox.confirm('éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼', '导åº', { confirmButtonText: '确认', cancelButtonText: 'åæ¶', type: 'warning', }) .then(() => { proxy.download("/device/maintenance/export", {}, "设å¤ä¿å ».xlsx"); proxy.download('/device/maintenance/export', {}, '设å¤ä¿å ».xlsx') }) .catch(() => { ElMessage.info("已忶"); }); }; ElMessage.info('已忶') }) } const handleDateChange = (date, type) => { if (type === 1) { filters.maintenanceActuallyTime = date ? dayjs(date).format('YYYY-MM-DD') : '' } else { filters.maintenancePlanTime = date ? dayjs(date).format('YYYY-MM-DD') : '' } getTableData() } onMounted(() => { getTableData(); }); // æ ¹æ®é»è®¤æ¿æ´»ç Tab è°ç¨å¯¹åºçæ¥è¯¢æ¥å£ if (activeTab.value === 'scheduled') { getScheduledTableData() } else { getTableData() } }) </script> <style lang="scss" scoped> @@ -311,3 +574,8 @@ margin-bottom: 10px; } </style> src/views/procurementManagement/procurementLedger/index.vue
@@ -44,32 +44,32 @@ <el-button type="danger" plain @click="handleDelete">å é¤</el-button> </div> <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)" :row-class-name="tableRowClassName" :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)" :row-class-name="tableRowClassName" > <el-table-column align="center" type="selection" width="55" /> <el-table-column type="expand"> <template #default="props"> <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable" :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable" > <el-table-column align="center" label="åºå·" type="index" width="60" align="center" label="åºå·" type="index" width="60" /> <el-table-column label="产å大类" prop="productCategory" /> <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> @@ -77,41 +77,41 @@ <el-table-column label="æ°é" prop="quantity" /> <el-table-column label="ç¨ç(%)" prop="taxRate" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> </el-table> </template> </el-table-column> <el-table-column align="center" label="åºå·" type="index" width="60" /> <el-table-column label="éè´ååå·" prop="purchaseContractNumber" width="200" show-overflow-tooltip label="éè´ååå·" prop="purchaseContractNumber" width="200" show-overflow-tooltip /> <el-table-column label="éå®ååå·" prop="salesContractNo" width="200" show-overflow-tooltip label="éå®ååå·" prop="salesContractNo" width="200" show-overflow-tooltip /> <el-table-column label="ä¾åºååç§°" width="240" prop="supplierName" show-overflow-tooltip label="ä¾åºååç§°" width="240" prop="supplierName" show-overflow-tooltip /> <el-table-column label="订åç¶æ" width="100" align="center"> <template #default="scope"> @@ -120,10 +120,10 @@ </template> </el-table-column> <el-table-column label="项ç®åç§°" prop="projectName" width="420" show-overflow-tooltip label="项ç®åç§°" prop="projectName" width="420" show-overflow-tooltip /> <el-table-column label="审æ¹ç¶æ" @@ -140,100 +140,100 @@ </template> </el-table-column> <el-table-column label="仿¬¾æ¹å¼" width="100" prop="paymentMethod" show-overflow-tooltip label="仿¬¾æ¹å¼" width="100" prop="paymentMethod" show-overflow-tooltip /> <el-table-column label="ååéé¢(å )" prop="contractAmount" width="200" show-overflow-tooltip :formatter="formattedNumber" label="ååéé¢(å )" prop="contractAmount" width="200" show-overflow-tooltip :formatter="formattedNumber" /> <el-table-column label="å½å ¥äºº" prop="recorderName" width="100" show-overflow-tooltip label="å½å ¥äºº" prop="recorderName" width="100" show-overflow-tooltip /> <el-table-column label="å½å ¥æ¥æ" prop="entryDate" width="100" show-overflow-tooltip label="å½å ¥æ¥æ" prop="entryDate" width="100" show-overflow-tooltip /> <el-table-column fixed="right" label="æä½" min-width="150" align="center" fixed="right" label="æä½" min-width="150" align="center" > <template #default="scope"> <el-button link type="primary" size="small" @click="openForm('edit', scope.row)" >ç¼è¾</el-button link type="primary" size="small" @click="openForm('edit', scope.row)" >ç¼è¾</el-button > <el-button link type="success" size="small" @click="showQRCode(scope.row)" >çæäºç»´ç </el-button link type="success" size="small" @click="showQRCode(scope.row)" >çæäºç»´ç </el-button > </template> </el-table-column> </el-table> <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" :page="page.current" :limit="page.size" @pagination="paginationChange" v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper" :page="page.current" :limit="page.size" @pagination="paginationChange" /> </div> <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" width="70%" @close="closeDia" v-model="dialogFormVisible" :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" width="70%" @close="closeDia" > <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef" :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="purchaseContractNumber"> <el-input v-model="form.purchaseContractNumber" placeholder="请è¾å ¥" clearable v-model="form.purchaseContractNumber" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="éå®ååå·ï¼" prop="salesLedgerId"> <el-select v-model="form.salesLedgerId" placeholder="è¯·éæ©" clearable @change="salesLedgerChange" v-model="form.salesLedgerId" placeholder="è¯·éæ©" clearable @change="salesLedgerChange" > <el-option v-for="item in salesContractList" :key="item.id" :label="item.salesContractNo" :value="item.id" v-for="item in salesContractList" :key="item.id" :label="item.salesContractNo" :value="item.id" /> </el-select> </el-form-item> @@ -243,17 +243,17 @@ <el-col :span="12"> <el-form-item label="ä¾åºååç§°ï¼" prop="supplierId"> <el-select v-model="form.supplierId" placeholder="è¯·éæ©" clearable filterable allow-create v-model="form.supplierId" placeholder="è¯·éæ©" clearable filterable allow-create > <el-option v-for="item in supplierList" :key="item.id" :label="item.supplierName" :value="item.id" v-for="item in supplierList" :key="item.id" :label="item.supplierName" :value="item.id" /> </el-select> </el-form-item> @@ -261,51 +261,65 @@ <el-col :span="12"> <el-form-item label="项ç®åç§°ï¼" prop="projectName"> <el-input v-model="form.projectName" placeholder="请è¾å ¥" clearable v-model="form.projectName" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="仿¬¾æ¹å¼"> <el-input v-model="form.paymentMethod" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç¾è®¢æ¥æï¼" prop="executionDate"> <el-date-picker style="width: 100%" v-model="form.executionDate" 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="recorderId"> <el-form-item label="仿¬¾æ¹å¼"> <el-input v-model="form.paymentMethod" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç¾è®¢æ¥æï¼" prop="executionDate"> <el-date-picker style="width: 100%" v-model="form.executionDate" 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="approverId"> <el-select v-model="form.recorderId" placeholder="è¯·éæ©" clearable disabled v-model="form.approverId" placeholder="è¯·éæ©å®¡æ¹äºº" clearable > <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> </el-select> </el-form-item> <el-form-item label="å½å ¥äººï¼" prop="recorderId" v-show="false"> <el-select v-model="form.recorderId" placeholder="è¯·éæ©" clearable disabled > <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> </el-select> </el-form-item> @@ -313,13 +327,13 @@ <el-col :span="12"> <el-form-item label="å½å ¥æ¥æï¼" prop="entryDate"> <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="è¯·éæ©" clearable style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" placeholder="è¯·éæ©" clearable /> </el-form-item> </el-col> @@ -327,64 +341,95 @@ <el-row> <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> <el-button type="primary" @click="openProductForm('add')" >æ·»å </el-button >æ·»å </el-button > <el-button plain type="danger" @click="deleteProduct" >å é¤</el-button >å é¤</el-button > </el-form-item> <div class="select-button-group" style="width: 220px; margin: 20px 0;" v-if="operationType === 'add'"> <el-select filterable allow-create :reserve-keyword="true" :default-first-option="false" v-model="templateName" :input-value="filterInputValue" @filter-change="onTemplateFilterChange" @change="onTemplateChange" style="width: 180px; border-right: none; border-radius: 4px 0 0 4px;" placeholder="è¯·éæ©" class="no-arrow-select" > <el-option v-for="item in templateList" :key="item.value" :label="item.templateName" :value="item.templateName" ></el-option> </el-select> <!-- æé®ï¼ä¸ Select é«åº¦å¹é ï¼å»æå·¦ä¾§è¾¹æ¡ï¼æ ç¼è¡æ¥ --> <el-button size="small" style="height: 32px; border-radius: 0 4px 4px 0; margin-left: -1px;" @click="handleButtonClick" :disabled="!templateName || templateName.trim() === '' || isTemplateNameDuplicate" > ä¿å </el-button> </div> </el-row> <el-table :data="productData" border @selection-change="productSelected" show-summary :summary-method="summarizeProTable" :data="productData" border @selection-change="productSelected" show-summary :summary-method="summarizeProTable" > <el-table-column align="center" type="selection" width="55" /> <el-table-column align="center" label="åºå·" type="index" width="60" align="center" label="åºå·" type="index" width="60" /> <el-table-column label="产å大类" prop="productCategory" /> <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> <el-table-column label="åä½" prop="unit" width="70" /> <el-table-column label="æ°é" prop="quantity" width="70" /> <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" width="120" show-overflow-tooltip /> <el-table-column label="åºåé¢è¦æ°é" prop="warnNum" width="120" show-overflow-tooltip /> <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> <el-table-column label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" width="150" label="å«ç¨åä»·(å )" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" width="150" /> <el-table-column label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" width="150" label="å«ç¨æ»ä»·(å )" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" width="150" /> <el-table-column label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" width="150" label="ä¸å«ç¨æ»ä»·(å )" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" width="150" /> <el-table-column fixed="right" label="æä½" min-width="60" align="center" fixed="right" label="æä½" min-width="60" align="center" > <template #default="scope"> <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row, scope.$index)" >ç¼è¾</el-button link type="primary" size="small" @click="openProductForm('edit', scope.row, scope.$index)" >ç¼è¾</el-button > </template> </el-table-column> @@ -393,11 +438,11 @@ <el-col :span="24"> <el-form-item label="夿³¨Â·ï¼" prop="remark"> <el-input v-model="form.remark" placeholder="请è¾å ¥" clearable type="textarea" :rows="2" v-model="form.remark" placeholder="请è¾å ¥" clearable type="textarea" :rows="2" /> </el-form-item> </el-col> @@ -406,16 +451,16 @@ <el-col :span="24"> <el-form-item label="éä»¶ææï¼" prop="remark"> <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove" v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove" > <el-button type="primary">ä¸ä¼ </el-button> <template #tip> @@ -437,30 +482,30 @@ </template> </el-dialog> <el-dialog v-model="productFormVisible" :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" width="40%" @close="closeProductDia" v-model="productFormVisible" :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" width="40%" @close="closeProductDia" > <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef" :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef" > <el-row :gutter="30"> <el-col :span="24"> <el-form-item label="产å大类ï¼" prop="productId"> <el-tree-select v-model="productForm.productId" placeholder="è¯·éæ©" clearable check-strictly @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" v-model="productForm.productId" placeholder="è¯·éæ©" clearable check-strictly @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" /> </el-form-item> </el-col> @@ -469,16 +514,16 @@ <el-col :span="24"> <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> <el-select v-model="productForm.productModelId" placeholder="è¯·éæ©" clearable @change="getProductModel" v-model="productForm.productModelId" placeholder="è¯·éæ©" clearable @change="getProductModel" > <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> </el-select> </el-form-item> @@ -488,75 +533,75 @@ <el-col :span="12"> <el-form-item label="åä½ï¼" prop="unit"> <el-input v-model="productForm.unit" placeholder="请è¾å ¥" clearable v-model="productForm.unit" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç¨ç(%)ï¼" prop="taxRate"> <el-select v-model="productForm.taxRate" placeholder="è¯·éæ©" clearable @change="mathNum" > <el-option label="1" value="1" /> <el-option label="6" value="6" /> <el-option label="13" value="13" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ç¨ç(%)ï¼" prop="taxRate"> <el-select v-model="productForm.taxRate" placeholder="è¯·éæ©" clearable @change="mathNum" > <el-option label="1" value="1" /> <el-option label="6" value="6" /> <el-option label="13" value="13" /> </el-select> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="å«ç¨åä»·(å )ï¼" prop="taxInclusiveUnitPrice"> <el-input-number v-model="productForm.taxInclusiveUnitPrice" :precision="2" :step="0.1" clearable style="width: 100%" @change="mathNum" v-model="productForm.taxInclusiveUnitPrice" :precision="2" :step="0.1" clearable style="width: 100%" @change="mathNum" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="æ°éï¼" prop="quantity"> <el-input-number :step="0.1" clearable :precision="2" style="width: 100%" v-model="productForm.quantity" placeholder="请è¾å ¥" @change="mathNum" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="æ°éï¼" prop="quantity"> <el-input-number :step="0.1" clearable :precision="2" style="width: 100%" v-model="productForm.quantity" placeholder="请è¾å ¥" @change="mathNum" /> </el-form-item> </el-col> </el-row> <el-row :gutter="30"> <el-col :span="12"> <el-form-item label="å«ç¨æ»ä»·(å )ï¼" prop="taxInclusiveTotalPrice"> <el-input-number v-model="productForm.taxInclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%" @change="reverseMathNum('taxInclusiveTotalPrice')" v-model="productForm.taxInclusiveTotalPrice" :precision="2" :step="0.1" clearable style="width: 100%" @change="reverseMathNum('taxInclusiveTotalPrice')" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ä¸å«ç¨æ»ä»·(å )ï¼" prop="taxExclusiveTotalPrice" label="ä¸å«ç¨æ»ä»·(å )ï¼" prop="taxExclusiveTotalPrice" > <el-input v-model="productForm.taxExclusiveTotalPrice" @change="reverseMathNum('taxExclusiveTotalPrice')" <el-input v-model="productForm.taxExclusiveTotalPrice" @change="reverseMathNum('taxExclusiveTotalPrice')" /> </el-form-item> </el-col> @@ -565,26 +610,26 @@ <el-col :span="12"> <el-form-item label="å票类åï¼" prop="invoiceType"> <el-select v-model="productForm.invoiceType" placeholder="è¯·éæ©" clearable v-model="productForm.invoiceType" placeholder="è¯·éæ©" clearable > <el-option label="墿®ç¥¨" value="墿®ç¥¨" /> <el-option label="å¢ä¸ç¥¨" value="å¢ä¸ç¥¨" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="åºåé¢è¦æ°éï¼" prop="warnNum"> <el-input-number v-model="productForm.warnNum" :precision="2" :step="0.1" clearable style="width: 100%" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="åºåé¢è¦æ°éï¼" prop="warnNum"> <el-input-number v-model="productForm.warnNum" :precision="2" :step="0.1" clearable style="width: 100%" /> </el-form-item> </el-col> </el-row> </el-form> <template #footer> @@ -594,13 +639,13 @@ </div> </template> </el-dialog> <!-- äºç»´ç æ¾ç¤ºå¯¹è¯æ¡ --> <el-dialog v-model="qrCodeDialogVisible" title="éè´ååå·äºç»´ç " width="400px" center v-model="qrCodeDialogVisible" title="éè´ååå·äºç»´ç " width="400px" center > <div style="text-align: center;"> <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> @@ -612,27 +657,27 @@ <!-- æ«ç æ°å¢å¯¹è¯æ¡ --> <el-dialog v-model="scanAddDialogVisible" title="æ«ç æ°å¢éè´å°è´¦" width="70%" @close="closeScanAddDialog" v-model="scanAddDialogVisible" title="æ«ç æ°å¢éè´å°è´¦" width="70%" @close="closeScanAddDialog" > <el-form :model="scanAddForm" label-width="140px" label-position="top" :rules="scanAddRules" ref="scanAddFormRef" :model="scanAddForm" label-width="140px" label-position="top" :rules="scanAddRules" ref="scanAddFormRef" > <el-row :gutter="20"> <el-col :span="24"> <el-form-item label="æ«ç å 容ï¼"> <el-input v-model="scanAddForm.scanContent" type="textarea" :rows="3" placeholder="è¯·æ«æäºç»´ç ææå¨è¾å ¥éè´ååä¿¡æ¯" @input="parseScanContent" v-model="scanAddForm.scanContent" type="textarea" :rows="3" placeholder="è¯·æ«æäºç»´ç ææå¨è¾å ¥éè´ååä¿¡æ¯" @input="parseScanContent" /> </el-form-item> </el-col> @@ -641,18 +686,18 @@ <el-col :span="12"> <el-form-item label="éè´ååå·ï¼" prop="purchaseContractNumber"> <el-input v-model="scanAddForm.purchaseContractNumber" placeholder="请è¾å ¥" clearable v-model="scanAddForm.purchaseContractNumber" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> <el-input v-model="scanAddForm.supplierName" placeholder="请è¾å ¥" clearable v-model="scanAddForm.supplierName" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> @@ -661,21 +706,21 @@ <el-col :span="12"> <el-form-item label="项ç®åç§°ï¼" prop="projectName"> <el-input v-model="scanAddForm.projectName" placeholder="请è¾å ¥" clearable v-model="scanAddForm.projectName" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="ååéé¢(å )ï¼" prop="contractAmount"> <el-input-number v-model="scanAddForm.contractAmount" :precision="2" :step="0.1" clearable style="width: 100%" placeholder="请è¾å ¥" v-model="scanAddForm.contractAmount" :precision="2" :step="0.1" clearable style="width: 100%" placeholder="请è¾å ¥" /> </el-form-item> </el-col> @@ -684,9 +729,9 @@ <el-col :span="12"> <el-form-item label="仿¬¾æ¹å¼ï¼"> <el-input v-model="scanAddForm.paymentMethod" placeholder="请è¾å ¥" clearable v-model="scanAddForm.paymentMethod" placeholder="请è¾å ¥" clearable /> </el-form-item> </el-col> @@ -700,11 +745,11 @@ <el-col :span="24"> <el-form-item label="夿³¨ï¼"> <el-input v-model="scanAddForm.remark" type="textarea" :rows="2" placeholder="请è¾å ¥å¤æ³¨ä¿¡æ¯" clearable v-model="scanAddForm.remark" type="textarea" :rows="2" placeholder="请è¾å ¥å¤æ³¨ä¿¡æ¯" clearable /> </el-form-item> </el-col> @@ -720,17 +765,17 @@ <!-- æ«ç ç»è®°å¯¹è¯æ¡ --> <el-dialog v-model="scanDialogVisible" title="æ«ç ç»è®°" width="60%" @close="closeScanDialog" v-model="scanDialogVisible" title="æ«ç ç»è®°" width="60%" @close="closeScanDialog" > <el-form :model="scanForm" label-width="120px" label-position="left" :rules="scanRules" ref="scanFormRef" :model="scanForm" label-width="120px" label-position="left" :rules="scanRules" ref="scanFormRef" > <el-row :gutter="20"> <el-col :span="12"> @@ -774,10 +819,10 @@ <el-col :span="24"> <el-form-item label="æ«ç 夿³¨ï¼"> <el-input v-model="scanForm.scanRemark" type="textarea" :rows="3" placeholder="请è¾å ¥æ«ç 夿³¨ä¿¡æ¯" v-model="scanForm.scanRemark" type="textarea" :rows="3" placeholder="请è¾å ¥æ«ç 夿³¨ä¿¡æ¯" /> </el-form-item> </el-col> @@ -809,35 +854,42 @@ </div> </template> </el-dialog> </div> </template> <script setup> import { getToken } from "@/utils/auth"; import {getToken} from "@/utils/auth"; import pagination from "@/components/PIMTable/Pagination.vue"; import { ref, onMounted, reactive, toRefs, getCurrentInstance, nextTick } from "vue"; import { Search } from "@element-plus/icons-vue"; import { ElMessageBox } from "element-plus"; import { userListNoPage } from "@/api/system/user.js"; import {getCurrentInstance, nextTick, onMounted, reactive, ref, toRefs} from "vue"; import {Search} from "@element-plus/icons-vue"; import {ElMessage, ElMessageBox} from "element-plus"; import {userListNoPage} from "@/api/system/user.js"; import { getSalesLedgerWithProducts, addOrUpdateSalesLedgerProduct, delProduct, delLedgerFile, delProduct, getProductInfoByContractNo, getSalesLedgerWithProducts, } from "@/api/salesManagement/salesLedger.js"; import { addOrEditPurchase, delPurchase, getSalesNo, purchaseListPage, productList, getPurchaseById, getOptions, addPurchaseTemplate, createPurchaseNo, delPurchase, getOptions, getPurchaseById, getPurchaseTemplateList, getSalesNo, productList, purchaseListPage } from "@/api/procurementManagement/procurementLedger.js"; import useFormData from "@/hooks/useFormData.js"; import QRCode from "qrcode"; import useUserStore from "@/store/modules/user"; import {modelList, productTreeList} from "@/api/basicData/product.js"; import dayjs from "dayjs"; const { proxy } = getCurrentInstance(); const tableData = ref([]); const productData = ref([]); @@ -855,9 +907,6 @@ }); const total = ref(0); const fileList = ref([]); import useUserStore from "@/store/modules/user"; import { modelList, productTreeList } from "@/api/basicData/product.js"; import dayjs from "dayjs"; const userStore = useUserStore(); @@ -870,6 +919,96 @@ 0: '审æ¹ä¸', 1: '审æ¹éè¿', 2: '审æ¹å¤±è´¥' }; const templateName = ref(''); const filterInputValue = ref(''); const templateList = ref([]); const isTemplateNameDuplicate = ref(false); // æ 记模æ¿åç§°æ¯å¦éå¤ // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ const checkTemplateNameDuplicate = (name) => { if (!name || name.trim() === '') { isTemplateNameDuplicate.value = false; return false; } const isDuplicate = templateList.value.some(item => item.templateName === name.trim()); isTemplateNameDuplicate.value = isDuplicate; return isDuplicate; }; // 鲿宿¶å¨ let duplicateCheckTimer = null; const onTemplateFilterChange = (val) => { filterInputValue.value = val ?? ''; // æ¸ é¤ä¹åç宿¶å¨ if (duplicateCheckTimer) { clearTimeout(duplicateCheckTimer); } // 宿¶æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ï¼é²æå¤çï¼é¿å é¢ç¹æç¤ºï¼ if (val && val.trim()) { duplicateCheckTimer = setTimeout(() => { const isDuplicate = checkTemplateNameDuplicate(val); if (isDuplicate) { ElMessage({ message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', type: 'warning', duration: 2000 }); } }, 300); // 300ms 鲿 } else { isTemplateNameDuplicate.value = false; } }; // allow-create æ¶ï¼è¾å ¥ä¸åå¨çå 容ä¼ä½ä¸º string å¼è¿åï¼è¿é忥åè¾å ¥æ¡ä»¥ç¡®ä¿æåä¸ä¸¢ const onTemplateChange = async (val) => { if (typeof val === 'string') { filterInputValue.value = val; // éæ©æè¾å ¥æ¶æ£æ¥éå¤ checkTemplateNameDuplicate(val); } // è¿æ»¤æ°æ®ï¼æ¥æ¾å¹é çæ¨¡æ¿ const matchedTemplate = templateList.value.find(item => item.templateName === val); if (matchedTemplate?.id) { // 妿æ¾å°æ¨¡æ¿ï¼å è½½æ¨¡æ¿æ°æ® form.value = { ...form.value, ...matchedTemplate, }; productData.value = matchedTemplate.productData || []; // çææ°çéè´ååå· try { const res = await createPurchaseNo(); if (res?.data) { form.value.purchaseContractNumber = res.data; } } catch (error) { console.error('çæéè´ååå·å¤±è´¥:', error); } } else { // å¦ææ²¡ææ¾å°æ¨¡æ¿ï¼é置表åï¼ä¿æå½å表åç¶æï¼ const currentFormData = { ...form.value }; const currentProductData = [...productData.value]; // å¦æå¯¹è¯æ¡æªæå¼ï¼å æå¼ if (!dialogFormVisible.value) { operationType.value = 'add'; dialogFormVisible.value = true; } // çå¾ ä¸ä¸ä¸ª tick 忢夿°æ® await nextTick(); form.value = { ...form.value, ...currentFormData, }; productData.value = currentProductData; } }; // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® @@ -895,7 +1034,7 @@ supplierName: "", supplierId: "", paymentMethod: "", executionDate: "", executionDate: "", }, rules: { purchaseContractNumber: [ @@ -903,8 +1042,9 @@ ], projectName: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], supplierId: [{ required: true, message: "请è¾å ¥", trigger: "blur" }], entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], approverId:[{ required: true, message: "è¯·éæ©å®¡æ¹äºº", trigger: "change" }], executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], }, }); const { form, rules } = toRefs(data); @@ -928,7 +1068,7 @@ taxInclusiveTotalPrice: "", taxExclusiveTotalPrice: "", invoiceType: "", warnNum: "", warnNum: "", }, productRules: { productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], @@ -939,7 +1079,7 @@ { required: true, message: "请è¾å ¥", trigger: "blur" }, ], taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], warnNum: [{ required: false, message: "è¯·éæ©", trigger: "change" }], warnNum: [{ required: false, message: "è¯·éæ©", trigger: "change" }], taxInclusiveTotalPrice: [ { required: true, message: "请è¾å ¥", trigger: "blur" }, ], @@ -969,7 +1109,14 @@ }; const formattedNumber = (row, column, cellValue) => { return parseFloat(cellValue).toFixed(2); if (cellValue === null || cellValue === undefined || cellValue === '') { return '0.00'; } const num = parseFloat(cellValue); if (isNaN(num)) { return '0.00'; } return num.toFixed(2); }; // æ¥è¯¢å表 /** æç´¢æé®æä½ */ @@ -977,23 +1124,100 @@ page.current = 1; getList(); }; // ä¿åæ¨¡æ¿ const handleButtonClick = async () => { // æ£æ¥æ¨¡æ¿åç§°æ¯å¦ä¸ºç©º if (!templateName.value || templateName.value.trim() === '') { ElMessage({ message: '请è¾å ¥æ¨¡æ¿åç§°', type: 'warning', }); return; } // æ£æ¥æ¨¡æ¿åç§°æ¯å¦éå¤ const isDuplicate = checkTemplateNameDuplicate(templateName.value); if (isDuplicate) { ElMessage({ message: '模æ¿åç§°å·²åå¨ï¼è¯·æ´æ¢æ¨¡æ¿åç§°', type: 'warning', }); return; } // æ£æ¥ä¾åºåæ¯å¦éæ© if (!form.value.supplierId) { ElMessage({ message: '请å éæ©ä¾åºå', type: 'warning', }); return; } // æ£æ¥æ¯å¦æäº§åæ°æ® // if (!productData.value || productData.value.length === 0) { // ElMessage({ // message: 'è¯·å æ·»å 产åä¿¡æ¯', // type: 'warning', // }); // return; // } try { let params = { productData: proxy.HaveJson(productData.value), supplierId: form.value.supplierId, paymentMethod: form.value.paymentMethod, recorderId: form.value.recorderId, approverId: form.value.approverId, templateName: templateName.value.trim() }; console.log(params); let res = await addPurchaseTemplate(params); if (res && res.code === 200) { ElMessage({ message: '模æ¿ä¿åæå', type: 'success', }); // ä¿åæååéæ°è·å模æ¿å表 await getTemplateList(); // æ¸ ç©ºæ¨¡æ¿åç§°è¾å ¥ templateName.value = ''; filterInputValue.value = ''; isTemplateNameDuplicate.value = false; } else { ElMessage({ message: res?.msg || '模æ¿ä¿å失败', type: 'error', }); } } catch (error) { console.error('ä¿å模æ¿å¤±è´¥:', error); ElMessage({ message: '模æ¿ä¿å失败ï¼è¯·ç¨åéè¯', type: 'error', }); } }; // å表åè®¡æ¹æ³ const summarizeChildrenTable = (param) => { return proxy.summarizeTable( param, [ "taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice", "ticketsNum", "ticketsAmount", "futureTickets", "futureTicketsAmount", ], { ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° } param, [ "taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice", "ticketsNum", "ticketsAmount", "futureTickets", "futureTicketsAmount", ], { ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° } ); }; const paginationChange = (obj) => { @@ -1005,23 +1229,24 @@ tableLoading.value = true; const { entryDate, ...rest } = searchForm; purchaseListPage({ ...rest, ...page }) .then((res) => { tableLoading.value = false; // tableData.value = res.data.records; // å¤çæ°æ®ï¼æ·»å 失æç¶ææ è®° tableData.value = res.data.records.map(record => ({ ...record, isInvalid: record.isWhite === 1 })); tableData.value.map((item) => { item.children = []; .then((res) => { tableLoading.value = false; // tableData.value = res.data.records; // å¤çæ°æ®ï¼æ·»å 失æç¶ææ è®° tableData.value = res.data.records.map(record => ({ ...record, isInvalid: record.isWhite === 1 })); // åå§ååæ°æ®æ°ç» tableData.value.forEach((item) => { item.children = []; }); total.value = res.data.total; expandedRowKeys.value = []; }) .catch(() => { tableLoading.value = false; }); total.value = res.data.total; expandedRowKeys.value = []; }) .catch(() => { tableLoading.value = false; }); }; // è¡¨æ ¼éæ©æ°æ® const handleSelectionChange = (selection) => { @@ -1032,19 +1257,24 @@ }; const expandedRowKeys = ref([]); // å±å¼è¡ const expandChange = (row, expandedRows) => { const expandChange = async (row, expandedRows) => { if (expandedRows.length > 0) { expandedRowKeys.value = []; try { productList({ salesLedgerId: row.id, type: 2 }).then((res) => { const index = tableData.value.findIndex((item) => item.id === row.id); if (index > -1) { tableData.value[index].children = res.data; } const res = await productList({ salesLedgerId: row.id, type: 2 }); const index = tableData.value.findIndex((item) => item.id === row.id); if (index > -1) { tableData.value[index].children = res.data || []; expandedRowKeys.value.push(row.id); }); } } catch (error) { console.log(error); console.error('å 载产åå表失败:', error); proxy.$modal.msgError('å 载产åå表失败'); // å±å¼å¤±è´¥æ¶ï¼ç§»é¤å±å¼ç¶æ const index = expandedRows.findIndex(item => item.id === row.id); if (index > -1) { expandedRows.splice(index, 1); } } } else { expandedRowKeys.value = []; @@ -1063,41 +1293,63 @@ ]); }; // æå¼å¼¹æ¡ const openForm = (type, row) => { const openForm = async (type, row) => { await getTemplateList() operationType.value = type; form.value = {}; productData.value = []; fileList.value = []; if (operationType.value == "add") { createPurchaseNo().then((res) => { form.value.purchaseContractNumber = res.data; }); } userListNoPage().then((res) => { userList.value = res.data; }); getSalesNo().then((res) => { salesContractList.value = res; }); getOptions().then((res) => { templateName.value = ''; filterInputValue.value = ''; isTemplateNameDuplicate.value = false; try { // å¹¶è¡å è½½åºç¡æ°æ® const [userRes, salesRes, supplierRes] = await Promise.all([ userListNoPage(), getSalesNo(), getOptions() ]); userList.value = userRes.data || []; salesContractList.value = salesRes || []; // ä¾åºåè¿æ»¤åºisWhite=0 çæ°æ® supplierList.value = res.data.filter((item) => item.isWhite == 0); }); form.value.recorderId = userStore.id; form.value.entryDate = getCurrentDate(); if (type === "edit") { currentId.value = row.id; getPurchaseById({ id: row.id, type: 2 }).then((res) => { form.value = { ...res }; productData.value = form.value.productData; if (form.value.salesLedgerFiles) { fileList.value = form.value.salesLedgerFiles; } else { fileList.value = []; supplierList.value = (supplierRes.data || []).filter((item) => item.isWhite === 0); // 设置é»è®¤å¼ form.value.recorderId = userStore.id; form.value.entryDate = getCurrentDate(); if (type === "add") { // æ°å¢æ¶çæéè´ååå· try { const purchaseNoRes = await createPurchaseNo(); if (purchaseNoRes?.data) { form.value.purchaseContractNumber = purchaseNoRes.data; } } catch (error) { console.error('çæéè´ååå·å¤±è´¥:', error); proxy.$modal.msgWarning('çæéè´ååå·å¤±è´¥'); } }); } else if (type === "edit" && row?.id) { // ç¼è¾æ¶å è½½æ°æ® currentId.value = row.id; try { const purchaseRes = await getPurchaseById({ id: row.id, type: 2 }); form.value = { ...purchaseRes }; productData.value = purchaseRes.productData || []; fileList.value = purchaseRes.salesLedgerFiles || []; } catch (error) { console.error('å è½½éè´å°è´¦æ°æ®å¤±è´¥:', error); proxy.$modal.msgError('å è½½æ°æ®å¤±è´¥'); return; } } dialogFormVisible.value = true; } catch (error) { console.error('æå¼è¡¨å失败:', error); proxy.$modal.msgError('å è½½åºç¡æ°æ®å¤±è´¥'); } dialogFormVisible.value = true; }; // ä¸ä¼ åæ ¡æ£ function handleBeforeUpload(file) { @@ -1126,43 +1378,57 @@ } } // ç§»é¤æä»¶ function handleRemove(file) { console.log("handleRemove", file.id); if (file.size > 1024 * 1024 * 10) { // ä» åç«¯æ¸ çï¼ä¸è°ç¨å 餿¥å£åæç¤º return; async function handleRemove(file) { if (!file?.id) { return; } if (operationType.value === "edit") { let ids = []; ids.push(file.id); delLedgerFile(ids).then((res) => { if (file.size > 1024 * 1024 * 10) { // ä» åç«¯æ¸ çï¼ä¸è°ç¨å 餿¥å£åæç¤º return; } if (operationType.value === "edit" && file.id) { try { await delLedgerFile([file.id]); proxy.$modal.msgSuccess("å 餿å"); }); } catch (error) { console.error('å é¤æä»¶å¤±è´¥:', error); proxy.$modal.msgError("å é¤æä»¶å¤±è´¥"); } } } // æäº¤è¡¨å const submitForm = () => { proxy.$refs["formRef"].validate((valid) => { if (valid) { if (productData.value.length > 0) { form.value.productData = proxy.HaveJson(productData.value); } else { proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); return; } let tempFileIds = []; if (fileList.value.length > 0) { tempFileIds = fileList.value.map((item) => item.tempId); } form.value.tempFileIds = tempFileIds; form.value.type = 2; addOrEditPurchase(form.value).then((res) => { proxy.$modal.msgSuccess("æäº¤æå"); closeDia(); getList(); }); const submitForm = async () => { try { const valid = await proxy.$refs["formRef"].validate().catch(() => false); if (!valid) { return; } }); if (!productData.value || productData.value.length === 0) { proxy.$modal.msgWarning("请添å 产åä¿¡æ¯"); return; } form.value.productData = proxy.HaveJson(productData.value); form.value.tempFileIds = fileList.value .filter(item => item.tempId) .map((item) => item.tempId); form.value.type = 2; try { await addOrEditPurchase(form.value); proxy.$modal.msgSuccess("æäº¤æå"); closeDia(); getList(); } catch (error) { console.error('æäº¤è¡¨å失败:', error); proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } } catch (error) { console.error('表åéªè¯å¤±è´¥:', error); } }; // å ³éå¼¹æ¡ const closeDia = () => { @@ -1181,17 +1447,26 @@ productFormVisible.value = true; getProductOptions(); }; const getProductOptions = () => { productTreeList().then((res) => { const getProductOptions = async () => { try { const res = await productTreeList(); productOptions.value = convertIdToValue(res); }); } catch (error) { console.error('å 载产åé项失败:', error); proxy.$modal.msgError('å 载产åé项失败'); } }; const getModels = (value) => { const getModels = async (value) => { if (value) { productForm.value.productCategory = findNodeById(productOptions.value, value) || ""; modelList({ id: value }).then((res) => { modelOptions.value = res; }); try { const res = await modelList({ id: value }); modelOptions.value = res || []; } catch (error) { console.error('å è½½è§æ ¼åå·å¤±è´¥:', error); proxy.$modal.msgError('å è½½è§æ ¼åå·å¤±è´¥'); modelOptions.value = []; } } else { productForm.value.productCategory = ""; modelOptions.value = []; @@ -1236,75 +1511,103 @@ }); } // æäº¤äº§å表å const submitProduct = () => { proxy.$refs["productFormRef"].validate((valid) => { if (valid) { if (operationType.value === "edit") { submitProductEdit(); } else { if (productOperationType.value === "add") { productData.value.push({ ...productForm.value }); console.log("productData.value---", productData.value); } else { productData.value[productOperationIndex.value] = { ...productForm.value, }; } closeProductDia(); } const submitProduct = async () => { try { const valid = await proxy.$refs["productFormRef"].validate().catch(() => false); if (!valid) { return; } }); if (operationType.value === "edit") { await submitProductEdit(); } else { if (productOperationType.value === "add") { productData.value.push({ ...productForm.value }); } else { productData.value[productOperationIndex.value] = { ...productForm.value, }; } closeProductDia(); } } catch (error) { console.error('æäº¤äº§å表å失败:', error); } }; const submitProductEdit = () => { productForm.value.salesLedgerId = currentId.value; productForm.value.type = 2; addOrUpdateSalesLedgerProduct(productForm.value).then((res) => { const submitProductEdit = async () => { try { productForm.value.salesLedgerId = currentId.value; productForm.value.type = 2; await addOrUpdateSalesLedgerProduct(productForm.value); proxy.$modal.msgSuccess("æäº¤æå"); closeProductDia(); getPurchaseById({ id: currentId.value, type: 2 }).then((res) => { productData.value = res.productData; }); }); // éæ°å è½½äº§åæ°æ® try { const res = await getPurchaseById({ id: currentId.value, type: 2 }); productData.value = res.productData || []; } catch (error) { console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); } } catch (error) { console.error('æäº¤äº§åç¼è¾å¤±è´¥:', error); proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } }; // å é¤äº§å const deleteProduct = () => { const deleteProduct = async () => { if (productSelectedRows.value.length === 0) { proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); return; } if (operationType.value === "add") { // æ°å¢æ¨¡å¼ä¸ï¼ç´æ¥ä»åç«¯æ°æ®ä¸å é¤ productSelectedRows.value.forEach((selectedRow) => { const index = productData.value.findIndex( (product) => product.id === selectedRow.id (product) => product.id === selectedRow.id ); if (index !== -1) { productData.value.splice(index, 1); } }); proxy.$modal.msgSuccess("å 餿å"); } else { let ids = []; if (productSelectedRows.value.length > 0) { ids = productSelectedRows.value.map((item) => item.id); // ç¼è¾æ¨¡å¼ä¸ï¼éè¦è°ç¨æ¥å£å é¤ const ids = productSelectedRows.value .filter(item => item.id) .map((item) => item.id); if (ids.length === 0) { proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); return; } ElMessageBox.confirm("éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { delProduct(ids).then((res) => { proxy.$modal.msgSuccess("å 餿å"); closeProductDia(); getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then( (res) => { productData.value = res.productData; } ); }); }) .catch(() => { proxy.$modal.msg("已忶"); try { await ElMessageBox.confirm("éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }); await delProduct(ids); proxy.$modal.msgSuccess("å 餿å"); closeProductDia(); // éæ°å è½½äº§åæ°æ® try { const res = await getSalesLedgerWithProducts({ id: currentId.value, type: 2 }); productData.value = res.productData || []; } catch (error) { console.error('éæ°å è½½äº§åæ°æ®å¤±è´¥:', error); } } catch (error) { if (error !== 'cancel') { console.error('å é¤äº§å失败:', error); proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } } } }; // å ³é产åå¼¹æ¡ @@ -1313,62 +1616,71 @@ productFormVisible.value = false; }; // å¯¼åº const handleOut = () => { ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); }) .catch(() => { proxy.$modal.msg("已忶"); const handleOut = async () => { try { await ElMessageBox.confirm("éä¸çå 容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åºç¡®è®¤", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }); proxy.download("/purchase/ledger/export", {}, "éè´å°è´¦.xlsx"); } catch (error) { if (error !== 'cancel') { console.error('导åºå¤±è´¥:', error); proxy.$modal.msgError("导åºå¤±è´¥ï¼è¯·ç¨åéè¯"); } } }; // å é¤ const handleDelete = () => { let ids = []; if (selectedRows.value.length > 0) { // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName); if (unauthorizedData.length > 0) { proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); return; } ids = selectedRows.value.map((item) => item.id); } else { const handleDelete = async () => { if (selectedRows.value.length === 0) { proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); return; } ElMessageBox.confirm("éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }) .then(() => { delPurchase(ids).then((res) => { proxy.$modal.msgSuccess("å 餿å"); getList(); }); }) .catch(() => { proxy.$modal.msg("已忶"); // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® const unauthorizedData = selectedRows.value.filter(item => item.recorderName !== userStore.nickName); if (unauthorizedData.length > 0) { proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); return; } const ids = selectedRows.value .filter(item => item.id) .map((item) => item.id); if (ids.length === 0) { proxy.$modal.msgWarning("è¯·éæ©ææçæ°æ®"); return; } try { await ElMessageBox.confirm("éä¸çå 容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤ç¡®è®¤", { confirmButtonText: "确认", cancelButtonText: "åæ¶", type: "warning", }); await delPurchase(ids); proxy.$modal.msgSuccess("å 餿å"); getList(); } catch (error) { if (error !== 'cancel') { console.error('å é¤å¤±è´¥:', error); proxy.$modal.msgError("å é¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } } }; // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD function getCurrentDate() { const today = new Date(); const year = today.getFullYear(); const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ const day = String(today.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; return dayjs().format("YYYY-MM-DD"); } const mathNum = () => { if (!productForm.value.taxRate) { proxy.$modal.msgWarning("请å éæ©ç¨ç"); return; } if (!productForm.value.taxRate) { proxy.$modal.msgWarning("请å éæ©ç¨ç"); return; } if (!productForm.value.taxInclusiveUnitPrice) { return; } @@ -1377,61 +1689,59 @@ } // å«ç¨æ»ä»·è®¡ç® productForm.value.taxInclusiveTotalPrice = proxy.calculateTaxIncludeTotalPrice( productForm.value.taxInclusiveUnitPrice, productForm.value.quantity ); proxy.calculateTaxIncludeTotalPrice( productForm.value.taxInclusiveUnitPrice, productForm.value.quantity ); if (productForm.value.taxRate) { // ä¸å«ç¨æ»ä»·è®¡ç® productForm.value.taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice( productForm.value.taxInclusiveTotalPrice, productForm.value.taxRate ); proxy.calculateTaxExclusiveTotalPrice( productForm.value.taxInclusiveTotalPrice, productForm.value.taxRate ); } }; const reverseMathNum = (field) => { if (!productForm.value.taxRate) { proxy.$modal.msgWarning("请å éæ©ç¨ç"); return; } if (!productForm.value.taxRate) { proxy.$modal.msgWarning("请å éæ©ç¨ç"); return; } const taxRate = Number(productForm.value.taxRate); if (!taxRate) return; if (field === 'taxInclusiveTotalPrice') { // å·²ç¥å«ç¨æ»ä»·åæ°éï¼åç®å«ç¨åä»· if (productForm.value.quantity) { productForm.value.taxInclusiveUnitPrice = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); productForm.value.taxInclusiveUnitPrice = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); } // å·²ç¥å«ç¨æ»ä»·åå«ç¨åä»·ï¼åç®æ°é else if (productForm.value.taxInclusiveUnitPrice) { productForm.value.quantity = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); productForm.value.quantity = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); } // åç®ä¸å«ç¨æ»ä»· productForm.value.taxExclusiveTotalPrice = (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2); productForm.value.taxExclusiveTotalPrice = (Number(productForm.value.taxInclusiveTotalPrice) / (1 + taxRate / 100)).toFixed(2); } else if (field === 'taxExclusiveTotalPrice') { // åç®å«ç¨æ»ä»· productForm.value.taxInclusiveTotalPrice = (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2); productForm.value.taxInclusiveTotalPrice = (Number(productForm.value.taxExclusiveTotalPrice) * (1 + taxRate / 100)).toFixed(2); // å·²ç¥æ°éï¼åç®å«ç¨åä»· if (productForm.value.quantity) { productForm.value.taxInclusiveUnitPrice = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); productForm.value.taxInclusiveUnitPrice = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.quantity)).toFixed(2); } // å·²ç¥å«ç¨åä»·ï¼åç®æ°é else if (productForm.value.taxInclusiveUnitPrice) { productForm.value.quantity = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); productForm.value.quantity = (Number(productForm.value.taxInclusiveTotalPrice) / Number(productForm.value.taxInclusiveUnitPrice)).toFixed(2); } } }; // éå®ååéæ©æ¹åæ¹æ³ const salesLedgerChange = async (row) => { console.log("row", row); var index = salesContractList.value.findIndex((item) => item.id == row); console.log("index", index); const index = salesContractList.value.findIndex((item) => item.id === row); if (index > -1) { form.value.projectName = salesContractList.value[index].projectName; await querygProductInfoByContractNo(); @@ -1478,14 +1788,19 @@ proxy.$modal.msgWarning("äºç»´ç æªçæ"); return; } const a = document.createElement('a'); a.href = qrCodeUrl.value; a.download = `éè´ååå·äºç»´ç _${new Date().getTime()}.png`; document.body.appendChild(a); a.click(); document.body.removeChild(a); proxy.$modal.msgSuccess("ä¸è½½æå"); try { const a = document.createElement('a'); a.href = qrCodeUrl.value; a.download = `éè´ååå·äºç»´ç _${dayjs().format('YYYYMMDDHHmmss')}.png`; document.body.appendChild(a); a.click(); document.body.removeChild(a); proxy.$modal.msgSuccess("ä¸è½½æå"); } catch (error) { console.error('ä¸è½½äºç»´ç 失败:', error); proxy.$modal.msgError("ä¸è½½å¤±è´¥ï¼è¯·ç¨åéè¯"); } }; // æ«ç æ°å¢å¯¹è¯æ¡ç¸å ³åé @@ -1538,7 +1853,7 @@ // è§£ææ«ç å å®¹ï¼æ¨¡æè§£æäºç»´ç æ°æ®ï¼ const parseScanContent = (content) => { if (!content) return; // 模æè§£æäºç»´ç å 容ï¼è¿éå¯ä»¥æ ¹æ®å®é éæ±è°æ´è§£æé»è¾ // å设æ«ç å å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|项ç®|éé¢|仿¬¾æ¹å¼ const parts = content.split('|'); @@ -1558,30 +1873,35 @@ }; // æäº¤æ«ç æ°å¢ const submitScanAdd = () => { proxy.$refs["scanAddFormRef"].validate((valid) => { if (valid) { // æå»ºæ°å¢æ°æ® const newData = { purchaseContractNumber: scanAddForm.purchaseContractNumber, supplierName: scanAddForm.supplierName, projectName: scanAddForm.projectName, contractAmount: scanAddForm.contractAmount, paymentMethod: scanAddForm.paymentMethod, recorderName: scanAddForm.recorderName, entryDate: getCurrentDate(), remark: scanAddForm.scanRemark, type: 2 }; // æ¨¡ææ°å¢æå proxy.$modal.msgSuccess("æ«ç æ°å¢æåï¼"); closeScanAddDialog(); // å¯ä»¥éæ©æ¯å¦å·æ°å表 // getList(); const submitScanAdd = async () => { try { const valid = await proxy.$refs["scanAddFormRef"].validate().catch(() => false); if (!valid) { return; } }); // æå»ºæ°å¢æ°æ® const newData = { purchaseContractNumber: scanAddForm.purchaseContractNumber, supplierName: scanAddForm.supplierName, projectName: scanAddForm.projectName, contractAmount: scanAddForm.contractAmount, paymentMethod: scanAddForm.paymentMethod, recorderName: scanAddForm.recorderName, entryDate: getCurrentDate(), remark: scanAddForm.scanRemark, type: 2 }; // await addOrEditPurchase(newData); proxy.$modal.msgSuccess("æ«ç æ°å¢æåï¼"); closeScanAddDialog(); getList(); // å·æ°å表 } catch (error) { console.error('æäº¤æ«ç æ°å¢å¤±è´¥:', error); proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } }; // æå¼æ«ç ç»è®°å¯¹è¯æ¡ @@ -1604,33 +1924,32 @@ }; // æäº¤æ«ç ç»è®° const submitScan = () => { proxy.$refs["scanFormRef"].validate((valid) => { if (valid) { // æ·»å æ«ç è®°å½ scanRecords.value.push({ ...scanForm, id: Date.now(), // 模æID scanTime: getCurrentDateTime(), }); scanForm.scanStatus = "å·²æ«ç "; scanForm.scanRemark = scanForm.scanRemark || "æ "; proxy.$modal.msgSuccess("æ«ç ç»è®°æåï¼"); closeScanDialog(); const submitScan = async () => { try { const valid = await proxy.$refs["scanFormRef"].validate().catch(() => false); if (!valid) { return; } }); // æ·»å æ«ç è®°å½ scanRecords.value.push({ ...scanForm, id: Date.now(), // 模æID scanTime: getCurrentDateTime(), }); scanForm.scanStatus = "å·²æ«ç "; scanForm.scanRemark = scanForm.scanRemark || "æ "; proxy.$modal.msgSuccess("æ«ç ç»è®°æåï¼"); closeScanDialog(); } catch (error) { console.error('æäº¤æ«ç ç»è®°å¤±è´¥:', error); proxy.$modal.msgError("æäº¤å¤±è´¥ï¼è¯·ç¨åéè¯"); } }; // è·åå½åæ¥ææ¶é´ function getCurrentDateTime() { const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); const hours = String(now.getHours()).padStart(2, "0"); const minutes = String(now.getMinutes()).padStart(2, "0"); const seconds = String(now.getSeconds()).padStart(2, "0"); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; return dayjs().format("YYYY-MM-DD HH:mm:ss"); } // æ·»å è¡ç±»åæ¹æ³ @@ -1638,8 +1957,18 @@ return row.isInvalid ? 'invalid-row' : ''; }; // è·å模æ¿ä¿¡æ¯ const getTemplateList =async ()=>{ let res = await getPurchaseTemplateList() if(res && res.code===200 && Array.isArray(res.data)){ templateList.value = res.data } } onMounted(() => { getList(); getTemplateList(); }); </script> @@ -1648,4 +1977,16 @@ opacity: 0.6; background-color: #f5f7fa; } .el-row{ justify-content: space-between; align-items: center } .no-arrow-select { --el-select-suffix-icon-color: transparent; /* éèé»è®¤ä¸æç®å¤´ */ } .select-button-group { display: flex; align-items: center; } </style>