diff --git a/lib/app-error.ts b/lib/app-error.ts index 2591e3e..8592bfb 100644 --- a/lib/app-error.ts +++ b/lib/app-error.ts @@ -95,6 +95,22 @@ export function toAppError(error: unknown, fallback?: AppErrorOptions) { return error; } + // Prisma 唯一约束冲突 + if (error instanceof Error && (error as any).code === "P2002") { + return conflictError("数据已存在,请检查是否重复", "UNIQUE_CONSTRAINT"); + } + + // Telefunc 重新包装错误后 instanceof 失效,通过 name 识别 + if (error instanceof Error && error.name === "AppError") { + const e = error as AppError; + return new AppError(e.message, { + code: e.code, + statusCode: e.statusCode, + expose: e.expose, + cause: e.cause, + }); + } + const abortValue = getTelefuncAbortValue(error); if (abortValue?.message && typeof abortValue.message === "string") { return new AppError(abortValue.message, { @@ -117,6 +133,7 @@ export function toAppError(error: unknown, fallback?: AppErrorOptions) { } export function normalizeTelefuncError(error: unknown, fallbackMessage: string) { + const abortValue = getTelefuncAbortValue(error); if (abortValue?.message && typeof abortValue.message === "string") { return abortValue.message; diff --git a/modules/catalog/service.ts b/modules/catalog/service.ts index fa1c0e1..1cf188a 100644 --- a/modules/catalog/service.ts +++ b/modules/catalog/service.ts @@ -51,13 +51,19 @@ export async function saveCategory(input: { throw badRequestError("分类 slug 不能为空", "CATEGORY_SLUG_REQUIRED"); } - const record = await upsertCategoryRecord(prisma, { - id: input.id, - name, - slug, - description: input.description?.trim() || null, - sort: Number.isFinite(input.sort) ? Number(input.sort) : 0, - }); + let record; + try { + record = await upsertCategoryRecord(prisma, { + id: input.id, + name, + slug, + description: input.description?.trim() || null, + sort: Number.isFinite(input.sort) ? Number(input.sort) : 0, + }); + } catch (e: any) { + if (e?.code === "P2002") throw conflictError("分类名称或 Slug 已存在,请换一个", "CATEGORY_SLUG_CONFLICT"); + throw e; + } await logAdminOperation( { diff --git a/pages/+Layout.vue b/pages/+Layout.vue index 7a5344e..972c880 100644 --- a/pages/+Layout.vue +++ b/pages/+Layout.vue @@ -40,7 +40,12 @@ {{ footerText ? footerText : "© 2026 designed" }} & developed by edgeKey - +
+ +
{{ supportContact }}
+ diff --git a/pages/admin/categories/+Page.vue b/pages/admin/categories/+Page.vue index 8f87c1f..bb3bf20 100644 --- a/pages/admin/categories/+Page.vue +++ b/pages/admin/categories/+Page.vue @@ -1,12 +1,9 @@管理前台商品分类、排序和启用状态。
-管理前台商品分类、排序和启用状态。
| ID | -名称 | -Slug | -排序 | -状态 | -- |
|---|---|---|---|---|---|
| 当前还没有分类,先创建第一条。 | -|||||
| {{ category.id }} | -
- {{ category.name }}
- {{ category.description }}
- |
- {{ category.slug }} | -{{ category.sort }} | -
- |
-
-
-
- |
-
| ID | -商品 | -分类 | -价格 | -限购 | -状态 | -- |
|---|---|---|---|---|---|---|
| 当前还没有商品,请先创建第一个商品。 | -||||||
| {{ product.id }} | -
- {{ product.name }}
- {{ product.slug }}
- |
- {{ product.categoryName || "未分类" }} | -{{ formatCents(product.price) }} | -{{ product.minBuy }} - {{ product.maxBuy }} | -
- |
-
-
-
- |
-