| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="list_box"> |
| | | <CardTitle title="åºåº" :hideAction="false"> |
| | | <template #action> |
| | | <wd-button type="icon" icon="scan" color="#0D867F" @click="openScan"></wd-button> |
| | | </template> |
| | | </CardTitle> |
| | | <view class="list_content"> |
| | | <view v-if="outboundList.length === 0" class="empty_tip"> |
| | | <view class="empty_text">ææ åºåºæ°æ®</view> |
| | | </view> |
| | | <view v-for="(item, index) in outboundList" :key="index" class="outbound_item"> |
| | | <view class="outbound_item_left"> |
| | | <view class="outbound_item_content"> |
| | | <view class="outbound_item_row"> |
| | | <text class="outbound_item_label">ååå·ï¼</text> |
| | | <text class="outbound_item_value">{{ item.contractNo || "-" }}</text> |
| | | </view> |
| | | <view class="outbound_item_row"> |
| | | <text class="outbound_item_label">çäº§æ¹æ¬¡å·ï¼</text> |
| | | <text class="outbound_item_value">{{ item.batchNo || "-" }}</text> |
| | | </view> |
| | | <view class="outbound_item_row"> |
| | | <text class="outbound_item_label">è§æ ¼åå·ï¼</text> |
| | | <text class="outbound_item_value">{{ item.model || "-" }}</text> |
| | | </view> |
| | | <view class="outbound_item_row"> |
| | | <text class="outbound_item_label">çäº§æ¥æï¼</text> |
| | | <text class="outbound_item_value">{{ item.productionDate || "-" }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="outbound_item_action"> |
| | | <wd-button |
| | | type="icon" |
| | | icon="delete" |
| | | size="small" |
| | | custom-class="delete-btn" |
| | | @click.stop="removeOutboundItem(index)" |
| | | ></wd-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-if="outboundList.length > 0" class="outbound_footer"> |
| | | <wd-button block @click="handleOutbound"> |
| | | <text class="text-[#fff]">åºåº</text> |
| | | </wd-button> |
| | | </view> |
| | | <Scan ref="scanRef" emitName="scanOutbound" /> |
| | | <wd-toast /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import CardTitle from "@/components/card-title/index.vue"; |
| | | import Scan from "@/components/scan/index.vue"; |
| | | import { useToast } from "wot-design-uni"; |
| | | import { dayjs } from "wot-design-uni"; |
| | | import OutboundApi from "@/api/product/outbound"; |
| | | |
| | | const scanRef = ref(); |
| | | const toast = useToast(); |
| | | const outboundList = ref<any[]>([]); |
| | | const projectId = ref<string | number>(""); |
| | | |
| | | // æ ¼å¼åæ¶é´ |
| | | const formatTime = (date: Date) => { |
| | | return dayjs(date).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | // è§£ææ«ç å
容 |
| | | const parseScanCode = (scanCode: string) => { |
| | | try { |
| | | // ç¬¬ä¸æ¬¡è§£æï¼è§£æå¤å±JSON |
| | | const outerParsed = JSON.parse(scanCode); |
| | | |
| | | // 妿å¤å±æ code åæ®µï¼ä¸æ¯å符串ï¼éè¦å次解æ |
| | | let innerData = null; |
| | | if (outerParsed.code && typeof outerParsed.code === "string") { |
| | | try { |
| | | const innerParsed = JSON.parse(outerParsed.code); |
| | | |
| | | // æ¥æ¾æææ°åkeyï¼å¦ "12480"ï¼ï¼è¿ä¸ªæ°åkeyå°±æ¯id |
| | | const keys = Object.keys(innerParsed); |
| | | // æ¾å°æææ°åkeyï¼æé¤ "code" åæ®µ |
| | | const numberKeys = keys.filter((key) => !isNaN(Number(key)) && key !== "code"); |
| | | |
| | | if (numberKeys.length > 0) { |
| | | // å第ä¸ä¸ªæ°åkeyï¼è¿ä¸ªå°±æ¯idï¼ |
| | | const dataKey = numberKeys[0]; |
| | | const idValue = Number(dataKey); // æ°åkeyå°±æ¯idå¼ |
| | | // æåæ°åkey对åºçæ°æ®å¯¹è±¡ |
| | | const extractedData = innerParsed[dataKey]; |
| | | if (extractedData) { |
| | | innerData = { ...extractedData }; // å¤å¶æ°æ®å¯¹è±¡ |
| | | // ç¡®ä¿æ°æ®å¯¹è±¡ä¸æidåæ®µï¼å¦ææ²¡æåä½¿ç¨æ°åkeyä½ä¸ºid |
| | | if (!innerData.id) { |
| | | innerData.id = idValue; |
| | | } |
| | | } |
| | | } else { |
| | | // å¦ææ²¡ææ°åkeyï¼å°è¯ç´æ¥ä½¿ç¨å¯¹è±¡ï¼æé¤ code åæ®µï¼ |
| | | const { code, ...rest } = innerParsed; |
| | | if (Object.keys(rest).length > 0) { |
| | | innerData = rest; |
| | | } |
| | | } |
| | | } catch (e) { |
| | | console.error("å
å±JSONè§£æå¤±è´¥:", e); |
| | | } |
| | | } else { |
| | | // å¦ææ²¡æ code åæ®µï¼ç´æ¥ä½¿ç¨å¤å±æ°æ® |
| | | innerData = outerParsed; |
| | | } |
| | | |
| | | // 妿 innerData ä»ç¶ä¸ºç©ºï¼å°è¯ç´æ¥è§£æ |
| | | if (!innerData) { |
| | | innerData = outerParsed; |
| | | } |
| | | |
| | | // 妿 innerData ä»ç¶å
嫿°åkeyç»æï¼å¦ { "12480": {...}, "code": "..." }ï¼ï¼éè¦å次æå |
| | | if (innerData && typeof innerData === "object" && !innerData.id && !innerData.contractno) { |
| | | const keys = Object.keys(innerData); |
| | | const numberKeys = keys.filter((key) => !isNaN(Number(key)) && key !== "code"); |
| | | if (numberKeys.length > 0) { |
| | | const dataKey = numberKeys[0]; |
| | | const extractedData = innerData[dataKey]; |
| | | if (extractedData) { |
| | | innerData = { ...extractedData }; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æåæ°æ®åæ®µï¼æ ¹æ®äºç»´ç å®é
åæ®µåç»ä¸ï¼ |
| | | const data = { |
| | | id: innerData?.id, |
| | | contractNo: innerData?.contractno, |
| | | batchNo: innerData?.monofilamentnumber, |
| | | model: innerData?.model, |
| | | weight: innerData?.actuallyweight, |
| | | productionDate: innerData?.producttime, |
| | | projectId: innerData?.projectid, |
| | | // ä¿çåå§æ°æ®ï¼ä¿åæååçæ°æ®å¯¹è±¡ï¼ |
| | | rawData: innerData, |
| | | scanCode: scanCode, |
| | | }; |
| | | |
| | | // 妿æ«ç æ°æ®ä¸æ projectIdï¼ä¿åå® |
| | | if (data.projectId && !projectId.value) { |
| | | projectId.value = data.projectId; |
| | | } |
| | | |
| | | return data; |
| | | } catch (error) { |
| | | console.error("JSONè§£æå¤±è´¥:", error); |
| | | // 妿䏿¯JSONï¼å°è¯æéå·åå²ï¼å¯è½æ¯CSVæ ¼å¼ï¼ |
| | | const parts = scanCode.split(","); |
| | | if (parts.length >= 5) { |
| | | return { |
| | | id: parts[0] || "-", // å设第ä¸ä¸ªæ¯id |
| | | contractNo: parts[1] || "-", |
| | | batchNo: parts[2] || "-", |
| | | model: parts[3] || "-", |
| | | weight: parts[4] || "-", |
| | | productionDate: parts[5] || "-", |
| | | projectId: projectId.value || "-", |
| | | scanCode: scanCode, |
| | | }; |
| | | } |
| | | // 妿齿 æ³è§£æï¼è¿ååå§å符串 |
| | | return { |
| | | id: scanCode, // 使ç¨åå§å符串ä½ä¸ºid |
| | | contractNo: scanCode, |
| | | batchNo: "-", |
| | | model: "-", |
| | | weight: "-", |
| | | productionDate: "-", |
| | | projectId: projectId.value || "-", |
| | | scanCode: scanCode, |
| | | }; |
| | | } |
| | | }; |
| | | |
| | | // æ«ç åè° |
| | | const getScanCode = (code: any) => { |
| | | // 妿 code æ¯å¯¹è±¡ä¸æ code åæ®µï¼ä½¿ç¨ code.codeï¼å¦åç´æ¥ä½¿ç¨ code |
| | | let scanCode = code.code || code; |
| | | |
| | | // 妿 scanCode æ¯å¯¹è±¡ï¼å°è¯è·åå
¶ code åæ®µ |
| | | if (typeof scanCode === "object" && scanCode.code) { |
| | | scanCode = scanCode.code; |
| | | } |
| | | |
| | | // 妿 scanCode æ¯å符串ï¼ç´æ¥ä½¿ç¨ï¼å¦ææ¯å¯¹è±¡ï¼è½¬ä¸ºå符串 |
| | | if (typeof scanCode !== "string") { |
| | | scanCode = JSON.stringify(scanCode); |
| | | } |
| | | |
| | | if (!scanCode) { |
| | | toast.error("æ«ç å
容为空"); |
| | | return; |
| | | } |
| | | |
| | | // è§£ææ«ç å
容 |
| | | const parsedData = parseScanCode(scanCode); |
| | | |
| | | // 使ç¨idä½ä¸ºå¯ä¸æ è¯ |
| | | const uniqueId = parsedData.id; |
| | | |
| | | // å¦ææ²¡æidï¼æç¤ºé误 |
| | | if (!uniqueId || uniqueId === "-" || uniqueId === null || uniqueId === undefined) { |
| | | toast.error("æ«ç å
容缺å°å¯ä¸æ è¯ï¼æ æ³æ·»å "); |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥æ¯å¦å·²åå¨ï¼æ ¹æ®idå¤æï¼ |
| | | const exists = outboundList.value.some((item) => { |
| | | const itemId = item.id; |
| | | return itemId && itemId === uniqueId && itemId !== "-"; |
| | | }); |
| | | |
| | | if (exists) { |
| | | toast.error("该æ¡ç å·²åå¨ï¼è¯·å¿é夿«ç "); |
| | | return; |
| | | } |
| | | |
| | | // æ·»å å°å表 |
| | | const newItem = { |
| | | ...parsedData, |
| | | scanTime: formatTime(new Date()), |
| | | }; |
| | | |
| | | outboundList.value.push(newItem); |
| | | toast.success("æ«ç æå"); |
| | | }; |
| | | |
| | | // è§¦åæ«ç |
| | | const openScan = () => { |
| | | scanRef.value.triggerScan(); |
| | | }; |
| | | |
| | | // å é¤é¡¹ |
| | | const removeOutboundItem = (index: number) => { |
| | | const item = outboundList.value[index]; |
| | | const itemName = item.contractNo || item.batchNo || `第${index + 1}项`; |
| | | |
| | | uni.showModal({ |
| | | title: "确认å é¤", |
| | | content: `ç¡®å®è¦å é¤"${itemName}"åï¼`, |
| | | confirmText: "å é¤", |
| | | cancelText: "åæ¶", |
| | | confirmColor: "#ff4444", |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | outboundList.value.splice(index, 1); |
| | | toast.success("å 餿å"); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å¤çåºåº |
| | | const handleOutbound = async () => { |
| | | if (outboundList.value.length === 0) { |
| | | toast.error("ææ åºåºæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | // æå»ºè¯·æ±æ°æ® |
| | | const requestData = outboundList.value.map((item) => ({ |
| | | outPutId: item.id, |
| | | projectId: item.projectId, |
| | | })); |
| | | |
| | | try { |
| | | uni.showLoading({ |
| | | title: "åºåºä¸...", |
| | | mask: true, |
| | | }); |
| | | console.log("requestData", requestData); |
| | | const { code, msg } = await OutboundApi.finishedOutbound(requestData); |
| | | |
| | | uni.hideLoading(); |
| | | |
| | | if (code === 200) { |
| | | toast.success("åºåºæå"); |
| | | // æ¸
空å表 |
| | | outboundList.value = []; |
| | | } else { |
| | | toast.error(msg || "åºåºå¤±è´¥"); |
| | | } |
| | | } catch (error: any) { |
| | | uni.hideLoading(); |
| | | console.error("åºåºå¤±è´¥:", error); |
| | | } |
| | | }; |
| | | |
| | | // ç¡®ä¿å
ç§»é¤åæ·»å çå¬ |
| | | const setupScanListener = () => { |
| | | uni.$off("scanOutbound", getScanCode); // å
ç§»é¤æ§ç |
| | | uni.$on("scanOutbound", getScanCode); // åæ·»å æ°ç |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | setupScanListener(); |
| | | }); |
| | | |
| | | onUnmounted(() => { |
| | | uni.$off("scanOutbound", getScanCode); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .list_box { |
| | | height: calc(100vh - 100px); |
| | | background: #f3f9f8; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .list_content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | padding-bottom: 120rpx; |
| | | } |
| | | |
| | | .empty_tip { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 100rpx 0; |
| | | color: #999; |
| | | |
| | | .empty_text { |
| | | font-size: 32rpx; |
| | | margin-bottom: 20rpx; |
| | | } |
| | | } |
| | | |
| | | .outbound_item { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 30rpx; |
| | | margin: 20rpx; |
| | | background: #fff; |
| | | border-radius: 16rpx; |
| | | box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .outbound_item_left { |
| | | display: flex; |
| | | align-items: center; |
| | | flex: 1; |
| | | } |
| | | |
| | | .outbound_item_content { |
| | | flex: 1; |
| | | } |
| | | |
| | | .outbound_item_row { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 12rpx; |
| | | font-size: 28rpx; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .outbound_item_label { |
| | | color: #666; |
| | | min-width: 140rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .outbound_item_value { |
| | | color: #333; |
| | | flex: 1; |
| | | word-break: break-all; |
| | | } |
| | | |
| | | .outbound_item_action { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | margin-left: 20rpx; |
| | | flex-shrink: 0; |
| | | } |
| | | } |
| | | |
| | | :deep(.delete-btn) { |
| | | .wd-button__content { |
| | | color: #ff4444 !important; |
| | | } |
| | | |
| | | &:active { |
| | | opacity: 0.7; |
| | | } |
| | | } |
| | | |
| | | :deep(.wd-button__content) { |
| | | color: #0d867f; |
| | | } |
| | | |
| | | .outbound_footer { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | padding: 20rpx 30rpx; |
| | | padding-bottom: calc(20rpx + env(safe-area-inset-bottom)); |
| | | z-index: 100; |
| | | } |
| | | </style> |