| | |
| | | <template> |
| | | <div class="container"> |
| | | <!-- 左侧åºå - æ 任使 颿 注 --> |
| | | <!-- 左侧åºå - ä»
ä¿çä¿¡å·ç¯+æå/é¶ä»¶åºå --> |
| | | <div class="left-area"> |
| | | <div class="left-top"> |
| | | <!-- æé®+ä¿¡å· æ¨ªåæåå®¹å¨ --> |
| | | <div class="btn-signal-group"> |
| | | <!-- æé®ç» - ä¿®æ¹ä¸ºä¸ä¸æå --> |
| | | <div class="btn-group"> |
| | | <button |
| | | class="btn" |
| | | :class="isPLCStarted ? 'stop-btn' : 'start-btn'" |
| | | @click="handleToggle" |
| | | > |
| | | <i class="icon" :class="isPLCStarted ? 'icon-stop' : 'icon-start'"></i> |
| | | {{ isPLCStarted ? "å
³é" : "å¯å¨" }} |
| | | </button> |
| | | <button |
| | | class="btn" |
| | | :class="isPLCPaused ? 'resume-btn' : 'pause-btn'" |
| | | @click="handlePauseToggle" |
| | | :disabled="!isPLCStarted" |
| | | > |
| | | <i class="icon" :class="isPLCPaused ? 'icon-resume' : 'icon-pause'"></i> |
| | | {{ isPLCPaused ? "æ¢å¤" : "æå" }} |
| | | </button> |
| | | </div> |
| | | |
| | | <!-- ä¿¡å·ç¯ç» å 两个æé®å®½åº¦ + æ´ä½æ¾å¤§ --> |
| | | <div class="signal-status"> |
| | | <div class="signal-item" v-for="(signal, index) in signalStates" :key="index"> |
| | | <div |
| | |
| | | <div class="signal-light-inner"></div> |
| | | </div> |
| | | <span class="signal-label">{{ signalLabels[index] }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | class="part-checkbox" |
| | | v-model="leftPartChecked[index]" |
| | | @change="handlePartCheck(index)" |
| | | :disabled="checkLoading[index]" |
| | | /> |
| | | <span class="checkmark"></span> |
| | | <span class="checkbox-label">{{ |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å³ä¾§åºå - æ 任使 颿 注 ãå·²å 餿¸
空+ä¿åæé®ã --> |
| | | <!-- å³ä¾§åºå - ä¿çåæå½å
¥+æäº¤+æ¸
é¤åè½ --> |
| | | <div class="right-area"> |
| | | <div class="right-top"> |
| | | <div class="form-row"> |
| | | <div class="form-row input-submit-row"> |
| | | <span class="label">å½å
¥æ¡ï¼</span> |
| | | <!-- â
åªä¿ç纯å½å
¥æ¡ï¼æ¸
空/ä¿åæé®å·²å é¤ --> |
| | | <input type="text" class="input-box" v-model="rightTopInput" /> |
| | | <button class="btn save-btn submit-input-btn" @click="saveData"> |
| | | <i class="icon icon-submit"></i>æäº¤ |
| | | </button> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="right-bottom"> |
| | | <div class="form-row tooling-board-row"> |
| | | <span class="short-label">å·¥è£
æ¿ç¼å·ï¼</span> |
| | | <input |
| | | type="text" |
| | | class="input-box short-input" |
| | | v-model="toolingBoardNo" |
| | | placeholder="请è¾å
¥å·¥è£
æ¿ç¼å·" |
| | | /> |
| | | <button class="btn clear-btn" @click="clearToolingBoardNo"> |
| | | <i class="icon icon-clear"></i>æ¸
é¤ |
| | | </button> |
| | | <button class="btn save-btn" @click="saveToolingBoardNo"> |
| | | <i class="icon icon-submit"></i>æäº¤ |
| | | </button> |
| | | </div> |
| | | <div class="parts-list"> |
| | | <div class="form-row part-item finished-product-row"> |
| | | <span class="label">æåç¼å·ï¼</span> |
| | |
| | | |
| | | export default { |
| | | setup() { |
| | | // åºç¡æ°æ®å®ä¹ - 1:1ç²¾å对æ¥å端 æåç¼å·+é¶ä»¶ç¼å· æ åä½å
¼å®¹ |
| | | const finishedProduct = ref(""); // 左侧æåç¼å·ï¼GetLeftInitialDataæ¥å£è¿åï¼ |
| | | const finishedProductId = ref(""); |
| | | const rightTopInput = ref(""); |
| | | // åºç¡æ°æ®å®ä¹ |
| | | const finishedProduct = ref(""); // 左侧æåç¼å·ï¼æ¥å£è¿åï¼ |
| | | const finishedProductId = ref(""); // 左侧æåIDï¼æ¥å£è¿åï¼ |
| | | const rightTopInput = ref(""); // å³ä¾§æ ¸å¿å½å
¥æ¡ |
| | | const leftPartCodes = ref(Array(10).fill("")); // 左侧é¶ä»¶ç¼å·æ°ç» |
| | | const rightPartCodes = ref(Array(10).fill("")); // å³ä¾§é¶ä»¶ç¼å·æ°ç» |
| | | const leftPartChecked = ref(Array(10).fill(false)); |
| | | const toolingBoardNo = ref(""); |
| | | const fillIndex = ref(-1); |
| | | const leftPartIds = ref(Array(10).fill("")); |
| | | const finishedProductCode = ref(""); // å³ä¾§æåç¼å·ï¼å·¥è£
æ¿æ¥å£è¿åï¼ |
| | | const leftPartChecked = ref(Array(10).fill(false)); // 左侧é¶ä»¶å¾éç¶æ |
| | | const leftPartIds = ref(Array(10).fill("")); // 左侧é¶ä»¶IDï¼æ¥å£è¿åï¼ |
| | | const finishedProductCode = ref(""); // å³ä¾§æåç¼å·è¾å
¥æ¡ |
| | | const fillIndex = ref(-1); // å½å
¥æ¡èªå¨å¡«å
ç´¢å¼ |
| | | const checkLoading = ref(Array(10).fill(false)); // é¶ä»¶å¾éå è½½é |
| | | |
| | | // PLCç¶æ |
| | | const isPLCStarted = ref(false); |
| | | const isPLCPaused = ref(false); |
| | | |
| | | // ä¿¡å·ç¸å
³ |
| | | // ä¿¡å·ç¯ç¸å
³ |
| | | const signalStates = ref([false, false, false, false, false]); |
| | | const signalLabels = ref([ |
| | | "å¿è·³ä¿¡å·", |
| | |
| | | "æ
éä¿¡å·", |
| | | ]); |
| | | |
| | | // 宿¶è½®è¯¢æ ¸å¿é
ç½® |
| | | // 宿¶/鲿ç¸å
³åé |
| | | let pollingTimer = null; |
| | | const pollingInterval = 5000; |
| | | const pollingInterval = 5000; // ä¿¡å·ç¯è½®è¯¢é´é5ç§ |
| | | let checkDebounceTimer = null; |
| | | let destroyDelayTimer = null; |
| | | const destroyDelayTime = 500; // â
æ ¸å¿ï¼å¡«å
+æ¸
空 é½å»¶è¿500æ¯«ç§ |
| | | let boardCodeDebounceTimer = null; |
| | | // â
æ°å¢ï¼èªå¨æäº¤é²æå®æ¶å¨ï¼é²æ¢éå¤æäº¤ |
| | | const destroyDelayTime = 500; // å½å
¥æ¡å¡«å
å»¶è¿500ms |
| | | let autoSubmitDebounceTimer = null; |
| | | // â
æ°å¢ï¼æäº¤éï¼é²æ¢æ å¾éæ¶éå¤è§¦åæäº¤ |
| | | let submitLock = ref(false); |
| | | let submitLock = ref(false); // æäº¤éï¼é²æ¢éå¤æäº¤ |
| | | |
| | | // â
â
â
æ ¸å¿æ°å¢1ï¼è®¡ç®å±æ§ - 宿¶ç»è®¡å·¦ä¾§å¾éçå¤éæ¡æ°é (èªå¨æ´æ°) |
| | | // 计ç®å±æ§ - ç»è®¡ææå¾é/å¡«å
æ°éï¼è¿æ»¤ç©ºå¼ï¼ |
| | | const checkedCount = computed(() => { |
| | | // ç»è®¡leftPartCheckedæ°ç»ä¸ä¸ºtrueçæ°é |
| | | return leftPartChecked.value.filter((checked) => checked === true).length; |
| | | }); |
| | | |
| | | // â
â
â
æ ¸å¿æ°å¢2ï¼è®¡ç®å±æ§ - 宿¶ç»è®¡å³ä¾§å·²å¡«å
çé¶ä»¶æ°é (èªå¨æ´æ°) |
| | | const filledPartCount = computed(() => { |
| | | // ç»è®¡rightPartCodesæ°ç»ä¸æå¼(é空)çé¶ä»¶æ°é |
| | | return rightPartCodes.value.filter((code) => code.trim() !== "").length; |
| | | }); |
| | | |
| | | // â
è·å左侧åå§æ°æ® - å¯¹æ¥ /api/scanStation/GetLeftInitialData |
| | | // è·å左侧åå§æ°æ®ï¼æå+é¶ä»¶+å¾éç¶æï¼ |
| | | const fetchLeftInitialData = async () => { |
| | | try { |
| | | console.log("æ£å¨è·å左侧åå§æ°æ®ï¼æåç¼å·+é¶ä»¶ç¼å·+å¾éç¶æ+é¶ä»¶IDï¼..."); |
| | | console.log("æ£å¨è·å左侧åå§æ°æ®..."); |
| | | const response = await axios.get("/api/scanStation/GetLeftInitialData", { |
| | | timeout: 5000, |
| | | }); |
| | |
| | | const data = resData.Data || resData.data || {}; |
| | | if (data.finishedProductId) finishedProductId.value = data.finishedProductId; |
| | | if (data.finishedProduct) finishedProduct.value = data.finishedProduct; |
| | | // èµå¼å·¦ä¾§é¶ä»¶ç¼å· |
| | | if (Array.isArray(data.leftPartCodes) && data.leftPartCodes.length >= 10) { |
| | | for (let i = 0; i < 10; i++) { |
| | | leftPartCodes.value[i] = data.leftPartCodes[i] || ""; |
| | | leftPartIds.value[i] = data.leftPartIds?.[i] || ""; |
| | | } |
| | | } |
| | | // èµå¼å¾éç¶æ |
| | | if (Array.isArray(data.leftPartChecked) && data.leftPartChecked.length >= 10) { |
| | | for (let i = 0; i < 10; i++) { |
| | | leftPartChecked.value[i] = !!data.leftPartChecked[i]; |
| | |
| | | } |
| | | }; |
| | | |
| | | // â
è·åä¿¡å·+PLCç¶æ |
| | | // è·åä¿¡å·ç¯ç¶æï¼å®æ¶è½®è¯¢ï¼ |
| | | const fetchSignalAndPLCStates = async () => { |
| | | try { |
| | | const response = await axios.get("/api/scanStation/GetSignalStates", { |
| | |
| | | const data = resData.Data || resData.data || {}; |
| | | const newSignalStates = data.signalStates || []; |
| | | for (let i = 0; i < 5; i++) signalStates.value[i] = newSignalStates[i] ?? false; |
| | | const plcStatus = data.plcStatus || data.plc_status || {}; |
| | | isPLCStarted.value = plcStatus.isStarted ?? isPLCStarted.value; |
| | | // â
ä¿®å¤BUGï¼åä»£ç æ¯ isPLCStarted.value å¯¼è´æåç¶æèµå¼é误 |
| | | isPLCPaused.value = plcStatus.isPaused ?? isPLCPaused.value; |
| | | } |
| | | } catch (error) { |
| | | console.error("è·åä¿¡å·åPLCç¶æå¤±è´¥ï¼", error); |
| | | console.error("è·åä¿¡å·ç¶æå¤±è´¥ï¼", error); |
| | | } |
| | | }; |
| | | |
| | | // â
ãæ ¸å¿ä¿®æ¹ãå·¥è£
æ¿æ¥è¯¢æ¥å£ - ææ°æ®å°±å¡«å
ï¼æ æ°æ®/失败 å®å
¨ä¿çåæå
容ï¼ä¸å任使¸
空æä½ |
| | | const fetchProductAndPartsByBoardCode = async (boardCode) => { |
| | | if (!boardCode.trim()) return; |
| | | try { |
| | | console.log(`å·¥è£
æ¿ç¼å·åæ´ï¼è¯·æ±æ°æ®ï¼${boardCode}`); |
| | | const response = await axios.get( |
| | | "/api/boxingDetail/GetProductAndPartsByBoardNo", |
| | | { |
| | | params: { palletCode: boardCode.trim() }, |
| | | timeout: 5000, |
| | | } |
| | | ); |
| | | const resData = response.data; |
| | | const isSuccess = resData.Status === true || resData.status === true; |
| | | // â
åªæãæ¥å£æå+æè¿åæ°æ®ãçæ¶åï¼ææ§è¡èµå¼è¦ç |
| | | if (isSuccess) { |
| | | const data = resData.Data || resData.data || {}; |
| | | // ææåç¼å·å°±èµå¼ï¼æ²¡æå°±ä¸æä½ |
| | | if (data.finishedProductCode) { |
| | | finishedProductCode.value = data.finishedProductCode; |
| | | } |
| | | // æé¶ä»¶å表就填å
ï¼æ²¡æå°±ä¸æä½ |
| | | const partsList = Array.isArray(data.partsList) ? data.partsList : []; |
| | | if (partsList.length > 0) { |
| | | for (let i = 0; i < 10; i++) { |
| | | if (partsList[i]) { |
| | | rightPartCodes.value[i] = partsList[i]; |
| | | } |
| | | } |
| | | } |
| | | console.log("â
å·¥è£
æ¿æ¥è¯¢æåï¼æåç¼å·+é¶ä»¶ç¼å·å¡«å
宿"); |
| | | } else { |
| | | // â
æ å¯¹åºæ°æ®ï¼åªå¼¹æç¤ºï¼ä¸æ¸
空任ä½å
容 |
| | | alert( |
| | | "è·åæ°æ®å¤±è´¥ï¼" + (resData.Message || resData.message || "æ 对åºå·¥è£
æ¿æ°æ®") |
| | | ); |
| | | } |
| | | } catch (error) { |
| | | // â
请æ±å¤±è´¥ï¼åªå¼¹æç¤ºï¼ä¸æ¸
空任ä½å
容 |
| | | alert("å·¥è£
æ¿æ°æ®è¯·æ±å¤±è´¥ï¼è¯·æ£æ¥ç½ç»ææ¥å£ï¼"); |
| | | console.error("å·¥è£
æ¿æ¥å£è¯·æ±å¤±è´¥ï¼", error); |
| | | } finally { |
| | | boardCodeDebounceTimer = null; |
| | | } |
| | | }; |
| | | |
| | | // å¯å¨/忢宿¶è½®è¯¢ |
| | | // å¯å¨/åæ¢ä¿¡å·ç¯è½®è¯¢ |
| | | const startPolling = () => { |
| | | if (pollingTimer) clearInterval(pollingTimer); |
| | | fetchSignalAndPLCStates(); |
| | |
| | | pollingTimer = null; |
| | | }; |
| | | |
| | | // PLCå¯å¨/å
³éé»è¾ |
| | | const handleToggle = async () => { |
| | | try { |
| | | const response = await axios.get("/api/scanStation/StartPLC", { |
| | | params: { isStop: isPLCStarted.value }, |
| | | timeout: 5000, |
| | | }); |
| | | const resData = response.data; |
| | | const isSuccess = resData.Status === true || resData.status === true; |
| | | if (isSuccess) { |
| | | isPLCStarted.value = !isPLCStarted.value; |
| | | isPLCPaused.value = false; |
| | | fetchSignalAndPLCStates(); |
| | | } else { |
| | | alert( |
| | | resData.Message || |
| | | resData.message || |
| | | (isPLCStarted.value ? "å
³é失败" : "å¯å¨å¤±è´¥") |
| | | ); |
| | | } |
| | | } catch (error) { |
| | | alert(isPLCStarted.value ? "å
³éPLC失败" : "å¯å¨PLC失败"); |
| | | console.error("PLCå¯å失败ï¼", error); |
| | | } |
| | | }; |
| | | |
| | | // PLCæå/æ¢å¤é»è¾ |
| | | const handlePauseToggle = async () => { |
| | | try { |
| | | const response = await axios.get("/api/scanStation/PausePLC", { |
| | | params: { isPause: !isPLCPaused.value }, |
| | | timeout: 5000, |
| | | }); |
| | | const resData = response.data; |
| | | const isSuccess = resData.Status === true || resData.status === true; |
| | | if (isSuccess) { |
| | | isPLCPaused.value = !isPLCPaused.value; |
| | | fetchSignalAndPLCStates(); |
| | | } else { |
| | | alert( |
| | | resData.Message || |
| | | resData.message || |
| | | (isPLCPaused.value ? "æ¢å¤å¤±è´¥" : "æå失败") |
| | | ); |
| | | } |
| | | } catch (error) { |
| | | alert(isPLCPaused.value ? "æ¢å¤PLC失败" : "æåPLC失败"); |
| | | console.error("PLCæåæ¢å¤å¤±è´¥ï¼", error); |
| | | } |
| | | }; |
| | | |
| | | // é¶ä»¶å¾éç¶æåæ´å¤ç |
| | | // 左侧é¶ä»¶å¾éç¶æåæ´å¤çï¼æ´æ°åç«¯ç¶æï¼ |
| | | const handlePartCheck = async (index) => { |
| | | const isChecked = leftPartChecked.value[index]; |
| | | const partCode = leftPartCodes.value[index]; |
| | | const partId = leftPartIds.value[index]; |
| | | |
| | | // åç½®æ ¡éª |
| | | if (!finishedProductId.value) { |
| | | alert("æåIDä¸åå¨ï¼æ æ³æ´æ°é¶ä»¶æ«ç ç¶æï¼"); |
| | | leftPartChecked.value[index] = !isChecked; |
| | |
| | | return; |
| | | } |
| | | |
| | | if (checkDebounceTimer) clearTimeout(checkDebounceTimer); |
| | | checkDebounceTimer = setTimeout(async () => { |
| | | checkLoading.value[index] = true; |
| | | try { |
| | | const response = await axios.post( |
| | | "/api/scanStation/UpdatePartScannedStatus", |
| | |
| | | const isSuccess = resData.Status === true || resData.status === true; |
| | | if (isSuccess) { |
| | | console.log(`é¶ä»¶${index + 1}æ«ç ç¶ææ´æ°æå`); |
| | | // â
å¾éç¶æååæ¶ï¼éç½®æäº¤é |
| | | submitLock.value = false; |
| | | } else { |
| | | leftPartChecked.value[index] = !isChecked; |
| | | alert( |
| | |
| | | alert(`é¶ä»¶${index + 1}ç¶ææ´æ°è¯·æ±å¤±è´¥ï¼è¯·æ£æ¥ç½ç»ææ¥å£ï¼`); |
| | | console.error(`æ´æ°é¶ä»¶${index + 1}æ«ç ç¶æå¤±è´¥ï¼`, error); |
| | | } finally { |
| | | checkLoading.value[index] = false; |
| | | if (checkDebounceTimer) clearTimeout(checkDebounceTimer); |
| | | checkDebounceTimer = null; |
| | | } |
| | | }, 500); |
| | | }; |
| | | |
| | | // â
æ ¸å¿ä¿®æ¹ï¼å»¶è¿0.5ç§å¡«å
+ å»¶è¿0.5ç§æ¸
空 忥æ§è¡ æ éæå¨æé® |
| | | // å³ä¾§å½å
¥æ¡å»¶è¿å¡«å
é»è¾ï¼æåâé¶ä»¶ä¾æ¬¡å¡«å
ï¼ |
| | | const fillContent = () => { |
| | | if (!rightTopInput.value.trim()) return; |
| | | const inputValue = rightTopInput.value.trim(); |
| | | |
| | | // æ¸
餿§å®æ¶å¨ï¼é²æ¢é夿§è¡ |
| | | if (destroyDelayTimer) clearTimeout(destroyDelayTimer); |
| | | // ç»ä¸å»¶è¿500msæ§è¡ãå¡«å
+æ¸
空ã |
| | | destroyDelayTimer = setTimeout(() => { |
| | | if (!toolingBoardNo.value.trim()) { |
| | | toolingBoardNo.value = inputValue; |
| | | } else if (!finishedProductCode.value.trim()) { |
| | | if (!finishedProductCode.value.trim()) { |
| | | finishedProductCode.value = inputValue; |
| | | } else if (fillIndex.value < 10) { |
| | | rightPartCodes.value[fillIndex.value] = inputValue; |
| | | fillIndex.value++; |
| | | } else { |
| | | alert("å·¥è£
æ¿ç¼å·ãæåç¼å·åé¶ä»¶1-10å·²å
¨é¨å¡«å
宿,æ æ³ç»§ç»å½å
¥!"); |
| | | alert("æåç¼å·åé¶ä»¶1-10å·²å
¨é¨å¡«å
宿,æ æ³ç»§ç»å½å
¥!"); |
| | | rightTopInput.value = ""; |
| | | destroyDelayTimer = null; |
| | | return; |
| | | } |
| | | // å¡«å
宿å èªå¨æ¸
空å½å
¥æ¡ |
| | | rightTopInput.value = ""; |
| | | destroyDelayTimer = null; |
| | | }, destroyDelayTime); |
| | | }; |
| | | |
| | | // â
çå¬å½å
¥æ¡å
容ååèªå¨è§¦åå¡«å
é»è¾ |
| | | // çå¬å³ä¾§å½å
¥æ¡è¾å
¥ï¼è§¦åèªå¨å¡«å
|
| | | watch( |
| | | rightTopInput, |
| | | (newVal) => { |
| | |
| | | { immediate: false } |
| | | ); |
| | | |
| | | // çå¬å·¥è£
æ¿ç¼å·ååæ¥è¯¢æ°æ® |
| | | watch( |
| | | toolingBoardNo, |
| | | (newVal) => { |
| | | const boardCode = newVal.trim(); |
| | | if (boardCode) { |
| | | if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer); |
| | | boardCodeDebounceTimer = setTimeout( |
| | | () => fetchProductAndPartsByBoardCode(boardCode), |
| | | 300 |
| | | ); |
| | | } else { |
| | | if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer); |
| | | } |
| | | }, |
| | | { immediate: false } |
| | | ); |
| | | |
| | | // å³ä¾§é¡µé¢æä½æ¹æ³ (å·²å 餿¸
空/ä¿åå½å
¥æ¡çæ¹æ³ï¼æ åä½) |
| | | const clearToolingBoardNo = () => (toolingBoardNo.value = ""); |
| | | // å³ä¾§è¾å
¥æ¡æ¸
餿¹æ³ |
| | | const clearRightPart = (index) => (rightPartCodes.value[index] = ""); |
| | | const clearFinishedProductCode = () => (finishedProductCode.value = ""); |
| | | |
| | | // æäº¤å·¥è£
æ¿æ°æ®å°å端 |
| | | const saveToolingBoardNo = async () => { |
| | | if (!toolingBoardNo.value.trim()) { |
| | | alert("å·¥è£
æ¿ç¼å·ä¸è½ä¸ºç©ºï¼è¯·è¾å
¥ååæäº¤ï¼"); |
| | | // æ ¸å¿ä¿®æ¹ï¼æ¢å¤æåç¼å·å¿
å¡«æ ¡éªï¼æªå¡«åç´æ¥æç¤ºå¹¶ç»æ¢æäº¤ |
| | | const saveData = async () => { |
| | | // 1. æåç¼å·å¿
å¡«æ ¡éªãæ ¸å¿æ°å¢ã |
| | | const productCode = finishedProductCode.value.trim(); |
| | | if (!productCode) { |
| | | alert("请å
å¡«åæåç¼å·ï¼æåç¼å·ä¸ºå¿
填项ï¼"); |
| | | return; |
| | | } |
| | | if (!finishedProductCode.value.trim()) { |
| | | alert("æåç¼å·ä¸è½ä¸ºç©ºï¼è¯·è¾å
¥ååæäº¤ï¼"); |
| | | return; |
| | | } |
| | | // 2. æäº¤éï¼é²æ¢éå¤ç¹å» |
| | | if (submitLock.value) return; |
| | | submitLock.value = true; |
| | | |
| | | try { |
| | | // 3. ä¼ åéé
ï¼å端Dtoæ¯å¤§é©¼å³°å段ï¼å¿
é¡»ä¸¥æ ¼å¹é
ï¼FinishedProductCode/PartsListï¼ |
| | | const submitData = { |
| | | toolingBoardNo: toolingBoardNo.value.trim(), |
| | | finishedProductCode: finishedProductCode.value.trim(), |
| | | partsList: rightPartCodes.value.map((item) => item.trim()), |
| | | FinishedProductCode: productCode, // ç´æ¥ä½¿ç¨å·²æ ¡éªçéç©ºå¼ |
| | | PartsList: rightPartCodes.value.map((item) => item.trim()), |
| | | }; |
| | | console.log("â
æäº¤å·¥è£
æ¿æ°æ®ï¼", submitData); |
| | | console.log("ð¤ æäº¤å°SaveToolingBoardNoçåæ°ï¼å¹é
å端Dtoï¼ï¼", submitData); |
| | | |
| | | // 4. è°ç¨å端æ¥å£ï¼å»¶é¿è¶
æ¶æ¶é´ï¼å端æPLC交äºï¼500msä¼ç ï¼è®¾ä¸º10ç§ï¼ |
| | | const response = await axios.post( |
| | | "/api/boxingDetail/SaveToolingBoardNo", |
| | | submitData, |
| | | { timeout: 5000 } |
| | | { timeout: 10000 } |
| | | ); |
| | | const resData = response.data; |
| | | const isSuccess = resData.Status === true || resData.status === true; |
| | | if (isSuccess) { |
| | | alert("â
æäº¤æåï¼"); |
| | | toolingBoardNo.value = ""; |
| | | console.log("ð¥ SaveToolingBoardNoæ¥å£è¿åï¼", resData); |
| | | |
| | | // 5. éé
å端è¿åæ ¼å¼ï¼status为true表示æåï¼å¦ååmessageéè¯¯ä¿¡æ¯ |
| | | if (resData.status === true) { |
| | | finishedProductCode.value = ""; |
| | | rightPartCodes.value = Array(10).fill(""); |
| | | rightTopInput.value = ""; |
| | | fillIndex.value = -1; |
| | | // â
æäº¤æååï¼éç½®æäº¤é |
| | | submitLock.value = false; |
| | | } else { |
| | | alert("æäº¤å¤±è´¥ï¼" + (resData.Message || resData.message || "æªç¥é误")); |
| | | // ä¸å¡é误ï¼ç´æ¥å±ç¤ºå端è¿åçmessageï¼å¦ç©æéè¯¯ãæ é
æ¹ï¼ |
| | | const errorMsg = resData.message || "æäº¤å¤±è´¥ï¼æªç¥ä¸å¡é误"; |
| | | alert(`æäº¤å¤±è´¥ï¼${errorMsg}`); |
| | | } |
| | | } catch (error) { |
| | | alert("æäº¤è¯·æ±å¤±è´¥ï¼è¯·æ£æ¥ç½ç»ææ¥å£ï¼"); |
| | | console.error("æäº¤æ¥å£å¤±è´¥ï¼", error); |
| | | // â
请æ±å¤±è´¥ä¹éç½®é |
| | | // 6. å¼å¸¸æè·ï¼å
¼å®¹åç«¯æªæè·å¼å¸¸ï¼å¦PLCé讯å¼å¸¸ãæ°ç»è¶çã500éè¯¯ï¼ |
| | | let errorMsg = "æäº¤è¯·æ±å¼å¸¸ï¼"; |
| | | if (error.code === "ECONNABORTED") { |
| | | errorMsg = "æäº¤è¯·æ±è¶
æ¶ï¼å端PLC交äº/æ°æ®åºæä½èæ¶è¿é¿"; |
| | | } else if (error.response) { |
| | | // æå¡å¨500é误ï¼å端æåºæªæè·å¼å¸¸ï¼å¦PLCæªè¿æ¥ãé¶ä»¶ä¸å¹é
ï¼ |
| | | errorMsg = `æå¡å¨é误ï¼${error.response.status} - ${error.response.statusText}ï¼è¯·æ£æ¥PLCé讯æé
æ¹é
ç½®`; |
| | | console.error("â å端æå¡å¨é误详æ
ï¼", error.response.data); |
| | | } else if (error.request) { |
| | | errorMsg = "ç½ç»å¼å¸¸ï¼æªæ¶å°å端ååºï¼è¯·æ£æ¥æ¥å£å°ååç½ç»"; |
| | | } else { |
| | | errorMsg = `请æ±é误ï¼${error.message}`; |
| | | } |
| | | alert(errorMsg); |
| | | console.error("â æäº¤æ¥å£å¼å¸¸è¯¦æ
ï¼", error); |
| | | } finally { |
| | | // 7. éæ¾æäº¤éï¼æ 论æå/失败é½è¦éæ¾ |
| | | submitLock.value = false; |
| | | } |
| | | }; |
| | | |
| | | // â
â
â
æ ¸å¿å级ï¼èªå¨æäº¤å¤æé»è¾ - æ°å¢æ å¾éæ¶æåç¼å·å¡«å
å³æäº¤ |
| | | // æ ¸å¿ä¿®æ¹ï¼èªå¨æäº¤é»è¾åæ¥å¢å æåç¼å·å¿
å¡«æ ¡éªï¼æ æåç¼å·ä¸è§¦åèªå¨æäº¤ï¼ |
| | | const checkAutoSubmit = () => { |
| | | // 鲿ï¼é²æ¢çæ¶é´å
夿¬¡è§¦åæäº¤ |
| | | if (autoSubmitDebounceTimer) clearTimeout(autoSubmitDebounceTimer); |
| | | autoSubmitDebounceTimer = setTimeout(() => { |
| | | const needCheckNum = checkedCount.value; // 左侧å¾éçæ°é |
| | | const filledNum = filledPartCount.value; // å³ä¾§å¡«å
çé¶ä»¶æ°é |
| | | const hasBoardNo = toolingBoardNo.value.trim() !== ""; // å·¥è£
æ¿æå¼ |
| | | const hasProductCode = finishedProductCode.value.trim() !== ""; // æåæå¼ |
| | | const needCheckNum = checkedCount.value; // 左侧å¾éé¶ä»¶æ° |
| | | const filledNum = filledPartCount.value; // å³ä¾§ææå¡«å
é¶ä»¶æ° |
| | | const productCode = finishedProductCode.value.trim(); // æåç¼å·ï¼å»ç©ºæ ¼ï¼ |
| | | const hasProductCode = !!productCode; // æåç¼å·æ¯å¦ææãä¿çåé»è¾ï¼å®é
æ¯å¿
å¡«æ ¡éªã |
| | | |
| | | console.log(`â
èªå¨æäº¤æ ¡éªï¼å·¦ä¾§å¾é${needCheckNum}个ï¼å³ä¾§å¡«å
${filledNum}个`); |
| | | console.log( |
| | | `â
èªå¨æäº¤æ ¡éªï¼å¾é${needCheckNum}个 | å¡«å
${filledNum}个 | æå已填${hasProductCode}` |
| | | ); |
| | | |
| | | // 忝1ï¼å·¦ä¾§æå¾é â åæé»è¾ï¼é¶ä»¶å¡«å
æ°â¥å¾éæ° ææäº¤ |
| | | if (needCheckNum > 0) { |
| | | if (hasBoardNo && hasProductCode && filledNum >= needCheckNum) { |
| | | console.log("â
满足å¾éæ°éæ¡ä»¶ï¼æ§è¡èªå¨æäº¤ï¼"); |
| | | saveToolingBoardNo(); |
| | | // åç½®æ»æ ¡éªï¼æåç¼å·æªå¡«åï¼ç´æ¥ä¸è§¦åä»»ä½èªå¨æäº¤ãæ ¸å¿å¼ºåã |
| | | if (!hasProductCode) { |
| | | console.log("â ï¸ æåç¼å·æªå¡«åï¼è·³è¿èªå¨æäº¤"); |
| | | autoSubmitDebounceTimer = null; |
| | | return; |
| | | } |
| | | |
| | | // åºæ¯1ï¼å·¦ä¾§æ å¾é â ä»
æåç¼å·ææå³æäº¤ï¼å·²æ»¡è¶³hasProductCodeï¼ |
| | | if (needCheckNum === 0) { |
| | | if (!submitLock.value) { |
| | | console.log("â
æ é¶ä»¶å¾éï¼æåå·²å¡«ï¼æ§è¡èªå¨æäº¤ï¼"); |
| | | saveData(); |
| | | } |
| | | } |
| | | // 忝2ï¼å·¦ä¾§æ å¾é â æ°å¢é»è¾ï¼å·¥è£
æ¿+æåé½æå¼ å°±æäº¤ (å éé²éå¤) |
| | | // åºæ¯2ï¼å·¦ä¾§æå¾é â æåææ + å¡«å
æ°=å¾éæ° ææäº¤ï¼å·²æ»¡è¶³hasProductCodeï¼ |
| | | else { |
| | | if (hasBoardNo && hasProductCode && !submitLock.value) { |
| | | console.log("â
左侧æ å¾éï¼æåç¼å·å¡«å
å®æï¼æ§è¡èªå¨æäº¤ï¼"); |
| | | submitLock.value = true; // å é鲿¢éå¤æäº¤ |
| | | saveToolingBoardNo(); |
| | | if (filledNum === needCheckNum && !submitLock.value) { |
| | | console.log("â
é¶ä»¶æ°éå¹é
ï¼æåå·²å¡«ï¼æ§è¡èªå¨æäº¤ï¼"); |
| | | saveData(); |
| | | } |
| | | } |
| | | autoSubmitDebounceTimer = null; |
| | | }, 300); |
| | | }, 300); // 300ms鲿ï¼é¿å
è¾å
¥é¢ç¹è§¦å |
| | | }; |
| | | |
| | | // â
â
â
æ ¸å¿æ°å¢4ï¼çå¬å
³é®æ°æ®ååï¼è§¦åèªå¨æäº¤æ ¡éª |
| | | watch( |
| | | [checkedCount, filledPartCount, toolingBoardNo, finishedProductCode], |
| | | () => { |
| | | checkAutoSubmit(); |
| | | }, |
| | | { deep: true, immediate: false } |
| | | ); |
| | | // çå¬èªå¨æäº¤ç¸å
³æ°æ®ååï¼è§¦åæ ¡éª |
| | | watch([checkedCount, filledPartCount, finishedProductCode], () => checkAutoSubmit(), { |
| | | deep: true, |
| | | immediate: false, |
| | | }); |
| | | |
| | | // èªå¨æ£æµå¡«å
ç´¢å¼é»è¾ |
| | | // èªå¨æ£æµå¡«å
ç´¢å¼ï¼æåå¡«å®åï¼æå第ä¸ä¸ªç©ºé¶ä»¶æ¡ï¼ |
| | | const detectFillIndex = () => { |
| | | if (!toolingBoardNo.value.trim() || !finishedProductCode.value.trim()) { |
| | | if (!finishedProductCode.value.trim()) { |
| | | fillIndex.value = -1; |
| | | return; |
| | | } |
| | |
| | | fillIndex.value = 10; |
| | | }; |
| | | |
| | | watch( |
| | | [toolingBoardNo, finishedProductCode, () => [...rightPartCodes.value]], |
| | | detectFillIndex, |
| | | { |
| | | // ç嬿å/é¶ä»¶è¾å
¥ï¼æ´æ°å¡«å
ç´¢å¼ |
| | | watch([finishedProductCode, () => [...rightPartCodes.value]], detectFillIndex, { |
| | | immediate: true, |
| | | deep: true, |
| | | } |
| | | ); |
| | | }); |
| | | |
| | | // é¡µé¢æè½½/å¸è½½çå½å¨æ |
| | | // çå½å¨æï¼æè½½æ¶å è½½åå§æ°æ®+å¯å¨è½®è¯¢ |
| | | onMounted(async () => { |
| | | await fetchLeftInitialData(); |
| | | startPolling(); |
| | | detectFillIndex(); |
| | | }); |
| | | |
| | | // çå½å¨æï¼å¸è½½æ¶æ¸
餿æå®æ¶å¨/鲿ï¼é²æ¢å
åæ³æ¼ |
| | | onUnmounted(() => { |
| | | stopPolling(); |
| | | if (checkDebounceTimer) clearTimeout(checkDebounceTimer); |
| | | if (destroyDelayTimer) clearTimeout(destroyDelayTimer); |
| | | if (boardCodeDebounceTimer) clearTimeout(boardCodeDebounceTimer); |
| | | if (autoSubmitDebounceTimer) clearTimeout(autoSubmitDebounceTimer); |
| | | [checkDebounceTimer, destroyDelayTimer, autoSubmitDebounceTimer].forEach( |
| | | (t) => t && clearTimeout(t) |
| | | ); |
| | | }); |
| | | |
| | | // æ´é²æ¨¡æ¿æé屿§/æ¹æ³ |
| | | return { |
| | | finishedProduct, |
| | | finishedProductId, |
| | | rightTopInput, |
| | | leftPartCodes, |
| | | rightPartCodes, |
| | | leftPartChecked, |
| | | leftPartIds, |
| | | toolingBoardNo, |
| | | isPLCStarted, |
| | | isPLCPaused, |
| | | signalStates, |
| | | signalLabels, |
| | | finishedProductCode, |
| | | handleToggle, |
| | | handlePauseToggle, |
| | | checkLoading, |
| | | handlePartCheck, |
| | | clearToolingBoardNo, |
| | | saveToolingBoardNo, |
| | | saveData, |
| | | clearRightPart, |
| | | clearFinishedProductCode, |
| | | }; |
| | |
| | | </script> |
| | | |
| | | <style scoped> |
| | | /* åºç¡æ ·å¼éç½®ä¸å
¨å±æ ·å¼ */ |
| | | /* åºç¡æ ·å¼éç½® */ |
| | | * { |
| | | margin: 0; |
| | | padding: 0; |
| | | box-sizing: border-box; |
| | | font-family: "Microsoft Yahei", "PingFang SC", "Inter", sans-serif; |
| | | font-family: "Microsoft Yahei", "PingFang SC", sans-serif; |
| | | scrollbar-width: none; |
| | | -ms-overflow-style: none; |
| | | } |
| | |
| | | font-size: 14px; |
| | | } |
| | | |
| | | /* 容卿 ·å¼ - æ¾å¤§ é´è·å 宽 */ |
| | | /* ä¸»å®¹å¨ */ |
| | | .container { |
| | | display: flex; |
| | | width: 100%; |
| | | height: 100vh; |
| | | margin: 0; |
| | | gap: 15px; |
| | | padding: 15px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* 颿¿éç¨æ ·å¼ - ç»ä¸å
è¾¹è· ç¡®ä¿å·¦å³å¯¹é½ */ |
| | | /* å·¦å³åºåéç¨æ ·å¼ */ |
| | | .left-area, |
| | | .right-area { |
| | | flex: 1; |
| | |
| | | transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); |
| | | } |
| | | |
| | | /* æé®+ä¿¡å· æ¨ªåæåå®¹å¨ - æ ¸å¿å¸å± */ |
| | | .btn-signal-group { |
| | | /* 左侧顶é¨-ä¿¡å·ç¯åºå */ |
| | | .left-top { |
| | | background: #f8fafc; |
| | | padding: 20px 15px; |
| | | border-radius: 12px; |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 20px; |
| | | width: 100%; |
| | | } |
| | | .btn-group { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | flex-shrink: 0; |
| | | justify-content: center; |
| | | } |
| | | .signal-status { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | justify-content: center; |
| | | align-items: center; |
| | | gap: 18px; |
| | | flex-shrink: 0; |
| | | padding: 0; |
| | | } |
| | | |
| | | .left-top { |
| | | background: #f8fafc; |
| | | padding: 15px; |
| | | border-radius: 12px; |
| | | gap: 25px; |
| | | flex-shrink: 0; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* ä¸ä¸åºåéç¨ */ |
| | | .left-bottom, |
| | | .right-bottom { |
| | | display: flex; |
| | |
| | | flex: 1; |
| | | overflow: hidden !important; |
| | | } |
| | | |
| | | .right-top { |
| | | padding: 15px; |
| | | background: #f8fafc; |
| | |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | /* 表åè¡æ ·å¼ - ç»ä¸é«åº¦åé´è· ç¡®ä¿å·¦å³å¯¹é½ */ |
| | | /* 表åè¡éç¨æ ·å¼ */ |
| | | .form-row { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | flex-shrink: 0; |
| | | width: 100%; |
| | | } |
| | | |
| | | .input-submit-row { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | flex-wrap: nowrap; |
| | | padding: 6px 10px; |
| | | border-radius: 8px; |
| | | transition: all 0.2s ease; |
| | | height: 48px; |
| | | line-height: 48px; |
| | | flex-shrink: 0; |
| | | width: 100%; |
| | | } |
| | | .form-row:hover { |
| | | background: #f8fafc; |
| | | } |
| | | |
| | | .finished-product-row { |
| | | /* æåç¼å·è¡æ ·å¼ */ |
| | | .right-bottom .finished-product-row { |
| | | margin-top: 16px; |
| | | background: #eff6ff; |
| | | border-left: 4px solid #3b82f6; |
| | | padding-top: 2px; |
| | | padding-bottom: 2px; |
| | | } |
| | | .left-bottom .finished-product-row { |
| | | background: #eff6ff; |
| | | border-left: 4px solid #3b82f6; |
| | | } |
| | | |
| | | .tooling-board-row { |
| | | background: #f0fdf4; |
| | | border-left: 4px solid #22c55e; |
| | | } |
| | | |
| | | /* é¶ä»¶é¡¹æ ·å¼ */ |
| | | .part-item { |
| | | border-bottom: 1px solid #f1f5f9; |
| | | margin-bottom: 3px; |
| | | } |
| | | |
| | | .part-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | /* æ ç¾æ ·å¼ - ç»ä¸å®½åº¦ ç¡®ä¿å·¦å³å¯¹é½ */ |
| | | /* æ ç¾æ ·å¼ */ |
| | | .label { |
| | | width: 90px; |
| | | text-align: right; |
| | |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .short-label { |
| | | width: 110px; |
| | | text-align: right; |
| | | color: #334155; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | /* è¾å
¥æ¡æ ·å¼ - ç»ä¸å°ºå¯¸ ç¡®ä¿å·¦å³å¯¹é½ */ |
| | | /* è¾å
¥æ¡æ ·å¼ */ |
| | | .input-box { |
| | | flex: 1; |
| | | min-width: 100px; |
| | |
| | | transition: all 0.2s ease; |
| | | background-color: #ffffff; |
| | | } |
| | | |
| | | .short-input { |
| | | width: 150px !important; |
| | | flex: none !important; |
| | | } |
| | | |
| | | .input-box:focus { |
| | | border-color: #3b82f6; |
| | | box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12); |
| | | } |
| | | |
| | | .input-box:disabled { |
| | | background-color: #f1f5f9; |
| | | color: #64748b; |
| | | cursor: not-allowed; |
| | | } |
| | | |
| | | .input-box::placeholder { |
| | | color: #94a3b8; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | /* æé®æ ·å¼ - åºå®å®½åº¦ ä¸å */ |
| | | /* æé®éç¨æ ·å¼ */ |
| | | .btn { |
| | | width: 120px; |
| | | height: 42px; |
| | |
| | | position: relative; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .submit-input-btn { |
| | | width: 110px !important; |
| | | height: 42px !important; |
| | | flex: none !important; |
| | | padding: 0 15px !important; |
| | | font-size: 15px !important; |
| | | } |
| | | .submit-input-btn .icon { |
| | | width: 20px !important; |
| | | height: 20px !important; |
| | | } |
| | | .btn:disabled { |
| | | opacity: 0.6; |
| | | cursor: not-allowed; |
| | | transform: none !important; |
| | | box-shadow: none !important; |
| | | } |
| | | |
| | | .btn::after { |
| | | content: ""; |
| | | position: absolute; |
| | |
| | | background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); |
| | | transition: all 0.5s ease; |
| | | } |
| | | |
| | | .btn:hover::after { |
| | | left: 100%; |
| | | } |
| | | |
| | | /* 徿 æ ·å¼ - 徿 æ¾å¤§ */ |
| | | /* 徿 æ ·å¼ */ |
| | | .icon { |
| | | display: inline-block; |
| | | width: 18px; |
| | |
| | | background-repeat: no-repeat; |
| | | background-position: center; |
| | | } |
| | | |
| | | .icon-start { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M8 5v14l11-7z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | .icon-stop { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 6h12v12H6z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | .icon-pause { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M6 19h4V5H6v14zm8-14v14h4V5h-4z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | .icon-resume { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M11 5L6 9H2v6h4l5 4V5zm7 0v14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | .icon-clear { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | .icon-submit { |
| | | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M2.01 21L15 13.4 23 21V5H2.01V21zM17 15l-5-5-5 5V7h10v8z'/%3E%3C/svg%3E"); |
| | | } |
| | | |
| | | /* æé®ç±»åæ ·å¼ - ä¸å */ |
| | | .start-btn { |
| | | background: linear-gradient(135deg, #10b981 0%, #059669 100%); |
| | | color: #fff; |
| | | } |
| | | .start-btn:hover:not(:disabled) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(16, 185, 129, 0.2); |
| | | } |
| | | |
| | | .stop-btn { |
| | | background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); |
| | | color: #fff; |
| | | } |
| | | .stop-btn:hover:not(:disabled) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(239, 68, 68, 0.2); |
| | | } |
| | | |
| | | .pause-btn { |
| | | background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); |
| | | color: #fff; |
| | | } |
| | | .pause-btn:hover:not(:disabled) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(245, 158, 11, 0.2); |
| | | } |
| | | |
| | | .resume-btn { |
| | | background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); |
| | | color: #fff; |
| | | } |
| | | .resume-btn:hover:not(:disabled) { |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(139, 92, 246, 0.2); |
| | | } |
| | | |
| | | /* æé®ä¸»é¢æ ·å¼ */ |
| | | .clear-btn { |
| | | background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); |
| | | color: #fff; |
| | |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(239, 68, 68, 0.15); |
| | | } |
| | | |
| | | .save-btn { |
| | | background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); |
| | | color: #fff; |
| | |
| | | box-shadow: 0 4px 8px rgba(59, 130, 246, 0.15); |
| | | } |
| | | |
| | | /* ä¿¡å·ç¯æ ·å¼ éç®æ¾å¤§ */ |
| | | /* ä¿¡å·ç¯æ ·å¼ */ |
| | | .signal-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | |
| | | font-size: 14px; |
| | | color: #334155; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | width: 100%; |
| | | text-align: center; |
| | | font-weight: 600; |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /* èªå®ä¹å¤éæ¡æ ·å¼ - æ¾å¤§ ç¹å»åºåæ´å¤§ */ |
| | | /* èªå®ä¹å¤éæ¡æ ·å¼ */ |
| | | .checkbox-container { |
| | | display: flex; |
| | | align-items: center; |
| | |
| | | } |
| | | .part-checkbox { |
| | | display: none; |
| | | } |
| | | .checkbox-container:has(.part-checkbox:disabled) { |
| | | opacity: 0.6; |
| | | cursor: not-allowed; |
| | | } |
| | | .checkmark { |
| | | width: 22px; |
| | |
| | | width: 100%; |
| | | flex: none; |
| | | } |
| | | .btn-signal-group { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | } |
| | | .signal-status { |
| | | width: 100%; |
| | | justify-content: flex-start; |
| | | flex-wrap: wrap; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | |
| | | @media (max-width: 768px) { |
| | | .form-row { |
| | | .form-row, |
| | | .input-submit-row { |
| | | flex-direction: column; |
| | | align-items: flex-start; |
| | | height: auto; |
| | | line-height: normal; |
| | | } |
| | | .label, |
| | | .short-label { |
| | | .label { |
| | | width: 100%; |
| | | text-align: left; |
| | | margin-bottom: 6px; |
| | |
| | | .input-box { |
| | | width: 100%; |
| | | } |
| | | .short-input { |
| | | .btn, |
| | | .submit-input-btn { |
| | | width: 100% !important; |
| | | } |
| | | .btn { |
| | | width: 100%; |
| | | margin-top: 6px; |
| | | } |
| | | .btn-group { |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | width: 100%; |
| | | .right-bottom .finished-product-row { |
| | | margin-top: 0 !important; |
| | | } |
| | | } |
| | | </style> |