From e7dc2205d169192eea267697061efd64d89f5d63 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 08 一月 2026 17:26:36 +0800
Subject: [PATCH] fix: 完成出库重构
---
src/pages.json | 6
src/api/product/outbound.ts | 32 +
src/pages/index/index.vue | 7
src/pages/outbound/material.vue | 627 +++++++++++++++++++++++++
src/pages/outbound/index0.vue | 350 ++++++++++++++
src/pages/outbound/index.vue | 476 ++++++------------
6 files changed, 1,190 insertions(+), 308 deletions(-)
diff --git a/src/api/product/outbound.ts b/src/api/product/outbound.ts
index 30059a7..d013d4d 100644
--- a/src/api/product/outbound.ts
+++ b/src/api/product/outbound.ts
@@ -11,6 +11,38 @@
});
},
+ // 鍑哄簱鍗曟煡璇�
+ queryErpOutboundOrder(params: {
+ contractNo?: string;
+ carNo?: string;
+ current: number;
+ size: number;
+ }) {
+ return request<BaseResult<any>>({
+ url: "/app/queryErpOutboundOrder",
+ method: "POST",
+ data: params,
+ });
+ },
+
+ // 鏌ヨ鍑鸿揣鍗曟槑缁�
+ queryErpOutboundOrderDetail(params: { vbillcode: string }) {
+ return request<BaseResult<any[]>>({
+ url: "/app/queryErpOutboundOrderDetail",
+ method: "POST",
+ data: params,
+ });
+ },
+
+ // 缁炵嚎/鎷変笣浜岀淮鐮佹煡璇紙鏀寔鍑哄簱鐘舵�佸垽鏂級
+ getTagByIdAll(params: { outPutId: string | number }) {
+ return request<BaseResult<any[]>>({
+ url: "/app/getTagByIdAll",
+ method: "GET",
+ data: params,
+ });
+ },
+
// 缁炵嚎浜岀淮鐮佹煡璇�
getTagByIdJx(params: { outPutId: string | number }) {
return request<BaseResult<any>>({
diff --git a/src/pages.json b/src/pages.json
index 1759892..4d61169 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -284,6 +284,12 @@
}
},
{
+ "path": "pages/outbound/material",
+ "style": {
+ "navigationBarTitleText": "鐗╂枡璇︽儏"
+ }
+ },
+ {
"path": "pages/routingInspection/index",
"style": {
"navigationBarTitleText": "宸℃"
diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue
index 2b23c76..662e7a6 100644
--- a/src/pages/index/index.vue
+++ b/src/pages/index/index.vue
@@ -278,14 +278,19 @@
}
}
- if (data.deviceGroupName.includes("涓�") || data.deviceGroupName.includes("缁�")) {
+ if (
+ (data.deviceGroupName && data.deviceGroupName.includes("涓�")) ||
+ (data.deviceGroupName && data.deviceGroupName.includes("缁�"))
+ ) {
// 濡傛灉鏄笣鎴栫粸锛屾樉绀虹敓浜х鐞嗚彍鍗�
navList[0].show = true;
}
+ console.log("isInspector.value", isInspector.value);
if (isInspector.value) {
// 濡傛灉鏄贰妫�鍛橈紝鏄剧ず宸℃鑿滃崟
navList[1].show = true;
}
+ console.log("isStorage.value", isStorage.value);
if (isStorage.value) {
// 濡傛灉鏄嚭搴撹鑹诧紝鏄剧ず鍑哄簱鑿滃崟
navList[2].show = true;
diff --git a/src/pages/outbound/index.vue b/src/pages/outbound/index.vue
index ec42661..ba578af 100644
--- a/src/pages/outbound/index.vue
+++ b/src/pages/outbound/index.vue
@@ -1,350 +1,212 @@
<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.weight || "-" }} kg</text>
- </view>
- <view class="outbound_item_row">
- <text class="outbound_item_label">鍘傚锛�</text>
- <text class="outbound_item_value">{{ item.clienteleName || "-" }}</text>
- </view>
- <view class="outbound_item_row">
- <text class="outbound_item_label">娈甸暱锛�</text>
- <text class="outbound_item_value">{{ item.actuallyLength || "-" }} M</text>
- </view>
- <view class="outbound_item_row">
- <text class="outbound_item_label">鐢熶骇鏃ユ湡锛�</text>
- <text class="outbound_item_value">{{ item.productionDate || "-" }}</text>
- </view>
+ <view class="outbound-page">
+ <view class="search-section">
+ <wd-row>
+ <wd-col :span="21">
+ <wd-search
+ v-model="searchKeyword"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+ placeholder-left
+ hide-cancel
+ @search="handleSearch"
+ @clear="handleClear"
+ ></wd-search>
+ </wd-col>
+ <wd-col :span="3">
+ <view class="scan_box" @click="handleSearch">
+ <wd-icon name="search" size="24px" color="#0D867F"></wd-icon>
</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>
+ </wd-col>
+ </wd-row>
</view>
- <view v-if="outboundList.length > 0" class="outbound_footer">
- <wd-button block @click="handleOutbound">
- <text class="text-[#fff]">鍑哄簱</text>
- </wd-button>
+
+ <view class="list-section">
+ <z-paging
+ ref="pagingRef"
+ v-model="shippingList"
+ :fixed="false"
+ :auto-show-back-to-top="true"
+ @query="getList"
+ >
+ <wd-card
+ v-for="(item, index) in shippingList"
+ :key="item.deliveryid || index"
+ custom-class="card_bg"
+ @click="toMaterialDetail(item)"
+ >
+ <template #title>
+ <text class="font-medium text-[#252525]">鍙戣揣鍗曞彿: {{ item.vbillcode || "-" }}</text>
+ </template>
+ <wd-row class="my-2">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 鍙戣揣鍗曟棩鏈�:
+ <text class="text-[#252525]">{{ item.dbilldate || "-" }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ <wd-row class="my-2">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 杞︾墝鍙�:
+ <text class="text-[#252525]">{{ item.carno || "-" }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ <wd-row class="my-2" v-if="item.vmemo">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 鍙戣揣鍗曞娉�:
+ <text class="text-[#252525]">{{ item.vmemo || "-" }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ </wd-card>
+ </z-paging>
</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 { ref } from "vue";
import { useToast } from "wot-design-uni";
-import { dayjs } from "wot-design-uni";
+import zPaging from "@/components/z-paging/z-paging.vue";
import OutboundApi from "@/api/product/outbound";
-const scanRef = ref();
const toast = useToast();
-const outboundList = ref<any[]>([]);
-const projectId = ref<string | number>("");
+const pagingRef = ref();
+const searchKeyword = ref("");
+const shippingList = ref<any[]>([]);
-// 鏍煎紡鍖栨椂闂�
-const formatTime = (date: Date) => {
- return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
-};
+// 鑾峰彇鍒楄〃鏁版嵁
+const getList = async (pageNo: number, pageSize: number) => {
+ const params: any = {
+ contractNo: "",
+ carNo: searchKeyword.value || "",
+ current: pageNo,
+ size: pageSize,
+ };
-// 鎵爜鍥炶皟
-const getScanCode = async (code: any) => {
try {
- // 濡傛灉 code 鏄璞′笖鏈� code 瀛楁锛屼娇鐢� code.code锛涘惁鍒欑洿鎺ヤ娇鐢� code
- let scanCode = code.code || code;
-
- // 濡傛灉 scanCode 鏄璞★紝灏濊瘯鑾峰彇鍏� code 瀛楁
- if (typeof scanCode === "object" && scanCode.code) {
- scanCode = scanCode.code;
+ const { code, data, msg } = await OutboundApi.queryErpOutboundOrder(params);
+ if (code === 200 && data) {
+ const records = data.records || [];
+ if (!records.length) {
+ pagingRef.value.complete(true);
+ } else {
+ pagingRef.value.complete(records);
+ }
+ } else {
+ toast.error(msg || "鑾峰彇鍑哄簱鍗曞垪琛ㄥけ璐�");
+ pagingRef.value.complete(true);
}
-
- // 濡傛灉 scanCode 鏄瓧绗︿覆锛岀洿鎺ヤ娇鐢紱濡傛灉鏄璞★紝杞负瀛楃涓�
- if (typeof scanCode !== "string") {
- scanCode = JSON.stringify(scanCode);
- }
-
- if (!scanCode) {
- toast.error("鎵爜鍐呭涓虹┖");
- return;
- }
-
- // 瑙f瀽鎵爜鏁版嵁锛岀幇鍦ㄤ簩缁寸爜鍙寘鍚玦d
- let scanData;
- try {
- scanData = JSON.parse(scanCode);
- } catch (e) {
- toast.error("浜岀淮鐮佹牸寮忛敊璇�");
- return;
- }
-
- const outPutId = scanData.id;
-
- if (!outPutId) {
- toast.error("浜岀淮鐮佹牸寮忛敊璇紝缂哄皯id淇℃伅");
- return;
- }
-
- // 妫�鏌ユ槸鍚﹀凡瀛樺湪锛堟牴鎹甶d鍒ゆ柇锛�
- const exists = outboundList.value.some((item) => {
- const itemId = item.id;
- return itemId && itemId === outPutId && itemId !== "-";
- });
-
- if (exists) {
- toast.error("璇ユ潯鐮佸凡瀛樺湪锛岃鍕块噸澶嶆壂鐮�");
- return;
- }
-
- // 璋冪敤鎺ュ彛鑾峰彇缁炵嚎璇︾粏淇℃伅
- const { data: tagData } = await OutboundApi.getTagByIdJx({
- outPutId: outPutId,
- });
-
- // 鎻愬彇鏁版嵁瀛楁锛堟牴鎹帴鍙h繑鍥炵殑鏁版嵁缁撴瀯锛�
- const parsedData = {
- id: tagData?.id || outPutId,
- contractNo: tagData?.contractno || tagData?.contractNo || "-",
- batchNo: tagData?.systemno || tagData?.systemNo || tagData?.batchNo || "-",
- model: tagData?.model || "-",
- weight: tagData?.actuallyweight || tagData?.actuallyWeight || tagData?.weight || "-",
- clienteleName: tagData?.clientelename || tagData?.clienteleName || "-",
- actuallyLength: tagData?.actuallylength || tagData?.actuallyLength || "-",
- productionDate: tagData?.producttime || tagData?.productionDate || "-",
- projectId: tagData?.projectid || tagData?.projectId || projectId.value || "",
- // 淇濈暀鍘熷鏁版嵁
- rawData: tagData,
- scanCode: scanCode,
- };
-
- // 濡傛灉鎺ュ彛杩斿洖鐨勬暟鎹腑鏈� projectId锛屼繚瀛樺畠
- if (parsedData.projectId && !projectId.value) {
- projectId.value = parsedData.projectId;
- }
-
- // 娣诲姞鍒板垪琛�
- const newItem = {
- ...parsedData,
- scanTime: formatTime(new Date()),
- };
-
- outboundList.value.push(newItem);
- toast.success("鎵爜鎴愬姛");
- } catch (error: any) {
- console.error("鎵爜澶勭悊澶辫触:", error);
- toast.error(error.msg || "浜岀淮鐮佸紓甯革紝璇锋洿鎹簩缁寸爜锛�");
+ } catch (error) {
+ console.error("鑾峰彇鍑哄簱鍗曞垪琛ㄥけ璐�:", error);
+ toast.error("鑾峰彇鍑哄簱鍗曞垪琛ㄥけ璐�");
+ pagingRef.value.complete(true);
}
};
-// 瑙﹀彂鎵爜
-const openScan = () => {
- scanRef.value.triggerScan();
+// 鎼滅储澶勭悊
+const handleSearch = () => {
+ // 閲嶆柊鍔犺浇鏁版嵁
+ pagingRef.value.reload();
};
-// 鍒犻櫎椤�
-const removeOutboundItem = (index: number) => {
- const item = outboundList.value[index];
- const itemName = item.contractNo || item.batchNo || `绗�${index + 1}椤筦;
+// 娓呯┖鎼滅储
+const handleClear = () => {
+ searchKeyword.value = "";
+ handleSearch();
+};
- uni.showModal({
- title: "纭鍒犻櫎",
- content: `纭畾瑕佸垹闄�"${itemName}"鍚楋紵`,
- confirmText: "鍒犻櫎",
- cancelText: "鍙栨秷",
- confirmColor: "#ff4444",
- success: (res) => {
- if (res.confirm) {
- outboundList.value.splice(index, 1);
- toast.success("鍒犻櫎鎴愬姛");
- }
- },
+// 璺宠浆鍒扮墿鏂欒鎯呴〉
+const toMaterialDetail = (item: any) => {
+ uni.navigateTo({
+ url: `/pages/outbound/material?id=${item.deliveryid}&vbillcode=${item.vbillcode}`,
});
};
-
-// 澶勭悊鍑哄簱
-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);
+.outbound-page {
+ min-height: 100vh;
background: #f3f9f8;
- display: flex;
- flex-direction: column;
+ padding: 10rpx;
}
-.list_content {
- flex: 1;
- overflow-y: auto;
- padding-bottom: 120rpx;
+.search-section {
+ background: #fff;
+ padding: 10rpx;
+ margin-bottom: 10rpx;
+}
+
+.scan_box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 38px;
+ height: 38px;
+ padding: 6px;
+ background: #fff;
+}
+
+.list-section {
+ padding: 0 4px;
+ height: calc(100vh - 150rpx);
+}
+
+.card_bg {
+ box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
+ padding-bottom: 10px;
+ margin-bottom: 10px;
+ margin-left: 6px;
+ margin-right: 6px;
+}
+
+.shipping-card {
+ margin: 0 5px;
+}
+
+.icon_box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ background: #e7f4ec99;
+ border-radius: 50%;
}
.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;
- }
+ padding: 40px 0;
}
-:deep(.delete-btn) {
- .wd-button__content {
- color: #ff4444 !important;
- }
-
- &:active {
- opacity: 0.7;
- }
+.empty_text {
+ color: #999;
+ font-size: 14px;
}
-: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;
+:deep(.wd-search__block) {
+ border-radius: unset;
}
</style>
diff --git a/src/pages/outbound/index0.vue b/src/pages/outbound/index0.vue
new file mode 100644
index 0000000..88beb06
--- /dev/null
+++ b/src/pages/outbound/index0.vue
@@ -0,0 +1,350 @@
+<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.weight || "-" }} kg</text>
+ </view>
+ <view class="outbound_item_row">
+ <text class="outbound_item_label">鍘傚锛�</text>
+ <text class="outbound_item_value">{{ item.clienteleName || "-" }}</text>
+ </view>
+ <view class="outbound_item_row">
+ <text class="outbound_item_label">娈甸暱锛�</text>
+ <text class="outbound_item_value">{{ item.actuallyLength || "-" }} M</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 getScanCode = async (code: any) => {
+ try {
+ // 濡傛灉 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;
+ }
+
+ // 瑙f瀽鎵爜鏁版嵁锛岀幇鍦ㄤ簩缁寸爜鍙寘鍚玦d
+ let scanData;
+ try {
+ scanData = JSON.parse(scanCode);
+ } catch (e) {
+ toast.error("浜岀淮鐮佹牸寮忛敊璇�");
+ return;
+ }
+
+ const outPutId = scanData.id;
+
+ if (!outPutId) {
+ toast.error("浜岀淮鐮佹牸寮忛敊璇紝缂哄皯id淇℃伅");
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚﹀凡瀛樺湪锛堟牴鎹甶d鍒ゆ柇锛�
+ const exists = outboundList.value.some((item) => {
+ const itemId = item.id;
+ return itemId && itemId === outPutId && itemId !== "-";
+ });
+
+ if (exists) {
+ toast.error("璇ユ潯鐮佸凡瀛樺湪锛岃鍕块噸澶嶆壂鐮�");
+ return;
+ }
+
+ // 璋冪敤鎺ュ彛鑾峰彇缁炵嚎璇︾粏淇℃伅
+ const { data: tagData } = await OutboundApi.getTagByIdJx({
+ outPutId: outPutId,
+ });
+
+ // 鎻愬彇鏁版嵁瀛楁锛堟牴鎹帴鍙h繑鍥炵殑鏁版嵁缁撴瀯锛�
+ const parsedData = {
+ id: tagData?.id || outPutId,
+ contractNo: tagData?.contractno || tagData?.contractNo || "-",
+ batchNo: tagData?.systemno || tagData?.systemNo || tagData?.batchNo || "-",
+ model: tagData?.model || "-",
+ weight: tagData?.actuallyweight || tagData?.actuallyWeight || tagData?.weight || "-",
+ clienteleName: tagData?.clientelename || tagData?.clienteleName || "-",
+ actuallyLength: tagData?.actuallylength || tagData?.actuallyLength || "-",
+ productionDate: tagData?.producttime || tagData?.productionDate || "-",
+ projectId: tagData?.projectid || tagData?.projectId || projectId.value || "",
+ // 淇濈暀鍘熷鏁版嵁
+ rawData: tagData,
+ scanCode: scanCode,
+ };
+
+ // 濡傛灉鎺ュ彛杩斿洖鐨勬暟鎹腑鏈� projectId锛屼繚瀛樺畠
+ if (parsedData.projectId && !projectId.value) {
+ projectId.value = parsedData.projectId;
+ }
+
+ // 娣诲姞鍒板垪琛�
+ const newItem = {
+ ...parsedData,
+ scanTime: formatTime(new Date()),
+ };
+
+ outboundList.value.push(newItem);
+ toast.success("鎵爜鎴愬姛");
+ } catch (error: any) {
+ console.error("鎵爜澶勭悊澶辫触:", error);
+ toast.error(error.msg || "浜岀淮鐮佸紓甯革紝璇锋洿鎹簩缁寸爜锛�");
+ }
+};
+
+// 瑙﹀彂鎵爜
+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: 5rpx;
+ 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>
diff --git a/src/pages/outbound/material.vue b/src/pages/outbound/material.vue
new file mode 100644
index 0000000..477cbd4
--- /dev/null
+++ b/src/pages/outbound/material.vue
@@ -0,0 +1,627 @@
+<template>
+ <view class="material-page">
+ <view class="material-header">
+ <CardTitle title="鐗╂枡璇︽儏" :hideAction="false">
+ <template #action>
+ <wd-button
+ type="icon"
+ icon="scan"
+ color="#0d867f"
+ @click="openScan"
+ style="color: #0d867f"
+ ></wd-button>
+ </template>
+ </CardTitle>
+
+ <!-- 鐗╂枡淇℃伅 -->
+ <view class="material-info">
+ <wd-card
+ v-for="(item, index) in materialList"
+ :key="item.materialcode || index"
+ custom-class="info-card"
+ >
+ <wd-row class="info-row">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 鐗╂枡鍚嶇О:
+ <text class="text-[#252525]">{{ item.materialname || "-" }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ <wd-row class="info-row">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 鐗╂枡瑙勬牸:
+ <text class="text-[#252525]">{{ item.materialspec || "-" }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ <wd-row class="info-row">
+ <wd-col :span="24">
+ <view class="flex">
+ <view class="icon_box">
+ <wd-icon name="folder" color="#0D867F"></wd-icon>
+ </view>
+ <text class="text-[#646874] mx-2">
+ 宸插彂璐ф暟閲�:
+ <text class="text-[#252525]">{{ item.shippedQuantity || 0 }}</text>
+ </text>
+ </view>
+ </wd-col>
+ </wd-row>
+ </wd-card>
+ </view>
+ </view>
+
+ <!-- 璐х墿鍒楄〃 -->
+ <view class="list_content">
+ <view v-if="goodsList.length === 0" class="empty_tip">
+ <view class="empty_text">鏆傛棤璐х墿鏁版嵁</view>
+ </view>
+ <view v-for="(item, index) in goodsList" :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.monofilamentNumber || "-" }}</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.weight || "-" }} kg</text>
+ </view>
+ <view class="outbound_item_row">
+ <text class="outbound_item_label">鍘傚锛�</text>
+ <text class="outbound_item_value">{{ item.clienteleName || "-" }}</text>
+ </view>
+ <view class="outbound_item_row">
+ <text class="outbound_item_label">娈甸暱锛�</text>
+ <text class="outbound_item_value">{{ item.actuallyLength || "-" }} M</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="removeGoodsItem(index)"
+ ></wd-button>
+ </view>
+ </view>
+ </view>
+
+ <!-- 搴曢儴鎸夐挳 -->
+ <view v-if="goodsList.length > 1" class="outbound_footer">
+ <wd-button block @click="handleOutbound" style="background: #0d867f">
+ <text class="text-[#fff]">鍑哄簱</text>
+ </wd-button>
+ </view>
+
+ <Scan ref="scanRef" emitName="scanMaterial" />
+ <wd-toast />
+ </view>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, onUnmounted } from "vue";
+import { onLoad } from "@dcloudio/uni-app";
+// @ts-ignore
+import CardTitle from "@/components/card-title/index.vue";
+// @ts-ignore
+import Scan from "@/components/scan/index.vue";
+import { useToast, dayjs } from "wot-design-uni";
+import OutboundApi from "@/api/product/outbound";
+
+const toast = useToast();
+const scanRef = ref();
+const materialId = ref<string>("");
+const vbillcode = ref<string>("");
+
+// 鐗╂枡淇℃伅鍒楄〃
+const materialList = ref<any[]>([]);
+
+// 璐х墿鍒楄〃
+const goodsList = ref<any[]>([]);
+
+// 鏍煎紡鍖栨椂闂�
+const formatTime = (date: Date) => {
+ return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+};
+
+// 鑾峰彇鐗╂枡璇︽儏
+const getMaterialDetail = async () => {
+ if (!vbillcode.value) {
+ toast.error("鍙戣揣鍗曞彿涓嶈兘涓虹┖");
+ return;
+ }
+
+ try {
+ uni.showLoading({
+ title: "鍔犺浇涓�...",
+ mask: true,
+ });
+
+ const { code, data, msg } = await OutboundApi.queryErpOutboundOrderDetail({
+ vbillcode: vbillcode.value,
+ });
+
+ uni.hideLoading();
+
+ if (code === 200 && data) {
+ // 灏嗘帴鍙h繑鍥炵殑鏁版嵁鏄犲皠鍒� materialList
+ materialList.value = data.map((item: any) => ({
+ materialcode: item.materialcode,
+ materialname: item.materialname || "-",
+ materialspec: item.materialspec || "-",
+ shippedQuantity: item.nnum || 0,
+ cdeliveryid: item.cdeliveryid,
+ cdeliverybid: item.cdeliverybid,
+ vsrccode: item.vsrccode,
+ }));
+ } else {
+ toast.error(msg || "鑾峰彇鐗╂枡璇︽儏澶辫触");
+ materialList.value = [];
+ }
+ } catch (error: any) {
+ uni.hideLoading();
+ console.error("鑾峰彇鐗╂枡璇︽儏澶辫触:", error);
+ toast.error(error.msg || "鑾峰彇鐗╂枡璇︽儏澶辫触");
+ materialList.value = [];
+ }
+};
+
+// 鐩存帴鎵爜
+const openScan = () => {
+ scanRef.value?.triggerScan();
+};
+
+// 鎵爜鍥炶皟
+const getScanCode = async (code: any) => {
+ try {
+ // 濡傛灉 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;
+ }
+
+ // 瑙f瀽鎵爜鏁版嵁锛岀幇鍦ㄤ簩缁寸爜鍙寘鍚玦d
+ let scanData;
+ try {
+ scanData = JSON.parse(scanCode);
+ } catch (e) {
+ toast.error("浜岀淮鐮佹牸寮忛敊璇�");
+ return;
+ }
+
+ const outPutId = scanData.id;
+
+ if (!outPutId) {
+ toast.error("浜岀淮鐮佹牸寮忛敊璇紝缂哄皯id淇℃伅");
+ return;
+ }
+
+ // 妫�鏌ユ槸鍚﹀凡瀛樺湪锛堟牴鎹甶d鍒ゆ柇锛�
+ const exists = goodsList.value.some((item) => {
+ const itemId = item.id;
+ return itemId && itemId === outPutId && itemId !== "-";
+ });
+
+ if (exists) {
+ toast.error("璇ユ潯鐮佸凡瀛樺湪锛岃鍕块噸澶嶆壂鐮�");
+ return;
+ }
+
+ // 璋冪敤鎺ュ彛鑾峰彇缁炵嚎/鎷変笣璇︾粏淇℃伅锛堝惈鍑哄簱鐘舵�侊級
+ const { data } = await OutboundApi.getTagByIdAll({
+ outPutId: outPutId,
+ });
+
+ const list = data || [];
+ if (!list.length) {
+ toast.error("鏈煡璇㈠埌鏉$爜淇℃伅");
+ return;
+ }
+
+ const tagData = list[0];
+
+ // 宸插嚭搴撴牎楠�
+ if (tagData?.state === "宸插嚭搴�") {
+ toast.error("璇ユ潯鐮佸凡鍑哄簱锛屾棤娉曢噸澶嶅嚭搴�");
+ return;
+ }
+
+ // 鎻愬彇鏁版嵁瀛楁锛堟牴鎹帴鍙h繑鍥炵殑鏁版嵁缁撴瀯锛�
+ const parsedData = {
+ id: tagData?.id || outPutId,
+ contractNo: tagData?.contractno || tagData?.contractNo || "-",
+ monofilamentNumber:
+ tagData?.monofilamentnumber ||
+ tagData?.monofilamentNumber ||
+ tagData?.systemno ||
+ tagData?.systemNo ||
+ "-",
+ model: tagData?.model || "-",
+ weight: tagData?.actuallylength || tagData?.actuallyLength || tagData?.weight || "-",
+ clienteleName: tagData?.clientelename || tagData?.clienteleName || "-",
+ actuallyLength: tagData?.actuallylength || tagData?.actuallyLength || "-",
+ productionDate: tagData?.producttime || tagData?.productionDate || "-",
+ type: tagData?.type || "",
+ devicemodel: tagData?.devicemodel || "",
+ state: tagData?.state || "",
+ projectId: tagData?.projectid || tagData?.projectId || "",
+ productuser: tagData?.productuser || "",
+ // 淇濈暀鍘熷鏁版嵁
+ rawData: tagData,
+ scanCode: scanCode,
+ };
+
+ // 娣诲姞鍒板垪琛�
+ const newItem = {
+ ...parsedData,
+ scanTime: formatTime(new Date()),
+ };
+
+ goodsList.value.push(newItem);
+ toast.success("鎵爜鎴愬姛");
+ } catch (error: any) {
+ console.error("鎵爜澶勭悊澶辫触:", error);
+ toast.error(error.msg || "浜岀淮鐮佸紓甯革紝璇锋洿鎹簩缁寸爜锛�");
+ }
+};
+
+// 鍒犻櫎璐х墿椤�
+const removeGoodsItem = (index: number) => {
+ const item = goodsList.value[index];
+ const itemName = item.contractNo || item.monofilamentNumber || `绗�${index + 1}椤筦;
+
+ uni.showModal({
+ title: "纭鍒犻櫎",
+ content: `纭畾瑕佸垹闄�"${itemName}"鍚楋紵`,
+ confirmText: "鍒犻櫎",
+ cancelText: "鍙栨秷",
+ confirmColor: "#ff4444",
+ success: (res) => {
+ if (res.confirm) {
+ goodsList.value.splice(index, 1);
+ toast.success("鍒犻櫎鎴愬姛");
+ }
+ },
+ });
+};
+
+// 缁熻鐗╂枡鏁伴噺鍜岀被鍨嬭鏍�
+const getMaterialStatistics = () => {
+ const statistics: Record<string, { type: string; model: string; count: number }> = {};
+
+ goodsList.value.forEach((item) => {
+ const type = item.type || "鏈煡绫诲瀷";
+ const model = item.model || "鏈煡瑙勬牸";
+ const key = `${type}_${model}`;
+
+ if (!statistics[key]) {
+ statistics[key] = {
+ type,
+ model,
+ count: 0,
+ };
+ }
+ statistics[key].count++;
+ });
+
+ return Object.values(statistics);
+};
+
+// 澶勭悊鍑哄簱
+const handleOutbound = async () => {
+ if (goodsList.value.length === 0) {
+ toast.error("鏆傛棤璐х墿鏁版嵁");
+ return;
+ }
+
+ // 缁熻鐗╂枡鏁伴噺鍜岀被鍨嬭鏍�
+ const statistics = getMaterialStatistics();
+
+ // 鏋勫缓缁熻淇℃伅鏂囨湰
+ let statisticsText = "鍑哄簱鐗╂枡缁熻锛歕n\n";
+ statistics.forEach((item, index) => {
+ statisticsText += `${index + 1}. ${item.type} - ${item.model}锛�${item.count}浠禱n`;
+ });
+ statisticsText += `\n鎬昏锛�${goodsList.value.length}浠禱n\n纭鍑哄簱鍚楋紵`;
+
+ // 鏄剧ず纭寮规
+ uni.showModal({
+ title: "纭鍑哄簱",
+ content: statisticsText,
+ confirmText: "纭",
+ cancelText: "鍙栨秷",
+ confirmColor: "#0d867f",
+ success: async (res) => {
+ if (res.confirm) {
+ // 鏋勫缓璇锋眰鏁版嵁
+ const requestData = goodsList.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("鍑哄簱鎴愬姛");
+ // 娓呯┖鍒楄〃
+ goodsList.value = [];
+ // 杩斿洖涓婁竴椤垫垨鍒锋柊鐗╂枡璇︽儏
+ setTimeout(() => {
+ uni.navigateBack();
+ }, 1500);
+ } else {
+ toast.error(msg || "鍑哄簱澶辫触");
+ }
+ } catch (error: any) {
+ uni.hideLoading();
+ console.error("鍑哄簱澶辫触:", error);
+ toast.error(error.msg || "鍑哄簱澶辫触");
+ }
+ }
+ },
+ });
+};
+
+// 璁剧疆鎵爜鐩戝惉
+const setupScanListener = () => {
+ uni.$off("scanMaterial", getScanCode);
+ uni.$on("scanMaterial", getScanCode);
+};
+
+onLoad((options: any) => {
+ materialId.value = options.id || "";
+ vbillcode.value = options.vbillcode || "";
+ getMaterialDetail();
+});
+
+onMounted(() => {
+ setupScanListener();
+});
+
+onUnmounted(() => {
+ uni.$off("scanMaterial", getScanCode);
+});
+</script>
+
+<style lang="scss" scoped>
+.material-page {
+ min-height: 100vh;
+ background: #f3f9f8;
+ padding-bottom: 200rpx;
+ display: flex;
+ flex-direction: column;
+}
+
+.material-header {
+ position: sticky;
+ top: 0;
+ z-index: 10;
+ background: #f3f9f8;
+ padding-bottom: 10rpx;
+}
+
+.material-info {
+ padding: 20rpx;
+}
+
+.info-card {
+ box-shadow: 0px 0px 12px 0px rgba(0, 0, 0, 0.05);
+ margin-bottom: 20rpx;
+ margin-left: 6px;
+ margin-right: 6px;
+ padding: 10px 18px;
+ background: #f3f9f8;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.info-row {
+ margin-bottom: 20rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+}
+
+.icon_box {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ background: #e7f4ec99;
+ border-radius: 50%;
+}
+
+.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: 30rpx;
+ 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;
+ }
+}
+
+.outbound_footer {
+ position: fixed;
+ bottom: 20rpx;
+ left: 0;
+ right: 0;
+ padding: 0 30rpx;
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+ z-index: 100;
+ background: transparent;
+}
+
+.shipping-btn-wrapper {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 20rpx 30rpx;
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+ background: #fff;
+ z-index: 100;
+ box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
+}
+
+.shipping-dialog {
+ background: #fff;
+ border-radius: 24rpx 24rpx 0 0;
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
+.dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 32rpx;
+ border-bottom: 1px solid #e6e6e6;
+}
+
+.dialog-title {
+ font-size: 32rpx;
+ font-weight: 500;
+ color: #333;
+}
+
+.close-icon {
+ font-size: 40rpx;
+ color: #999;
+ padding: 8rpx;
+}
+
+.dialog-content {
+ padding: 32rpx;
+}
+
+.scan-tip {
+ text-align: center;
+ color: #666;
+ font-size: 28rpx;
+ padding: 40rpx 0;
+}
+</style>
--
Gitblit v1.9.3