support split unit for product order

This commit is contained in:
Timi
2026-09-09 10:50:53 +08:00
parent 07205f869b
commit f91fb530a4
10 changed files with 384 additions and 81 deletions
+16 -17
View File
@@ -129,23 +129,23 @@
<div class="content">
<div class="metric">
<strong v-text="getPackageQuantityText(item.quantity)" />
<span>总数</span>
<span>订单数量</span>
</div>
<div class="metric">
<strong :class="getAvailableQuantityClass(item)" v-text="getPackageQuantityText(item.availableQuantity)" />
<span>可履约</span>
<strong :class="getAvailableQuantityClass(item)" v-text="getPackageQuantityText(item.availableBaseQuantity)" />
<span>可履约(基础)</span>
</div>
<div class="metric">
<strong v-text="getPackageQuantityText(item.pendingQuantity)" />
<span>待核销</span>
<strong v-text="getPackageQuantityText(item.pendingBaseQuantity)" />
<span>待核销(基础)</span>
</div>
<div class="metric">
<strong :class="getFulfilledQuantityClass(item)" v-text="getPackageQuantityText(item.fulfilledQuantity)" />
<span>已履约</span>
<strong :class="getFulfilledQuantityClass(item)" v-text="getPackageQuantityText(item.fulfilledBaseQuantity)" />
<span>已履约(基础)</span>
</div>
<div class="metric">
<strong :class="getRemainingQuantityClass(item)" v-text="getPackageQuantityText(item.remainingQuantity)" />
<span>剩余</span>
<strong :class="getRemainingQuantityClass(item)" v-text="getPackageQuantityText(item.remainingBaseQuantity)" />
<span>剩余(基础)</span>
</div>
</div>
</div>
@@ -242,7 +242,7 @@ import {
getStatusTheme
} from "@/utils/salesOrder";
import { Message } from "@/utils/message";
import { permissionCodes } from "@/utils/permission";
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
import { uploadPhotoList } from "@/utils/photo";
defineOptions({ name: "SalesOrderDetail" });
@@ -261,12 +261,11 @@ const canReadFund = computed(() => userStore.hasPermissions(permissionCodes.fund
const canReadMyReceive = computed(() => userStore.hasPermissions(permissionCodes.fundReceive.create));
const canUpdate = computed(() => userStore.hasPermissions(permissionCodes.salesOrder.update));
const canCreateFulfillment = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create));
const canOperateStock = computed(() => userStore.hasPermissions(permissionCodes.productStock.create));
const canReceive = computed(() => !!order.value && order.value.status !== "CANCELLED" && order.value.paymentStatus !== "PAID" && userStore.hasPermissions(permissionCodes.fundReceive.create));
const canRefund = computed(() => !!order.value && order.value.status === "CANCELLED" && order.value.refundStatus === "PENDING" && userStore.hasPermissions(permissionCodes.fund.refund));
const canConfirmNoRefund = computed(() => !!order.value && order.value.status === "CANCELLED" && order.value.refundStatus === "PENDING" && userStore.hasPermissions(permissionCodes.fund.refund));
const canCancel = computed(() => !!order.value && order.value.status === "ACTIVE" && !hasPendingFulfillment.value && userStore.hasPermissions(permissionCodes.salesOrder.cancel));
const canFulfillByPayment = computed(() => order.value?.paymentStatus === "PAID" || (order.value?.paymentStatus === "PARTIALLY_PAID" && canOperateStock.value));
const canFulfillByPayment = computed(() => order.value?.paymentStatus === "PAID" || userStore.hasRoles(gaoRoleCodes.storeManager));
const photoURLList = computed(() => photoItems.value.map(item => item.url));
function toPhotoItems(attachmentList?: readonly Partial<Attachment>[]): PhotoItem[] {
@@ -312,20 +311,20 @@ function getRemainingAmountClass(amount?: number | null): "green" | "red" | "gra
}
function getAvailableQuantityClass(item: GaoSalesOrderItem): "green" | "orange" {
return Number(item.availableQuantity || 0) === 0 ? "green" : "orange";
return Number(item.availableBaseQuantity || 0) === 0 ? "green" : "orange";
}
function getFulfilledQuantityClass(item: GaoSalesOrderItem): "green" | "orange" {
return Number(item.remainingQuantity || 0) === 0 ? "green" : "orange";
return Number(item.remainingBaseQuantity || 0) === 0 ? "green" : "orange";
}
function getRemainingQuantityClass(item: GaoSalesOrderItem): "green" | "orange" {
return Number(item.remainingQuantity || 0) === 0 ? "green" : "orange";
return Number(item.remainingBaseQuantity || 0) === 0 ? "green" : "orange";
}
function getItemFulfillmentStatus(item: GaoSalesOrderItem): { text: string; theme: "success" | "warning" | "danger" } {
const fulfilledQuantity = Number(item.fulfilledQuantity || 0);
const remainingQuantity = Number(item.remainingQuantity || 0);
const fulfilledQuantity = Number(item.fulfilledBaseQuantity || 0);
const remainingQuantity = Number(item.remainingBaseQuantity || 0);
if (0 < fulfilledQuantity && remainingQuantity === 0) {
return { text: "已完成", theme: "success" };
}
+3 -3
View File
@@ -48,7 +48,7 @@
:order="item"
:can-receive="canReceive"
:can-fulfill="canCreateFulfillment"
:can-operate-stock="canOperateStock"
:can-store-manager="canStoreManager"
v-entrance-transition="index * 30"
@click="toDetail(item)"
@receive="toPayment(item)"
@@ -73,7 +73,7 @@ import { useNavBarStore } from "@/store/navBarStore";
import type { GaoSalesOrderStatus, GaoSalesOrderType, GaoSalesPaymentStatus, GaoSalesRefundStatus, SalesOrder, SalesOrderPage } from "@/types/SalesOrder";
import { getErrorMessage } from "@/utils/error";
import { Message } from "@/utils/message";
import { permissionCodes } from "@/utils/permission";
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
defineOptions({ name: "SalesOrderList" });
const route = useRoute();
@@ -84,7 +84,7 @@ const canCreate = computed(() => userStore.hasPermissions(permissionCodes.salesO
const canCreatePackageOrder = computed(() => userStore.hasPermissions(permissionCodes.customerPackage.create));
const canReceive = computed(() => userStore.hasPermissions(permissionCodes.fundReceive.create));
const canCreateFulfillment = computed(() => userStore.hasPermissions(permissionCodes.orderFulfillment.create));
const canOperateStock = computed(() => userStore.hasPermissions(permissionCodes.productStock.create));
const canStoreManager = computed(() => userStore.hasRoles(gaoRoleCodes.storeManager));
const actions = computed(() => [
...(canCreate.value ? [{
key: "create",
@@ -100,7 +100,7 @@ const props = defineProps<{
order: SalesOrder;
canReceive: boolean;
canFulfill: boolean;
canOperateStock: boolean;
canStoreManager: boolean;
}>();
const emit = defineEmits<{
click: [];
@@ -113,10 +113,10 @@ const avatarText = computed(() => customerName.value.slice(0, 1) || "客");
const photoURL = computed(() => getCustomerPhotoURL(props.order.customer, 64));
const orderNoText = computed(() => `订单号:${props.order.orderNo || props.order.id || "未知"}`);
const totalProductQuantity = computed(() => sumProductQuantity("quantity"));
const fulfilledProductQuantity = computed(() => sumProductQuantity("fulfilledQuantity"));
const productSummaryText = computed(() => `共 ${itemList.value.length} 项 · 总数量 ${totalProductQuantity.value} · 已履约 ${fulfilledProductQuantity.value}`);
const fulfilledProductQuantity = computed(() => sumProductQuantity("fulfilledBaseQuantity"));
const productSummaryText = computed(() => `共 ${itemList.value.length} 项 · 订单数量 ${totalProductQuantity.value} · 已履约(基础)${fulfilledProductQuantity.value}`);
const showReceiveAction = computed(() => props.canReceive && props.order.status !== "CANCELLED" && props.order.paymentStatus !== "PAID");
const canFulfillByPayment = computed(() => props.order.paymentStatus === "PAID" || (props.order.paymentStatus === "PARTIALLY_PAID" && props.canOperateStock));
const canFulfillByPayment = computed(() => props.order.paymentStatus === "PAID" || props.canStoreManager);
const showFulfillAction = computed(() => props.canFulfill && canFulfillByPayment.value && props.order.status === "ACTIVE");
function getPaymentStatusTheme(status?: GaoSalesPaymentStatus): "success" | "warning" | "danger" | "default" {
@@ -132,7 +132,7 @@ function getPaymentStatusTheme(status?: GaoSalesPaymentStatus): "success" | "war
return "default";
}
function sumProductQuantity(field: "quantity" | "fulfilledQuantity"): string {
function sumProductQuantity(field: "quantity" | "fulfilledBaseQuantity"): string {
let total = 0;
for (const item of itemList.value) {
const quantity = Number(item[field] || 0);