已添加29个文件
已重命名1个文件
已修改102个文件
已删除121个文件
| | |
| | | { |
| | | "default": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "è¯å¯¼äºï¼ç®¡çä¿¡æ¯ç³»ç»ï¼" |
| | | "VITE_APP_TITLE": "åæ³°ä¼ä¸ä¿¡æ¯ç®¡çç³»ç»" |
| | | }, |
| | | "screen": "screen/SQDView.png", |
| | | "logo": "logo/SQDLogo.png", |
| | | "favicon": "favicon/SQDico.ico" |
| | | "screen": "screen/JTWYView.png", |
| | | "logo": "logo/JTWYLogo.png", |
| | | "favicon": "favicon/JTWYico.ico" |
| | | }, |
| | | "SQD": { |
| | | "JTWY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "天津åå¥ç¹ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9042", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9044" |
| | | "VITE_APP_TITLE": "åæ³°ä¼ä¸ä¿¡æ¯ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://114.132.189.42:9123", |
| | | "VITE_JAVA_API": "http://114.132.189.42:9031" |
| | | }, |
| | | "screen": "screen/SQDView.png", |
| | | "logo": "logo/SQDLogo.png", |
| | | "favicon": "favicon/SQDico.ico" |
| | | "screen": "screen/JTWYView.png", |
| | | "logo": "logo/JTWYLogo.png", |
| | | "favicon": "favicon/JTWYico.ico" |
| | | }, |
| | | "screen": "/src/assets/images/login-background.png", |
| | | "logo": "/src/assets/logo/logo.png", |
| | |
| | | "fuse.js": "6.6.2", |
| | | "js-beautify": "1.14.11", |
| | | "js-cookie": "3.0.5", |
| | | "jsbarcode": "^3.12.1", |
| | | "jsencrypt": "3.3.2", |
| | | "nprogress": "0.2.0", |
| | | "pinia": "2.1.7", |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request.js"; |
| | | |
| | | export function productModelList(query) { |
| | | return request({ |
| | | url: '/basic/product/pageModel', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // å é¤è®°å½ |
| | | export function ledgerRecordDelete(ids) { |
| | | return request({ |
| | | url: "/measuringInstrumentLedgerRecord/delete", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | |
| | | // å é¤èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function delStockInCustom(ids) { |
| | | return request({ |
| | | url: '/stockin/deleteCustom', |
| | | method: 'delete', |
| | | url: '/stockin/delteCustom', |
| | | method: 'post', |
| | | data: ids |
| | | }) |
| | | } |
| | |
| | | export function selectProductRecordListByPuechaserId(query) { |
| | | return request({ |
| | | url: '/stockin/productlist', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // èªå®ä¹å
¥åº-详æ
|
| | | export function detailManagementByCustom(query) { |
| | | return request({ |
| | | url: '/stockin/detailManagementByCustom', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | // éè´å
¥åº-详æ
|
| | | export function stockinDetail(query) { |
| | | return request({ |
| | | url: '/stockin/detail', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | //æ¥è¯¢åºåºå表 |
| | | // åºåºå°è´¦-éè´åºåºæ¥è¯¢åºåºå表 |
| | | export const getStockOutPage = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPage", |
| | |
| | | data: ids |
| | | }) |
| | | } |
| | | |
| | | //导åºåºåºä¿¡æ¯ |
| | | export const exportStockOut = (query) => { |
| | | return request({ |
| | | url: '/stockmanagement/export', |
| | | method: 'get', |
| | | params: query, |
| | | responseType: 'blob' |
| | | }) |
| | | } |
| | |
| | | method: 'get', |
| | | params: query, |
| | | }) |
| | | } |
| | | |
| | | // 导åºåå坿¬ |
| | | export function staffOnJobExportCopy(data) { |
| | | return request({ |
| | | url: '/staff/staffOnJob/exportCopy', |
| | | method: 'post', |
| | | data: data, |
| | | }) |
| | | } |
| | |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| | | // 导å
¥ |
| | | export function importData(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/importData", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // ä¸è½½æ¨¡ç |
| | | export function exportTemplate(query) { |
| | | return request({ |
| | | url: "/compensationPerformance/exportTemplate", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | export function getCurrentUserLatestScheduling(){ |
| | | return request({ |
| | | url: "/staff/staffScheduling/getCurrentUserLatestScheduling", |
| | | method: "get" |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/processRoute/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/processRoute", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function del(ids) { |
| | | return request({ |
| | | url: '/processRoute/' + ids, |
| | | method: 'delete', |
| | | }) |
| | | } |
| | | |
| | | export function update(data) { |
| | | return request({ |
| | | url: '/processRoute', |
| | | method: 'put', |
| | | data: data, |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡¹ç®é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å表æ¥è¯¢ |
| | | export function findProcessRouteItemList(query) { |
| | | return request({ |
| | | url: "/processRouteItem/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function addOrUpdateProcessRouteItem(data) { |
| | | return request({ |
| | | url: "/processRouteItem", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥èºè·¯çº¿é¡¹ç®é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å表æ¥è¯¢ |
| | | export function findProductProcessRouteItemList(query) { |
| | | return request({ |
| | | url: "/productProcessRoute/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function addOrUpdateProductProcessRouteItem(data) { |
| | | return request({ |
| | | url: "/productProcessRoute/updateRouteItem", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // å é¤å®¢æ·æ¡£æ¡ |
| | | export function deleteRouteItem(ids) { |
| | | return request({ |
| | | url: '/productProcessRoute/deleteRouteItem', |
| | | method: 'delete', |
| | | data: ids |
| | | }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // 产åç»æé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function queryList(id) { |
| | | return request({ |
| | | url: "/productStructure/listByproductModelId/" + id, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/productStructure", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | |
| | | export function productOrderListPage(query) { |
| | | return request({ |
| | | url: "/productOrder/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // è·åçæºæ£å¨å·¥ä½éæ°æ® |
| | | export function schedulingList(query) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // ä¿åçæºè®¾ç½® |
| | | export function addSpeculatTrading(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/addSpeculatTrading", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹çæºè®¾ç½® |
| | | export function updateSpeculatTrading(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/updateSpeculatTrading", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ç产派工 |
| | | export function productionDispatch(query) { |
| | | return request({ |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | // èªå¨æ´¾å·¥ |
| | | export function productionDispatchList(query) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/productionDispatchList", |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // æ¥è¯¢æèç |
| | | export function getLossRate() { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/loss", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | // æ°å¢æèç |
| | | export function addLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/addLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // ä¿®æ¹æèç |
| | | export function updateLossRate(data) { |
| | | return request({ |
| | | url: "/salesLedger/scheduling/updateLoss", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å·¥åºé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function listPage(query) { |
| | | return request({ |
| | | url: "/productProcess/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function processList(query) { |
| | | return request({ |
| | | url: "/productProcess/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function add(data) { |
| | | return request({ |
| | | url: "/productProcess", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function del(data) { |
| | | return request({ |
| | | url: '/productProcess/batchDelete', |
| | | method: 'delete', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | export function update(data) { |
| | | return request({ |
| | | url: '/productProcess/update', |
| | | method: 'put', |
| | | data: data, |
| | | }) |
| | | } |
| | | |
| | | // å·¥åºæ¥è¯¢ |
| | | export function list() { |
| | | return request({ |
| | | url: "/productProcess/list", |
| | | method: "get", |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产æå
¥é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductInputListPage(query) { |
| | | return request({ |
| | | url: "/productionProductInput/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产æ¥å·¥é¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductMainListPage(query) { |
| | | return request({ |
| | | url: "/productionProductMain/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // ç产产åºé¡µé¢æ¥å£ |
| | | import request from "@/utils/request"; |
| | | |
| | | // å页æ¥è¯¢ |
| | | export function productionProductOutputListPage(query) { |
| | | return request({ |
| | | url: "/productionProductOutput/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | method: "post", |
| | | data: query, |
| | | }); |
| | | } |
| | | } |
| | | // ç产æ¥å·¥-å é¤ |
| | | export function productionReportDelete(query) { |
| | | return request({ |
| | | url: "/productionProductMain/delete", |
| | | method: "delete", |
| | | data: query, |
| | | }); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | export function productWorkOrderPage(query) { |
| | | return request({ |
| | | url: "/productWorkOrder/page", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | export function updateProductWorkOrder(data) { |
| | | return request({ |
| | | url: "/productWorkOrder/updateProductWorkOrder", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | export function addProductMain(data) { |
| | | return request({ |
| | | url: "/productionProductMain/addProductMain", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | method: 'get',
|
| | | params: query
|
| | | })
|
| | | }// æ¥è¯¢ç¨æ·å表
|
| | | export function listAll(query) {
|
| | | return request({
|
| | | url: '/system/user//listAll',
|
| | | method: 'get',
|
| | | params: query
|
| | | })
|
| | | }
|
| | |
|
| | | // æ¥è¯¢ç¨æ·è¯¦ç»
|
| | |
| | | url: '/sales/ledger/getAmountHalfYear', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // ååå¾
审æ¹åæ¥ä¿®å¾
åäºé¡¹ |
| | | export const approveAndDeviceTodos = () => { |
| | | return request({ |
| | | url: '/home/approveAndDeviceTodos', |
| | | method: 'get' |
| | | }) |
| | | } |
| | | export const noticesCount = () => { |
| | | return request({ |
| | | url: '/home/noticesCount', |
| | | method: 'get' |
| | | }) |
| | | } |
| | |
| | | </el-table-column> |
| | | </el-table> |
| | | <pagination |
| | | v-if="isShowPage" |
| | | :total="page.total" |
| | | :layout="page.layout" |
| | | :page="page.current" |
| | |
| | | isSelection: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | isShowPage: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | isShowSummary: { |
| | | type: Boolean, |
| | |
| | | }) |
| | | |
| | | const handleSizeChange = (val) => { |
| | | console.log('handleSizeChange', val) |
| | | if (currentPage.value * val > props.total) { |
| | | currentPage.value = 1 |
| | | } |
| | |
| | | } |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | console.log('handleCurrentChange---', val) |
| | | emit('pagination', { page: val, limit: pageSize.value }) |
| | | if (props.autoScroll) { |
| | | scrollTo(0, 800) |
| | |
| | | }); |
| | | |
| | | const props = defineProps({ |
| | | // downloadTemplate: Function, |
| | | downloadTemplate: Function, |
| | | showTips: Boolean, |
| | | accept: { |
| | | type: String, |
| | |
| | | default: 1, |
| | | }, |
| | | }); |
| | | const emits = defineEmits(["success", "remove", "downloadTemplate"]); |
| | | const emits = defineEmits(["success", "remove"]); |
| | | |
| | | const uploadRef = ref(); |
| | | const fileList = ref([]); |
| | |
| | | type="primary" |
| | | link |
| | | class="reset-margin" |
| | | @click="emits('downloadTemplate')" |
| | | @click="props.downloadTemplate()" |
| | | > |
| | | <span style="font-size: 12px; font-weight: normal">ä¸è½½æ¨¡æ¿</span> |
| | | </el-button> |
| | |
| | | <el-select |
| | | v-model="form.maintainer" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | clearable |
| | | disabled |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | return row.maintainer !== userStore.nickName |
| | | } |
| | | } |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.maintainer !== userStore.nickName); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | |
| | | <el-dialog v-model="upload.open" :title="upload.title"> |
| | | <FileUpload |
| | | ref="fileUploadRef" |
| | | accept=".xlsx,.xls" |
| | | accept=".xlsx, .xls" |
| | | :headers="upload.headers" |
| | | :action="upload.url + '?updateSupport=' + upload.updateSupport" |
| | | :disabled="upload.isUploading" |
| | | :showTip="true" |
| | | :showTip="false" |
| | | @success="handleFileSuccess" |
| | | @downloadTemplate="downloadTemplate" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { reactive, ref, getCurrentInstance } from "vue"; |
| | | import { reactive } from "vue"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | import { FileUpload } from "@/components/Upload"; |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | defineOptions({ |
| | | name: "产åç»´æ¤å¯¼å
¥", |
| | | }); |
| | |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import", |
| | | updateSupport: true, |
| | | }); |
| | | // ç¹å»å¯¼å
¥ |
| | | const handleImport = () => { |
| | | upload.open = true; |
| | | upload.title = "产å导å
¥"; |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿ |
| | | const downloadTemplate = () =>{ |
| | | proxy.download("/basic/product/downloadTemplate", {}, "产å导å
¥æ¨¡æ¿.xlsx"); |
| | | } |
| | | |
| | | const submitFileForm = () => { |
| | | fileUploadRef.value.uploadApi(); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | title="éæ©äº§å" |
| | | width="900px" |
| | | destroy-on-close |
| | | :close-on-click-modal="false" |
| | | > |
| | | <el-form :inline="true" :model="query" class="mb-2"> |
| | | <el-form-item label="产å大类"> |
| | | <el-input |
| | | v-model="query.productName" |
| | | placeholder="è¾å
¥äº§å大类" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="åå·åç§°"> |
| | | <el-input |
| | | v-model="query.model" |
| | | placeholder="è¾å
¥åå·åç§°" |
| | | clearable |
| | | @keyup.enter="onSearch" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item> |
| | | <el-button type="primary" @click="onSearch">æç´¢</el-button> |
| | | <el-button @click="onReset">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- å表 --> |
| | | <el-table |
| | | v-loading="loading" |
| | | :data="tableData" |
| | | height="420" |
| | | highlight-current-row |
| | | row-key="id" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column type="index" label="#" width="60"/> |
| | | <el-table-column prop="productName" label="产å大类" min-width="160"/> |
| | | <el-table-column prop="model" label="åå·åç§°" min-width="200"/> |
| | | <el-table-column prop="unit" label="åä½" min-width="160"/> |
| | | </el-table> |
| | | |
| | | <div class="mt-3 flex justify-end"> |
| | | <el-pagination |
| | | background |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :total="total" |
| | | v-model:page-size="page.pageSize" |
| | | v-model:current-page="page.pageNum" |
| | | :page-sizes="[10, 20, 50, 100]" |
| | | @size-change="onPageChange" |
| | | @current-change="onPageChange" |
| | | /> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <el-button @click="close()">åæ¶</el-button> |
| | | <el-button type="primary" :disabled="multipleSelection.length === 0" @click="onConfirm"> |
| | | ç¡®å® |
| | | </el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {computed, onMounted, reactive, ref, watch} from "vue"; |
| | | import {ElMessage} from "element-plus"; |
| | | import {productModelList} from '@/api/basicData/productModel' |
| | | |
| | | export type ProductRow = { |
| | | id: number; |
| | | productName: string; |
| | | model: string; |
| | | unit?: string; |
| | | }; |
| | | |
| | | const props = defineProps<{ |
| | | modelValue: boolean; |
| | | }>(); |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'confirm']); |
| | | |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (v) => emit("update:modelValue", v), |
| | | }); |
| | | |
| | | const query = reactive({ |
| | | productName: "", |
| | | model: "", |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | }); |
| | | |
| | | const loading = ref(false); |
| | | const tableData = ref<ProductRow[]>([]); |
| | | const total = ref(0); |
| | | const multipleSelection = ref<ProductRow[]>([]) |
| | | |
| | | function close() { |
| | | visible.value = false; |
| | | } |
| | | |
| | | const handleSelectionChange = (val: ProductRow[]) => { |
| | | multipleSelection.value = val |
| | | } |
| | | |
| | | function onSearch() { |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onReset() { |
| | | query.productName = ""; |
| | | query.model = ""; |
| | | page.pageNum = 1; |
| | | loadData(); |
| | | } |
| | | |
| | | function onPageChange() { |
| | | loadData(); |
| | | } |
| | | |
| | | function onConfirm() { |
| | | if (multipleSelection.value.length === 0) { |
| | | ElMessage.warning("è¯·éæ©ä¸æ¡äº§å"); |
| | | return; |
| | | } |
| | | emit("confirm", multipleSelection.value); |
| | | close(); |
| | | } |
| | | |
| | | async function loadData() { |
| | | loading.value = true; |
| | | try { |
| | | multipleSelection.value = []; // 翻页/æç´¢åæ¸
ç©ºéæ©æ´ç¬¦å颿 |
| | | const res = await productModelList({ |
| | | productName: query.productName.trim(), |
| | | model: query.model.trim(), |
| | | current: page.pageNum, |
| | | size: page.pageSize, |
| | | }); |
| | | tableData.value = res.records; |
| | | total.value = res.total; |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | loadData() |
| | | }) |
| | | </script> |
| | |
| | | <div class="right"> |
| | | <div style="margin-bottom: 10px" v-if="isShowButton"> |
| | | <el-button type="primary" @click="openModelDia('add')"> |
| | | æ°å¢äº§åé«åº¦ |
| | | æ°å¢è§æ ¼åå· |
| | | </el-button> |
| | | <ImportExcel @uploadSuccess="getModelList" /> |
| | | <el-button |
| | |
| | | </el-dialog> |
| | | <el-dialog |
| | | v-model="modelDia" |
| | | title="产åé«åº¦" |
| | | title="è§æ ¼åå·" |
| | | width="400px" |
| | | @close="closeModelDia" |
| | | @keydown.enter.prevent |
| | |
| | | > |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产åé«åº¦ï¼" prop="model"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="model"> |
| | | <el-input |
| | | v-model="modelForm.model" |
| | | placeholder="请è¾å
¥äº§åé«åº¦" |
| | | placeholder="请è¾å
¥è§æ ¼åå·(g*è¢æ°)" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="é«åº¦åä½ï¼" prop="unit"> |
| | | <el-form-item label="å
¶ä»è§æ ¼åå·ï¼" prop="otherModel"> |
| | | <el-input |
| | | v-model="modelForm.unit" |
| | | placeholder="请è¾å
¥é«åº¦åä½" |
| | | v-model="modelForm.otherModel" |
| | | placeholder="请è¾å
¥å
¶ä»è§æ ¼åå·" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="åä½ï¼" prop="unit"> |
| | | <el-input |
| | | v-model="modelForm.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- <el-row>--> |
| | | <!-- <el-col :span="24">--> |
| | | <!-- <el-form-item label="ç»å®æºå¨ï¼" prop="speculativeTradingName">--> |
| | | <!-- <el-select--> |
| | | <!-- v-model="modelForm.speculativeTradingName"--> |
| | | <!-- placeholder="è¯·éæ©ç»å®æºå¨"--> |
| | | <!-- multiple--> |
| | | <!-- clearable--> |
| | | <!-- style="width: 100%"--> |
| | | <!-- >--> |
| | | <!-- <el-option label="çæº1" value="çæº1" />--> |
| | | <!-- <el-option label="çæº2" value="çæº2" />--> |
| | | <!-- <el-option label="çæº3" value="çæº3" />--> |
| | | <!-- <el-option label="çæº4" value="çæº4" />--> |
| | | <!-- </el-select>--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | const expandedKeys = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "产åé«åº¦", |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "é«åº¦åä½", |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | // { |
| | | // label: "ç»å®æºå¨", |
| | | // prop: "speculativeTradingName", |
| | | // }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | |
| | | productName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | modelForm: { |
| | | otherModel:'', |
| | | model: "", |
| | | unit: "", |
| | | speculativeTradingName: [], |
| | | }, |
| | | modelRules: { |
| | | model: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | model: [ |
| | | // { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | { |
| | | pattern: /^[0-9*]*$/, |
| | | message: "åªè½è¾å
¥æ°åå*å·", |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | // unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // speculativeTradingName: [{ required: false, message: "è¯·éæ©ç»å®æºå¨", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules, modelForm, modelRules } = toRefs(data); |
| | |
| | | form.value.productName = data.productName; |
| | | } |
| | | }; |
| | | // æå¼äº§åé«åº¦å¼¹æ¡ |
| | | // æå¼è§æ ¼åå·å¼¹æ¡ |
| | | const openModelDia = (type, data) => { |
| | | modelOperationType.value = type; |
| | | modelDia.value = true; |
| | | modelForm.value.model = ""; |
| | | modelForm.value.model = ""; |
| | | modelForm.value.unit = ""; |
| | | modelForm.value.speculativeTradingName = []; |
| | | modelForm.value.id = ""; |
| | | if (type === "edit") { |
| | | modelForm.value = { ...data }; |
| | | // 妿å端è¿åçæ¯å符串ï¼éè¦è½¬æ¢ä¸ºæ°ç» |
| | | if (data.speculativeTradingName && typeof data.speculativeTradingName === 'string') { |
| | | modelForm.value.speculativeTradingName = data.speculativeTradingName.split(','); |
| | | } |
| | | } |
| | | }; |
| | | // æäº¤äº§ååç§°ä¿®æ¹ |
| | |
| | | const submitModelForm = () => { |
| | | proxy.$refs.modelFormRef.validate((valid) => { |
| | | if (valid) { |
| | | modelForm.value.productId = currentId.value; |
| | | addOrEditProductModel(modelForm.value).then((res) => { |
| | | let _modelForm = { ...modelForm.value }; |
| | | |
| | | if(_modelForm.otherModel){ |
| | | _modelForm.model = _modelForm.otherModel; |
| | | } |
| | | delete _modelForm.otherModel; |
| | | // å°éä¸çæºå¨æ°ç»è½¬æ¢ä¸ºéå·åéçå符串 |
| | | const submitData = { |
| | | ..._modelForm, |
| | | productId: currentId.value, |
| | | speculativeTradingName: modelForm.value.speculativeTradingName.join(',') |
| | | }; |
| | | addOrEditProductModel(submitData).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeModelDia(); |
| | | getModelList(); |
| | |
| | | v-model="form.maintainUserId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | return row.maintainUserName !== userStore.nickName |
| | | } |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | |
| | | <template #footer v-if="operationType === 'approval'"> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm(2)">ä¸éè¿</el-button> |
| | | <el-button type="primary" @click="openSignatureDialog(1)">éè¿</el-button> |
| | | <el-button type="primary" @click="submitForm(1)">éè¿</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <!-- çµåç¾åå¼¹çªï¼vue3-signature-padï¼ --> |
| | | <el-dialog v-model="signatureDialogVisible" title="çµåç¾å" width="600px" append-to-body> |
| | | <vueEsign |
| | | ref="esign" |
| | | class="mySign" |
| | | :width="800" |
| | | :height="300" |
| | | :isCrop="isCrop" |
| | | :lineWidth="lineWidth" |
| | | :lineColor="lineColor" |
| | | /> |
| | | <div style="margin-top:10px;"> |
| | | <el-button @click="clearSignature">æ¸
é¤</el-button> |
| | | <el-button type="primary" @click="confirmSignature">ç¡®å®</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getCurrentInstance, reactive, ref, toRefs } from "vue"; |
| | | import vueEsign from "vue-esign"; |
| | | import { |
| | | approveProcessDetails, |
| | | getDept, |
| | |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue' |
| | | import { getToken } from "@/utils/auth"; |
| | | const emit = defineEmits(['close']) |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | |
| | | }, |
| | | }); |
| | | const { form } = toRefs(data); |
| | | const signatureDialogVisible = ref(false); |
| | | const signatureImg = ref(''); |
| | | let submitStatus = null; // 临æ¶åå¨éè¿/ä¸éè¿ç¶æ |
| | | const isCrop = ref(""); |
| | | const esign = ref(null); |
| | | const lineWidth = ref(0); |
| | | const lineColor = ref("#000000"); |
| | | |
| | | // ä¸ä¼ é
ç½® |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | // èç¹æ é¢ |
| | | const getNodeTitle = (index, len) => { |
| | |
| | | productOptions.value = res.data; |
| | | }); |
| | | }; |
| | | // æå¼ç¾åå¼¹çª |
| | | const openSignatureDialog = (status) => { |
| | | submitStatus = status; |
| | | signatureDialogVisible.value = true; |
| | | }; |
| | | // æ¸
é¤ç¾å |
| | | const clearSignature = () => { |
| | | esign.value.reset(); |
| | | }; |
| | | // 确认ç¾å |
| | | const confirmSignature = () => { |
| | | esign.value.generate().then((res) => { |
| | | console.log(res); |
| | | // å°base64转æ¢ä¸ºäºè¿å¶ |
| | | const base64Data = res.split(',')[1]; // ç§»é¤data:image/png;base64,åç¼ |
| | | const binaryString = atob(base64Data); |
| | | const bytes = new Uint8Array(binaryString.length); |
| | | for (let i = 0; i < binaryString.length; i++) { |
| | | bytes[i] = binaryString.charCodeAt(i); |
| | | } |
| | | signatureImg.value = bytes; |
| | | |
| | | // å建æä»¶å¯¹è±¡ç¨äºä¸ä¼ |
| | | const blob = new Blob([bytes], { type: 'image/png' }); |
| | | const file = new File([blob], 'signature.png', { type: 'image/png' }); |
| | | |
| | | // å建FormData |
| | | const formData = new FormData(); |
| | | formData.append('file', file); |
| | | |
| | | // ä¸ä¼ ç¾åå¾ç |
| | | fetch(upload.url, { |
| | | method: 'POST', |
| | | headers: upload.headers, |
| | | body: formData |
| | | }) |
| | | .then(response => response.json()) |
| | | .then(data => { |
| | | if (data.code === 200) { |
| | | console.log('data---', data) |
| | | let tempFileIds = []; |
| | | tempFileIds.push(data.data.tempId); |
| | | signatureDialogVisible.value = false; |
| | | clearSignature(); |
| | | // åªæéè¿æ¶æä¼ éç¾åæä»¶ID |
| | | if (submitStatus === 1) { |
| | | submitForm(submitStatus, tempFileIds); |
| | | } else { |
| | | submitForm(submitStatus); |
| | | } |
| | | } else { |
| | | proxy.$modal.msgError("ç¾åå¾çä¸ä¼ 失败ï¼" + data.msg); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('ä¸ä¼ 失败:', error); |
| | | proxy.$modal.msgError("ç¾åå¾çä¸ä¼ 失败"); |
| | | }); |
| | | }).catch((err) => { |
| | | console.log(err); |
| | | proxy.$modal.msgWarning("请å
ç¾åï¼"); |
| | | }) |
| | | }; |
| | | // æäº¤å®¡æ¹ |
| | | const submitForm = (status, tempFileIds) => { |
| | | const submitForm = (status) => { |
| | | const filteredActivities = activities.value.filter(activity => activity.isShen); |
| | | filteredActivities[0].approveNodeStatus = status; |
| | | // åªæéè¿æ¶æéè¦ç¾å |
| | | if (status === 1 && tempFileIds) { |
| | | filteredActivities[0].tempFileIds = tempFileIds; |
| | | } |
| | | // 夿æ¯å¦ä¸ºæå䏿¥ |
| | | const isLast = activities.value.findIndex(a => a.isShen) === activities.value.length-1; |
| | | updateApproveNode({ ...filteredActivities[0], isLast }).then(() => { |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼" prop="approveDeptId"> |
| | | <el-select |
| | | disabled |
| | | v-model="form.approveDeptId" |
| | | placeholder="éæ©é¨é¨" |
| | | > |
| | | <el-option |
| | | v-for="user in productOptions" |
| | | :key="user.deptId" |
| | | :label="user.deptName" |
| | | :value="user.deptId" |
| | | /> |
| | | </el-select> |
| | | <el-form-item label="ç³è¯·é¨é¨ï¼" prop="approveDeptName"> |
| | | <el-input v-model="form.approveDeptName" placeholder="请è¾å
¥" clearable/> |
| | | <!-- <el-select--> |
| | | <!-- disabled--> |
| | | <!-- v-model="form.approveDeptId"--> |
| | | <!-- placeholder="éæ©é¨é¨"--> |
| | | <!-- >--> |
| | | <!-- <el-option--> |
| | | <!-- v-for="user in productOptions"--> |
| | | <!-- :key="user.deptId"--> |
| | | <!-- :label="user.deptName"--> |
| | | <!-- :value="user.deptId"--> |
| | | <!-- />--> |
| | | <!-- </el-select>--> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item :label="props.approveType == 5 ? 'éè´è¯´æï¼' : '审æ¹äºç±ï¼'" prop="approveReason"> |
| | | <el-input v-model="form.approveReason" placeholder="请è¾å
¥" clearable type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- è¯·åæ¶é´ï¼ä»
å½ approveType 为 2 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row :gutter="30" v-if="props.approveType == 2"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="请åå¼å§æ¶é´ï¼" prop="startDate"> |
| | | <el-date-picker |
| | | v-model="form.startDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©å¼å§æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="请åç»ææ¶é´ï¼" prop="endDate"> |
| | | <el-date-picker |
| | | v-model="form.endDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ç»ææ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- æ¥ééé¢ï¼ä»
å½ approveType 为 4 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row v-if="props.approveType == 4"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ¥ééé¢ï¼" prop="price"> |
| | | <el-input-number |
| | | v-model="form.price" |
| | | placeholder="请è¾å
¥æ¥ééé¢" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="0.01" |
| | | style="width: 100%" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- åºå·®å°ç¹ï¼ä»
å½ approveType 为 3 æ¶æ¾ç¤ºï¼ --> |
| | | <el-row v-if="props.approveType == 3"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="åºå·®å°ç¹ï¼" prop="location"> |
| | | <el-input |
| | | v-model="form.location" |
| | | placeholder="请è¾å
¥åºå·®å°ç¹" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-select |
| | | v-model="form.approveUser" |
| | | placeholder="éæ©äººå" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | |
| | | approveId: "", |
| | | approveUser: "", |
| | | approveDeptId: "", |
| | | approveDeptName: "", |
| | | approveReason: "", |
| | | checkResult: "", |
| | | tempFileIds: [], |
| | | approverList: [] // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | approverList: [], // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | startDate: "", // 请åå¼å§æ¶é´ |
| | | endDate: "", // 请åç»ææ¶é´ |
| | | price: null, // æ¥ééé¢ |
| | | location: "" // åºå·®å°ç¹ |
| | | }, |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" },], |
| | | approveId: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveUser: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveDeptName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | startDate: [{ required: true, message: "è¯·éæ©è¯·åå¼å§æ¶é´", trigger: "change" }], |
| | | endDate: [{ required: true, message: "è¯·éæ©è¯·åç»ææ¶é´", trigger: "change" }], |
| | | price: [{ required: true, message: "请è¾å
¥æ¥ééé¢", trigger: "blur" }], |
| | | location: [{ required: true, message: "请è¾å
¥åºå·®å°ç¹", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | console.log('openDialog', type, row) |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | userListNoPageByTenantId().then((res) => { |
| | |
| | | proxy.$modal.msgError("请为ææå®¡æ¹èç¹éæ©å®¡æ¹äººï¼") |
| | | return |
| | | } |
| | | // å½ approveType 为 2 æ¶ï¼æ ¡éªè¯·åæ¶é´ |
| | | if (props.approveType == 2) { |
| | | if (!form.value.startDate) { |
| | | proxy.$modal.msgError("è¯·éæ©è¯·åå¼å§æ¶é´ï¼") |
| | | return |
| | | } |
| | | if (!form.value.endDate) { |
| | | proxy.$modal.msgError("è¯·éæ©è¯·åç»ææ¶é´ï¼") |
| | | return |
| | | } |
| | | // æ ¡éªç»ææ¶é´ä¸è½æ©äºå¼å§æ¶é´ |
| | | if (new Date(form.value.endDate) < new Date(form.value.startDate)) { |
| | | proxy.$modal.msgError("请åç»ææ¶é´ä¸è½æ©äºå¼å§æ¶é´ï¼") |
| | | return |
| | | } |
| | | } |
| | | // å½ approveType 为 3 æ¶ï¼æ ¡éªåºå·®å°ç¹ |
| | | if (props.approveType == 3) { |
| | | if (!form.value.location || form.value.location.trim() === '') { |
| | | proxy.$modal.msgError("请è¾å
¥åºå·®å°ç¹ï¼") |
| | | return |
| | | } |
| | | } |
| | | // å½ approveType 为 4 æ¶ï¼æ ¡éªæ¥ééé¢ |
| | | if (props.approveType == 4) { |
| | | if (!form.value.price || form.value.price <= 0) { |
| | | proxy.$modal.msgError("请è¾å
¥ææçæ¥ééé¢ï¼") |
| | | return |
| | | } |
| | | } |
| | | proxy.$refs.formRef.validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import { delCommonFile } from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | delCommonFile([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage.info('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "ç³è¯·æ¥æ", |
| | | prop: "approveTime", |
| | | label: "éé¢ï¼å
ï¼", |
| | | prop: "price", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: props.approveType === 2 ? "å¼å§æ¥æ" : "ç³è¯·æ¥æ", |
| | | prop: props.approveType === 2 ? "startDate" : "approveTime", |
| | | width: 200 |
| | | }, |
| | | { |
| | | label: "ç»ææ¥æ", |
| | | prop: "approveOverTime", |
| | | prop: props.approveType === 2 ? "endDate" : "approveOverTime", |
| | | width: 120 |
| | | }, |
| | | { |
| | |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4 |
| | | }, |
| | | { |
| | | name: "å®¡æ ¸", |
| | |
| | | |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <div class="notice-board"> |
| | | <!-- æ¾åéç¥åºå --> |
| | | <div class="notice-section" v-if="holidayNoticeCount > 0"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <div class="notice-section" v-if="totalNoticeCount > 0"> |
| | | <div class="section-header"> |
| | | <h3>ð
æ¾åéç¥</h3> |
| | | <span class="section-count">{{ holidayNoticeCount }}æ¡</span> |
| | | <h3>� éç¥å
Œ</h3> |
| | | <span class="section-count">{{ totalNoticeCount }}æ¡</span> |
| | | </div> |
| | | <div class="notice-cards"> |
| | | <!-- æ¾åéç¥ --> |
| | | <div |
| | | v-for="notice in holidayNotices" |
| | | :key="notice.id" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | |
| | | </div> |
| | | <div class="card-footer"> |
| | | <div class="card-meta"> |
| | | <span class="type" :class="'type-' + notice.type"> |
| | | {{ notice.type }} |
| | | </span> |
| | | <span class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </span> |
| | |
| | | <span>{{ notice.remark }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <pagination |
| | | v-if="holidayNoticePage.total > 0" |
| | | :total="holidayNoticePage.total" |
| | | :page="holidayNoticePage.current" |
| | | :limit="holidayNoticePage.size" |
| | | @pagination="handleHolidayNoticeCurrentChange" |
| | | /> |
| | | |
| | | <!-- 设å¤ç»´ä¿®éç¥åºå --> |
| | | <div class="notice-section" v-if="maintenanceNoticeCount > 0"> |
| | | <div class="section-header"> |
| | | <h3>ð§ 设å¤ç»´ä¿®éç¥</h3> |
| | | <span class="section-count">{{ maintenanceNoticeCount }}æ¡</span> |
| | | </div> |
| | | <div class="notice-cards"> |
| | | |
| | | <!-- 设å¤ç»´ä¿®éç¥ --> |
| | | <div |
| | | v-for="notice in maintenanceNotices" |
| | | :key="notice.id" |
| | | :key="'maintenance-' + notice.id" |
| | | class="notice-card maintenance-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ç»ä¸å页 --> |
| | | <pagination |
| | | v-if="maintenanceNoticePage.total > 0" |
| | | :total="maintenanceNoticePage.total" |
| | | :page="maintenanceNoticePage.current" |
| | | :limit="maintenanceNoticePage.size" |
| | | @pagination="handleMaintenanceNoticeCurrentChange" |
| | | v-if="(holidayNoticePage.total + maintenanceNoticePage.total) > 0" |
| | | :total="holidayNoticePage.total + maintenanceNoticePage.total" |
| | | :page="Math.max(holidayNoticePage.current, maintenanceNoticePage.current)" |
| | | :limit="Math.max(holidayNoticePage.size, maintenanceNoticePage.size)" |
| | | @pagination="handleCurrentChange" |
| | | /> |
| | | |
| | | <!-- ç©ºç¶æ --> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬åç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©å
¬åç±»å" style="width: 100%"> |
| | | <el-option label="æ¾åéç¥" :value="1"/> |
| | | <el-option label="设å¤ç»´ä¿®éç¥" :value="2"/> |
| | | </el-select> |
| | | <el-input v-model="form.type" placeholder="请è¾å
¥å
¬åæ é¢"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | }); |
| | | }; |
| | | |
| | | const holidayNoticeCount = ref() |
| | | const maintenanceNoticeCount = ref() |
| | | const totalNoticeCount = ref(0) |
| | | const fetchCount = () => { |
| | | getCount().then(res => { |
| | | holidayNoticeCount.value = res.data.filter(item => { |
| | | return item.type === 1 |
| | | })[0].count; |
| | | maintenanceNoticeCount.value = res.data.filter(item => { |
| | | return item.type === 2 |
| | | })[0].count; |
| | | totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0); |
| | | }); |
| | | } |
| | | |
| | |
| | | }) |
| | | |
| | | const fetchHolidayNotices = () => { |
| | | listNotice({...holidayNoticePage.value, type: 1}).then(res => { |
| | | listNotice({...holidayNoticePage.value}).then(res => { |
| | | holidayNotices.value = res.data.records |
| | | holidayNoticePage.value.total = res.data.total |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | const handleHolidayNoticeCurrentChange = (val) => { |
| | | const handleCurrentChange = (val) => { |
| | | holidayNoticePage.value.size = val.limit |
| | | holidayNoticePage.value.current = val.page |
| | | fetchHolidayNotices() |
| | | }; |
| | | |
| | | const handleMaintenanceNoticeCurrentChange = (val) => { |
| | | maintenanceNoticePage.value.size = val.limit |
| | | maintenanceNoticePage.value.current = val.page |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | }; |
| | | |
| | |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | word-wrap: break-word; |
| | | } |
| | | |
| | | .card-footer { |
| | |
| | | gap: 8px; |
| | | } |
| | | |
| | | .priority, .status { |
| | | .type, .priority, .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .type-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-1 { |
| | |
| | | font-size: 12px; |
| | | color: #606266; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .card-remark span { |
| | | flex: 1; |
| | | min-width: 0; |
| | | word-wrap: break-word; |
| | | word-break: break-all; |
| | | white-space: normal; |
| | | line-height: 1.5; |
| | | } |
| | | |
| | | .empty-state { |
| | |
| | | |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" link @click="openForm('view', row)">æ¥ç</el-button> |
| | | <el-button type="primary" link @click="openForm('edit', row)" v-if="row.status === 1">ç¼è¾</el-button> |
| | | <el-button type="primary" link @click="openForm('edit', row)">ç¼è¾</el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | return row.checkUserId !== userStore.id || row.status !== 1 |
| | | } |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.checkUserId !== userStore.id); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | |
| | | |
| | | <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() |
| | | |
| | |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | width: 100, |
| | | align: "center", |
| | | fixed: 'right', |
| | | operation: [ |
| | |
| | | clickFun: (row) => { |
| | | openCalibrationDia("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | return row.userId !== userStore.id |
| | | } |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "text", |
| | | style: { |
| | | color: "#F56C6C" |
| | | }, |
| | | clickFun: (row) => { |
| | | handleDelete(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | |
| | | }) |
| | | } |
| | | |
| | | // å é¤è®°å½ |
| | | 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("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | <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> |
| | |
| | | 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> |
| | |
| | | |
| | | <!-- ç产å --> |
| | | <div class="form-container"> |
| | | <div class="title">ç产å</div> |
| | | <div class="title">ç产ä¸</div> |
| | | |
| | | <!-- å¾çå表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | |
| | | |
| | | <!-- ç产é®é¢ --> |
| | | <div class="form-container"> |
| | | <div class="title">ç产é®é¢</div> |
| | | <div class="title">ç产å</div> |
| | | |
| | | <!-- å¾çå表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | |
| | | <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> |
| | |
| | | |
| | | // æ¥å£å¼å
¥ |
| | | import { |
| | | delTimingTask, |
| | | inspectionTaskList, |
| | | timingTaskList |
| | | delTimingTask, |
| | | inspectionTaskList, |
| | | timingTaskList |
| | | } from "@/api/inspectionManagement/index.js"; |
| | | |
| | | // å
¨å±åé |
| | |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | searchAll: "", |
| | | searchAll: "", |
| | | }); |
| | | |
| | | // åéæ¡é
ç½® |
| | | const activeRadio = ref("taskManage"); |
| | | const radios = reactive([ |
| | | { name: "taskManage", label: "宿¶ä»»å¡ç®¡ç" }, |
| | | { name: "task", label: "宿¶ä»»å¡è®°å½" }, |
| | | { name: "taskManage", label: "宿¶ä»»å¡ç®¡ç" }, |
| | | { name: "task", label: "宿¶ä»»å¡è®°å½" }, |
| | | ]); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | |
| | | |
| | | // åé
ç½® |
| | | 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, |
| | | 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: "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> |
| | |
| | | </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"> |
| | | <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> |
| | | |
| | |
| | | }; |
| | | |
| | | 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(() => { |
| | |
| | | <el-select |
| | | v-model="form.userId" |
| | | placeholder="è¯·éæ©" |
| | | disabled |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | clearable |
| | | > |
| | | <el-option |
| | |
| | | v-model="form.userId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | // { |
| | | // name: "éä»¶", |
| | | // type: "text", |
| | | // clickFun: (row) => { |
| | | // openFilesFormDia(row); |
| | | // }, |
| | | // }, |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | 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("è¯·éæ©æ°æ®"); |
| | |
| | | <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" |
| | |
| | | maintenanceName: undefined, // ç»´ä¿®åç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: undefined, // ç»´ä¿®æ¥æ |
| | | status: 0, |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | |
| | | <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 |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | const { id } = defineProps(["id"]) |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | |
| | | repairTime: undefined, // æ¥ä¿®æ¥æ |
| | | repairName: userStore.nickName, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | status: 0, // æ¥ä¿®ç¶æ |
| | | }); |
| | | |
| | | const setDeviceModel = (id) => { |
| | |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | }; |
| | | |
| | | // onMounted(() => { |
| | |
| | | <template> |
| | | <el-dialog v-model="visible" :title="modalOptions.title" @close="close"> |
| | | <RepairForm ref="repairFormRef" /> |
| | | <RepairForm ref="repairFormRef" :id="id" /> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | |
| | | @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 |
| | |
| | | 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> |
| | |
| | | maintenanceActuallyName: undefined, // å®é
ä¿å
»äºº |
| | | maintenanceActuallyTime: undefined, // å®é
ä¿å
»æ¥æ |
| | | maintenanceResult: undefined, // ä¿å
ȍȾ |
| | | status: 0, // ä¿å
»ç¶æ |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | |
| | | v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | placeholder="è¯·éæ©è®¾å¤" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | |
| | | 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.userName" |
| | | :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 |
| | |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { onMounted } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | |
| | | defineOptions({ |
| | | name: "计å表å", |
| | |
| | | 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) => { |
| | |
| | | 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({ |
| | |
| | | width="30%" |
| | | @close="close" |
| | | > |
| | | <PlanForm ref="planFormRef"></PlanForm> |
| | | <PlanForm ref="planFormRef" :id="id"></PlanForm> |
| | | <template #footer> |
| | | <el-button type="primary" @click="sendForm" :loading="loading"> |
| | | {{ modalOptions.confirmText }} |
| | |
| | | @pagination="changePage" |
| | | > |
| | | <template #maintenanceResultRef="{ row }"> |
| | | <el-tag v-if="row.maintenanceResult === 1" type="success"> |
| | | <div>{{ row.maintenanceResult || '-' }}</div> |
| | | <!-- <el-tag v-if="row.maintenanceResult === 1" type="success"> |
| | | å®å¥½ |
| | | </el-tag> |
| | | <el-tag v-if="row.maintenanceResult === 0" type="danger"> |
| | | ç»´ä¿® |
| | | </el-tag> |
| | | </el-tag> --> |
| | | </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 |
| | |
| | | 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: "createTime", |
| | | // formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"), |
| | | // width: 200, |
| | | // }, |
| | | { |
| | | label: "å®é
ä¿å
»äºº", |
| | | align: "center", |
| | |
| | | listPage, |
| | | { |
| | | expenseMethod: undefined, |
| | | entryDate: undefined, |
| | | }, |
| | | [ |
| | | { |
| | |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | filters.entryDate = value; |
| | | filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | filters.entryDate = null; |
| | | filters.entryDateStart = undefined; |
| | | filters.entryDateEnd = undefined; |
| | | } |
| | |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | filters.entryDate = [ |
| | | dayjs().format("YYYY-MM-DD"), |
| | | dayjs().add(1, "day").format("YYYY-MM-DD"), |
| | | ] |
| | | filters.entryDateStart = dayjs().format("YYYY-MM-DD") |
| | | filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD") |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <template> |
| | | <div style="padding: 20px;"> |
| | | <!-- 页颿 é¢åæ¥æçé --> |
| | | <div class="w-full md:w-auto flex items-center gap-3" style="margin-bottom: 20px;"> |
| | |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | clearable |
| | | :default-value="[new Date(firstDayOfMonth), new Date()]" |
| | | @change="handleDateChange" |
| | | class="w-full md:w-auto" |
| | | style="margin-right: 30px;" |
| | |
| | | import dayjs from "dayjs"; |
| | | |
| | | // æ¥æèå´ |
| | | const dateRange = ref(null); |
| | | const dateRange = ref([]); |
| | | const firstDayOfMonth = ref(null); |
| | | const chartStyle = { |
| | | width: '100%', |
| | | height: '100%', // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | |
| | | }) |
| | | |
| | | const getData = async () => { |
| | | if (!dateRange.value || !dateRange.value.length) { |
| | | return; |
| | | } |
| | | try { |
| | | const {code,data} = await reportForms({entryDateStart:dateRange.value[0], entryDateEnd:dateRange.value[1]}); |
| | | if(code === 200) { |
| | |
| | | }; |
| | | |
| | | |
| | | // åå§å |
| | | // åå§åæ¥æèå´ï¼é»è®¤å½æï¼ |
| | | onMounted(() => { |
| | | // ä¸è®¾ç½®é»è®¤æ¥æï¼ç±ç¨æ·æå¨éæ© |
| | | const today = new Date(); |
| | | const firstDay = new Date(today.getFullYear(), today.getMonth(), 1); |
| | | firstDayOfMonth.value = firstDay; |
| | | dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")]; |
| | | getData() |
| | | |
| | | }); |
| | | |
| | | // å¤çæ¥æèå´åå |
| | | const handleDateChange = (newRange) => { |
| | | dateRange.value = newRange; |
| | | if (newRange && newRange.length === 2) { |
| | | dateRange.value = newRange; |
| | | getData() |
| | | } |
| | | }; |
| | | |
| | | // éç½®æ¥æèå´ |
| | | const resetDateRange = () => { |
| | | dateRange.value = null; |
| | | const today = new Date(); |
| | | const firstDay = new Date(today.getFullYear(), today.getMonth(), 1); |
| | | dateRange.value = [dayjs(firstDay).format("YYYY-MM-DD"), dayjs(today).format("YYYY-MM-DD")]; |
| | | getData() |
| | | }; |
| | | |
| | | </script> |
| | |
| | | listPage, |
| | | { |
| | | incomeMethod: undefined, |
| | | entryDate: undefined, |
| | | }, |
| | | [ |
| | | { |
| | |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | filters.entryDate = value; |
| | | filters.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | filters.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } else { |
| | | filters.entryDate = null; |
| | | filters.entryDateStart = undefined; |
| | | filters.entryDateEnd = undefined; |
| | | } |
| | |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | filters.entryDate = [ |
| | | dayjs().format("YYYY-MM-DD"), |
| | | dayjs().add(1, "day").format("YYYY-MM-DD"), |
| | | ] |
| | | filters.entryDateStart = dayjs().format("YYYY-MM-DD") |
| | | filters.entryDateEnd = dayjs().add(1, "day").format("YYYY-MM-DD") |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | |
| | | <div class="company-meta">{{userStore.roleName}}</div> |
| | | </div> |
| | | <div style="display: flex;align-items: center;gap: 8px"> |
| | | <el-icon color="#5053B5" size="22"><Clock /></el-icon> |
| | | <span>ç»éæ¥æï¼{{userStore.currentLoginTime}}</span> |
| | | </div> |
| | | <el-icon color="#5053B5" size="22"><Clock /></el-icon> |
| | | <span>ç»éæ¥æï¼{{userStore.currentLoginTime}}</span> |
| | | </div> |
| | | <div style="display: flex;align-items: center;gap: 8px"> |
| | | <el-icon color="#5053B5" size="22"><Calendar /></el-icon> |
| | | <span>æçæ¶é´ï¼{{scheduleTime}}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="data-cards"> |
| | |
| | | <div class="data-num"> |
| | | <div> |
| | | <div class="data-desc">æ¬æéå®é¢/å
</div> |
| | | <div class="data-value" :title="businessInfo.monthSaleMoney">{{businessInfo.monthSaleMoney}}</div> |
| | | <div class="data-value">{{businessInfo.monthSaleMoney}}</div> |
| | | </div> |
| | | <div> |
| | | <div class="data-desc">æªå¼ç¥¨éé¢/å
</div> |
| | | <div class="data-value" :title="businessInfo.monthSaleHaveMoney">{{businessInfo.monthSaleHaveMoney}}</div> |
| | | <div class="data-value">{{businessInfo.monthSaleHaveMoney}}</div> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | <div class="data-num"> |
| | | <div> |
| | | <div class="data-desc">æ¬æéè´é¢/å
</div> |
| | | <div class="data-value" :title="businessInfo.monthPurchaseMoney">{{businessInfo.monthPurchaseMoney}}</div> |
| | | <div class="data-value">{{businessInfo.monthPurchaseMoney}}</div> |
| | | </div> |
| | | <div> |
| | | <div class="data-desc">å¾
仿¬¾éé¢/å
</div> |
| | | <div class="data-value" :title="businessInfo.monthPurchaseHaveMoney">{{businessInfo.monthPurchaseHaveMoney}}</div> |
| | | <div class="data-value">{{businessInfo.monthPurchaseHaveMoney}}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="data-card inventory"> |
| | | <div class="data-title">éè´åºå</div> |
| | | <div class="data-title">åºåæ°æ®</div> |
| | | <div class="data-num"> |
| | | <div> |
| | | <div class="data-desc">å½ååºåæ»é/ä»¶</div> |
| | | <div class="data-value" :title="businessInfo.inventoryNum">{{businessInfo.inventoryNum}}</div> |
| | | <div class="data-value">{{businessInfo.inventoryNum}}</div> |
| | | </div> |
| | | <div> |
| | | <div class="data-desc">仿¥å
¥åº/ä»¶</div> |
| | | <div class="data-value" :title="businessInfo.todayInventoryNum">{{businessInfo.todayInventoryNum}}</div> |
| | | <div class="data-value">{{businessInfo.todayInventoryNum}}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="main-panel"> |
| | | <div style="display: flex;justify-content: space-between;"> |
| | | <div class="section-title">åºæ¶åºä»ç»è®¡</div> |
| | | <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable"> |
| | | <el-radio-button label="æå¨" :value="1" /> |
| | | <el-radio-button label="ææ" :value="2" /> |
| | | <el-radio-button label="æå£åº¦" :value="3" /> |
| | | </el-radio-group> |
| | | <!-- <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable">--> |
| | | <!-- <el-radio-button label="æå¨" :value="1" />--> |
| | | <!-- <el-radio-button label="ææ" :value="2" />--> |
| | | <!-- <el-radio-button label="æå£åº¦" :value="3" />--> |
| | | <!-- </el-radio-group>--> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :color="barColors2" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElNotification } from 'element-plus' |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import * as echarts from 'echarts'; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import { Clock, Calendar } from '@element-plus/icons-vue' |
| | | import { |
| | | analysisCustomerContractAmounts, getAmountHalfYear, |
| | | getBusiness, |
| | | homeTodos, |
| | | qualityStatistics, |
| | | statisticsReceivablePayable |
| | | statisticsReceivablePayable, |
| | | approveAndDeviceTodos, |
| | | noticesCount |
| | | } from "@/api/viewIndex.js"; |
| | | import { getCurrentUserLatestScheduling } from "@/api/personnelManagement/scheduling.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | |
| | | formatter: function (params) { |
| | | // å¨æçææç¤ºä¿¡æ¯ï¼åºäºæ°æ®é¡¹ç name 屿§ |
| | | const description = params.name === 'æ¬æåæ¬¾éé¢' ? 'æ¬æåæ¬¾éé¢' : 'åºæ¶æ¬¾éé¢'; |
| | | return `${description} ${formattedNumber(params.value)}å
${params.percent}%`; |
| | | return `${description} ${formatNumber(params.value)}å
${params.percent}%`; |
| | | }, |
| | | position: 'right' |
| | | }) |
| | |
| | | const todoList = ref([]) |
| | | const radio1 = ref(1) |
| | | |
| | | // æçæ¶é´ |
| | | const scheduleTime = ref('') |
| | | const scheduleInfo = ref({}) |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | const barChart = ref(null) |
| | | const lineChart = ref(null) |
| | |
| | | statisticsReceivable() |
| | | qualityStatisticsInfo() |
| | | getAmountHalfYearNum() |
| | | getCurrentUserSchedule() |
| | | getApproveAndDeviceTodos() |
| | | getOngoingAnnouncementNoticeNumber() |
| | | }) |
| | | // æ°æ®ç»è®¡ |
| | | const getBusinessData = () => { |
| | |
| | | businessInfo.value = {...res.data} |
| | | }) |
| | | } |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | // 妿åªä¼ äºä¸ä¸ªåæ°ï¼ç´æ¥æ ¼å¼åè¯¥åæ° |
| | | if (column === undefined && cellValue === undefined) { |
| | | return parseFloat(row).toFixed(2) |
| | | } |
| | | return parseFloat(cellValue).toFixed(2) |
| | | }; |
| | | // ååéé¢ |
| | | const analysisCustomer = () => { |
| | | analysisCustomerContractAmounts().then((res) => { |
| | |
| | | qualityStatisticsObject.value.factoryNum = res.data.factoryNum |
| | | }) |
| | | } |
| | | // è·åå½åç¨æ·æçä¿¡æ¯ |
| | | const getCurrentUserSchedule = async () => { |
| | | try { |
| | | const res = await getCurrentUserLatestScheduling() |
| | | |
| | | if (res.data) { |
| | | const currentSchedule = res.data |
| | | scheduleInfo.value = currentSchedule |
| | | |
| | | // æ ¼å¼åæçæ¶é´æ¾ç¤º |
| | | if (currentSchedule.startTime && currentSchedule.endTime) { |
| | | scheduleTime.value = `${currentSchedule.startTime} - ${currentSchedule.endTime}` |
| | | } else if (currentSchedule.workStartTime && currentSchedule.workEndTime) { |
| | | const startTime = dayjs(currentSchedule.workStartTime).format('HH:mm') |
| | | const endTime = dayjs(currentSchedule.workEndTime).format('HH:mm') |
| | | scheduleTime.value = `${startTime} - ${endTime}` |
| | | } else { |
| | | scheduleTime.value = '仿¥æ æç' |
| | | } |
| | | } else { |
| | | scheduleTime.value = '仿¥æ æç' |
| | | scheduleInfo.value = {} |
| | | } |
| | | } catch (error) { |
| | | console.error('è·åæçä¿¡æ¯å¤±è´¥:', error) |
| | | scheduleTime.value = 'è·åæçä¿¡æ¯å¤±è´¥' |
| | | } |
| | | } |
| | | |
| | | const getAmountHalfYearNum = async () => { |
| | | const res = await getAmountHalfYear() |
| | | console.log(res) |
| | |
| | | xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~')); |
| | | lineSeries.value = [ |
| | | { |
| | | name: '忬¾', |
| | | name: 'å¼ç¥¨', |
| | | type: 'line', |
| | | data: receiptAmount, |
| | | stack: 'Total', |
| | |
| | | showSymbol: true, |
| | | }, |
| | | { |
| | | name: 'å¼ç¥¨', |
| | | name: '忬¾', |
| | | type: 'line', |
| | | data: invoiceAmount, |
| | | stack: 'Total', |
| | |
| | | }, |
| | | } |
| | | ] |
| | | } |
| | | |
| | | // ååå¾
审æ¹åæ¥ä¿®å¾
åäºé¡¹ |
| | | const getApproveAndDeviceTodos = async () => { |
| | | try { |
| | | const res = await approveAndDeviceTodos() |
| | | const { approveTodo, deviceRepairTodo } = res.data |
| | | |
| | | // æ¾ç¤ºéç¥ |
| | | ElNotification({ |
| | | title: 'å¾
åäºé¡¹æé', |
| | | message: `å½åæ${approveTodo}æ¡å¾
审æ¹äºé¡¹ï¼${deviceRepairTodo}æ¡å¾
ç»´ä¿®äºé¡¹`, |
| | | type: 'warning', |
| | | duration: 5000 |
| | | }) |
| | | } catch (error) { |
| | | console.error('è·åååå¾
åäºé¡¹å¤±è´¥:', error) |
| | | } |
| | | } |
| | | // è¿è¡ä¸å
¬åéç¥ |
| | | const getOngoingAnnouncementNoticeNumber = async () => { |
| | | try { |
| | | const res = await noticesCount() |
| | | // const { approveTodo, deviceRepairTodo } = res.data |
| | | const _noticesCount = res.data |
| | | if(!_noticesCount){ |
| | | return |
| | | } |
| | | // æ¾ç¤ºéç¥ |
| | | ElNotification({ |
| | | title: 'éç¥å
¬åéç¥', |
| | | message: `å½åæ${_noticesCount}æ¡å
¬åéç¥ï¼æ³¨ææ¥ç`, |
| | | type: 'warning', |
| | | duration: 5000 |
| | | }) |
| | | } catch (error) { |
| | | console.error('è·åååå¾
åäºé¡¹å¤±è´¥:', error) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | |
| | | color: #FFFFFF; |
| | | } |
| | | .data-value { |
| | | max-width: 100px; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | font-size: 18px; |
| | | font-weight: 500; |
| | | margin: 10px 0; |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <!-- <el-tab-pane label="éè´åºåº" name="production"> |
| | | <el-tab-pane label="æååºåº" name="production"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">åºåºæ¥æï¼</span> |
| | |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" min-width="120" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | |
| | | @pagination="paginationChange" |
| | | /> |
| | | </div> |
| | | </el-tab-pane> --> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="éè´åºåº" name="purchase"> |
| | | <el-tab-pane label="åæåºåº" name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">åºåºæ¥æï¼</span> |
| | |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åºåºæ°é/ä»¶" prop="inboundNum" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)/æ¯" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <el-table-column label="åºåºäºº" prop="createBy" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="éè´ååå·" prop="purchaseContractNumber" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="åºåºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="æååºåº" name="manual"> |
| | | <el-tab-pane label="ææåºåº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">åºåºæ¥æï¼</span> |
| | |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产åå¾ç" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <img class="barcode-img" :src="javaApiUrl+scope.row.url"></img> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åºåºæ°é/ä»¶" prop="inboundNum" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <el-table-column label="åºåºäºº" prop="createBy" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ¥æ" prop="createTime" show-overflow-tooltip width="130"/> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="åºåºæ°é" prop="inboundNum" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="åºåºäºº" prop="createBy" show-overflow-tooltip /> |
| | | </el-table> |
| | | <pagination |
| | | v-show="total > 0" |
| | |
| | | <div v-for="(item, index) in printData" :key="index" class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">天津åå¥ç¹æé责任å
¬å¸</div> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | <div> |
| | | |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">{{ item.supplierName }}</span> |
| | | <span class="value">{{ item.supplierName || 'å¼ ç±æ' }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>产åé«åº¦</th> |
| | | <th>åä»·ï¼ç¾å
ï¼/ä»¶</th> |
| | | <th>é¶å®æ°é/ä»¶</th> |
| | | <th>æ¯ä»¶æ°é/æ¯</th> |
| | | <th>çº¸ç®±è§æ ¼</th> |
| | | <th>è§æ ¼åå·</th> |
| | | <th>åä½</th> |
| | | <th>åä»·</th> |
| | | <th>é¶å®æ°é</th> |
| | | <th>é¶å®éé¢</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>{{ item.productCategory || '' }}</td> |
| | | <td>{{ item.specificationModel || '' }}{{ item.unit || '' }}</td> |
| | | <td>{{ item.productCategory || 'ç ç°ç ' }}</td> |
| | | <td>{{ item.specificationModel || 'æ å' }}</td> |
| | | <td>{{ item.unit || 'å' }}</td> |
| | | <td>{{ item.taxInclusiveUnitPrice || '0' }}</td> |
| | | <td>{{ item.inboundNum || '0' }}</td> |
| | | <td>{{ item.boxNum || '0' }}</td> |
| | | <td>{{ item.cartonSpecifications || '0' }}</td> |
| | | <td>{{ item.inboundNum || '2000' }}</td> |
| | | <td>{{ item.taxInclusiveTotalPrice || '0' }}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | <!-- <tr> |
| | | <tr> |
| | | <td class="label">å计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">{{ item.inboundNum || '2000' }}</td> |
| | | <td class="total-value">{{ item.taxInclusiveTotalPrice || '0' }}</td> |
| | | </tr> --> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | |
| | | getStockInPageByProduct, |
| | | getStockInPageByCustom, |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | const javaApiUrl = __BASE_API__; |
| | | |
| | | const userStore = useUserStore(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | | const activeTab = ref('purchase'); |
| | | const activeTab = ref('production'); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | |
| | | page.current = 1 |
| | | searchForm.value.supplierName = '' |
| | | searchForm.value.customerName = '' |
| | | searchForm.value.timeStr = getCurrentDate() // é置为å½åæ¥æ |
| | | searchForm.value.timeStr = '' |
| | | selectedRows.value = [] |
| | | searchForm.value.productCategory = '' |
| | | getList() |
| | |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">åå¥ç¹æé责任å
¬å¸</div> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | </div> |
| | | <div> |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">${item.supplierName}</span> |
| | | <span class="value">${item.supplierName || 'å¼ ç±æ'}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <span class="label">åå·ï¼</span> |
| | | <span class="value">${item.code}</span> |
| | | <span class="value">${item.code || ''}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>产åé«åº¦</th> |
| | | <th>åä»·ï¼ç¾å
ï¼/ä»¶</th> |
| | | <th>é¶å®æ°é/ä»¶</th> |
| | | <th>æ¯ä»¶æ°é/æ¯</th> |
| | | <th>çº¸ç®±è§æ ¼</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>{{ item.productCategory || '' }}</td> |
| | | <td>{{ item.specificationModel || '' }}{{ item.unit || '' }}</td> |
| | | <td>{{ item.taxInclusiveUnitPrice || '0' }}</td> |
| | | <td>{{ item.inboundNum || '0' }}</td> |
| | | <td>{{ item.boxNum || '0' }}</td> |
| | | <td>{{ item.cartonSpecifications || '0' }}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产ååç§°</th> |
| | | <th>è§æ ¼åå·</th> |
| | | <th>åä½</th> |
| | | <th>åä»·</th> |
| | | <th>é¶å®æ°é</th> |
| | | <th>é¶å®éé¢</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | <tr> |
| | | <td>${item.productCategory || 'ç ç°ç '}</td> |
| | | <td>${item.specificationModel || 'æ å'}</td> |
| | | <td>${item.unit || 'å'}</td> |
| | | <td>${item.taxInclusiveUnitPrice || '0'}</td> |
| | | <td>${item.inboundNum || '2000'}</td> |
| | | <td>${item.taxInclusiveTotalPrice || '0'}</td> |
| | | </tr> |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">å计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">${item.inboundNum || '2000'}</td> |
| | | <td class="total-value">${item.taxInclusiveTotalPrice || '0'}</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | .barcode-img{ |
| | | width: 80px; |
| | | height: 80px; |
| | | border-radius: 5px; |
| | | background-color: #F5F5F5; |
| | | } |
| | | </style> |
| | | |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <!-- <el-tab-pane label="éè´åºåº" name="production"> |
| | | <el-tab-pane label="æååºåº" name="production"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row);">é¢ç¨</el-button> |
| | | <el-button link type="primary" size="small" @click="openForm(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" /> |
| | | </div> |
| | | </el-tab-pane> --> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="éè´åºåº" name="purchase"> |
| | | <el-tab-pane label="åæåºåº" name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é/ä»¶" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="éè´ååå·" prop="purchaseContractNumber" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row);" :disabled="!scope.row.inboundNum0">é¢ç¨</el-button> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row);">é¢ç¨</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="æååºåº" name="manual"> |
| | | <el-tab-pane label="ææåºåº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <!-- <span class="search_title">ä¾åºååç§°ï¼</span>--> |
| | | <!-- <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请è¾å
¥" @change="handleQuery"--> |
| | | <!-- clearable prefix-icon="Search" />--> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <!-- <el-table-column align="center" type="selection" width="55" /> --> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产åå¾ç" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <img class="barcode-img" :src="javaApiUrl+scope.row.url"></img> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="inboundDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é/ä»¶" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="90" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row);" :disabled="!scope.row.inboundNum0">é¢ç¨</el-button> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row);">é¢ç¨</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <el-dialog v-model="dialogFormVisible" :title="'æ°å¢åºåº'" width="40%" @close="closeDia"> |
| | | <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="40%" @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <div>å¯åºåºæ°é:{{currentRowNum}}</div> |
| | | <el-form-item label="åºåºæ°éï¼" prop="salesContractNo"> |
| | | <el-input-number :step="1" :min="0" :max="currentRowNum" style="width: 100%" v-model="form.inboundQuantity" placeholder="请è¾å
¥" clearable /> |
| | | <div>{{getAvailableQuantityText()}}:{{currentRowNum}}</div> |
| | | <el-form-item :label="getQuantityLabel()" prop="salesContractNo"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="form.inboundQuantity" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="åºåºæ¥æï¼" prop="projectName"> |
| | | <el-form-item :label="getDateLabel()" prop="projectName"> |
| | | <el-date-picker style="width: 100%" v-model="form.inboundTime" value-format="YYYY-MM-DD" format="YYYY-MM-DD" |
| | | type="date" placeholder="è¯·éæ©" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="åºåºäººï¼" prop="entryPerson"> |
| | | <el-form-item :label="getPersonLabel()" prop="entryPerson"> |
| | | <el-select v-model="form.nickName" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" clearable> |
| | |
| | | delStockManage, |
| | | stockOut, |
| | | } from "@/api/inventoryManagement/stockManage.js"; |
| | | const javaApiUrl = __BASE_API__; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const dialogFormVisible = ref(false) |
| | | const activeTab = ref('purchase') |
| | | const activeTab = ref('production') |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: '', |
| | | customerName: '', |
| | | inboundQuantity:0, |
| | | inboundQuantity:'', |
| | | inboundTime:'', |
| | | nickName: '', |
| | | userId: '', |
| | |
| | | page.current = 1 |
| | | searchForm.value.supplierName = '' |
| | | searchForm.value.customerName = '' |
| | | searchForm.value.timeStr = getCurrentDate() // é置为å½åæ¥æ |
| | | searchForm.value.timeStr = '' |
| | | selectedRows.value = [] |
| | | searchForm.value.productCategory = '' |
| | | getList() |
| | |
| | | // åå§åè¡¨åæ°æ® |
| | | form.value = { |
| | | productrecordId: '', |
| | | inboundQuantity: 0, // åºåºæ°éæ¸
空 |
| | | inboundQuantity: '', // åºåºæ°éæ¸
空 |
| | | inboundTime: getCurrentDate(), // é»è®¤å½åæ¥æ |
| | | nickName: '', // é»è®¤å½åç¨æ· |
| | | } |
| | |
| | | const submitForm = () => { |
| | | let num = Number(form.value.inboundQuantity) |
| | | if(num <= 0 || num > currentRowNum.value){ |
| | | return proxy.$modal.msgWarning("请填ååºåºæ°é") |
| | | } |
| | | if(!form.value.nickName){ |
| | | return proxy.$modal.msgWarning("è¯·éæ©åºåºäºº") |
| | | } |
| | | if(!form.value.inboundTime){ |
| | | return proxy.$modal.msgWarning("è¯·éæ©åºåºæ¶é´") |
| | | return proxy.$modal.msgWarning("请填å
¥æææ°å") |
| | | } |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid && currentRowId.value) { |
| | |
| | | } |
| | | ).then(() => { |
| | | // æ ¹æ®ä¸åç tab ç±»åè°ç¨ä¸åçå¯¼åºæ¥å£ |
| | | let exportUrl = "/stockmanagement/export" |
| | | let exportUrl = "/stockin/export" |
| | | if (activeTab.value === 'production') { |
| | | exportUrl = "/stockmanagement/exportOne" |
| | | exportUrl = "/stockin/exportOne" |
| | | } else if (activeTab.value === 'manual') { |
| | | exportUrl = "/stockmanagement/exportTwo" |
| | | exportUrl = "/stockin/exportTwo" |
| | | } |
| | | proxy.download(exportUrl, {}, 'åºåºå°è´¦.xlsx') |
| | | proxy.download(exportUrl, {}, 'å
¥åºå°è´¦.xlsx') |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶") |
| | | }) |
| | |
| | | const day = String(today.getDate()).padStart(2, '0'); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | // æ ¹æ®tabç±»åè·åå¼¹æ¡æ é¢ |
| | | const getDialogTitle = () => { |
| | | const titleMap = { |
| | | production: 'æ°å¢åè´§', |
| | | purchase: 'æ°å¢é¢ç¨', |
| | | manual: 'æ°å¢é¢ç¨' |
| | | }; |
| | | return titleMap[activeTab.value] || 'æ°å¢åºåº'; |
| | | }; |
| | | |
| | | // æ ¹æ®tabç±»åè·åå¯åºåºæ°éææ¬ |
| | | const getAvailableQuantityText = () => { |
| | | const textMap = { |
| | | production: 'å¯åè´§æ°é', |
| | | purchase: 'å¯é¢ç¨æ°é', |
| | | manual: 'å¯é¢ç¨æ°é' |
| | | }; |
| | | return textMap[activeTab.value] || 'å¯åºåºæ°é'; |
| | | }; |
| | | |
| | | // æ ¹æ®tabç±»åè·åæ°éåæ®µæ ç¾ |
| | | const getQuantityLabel = () => { |
| | | const labelMap = { |
| | | production: 'åè´§æ°éï¼', |
| | | purchase: 'é¢ç¨æ°éï¼', |
| | | manual: 'é¢ç¨æ°éï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºæ°éï¼'; |
| | | }; |
| | | |
| | | // æ ¹æ®tabç±»åè·åæ¥æåæ®µæ ç¾ |
| | | const getDateLabel = () => { |
| | | const labelMap = { |
| | | production: 'åè´§æ¥æï¼', |
| | | purchase: 'é¢ç¨æ¥æï¼', |
| | | manual: 'é¢ç¨æ¥æï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºæ¥æï¼'; |
| | | }; |
| | | |
| | | // æ ¹æ®tabç±»åè·å人ååæ®µæ ç¾ |
| | | const getPersonLabel = () => { |
| | | const labelMap = { |
| | | production: 'å货人ï¼', |
| | | purchase: 'é¢ç¨äººï¼', |
| | | manual: 'é¢ç¨äººï¼' |
| | | }; |
| | | return labelMap[activeTab.value] || 'åºåºäººï¼'; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .barcode-img{ |
| | | width: 80px; |
| | | height: 80px; |
| | | border-radius: 5px; |
| | | background-color: #F5F5F5; |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | | |
| | | |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="éè´è®¢åå·" prop="purchaseContractNumber"> |
| | | <el-select |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="è¯·éæ©éè´è®¢åå·" |
| | | clearable |
| | | filterable |
| | | :loading="loadingPurchaseOptions" |
| | | @change="handlePurchaseChange" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseOptions" |
| | | :key="item.purchaseContractNumber" |
| | | :label="formatPurchaseOption(item)" |
| | | :value="item.purchaseContractNumber" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | 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="supplierName" width="100" /> --> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"> |
| | | <el-dialog v-model="dialogFormVisible" :title="getDialogTitle()" width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-form-item label="éè´è®¢åå·" prop="purchaseContractNumber"> |
| | | <el-select |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="è¯·éæ©éè´è®¢åå·" |
| | | clearable |
| | | filterable |
| | | :loading="loadingPurchaseOptions" |
| | | @change="handlePurchaseChange" |
| | | :disabled="operationType === 'edit'" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="item in purchaseOptions" |
| | | :key="item.purchaseContractNumber" |
| | | :label="formatPurchaseOption(item)" |
| | | :value="item.purchaseContractNumber" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | 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="supplierName" width="100" /> --> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" :disabled="operationType === 'edit'"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ»ä»·(å
)" |
| | | <el-table-column |
| | | label="æ»ä»·(å
)" |
| | | :formatter="formattedNumber" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="150" |
| | | > |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | prop="taxInclusiveTotalPrice" |
| | | width="150" |
| | | > |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, getCurrentInstance } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { |
| | | updateStockIn, |
| | | addSutockIn, |
| | | selectProductRecordListByPuechaserId |
| | | updateStockIn, |
| | | addSutockIn, |
| | | selectProductRecordListByPuechaserId |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { purchaseListPage } from "@/api/procurementManagement/procurementLedger.js"; |
| | | |
| | |
| | | const loading = ref(false); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: null, |
| | | purchaseContractNumber: '', // éè´è®¢åå· |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | inboundTime: '', // å
¥åºæ¶é´ |
| | | inboundBatch: '', // å
¥åºæ¹æ¬¡ |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "è¯·éæ©ä¾åºå", trigger: "change" }], |
| | | inboundTime: [{ required: true, message: "è¯·éæ©å
¥åºæ¶é´", trigger: "change" }], |
| | | inboundBatch: [{ required: true, message: "请è¾å
¥å
¥åºæ¹æ¬¡", trigger: "blur" }] |
| | | } |
| | | form: { |
| | | id: null, |
| | | purchaseContractNumber: '', // éè´è®¢åå· |
| | | supplierId: null, // ä¾åºåID |
| | | supplierName: '', // ä¾åºååç§° |
| | | inboundTime: '', // å
¥åºæ¶é´ |
| | | inboundBatch: '', // å
¥åºæ¹æ¬¡ |
| | | recorderId: userStore.userId, // å½å
¥äººID |
| | | recorderName: userStore.name, // å½å
¥äººå§å |
| | | entryDate: getCurrentDate(), // å½å
¥æ¥æ |
| | | remark: '', // 夿³¨ |
| | | }, |
| | | rules: { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "è¯·éæ©ä¾åºå", trigger: "change" }], |
| | | inboundTime: [{ required: true, message: "è¯·éæ©å
¥åºæ¶é´", trigger: "change" }], |
| | | inboundBatch: [{ required: true, message: "请è¾å
¥å
¥åºæ¹æ¬¡", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | |
| | | // å¨æè®¡ç®å¯¹è¯æ¡æ é¢ |
| | | const getDialogTitle = () => { |
| | | return operationType.value === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº' |
| | | return operationType.value === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº' |
| | | } |
| | | |
| | | const formatPurchaseOption = (item = {}) => { |
| | | const contract = item.purchaseContractNumber || '--'; |
| | | const supplier = item.supplierName ? ` · ${item.supplierName}` : ''; |
| | | return `${contract}${supplier}`; |
| | | const contract = item.purchaseContractNumber || '--'; |
| | | const supplier = item.supplierName ? ` · ${item.supplierName}` : ''; |
| | | return `${contract}${supplier}`; |
| | | }; |
| | | |
| | | const loadPurchaseOptions = async (keyword = '') => { |
| | | try { |
| | | loadingPurchaseOptions.value = true; |
| | | const res = await purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | purchaseContractNumber: keyword, |
| | | }); |
| | | const records = res.data?.records || []; |
| | | purchaseOptions.value = records; |
| | | if ( |
| | | form.value.purchaseContractNumber && |
| | | !purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === form.value.purchaseContractNumber |
| | | ) |
| | | ) { |
| | | purchaseOptions.value.push({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | supplierName: form.value.supplierName, |
| | | supplierId: form.value.supplierId, |
| | | }); |
| | | } |
| | | } finally { |
| | | loadingPurchaseOptions.value = false; |
| | | } |
| | | try { |
| | | loadingPurchaseOptions.value = true; |
| | | const res = await purchaseListPage({ |
| | | current: -1, |
| | | size: -1, |
| | | purchaseContractNumber: keyword, |
| | | }); |
| | | const records = res.data?.records || []; |
| | | purchaseOptions.value = records; |
| | | if ( |
| | | form.value.purchaseContractNumber && |
| | | !purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === form.value.purchaseContractNumber |
| | | ) |
| | | ) { |
| | | purchaseOptions.value.push({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | supplierName: form.value.supplierName, |
| | | supplierId: form.value.supplierId, |
| | | }); |
| | | } |
| | | } finally { |
| | | loadingPurchaseOptions.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handlePurchaseChange = (value) => { |
| | | form.value.purchaseContractNumber = value || ''; |
| | | const matched = purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === value |
| | | ); |
| | | if (matched) { |
| | | form.value.supplierName = matched.supplierName || form.value.supplierName; |
| | | form.value.supplierId = matched.supplierId || form.value.supplierId; |
| | | } |
| | | if (!value) { |
| | | productList.value = []; |
| | | return; |
| | | } |
| | | fetchProductsByContract(); |
| | | form.value.purchaseContractNumber = value || ''; |
| | | const matched = purchaseOptions.value.find( |
| | | (item) => item.purchaseContractNumber === value |
| | | ); |
| | | if (matched) { |
| | | form.value.supplierName = matched.supplierName || form.value.supplierName; |
| | | form.value.supplierId = matched.supplierId || form.value.supplierId; |
| | | } |
| | | if (!value) { |
| | | productList.value = []; |
| | | return; |
| | | } |
| | | fetchProductsByContract(); |
| | | }; |
| | | |
| | | const exceedsAddLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | }; |
| | | |
| | | const exceedsEditLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | }; |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | |
| | | // è®¡ç®æ»ä»· |
| | | const calculateTotalPrice = (row) => { |
| | | const quantityStock = Number(row?.quantityStock ?? 0); |
| | | const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0); |
| | | |
| | | if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) { |
| | | row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice; |
| | | } else { |
| | | row.taxInclusiveTotalPrice = 0; |
| | | } |
| | | const quantityStock = Number(row?.quantityStock ?? 0); |
| | | const taxInclusiveUnitPrice = Number(row?.taxInclusiveUnitPrice ?? 0); |
| | | |
| | | if (Number.isFinite(quantityStock) && Number.isFinite(taxInclusiveUnitPrice)) { |
| | | row.taxInclusiveTotalPrice = quantityStock * taxInclusiveUnitPrice; |
| | | } else { |
| | | row.taxInclusiveTotalPrice = 0; |
| | | } |
| | | }; |
| | | |
| | | const fetchProductsByContract = async () => { |
| | | if (!form.value.purchaseContractNumber) { |
| | | proxy.$modal.msgWarning('è¯·éæ©ååå·') |
| | | return |
| | | } |
| | | try { |
| | | loadingProducts.value = true |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber |
| | | }); |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | if (!form.value.purchaseContractNumber) { |
| | | proxy.$modal.msgWarning('è¯·éæ©ååå·') |
| | | return |
| | | } |
| | | try { |
| | | loadingProducts.value = true |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber |
| | | }); |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | |
| | | const updatePro = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©äº§å'); |
| | | return; |
| | | } |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock), |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©äº§å'); |
| | | return; |
| | | } |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock), |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | } |
| | | |
| | | const submitForm = async () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©éè´ååå¹¶éæ©äº§å') |
| | | return |
| | | } |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgWarning('æ¬æ¬¡å
¥åºæ°éä¸è½å¤§äºå¾
å
¥åºæ°éï¼ä¸é大äº0'); |
| | | return; |
| | | } |
| | | |
| | | const stockInData = { |
| | | ...form.value, |
| | | inboundTime: formatDateTime(), |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | inboundQuantity: Number(product.quantityStock), |
| | | unitPrice: Number(product.taxInclusiveUnitPrice), |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgWarning('请å
éæ©éè´ååå¹¶éæ©äº§å') |
| | | return |
| | | } |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éé大äº0ï¼ä¸ä¸è½è¶
è¿å¾
å
¥åºæ°é') |
| | | return |
| | | } |
| | | |
| | | const stockInData = { |
| | | ...form.value, |
| | | inboundTime: formatDateTime(form.value.inboundTime), |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | inboundQuantity: Number(product.quantityStock), |
| | | taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice), |
| | | taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice) |
| | | })), |
| | | }; |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('æ°å¢å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | })), |
| | | }; |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('æ°å¢å
¥åºæå') |
| | | closeDia() |
| | | emit('success') |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | emit('close') |
| | | proxy.$refs.formRef.resetFields() |
| | | dialogFormVisible.value = false |
| | | emit('close') |
| | | } |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | const d = new Date(date); |
| | | const year = d.getFullYear(); |
| | | const month = String(d.getMonth() + 1).padStart(2, '0'); |
| | | const day = String(d.getDate()).padStart(2, '0'); |
| | | |
| | | if (!includeTime) { |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | const hours = String(d.getHours()).padStart(2, '0'); |
| | | const minutes = String(d.getMinutes()).padStart(2, '0'); |
| | | const seconds = String(d.getSeconds()).padStart(2, '0'); |
| | | |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; |
| | | } |
| | | |
| | | function getCurrentDate() { |
| | | return formatDateTime(new Date(), false); |
| | | return formatDateTime(new Date(), false); |
| | | } |
| | | |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | selectedRows.value = [] |
| | | await loadPurchaseOptions(); |
| | | |
| | | if (type === 'add') { |
| | | form.value = { |
| | | id: null, |
| | | purchaseContractNumber: '', |
| | | supplierId: null, |
| | | supplierName: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] |
| | | } else { |
| | | form.value = JSON.parse(JSON.stringify(row)) |
| | | try { |
| | | loadingProducts.value = true |
| | | const res = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | id: row.id |
| | | }); |
| | | productList.value = res.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('å 载产å失败:', error) |
| | | proxy.$modal.msgError('å 载产å失败') |
| | | productList.value = [] |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | selectedRows.value = [] |
| | | await loadPurchaseOptions(); |
| | | |
| | | if (type === 'add') { |
| | | form.value = { |
| | | id: null, |
| | | purchaseContractNumber: '', |
| | | supplierId: null, |
| | | supplierName: '', |
| | | inboundTime: '', |
| | | inboundBatch: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] |
| | | } else { |
| | | form.value = JSON.parse(JSON.stringify(row)) |
| | | try { |
| | | loadingProducts.value = true |
| | | const res = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: form.value.purchaseContractNumber, |
| | | id: row.id |
| | | }); |
| | | productList.value = res.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | taxInclusiveUnitPrice: Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: Number(item?.quantityStock ?? 0) * Number(item?.taxInclusiveUnitPrice ?? 0), |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? row.inboundNum ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('å 载产å失败:', error) |
| | | proxy.$modal.msgError('å 载产å失败') |
| | | productList.value = [] |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | } |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | openDialog, |
| | | }) |
| | | </script> |
| | | |
| | |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产åå¾ç" align="center" prop="productCategory" width="100"> |
| | | <el-table-column label="产å大类" prop="productCategory" width="200"> |
| | | <template #default="scope"> |
| | | <el-upload |
| | | :action="uploadUrl" |
| | | :before-upload="handleBeforeUpload" |
| | | :on-success="(res,file)=>{handleUploadSuccess(res,file,scope.row)}" |
| | | :on-error="handleUploadError" |
| | | name="file" |
| | | :show-file-list="false" |
| | | :headers="headers" |
| | | accept="image/*" |
| | | :data="{ type: 9 }" |
| | | > |
| | | <img class="upload-img" v-if="scope.row.url" :src="javaApiUrl+scope.row.url"></img> |
| | | <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> |
| | | </el-upload> |
| | | <el-input v-model="scope.row.productCategory" placeholder="请è¾å
¥äº§å大类" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产ååç§°" prop="productCategory" width="200"> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.productCategory" placeholder="请è¾å
¥äº§ååç§°" /> |
| | | <el-input v-model="scope.row.specificationModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="200"> |
| | | <el-table-column label="åä½" prop="unit" width="100"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.specificationModel" placeholder="请è¾å
¥äº§åé«åº¦" /> |
| | | <el-input v-model="scope.row.unit" placeholder="请è¾å
¥åä½" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="200"> |
| | | <el-table-column label="ä¾åºå" prop="supplierName" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.cartonSpecifications" placeholder="请è¾å
¥çº¸ç®±è§æ ¼" /> |
| | | <el-input v-model="scope.row.supplierName" placeholder="请è¾å
¥ä¾åºå" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é-ä»¶" prop="inboundNum" width="150"> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="1" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" /> |
| | | <el-select v-model="scope.row.itemType" filterable allow-create placeholder="è¯·éæ©ç©åç±»å" style="width: 100%"> |
| | | <el-option |
| | | v-for="item in itemTypeOptions" |
| | | :key="item.value" |
| | | :label="item.label" |
| | | :value="item.value" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="150"> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="1" :min="0" style="width: 100%" v-model="scope.row.boxNum" @change="() => calculateTotalPrice(scope.row)" /> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.inboundNum" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="inboundDate" width="180"> |
| | | <template #default="scope"> |
| | | <el-date-picker |
| | |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="æ°é" prop="quantityStock" width="150">--> |
| | | <!-- <template #default="scope">--> |
| | | <!-- <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" />--> |
| | | <!-- </template>--> |
| | | <!-- </el-table-column>--> |
| | | |
| | | <!-- <el-table-column --> |
| | | <!-- label="æ»ä»·(å
)" --> |
| | | <!-- prop="taxInclusiveTotalPrice" --> |
| | | <!-- width="150" --> |
| | | <!-- >--> |
| | | <!-- </el-table-column>--> |
| | | <el-table-column label="æ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.taxInclusiveUnitPrice" @change="() => calculateTotalPrice(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | width="150" |
| | | > |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80" v-if="operationType === 'add'"> |
| | | <template #default="scope"> |
| | | <el-button type="danger" size="small" @click="removeProductRow(scope.$index)">å é¤</el-button> |
| | |
| | | addStockInCustom, |
| | | updateStockInCustom, |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | | const headers = ref({ |
| | | Authorization: "Bearer " + getToken(), |
| | | }); |
| | | |
| | | const javaApiUrl = __BASE_API__; |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close', 'success']) |
| | | |
| | | const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // ä¸ä¼ çå¾çæå¡å¨å°å |
| | | |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const dialogFormVisible = ref(false)// å¼¹æ¡æ¾ç¤ºç¶æ |
| | |
| | | id: null, |
| | | productCategory: '', |
| | | specificationModel: '', |
| | | cartonSpecifications:'', |
| | | unit: '', |
| | | supplierName: form.value.supplierName || '', |
| | | itemType: '', |
| | | inboundNum: 0, |
| | |
| | | taxInclusiveTotalPrice: 0, |
| | | taxRate: null, |
| | | taxExclusiveTotalPrice: 0, |
| | | boxNum: 0, |
| | | }); |
| | | }; |
| | | |
| | |
| | | // éªè¯èªå®ä¹æ·»å çæ°æ®å¿
å¡«åæ®µ |
| | | for (let i = 0; i < productList.value.length; i++) { |
| | | const product = productList.value[i]; |
| | | if (!product.productCategory || !product.specificationModel) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡äº§åæ°æ®æªå¡«å宿´ï¼äº§åã产åé«åº¦ãé«åº¦åä½ä¸ºå¿
å¡«ï¼`) |
| | | if (!product.productCategory || !product.specificationModel || !product.unit) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡äº§åæ°æ®æªå¡«å宿´ï¼äº§å大类ãè§æ ¼åå·ãåä½ä¸ºå¿
å¡«ï¼`) |
| | | return |
| | | } |
| | | if (!product.url) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡äº§åæªä¸ä¼ 产åå¾ç`) |
| | | return |
| | | } |
| | | if (!product.cartonSpecifications) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡äº§åæªå¡«åçº¸ç®±è§æ ¼`) |
| | | return |
| | | } |
| | | // if (!product.itemType) { |
| | | // proxy.$modal.msgError(`第${i + 1}è¡è¯·éæ©ç©åç±»å`) |
| | | // return |
| | | // } |
| | | const stock = Number(product?.inboundNum ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡æ¬æ¬¡å
¥åºæ°éé大äº0`) |
| | | return |
| | | } |
| | | const boxNum = Number(product?.boxNum ?? 0); |
| | | if (!Number.isFinite(boxNum) || boxNum <= 0) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡æ¯ä»¶æ°é/æ¯é大äº0`) |
| | | return |
| | | } |
| | | const taxInclusiveUnitPrice = Number(product?.taxInclusiveUnitPrice ?? 0); |
| | | if (!Number.isFinite(taxInclusiveUnitPrice) || taxInclusiveUnitPrice <= 0) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡åä»·ï¼å
ï¼é大äº0`) |
| | | if (!product.itemType) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡è¯·éæ©ç©åç±»å`) |
| | | return |
| | | } |
| | | if (!product.inboundDate) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡è¯·éæ©å
¥åºæ¥æ`) |
| | | return |
| | | } |
| | | |
| | | const stock = Number(product?.inboundNum ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡æ¬æ¬¡å
¥åºæ°éé大äº0`) |
| | | return |
| | | } |
| | | } |
| | | |
| | | const payloadList = productList.value.map(product => ({ |
| | |
| | | inboundNum: Number(product.inboundNum), |
| | | productCategory: product.productCategory, |
| | | specificationModel: product.specificationModel, |
| | | unit: product.unit, |
| | | supplierName: product.supplierName || form.value.supplierName, |
| | | itemType: product.itemType, |
| | | inboundDate: formatDateTime(product.inboundDate, false), |
| | |
| | | taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0), |
| | | taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0), |
| | | taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0), |
| | | boxNum:Number(product.boxNum), |
| | | cartonSpecifications: product.cartonSpecifications, |
| | | url: product.url||'', |
| | | })); |
| | | loading.value = true |
| | | if (operationType.value === 'edit') { |
| | |
| | | dialogFormVisible.value = false |
| | | productList.value = [] |
| | | emit('close') |
| | | } |
| | | |
| | | // ä¸ä¼ åæ ¡æ£æ ¼å¼åå¤§å° |
| | | function handleBeforeUpload(file) { |
| | | const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; |
| | | const isJPG = type.includes(file.type); |
| | | //æ£éªæä»¶æ ¼å¼ |
| | | if (!isJPG) { |
| | | proxy.$modal.msgError(`å¾çæ ¼å¼é误!`); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | const handleUploadSuccess = (res, file,item) => { |
| | | // 妿ä¸ä¼ æå |
| | | if (res.code == 200) { |
| | | item.url = res.data?.tempPath||'' |
| | | } else { |
| | | proxy.$modal.msgError("å¾çæå
¥å¤±è´¥"); |
| | | } |
| | | } |
| | | // ä¸ä¼ 失败å¤ç |
| | | function handleUploadError() { |
| | | proxy.$modal.msgError("å¾çæå
¥å¤±è´¥"); |
| | | } |
| | | |
| | | const openDialog = async (type, row) => { |
| | |
| | | id: row?.id ?? null, |
| | | productCategory: row?.productCategory ?? '', |
| | | specificationModel: row?.specificationModel ?? '', |
| | | unit: row?.unit ?? '', |
| | | supplierName: row?.supplierName ?? '', |
| | | itemType: row?.itemType ?? '', |
| | | inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0), |
| | |
| | | taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0), |
| | | taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0), |
| | | boxNum: Number(row?.boxNum ?? 0), |
| | | cartonSpecifications: row?.cartonSpecifications ?? '', |
| | | url: row?.url ?? '', |
| | | }] |
| | | } |
| | | } |
| | |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .upload-img{ |
| | | width: 80px; |
| | | height: 80px; |
| | | object-fit: contain; |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | | |
| | |
| | | taxRate: Number(row?.taxRate ?? 0), |
| | | unitPrice: Number(row?.unitPrice ?? 0), |
| | | taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0), |
| | | dollarPrice: Number(row?.dollarPrice ?? 0), |
| | | }] |
| | | } |
| | | } |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <el-tab-pane label="éè´å
¥åº" name="purchase"> |
| | | <el-tab-pane label="æåå
¥åº" name="production"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="unitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="totalPrice" width="150"></el-table-column> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'production');">ç¼è¾</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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="åæå
¥åº" name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="éè´ååå·" prop="purchaseContractNumber" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="240" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'purchase');">ç¼è¾</el-button> |
| | | <!-- <el-button link type="success" size="small" @click="showQRCode(scope.row,1)">çææ¡å½¢ç </el-button> |
| | | <el-button link type="success" size="small" @click="showERCode(scope.row,1)">çæäºç»´ç </el-button> --> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="æåå
¥åº" name="manual"> |
| | | <el-tab-pane label="ææå
¥åº" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产åå¾ç" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <img class="barcode-img" :src="javaApiUrl+scope.row.url"></img> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ¶é´" prop="inboundDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å
¥åºæ°é/ä»¶" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="150" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="70" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column label="å
¥åºäºº" prop="createBy" width="80" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row, 'manual');">ç¼è¾</el-button> |
| | | <el-button link type="success" size="small" @click="showQRCode(scope.row,2)">çææ¡å½¢ç </el-button> |
| | | <el-button link type="success" size="small" @click="showERCode(scope.row,2)">çæäºç»´ç </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <form-dia ref="formDia" @close="handleQuery" @success="handleQuery"></form-dia> |
| | | <form-dia-manual ref="formDiaManual" @close="handleQuery" @success="handleQuery"></form-dia-manual> |
| | | <form-dia-product ref="formDiaProduct" @close="handleQuery" @success="handleQuery"></form-dia-product> |
| | | <el-dialog |
| | | v-model="qrCodeDialogVisible" |
| | | title="å忡形ç " |
| | | width="400px" |
| | | center |
| | | > |
| | | <div style="text-align: center;"> |
| | | <img id="barcode" style="width:200px;height: 50px;"/> |
| | | <!-- <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> --> |
| | | <div style="margin: 20px;"> |
| | | <el-button type="primary" @click="downloadQRCode">ä¸è½½æ¡å½¢ç </el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <!-- äºç»´ç æ¾ç¤ºå¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | v-model="erCodeDialogVisible" |
| | | title="ååäºç»´ç " |
| | | width="400px" |
| | | center |
| | | > |
| | | <div style="text-align: center;"> |
| | | <img :src="erCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> |
| | | <div style="margin: 20px;"> |
| | | <el-button type="primary" @click="downloadERCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog v-model="barcodeDia" title="产åä¿¡æ¯" width="40%" @close="closeBarcodeDia"> |
| | | <div> |
| | | <el-row v-if="barcodeDetail.url" :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">å¾ç</div> |
| | | <img class="barcode-img" :src="javaApiUrl+barcodeDetail.url"></img> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">åç§°</div> |
| | | <div class="barcode-value">{{barcodeDetail.productCategory}}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">产åé«åº¦</div> |
| | | <div class="barcode-value">{{barcodeDetail.specificationModel}}{{barcodeDetail.unit}}</div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">åä»·</div> |
| | | <div class="barcode-value">{{barcodeDetail.taxInclusiveUnitPrice}}ç¾å
/ä»¶</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">æ°é/ä»¶</div> |
| | | <div class="barcode-value">{{barcodeDetail.inboundNum}}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">æ¯ä»¶æ°é/æ¯</div> |
| | | <div class="barcode-value">{{barcodeDetail.boxNum}}</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">çº¸ç®±è§æ ¼</div> |
| | | <div class="barcode-value">{{barcodeDetail.cartonSpecifications}}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">å
¥åºäºº</div> |
| | | <div class="barcode-value">{{barcodeDetail.createBy}}</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeBarcodeDia">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import dayjs from 'dayjs' |
| | | const javaApiUrl = __BASE_API__; |
| | | import { |
| | | getStockInPage, |
| | | getStockInPageByProduction, |
| | | delStockIn, |
| | | delStockInCustom, getInPageByCustom, |
| | | stockinDetail,detailManagementByCustom |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | import FormDia from './components/formDia.vue' |
| | | import FormDiaManual from './components/formDiaManual.vue' |
| | | import FormDiaProduct from './components/formDiaProduct.vue' |
| | | import QRCode from "qrcode"; |
| | | import JsBarcode from "jsbarcode"; |
| | | |
| | | // è·åå½åæ¥æ |
| | | function getCurrentDate() { |
| | |
| | | const formDia = ref() |
| | | const formDiaManual = ref() |
| | | const formDiaProduct = ref() |
| | | const activeTab = ref('purchase') // å½åæ¿æ´»ç tab |
| | | const activeTab = ref('production') // å½åæ¿æ´»ç tab |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | |
| | | // 忢 tab æ¶æ¸
空æç´¢æ¡ä»¶ |
| | | searchForm.value.supplierName = '' |
| | | searchForm.value.customerName = '' |
| | | searchForm.value.timeStr = getCurrentDate() // é置为å½åæ¥æ |
| | | searchForm.value.timeStr = '' |
| | | searchForm.value.productCategory = '' |
| | | getList() |
| | | } |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row, tabType) => { |
| | | if(barcodeDia.value)return |
| | | const currentTab = tabType || activeTab.value |
| | | await nextTick(() => { |
| | | if (currentTab === 'manual') { |
| | |
| | | } else { |
| | | // ææå
¥åº |
| | | deleteApi = delStockInCustom |
| | | deleteParams = [...ids] |
| | | deleteParams = { ids } |
| | | } |
| | | |
| | | deleteApi(deleteParams).then(() => { |
| | |
| | | }) |
| | | } |
| | | |
| | | |
| | | // äºç»´ç ç¸å
³åé |
| | | const qrCodeDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const showQRCode = async (row,type) => { |
| | | if(barcodeDia.value)return |
| | | try { |
| | | // æå»ºäºç»´ç å
容ï¼åªå
å«éè´ååå·ï¼çº¯ææ¬ï¼ |
| | | let qrContent = row.id || ''; |
| | | // æ£æ¥å
容æ¯å¦ä¸ºç©º |
| | | if (!qrContent) { |
| | | proxy.$modal.msgWarning("该è¡ååidï¼æ æ³çææ¡å½¢ç "); |
| | | return; |
| | | } |
| | | qrContent+=`,${type}` |
| | | qrCodeDialogVisible.value = true; |
| | | await nextTick(); |
| | | JsBarcode("#barcode", qrContent+'', { |
| | | width:10, |
| | | height:100, |
| | | displayValue: false |
| | | }); |
| | | } catch (error) { |
| | | console.error('çææ¡å½¢ç 失败:', error); |
| | | proxy.$modal.msgError("çææ¡å½¢ç 失败ï¼" + error.message); |
| | | } |
| | | }; |
| | | |
| | | const erCodeDialogVisible = ref(false); |
| | | const erCodeUrl = ref(""); |
| | | const showERCode = async (row,type) => { |
| | | if(barcodeDia.value)return |
| | | let qrContent = row.id || ''; |
| | | // æ£æ¥å
容æ¯å¦ä¸ºç©º |
| | | if (!qrContent) { |
| | | proxy.$modal.msgWarning("该è¡ååidï¼æ æ³çæäºç»´ç "); |
| | | return; |
| | | } |
| | | qrContent+=`,${type}` |
| | | try { |
| | | erCodeUrl.value = await QRCode.toDataURL(qrContent+'', { |
| | | width: 200, |
| | | margin: 2, |
| | | color: { |
| | | dark: '#000000', |
| | | light: '#FFFFFF' |
| | | } |
| | | }); |
| | | erCodeDialogVisible.value = true; |
| | | } catch (error) { |
| | | console.error('çæäºç»´ç 失败:', error); |
| | | proxy.$modal.msgError("çæäºç»´ç 失败ï¼" + error.message); |
| | | } |
| | | }; |
| | | const downloadQRCode = () => { |
| | | const imgSrc = document.getElementById('barcode').src |
| | | const a = document.createElement('a'); |
| | | if(!imgSrc){ |
| | | proxy.$modal.msgWarning('ææ æ¡å½¢ç ') |
| | | return |
| | | } |
| | | a.href = imgSrc; |
| | | a.download = `å忡形ç _${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | }; |
| | | |
| | | // ä¸è½½äºç»´ç |
| | | const downloadERCode = () => { |
| | | if (!erCodeUrl.value) { |
| | | proxy.$modal.msgWarning("äºç»´ç æªçæ"); |
| | | return; |
| | | } |
| | | |
| | | const a = document.createElement('a'); |
| | | a.href = erCodeUrl.value; |
| | | a.download = `ååäºç»´ç _${new Date().getTime()}.png`; |
| | | document.body.appendChild(a); |
| | | a.click(); |
| | | document.body.removeChild(a); |
| | | proxy.$modal.msgSuccess("ä¸è½½æå"); |
| | | }; |
| | | |
| | | //æ«ç ç¸å
³åæ° |
| | | const barcodeDia = ref(false); |
| | | const scanBarcodeInput = ref(''); |
| | | const barcodeDetail = ref({}) |
| | | // æ«ç 彿° |
| | | function scanBarcode (e){ |
| | | if(!e||!e.target||!e.target.tagName){ |
| | | return; |
| | | } |
| | | if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') { |
| | | return |
| | | } |
| | | if (e.key === 'Enter') { |
| | | let _value = scanBarcodeInput.value |
| | | getDetail(_value) |
| | | scanBarcodeInput.value = "" |
| | | } else { |
| | | scanBarcodeInput.value += e.key |
| | | } |
| | | } |
| | | const getDetail = (barcode)=>{ |
| | | if(barcode.indexOf(",")==-1){ |
| | | proxy.$modal.msgWarning("è¯·æ«ææ£ç¡®çæ¡å½¢ç ") |
| | | return |
| | | } |
| | | let barcodeList = barcode.split(",") |
| | | let barcodeId = barcodeList[0] |
| | | let type = barcodeList[1] |
| | | let detailApi = null |
| | | if(type==1){ |
| | | detailApi = stockinDetail |
| | | }else if(type==2){ |
| | | detailApi = detailManagementByCustom |
| | | } |
| | | |
| | | if(!detailApi){ |
| | | proxy.$modal.msgWarning("è¯·æ«ææ£ç¡®çæ¡å½¢ç ") |
| | | return |
| | | } |
| | | detailApi({id:barcodeId}).then((resp) => { |
| | | if(!resp.data){ |
| | | proxy.$modal.msgError("ååä¸åå¨") |
| | | return |
| | | } |
| | | if(resp.code!=200){ |
| | | proxy.$modal.msgError(res.msg) |
| | | return |
| | | } |
| | | barcodeDetail.value = resp.data |
| | | barcodeDia.value = true |
| | | }).catch(() => { |
| | | proxy.$modal.msgError("æ¥ç详æ
失败") |
| | | }) |
| | | |
| | | } |
| | | |
| | | const closeBarcodeDia = () => { |
| | | barcodeDia.value = false |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // æ·»å æ«ç æªçå¬äºä»¶ |
| | | document.removeEventListener('keypress',scanBarcode) |
| | | document.addEventListener('keypress', scanBarcode) |
| | | getList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .barcode-item{ |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 5px 0; |
| | | |
| | | } |
| | | .barcode-img{ |
| | | width: 80px; |
| | | height: 80px; |
| | | border-radius: 5px; |
| | | background-color: #F5F5F5; |
| | | } |
| | | </style> |
| | | <style scoped lang="scss"></style> |
| | | |
| | | |
| | | |
| | |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产ååç§°ï¼" prop="productCategory"> |
| | | <el-form-item label="产å大类ï¼" prop="productCategory"> |
| | | <el-input disabled v-model="form.productCategory" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产åé«åº¦ï¼" prop="specificationModel"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="specificationModel"> |
| | | <el-input disabled v-model="form.specificationModel" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é«åº¦åä½ï¼" prop="unit"> |
| | | <el-form-item label="åä½ï¼" prop="unit"> |
| | | <el-input disabled v-model="form.unit" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç©åç±»åï¼" prop="itemType"> |
| | | <el-input disabled v-model="form.itemType" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> --> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¥åºæ°é/ä»¶ï¼" prop="inboundNum"> |
| | | <el-input-number :step="1" v-model="form.inboundNum" :min="form.totalInboundNum" style="width: 100%" |
| | | placeholder="请è¾å
¥" clearable/> |
| | | <el-form-item label="åºåæ°éï¼" prop="inboundNum"> |
| | | <el-input v-model="form.inboundNum" placeholder="请è¾å
¥" clearable @input="calculateTotalPrice" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å·²åºåºæ°é/ä»¶ï¼" prop="totalInboundNum"> |
| | | <el-form-item label="å·²åºåºæ°éï¼" prop="totalInboundNum"> |
| | | <el-input disabled v-model="form.totalInboundNum" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¾
åºåºæ°é/ä»¶ï¼" prop="inboundNum0"> |
| | | <el-form-item label="å¾
åºåºæ°éï¼" prop="inboundNum0"> |
| | | <el-input disabled v-model="form.inboundNum0" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- <el-row :gutter="30">--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="åä»·(å
)ï¼" prop="taxInclusiveUnitPrice">--> |
| | | <!-- <el-input v-model="form.taxInclusiveUnitPrice" placeholder="请è¾å
¥" clearable @input="calculateTotalPrice" />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="æ»ä»·(å
)ï¼" prop="taxInclusiveTotalPrice">--> |
| | | <!-- <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="èªå¨è®¡ç®" clearable />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä»·(å
)ï¼" prop="taxInclusiveUnitPrice"> |
| | | <el-input v-model="form.taxInclusiveUnitPrice" placeholder="请è¾å
¥" clearable @input="calculateTotalPrice" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ»ä»·(å
)ï¼" prop="taxInclusiveTotalPrice"> |
| | | <el-input disabled v-model="form.taxInclusiveTotalPrice" placeholder="èªå¨è®¡ç®" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <!-- <el-tab-pane label="éè´åºå" name="production"> |
| | | <el-tab-pane label="æååºå" name="production"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产ååç§°ï¼</span> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="unitPrice" width="150"></el-table-column> |
| | |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', 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" /> |
| | | </div> |
| | | </el-tab-pane> --> |
| | | |
| | | <el-tab-pane label="éè´åºå" name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">产ååç§°ï¼</span> |
| | | <el-input v-model="searchForm.productCategory" style="width: 240px" placeholder="请è¾å
¥" clearable /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :row-class-name="tableRowClassName" :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="æååºå" name="manual"> |
| | | <el-tab-pane label="åæåºå" name="purchase"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :row-class-name="tableRowClassName" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="createTime" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="éè´ååå·" prop="purchaseContractNumber" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" show-overflow-tooltip /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | |
| | | <el-tab-pane label="ææåºå" name="manual"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <!-- <span class="search_title">ä¾åºååç§°ï¼</span>--> |
| | | <!-- <el-input v-model="searchForm.supplierName" style="width: 240px" placeholder="请è¾å
¥" @change="handleQuery"--> |
| | | <!-- clearable prefix-icon="Search" />--> |
| | | <span class="search_title ml10">产ååç§°ï¼</span> |
| | | <el-input v-model="searchForm.productCategory" style="width: 240px" placeholder="请è¾å
¥" clearable /> |
| | | <span class="search_title ml10">å
¥åºæ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.timeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">产å大类ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.productCategory" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | <!-- <el-button type="danger" plain @click="handleDelete">å é¤</el-button>--> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="row => row.id" show-summary style="width: 100%" |
| | | :row-class-name="tableRowClassName" :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | :row-class-name="tableRowClassName" |
| | | :summary-method="summarizeMainTable" height="calc(100vh - 18.5em)"> |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产åå¾ç" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <img class="barcode-img" :src="javaApiUrl + scope.row.url"></img> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产ååç§°" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ¯ä»¶æ°é/æ¯" prop="boxNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å
¥åºæ°é" prop="inboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="çº¸ç®±è§æ ¼" prop="cartonSpecifications" width="150"></el-table-column> |
| | | <!-- <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <el-table-column label="å
¥åºæ¥æ" prop="inboundDate" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="æ¹æ¬¡å·" prop="code" width="130" show-overflow-tooltip /> |
| | | <el-table-column label="产å大类" prop="productCategory" show-overflow-tooltip /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" show-overflow-tooltip /> |
| | | <el-table-column label="åä½" prop="unit" width="80" show-overflow-tooltip /> |
| | | <el-table-column label="ç©åç±»å" prop="itemType" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="å·²åºåºæ°é" prop="totalInboundNum" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å©ä½åºå" prop="inboundNum0" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="åä»·(å
)" prop="taxInclusiveUnitPrice" width="150"></el-table-column> |
| | | <el-table-column label="æ»ä»·(å
)" prop="taxInclusiveTotalPrice" width="150"></el-table-column> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row);">ç¼è¾</el-button> |
| | | </template> |
| | | </el-table-column> --> |
| | | </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" /> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | |
| | | |
| | | <!-- æååºåå¼¹æ¡ --> |
| | | <FormDiaProduction v-model:dialogFormVisible="productionDialogVisible" :operationType="operationType" |
| | | :formData="form" @submit="submitForm" @close="closeDia" /> |
| | | |
| | | <FormDiaProduction |
| | | v-model:dialogFormVisible="productionDialogVisible" |
| | | :operationType="operationType" |
| | | :formData="form" |
| | | @submit="submitForm" |
| | | @close="closeDia" |
| | | /> |
| | | |
| | | <!-- åæåºåå¼¹æ¡ --> |
| | | <FormDiaPurchase v-model:dialogFormVisible="purchaseDialogVisible" :operationType="operationType" :formData="form" |
| | | @submit="submitForm" @close="closeDia" /> |
| | | |
| | | <FormDiaPurchase |
| | | v-model:dialogFormVisible="purchaseDialogVisible" |
| | | :operationType="operationType" |
| | | :formData="form" |
| | | @submit="submitForm" |
| | | @close="closeDia" |
| | | /> |
| | | |
| | | <!-- ææåºåå¼¹æ¡ --> |
| | | <FormDiaManual v-model:dialogFormVisible="manualDialogVisible" :operationType="operationType" :formData="form" |
| | | @submit="submitForm" @close="closeDia" /> |
| | | <FormDiaManual |
| | | v-model:dialogFormVisible="manualDialogVisible" |
| | | :operationType="operationType" |
| | | :formData="form" |
| | | @submit="submitForm" |
| | | @close="closeDia" |
| | | /> |
| | | </div> |
| | | <el-dialog v-model="barcodeDia" title="产åä¿¡æ¯" width="70%" @close="closeBarcodeDia"> |
| | | <div> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">åç§°</div> |
| | | <div class="barcode-value">{{ barcodeDetail.barcode }}</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">åä»·</div> |
| | | <div class="barcode-value">xxxå
</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">产åé«åº¦</div> |
| | | <div class="barcode-value">222cm</div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">æ°é/ä»¶</div> |
| | | <div class="barcode-value">120</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <div class="barcode-item"> |
| | | <div class="barcode-label">è§æ ¼</div> |
| | | <div class="barcode-value">12*20*30</div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeBarcodeDia">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import { productTreeList, modelList } from "@/api/basicData/product.js" |
| | | import { productTreeList,modelList } from "@/api/basicData/product.js" |
| | | import { |
| | | getStockManagePage, |
| | | getStockManagePageByProduction, |
| | |
| | | delStockManage, |
| | | } from "@/api/inventoryManagement/stockManage.js"; |
| | | import { |
| | | updateManagement, updateManagementByCustom, updateStockIn |
| | | updateManagement, updateManagementByCustom, updateStockIn |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | const javaApiUrl = __BASE_API__; |
| | | |
| | | // 导å
¥ä¸ä¸ªç¬ç«çå¼¹æ¡ç»ä»¶ |
| | | import FormDiaProduction from './components/FormDiaProduction.vue' |
| | |
| | | const loading = ref(false); |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref('') |
| | | const activeTab = ref('purchase') |
| | | const activeTab = ref('production') |
| | | |
| | | // ä¸ä¸ªç¬ç«çå¼¹æ¡æ¾ç¤ºç¶æ |
| | | const productionDialogVisible = ref(false) |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | // supplierName: '', |
| | | productCategory: '', |
| | | productCategory:'', |
| | | customerName: '', |
| | | timeStr: getCurrentDate(), |
| | | }, |
| | | form: { |
| | | supplierId: null, |
| | |
| | | inboundBatch: '', |
| | | stockQuantity: '', |
| | | boundTime: '', |
| | | warnNum: '', // æ°å¢æä½åºååæ®µ |
| | | warnNum: '', // æ°å¢æä½åºååæ®µ |
| | | salesLedgerProductId: null, |
| | | }, |
| | | rules: { |
| | |
| | | boundTime: [{ required: true, message: 'è¯·éæ©åºåæ¶é´', trigger: 'change' }], |
| | | inboundTime: [{ required: true, message: 'è¯·éæ©å
¥åºæ¶é´', trigger: 'change' }], |
| | | inboundPerson: [{ required: true, message: 'è¯·éæ©åºåºäºº', trigger: 'change' }], |
| | | warnNum: [{ required: true, message: '请è¾å
¥æä½åºå', trigger: 'blur' }], |
| | | warnNum: [{ required: true, message: '请è¾å
¥æä½åºå', trigger: 'blur' }], |
| | | } |
| | | }) |
| | | const { searchForm, form, rules } = toRefs(data) |
| | |
| | | const buildQueryParams = () => { |
| | | const params = { |
| | | ...page, |
| | | timeStr: searchForm.value.timeStr, |
| | | } |
| | | params.productCategory = searchForm.value.productCategory |
| | | if (activeTab.value === 'production') { |
| | |
| | | apiCall.then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | |
| | | |
| | | // ä¸ºè¡¨æ ¼æ°æ®èªå¨è®¡ç®æ»ä»· |
| | | tableData.value = tableData.value.map(item => { |
| | | // 计ç®å©ä½åºå |
| | | const stockQuantity = parseFloat(item.inboundNum) || 0 |
| | | const outboundQuantity = parseFloat(item.totalInboundNum) || 0 |
| | | const remainingStock = Math.max(stockQuantity - outboundQuantity, 0) |
| | | |
| | | |
| | | // æ ¹æ®æ ç¾é¡µç±»åè®¡ç®æ»ä»· |
| | | if (activeTab.value === 'production') { |
| | | // æååºåï¼æ»ä»· = åä»· à å©ä½åºå |
| | |
| | | const taxInclusiveUnitPrice = parseFloat(item.taxInclusiveUnitPrice) || 0 |
| | | item.taxInclusiveTotalPrice = (taxInclusiveUnitPrice * remainingStock).toFixed(2) |
| | | } |
| | | |
| | | |
| | | return item |
| | | }) |
| | | |
| | | |
| | | total.value = res.data.total |
| | | // æ°æ®å è½½å®æåæ£æ¥åºå |
| | | // checkStockAndCreatePurchase(); |
| | |
| | | page.current = 1 |
| | | // searchForm.value.supplierName = '' |
| | | searchForm.value.customerName = '' |
| | | searchForm.value.timeStr = '' |
| | | selectedRows.value = [] |
| | | searchForm.value.productCategory = '' |
| | | getList() |
| | |
| | | userList.value = userLists.data |
| | | if (type === 'edit') { |
| | | form.value = { ...row } |
| | | productTreeList().then(res => { |
| | | productTreeList().then(res =>{ |
| | | productList.value = res |
| | | productList.value.forEach(i => { |
| | | productList.value.forEach(i =>{ |
| | | if (i.label === row.productCategory) { |
| | | modelList({ id: i.id }).then((res) => { |
| | | productModelList.value = res; |
| | |
| | | }) |
| | | } |
| | | form.value.entryDate = getCurrentDate() // 设置é»è®¤å½å
¥æ¥æä¸ºå½åæ¥æ |
| | | |
| | | |
| | | // æ ¹æ®å½åæ ç¾é¡µæ¾ç¤ºå¯¹åºçå¼¹æ¡ |
| | | if (activeTab.value === 'production') { |
| | | productionDialogVisible.value = true |
| | |
| | | // æäº¤è¡¨å |
| | | const submitForm = (submittedData) => { |
| | | console.log('åç»ä»¶æäº¤çæ°æ®:', submittedData) |
| | | |
| | | |
| | | // 使ç¨åç»ä»¶æäº¤çæ°æ®ï¼è䏿¯ç¶ç»ä»¶çform对象 |
| | | const submitData = { ...submittedData } |
| | | |
| | | |
| | | // æ ¹æ®å½åæ ç¾é¡µç§»é¤å¯¹åºçæ»ä»·å段 |
| | | if (activeTab.value === 'production') { |
| | | // æååºåï¼ç§»é¤æ»ä»·å段 |
| | |
| | | // ææåºåï¼ç§»é¤å«ç¨æ»ä»·å段 |
| | | delete submitData.taxInclusiveTotalPrice |
| | | } |
| | | |
| | | |
| | | // ç§»é¤å
¶ä»å¯è½çæ»ä»·å段 |
| | | delete submitData.taxExclusiveTotalPrice |
| | | |
| | | |
| | | console.log('æäº¤ç»åç«¯çæ°æ®ï¼å·²ç§»é¤æ»ä»·å段ï¼:', submitData) |
| | | submitData.inboundNum = parseFloat(submitData.inboundNum) || 0 |
| | | |
| | | // æ ¹æ®å½åæ ç¾é¡µè°ç¨ä¸åçæäº¤æ¥å£ |
| | | let apiCall |
| | | if (activeTab.value === 'production') { |
| | |
| | | // åæåºåä½¿ç¨ updateManagementByCustom æ¥å£ |
| | | apiCall = updateManagementByCustom(submitData) |
| | | } |
| | | |
| | | |
| | | apiCall.then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå") |
| | | closeDia() |
| | |
| | | type: 'warning', |
| | | } |
| | | ).then(() => { |
| | | delStockManage({ ids: ids }).then(res => { |
| | | delStockManage({ids:ids}).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å") |
| | | getList() |
| | | }) |
| | |
| | | const day = String(today.getDate()).padStart(2, '0'); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | //æ«ç ç¸å
³åæ° |
| | | const barcodeDia = ref(false); |
| | | const scanBarcodeInput = ref(''); |
| | | const barcodeDetail = ref({}) |
| | | // æ«ç 彿° |
| | | const scanBarcode = (e) => { |
| | | if (!e || !e.target || !e.target.tagName) { |
| | | return; |
| | | } |
| | | if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') { |
| | | return |
| | | } |
| | | if (e.key === 'Enter') { |
| | | let _value = scanBarcodeInput.value |
| | | getDetail(_value) |
| | | scanBarcodeInput.value = "" |
| | | } else { |
| | | scanBarcodeInput.value += e.key |
| | | } |
| | | } |
| | | const getDetail = (barcode) => { |
| | | barcodeDetail.value = { |
| | | barcode: barcode |
| | | } |
| | | barcodeDia.value = true |
| | | } |
| | | |
| | | const closeBarcodeDia = () => { |
| | | barcodeDia.value = false |
| | | } |
| | | onMounted(() => { |
| | | // æ·»å æ«ç æªçå¬äºä»¶ |
| | | // document.addEventListener('keypress', scanBarcode) |
| | | getList() |
| | | // checkStockAndCreatePurchase(); |
| | | // æ¯å°æ¶æ£æ¥ä¸æ¬¡åºå |
| | | // const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000); |
| | | // æ¯å°æ¶æ£æ¥ä¸æ¬¡åºå |
| | | // const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000); |
| | | |
| | | // onUnmounted(() => { |
| | | // // ç»ä»¶å¸è½½æ¶æ¸
é¤å®æ¶å¨ |
| | | // clearInterval(intervalId); |
| | | // }); |
| | | }) |
| | | onUnmounted(() => { |
| | | // ç§»é¤é®ççå¬äºä»¶ |
| | | document.removeEventListener('keypress', scanBarcode) |
| | | console.log('ç»ä»¶å¸è½½') |
| | | // onUnmounted(() => { |
| | | // // ç»ä»¶å¸è½½æ¶æ¸
é¤å®æ¶å¨ |
| | | // clearInterval(intervalId); |
| | | // }); |
| | | }) |
| | | </script> |
| | | |
| | |
| | | |
| | | :deep(.row-low-stock:hover > td) { |
| | | background-color: #fcd4d4; |
| | | } |
| | | |
| | | .barcode-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 5px 0; |
| | | } |
| | | |
| | | .barcode-img { |
| | | width: 80px; |
| | | height: 80px; |
| | | border-radius: 5px; |
| | | background-color: #F5F5F5; |
| | | } |
| | | </style> |
| | |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="true" |
| | | :isShowPage="false" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | :page="page" |
| | | @pagination="pagination" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | |
| | | currentId.value = row.id; |
| | | getList() |
| | | } |
| | | const paginationSearch = (obj) => { |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | |
| | | const getList = () => { |
| | | fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | page.total = res.data.total; |
| | | }) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref } from "vue"; |
| | | import { Search, UploadFilled } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue"; |
| | | import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import { staffOnJobListPage, staffOnJobExportCopy } from "@/api/personnelManagement/employeeRecord.js"; |
| | | import dayjs from "dayjs"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 120, |
| | | width: 180, |
| | | operation: [ |
| | | { |
| | | name: "详æ
", |
| | |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ä¸è½½åå", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | handleDownloadContract(row); |
| | | }, |
| | | }, |
| | | ], |
| | |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // ä¸è½½åå |
| | | const handleDownloadContract = (row) => { |
| | | const fileName = `${row.staffName || "åå"}å³å¨åå.docx`; |
| | | proxy.$modal?.loading?.("æ£å¨çæååï¼è¯·ç¨å..."); |
| | | staffOnJobExportCopy({ ...row }) |
| | | .then((res) => { |
| | | proxy.$modal?.closeLoading?.(); |
| | | if (res?.code === 200 && res?.msg) { |
| | | const javaApi = proxy.javaApi || import.meta.env.VITE_JAVA_API || ""; |
| | | const downloadPath = res.msg.startsWith("/") ? res.msg : `/${res.msg}`; |
| | | const downloadUrl = `${javaApi}${downloadPath}`; |
| | | const link = document.createElement("a"); |
| | | link.href = downloadUrl; |
| | | link.download = fileName; |
| | | link.target = "_blank"; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | } else { |
| | | proxy.$modal.msgError(res?.msg || "ååçæå¤±è´¥"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal?.closeLoading?.(); |
| | | proxy.$modal.msgError("ååçæå¤±è´¥ï¼è¯·ç¨åéè¯"); |
| | | }); |
| | | }; |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼åå导å
¥ï¼ |
| | | open: false, |
| | |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">å§åï¼</span> |
| | | <el-select v-model="form.staffName" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect"> |
| | | <el-select v-model="form.staffName" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :tableLoading="tableLoading" |
| | | height="600" |
| | | ></PIMTable> |
| | | <el-descriptions class="detail-descriptions" :column="2" border size="small"> |
| | | <el-descriptions-item label="åå·¥ç¼å·">{{ formData.staffNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å§å">{{ formData.staffName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ§å«">{{ formData.sex || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¹´é¾">{{ formData.age || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="身份è¯å·">{{ formData.identityCard || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ·ç±ä½å" :span="2">{{ formData.nativePlace || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç°ä½å" :span="2">{{ formData.adress || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å²ä½">{{ formData.postJob || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="第ä¸å¦å">{{ formData.firstStudy || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸ä¸">{{ formData.profession || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="èç³»çµè¯">{{ formData.phone || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç´§æ¥è系人">{{ formData.emergencyContact || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç´§æ¥è系人çµè¯">{{ formData.emergencyContactPhone || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="ååç¾è®¢æ¥æ">{{ formData.signDate || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å³å¨ååæééæ©"> |
| | | <span v-if="formData.dateSelect === 'A'">Aãæåºå®æé</span> |
| | | <span v-else-if="formData.dateSelect === 'B'">Bãæ åºå®æé</span> |
| | | <span v-else-if="formData.dateSelect === 'C'">Cã以宿ä¸å®å·¥ä½ä»»å¡ä¸ºæé</span> |
| | | <span v-else>-</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ååå¹´é">{{ formattedContractTerm }}</el-descriptions-item> |
| | | <el-descriptions-item label="è¯ç¨æå¼å§æ¥æ" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'"> |
| | | {{ formData.trialStartDate || '-' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="è¯ç¨æç»ææ¥æ" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'"> |
| | | {{ formData.trialEndDate || '-' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="è¯ç¨æå·¥èµ" v-if="formData.dateSelect === 'A' || formData.dateSelect === 'B'"> |
| | | {{ formData.proSalary ? formData.proSalary.toFixed(2) : '-' }} |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ååå¼å§æ¥æ">{{ calculatedContractStart }}</el-descriptions-item> |
| | | <el-descriptions-item label="ååç»ææ¥æ">{{ formData.contractEndTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="å·¥èµæ¥é
¬" :span="2"> |
| | | <span v-if="formData.salarySelect === 'A'"> |
| | | Aã乿¹çå·¥èµæ¥é
¬æç
§ç²æ¹ä¾æ³å¶å®çè§ç« å¶åº¦ä¸çå
é¨å·¥èµåé
åæ³ç¡®å®ï¼æ ¹æ®ä¹æ¹çå·¥ä½å²ä½ç¡®å®å
¶æ¯æå·¥èµã |
| | | </span> |
| | | <span v-else-if="formData.salarySelect === 'B'"> |
| | | Bãç²æ¹å¯¹ä¹æ¹å®è¡åºæ¬å·¥èµå绩æå·¥èµç¸ç»åçå
é¨å·¥èµåé
åæ³ï¼ä¹æ¹çæ¶å
¥å
æ¬åºæ¬å·¥èµã误é¤ã交éãçæ´»ä½å®¿çå项补å©ï¼å¦æå卿 ¹æ®å
é¨å·¥èµåé
åæ³è°æ´å
¶å·¥èµï¼ç»©æå·¥èµæ ¹æ®ä¹æ¹çå·¥ä½ä¸ç»©ãå³å¨ææåå®é
è´¡ç®æç
§å
é¨åé
åæ³èæ ¸ç¡®å®ã |
| | | </span> |
| | | <span v-else-if="formData.salarySelect === 'C'"> |
| | | Cãç²æ¹å®è¡è®¡ä»¶å·¥èµå¶ï¼ä»¥ç²æ¹æ¥å°è®¢ååå
¬å¸ç产计åï¼æç
§å®é¢å计件åä»·ï¼æ ¹æ®ä¹æ¹å®æçä¸ç»©ï¼ææ¶è¶³é¢æ¯ä»ä¹æ¹çå·¥èµæ¥é
‹ |
| | | </span> |
| | | <span v-else>-</span> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="ç¦å©å¾
é" :span="2">{{ formData.remark || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | <el-button @click="closeDia">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {staffOnJobInfo} from "@/api/personnelManagement/employeeRecord.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | import {ref, reactive, computed} from "vue"; |
| | | import dayjs from "dayjs"; |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableColumn = ref([ |
| | | // { |
| | | // label: "ååå¹´é", |
| | | // prop: "contractTerm", |
| | | // }, |
| | | { |
| | | label: "ååå¼å§æ¥æ", |
| | | prop: "contractStartTime", |
| | | }, |
| | | { |
| | | label: "ååç»ææ¥æ", |
| | | prop: "contractEndTime", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const formData = reactive({ |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | identityCard: "", |
| | | nativePlace: "", |
| | | postJob: "", |
| | | adress: "", |
| | | firstStudy: "", |
| | | profession: "", |
| | | age: 0, |
| | | phone: "", |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | dateSelect: "", |
| | | trialStartDate: "", |
| | | trialEndDate: "", |
| | | proSalary: null, |
| | | signDate: "", |
| | | salarySelect: "", |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | contractTerm: null, |
| | | remark: "", |
| | | }); |
| | | |
| | | const formattedContractTerm = computed(() => { |
| | | const value = formData.contractTerm; |
| | | if (value === null || value === undefined || value === "") { |
| | | return "-"; |
| | | } |
| | | const numberValue = Number(value); |
| | | if (!isNaN(numberValue)) { |
| | | return `${numberValue}å¹´`; |
| | | } |
| | | return value; |
| | | }); |
| | | |
| | | const calculatedContractStart = computed(() => { |
| | | const endDate = formData.contractEndTime; |
| | | const termValue = formData.contractTerm; |
| | | const numberValue = Number(termValue); |
| | | if (!endDate || isNaN(numberValue)) { |
| | | return formData.contractStartTime || "-"; |
| | | } |
| | | const start = dayjs(endDate).subtract(numberValue, "year"); |
| | | if (!start.isValid()) { |
| | | return formData.contractStartTime || "-"; |
| | | } |
| | | return start.format("YYYY-MM-DD"); |
| | | }); |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | if (operationType.value === 'edit') { |
| | | staffOnJobInfo({staffNo: row.staffNo}).then(res => { |
| | | tableData.value = res.data |
| | | }) |
| | | // éç½®è¡¨åæ°æ® |
| | | Object.keys(formData).forEach(key => { |
| | | if (key === 'age') { |
| | | formData[key] = 0; |
| | | } else if (["proSalary", "contractTerm"].includes(key)) { |
| | | formData[key] = null; |
| | | } else { |
| | | formData[key] = ""; |
| | | } |
| | | }); |
| | | |
| | | if (operationType.value === 'edit' && row) { |
| | | // ç´æ¥ä½¿ç¨ row æ°æ®èµå¼ |
| | | Object.assign(formData, row); |
| | | } |
| | | } |
| | | |
| | |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .detail-descriptions { |
| | | margin-bottom: 16px; |
| | | border-radius: 6px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .detail-descriptions :deep(.el-descriptions__cell) { |
| | | padding: 12px 16px !important; |
| | | } |
| | | |
| | | .detail-descriptions :deep(.el-descriptions__label) { |
| | | width: 140px; |
| | | color: #606266; |
| | | background-color: #f7f9fc; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-descriptions :deep(.el-descriptions__content) { |
| | | color: #303133; |
| | | line-height: 20px; |
| | | } |
| | | </style> |
| | |
| | | <el-input v-model="form.emergencyContactPhone" placeholder="请è¾å
¥" clearable/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååå¹´éï¼" prop="contractTerm"> |
| | | <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="ååå¹´éï¼" prop="contractTermcontractTerm">--> |
| | | <!-- <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value.id = '' |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | form.value = {...res.data} |
| | | // ç¼è¾æ¶ä¹è®¡ç®ä¸æ¬¡ååå¹´é |
| | | calculateContractTerm(); |
| | | // calculateContractTerm(); |
| | | }) |
| | | } else { |
| | | form.value.id = '' |
| | | } |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="身份è¯å·ï¼" prop="identityCard"> |
| | | <el-input v-model="form.identityCard" placeholder="请è¾å
¥èº«ä»½è¯å·ç " clearable maxlength="18" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¹´é¾ï¼" prop="age"> |
| | | <el-input-number v-model="form.age" :precision="0" :step="1" style="width: 100%"/> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååç¾è®¢æ¥æï¼" prop="trialStartDate"> |
| | | <el-form-item label="ååç¾è®¢æ¥æï¼" prop="signDate"> |
| | | <el-date-picker |
| | | v-model="form.trialStartDate" |
| | | v-model="form.signDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | </el-row> |
| | | <el-row :gutter="30" v-if="showProbationDates"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è¯ç¨æå¼å§æ¥æï¼" prop="signDate"> |
| | | <el-form-item label="è¯ç¨æå¼å§æ¥æï¼" prop="trialStartDate"> |
| | | <el-date-picker |
| | | v-model="form.signDate" |
| | | v-model="form.trialStartDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- <el-row :gutter="30">--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="ååå¹´éï¼" prop="contractTerm">--> |
| | | <!-- <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/>--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååå¹´éï¼" prop="contractTerm"> |
| | | <el-input-number v-model="form.contractTerm" :precision="0" :step="1" style="width: 100%" :disabled="true"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ååå¼å§æ¥æï¼" prop="contractStartTime"> |
| | |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="calculateContractTerm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | staffNo: "", |
| | | staffName: "", |
| | | sex: "", |
| | | identityCard: "", |
| | | nativePlace: "", |
| | | postJob: "", |
| | | adress: "", |
| | |
| | | emergencyContact: "", |
| | | emergencyContactPhone: "", |
| | | dateSelect: "", |
| | | signDate: "", |
| | | trialStartDate: "", |
| | | trialEndDate: "", |
| | | proSalary: null, |
| | | trialStartDate: "", |
| | | signDate: "", |
| | | salarySelect: "", |
| | | // contractTerm: 0, |
| | | contractTerm: 0, |
| | | contractStartTime: "", |
| | | contractEndTime: "", |
| | | staffState: "", |
| | | remark: "æ ", |
| | | }, |
| | | rules: { |
| | | staffNo: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | | staffName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | sex: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | identityCard: [{ required: true, message: "请è¾å
¥èº«ä»½è¯å·ç ", trigger: "blur" }], |
| | | nativePlace: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | postJob: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | adress: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | |
| | | emergencyContact: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | remark: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | dateSelect: [{ required: true, message: "è¯·éæ©å³å¨ååæé", trigger: "change" }], |
| | | signDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | trialStartDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | trialEndDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | trialStartDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | signDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | salarySelect: [{ required: true, message: "è¯·éæ©å·¥èµæ¥é
¬æ¹å¼", trigger: "change" }], |
| | | // contractTerm: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractTerm: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractStartTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contractEndTime: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | proSalary: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | form.value.id = '' |
| | | if (operationType.value === 'edit') { |
| | | getStaffJoinInfo(row.id).then(res => { |
| | | form.value = {...res.data} |
| | | // ç¼è¾æ¶ä¹è®¡ç®ä¸æ¬¡ååå¹´é |
| | | // calculateContractTerm(); |
| | | calculateContractTerm(); |
| | | }) |
| | | } |
| | | } |
| | |
| | | }) |
| | | } |
| | | // 计ç®ååå¹´é |
| | | // const calculateContractTerm = () => { |
| | | // if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | // const startDate = new Date(form.value.contractStartTime); |
| | | // const endDate = new Date(form.value.contractEndTime); |
| | | // |
| | | // if (endDate > startDate) { |
| | | // // 计ç®å¹´ä»½å·® |
| | | // const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | // const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | // const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | // |
| | | // let years = yearDiff; |
| | | // |
| | | // // å¦æç»ææ¥æçææ¥å°äºå¼å§æ¥æçææ¥ï¼ååå»1å¹´ |
| | | // if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | // years = yearDiff - 1; |
| | | // } |
| | | // |
| | | // form.value.contractTerm = Math.max(0, years); |
| | | // } else { |
| | | // form.value.contractTerm = 0; |
| | | // } |
| | | // } else { |
| | | // form.value.contractTerm = 0; |
| | | // } |
| | | // }; |
| | | const calculateContractTerm = () => { |
| | | if (form.value.contractStartTime && form.value.contractEndTime) { |
| | | const startDate = new Date(form.value.contractStartTime); |
| | | const endDate = new Date(form.value.contractEndTime); |
| | | |
| | | if (endDate > startDate) { |
| | | // 计ç®å¹´ä»½å·® |
| | | const yearDiff = endDate.getFullYear() - startDate.getFullYear(); |
| | | const monthDiff = endDate.getMonth() - startDate.getMonth(); |
| | | const dayDiff = endDate.getDate() - startDate.getDate(); |
| | | |
| | | let years = yearDiff; |
| | | |
| | | // å¦æç»ææ¥æçææ¥å°äºå¼å§æ¥æçææ¥ï¼ååå»1å¹´ |
| | | if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) { |
| | | years = yearDiff - 1; |
| | | } |
| | | |
| | | form.value.contractTerm = Math.max(0, years); |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | } else { |
| | | form.value.contractTerm = 0; |
| | | } |
| | | }; |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/onboarding/components/formDia.vue"; |
| | | // import FormDia from "@/views/personnelManagement/onboarding/components/formDiaXJHT.vue"; // æ°çé£åå
¬å¸ç¨ç表å |
| | | // import FormDia from "@/views/personnelManagement/onboarding/components/formDia.vue"; |
| | | import FormDia from "@/views/personnelManagement/onboarding/components/formDiaXJHT.vue"; // æ°çé£åå
¬å¸ç¨ç表å |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | |
| | | <el-select v-model="form.staffId" placeholder="è¯·éæ©äººå" style="width: 100%" @change="handleSelect" :disabled="operationType === 'edit'"> |
| | | <el-option |
| | | v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | | :value="item.id" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåºå¤å¤©æ°ï¼" prop="shouldAttendedNum"> |
| | | <el-input v-model="form.shouldAttendedNum" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®é
åºå¤å¤©æ°ï¼" prop="actualAttendedNum"> |
| | | <el-input v-model="form.actualAttendedNum" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºæ¬å·¥èµï¼" prop="basicSalary"> |
| | | <el-input v-model="form.basicSalary" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å²ä½å·¥èµï¼" prop="postSalary"> |
| | | <el-input v-model="form.postSalary" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¥ç¦»èç¼ºå¤æ£æ¬¾ï¼" prop="deductionAbsenteeism"> |
| | | <el-input v-model="form.deductionAbsenteeism" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç
åæ£æ¬¾ï¼" prop="sickLeaveDeductions"> |
| | | <el-input v-model="form.sickLeaveDeductions" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="äºåæ£æ¬¾ï¼" prop="deductionPersonalLeave"> |
| | | <el-input v-model="form.deductionPersonalLeave" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¿è®°æå¡æ£æ¬¾ï¼" prop="forgetClockDeduct"> |
| | | <el-input v-model="form.forgetClockDeduct" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="绩æå¾åï¼" prop="performanceScore"> |
| | | <el-input v-model="form.performanceScore" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="绩æå·¥èµï¼" prop="performancePay"> |
| | | <el-input v-model="form.performancePay" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºåå计ï¼" prop="payableWages"> |
| | | <el-input v-model="form.payableWages" placeholder="请è¾å
¥" clearable type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿ä¸ªäººï¼" prop="socialSecurityIndividuals"> |
| | | <el-input v-model="form.socialSecurityIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿å
¬å¸ï¼" prop="socialSecurityCompanies"> |
| | | <el-input v-model="form.socialSecurityCompanies" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="社ä¿å计ï¼" prop="socialSecurityTotal"> |
| | | <el-input v-model="form.socialSecurityTotal" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯é个人ï¼" prop="providentFundIndividuals"> |
| | | <el-input v-model="form.providentFundIndividuals" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯éå
¬å¸ï¼" prop="providentFundCompany"> |
| | | <el-input v-model="form.providentFundCompany" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬ç§¯éå计ï¼" prop="providentFundTotal"> |
| | | <el-input v-model="form.providentFundTotal" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åºç¨å·¥èµï¼" prop="taxableWaget"> |
| | | <el-input v-model="form.taxableWaget" :precision="0" :step="1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="个人æå¾ç¨ï¼" prop="personalIncomeTax"> |
| | | <el-input v-model="form.personalIncomeTax" :step="0.1" style="width: 100%" type="number"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å®åå·¥èµï¼" prop="actualWages"> |
| | | <el-input v-model="form.actualWages" style="width: 100%" type="number"/> |
| | |
| | | import {ref} from "vue"; |
| | | import {getStaffJoinInfo, getStaffOnJob, staffJoinAdd, staffJoinUpdate} from "@/api/personnelManagement/onboarding.js"; |
| | | import {compensationAdd, compensationUpdate} from "@/api/personnelManagement/payrollManagement.js"; |
| | | import {listUser} from "@/api/system/user.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | payDate: "", |
| | | staffId: "", |
| | | name: "", |
| | | shouldAttendedNum: "", |
| | | actualAttendedNum: "", |
| | | basicSalary: "", |
| | | postSalary: "", |
| | | deductionAbsenteeism: "", |
| | | sickLeaveDeductions: "", |
| | | deductionPersonalLeave: "", |
| | | forgetClockDeduct: "", |
| | | performanceScore: "", |
| | | performancePay: "", |
| | | payableWages: "", |
| | | socialSecurityIndividuals: "", |
| | | socialSecurityCompanies: "", |
| | | socialSecurityTotal: "", |
| | | providentFundIndividuals: "", |
| | | providentFundCompany: "", |
| | | providentFundTotal: "", |
| | | taxableWaget: "", |
| | | personalIncomeTax: "", |
| | | actualWages: "", |
| | | }, |
| | | rules: { |
| | | payDate: [{ required: true, message: "è¯·éæ©", trigger: "change" },], |
| | | staffId: [{ required: true, message: "è¯·éæ©", trigger: "change" },], |
| | | staffName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | shouldAttendedNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | actualAttendedNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | basicSalary: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | postSalary: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | deductionAbsenteeism: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | sickLeaveDeductions: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | deductionPersonalLeave: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | forgetClockDeduct: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | performanceScore: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | performancePay: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | payableWages: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityIndividuals: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityCompanies: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | socialSecurityTotal: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundIndividuals: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundCompany: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | providentFundTotal: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxableWaget: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | personalIncomeTax: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | actualWages: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }, |
| | | }); |
| | |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | listUser().then(res => { |
| | | personList.value = res.rows |
| | | }) |
| | | form.value = {} |
| | | if (operationType.value === 'edit') { |
| | |
| | | } |
| | | } |
| | | const handleSelect = (value) => { |
| | | console.log('value', value) |
| | | const index = personList.value.findIndex(row => row.id === value) |
| | | const index = personList.value.findIndex(row => row.userId === value) |
| | | if (index > -1) { |
| | | form.value.name = personList.value[index].staffName |
| | | form.value.name = personList.value[index].nickName |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | <el-button @click="handleImport">导å
¥</el-button> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢èªèµ</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleExport">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | |
| | | <!-- 导å
¥å¼¹çª --> |
| | | <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body @close="handleUploadClose"> |
| | | <el-upload |
| | | ref="uploadRef" |
| | | :limit="1" |
| | | accept=".xlsx, .xls" |
| | | :headers="upload.headers" |
| | | :action="upload.url" |
| | | :disabled="upload.isUploading" |
| | | :on-progress="upload.onProgress" |
| | | :on-success="upload.onSuccess" |
| | | :on-error="upload.onError" |
| | | :on-change="upload.onChange" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip text-center"> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link |
| | | type="primary" |
| | | :underline="false" |
| | | style="font-size: 12px; vertical-align: baseline" |
| | | @click="importTemplate" |
| | | >ä¸è½½æ¨¡æ¿</el-link> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitFileForm">ç¡® å®</el-button> |
| | | <el-button @click="handleUploadCancel">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { Search, UploadFilled } from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/personnelManagement/payrollManagement/components/formDia.vue"; |
| | | import {staffJoinDel} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {compensationDelete, compensationListPage} from "@/api/personnelManagement/payrollManagement.js"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | |
| | | { |
| | | label: "å§å", |
| | | prop: "name", |
| | | }, |
| | | { |
| | | label: "åºåºå¤å¤©æ°", |
| | | prop: "shouldAttendedNum", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å®é
åºå¤å¤©æ°", |
| | | prop: "actualAttendedNum", |
| | | width:110 |
| | | }, |
| | | { |
| | | label: "åºæ¬å·¥èµ", |
| | | prop: "basicSalary", |
| | | }, |
| | | { |
| | | label: "å²ä½å·¥èµ", |
| | | prop: "postSalary", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å
¥ç¦»èç¼ºå¤æ£æ¬¾", |
| | | prop: "deductionAbsenteeism", |
| | | width:130 |
| | | }, |
| | | { |
| | | label: "ç
åæ£æ¬¾", |
| | | prop: "sickLeaveDeductions", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "äºåæ£æ¬¾", |
| | | prop: "deductionPersonalLeave", |
| | | width:100 |
| | | }, |
| | | { |
| | | label: "å¿è®°æå¡æ£æ¬¾", |
| | | prop: "forgetClockDeduct", |
| | | width:110 |
| | | }, |
| | | { |
| | | label: "绩æå¾å", |
| | | prop: "performanceScore", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "绩æå·¥èµ", |
| | | prop: "performancePay", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "åºåå计", |
| | | prop: "payableWages", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "社ä¿ä¸ªäºº", |
| | | prop: "socialSecurityIndividuals", |
| | | }, |
| | | { |
| | | label: "社ä¿å
¬å¸", |
| | | prop: "socialSecurityCompanies", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "社ä¿å计", |
| | | prop: "socialSecurityTotal", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯é个人", |
| | | prop: "providentFundIndividuals", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯éå
¬å¸", |
| | | prop: "providentFundCompany", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å
¬ç§¯éå计", |
| | | prop: "providentFundTotal", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "åºç¨å·¥èµ", |
| | | prop: "taxableWaget", |
| | | }, |
| | | { |
| | | label: "个人æå¾ç¨", |
| | | prop: "personalIncomeTax", |
| | | width: 120 |
| | | }, |
| | | { |
| | | label: "å®åå·¥èµ", |
| | |
| | | }); |
| | | const formDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // 导å
¥åè½é
ç½® |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼èªèµå¯¼å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼èªèµå¯¼å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/compensationPerformance/importData", |
| | | // æä»¶ä¸ä¼ åçåè° |
| | | beforeUpload: (file) => { |
| | | // å¯ä»¥å¨æ¤å¤åæä»¶ç±»åæå¤§å°æ ¡éª |
| | | const isValid = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.name.endsWith('.xlsx') || file.name.endsWith('.xls'); |
| | | if (!isValid) { |
| | | proxy.$modal.msgError("åªè½ä¸ä¼ Excel æä»¶"); |
| | | } |
| | | return isValid; |
| | | }, |
| | | // æä»¶ç¶ææ¹åæ¶çåè° |
| | | onChange: (file, fileList) => { |
| | | console.log('æä»¶ç¶ææ¹å', file, fileList); |
| | | }, |
| | | // æä»¶ä¸ä¼ æåæ¶çåè° |
| | | onSuccess: (response, file, fileList) => { |
| | | upload.isUploading = false; |
| | | if(response.code === 200){ |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | handleUploadClose(); |
| | | getList(); |
| | | }else if(response.code === 500){ |
| | | proxy.$modal.msgError(response.msg); |
| | | }else{ |
| | | proxy.$modal.msgWarning(response.msg); |
| | | } |
| | | }, |
| | | // æä»¶ä¸ä¼ 失败æ¶çåè° |
| | | onError: (error, file, fileList) => { |
| | | console.error('ä¸ä¼ 失败', error, file, fileList); |
| | | upload.isUploading = false; |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | }, |
| | | // æä»¶ä¸ä¼ è¿åº¦åè° |
| | | onProgress: (event, file, fileList) => { |
| | | console.log('ä¸ä¼ ä¸...', event.percent); |
| | | } |
| | | }); |
| | | |
| | | const handleDateChange = (value,type) => { |
| | | searchForm.value.entryDateEnd = null |
| | |
| | | }); |
| | | }; |
| | | |
| | | /** 导å
¥æé®æä½ */ |
| | | function handleImport() { |
| | | upload.title = "èªèµå¯¼å
¥"; |
| | | upload.open = true; |
| | | } |
| | | |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | | upload.isUploading = true; |
| | | proxy.$refs["uploadRef"].submit(); |
| | | } |
| | | |
| | | /** ä¸è½½æ¨¡æ¿ */ |
| | | function importTemplate() { |
| | | proxy.download("/compensationPerformance/exportTemplate", {}, "èªèµå¯¼å
¥æ¨¡æ¿.xlsx"); |
| | | } |
| | | |
| | | // å¤çä¸ä¼ å¼¹æ¡åæ¶ |
| | | function handleUploadCancel() { |
| | | upload.open = false; |
| | | handleUploadClose(); |
| | | } |
| | | |
| | | // å¤çä¸ä¼ å¼¹æ¡å
³é |
| | | function handleUploadClose() { |
| | | upload.open = false; |
| | | upload.isUploading = false; |
| | | // æ¸
空ä¸ä¼ æä»¶ç¼å |
| | | if (proxy.$refs.uploadRef) { |
| | | proxy.$refs.uploadRef.clearFiles(); |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | |
| | | style="width: 150px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="çæ¬¡ç±»åï¼"> |
| | | <el-select v-model="filterForm.shiftType" placeholder="è¯·éæ©çæ¬¡" clearable style="width: 120px"> |
| | | <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥æèå´ï¼"> |
| | | <el-date-picker |
| | | v-model="filterForm.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 250px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleFilter"> |
| | | <el-icon><Search/></el-icon> |
| | | çé |
| | | æç´¢ |
| | | </el-button> |
| | | <el-button @click="resetFilter"> |
| | | <el-icon><Refresh/></el-icon> |
| | | éç½® |
| | | </el-button> |
| | | <el-button @click="handleExport"> |
| | | <el-icon><Download/></el-icon> |
| | | å¯¼åº |
| | | </el-button> |
| | | <el-button type="primary" @click="openScheduleDialog('add')"> |
| | |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55"/> |
| | | <el-table-column prop="staffName" label="åå·¥å§å" width="120"/> |
| | | <el-table-column prop="staffNo" label="å工工å·" width="100"/> |
| | | <el-table-column prop="department" label="é¨é¨" width="120"> |
| | | <el-table-column prop="staffName" label="åå·¥å§å"/> |
| | | <!-- <el-table-column prop="staffNo" label="å工工å·" width="100"/> --> |
| | | <!-- <el-table-column prop="department" label="é¨é¨" width="120"> |
| | | <template #default="scope"> |
| | | {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="shiftType" label="çæ¬¡ç±»å" width="100"> |
| | | </el-table-column> --> |
| | | <el-table-column prop="shiftType" label="çæ¬¡ç±»å" width="120"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getShiftTagType(scope.row.shiftType)"> |
| | | {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }} |
| | | {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label || 'æªç¥' }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workDate" label="工使¥æ" width="120"/> |
| | | <el-table-column prop="startTime" label="å¼å§æ¶é´" width="100"/> |
| | | <el-table-column prop="endTime" label="ç»ææ¶é´" width="100"/> |
| | | <el-table-column prop="workHours" label="工使¶é¿" width="100"> |
| | | <!-- <el-table-column prop="workDate" label="工使¥æ" width="120"/> --> |
| | | <el-table-column prop="workStartTime" label="å¼å§æ¶é´"/> |
| | | <el-table-column prop="workEndTime" label="ç»ææ¶é´"/> |
| | | <el-table-column prop="lunchTime" label="å伿¶é´(h)"> |
| | | <template #default="scope"> |
| | | {{ scope.row.lunchTime }}å°æ¶ |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column prop="workHours" label="工使¶é¿" width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.workHours }}å°æ¶ |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | </el-table-column> --> |
| | | <!-- <el-table-column prop="status" label="ç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusTagType(scope.row.status)"> |
| | | {{ (schedule_status.find(i => i.value === String(scope.row.status)) || {}).label }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="夿³¨" min-width="150"/> |
| | | <el-table-column label="æä½" width="200" fixed="right"> |
| | | </el-table-column> --> |
| | | <!-- <el-table-column prop="remark" label="夿³¨" min-width="150"/> --> |
| | | <el-table-column label="æä½" width="200" fixed="right" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | link |
| | | type="primary" |
| | | @click="openScheduleDialog('edit', scope.row)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | size="small" |
| | | link |
| | | type="danger" |
| | | @click="handleDelete(scope.row)" |
| | | > |
| | | å é¤ |
| | |
| | | label-width="120px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åå·¥å§åï¼" prop="staffId"> |
| | | <el-select v-model="scheduleForm.staffId" placeholder="请è¾å
¥åå·¥å§å" style="width: 100%" |
| | | <el-col :span="24"> |
| | | <el-form-item label="åå·¥å§åï¼" prop="staffIds"> |
| | | <el-select v-model="scheduleForm.staffIds" placeholder="è¯·éæ©åå·¥å§å" style="width: 100%" |
| | | multiple filterable collapse-tags-tooltip |
| | | @change="handleSelectStaff"> |
| | | <el-option v-for="item in personList" :label="item.staffName" :value="item.id" :key="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-option v-for="item in personList" :label="item.nickName" :value="item.userId" :key="item.userId"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å工工å·ï¼" prop="staffNo"> |
| | | <el-input :disabled="true" v-model="scheduleForm.staffNo" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-row> --> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="çæ¬¡ç±»åï¼" prop="shiftType"> |
| | | <el-select v-model="scheduleForm.shiftType" placeholder="è¯·éæ©çæ¬¡ç±»å" style="width: 100%"> |
| | | <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é¨é¨ï¼" prop="department"> |
| | | <el-select v-model="scheduleForm.department" placeholder="è¯·éæ©é¨é¨" style="width: 100%"> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-row> --> |
| | | |
| | | <el-row :gutter="20"> |
| | | <!-- <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="工使¥æï¼" prop="workDate"> |
| | | <el-date-picker |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-row> --> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¶é´ï¼" prop="startTime"> |
| | | <el-form-item label="å¼å§æ¶é´ï¼" prop="workStartTime"> |
| | | <el-time-picker |
| | | v-model="scheduleForm.startTime" |
| | | v-model="scheduleForm.workStartTime" |
| | | placeholder="éæ©å¼å§æ¶é´" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ææ¶é´ï¼" prop="endTime"> |
| | | <el-form-item label="ç»ææ¶é´ï¼" prop="workEndTime"> |
| | | <el-time-picker |
| | | v-model="scheduleForm.endTime" |
| | | v-model="scheduleForm.workEndTime" |
| | | placeholder="éæ©ç»ææ¶é´" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å伿¶é´(h)ï¼" prop="lunchTime"> |
| | | <el-input-number |
| | | v-model="scheduleForm.lunchTime" |
| | | :min="0" |
| | | :max="8" |
| | | :step="0.5" |
| | | placeholder="请è¾å
¥å伿¶é´" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨ï¼" prop="remark"> |
| | | <el-input |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-row> --> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, computed, onMounted, getCurrentInstance} from 'vue' |
| | | import {ref, reactive, computed, onMounted, getCurrentInstance, watch} from 'vue' |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import {useDict} from "@/utils/dict.js" |
| | | import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue' |
| | |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import {listUser} from "@/api/system/user.js"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | |
| | | // çé表å |
| | | const filterForm = reactive({ |
| | | staffName: '', |
| | | shiftType: '', |
| | | dateRange: [], |
| | | current:1, |
| | | size: 10 |
| | | }) |
| | |
| | | // æç表å |
| | | const scheduleForm = reactive({ |
| | | id: '', |
| | | staffId: '', |
| | | staffNo: '', |
| | | department: '', |
| | | staffIds: [], |
| | | // staffNo: '', |
| | | // department: '', |
| | | shiftType: '', |
| | | workDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | // workDate: '', |
| | | workStartTime: '', |
| | | workEndTime: '', |
| | | workHours: 0, |
| | | status: '', |
| | | remark: '' |
| | | lunchTime: 3, |
| | | // workStartTime: '', |
| | | // workEndTime: '', |
| | | // workHours: 0, |
| | | // status: '', |
| | | // remark: '' |
| | | }) |
| | | |
| | | // 表åéªè¯è§å |
| | | const scheduleRules = reactive({ |
| | | staffId: [{required: true, message: 'è¯·éæ©åå·¥', trigger: 'change'}], |
| | | department: [{required: true, message: 'è¯·éæ©é¨é¨', trigger: 'change'}], |
| | | staffIds: [{required: true, message: 'è¯·éæ©åå·¥', trigger: 'change'}], |
| | | // department: [{required: true, message: 'è¯·éæ©é¨é¨', trigger: 'change'}], |
| | | shiftType: [{required: true, message: 'è¯·éæ©çæ¬¡ç±»å', trigger: 'change'}], |
| | | workDate: [{required: true, message: 'è¯·éæ©å·¥ä½æ¥æ', trigger: 'change'}], |
| | | startTime: [{required: true, message: 'è¯·éæ©å¼å§æ¶é´', trigger: 'change'}], |
| | | endTime: [{required: true, message: 'è¯·éæ©ç»ææ¶é´', trigger: 'change'}], |
| | | status: [{required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change'}] |
| | | // workDate: [{required: true, message: 'è¯·éæ©å·¥ä½æ¥æ', trigger: 'change'}], |
| | | workStartTime: [{required: true, message: 'è¯·éæ©å¼å§æ¶é´', trigger: 'change'}], |
| | | workEndTime: [{required: true, message: 'è¯·éæ©ç»ææ¶é´', trigger: 'change'}], |
| | | lunchTime: [{required: true, message: '请è¾å
¥å伿¶é´', trigger: 'blur'}], |
| | | // status: [{required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change'}] |
| | | }) |
| | | const tableLoading = ref(false) |
| | | |
| | |
| | | * è·åå½åå¨è人åå表 |
| | | */ |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | }) |
| | | listUser().then(res => { |
| | | personList.value = res.rows |
| | | }) |
| | | }; |
| | | const paginationChange = (obj) => { |
| | | filterForm.current = obj.page; |
| | |
| | | }; |
| | | |
| | | const handleSelectStaff = (val) => { |
| | | let obj = personList.value.find(item => item.id === val) |
| | | scheduleForm.staffNo = obj.staffNo |
| | | |
| | | // å¤éåå·¥ï¼ä¸åèªå¨è®¾ç½®åå·¥å·¥å· |
| | | // let obj = personList.value.find(item => item.id === val) |
| | | // scheduleForm.staffNo = obj.staffNo |
| | | } |
| | | |
| | | // è·åçæ¬¡æ ç¾ç±»å |
| | |
| | | const handleFilter = async () => { |
| | | tableLoading.value = true |
| | | let searchForm = { |
| | | ...filterForm, |
| | | ...(filterForm.dateRange.length > 0 && { |
| | | startDate: filterForm.dateRange[0], |
| | | endDate: filterForm.dateRange[1], |
| | | }) |
| | | ...filterForm |
| | | } |
| | | let resp = await listPage(searchForm) |
| | | tableCount.value = resp.data.total |
| | | scheduleList.value = resp.data.records.map(it => { |
| | | return { |
| | | ...it, |
| | | 'startTime': dayjs(it.workStartTime).format('HH:mm'), |
| | | 'endTime': dayjs(it.workEndTime).format('HH:mm'), |
| | | // ä¿ååå§æ¶é´æ ¼å¼ç¨äºç¼è¾ |
| | | 'originalWorkStartTime': it.workStartTime, |
| | | 'originalWorkEndTime': it.workEndTime, |
| | | // æ ¼å¼åæ¶é´ç¨äºè¡¨æ ¼æ¾ç¤º |
| | | 'workStartTime': dayjs(it.workStartTime).format('HH:mm'), |
| | | 'workEndTime': dayjs(it.workEndTime).format('HH:mm'), |
| | | } |
| | | }) |
| | | tableLoading.value = false |
| | |
| | | // éç½®çé |
| | | const resetFilter = () => { |
| | | filterForm.staffName = '' |
| | | filterForm.shiftType = '' |
| | | filterForm.dateRange = [] |
| | | } |
| | | |
| | | // æå¼æçå¯¹è¯æ¡ |
| | |
| | | scheduleDialog.value = true |
| | | getPersonList() |
| | | if (type === 'edit' && data) { |
| | | // ç¼è¾æ¨¡å¼ï¼å¤å¶æ°æ® |
| | | Object.assign(scheduleForm, {...data}) |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼é置表å |
| | | Object.keys(scheduleForm).forEach(key => { |
| | | scheduleForm[key] = '' |
| | | // ç¼è¾æ¨¡å¼ï¼å¤å¶æ°æ®ï¼å°åå·¥IDå符串转æ¢ä¸ºæ°ç»æ ¼å¼ï¼å¹¶å¤çæ¶é´å段 |
| | | Object.assign(scheduleForm, { |
| | | ...data, |
| | | lunchTime: Number(data.lunchTime), |
| | | staffIds: data.staffId ? data.staffId.split(',').map(id => parseInt(id)) : [], |
| | | // 使ç¨åå§æ¶é´å符串ï¼å ä¸ºè¡¨æ ¼ä¸æ¾ç¤ºçæ¯æ ¼å¼ååçHH:mm |
| | | workStartTime: data.originalWorkStartTime || '', |
| | | workEndTime: data.originalWorkEndTime || '' |
| | | }) |
| | | // scheduleForm.status = '已宿' |
| | | scheduleForm.workDate = new Date().toISOString().split('T')[0] |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼é置表å |
| | | Object.keys(scheduleForm).forEach(key => { |
| | | if (key === 'staffIds') { |
| | | scheduleForm[key] = [] |
| | | } else if (key === 'lunchTime') { |
| | | scheduleForm[key] = 3 |
| | | } else { |
| | | scheduleForm[key] = '' |
| | | } |
| | | }) |
| | | // scheduleForm.status = '已宿' |
| | | // scheduleForm.workDate = new Date().toISOString().split('T')[0] |
| | | } |
| | | } |
| | | |
| | | // å
³éæçå¯¹è¯æ¡ |
| | |
| | | |
| | | // 计ç®å·¥ä½æ¶é¿ |
| | | const calculateWorkHours = () => { |
| | | if (scheduleForm.workDate && scheduleForm.startTime && scheduleForm.endTime) { |
| | | // ä½¿ç¨ workDate ä¸ startTime å endTime ç»å |
| | | const startDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.startTime}`) |
| | | const endDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.endTime}`) |
| | | if (!scheduleForm.workStartTime || !scheduleForm.workEndTime) { |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | // 使ç¨dayjsæ£ç¡®è§£ææ¶é´ |
| | | const startDayjs = dayjs(scheduleForm.workStartTime); |
| | | const endDayjs = dayjs(scheduleForm.workEndTime); |
| | | |
| | | if (!startDayjs.isValid() || !endDayjs.isValid()) { |
| | | return; |
| | | } |
| | | |
| | | const startDateTime = startDayjs.toDate(); |
| | | const endDateTime = endDayjs.toDate(); |
| | | |
| | | // å¤ç跨天æ
åµï¼ç»ææ¶é´æ©äºå¼å§æ¶é´ï¼ |
| | | if (endDateTime < startDateTime) { |
| | | // 跨天ï¼å°ç»ææ¥æå ä¸å¤© |
| | | endDateTime.setDate(endDateTime.getDate() + 1) |
| | | endDateTime.setDate(endDateTime.getDate() + 1); |
| | | } |
| | | // 计ç®å·¥ä½æ¶é¿ï¼å°æ¶ï¼ |
| | | const diffMs = endDateTime - startDateTime |
| | | const diffHours = diffMs / (1000 * 60 * 60) |
| | | scheduleForm.workHours = Math.round(diffHours * 100) / 100 |
| | | scheduleForm.workStartTime = dayjs(startDateTime).format("YYYY-MM-DD HH:mm:ss") |
| | | scheduleForm.workEndTime = dayjs(endDateTime).format("YYYY-MM-DD HH:mm:ss") |
| | | |
| | | // 计ç®å·¥ä½æ¶é¿ï¼å°æ¶ï¼ |
| | | const diffMs = endDateTime - startDateTime; |
| | | const diffHours = diffMs / (1000 * 60 * 60); |
| | | scheduleForm.workHours = Math.round(diffHours * 100) / 100; |
| | | } catch (error) { |
| | | console.error('æ¶é´è®¡ç®é误:', error); |
| | | } |
| | | } |
| | | |
| | | // ç嬿¶é´å段ååï¼èªå¨è®¡ç®å·¥ä½æ¶é¿ |
| | | watch( |
| | | () => [scheduleForm.workStartTime, scheduleForm.workEndTime], |
| | | () => { |
| | | calculateWorkHours() |
| | | }, |
| | | { deep: true } |
| | | ) |
| | | |
| | | // æäº¤æç表å |
| | | const submitScheduleForm = async () => { |
| | | const valid = await scheduleFormRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | calculateWorkHours() |
| | | const newSchedule = {...scheduleForm} |
| | | // ç±äºåå·¥æ¯å¤éï¼éè¦ä¸ºæ¯ä¸ªéä¸çåå·¥å建æçè®°å½ |
| | | const selectedStaffIds = scheduleForm.staffIds || [] |
| | | |
| | | if (selectedStaffIds.length === 0) { |
| | | ElMessage.warning('请è³å°éæ©ä¸ä¸ªåå·¥') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | // è·åéä¸çåå·¥å§åå表 |
| | | const selectedStaffNames = selectedStaffIds.map(staffId => { |
| | | const staff = personList.value.find(item => item.userId === staffId) |
| | | return staff ? staff.nickName : '' |
| | | }).filter(name => name !== '') |
| | | |
| | | // å°åå·¥å§åç»è£
æéå·åéçå符串 |
| | | const staffNameString = selectedStaffNames.join(',') |
| | | |
| | | // å建æçè®°å½ï¼å°åå·¥å§åä¿å为åç¬¦ä¸²æ ¼å¼ |
| | | const newSchedule = { |
| | | ...scheduleForm, |
| | | staffName: staffNameString, |
| | | staffId: selectedStaffIds.join(','), // å°åå·¥IDä¹ä¿å为éå·åéçå符串 |
| | | // 设置å
¶ä»å¿
è¦å段çé»è®¤å¼ |
| | | staffNo: '', // å¯ä»¥æ ¹æ®éè¦ä»personListä¸è·å |
| | | department: '', |
| | | shiftType: scheduleForm.shiftType, |
| | | workDate: '', |
| | | status: '', |
| | | remark: '' |
| | | } |
| | | |
| | | await save(newSchedule) |
| | | ElMessage.success('ä¿åæçæå') |
| | | |
| | | ElMessage.success(`æå为 ${selectedStaffNames.length} 个åå·¥å建æç`) |
| | | |
| | | handleFilter() |
| | | closeScheduleDialog() |
| | |
| | | // å¯¼åº |
| | | const handleExport = () => { |
| | | let searchForm = { |
| | | ...filterForm, |
| | | ...(filterForm.dateRange.length > 0 && { |
| | | startDate: filterForm.dateRange[0], |
| | | endDate: filterForm.dateRange[1], |
| | | }) |
| | | ...filterForm |
| | | } |
| | | proxy.download('/staff/staffScheduling/export', {}, '人åæç.xlsx') |
| | | } |
| | |
| | | <template> |
| | | <el-dialog :title="modalOptions.title" v-model="visible" width="70%"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseLedgerNo"> |
| | | <el-input v-model="form.purchaseLedgerNo" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼" prop="invoiceNumber"> |
| | | <el-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)ï¼" prop="invoiceAmount"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.invoiceAmount" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | :disabled="true" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="issUer"> |
| | | <el-input |
| | | v-model="form.issUer" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æï¼" prop="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¼ éä»¶"> |
| | | <FileUpload |
| | | :showTip="false" |
| | | accept="*" |
| | | :autoUpload="true" |
| | | :action="action" |
| | | :headers="{ |
| | | <el-dialog :title="modalOptions.title" v-model="visible" width="70%"> |
| | | <el-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="120px" |
| | | label-position="top" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼" prop="purchaseLedgerNo"> |
| | | <el-input v-model="form.purchaseLedgerNo" disabled placeholder="å¤ååæ¹éå¤çï¼å
·ä½ååå·è§äº§åå表ï¼" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="项ç®åç§°ï¼" prop="projectName">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="form.projectName"--> |
| | | <!-- placeholder="èªå¨å¡«å
"--> |
| | | <!-- clearable--> |
| | | <!-- disabled--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼" prop="invoiceNumber"> |
| | | <el-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)ï¼" prop="invoiceAmount"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.invoiceAmount" |
| | | placeholder="请è¾å
¥å票éé¢" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="issUer"> |
| | | <el-input |
| | | v-model="form.issUer" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æï¼" prop="entryDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.entryDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="enterDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.enterDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸ä¼ éä»¶"> |
| | | <FileUpload |
| | | :showTip="false" |
| | | accept="*" |
| | | :autoUpload="true" |
| | | :action="action" |
| | | :headers="{ |
| | | Authorization: 'Bearer ' + getToken(), |
| | | }" |
| | | :limit="10" |
| | | @success="uploadSuccess" |
| | | @remove="removeFile" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="enterDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.enterDate" |
| | | type="date" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼"> </el-form-item> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="columns" |
| | | :tableData="form.productData" |
| | | :summaryMethod="summarizeChildrenTable" |
| | | :isShowSummary="true" |
| | | height="auto" |
| | | > |
| | | <template #ticketsNumRef="{ row }"> |
| | | <el-input-number |
| | | v-model="row.ticketsNum" |
| | | placeholder="请è¾å
¥" |
| | | :min="0" |
| | | :step="0.1" |
| | | :precision="2" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="invoiceNumBlur(row)" |
| | | /> |
| | | </template> |
| | | <template #ticketsAmountRef="{ row }"> |
| | | <el-input-number |
| | | v-model="row.ticketsAmount" |
| | | placeholder="请è¾å
¥" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="0.1" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="invoiceAmountBlur(row)" |
| | | /> |
| | | </template> |
| | | </PIMTable> |
| | | </el-form> |
| | | <template #footer> |
| | | :limit="10" |
| | | @success="uploadSuccess" |
| | | @remove="removeFile" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | </el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼"> </el-form-item> |
| | | <el-table |
| | | :data="form.productData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="æå±åå" prop="purchaseLedgerNo" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-tag type="primary">{{ row.purchaseLedgerNo }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="150" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column label="æ¬æ¬¡å¼ç¥¨æ°" prop="ticketsNum" width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.ticketsNum" |
| | | @change="invoiceNumBlur(scope.row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" |
| | | prop="ticketsAmount" |
| | | width="180" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.ticketsAmount" |
| | | @change="invoiceAmountBlur(scope.row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨æ°" |
| | | prop="futureTickets" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" |
| | | prop="ticketsAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨æ°" |
| | | prop="futureTickets" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªæ¥ç¥¨éé¢(å
)" |
| | | prop="futureTicketsAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" :loading="modalLoading" @click="submitForm"> |
| | | {{ modalOptions.confirmText }} |
| | | 确认 |
| | | </el-button> |
| | | <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import FileUpload from "@/components/Upload/FileUpload.vue"; |
| | | import { |
| | | getPurchaseNoById, |
| | | getInfo, |
| | | addOrUpdateRegistration, |
| | | getPurchaseNoById, |
| | | getInfo, |
| | | addOrUpdateRegistration, |
| | | } from "@/api/procurementManagement/invoiceEntry.js"; |
| | | import { getPurchaseById } from "@/api/procurementManagement/procurementLedger.js"; |
| | | import { getToken } from "@/utils/auth"; |
| | |
| | | import dayjs from "dayjs"; |
| | | |
| | | defineOptions({ |
| | | name: "æ¥ç¥¨ç»è®°æ¨¡ææ¡", |
| | | name: "æ¥ç¥¨ç»è®°æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | |
| | | const formRef = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | const { form } = useFormData({ |
| | | purchaseLedgerNo: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | supplierName: undefined, // ä¾åºååç§° |
| | | projectName: undefined, // 项ç®åç§° |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | invoiceAmount: undefined, // å票éé¢(å
) |
| | | issUerId: userStore.id, // å½å
¥äºº |
| | | issUer: userStore.nickName, // å½å
¥äºº |
| | | entryDate: undefined, // å¼ç¥¨æ¥æ |
| | | salesContractNoId: undefined, // å¼ç¥¨æ¥æ |
| | | enterDate: dayjs().format("YYYY-MM-DD"), |
| | | productData: [], // è¡¨æ ¼ |
| | | tempFileIds: [], // æä»¶ |
| | | purchaseLedgerNo: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | supplierName: undefined, // ä¾åºååç§° |
| | | projectName: undefined, // 项ç®åç§° |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | invoiceAmount: undefined, // å票éé¢(å
) |
| | | issUerId: userStore.id, // å½å
¥äºº |
| | | issUer: userStore.nickName, // å½å
¥äºº |
| | | entryDate: undefined, // å¼ç¥¨æ¥æ |
| | | salesContractNoId: undefined, // å¼ç¥¨æ¥æ |
| | | enterDate: dayjs().format("YYYY-MM-DD"), |
| | | productData: [], // è¡¨æ ¼ |
| | | tempFileIds: [], // æä»¶ |
| | | }); |
| | | |
| | | const selectedContracts = ref([]); // åå¨éä¸çååæ°æ® |
| | | |
| | | const rules = ref({ |
| | | invoiceNumber: [ |
| | | { required: true, message: "请è¾å
¥å票å·", trigger: "blur" }, |
| | | { type: "string" }, |
| | | ], |
| | | invoiceAmount: [ |
| | | { required: true, message: "请è¾å
¥å票éé¢", trigger: "blur" }, |
| | | ], |
| | | entryDate: [{ required: true, message: "è¯·éæ©å¼ç¥¨æ¥æ", trigger: "change" }], |
| | | enterDate: [{ required: true, message: "è¯·éæ©å½å
¥æ¥æ", trigger: "change" }], |
| | | invoiceNumber: [ |
| | | { required: true, message: "请è¾å
¥å票å·", trigger: "blur" }, |
| | | { type: "string" }, |
| | | ], |
| | | invoiceAmount: [ |
| | | { required: true, message: "请è¾å
¥å票éé¢", trigger: "blur" }, |
| | | ], |
| | | entryDate: [{ required: true, message: "è¯·éæ©å¼ç¥¨æ¥æ", trigger: "change" }], |
| | | enterDate: [{ required: true, message: "è¯·éæ©å½å
¥æ¥æ", trigger: "change" }], |
| | | }); |
| | | |
| | | const { |
| | | id, |
| | | visible, |
| | | loading: modalLoading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | id, |
| | | visible, |
| | | loading: modalLoading, |
| | | openModal, |
| | | modalOptions, |
| | | handleConfirm, |
| | | closeModal, |
| | | } = useModal({ |
| | | title: "æ¥ç¥¨ç»è®°", |
| | | title: "æ¥ç¥¨ç»è®°", |
| | | }); |
| | | |
| | | const emit = defineEmits(['refreshList']); |
| | | |
| | | const columns = [ |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | prop: "quantity", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "ç¨ç(%)", |
| | | prop: "taxRate", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "registerDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·(å
)", |
| | | prop: "taxInclusiveUnitPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·(å
)", |
| | | prop: "taxInclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·(å
)", |
| | | prop: "taxExclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨æ°", |
| | | prop: "ticketsNum", |
| | | dataType: "slot", |
| | | slot: "ticketsNumRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨éé¢(å
)", |
| | | prop: "ticketsAmount", |
| | | dataType: "slot", |
| | | slot: "ticketsAmountRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨æ°", |
| | | prop: "futureTickets", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | prop: "quantity", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "ç¨ç(%)", |
| | | prop: "taxRate", |
| | | width: 80, |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "registerDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å«ç¨åä»·(å
)", |
| | | prop: "taxInclusiveUnitPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return val ? parseFloat(val).toFixed(2) : 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å«ç¨æ»ä»·(å
)", |
| | | prop: "taxInclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "ä¸å«ç¨æ»ä»·(å
)", |
| | | prop: "taxExclusiveTotalPrice", |
| | | width: 150, |
| | | formatData: (val) => { |
| | | return parseFloat(val).toFixed(2) ?? 0; |
| | | }, |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨æ°", |
| | | prop: "ticketsNum", |
| | | dataType: "slot", |
| | | slot: "ticketsNumRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æ¬æ¬¡æ¥ç¥¨éé¢(å
)", |
| | | prop: "ticketsAmount", |
| | | dataType: "slot", |
| | | slot: "ticketsAmountRef", |
| | | width: 180, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨æ°", |
| | | prop: "futureTickets", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨éé¢(å
)", |
| | | prop: "futureTicketsAmount", |
| | | }, |
| | | { |
| | | label: "æªæ¥ç¥¨éé¢(å
)", |
| | | prop: "futureTicketsAmount", |
| | | width: 200, |
| | | }, |
| | | }, |
| | | ]; |
| | | |
| | | const getTableData = async (type, id) => { |
| | | if (type == "add") { |
| | | const { data } = await getPurchaseNoById({ id }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.entryDate = data.entryDate; |
| | | form.salesContractNoId = data.salesContractNoId; |
| | | |
| | | const { data: infoData } = await getInfo({ id }); |
| | | form.salesContractNo = infoData.salesContractNo; |
| | | form.projectName = infoData.projectName; |
| | | form.supplierName = infoData.supplierName; |
| | | form.productData = infoData.productData; |
| | | } else if (type == "edit") { |
| | | const data = await getPurchaseById({ id, type: 2 }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.projectName = data.projectName; |
| | | form.supplierName = data.supplierName; |
| | | form.entryDate = data.entryDate; |
| | | form.productData = data.productData; |
| | | } |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue == 0) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } |
| | | if (cellValue) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } else { |
| | | return cellValue; |
| | | } |
| | | }; |
| | | const getTableData = async (type, selectedRows) => { |
| | | if (type == "add") { |
| | | // æ£æ¥ææéæ©çå忝å¦å
·æç¸åçä¾åºååç§° |
| | | const firstRow = selectedRows[0]; |
| | | const isSameSupplier = selectedRows.every(row => |
| | | row.supplierName === firstRow.supplierName |
| | | ); |
| | | |
| | | if (!isSameSupplier) { |
| | | proxy.$modal.msgError("è¯·éæ©ç¸åä¾åºååç§°çåå"); |
| | | return; |
| | | } |
| | | |
| | | // å
许ä¸åçéè´ååå·æ¹éå¤çï¼æ 鿣æ¥éå¤ |
| | | |
| | | // æ¸
ç©ºè¡¨åæ°æ® |
| | | Object.keys(form).forEach(key => { |
| | | if (key !== 'productData') { |
| | | form[key] = undefined; |
| | | } |
| | | }); |
| | | form.productData = []; |
| | | |
| | | // å è½½ææéä¸ååçäº§åæ°æ® |
| | | const promises = selectedRows.map(row => |
| | | getInfo({ id: row.id }) |
| | | ); |
| | | |
| | | Promise.all(promises).then(results => { |
| | | // åå¹¶ææååçäº§åæ°æ®ï¼å¹¶ä¸ºæ¯ä¸ªäº§åæ·»å 对åºçååä¿¡æ¯ |
| | | const allProductData = []; |
| | | results.forEach((result, index) => { |
| | | const contract = selectedRows[index]; |
| | | const contractId = contract.id; |
| | | if (result.data && result.data.productData) { |
| | | result.data.productData.forEach(item => { |
| | | allProductData.push({ |
| | | ...item, |
| | | id: contractId, // æç¡®è®¾ç½®ååID |
| | | purchaseLedgerNo: contract.purchaseContractNumber, // æ·»å éè´ååå· |
| | | supplierName: contract.supplierName, // æ·»å ä¾åºååç§° |
| | | projectName: contract.projectName // æ·»å 项ç®åç§° |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // è®¾ç½®è¡¨åæ°æ®ï¼ä½¿ç¨ç¬¬ä¸ä¸ªååçåºæ¬ä¿¡æ¯ï¼éè´ååå·çç©ºï¼ |
| | | form.purchaseLedgerNo = ""; // éè´ååå·ç空ï¼å 为ä¼å¨äº§åè¡¨æ ¼ä¸å嫿¾ç¤º |
| | | form.invoiceAmount = 0; |
| | | form.invoiceNumber = ""; |
| | | form.entryDate = dayjs().format("YYYY-MM-DD"); |
| | | form.enterDate = dayjs().format("YYYY-MM-DD"); |
| | | form.salesContractNo = results[0].data.salesContractNo; |
| | | form.projectName = results[0].data.projectName; |
| | | form.supplierName = results[0].data.supplierName; |
| | | // ä¿çå½å
¥äººä¿¡æ¯ |
| | | form.issUerId = userStore.id; |
| | | form.issUer = userStore.nickName; |
| | | |
| | | form.productData = allProductData; |
| | | |
| | | // åå¨éä¸çååæ°æ® |
| | | selectedContracts.value = selectedRows; |
| | | }); |
| | | } else if (type == "edit") { |
| | | const id = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows; |
| | | const data = await getPurchaseById({ id, type: 2 }); |
| | | form.purchaseLedgerNo = data.purchaseContractNumber; |
| | | form.invoiceAmount = data.invoiceAmount; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.projectName = data.projectName; |
| | | form.supplierName = data.supplierName; |
| | | form.entryDate = data.entryDate; |
| | | form.productData = data.productData; |
| | | } |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = (param) => { |
| | |
| | | }; |
| | | //æ¬æ¬¡æ¥ç¥¨æ°å¤±ç¦æä½ |
| | | const invoiceNumBlur = (row) => { |
| | | if (!row.ticketsNum || row.ticketsNum === "") { |
| | | row.ticketsNum = 0; |
| | | } |
| | | if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.ticketsNum = 0; |
| | | return; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | if (!row.ticketsNum || row.ticketsNum === "") { |
| | | row.ticketsNum = 0; |
| | | } |
| | | if (Number(row.ticketsNum) > Number(row.tempFutureTickets)) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.ticketsNum = 0; |
| | | return; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨éé¢ |
| | | row.ticketsAmount = (row.ticketsNum * row.taxInclusiveUnitPrice).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | | // æ¬æ¬¡æ¥ç¥¨éé¢å¤±ç¦æä½ |
| | | const invoiceAmountBlur = (row) => { |
| | | if (!row.ticketsAmount) { |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿æ¥ç¥¨æ»éé¢ |
| | | if (row.ticketsAmount > row.tempFutureTicketsAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæªæ¥ç¥¨éé¢"); |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨æ° |
| | | row.ticketsNum = Number( |
| | | (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) |
| | | ); |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | if (!row.ticketsAmount) { |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿æ¥ç¥¨æ»éé¢ |
| | | if (row.ticketsAmount > row.tempFutureTicketsAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæªæ¥ç¥¨éé¢"); |
| | | row.ticketsAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡æ¥ç¥¨æ° |
| | | row.ticketsNum = Number( |
| | | (row.ticketsAmount / row.taxInclusiveUnitPrice).toFixed(2) |
| | | ); |
| | | // è®¡ç®æªæ¥ç¥¨æ° |
| | | row.futureTickets = (row.tempFutureTickets - row.ticketsNum).toFixed(2) |
| | | // è®¡ç®æªæ¥ç¥¨éé¢ |
| | | row.futureTicketsAmount = (row.tempFutureTicketsAmount - row.ticketsAmount).toFixed(2) |
| | | calculateinvoiceAmount(); |
| | | }; |
| | | |
| | | const calculateinvoiceAmount = () => { |
| | | let invoiceAmountTotal = 0; |
| | | form.productData.forEach((item) => { |
| | | if (item.ticketsAmount) { |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | let invoiceAmountTotal = 0; |
| | | form.productData.forEach((item) => { |
| | | if (item.ticketsAmount) { |
| | | invoiceAmountTotal += Number(item.ticketsAmount); |
| | | } |
| | | }); |
| | | form.invoiceAmount = invoiceAmountTotal.toFixed(2); |
| | | }; |
| | | |
| | | const open = (type, eid) => { |
| | | openModal(); |
| | | getTableData(type, eid); |
| | | id.value = eid; |
| | | const open = async (type, selectedRows) => { |
| | | visible.value = true; |
| | | |
| | | // å¦ææ¯æ¹éæä½ï¼è®¾ç½®æ é¢ |
| | | if (Array.isArray(selectedRows) && selectedRows.length > 1) { |
| | | modalOptions.title = `æ¹éæ°å¢ (${selectedRows.length}æ¡)`; |
| | | } else { |
| | | modalOptions.title = type == "add" ? "æ°å¢" : "ç¼è¾"; |
| | | } |
| | | |
| | | // 妿æ¯å个æä½ï¼è·åid |
| | | if (!Array.isArray(selectedRows) || selectedRows.length === 1) { |
| | | const idValue = Array.isArray(selectedRows) ? selectedRows[0].id : selectedRows; |
| | | id.value = idValue; |
| | | } |
| | | |
| | | await getTableData(type, selectedRows); |
| | | }; |
| | | |
| | | const uploadSuccess = (response) => { |
| | | form.tempFileIds.push(response.data.tempId); |
| | | console.log(form); |
| | | form.tempFileIds.push(response.data.tempId); |
| | | console.log(form); |
| | | }; |
| | | |
| | | const removeFile = (file) => { |
| | | const { tempId } = file.response.data; |
| | | form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId); |
| | | const { tempId } = file.response.data; |
| | | form.tempFileIds = form.tempFileIds.filter((item) => item !== tempId); |
| | | }; |
| | | |
| | | const closeAndRefresh = () => { |
| | | closeModal(); |
| | | emit('refreshList'); |
| | | closeModal(); |
| | | emit('refreshList'); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | formRef.value.validate(async (valid, fields) => { |
| | | if (valid) { |
| | | // modalLoading.value = true; |
| | | const { code } = await addOrUpdateRegistration({ |
| | | purchaseLedgerId: id.value, |
| | | purchaseContractNumber: form.purchaseLedgerNo, |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | salesContractNo: form.salesContractNo, |
| | | projectName: form.projectName, |
| | | productData: form.productData, |
| | | issueDate: form.entryDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | salesContractNoId: form.salesContractNoId, |
| | | supplierName: form.supplierName, |
| | | tempFileIds: form.tempFileIds, |
| | | enterDate: form.enterDate, |
| | | type: 4, |
| | | }); |
| | | modalLoading.value = false; |
| | | if (code == 200) { |
| | | closeAndRefresh(); |
| | | } |
| | | } else { |
| | | modalLoading.value = false; |
| | | } |
| | | }); |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | // å¦ææ¯æ¹éæä½ï¼å°ææååçæ°æ®æ¾å¨ä¸ä¸ªæ°ç»éï¼åªè°ç¨ä¸æ¬¡æ¥å£ |
| | | if (selectedContracts.value.length > 1) { |
| | | // å建å
嫿æååæ°æ®çæ°ç» |
| | | const batchData = selectedContracts.value.map(contract => { |
| | | // çéåºå±äºå½åååçäº§åæ°æ® |
| | | const contractProductData = form.productData.filter(item => |
| | | item.id === contract.id |
| | | ); |
| | | |
| | | // 为æ¯ä¸ªéè´ååå建ç¬ç«ç对象 |
| | | return { |
| | | // åºç¡è¡¨åæ°æ® |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | entryDate: form.entryDate, |
| | | enterDate: form.enterDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | tempFileIds: form.tempFileIds, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | purchaseLedgerId: contract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºpurchaseLedgerId |
| | | purchaseContractNumber: contract.purchaseContractNumber, // 使ç¨å®é
çéè´ååå· |
| | | salesContractNo: contract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | supplierName: contract.supplierName, // 使ç¨å®é
çä¾åºååç§° |
| | | projectName: contract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(contractProductData), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: true, |
| | | type: 4 |
| | | }; |
| | | }); |
| | | |
| | | // åªè°ç¨ä¸æ¬¡æ¥å£ï¼ä¼ éå
嫿æååæ°æ®çæ°ç» |
| | | modalLoading.value = true; |
| | | addOrUpdateRegistration(batchData).then((res) => { |
| | | modalLoading.value = false; |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æ¹éç»è®°æå"); |
| | | closeAndRefresh(); |
| | | } |
| | | }).catch(() => { |
| | | modalLoading.value = false; |
| | | proxy.$modal.msgError("æ¹éç»è®°å¤±è´¥"); |
| | | }); |
| | | } else { |
| | | // å个ååæäº¤é»è¾ - 以æ°ç»æ ¼å¼ä¼ é |
| | | const singleContract = selectedContracts.value[0]; |
| | | const singleFormArray = [{ |
| | | // åºç¡è¡¨åæ°æ® |
| | | invoiceNumber: form.invoiceNumber, |
| | | invoiceAmount: form.invoiceAmount, |
| | | entryDate: form.entryDate, |
| | | enterDate: form.enterDate, |
| | | issUerId: form.issUerId, // å½å
¥äººid |
| | | issUer: form.issUer, // å½å
¥äºº |
| | | tempFileIds: form.tempFileIds, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | purchaseLedgerId: singleContract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºpurchaseLedgerId |
| | | purchaseContractNumber: singleContract.purchaseContractNumber, // 使ç¨å®é
çéè´ååå· |
| | | salesContractNo: singleContract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | supplierName: singleContract.supplierName, // 使ç¨å®é
çä¾åºååç§° |
| | | projectName: singleContract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(form.productData), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: false, |
| | | type: 4 |
| | | }]; |
| | | |
| | | modalLoading.value = true; |
| | | addOrUpdateRegistration(singleFormArray).then((res) => { |
| | | modalLoading.value = false; |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("ç»è®°æå"); |
| | | closeAndRefresh(); |
| | | } |
| | | }).catch(() => { |
| | | modalLoading.value = false; |
| | | proxy.$modal.msgError("ç»è®°å¤±è´¥"); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | open, |
| | | closeAndRefresh, |
| | | open, |
| | | closeAndRefresh, |
| | | }); |
| | | </script> |
| | | |
| | |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°"> |
| | | <el-input |
| | | v-model="filters.projectName" |
| | | placeholder="请è¾å
¥é¡¹ç®åç§°" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData"> æç´¢ </el-button> |
| | | <el-button @click="resetFilters"> éç½® </el-button> |
| | |
| | | width:300 |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:400 |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "recorderName", |
| | | }, |
| | |
| | | }; |
| | | |
| | | const handleAdd = (type) => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$modal.msgWarning("请å
éä¸ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | modalRef.value.open(type, selectedRows.value[0].id); |
| | | if (selectedRows.value.length < 1) { |
| | | proxy.$modal.msgWarning("请è³å°éä¸ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | modalRef.value.open(type, selectedRows.value); |
| | | }; |
| | | |
| | | const handleEdit = (type, id) => { |
| | |
| | | size="small" |
| | | @click="changeEditType(scope.row)" |
| | | v-if="!scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-button |
| | |
| | | size="small" |
| | | @click="saveReceiptPayment(scope.row)" |
| | | v-if="scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >ä¿å</el-button |
| | | > |
| | | <el-button |
| | |
| | | type="primary" |
| | | size="small" |
| | | @click="handleDelete(scope.row)" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >å é¤</el-button |
| | | > |
| | | </template> |
| | |
| | | v-model="form.registrant" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | const { form: searchForm } = useFormData({ |
| | | searchText: undefined, |
| | | purchaseContractNumber: undefined, |
| | | paymentDate: [], |
| | | paymentDateStart: undefined, |
| | | paymentDateEnd: undefined, |
| | | // è®¾ç½®ä»æ¬¾æ¥æèå´ä¸ºå½å¤© |
| | | paymentDate: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')], |
| | | paymentDateStart: dayjs().startOf('day').format('YYYY-MM-DD'), |
| | | paymentDateEnd: dayjs().endOf('day').format('YYYY-MM-DD'), |
| | | }); |
| | | |
| | | // æ¥è¯¢å表 |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { paymentDate, ...rest } = searchForm; |
| | | paymentHistoryListPage({ ...rest, ...page }).then((res) => { |
| | | const { total, ...pageParams } = page; |
| | | paymentHistoryListPage({ ...rest, ...pageParams }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | | page.total = res.total; |
| | |
| | | :tableLoading="tableLoadingSon" |
| | | :isShowSummary="isShowSummarySon" |
| | | :summaryMethod="summarizeMainTable1" |
| | | :isShowPage="false" |
| | | height="calc(100vh - 18.5em)" |
| | | height="calc(100vh - 18.5em)" |
| | | > |
| | | <template #payableAmountSlot="{ row }"> |
| | | <el-text type="danger"> |
| | |
| | | </el-text> |
| | | </template> |
| | | </PIMTable> |
| | | <!-- <pagination--> |
| | | <!-- v-show="sonTotal > 0"--> |
| | | <!-- :total="sonTotal"--> |
| | | <!-- @pagination="sonPaginationSearch"--> |
| | | <!-- :layout="page.layout"--> |
| | | <!-- :page="sonPage.current"--> |
| | | <!-- :limit="sonPage.size"--> |
| | | <!-- />--> |
| | | <pagination |
| | | v-show="sonTotal > 0" |
| | | :total="sonTotal" |
| | | @pagination="sonPaginationSearch" |
| | | :layout="page.layout" |
| | | :page="sonPage.current" |
| | | :limit="sonPage.size" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | paymentLedgerList({ |
| | | ...searchForm.value, |
| | | ...page, |
| | | detailPageNum: detailPageNum.value, // æ°å¢ |
| | | detailPageSize: detailPageSize.value, // æ°å¢ |
| | | }).then((res) => { |
| | | let result = res.data; |
| | | tableLoading.value = false; |
| | |
| | | <template> |
| | | <el-form :model="form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-tag size="large">{{ form.purchaseContractNumber }}</el-tag> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼"> |
| | | <el-text>{{ form.salesContractNo }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼"> |
| | | <el-text type="primary">{{ form.taxInclusiveUnitPrice }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´ï¼"> |
| | | <el-text>{{ form.createdAt }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼"> |
| | | <el-input v-model="form.invoiceNumber" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ç¥¨æ°ï¼"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" v-model="form.ticketsNum" @change="inputTicketsNum" :precision="2"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)ï¼"> |
| | | <el-form :model="form"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éè´ååå·ï¼"> |
| | | <el-tag size="large">{{ form.purchaseContractNumber }}</el-tag> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼"> |
| | | <el-text>{{ form.salesContractNo }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼"> |
| | | <el-text type="primary">{{ form.taxInclusiveUnitPrice }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å建æ¶é´ï¼"> |
| | | <el-text>{{ form.createdAt }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ï¼"> |
| | | <el-input v-model="form.invoiceNumber" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ç¥¨æ°ï¼"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" v-model="form.ticketsNum" @change="inputTicketsNum" :precision="2"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)ï¼"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" v-model="form.ticketsAmount" @change="inputTicketsAmount" :precision="2"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æªæ¥ç¥¨æ°ï¼"> |
| | | <el-text type="success">{{ form.futureTickets }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æªæ¥ç¥¨æ°ï¼"> |
| | | <el-text type="success">{{ form.futureTickets }}</el-text> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | defineOptions({ |
| | | name: "æ¥ç¥¨å°è´¦è¡¨å", |
| | | name: "æ¥ç¥¨å°è´¦è¡¨å", |
| | | }); |
| | | const temFutureTickets = ref(0) // åå§æªæ¥ç¥¨æ° |
| | | const initialTicketsNum = ref(0) // åå§æ¥ç¥¨æ° |
| | | const initialTicketsAmount = ref(0) // åå§æ¥ç¥¨éé¢ |
| | | const quantity = ref(0) // æ»æ°é |
| | | const temFutureTickets = ref(0) |
| | | const { form, resetForm } = useFormData({ |
| | | id: undefined, |
| | | purchaseContractNumber: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | createdAt: undefined, // å建æ¶é´ |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | ticketsNum: undefined, // æ¥ç¥¨æ° |
| | | ticketsAmount: undefined, // æ¥ç¥¨éé¢ |
| | | id: undefined, |
| | | purchaseContractNumber: undefined, // éè´ååå· |
| | | salesContractNo: undefined, // éå®ååå· |
| | | createdAt: undefined, // å建æ¶é´ |
| | | invoiceNumber: undefined, // åç¥¨å· |
| | | ticketsNum: undefined, // æ¥ç¥¨æ° |
| | | ticketsAmount: undefined, // æ¥ç¥¨éé¢ |
| | | taxInclusiveUnitPrice: undefined, // å«ç¨åä»· |
| | | ticketRegistrationId: undefined, // å«ç¨åä»· |
| | | }); |
| | | |
| | | const load = async (id) => { |
| | | const { code, data } = await getProductRecordById({ id }); |
| | | if (code === 200) { |
| | | form.id = data.id; |
| | | form.purchaseContractNumber = data.purchaseContractNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.createdAt = data.createdAt; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.ticketsNum = data.ticketsNum; |
| | | form.ticketsAmount = data.ticketsAmount ? Number(data.ticketsAmount).toFixed(2) : 0; |
| | | form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice; |
| | | form.futureTickets = data.futureTickets; |
| | | temFutureTickets.value = data.futureTickets; |
| | | initialTicketsNum.value = data.ticketsNum || 0; |
| | | initialTicketsAmount.value = data.ticketsAmount || 0; |
| | | const { code, data } = await getProductRecordById({ id }); |
| | | if (code === 200) { |
| | | form.id = data.id; |
| | | form.purchaseContractNumber = data.purchaseContractNumber; |
| | | form.salesContractNo = data.salesContractNo; |
| | | form.createdAt = data.createdAt; |
| | | form.invoiceNumber = data.invoiceNumber; |
| | | form.ticketsNum = data.ticketsNum; |
| | | form.ticketsAmount = data.ticketsAmount.toFixed(2); |
| | | form.taxInclusiveUnitPrice = data.taxInclusiveUnitPrice; |
| | | form.futureTickets = data.futureTickets; |
| | | temFutureTickets.value = data.futureTickets; |
| | | form.ticketRegistrationId = data.ticketRegistrationId; |
| | | // è·åæ»æ°éï¼å¦ææ°æ®ä¸æ quantity åæ®µå使ç¨ï¼å¦åä½¿ç¨æ¥ç¥¨æ°+æªæ¥ç¥¨æ° |
| | | quantity.value = data.quantity || (Number(data.ticketsNum || 0) + Number(data.futureTickets || 0)); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const inputTicketsNum = (val) => { |
| | |
| | | proxy.$modal.msgWarning("å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹"); |
| | | return; |
| | | } |
| | | |
| | | const newTicketsNum = Number(form.ticketsNum) || 0; |
| | | const currentTicketsNum = Number(initialTicketsNum.value) || 0; |
| | | |
| | | // è®¡ç®æ°å¢çæ¥ç¥¨æ° |
| | | const addedTicketsNum = newTicketsNum - currentTicketsNum; |
| | | |
| | | // è®¡ç®æ°çæªæ¥ç¥¨æ° = åå§æªæ¥ç¥¨æ° - æ°å¢çæ¥ç¥¨æ° |
| | | const newFutureTickets = Number(temFutureTickets.value) - addedTicketsNum; |
| | | |
| | | // éªè¯ï¼æ°çæ¥ç¥¨æ° + æ°çæªæ¥ç¥¨æ° ⤠quantity |
| | | if (newTicketsNum + newFutureTickets > Number(quantity.value)) { |
| | | proxy.$modal.msgWarning(`æ¥ç¥¨æ°+æªæ¥ç¥¨æ°ä¸è½å¤§äºæ»æ°é(${quantity.value})`); |
| | | // éå¶æ¥ç¥¨æ°ï¼ä½¿å
¶æ»¡è¶³ï¼æ¥ç¥¨æ° + æªæ¥ç¥¨æ° ⤠quantity |
| | | // æå¤§æ¥ç¥¨æ° = quantity - åå§æªæ¥ç¥¨æ° + åå§æ¥ç¥¨æ° |
| | | const maxTicketsNum = Number(quantity.value) - Number(temFutureTickets.value) + Number(initialTicketsNum.value); |
| | | form.ticketsNum = Math.max(0, Math.min(maxTicketsNum, newTicketsNum)); |
| | | // éæ°è®¡ç® |
| | | const recalculatedAddedTicketsNum = Number(form.ticketsNum) - Number(initialTicketsNum.value); |
| | | const recalculatedFutureTickets = Number(temFutureTickets.value) - recalculatedAddedTicketsNum; |
| | | form.futureTickets = Number(recalculatedFutureTickets.toFixed(2)); |
| | | const ticketsAmount = Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice); |
| | | form.ticketsAmount = Number(ticketsAmount.toFixed(2)); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ°å¢çæ¥ç¥¨æ°æ¯å¦å¤§äºåå§æªæ¥ç¥¨æ° |
| | | if (addedTicketsNum > Number(temFutureTickets.value)) { |
| | | proxy.$modal.msgWarning("æ°å¢å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | form.ticketsNum = Number(initialTicketsNum.value) + Number(temFutureTickets.value); |
| | | if (Number(form.ticketsNum) > Number(temFutureTickets.value)) { |
| | | proxy.$modal.msgWarning("å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | form.ticketsNum = temFutureTickets.value |
| | | } |
| | | |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const finalTicketsNum = Number(form.ticketsNum) || 0; |
| | | const finalAddedTicketsNum = finalTicketsNum - Number(initialTicketsNum.value); |
| | | const finalFutureTickets = Number(temFutureTickets.value) - finalAddedTicketsNum; |
| | | const ticketsAmount = finalTicketsNum * Number(form.taxInclusiveUnitPrice); |
| | | form.futureTickets = Number(finalFutureTickets.toFixed(2)); |
| | | const ticketsAmount = Number(form.ticketsNum) * Number(form.taxInclusiveUnitPrice); |
| | | const futureTickets = Number(temFutureTickets.value) - Number(form.ticketsNum); |
| | | form.futureTickets = Number(futureTickets.toFixed(2)); |
| | | form.ticketsAmount = Number(ticketsAmount.toFixed(2)); |
| | | }; |
| | | const inputTicketsAmount = (val) => { |
| | |
| | | return; |
| | | } |
| | | |
| | | const newTicketsAmount = Number(val) || 0; |
| | | |
| | | // è®¡ç®æ°çæ¥ç¥¨æ° |
| | | const newTicketsNum = newTicketsAmount / Number(form.taxInclusiveUnitPrice); |
| | | const currentTicketsNum = Number(initialTicketsNum.value) || 0; |
| | | |
| | | // è®¡ç®æ°å¢çæ¥ç¥¨æ° |
| | | const addedTicketsNum = newTicketsNum - currentTicketsNum; |
| | | |
| | | // è®¡ç®æ°çæªæ¥ç¥¨æ° = åå§æªæ¥ç¥¨æ° - æ°å¢çæ¥ç¥¨æ° |
| | | const newFutureTickets = Number(temFutureTickets.value) - addedTicketsNum; |
| | | |
| | | // éªè¯ï¼æ°çæ¥ç¥¨æ° + æ°çæªæ¥ç¥¨æ° ⤠quantity |
| | | if (newTicketsNum + newFutureTickets > Number(quantity.value)) { |
| | | proxy.$modal.msgWarning(`æ¥ç¥¨æ°+æªæ¥ç¥¨æ°ä¸è½å¤§äºæ»æ°é(${quantity.value})`); |
| | | // éå¶æ¥ç¥¨æ°ï¼ä½¿å
¶æ»¡è¶³ï¼æ¥ç¥¨æ° + æªæ¥ç¥¨æ° ⤠quantity |
| | | const maxTicketsNum = Number(quantity.value) - Number(temFutureTickets.value) + Number(initialTicketsNum.value); |
| | | form.ticketsNum = Math.max(0, Math.min(maxTicketsNum, newTicketsNum)); |
| | | form.ticketsAmount = Number((form.ticketsNum * Number(form.taxInclusiveUnitPrice)).toFixed(2)); |
| | | const recalculatedAddedTicketsNum = Number(form.ticketsNum) - Number(initialTicketsNum.value); |
| | | const recalculatedFutureTickets = Number(temFutureTickets.value) - recalculatedAddedTicketsNum; |
| | | form.futureTickets = Number(recalculatedFutureTickets.toFixed(2)); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ°å¢çæ¥ç¥¨é颿¯å¦å¤§äºåå§æªæ¥ç¥¨æ°å¯¹åºçéé¢ |
| | | const maxAddedAmount = Number(temFutureTickets.value * form.taxInclusiveUnitPrice); |
| | | if (addedTicketsNum > 0 && addedTicketsNum * Number(form.taxInclusiveUnitPrice) > maxAddedAmount) { |
| | | proxy.$modal.msgWarning("æ°å¢æ¥ç¥¨éé¢ä¸å¾å¤§äºæªå¼ç¥¨éé¢"); |
| | | form.ticketsAmount = Number((initialTicketsAmount.value + maxAddedAmount).toFixed(2)); |
| | | form.ticketsNum = Number((currentTicketsNum + Number(temFutureTickets.value)).toFixed(2)); |
| | | form.futureTickets = 0; |
| | | if (Number(val) > Number(form.futureTickets*form.taxInclusiveUnitPrice)) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæ»éé¢"); |
| | | form.ticketsAmount = (form.futureTickets*form.taxInclusiveUnitPrice).toFixed(2) |
| | | const ticketsNum = Number(form.ticketsAmount) / Number(form.taxInclusiveUnitPrice); |
| | | form.ticketsNum = Number(ticketsNum.toFixed(2)) |
| | | return; |
| | | } |
| | | |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const finalTicketsNum = Number(newTicketsNum.toFixed(2)); |
| | | const finalAddedTicketsNum = finalTicketsNum - Number(initialTicketsNum.value); |
| | | const finalFutureTickets = Number(temFutureTickets.value) - finalAddedTicketsNum; |
| | | form.ticketsNum = finalTicketsNum; |
| | | form.futureTickets = Number(finalFutureTickets.toFixed(2)); |
| | | const ticketsNum = Number(val) / Number(form.taxInclusiveUnitPrice); |
| | | form.ticketsNum = Number(ticketsNum.toFixed(2)); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | load, |
| | | form, |
| | | resetForm, |
| | | load, |
| | | form, |
| | | resetForm, |
| | | }); |
| | | </script> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="50%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | <UploadModal ref="uploadModalRef" @uploadSuccess="handleUploadSuccess" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import UploadModal from './Modal/UploadModal.vue' |
| | | import { delCommonFileInvoiceLedger} from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | | const currentId = ref('') |
| | | const { proxy } = getCurrentInstance(); |
| | | const filePreviewRef = ref() |
| | | const uploadModalRef = ref() |
| | | |
| | | const handleClose = () => { |
| | | dialogVisible.value = false |
| | | } |
| | | |
| | | const open = (list, id = '') => { |
| | | dialogVisible.value = true |
| | | tableData.value = list |
| | | currentId.value = id |
| | | } |
| | | |
| | | const handleUpload = () => { |
| | | if (!currentId.value) { |
| | | ElMessage.warning('æ æ³è·åå½åè®°å½IDï¼è¯·å
³éåéæ°æå¼éä»¶çªå£') |
| | | return |
| | | } |
| | | uploadModalRef.value.handleImport(currentId.value) |
| | | } |
| | | |
| | | const handleUploadSuccess = (data) => { |
| | | ElMessage.success('ä¸ä¼ æå') |
| | | // è¿éå¯ä»¥æ·»å å·æ°éä»¶å表çé»è¾ |
| | | // ææ¶å
å
³éä¸ä¼ æ¨¡ææ¡ |
| | | } |
| | | |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.name(row.url); |
| | | } |
| | | |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'å é¤ç¡®è®¤', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }).then(() => { |
| | | delCommonFileInvoiceLedger([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg('已忶å é¤') |
| | | }) |
| | | } |
| | | |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| | |
| | | <el-button link :icon="Files" type="danger"> éä»¶ </el-button> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | | <el-dropdown-item |
| | | v-if="row.commonFiles.length !== 0" |
| | | :icon="Download" |
| | | command="download" |
| | | > |
| | | ä¸è½½ |
| | | </el-dropdown-item> |
| | | <el-dropdown-item :icon="Upload" command="upload"> |
| | | ä¸ä¼ |
| | | </el-dropdown-item> |
| | |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | link |
| | | @click="openEdit(row)" |
| | | :disabled="row.issUerId !== userStore.id" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(row)">éä»¶</el-button> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | :disabled="row.issUerId !== userStore.id" |
| | | link |
| | | @click="handleDelete(row)" |
| | | > |
| | | å é¤ |
| | |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <FileList ref="fileListRef" /> |
| | | <UploadModal ref="modalRef" @uploadSuccess="uploadSuccess"></UploadModal> |
| | | <EditModal ref="editmodalRef" @success="getTableData"></EditModal> |
| | | </div> |
| | |
| | | Search, |
| | | Upload, |
| | | EditPen, |
| | | Delete, |
| | | } from "@element-plus/icons-vue"; |
| | | import { |
| | | delRegistration, |
| | | productRecordPage, |
| | | productUploadFile, |
| | | } from "@/api/procurementManagement/procurementInvoiceLedger.js"; |
| | | import { delCommonFile } from "@/api/publicApi/commonFile.js"; |
| | | import { onMounted } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import UploadModal from "./Modal/UploadModal.vue"; |
| | | import EditModal from "./Modal/EditModal.vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {delInvoiceLedgerByRegProductId} from "@/api/salesManagement/invoiceLedger.js"; |
| | | const userStore = useUserStore(); |
| | | import dayjs from "dayjs"; |
| | | import FileList from "./fileList.vue"; |
| | | |
| | | defineOptions({ |
| | | name: "æ¥ç¥¨å°è´¦", |
| | |
| | | { |
| | | purchaseContractNumber: undefined, // éè´ååå· |
| | | supplierName: undefined, // ä¾åºå |
| | | createdAt: [], // æ¥ç¥¨æ¥æ |
| | | // 设置æ¥ç¥¨æ¥æèå´ä¸ºå½å¤© |
| | | createdAt: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')], // æ¥ç¥¨æ¥æ |
| | | }, |
| | | [ |
| | | { |
| | |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width: 240, |
| | | }, |
| | | { |
| | | label: "ä¾åºååç§°", |
| | |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | width: 150, |
| | | width: 190, |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | |
| | | const handleSelectionChange = (val) => { |
| | | multipleVal.value = val; |
| | | }; |
| | | |
| | | //éä»¶ç¸å
³ |
| | | const fileListRef = ref(null) |
| | | //æ¥çéä»¶ |
| | | const downLoadFile = (row) => { |
| | | fileListRef.value.open(row.commonFiles, row.id) |
| | | } |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | console.log(row.commonFiles); |
| | | openUoload(row.ticketRegistrationId); |
| | | break; |
| | | case "delete": |
| | | // å 餿æéä»¶ |
| | | if (row.commonFiles.length > 0) { |
| | | ElMessageBox.confirm(`确认å é¤è¯¥è®°å½çææéä»¶åï¼`, 'æç¤º', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | // è·åææéä»¶çID |
| | | const fileIds = row.commonFiles.map(file => file.id); |
| | | |
| | | delCommonFile(fileIds).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // å·æ°æ°æ® |
| | | getTableData(); |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | ElMessage.info('已忶å é¤') |
| | | }) |
| | | } |
| | | break; |
| | | } |
| | | }; |
| | | |
| | |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æï¼"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | |
| | | <div class="table_list"> |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <!-- <el-button type="success" @click="openScanAddDialog">æ«ç æ°å¢</el-button> --> |
| | | <el-button type="success" @click="openScanAddDialog">æ«ç æ°å¢</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | |
| | | prop="supplierName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="420" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="ç¾è®¢æ¥æ" |
| | | prop="executionDate" |
| | | width="100" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="仿¬¾æ¹å¼" |
| | | width="100" |
| | |
| | | <el-table-column |
| | | label="å½å
¥äºº" |
| | | prop="recorderName" |
| | | width="100" |
| | | width="120" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | |
| | | <el-table-column |
| | | fixed="right" |
| | | label="æä½" |
| | | min-width="100" |
| | | width="180" |
| | | align="center" |
| | | > |
| | | <template #default="scope"> |
| | |
| | | size="small" |
| | | @click="openForm('edit', scope.row)" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-button |
| | | link |
| | | type="success" |
| | | size="small" |
| | | @click="showQRCode(scope.row)" |
| | | >çæäºç»´ç </el-button |
| | | > |
| | | <el-button |
| | | link |
| | |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable |
| | | @change="salesLedgerChange" |
| | | > |
| | | <el-option |
| | | v-for="item in salesContractList" |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | 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 |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¾è®¢æ¥æï¼" prop="executionDate"> |
| | | <el-date-picker |
| | |
| | | v-model="form.recorderId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | filterable |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | 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" |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="scanForm.projectName" disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ«ç æ¶é´ï¼"> |
| | | <el-input v-model="scanForm.scanTime" disabled /> |
| | |
| | | supplierName: "", // ä¾åºååç§° |
| | | purchaseContractNumber: "", // éè´ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | |
| | | form: { |
| | | purchaseContractNumber: "", |
| | | salesLedgerId: "", |
| | | projectName: "", |
| | | recorderId: "", |
| | | entryDate: "", |
| | | productData: [], |
| | |
| | | purchaseContractNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | projectName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | supplierId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm } = useFormData(data.searchForm); |
| | | const { form: searchForm } = useFormData({ |
| | | ...data.searchForm, |
| | | // 设置å½å
¥æ¥æèå´ä¸ºå½å¤© |
| | | entryDate: [dayjs().startOf('day').format('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')], |
| | | entryDateStart: dayjs().startOf('day').format('YYYY-MM-DD'), |
| | | entryDateEnd: dayjs().endOf('day').format('YYYY-MM-DD') |
| | | }); |
| | | |
| | | // 产å表åå¼¹æ¡æ°æ® |
| | | const productFormVisible = ref(false); |
| | |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | warnNum: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | |
| | | } |
| | | form.value.tempFileIds = tempFileIds; |
| | | form.value.type = 2; |
| | | |
| | | // 妿salesLedgerId为空ï¼åä¸ä¼ ésalesContractNo |
| | | if (!form.value.salesLedgerId) { |
| | | form.value.salesContractNo = '' |
| | | } |
| | | |
| | | addOrEditPurchase(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | |
| | | const getModels = (value) => { |
| | | if (value) { |
| | | productForm.value.productCategory = findNodeById(productOptions.value, value) || ""; |
| | | productForm.value.productId = value; |
| | | modelList({ id: value }).then((res) => { |
| | | modelOptions.value = res; |
| | | }); |
| | |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | // ä¿è¯è³å°ä¿ç䏿¡äº§åä¿¡æ¯ |
| | | const remainingCount = |
| | | productData.value.length - productSelectedRows.value.length; |
| | | if (remainingCount < 1) { |
| | | proxy.$modal.msgWarning("è³å°ä¿ç䏿¡äº§åä¿¡æ¯ï¼æ æ³å
¨é¨å é¤"); |
| | | return; |
| | | } |
| | | if (operationType.value === "add") { |
| | | productSelectedRows.value.forEach((selectedRow) => { |
| | | const index = productData.value.findIndex( |
| | |
| | | delProduct(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | getPurchaseById({ id: currentId.value, type: 2 }).then( |
| | | getSalesLedgerWithProducts({ id: currentId.value, type: 2 }).then( |
| | | (res) => { |
| | | productData.value = res.productData; |
| | | } |
| | |
| | | var index = salesContractList.value.findIndex((item) => item.id == row); |
| | | console.log("index", index); |
| | | if (index > -1) { |
| | | form.value.projectName = salesContractList.value[index].projectName; |
| | | await querygProductInfoByContractNo(); |
| | | } |
| | | }; |
| | |
| | | scanContent: "", |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | contractAmount: "", |
| | | paymentMethod: "", |
| | | recorderName: "", |
| | |
| | | const scanAddRules = { |
| | | purchaseContractNumber: [{ required: true, message: "请è¾å
¥éè´ååå·", trigger: "blur" }], |
| | | supplierName: [{ required: true, message: "请è¾å
¥ä¾åºååç§°", trigger: "blur" }], |
| | | projectName: [{ required: true, message: "请è¾å
¥é¡¹ç®åç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | // æ«ç ç»è®°å¯¹è¯æ¡ç¸å
³åé |
| | |
| | | const scanForm = reactive({ |
| | | purchaseContractNumber: "", |
| | | supplierName: "", |
| | | projectName: "", |
| | | scanTime: "", |
| | | scannerName: "", |
| | | scanStatus: "æªæ«ç ", |
| | |
| | | scanAddForm.scanContent = ""; |
| | | scanAddForm.purchaseContractNumber = ""; |
| | | scanAddForm.supplierName = ""; |
| | | scanAddForm.projectName = ""; |
| | | scanAddForm.contractAmount = ""; |
| | | scanAddForm.paymentMethod = ""; |
| | | scanAddForm.recorderName = userStore.nickName; |
| | |
| | | if (!content) return; |
| | | |
| | | // 模æè§£æäºç»´ç å
容ï¼è¿éå¯ä»¥æ ¹æ®å®é
éæ±è°æ´è§£æé»è¾ |
| | | // å设æ«ç å
å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|项ç®|éé¢|仿¬¾æ¹å¼ |
| | | // å设æ«ç å
å®¹æ ¼å¼ä¸ºï¼ååå·|ä¾åºå|éé¢|仿¬¾æ¹å¼ |
| | | const parts = content.split('|'); |
| | | if (parts.length >= 3) { |
| | | if (parts.length >= 2) { |
| | | scanAddForm.purchaseContractNumber = parts[0] || ""; |
| | | scanAddForm.supplierName = parts[1] || ""; |
| | | scanAddForm.projectName = parts[2] || ""; |
| | | scanAddForm.contractAmount = parts[3] || ""; |
| | | scanAddForm.paymentMethod = parts[4] || ""; |
| | | scanAddForm.contractAmount = parts[2] || ""; |
| | | scanAddForm.paymentMethod = parts[3] || ""; |
| | | } |
| | | }; |
| | | |
| | |
| | | const newData = { |
| | | purchaseContractNumber: scanAddForm.purchaseContractNumber, |
| | | supplierName: scanAddForm.supplierName, |
| | | projectName: scanAddForm.projectName, |
| | | contractAmount: scanAddForm.contractAmount, |
| | | paymentMethod: scanAddForm.paymentMethod, |
| | | recorderName: scanAddForm.recorderName, |
| | |
| | | const openScanDialog = (row) => { |
| | | scanForm.purchaseContractNumber = row.purchaseContractNumber; |
| | | scanForm.supplierName = row.supplierName; |
| | | scanForm.projectName = row.projectName; |
| | | scanForm.scanTime = getCurrentDateTime(); |
| | | scanForm.scannerName = userStore.nickName; |
| | | scanForm.scanStatus = "æªæ«ç "; |
| | |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| | | <style scoped lang="scss"></style> |
| | |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { Document, List, TrendCharts, Shop, Search, Refresh, Download } from '@element-plus/icons-vue' |
| | | import dayjs from "dayjs"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 设置é»è®¤æ¶é´èå´ä¸ºæè¿30天 |
| | | const endDate = new Date() |
| | | const startDate = new Date() |
| | | startDate.setDate(startDate.getDate() - 30) |
| | | |
| | | // 设置é»è®¤æ¶é´èå´ä¸ºå½å¤© |
| | | searchForm.dateRange = [ |
| | | startDate.toISOString().split('T')[0], |
| | | endDate.toISOString().split('T')[0] |
| | | dayjs().startOf('day').format('YYYY-MM-DD'), |
| | | dayjs().endOf('day').format('YYYY-MM-DD') |
| | | ] |
| | | }) |
| | | </script> |
| | |
| | | > |
| | | <el-button type="primary" @click="addRow" style="margin-bottom: 10px;">æ°å¢</el-button> |
| | | <span style="font-size: 18px;margin-left: 10px">å¾
æäº§æ°éï¼{{pendingNum}}</span> |
| | | <!-- <div style="margin-bottom: 10px; margin-left: 10px;">--> |
| | | <!-- <el-form-item label="é¢ç¨ï¼" style="margin-bottom: 0;">--> |
| | | <!-- <el-input v-model="receive" placeholder="请è¾å
¥é¢ç¨" style="width: 200px;" />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </div>--> |
| | | <el-table :data="tableData" border style="width: 100%" :summary-method="summarizeMainTable" show-summary :row-key="row => row.id"> |
| | | <el-table-column label="åºå·" width="60"> |
| | | <el-table-column label="åºå·" width="60" align="center"> |
| | | <template #default="scope"> |
| | | {{ scope.$index + 1 }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å·¥åº" prop="process"> |
| | | <el-table-column label="å·¥åº" prop="process" width="150"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.process" placeholder="请è¾å
¥å·¥åº" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä½" prop="unit"> |
| | | <el-table-column label="产线" prop="productionLine" width="150"> |
| | | <template #default="scope"> |
| | | <el-select |
| | | v-model="scope.row.productionLine" |
| | | placeholder="éæ©äº§çº¿" |
| | | style="width: 100%;" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="line in productionLines" |
| | | :key="line.value" |
| | | :label="line.label" |
| | | :value="line.value" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä½" prop="unit" width="90"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.unit" placeholder="请è¾å
¥åä½" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="å£å³/åå/è§æ ¼" prop="type" width="150"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.type" placeholder="请è¾å
¥" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æäº§æ°é" width="200" prop="schedulingNum"> |
| | |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æäº§æ¥æ" prop="schedulingDate"> |
| | | <el-table-column label="æäº§æ¥æ" prop="schedulingDate" width="200"> |
| | | <template #default="scope"> |
| | | <el-date-picker v-model="scope.row.schedulingDate" type="date" placeholder="éæ©æ¥æ" style="width: 100%;" value-format="YYYY-MM-DD" format="YYYY-MM-DD"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æäº§äºº" prop="schedulingUserId"> |
| | | <el-table-column label="æäº§äºº" prop="schedulingUserId" width="150"> |
| | | <template #default="scope"> |
| | | <el-select |
| | | v-model="scope.row.schedulingUserId" |
| | | placeholder="éæ©äººå" |
| | | style="width: 100%;" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | |
| | | :value="user.userId" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="夿³¨" prop="remark" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.remark" placeholder="请è¾å
¥å¤æ³¨" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="80"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {ref, getCurrentInstance} from "vue"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {processScheduling} from "@/api/productionManagement/operationScheduling.js"; |
| | | const { proxy } = getCurrentInstance() |
| | |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const tableData = ref([ |
| | | { process: '', schedulingDate: '', schedulingNum: '', schedulingUserId: '', workHours: '', unit: '' } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const unitFromRow = ref(''); |
| | | const idFromRow = ref(''); |
| | | const pendingNum = ref(''); |
| | | const specificationModelFromRow = ref(''); |
| | | const pendingNum = ref(0); |
| | | const userList = ref([]) |
| | | const receive = ref('') |
| | | const sunqianUserId = ref('') |
| | | // 产线é项 |
| | | const productionLines = ref([ |
| | | { label: '产线1', value: '产线1' }, |
| | | { label: '产线2', value: '产线2' }, |
| | | { label: '产线3', value: '产线3' }, |
| | | { label: '产线4', value: '产线4' } |
| | | ]) |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | pendingNum.value = row?.pendingNum ?? 0; |
| | | unitFromRow.value = row?.unit ?? ''; |
| | | idFromRow.value = row?.id ?? ''; |
| | | specificationModelFromRow.value = row?.specificationModel ?? ''; |
| | | |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | // æ¾å°åå©çç¨æ·ID并设置为é»è®¤å¼ |
| | | const sunqianUser = userList.value.find(user => user.nickName === 'åå©'); |
| | | if (sunqianUser) { |
| | | sunqianUserId.value = sunqianUser.userId; |
| | | } |
| | | // å¨ç¨æ·å表å è½½å®æååå»ºè¡æ°æ®ï¼å¹¶å°äº§çº¿æ°æ®å¸¦å
¥ |
| | | tableData.value = [createRow(row)]; |
| | | }); |
| | | pendingNum.value = row.pendingNum |
| | | if (row && row.unit !== undefined) { |
| | | unitFromRow.value = row.unit; |
| | | idFromRow.value = row.id; |
| | | tableData.value.forEach(item => { |
| | | item.unit = row.unit; |
| | | item.id = row.id; |
| | | }); |
| | | } else { |
| | | unitFromRow.value = ''; |
| | | } |
| | | } |
| | | |
| | | const createRow = (row) => ({ |
| | | id: idFromRow.value, |
| | | process: 'å
è£
', |
| | | schedulingDate: '', |
| | | schedulingNum: null, |
| | | schedulingUserId: sunqianUserId.value, // é»è®¤è®¾ç½®ä¸ºåå©çç¨æ·ID |
| | | workHours: null, |
| | | unit: unitFromRow.value, |
| | | remark: '', |
| | | type: specificationModelFromRow.value, |
| | | productionLine: row?.productionLine ?? '', // ä»è¡æ°æ®ä¸è·åäº§çº¿ä¿¡æ¯ |
| | | }); |
| | | |
| | | const submitForm = () => { |
| | | // 1. æ£æ¥æ¯ä¸è¡æ¯å¦å¡«å宿´ |
| | | for (let i = 0; i < tableData.value.length; i++) { |
| | |
| | | row.schedulingNum === '' || row.schedulingNum === null || |
| | | !row.schedulingUserId || |
| | | row.workHours === '' || row.workHours === null || |
| | | !row.unit |
| | | !row.unit || |
| | | !row.productionLine |
| | | ) { |
| | | proxy.$modal.msgError(`第${i + 1}è¡æ°æ®æªå¡«å宿´`); |
| | | return; |
| | |
| | | proxy.$modal.msgError('æäº§æ°éå计ä¸è½è¶
è¿å¾
æäº§æ°é'); |
| | | return; |
| | | } |
| | | processScheduling(tableData.value).then((res) => { |
| | | // 3. å° receive åæ®µæ·»å å°æ¯æ¡æ°æ®ä¸ï¼å¹¶ç§»é¤ loss åæ®µ |
| | | const submitData = tableData.value.map(row => { |
| | | const { loss, ...rest } = row; |
| | | return { |
| | | ...rest, |
| | | receive: receive.value |
| | | }; |
| | | }); |
| | | processScheduling(submitData).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | }) |
| | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false; |
| | | receive.value = ''; |
| | | tableData.value = []; |
| | | unitFromRow.value = ''; |
| | | idFromRow.value = ''; |
| | | specificationModelFromRow.value = ''; |
| | | pendingNum.value = 0; |
| | | emit('close') |
| | | }; |
| | | defineExpose({ |
| | |
| | | }); |
| | | |
| | | const addRow = () => { |
| | | tableData.value.push({ id: idFromRow.value, process: '', unit: unitFromRow.value, schedulingNum: '', workHours: '', schedulingDate: '', schedulingUserId: '' }); |
| | | tableData.value.push(createRow()); |
| | | }; |
| | | const removeRow = (index) => { |
| | | tableData.value.splice(index, 1); |
| | |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°:"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | <el-form-item label="ååå·:"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <!-- <el-form-item label="项ç®åç§°:">--> |
| | | <!-- <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search"--> |
| | | <!-- style="width: 200px;"--> |
| | | <!-- @change="handleQuery" />--> |
| | | <!-- </el-form-item>--> |
| | | <el-form-item label="æ´¾å·¥æ¥æ:"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | staffName: "", |
| | | customerName: "", |
| | | salesContractNo: "", |
| | | status: 1, |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½å
¥æ¥æï¼é»è®¤å½å¤© |
| | | entryDateStart: dayjs().format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().format("YYYY-MM-DD"), |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | |
| | | prop: "salesContractNo", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width: 200, |
| | | }, |
| | | // { |
| | | // label: "客æ·ååå·", |
| | | // prop: "customerContractNo", |
| | | // width: 200, |
| | | // }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:300 |
| | | }, |
| | | // { |
| | | // label: "项ç®åç§°", |
| | | // prop: "projectName", |
| | | // width:300 |
| | | // }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ç»å®æºå¨", |
| | | prop: "speculativeTradingName", |
| | | width: 220, |
| | | }, |
| | | // { |
| | | // label: "产线", |
| | | // prop: "productionLine", |
| | | // width: 220, |
| | | // }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="ç¼è¾å·¥èºè·¯çº¿" |
| | | width="400" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-tree-select |
| | | v-model="formState.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-select |
| | | v-model="formState.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in productModelsOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="description"> |
| | | <el-input v-model="formState.description" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance, onMounted} from "vue"; |
| | | import {update} from "@/api/productionManagement/processRoute.js"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | |
| | | record: { |
| | | type: Object, |
| | | required: true, |
| | | } |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({}); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | const productModelsOptions = ref([]) |
| | | const productOptions = ref([]) |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const setFormData = () => { |
| | | formState.value = props.record |
| | | } |
| | | |
| | | const getProductOptions = () => { |
| | | productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | const getModels = (value) => { |
| | | formState.value.productModelId = undefined; |
| | | productModelsOptions.value = []; |
| | | if (value) { |
| | | modelList({ id: value }).then((res) => { |
| | | productModelsOptions.value = res; |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | update(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | |
| | | |
| | | onMounted(() => { |
| | | getProductOptions() |
| | | getModels(props.record.productId) |
| | | nextTick(() => { |
| | | setFormData() |
| | | }); |
| | | }) |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="å·¥èºè·¯çº¿é¡¹ç®" |
| | | width="800px" |
| | | @close="closeModal" |
| | | > |
| | | <div class="operate-button"> |
| | | <el-button |
| | | type="primary" |
| | | @click="isShowProductSelectDialog = true" |
| | | class="mb5" |
| | | style="margin-bottom: 10px;" |
| | | > |
| | | éæ©äº§å |
| | | </el-button> |
| | | |
| | | <el-switch |
| | | v-model="isTable" |
| | | inline-prompt |
| | | active-text="è¡¨æ ¼" |
| | | inactive-text="å表" |
| | | @change="handleViewChange" |
| | | /> |
| | | </div> |
| | | |
| | | <el-table |
| | | v-if="isTable" |
| | | ref="multipleTable" |
| | | v-loading="tableLoading" |
| | | border |
| | | :data="routeItems" |
| | | :header-cell-style="{ background: '#F0F1F5', color: '#333333' }" |
| | | row-key="id" |
| | | tooltip-effect="dark" |
| | | class="lims-table" |
| | | style="cursor: move;" |
| | | > |
| | | <el-table-column align="center" label="åºå·" width="60"> |
| | | <template #default="scope"> |
| | | {{ scope.$index + 1 }} |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column |
| | | v-for="(item, index) in tableColumn" |
| | | :key="index" |
| | | :label="item.label" |
| | | :width="item.width" |
| | | show-overflow-tooltip |
| | | > |
| | | <template #default="scope" v-if="item.dataType === 'action'"> |
| | | <el-button |
| | | v-for="(op, opIndex) in item.operation" |
| | | :key="opIndex" |
| | | :type="op.type" |
| | | :link="op.link" |
| | | size="small" |
| | | @click.stop="op.clickFun(scope.row)" |
| | | > |
| | | {{ op.name }} |
| | | </el-button> |
| | | </template> |
| | | |
| | | <template #default="scope" v-else> |
| | | <template v-if="item.prop === 'processId'"> |
| | | <el-select |
| | | v-model="scope.row[item.prop]" |
| | | style="width: 100%;" |
| | | @mousedown.stop |
| | | > |
| | | <el-option |
| | | v-for="process in processOptions" |
| | | :key="process.id" |
| | | :label="process.name" |
| | | :value="process.id" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | <template v-else> |
| | | {{ scope.row[item.prop] || '-' }} |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <!-- ä½¿ç¨æ®édivæ¿ä»£el-steps --> |
| | | <div |
| | | v-else |
| | | ref="stepsContainer" |
| | | class="mb5 custom-steps" |
| | | style="padding: 10px 0; display: flex; flex-wrap: nowrap; gap: 20px; align-items: flex-start;" |
| | | > |
| | | <div |
| | | v-for="(item, index) in routeItems" |
| | | :key="item.id" |
| | | class="custom-step draggable-step" |
| | | :data-id="item.id" |
| | | style="cursor: move; flex: 0 0 auto; min-width: 220px;" |
| | | > |
| | | <div class="step-content"> |
| | | <div class="step-number">{{ index + 1 }}</div> |
| | | <el-card |
| | | :header="item.productName" |
| | | class="step-card" |
| | | style="cursor: move;" |
| | | > |
| | | <div class="step-card-content"> |
| | | <p>{{ item.model }}</p> |
| | | <p>{{ item.unit }}</p> |
| | | <el-select |
| | | v-model="item.processId" |
| | | style="width: 100%;" |
| | | @mousedown.stop |
| | | > |
| | | <el-option |
| | | v-for="process in processOptions" |
| | | :key="process.id" |
| | | :label="process.name" |
| | | :value="process.id" |
| | | /> |
| | | </el-select> |
| | | </div> |
| | | <template #footer> |
| | | <div class="step-card-footer"> |
| | | <el-button type="danger" link size="small" @click.stop="removeItemByID(item.id)">å é¤</el-button> |
| | | </div> |
| | | </template> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <ProductSelectDialog |
| | | v-model="isShowProductSelectDialog" |
| | | @confirm="handelSelectProducts" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, getCurrentInstance, onMounted, onUnmounted, nextTick } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { findProcessRouteItemList, addOrUpdateProcessRouteItem } from "@/api/productionManagement/processRouteItem.js"; |
| | | import { processList } from "@/api/productionManagement/productionProcess.js"; |
| | | import Sortable from 'sortablejs'; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | default: false |
| | | }, |
| | | record: { |
| | | type: Object, |
| | | required: true, |
| | | default: () => ({}) |
| | | } |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | const processOptions = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowProductSelectDialog = ref(false); |
| | | const routeItems = ref([]); |
| | | let tableSortable = null; |
| | | let stepsSortable = null; |
| | | const multipleTable = ref(null); |
| | | const stepsContainer = ref(null); |
| | | const isTable = ref(true); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | } |
| | | }); |
| | | |
| | | const tableColumn = ref([ |
| | | { label: "产ååç§°", prop: "productName", width: 180 }, |
| | | { label: "è§æ ¼åç§°", prop: "model", width: 150 }, |
| | | { label: "åä½", prop: "unit", width: 80 }, |
| | | { label: "å·¥åºåç§°", prop: "processId", width: 180 }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 100, |
| | | operation: [ |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | clickFun: (row) => { |
| | | const idx = routeItems.value.findIndex(item => item.id === row.id); |
| | | if (idx > -1) { |
| | | removeItem(idx) |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | |
| | | const removeItem = (index) => { |
| | | routeItems.value.splice(index, 1); |
| | | nextTick(() => initSortable()); |
| | | }; |
| | | |
| | | const removeItemByID = (id) => { |
| | | const idx = routeItems.value.findIndex(item => item.id === id); |
| | | if (idx > -1) { |
| | | routeItems.value.splice(idx, 1); |
| | | nextTick(() => initSortable()); |
| | | } |
| | | }; |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const handelSelectProducts = (products) => { |
| | | destroySortable(); |
| | | |
| | | const newData = products.map(({ id, ...product }) => ({ |
| | | ...product, |
| | | productModelId: id, |
| | | routeId: props.record.id, |
| | | id: `${Date.now()}-${Math.random().toString(36).slice(2)}`, |
| | | processId: undefined |
| | | })); |
| | | |
| | | console.log('éæ©äº§ååæ°ç»:', routeItems.value); |
| | | routeItems.value.push(...newData); |
| | | routeItems.value = [...routeItems.value]; |
| | | console.log('éæ©äº§ååæ°ç»:', routeItems.value); |
| | | |
| | | // å»¶è¿åå§åï¼ç¡®ä¿DOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | // 强å¶éæ°æ¸²æç»ä»¶ |
| | | if (proxy?.$forceUpdate) { |
| | | proxy.$forceUpdate(); |
| | | } |
| | | |
| | | const temp = [...routeItems.value]; |
| | | routeItems.value = []; |
| | | nextTick(() => { |
| | | routeItems.value = temp; |
| | | initSortable(); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const findProcessRouteItems = () => { |
| | | tableLoading.value = true; |
| | | findProcessRouteItemList({ routeId: props.record.id }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | routeItems.value = res.data.map(item => ({ |
| | | ...item, |
| | | processId: item.processId === 0 ? undefined : item.processId |
| | | })); |
| | | // å»¶è¿åå§åï¼ç¡®ä¿DOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | setTimeout(() => initSortable(), 100); |
| | | }); |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | console.error("è·åå表失败ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | const findProcessList = () => { |
| | | processList({}) |
| | | .then(res => { |
| | | processOptions.value = res.data; |
| | | }) |
| | | .catch(err => { |
| | | console.error("è·åå·¥åºå¤±è´¥ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | const { proxy } = getCurrentInstance() || {}; |
| | | |
| | | const handleSubmit = () => { |
| | | const hasEmptyProcess = routeItems.value.some(item => !item.processId); |
| | | if (hasEmptyProcess) { |
| | | proxy?.$modal?.msgError("请为ææé¡¹ç®éæ©å·¥åº"); |
| | | return; |
| | | } |
| | | |
| | | addOrUpdateProcessRouteItem({ |
| | | routeId: props.record.id, |
| | | processRouteItem: routeItems.value.map(({ id, ...item }) => item) |
| | | }) |
| | | .then(res => { |
| | | isShow.value = false; |
| | | emit('completed'); |
| | | proxy?.$modal?.msgSuccess("æäº¤æå"); |
| | | }) |
| | | .catch(err => { |
| | | proxy?.$modal?.msgError(`æäº¤å¤±è´¥ï¼${err.msg || "ç½ç»å¼å¸¸"}`); |
| | | }); |
| | | }; |
| | | |
| | | const destroySortable = () => { |
| | | if (tableSortable) { |
| | | tableSortable.destroy(); |
| | | tableSortable = null; |
| | | } |
| | | if (stepsSortable) { |
| | | stepsSortable.destroy(); |
| | | stepsSortable = null; |
| | | } |
| | | }; |
| | | |
| | | const initSortable = () => { |
| | | destroySortable(); |
| | | |
| | | if (isTable.value) { |
| | | if (!multipleTable.value) return; |
| | | const tbody = multipleTable.value.$el.querySelector('.el-table__body tbody') || |
| | | multipleTable.value.$el.querySelector('.el-table__body-wrapper > table > tbody'); |
| | | if (!tbody) return; |
| | | |
| | | tableSortable = new Sortable(tbody, { |
| | | animation: 150, |
| | | ghostClass: 'sortable-ghost', |
| | | handle: '.el-table__row', |
| | | filter: '.el-button, .el-select', |
| | | onEnd: (evt) => { |
| | | if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) return; |
| | | |
| | | // ä½¿ç¨æ°ç» splice æ¹æ³éæ°æåºï¼ä¸è¡¨æ ¼æ¨¡å¼ä¿æä¸è´ |
| | | const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0]; |
| | | routeItems.value.splice(evt.newIndex, 0, moveItem); |
| | | routeItems.value = [...routeItems.value]; |
| | | console.log('æåºåæ°ç»:', routeItems.value); |
| | | } |
| | | }); |
| | | } else { |
| | | if (!stepsContainer.value) return; |
| | | |
| | | // ä¿®æ¹ï¼ç´æ¥ä½¿ç¨stepsContainer.valueä½ä¸ºææ½å®¹å¨ |
| | | const stepsList = stepsContainer.value; |
| | | if (!stepsList) { |
| | | console.warn('æªæ¾å°æ¥éª¤æ¡ææ½å®¹å¨'); |
| | | return; |
| | | } |
| | | |
| | | // ä¿®æ¹ï¼ç®åææ½é
ç½® |
| | | stepsSortable = new Sortable(stepsList, { |
| | | animation: 150, |
| | | ghostClass: 'sortable-ghost', |
| | | draggable: '.draggable-step', // 坿æ½å
ç´ |
| | | handle: '.draggable-step, .step-card', // ææ½ææ |
| | | filter: '.el-button, .el-select, .el-input', // è¿æ»¤æé®/éæ©å¨ |
| | | forceFallback: true, |
| | | fallbackClass: 'sortable-fallback', |
| | | preventOnFilter: true, |
| | | scroll: true, |
| | | scrollSensitivity: 30, |
| | | scrollSpeed: 10, |
| | | bubbleScroll: true, |
| | | onEnd: (evt) => { |
| | | if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) return; |
| | | |
| | | // ä½¿ç¨æ°ç» splice æ¹æ³éæ°æåº |
| | | const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0]; |
| | | routeItems.value.splice(evt.newIndex, 0, moveItem); |
| | | routeItems.value = [...routeItems.value]; |
| | | } |
| | | }); |
| | | |
| | | // è°è¯ï¼æå°å®¹å¨åå®ä¾ï¼ç¡®è®¤ç»å®æå |
| | | console.log('æ¥éª¤æ¡ææ½å®¹å¨:', stepsList); |
| | | console.log('Sortableå®ä¾:', stepsSortable); |
| | | } |
| | | }; |
| | | |
| | | const handleViewChange = () => { |
| | | destroySortable(); |
| | | // å»¶è¿åå§åï¼ç¡®ä¿è§å¾åæ¢åDOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | setTimeout(() => initSortable(), 100); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | findProcessRouteItems(); |
| | | findProcessList(); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | destroySortable(); |
| | | }); |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.sortable-ghost) { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa !important; |
| | | } |
| | | |
| | | :deep(.el-table__row) { |
| | | transition: background-color 0.2s; |
| | | } |
| | | |
| | | :deep(.el-table__row:hover) { |
| | | background-color: #f9fafc !important; |
| | | } |
| | | |
| | | :deep(.el-card__footer){ |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | .operate-button { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | /* ä¿®æ¹ï¼èªå®ä¹æ¥éª¤æ¡å®¹å¨æ ·å¼ */ |
| | | .custom-steps { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: flex-start; |
| | | gap: 20px; |
| | | min-height: 100px; |
| | | } |
| | | |
| | | /* ä¿®æ¹ï¼èªå®ä¹æ¥éª¤é¡¹æ ·å¼ */ |
| | | .custom-step { |
| | | cursor: move !important; |
| | | padding: 8px; |
| | | position: relative; |
| | | transition: all 0.2s ease; |
| | | flex: 0 0 auto; |
| | | min-width: 220px; |
| | | touch-action: none; |
| | | } |
| | | |
| | | /* ææ½æ¬æµ®æ ·å¼ï¼æç¤ºå¯ææ½ */ |
| | | .custom-step:hover { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .sortable-ghost { |
| | | opacity: 0.4; |
| | | background-color: #f5f7fa !important; |
| | | border: 2px dashed #409eff; |
| | | margin: 10px; |
| | | transform: scale(1.02); |
| | | } |
| | | |
| | | .sortable-fallback { |
| | | opacity: 0.9; |
| | | background-color: #f5f7fa; |
| | | border: 1px solid #409eff; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | transform: rotate(2deg); |
| | | margin: 10px; |
| | | } |
| | | |
| | | .step-card { |
| | | cursor: move !important; |
| | | transition: box-shadow 0.2s ease; |
| | | user-select: none; |
| | | -webkit-user-select: none; |
| | | pointer-events: auto; |
| | | margin: 10px; |
| | | height: 240px; |
| | | } |
| | | |
| | | .step-card:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .step-content { |
| | | width: 220px; |
| | | user-select: none; |
| | | } |
| | | |
| | | .step-card-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .step-card-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | padding: 10px; |
| | | } |
| | | |
| | | /* èªå®ä¹åºå·æ ·å¼ä¼å */ |
| | | .step-number { |
| | | font-weight: bold; |
| | | text-align: center; |
| | | width: 36px; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | margin: 0 auto 10px; |
| | | background: #409eff; |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | font-size: 14px; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢å·¥èºè·¯çº¿" |
| | | width="400" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item label="产å大类ï¼" prop="productId"> |
| | | <el-tree-select |
| | | v-model="formState.productId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | check-strictly |
| | | @change="getModels" |
| | | :data="productOptions" |
| | | :render-after-expand="false" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-select |
| | | v-model="formState.productModelId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="item in productModelsOptions" |
| | | :key="item.id" |
| | | :label="item.model" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="夿³¨" prop="description"> |
| | | <el-input v-model="formState.description" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, getCurrentInstance, onMounted} from "vue"; |
| | | import {add} from "@/api/productionManagement/processRoute.js"; |
| | | import {modelList, productTreeList} from "@/api/basicData/product.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | productId: undefined, |
| | | productModelId: undefined, |
| | | description: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const productModelsOptions = ref([]) |
| | | const productOptions = ref([]) |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const getProductOptions = () => { |
| | | productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res); |
| | | }); |
| | | }; |
| | | const getModels = (value) => { |
| | | formState.value.productId = undefined; |
| | | formState.value.productModelId = undefined; |
| | | productModelsOptions.value = []; |
| | | |
| | | if (value) { |
| | | formState.value.productId = findNodeById(productOptions.value, value) || undefined; |
| | | modelList({ id: value }).then((res) => { |
| | | productModelsOptions.value = res; |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const findNodeById = (nodes, productId) => { |
| | | for (let i = 0; i < nodes.length; i++) { |
| | | if (nodes[i].value === productId) { |
| | | return nodes[i].label; // æ¾å°èç¹ï¼è¿å该èç¹çlabel |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const foundNode = findNodeById(nodes[i].children, productId); |
| | | if (foundNode) { |
| | | return foundNode; // å¨åèç¹ä¸æ¾å°ï¼ç´æ¥è¿åï¼å·²ç»æ¯labelåç¬¦ä¸²ï¼ |
| | | } |
| | | } |
| | | } |
| | | return null; // æ²¡ææ¾å°èç¹ï¼è¿ånull |
| | | }; |
| | | |
| | | function convertIdToValue(data) { |
| | | return data.map((item) => { |
| | | const { id, children, ...rest } = item; |
| | | const newItem = { |
| | | ...rest, |
| | | value: id, // å° id æ¹ä¸º value |
| | | }; |
| | | if (children && children.length > 0) { |
| | | newItem.children = convertIdToValue(children); |
| | | } |
| | | |
| | | return newItem; |
| | | }); |
| | | } |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | add(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getProductOptions() |
| | | }) |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="è§æ ¼åç§°:"> |
| | | <el-input v-model="searchForm.model" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" class="mb10"> |
| | | <el-button type="primary" @click="showNewModal">æ°å¢å·¥èºè·¯çº¿</el-button> |
| | | <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>å é¤å·¥èºè·¯çº¿</el-button> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | /> |
| | | </div> |
| | | <new-process |
| | | v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <edit-process |
| | | v-if="isShowEditModal" |
| | | v-model:visible="isShowEditModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <route-item-form |
| | | v-if="isShowItemModal" |
| | | v-model:visible="isShowItemModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import NewProcess from "@/views/productionManagement/processRoute/New.vue"; |
| | | import EditProcess from "@/views/productionManagement/processRoute/Edit.vue"; |
| | | import RouteItemForm from "@/views/productionManagement/processRoute/ItemsForm.vue"; |
| | | import {listPage, del} from "@/api/productionManagement/processRoute.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | model: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åç§°", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "æè¿°", |
| | | prop: "description", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showEditModal(row); |
| | | } |
| | | }, |
| | | { |
| | | name: "路线项ç®", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showItemModal(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowNewModal = ref(false); |
| | | const isShowEditModal = ref(false); |
| | | const isShowItemModal = ref(false); |
| | | const record = ref({}); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | listPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢å¼¹æ¡ |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true |
| | | }; |
| | | |
| | | const showEditModal = (row) => { |
| | | isShowEditModal.value = true |
| | | record.value = row |
| | | }; |
| | | |
| | | const showItemModal = (row) => { |
| | | isShowItemModal.value = true |
| | | record.value = row |
| | | }; |
| | | |
| | | // å é¤ |
| | | function handleDelete() { |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | proxy.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤å·²å¾éçæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog |
| | | v-model="visible" |
| | | title="ç»æ" |
| | | width="1200" |
| | | close-on-click-modal |
| | | @close="visible = false" |
| | | > |
| | | <el-button |
| | | v-if="dataValue.isEdit" |
| | | type="primary" |
| | | @click="addItem" |
| | | style="margin-bottom: 10px" |
| | | >æ·»å |
| | | </el-button> |
| | | <el-button |
| | | v-if="!dataValue.isEdit" |
| | | type="primary" |
| | | @click="dataValue.isEdit = true" |
| | | style="margin-bottom: 10px" |
| | | >ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | v-if="dataValue.isEdit" |
| | | type="primary" |
| | | @click="cancelEdit" |
| | | style="margin-bottom: 10px" |
| | | >åæ¶ |
| | | </el-button> |
| | | <el-form |
| | | ref="form" |
| | | :model="dataValue" |
| | | > |
| | | <el-table :data="dataValue.dataList" style="width: 100%"> |
| | | <el-table-column prop="productName" label="产å" width="150"/> |
| | | <el-table-column prop="model" label="è§æ ¼" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | v-if="dataValue.isEdit" |
| | | :prop="`dataList.${$index}.model`" |
| | | :rules="[{ required: true, message: 'è¯·éæ©è§æ ¼', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-select |
| | | v-model="row.model" |
| | | placeholder="è¯·éæ©äº§å" |
| | | clearable |
| | | :disabled="!dataValue.isEdit" |
| | | style="width: 100%" |
| | | @visible-change="(v) => { if (v) openDialog($index) }" |
| | | > |
| | | <el-option v-if="row.model" :label="row.model" :value="row.model" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="processId" label="æ¶èå·¥åº" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.processId`" |
| | | :rules="[{ required: true, message: 'è¯·éæ©æ¶èå·¥åº', trigger: 'change' }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-select |
| | | v-model="row.processId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | > |
| | | <el-option |
| | | v-for="item in dataValue.processOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="unitQuantity" label="åä½äº§åºæéæ°é" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.unitQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥åä½äº§åºæéæ°é', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.unitQuantity" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="demandedQuantity" label="éæ±æ»é" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.demandedQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥éæ±æ»é', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.demandedQuantity" |
| | | :min="0" |
| | | :precision="2" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="unit" label="åä½" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.unit`" |
| | | :rules="[{ required: true, message: '请è¾å
¥åä½', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input |
| | | v-model="row.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="diskQuantity" label="çæ°ï¼çï¼" width="150"> |
| | | <template #default="{ row, $index }"> |
| | | <el-form-item |
| | | :prop="`dataList.${$index}.diskQuantity`" |
| | | :rules="[{ required: true, message: '请è¾å
¥çæ°', trigger: ['blur','change'] }]" |
| | | style="margin: 0" |
| | | > |
| | | <el-input-number |
| | | v-model="row.diskQuantity" |
| | | :min="0" |
| | | :precision="0" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 100%" |
| | | :disabled="!dataValue.isEdit" |
| | | /> |
| | | </el-form-item> |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column label="æä½"> |
| | | <template #default="{ row, $index }"> |
| | | <el-button |
| | | type="danger" |
| | | text |
| | | @click="dataValue.dataList.splice($index, 1)" |
| | | >å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | |
| | | <product-select-dialog |
| | | v-if="dataValue.showProductDialog" |
| | | v-model:model-value="dataValue.showProductDialog" |
| | | @confirm="handleProduct"/> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="visible = false">åæ¶</el-button> |
| | | <el-button type="primary" :loading="dataValue.loading" @click="submit" :disabled="!dataValue.isEdit"> |
| | | 确认 |
| | | </el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import {computed, defineAsyncComponent, defineComponent, onMounted, reactive, ref} from "vue"; |
| | | import {queryList, add} from '@/api/productionManagement/productStructure.js' |
| | | import {list} from '@/api/productionManagement/productionProcess' |
| | | import {ElMessage} from "element-plus"; |
| | | |
| | | |
| | | defineComponent({ |
| | | name: "StructureEdit", |
| | | }) |
| | | |
| | | const ProductSelectDialog = defineAsyncComponent(() => import('@/views/basicData/product/ProductSelectDialog.vue')) |
| | | const form = ref() |
| | | |
| | | |
| | | |
| | | const props = defineProps({ |
| | | showModel: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | productModelId: { |
| | | type: Number, |
| | | required: true |
| | | } |
| | | }) |
| | | |
| | | const emits = defineEmits(['update:showModel']) |
| | | const visible = computed({ |
| | | get() { |
| | | return props.showModel |
| | | }, |
| | | set(val) { |
| | | emits('update:showModel', val) |
| | | } |
| | | }) |
| | | |
| | | const dataValue = reactive({ |
| | | dataList: [], |
| | | productOptions: [], |
| | | processOptions: [], |
| | | showProductDialog: false, |
| | | currentRowIndex: null, |
| | | loading: false, |
| | | isEdit: false, |
| | | }); |
| | | |
| | | const openDialog = (index) => { |
| | | dataValue.currentRowIndex = index |
| | | dataValue.showProductDialog = true |
| | | } |
| | | |
| | | const fetchData = async () => { |
| | | const {data} = await queryList(props.productModelId) |
| | | dataValue.dataList = data |
| | | } |
| | | |
| | | const fetchProcessOptions = async () => { |
| | | const {data} = await list(props.productModelId) |
| | | dataValue.processOptions = data |
| | | } |
| | | |
| | | const handleProduct = (row) => { |
| | | if (row?.length > 1) { |
| | | ElMessage.error('åªè½éæ©ä¸ä¸ªäº§å') |
| | | } |
| | | dataValue.dataList[dataValue.currentRowIndex].productName = row[0].productName |
| | | dataValue.dataList[dataValue.currentRowIndex].model = row[0].model |
| | | dataValue.dataList[dataValue.currentRowIndex].productModelId = row[0].id |
| | | dataValue.showProductDialog = false |
| | | } |
| | | |
| | | const submit = () => { |
| | | form.value.validate(valid => { |
| | | dataValue.loading = true |
| | | if (valid) { |
| | | add({ |
| | | parentId: props.productModelId, |
| | | productStructureList: dataValue.dataList || [] |
| | | }).then(res => { |
| | | ElMessage.success('ä¿åæå') |
| | | visible.value = false |
| | | dataValue.loading = false |
| | | }) |
| | | } |
| | | }).finally(() => { |
| | | dataValue.loading = false |
| | | }) |
| | | } |
| | | |
| | | const addItem = () => { |
| | | dataValue.dataList.push({ |
| | | productName: '', |
| | | productId: '', |
| | | model: undefined, |
| | | productModelId: undefined, |
| | | processId: '', |
| | | unitQuantity: 0, |
| | | demandedQuantity: 0, |
| | | unit: '', |
| | | diskQuantity: 0, |
| | | }) |
| | | } |
| | | |
| | | const cancelEdit = () => { |
| | | dataValue.isEdit = false |
| | | dataValue.dataList = dataValue.dataList.filter(item => item.id !== undefined) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | fetchData() |
| | | fetchProcessOptions() |
| | | }) |
| | | |
| | | |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | > |
| | | <template #detail="{row}"> |
| | | <el-button |
| | | type="primary" |
| | | text |
| | | @click="() =>{ |
| | | currentRowId = row.id; |
| | | showEdit = true; |
| | | }" |
| | | >{{ row.productName }} |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | <StructureEdit v-if="showEdit" v-model:show-model="showEdit" :product-model-id="currentRowId"/> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref} from "vue"; |
| | | import {productModelList} from "@/api/basicData/productModel.js"; |
| | | |
| | | const StructureEdit = defineAsyncComponent(() => import('@/views/productionManagement/productStructure/StructureEdit.vue')) |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | dataType: 'slot', |
| | | slot: "detail" |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const showEdit = ref(false); |
| | | const selectedRows = ref([]); |
| | | const currentRowId = ref(0); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | const data = reactive({ |
| | | form: { |
| | | productName: "", |
| | | }, |
| | | rules: { |
| | | productName: [{required: true, message: "请è¾å
¥", trigger: "blur"}], |
| | | }, |
| | | modelForm: { |
| | | otherModel: '', |
| | | model: "", |
| | | unit: "", |
| | | speculativeTradingName: [], |
| | | }, |
| | | }); |
| | | const {form, rules} = toRefs(data); |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æ¥è¯¢è§æ ¼åå· |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getModelList(); |
| | | }; |
| | | const getModelList = () => { |
| | | tableLoading.value = true; |
| | | productModelList({ |
| | | current: page.current, |
| | | size: page.size, |
| | | }).then((res) => { |
| | | tableData.value = res.records; |
| | | page.total = res.total; |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getModelList(); |
| | | }) |
| | | </script> |
| | |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">ååå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.salesContractNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | |
| | | prop: "salesContractNo", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width: 250, |
| | | }, |
| | | // { |
| | | // label: "客æ·ååå·", |
| | | // prop: "customerContractNo", |
| | | // width: 250, |
| | | // }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:300 |
| | | }, |
| | | // { |
| | | // label: "项ç®åç§°", |
| | | // prop: "projectName", |
| | | // width:300 |
| | | // }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | schedulingUserName: "", |
| | | salesContractNo: "", |
| | | entryDate: [ |
| | | dayjs().format("YYYY-MM-DD"), |
| | | dayjs().add(1, "day").format("YYYY-MM-DD"), |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/productionAccounting/export", {}, "çäº§æ ¸ç®.xlsx"); |
| | | proxy.download("/basic/customer/export", {}, "çäº§æ ¸ç®.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="èªå¨æ´¾å·¥" |
| | | width="80%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" ref="formRef"> |
| | | <el-divider content-position="left">派工å表</el-divider> |
| | | |
| | | <el-table |
| | | :data="dispatchList" |
| | | border |
| | | style="width: 100%; margin-top: 20px;" |
| | | :row-class-name="tableRowClassName" |
| | | > |
| | | <el-table-column label="åºå·" type="index" width="60" align="center" /> |
| | | <el-table-column label="ååå·" prop="salesContractNo" width="200" /> |
| | | <el-table-column label="客æ·åç§°" prop="customerName" width="200" /> |
| | | <!-- <el-table-column label="项ç®åç§°" prop="projectName" width="250" /> --> |
| | | <el-table-column label="产å大类" prop="productCategory" width="150" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="200" /> |
| | | <el-table-column label="ç»å®æºå¨" prop="speculativeTradingName" width="120" /> |
| | | <el-table-column label="æ»æ°é" prop="quantity" width="100" align="right" /> |
| | | <el-table-column label="å·²æäº§" prop="schedulingNum" width="100" align="right" fixed="right" /> |
| | | <el-table-column label="å¾
æäº§" prop="pendingQuantity" width="100" align="right" fixed="right" /> |
| | | <el-table-column label="æ¬æ¬¡æäº§" width="150" align="center" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-input-number |
| | | v-model="row.schedulingNum" |
| | | :min="0" |
| | | :max="row.pendingQuantity" |
| | | :step="1" |
| | | :precision="0" |
| | | size="small" |
| | | style="width: 120px" |
| | | @change="(value) => changeCurrentNum(value, row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认派工</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs, computed} from "vue"; |
| | | import {productionDispatch, productionDispatchList} from "@/api/productionManagement/productionOrder.js"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | |
| | | const data = reactive({ |
| | | form: {}, |
| | | dispatchList: [], // 派工åè¡¨æ°æ® |
| | | }); |
| | | |
| | | const { form, dispatchList } = toRefs(data); |
| | | |
| | | |
| | | // è¡¨æ ¼è¡æ ·å¼ |
| | | const tableRowClassName = ({ rowIndex }) => { |
| | | if (rowIndex % 2 === 1) { |
| | | return 'even-row' |
| | | } |
| | | return '' |
| | | } |
| | | |
| | | // ä¿®æ¹æ¬æ¬¡æäº§æ°é |
| | | const changeCurrentNum = (value, row) => { |
| | | if (value > row.pendingQuantity) { |
| | | row.schedulingNum = row.pendingQuantity |
| | | proxy.$modal.msgWarning('æäº§æ°éä¸å¯å¤§äºå¾
æäº§æ°é') |
| | | } |
| | | } |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, rows) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | |
| | | // å¤çä¼ å
¥çæ°æ® |
| | | dispatchList.value = rows.map(row => ({ |
| | | ...row, |
| | | schedulingNum: 0, // åå§åæ¬æ¬¡æäº§æ°é为0 |
| | | pendingQuantity: (Number(row.quantity) || 0) - (Number(row.schedulingNum) || 0) // 计ç®å¾
æäº§æ°é |
| | | })) |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | // æ£æ¥æ¯å¦ææäº§æ°æ® |
| | | const hasSchedulingData = dispatchList.value.some(item => item.schedulingNum > 0) |
| | | if (!hasSchedulingData) { |
| | | proxy.$modal.msgWarning('请è³å°ä¸ºä¸æ¡è®°å½è®¾ç½®æäº§æ°é') |
| | | return |
| | | } |
| | | |
| | | // æé æäº¤æ°æ® - ç´æ¥ä¼ éæ°ç»ï¼ä¸è¿æ»¤ |
| | | const submitData = dispatchList.value |
| | | |
| | | console.log('æäº¤èªå¨æ´¾å·¥æ°æ®:', submitData) |
| | | |
| | | // è°ç¨APIï¼è¿ééè¦æ ¹æ®å®é
æ¥å£è°æ´ï¼ |
| | | productionDispatchList(submitData).then(res => { |
| | | proxy.$modal.msgSuccess(res.msg); |
| | | closeDia(); |
| | | }).catch(err => { |
| | | proxy.$modal.msgError("派工失败"); |
| | | console.error('派工失败:', err); |
| | | }) |
| | | } |
| | | |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | dispatchList.value = [] |
| | | emit('close') |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openDialog, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.even-row) { |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | :deep(.el-table .cell) { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f5f7fa; |
| | | color: #606266; |
| | | font-weight: 600; |
| | | } |
| | | </style> |
| | |
| | | @close="closeDia" |
| | | > |
| | | <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <!-- <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input v-model="form.projectName" placeholder="请è¾å
¥" clearable disabled/> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="产å大类ï¼" prop="productCategory"> |
| | | <el-input v-model="form.productCategory" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> --> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="specificationModel"> |
| | | <el-input v-model="form.specificationModel" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»å®æºå¨ï¼" prop="speculativeTradingName"> |
| | | <el-input v-model="form.speculativeTradingName" placeholder="èªå¨è·å" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="产å大类ï¼" prop="productCategory"> |
| | | <el-input v-model="form.productCategory" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | |
| | | v-model="form.schedulingUserId" |
| | | placeholder="éæ©äººå" |
| | | style="width: 100%;" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | |
| | | form: { |
| | | projectName: "", |
| | | productCategory: "", |
| | | specificationModel: "", // è§æ ¼åå· |
| | | quantity: "", |
| | | schedulingNum: "", |
| | | schedulingUserId: "", |
| | | schedulingDate: "", |
| | | pendingQuantity: "", |
| | | speculativeTradingName: "", // ç»å®æºå¨åç§° |
| | | }, |
| | | rules: { |
| | | schedulingNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | |
| | | const userList = ref([]) |
| | | const userStore = useUserStore() |
| | | |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openDialog = (type, row) => { |
| | | operationType.value = type; |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- çæº1-4 å±ç¤ºï¼æ»é / æ£å¨ç产é / 空ä½éï¼ --> |
| | | <div class="machines-grid"> |
| | | <div v-for="machine in machines" :key="machine.id" class="machine-card"> |
| | | <div class="machine-title">{{ machine.name }}</div> |
| | | <div class="machine-metrics"> |
| | | <div class="machine-control"> |
| | | <span>æ»é(kg)ï¼</span> |
| | | <el-input-number v-model="machineData[machine.name].workLoad" :min="0" :step="1" size="small" /> |
| | | </div> |
| | | <div><span> é¢è®¡æå
¥é(kg)ï¼</span><span>{{ machineData[machine.name].currentWorkLoad }}</span></div> |
| | | <div><span>空ä½å·¥ä½é(kg)ï¼</span><span>{{ machineData[machine.name].vacant }}</span></div> |
| | | </div> |
| | | </div> |
| | | <div class="save-button-container"> |
| | | <div class="loss-rate-container"> |
| | | <span class="loss-rate-label">æèç(%)ï¼</span> |
| | | <el-select v-model="rate" placeholder="è¯·éæ©æèç" style="width: 120px" size="small"> |
| | | <el-option label="6" :value="6" /> |
| | | <el-option label="7" :value="7" /> |
| | | <el-option label="8" :value="8" /> |
| | | <el-option label="9" :value="9" /> |
| | | <el-option label="10" :value="10" /> |
| | | </el-select> |
| | | </div> |
| | | <el-button type="primary" @click="saveMachineTotals" size="small">ä¿å设置</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">客æ·åç§°ï¼</span> |
| | |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">项ç®åç§°ï¼</span> |
| | | <span class="search_title ml10">ååå·ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.projectName" |
| | | v-model="searchForm.salesContractNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <!-- <span class="search_title ml10">项ç®åç§°ï¼</span>--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="searchForm.projectName"--> |
| | | <!-- style="width: 240px"--> |
| | | <!-- placeholder="请è¾å
¥"--> |
| | | <!-- @change="handleQuery"--> |
| | | <!-- clearable--> |
| | | <!-- prefix-icon="Search"--> |
| | | <!-- />--> |
| | | <span class="search_title ml10">å½å
¥æ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <el-checkbox |
| | | style="margin-left: 10px" |
| | | v-model="searchForm.status" |
| | | label="䏿¾ç¤ºå¾
ææ°é为0" |
| | | @change="handleQuery" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">ç产派工</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | <el-button type="primary" @click="openForm('add')">ç产派工</el-button> |
| | | <el-button type="success" @click="openAutoDispatch">èªå¨æ´¾å·¥</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <auto-dispatch-dia ref="autoDispatchDia" @close="handleQuery"></auto-dispatch-dia> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick, computed, watch} from "vue"; |
| | | import FormDia from "@/views/productionManagement/productionDispatching/components/formDia.vue"; |
| | | import AutoDispatchDia from "@/views/productionManagement/productionDispatching/components/autoDispatchDia.vue"; |
| | | import dayjs from "dayjs"; |
| | | import {schedulingListPage} from "@/api/productionManagement/productionOrder.js"; |
| | | import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading, getLossRate, addLossRate, updateLossRate} from "@/api/productionManagement/productionOrder.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | salesContractNo: "", |
| | | projectName: "", |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | status: true, |
| | | entryDate: [dayjs().format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD")], // å½å
¥æ¥æï¼é»è®¤å½å¤© |
| | | entryDateStart: dayjs().format("YYYY-MM-DD"), |
| | | entryDateEnd: dayjs().format("YYYY-MM-DD"), |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:300 |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 220, |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç»å®æºå¨", |
| | | prop: "speculativeTradingName", |
| | | width: 160, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "entryDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'ç产ä¸') { |
| | | return "warning"; |
| | | } else if (params == 'æªå¼å§') { |
| | | return "danger"; |
| | | } else { |
| | | return "success"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "ç产è¿åº¦", |
| | | prop: "progress", |
| | | formatData: (cellValue) => { |
| | | // 妿å¼ä¸ºç©ºæundefinedï¼æ¾ç¤ºç©ºå符串 |
| | | if (cellValue === null || cellValue === undefined || cellValue === '') { |
| | | return ''; |
| | | } |
| | | // ç´æ¥å¨æ°åå颿·»å ç¾åå· |
| | | return `${cellValue}%`; |
| | | } |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | |
| | | label: "å¾
ææ°é", |
| | | prop: "pendingQuantity", |
| | | width: 100, |
| | | fixed: 'right', |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | |
| | | total: 0, |
| | | }); |
| | | const formDia = ref() |
| | | const autoDispatchDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // çæºæ°æ® |
| | | const machineData = reactive({ |
| | | "çæº1": { workLoad: 0, currentWorkLoad: 0, vacant: 0 }, |
| | | "çæº2": { workLoad: 0, currentWorkLoad: 0, vacant: 0 }, |
| | | "çæº3": { workLoad: 0, currentWorkLoad: 0, vacant: 0 }, |
| | | "çæº4": { workLoad: 0, currentWorkLoad: 0, vacant: 0 } |
| | | }) |
| | | |
| | | // çæºé
ç½®æ°ç» |
| | | const machines = [ |
| | | { id: 1, name: 'çæº1' }, |
| | | { id: 2, name: 'çæº2' }, |
| | | { id: 3, name: 'çæº3' }, |
| | | { id: 4, name: 'çæº4' } |
| | | ] |
| | | |
| | | // ä¿åçæºæ»é设置 |
| | | const saveMachineTotals = () => { |
| | | // éªè¯æèçæ¯å¦å·²éæ© |
| | | if (rate.value === null || rate.value === undefined || isNaN(rate.value)) { |
| | | proxy.$message.warning('è¯·éæ©æèç'); |
| | | return; |
| | | } |
| | | |
| | | // æé ä¿åæ°æ®æ°ç»ï¼ä½¿ç¨machinesæ°ç»å¾ªç¯æå»º |
| | | const saveData = machines.map(machine => { |
| | | const saveItem = { |
| | | name: machine.name, // çæºåç§° |
| | | workLoad: machineData[machine.name].workLoad, // æ»é |
| | | currentWorkLoad: machineData[machine.name].currentWorkLoad, // é¢è®¡æå
¥é |
| | | vacant: machineData[machine.name].vacant // 空ä½é |
| | | }; |
| | | |
| | | // 妿æ¯ä¿®æ¹æä½ï¼éè¦ä¼ éidåæ®µ |
| | | if (hasQueryData.value) { |
| | | const queryData = getMachineQueryData(machine.id); |
| | | if (queryData && queryData.id) { |
| | | saveItem.id = queryData.id; |
| | | } |
| | | } |
| | | |
| | | return saveItem; |
| | | }); |
| | | |
| | | // æé æèçæ°æ® |
| | | const rateData = { |
| | | rate: rate.value |
| | | }; |
| | | |
| | | // 妿æIDï¼è¯´ææ¯ä¿®æ¹æä½ |
| | | if (rateId.value) { |
| | | rateData.id = rateId.value; |
| | | } |
| | | |
| | | // æ ¹æ®æ¯å¦ææ¥è¯¢æ°æ®å³å®è°ç¨æ°å¢æ¥å£è¿æ¯ä¿®æ¹æ¥å£ |
| | | const saveApi = hasQueryData.value ? updateSpeculatTrading : addSpeculatTrading; |
| | | const successMessage = hasQueryData.value ? 'çæºè®¾ç½®ä¿®æ¹æå' : 'çæºè®¾ç½®æ°å¢æå'; |
| | | |
| | | // æ ¹æ®æ¯å¦æIDå³å®è°ç¨æ°å¢æ¥å£è¿æ¯ä¿®æ¹æ¥å£ |
| | | const rateApi = rateId.value ? updateLossRate : addLossRate; |
| | | const rateSuccessMessage = rateId.value ? 'æèçä¿®æ¹æå' : 'æèçæ°å¢æå'; |
| | | |
| | | // å¹¶è¡è°ç¨ä¸¤ä¸ªæ¥å£ |
| | | Promise.all([ |
| | | saveApi(saveData), |
| | | rateApi(rateData) |
| | | ]).then(([saveRes, rateRes]) => { |
| | | proxy.$message.success(successMessage); |
| | | proxy.$message.success(rateSuccessMessage); |
| | | |
| | | // ä¿åæååï¼è®¾ç½®hasQueryData为trueï¼ä¸æ¬¡ä¿åå°è°ç¨ä¿®æ¹æ¥å£ |
| | | if (!hasQueryData.value) { |
| | | hasQueryData.value = true; |
| | | } |
| | | |
| | | // 妿è¿åäºIDï¼ä¿åèµ·æ¥ |
| | | if (rateRes && rateRes.data && rateRes.data.id) { |
| | | rateId.value = rateRes.data.id; |
| | | } |
| | | |
| | | // ä¿åæååéæ°è°ç¨æ¥è¯¢é¡µé¢ |
| | | getList(); |
| | | }).catch(err => { |
| | | proxy.$message.error('ä¿å失败'); |
| | | console.error('ä¿å失败:', err); |
| | | }); |
| | | } |
| | | |
| | | // è·åçæºæ¥è¯¢æ°æ® |
| | | const machineQueryData = ref([]); |
| | | |
| | | const getMachineQueryData = (machineId) => { |
| | | return machineQueryData.value.find(item => item.id === machineId); |
| | | }; |
| | | |
| | | const getMachineIndex = (item) => { |
| | | // å
¼å®¹å¤ç§å段å½åï¼è¿å 1-4 ä¹ä¸ï¼å¦åè¿å 0ï¼æªç¥ï¼ |
| | | const candidates = [item.machineId, item.machineNo, item.machine, item.deviceNo, item.deviceId] |
| | | for (const v of candidates) { |
| | | if (v === undefined || v === null) continue |
| | | const n = Number(String(v).replace(/[^\d]/g, "")) // æ½åæ°å |
| | | if ([1,2,3,4].includes(n)) return n |
| | | } |
| | | return 0 |
| | | } |
| | | |
| | | const computeTodaySummary = () => { |
| | | const todayStr = dayjs().format("YYYY-MM-DD") |
| | | |
| | | // éç½®ææçæºæ°æ® |
| | | machines.forEach(machine => { |
| | | machineData[machine.name] = { workLoad: 0, currentWorkLoad: 0, vacant: 0 } |
| | | }) |
| | | |
| | | tableData.value.forEach(item => { |
| | | // ä»
ç»è®¡å½å¤© |
| | | const isToday = dayjs(item.entryDate).format("YYYY-MM-DD") === todayStr |
| | | if (!isToday) return |
| | | |
| | | // ä½¿ç¨æ£ç¡®çåæ®µåï¼workLoadï¼çæºå·¥ä½éï¼, currentWorkLoadï¼çæºæ£å¨å·¥ä½éï¼ |
| | | const workLoad = Number(item.workLoad) || 0 |
| | | const currentWorkLoad = Number(item.currentWorkLoad) || 0 |
| | | const machineName = item.speculativeTradingName || 'çæº1' |
| | | |
| | | if (machineData[machineName]) { |
| | | machineData[machineName].workLoad += workLoad |
| | | machineData[machineName].currentWorkLoad += currentWorkLoad |
| | | machineData[machineName].vacant = machineData[machineName].workLoad - machineData[machineName].currentWorkLoad |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¯å¦ææ¥è¯¢æ°æ® |
| | | const hasQueryData = ref(false) |
| | | // æèç |
| | | const rate = ref(6) |
| | | // æèçID |
| | | const rateId = ref(null) |
| | | |
| | | // è·åçæºæ£å¨å·¥ä½éæ°æ® |
| | | const getMachineProductionData = () => { |
| | | schedulingList().then((res) => { |
| | | // å¤ççæºæ£å¨å·¥ä½éæ°æ® |
| | | if (res.data && Array.isArray(res.data)) { |
| | | // 设置æ¯å¦ææ¥è¯¢æ°æ® |
| | | hasQueryData.value = res.data.length > 0 |
| | | |
| | | // ä¿åæ¥è¯¢æ°æ®å°machineQueryData |
| | | machineQueryData.value = res.data; |
| | | |
| | | // éç½®ææçæºæ°æ® |
| | | machines.forEach(machine => { |
| | | machineData[machine.name] = { workLoad: 0, currentWorkLoad: 0, vacant: 0 } |
| | | }); |
| | | |
| | | // éåæ°æ®ï¼æ ¹æ®æ¥è¯¢è¿åçæ°æ®ç»æå¤ç |
| | | res.data.forEach(item => { |
| | | // æ ¹æ®nameåæ®µç¡®å®çæº |
| | | const machineName = item.name || 'çæº1'; |
| | | |
| | | if (machineData[machineName]) { |
| | | // 妿æ¥è¯¢æ°æ®ä¸æworkLoadï¼ååå§åçæºæ»é |
| | | if (item.workLoad !== null && item.workLoad !== undefined) { |
| | | machineData[machineName].workLoad = Number(item.workLoad) || 0; |
| | | } |
| | | |
| | | // 妿æ¥è¯¢æ°æ®ä¸æcurrentWorkLoadï¼å设置æ£å¨å·¥ä½é |
| | | if (item.currentWorkLoad !== null && item.currentWorkLoad !== undefined) { |
| | | machineData[machineName].currentWorkLoad = Number(item.currentWorkLoad) || 0; |
| | | } |
| | | |
| | | // 计ç®ç©ºä½å·¥ä½é |
| | | machineData[machineName].vacant = machineData[machineName].workLoad - machineData[machineName].currentWorkLoad; |
| | | } |
| | | }); |
| | | } |
| | | }).catch(err => { |
| | | console.error('è·åçæºæ£å¨å·¥ä½éæ°æ®å¤±è´¥:', err); |
| | | }); |
| | | }; |
| | | |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.value.entryDateStart = value[0]; |
| | |
| | | pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0) |
| | | })); |
| | | page.total = res.data.total; |
| | | computeTodaySummary() |
| | | |
| | | // åæ¶è·åçæºæ£å¨å·¥ä½éæ°æ® |
| | | getMachineProductionData(); |
| | | // è·åæèçæ°æ® |
| | | getLossRateData(); |
| | | }).catch(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // è·åæèçæ°æ® |
| | | const getLossRateData = () => { |
| | | getLossRate().then((res) => { |
| | | const data = res.data || res; |
| | | if (data && data.rate !== undefined && data.rate !== null) { |
| | | rate.value = Number(data.rate); // ç¡®ä¿è½¬æ¢ä¸ºæ°å |
| | | rateId.value = data.id || null; |
| | | } else { |
| | | rate.value = 6; |
| | | rateId.value = null; |
| | | } |
| | | }).catch(err => { |
| | | console.error('è·åæèçæ°æ®å¤±è´¥:', err); |
| | | rate.value = 6; |
| | | rateId.value = null; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | |
| | | }) |
| | | }; |
| | | |
| | | // æå¼èªå¨æ´¾å·¥å¼¹æ¡ |
| | | const openAutoDispatch = () => { |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$message.error("è¯·éæ©è³å°ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // è¿æ»¤æå¾
æäº§æ°é为0çæ°æ® |
| | | const validRows = selectedRows.value.filter(row => row.pendingQuantity > 0); |
| | | |
| | | if (validRows.length === 0) { |
| | | proxy.$message.warning("éä¸çæ°æ®æ éæ´¾å·¥"); |
| | | return; |
| | | } |
| | | |
| | | nextTick(() => { |
| | | autoDispatchDia.value?.openDialog('auto', validRows) |
| | | }) |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getLossRateData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped> |
| | | .summary-bar{ |
| | | display: flex; |
| | | gap: 16px; |
| | | margin: 10px 0 16px 0; |
| | | } |
| | | .summary-item{ |
| | | background: #f5f7fa; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 6px; |
| | | padding: 10px 16px; |
| | | min-width: 160px; |
| | | } |
| | | .summary-label{ |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-bottom: 6px; |
| | | } |
| | | .summary-value{ |
| | | color: #303133; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | } |
| | | .summary-control{ |
| | | display: flex; |
| | | align-items: center; |
| | | height: 28px; |
| | | } |
| | | .machines-grid{ |
| | | display: grid; |
| | | grid-template-columns: repeat(4, 1fr); |
| | | gap: 16px; |
| | | margin-bottom: 20px; |
| | | padding: 16px; |
| | | background: #f8f9fa; |
| | | border-radius: 8px; |
| | | border: 1px solid #e9ecef; |
| | | } |
| | | .machine-card{ |
| | | border: 1px solid #dee2e6; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | background: #fff; |
| | | box-shadow: 0 2px 4px rgba(0,0,0,0.05); |
| | | transition: all 0.3s ease; |
| | | } |
| | | .machine-card:hover{ |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 4px 8px rgba(0,0,0,0.1); |
| | | } |
| | | .machine-title{ |
| | | font-weight: 600; |
| | | font-size: 16px; |
| | | margin-bottom: 12px; |
| | | color: #2c3e50; |
| | | text-align: center; |
| | | padding-bottom: 8px; |
| | | border-bottom: 2px solid #3498db; |
| | | } |
| | | .machine-metrics{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | color: #495057; |
| | | } |
| | | .machine-control{ |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | gap: 8px; |
| | | padding: 8px 0; |
| | | border-bottom: 1px solid #f1f3f4; |
| | | } |
| | | .machine-control span{ |
| | | font-size: 14px; |
| | | white-space: nowrap; |
| | | color: #6c757d; |
| | | font-weight: 500; |
| | | } |
| | | .machine-metrics > div:not(.machine-control) { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 4px 0; |
| | | font-size: 14px; |
| | | } |
| | | .machine-metrics > div:not(.machine-control) span:first-child { |
| | | color: #6c757d; |
| | | } |
| | | .machine-metrics > div:not(.machine-control) span:last-child { |
| | | font-weight: 600; |
| | | color: #2c3e50; |
| | | } |
| | | .save-button-container{ |
| | | grid-column: 1 / -1; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | gap: 16px; |
| | | margin-top: 16px; |
| | | padding-top: 16px; |
| | | border-top: 1px solid #e9ecef; |
| | | } |
| | | .loss-rate-container{ |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .loss-rate-label{ |
| | | font-size: 14px; |
| | | color: #6c757d; |
| | | font-weight: 500; |
| | | white-space: nowrap; |
| | | } |
| | | </style> |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog v-model="isShow" |
| | | title="å·¥èºè·¯çº¿é¡¹ç®" |
| | | width="800px" |
| | | @close="closeModal"> |
| | | <div class="operate-button"> |
| | | <el-button type="primary" |
| | | @click="isShowProductSelectDialog = true" |
| | | class="mb5" |
| | | style="margin-bottom: 10px;"> |
| | | éæ©äº§å |
| | | </el-button> |
| | | <el-switch v-model="isTable" |
| | | inline-prompt |
| | | active-text="è¡¨æ ¼" |
| | | inactive-text="å表" |
| | | @change="handleViewChange" /> |
| | | </div> |
| | | <el-table v-if="isTable" |
| | | ref="multipleTable" |
| | | v-loading="tableLoading" |
| | | border |
| | | :data="routeItems" |
| | | :header-cell-style="{ background: '#F0F1F5', color: '#333333' }" |
| | | row-key="id" |
| | | tooltip-effect="dark" |
| | | class="lims-table" |
| | | style="cursor: move;"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | width="60"> |
| | | <template #default="scope"> |
| | | {{ scope.$index + 1 }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column v-for="(item, index) in tableColumn" |
| | | :key="index" |
| | | :label="item.label" |
| | | :width="item.width" |
| | | show-overflow-tooltip> |
| | | <template #default="scope" |
| | | v-if="item.dataType === 'action'"> |
| | | <el-button v-for="(op, opIndex) in item.operation" |
| | | :key="opIndex" |
| | | :type="op.type" |
| | | :link="op.link" |
| | | size="small" |
| | | @click.stop="op.clickFun(scope.row)"> |
| | | {{ op.name }} |
| | | </el-button> |
| | | </template> |
| | | <template #default="scope" |
| | | v-else> |
| | | <template v-if="item.prop === 'processId'"> |
| | | <el-select v-model="scope.row[item.prop]" |
| | | style="width: 100%;" |
| | | @mousedown.stop> |
| | | <el-option v-for="process in processOptions" |
| | | :key="process.id" |
| | | :label="process.name" |
| | | :value="process.id" /> |
| | | </el-select> |
| | | </template> |
| | | <template v-else> |
| | | {{ scope.row[item.prop] || '-' }} |
| | | </template> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- ä½¿ç¨æ®édivæ¿ä»£el-steps --> |
| | | <div v-else |
| | | ref="stepsContainer" |
| | | class="mb5 custom-steps" |
| | | style="padding: 10px 0; display: flex; flex-wrap: nowrap; gap: 20px; align-items: flex-start;"> |
| | | <div v-for="(item, index) in routeItems" |
| | | :key="item.id" |
| | | class="custom-step draggable-step" |
| | | :data-id="item.id" |
| | | style="cursor: move; flex: 0 0 auto; min-width: 220px;"> |
| | | <div class="step-content"> |
| | | <div class="step-number">{{ index + 1 }}</div> |
| | | <el-card :header="item.productName" |
| | | class="step-card" |
| | | style="cursor: move;"> |
| | | <div class="step-card-content"> |
| | | <p>{{ item.model }}</p> |
| | | <p>{{ item.unit }}</p> |
| | | <el-select v-model="item.processId" |
| | | style="width: 100%;" |
| | | @mousedown.stop> |
| | | <el-option v-for="process in processOptions" |
| | | :key="process.id" |
| | | :label="process.name" |
| | | :value="process.id" /> |
| | | </el-select> |
| | | </div> |
| | | <template #footer> |
| | | <div class="step-card-footer"> |
| | | <el-button type="danger" |
| | | link |
| | | size="small" |
| | | @click.stop="removeItemByID(item.id)">å é¤</el-button> |
| | | </div> |
| | | </template> |
| | | </el-card> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" |
| | | @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <ProductSelectDialog v-model="isShowProductSelectDialog" |
| | | @confirm="handelSelectProducts" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | ref, |
| | | computed, |
| | | getCurrentInstance, |
| | | onMounted, |
| | | onUnmounted, |
| | | nextTick, |
| | | } from "vue"; |
| | | import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue"; |
| | | import { |
| | | findProductProcessRouteItemList, |
| | | addOrUpdateProductProcessRouteItem, |
| | | deleteRouteItem, |
| | | } from "@/api/productionManagement/productProcessRoute.js"; |
| | | import { processList } from "@/api/productionManagement/productionProcess.js"; |
| | | import Sortable from "sortablejs"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | default: false, |
| | | }, |
| | | record: { |
| | | type: Object, |
| | | required: true, |
| | | default: () => ({}), |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(["update:visible", "completed"]); |
| | | |
| | | const processOptions = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowProductSelectDialog = ref(false); |
| | | const routeItems = ref([]); |
| | | let tableSortable = null; |
| | | let stepsSortable = null; |
| | | const multipleTable = ref(null); |
| | | const stepsContainer = ref(null); |
| | | const isTable = ref(true); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit("update:visible", val); |
| | | }, |
| | | }); |
| | | |
| | | const tableColumn = ref([ |
| | | { label: "产ååç§°", prop: "productName", width: 180 }, |
| | | { label: "è§æ ¼åç§°", prop: "model", width: 150 }, |
| | | { label: "åä½", prop: "unit", width: 80 }, |
| | | { label: "å·¥åºåç§°", prop: "processId", width: 180 }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 100, |
| | | operation: [ |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | link: true, |
| | | clickFun: row => { |
| | | console.log(row.id, "å é¤"); |
| | | |
| | | const dragSortx = routeItems.value.findIndex( |
| | | item => item.dragSort === row.dragSort |
| | | ); |
| | | const idx = routeItems.value.findIndex(item => item.id === row.id); |
| | | console.log(idx, "idx"); |
| | | if (row.id) { |
| | | deleteRouteItemByIds({ id: row.id }, idx); |
| | | } else { |
| | | removeItem(dragSortx); |
| | | } |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | |
| | | const removeItem = index => { |
| | | console.log("软å é¤", index); |
| | | |
| | | routeItems.value.splice(index, 1); |
| | | updateDragSort(); |
| | | nextTick(() => initSortable()); |
| | | }; |
| | | |
| | | const removeItemByID = id => { |
| | | const idx = routeItems.value.findIndex(item => item.id === id); |
| | | if (idx > -1) { |
| | | routeItems.value.splice(idx, 1); |
| | | updateDragSort(); |
| | | nextTick(() => initSortable()); |
| | | } |
| | | }; |
| | | |
| | | const deleteRouteItemByIds = (ids, index) => { |
| | | deleteRouteItem(ids).then(res => { |
| | | routeItems.value.splice(index, 1); |
| | | updateDragSort(); |
| | | nextTick(() => initSortable()); |
| | | }); |
| | | }; |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const updateDragSort = () => { |
| | | routeItems.value.forEach((item, index) => { |
| | | item.dragSort = index + 1; |
| | | }); |
| | | routeItems.value = [...routeItems.value]; |
| | | console.log("æ´æ°åçæ°ç»:", routeItems.value); |
| | | }; |
| | | |
| | | const handelSelectProducts = products => { |
| | | destroySortable(); |
| | | |
| | | // è®¡ç®æ°çdragSortå¼èµ·å§ç¹ |
| | | const maxDragSort = |
| | | routeItems.value.length > 0 |
| | | ? Math.max(...routeItems.value.map(item => item.dragSort || 0)) |
| | | : 0; |
| | | |
| | | const newData = products.map(({ id, ...product }, index) => ({ |
| | | ...product, |
| | | productModelId: id, |
| | | routeId: props.record.id, |
| | | // id: `${Date.now()}-${Math.random().toString(36).slice(2)}`, |
| | | processId: undefined, |
| | | dragSort: maxDragSort + index + 1, |
| | | })); |
| | | |
| | | console.log("éæ©äº§ååæ°ç»:", routeItems.value); |
| | | routeItems.value.push(...newData); |
| | | updateDragSort(); |
| | | console.log("éæ©äº§ååæ°ç»:", routeItems.value); |
| | | |
| | | // å»¶è¿åå§åï¼ç¡®ä¿DOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | // 强å¶éæ°æ¸²æç»ä»¶ |
| | | if (proxy?.$forceUpdate) { |
| | | proxy.$forceUpdate(); |
| | | } |
| | | |
| | | const temp = [...routeItems.value]; |
| | | routeItems.value = []; |
| | | nextTick(() => { |
| | | routeItems.value = temp; |
| | | initSortable(); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const findProcessRouteItems = () => { |
| | | tableLoading.value = true; |
| | | findProductProcessRouteItemList({ orderId: props.record.id }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | routeItems.value = res.data.map(item => ({ |
| | | ...item, |
| | | processId: item.processId === 0 ? undefined : item.processId, |
| | | })); |
| | | // å»¶è¿åå§åï¼ç¡®ä¿DOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | setTimeout(() => initSortable(), 100); |
| | | }); |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | console.error("è·åå表失败ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | const findProcessList = () => { |
| | | processList({}) |
| | | .then(res => { |
| | | processOptions.value = res.data; |
| | | }) |
| | | .catch(err => { |
| | | console.error("è·åå·¥åºå¤±è´¥ï¼", err); |
| | | }); |
| | | }; |
| | | |
| | | const { proxy } = getCurrentInstance() || {}; |
| | | |
| | | const handleSubmit = () => { |
| | | const hasEmptyProcess = routeItems.value.some(item => !item.processId); |
| | | if (hasEmptyProcess) { |
| | | proxy?.$modal?.msgError("请为ææé¡¹ç®éæ©å·¥åº"); |
| | | return; |
| | | } |
| | | |
| | | addOrUpdateProductProcessRouteItem({ |
| | | routeId: props.record.id, |
| | | processRouteItem: routeItems.value, |
| | | }) |
| | | .then(res => { |
| | | isShow.value = false; |
| | | emit("completed"); |
| | | proxy?.$modal?.msgSuccess("æäº¤æå"); |
| | | }) |
| | | .catch(err => { |
| | | proxy?.$modal?.msgError(`æäº¤å¤±è´¥ï¼${err.msg || "ç½ç»å¼å¸¸"}`); |
| | | }); |
| | | }; |
| | | |
| | | const destroySortable = () => { |
| | | if (tableSortable) { |
| | | tableSortable.destroy(); |
| | | tableSortable = null; |
| | | } |
| | | if (stepsSortable) { |
| | | stepsSortable.destroy(); |
| | | stepsSortable = null; |
| | | } |
| | | }; |
| | | |
| | | const initSortable = () => { |
| | | destroySortable(); |
| | | |
| | | if (isTable.value) { |
| | | if (!multipleTable.value) return; |
| | | const tbody = |
| | | multipleTable.value.$el.querySelector(".el-table__body tbody") || |
| | | multipleTable.value.$el.querySelector( |
| | | ".el-table__body-wrapper > table > tbody" |
| | | ); |
| | | if (!tbody) return; |
| | | |
| | | tableSortable = new Sortable(tbody, { |
| | | animation: 150, |
| | | ghostClass: "sortable-ghost", |
| | | handle: ".el-table__row", |
| | | filter: ".el-button, .el-select", |
| | | onEnd: evt => { |
| | | if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) |
| | | return; |
| | | |
| | | // ä½¿ç¨æ°ç» splice æ¹æ³éæ°æåºï¼ä¸è¡¨æ ¼æ¨¡å¼ä¿æä¸è´ |
| | | const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0]; |
| | | routeItems.value.splice(evt.newIndex, 0, moveItem); |
| | | updateDragSort(); |
| | | console.log("æåºåæ°ç»:", routeItems.value); |
| | | }, |
| | | }); |
| | | } else { |
| | | if (!stepsContainer.value) return; |
| | | |
| | | // ä¿®æ¹ï¼ç´æ¥ä½¿ç¨stepsContainer.valueä½ä¸ºææ½å®¹å¨ |
| | | const stepsList = stepsContainer.value; |
| | | if (!stepsList) { |
| | | console.warn("æªæ¾å°æ¥éª¤æ¡ææ½å®¹å¨"); |
| | | return; |
| | | } |
| | | |
| | | // ä¿®æ¹ï¼ç®åææ½é
ç½® |
| | | stepsSortable = new Sortable(stepsList, { |
| | | animation: 150, |
| | | ghostClass: "sortable-ghost", |
| | | draggable: ".draggable-step", // 坿æ½å
ç´ |
| | | handle: ".draggable-step, .step-card", // ææ½ææ |
| | | filter: ".el-button, .el-select, .el-input", // è¿æ»¤æé®/éæ©å¨ |
| | | forceFallback: true, |
| | | fallbackClass: "sortable-fallback", |
| | | preventOnFilter: true, |
| | | scroll: true, |
| | | scrollSensitivity: 30, |
| | | scrollSpeed: 10, |
| | | bubbleScroll: true, |
| | | onEnd: evt => { |
| | | if (evt.oldIndex === evt.newIndex || !routeItems.value[evt.oldIndex]) |
| | | return; |
| | | |
| | | // ä½¿ç¨æ°ç» splice æ¹æ³éæ°æåº |
| | | const moveItem = routeItems.value.splice(evt.oldIndex, 1)[0]; |
| | | routeItems.value.splice(evt.newIndex, 0, moveItem); |
| | | updateDragSort(); |
| | | }, |
| | | }); |
| | | |
| | | // è°è¯ï¼æå°å®¹å¨åå®ä¾ï¼ç¡®è®¤ç»å®æå |
| | | console.log("æ¥éª¤æ¡ææ½å®¹å¨:", stepsList); |
| | | console.log("Sortableå®ä¾:", stepsSortable); |
| | | } |
| | | }; |
| | | |
| | | const handleViewChange = () => { |
| | | destroySortable(); |
| | | // å»¶è¿åå§åï¼ç¡®ä¿è§å¾åæ¢åDOMå®å
¨æ¸²æ |
| | | nextTick(() => { |
| | | setTimeout(() => initSortable(), 100); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | findProcessRouteItems(); |
| | | findProcessList(); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | destroySortable(); |
| | | }); |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.sortable-ghost) { |
| | | opacity: 0.6; |
| | | background-color: #f5f7fa !important; |
| | | } |
| | | |
| | | :deep(.el-table__row) { |
| | | transition: background-color 0.2s; |
| | | } |
| | | |
| | | :deep(.el-table__row:hover) { |
| | | background-color: #f9fafc !important; |
| | | } |
| | | |
| | | :deep(.el-card__footer) { |
| | | padding: 0 !important; |
| | | } |
| | | |
| | | .operate-button { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | /* ä¿®æ¹ï¼èªå®ä¹æ¥éª¤æ¡å®¹å¨æ ·å¼ */ |
| | | .custom-steps { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: flex-start; |
| | | gap: 20px; |
| | | min-height: 100px; |
| | | } |
| | | |
| | | /* ä¿®æ¹ï¼èªå®ä¹æ¥éª¤é¡¹æ ·å¼ */ |
| | | .custom-step { |
| | | cursor: move !important; |
| | | padding: 8px; |
| | | position: relative; |
| | | transition: all 0.2s ease; |
| | | flex: 0 0 auto; |
| | | min-width: 220px; |
| | | touch-action: none; |
| | | } |
| | | |
| | | /* ææ½æ¬æµ®æ ·å¼ï¼æç¤ºå¯ææ½ */ |
| | | .custom-step:hover { |
| | | background-color: rgba(64, 158, 255, 0.05); |
| | | transform: translateY(-2px); |
| | | } |
| | | |
| | | .sortable-ghost { |
| | | opacity: 0.4; |
| | | background-color: #f5f7fa !important; |
| | | border: 2px dashed #409eff; |
| | | margin: 10px; |
| | | transform: scale(1.02); |
| | | } |
| | | |
| | | .sortable-fallback { |
| | | opacity: 0.9; |
| | | background-color: #f5f7fa; |
| | | border: 1px solid #409eff; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); |
| | | transform: rotate(2deg); |
| | | margin: 10px; |
| | | } |
| | | |
| | | .step-card { |
| | | cursor: move !important; |
| | | transition: box-shadow 0.2s ease; |
| | | user-select: none; |
| | | -webkit-user-select: none; |
| | | pointer-events: auto; |
| | | margin: 10px; |
| | | height: 240px; |
| | | } |
| | | |
| | | .step-card:hover { |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .step-content { |
| | | width: 220px; |
| | | user-select: none; |
| | | } |
| | | |
| | | .step-card-content { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .step-card-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | padding: 10px; |
| | | } |
| | | |
| | | /* èªå®ä¹åºå·æ ·å¼ä¼å */ |
| | | .step-number { |
| | | font-weight: bold; |
| | | text-align: center; |
| | | width: 36px; |
| | | height: 36px; |
| | | line-height: 36px; |
| | | margin: 0 auto 10px; |
| | | background: #409eff; |
| | | color: #fff; |
| | | border-radius: 50%; |
| | | font-size: 14px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">客æ·åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.customerName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">项ç®åç§°ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.projectName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | <span class="search_title ml10">å½å
¥æ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | </div> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="客æ·åç§°:"> |
| | | <el-input v-model="searchForm.customerName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ååå·:"> |
| | | <el-input v-model="searchForm.salesContractNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°:"> |
| | | <el-input v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="产ååç§°:"> |
| | | <el-input v-model="searchForm.productCategory" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼:"> |
| | | <el-input v-model="searchForm.specificationModel" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination"></PIMTable> |
| | | </div> |
| | | <process-route-item-form v-if="isShowItemModal" |
| | | v-model:visible="isShowItemModal" |
| | | :record="record" |
| | | @completed="getList" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {schedulingListPage} from "@/api/productionManagement/productionOrder.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | import { onMounted, ref } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { productOrderListPage } from "@/api/productionManagement/productionOrder.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | import ProcessRouteItemForm from "@/views/productionManagement/productionOrder/ProcessRouteItemForm.vue"; |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "entryDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "ååå·", |
| | | prop: "salesContractNo", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:300 |
| | | }, |
| | | { |
| | | label: "çäº§ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatType: (params) => { |
| | | if (params == 'æªå®æ') { |
| | | return "danger"; |
| | | } else if (params == '已宿') { |
| | | return "success"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | width: 160, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | width:90 |
| | | }, |
| | | { |
| | | label: "æ°é", |
| | | prop: "quantity", |
| | | }, |
| | | { |
| | | label: "æäº§æ°é", |
| | | prop: "schedulingNum", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "å®å·¥æ°é", |
| | | prop: "successNum", |
| | | width: 100, |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ç产订åå·", |
| | | prop: "npsNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width: 300, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productCategory", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | | prop: "specificationModel", |
| | | width: 250, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "å·¥èºè·¯çº¿", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showRouteItemModal(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | projectName: "", |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | salesContractNo: "", |
| | | projectName: "", |
| | | productCategory: "", |
| | | specificationModel: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.value.entryDateStart = value[0]; |
| | | searchForm.value.entryDateEnd = value[1]; |
| | | } else { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // æé ä¸ä¸ªæ°ç对象ï¼ä¸å
å«entryDateåæ®µ |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | schedulingListPage(params).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const changeDaterange = value => { |
| | | if (value) { |
| | | searchForm.value.entryDateStart = value[0]; |
| | | searchForm.value.entryDateEnd = value[1]; |
| | | } else { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // æé ä¸ä¸ªæ°ç对象ï¼ä¸å
å«entryDateåæ®µ |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | productOrderListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/scheduling/export", {}, "ç产订å.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | const isShowItemModal = ref(false); |
| | | const record = ref({}); |
| | | const showRouteItemModal = row => { |
| | | isShowItemModal.value = true; |
| | | record.value = row; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/scheduling/export", {}, "ç产订å.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | const handleConfirmRoute = () => {}; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="ç¼è¾å·¥åº" |
| | | width="400" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="å·¥åºåç§°ï¼" |
| | | prop="name" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请è¾å
¥å·¥åºåç§°', |
| | | }, |
| | | { |
| | | max: 100, |
| | | message: 'æå¤100个å符', |
| | | } |
| | | ]"> |
| | | <el-input v-model="formState.name" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥èµå®é¢" prop="salaryQuota"> |
| | | <el-input v-model="formState.salaryQuota" type="number" :step="0.001" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, getCurrentInstance } from "vue"; |
| | | import {update} from "@/api/productionManagement/productionProcess.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | |
| | | record: { |
| | | type: Object, |
| | | required: true, |
| | | } |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | id: props.record.id, |
| | | name: props.record.name, |
| | | remark: props.record.remark, |
| | | salaryQuota: props.record.salaryQuota, |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | update(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æ°å¢å·¥åº" |
| | | width="400" |
| | | @close="closeModal" |
| | | > |
| | | <el-form label-width="140px" :model="formState" label-position="top" ref="formRef"> |
| | | <el-form-item |
| | | label="å·¥åºåç§°ï¼" |
| | | prop="name" |
| | | :rules="[ |
| | | { |
| | | required: true, |
| | | message: '请è¾å
¥å·¥åºåç§°', |
| | | }, |
| | | { |
| | | max: 100, |
| | | message: 'æå¤100个å符', |
| | | } |
| | | ]"> |
| | | <el-input v-model="formState.name" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥èµå®é¢" prop="salaryQuota"> |
| | | <el-input v-model="formState.salaryQuota" type="number" :step="0.001" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input v-model="formState.remark" type="textarea" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="handleSubmit">确认</el-button> |
| | | <el-button @click="closeModal">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, getCurrentInstance } from "vue"; |
| | | import {add} from "@/api/productionManagement/productionProcess.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | // ååºå¼æ°æ®ï¼æ¿ä»£é项å¼ç dataï¼ |
| | | const formState = ref({ |
| | | name: '', |
| | | remark: '', |
| | | salaryQuota: '', |
| | | }); |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | let { proxy } = getCurrentInstance() |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const handleSubmit = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | add(formState.value).then(res => { |
| | | // å
³éæ¨¡ææ¡ |
| | | isShow.value = false; |
| | | // åç¥ç¶ç»ä»¶å·²å®æ |
| | | emit('completed'); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }) |
| | | } |
| | | }) |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | handleSubmit, |
| | | isShow, |
| | | }); |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="å·¥åºåç§°:"> |
| | | <el-input v-model="searchForm.name" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åºç¼å·:"> |
| | | <el-input v-model="searchForm.no" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" class="mb10"> |
| | | <el-button type="primary" @click="showNewModal">æ°å¢å·¥åº</el-button> |
| | | <el-button type="danger" @click="handleDelete" :disabled="selectedRows.length === 0" plain>å é¤å·¥åº</el-button> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | ></PIMTable> |
| | | </div> |
| | | <new-process |
| | | v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="getList" |
| | | /> |
| | | |
| | | <edit-process |
| | | v-if="isShowEditModal" |
| | | v-model:visible="isShowEditModal" |
| | | :record="record" |
| | | @completed="getList" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import NewProcess from "@/views/productionManagement/productionProcess/New.vue"; |
| | | import EditProcess from "@/views/productionManagement/productionProcess/Edit.vue"; |
| | | import {listPage, del} from "@/api/productionManagement/productionProcess.js"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | name: "", |
| | | no: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å·¥åºåç§°", |
| | | prop: "name", |
| | | }, |
| | | { |
| | | label: "å·¥åºç¼å·", |
| | | prop: "no", |
| | | }, |
| | | { |
| | | label: "å·¥èµå®é¢", |
| | | prop: "salaryQuota", |
| | | }, |
| | | { |
| | | label: "夿³¨", |
| | | prop: "remark", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | showEditModal(row); |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const isShowNewModal = ref(false); |
| | | const isShowEditModal = ref(false); |
| | | const record = ref({}); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | listPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // æå¼æ°å¢å¼¹æ¡ |
| | | const showNewModal = () => { |
| | | isShowNewModal.value = true |
| | | }; |
| | | |
| | | const showEditModal = (row) => { |
| | | isShowEditModal.value = true |
| | | record.value = row |
| | | }; |
| | | |
| | | // å é¤ |
| | | function handleDelete() { |
| | | const no = selectedRows.value.map((item) => item.no); |
| | | const ids = selectedRows.value.map((item) => item.id); |
| | | proxy.$modal |
| | | .confirm('æ¯å¦ç¡®è®¤å é¤å·¥åºç¼å·ä¸º"' + no + '"çæ°æ®é¡¹ï¼') |
| | | .then(function () { |
| | | return del(ids); |
| | | }) |
| | | .then(() => { |
| | | getList(); |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | |
| | | // å¯¼åº |
| | | // const handleOut = () => { |
| | | // ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | // confirmButtonText: "确认", |
| | | // cancelButtonText: "åæ¶", |
| | | // type: "warning", |
| | | // }) |
| | | // .then(() => { |
| | | // proxy.download("/salesLedger/scheduling/exportTwo", {}, "å·¥åºæäº§.xlsx"); |
| | | // }) |
| | | // .catch(() => { |
| | | // proxy.$modal.msg("已忶"); |
| | | // }); |
| | | // }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="æå
¥" |
| | | @close="closeModal" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="data" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="closeModal">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, onMounted} from "vue"; |
| | | import { productionProductInputListPage } from "@/api/productionManagement/productionProductInput"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | productionProductMainId: { |
| | | type: Number, |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | fetchData(); |
| | | }; |
| | | |
| | | const tableLoading = ref(false); |
| | | |
| | | const tableColumn = [ |
| | | { |
| | | label: 'æ¥å·¥åå·', |
| | | prop: 'productNo', |
| | | }, |
| | | { |
| | | label: '产ååå·', |
| | | prop: 'model', |
| | | }, |
| | | { |
| | | label: 'æå
¥æ°é', |
| | | prop: 'quantity', |
| | | }, |
| | | ] |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const data = ref([]) |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const fetchData = () => { |
| | | tableLoading.value = true; |
| | | const params = { productMainId: props.productionProductMainId, ...page }; |
| | | |
| | | productionProductInputListPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | data.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | isShow, |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | fetchData() |
| | | }) |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog |
| | | v-model="isShow" |
| | | title="产åº" |
| | | @close="closeModal" |
| | | > |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="data" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="closeModal">å
³é</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, computed, onMounted} from "vue"; |
| | | import { productionProductOutputListPage } from "@/api/productionManagement/productionProductOutput.js"; |
| | | |
| | | const props = defineProps({ |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | }, |
| | | productionProductMainId: { |
| | | type: Number, |
| | | required: true, |
| | | }, |
| | | }); |
| | | |
| | | const emit = defineEmits(['update:visible', 'completed']); |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | fetchData(); |
| | | }; |
| | | |
| | | const tableLoading = ref(false); |
| | | |
| | | const tableColumn = [ |
| | | { |
| | | label: 'æ¥å·¥åå·', |
| | | prop: 'productNo', |
| | | }, |
| | | { |
| | | label: '产ååå·', |
| | | prop: 'model', |
| | | }, |
| | | { |
| | | label: 'æå
¥æ°é', |
| | | prop: 'quantity', |
| | | }, |
| | | ] |
| | | |
| | | const isShow = computed({ |
| | | get() { |
| | | return props.visible; |
| | | }, |
| | | set(val) { |
| | | emit('update:visible', val); |
| | | }, |
| | | }); |
| | | |
| | | const data = ref([]) |
| | | |
| | | const closeModal = () => { |
| | | isShow.value = false; |
| | | }; |
| | | |
| | | const fetchData = () => { |
| | | tableLoading.value = true; |
| | | const params = { productMainId: props.productionProductMainId, ...page }; |
| | | |
| | | productionProductOutputListPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | data.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | defineExpose({ |
| | | closeModal, |
| | | isShow, |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | fetchData() |
| | | }) |
| | | </script> |
| | |
| | | <el-input v-model="form.schedulingNum" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬æ¬¡ç产æ°éï¼" prop="finishedNum"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¾
ç产æ°éï¼" prop="pendingNum"> |
| | | <el-input v-model="form.pendingNum" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¬æ¬¡ç产æ°éï¼" prop="finishedNum"> |
| | | <el-input-number |
| | | v-model="form.finishedNum" |
| | | placeholder="请è¾å
¥" |
| | |
| | | style="width: 100%" |
| | | @change="changeNum" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä»·(å
)ï¼" prop="unitPrice"> |
| | | <el-input v-model="form.unitPrice" placeholder="请è¾å
¥" clearable @input="calculateTotalPrice"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¾
ç产æ°éï¼" prop="pendingNum"> |
| | | <el-input :value="form.pendingNum !== undefined && form.pendingNum !== null ? Number(form.pendingNum).toFixed(2) : ''" placeholder="请è¾å
¥" clearable disabled/> |
| | | <el-form-item label="æ»ä»·(å
)ï¼" prop="totalPrice"> |
| | | <el-input v-model="form.totalPrice" placeholder="请è¾å
¥" clearable disabled/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | v-model="form.schedulingUserId" |
| | | placeholder="éæ©äººå" |
| | | style="width: 100%;" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | |
| | | const userList = ref([]) |
| | | const dialogFormVisible = ref(false); |
| | | const operationType = ref('') |
| | | const pendingFinishNum = ref(0) // å¤é¨ä¼ å
¥çå¾
ç产æ°éï¼å©ä½å¯æ¥å·¥æ°éï¼ |
| | | const data = reactive({ |
| | | form: { |
| | | successNum: "", |
| | |
| | | finishedNum: "", |
| | | schedulingUserId: "", |
| | | schedulingDate: "", |
| | | unitPrice: "", |
| | | totalPrice: "", |
| | | }, |
| | | rules: { |
| | | schedulingNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" },], |
| | |
| | | userList.value = res.data; |
| | | }); |
| | | form.value = {...row} |
| | | pendingFinishNum.value = Number(row?.pendingFinishNum || 0) |
| | | // å°å¾
ç产æ°é带å
¥è¡¨åï¼æ¹ä¾¿å±ç¤ºä¸æ ¡éªï¼ä¿ç两ä½å°æ° |
| | | form.value.pendingNum = Number(pendingFinishNum.value.toFixed(2)) |
| | | } |
| | | |
| | | const changeNum = (value) => { |
| | | const maxPending = Number(pendingFinishNum.value) || 0 |
| | | // ä¸éï¼ä¸è½è¶
è¿å¾
ç产æ°é |
| | | if (Number(value) > maxPending) { |
| | | form.value.finishedNum = Number(maxPending.toFixed(2)); |
| | | proxy.$modal.msgWarning('æ¬æ¬¡ç产æ°éä¸å¯å¤§äºå¾
ç产æ°é') |
| | | if (value > form.value.schedulingNum) { |
| | | form.value.finishedNum = form.value.schedulingNum; |
| | | proxy.$modal.msgWarning('æ¬æ¬¡ç产æ°éä¸å¯å¤§äºæäº§æ°é') |
| | | } |
| | | // éæ°è®¡ç®å©ä½å¾
ç产æ°éï¼ä¿ç两ä½å°æ° |
| | | const finishedNum = Number(form.value.finishedNum) || 0 |
| | | form.value.pendingNum = Number((maxPending - finishedNum).toFixed(2)); |
| | | form.value.pendingNum = form.value.schedulingNum - form.value.finishedNum; |
| | | calculateTotalPrice(); |
| | | } |
| | | |
| | | // è®¡ç®æ»ä»· |
| | | const calculateTotalPrice = () => { |
| | | const quantity = Number(form.value.finishedNum ?? 0); |
| | | const unitPrice = Number(form.value.unitPrice ?? 0); |
| | | |
| | | if (quantity > 0 && unitPrice > 0) { |
| | | form.value.totalPrice = (quantity * unitPrice).toFixed(2); |
| | | } else { |
| | | form.value.totalPrice = '0.00'; |
| | | } |
| | | } |
| | | // æäº¤äº§å表å |
| | | const submitForm = () => { |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="客æ·åç§°:"> |
| | | <el-input v-model="searchForm.customerName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°:"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="æäº§æ¥æ:"> |
| | | <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | </el-form-item> |
| | | <el-form-item label="ç¶æ:"> |
| | | <el-select v-model="searchForm.status" placeholder="è¯·éæ©ç¶æ" style="width: 140px" clearable> |
| | | <el-option label="å¾
ç产" :value="1"></el-option> |
| | | <el-option label="å·²æ¥å·¥" :value="3"></el-option> |
| | | <el-option label="ç产ä¸" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" class="mb10"> |
| | | <el-button type="primary" @click="openForm('add')">ç产æ¥å·¥</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | :expandRowKeys="expandedRowKeys" |
| | | @expand-change="expandChange" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total" |
| | | > |
| | | <template #expand="{ row }"> |
| | | <el-table |
| | | :data="expandData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | v-loading="childrenLoading" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="æ¬æ¬¡ç产æ°é" prop="finishedNum" align="center" width="400"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="scope.row.finishedNum" |
| | | :disabled="!scope.row.editType" |
| | | :precision="2" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | @change="changeNum(scope.row)" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="å¾
ç产æ°é" prop="pendingNum" width="240" align="center"></el-table-column>--> |
| | | <el-table-column label="ç产人" prop="schedulingUserId" width="400"> |
| | | <template #default="scope"> |
| | | <el-select |
| | | v-model="scope.row.schedulingUserId" |
| | | placeholder="éæ©äººå" |
| | | :disabled="!scope.row.editType" |
| | | style="width: 100%;" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" |
| | | /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çäº§æ¥æ" prop="schedulingDate" width="400"> |
| | | <template #default="scope"> |
| | | <el-date-picker |
| | | v-model="scope.row.schedulingDate" |
| | | type="date" |
| | | :disabled="!scope.row.editType" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="60"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="changeEditType(scope.row)" |
| | | v-if="!scope.row.editType" |
| | | :disabled="scope.row.parentStatus === 3" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | @click="saveReceiptPayment(scope.row)" |
| | | v-if="scope.row.editType" |
| | | >ä¿å</el-button |
| | | > |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | </div> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :model="searchForm" |
| | | :inline="true"> |
| | | <el-form-item label="æ¥å·¥äººååç§°:"> |
| | | <el-input v-model="searchForm.nickName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åå·:"> |
| | | <el-input v-model="searchForm.workOrderNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 200px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å·¥åç¶æ:"> |
| | | <el-select v-model="searchForm.workOrderStatus" |
| | | placeholder="è¯·éæ©å·¥åç¶æ" |
| | | style="width: 140px" |
| | | clearable> |
| | | <el-option label="å¾
确认" |
| | | :value="1"></el-option> |
| | | <el-option label="å¾
ç产" |
| | | :value="2"></el-option> |
| | | <el-option label="ç产ä¸" |
| | | :value="3"></el-option> |
| | | <el-option label="å·²ç产" |
| | | :value="4"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div style="text-align: right" |
| | | class="mb10"> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">ç产æ¥å·¥</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | :expandRowKeys="expandedRowKeys" |
| | | @expand-change="expandChange" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :total="page.total"> |
| | | <template #expand="{ row }"> |
| | | <el-table :data="expandData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | v-loading="childrenLoading"> |
| | | <el-table-column align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" /> |
| | | <el-table-column label="æ¬æ¬¡ç产æ°é" |
| | | prop="finishedNum" |
| | | align="center" |
| | | width="400"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" |
| | | :min="0" |
| | | style="width: 100%" |
| | | v-model="scope.row.finishedNum" |
| | | :disabled="!scope.row.editType" |
| | | :precision="2" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | @change="changeNum(scope.row)" /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="å¾
ç产æ°é" prop="pendingNum" width="240" align="center"></el-table-column>--> |
| | | <el-table-column label="ç产人" |
| | | prop="schedulingUserId" |
| | | width="400"> |
| | | <template #default="scope"> |
| | | <el-select v-model="scope.row.schedulingUserId" |
| | | placeholder="éæ©äººå" |
| | | :disabled="!scope.row.editType" |
| | | style="width: 100%;"> |
| | | <el-option v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="çäº§æ¥æ" |
| | | prop="schedulingDate" |
| | | width="400"> |
| | | <template #default="scope"> |
| | | <el-date-picker v-model="scope.row.schedulingDate" |
| | | type="date" |
| | | :disabled="!scope.row.editType" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" |
| | | width="60"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="changeEditType(scope.row)" |
| | | v-if="!scope.row.editType" |
| | | :disabled="scope.row.parentStatus === 3">ç¼è¾</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | size="small" |
| | | @click="saveReceiptPayment(scope.row)" |
| | | v-if="scope.row.editType">ä¿å</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery"></form-dia> |
| | | <input-modal v-if="isShowInput" |
| | | v-model:visible="isShowInput" |
| | | :production-product-main-id="isShowingId" /> |
| | | <output-modal v-if="isShowOutput" |
| | | v-model:visible="isShowOutput" |
| | | :production-product-main-id="isShowingId" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import FormDia from "@/views/productionManagement/productionReporting/components/formDia.vue"; |
| | | import {staffJoinDel, staffJoinListPage} from "@/api/personnelManagement/onboarding.js"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | productionReportUpdate, |
| | | workListPage, |
| | | workListPageById |
| | | } from "@/api/productionManagement/productionReporting.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { onMounted, ref } from "vue"; |
| | | import FormDia from "@/views/productionManagement/productionReporting/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | productionReportUpdate, |
| | | workListPageById, |
| | | productionReportDelete, |
| | | } from "@/api/productionManagement/productionReporting.js"; |
| | | import { productionProductMainListPage } from "@/api/productionManagement/productionProductMain.js"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user.js"; |
| | | import InputModal from "@/views/productionManagement/productionReporting/Input.vue"; |
| | | import OutputModal from "@/views/productionManagement/productionReporting/Output.vue"; |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | staffName: "", |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const expandedRowKeys = ref([]); |
| | | const expandData = ref([]); |
| | | const userList = ref([]) |
| | | const tableColumn = ref([ |
| | | { |
| | | type: "expand", |
| | | dataType: "slot", |
| | | slot: "expand", |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: (params) => { |
| | | if (params == 3) { |
| | | return "å·²æ¥å·¥"; |
| | | } else if (params == 1) { |
| | | return "å¾
ç产"; |
| | | } else { |
| | | return 'ç产ä¸'; |
| | | } |
| | | }, |
| | | formatType: (params) => { |
| | | if (params == 3) { |
| | | return "success"; |
| | | } else if (params == 1) { |
| | | return "primary"; |
| | | } else { |
| | | return 'warning'; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "æäº§æ¥æ", |
| | | prop: "schedulingDate", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æäº§äºº", |
| | | prop: "schedulingUserName", |
| | | }, |
| | | { |
| | | label: "ååå·", |
| | | prop: "salesContractNo", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: 200, |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:300 |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productCategory", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "specificationModel", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "process", |
| | | }, |
| | | { |
| | | label: "æäº§æ°é", |
| | | prop: "schedulingNum", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "ç产æ°é", |
| | | prop: "finishedNum", |
| | | width: 100, |
| | | }, |
| | | { |
| | | label: "å¾
ç产æ°é", |
| | | prop: "pendingFinishNum", |
| | | width: 100, |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const childrenLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const formDia = ref() |
| | | const { proxy } = getCurrentInstance() |
| | | const data = reactive({ |
| | | searchForm: { |
| | | nickName: "", |
| | | workOrderNo: "", |
| | | workOrderStatus: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const expandedRowKeys = ref([]); |
| | | const expandData = ref([]); |
| | | const userList = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "æ¥å·¥åå·", |
| | | prop: "productNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ¥å·¥äººå", |
| | | prop: "nickName", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "å·¥åç¼å·", |
| | | prop: "workOrderNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "æ¥å·¥ç¶æ", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | if (params == 3) { |
| | | return "å·²æ¥å·¥"; |
| | | } else if (params == 1) { |
| | | return "å¾
ç产"; |
| | | } else { |
| | | return "ç产ä¸"; |
| | | } |
| | | }, |
| | | formatType: params => { |
| | | if (params == 3) { |
| | | return "success"; |
| | | } else if (params == 1) { |
| | | return "primary"; |
| | | } else { |
| | | return "warning"; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | label: "å·¥åç¶æ", |
| | | prop: "workOrderStatus", |
| | | dataType: "tag", |
| | | formatData: params => { |
| | | switch (params) { |
| | | case "1": |
| | | return "å¾
确认"; |
| | | case "2": |
| | | return "å¾
ç产"; |
| | | case "3": |
| | | return "ç产ä¸"; |
| | | case "4": |
| | | return "å·²ç产"; |
| | | default: |
| | | return ""; |
| | | } |
| | | }, |
| | | formatType: params => { |
| | | switch (params) { |
| | | case "1": |
| | | return "primary"; |
| | | case "2": |
| | | return "info"; |
| | | case "3": |
| | | return "warning"; |
| | | case "4": |
| | | return "success"; |
| | | default: |
| | | return ""; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 200, |
| | | operation: [ |
| | | { |
| | | name: "æ¥çæå
¥", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showInput(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥ç产åº", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showOutput(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å é¤", |
| | | type: "danger", |
| | | clickFun: row => { |
| | | deleteReport(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const childrenLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const formDia = ref(); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const changeDaterange = (value) => { |
| | | if (value) { |
| | | searchForm.value.entryDateStart = value[0]; |
| | | searchForm.value.entryDateEnd = value[1]; |
| | | } else { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined |
| | | expandedRowKeys.value = [] |
| | | workListPage(params).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | pendingFinishNum: (Number(item.schedulingNum) || 0) - (Number(item.finishedNum) || 0) |
| | | })); |
| | | page.total = res.data.total; |
| | | }).catch(err => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // å±å¼è¡ |
| | | const expandChange = (row, expandedRows) => { |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | if (expandedRows.length > 0) { |
| | | nextTick(() => { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | childrenLoading.value = true; |
| | | workListPageById({ id: row.id }).then((res) => { |
| | | childrenLoading.value = false; |
| | | const index = tableData.value.findIndex((item) => item.id === row.id); |
| | | if (index > -1) { |
| | | expandData.value = res.data.map(item => ({ |
| | | ...item, |
| | | pendingNum: (Number(item.schedulingNum) || 0) - (Number(item.finishedNum) || 0), |
| | | parentStatus: row.status // æ°å¢ç¶è¡¨ç¶æ |
| | | })); |
| | | } |
| | | expandedRowKeys.value.push(row.id); |
| | | }); |
| | | } catch (error) { |
| | | childrenLoading.value = false; |
| | | console.log(error); |
| | | } |
| | | }) |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | }; |
| | | const changeNum = (row) => { |
| | | // æ¾å°ç¶è¡¨æ ¼æ°æ® |
| | | const parentRow = tableData.value.find(item => item.id === expandedRowKeys.value[0]); |
| | | // è®¡ç®ææåè¡¨æ ¼ finishedNum çæ»å |
| | | const totalFinishedNum = expandData.value.reduce((sum, item) => sum + (Number(item.finishedNum) || 0), 0); |
| | | // ç¶è¡¨æ ¼çæäº§æ°é |
| | | const schedulingNum = parentRow ? Number(parentRow.schedulingNum) : 0; |
| | | |
| | | if (totalFinishedNum > schedulingNum) { |
| | | // åéæ¬æ¬¡è¾å
¥ |
| | | row.finishedNum = schedulingNum - (totalFinishedNum - Number(row.finishedNum)); |
| | | proxy.$modal.msgWarning('æææ¬æ¬¡ç产æ°éä¹åä¸å¯å¤§äºæäº§æ°é'); |
| | | } |
| | | row.pendingNum = row.schedulingNum - row.finishedNum; |
| | | } |
| | | // ç¼è¾ä¿®æ¹ç¶æ |
| | | const changeEditType = (row) => { |
| | | row.editType = !row.editType; |
| | | }; |
| | | // ä¿åè®°å½ |
| | | const saveReceiptPayment = (row) => { |
| | | productionReportUpdate(row).then((res) => { |
| | | row.editType = !row.editType; |
| | | getList(); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "finishedNum" |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$message.error("è¯·éæ©ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | if (selectedRows.value[0].pendingFinishNum == 0) { |
| | | proxy.$message.warning("æ é忥工"); |
| | | return; |
| | | } |
| | | nextTick(() => { |
| | | const rowInfo = type === 'add' ? selectedRows.value[0] : row |
| | | formDia.value?.openDialog(type, rowInfo) |
| | | }) |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const changeDaterange = value => { |
| | | if (value) { |
| | | searchForm.value.entryDateStart = value[0]; |
| | | searchForm.value.entryDateEnd = value[1]; |
| | | } else { |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | const deleteReport = row => { |
| | | ElMessageBox.confirm("ç¡®å®å é¤è¯¥æ¥å·¥åï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | productionReportDelete({ id: row.id }).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | } else { |
| | | ElMessageBox.alert(res.msg || "å é¤å¤±è´¥", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | params.entryDate = undefined; |
| | | expandedRowKeys.value = []; |
| | | productionProductMainListPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records.map(item => ({ |
| | | ...item, |
| | | pendingFinishNum: |
| | | (Number(item.schedulingNum) || 0) - (Number(item.finishedNum) || 0), |
| | | })); |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // å±å¼è¡ |
| | | const expandChange = (row, expandedRows) => { |
| | | userListNoPageByTenantId().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | if (expandedRows.length > 0) { |
| | | nextTick(() => { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | childrenLoading.value = true; |
| | | workListPageById({ id: row.id }).then(res => { |
| | | childrenLoading.value = false; |
| | | const index = tableData.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | expandData.value = res.data.map(item => ({ |
| | | ...item, |
| | | pendingNum: |
| | | (Number(item.schedulingNum) || 0) - |
| | | (Number(item.finishedNum) || 0), |
| | | parentStatus: row.status, // æ°å¢ç¶è¡¨ç¶æ |
| | | })); |
| | | } |
| | | expandedRowKeys.value.push(row.id); |
| | | }); |
| | | } catch (error) { |
| | | childrenLoading.value = false; |
| | | console.log(error); |
| | | } |
| | | }); |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | }; |
| | | const changeNum = row => { |
| | | // æ¾å°ç¶è¡¨æ ¼æ°æ® |
| | | const parentRow = tableData.value.find( |
| | | item => item.id === expandedRowKeys.value[0] |
| | | ); |
| | | // è®¡ç®ææåè¡¨æ ¼ finishedNum çæ»å |
| | | const totalFinishedNum = expandData.value.reduce( |
| | | (sum, item) => sum + (Number(item.finishedNum) || 0), |
| | | 0 |
| | | ); |
| | | // ç¶è¡¨æ ¼çæäº§æ°é |
| | | const schedulingNum = parentRow ? Number(parentRow.schedulingNum) : 0; |
| | | |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | staffJoinDel(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/work/export", {}, "ç产æ¥å·¥.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | if (totalFinishedNum > schedulingNum) { |
| | | // åéæ¬æ¬¡è¾å
¥ |
| | | row.finishedNum = |
| | | schedulingNum - (totalFinishedNum - Number(row.finishedNum)); |
| | | proxy.$modal.msgWarning("æææ¬æ¬¡ç产æ°éä¹åä¸å¯å¤§äºæäº§æ°é"); |
| | | } |
| | | row.pendingNum = row.schedulingNum - row.finishedNum; |
| | | }; |
| | | // ç¼è¾ä¿®æ¹ç¶æ |
| | | const changeEditType = row => { |
| | | row.editType = !row.editType; |
| | | }; |
| | | // ä¿åè®°å½ |
| | | const saveReceiptPayment = row => { |
| | | productionReportUpdate(row).then(res => { |
| | | row.editType = !row.editType; |
| | | getList(); |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const summarizeMainTable = param => { |
| | | return proxy.summarizeTable(param, ["finishedNum"]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | if (selectedRows.value.length !== 1) { |
| | | proxy.$message.error("è¯·éæ©ä¸æ¡æ°æ®"); |
| | | return; |
| | | } |
| | | if (selectedRows.value[0].pendingFinishNum == 0) { |
| | | proxy.$message.warning("æ é忥工"); |
| | | return; |
| | | } |
| | | nextTick(() => { |
| | | const rowInfo = type === "add" ? selectedRows.value[0] : row; |
| | | formDia.value?.openDialog(type, rowInfo); |
| | | }); |
| | | }; |
| | | |
| | | // æå¼æå
¥æ¨¡ææ¡ |
| | | const isShowInput = ref(false); |
| | | const isShowingId = ref(0); |
| | | const showInput = row => { |
| | | isShowInput.value = true; |
| | | isShowingId.value = row.id; |
| | | }; |
| | | |
| | | // æå¼äº§åºæ¨¡ææ¡ |
| | | const isShowOutput = ref(false); |
| | | const showOutput = row => { |
| | | isShowOutput.value = true; |
| | | isShowingId.value = row.id; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/work/export", {}, "ç产æ¥å·¥.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div class="search-row"> |
| | | <div class="search-item"> |
| | | <span class="search_title">å·¥åç¼å·ï¼</span> |
| | | <el-input v-model="searchForm.workOrderNo" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" /> |
| | | </div> |
| | | <div class="search-item"> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æç´¢</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination"></PIMTable> |
| | | </div> |
| | | <el-dialog v-model="editDialogVisible" |
| | | title="ç¼è¾æ¶é´" |
| | | width="500px"> |
| | | <el-form :model="editrow" |
| | | label-width="120px"> |
| | | <el-form-item label="计åå¼å§æ¶é´"> |
| | | <el-date-picker v-model="editrow.planStartTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | | <el-form-item label="计åç»ææ¶é´"> |
| | | <el-date-picker v-model="editrow.planEndTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
å¼å§æ¶é´"> |
| | | <el-date-picker v-model="editrow.actualStartTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
ç»ææ¶é´"> |
| | | <el-date-picker v-model="editrow.actualEndTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="editDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleUpdate">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | <el-dialog v-model="transferCardVisible" |
| | | title="æµè½¬å¡" |
| | | width="1000px"> |
| | | <div class="transfer-card-title">å·¥åæµè½¬å¡</div> |
| | | <div class="transfer-card-container"> |
| | | <div class="transfer-card-info"> |
| | | <div class="info-group"> |
| | | <div class="info-item"> |
| | | <span class="info-label">å·¥åç¼å·</span> |
| | | <span class="info-value">{{ transferCardRowData.workOrderNo }}</span> |
| | | </div> |
| | | <!-- <div class="info-item"> |
| | | <span class="info-label">产åç¼å·</span> |
| | | <span class="info-value">{{ transferCardRowData.productNo }}</span> |
| | | </div> --> |
| | | <div class="info-item"> |
| | | <span class="info-label">产ååç§°</span> |
| | | <span class="info-value">{{ transferCardRowData.productName }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">产åè§æ ¼</span> |
| | | <span class="info-value">{{ transferCardRowData.model }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">å·¥åç¶æ</span> |
| | | <span class="info-value">{{ |
| | | transferCardRowData.status === 1 ? 'å¾
确认' : |
| | | transferCardRowData.status === 2 ? 'å¾
ç产' : |
| | | transferCardRowData.status === 3 ? 'ç产ä¸' : |
| | | transferCardRowData.status === 4 ? 'å·²ç产' : |
| | | transferCardRowData.status |
| | | }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">计åå¼å§æ¶é´</span> |
| | | <span class="info-value">{{ transferCardRowData.planStartTime }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">计åç»ææ¶é´</span> |
| | | <span class="info-value">{{ transferCardRowData.planEndTime }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">夿³¨</span> |
| | | <span class="info-value">{{ transferCardRowData.remark }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-group"> |
| | | <div class="info-item"> |
| | | <span class="info-label"> </span> |
| | | <span class="info-value"> </span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">è®¡åæ°é</span> |
| | | <span class="info-value">{{ transferCardRowData.planQuantity }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">è¯åæ°é</span> |
| | | <span class="info-value">0</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">ä¸è¯åæ°</span> |
| | | <span class="info-value">0</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">å®é
å¼å§æ¶é´</span> |
| | | <span class="info-value">{{ transferCardRowData.actualStartTime }}</span> |
| | | </div> |
| | | <div class="info-item"> |
| | | <span class="info-label">å®é
ç»ææ¶é´</span> |
| | | <span class="info-value">{{ transferCardRowData.actualEndTime }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="transfer-card-qr"> |
| | | <div class="qr-container"> |
| | | <img :src="transferCardQrUrl" |
| | | alt="æµè½¬å¡äºç»´ç " |
| | | style="width: 200px; height: 200px;" /> |
| | | <!-- <div class="qr-tip" |
| | | style="margin-top: 10px; text-align: center;">æµè½¬å¡äºç»´ç </div> --> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="print-button-container" |
| | | style=" text-align: center; |
| | | margin-bottom: 40px;"> |
| | | <el-button type="primary" |
| | | style="margin-top: 20px;" |
| | | @click="printTransferCard">æå°æµè½¬å¡</el-button> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog v-model="reportDialogVisible" |
| | | title="æ¥å·¥" |
| | | width="500px"> |
| | | <el-form :model="reportForm" |
| | | label-width="120px"> |
| | | <el-form-item label="å¾
ç产æ°é"> |
| | | <el-input v-model="reportForm.remainingQuantity" |
| | | readonly |
| | | style="width: 300px" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¬æ¬¡ç产æ°é"> |
| | | <el-input v-model.number="reportForm.quantity" |
| | | type="number" |
| | | min="1" |
| | | style="width: 300px" |
| | | placeholder="请è¾å
¥æ¬æ¬¡ç产æ°é" /> |
| | | </el-form-item> |
| | | <el-form-item label="çç»ä¿¡æ¯"> |
| | | <el-input v-model="reportForm.userName" |
| | | style="width: 300px" |
| | | readonly |
| | | placeholder="请è¾å
¥çç»ä¿¡æ¯" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="reportDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" |
| | | @click="handleReport">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | productWorkOrderPage, |
| | | updateProductWorkOrder, |
| | | addProductMain, |
| | | } from "@/api/productionManagement/workOrder.js"; |
| | | import { getUserProfile } from "@/api/system/user.js"; |
| | | import QRCode from "qrcode"; |
| | | import { getCurrentInstance, reactive, toRefs } from "vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "å·¥åç¼å·", |
| | | prop: "workOrderNo", |
| | | }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | | prop: "model", |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | }, |
| | | { |
| | | label: "å·¥åºåç§°", |
| | | prop: "processName", |
| | | }, |
| | | { |
| | | label: "计åå¼å§æ¶é´", |
| | | prop: "planStartTime", |
| | | }, |
| | | { |
| | | label: "计åç»ææ¶é´", |
| | | prop: "planEndTime", |
| | | }, |
| | | { |
| | | label: "å®é
å¼å§æ¶é´", |
| | | prop: "actualStartTime", |
| | | }, |
| | | { |
| | | label: "å®é
ç»ææ¶é´", |
| | | prop: "actualEndTime", |
| | | }, |
| | | { |
| | | label: "æä½", |
| | | width: "200", |
| | | align: "center", |
| | | dataType: "action", |
| | | fixed: "right", |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | clickFun: row => { |
| | | handleEdit(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æµè½¬å¡", |
| | | clickFun: row => { |
| | | showTransferCard(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥å·¥", |
| | | clickFun: row => { |
| | | showReportDialog(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const qrRowData = ref(null); |
| | | const editDialogVisible = ref(false); |
| | | const transferCardVisible = ref(false); |
| | | const transferCardData = ref([]); |
| | | const transferCardQrUrl = ref(""); |
| | | const transferCardRowData = ref(null); |
| | | const reportDialogVisible = ref(false); |
| | | const reportForm = reactive({ |
| | | remainingQuantity: 0, |
| | | quantity: 0, |
| | | userName: "", |
| | | workOrderId: "", |
| | | reportWork: "", |
| | | productProcessRouteItemId: "", |
| | | userId: "", |
| | | productMainId: null, |
| | | }); |
| | | const currentReportRowData = ref(null); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | workOrderNo: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | let editrow = ref(null); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | productWorkOrderPage(params) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const showTransferCard = async row => { |
| | | transferCardRowData.value = row; |
| | | const qrContent = |
| | | proxy.javaApi + "/work-order?orderRow=" + JSON.stringify(row); |
| | | console.log(qrContent, "qrContent"); |
| | | |
| | | transferCardQrUrl.value = await QRCode.toDataURL(qrContent); |
| | | transferCardVisible.value = true; |
| | | }; |
| | | |
| | | const printTransferCard = () => { |
| | | window.print(); |
| | | }; |
| | | |
| | | const handleEdit = row => { |
| | | editrow.value = JSON.parse(JSON.stringify(row)); |
| | | editDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleUpdate = () => { |
| | | updateProductWorkOrder(editrow.value) |
| | | .then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | editDialogVisible.value = false; |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | ElMessageBox.alert("ä¿®æ¹å¤±è´¥", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const showReportDialog = row => { |
| | | currentReportRowData.value = row; |
| | | reportForm.remainingQuantity = 1; |
| | | reportForm.quantity = row.quantity; |
| | | reportForm.productProcessRouteItemId = row.productProcessRouteItemId; |
| | | reportForm.workOrderId = row.id; |
| | | reportForm.reportWork = row.reportWork; |
| | | reportForm.productMainId = row.productMainId; |
| | | // è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | |
| | | reportDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleReport = () => { |
| | | if (!reportForm.quantity || reportForm.quantity <= 0) { |
| | | ElMessageBox.alert("请è¾å
¥ææçæ¬æ¬¡ç产æ°é", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | return; |
| | | } |
| | | if (reportForm.quantity > reportForm.remainingQuantity) { |
| | | ElMessageBox.alert("æ¬æ¬¡ç产æ°éä¸è½è¶
è¿å¾
ç产æ°é", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | return; |
| | | } |
| | | // console.log(reportForm); |
| | | addProductMain(reportForm).then(res => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess("æ¥å·¥æå"); |
| | | reportDialogVisible.value = false; |
| | | getList(); |
| | | } else { |
| | | ElMessageBox.alert(res.msg || "æ¥å·¥å¤±è´¥", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getUserProfile() |
| | | .then(res => { |
| | | if (res.code === 200) { |
| | | reportForm.userName = res.data.userName; |
| | | reportForm.userId = res.data.userId; |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | console.error("è·åç¨æ·ä¿¡æ¯å¤±è´¥", err); |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .search_form { |
| | | margin-bottom: 20px; |
| | | .search-row { |
| | | display: flex; |
| | | gap: 20px; |
| | | align-items: center; |
| | | .search-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .transfer-card-title { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | text-align: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .transfer-card-container { |
| | | display: flex; |
| | | gap: 20px; |
| | | height: 350px; |
| | | .transfer-card-info { |
| | | flex: 1; |
| | | overflow: auto; |
| | | .info-group { |
| | | width: 50%; |
| | | float: left; |
| | | } |
| | | .info-item { |
| | | display: flex; |
| | | margin-bottom: 15px; |
| | | .info-label { |
| | | width: 120px; |
| | | font-weight: bold; |
| | | margin-right: 20px; |
| | | } |
| | | .info-value { |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | .transfer-card-qr { |
| | | width: 240px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | } |
| | | } |
| | | </style> |
| | | |
| | | <style lang="scss"> |
| | | @media print { |
| | | @page { |
| | | size: landscape; |
| | | } |
| | | body * { |
| | | visibility: hidden; |
| | | } |
| | | .el-dialog__wrapper, |
| | | .el-dialog, |
| | | .el-dialog__body, |
| | | .transfer-card-title, |
| | | .transfer-card-container, |
| | | .transfer-card-container *, |
| | | .info-item, |
| | | .info-label, |
| | | .info-value { |
| | | visibility: visible; |
| | | } |
| | | .print-button-container { |
| | | visibility: hidden; |
| | | } |
| | | .el-dialog__wrapper { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | margin: 0; |
| | | } |
| | | .el-dialog { |
| | | width: 100% !important; |
| | | max-width: 800px; |
| | | margin: 0 auto !important; |
| | | } |
| | | .el-dialog__header, |
| | | .el-dialog__footer { |
| | | display: none; |
| | | } |
| | | .el-dialog__body { |
| | | padding: 20px; |
| | | } |
| | | .transfer-card-container { |
| | | height: auto; |
| | | display: flex; |
| | | gap: 20px; |
| | | } |
| | | .transfer-card-info { |
| | | flex: 1; |
| | | .info-group { |
| | | width: 100%; |
| | | float: none; |
| | | margin-bottom: 20px; |
| | | } |
| | | .info-item { |
| | | display: flex; |
| | | margin-bottom: 10px; |
| | | .info-label { |
| | | width: 100px; |
| | | font-weight: bold; |
| | | margin-right: 15px; |
| | | white-space: nowrap; |
| | | } |
| | | .info-value { |
| | | flex: 1; |
| | | word-break: break-word; |
| | | } |
| | | } |
| | | } |
| | | .transfer-card-qr { |
| | | width: 160px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | } |
| | | .qr-container img { |
| | | width: 140px !important; |
| | | height: 140px !important; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | :page="page" |
| | | @pagination="pagination" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | |
| | | currentId.value = row.id; |
| | | getList() |
| | | } |
| | | const paginationSearch = (obj) => { |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | |
| | | const getList = () => { |
| | | qualityInspectFileListPage({inspectId: currentId.value}).then(res => { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | page.total = res.data.total; |
| | | }) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-select v-model="form.checkName" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | </el-select> |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | :page="page" |
| | | @pagination="pagination" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | qualityInspectFileDel, |
| | | qualityInspectFileListPage |
| | | } from "@/api/qualityManagement/qualityInspectFile.js"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | |
| | | currentId.value = row.id; |
| | | getList() |
| | | } |
| | | const paginationSearch = (obj) => { |
| | | |
| | | const getList = () => { |
| | | qualityInspectFileListPage({inspectId: currentId.value}).then(res => { |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | } |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | qualityInspectFileListPage({inspectId: currentId.value}).then(res => { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | }) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ£éªåï¼" prop="checkName"> |
| | | <el-select v-model="form.checkName" placeholder="è¯·éæ©" clearable> |
| | | <el-select v-model="form.checkName" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName"/> |
| | | </el-select> |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | height="500" |
| | | :page="page" |
| | | @pagination="pagination" |
| | | > |
| | | </PIMTable> |
| | | <pagination |
| | | style="margin: 10px 0" |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | |
| | | qualityInspectFileDel, |
| | | qualityInspectFileListPage |
| | | } from "@/api/qualityManagement/qualityInspectFile.js"; |
| | | import Pagination from "@/components/PIMTable/Pagination.vue"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0 |
| | | }); |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | |
| | | currentId.value = row.id; |
| | | getList() |
| | | } |
| | | const paginationSearch = (obj) => { |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | qualityInspectFileListPage({inspectId: currentId.value, ...page}).then(res => { |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | | page.total = res.data.total; |
| | | }) |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 280, |
| | | width: 300, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | |
| | | |
| | | <!-- è´¨éç»è®¡ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">è´¨éç»è®¡</span> |
| | | <span class="panel-title">è¿4æè´¨éç»è®¡</span> |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | |
| | | </div> |
| | | |
| | | <div class="financial-header"> |
| | | <span class="financial-title">è´¢å¡åæ</span> |
| | | <span class="financial-title">è¿4æè´¢å¡åæ</span> |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | |
| | | <div class="panel-item-customers"> |
| | | <div style="display: flex;justify-content: space-between;margin-bottom: 20px;"> |
| | | <div class="section-title">åºæ¶åºä»ç»è®¡</div> |
| | | <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group"> |
| | | <el-radio-button label="æå¨" :value="1" /> |
| | | <el-radio-button label="ææ" :value="2" /> |
| | | <el-radio-button label="æå£åº¦" :value="3" /> |
| | | </el-radio-group> |
| | | <!-- <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">--> |
| | | <!-- <el-radio-button label="æå¨" :value="1" />--> |
| | | <!-- <el-radio-button label="ææ" :value="2" />--> |
| | | <!-- <el-radio-button label="æå£åº¦" :value="3" />--> |
| | | <!-- </el-radio-group>--> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :color="barColors2" |
| | |
| | | |
| | | <!-- 忬¾ä¸å¼ç¥¨åæ --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">忬¾ä¸å¼ç¥¨åæ</span> |
| | | <span class="panel-title">è¿ä¸æå款ä¸å¼ç¥¨åæ</span> |
| | | </div> |
| | | <div class="panel-item-customers" style="padding-top: 60px;"> |
| | | <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries" |
| | |
| | | const barLegend = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['åææä¸åæ ¼æ°', 'è¿ç¨ä¸åæ ¼æ°', 'åºåä¸åæ ¼æ°'] |
| | | data: ['åææåæ ¼æ°', 'è¿ç¨åæ ¼æ°', 'åºä¸åæ ¼æ°'] |
| | | } |
| | | const barLegend1 = { |
| | | show: true, |
| | |
| | | ]) |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: 'åææä¸åæ ¼æ°', |
| | | name: 'åææåæ ¼æ°', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'è¿ç¨ä¸åæ ¼æ°', |
| | | name: 'è¿ç¨åæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'åºåä¸åæ ¼æ°', |
| | | name: 'åºååæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | |
| | | getLedgerPage(params).then((res) => { |
| | | equipmentNum.value = res.data.total |
| | | }); |
| | | getRepairPage(params).then((res) => { |
| | | getRepairPage({...params, status:0}).then((res) => { |
| | | equipmentRepair.value = res.data.total |
| | | }); |
| | | getUpkeepPage(params).then((res) => { |
| | | getUpkeepPage({...params, status:0}).then((res) => { |
| | | equipmentMaintain.value = res.data.total |
| | | }); |
| | | measuringInstrumentListPage(params).then((res) => { |
| | |
| | | // 使ç¨nextTickç¡®ä¿DOMå®å
¨æ¸²æåååå§åå¾è¡¨ |
| | | nextTick(() => { |
| | | // åå§åautofitèªéåº |
| | | autofit.init({ dh: 1080, dw: 1920, el: '.data-dashboard', resize: true }, false) |
| | | autofit.init({ dh: 800, dw: 1280, el: '.data-dashboard', resize: true }, false) |
| | | |
| | | // æ·»å èªå¨æ»å¨å¨ç»ææ - 客æ·ä¿¡æ¯å表 |
| | | const contractList = refContractList.value |
| | |
| | | align: "center", |
| | | prop: "customerName", |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | align: "center", |
| | | prop: "projectName", |
| | | }, |
| | | // { |
| | | // label: "项ç®åç§°", |
| | | // align: "center", |
| | | // prop: "projectName", |
| | | // }, |
| | | { |
| | | label: "ååéé¢", |
| | | align: "center", |
| | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // è®¾ç½®ææ ç鿥æèå´é»è®¤å¼ä¸ºå½å¤© |
| | | const today = dayjs().format('YYYY-MM-DD') |
| | | indicatorFilter.dateRange = [today, today] |
| | | |
| | | nextTick(() => initIndicatorChart()) |
| | | }) |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-dialog> |
| | | <filePreview ref="filePreviewRef" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { delCommonFileInvoiceLedger} from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | | const { proxy } = getCurrentInstance(); |
| | | const filePreviewRef = ref() |
| | | const handleClose = () => { |
| | | dialogVisible.value = false |
| | | } |
| | | const open = (list) => { |
| | | dialogVisible.value = true |
| | | tableData.value = list |
| | | } |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.name(row.url); |
| | | |
| | | } |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'å é¤ç¡®è®¤', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }).then(() => { |
| | | delCommonFileInvoiceLedger([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | | </script> |
| | | |
| | | <style></style> |
| | |
| | | @change="changeDateRange" @clear="clearRange" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æ"> |
| | | <el-date-picker style="width: 100%" v-model="searchForm.createTimeStart" value-format="YYYY-MM-DD" |
| | | <el-date-picker style="width: 100%" v-model="searchForm.createTimeStart" value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD" type="date" placeholder="è¯·éæ©" clearable @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="䏿¾ç¤ºæå票è¡"> |
| | |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="éå®ååå·" prop="salesContractNo" show-overflow-tooltip width="180" /> |
| | | <el-table-column label="客æ·ååå·" prop="customerContractNo" show-overflow-tooltip width="180" /> |
| | | <el-table-column label="客æ·åç§°" prop="customerName" show-overflow-tooltip width="240" /> |
| | | <el-table-column label="项ç®" prop="projectName" width="320" /> |
| | | <!-- <el-table-column label="项ç®" prop="projectName" width="320" />--> |
| | | <el-table-column label="产å大类" prop="productCategory" width="200" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" width="160" show-overflow-tooltip /> |
| | | <el-table-column label="å票å·" prop="invoiceNo" width="200" show-overflow-tooltip /> |
| | |
| | | <el-table-column label="å½å
¥äºº" prop="invoicePerson" show-overflow-tooltip /> |
| | | <el-table-column label="å½å
¥æ¥æ" prop="createTime" show-overflow-tooltip :formatter="formatDate" width="180" /> |
| | | <el-table-column label="å¼ç¥¨æ¥æ" prop="invoiceDate" show-overflow-tooltip width="120" /> |
| | | <el-table-column label="å票" prop="invoiceFileName" width="120" align="center" show-overflow-tooltip fixed="right"> |
| | | <!-- <el-table-column label="å票" prop="invoiceFileName" width="120" align="center" show-overflow-tooltip fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button v-if="scope.row.invoiceFileName" text bg type="primary" |
| | | @click="handleFile(scope.row.commonFiles)"> |
| | | æ¥çéä»¶ |
| | | </el-button> |
| | | <el-button v-else link type="primary" @click="handleDownload(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName"> |
| | | <el-button v-else link type="primary" @click="handleDownload(scope.row)"> |
| | | ä¸ä¼ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table-column> --> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName">ç¼è¾</el-button> |
| | | <el-button link type="primary" size="small" @click="delInvoiceLedger(scope.row)" :disabled="scope.row.invoicePerson !== userStore.nickName">å é¤</el-button> |
| | | <el-button link type="primary" size="small" @click="openForm(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | <el-button link type="primary" size="small" @click="delInvoiceLedger(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | <el-form-item label="éä»¶ææï¼" prop="remark"> |
| | | <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload |
| | | :headers="upload.headers" accept=".pdf" :limit="10" :before-upload="handleBeforeUpload" |
| | | :on-error="handleUploadError" :on-success="handleUploadSuccess" :on-remove="handleRemove"> |
| | | :on-error="handleUploadError" :on-success="handleUploadSuccess"> |
| | | <el-button type="primary">ä¸ä¼ </el-button> |
| | | <template #tip> |
| | | <!-- æä»¶æ ¼å¼æ¯æ docï¼docxï¼xlsï¼xlsxï¼pptï¼pptxï¼pdfï¼txtï¼xmlï¼jpgï¼jpegï¼pngï¼gifï¼bmpï¼rarï¼zipï¼7z--> |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | <FileList ref="fileListRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | commitFile, |
| | | registrationProductPage, |
| | | delInvoiceLedgerByRegProductId, |
| | | } from "../../../api/salesManagement/invoiceLedger.js"; |
| | | } from "@/api/salesManagement/invoiceLedger.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import dayjs from "dayjs"; |
| | | import FileList from "./fileList.vue"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const tableData = ref([]); |
| | |
| | | return parseFloat(cellValue).toFixed(2); |
| | | }; |
| | | const formatDate = (row, column, cellValue) => { |
| | | return dayjs(cellValue).format("YYYY-MM-DD"); |
| | | return dayjs(cellValue).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { invoiceDate, ...rest } = searchForm; |
| | | registrationProductPage({ ...rest, ...page }).then((res) => { |
| | | // å°èå´æ¥æåæ®µä¼ éç»å端 |
| | | const params = { ...rest, ...page }; |
| | | // ç§»é¤å¼ç¥¨æ¥æçé»è®¤å¼è®¾ç½®ï¼åªä¿çèå´æ¥æå段 |
| | | delete params.invoiceDate; |
| | | registrationProductPage(params).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | total.value = res.data.total; |
| | |
| | | invoiceLedgerProductInfo({ id: row.id }).then((res) => { |
| | | form.value = { ...res.data }; |
| | | fileList.value = res.data.fileList; |
| | | // ä¿åticketRegistrationIdå°è¡¨åæ°æ®ä¸ |
| | | if (row.ticketRegistrationId) { |
| | | form.value.ticketRegistrationId = row.ticketRegistrationId; |
| | | } |
| | | if (!form.value.invoicePerson) { |
| | | form.value.invoicePerson = userStore.nickName; |
| | | form.value.entryDate = getCurrentDate(); |
| | | // ç§»é¤å½å
¥æ¥æé»è®¤å¼è®¾ç½®ï¼åªå¤çèå´æ¥æå段 |
| | | } |
| | | if (!form.value.invoiceDate) { |
| | | form.value.invoiceDate = getCurrentDate(); |
| | | } |
| | | // ç§»é¤å¼ç¥¨æ¥æé»è®¤å¼è®¾ç½®ï¼åªå¤çèå´æ¥æå段 |
| | | }); |
| | | dialogFormVisible.value = true; |
| | | }; |
| | |
| | | }; |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | console.log("file", file); |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (file.size > 1024 * 1024 * 10) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB!"); |
| | |
| | | proxy.$modal.msgError("æä»¶æ ¼å¼ä¸å¹é
"); |
| | | return false; |
| | | } |
| | | console.log('handleBeforeUpload'); |
| | | proxy.$modal.loading("æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å..."); |
| | | return true; |
| | | } |
| | |
| | | // ä¸ä¼ æååè° |
| | | function handleUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | console.log('handleUploadSuccess'); |
| | | if (res.code === 200) { |
| | | proxy.$refs["fileUpload"].handleRemove(file); |
| | | fileList.value.push(res.data); |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | // å°ä¸ä¼ æåçæä»¶ä¿¡æ¯æ·»å å°fileListä¸ |
| | | const fileInfo = { |
| | | name: file.name, |
| | | url: res.data.url || file.response?.data?.url || file.url, |
| | | response: file.response |
| | | }; |
| | | // æ£æ¥æ¯å¦å·²åå¨ç¸åæä»¶ï¼é¿å
é夿·»å |
| | | const existingFileIndex = fileList.value.findIndex(f => f.name === fileInfo.name); |
| | | if (existingFileIndex === -1) { |
| | | fileList.value.push(fileInfo); |
| | | } else { |
| | | fileList.value[existingFileIndex] = fileInfo; |
| | | } |
| | | // ç¡®ä¿è¡¨åæ°æ®ä¸çfileList乿´æ° |
| | | form.value.fileList = fileList.value; |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | function handleRemove(file) { |
| | | let index = fileList.value.findIndex((item) => item.url === file.url); |
| | | if (index > -1) { |
| | | fileList.value.splice(index, 1); |
| | | } |
| | | } |
| | | // æäº¤è¡¨å |
| | |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // æå¼éä»¶ä¸ä¼ å¼¹çª |
| | | const handleDownload = (val) => { |
| | | fileList.value = []; |
| | | uploadModal.value = true; |
| | | currentId.value = val.id; |
| | | }; |
| | | |
| | | // 确认æä»¶ä¸ä¼ |
| | |
| | | getList(); |
| | | }; |
| | | |
| | | //éä»¶ç¸å
³ |
| | | const fileListRef = ref(null) |
| | | //æ¥çéä»¶ |
| | | const downLoadFile = (row) => { |
| | | invoiceLedgerProductInfo({ id: row.id }).then((res) => { |
| | | fileListRef.value.open(res.data.fileList) |
| | | }); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 设置å¼ç¥¨æ¥æèå´é»è®¤å¼ä¸ºå½å¤© |
| | | const today = dayjs().format('YYYY-MM-DD'); |
| | | searchForm.invoiceDate = [today, today]; |
| | | // 设置èå´æ¥æå段çèµ·å§åç»ææ¶é´ |
| | | searchForm.invoiceDateStart = today; |
| | | searchForm.invoiceDateEnd = today; |
| | | getList(); |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :inline="true" :model="searchForm"> |
| | | <el-form-item label="客æ·åç§°"> |
| | | <el-input |
| | | v-model="searchForm.customerName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥åç§°æç´¢" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·ååå·"> |
| | | <el-input |
| | | v-model="searchForm.customerContractNo" |
| | | placeholder="请è¾å
¥å®¢æ·ååå·" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°"> |
| | | <el-input |
| | | v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥é¡¹ç®åç§°" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-checkbox |
| | | v-model="searchForm.status" |
| | | label="䏿¾ç¤ºæªå¼ç¥¨éé¢ä¸º0" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> æç´¢ </el-button> |
| | | <el-button @click="resetForm"> éç½® </el-button> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="flex justify-between"> |
| | | <div></div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm" style="margin-bottom: 8px"> |
| | | æ°å¢ç»è®° |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | :border="true" |
| | | height="calc(100vh - 21em)" |
| | | v-loading="tableLoading" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <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" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å¼ç¥¨æ°" |
| | | prop="invoiceNum" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å¼ç¥¨éé¢(å
)" |
| | | prop="invoiceAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨æ°" |
| | | prop="noInvoiceNum" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="客æ·ååå·" |
| | | prop="customerContractNo" |
| | | width="200" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | label="客æ·åç§°" |
| | | prop="customerName" |
| | | show-overflow-tooltip |
| | | width="240" |
| | | /> |
| | | <el-table-column label="ä¸å¡å" prop="salesman" show-overflow-tooltip width="90"/> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | prop="projectName" |
| | | show-overflow-tooltip |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="220" |
| | | |
| | | /> |
| | | <el-table-column |
| | | label="å·²å¼ç¥¨éé¢(å
)" |
| | | prop="invoiceTotal" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="120" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmountTotal" |
| | | show-overflow-tooltip |
| | | width="120" |
| | | > |
| | | <template #default="{ row, column }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.noInvoiceAmountTotal) }} |
| | | </el-text> |
| | | </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" |
| | | /> |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="æ°å¢å¼ç¥¨ç»è®°é¡µé¢" |
| | | width="85%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input v-model="form.salesContractNo" disabled></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·åç§°ï¼" prop="customerName"> |
| | | <el-input |
| | | v-model="form.customerName" |
| | | placeholder="èªå¨å¡«å
" |
| | | disabled |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å¡åï¼" prop="salesman"> |
| | | <el-input |
| | | v-model="form.salesman" |
| | | placeholder="èªå¨å¡«å
" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input |
| | | v-model="form.projectName" |
| | | placeholder="èªå¨å¡«å
" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äºº" prop="createUer"> |
| | | <el-input v-model="form.createUer" placeholder="请è¾å
¥å½å
¥äºº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æ" prop="issueDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.issueDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="createTime"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.createTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ç ï¼" prop="invoiceNo"> |
| | | <el-input |
| | | v-model="form.invoiceNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> </el-form-item> |
| | | </el-row> |
| | | <el-table |
| | | :data="productData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <el-form :inline="true" :model="searchForm"> |
| | | <el-form-item label="客æ·åç§°"> |
| | | <el-input |
| | | v-model="searchForm.customerName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥åç§°æç´¢" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-checkbox |
| | | v-model="searchForm.status" |
| | | label="䏿¾ç¤ºæªå¼ç¥¨éé¢ä¸º0" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> æç´¢ </el-button> |
| | | <el-button @click="resetForm"> éç½® </el-button> |
| | | <el-button @click="handleExport" style="margin-right: 10px">导åº</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="flex justify-between"> |
| | | <div></div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm" style="margin-bottom: 8px"> |
| | | æ°å¢ç»è®° |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <el-table |
| | | :data="tableData" |
| | | :border="true" |
| | | height="calc(100vh - 21em)" |
| | | v-loading="tableLoading" |
| | | :expand-row-keys="expandedRowKeys" |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeMainTable" |
| | | @expand-change="expandChange" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <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" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å¼ç¥¨æ°" |
| | | prop="invoiceNum" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å¼ç¥¨éé¢(å
)" |
| | | prop="invoiceAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨æ°" |
| | | prop="noInvoiceNum" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmount" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column |
| | | label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | show-overflow-tooltip |
| | | /> |
| | | <!-- <el-table-column--> |
| | | <!-- label="客æ·ååå·"--> |
| | | <!-- prop="customerContractNo"--> |
| | | <!-- width="200"--> |
| | | <!-- show-overflow-tooltip--> |
| | | <!-- />--> |
| | | <el-table-column |
| | | label="客æ·åç§°" |
| | | prop="customerName" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column label="ä¸å¡å" prop="salesman" show-overflow-tooltip/> |
| | | <el-table-column |
| | | label="ååéé¢(å
)" |
| | | prop="contractAmount" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | |
| | | /> |
| | | <el-table-column |
| | | label="å·²å¼ç¥¨éé¢(å
)" |
| | | prop="invoiceTotal" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmountTotal" |
| | | show-overflow-tooltip |
| | | width="120" |
| | | > |
| | | <template #default="{ row, column }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.noInvoiceAmountTotal) }} |
| | | </el-text> |
| | | </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" |
| | | /> |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="æ°å¢å¼ç¥¨ç»è®°é¡µé¢" |
| | | width="85%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éå®ååå·ï¼" prop="salesContractNo"> |
| | | <el-input v-model="form.salesContractNo" disabled placeholder="å¤ååæ¹éå¤çï¼å
·ä½ååå·è§äº§åå表ï¼"></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·åç§°ï¼" prop="customerName"> |
| | | <el-input |
| | | v-model="form.customerName" |
| | | placeholder="èªå¨å¡«å
" |
| | | disabled |
| | | ></el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å¡åï¼" prop="salesman"> |
| | | <el-input |
| | | v-model="form.salesman" |
| | | placeholder="èªå¨å¡«å
" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äºº" prop="createUer"> |
| | | <el-input v-model="form.createUer" placeholder="请è¾å
¥å½å
¥äºº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æ" prop="issueDate"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.issueDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥æ¥æï¼" prop="createTime"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.createTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ç ï¼" prop="invoiceNo"> |
| | | <el-input |
| | | v-model="form.invoiceNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> </el-form-item> |
| | | </el-row> |
| | | <el-table |
| | | :data="productData" |
| | | border |
| | | show-summary |
| | | :summary-method="summarizeChildrenTable" |
| | | > |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="æå±åå" prop="salesContractNo" width="200"> |
| | | <template #default="{ row }"> |
| | | <el-tag type="primary">{{ row.salesContractNo }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column |
| | | label="è§æ ¼åå·" |
| | | prop="specificationModel" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" width="70" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="80" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="200" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="æ¬æ¬¡å¼ç¥¨æ°" prop="currentInvoiceNum" width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column label="æ¬æ¬¡å¼ç¥¨æ°" prop="currentInvoiceNum" width="180"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.1" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.currentInvoiceNum" |
| | | @change="invoiceNumBlur(scope.row)" |
| | | ></el-input-number> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" |
| | | prop="currentInvoiceAmount" |
| | | width="180" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="scope.row.currentInvoiceNum" |
| | | @change="invoiceNumBlur(scope.row)" |
| | | ></el-input-number> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æ¬æ¬¡å¼ç¥¨éé¢(å
)" |
| | | prop="currentInvoiceAmount" |
| | | width="180" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | :precision="2" |
| | | v-model="scope.row.currentInvoiceAmount" |
| | | @change="invoiceAmountBlur(scope.row)" |
| | | ></el-input-number> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æªå¼ç¥¨æ°" prop="noInvoiceNum" width="120"> |
| | | <template #default="scope"> |
| | | <el-input |
| | | type="number" |
| | | min="0" |
| | | disabled |
| | | v-model="scope.row.noInvoiceNum" |
| | | ></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmount" |
| | | width="200" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input |
| | | type="number" |
| | | min="0" |
| | | disabled |
| | | v-model="scope.row.noInvoiceAmount" |
| | | :formatter="formattedInputNumber" |
| | | :precision="2" |
| | | :step="0.01" |
| | | ></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°äºº" prop="register" width="100"> |
| | | <!-- <template #default="{ row }"> |
| | | <el-input |
| | | v-model="row.register" |
| | | placeholder="请è¾å
¥ç»è®°äºº" |
| | | disabled |
| | | /> |
| | | </template> --> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°æ¥æ" prop="registerDate" width="150"> |
| | | <!-- <template #default="{ row }"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="row.registerDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </template> --> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | v-model="scope.row.currentInvoiceAmount" |
| | | @change="invoiceAmountBlur(scope.row)" |
| | | ></el-input-number> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æªå¼ç¥¨æ°" prop="noInvoiceNum" width="120"> |
| | | <template #default="scope"> |
| | | <el-input |
| | | type="number" |
| | | min="0" |
| | | disabled |
| | | v-model="scope.row.noInvoiceNum" |
| | | ></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="æªå¼ç¥¨éé¢(å
)" |
| | | prop="noInvoiceAmount" |
| | | width="200" |
| | | > |
| | | <template #default="scope"> |
| | | <el-input |
| | | type="number" |
| | | min="0" |
| | | disabled |
| | | v-model="scope.row.noInvoiceAmount" |
| | | :formatter="formattedInputNumber" |
| | | :precision="2" |
| | | :step="0.01" |
| | | ></el-input> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°äºº" prop="register" width="100"> |
| | | <!-- <template #default="{ row }"> |
| | | <el-input |
| | | v-model="row.register" |
| | | placeholder="请è¾å
¥ç»è®°äºº" |
| | | disabled |
| | | /> |
| | | </template> --> |
| | | </el-table-column> |
| | | <el-table-column label="ç»è®°æ¥æ" prop="registerDate" width="150"> |
| | | <!-- <template #default="{ row }"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="row.registerDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </template> --> |
| | | </el-table-column> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | |
| | | import { ElMessageBox } from "element-plus"; |
| | | // import {userListNoPage} from "@/api/system/user.js"; |
| | | import { |
| | | getSalesLedgerWithProducts, |
| | | ledgerListPage, |
| | | productList, |
| | | getSalesLedgerWithProducts, |
| | | ledgerListPage, |
| | | productList, |
| | | } from "@/api/salesManagement/salesLedger.js"; |
| | | import { invoiceRegistrationSave } from "@/api/salesManagement/invoiceRegistration.js"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | current: 1, |
| | | size: 100, |
| | | }); |
| | | const total = ref(0); |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | status: false, |
| | | customerContractNo: undefined, // 客æ·ååå· |
| | | projectName: undefined, // 项ç®åç§° |
| | | createUer: undefined, // ç»è®°äºº |
| | | issueDate: undefined, // å¼ç¥¨æ¥æ |
| | | createTime: undefined, // å½å
¥æ¥æï¼ |
| | | }, |
| | | form: { |
| | | salesLedgerId: "", |
| | | customerName: "", |
| | | salesman: "", |
| | | projectName: "", |
| | | productData: [], |
| | | invoiceNo: "", |
| | | createUer: userStore.nickName, |
| | | issueDate: dayjs().format("YYYY-MM-DD"), |
| | | }, |
| | | rules: { |
| | | salesLedgerId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | createUer: [{ required: true, message: "è¯·éæ©", trigger: "blur" }], |
| | | issueDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | invoiceNo: [{ required: true, message: "请è¾å
¥", trigger: "change" }], |
| | | createTime: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | searchForm: { |
| | | customerName: "", |
| | | status: false, |
| | | customerContractNo: undefined, // 客æ·ååå· |
| | | projectName: undefined, // 项ç®åç§° |
| | | createUer: undefined, // ç»è®°äºº |
| | | issueDate: undefined, // å¼ç¥¨æ¥æ |
| | | createTime: undefined, // å½å
¥æ¥æï¼ |
| | | productCategory: "", |
| | | isInvoice: 1 |
| | | }, |
| | | form: { |
| | | salesLedgerId: "", |
| | | customerName: "", |
| | | salesman: "", |
| | | projectName: "", |
| | | productData: [], |
| | | invoiceNo: "", |
| | | createUer: userStore.nickName, |
| | | issueDate: dayjs().format("YYYY-MM-DD"), |
| | | selectedContractIds: [], // æ°å¢ï¼å卿æéä¸çååID |
| | | isBatch: false // æ°å¢ï¼æ è¯æ¯å¦ä¸ºæ¹éæä½ |
| | | }, |
| | | rules: { |
| | | createUer: [{ required: true, message: "è¯·éæ©", trigger: "blur" }], |
| | | issueDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | invoiceNo: [{ required: true, message: "请è¾å
¥", trigger: "change" }], |
| | | createTime: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | | const { form: searchForm, resetForm } = useFormData(data.searchForm); |
| | | |
| | | const formattedNumber = (row, column, cellValue) => { |
| | | if (cellValue == 0) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } |
| | | if (cellValue) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } else { |
| | | return cellValue; |
| | | } |
| | | if (cellValue == 0) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } |
| | | if (cellValue) { |
| | | return parseFloat(cellValue).toFixed(2); |
| | | } else { |
| | | return cellValue; |
| | | } |
| | | }; |
| | | |
| | | const formattedInputNumber = (value) => { |
| | | return value ? parseFloat(value).toFixed(2) : 0; |
| | | return value ? parseFloat(value).toFixed(2) : 0; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | ledgerListPage({ ...searchForm, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | | total.value = res.total; |
| | | expandedRowKeys.value = []; |
| | | }); |
| | | tableLoading.value = true; |
| | | ledgerListPage({ ...searchForm, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | | total.value = res.total; |
| | | expandedRowKeys.value = []; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | console.log("selection", selection); |
| | | selectedRows.value = selection.filter( |
| | | (item) => item.salesContractNo !== undefined |
| | | ); |
| | | console.log("selection", selection); |
| | | selectedRows.value = selection.filter( |
| | | (item) => item.salesContractNo !== undefined |
| | | ); |
| | | }; |
| | | const expandedRowKeys = ref([]); |
| | | // å±å¼è¡ |
| | | const expandChange = (row, expandedRows) => { |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | productList({ salesLedgerId: row.id, type: 1 }).then((res) => { |
| | | 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); |
| | | } |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | if (expandedRows.length > 0) { |
| | | expandedRowKeys.value = []; |
| | | try { |
| | | productList({ salesLedgerId: row.id, type: 1 }).then((res) => { |
| | | 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); |
| | | } |
| | | } else { |
| | | expandedRowKeys.value = []; |
| | | } |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "contractAmount", |
| | | "invoiceTotal", |
| | | "noInvoiceAmountTotal", |
| | | ]); |
| | | return proxy.summarizeTable(param, [ |
| | | "contractAmount", |
| | | "invoiceTotal", |
| | | "noInvoiceAmountTotal", |
| | | ]); |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = (param) => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | "invoiceNum", |
| | | "invoiceAmount", |
| | | "currentInvoiceAmount", |
| | | "noInvoiceNum", |
| | | "noInvoiceAmount", |
| | | "currentInvoiceNum", |
| | | ]); |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | "invoiceNum", |
| | | "invoiceAmount", |
| | | "currentInvoiceAmount", |
| | | "noInvoiceNum", |
| | | "noInvoiceAmount", |
| | | "currentInvoiceNum", |
| | | ]); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = () => { |
| | | // 夿æ¯å¦å¤é |
| | | if (selectedRows.value.length != 1) { |
| | | proxy.$modal.msgError("è¯·éæ©ä¸æ¡åå"); |
| | | return; |
| | | } |
| | | form.value = {}; |
| | | productData.value = []; |
| | | getSalesLedgerWithProducts({ id: selectedRows.value[0].id }).then((res) => { |
| | | form.value = { ...res }; |
| | | form.value.createTime = dayjs().format("YYYY-MM-DD"); |
| | | form.value.issueDate = dayjs().format("YYYY-MM-DD"); |
| | | form.value.createUer = userStore.nickName; |
| | | productData.value = form.value.productData.map((item) => { |
| | | return item; |
| | | }); |
| | | dialogFormVisible.value = true; |
| | | console.log("productData.value ", productData.value); |
| | | }); |
| | | // 夿æ¯å¦éæ©äºåå |
| | | if (selectedRows.value.length === 0) { |
| | | proxy.$modal.msgError("请è³å°éæ©ä¸æ¡åå"); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥ææéæ©çå忝å¦å
·æç¸åç客æ·åç§° |
| | | const firstRow = selectedRows.value[0]; |
| | | const isSameCustomer = selectedRows.value.every(row => |
| | | row.customerName === firstRow.customerName |
| | | ); |
| | | |
| | | if (!isSameCustomer) { |
| | | proxy.$modal.msgError("è¯·éæ©ç¸å客æ·åç§°çåå"); |
| | | return; |
| | | } |
| | | |
| | | // å
许ä¸åçéå®ååå·æ¹éå¤çï¼æ 鿣æ¥éå¤ |
| | | |
| | | form.value = {}; |
| | | productData.value = []; |
| | | |
| | | // å è½½ææéä¸ååçäº§åæ°æ® |
| | | const promises = selectedRows.value.map(row => |
| | | getSalesLedgerWithProducts({ id: row.id }) |
| | | ); |
| | | |
| | | Promise.all(promises).then(results => { |
| | | // åå¹¶ææååçäº§åæ°æ®ï¼å¹¶ä¸ºæ¯ä¸ªäº§åæ·»å 对åºçååä¿¡æ¯ |
| | | const allProductData = []; |
| | | results.forEach((result, index) => { |
| | | const contract = selectedRows.value[index]; |
| | | const contractId = contract.id; |
| | | if (result.productData) { |
| | | result.productData.forEach(item => { |
| | | allProductData.push({ |
| | | ...item, |
| | | id: contractId, // æç¡®è®¾ç½®ååID |
| | | salesContractNo: contract.salesContractNo, // æ·»å éå®ååå· |
| | | customerName: contract.customerName, // æ·»å 客æ·åç§° |
| | | customerContractNo: contract.customerContractNo // æ·»å 客æ·ååå· |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // è®¾ç½®è¡¨åæ°æ®ï¼ä½¿ç¨ç¬¬ä¸ä¸ªååçåºæ¬ä¿¡æ¯ï¼éå®ååå·çç©ºï¼ |
| | | form.value = { ...results[0] }; |
| | | form.value.createTime = dayjs().format("YYYY-MM-DD"); |
| | | form.value.issueDate = dayjs().format("YYYY-MM-DD"); |
| | | form.value.createUer = userStore.nickName; |
| | | form.value.selectedContractIds = selectedRows.value.map(row => row.id); // å卿æéä¸çååID |
| | | form.value.salesContractNo = ""; // éå®ååå·ç空ï¼å 为ä¼å¨äº§åè¡¨æ ¼ä¸å嫿¾ç¤º |
| | | |
| | | productData.value = allProductData; |
| | | |
| | | dialogFormVisible.value = true; |
| | | console.log("productData.value ", productData.value); |
| | | }); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | form.value.productData = proxy.HaveJson(productData.value); |
| | | invoiceRegistrationSave(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | }); |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | // å¦ææ¯æ¹éæä½ï¼å°ææååçæ°æ®æ¾å¨ä¸ä¸ªæ°ç»éï¼åªè°ç¨ä¸æ¬¡æ¥å£ |
| | | if (selectedRows.value.length > 1) { |
| | | // å建å
嫿æååæ°æ®çæ°ç» |
| | | const batchData = selectedRows.value.map(contract => { |
| | | // çéåºå±äºå½åååçäº§åæ°æ® |
| | | const contractProductData = productData.value.filter(item => |
| | | item.salesLedgerId === contract.id |
| | | ); |
| | | |
| | | // 为æ¯ä¸ªéå®ååå·å建ç¬ç«ç对象 |
| | | return { |
| | | // åºç¡è¡¨åæ°æ® |
| | | issueDate: form.value.issueDate, |
| | | createTime: form.value.createTime, |
| | | createUer: form.value.createUer, |
| | | invoiceNo: form.value.invoiceNo, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | id: contract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºsalesLedgerId |
| | | salesContractNo: contract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | customerName: contract.customerName, // 使ç¨å®é
ç客æ·åç§° |
| | | customerId: contract.customerId, // æ·»å 客æ·ID |
| | | customerContractNo: contract.customerContractNo, // 使ç¨å®é
ç客æ·ååå· |
| | | projectName: contract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | salesman: contract.salesman, // 使ç¨å®é
çä¸å¡å |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(contractProductData), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: true |
| | | }; |
| | | }); |
| | | |
| | | // åªè°ç¨ä¸æ¬¡æ¥å£ï¼ä¼ éå
嫿æååæ°æ®çæ°ç» |
| | | invoiceRegistrationSave(batchData).then(() => { |
| | | proxy.$modal.msgSuccess("æ¹éæ°å¢æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } else { |
| | | // å个ååæäº¤é»è¾ - ä¹ä»¥æ°ç»å½¢å¼ä¼ é |
| | | const singleContract = selectedRows.value[0]; |
| | | const singleFormArray = [ |
| | | { |
| | | // åºç¡è¡¨åæ°æ® |
| | | issueDate: form.value.issueDate, |
| | | createTime: form.value.createTime, |
| | | createUer: form.value.createUer, |
| | | invoiceNo: form.value.invoiceNo, |
| | | |
| | | // ååå®é
ä¿¡æ¯ |
| | | id: singleContract.id, // 使ç¨idä½ä¸ºå段åï¼å¼ä¸ºsalesLedgerId |
| | | salesContractNo: singleContract.salesContractNo, // 使ç¨å®é
çéå®ååå· |
| | | customerName: singleContract.customerName, // 使ç¨å®é
ç客æ·åç§° |
| | | customerId: singleContract.customerId, // æ·»å 客æ·ID |
| | | customerContractNo: singleContract.customerContractNo, // 使ç¨å®é
ç客æ·ååå· |
| | | projectName: singleContract.projectName, // 使ç¨å®é
ç项ç®åç§° |
| | | salesman: singleContract.salesman, // 使ç¨å®é
çä¸å¡å |
| | | |
| | | // äº§åæ°æ® |
| | | productData: proxy.HaveJson(productData.value), |
| | | |
| | | // æ¹éæ è¯ |
| | | isBatch: false |
| | | } |
| | | ]; |
| | | invoiceRegistrationSave(singleFormArray).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/invoiceRegistration/export", {}, "å¼ç¥¨ç»è®°ä¿¡æ¯.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/invoiceRegistration/export", {}, "å¼ç¥¨ç»è®°ä¿¡æ¯.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // 导åºéå®å°è´¦ |
| | | const handleExport = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/sales/ledger/exportOne", { ...searchForm, ...page }, "å¼ç¥¨ç»è®°.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/sales/ledger/exportOne", { ...searchForm, ...page }, "å¼ç¥¨ç»è®°.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | //æ¬æ¬¡å¼ç¥¨å¤±ç¦æä½ |
| | | const invoiceNumBlur = (row) => { |
| | | if (!row.currentInvoiceNum) { |
| | | row.currentInvoiceNum = 0; |
| | | } |
| | | if (row.currentInvoiceNum > row.tempNoInvoiceNum) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.currentInvoiceNum = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡å¼ç¥¨éé¢ |
| | | row.currentInvoiceAmount = ( |
| | | row.currentInvoiceNum * row.taxInclusiveUnitPrice |
| | | ).toFixed(2); |
| | | // è®¡ç®æªå¼ç¥¨æ° |
| | | row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed( |
| | | 2 |
| | | ); |
| | | // è®¡ç®æªå¼ç¥¨éé¢ |
| | | row.noInvoiceAmount = ( |
| | | row.tempnoInvoiceAmount - row.currentInvoiceAmount |
| | | ).toFixed(2); |
| | | if (!row.currentInvoiceNum) { |
| | | row.currentInvoiceNum = 0; |
| | | } |
| | | if (row.currentInvoiceNum > row.tempNoInvoiceNum) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨æ°ä¸å¾å¤§äºæªå¼ç¥¨æ°"); |
| | | row.currentInvoiceNum = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡å¼ç¥¨éé¢ |
| | | row.currentInvoiceAmount = ( |
| | | row.currentInvoiceNum * row.taxInclusiveUnitPrice |
| | | ).toFixed(2); |
| | | // è®¡ç®æªå¼ç¥¨æ° |
| | | row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed( |
| | | 2 |
| | | ); |
| | | // è®¡ç®æªå¼ç¥¨éé¢ |
| | | row.noInvoiceAmount = ( |
| | | row.tempnoInvoiceAmount - row.currentInvoiceAmount |
| | | ).toFixed(2); |
| | | }; |
| | | // æ¬æ¬¡å¼ç¥¨éé¢å¤±ç¦æä½ |
| | | const invoiceAmountBlur = (row) => { |
| | | if (!row.currentInvoiceAmount) { |
| | | row.currentInvoiceAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿å¼ç¥¨æ»éé¢ |
| | | if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨éé¢ä¸å¾å¤§äºæªå¼ç¥¨éé¢"); |
| | | row.currentInvoiceAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡å¼ç¥¨æ° |
| | | row.currentInvoiceNum = ( |
| | | row.currentInvoiceAmount / row.taxInclusiveUnitPrice |
| | | ).toFixed(2); |
| | | console.log("row.currentInvoiceNum ", row.currentInvoiceNum); |
| | | console.log(" row.originalNoInvoiceNum ", row.originalNoInvoiceNum); |
| | | // è®¡ç®æªå¼ç¥¨æ° |
| | | row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed( |
| | | 2 |
| | | ); |
| | | // è®¡ç®æªå¼ç¥¨éé¢ |
| | | row.noInvoiceAmount = ( |
| | | row.tempnoInvoiceAmount - row.currentInvoiceAmount |
| | | ).toFixed(2); |
| | | if (!row.currentInvoiceAmount) { |
| | | row.currentInvoiceAmount = 0; |
| | | } |
| | | // è®¡ç®æ¯å¦è¶
è¿å¼ç¥¨æ»éé¢ |
| | | if (row.currentInvoiceAmount > row.tempnoInvoiceAmount) { |
| | | proxy.$modal.msgWarning("æ¬æ¬¡å¼ç¥¨éé¢ä¸å¾å¤§äºæªå¼ç¥¨éé¢"); |
| | | row.currentInvoiceAmount = 0; |
| | | } |
| | | // è®¡ç®æ¬æ¬¡å¼ç¥¨æ° |
| | | row.currentInvoiceNum = ( |
| | | row.currentInvoiceAmount / row.taxInclusiveUnitPrice |
| | | ).toFixed(2); |
| | | console.log("row.currentInvoiceNum ", row.currentInvoiceNum); |
| | | console.log(" row.originalNoInvoiceNum ", row.originalNoInvoiceNum); |
| | | // è®¡ç®æªå¼ç¥¨æ° |
| | | row.noInvoiceNum = (row.originalNoInvoiceNum - row.currentInvoiceNum).toFixed( |
| | | 2 |
| | | ); |
| | | // è®¡ç®æªå¼ç¥¨éé¢ |
| | | row.noInvoiceAmount = ( |
| | | row.tempnoInvoiceAmount - row.currentInvoiceAmount |
| | | ).toFixed(2); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .table_list { |
| | | margin-top: unset; |
| | | margin-top: unset; |
| | | } |
| | | .flex { |
| | | display: flex; |
| | | display: flex; |
| | | } |
| | | .justify-between { |
| | | justify-content: space-between; |
| | | justify-content: space-between; |
| | | } |
| | | ::v-deep(.el-checkbox__label) { |
| | | font-weight: bold; |
| | | font-weight: bold; |
| | | } |
| | | </style> |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | ¥{{ scope.row.amount.toFixed(2) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="paymentMethod" label="仿¬¾æ¹å¼" width="120" /> |
| | | <el-table-column prop="status" label="订åç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusType(scope.row.status)"> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="paymentMethod"> |
| | | <el-select v-model="form.paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width: 100%"> |
| | | <el-option label="å
¨æ¬¾å°ä»" value="å
¨æ¬¾å°ä»"></el-option> |
| | | <el-option label="åæä»æ¬¾" value="åæä»æ¬¾"></el-option> |
| | | <el-option label="æç»" value="æç»"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="订åç¶æ" prop="status"> |
| | | <el-select v-model="form.status" placeholder="è¯·éæ©ç¶æ" style="width: 100%"> |
| | |
| | | { |
| | | id: 1, |
| | | orderNo: 'ORD202312001', |
| | | customer: '䏿µ·ç§ææéå
¬å¸', |
| | | salesperson: 'éå¿å¼º', |
| | | customer: '广å·ç§æå
¬å¸', |
| | | salesperson: 'å¼ ä¸', |
| | | orderDate: '2023-12-01', |
| | | amount: 50000.00, |
| | | paymentMethod: 'å
¨æ¬¾å°ä»', |
| | | status: 'å¾
å®¡æ ¸', |
| | | remark: 'éè¦å®¢æ·è®¢å' |
| | | }, |
| | |
| | | salesperson: 'åé
å©·', |
| | | orderDate: '2023-12-02', |
| | | amount: 35000.00, |
| | | paymentMethod: 'åæä»æ¬¾', |
| | | status: 'å·²å®¡æ ¸', |
| | | remark: '常è§è®¢å' |
| | | }, |
| | |
| | | salesperson: 'ç建å½', |
| | | orderDate: '2023-12-03', |
| | | amount: 28000.00, |
| | | paymentMethod: 'æç»', |
| | | status: 'å·²åè´§', |
| | | remark: 'æ°å®¢æ·è®¢å' |
| | | } |
| | |
| | | salesperson: '', |
| | | orderDate: '', |
| | | amount: 0, |
| | | paymentMethod: '', |
| | | status: 'å¾
å®¡æ ¸', |
| | | remark: '' |
| | | }) |
| | |
| | | salesperson: [{ required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'change' }], |
| | | orderDate: [{ required: true, message: 'è¯·éæ©è®¢åæ¥æ', trigger: 'change' }], |
| | | amount: [{ required: true, message: '请è¾å
¥è®¢åéé¢', trigger: 'blur' }], |
| | | paymentMethod: [{ required: true, message: 'è¯·éæ©ä»æ¬¾æ¹å¼', trigger: 'change' }], |
| | | status: [{ required: true, message: 'è¯·éæ©ç¶æ', trigger: 'change' }] |
| | | } |
| | | |
| | |
| | | form.salesperson = '' |
| | | form.orderDate = '' |
| | | form.amount = 0 |
| | | form.paymentMethod = '' |
| | | form.status = 'å¾
å®¡æ ¸' |
| | | form.remark = '' |
| | | dialogVisible.value = true |
| | |
| | | ¥{{ scope.row.paidAmount }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="paymentMethod" label="仿¬¾æ¹å¼" width="120" /> |
| | | <el-table-column prop="paymentStatus" label="仿¬¾ç¶æ" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getPaymentStatusType(scope.row.paymentStatus)"> |
| | |
| | | <el-col :span="12"> |
| | | <el-form-item label="订åéé¢" prop="orderAmount"> |
| | | <el-input-number v-model="form.orderAmount" :precision="2" :min="0" style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="paymentMethod"> |
| | | <el-select v-model="form.paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width: 100%"> |
| | | <el-option label="å
¨æ¬¾å°ä»" value="å
¨æ¬¾å°ä»"></el-option> |
| | | <el-option label="åæä»æ¬¾" value="åæä»æ¬¾"></el-option> |
| | | <el-option label="æç»" value="æç»"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾éé¢" prop="paymentAmount"> |
| | | <el-input-number v-model="paymentAmount" :precision="2" :min="0" :max="currentRecord.orderAmount" style="width: 100%"></el-input-number> |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="paymentMethod"> |
| | | <el-select v-model="paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width: 100%"> |
| | | <el-option label="ç°é" value="ç°é"></el-option> |
| | | <el-option label="é¶è¡è½¬è´¦" value="é¶è¡è½¬è´¦"></el-option> |
| | | <el-option label="æ¯ä»å®" value="æ¯ä»å®"></el-option> |
| | | <el-option label="微信æ¯ä»" value="微信æ¯ä»"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="仿¬¾å¤æ³¨" prop="paymentRemark"> |
| | | <el-input type="textarea" v-model="paymentRemark" rows="3" placeholder="请è¾å
¥ä»æ¬¾å¤æ³¨"></el-input> |
| | |
| | | orderNo: '', |
| | | customer: '', |
| | | orderAmount: 0, |
| | | paymentMethod: '', |
| | | paymentStatus: 'æªä»æ¬¾', |
| | | shippingStatus: 'å¾
åè´§', |
| | | shippingDate: '', |
| | |
| | | // orderNo: [{ required: true, message: '请è¾å
¥è®¢åå·', trigger: 'blur' }], |
| | | customer: [{ required: true, message: 'è¯·éæ©å®¢æ·', trigger: 'change' }], |
| | | orderAmount: [{ required: true, message: '请è¾å
¥è®¢åéé¢', trigger: 'blur' }], |
| | | paymentMethod: [{ required: true, message: 'è¯·éæ©ä»æ¬¾æ¹å¼', trigger: 'change' }], |
| | | paymentStatus: [{ required: true, message: 'è¯·éæ©ä»æ¬¾ç¶æ', trigger: 'change' }], |
| | | shippingStatus: [{ required: true, message: 'è¯·éæ©åè´§ç¶æ', trigger: 'change' }] |
| | | } |
| | |
| | | const shippingDialogVisible = ref(false) |
| | | const currentRecord = ref({}) |
| | | const paymentAmount = ref(0) |
| | | const paymentMethod = ref('') |
| | | const paymentRemark = ref('') |
| | | const shippingDate = ref('') |
| | | const logisticsCompany = ref('') |
| | |
| | | form.orderNo = '' |
| | | form.customer = '' |
| | | form.orderAmount = 0 |
| | | form.paymentMethod = '' |
| | | form.paymentStatus = 'æªä»æ¬¾' |
| | | form.shippingStatus = 'å¾
åè´§' |
| | | form.shippingDate = '' |
| | |
| | | const handlePayment = (row) => { |
| | | currentRecord.value = row |
| | | paymentAmount.value = row.orderAmount - row.paidAmount |
| | | paymentMethod.value = '' |
| | | paymentRemark.value = '' |
| | | paymentDialogVisible.value = true |
| | | } |
| | |
| | | } |
| | | |
| | | const savePayment = () => { |
| | | if (!paymentMethod.value) { |
| | | ElMessage.warning('è¯·éæ©ä»æ¬¾æ¹å¼') |
| | | return |
| | | } |
| | | currentRecord.value.paidAmount = Number(currentRecord.value.paidAmount) + paymentAmount.value |
| | | if(currentRecord.value.paidAmount == currentRecord.value.orderAmount){ |
| | | currentRecord.value.paymentStatus = '已仿¬¾' |
| | |
| | | prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·ååå·"> |
| | | <el-input |
| | | v-model="searchForm.customerContractNo" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°"> |
| | | <el-input |
| | | v-model="searchForm.projectName" |
| | | placeholder="请è¾å
¥" |
| | | @change="handleQuery" |
| | | clearable |
| | | prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-checkbox |
| | | v-model="searchForm.status" |
| | |
| | | size="small" |
| | | @click="changeEditType(scope.row)" |
| | | v-if="!scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >ç¼è¾</el-button |
| | | > |
| | | <el-button |
| | |
| | | size="small" |
| | | @click="saveReceiptPayment(scope.row)" |
| | | v-if="scope.row.editType" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >ä¿å</el-button |
| | | > |
| | | <el-button |
| | |
| | | type="primary" |
| | | size="small" |
| | | @click="delReceiptRecord(scope.row)" |
| | | :disabled="scope.row.registrant !== userStore.nickName" |
| | | >å é¤</el-button |
| | | > |
| | | </template> |
| | |
| | | width="240" |
| | | /> |
| | | <el-table-column |
| | | label="客æ·ååå·" |
| | | prop="customerContractNo" |
| | | show-overflow-tooltip |
| | | width="240" |
| | | |
| | | /> |
| | | <el-table-column |
| | | label="客æ·åç§°" |
| | | prop="customerName" |
| | | show-overflow-tooltip |
| | | width="240" |
| | | /> |
| | | <el-table-column |
| | | label="项ç®åç§°" |
| | | prop="projectName" |
| | | show-overflow-tooltip |
| | | width="340" |
| | | /> |
| | | <el-table-column |
| | | label="忬¾ç¶æ" |
| | |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="产å大类" |
| | | prop="productCategory" |
| | | show-overflow-tooltip |
| | | width="100" |
| | | /> |
| | | <!-- <el-table-column--> |
| | | <!-- label="产å大类"--> |
| | | <!-- prop="productCategory"--> |
| | | <!-- show-overflow-tooltip--> |
| | | <!-- width="100"--> |
| | | <!-- />--> |
| | | <el-table-column |
| | | label="å票å·" |
| | | prop="invoiceNo" |
| | |
| | | v-model="form.registrant" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | console.log("selection", selection); |
| | | selectedRows.value = selection.filter( |
| | | (item) => item.customerContractNo !== null |
| | | ); |
| | | selectedRows.value = selection |
| | | }; |
| | | // 主表åè®¡æ¹æ³ |
| | | const summarizeMainTable = (param) => { |
| | |
| | | :prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·ååå·"> |
| | | <el-input |
| | | v-model="searchForm.customerContractNo" |
| | | placeholder="è¾å
¥å®¢æ·ååå·" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°"> |
| | | <el-input |
| | | v-model="searchForm.projectName" |
| | | placeholder="è¾å
¥é¡¹ç®åç§°" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="忬¾æ¥æ"> |
| | | <el-date-picker |
| | | v-model="searchForm.receiptPaymentDate" |
| | |
| | | width:240 |
| | | }, |
| | | { |
| | | label: "客æ·ååå·", |
| | | prop: "customerContractNo", |
| | | width:240 |
| | | }, |
| | | { |
| | | label: "忬¾æ¥æ", |
| | | prop: "receiptPaymentDate", |
| | | width:100 |
| | |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width:240 |
| | | }, |
| | | { |
| | | label: "项ç®åç§°", |
| | | prop: "projectName", |
| | | width:200 |
| | | }, |
| | | { |
| | | label: "忬¾éé¢ï¼å
ï¼", |
| | |
| | | receiptPaymentDate: [], |
| | | receiptPaymentDateStart: undefined, |
| | | receiptPaymentDateEnd: undefined, |
| | | customerContractNo: undefined, |
| | | projectName: undefined, |
| | | }); |
| | | const { receipt_payment_type } = proxy.useDict("receipt_payment_type"); |
| | | const isShowSummarySon = ref(true); |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { receiptPaymentDate, ...rest } = searchForm; |
| | | receiptPaymentHistoryListPage({ ...rest, ...page }).then((res) => { |
| | | // å°èå´æ¥æåæ®µä¼ éç»å端 |
| | | const params = { ...rest, ...page }; |
| | | // ç§»é¤åæ¬¾æ¥æçé»è®¤å¼è®¾ç½®ï¼åªä¿çèå´æ¥æå段 |
| | | delete params.receiptPaymentDate; |
| | | receiptPaymentHistoryListPage(params).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | | page.total = res.total; |
| | |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // è®¾ç½®åæ¬¾æ¥æèå´é»è®¤å¼ä¸ºå½å¤© |
| | | const today = dayjs().format('YYYY-MM-DD'); |
| | | searchForm.receiptPaymentDate = [today, today]; |
| | | // 设置èå´æ¥æå段çèµ·å§åç»ææ¶é´ |
| | | searchForm.receiptPaymentDateStart = dayjs(today).format('YYYY-MM-DD 00:00:00'); |
| | | searchForm.receiptPaymentDateEnd = dayjs(today).format('YYYY-MM-DD 23:59:59'); |
| | | getList(); |
| | | }); |
| | | </script> |
| | |
| | | <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> |
| | | <el-table :data="tableData" border height="40vh"> |
| | | <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" width="100" align="center"> |
| | | <el-table-column fixed="right" label="æä½" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> |
| | | <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { ElMessageBox, ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { delCommonFile } from '@/api/publicApi/commonFile.js' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const tableData = ref([]) |
| | |
| | | const lookFile = (row) => { |
| | | filePreviewRef.value.open(row.url) |
| | | } |
| | | // å é¤éä»¶ |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm(`确认å é¤éä»¶"${row.name}"åï¼`, 'å é¤ç¡®è®¤', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }).then(() => { |
| | | delCommonFile([row.id]).then(() => { |
| | | ElMessage.success('å 餿å') |
| | | // ä»å表ä¸ç§»é¤å·²å é¤çéä»¶ |
| | | const index = tableData.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | tableData.value.splice(index, 1) |
| | | } |
| | | }).catch(() => { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | }) |
| | | }).catch(() => { |
| | | proxy.$modal.msg('已忶å é¤') |
| | | }) |
| | | } |
| | | defineExpose({ |
| | | open |
| | | }) |
| | |
| | | <el-input v-model="searchForm.customerName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="客æ·ååå·ï¼"> |
| | | <el-input v-model="searchForm.customerContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="éå®ååå·ï¼"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="项ç®åç§°ï¼"> |
| | | <el-input v-model="searchForm.projectName" placeholder="请è¾å
¥" clearable prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æï¼"> |
| | |
| | | </div> |
| | | <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange" |
| | | :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%" |
| | | :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)"> |
| | | :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 21em)"> |
| | | <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"> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产ååç§°" prop="productCategory"/> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel" width="100"> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ°é" prop="quantity"/> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" :formatter="formattedNumber"></el-table-column> |
| | | |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" /> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(ç¾å
)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(ç¾å
)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column 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="salesContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="客æ·ååå·" prop="customerContractNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="客æ·åç§°" prop="customerName" width="300" show-overflow-tooltip /> |
| | | <el-table-column label="ä¸å¡å" prop="salesman" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="项ç®åç§°" prop="projectName" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="仿¬¾æ¹å¼" prop="paymentMethod" show-overflow-tooltip /> |
| | | <el-table-column label="ååéé¢(å
)" prop="contractAmount" width="220" show-overflow-tooltip |
| | | :formatter="formattedNumber" /> |
| | | <el-table-column label="å½å
¥äºº" prop="entryPersonName" width="100" show-overflow-tooltip /> |
| | | <el-table-column label="å货车ç" prop="shippingCarNumber" width="120" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <div> |
| | | <div v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</div> |
| | | <el-tag v-else type="warning">æªåè´§</el-tag> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åè´§æ¥æ" prop="shippingDate" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="å½å
¥æ¥æ" prop="entryDate" width="120" show-overflow-tooltip /> |
| | | <el-table-column label="ç¾è®¢æ¥æ" prop="executionDate" width="120" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="æä½" min-width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" :disabled="scope.row.invoiceTotal>0 || scope.row.entryPersonName !== userStore.nickName" @click="openForm('edit', scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">ç¼è¾</el-button> |
| | | <!-- <el-button link type="primary" size="small" @click="openForm('view', scope.row)">详æ
</el-button>--> |
| | | <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">éä»¶</el-button> |
| | | <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">åè´§</el-button> |
| | | <el-button v-if="!scope.row.shippingCarNumber" link type="primary" size="small" @click="openDeliveryForm(scope.row)">åè´§</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å¡åï¼" prop="salesman"> |
| | | <el-select v-model="form.salesman" placeholder="è¯·éæ©" clearable :disabled="operationType === 'view'"> |
| | | <el-select v-model="form.salesman" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" clearable :disabled="operationType === 'view'"> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" |
| | | :value="item.nickName" /> |
| | | </el-select> |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·ååå·ï¼" prop="customerContractNo"> |
| | | <el-input v-model="form.customerContractNo" placeholder="请è¾å
¥" clearable :disabled="operationType === 'view'"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客æ·åç§°ï¼" prop="customerId"> |
| | | <el-select v-model="form.customerId" placeholder="è¯·éæ©" clearable :disabled="operationType === 'view'"> |
| | | <el-select v-model="form.customerId" placeholder="è¯·éæ©" clearable :disabled="operationType === 'view'" filterable> |
| | | <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id"> |
| | | {{ |
| | | item.customerName + "ââ" + item.taxpayerIdentificationNumber |
| | | }} |
| | | </el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项ç®åç§°ï¼" prop="projectName"> |
| | | <el-input v-model="form.projectName" placeholder="请è¾å
¥" clearable :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å½å
¥äººï¼" prop="entryPerson"> |
| | | <el-select v-model="form.entryPerson" placeholder="è¯·éæ©" clearable @change="changs" disabled> |
| | | <el-select v-model="form.entryPerson" filterable |
| | | default-first-option |
| | | :reserve-keyword="false" placeholder="è¯·éæ©" clearable @change="changs"> |
| | | <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | </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 :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row> |
| | | <el-form-item label="产åä¿¡æ¯ï¼" prop="entryDate"> |
| | | <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">æ·»å </el-button> |
| | |
| | | :summary-method="summarizeMainTable"> |
| | | <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'" /> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="产ååç§°" prop="productCategory" /> |
| | | <el-table-column label="产åé«åº¦" prop="specificationModel"> |
| | | <template #default="scope"> |
| | | <div>{{ scope.row.specificationModel }}{{ scope.row.unit }}</div> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- <el-table-column label="åä½" prop="unit" /> --> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="ç»å®æºå¨" prop="speculativeTradingName" /> |
| | | <el-table-column label="åä½" prop="unit" /> |
| | | <el-table-column label="æ°é" prop="quantity" /> |
| | | <!-- <el-table-column label="ç¨ç(%)" prop="taxRate" /> --> |
| | | <el-table-column label="åä»·(ç¾å
)/ä»¶" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> |
| | | <!-- <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> --> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" /> |
| | | <el-table-column fixed="right" label="æä½" min-width="60" align="center" v-if="operationType !== 'view'"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row,scope.$index)">ç¼è¾</el-button> |
| | |
| | | <el-form :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="productCategory"> |
| | | <el-form-item label="产å大类ï¼" prop="productCategory"> |
| | | <!-- <el-select v-model="productForm.productCategory" placeholder="è¯·éæ©" clearable> |
| | | <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/> |
| | | </el-select> --> |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="产åé«åº¦ï¼" prop="productModelId"> |
| | | <el-form-item label="è§æ ¼åå·ï¼" prop="productModelId"> |
| | | <el-select v-model="productForm.productModelId" placeholder="è¯·éæ©" clearable @change="getProductModel"> |
| | | <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" /> |
| | | </el-select> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="ç»å®æºå¨ï¼"> |
| | | <el-input v-model="productForm.speculativeTradingName" placeholder="请å
éæ©è§æ ¼åå·" clearable disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="é«åº¦åä½ï¼" prop="unit"> |
| | | <el-form-item label="åä½ï¼" prop="unit"> |
| | | <el-input v-model="productForm.unit" placeholder="请è¾å
¥" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="åä»·(ç¾å
)/ä»¶ï¼" prop="taxInclusiveUnitPrice"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" prop="taxInclusiveUnitPrice"> |
| | | <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%" |
| | | :precision="2" |
| | | placeholder="请è¾å
¥" clearable @change="calculateFromUnitPrice" /> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°éï¼" prop="quantity"> |
| | | <el-input-number :min="0" v-model="productForm.quantity" placeholder="请è¾å
¥" clearable |
| | | <el-input-number :step="0.1" :min="0" v-model="productForm.quantity" placeholder="请è¾å
¥" clearable |
| | | :precision="2" |
| | | @change="calculateFromQuantity" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨æ»ä»·(ç¾å
)ï¼" prop="taxInclusiveTotalPrice"> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" prop="taxInclusiveTotalPrice"> |
| | | <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="请è¾å
¥" clearable @change="calculateFromTotalPrice" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·(ç¾å
)ï¼" prop="taxExclusiveTotalPrice"> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·(å
)ï¼" prop="taxExclusiveTotalPrice"> |
| | | <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="请è¾å
¥" clearable @change="calculateFromExclusiveTotalPrice" /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <div v-for="(item, index) in printData" :key="index" class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">åå¥ç¹æé责任å
¬å¸</div> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | <span class="value">{{ formatDate(item.createTime) }}</span> |
| | | </div> |
| | | <div> |
| | | |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">{{ item.customerName || 'å¼ ç±æ' }}</span> |
| | | <span class="label">å货车çå·ï¼</span> |
| | | <span class="value">{{ item.shippingCarNumber }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">客æ·åç§°ï¼</span> |
| | | <span class="value">{{ item.customerName || 'å¼ ç±æ' }}</span> |
| | | </div> |
| | | <span class="label">åå·ï¼</span> |
| | | <span class="value">{{ item.salesContractNo }}</span> |
| | | </div> |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="å货车çå·ï¼" prop="shippingCarNumber"> |
| | | <el-input |
| | | <el-select v-model="deliveryForm.shippingCarNumber" filterable allow-create placeholder="è¯·éæ©å货车çå·"> |
| | | <el-option key="1" label="æ°A H5153" value="æ°A H5153"/> |
| | | <el-option key="2" label="æ°A H4232" value="æ°A H4232"/> |
| | | <el-option key="3" label="æ°A H4001" value="æ°A H4001"/> |
| | | <el-option key="4" label="æ°A H6409" value="æ°A H6409"/> |
| | | <el-option key="5" label="æ°A G7446" value="æ°A G7446"/> |
| | | <el-option key="6" label="æ°H 80369" value="æ°H 80369"/> |
| | | </el-select> |
| | | <!-- <el-input |
| | | v-model="deliveryForm.shippingCarNumber" |
| | | placeholder="请è¾å
¥å货车çå·" |
| | | clearable |
| | | /> |
| | | /> --> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", // 客æ·åç§° |
| | | customerContractNo: "", // 客æ·ååç¼å· |
| | | salesContractNo: "", // éå®ååç¼å· |
| | | projectName: "", // 项ç®åç§° |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | |
| | | form: { |
| | | salesContractNo: "", |
| | | salesman: "", |
| | | customerContractNo: "", |
| | | customerId: "", |
| | | projectName: "", |
| | | entryPerson: "", |
| | | entryDate: "", |
| | | maintenanceTime: "", |
| | | productData: [], |
| | | executionDate: "", |
| | | paymentMethod: "", |
| | | }, |
| | | rules: { |
| | | salesman: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | customerContractNo: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | customerId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | projectName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | entryPerson: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | entryDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | executionDate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | cartonSpecifications:'', |
| | | speculativeTradingName: "", |
| | | }, |
| | | productRules: { |
| | | productCategory: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | cartonSpecifications: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | // åªæå¨ç¹å»æç´¢æé®æ¶æé置页ç å°ç¬¬ä¸é¡µ |
| | | // é¿å
表ååæ®µchangeäºä»¶å¹²æ°å页 |
| | | if (arguments.length === 0) { |
| | | page.current = 1; |
| | | } |
| | | expandedRowKeys.value = []; |
| | | getList(); |
| | | }; |
| | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const { entryDate, ...rest } = searchForm; |
| | | ledgerListPage({ ...rest, ...page }) |
| | | // å°èå´æ¥æåæ®µä¼ éç»å端 |
| | | const params = { ...rest, ...page }; |
| | | // ç§»é¤å½å
¥æ¥æçé»è®¤å¼è®¾ç½®ï¼åªä¿çèå´æ¥æå段 |
| | | delete params.entryDate; |
| | | ledgerListPage(params) |
| | | .then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.records; |
| | |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è·å产ååç§°treeæ°æ® |
| | | // è·å产å大类treeæ°æ® |
| | | const getProductOptions = () => { |
| | | productTreeList().then((res) => { |
| | | productOptions.value = convertIdToValue(res); |
| | |
| | | // è·åtreeåæ°æ® |
| | | const getModels = (value) => { |
| | | productForm.value.productCategory = findNodeById(productOptions.value, value); |
| | | productForm.value.productId = value; |
| | | modelList({ id: value }).then((res) => { |
| | | modelOptions.value = res; |
| | | }); |
| | |
| | | if (index !== -1) { |
| | | productForm.value.specificationModel = modelOptions.value[index].model; |
| | | productForm.value.unit = modelOptions.value[index].unit; |
| | | productForm.value.speculativeTradingName = modelOptions.value[index].speculativeTradingName || ""; |
| | | } else { |
| | | productForm.value.specificationModel = null; |
| | | productForm.value.unit = null; |
| | | productForm.value.speculativeTradingName = ""; |
| | | } |
| | | }; |
| | | const findNodeById = (nodes, productId) => { |
| | |
| | | // form.value.entryPerson = userAll.user.userId // 设置é»è®¤ä¸å¡å为å½åç¨æ· |
| | | // } |
| | | // }); |
| | | form.value.entryDate = getCurrentDate(); // 设置é»è®¤å½å
¥æ¥æä¸ºå½åæ¥æ |
| | | // ç§»é¤å½å
¥æ¥æé»è®¤å¼è®¾ç½®ï¼åªå¤çèå´æ¥æå段 |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | function changs(val) { |
| | |
| | | }else{ |
| | | productData.value[productIndex.value] = { ...productForm.value } |
| | | } |
| | | console.log('productData',productData) |
| | | closeProductDia(); |
| | | } |
| | | } |
| | |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="company-name">åå¥ç¹æé责任å
¬å¸</div> |
| | | <div class="company-name">æµ·å·å¼å¿é£åæéå
¬å¸</div> |
| | | <div class="document-title">é¶å®åè´§å</div> |
| | | </div> |
| | | |
| | |
| | | |
| | | // æ ¹æ®ä¸å«ç¨æ»ä»·è®¡ç®å«ç¨åä»·åæ°é |
| | | const calculateFromExclusiveTotalPrice = () => { |
| | | // if (!productForm.value.taxRate) { |
| | | // proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | // return; |
| | | // } |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (isCalculating.value) return; |
| | | |
| | | const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice); |
| | |
| | | |
| | | // æ ¹æ®æ°éååè®¡ç®æ»ä»· |
| | | const calculateFromQuantity = () => { |
| | | // if (!productForm.value.taxRate) { |
| | | // proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | // return; |
| | | // } |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (isCalculating.value) return; |
| | | |
| | | const quantity = parseFloat(productForm.value.quantity); |
| | |
| | | |
| | | // æ ¹æ®å«ç¨åä»·ååè®¡ç®æ»ä»· |
| | | const calculateFromUnitPrice = () => { |
| | | // if (!productForm.value.taxRate) { |
| | | // proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | // return; |
| | | // } |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (isCalculating.value) return; |
| | | |
| | | const quantity = parseFloat(productForm.value.quantity); |
| | |
| | | |
| | | // æ ¹æ®ç¨çåå计ç®ä¸å«ç¨æ»ä»· |
| | | const calculateFromTaxRate = () => { |
| | | // if (!productForm.value.taxRate) { |
| | | // proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | // return; |
| | | // } |
| | | if (!productForm.value.taxRate) { |
| | | proxy.$modal.msgWarning("请å
éæ©ç¨ç"); |
| | | return; |
| | | } |
| | | if (isCalculating.value) return; |
| | | |
| | | const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice); |
| | |
| | | const openDeliveryForm = (row) => { |
| | | currentDeliveryRow.value = row; |
| | | deliveryForm.value = { |
| | | shippingDate: getCurrentDate(), |
| | | shippingDate: "", // ç§»é¤é»è®¤å¼è®¾ç½® |
| | | shippingCarNumber: "", |
| | | }; |
| | | deliveryFormVisible.value = true; |
| | |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | // 设置å½å
¥æ¥æèå´é»è®¤å¼ä¸ºå½å¤© |
| | | const today = dayjs().format('YYYY-MM-DD'); |
| | | searchForm.entryDate = [today, today]; |
| | | // 设置èå´æ¥æå段çèµ·å§åç»ææ¶é´ |
| | | searchForm.entryDateStart = today; |
| | | searchForm.entryDateEnd = today; |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="仿¬¾æ¹å¼" prop="paymentMethod"> |
| | | <el-select v-model="form.paymentMethod" placeholder="è¯·éæ©ä»æ¬¾æ¹å¼" style="width: 100%"> |
| | | <el-option label="å
¨æ¬¾å°ä»" value="å
¨æ¬¾å°ä»"></el-option> |
| | | <el-option label="åæä»æ¬¾" value="åæä»æ¬¾"></el-option> |
| | | <el-option label="æç»" value="æç»"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="交货æ" prop="deliveryPeriod"> |
| | | <el-date-picker |
| | | v-model="form.deliveryPeriod" |
| | |
| | | <el-descriptions-item label="ä¸å¡å">{{ currentQuotation.salesperson }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¥ä»·æ¥æ">{{ currentQuotation.quotationDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="æææè³">{{ currentQuotation.validDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="仿¬¾æ¹å¼">{{ currentQuotation.paymentMethod }}</el-descriptions-item> |
| | | <el-descriptions-item label="交货æ">{{ currentQuotation.deliveryPeriod }}</el-descriptions-item> |
| | | <!-- <el-descriptions-item label="æ¥ä»·ç¶æ">--> |
| | | <!-- <el-tag :type="getStatusType(currentQuotation.status)">{{ currentQuotation.status }}</el-tag>--> |
| | |
| | | salesperson: [{ required: true, message: 'è¯·éæ©ä¸å¡å', trigger: 'change' }], |
| | | quotationDate: [{ required: true, message: 'è¯·éæ©æ¥ä»·æ¥æ', trigger: 'change' }], |
| | | validDate: [{ required: true, message: 'è¯·éæ©æææ', trigger: 'change' }], |
| | | paymentMethod: [{ required: true, message: 'è¯·éæ©ä»æ¬¾æ¹å¼', trigger: 'change' }], |
| | | deliveryPeriod: [{ required: true, message: 'è¯·éæ©äº¤è´§æ', trigger: 'change' }] |
| | | } |
| | | const userList = ref([]); |
| | |
| | | export default defineConfig(({ mode, command }) => { |
| | | const env = loadEnv(mode, process.cwd()); |
| | | const { VITE_APP_ENV } = env; |
| | | const baseUrl = |
| | | env.VITE_APP_ENV === "development" |
| | | ? "http://114.132.189.42:9036" |
| | | : env.VITE_BASE_API; |
| | | const javaUrl = |
| | | env.VITE_APP_ENV === "development" |
| | | ? "http://114.132.189.42:9037" |
| | | : env.VITE_JAVA_API; |
| | | const baseUrl = env.VITE_APP_ENV === "development" ? "http://192.168.1.35:7003" : env.VITE_BASE_API; |
| | | const javaUrl = env.VITE_APP_ENV === "development" ? "http://114.132.189.42:9037" : env.VITE_JAVA_API; |
| | | return { |
| | | define:{ |
| | | __BASE_API__: JSON.stringify(javaUrl) |
| | | define: { |
| | | __BASE_API__: JSON.stringify(javaUrl), |
| | | }, |
| | | // é¨ç½²ç产ç¯å¢åå¼åç¯å¢ä¸çURLã |
| | | // é»è®¤æ
åµä¸ï¼vite ä¼åè®¾ä½ çåºç¨æ¯è¢«é¨ç½²å¨ä¸ä¸ªååçæ ¹è·¯å¾ä¸ |
| | |
| | | "/dev-api": { |
| | | target: baseUrl, |
| | | changeOrigin: true, |
| | | rewrite: (p) => p.replace(/^\/dev-api/, ""), |
| | | rewrite: p => p.replace(/^\/dev-api/, ""), |
| | | }, |
| | | // springdoc proxy |
| | | "^/v3/api-docs/(.*)": { |
| | |
| | | { |
| | | postcssPlugin: "internal:charset-removal", |
| | | AtRule: { |
| | | charset: (atRule) => { |
| | | charset: atRule => { |
| | | if (atRule.name === "charset") { |
| | | atRule.remove(); |
| | | } |