src/api/productionManagement/productionOrder.js
@@ -17,63 +17,3 @@ data: query, }); } // èªå¨æ´¾å·¥ export function productionDispatchList(query) { return request({ url: "/salesLedger/scheduling/productionDispatchList", method: "post", data: 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 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, }); } src/api/productionManagement/productionReporting.js
@@ -17,6 +17,14 @@ params: query, }); } // æ ¹æ®IDè·åå·¥å详æ export function getProductWorkOrderById(query) { return request({ url: "/productWorkOrder/getProductWorkOrderById", method: "get", params: query, }); } // ç产æ¥å·¥ export function productionReport(query) { return request({ @@ -33,7 +41,7 @@ data: query, }); } // æ°å¢æ¥å·¥ // æ°å¢äº§å主表 export function addProductMain(data) { return request({ url: "/productionProductMain/addProductMain", src/pages.json
@@ -501,7 +501,7 @@ } }, { "path": "pages/productionManagement/productionReporting/index", "path": "pages/productionManagement/productionReport/index", "style": { "navigationBarTitleText": "ç产æ¥å·¥", "navigationStyle": "custom" src/pages/index.vue
@@ -18,7 +18,7 @@ <view class="hero-section"> <view class="bg-img"> <view class="hero-content"> <text class="hero-title">æµ·å·å¼å¿é£å</text> <text class="hero-title">åæ³°ä¼ä¸</text> </view> <view class="hero-wave"></view> </view> @@ -38,103 +38,108 @@ <!-- </view>--> <!-- </view>--> <!-- è¥éç®¡çæ¨¡å --> <view class="common-module marketing-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">è¥é管ç</text> </view> </view> <view class="module-content"> <up-grid :border="false" col="4"> <up-grid-item v-for="(item, index) in marketingItems" :key="index" @click="handleCommonItemClick(item)"> <view class="icon-container" :style="{ background: item.bgColor }"> <up-icon :name="item.icon" :size="58" color="#ffffff"></up-icon> </view> <text class="item-label">{{item.label}}</text> </up-grid-item> </up-grid> </view> </view> <!-- éè´ç®¡ç模å --> <view class="common-module purchase-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">éè´ç®¡ç</text> </view> </view> <view class="module-content"> <up-grid :border="false" col="4"> <up-grid-item v-for="(item, index) in purchaseItems" :key="index" @click="handleCommonItemClick(item)"> <view class="icon-container" :style="{ background: item.bgColor }"> <up-icon :name="item.icon" :size="58" color="#ffffff"></up-icon> </view> <text class="item-label">{{item.label}}</text> </up-grid-item> </up-grid> </view> </view> <!-- åååå ¬æ¨¡å --> <view class="common-module collaboration-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">åååå ¬</text> </view> </view> <view class="module-content"> <up-grid :border="false" col="4"> <up-grid-item v-for="(item, index) in collaborationItems" :key="index" @click="handleCommonItemClick(item)"> <view class="icon-container" :style="{ background: item.bgColor }"> <up-icon :name="item.icon" :size="58" color="#ffffff"></up-icon> </view> <text class="item-label">{{item.label}}</text> </up-grid-item> </up-grid> </view> </view> <!-- å ¥åºç®¡ç --> <view class="common-module collaboration-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">ä»å¨ç©æµ</text> </view> </view> <view class="module-content"> <up-grid :border="false" col="4"> <up-grid-item v-for="(item, index) in inventoryManagement" :key="index" @click="handleCommonItemClick(item)"> <view class="icon-container" :style="{ background: item.bgColor }"> <up-icon :name="item.icon" :size="58" color="#ffffff"></up-icon> </view> <text class="item-label">{{item.label}}</text> </up-grid-item> </up-grid> </view> </view> <!-- <view class="common-module marketing-module">--> <!-- <view class="module-header">--> <!-- <view class="module-title-container">--> <!-- <text class="module-title">è¥é管ç</text>--> <!-- </view>--> <!-- </view>--> <!-- <view class="module-content">--> <!-- <up-grid :border="false"--> <!-- col="4">--> <!-- <up-grid-item v-for="(item, index) in marketingItems"--> <!-- :key="index"--> <!-- @click="handleCommonItemClick(item)">--> <!-- <view class="icon-container"--> <!-- :style="{ background: item.bgColor }">--> <!-- <up-icon :name="item.icon"--> <!-- :size="58"--> <!-- color="#ffffff"></up-icon>--> <!-- </view>--> <!-- <text class="item-label">{{item.label}}</text>--> <!-- </up-grid-item>--> <!-- </up-grid>--> <!-- </view>--> <!-- </view>--> <!-- <!– éè´ç®¡çæ¨¡å –>--> <!-- <view class="common-module purchase-module">--> <!-- <view class="module-header">--> <!-- <view class="module-title-container">--> <!-- <text class="module-title">éè´ç®¡ç</text>--> <!-- </view>--> <!-- </view>--> <!-- <view class="module-content">--> <!-- <up-grid :border="false"--> <!-- col="4">--> <!-- <up-grid-item v-for="(item, index) in purchaseItems"--> <!-- :key="index"--> <!-- @click="handleCommonItemClick(item)">--> <!-- <view class="icon-container"--> <!-- :style="{ background: item.bgColor }">--> <!-- <up-icon :name="item.icon"--> <!-- :size="58"--> <!-- color="#ffffff"></up-icon>--> <!-- </view>--> <!-- <text class="item-label">{{item.label}}</text>--> <!-- </up-grid-item>--> <!-- </up-grid>--> <!-- </view>--> <!-- </view>--> <!-- <!– åååå ¬æ¨¡å –>--> <!-- <view class="common-module collaboration-module">--> <!-- <view class="module-header">--> <!-- <view class="module-title-container">--> <!-- <text class="module-title">åååå ¬</text>--> <!-- </view>--> <!-- </view>--> <!-- <view class="module-content">--> <!-- <up-grid :border="false"--> <!-- col="4">--> <!-- <up-grid-item v-for="(item, index) in collaborationItems"--> <!-- :key="index"--> <!-- @click="handleCommonItemClick(item)">--> <!-- <view class="icon-container"--> <!-- :style="{ background: item.bgColor }">--> <!-- <up-icon :name="item.icon"--> <!-- :size="58"--> <!-- color="#ffffff"></up-icon>--> <!-- </view>--> <!-- <text class="item-label">{{item.label}}</text>--> <!-- </up-grid-item>--> <!-- </up-grid>--> <!-- </view>--> <!-- </view>--> <!-- çäº§ç®¡æ§æ¨¡å --> <view class="common-module production-module"> <!-- <view class="common-module production-module">--> <!-- <view class="module-header">--> <!-- <view class="module-title-container">--> <!-- <text class="module-title">ç产管æ§</text>--> <!-- </view>--> <!-- </view>--> <!-- <view class="module-content">--> <!-- <up-grid--> <!-- :border="false"--> <!-- col="4"--> <!-- >--> <!-- <up-grid-item--> <!-- v-for="(item, index) in productionItems"--> <!-- :key="index"--> <!-- @click="handleCommonItemClick(item)"--> <!-- >--> <!-- <view class="icon-container" :style="{ background: item.bgColor }">--> <!-- <up-icon--> <!-- :name="item.icon"--> <!-- :size="58"--> <!-- color="#ffffff"--> <!-- ></up-icon>--> <!-- </view>--> <!-- <text class="item-label">{{item.label}}</text>--> <!-- </up-grid-item>--> <!-- </up-grid>--> <!-- </view>--> <!-- </view>--> <!-- çäº§ç®¡æ§æ¨¡å --> <view class="common-module equipment-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">ç产管æ§</text> @@ -158,39 +163,38 @@ </view> </view> <!-- 设å¤ç®¡ç模å --> <view class="common-module equipment-module"> <view class="module-header"> <view class="module-title-container"> <text class="module-title">设å¤ç®¡ç</text> </view> </view> <view class="module-content"> <up-grid :border="false" col="4"> <up-grid-item v-for="(item, index) in equipmentItems" :key="index" @click="handleCommonItemClick(item)"> <view class="icon-container" :style="{ background: item.bgColor }"> <up-icon :name="item.icon" :size="58" color="#ffffff"></up-icon> </view> <text class="item-label">{{item.label}}</text> </up-grid-item> </up-grid> </view> </view> <!-- <view class="common-module equipment-module">--> <!-- <view class="module-header">--> <!-- <view class="module-title-container">--> <!-- <text class="module-title">设å¤ç®¡ç</text>--> <!-- </view>--> <!-- </view>--> <!-- <view class="module-content">--> <!-- <up-grid :border="false"--> <!-- col="4">--> <!-- <up-grid-item v-for="(item, index) in equipmentItems"--> <!-- :key="index"--> <!-- @click="handleCommonItemClick(item)">--> <!-- <view class="icon-container"--> <!-- :style="{ background: item.bgColor }">--> <!-- <up-icon :name="item.icon"--> <!-- :size="58"--> <!-- color="#ffffff"></up-icon>--> <!-- </view>--> <!-- <text class="item-label">{{item.label}}</text>--> <!-- </up-grid-item>--> <!-- </up-grid>--> <!-- </view>--> <!-- </view>--> </view> </template> <script setup> import { ref, onMounted, nextTick, reactive } from "vue"; import dayjs from "dayjs"; import { userLoginFacotryList, noticesList } from "@/api/login"; import { userLoginFacotryList } from "@/api/login"; import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting"; import modal from "@/plugins/modal"; import useUserStore from "@/store/modules/user"; import { onShow } from "@dcloudio/uni-app"; const userStore = useUserStore(); const factoryId = ref(""); @@ -275,46 +279,6 @@ // åååå ¬åè½æ°æ® const collaborationItems = reactive([ { icon: "/static/images/icon/gongchuguanli@2x.png", label: "å ¬åºç®¡ç", }, { icon: "/static/images/icon/qingjiaguanli@2x.png", label: "请å管ç", }, { icon: "/static/images/icon/chuchaiguanli@2x.png", label: "åºå·®ç®¡ç", }, { icon: "/static/images/icon/chuchaiguanli@2x.png", label: "æ¥é管ç", }, { icon: "/static/images/icon/chuchaiguanli@2x.png", label: "éè´ç®¡ç", }, { icon: "/static/images/icon/chuchaiguanli@2x.png", label: "æ¥ä»·ç®¡ç", }, { icon: "/static/images/icon/chuchaiguanli@2x.png", label: "åºåºç®¡ç", }, { icon: "/static/images/icon/qingjiaguanli@2x.png", label: "ä¼è®®è®¾ç½®", }, { icon: "/static/images/icon/qingjiaguanli@2x.png", label: "ä¼è®®å表", }, { icon: "/static/images/icon/qingjiaguanli@2x.png", label: "ä¼è®®ç³è¯·", }, { icon: "/static/images/icon/xietongshenpi@2x.png", label: "åå审æ¹", }, @@ -322,58 +286,43 @@ icon: "/static/images/icon/kehubaifang@2x.png", label: "å®¢æ·æè®¿", }, { icon: "/static/images/icon/qingjiaguanli@2x.png", label: "éç¥å ¬å", }, ]); // åååå ¬åè½æ°æ®inventoryManagement/receiptManagement const inventoryManagement = reactive([ { icon: "/static/images/icon/rukuguanli@2x.png", label: "èªå®ä¹å ¥åº", }, { icon: "/static/images/icon/zidingyichuku.png", label: "èªå®ä¹åºåº", }, ]); // ç产管æ§åè½æ°æ® const productionItems = reactive([ { icon: "/static/images/icon/shengchandingdan@2x.png", label: "ç产订å", bgColor: "#FF9800", }, { icon: "/static/images/icon/shengchanpaigong@2x.png", label: "ç产派工", bgColor: "#FF6B35", }, { icon: "/static/images/icon/shengchanpaichan@2x.png", label: "å·¥åºæäº§", bgColor: "#E91E63", }, // { // icon: "/static/images/icon/shengchandingdan@2x.png", // label: "ç产订å", // bgColor: "#FF9800", // }, // { // icon: "/static/images/icon/shengchanpaigong@2x.png", // label: "ç产派工", // bgColor: "#FF6B35", // }, // { // icon: "/static/images/icon/shengchanpaichan@2x.png", // label: "å·¥åºæäº§", // bgColor: "#E91E63", // }, { icon: "/static/images/icon/shengchanbaogong@2x.png", label: "ç产æ¥å·¥", bgColor: "#673AB7", }, { icon: "/static/images/icon/shengchanhesuan@2x.png", label: "çäº§æ ¸ç®", bgColor: "#3F51B5", }, // { // icon: "/static/images/icon/shengchanhesuan@2x.png", // label: "çäº§æ ¸ç®", // bgColor: "#3F51B5", // }, ]); // 设å¤ç®¡çåè½æ°æ® const equipmentItems = reactive([ { icon: "/static/images/icon/shebeitaizhang@2x.png", label: "设å¤å°è´¦", }, // { // icon: '/static/images/icon/shebeitaizhang@2x.png', // label: '设å¤å°è´¦', // }, { icon: "/static/images/icon/shbeibaoxiu@2x.png", label: "è®¾å¤æ¥ä¿®", @@ -386,26 +335,26 @@ icon: "/static/images/icon/xunjianshangchuan@2x.png", label: "å·¡æ£ä¸ä¼ ", }, // { // icon: '/static/images/icon/guzhangfenxi@2x.png', // label: 'åæè¿½æº¯', // bgColor: '#ff9800' // }, // { // icon: '/static/images/icon/zhinengpaidan@2x.png', // label: 'æºè½æ´¾å', // bgColor: '#ff6b35' // }, // { // icon: '/static/images/icon/zuoyezhidao@2x.png', // label: 'ä½ä¸æå¯¼', // bgColor: '#4caf50' // }, // { // icon: '/static/images/icon/jieguoyanzheng@2x.png', // label: 'ç»æéªè¯', // bgColor: '#9c27b0' // } { icon: "/static/images/icon/guzhangfenxi@2x.png", label: "åæè¿½æº¯", bgColor: "#ff9800", }, { icon: "/static/images/icon/zhinengpaidan@2x.png", label: "æºè½æ´¾å", bgColor: "#ff6b35", }, { icon: "/static/images/icon/zuoyezhidao@2x.png", label: "ä½ä¸æå¯¼", bgColor: "#4caf50", }, { icon: "/static/images/icon/jieguoyanzheng@2x.png", label: "ç»æéªè¯", bgColor: "#9c27b0", }, ]); // å¤ç常ç¨åè½ç¹å» @@ -472,56 +421,6 @@ url: "/pages/procurementManagement/paymentLedger/index", }); break; case "å ¬åºç®¡ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index1", }); break; case "请å管ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index2", }); break; case "åºå·®ç®¡ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index3", }); break; case "æ¥é管ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index4", }); break; case "éè´ç®¡ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index5", }); break; case "æ¥ä»·ç®¡ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index6", }); break; case "åºåºç®¡ç": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index7", }); break; case "ä¼è®®è®¾ç½®": uni.navigateTo({ url: "/pages/managementMeetings/meetingSettings/index", }); break; case "ä¼è®®å表": uni.navigateTo({ url: "/pages/managementMeetings/meetingList/index", }); break; case "ä¼è®®ç³è¯·": uni.navigateTo({ url: "/pages/managementMeetings/meetApplication/index", }); break; case "åå审æ¹": uni.navigateTo({ url: "/pages/cooperativeOffice/collaborativeApproval/index", @@ -530,21 +429,6 @@ case "å®¢æ·æè®¿": uni.navigateTo({ url: "/pages/cooperativeOffice/clientVisit/index", }); break; case "éç¥å ¬å": uni.navigateTo({ url: "/pages/cooperativeOffice/noticeManagement/index", }); break; case "èªå®ä¹å ¥åº": uni.navigateTo({ url: "/pages/inventoryManagement/receiptManagement/index", }); break; case "èªå®ä¹åºåº": uni.navigateTo({ url: "/pages/inventoryManagement/issueManagement/index", }); break; case "ç产订å": @@ -559,18 +443,15 @@ break; case "å·¥åºæäº§": uni.navigateTo({ url: "/pages/productionManagement/operationScheduling/index", url: "/pages/productionManagement/processScheduling/index", }); break; case "ç产æ¥å·¥": getcode(); // uni.navigateTo({ // url: '/pages/productionManagement/productionReporting/index' // }); break; case "çäº§æ ¸ç®": uni.navigateTo({ url: "/pages/productionManagement/productionCosting/index", url: "/pages/productionManagement/productionAccounting/index", }); break; case "设å¤å°è´¦": @@ -620,53 +501,12 @@ }); } }; const getcode = () => { uni.scanCode({ success: res => { // è§£æäºç»´ç å 容 const scanResult = res.result; let orderRow = ""; // å°è¯ä»æ«ç ç»æä¸æåorderRowåæ° try { // å¤çæ··åæ ¼å¼: http://...?orderRow={...} const orderRowStart = scanResult.indexOf("orderRow={"); // æåä»orderRow={å¼å§çJSONå 容 const jsonPart = scanResult.substring(orderRowStart + 9); // 9æ¯"orderRow=".length // å°è¯ç´æ¥ä½¿ç¨è¿ä¸ªJSONé¨å orderRow = jsonPart; } catch (e) { orderRow = ""; } try { JSON.parse(orderRow); } catch (error) { modal.msgError("订åè§£æå¤±è´¥"); return; } // æ«ç æåå跳转å°ç产æ¥å·¥é¡µé¢ï¼å¹¶ä¼ éorderRowåæ° uni.navigateTo({ url: `/pages/productionManagement/productionReporting/index?orderRow=${orderRow}`, }); }, fail: err => { uni.showToast({ title: "æ«ç 失败", icon: "none", }); // uni.navigateTo({ // url: `/pages/productionManagement/productionReporting/index`, // }); }, }); }; // å建对åç»ä»¶çå¼ç¨ const uToastRef = ref(null); function getUserLoginFacotryList() { userLoginFacotryList({ userName: userStore.nickName, }) userLoginFacotryList({ userName: userStore.nickName }) .then(res => { // æ£æ¥res.dataæ¯å¦ä¸ºæ°ç» factoryList.value[0] = []; @@ -686,6 +526,89 @@ factoryList.value = []; }); } const getcode = () => { uni.scanCode({ success: async res => { // è§£æäºç»´ç å 容 const scanResult = res.result; let orderRow = ""; // å¤ææ«æç»ææ¯å¦ä¸ºçº¯æ°åï¼idï¼ const isNumericId = /^\d+$/.test(scanResult.trim()); if (isNumericId) { // 妿æ¯çº¯æ°åï¼æ ¹æ® id è·åå·¥åæ°æ® const workOrderId = scanResult.trim(); modal.loading("æ£å¨è·åå·¥åä¿¡æ¯..."); try { const workRes = await getProductWorkOrderById({ id: workOrderId }); modal.closeLoading(); console.log("å·¥åæ¥è¯¢ç»æ:", workRes); if (workRes.code === 200 && workRes.data) { // æ°æ¥å£è¿åçæ¯å个对象ï¼ä¸æ¯æ°ç» const workData = workRes.data; console.log("工忰æ®:", workData); orderRow = JSON.stringify({ id: workData.id || workOrderId, planQuantity: workData.planQuantity-workData.completeQuantity, productProcessRouteItemId: workData.productProcessRouteItemId || workData.产åå·¥èºè·¯çº¿é¡¹ID || "", }); console.log("æé çorderRow:", orderRow); } else { modal.msgError("æªæ¾å°å¯¹åºçå·¥åä¿¡æ¯"); return; } } catch (error) { modal.closeLoading(); console.error("è·åå·¥åä¿¡æ¯å¤±è´¥:", error); modal.msgError("è·åå·¥åä¿¡æ¯å¤±è´¥: " + (error.message || "æªç¥é误")); return; } } else { // 妿䏿¯çº¯æ°åï¼å°è¯ä»æ«ç ç»æä¸æåorderRowåæ° try { // å¤çæ··åæ ¼å¼: http://...?orderRow={...} const orderRowStart = scanResult.indexOf("orderRow={"); if (orderRowStart !== -1) { // æåä»orderRow={å¼å§çJSONå 容 const jsonPart = scanResult.substring(orderRowStart + 9); // 9æ¯"orderRow=".length orderRow = jsonPart; } else { // å¦æç´æ¥æ¯JSONå符串ï¼å°è¯è§£æ orderRow = scanResult; } } catch (e) { console.error(e, "è§£æå¤±è´¥====????====="); orderRow = ""; } // éªè¯æ¯å¦ä¸ºææçJSON try { JSON.parse(orderRow); } catch (error) { modal.msgError("订åè§£æå¤±è´¥ï¼è¯·æ£æ¥äºç»´ç æ ¼å¼"); return; } } console.log(orderRow, "orderRow======@@@@@@@@"); // æ«ç æåå跳转å°ç产æ¥å·¥é¡µé¢ï¼å¹¶ä¼ éorderRowåæ° uni.navigateTo({ url: `/pages/productionManagement/productionReport/index?orderRow=${orderRow}`, }); }, fail: err => { uni.showToast({ title: "æ«ç 失败", icon: "none", }); }, }); }; const changeFactory = async arr => { show.value = false; const factoryId = factoryListTem.value[arr.indexs[0]].deptId; @@ -707,7 +630,6 @@ modal.closeLoading(); }); }; function loginSuccess(result) { uni.reLaunch({ url: "/pages/index", @@ -720,68 +642,6 @@ uToastRef.value.success(`ç¹å»äºç¬¬${name + 1}个`); // 注æï¼è¿éå 1æ¯å 为é常æä»¬æ¯ä»ç¬¬1个å¼å§è®¡æ°ç } }; const isShowNoticesList = ref(true); // è·åå ¬åæ°é const getNoticesList = () => { if (!isShowNoticesList.value) { return; } const current_date = dayjs().format("YYYY-MM-DD"); noticesList({ current: -1, size: -1, status: 1, current_date, }) .then(resp => { console.log("noticesList", resp); if ( resp.code != 200 || !resp.data || !resp.data.records || !resp.data.records.length ) { return; } const res = uni.getAppAuthorizeSetting(); if (res.notificationAuthorized == "denied") { uni.showModal({ title: "æç¤º", content: "请å¨è®¾ç½®ä¸å¼å¯éç¥æé", success: res => { if (res.confirm) { uni.openAppAuthorizeSetting({ success: res => {}, }); } else { isShowNoticesList.value = false; } }, }); return; } resp.data.records.map(item => { createPushMessage(item.title); }); }) .catch(error => { // modal.msgError("è·åå ¬åæ°é:", error); }); }; const createPushMessage = text => { uni.createPushMessage({ title: "å ¬åéç¥", content: text || "", success: resp => { console.log("success", resp); isShowNoticesList.value = false; }, fail: resp => { console.log("fail", resp); }, }); }; onMounted(() => { // è®¾ç½®ç¨æ·ä¿¡æ¯ @@ -790,10 +650,8 @@ // å¯å¨éç¥ç¶æå®æ¶å¨ startStatusTimer(); }); onShow(() => { getNoticesList(); }); </script> <style scoped lang="scss"> .content { @@ -943,12 +801,10 @@ letter-spacing: 0.03125rem; text-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.5); } .hero-subtitle { font-size: 0.8125rem; margin-top: 0.375rem; } .hero-wave { height: 2.75rem; } @@ -1029,7 +885,6 @@ 0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); } 100% { transform: translateX(100%) translateY(100%) rotate(45deg); } @@ -1040,7 +895,6 @@ opacity: 0; transform: translateY(-1.25rem); } to { opacity: 1; transform: translateY(0); @@ -1052,7 +906,6 @@ opacity: 0; transform: translateY(1.25rem); } to { opacity: 1; transform: translateY(0); @@ -1064,7 +917,6 @@ opacity: 0; transform: translateY(0.5rem) scale(0.96); } 100% { opacity: 1; transform: translateY(0) scale(1); @@ -1124,9 +976,10 @@ } .notice-unit { color: #666666; font-size: 0.875rem; margin-left: 0.125rem; font-weight: 600; font-size: 1rem; color: #1976d2; margin-left: 0.25rem; } /* åè½æ¨¡åæ ·å¼ */ @@ -1300,20 +1153,16 @@ .content { background: linear-gradient(135deg, #121317 0%, #161a20 100%); } .content::before { background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="rgba(255, 255, 255, 0.05)"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>'); } .common-module { background: linear-gradient(135deg, #1e1f24 0%, #23252b 100%); box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35); } .module-title { color: #e9edf3; } .module-subtitle, .item-label, .notice-text, @@ -1321,18 +1170,15 @@ .notice-label { color: #c7cbd3; } .notice { background: linear-gradient(135deg, #1b2330 0%, #1a2432 100%); border-color: rgba(255, 255, 255, 0.06); box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4); } .notice-status, .notice-number { color: #8ab4ff; } .bg-img { background: linear-gradient(135deg, #1f4fb9 0%, #0e3a8a 100%); } @@ -1342,7 +1188,6 @@ from { transform: rotate(0deg); } to { transform: rotate(360deg); } @@ -1353,7 +1198,6 @@ opacity: 0; transform: translateY(-1.25rem); } to { opacity: 1; transform: translateY(0); @@ -1365,7 +1209,6 @@ opacity: 0; transform: translateY(1.25rem); } to { opacity: 1; transform: translateY(0); @@ -1377,7 +1220,6 @@ opacity: 0; transform: translateY(0.5rem) scale(0.96); } 100% { opacity: 1; transform: translateY(0) scale(1); @@ -1387,31 +1229,25 @@ .notice-left { margin-right: 1rem; } .notice-status { font-size: 1rem; } .notice-separator { width: 0.0625rem; height: 1.5rem; margin-right: 1rem; } .notice-label { font-size: 0.875rem; margin-right: 0.75rem; } .notice-text { font-size: 0.875rem; } .notice-number { font-size: 1rem; margin-left: 0.25rem; } .notice-unit { font-size: 0.875rem; margin-left: 0.125rem; @@ -1527,7 +1363,6 @@ margin-top: 0.25rem; margin-bottom: 0.625rem; } .grid-text { font-size: 0.875rem; } @@ -1536,7 +1371,6 @@ .common-module { box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35); } .notice { box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4); } src/pages/productionManagement/operationScheduling/components/formDia.vue
ÎļþÒÑɾ³ý src/pages/productionManagement/operationScheduling/index.vue
ÎļþÒÑɾ³ý src/pages/productionManagement/productionCosting/index.vue
ÎļþÒÑɾ³ý src/pages/productionManagement/productionDispatching/components/DispatchModal.vue
@@ -1,7 +1,7 @@ <template> <uni-popup ref="popupRef" type="bottom" <up-popup v-model:show="show" mode="bottom" :round="20" :safeAreaInsetBottom="true" @close="handleClose" @@ -26,33 +26,19 @@ > <!-- 项ç®åºæ¬ä¿¡æ¯ --> <view class="form-section"> <text class="section-title">产åä¿¡æ¯</text> <!-- <up-form-item label="项ç®åç§°" prop="projectName"> <text class="section-title">项ç®ä¿¡æ¯</text> <up-form-item label="项ç®åç§°" prop="projectName"> <up-input v-model="form.projectName" disabled placeholder="项ç®åç§°" /> </up-form-item> --> </up-form-item> <up-form-item label="产å大类" prop="productCategory"> <up-input v-model="form.productCategory" disabled placeholder="产å大类" /> </up-form-item> <up-form-item label="è§æ ¼åå·" prop="specificationModel"> <up-input v-model="form.specificationModel" disabled placeholder="è§æ ¼åå·" /> </up-form-item> <up-form-item label="ç»å®æºå¨" prop="speculativeTradingName"> <up-input v-model="form.speculativeTradingName" disabled placeholder="ç»å®æºå¨" /> </up-form-item> </view> @@ -90,14 +76,22 @@ <view class="form-section"> <text class="section-title">派工信æ¯</text> <up-form-item label="派工人" prop="schedulingUserId" required> <uni-data-select v-model="form.schedulingUserId" :localdata="userColumns" :clear="false"></uni-data-select> <up-input v-model="selectedUserName" placeholder="è¯·éæ©æ´¾å·¥äºº" readonly @click="showUserPicker = true" suffixIcon="arrow-down" /> </up-form-item> <up-form-item label="æ´¾å·¥æ¥æ" prop="schedulingDate" required> <uni-datetime-picker type="date" :clear-icon="false" v-model="form.schedulingDate"> <view class="datetime-picker-value"> {{form.schedulingDate}} </view> </uni-datetime-picker> <up-input v-model="form.schedulingDate" placeholder="è¯·éæ©æ´¾å·¥æ¥æ" readonly @click="showDatePicker = true" suffixIcon="calendar" /> </up-form-item> </view> </up-form> @@ -121,7 +115,23 @@ /> </view> </view> </uni-popup> <!-- 人åéæ©å¨ --> <up-picker v-model="showUserPicker" :columns="userColumns" @confirm="handleUserSelect" @cancel="showUserPicker = false" /> <!-- æ¥æéæ©å¨ --> <up-datetime-picker v-model="showDatePicker" mode="date" @confirm="handleDateSelect" @cancel="showDatePicker = false" /> </up-popup> </template> <script setup> @@ -136,16 +146,26 @@ const emit = defineEmits(['confirm']); // å¼¹çªæ¾ç¤ºç¶æ const popupRef = ref(); const show = ref(false); const submitting = ref(false); // 鿩卿¾ç¤ºç¶æ const showUserPicker = ref(false); const showDatePicker = ref(false); // ç¨æ·å表 const userList = ref([]); const userColumns = computed(() => { return userList.value.map(user => ({ text: user.nickName, const userColumns = computed(() => [ userList.value.map(user => ({ label: user.nickName, value: user.userId })) ]); // éä¸çç¨æ·åç§°ï¼ç¨äºæ¾ç¤ºï¼ const selectedUserName = computed(() => { const user = userList.value.find(u => u.userId === form.schedulingUserId); return user ? user.nickName : ''; }); // è¡¨åæ°æ® @@ -162,15 +182,15 @@ // 表åéªè¯è§å const rules = reactive({ // schedulingNum: [ // { required: true, message: "请è¾å ¥æäº§æ°é", trigger: "blur" } // ], // schedulingUserId: [ // { required: true, message: "è¯·éæ©æ´¾å·¥äºº", trigger: "change" } // ], // schedulingDate: [ // { required: true, message: "è¯·éæ©æ´¾å·¥æ¥æ", trigger: "change" } // ] schedulingNum: [ { required: true, message: "请è¾å ¥æäº§æ°é", trigger: "blur" } ], schedulingUserId: [ { required: true, message: "è¯·éæ©æ´¾å·¥äºº", trigger: "change" } ], schedulingDate: [ { required: true, message: "è¯·éæ©æ´¾å·¥æ¥æ", trigger: "change" } ] }); // 表åå¼ç¨ @@ -190,9 +210,9 @@ schedulingUserId: userStore.id, schedulingDate: dayjs().format("YYYY-MM-DD") }); popupRef.value.open() show.value = true; } catch (error) { console.log(error) uni.showToast({ title: 'å è½½ç¨æ·å表失败', icon: 'error' @@ -211,30 +231,29 @@ } }; // å¤çç¨æ·éæ© const handleUserSelect = (params) => { if (params.value && params.value.length > 0) { form.schedulingUserId = params.value[0]; } showUserPicker.value = false; }; // å¤çæ¥æéæ© const handleDateSelect = (params) => { if (params.value) { form.schedulingDate = dayjs(params.value).format("YYYY-MM-DD"); } showDatePicker.value = false; }; // 确认派工 const handleConfirm = async () => { if(!form.schedulingNum){ uni.showToast({ title: '请è¾å ¥æäº§æ°é', icon:'none' }) return } if(!form.schedulingUserId){ uni.showToast({ title: 'è¯·éæ©æ´¾å·¥äºº', icon:'none' }) return } if(!form.schedulingDate){ uni.showToast({ title: 'è¯·éæ©æ´¾å·¥æ¥æ', icon:'none' }) return } try { // 表åéªè¯ const valid = await formRef.value?.validate(); if (!valid) return; if (form.schedulingNum <= 0) { uni.showToast({ title: 'æäº§æ°éå¿ é¡»å¤§äº0', @@ -273,7 +292,10 @@ // å ³éå¼¹çª const handleClose = () => { popupRef.value.close() show.value = false; showUserPicker.value = false; showDatePicker.value = false; // é置表å Object.assign(form, { projectName: "", @@ -331,24 +353,6 @@ flex: 1; padding: 0 20px; overflow-y: auto; .datetime-picker-value{ font-size: 14px; border: 1px solid #e5e5e5; box-sizing: border-box; border-radius: 4px; padding: 0 5px; padding-left: 10px; position: relative; display: flex; -webkit-user-select: none; -moz-user-select: none; user-select: none; flex-direction: row; align-items: center; width: 100%; flex: 1; height: 35px; } } .form-section { src/pages/productionManagement/productionDispatching/components/autoDispatchDia.vue
ÎļþÒÑɾ³ý src/pages/productionManagement/productionDispatching/index.vue
@@ -3,134 +3,28 @@ <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="ç产派工" @back="goBack" /> <!-- çæºç¶æå±ç¤º --> <view class="machines-section"> <view class="section-title">çæºç¶æ</view> <view class="machines-grid"> <view v-for="machine in machines" :key="machine.id" class="machine-card"> <view class="machine-title">çæº{{ machine.id }}</view> <view class="machine-metrics"> <view class="metric-item"> <text class="metric-label">æ»é(kg)</text> <up-input v-model="machineTotal[machine.key]" type="number" placeholder="请è¾å ¥æ»é" border="surround" size="mini" class="metric-input" @change="updateMachineVacant(machine.key)" /> </view> <view class="metric-item"> <text class="metric-label">æ£å¨ç产(kg)</text> <text class="metric-value">{{ machineInProduction[machine.key] }}</text> </view> <view class="metric-item"> <text class="metric-label">空ä½é(kg)</text> <text class="metric-value">{{ machineVacant[machine.key] }}</text> </view> </view> </view> </view> <!-- æèç设置 --> <view class="loss-rate-section"> <view class="section-title">æèç设置</view> <view class="loss-rate-content"> <view class="loss-rate-item"> <up-button class="loss-rate-btn" type="primary" plain size="small" @click="showLossRateSheet = true" >{{ lossRate ? `æèç: ${lossRate}%` : 'è¯·éæ©æèç' }}</up-button> <up-action-sheet :show="showLossRateSheet" :actions="lossRateOptions" @select="onLossRateSelect" title="éæ©æèç" @close="showLossRateSheet = false" /> </view> </view> </view> <view class="save-section"> <up-button type="primary" @click="saveMachineTotals" size="normal" class="save-btn">ä¿åçæºè®¾ç½®</up-button> </view> </view> <!-- æç´¢åºå --> <view class="search-section"> <view class="search-form"> <view class="search-item"> <text class="search-label">客æ·åç§°</text> <view class="search-bar"> <view class="search-input"> <up-input class="search-text" placeholder="请è¾å ¥å®¢æ·åç§°æç´¢" v-model="searchForm.customerName" placeholder="请è¾å ¥å®¢æ·åç§°" @change="handleQuery" clearable border="surround" class="search-input" /> </view> <view class="search-item"> <text class="search-label">项ç®åç§°</text> <up-input v-model="searchForm.projectName" placeholder="请è¾å ¥é¡¹ç®åç§°" @change="handleQuery" clearable border="surround" class="search-input" /> <view class="filter-button" @click="handleQuery"> <up-icon name="search" size="24" color="#999"></up-icon> </view> <view class="search-buttons"> <up-button type="primary" @click="handleQuery" size="small" class="search-btn">æç´¢</up-button> <up-button @click="handleReset" size="small" class="reset-btn">éç½®</up-button> </view> </view> </view> <!-- æ¹éæä½åºå --> <view class="batch-actions-section" v-if="showBatchActions"> <view class="batch-info"> <text class="batch-text">已鿩 {{ selectedItems.length }} 个项ç®</text> </view> <view class="batch-buttons"> <up-button type="primary" size="small" @click="handleAutoDispatch" class="batch-btn">èªå¨æ´¾å</up-button> <up-button type="default" size="small" @click="clearSelection" class="batch-btn">åæ¶éæ©</up-button> </view> </view> <!-- å ¨éæä½åºå --> <view class="select-all-section" v-if="tableData.length > 0"> <view class="select-all-content"> <up-checkbox v-model="isAllSelected" @change="toggleAllSelection" label="å ¨é" class="select-all-checkbox" :disabled="tableData.length === 0 || tableData.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName).length === 0" /> </view> </view> <!-- ç产派工å表 --> <view class="ledger-list" v-if="tableData.length > 0"> <view v-for="(item, index) in tableData" :key="item.id || index" class="list-item"> <view v-for="(item, index) in tableData" :key="item.id || index"> <view class="ledger-item"> <!-- éæ©å¤éæ¡ --> <view class="item-checkbox"> <up-checkbox :model-value="selectedItems.some(selected => selected.id === item.id)" @change="(checked) => toggleItemSelection(item, checked)" :disabled="item.pendingQuantity <= 0 || !item.speculativeTradingName" shape="circle" /> </view> <view class="item-content"> <view class="item-header"> <view class="item-left"> <view class="document-icon"> @@ -138,22 +32,26 @@ </view> <text class="item-id">{{ item.salesContractNo }}</text> </view> <text class="entry-date">{{ item.entryDate }}</text> </view> <up-divider></up-divider> <view class="item-details"> <!-- <view class="detail-row"> <view class="detail-row"> <text class="detail-label">å½å ¥æ¥æ</text> <text class="detail-value">{{ item.entryDate }}</text> </view> <view class="detail-row"> <text class="detail-label">客æ·ååå·</text> <text class="detail-value">{{ item.customerContractNo }}</text> </view> --> </view> <view class="detail-row"> <text class="detail-label">客æ·åç§°</text> <text class="detail-value">{{ item.customerName }}</text> </view> <!-- <view class="detail-row"> <view class="detail-row"> <text class="detail-label">项ç®åç§°</text> <text class="detail-value">{{ item.projectName }}</text> </view> --> </view> <view class="detail-row"> <text class="detail-label">产å大类</text> <text class="detail-value">{{ item.productCategory }}</text> @@ -163,20 +61,8 @@ <text class="detail-value">{{ item.specificationModel }}</text> </view> <view class="detail-row"> <text class="detail-label">ç»å®æºå¨</text> <text class="detail-value">{{ item.speculativeTradingName }}</text> </view> <view class="detail-row"> <text class="detail-label">åä½</text> <text class="detail-value">{{ item.unit }}</text> </view> <view class="detail-row"> <text class="detail-label">å½å ¥æ¥æ</text> <text class="detail-value">{{ item.entryDate }}</text> </view> <view class="detail-row"> <text class="detail-label">æ°é</text> <text class="detail-value">{{ item.quantity }}</text> <text class="detail-label">æ»æ°é</text> <text class="detail-value">{{ item.quantity }} {{ item.unit }}</text> </view> <view class="detail-row"> <text class="detail-label">æäº§æ°é</text> @@ -186,6 +72,7 @@ <text class="detail-label">å¾ ææ°é</text> <text class="detail-value" :class="{ 'danger': item.pendingQuantity <= 0 }">{{ item.pendingQuantity }}</text> </view> </view> <!-- æä½æé®åºå --> <view class="action-buttons"> @@ -194,40 +81,30 @@ size="small" @click="handleDispatch(item)" class="action-btn" :disabled="item.pendingQuantity <= 0 || !item.speculativeTradingName" :disabled="item.pendingQuantity <= 0" > {{ item.pendingQuantity <= 0 ? 'æ éæ´¾å·¥' : !item.speculativeTradingName ? 'æªç»å®æºå¨' : 'ç产派工' }} ç产派工 </up-button> </view> </view> </view> </view> </view> </view> <view v-else class="no-data"> <up-empty mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png"> <text class="no-data-text">ææ çäº§æ´¾å·¥æ°æ®</text> </up-empty> <text>ææ çäº§æ´¾å·¥æ°æ®</text> </view> <!-- æ´¾å·¥å¼¹çª --> <DispatchModal ref="dispatchModalRef" @confirm="handleDispatchConfirm" /> <!-- èªå¨æ´¾åå¼¹çª --> <AutoDispatchDia ref="autoDispatchDia" /> </view> </template> <script setup> import { ref, reactive, toRefs, getCurrentInstance, nextTick } from "vue"; import { ref, reactive, toRefs, getCurrentInstance } from "vue"; import { onShow } from '@dcloudio/uni-app'; import dayjs from "dayjs"; import {schedulingListPage, schedulingList, addSpeculatTrading, updateSpeculatTrading, getLossRate, addLossRate, updateLossRate} from "@/api/productionManagement/productionOrder.js"; import {schedulingListPage} from "@/api/productionManagement/productionOrder.js"; import PageHeader from "@/components/PageHeader.vue"; import DispatchModal from "./components/DispatchModal.vue"; import AutoDispatchDia from "./components/autoDispatchDia.vue"; const { proxy } = getCurrentInstance(); // å è½½ç¶æ @@ -236,77 +113,23 @@ // åè¡¨æ°æ® const tableData = ref([]); // éæ©ç¸å ³æ°æ® const selectedItems = ref([]); const isAllSelected = ref(false); const showBatchActions = ref(false); // æç´¢è¡¨åæ°æ® const data = reactive({ searchForm: { customerName: "", projectName: "", }, }); const { searchForm } = toRefs(data); // å页é ç½® const page = reactive({ current: 1, size: 100, total: 0, current: -1, size: -1, }); // çæºç¶ææ°æ® const machineTotal = reactive({ m1: 0, m2: 0, m3: 0, m4: 0, }) const machineInProduction = reactive({ m1: 0, m2: 0, m3: 0, m4: 0, }) const machineVacant = reactive({ m1: 0, m2: 0, m3: 0, m4: 0, }) // çæºé ç½®æ°ç» const machines = [ { id: 1, key: 'm1' }, { id: 2, key: 'm2' }, { id: 3, key: 'm3' }, { id: 4, key: 'm4' } ] // æ¯å¦ææ¥è¯¢æ°æ®ï¼ç¨äºå¤ææ¯æ°å¢è¿æ¯ä¿®æ¹ï¼ const hasQueryData = ref(false); // æèçç¸å ³æ°æ® const lossRate = ref(""); // å½åéæ©çæèç const showLossRateSheet = ref(false); // æ§å¶æèç鿩颿¿æ¾ç¤º const lossRateOptions = ref([ { name: "6%", value: "6" }, { name: "7%", value: "7" }, { name: "8%", value: "8" }, { name: "9%", value: "9" }, { name: "10%", value: "10" } ]); const lossRateData = ref(null); // æèçæ¥è¯¢è¿åçæ°æ® // 派工弹çªå¼ç¨ const dispatchModalRef = ref(); // èªå¨æ´¾åå¼¹çªå¼ç¨ const autoDispatchDia = ref(); // éç¨æç¤ºå½æ° const showLoadingToast = (message) => { @@ -325,73 +148,9 @@ uni.navigateBack(); }; // éç½®æç´¢ const handleReset = () => { searchForm.value.customerName = ""; searchForm.value.projectName = ""; handleQuery(); }; // æ¥è¯¢å表 const handleQuery = () => { page.current = 1; getList(); }; // è·åçæºçäº§æ°æ® const getMachineProductionData = () => { schedulingList().then((res) => { if (res.data && Array.isArray(res.data)) { // éç½®æ°æ® machineInProduction.m1 = 0; machineInProduction.m2 = 0; machineInProduction.m3 = 0; machineInProduction.m4 = 0; // å¤ççæºæ°æ® res.data.forEach(item => { const machineId = Number(item.id); if (machineId >= 1 && machineId <= 4) { const machineKey = `m${machineId}`; if (item.workLoad !== null && item.workLoad !== undefined) { machineTotal[machineKey] = Number(item.workLoad) || 0; } if (item.currentWorkLoad !== null && item.currentWorkLoad !== undefined) { machineInProduction[machineKey] = Number(item.currentWorkLoad) || 0; } // 计ç®ç©ºä½é machineVacant[machineKey] = machineTotal[machineKey] - machineInProduction[machineKey]; } }); } }).catch(err => { console.error('è·åçæºæ°æ®å¤±è´¥:', err); }); }; // æèçéæ©äºä»¶ const onLossRateSelect = (action) => { lossRate.value = action.value; showLossRateSheet.value = false; console.log('éæ©äºæèç:', action.name, 'å¼:', action.value); }; // è·åæèçæ°æ® const getLossRateData = () => { getLossRate().then((res) => { if (res.data) { lossRateData.value = res.data; // 设置å½åéæ©çæèç if (res.data.rate !== null && res.data.rate !== undefined) { lossRate.value = res.data.rate.toString(); } } }).catch(err => { console.error('è·åæèç失败:', err); }); }; // è·ååè¡¨æ°æ® @@ -399,25 +158,18 @@ loading.value = true; showLoadingToast('å è½½ä¸...'); // æé 请æ±åæ° const params = { ...searchForm.value, ...page }; schedulingListPage(params).then((res) => { loading.value = false; closeToast(); // å¤çæ¯æ¡æ°æ®ï¼å¢å pendingQuantityåæ®µ tableData.value = (res.data.records || []).map(item => ({ ...item, pendingQuantity: (Number(item.quantity) || 0) - (Number(item.schedulingNum) || 0) })).filter(item => item.pendingQuantity > 0); page.total = res.data.total || 0; // è·åçæºæ°æ® getMachineProductionData(); // è·åæèçæ°æ® getLossRateData(); })); }).catch(() => { loading.value = false; closeToast(); @@ -438,14 +190,6 @@ return; } if (!item.speculativeTradingName) { uni.showToast({ title: 'è¯¥é¡¹ç®æªç»å®æºå¨ï¼æ æ³æ´¾å·¥', icon: 'none' }); return; } dispatchModalRef.value?.open(item); }; @@ -454,479 +198,25 @@ getList(); // å·æ°å表 }; // æ´æ°çæºç©ºä½é const updateMachineVacant = (machineKey) => { machineVacant[machineKey] = (Number(machineTotal[machineKey]) || 0) - (Number(machineInProduction[machineKey]) || 0); }; // è·åçæºæ¥è¯¢æ°æ® const getMachineQueryData = (machineId) => { // è¿ééè¦æ ¹æ®å®é æ åµä»æ¥è¯¢æ°æ®ä¸è·å对åºççæºæ°æ® // ææ¶è¿åä¸ä¸ªæ¨¡ææ°æ® return { id: machineId, name: `çæº${machineId}`, workLoad: machineTotal[`m${machineId}`] || 0, currentWorkLoad: machineInProduction[`m${machineId}`] || 0 }; }; // ä¿åæèç设置 const saveLossRate = () => { if (!lossRate.value) { console.log('æªéæ©æèçï¼è·³è¿ä¿å'); return Promise.resolve(); } const lossRateDataToSave = { rate: parseFloat(lossRate.value) || 0 }; // å¦æææ¥è¯¢å°çæèçæ°æ®ï¼è¯´ææ¯ä¿®æ¹æä½ï¼éè¦ä¼ éid if (lossRateData.value && lossRateData.value.id) { lossRateDataToSave.id = lossRateData.value.id; } console.log('ä¿åæèçæ°æ®:', lossRateDataToSave); // æ ¹æ®æ¯å¦ææèçæ°æ®å³å®è°ç¨æ°å¢æ¥å£è¿æ¯ä¿®æ¹æ¥å£ const saveLossApi = lossRateData.value && lossRateData.value.id ? updateLossRate : addLossRate; const successMessage = lossRateData.value && lossRateData.value.id ? 'æèçä¿®æ¹æå' : 'æèçæ°å¢æå'; return saveLossApi(lossRateDataToSave).then(res => { console.log('æèçä¿åæå:', res); uni.showToast({ title: successMessage, icon: 'success' }); // æ´æ°æèçæ°æ® if (res.data) { lossRateData.value = res.data; } return res; }).catch(err => { console.error('æèçä¿å失败:', err); uni.showToast({ title: 'æèçä¿å失败', icon: 'none' }); throw err; }); }; // ä¿åçæºæ»é设置 const saveMachineTotals = () => { // æé ä¿åæ°æ®æ°ç»ï¼ä½¿ç¨machinesæ°ç»å¾ªç¯æå»º const saveData = machines.map(machine => { const machineData = { name: `çæº${machine.id}`, // çæºåç§° workLoad: machineTotal[machine.key] || 0, // æ»é vacant: machineVacant[machine.key] || 0 // 空ä½é }; // 妿æ¯ä¿®æ¹æä½ï¼éè¦ä¼ éidåæ®µ if (hasQueryData.value) { // è¿ééè¦ä»æ¥è¯¢æ°æ®ä¸è·å对åºçid // å设æ¥è¯¢æ°æ®ä¸æ¯ä¸ªçæºæ°æ®é½æidåæ®µ const queryData = getMachineQueryData(machine.id); if (queryData && queryData.id) { machineData.id = queryData.id; } } return machineData; }); console.log('ä¿åçæºè®¾ç½®æ°æ®:', saveData); // æ ¹æ®æ¯å¦ææ¥è¯¢æ°æ®å³å®è°ç¨æ°å¢æ¥å£è¿æ¯ä¿®æ¹æ¥å£ const saveApi = hasQueryData.value ? updateSpeculatTrading : addSpeculatTrading; const successMessage = hasQueryData.value ? 'çæºè®¾ç½®ä¿®æ¹æå' : 'çæºè®¾ç½®æ°å¢æå'; console.log(`è°ç¨æ¥å£: ${hasQueryData.value ? 'ä¿®æ¹' : 'æ°å¢'}`); // å ä¿åæèçï¼åä¿åçæºè®¾ç½® saveLossRate().then(() => { // è°ç¨å端APIä¿åçæºè®¾ç½® return saveApi(saveData); }).then(res => { uni.showToast({ title: successMessage, icon: 'success' }); console.log('ä¿åæå:', res); // ä¿åæååï¼è®¾ç½®hasQueryData为trueï¼ä¸æ¬¡ä¿åå°è°ç¨ä¿®æ¹æ¥å£ if (!hasQueryData.value) { hasQueryData.value = true; } }).catch(err => { uni.showToast({ title: 'ä¿å失败', icon: 'none' }); console.error('ä¿å失败:', err); }); }; // 忢å个项ç®éæ©ç¶æ const toggleItemSelection = (item, checked) => { // ä» å è®¸éæ©å·²ç»å®æºå¨ä¸å¾ æ´¾æ°é>0çé¡¹ç® if (!item.speculativeTradingName || item.pendingQuantity <= 0) return; console.log('åæ¢éæ©ç¶æ:', item.id, checked); // ä½¿ç¨æ´ä¸¥æ ¼çæ¯è¾é»è¾ï¼ç¡®ä¿IDå¯ä¸æ§ const index = selectedItems.value.findIndex(selected => { // 深度æ¯è¾å¯¹è±¡ï¼ç¡®ä¿æ¯åä¸ä¸ªé¡¹ç® return JSON.stringify(selected) === JSON.stringify(item); }); if (checked) { // 妿éä¸ä¸ä¸å¨éä¸å表ä¸ï¼åæ·»å if (index === -1) { selectedItems.value.push({...item}); // å建æ°å¯¹è±¡ï¼é¿å å¼ç¨é®é¢ console.log('æ·»å 项ç®åé䏿°é:', selectedItems.value.length); } } else { // 妿忶éä¸ä¸å¨éä¸å表ä¸ï¼åç§»é¤ if (index > -1) { selectedItems.value.splice(index, 1); console.log('ç§»é¤é¡¹ç®åé䏿°é:', selectedItems.value.length); } } console.log('å½åéä¸é¡¹ç®å表:', selectedItems.value.map(s => s.id)); updateAllSelectedStatus(); updateBatchActionsVisibility(); }; // åæ¢å ¨éç¶æ const toggleAllSelection = () => { if (isAllSelected.value) { selectedItems.value = []; } else { selectedItems.value = tableData.value.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName).map(item => ({ ...item })); } isAllSelected.value = !isAllSelected.value; updateBatchActionsVisibility(); }; // æ´æ°å ¨éç¶æ const updateAllSelectedStatus = () => { const selectableItems = tableData.value.filter(item => item.pendingQuantity > 0 && item.speculativeTradingName); if (selectableItems.length > 0 && selectedItems.value.length === selectableItems.length && selectableItems.every(item => selectedItems.value.some(selected => selected.id === item.id))) { isAllSelected.value = true; } else { isAllSelected.value = false; } }; // æ´æ°æ¹éæä½æ¾ç¤ºç¶æ const updateBatchActionsVisibility = () => { showBatchActions.value = selectedItems.value.length > 0; }; // æ¸ ç©ºéæ© const clearSelection = () => { selectedItems.value = []; isAllSelected.value = false; showBatchActions.value = false; }; // è·åéä¸çé¡¹ç® const getSelectedItems = () => { return selectedItems.value; }; // å¤çèªå¨æ´¾å const handleAutoDispatch = () => { if (selectedItems.value.length === 0) { uni.showToast({ title: 'è¯·éæ©è¦æ´¾å·¥ç项ç®', icon: 'none' }); return; } // æ£æ¥æ¯å¦ææéä¸é¡¹ç®é½æç»å®æºå¨ const unboundItems = selectedItems.value.filter(item => !item.speculativeTradingName); if (unboundItems.length > 0) { uni.showToast({ title: 'æé项ç®ä¸ææªç»å®æºå¨ç项ç®ï¼æ æ³èªå¨æ´¾å', icon: 'none' }); return; } // ç¡®ä¿ä¼ éçæ¯å®æ´çéä¸é¡¹ç®æ°ç» autoDispatchDia.value?.openDialog([...selectedItems.value]); }; // 页颿¾ç¤ºæ¶å è½½æ°æ® onShow(() => { // å è½½åè¡¨æ°æ® getList(); clearSelection(); }); </script> <style scoped lang="scss"> @import '@/styles/sales-common.scss'; // çäº§æ´¾å·¥é¡µé¢æ ·å¼ .production-dispatching { min-height: 100vh; background: #f8f9fa; padding: 20rpx; position: relative; } // æèç设置åºå .loss-rate-section { background: #ffffff; border: 1rpx solid #e4e7ed; border-radius: 12rpx; padding: 32rpx; margin-top: 24rpx; margin-bottom: 32rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08); } .loss-rate-section .section-title { font-size: 32rpx; font-weight: 600; color: #303133; margin-bottom: 20rpx; } .loss-rate-section .loss-rate-content { display: flex; flex-direction: column; gap: 24rpx; } .loss-rate-section .loss-rate-content .loss-rate-item { display: flex; align-items: center; gap: 24rpx; } .loss-rate-section .loss-rate-content .loss-rate-label { font-size: 30rpx; font-weight: 500; color: #303133; min-width: 140rpx; white-space: nowrap; } .loss-rate-section .loss-rate-content .loss-rate-btn { min-width: 260rpx; font-size: 28rpx; height: 64rpx; line-height: 64rpx; border-radius: 8rpx; font-weight: 500; } // çæºç¶æåºå .machines-section { margin-bottom: 30rpx; } .machines-section .section-title { font-size: 32rpx; font-weight: 600; color: #303133; margin-bottom: 20rpx; } .machines-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20rpx; } .machine-card { background: #ffffff; border-radius: 16rpx; padding: 24rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); border: 1rpx solid #e9ecef; } .machine-title { font-size: 28rpx; font-weight: 600; color: #2c3e50; text-align: center; margin-bottom: 20rpx; padding-bottom: 16rpx; border-bottom: 2rpx solid #3498db; } .machine-metrics { display: flex; flex-direction: column; gap: 16rpx; } .metric-item { display: flex; justify-content: space-between; align-items: center; padding: 8rpx 0; } .metric-label { font-size: 24rpx; color: #6c757d; } .metric-value { font-size: 26rpx; font-weight: 600; color: #2c3e50; } // è¾å ¥æ¡æ ·å¼ .metric-input { width: 120rpx; text-align: right; } // ä¿ååºå .save-section { display: flex; justify-content: center; margin-top: 30rpx; padding-top: 20rpx; border-top: 1rpx solid #e9ecef; } .save-btn { min-width: 200rpx; } // æç´¢åºå .search-section { background: #ffffff; border-radius: 16rpx; padding: 24rpx; margin-bottom: 30rpx; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); } .search-form { display: flex; flex-direction: column; gap: 20rpx; } .search-item { display: flex; align-items: center; gap: 20rpx; } .search-label { font-size: 26rpx; color: #606266; min-width: 140rpx; } .search-input { flex: 1; } .search-buttons { display: flex; gap: 20rpx; justify-content: flex-end; margin-top: 10rpx; } .search-btn, .reset-btn { min-width: 120rpx; } // åè¡¨æ ·å¼ .ledger-list { display: flex; flex-direction: column; gap: 24rpx; } .list-item { background: #ffffff; border-radius: 16rpx; overflow: hidden; box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); } // åè¡¨é¡¹æ ·å¼ .ledger-item { padding: 0; } .item-header { display: flex; justify-content: space-between; align-items: center; padding: 24rpx 24rpx 0 24rpx; } .item-left { display: flex; align-items: center; gap: 16rpx; } .document-icon { width: 48rpx; height: 48rpx; background: #409eff; border-radius: 8rpx; display: flex; align-items: center; justify-content: center; } .item-id { font-size: 28rpx; font-weight: 600; color: #303133; } .entry-date { font-size: 24rpx; color: #909399; } .item-details { padding: 24rpx; } .detail-row { display: flex; justify-content: space-between; align-items: center; padding: 12rpx 0; border-bottom: 1rpx solid #f5f5f5; } .detail-row:last-child { border-bottom: none; } .detail-label { font-size: 26rpx; color: #606266; } .detail-value { font-size: 26rpx; color: #303133; font-weight: 500; } .detail-value.highlight { color: #ff6b35; font-weight: 600; @@ -936,113 +226,10 @@ color: #ee0a24; font-weight: 600; } .action-buttons { padding: 0 24rpx 24rpx 24rpx; display: flex; justify-content: flex-end; } .action-btn { min-width: 180rpx; } // æ¹éæä½åºåæ ·å¼ .batch-actions-section { background: #e8f4ff; border: 1rpx solid #409eff; border-radius: 12rpx; padding: 20rpx 24rpx; margin-bottom: 24rpx; display: flex; justify-content: space-between; align-items: center; } .batch-actions-section .batch-text { font-size: 28rpx; font-weight: 600; color: #409eff; } .batch-actions-section .batch-buttons { display: flex; gap: 16rpx; } .batch-actions-section .batch-btn { min-width: 140rpx; } // å ¨éæä½åºåæ ·å¼ .select-all-section { background: #ffffff; border-radius: 12rpx; padding: 20rpx 24rpx; margin-bottom: 16rpx; border: 1rpx solid #e4e7ed; } .select-all-section .select-all-content { display: flex; align-items: center; } .select-all-section .select-all-checkbox { font-size: 28rpx; font-weight: 500; } // åè¡¨é¡¹éæ©æ¡æ ·å¼ .ledger-item { display: flex; align-items: flex-start; padding: 0; } .item-checkbox { padding: 24rpx 16rpx 0 24rpx; display: flex; align-items: center; } .item-content { flex: 1; } // ç©ºç¶æ .no-data { padding: 100rpx 0; text-align: center; } .no-data-text { font-size: 28rpx; color: #909399; margin-top: 20rpx; } // ç¹å»ç¼è¾åºåæ ·å¼ .metric-value-container { cursor: pointer; min-width: 120rpx; text-align: right; padding: 4rpx 8rpx; border-radius: 4rpx; transition: all 0.2s ease; } .metric-value-container:hover { background-color: #f0f8ff; border: 1rpx solid #409eff; } // éé uView ç»ä»¶æ ·å¼ :deep(.up-input) { background: transparent; } :deep(.up-input__content) { background: #f8f9fa; } </style> src/pages/productionManagement/productionOrder/index.vue
@@ -40,29 +40,17 @@ <text class="detail-label">å½å ¥æ¥æ</text> <text class="detail-value">{{ item.entryDate }}</text> </view> <!-- <view class="detail-row"> <view class="detail-row"> <text class="detail-label">客æ·ååå·</text> <text class="detail-value">{{ item.customerContractNo }}</text> </view> --> </view> <view class="detail-row"> <text class="detail-label">客æ·åç§°</text> <text class="detail-value">{{ item.customerName }}</text> </view> <!-- <view class="detail-row"> <view class="detail-row"> <text class="detail-label">项ç®åç§°</text> <text class="detail-value">{{ item.projectName }}</text> </view> --> <view class="detail-row"> <text class="detail-label">仿¬¾ç¶æ</text> <view v-if="item.status=='已宿'" class="detail-value"> <uni-tag :inverted="true" text="已宿" type="success" size="mini" /> </view> <view v-else-if="item.status=='æªå®æ'" class="detail-value"> <uni-tag :inverted="true" text="æªå®æ" type="error" size="mini" /> </view> <view v-else class="detail-value"> <uni-tag :inverted="true" :text="item.status" type="primary" size="mini" /> </view> </view> <view class="detail-row"> <text class="detail-label">产å大类</text> @@ -157,6 +145,7 @@ schedulingListPage(params).then((res) => { loading.value = false; closeToast(); tableData.value = res.data.records || []; }).catch(() => { loading.value = false; src/pages/productionManagement/productionReport/index.vue
ÎļþÃû´Ó src/pages/productionManagement/productionReporting/index.vue ÐÞ¸Ä @@ -35,7 +35,9 @@ required> <u-input v-model="form.userName" placeholder="è¯·éæ©ç产人" readonly /> readonly @click="openProducerPicker" suffix-icon="arrow-down" /> </u-form-item> </view> <!-- 使ç¨FooterButtonsç»ä»¶ --> @@ -55,10 +57,9 @@ </template> <script setup> import { ref, onMounted } from "vue"; import { ref, nextTick } from "vue"; import { onLoad } from "@dcloudio/uni-app"; import FooterButtons from "@/components/FooterButtons.vue"; import modal from "@/plugins/modal"; const showToast = message => { uni.showToast({ @@ -68,35 +69,52 @@ }; import { addProductMain } from "@/api/productionManagement/productionReporting"; import { getInfo } from "@/api/login"; import { userListNoPageByTenantId } from "@/api/system/user"; // 表åå¼ç¨ const formRef = ref(); // è¡¨åæ°æ® let form = ref({ planQuantity: 0, quantity: 0, planQuantity: "", quantity: "", userName: "", workOrderId: "", reportWork: "", productProcessRouteItemId: "", userId: "", productMainId: null, schedulingUserId: "", }); let schedulingUserName = ref(""); // æ¥æéæ©å¨ç¶æ const showEnterDatePicker = ref(false); const enterDateValue = ref(Date.now()); // çäº§äººéæ©å¨ç¶æ const showProducerPicker = ref(false); const producerList = ref([]); // æå¼çäº§äººéæ©å¨ const openProducerPicker = async () => { if (producerList.value.length === 0) { // 妿å表为空ï¼å å è½½ç¨æ·å表 try { const res = await userListNoPageByTenantId(); const users = res.data || []; // 转æ¢ä¸º action-sheet éè¦çæ ¼å¼ producerList.value = users.map(user => ({ name: user.nickName || user.userName, value: user.userId, })); } catch (error) { console.error("å è½½ç¨æ·å表失败:", error); showToast("å è½½ç¨æ·å表失败"); return; } } showProducerPicker.value = true; }; // çäº§äººéæ©ç¡®è®¤ const onProducerConfirm = e => { form.value.schedulingUserId = e.value; schedulingUserName.value = e.name; form.value.userName = e.name; form.value.userId = e.value; // åæ¶æ´æ° userId showProducerPicker.value = false; }; @@ -116,14 +134,28 @@ showToast("请è¾å ¥æ¬æ¬¡ç产æ°é"); return; } if (form.value.quantity > form.value.planQuantity) { if (!form.value.schedulingUserId) { submitting.value = false; showToast("è¯·éæ©ç产人"); return; } // 转æ¢ä¸ºæ°åè¿è¡æ¯è¾ const quantity = Number(form.value.quantity); const planQuantity = Number(form.value.planQuantity); if (quantity > planQuantity) { submitting.value = false; showToast("æ¬æ¬¡ç产æ°éä¸è½å¤§äºå¾ ç产æ°é"); return; } console.log(form.value, "form.value"); // åå¤æäº¤æ°æ®ï¼ç¡®ä¿æ°éåæ®µä¸ºæ°åç±»å const submitData = { ...form.value, quantity: Number(form.value.quantity), planQuantity: Number(form.value.planQuantity) || 0, }; console.log(submitData, "submitData"); addProductMain(form.value).then(res => { addProductMain(submitData).then(res => { if (res.code === 200) { showToast("æ¥å·¥æå"); submitting.value = false; @@ -142,19 +174,25 @@ console.log(options, "options"); try { const orderRow = JSON.parse(options.orderRow); console.log("æé çorderRow:", orderRow); console.log(orderRow, "orderRow======########"); form.value.planQuantity = orderRow.planQuantity; form.value.quantity = orderRow.quantity; form.value.productProcessRouteItemId = orderRow.productProcessRouteItemId; form.value.workOrderId = orderRow.id; form.value.reportWork = orderRow.reportWork; form.value.productMainId = orderRow.productMainId; // ç¡®ä¿ planQuantity 转æ¢ä¸ºå符串ï¼ä»¥ä¾¿å¨ u-input 䏿£ç¡®æ¾ç¤º form.value.planQuantity = orderRow.planQuantity != null ? String(orderRow.planQuantity) : ""; form.value.productProcessRouteItemId = orderRow.productProcessRouteItemId || ""; form.value.workOrderId = orderRow.id || ""; getInfo().then(res => { // é»è®¤ä½¿ç¨å½åç»å½ç¨æ·ï¼ä½å è®¸ç¨æ·ä¿®æ¹ form.value.userId = res.user.userId; form.value.userName = res.user.userName; form.value.schedulingUserId = res.user.userId; }); // ä½¿ç¨ nextTick ç¡®ä¿ DOM æ´æ° nextTick(() => { console.log("form.value after assignment:", form.value); }); } catch (error) { modal.msgError("订åè§£æå¤±è´¥"); console.error("订åè§£æå¤±è´¥:", error); showToast("订åè§£æå¤±è´¥"); goBack(); return; } src/pages/productionManagement/productionReporting/components/formDia.vue
ÎļþÒÑɾ³ý yarn.lock
ÎļþÒÑɾ³ý