feat(M09-D4): 完成商品选购与运营工作台

This commit is contained in:
Codex
2026-08-11 08:06:13 +08:00
parent 60264cbd11
commit e91b979128
32 changed files with 1065 additions and 60 deletions
+4 -2
View File
@@ -113,8 +113,10 @@ function adminAccess(access: AccessProfile) {
const storeRead = tenant || access.capabilities.includes('store.operation.read');
const menus = [
...(storeRead ? ['overview', 'stores', 'orders', 'thirdParty'] : []),
...(tenant || access.capabilities.includes('product.catalog.read')
|| access.capabilities.includes('inventory.read') ? ['products'] : []),
...(tenant || access.capabilities.some((capability) => [
'product.catalog.read', 'product.catalog.write', 'inventory.read', 'inventory.adjust',
'goods.order.read', 'goods.order.manage', 'goods.storage.read', 'goods.storage.manage'
].includes(capability)) ? ['products'] : []),
...(tenant ? ['platformApps', 'content', 'franchise', 'system', 'payments', 'people'] : []),
...(tenant || access.capabilities.includes('device.read') ? ['devices'] : []),
...(tenant || access.capabilities.includes('cleaning.task.read') ? ['cleaning'] : [])
+22 -1
View File
@@ -119,13 +119,34 @@ export interface ProductRouteOptions {
| 'listProducts' | 'createProduct' | 'updateProduct' | 'archiveProduct'
| 'listSkus' | 'createSku' | 'updateSku' | 'archiveSku'
| 'listListings' | 'putListing' | 'archiveListing'
| 'getStoreSettings' | 'putStoreSettings'>;
| 'getStoreSettings' | 'putStoreSettings' | 'listStoreCatalog'>;
authRepository: Pick<AuthRepository, 'validateSession'>;
accessControl: { getAccessProfile(tenantId: string, userId: string): Promise<AccessProfile> };
jwtSecret: string;
}
export async function registerProductRoutes(app: FastifyInstance, options: ProductRouteOptions) {
app.get('/app-api/stores/:storeId/product-catalog', async (request, reply) => {
const auth = await authenticateAccessToken(
request.headers.authorization, options.authRepository, options.jwtSecret
);
const params = storeParamsSchema.safeParse(request.params);
if (!auth) {
reply.status(401).send({
code: 'AUTH_SESSION_INVALID', message: 'Authentication required.', traceId: request.traceId
});
return;
}
if (!params.success) return invalid(reply, request.traceId);
return handle(reply, request.traceId, async () => ({
code: 0,
data: await options.repository.listStoreCatalog({
tenantId: auth.session.tenantId, storeId: params.data.storeId
}),
traceId: request.traceId
}));
});
for (const path of [
'/admin-api/stores/:storeId/product-categories',
'/app-api/management/stores/:storeId/product-categories'