add product

This commit is contained in:
Timi
2026-09-03 14:27:40 +08:00
parent 7f669621fb
commit 333999fe21
63 changed files with 5662 additions and 2210 deletions
+43 -14
View File
@@ -36,12 +36,15 @@
label-width="6rem"
>
<div class="header">
<t-input v-model="item.productName" borderless placeholder="产品名称" />
<strong v-text="item.productNameSnapshot || '未选择产品'" />
<t-button theme="danger" variant="text" size="small" @click="removeItem(index)">删除</t-button>
</div>
<t-form-item label="单位" required-mark>
<t-input v-model.trim="item.unit" borderless placeholder="例如 盒、次" />
</t-form-item>
<product-selector
:model-value="item.productId && item.productUnitId ? {productId: item.productId, productUnitId: item.productUnitId} : undefined"
label="产品单位"
required-mark
@update:model-value="applyProduct(index, $event)"
/>
<t-form-item label="默认配额" required-mark>
<t-input v-model.trim="item.defaultQuantity" type="number" borderless />
</t-form-item>
@@ -79,13 +82,15 @@ import PackageAPI from "@/api/PackageAPI";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { useNavBarStore } from "@/store/navBarStore";
import type { GaoPackageConfig, PackageConfigItem, PackageConfigStatus } from "@/types/Package";
import ProductAPI from "@/api/ProductAPI";
import type { Product } from "@/types/Product";
import { getErrorMessage } from "@/utils/error";
import { formatPackageAmountInput, getPackageConfigStatusText, normalizePackageQuantity, parsePackageAmount } from "@/utils/package";
import { Message } from "@/utils/message";
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
type PickerValue = string | number;
type PackageConfigFormItem = PackageConfigItem & { clientKey: string };
type PackageConfigFormItem = Partial<PackageConfigItem> & { clientKey: string };
defineOptions({ name: "PackageConfigEdit" });
@@ -132,13 +137,29 @@ function createItem(item?: Partial<PackageConfigItem>): PackageConfigFormItem {
return {
...item,
clientKey: window.crypto.randomUUID(),
productName: item?.productName || "",
unit: item?.unit || "",
defaultQuantity: item?.defaultQuantity ?? "",
remark: item?.remark || ""
};
}
const productCache = new Map<string, Product>();
async function applyProduct(index: number, value?: { productId: string; productUnitId: string }): Promise<void> {
if (!value) {
return;
}
const product = productCache.get(value.productId) || await ProductAPI.detail(value.productId);
productCache.set(value.productId, product);
const unit = product.unitList?.find(item => item.id === value.productUnitId);
Object.assign(form.itemList[index], {
productId: value.productId,
productUnitId: value.productUnitId,
productNameSnapshot: product.name,
unitSnapshot: unit?.name || "",
baseQuantityPerUnitSnapshot: unit?.baseQuantityPerUnit
});
}
function addItem(): void {
form.itemList.push(createItem());
}
@@ -224,10 +245,10 @@ function validateForm(): boolean {
}
const keySet = new Set<string>();
for (const item of form.itemList) {
const quantity = normalizePackageQuantity(item.defaultQuantity);
const key = `${item.productName.trim()}\u0000${item.unit.trim()}`;
if (!item.productName.trim() || !item.unit.trim() || !quantity || quantity === "0") {
Message.warning("产品名称、单位和正数量不能为空");
const quantity = normalizePackageQuantity(item.defaultQuantity ?? "");
const key = `${item.productId}\u0000${item.productUnitId}`;
if (!item.productId || !item.productUnitId || !quantity || quantity === "0") {
Message.warning("产品单位和正数量不能为空");
return false;
}
if (keySet.has(key)) {
@@ -261,9 +282,9 @@ async function save(): Promise<void> {
beginAt: form.beginAt ?? null,
endAt: form.endAt ?? null,
itemList: form.itemList.map((item, index) => ({
productName: item.productName.trim(),
unit: item.unit.trim(),
defaultQuantity: normalizePackageQuantity(item.defaultQuantity)!,
productId: item.productId!,
productUnitId: item.productUnitId!,
defaultQuantity: normalizePackageQuantity(item.defaultQuantity ?? "")!,
sort: index,
remark: item.remark?.trim() || null
}))
@@ -337,6 +358,14 @@ onUnmounted(() => navBarStore.clearRight());
padding: calc(var(--app-nav-height) + 1rem) 0 calc(1rem + env(safe-area-inset-bottom, 0));
flex-direction: column;
.form {
margin: 0 1rem;
background: var(--td-bg-color-container);
box-shadow: var(--td-shadow-1);
border-radius: 1rem;
overflow: hidden;
}
.items {
padding: 1rem 0;