From 01c045e6ebc486e2a050b1739fad075b7f424254 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 18 五月 2026 14:47:50 +0800
Subject: [PATCH] 优化设备保养:在新增和编辑保养计划时,清除本地存储中的repairId,确保数据一致性。
---
src/pages/inventoryManagement/scanOut/index.vue | 1116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,106 insertions(+), 10 deletions(-)
diff --git a/src/pages/inventoryManagement/scanOut/index.vue b/src/pages/inventoryManagement/scanOut/index.vue
index 8359451..8e42473 100644
--- a/src/pages/inventoryManagement/scanOut/index.vue
+++ b/src/pages/inventoryManagement/scanOut/index.vue
@@ -2,7 +2,7 @@
<view class="scan-container">
- <PageHeader title="鎵爜鍑哄簱"
+ <PageHeader title="鎵爜鍙戣揣"
@back="goBack" />
@@ -28,7 +28,7 @@
<text class="module-label">鍚堟牸鍑哄簱</text>
- <text class="module-desc">鎵弿鍚堟牸鍝佽繘琛岄鐢ㄥ嚭搴�</text>
+ <text class="module-desc">璁板綍鍚堟牸鍝佺殑鍑哄簱娴佸悜锛岄攢鍞簩缁寸爜鎵弿鍙戣揣</text>
</view>
@@ -193,19 +193,27 @@
<view class="kv-row stocked-qty-row">
- <text class="kv-label">鍑哄簱鏁伴噺</text>
+ <text class="kv-label">{{ needScanShipFlow ? "鏈鍙戣揣鏁伴噺" : "鍑哄簱鏁伴噺" }}</text>
<view class="kv-value stocked-qty-input-wrap">
- <up-input :key="'stocked-' + idx"
+ <text v-if="needScanShipFlow"
+
+ class="scan-ship-qty-readonly">{{ resolveScanShipLineQuantity(item) }}</text>
+
+ <up-input v-else
+
+ :key="'stocked-' + idx"
v-model="item.operateQuantity"
type="number"
placeholder="璇疯緭鍏ュ嚭搴撴暟閲�"
+ :clearable="!isSalesQualifiedOutboundQtyLocked"
- clearable
+ :disabled="isSalesQualifiedOutboundQtyLocked"
+
border="surround"
@@ -215,9 +223,221 @@
</view>
+ <text v-if="needScanShipFlow"
+
+ class="scan-ship-qty-hint">鏁村崟涓�娆℃�у彂璐э紝鏁伴噺浠ヨ鍗曚负鍑嗭紝涓嶅彲淇敼</text>
+
</view>
</view>
+
+ <view v-if="needScanShipFlow"
+
+ class="scan-ship-card">
+
+ <view class="scan-ship-title">鍙戣揣淇℃伅</view>
+
+ <u-form label-width="220rpx">
+
+ <u-form-item label="鍙戣揣鏂瑰紡"
+
+ class="scan-ship-type-form-item"
+
+ required>
+
+ <view class="scan-ship-type-trigger"
+
+ @tap.stop="openScanShipTypeSheet">
+
+ <u-input v-model="scanShipTypeLabel"
+
+ readonly
+
+ placeholder="璇烽�夋嫨" />
+
+ <u-icon name="arrow-right"
+
+ color="#c0c4cc"
+
+ size="18" />
+
+ </view>
+
+ </u-form-item>
+
+ <u-form-item v-if="scanShipTypeValue === '璐ц溅'"
+
+ label="杞︾墝鍙�"
+
+ required>
+
+ <u-input v-model="scanShipCarNumber"
+
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+
+ clearable />
+
+ </u-form-item>
+
+ <u-form-item v-if="scanShipTypeValue === '蹇��'"
+
+ label="蹇�掑崟鍙�"
+
+ required>
+
+ <u-input v-model="scanShipExpress"
+
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+
+ clearable />
+
+ </u-form-item>
+
+ </u-form>
+
+ <view class="approval-process">
+
+ <view class="approval-header">
+
+ <text class="approval-title">瀹℃壒娴佺▼</text>
+
+ <text class="approval-desc">姣忎釜姝ラ鍙兘閫夋嫨涓�涓鎵逛汉</text>
+
+ </view>
+
+ <view class="approval-steps">
+
+ <view v-for="(step, stepIndex) in scanShipApproverNodes"
+
+ :key="step.id"
+
+ class="approval-step">
+
+ <view class="step-title">
+
+ <text>瀹℃壒浜�</text>
+
+ </view>
+
+ <view class="approver-container">
+
+ <view v-if="step.nickName"
+
+ class="approver-item">
+
+ <view class="approver-avatar">
+
+ <text class="avatar-text">{{ step.nickName.charAt(0) }}</text>
+
+ </view>
+
+ <view class="approver-info">
+
+ <text class="approver-name">{{ step.nickName }}</text>
+
+ </view>
+
+ <view class="delete-approver-btn"
+
+ @tap.stop="removeScanShipApproverUser(stepIndex)">脳</view>
+
+ </view>
+
+ <view v-else
+
+ class="add-approver-btn"
+
+ @tap.stop="openScanShipContactSelect(stepIndex)">
+
+ <view class="add-circle">+</view>
+
+ <text class="add-label">閫夋嫨瀹℃壒浜�</text>
+
+ </view>
+
+ </view>
+
+ <view class="delete-step-btn"
+
+ v-if="scanShipApproverNodes.length > 1"
+
+ @tap.stop="removeScanShipApproverNode(stepIndex)">鍒犻櫎鑺傜偣</view>
+
+ </view>
+
+ </view>
+
+ <view class="add-step-btn">
+
+ <u-button icon="plus"
+
+ plain
+
+ type="primary"
+
+ style="width: 100%"
+
+ @click="addScanShipApproverNode">鏂板鑺傜偣</u-button>
+
+ </view>
+
+ </view>
+
+ <view class="scan-ship-files">
+
+ <text class="scan-ship-subtitle">鍙戣揣闄勪欢锛堥�夊~锛屾渶澶�10寮狅級</text>
+
+ <u-button class="scan-ship-add-img-btn"
+
+ size="small"
+
+ type="primary"
+
+ :loading="scanShipUploading"
+
+ :disabled="scanShipFiles.length >= 10"
+
+ @click="chooseScanShipImage">娣诲姞鍥剧墖</u-button>
+
+ <view v-if="scanShipFiles.length"
+
+ class="scan-ship-file-grid">
+
+ <view v-for="(f, fi) in scanShipFiles"
+
+ :key="fi"
+
+ class="scan-ship-thumb-wrap">
+
+ <image :src="scanShipFileUrl(f)"
+
+ class="scan-ship-thumb"
+
+ mode="aspectFill"
+
+ @click="previewScanShipImage(fi)" />
+
+ <text class="scan-ship-thumb-del"
+
+ @click.stop="removeScanShipFile(fi)">脳</text>
+
+ </view>
+
+ </view>
+
+ </view>
+
+ </view>
+
+ <up-action-sheet :show="scanShipTypeSheetShow"
+
+ :actions="scanShipTypeActions"
+
+ title="鍙戣揣鏂瑰紡"
+
+ @select="onScanShipTypeSelect"
+
+ @close="scanShipTypeSheetShow = false" />
<view class="footer-btns">
@@ -225,7 +445,17 @@
@click="cancelForm">杩斿洖</u-button>
- <u-button class="footer-confirm-btn"
+ <u-button v-if="needScanShipFlow"
+
+ class="footer-confirm-btn"
+
+ :loading="submitLoading"
+
+ @click="confirmScanShipApply">鎻愪氦鍙戣揣瀹℃壒</u-button>
+
+ <u-button v-else
+
+ class="footer-confirm-btn"
:loading="submitLoading"
@@ -243,11 +473,15 @@
<script setup>
- import { ref, computed } from "vue";
+ import { ref, computed, onMounted, onUnmounted } from "vue";
import PageHeader from "@/components/PageHeader.vue";
- import { productList as salesProductList } from "@/api/salesManagement/salesLedger";
+ import { productList as salesProductList, scanShipApply } from "@/api/salesManagement/salesLedger";
+
+ import config from "@/config";
+ import { getToken } from "@/utils/auth";
+ import { getLedgerShippingLabel } from "@/utils/salesLedgerShip";
import modal from "@/plugins/modal";
@@ -260,6 +494,8 @@
resolveListTypeForDetail,
resolveContractNo,
buildSalesLedgerProductList,
+ buildScanShipProductList,
+ resolveScanShipLineQuantity,
hasAnyPositiveStockedQty,
resolveSubmitSceneKey,
} from "./scanOut.logic";
@@ -283,6 +519,241 @@
const submitLoading = ref(false);
+ /** 閿�鍞� + 鍚堟牸锛氳蛋銆屾彁浜ゅ彂璐у鎵广�嶏紝涓嶅啀鐩存帴鍑哄簱鎴栬烦杞師鍙戣揣椤� */
+ const needScanShipFlow = computed(
+ () =>
+ showForm.value &&
+ type.value === QUALITY_TYPE.qualified &&
+ contractKind.value === CONTRACT_KIND.sales
+ );
+
+ const scanShipTypeValue = ref("璐ц溅");
+ const scanShipTypeLabel = computed(() => scanShipTypeValue.value);
+ const scanShipTypeSheetShow = ref(false);
+ const scanShipTypeActions = ref([
+ { name: "璐ц溅", value: "璐ц溅" },
+ { name: "蹇��", value: "蹇��" },
+ ]);
+ const scanShipCarNumber = ref("");
+ const scanShipExpress = ref("");
+ let nextScanShipApproverNodeId = 2;
+ const scanShipApproverNodes = ref([{ id: 1, userId: null, nickName: "" }]);
+ const scanShipFiles = ref([]);
+ const scanShipUploading = ref(false);
+
+ const scanShipUploadConfig = {
+ action: "/file/upload",
+ limit: 10,
+ fileType: ["jpg", "jpeg", "png", "gif", "webp"],
+ formType: 10,
+ };
+
+ const uploadScanShipFileUrl = computed(
+ () => (config.baseUrl || "").replace(/\/$/, "") + scanShipUploadConfig.action
+ );
+
+ const onScanShipTypeSelect = item => {
+ scanShipTypeValue.value = item.name || item.value || "璐ц溅";
+ scanShipTypeSheetShow.value = false;
+ if (scanShipTypeValue.value === "璐ц溅") scanShipExpress.value = "";
+ else scanShipCarNumber.value = "";
+ };
+
+ const openScanShipTypeSheet = () => {
+ scanShipTypeSheetShow.value = true;
+ };
+
+ const addScanShipApproverNode = () => {
+ scanShipApproverNodes.value.push({
+ id: nextScanShipApproverNodeId++,
+ userId: null,
+ nickName: "",
+ });
+ };
+
+ const removeScanShipApproverNode = stepIndex => {
+ if (scanShipApproverNodes.value.length <= 1) return;
+ scanShipApproverNodes.value.splice(stepIndex, 1);
+ };
+
+ const removeScanShipApproverUser = stepIndex => {
+ const step = scanShipApproverNodes.value[stepIndex];
+ if (!step) return;
+ step.userId = null;
+ step.nickName = "";
+ };
+
+ const openScanShipContactSelect = stepIndex => {
+ uni.setStorageSync("stepIndex", stepIndex);
+ uni.navigateTo({
+ url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect?approveType=7&source=scanShip",
+ });
+ };
+
+ const handleScanShipSelectContact = data => {
+ if (data?.source !== "scanShip") return;
+ if (!needScanShipFlow.value) return;
+ const c = data?.contact;
+ if (!c) return;
+ const idx = Number(data.stepIndex);
+ const i = Number.isNaN(idx) ? 0 : idx;
+ if (i < 0 || i >= scanShipApproverNodes.value.length) return;
+ const row = scanShipApproverNodes.value[i];
+ row.userId = c.userId;
+ row.nickName = c.nickName || c.userName || "";
+ };
+
+ const scanShipFileUrl = file => {
+ const base = config.fileUrl || "";
+ const link = file?.link || file?.url || "";
+ if (link && String(link).startsWith("http")) return link;
+ if (link && link.startsWith("/")) return base + link;
+ return file?.tempFilePath || file?.path || "";
+ };
+
+ const chooseScanShipImage = () => {
+ if (scanShipFiles.value.length >= scanShipUploadConfig.limit) {
+ modal.msgError(`鏈�澶�${scanShipUploadConfig.limit}寮燻);
+ return;
+ }
+ uni.chooseImage({
+ count: 1,
+ sizeType: ["compressed"],
+ sourceType: ["album", "camera"],
+ success: res => {
+ const path = res?.tempFilePaths?.[0];
+ const tf = res?.tempFiles?.[0] || {};
+ if (!path) return;
+ const token = getToken();
+ if (!token) {
+ modal.msgError("鏈櫥褰�");
+ return;
+ }
+ scanShipUploading.value = true;
+ uni.uploadFile({
+ url: uploadScanShipFileUrl.value,
+ filePath: path,
+ name: "file",
+ formData: { type: scanShipUploadConfig.formType },
+ header: { Authorization: `Bearer ${token}` },
+ success: up => {
+ try {
+ const body = JSON.parse(up.data || "{}");
+ if (body.code === 200 && body.data) {
+ const d = body.data;
+ scanShipFiles.value.push({
+ tempId: d.tempId ?? d.tempFileId ?? d.id,
+ link: d.link || d.url,
+ url: d.url,
+ name: d.originalFilename || d.originalName || "鍥剧墖",
+ tempFilePath: path,
+ });
+ modal.msgSuccess("涓婁紶鎴愬姛");
+ } else {
+ modal.msgError(body.msg || "涓婁紶澶辫触");
+ }
+ } catch (e) {
+ modal.msgError("涓婁紶瑙f瀽澶辫触");
+ }
+ },
+ fail: () => modal.msgError("涓婁紶澶辫触"),
+ complete: () => {
+ scanShipUploading.value = false;
+ },
+ });
+ },
+ });
+ };
+
+ const removeScanShipFile = idx => {
+ scanShipFiles.value.splice(idx, 1);
+ };
+
+ const previewScanShipImage = idx => {
+ const urls = scanShipFiles.value.map(f => scanShipFileUrl(f)).filter(Boolean);
+ const cur = urls[idx];
+ if (urls.length && cur) uni.previewImage({ urls, current: cur });
+ };
+
+ const getScanShipTempFileIds = () =>
+ scanShipFiles.value.map(f => f.tempId).filter(id => id != null && id !== "");
+
+ const confirmScanShipApply = async () => {
+ if (scanLedgerId.value == null || scanLedgerId.value === "") {
+ modal.msgError("缂哄皯璁㈠崟淇℃伅锛岃閲嶆柊鎵爜");
+ return;
+ }
+ if (!hasEditableOutboundItems.value) {
+ modal.msgError("璇ヤ骇鍝佸凡缁忓叏閮ㄥ嚭搴�");
+ return;
+ }
+ const salesLedgerProductList = buildScanShipProductList(recordList.value);
+ if (!hasAnyPositiveStockedQty(salesLedgerProductList)) {
+ modal.msgError("褰撳墠璁㈠崟鏃犲彲鍙戣揣鏁伴噺");
+ return;
+ }
+ if (scanShipTypeValue.value === "璐ц溅" && !String(scanShipCarNumber.value || "").trim()) {
+ modal.msgError("璇疯緭鍏ヨ溅鐗屽彿");
+ return;
+ }
+ if (scanShipTypeValue.value === "蹇��" && !String(scanShipExpress.value || "").trim()) {
+ modal.msgError("璇疯緭鍏ュ揩閫掑崟鍙�");
+ return;
+ }
+ const hasEmptyStep = scanShipApproverNodes.value.some(s => !s?.userId);
+ if (hasEmptyStep) {
+ modal.msgError("璇蜂负姣忎釜瀹℃壒姝ラ閫夋嫨瀹℃壒浜�");
+ return;
+ }
+ if (scanShipUploading.value) {
+ modal.msgError("闄勪欢涓婁紶涓紝璇风◢鍊�");
+ return;
+ }
+ const approveUserIds = scanShipApproverNodes.value
+ .map(s => s.userId)
+ .filter(id => id != null && id !== "")
+ .join(",");
+ const payload = {
+ salesLedgerId: scanLedgerId.value,
+ salesLedgerProductList,
+ approveUserIds,
+ shipType: scanShipTypeValue.value,
+ shippingCarNumber:
+ scanShipTypeValue.value === "璐ц溅" ? String(scanShipCarNumber.value || "").trim() : "",
+ expressNumber:
+ scanShipTypeValue.value === "蹇��" ? String(scanShipExpress.value || "").trim() : "",
+ tempFileIds: getScanShipTempFileIds(),
+ };
+ try {
+ submitLoading.value = true;
+ modal.loading("鎻愪氦涓�...");
+ const res = await scanShipApply(payload);
+ modal.closeLoading();
+ if (res.code === 200) {
+ modal.msgSuccess(res.msg || "鍙戣揣瀹℃壒宸插彂璧�");
+ resetDetailView();
+ } else {
+ modal.msgError(res.msg || "鎻愪氦澶辫触");
+ }
+ } catch (e) {
+ modal.closeLoading();
+ console.error(e);
+ } finally {
+ submitLoading.value = false;
+ }
+ };
+
+ onMounted(() => {
+ uni.$on("selectContact", handleScanShipSelectContact);
+ });
+ onUnmounted(() => {
+ uni.$off("selectContact", handleScanShipSelectContact);
+ });
+ const isSalesQualifiedOutboundQtyLocked = computed(
+ () =>
+ type.value === QUALITY_TYPE.qualified &&
+ contractKind.value === CONTRACT_KIND.sales
+ );
const submitConfigByScene = createSubmitConfig(scanLedgerId);
const cardTitleMain = computed(() => {
@@ -568,6 +1039,8 @@
return formatProductStockStatus(item.productStockStatus);
+ if (row.key === "ledgerShippingStatus") return getLedgerShippingLabel(item);
+
if (row.key === "heavyBox") return formatHeavyBox(item.heavyBox);
if (row.key === "remainingQuantity") {
@@ -637,6 +1110,15 @@
expandedByIndex.value = {};
recordList.value = [];
+
+ scanShipTypeValue.value = "璐ц溅";
+ scanShipCarNumber.value = "";
+ scanShipExpress.value = "";
+ nextScanShipApproverNodeId = 2;
+ scanShipApproverNodes.value = [{ id: 1, userId: null, nickName: "" }];
+ scanShipFiles.value = [];
+ scanShipUploading.value = false;
+ scanShipTypeSheetShow.value = false;
};
@@ -732,8 +1214,6 @@
}
};
-
-
const goBack = () => {
@@ -994,6 +1474,12 @@
height: 140rpx;
+ min-width: 140rpx;
+
+ min-height: 140rpx;
+
+ flex-shrink: 0;
+
border-radius: 32rpx;
display: flex;
@@ -1033,6 +1519,10 @@
display: flex;
flex-direction: column;
+
+ flex: 1;
+
+ min-width: 0;
}
@@ -1306,6 +1796,612 @@
+ /* 鍙戣揣淇℃伅锛氫笌鎵爜鍏ュ簱瀹℃壒鍖恒�佸彴璐﹀彂璐ч〉琛ㄥ崟椋庢牸涓�鑷� */
+
+ .scan-ship-card {
+
+ background-color: #fff;
+
+ margin: 20rpx;
+
+ padding: 0 0 24rpx;
+
+ border-radius: 16rpx;
+
+ box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
+
+ overflow: hidden;
+
+ }
+
+
+
+ .scan-ship-title {
+
+ font-size: 30rpx;
+
+ font-weight: 600;
+
+ color: #333;
+
+ padding: 28rpx 28rpx 20rpx;
+
+ border-bottom: 1rpx solid #eee;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form) {
+
+ background: transparent;
+
+ margin: 0;
+
+ padding: 0;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form-item) {
+
+ background: #fff;
+
+ padding: 0 28rpx;
+
+ border-bottom: 1rpx solid #f0f0f0;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form-item:last-child) {
+
+ border-bottom: none;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form-item__body) {
+
+ padding: 24rpx 0;
+
+ min-height: 88rpx;
+
+ display: flex;
+
+ align-items: center;
+
+ border: none;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form-item__label) {
+
+ font-size: 28rpx;
+
+ color: #888;
+
+ font-weight: 400;
+
+ flex-shrink: 0;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-form-item__content) {
+
+ flex: 1;
+
+ min-width: 0;
+
+ display: flex;
+
+ justify-content: flex-end;
+
+ align-items: center;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-input),
+
+ .scan-ship-card :deep(.u-input input),
+
+ .scan-ship-card :deep(.u-input__content__field-wrapper__field),
+
+ .scan-ship-card :deep(.u-input__input) {
+
+ border: none !important;
+
+ box-shadow: none !important;
+
+ background: transparent !important;
+
+ font-size: 28rpx;
+
+ color: #1a1a1a;
+
+ text-align: right;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-input input[readonly]),
+
+ .scan-ship-card :deep(.u-input__input[readonly]) {
+
+ color: #666;
+
+ }
+
+
+
+ .scan-ship-card :deep(.scan-ship-type-form-item .u-form-item__content) {
+
+ justify-content: flex-start;
+
+ align-items: center;
+
+ }
+
+
+
+ .scan-ship-type-trigger {
+
+ display: flex;
+
+ flex-direction: row;
+
+ align-items: center;
+
+ width: 100%;
+
+ min-height: 72rpx;
+
+ padding: 8rpx 0;
+
+ box-sizing: border-box;
+
+ }
+
+
+
+ .scan-ship-type-trigger :deep(.u-input) {
+
+ flex: 1;
+
+ min-width: 0;
+
+ }
+
+
+
+ .scan-ship-type-trigger :deep(input),
+
+ .scan-ship-type-trigger :deep(.u-input__input) {
+
+ pointer-events: none;
+
+ }
+
+
+
+ .scan-ship-card :deep(.u-input input::placeholder),
+
+ .scan-ship-card :deep(.u-input__input::placeholder) {
+
+ color: #c0c4cc;
+
+ font-size: 28rpx;
+
+ }
+
+
+
+ .scan-ship-card :deep(.scan-ship-type-form-item .u-input input),
+
+ .scan-ship-card :deep(.scan-ship-type-form-item .u-input__input) {
+
+ text-align: left;
+
+ }
+
+
+
+ .scan-ship-card .approval-process {
+
+ background: transparent;
+
+ margin: 0;
+
+ padding: 24rpx 28rpx 8rpx;
+
+ border-radius: 0;
+
+ box-shadow: none;
+
+ border-top: 1rpx solid #f0f0f0;
+
+ margin-top: 8rpx;
+
+ }
+
+
+
+ .scan-ship-card .approval-header {
+
+ margin-bottom: 16rpx;
+
+ }
+
+
+
+ .scan-ship-card .approval-title {
+
+ font-size: 30rpx;
+
+ font-weight: 600;
+
+ color: #333;
+
+ display: block;
+
+ }
+
+
+
+ .scan-ship-card .approval-desc {
+
+ font-size: 24rpx;
+
+ color: #999;
+
+ margin-top: 6rpx;
+
+ }
+
+
+
+ .scan-ship-card .approval-step {
+
+ margin-bottom: 18rpx;
+
+ }
+
+
+
+ .scan-ship-card .step-title text {
+
+ font-size: 24rpx;
+
+ color: #666;
+
+ }
+
+
+
+ .scan-ship-card .approver-container {
+
+ display: flex;
+
+ align-items: center;
+
+ margin-top: 10rpx;
+
+ }
+
+
+
+ .scan-ship-card .approver-item {
+
+ width: 100%;
+
+ display: flex;
+
+ align-items: center;
+
+ gap: 12rpx;
+
+ padding: 12rpx 0;
+
+ }
+
+
+
+ .scan-ship-card .approver-avatar {
+
+ width: 64rpx;
+
+ height: 64rpx;
+
+ border-radius: 50%;
+
+ background: #f3f4f6;
+
+ border: 2rpx solid #e5e7eb;
+
+ display: flex;
+
+ align-items: center;
+
+ justify-content: center;
+
+ }
+
+
+
+ .scan-ship-card .avatar-text {
+
+ font-size: 24rpx;
+
+ color: #374151;
+
+ font-weight: 600;
+
+ }
+
+
+
+ .scan-ship-card .approver-info {
+
+ flex: 1;
+
+ }
+
+
+
+ .scan-ship-card .approver-name {
+
+ font-size: 28rpx;
+
+ color: #333;
+
+ }
+
+
+
+ .scan-ship-card .delete-approver-btn {
+
+ font-size: 32rpx;
+
+ color: #ff4d4f;
+
+ padding: 0 8rpx;
+
+ }
+
+
+
+ .scan-ship-card .add-approver-btn {
+
+ display: flex;
+
+ align-items: center;
+
+ gap: 10rpx;
+
+ color: #3b82f6;
+
+ padding: 10rpx 0;
+
+ }
+
+
+
+ .scan-ship-card .add-circle {
+
+ width: 52rpx;
+
+ height: 52rpx;
+
+ border: 2rpx dashed #a0aec0;
+
+ border-radius: 50%;
+
+ color: #6b7280;
+
+ display: flex;
+
+ align-items: center;
+
+ justify-content: center;
+
+ font-size: 34rpx;
+
+ line-height: 1;
+
+ }
+
+
+
+ .scan-ship-card .add-label {
+
+ font-size: 26rpx;
+
+ }
+
+
+
+ .scan-ship-card .delete-step-btn {
+
+ color: #ff4d4f;
+
+ font-size: 24rpx;
+
+ margin-top: 8rpx;
+
+ }
+
+
+
+ .scan-ship-card .add-step-btn {
+
+ margin-top: 8rpx;
+
+ }
+
+
+
+ .scan-ship-subtitle {
+
+ display: block;
+
+ font-size: 24rpx;
+
+ color: #666;
+
+ margin-bottom: 16rpx;
+
+ }
+
+
+
+ .scan-ship-files {
+
+ padding: 28rpx 28rpx 0;
+
+ border-top: 1rpx solid #f0f0f0;
+
+ margin-top: 16rpx;
+
+ }
+
+
+
+ .scan-ship-files :deep(.scan-ship-add-img-btn) {
+
+ width: 100% !important;
+
+ margin-top: 8rpx;
+
+ border-radius: 16rpx !important;
+
+ min-height: 88rpx;
+
+ }
+
+
+
+ .scan-ship-file-grid {
+
+ display: flex;
+
+ flex-wrap: wrap;
+
+ gap: 24rpx;
+
+ margin-top: 24rpx;
+
+ }
+
+
+
+ .scan-ship-thumb-wrap {
+
+ position: relative;
+
+ width: calc(50% - 12rpx);
+
+ min-width: 200rpx;
+
+ padding: 16rpx;
+
+ box-sizing: border-box;
+
+ background: #fff;
+
+ border-radius: 16rpx;
+
+ border: 1rpx solid #e9ecef;
+
+ box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.05);
+
+ }
+
+
+
+ .scan-ship-thumb {
+
+ width: 100%;
+
+ height: 200rpx;
+
+ border-radius: 12rpx;
+
+ display: block;
+
+ border: 2rpx solid #f0f0f0;
+
+ background: #f5f5f5;
+
+ }
+
+
+
+ .scan-ship-thumb-del {
+
+ position: absolute;
+
+ top: 8rpx;
+
+ right: 8rpx;
+
+ width: 44rpx;
+
+ height: 44rpx;
+
+ background: #ff4757;
+
+ color: #fff;
+
+ font-size: 28rpx;
+
+ line-height: 44rpx;
+
+ text-align: center;
+
+ border-radius: 50%;
+
+ box-shadow: 0 4rpx 8rpx rgba(255, 71, 87, 0.35);
+
+ }
+
+
+
+ .scan-ship-qty-readonly {
+
+ font-size: 30rpx;
+
+ font-weight: 600;
+
+ color: #1a1a1a;
+
+ }
+
+ .scan-ship-qty-hint {
+
+ display: block;
+
+ font-size: 24rpx;
+
+ color: #999;
+
+ padding: 8rpx 0 0;
+
+ line-height: 1.4;
+
+ }
+
+
+
.footer-btns {
display: flex;
--
Gitblit v1.9.3