style(project): format product detail split modules

This commit is contained in:
2026-02-22 10:14:04 +08:00
parent d6e5138e53
commit 37b3ef693d
5 changed files with 60 additions and 34 deletions

View File

@@ -69,7 +69,7 @@ function ensureProductDetailRoute(
path: PRODUCT_DETAIL_PATH, path: PRODUCT_DETAIL_PATH,
component: '/views/product/detail/index.vue', component: '/views/product/detail/index.vue',
meta: { meta: {
...(listMeta ?? {}), ...listMeta,
title: '商品详情', title: '商品详情',
hideInMenu: true, hideInMenu: true,
}, },

View File

@@ -1,13 +1,13 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import type { ProductDetailFormState } from '../../types';
import type { ProductPickerItemDto } from '#/api/product'; import type { ProductPickerItemDto } from '#/api/product';
import { computed } from 'vue'; import { computed } from 'vue';
import { searchProductPickerApi } from '#/api/product'; import { searchProductPickerApi } from '#/api/product';
import type { ProductDetailFormState } from '../../types';
interface CreateProductDetailComboActionsOptions { interface CreateProductDetailComboActionsOptions {
comboPickerCurrentGroupIndex: Ref<number>; comboPickerCurrentGroupIndex: Ref<number>;
comboPickerKeyword: Ref<string>; comboPickerKeyword: Ref<string>;
@@ -51,7 +51,9 @@ export function createProductDetailComboActions(
function removeComboGroup(groupIndex: number) { function removeComboGroup(groupIndex: number) {
if (groupIndex < 0 || groupIndex >= form.comboGroups.length) return; if (groupIndex < 0 || groupIndex >= form.comboGroups.length) return;
form.comboGroups = form.comboGroups.filter((_, index) => index !== groupIndex); form.comboGroups = form.comboGroups.filter(
(_, index) => index !== groupIndex,
);
form.comboGroups.forEach((group, index) => { form.comboGroups.forEach((group, index) => {
group.sortOrder = index + 1; group.sortOrder = index + 1;
}); });
@@ -90,7 +92,11 @@ export function createProductDetailComboActions(
} }
} }
function setComboItemQuantity(groupIndex: number, itemIndex: number, value: number) { function setComboItemQuantity(
groupIndex: number,
itemIndex: number,
value: number,
) {
const group = form.comboGroups[groupIndex]; const group = form.comboGroups[groupIndex];
if (!group) return; if (!group) return;
const item = group.items[itemIndex]; const item = group.items[itemIndex];
@@ -117,7 +123,9 @@ export function createProductDetailComboActions(
keyword: comboPickerKeyword.value.trim() || undefined, keyword: comboPickerKeyword.value.trim() || undefined,
limit: 100, limit: 100,
}); });
comboPickerProducts.value = products.filter((item) => item.id !== form.id); comboPickerProducts.value = products.filter(
(item) => item.id !== form.id,
);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
comboPickerProducts.value = []; comboPickerProducts.value = [];
@@ -153,7 +161,9 @@ export function createProductDetailComboActions(
return; return;
} }
const currentItemMap = new Map(group.items.map((item) => [item.productId, item])); const currentItemMap = new Map(
group.items.map((item) => [item.productId, item]),
);
const selectedProducts = comboPickerSelectedProducts.value; const selectedProducts = comboPickerSelectedProducts.value;
group.items = selectedProducts.map((product, index) => { group.items = selectedProducts.map((product, index) => {

View File

@@ -1,6 +1,11 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import type { Router } from 'vue-router'; import type { Router } from 'vue-router';
import type {
ProductDetailCategoryOption,
ProductDetailFormState,
} from '../../types';
import type { import type {
ProductAddonGroupDto, ProductAddonGroupDto,
ProductDetailDto, ProductDetailDto,
@@ -22,11 +27,6 @@ import {
saveProductApi, saveProductApi,
} from '#/api/product'; } from '#/api/product';
import type {
ProductDetailCategoryOption,
ProductDetailFormState,
} from '../../types';
import { DEFAULT_PRODUCT_DETAIL_FORM } from './constants'; import { DEFAULT_PRODUCT_DETAIL_FORM } from './constants';
import { import {
buildLocalSkuCode, buildLocalSkuCode,
@@ -91,10 +91,10 @@ export function createProductDetailDataActions(
form.description = data.description; form.description = data.description;
form.sortWeight = Math.max(0, Number(data.sortWeight || 0)); form.sortWeight = Math.max(0, Number(data.sortWeight || 0));
form.imageUrls = dedupeTextList([...(data.imageUrls || []), data.imageUrl]).slice( form.imageUrls = dedupeTextList([
0, ...(data.imageUrls || []),
5, data.imageUrl,
); ]).slice(0, 5);
form.price = Number(data.price || 0); form.price = Number(data.price || 0);
form.originalPrice = form.originalPrice =
@@ -178,7 +178,9 @@ export function createProductDetailDataActions(
function removeImage(index: number) { function removeImage(index: number) {
if (index < 0 || index >= form.imageUrls.length) return; if (index < 0 || index >= form.imageUrls.length) return;
form.imageUrls = form.imageUrls.filter((_, itemIndex) => itemIndex !== index); form.imageUrls = form.imageUrls.filter(
(_, itemIndex) => itemIndex !== index,
);
} }
function setPrimaryImage(index: number) { function setPrimaryImage(index: number) {
@@ -197,16 +199,18 @@ export function createProductDetailDataActions(
isLoading.value = true; isLoading.value = true;
try { try {
const [detailData, categories, specs, addons, labels] = await Promise.all([ const [detailData, categories, specs, addons, labels] = await Promise.all(
getProductDetailApi({ [
storeId: storeId.value, getProductDetailApi({
productId: productId.value, storeId: storeId.value,
}), productId: productId.value,
getProductCategoryListApi(storeId.value), }),
getProductSpecListApi({ storeId: storeId.value }), getProductCategoryListApi(storeId.value),
getProductAddonGroupListApi({ storeId: storeId.value }), getProductSpecListApi({ storeId: storeId.value }),
getProductLabelListApi({ storeId: storeId.value }), getProductAddonGroupListApi({ storeId: storeId.value }),
]); getProductLabelListApi({ storeId: storeId.value }),
],
);
detail.value = detailData; detail.value = detailData;
categoryOptions.value = categories.map((item) => ({ categoryOptions.value = categories.map((item) => ({
@@ -319,7 +323,10 @@ export function createProductDetailDataActions(
: null, : null,
stock: Math.max(0, Math.floor(Number(item.stock || 0))), stock: Math.max(0, Math.floor(Number(item.stock || 0))),
isEnabled: item.isEnabled, isEnabled: item.isEnabled,
sortOrder: Math.max(1, Math.floor(Number(item.sortOrder || index + 1))), sortOrder: Math.max(
1,
Math.floor(Number(item.sortOrder || index + 1)),
),
attributes: item.attributes.map((attr) => ({ attributes: item.attributes.map((attr) => ({
templateId: attr.templateId, templateId: attr.templateId,
optionId: attr.optionId, optionId: attr.optionId,
@@ -329,8 +336,14 @@ export function createProductDetailDataActions(
form.kind === 'combo' form.kind === 'combo'
? form.comboGroups.map((group, groupIndex) => ({ ? form.comboGroups.map((group, groupIndex) => ({
name: group.name.trim(), name: group.name.trim(),
minSelect: Math.max(1, Math.floor(Number(group.minSelect || 1))), minSelect: Math.max(
maxSelect: Math.max(1, Math.floor(Number(group.maxSelect || 1))), 1,
Math.floor(Number(group.minSelect || 1)),
),
maxSelect: Math.max(
1,
Math.floor(Number(group.maxSelect || 1)),
),
sortOrder: Math.max( sortOrder: Math.max(
1, 1,
Math.floor(Number(group.sortOrder || groupIndex + 1)), Math.floor(Number(group.sortOrder || groupIndex + 1)),

View File

@@ -1,13 +1,13 @@
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import type { ProductSpecDto } from '#/api/product';
import type { import type {
ProductDetailFormState, ProductDetailFormState,
ProductDetailSkuBatchState, ProductDetailSkuBatchState,
ProductDetailSkuRowState, ProductDetailSkuRowState,
} from '../../types'; } from '../../types';
import type { ProductSpecDto } from '#/api/product';
import { import {
buildLocalSkuCode, buildLocalSkuCode,
buildSkuCombinations, buildSkuCombinations,
@@ -42,7 +42,10 @@ export function createProductDetailSkuActions(
); );
} }
function getSkuAttrOptionId(row: ProductDetailSkuRowState, templateId: string) { function getSkuAttrOptionId(
row: ProductDetailSkuRowState,
templateId: string,
) {
return row.attributes.find((item) => item.templateId === templateId) return row.attributes.find((item) => item.templateId === templateId)
?.optionId; ?.optionId;
} }

View File

@@ -15,8 +15,8 @@ import type {
import { computed, reactive, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { DEFAULT_PRODUCT_DETAIL_FORM } from './product-detail-page/constants';
import { createProductDetailComboActions } from './product-detail-page/combo-actions'; import { createProductDetailComboActions } from './product-detail-page/combo-actions';
import { DEFAULT_PRODUCT_DETAIL_FORM } from './product-detail-page/constants';
import { createProductDetailDataActions } from './product-detail-page/data-actions'; import { createProductDetailDataActions } from './product-detail-page/data-actions';
import { createProductDetailSkuActions } from './product-detail-page/sku-actions'; import { createProductDetailSkuActions } from './product-detail-page/sku-actions';