From 3682ad63b5bdb47228325dea1efe2bb9069254a5 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 11 五月 2026 15:53:18 +0800
Subject: [PATCH] 合格出库扫销售二维码进行发货
---
src/pages/inventoryManagement/scanOut/scanOut.fields.ts | 2
src/pages/sales/salesAccount/goOut.vue | 570 +++++++++++++++++++++++++++++
src/pages/inventoryManagement/scanOut/index.vue | 128 ++++++
src/pages/sales/salesAccount/index.vue | 181 ---------
src/pages/sales/salesAccount/out.vue | 5
src/utils/salesLedgerShip.js | 209 +++++++++++
6 files changed, 917 insertions(+), 178 deletions(-)
diff --git a/src/pages/inventoryManagement/scanOut/index.vue b/src/pages/inventoryManagement/scanOut/index.vue
index 8359451..69b9d07 100644
--- a/src/pages/inventoryManagement/scanOut/index.vue
+++ b/src/pages/inventoryManagement/scanOut/index.vue
@@ -28,7 +28,7 @@
<text class="module-label">鍚堟牸鍑哄簱</text>
- <text class="module-desc">鎵弿鍚堟牸鍝佽繘琛岄鐢ㄥ嚭搴�</text>
+ <text class="module-desc">鎵弿鍚堟牸鍝佽繘琛岄鐢ㄥ嚭搴擄紝閿�鍞壂鐮佸彂璐�</text>
</view>
@@ -225,7 +225,19 @@
@click="cancelForm">杩斿洖</u-button>
- <u-button class="footer-confirm-btn"
+ <u-button v-if="showSalesShipButton"
+
+ class="footer-confirm-btn"
+
+ :loading="submitLoading"
+
+ :disabled="salesShipButtonDisabled"
+
+ @click="handleSalesShipFromScan">鍙戣揣</u-button>
+
+ <u-button v-else
+
+ class="footer-confirm-btn"
:loading="submitLoading"
@@ -247,7 +259,12 @@
import PageHeader from "@/components/PageHeader.vue";
- import { productList as salesProductList } from "@/api/salesManagement/salesLedger";
+ import {
+ productList as salesProductList,
+ getSalesLedgerWithProducts,
+ } from "@/api/salesManagement/salesLedger";
+
+ import { canLedgerShip, executeSalesLedgerShip, getLedgerShippingLabel } from "@/utils/salesLedgerShip";
import modal from "@/plugins/modal";
@@ -281,7 +298,24 @@
/** 浜岀淮鐮佷腑鐨勫彴璐︿富閿� id */
const scanLedgerId = ref(null);
+ /** 鍚堟牸鍑哄簱+閿�鍞爜锛氱敤浜庛�屽彂璐с�嶆寜閽笌鍙拌处绾ф牎楠岋紙涓庨攢鍞彴璐︿竴鑷达級 */
+ const salesLedgerSnapshotForShip = ref(null);
+
const submitLoading = ref(false);
+
+ const showSalesShipButton = computed(
+ () =>
+ showForm.value &&
+ type.value === QUALITY_TYPE.qualified &&
+ contractKind.value === CONTRACT_KIND.sales
+ );
+
+ const salesShipButtonDisabled = computed(() => {
+ if (!showSalesShipButton.value) return false;
+ const snap = salesLedgerSnapshotForShip.value;
+ if (!snap) return false;
+ return !canLedgerShip(snap);
+ });
const submitConfigByScene = createSubmitConfig(scanLedgerId);
@@ -568,6 +602,8 @@
return formatProductStockStatus(item.productStockStatus);
+ if (row.key === "ledgerShippingStatus") return getLedgerShippingLabel(item);
+
if (row.key === "heavyBox") return formatHeavyBox(item.heavyBox);
if (row.key === "remainingQuantity") {
@@ -633,6 +669,8 @@
contractKind.value = CONTRACT_KIND.sales;
scanLedgerId.value = null;
+
+ salesLedgerSnapshotForShip.value = null;
expandedByIndex.value = {};
@@ -724,6 +762,62 @@
modal.closeLoading();
console.error("鎵爜鍑哄簱鎻愪氦澶辫触", e);
+
+ } finally {
+
+ submitLoading.value = false;
+
+ }
+
+ };
+
+ const handleSalesShipFromScan = async () => {
+
+ if (scanLedgerId.value == null || scanLedgerId.value === "") {
+
+ modal.msgError("缂哄皯璁㈠崟淇℃伅锛岃閲嶆柊鎵爜");
+
+ return;
+
+ }
+
+ if (salesLedgerSnapshotForShip.value && !canLedgerShip(salesLedgerSnapshotForShip.value)) return;
+
+ submitLoading.value = true;
+
+ try {
+
+ modal.loading("鍔犺浇涓�...");
+
+ let ledgerRow = salesLedgerSnapshotForShip.value;
+
+ if (!ledgerRow?.id) {
+
+ ledgerRow = await getSalesLedgerWithProducts({ id: scanLedgerId.value, type: 1 });
+
+ }
+
+ modal.closeLoading();
+
+ if (!ledgerRow?.id) {
+
+ modal.msgError("鑾峰彇鍙拌处澶辫触");
+
+ return;
+
+ }
+
+ const { productData: _pd, ...ledgerForShip } = ledgerRow;
+
+ await executeSalesLedgerShip(ledgerForShip);
+
+ } catch (e) {
+
+ modal.closeLoading();
+
+ console.error("鎵爜鍙戣揣澶辫触", e);
+
+ modal.msgError("鑾峰彇鍙拌处澶辫触");
} finally {
@@ -900,9 +994,35 @@
showForm.value = true;
+ if (type.value === QUALITY_TYPE.qualified && kind === CONTRACT_KIND.sales) {
+
+ salesLedgerSnapshotForShip.value = null;
+
+ getSalesLedgerWithProducts({ id: scanData.id, type: 1 })
+
+ .then(res => {
+
+ salesLedgerSnapshotForShip.value = res;
+
+ })
+
+ .catch(() => {
+
+ salesLedgerSnapshotForShip.value = null;
+
+ });
+
+ } else {
+
+ salesLedgerSnapshotForShip.value = null;
+
+ }
+
} else {
scanLedgerId.value = null;
+
+ salesLedgerSnapshotForShip.value = null;
modal.msgError("鏈煡璇㈠埌鏄庣粏鏁版嵁");
@@ -914,6 +1034,8 @@
scanLedgerId.value = null;
+ salesLedgerSnapshotForShip.value = null;
+
console.error("澶勭悊鎵爜缁撴灉澶辫触", error);
modal.msgError("鎵爜澶勭悊澶辫触锛岃閲嶈瘯");
diff --git a/src/pages/inventoryManagement/scanOut/scanOut.fields.ts b/src/pages/inventoryManagement/scanOut/scanOut.fields.ts
index 6aabc56..ea46b12 100644
--- a/src/pages/inventoryManagement/scanOut/scanOut.fields.ts
+++ b/src/pages/inventoryManagement/scanOut/scanOut.fields.ts
@@ -28,6 +28,7 @@
{ label: "閲嶇", key: "heavyBox" },
{ label: "浜у搧鐘舵��", key: "approveStatus" },
{ label: "鍏ュ簱鐘舵��", key: "productStockStatus" },
+ { label: "鍙戣揣鐘舵��", key: "ledgerShippingStatus" },
{ label: "蹇�掑叕鍙�", key: "expressCompany" },
{ label: "蹇�掑崟鍙�", key: "expressNumber" },
{ label: "鍙戣揣杞︾墝", key: "shippingCarNumber" },
@@ -59,6 +60,7 @@
{ label: "鏁伴噺", key: "quantity" },
{ label: "浜у搧鐘舵��", key: "approveStatus" },
{ label: "鍏ュ簱鐘舵��", key: "productStockStatus" },
+ { label: "鍙戣揣鐘舵��", key: "ledgerShippingStatus" },
] as const;
export const summaryFieldRowsPurchase = [
diff --git a/src/pages/sales/salesAccount/goOut.vue b/src/pages/sales/salesAccount/goOut.vue
index 35e2a3f..05e3f90 100644
--- a/src/pages/sales/salesAccount/goOut.vue
+++ b/src/pages/sales/salesAccount/goOut.vue
@@ -20,7 +20,78 @@
@click="showPicker = true"></up-icon>
</template>
</u-form-item>
+ <u-form-item v-if="typeValue === '璐ц溅'"
+ prop="shippingCarNumber"
+ label="杞︾墝鍙�"
+ required>
+ <u-input v-model="form.shippingCarNumber"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+ clearable />
+ </u-form-item>
+ <u-form-item v-if="typeValue === '蹇��'"
+ prop="expressNumber"
+ label="蹇�掑崟鍙�"
+ required>
+ <u-input v-model="form.expressNumber"
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+ clearable />
+ </u-form-item>
</u-form>
+ <!-- 鍙戣揣鍥剧墖锛氱浉鍐屾垨鐩告満銆�/file/upload銆侀瑙堜笌鍒楄〃鏍峰紡 -->
+ <view class="ship-images-card">
+ <view class="ship-images-header">
+ <text class="ship-images-title">鍙戣揣鍥剧墖</text>
+ <text class="ship-images-hint">鏈�澶� {{ uploadConfig.limit }} 寮�</text>
+ </view>
+ <view class="simple-upload-area">
+ <view class="upload-buttons">
+ <u-button type="primary"
+ @click="chooseShipImage"
+ :loading="shipUploading"
+ :disabled="shipFiles.length >= uploadConfig.limit"
+ :customStyle="{ width: '100%' }">
+ <u-icon name="camera"
+ size="18"
+ color="#fff"
+ style="margin-right: 5px;"></u-icon>
+ {{ shipUploading ? '涓婁紶涓�...' : '娣诲姞鍥剧墖' }}
+ </u-button>
+ </view>
+ <view v-if="shipUploading"
+ class="upload-progress">
+ <u-line-progress :percentage="shipUploadProgress"
+ :showText="true"
+ activeColor="#409eff"></u-line-progress>
+ </view>
+ <view v-if="shipFiles.length > 0"
+ class="file-list">
+ <view v-for="(file, index) in shipFiles"
+ :key="file.uid || index"
+ class="file-item">
+ <view class="file-preview-container"
+ @click="previewShipImage(file)">
+ <image :src="getFileAccessUrl(file)"
+ class="file-preview"
+ mode="aspectFill" />
+ <view class="delete-btn"
+ @click.stop="removeShipFile(index)">
+ <u-icon name="close"
+ size="12"
+ color="#fff"></u-icon>
+ </view>
+ </view>
+ <view class="file-info">
+ <text class="file-name">{{ file.bucketFilename || file.name || '鍥剧墖' }}</text>
+ <text class="file-size">{{ formatFileSize(file.size) }}</text>
+ </view>
+ </view>
+ </view>
+ <view v-else
+ class="empty-state">
+ <text>璇蜂粠鐩稿唽閫夋嫨鎴栨媿鐓т笂浼犲彂璐у浘鐗�</text>
+ </view>
+ </view>
+ </view>
<!-- 閫夋嫨鍣ㄥ脊绐� -->
<up-action-sheet :show="showPicker"
:actions="productOptions"
@@ -87,9 +158,11 @@
</template>
<script setup>
- import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
+ import { ref, computed, onMounted, onUnmounted, reactive, toRefs } from "vue";
import PageHeader from "@/components/PageHeader.vue";
import { addShippingInfo } from "@/api/salesManagement/salesLedger";
+ import config from "@/config";
+ import { getToken } from "@/utils/auth";
const showToast = message => {
uni.showToast({
title: message,
@@ -97,6 +170,8 @@
});
};
import { userListNoPageByTenantId } from "@/api/system/user";
+
+ const typeValue = ref("璐ц溅");
const data = reactive({
form: {
@@ -114,9 +189,43 @@
endDate: "",
location: "",
price: "",
+ shippingCarNumber: "",
+ expressNumber: "",
},
rules: {
typeValue: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+ shippingCarNumber: [
+ {
+ validator: (rule, value, callback) => {
+ if (typeValue.value !== "璐ц溅") {
+ callback();
+ return;
+ }
+ if (!value || !String(value).trim()) {
+ callback(new Error("璇疯緭鍏ヨ溅鐗屽彿"));
+ return;
+ }
+ callback();
+ },
+ trigger: ["blur", "change"],
+ },
+ ],
+ expressNumber: [
+ {
+ validator: (rule, value, callback) => {
+ if (typeValue.value !== "蹇��") {
+ callback();
+ return;
+ }
+ if (!value || !String(value).trim()) {
+ callback(new Error("璇疯緭鍏ュ揩閫掑崟鍙�"));
+ return;
+ }
+ callback();
+ },
+ trigger: ["blur", "change"],
+ },
+ ],
},
});
const { form, rules } = toRefs(data);
@@ -138,6 +247,329 @@
const formRef = ref(null);
const approveType = ref(0);
const goOutData = ref({});
+
+ // 涓庤澶囧贰妫� inspectionUpload/index.vue 涓� uploadConfig 涓�鑷�
+ const uploadConfig = {
+ action: "/file/upload",
+ limit: 10,
+ fileSize: 50,
+ fileType: ["jpg", "jpeg", "png", "gif", "webp"],
+ };
+
+ /** 涓庤澶囧贰妫�涓�鑷达細鐢熶骇鍓� type=10 浼犵粰 /file/upload 鐨� formData.type */
+ const shipUploadFormType = 10;
+
+ const uploadFileUrl = computed(() => (config.baseUrl || "").replace(/\/$/, "") + uploadConfig.action);
+
+ const shipFiles = ref([]);
+ const shipUploading = ref(false);
+ const shipUploadProgress = ref(0);
+
+ const isImageFile = file => {
+ if (file?.contentType && String(file.contentType).startsWith("image/")) return true;
+ if (file?.type === "image" || file?.mediaType === "image") return true;
+ const name = file?.bucketFilename || file?.originalFilename || file?.name || "";
+ const ext = name.split(".").pop()?.toLowerCase();
+ return ["jpg", "jpeg", "png", "gif", "webp"].includes(ext);
+ };
+
+ const filePreviewBase = config.fileUrl;
+
+ const normalizeFileUrl = (rawUrl = "") => {
+ let fileUrl = rawUrl || "";
+ if (typeof fileUrl === "string") {
+ fileUrl = fileUrl.trim().replace(/^['"]|['"]$/g, "");
+ }
+ const javaApi = filePreviewBase;
+ const localPrefixes = ["wxfile://", "file://", "content://", "blob:", "data:"];
+
+ if (localPrefixes.some(prefix => fileUrl.startsWith(prefix))) {
+ return fileUrl;
+ }
+
+ if (fileUrl && fileUrl.indexOf("\\") > -1) {
+ const lowerPath = fileUrl.toLowerCase();
+ const uploadPathIndex = lowerPath.indexOf("uploadpath");
+ const prodIndex = lowerPath.indexOf("\\prod\\");
+
+ if (uploadPathIndex > -1) {
+ fileUrl = fileUrl.substring(uploadPathIndex).replace(/\\/g, "/");
+ } else if (prodIndex > -1) {
+ fileUrl = fileUrl
+ .substring(prodIndex + "\\prod\\".length)
+ .replace(/\\/g, "/");
+ } else {
+ fileUrl = fileUrl.replace(/\\/g, "/");
+ }
+ }
+ const normalizedLower = String(fileUrl).toLowerCase();
+ const fileProdIdx = normalizedLower.indexOf("/file/prod/");
+ if (fileProdIdx > -1) {
+ fileUrl = `/profile/prod/${fileUrl.substring(fileProdIdx + "/file/prod/".length)}`;
+ }
+ const fileTempIdx = normalizedLower.indexOf("/file/temp/");
+ if (fileTempIdx > -1) {
+ fileUrl = `/profile/temp/${fileUrl.substring(fileTempIdx + "/file/temp/".length)}`;
+ }
+
+ if (/^\/?uploadPath/i.test(fileUrl)) {
+ fileUrl = fileUrl.replace(/^\/?uploadPath/i, "/profile");
+ }
+
+ if (fileUrl && !fileUrl.startsWith("http")) {
+ if (!fileUrl.startsWith("/")) fileUrl = "/" + fileUrl;
+ fileUrl = javaApi + fileUrl;
+ }
+
+ return fileUrl;
+ };
+
+ const getFileAccessUrl = (file = {}) => {
+ if (file?.link) {
+ if (String(file.link).startsWith("http")) return file.link;
+ return normalizeFileUrl(file.link);
+ }
+ const remoteUrl = normalizeFileUrl(
+ file?.url || file?.downloadUrl || file?.tempPath || ""
+ );
+ if (remoteUrl) return remoteUrl;
+ if (file?._localPreviewUrl) return file._localPreviewUrl;
+ return normalizeFileUrl(file?.tempFilePath || file?.path || "");
+ };
+
+ const formatFileSize = size => {
+ if (!size) return "";
+ if (size < 1024) return size + "B";
+ if (size < 1024 * 1024) return (size / 1024).toFixed(1) + "KB";
+ return (size / (1024 * 1024)).toFixed(1) + "MB";
+ };
+
+ const handleShipUploadError = (message = "涓婁紶鏂囦欢澶辫触") => {
+ shipUploading.value = false;
+ shipUploadProgress.value = 0;
+ uni.showToast({ title: message, icon: "error" });
+ };
+
+ const handleShipUploadSuccess = (res, file) => {
+ const uploadedFile = res.data;
+ if (!uploadedFile) {
+ handleShipUploadError("涓婁紶鍝嶅簲鏁版嵁鏍煎紡閿欒");
+ return;
+ }
+ const fileData = {
+ ...file,
+ id: uploadedFile.id,
+ tempId: uploadedFile.tempId ?? uploadedFile.tempFileId ?? uploadedFile.id,
+ url:
+ uploadedFile.url ||
+ uploadedFile.downloadUrl ||
+ uploadedFile.tempPath ||
+ file.tempFilePath ||
+ file.path,
+ tempPath: uploadedFile.tempPath || file.tempPath || "",
+ _localPreviewUrl: file.tempFilePath || file.path || "",
+ bucketFilename:
+ uploadedFile.bucketFilename ||
+ uploadedFile.originalFilename ||
+ uploadedFile.originalName ||
+ file.name,
+ downloadUrl: uploadedFile.downloadUrl || uploadedFile.url,
+ size: uploadedFile.size || uploadedFile.byteSize || file.size,
+ createTime: uploadedFile.createTime || new Date().getTime(),
+ mediaType: file.type || uploadedFile.mediaType,
+ };
+ shipFiles.value.push(fileData);
+ uni.showToast({ title: "涓婁紶鎴愬姛", icon: "success" });
+ };
+
+ const uploadShipWithUniUploadFile = (file, filePath, token) => {
+ if (!filePath) {
+ handleShipUploadError("鏂囦欢璺緞涓嶅瓨鍦�");
+ return;
+ }
+ shipUploading.value = true;
+ shipUploadProgress.value = 0;
+
+ const uploadTask = uni.uploadFile({
+ url: uploadFileUrl.value,
+ filePath,
+ name: "file",
+ formData: {
+ type: shipUploadFormType,
+ },
+ header: {
+ Authorization: `Bearer ${token}`,
+ },
+ success: res => {
+ try {
+ if (res.statusCode === 200) {
+ const response = JSON.parse(res.data || "{}");
+ if (response.code === 200) {
+ handleShipUploadSuccess(response, file);
+ } else {
+ handleShipUploadError(response.msg || "鏈嶅姟鍣ㄨ繑鍥為敊璇�");
+ }
+ } else {
+ handleShipUploadError(`鏈嶅姟鍣ㄩ敊璇紝鐘舵�佺爜: ${res.statusCode}`);
+ }
+ } catch (e) {
+ console.error("瑙f瀽鍝嶅簲澶辫触:", e);
+ handleShipUploadError("鍝嶅簲鏁版嵁瑙f瀽澶辫触");
+ }
+ },
+ fail: err => {
+ let errorMessage = "涓婁紶澶辫触";
+ if (err.errMsg) {
+ if (err.errMsg.includes("statusCode: null")) {
+ errorMessage = "缃戠粶杩炴帴澶辫触锛岃妫�鏌ョ綉缁滆缃�";
+ } else if (err.errMsg.includes("timeout")) {
+ errorMessage = "涓婁紶瓒呮椂锛岃閲嶈瘯";
+ } else if (err.errMsg.includes("fail")) {
+ errorMessage = "涓婁紶澶辫触锛岃妫�鏌ョ綉缁滆繛鎺�";
+ } else {
+ errorMessage = err.errMsg;
+ }
+ }
+ handleShipUploadError(errorMessage);
+ },
+ complete: () => {
+ shipUploading.value = false;
+ shipUploadProgress.value = 0;
+ },
+ });
+
+ if (uploadTask && uploadTask.onProgressUpdate) {
+ uploadTask.onProgressUpdate(r => {
+ shipUploadProgress.value = r.progress;
+ });
+ }
+ };
+
+ const uploadShipFile = file => {
+ const token = getToken();
+ if (!token) {
+ handleShipUploadError("鐢ㄦ埛鏈櫥褰�");
+ return;
+ }
+ uploadShipWithUniUploadFile(file, file.tempFilePath || file.path || "", token);
+ };
+
+ const handleBeforeShipUpload = async file => {
+ if (uploadConfig.fileType?.length) {
+ const fileName = file.name || "";
+ const fileExtension = fileName ? fileName.split(".").pop().toLowerCase() : "";
+ const expectedTypes = ["jpg", "jpeg", "png", "gif", "webp"];
+ if (fileExtension && expectedTypes.length > 0) {
+ const isAllowed = expectedTypes.some(
+ t => uploadConfig.fileType.includes(t) && t === fileExtension
+ );
+ if (!isAllowed) {
+ uni.showToast({
+ title: `鏂囦欢鏍煎紡涓嶆敮鎸侊紝璇烽�夋嫨 ${expectedTypes.join("/")} 鏍煎紡鐨勫浘鐗嘸,
+ icon: "none",
+ });
+ return false;
+ }
+ }
+ }
+ uploadShipFile(file);
+ return true;
+ };
+
+ const chooseShipImage = () => {
+ if (shipFiles.value.length >= uploadConfig.limit) {
+ uni.showToast({
+ title: `鏈�澶氬彧鑳戒笂浼�${uploadConfig.limit}寮犲浘鐗嘸,
+ icon: "none",
+ });
+ return;
+ }
+
+ const remaining = uploadConfig.limit - shipFiles.value.length;
+
+ if (typeof uni.chooseMedia === "function") {
+ uni.chooseMedia({
+ count: Math.min(remaining, 1),
+ mediaType: ["image"],
+ sizeType: ["compressed", "original"],
+ sourceType: ["album", "camera"],
+ success: res => {
+ try {
+ const files = res?.tempFiles || [];
+ if (!files.length) throw new Error("鏈幏鍙栧埌鏂囦欢");
+ files.forEach((tf, idx) => {
+ const filePath = tf.tempFilePath || tf.path || "";
+ const file = {
+ tempFilePath: filePath,
+ path: filePath,
+ type: "image",
+ name: `image_${Date.now()}_${idx}.jpg`,
+ size: tf.size || 0,
+ createTime: Date.now(),
+ uid: Date.now() + Math.random() + idx,
+ };
+ handleBeforeShipUpload(file);
+ });
+ } catch (e) {
+ console.error("澶勭悊鍥剧墖閫夋嫨缁撴灉澶辫触:", e);
+ uni.showToast({ title: "澶勭悊鏂囦欢澶辫触", icon: "error" });
+ }
+ },
+ fail: () => uni.showToast({ title: "閫夋嫨鍥剧墖澶辫触", icon: "error" }),
+ });
+ return;
+ }
+
+ uni.chooseImage({
+ count: 1,
+ sizeType: ["compressed", "original"],
+ sourceType: ["album", "camera"],
+ success: res => {
+ const tempFilePath = res?.tempFilePaths?.[0];
+ const tempFile = res?.tempFiles?.[0] || {};
+ if (!tempFilePath) return;
+ handleBeforeShipUpload({
+ tempFilePath,
+ path: tempFilePath,
+ type: "image",
+ name: `photo_${Date.now()}.jpg`,
+ size: tempFile.size || 0,
+ createTime: Date.now(),
+ uid: Date.now() + Math.random(),
+ });
+ },
+ fail: () => uni.showToast({ title: "閫夋嫨鍥剧墖澶辫触", icon: "none" }),
+ });
+ };
+
+ const previewShipImage = file => {
+ if (!file || !isImageFile(file)) return;
+ const imageUrls = shipFiles.value
+ .filter(f => isImageFile(f))
+ .map(f => getFileAccessUrl(f))
+ .filter(Boolean);
+ const current = getFileAccessUrl(file);
+ if (!imageUrls.length || !current) return;
+ uni.previewImage({ urls: imageUrls, current });
+ };
+
+ const removeShipFile = index => {
+ uni.showModal({
+ title: "纭鍒犻櫎",
+ content: "纭畾瑕佸垹闄よ繖涓枃浠跺悧锛�",
+ success: res => {
+ if (res.confirm) {
+ shipFiles.value.splice(index, 1);
+ uni.showToast({ title: "鍒犻櫎鎴愬姛", icon: "success" });
+ }
+ },
+ });
+ };
+
+ const getShipTempFileIds = () =>
+ shipFiles.value
+ .map(it => it.tempId ?? it.tempFileId ?? it.id)
+ .filter(v => v !== undefined && v !== null && v !== "");
onMounted(async () => {
try {
userListNoPageByTenantId().then(res => {
@@ -161,11 +593,14 @@
// 绉婚櫎浜嬩欢鐩戝惉
uni.$off("selectContact", handleSelectContact);
});
- const typeValue = ref("璐ц溅");
const onConfirm = item => {
- // 璁剧疆閫変腑鐨勯儴闂�
typeValue.value = item.name;
showPicker.value = false;
+ if (item.name === "璐ц溅") {
+ form.value.expressNumber = "";
+ } else {
+ form.value.shippingCarNumber = "";
+ }
};
const goBack = () => {
@@ -183,6 +618,10 @@
showToast("璇蜂负姣忎釜瀹℃壒姝ラ閫夋嫨瀹℃壒浜�");
return;
}
+ if (shipUploading.value) {
+ showToast("鍥剧墖姝e湪涓婁紶锛岃绋嶅��");
+ return;
+ }
formRef.value
.validate()
.then(valid => {
@@ -198,6 +637,11 @@
salesLedgerProductId: goOutData.value.id,
type: typeValue.value,
approveUserIds,
+ shippingCarNumber:
+ typeValue.value === "璐ц溅" ? String(form.value.shippingCarNumber || "").trim() : "",
+ expressNumber:
+ typeValue.value === "蹇��" ? String(form.value.expressNumber || "").trim() : "",
+ tempFileIds: getShipTempFileIds(),
};
console.log(params, "params");
@@ -273,6 +717,126 @@
<style scoped lang="scss">
@import "@/static/scss/form-common.scss";
+ .ship-images-card {
+ background: #fff;
+ margin: 16px;
+ border-radius: 16px;
+ padding: 16px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+ }
+
+ .ship-images-header {
+ margin-bottom: 12px;
+ }
+
+ .ship-images-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333;
+ display: block;
+ margin-bottom: 4px;
+ }
+
+ .ship-images-hint {
+ font-size: 12px;
+ color: #999;
+ }
+
+ /* 浠ヤ笅涓� inspectionUpload/index.vue 绠�鍖栦笂浼犲尯銆佹枃浠跺垪琛ㄣ�佽棰戝脊绐椾竴鑷� */
+ .simple-upload-area {
+ padding: 0;
+ }
+
+ .upload-buttons {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 15px;
+ }
+
+ .upload-progress {
+ margin-bottom: 12px;
+ }
+
+ .file-list {
+ margin-top: 15px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ }
+
+ .file-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ background: #fff;
+ border-radius: 12px;
+ padding: 8px;
+ border: 1px solid #e9ecef;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+ width: calc(50% - 6px);
+ min-width: 120px;
+ }
+
+ .file-preview-container {
+ position: relative;
+ margin-bottom: 8px;
+ }
+
+ .file-preview {
+ width: 80px;
+ height: 80px;
+ border-radius: 8px;
+ object-fit: cover;
+ border: 2px solid #f0f0f0;
+ }
+
+ .delete-btn {
+ position: absolute;
+ top: -6px;
+ right: -6px;
+ width: 20px;
+ height: 20px;
+ background: #ff4757;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 2px 4px rgba(255, 71, 87, 0.3);
+ }
+
+ .file-info {
+ text-align: center;
+ width: 100%;
+ }
+
+ .file-name {
+ font-size: 12px;
+ color: #333;
+ font-weight: 500;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width: 100px;
+ }
+
+ .file-size {
+ font-size: 10px;
+ color: #999;
+ margin-top: 2px;
+ display: block;
+ }
+
+ .empty-state {
+ text-align: center;
+ padding: 24px 16px;
+ color: #999;
+ font-size: 14px;
+ background: #f8f9fa;
+ border-radius: 8px;
+ border: 2px dashed #ddd;
+ }
+
.approval-process {
background: #fff;
margin: 16px;
diff --git a/src/pages/sales/salesAccount/index.vue b/src/pages/sales/salesAccount/index.vue
index 3834435..2e1b083 100644
--- a/src/pages/sales/salesAccount/index.vue
+++ b/src/pages/sales/salesAccount/index.vue
@@ -137,11 +137,14 @@
<script setup>
import { ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
+ import { ledgerListPage, delLedger, productList } from "@/api/salesManagement/salesLedger";
import {
- ledgerListPage,
- delLedger,
- productList,
- } from "@/api/salesManagement/salesLedger";
+ hasShippedProducts,
+ getLedgerShippingLabel,
+ getLedgerShippingTagType,
+ canLedgerShip,
+ executeSalesLedgerShip,
+ } from "@/utils/salesLedgerShip";
import useUserStore from "@/store/modules/user";
import PageHeader from "@/components/PageHeader.vue";
const userStore = useUserStore();
@@ -161,173 +164,7 @@
// 閿�鍞彴璐︽暟鎹�
const ledgerList = ref([]);
- // 鍒ゆ柇鏄惁瀛樺湪宸插彂璐�/鍙戣揣瀹屾垚鐨勪骇鍝�
- const hasShippedProducts = products => {
- if (!products || products.length === 0) return false;
- return products.some(p => {
- const statusCode = normalizeShippingStatusToCode(p.deliveryStatus ?? p.shippingStatus);
- const statusStr = (p.shippingStatus ?? "").toString().trim();
- // 鏈夊彂璐ф棩鏈�/杞︾墝鍙凤紝鎴栫姸鎬佹槑纭负鈥滃凡鍙戣揣/鍙戣揣瀹屾垚鈥濊涓哄凡鍙戣揣
- return (
- statusCode === 5 ||
- statusStr === "宸插彂璐�" ||
- statusStr === "鍙戣揣瀹屾垚" ||
- statusStr === "宸插畬鎴愬彂璐�" ||
- !!p.shippingDate ||
- !!p.shippingCarNumber
- );
- });
- };
-
- // 鍙拌处鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐э紙涓庡悗绔灇涓惧榻愶紝鍏煎澶氱瀛楁鍚嶏級
- const LEDGER_SHIPPING_LABELS = {
- 1: "鏈彂璐�",
- 2: "瀹℃壒涓�",
- 3: "瀹℃壒涓嶉�氳繃",
- 4: "瀹℃壒閫氳繃",
- 5: "宸插彂璐�",
- };
-
- const normalizeShippingStatusToCode = v => {
- if (v === null || v === undefined || v === "") return 1;
- const n = Number(v);
- if (!Number.isNaN(n) && n >= 1 && n <= 5) return n;
- const s = String(v).trim();
- const textMap = {
- 鏈彂璐�: 1,
- 寰呭彂璐�: 1,
- 瀹℃壒涓�: 2,
- 瀹℃牳涓�: 2,
- 寰呭鏍�: 2,
- 瀹℃壒涓嶉�氳繃: 3,
- 瀹℃牳鎷掔粷: 3,
- 瀹℃壒閫氳繃: 4,
- 瀹℃牳閫氳繃: 4,
- 宸插彂璐�: 5,
- 鍙戣揣瀹屾垚: 5,
- 宸插畬鎴愬彂璐�: 5,
- };
- return textMap[s] ?? 1;
- };
-
- const getLedgerShippingStatusCode = item => {
- if (!item) return 1;
- const raw =
- item.deliveryStatus ??
- item.shippingApprovalStatus ??
- item.shipmentApproveStatus ??
- item.ledgerShippingStatus;
- if (raw !== null && raw !== undefined && raw !== "") {
- return normalizeShippingStatusToCode(raw);
- }
- if (item.shippingStatus !== null && item.shippingStatus !== undefined && item.shippingStatus !== "") {
- return normalizeShippingStatusToCode(item.shippingStatus);
- }
- return 1;
- };
-
- const getLedgerShippingLabel = item =>
- LEDGER_SHIPPING_LABELS[getLedgerShippingStatusCode(item)] ?? "鏈彂璐�";
-
- const getLedgerShippingTagType = item => {
- const t = { 1: "info", 2: "warning", 3: "error", 4: "primary", 5: "success" };
- return t[getLedgerShippingStatusCode(item)] ?? "info";
- };
-
- const canLedgerShip = item => {
- const c = getLedgerShippingStatusCode(item);
- return c === 1 || c === 3;
- };
-
- /**
- * 鍒ゆ柇鏄惁鍙互鍙戣揣
- * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
- * @param row 琛屾暟鎹�
- */
- const canShip = row => {
- if (!row) return false;
-
- // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
- if (row.approveStatus !== 1) return false;
-
- // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
- if (row.shippingDate || row.shippingCarNumber) return false;
-
- // 濡傛灉鍚庣杩斿洖浜嗗彂璐х姸鎬侊紙deliveryStatus锛夛紝宸插彂璐у垯绂佹鍐嶆鍙戣揣
- const deliveryStatus = row.deliveryStatus;
- if (deliveryStatus !== null && deliveryStatus !== undefined && String(deliveryStatus).trim() !== "") {
- const code = normalizeShippingStatusToCode(deliveryStatus);
- if (code === 5) return false;
- }
-
- // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
- const statusStr = row.shippingStatus ? String(row.shippingStatus).trim() : "";
- return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
- };
-
- const productLabel = row => {
- if (!row) return "浜у搧";
- const parts = [row.productCategory, row.floorCode, row.specificationModel].filter(Boolean);
- return parts.length ? parts.join(" / ") : (row.productName || row.goodsName || "浜у搧");
- };
-
- const handleShip = async item => {
- if (!canLedgerShip(item)) {
- uni.showToast({
- title: "浠呮湭鍙戣揣鎴栧鎵逛笉閫氳繃鏃跺彲鍙戣揣",
- icon: "none",
- });
- return;
- }
- if (!item?.id) return;
- showLoadingToast("鍔犺浇涓�...");
- try {
- const res = await productList({ salesLedgerId: item.id, type: 1 });
- const products = res.data || res.records || [];
- closeToast();
- if (!products.length) {
- uni.showToast({
- title: "娌℃湁浜у搧鏁版嵁",
- icon: "none",
- });
- return;
- }
-
- // 鍏堟鏌ユ槸鍚﹀瓨鍦ㄢ�滀笉瓒斥�濈殑浜у搧锛氭湁涓�涓笉瓒冲氨绂佹鍙戣揣骞舵彁绀�
- const insufficient = products.filter(p => p?.approveStatus !== 1);
- if (insufficient.length) {
- const names = insufficient.slice(0, 3).map(productLabel).join("銆�");
- uni.showToast({
- title: `瀛樺湪搴撳瓨涓嶈冻浜у搧锛�${names}${insufficient.length > 3 ? "鈥�" : ""}`,
- icon: "none",
- duration: 2500,
- });
- return;
- }
-
- // 鍏ㄩ儴鍏呰冻鍚庯紝鍐嶇瓫閫夊彲鍙戣揣浜у搧锛堜粎寰呭彂璐�/瀹℃牳鎷掔粷锛�
- const row = products.find(p => canShip(p));
- if (!row) {
- uni.showToast({
- title: "娌℃湁鍙彂璐х殑浜у搧锛堜粎寰呭彂璐�/瀹℃牳鎷掔粷鍙彂璐э級",
- icon: "none",
- duration: 2500,
- });
- return;
- }
-
- uni.setStorageSync("goOutData", JSON.stringify(row));
- uni.navigateTo({
- url: "/pages/sales/salesAccount/goOut",
- });
- } catch (e) {
- closeToast();
- uni.showToast({
- title: "鍔犺浇浜у搧澶辫触",
- icon: "none",
- });
- }
- };
+ const handleShip = item => executeSalesLedgerShip(item);
// 杩斿洖涓婁竴椤�
const goBack = () => {
@@ -374,7 +211,7 @@
if (hasShippedProducts(products)) {
uni.showToast({
- title: "宸插彂璐�/鍙戣揣瀹屾垚鐨勯攢鍞鍗曚笉鑳藉垹闄�",
+ title: "宸插彂璐с�侀儴鍒嗗彂璐ф垨宸叉湁鍙戣揣璁板綍鐨勯攢鍞鍗曚笉鑳藉垹闄�",
icon: "none",
});
return;
diff --git a/src/pages/sales/salesAccount/out.vue b/src/pages/sales/salesAccount/out.vue
index 74affb7..117bd6b 100644
--- a/src/pages/sales/salesAccount/out.vue
+++ b/src/pages/sales/salesAccount/out.vue
@@ -113,6 +113,10 @@
class="detail-value danger">涓嶈冻</text>
</view>
<view class="detail-row">
+ <text class="detail-label">鍙戣揣鐘舵��</text>
+ <text class="detail-value">{{ getLedgerShippingLabel(item) }}</text>
+ </view>
+ <view class="detail-row">
<text class="detail-label">蹇�掑叕鍙�</text>
<text class="detail-value">{{ dv(item.expressCompany) }}</text>
</view>
@@ -166,6 +170,7 @@
<script setup>
import { ref, onMounted } from "vue";
import { productList } from "@/api/salesManagement/salesLedger";
+ import { getLedgerShippingLabel } from "@/utils/salesLedgerShip";
// 瀹㈡埛淇℃伅
const supplierId = ref("");
diff --git a/src/utils/salesLedgerShip.js b/src/utils/salesLedgerShip.js
new file mode 100644
index 0000000..00df9af
--- /dev/null
+++ b/src/utils/salesLedgerShip.js
@@ -0,0 +1,209 @@
+import { productList } from "@/api/salesManagement/salesLedger";
+
+/** 鍙拌处/浜у搧鍙戣揣鐘舵�侊細1-鏈彂璐� 鈥� 5-宸插彂璐� 6-閮ㄥ垎鍙戣揣锛堜笌鍚庣鏋氫妇瀵归綈锛屽吋瀹瑰绉嶅瓧娈靛悕锛� */
+export const LEDGER_SHIPPING_LABELS = {
+ 1: "鏈彂璐�",
+ 2: "瀹℃壒涓�",
+ 3: "瀹℃壒涓嶉�氳繃",
+ 4: "瀹℃壒閫氳繃",
+ 5: "宸插彂璐�",
+ 6: "閮ㄥ垎鍙戣揣",
+};
+
+export const normalizeShippingStatusToCode = v => {
+ if (v === null || v === undefined || v === "") return 1;
+ const n = Number(v);
+ if (!Number.isNaN(n) && n >= 1 && n <= 6) return n;
+ const s = String(v).trim();
+ const textMap = {
+ 鏈彂璐�: 1,
+ 寰呭彂璐�: 1,
+ 瀹℃壒涓�: 2,
+ 瀹℃牳涓�: 2,
+ 寰呭鏍�: 2,
+ 瀹℃壒涓嶉�氳繃: 3,
+ 瀹℃牳鎷掔粷: 3,
+ 瀹℃壒閫氳繃: 4,
+ 瀹℃牳閫氳繃: 4,
+ 宸插彂璐�: 5,
+ 鍙戣揣瀹屾垚: 5,
+ 宸插畬鎴愬彂璐�: 5,
+ 閮ㄥ垎鍙戣揣: 6,
+ 閮ㄥ垎宸插彂璐�: 6,
+ };
+ return textMap[s] ?? 1;
+};
+
+export const getLedgerShippingStatusCode = item => {
+ if (!item) return 1;
+ const raw =
+ item.deliveryStatus ??
+ item.shippingApprovalStatus ??
+ item.shipmentApproveStatus ??
+ item.ledgerShippingStatus;
+ if (raw !== null && raw !== undefined && raw !== "") {
+ return normalizeShippingStatusToCode(raw);
+ }
+ if (item.shippingStatus !== null && item.shippingStatus !== undefined && item.shippingStatus !== "") {
+ return normalizeShippingStatusToCode(item.shippingStatus);
+ }
+ return 1;
+};
+
+export const getLedgerShippingLabel = item =>
+ LEDGER_SHIPPING_LABELS[getLedgerShippingStatusCode(item)] ?? "鏈彂璐�";
+
+export const getLedgerShippingTagType = item => {
+ const t = {
+ 1: "info",
+ 2: "warning",
+ 3: "error",
+ 4: "primary",
+ 5: "success",
+ 6: "warning",
+ };
+ return t[getLedgerShippingStatusCode(item)] ?? "info";
+};
+
+/** 鍙拌处绾ф槸鍚﹀厑璁稿彂璧�/缁х画鍙戣揣锛堝惈閮ㄥ垎鍙戣揣鍚庣户缁彂鍓╀綑锛� */
+export const canLedgerShip = item => {
+ const c = getLedgerShippingStatusCode(item);
+ return c === 1 || c === 3 || c === 6;
+};
+
+/** productStockStatus锛�0 鏈嚭搴� 鈥� 涓嶅厑璁稿彂璐э紙涓庝笟鍔$灞曠ず涓�鑷达級 */
+export const isProductStockStatusUnOutbound = row => {
+ if (!row) return false;
+ const v = row.productStockStatus;
+ return v === 0 || v === "0";
+};
+
+/**
+ * 鍗曡浜у搧鏄惁鍏佽杩涘叆鍙戣揣椤碉紙鍏呰冻 + 闈炴湭鍑哄簱锛涘緟鍙戣揣/瀹℃牳鎷掔粷/閮ㄥ垎鍙戣揣鍙户缁級
+ * 閮ㄥ垎鍙戣揣琛屽彲鑳藉凡鏈� shippingDate/杞︾墝锛屼粛鍏佽鍐嶆鍙戣揣
+ */
+export const canShipProductRow = row => {
+ if (!row) return false;
+ if (isProductStockStatusUnOutbound(row)) return false;
+ if (row.approveStatus !== 1) return false;
+
+ const statusStr = row.shippingStatus ? String(row.shippingStatus).trim() : "";
+ let rowCode = 1;
+ if (row.deliveryStatus !== null && row.deliveryStatus !== undefined && String(row.deliveryStatus).trim() !== "") {
+ rowCode = normalizeShippingStatusToCode(row.deliveryStatus);
+ } else if (statusStr) {
+ rowCode = normalizeShippingStatusToCode(statusStr);
+ }
+
+ if (rowCode === 5) return false;
+
+ const isPartialRow = rowCode === 6 || statusStr === "閮ㄥ垎鍙戣揣" || statusStr === "閮ㄥ垎宸插彂璐�";
+ if ((row.shippingDate || row.shippingCarNumber) && !isPartialRow) return false;
+
+ if (row.deliveryStatus !== null && row.deliveryStatus !== undefined && String(row.deliveryStatus).trim() !== "") {
+ const code = normalizeShippingStatusToCode(row.deliveryStatus);
+ if (code === 5) return false;
+ }
+
+ return (
+ statusStr === "寰呭彂璐�" ||
+ statusStr === "瀹℃牳鎷掔粷" ||
+ statusStr === "閮ㄥ垎鍙戣揣" ||
+ statusStr === "閮ㄥ垎宸插彂璐�" ||
+ rowCode === 6
+ );
+};
+
+export const productLabelForShip = row => {
+ if (!row) return "浜у搧";
+ const parts = [row.productCategory, row.floorCode, row.specificationModel].filter(Boolean);
+ return parts.length ? parts.join(" / ") : row.productName || row.goodsName || "浜у搧";
+};
+
+/** 鍒ゆ柇鏄惁瀛樺湪宸插彂璐с�侀儴鍒嗗彂璐ф垨宸叉湁鍙戣揣鐥曡抗鐨勪骇鍝侊紙鍒犻櫎鍙拌处绛夊満鏅級 */
+export const hasShippedProducts = products => {
+ if (!products || products.length === 0) return false;
+ return products.some(p => {
+ const statusCode = normalizeShippingStatusToCode(p.deliveryStatus ?? p.shippingStatus);
+ const statusStr = (p.shippingStatus ?? "").toString().trim();
+ return (
+ statusCode === 5 ||
+ statusCode === 6 ||
+ statusStr === "宸插彂璐�" ||
+ statusStr === "鍙戣揣瀹屾垚" ||
+ statusStr === "宸插畬鎴愬彂璐�" ||
+ statusStr === "閮ㄥ垎鍙戣揣" ||
+ statusStr === "閮ㄥ垎宸插彂璐�" ||
+ !!p.shippingDate ||
+ !!p.shippingCarNumber
+ );
+ });
+};
+
+const showLoadingToast = message => {
+ uni.showLoading({ title: message, mask: true });
+};
+const closeToast = () => {
+ uni.hideLoading();
+};
+
+/**
+ * 涓庨攢鍞彴璐︺�屽彂璐с�嶆寜閽竴鑷达細鏍¢獙鍙拌处鐘舵�� 鈫� 鎷変骇鍝� 鈫� 鏍¢獙搴撳瓨涓庡彲鍙戣揣琛� 鈫� 璺宠浆 goOut
+ * @param {Record<string, any>} ledgerItem 鑷冲皯鍚� id锛涘惈鍙戣揣瀹℃壒瀛楁鏃跺厛鍋� canLedgerShip 鏍¢獙
+ */
+export async function executeSalesLedgerShip(ledgerItem) {
+ if (!canLedgerShip(ledgerItem)) {
+ uni.showToast({
+ title: "浠呮湭鍙戣揣銆佸鎵逛笉閫氳繃鎴栭儴鍒嗗彂璐ф椂鍙户缁彂璐�",
+ icon: "none",
+ });
+ return;
+ }
+ if (!ledgerItem?.id) return;
+ showLoadingToast("鍔犺浇涓�...");
+ try {
+ const res = await productList({ salesLedgerId: ledgerItem.id, type: 1 });
+ const products = res.data || res.records || [];
+ closeToast();
+ if (!products.length) {
+ uni.showToast({ title: "娌℃湁浜у搧鏁版嵁", icon: "none" });
+ return;
+ }
+ const insufficient = products.filter(p => p?.approveStatus !== 1);
+ if (insufficient.length) {
+ const names = insufficient.slice(0, 3).map(productLabelForShip).join("銆�");
+ uni.showToast({
+ title: `瀛樺湪搴撳瓨涓嶈冻浜у搧锛�${names}${insufficient.length > 3 ? "鈥�" : ""}`,
+ icon: "none",
+ duration: 2500,
+ });
+ return;
+ }
+ const unOutbound = products.filter(p => isProductStockStatusUnOutbound(p));
+ if (unOutbound.length) {
+ const names = unOutbound.slice(0, 3).map(productLabelForShip).join("銆�");
+ uni.showToast({
+ title: `瀛樺湪鏈嚭搴撲骇鍝侊紝涓嶈兘鍙戣揣锛�${names}${unOutbound.length > 3 ? "鈥�" : ""}`,
+ icon: "none",
+ duration: 2500,
+ });
+ return;
+ }
+ const row = products.find(p => canShipProductRow(p));
+ if (!row) {
+ uni.showToast({
+ title: "娌℃湁鍙彂璐х殑浜у搧锛堝緟鍙戣揣銆佸鏍告嫆缁濇垨閮ㄥ垎鍙戣揣鍙户缁級",
+ icon: "none",
+ duration: 2500,
+ });
+ return;
+ }
+ uni.setStorageSync("goOutData", JSON.stringify(row));
+ uni.navigateTo({
+ url: "/pages/sales/salesAccount/goOut",
+ });
+ } catch (e) {
+ closeToast();
+ uni.showToast({ title: "鍔犺浇浜у搧澶辫触", icon: "none" });
+ }
+}
--
Gitblit v1.9.3