feat(freight): shop freight templates, server-side checkout fees, company dictionary (add-freight-templates)

This commit is contained in:
Chengdong Zhang
2026-09-24 15:03:51 +08:00
parent 5b426486ac
commit 473d19d089
44 changed files with 2409 additions and 67 deletions
+17 -1
View File
@@ -1,10 +1,11 @@
<script setup lang="ts">
import { t as localized } from "@vmall/shared";
import type { Category, Product, ProductUpsertBody } from "@vmall/shared";
import type { Category, FreightTemplate, Product, ProductUpsertBody } from "@vmall/shared";
const props = defineProps<{
product?: Product;
categories: Category[];
freightTemplates: FreightTemplate[];
busy?: boolean;
}>();
const emit = defineEmits<{ submit: [body: ProductUpsertBody] }>();
@@ -16,6 +17,7 @@ const nameZh = ref("");
const descriptionEn = ref("");
const descriptionZh = ref("");
const categoryId = ref("");
const freightTemplateId = ref("");
const images = ref("");
const validationError = ref("");
@@ -26,6 +28,7 @@ function resetFromProduct(product: Product | undefined): void {
descriptionEn.value = product?.description.en ?? "";
descriptionZh.value = product?.description.zh ?? "";
categoryId.value = product?.category_id ?? "";
freightTemplateId.value = product?.freight_template_id ?? "";
images.value = product?.images.join("\n") ?? "";
validationError.value = "";
}
@@ -45,6 +48,7 @@ function submit(): void {
validationError.value = "";
const body: ProductUpsertBody = {
category_id: categoryId.value || null,
freight_template_id: freightTemplateId.value || null,
slug: cleanSlug,
name: { en: nameEn.value.trim(), zh: nameZh.value.trim() },
description: { en: descriptionEn.value.trim(), zh: descriptionZh.value.trim() },
@@ -100,6 +104,18 @@ function submit(): void {
</option>
</select>
</VField>
<VField :label="$t('shop.freightTemplate')">
<select
id="product-freight-template"
v-model="freightTemplateId"
class="border-border bg-surface text-text focus:border-primary focus:outline-primary/30 w-full rounded-md border px-3 py-2 text-sm focus:outline-2"
>
<option value="">{{ $t("shop.freightTemplateDefault") }}</option>
<option v-for="template in freightTemplates" :key="template.id" :value="template.id">
{{ template.name }}
</option>
</select>
</VField>
<VField :label="$t('product.images')">
<textarea
id="product-images"