|
@@ -10,13 +10,13 @@ import { parseWithAwait } from '@d8d/shared-utils';
|
|
|
|
|
|
|
|
// 定义批量创建子商品Schema
|
|
// 定义批量创建子商品Schema
|
|
|
const BatchCreateChildrenSchema = z.object({
|
|
const BatchCreateChildrenSchema = z.object({
|
|
|
- parentGoodsId: z.number<number>().int().positive('父商品ID必须是正整数'),
|
|
|
|
|
|
|
+ parentGoodsId: z.coerce.number<Number>().int().positive('父商品ID必须是正整数'),
|
|
|
specs: z.array(z.object({
|
|
specs: z.array(z.object({
|
|
|
name: z.string().min(1, '规格名称不能为空').max(255, '规格名称不能超过255个字符'),
|
|
name: z.string().min(1, '规格名称不能为空').max(255, '规格名称不能超过255个字符'),
|
|
|
- price: z.number<number>().nonnegative('价格不能为负数'),
|
|
|
|
|
- costPrice: z.number<number>().nonnegative('成本价不能为负数'),
|
|
|
|
|
- stock: z.number<number>().int().nonnegative('库存不能为负数'),
|
|
|
|
|
- sort: z.number<number>().int().default(0)
|
|
|
|
|
|
|
+ price: z.coerce.number<Number>().nonnegative('价格不能为负数'),
|
|
|
|
|
+ costPrice: z.coerce.number<Number>().nonnegative('成本价不能为负数'),
|
|
|
|
|
+ stock: z.coerce.number<Number>().int().nonnegative('库存不能为负数'),
|
|
|
|
|
+ sort: z.coerce.number<Number>().int().default(0)
|
|
|
})).min(1, '至少需要一个规格')
|
|
})).min(1, '至少需要一个规格')
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -36,8 +36,8 @@ const getChildrenRoute = createRoute({
|
|
|
}).refine((val) => val > 0, '商品ID必须是正整数')
|
|
}).refine((val) => val > 0, '商品ID必须是正整数')
|
|
|
}),
|
|
}),
|
|
|
query: z.object({
|
|
query: z.object({
|
|
|
- page: z.coerce.number<number>().int().positive('页码必须是正整数').default(1),
|
|
|
|
|
- pageSize: z.coerce.number<number>().int().positive('每页数量必须是正整数').default(10),
|
|
|
|
|
|
|
+ page: z.coerce.number<Number>().int().positive('页码必须是正整数').default(1),
|
|
|
|
|
+ pageSize: z.coerce.number<Number>().int().positive('每页数量必须是正整数').default(10),
|
|
|
keyword: z.string().optional(),
|
|
keyword: z.string().optional(),
|
|
|
sortBy: z.string().optional().default('sort'),
|
|
sortBy: z.string().optional().default('sort'),
|
|
|
sortOrder: z.enum(['ASC', 'DESC']).optional().default('ASC')
|
|
sortOrder: z.enum(['ASC', 'DESC']).optional().default('ASC')
|
|
@@ -50,10 +50,10 @@ const getChildrenRoute = createRoute({
|
|
|
'application/json': {
|
|
'application/json': {
|
|
|
schema: z.object({
|
|
schema: z.object({
|
|
|
data: z.array(GoodsSchema),
|
|
data: z.array(GoodsSchema),
|
|
|
- total: z.number<number>().int().nonnegative(),
|
|
|
|
|
- page: z.number<number>().int().positive(),
|
|
|
|
|
- pageSize: z.number<number>().int().positive(),
|
|
|
|
|
- totalPages: z.number<number>().int().nonnegative()
|
|
|
|
|
|
|
+ total: z.coerce.number<Number>().int().nonnegative(),
|
|
|
|
|
+ page: z.coerce.number<Number>().int().positive(),
|
|
|
|
|
+ pageSize: z.coerce.number<Number>().int().positive(),
|
|
|
|
|
+ totalPages: z.coerce.number<Number>().int().nonnegative()
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -160,7 +160,7 @@ const removeParentRoute = createRoute({
|
|
|
// 4. 批量创建子商品路由
|
|
// 4. 批量创建子商品路由
|
|
|
const batchCreateChildrenRoute = createRoute({
|
|
const batchCreateChildrenRoute = createRoute({
|
|
|
method: 'post',
|
|
method: 'post',
|
|
|
- path: '/batch-create-children',
|
|
|
|
|
|
|
+ path: '/batchCreateChildren',
|
|
|
middleware: [authMiddleware],
|
|
middleware: [authMiddleware],
|
|
|
request: {
|
|
request: {
|
|
|
body: {
|
|
body: {
|
|
@@ -178,7 +178,7 @@ const batchCreateChildrenRoute = createRoute({
|
|
|
'application/json': {
|
|
'application/json': {
|
|
|
schema: z.object({
|
|
schema: z.object({
|
|
|
success: z.boolean(),
|
|
success: z.boolean(),
|
|
|
- count: z.number<number>().int().nonnegative(),
|
|
|
|
|
|
|
+ count: z.number().int().nonnegative(),
|
|
|
children: z.array(GoodsSchema)
|
|
children: z.array(GoodsSchema)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
@@ -204,10 +204,10 @@ const batchCreateChildrenRoute = createRoute({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 创建路由实例
|
|
// 创建路由实例
|
|
|
-const app = new OpenAPIHono<AuthContext>();
|
|
|
|
|
|
|
+const app = new OpenAPIHono<AuthContext>()
|
|
|
|
|
|
|
|
// 1. 实现获取子商品列表
|
|
// 1. 实现获取子商品列表
|
|
|
-app.openapi(getChildrenRoute, async (c) => {
|
|
|
|
|
|
|
+.openapi(getChildrenRoute, async (c) => {
|
|
|
try {
|
|
try {
|
|
|
const { id: parentId } = c.req.valid('param');
|
|
const { id: parentId } = c.req.valid('param');
|
|
|
const query = c.req.valid('query');
|
|
const query = c.req.valid('query');
|
|
@@ -226,10 +226,11 @@ app.openapi(getChildrenRoute, async (c) => {
|
|
|
|
|
|
|
|
if (!tenantId) {
|
|
if (!tenantId) {
|
|
|
console.debug('无法获取租户信息,用户对象:', user);
|
|
console.debug('无法获取租户信息,用户对象:', user);
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 400,
|
|
code: 400,
|
|
|
message: '无法获取租户信息'
|
|
message: '无法获取租户信息'
|
|
|
- }, 400);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 400);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 验证父商品是否存在且属于当前租户
|
|
// 验证父商品是否存在且属于当前租户
|
|
@@ -239,10 +240,11 @@ app.openapi(getChildrenRoute, async (c) => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (!parentGoods) {
|
|
if (!parentGoods) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 404,
|
|
code: 404,
|
|
|
message: '父商品不存在'
|
|
message: '父商品不存在'
|
|
|
- }, 404);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 404);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 创建查询构建器
|
|
// 创建查询构建器
|
|
@@ -291,15 +293,16 @@ app.openapi(getChildrenRoute, async (c) => {
|
|
|
}, 200);
|
|
}, 200);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('获取子商品列表失败:', error);
|
|
console.error('获取子商品列表失败:', error);
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const errorResponse = await parseWithAwait(ErrorSchema, {
|
|
|
code: 500,
|
|
code: 500,
|
|
|
message: error instanceof Error ? error.message : '获取子商品列表失败'
|
|
message: error instanceof Error ? error.message : '获取子商品列表失败'
|
|
|
- }, 500);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(errorResponse, 500);
|
|
|
}
|
|
}
|
|
|
-});
|
|
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 2. 实现设为父商品
|
|
// 2. 实现设为父商品
|
|
|
-app.openapi(setAsParentRoute, async (c) => {
|
|
|
|
|
|
|
+.openapi(setAsParentRoute, async (c) => {
|
|
|
try {
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
|
|
|
|
@@ -308,10 +311,11 @@ app.openapi(setAsParentRoute, async (c) => {
|
|
|
const tenantId = c.get('tenantId');
|
|
const tenantId = c.get('tenantId');
|
|
|
|
|
|
|
|
if (!tenantId) {
|
|
if (!tenantId) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 400,
|
|
code: 400,
|
|
|
message: '无法获取租户信息'
|
|
message: '无法获取租户信息'
|
|
|
- }, 400);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 400);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 获取商品
|
|
// 获取商品
|
|
@@ -320,18 +324,20 @@ app.openapi(setAsParentRoute, async (c) => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (!goods) {
|
|
if (!goods) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 404,
|
|
code: 404,
|
|
|
message: '商品不存在'
|
|
message: '商品不存在'
|
|
|
- }, 404);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 404);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 验证:不能是子商品
|
|
// 验证:不能是子商品
|
|
|
if (goods.spuId > 0) {
|
|
if (goods.spuId > 0) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 400,
|
|
code: 400,
|
|
|
message: '子商品不能设为父商品'
|
|
message: '子商品不能设为父商品'
|
|
|
- }, 400);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 400);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 更新商品为父商品(spuId已经是0,不需要修改)
|
|
// 更新商品为父商品(spuId已经是0,不需要修改)
|
|
@@ -352,10 +358,10 @@ app.openapi(setAsParentRoute, async (c) => {
|
|
|
message: error instanceof Error ? error.message : '设为父商品失败'
|
|
message: error instanceof Error ? error.message : '设为父商品失败'
|
|
|
}, 500);
|
|
}, 500);
|
|
|
}
|
|
}
|
|
|
-});
|
|
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 3. 实现解除父子关系
|
|
// 3. 实现解除父子关系
|
|
|
-app.openapi(removeParentRoute, async (c) => {
|
|
|
|
|
|
|
+.openapi(removeParentRoute, async (c) => {
|
|
|
try {
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
|
|
|
|
@@ -364,10 +370,11 @@ app.openapi(removeParentRoute, async (c) => {
|
|
|
const tenantId = c.get('tenantId');
|
|
const tenantId = c.get('tenantId');
|
|
|
|
|
|
|
|
if (!tenantId) {
|
|
if (!tenantId) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 400,
|
|
code: 400,
|
|
|
message: '无法获取租户信息'
|
|
message: '无法获取租户信息'
|
|
|
- }, 400);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 400);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 获取商品
|
|
// 获取商品
|
|
@@ -376,10 +383,11 @@ app.openapi(removeParentRoute, async (c) => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
if (!goods) {
|
|
if (!goods) {
|
|
|
- return c.json({
|
|
|
|
|
|
|
+ const error = await parseWithAwait(ErrorSchema, {
|
|
|
code: 404,
|
|
code: 404,
|
|
|
message: '商品不存在'
|
|
message: '商品不存在'
|
|
|
- }, 404);
|
|
|
|
|
|
|
+ });
|
|
|
|
|
+ return c.json(error, 404);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 验证:必须是子商品
|
|
// 验证:必须是子商品
|
|
@@ -419,16 +427,16 @@ app.openapi(removeParentRoute, async (c) => {
|
|
|
message: error instanceof Error ? error.message : '解除父子关系失败'
|
|
message: error instanceof Error ? error.message : '解除父子关系失败'
|
|
|
}, 500);
|
|
}, 500);
|
|
|
}
|
|
}
|
|
|
-});
|
|
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
// 4. 实现批量创建子商品
|
|
// 4. 实现批量创建子商品
|
|
|
-app.openapi(batchCreateChildrenRoute, async (c) => {
|
|
|
|
|
|
|
+.openapi(batchCreateChildrenRoute, async (c) => {
|
|
|
const queryRunner = AppDataSource.createQueryRunner();
|
|
const queryRunner = AppDataSource.createQueryRunner();
|
|
|
await queryRunner.connect();
|
|
await queryRunner.connect();
|
|
|
await queryRunner.startTransaction();
|
|
await queryRunner.startTransaction();
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- const { parentGoodsId, specs } = c.req.valid('body');
|
|
|
|
|
|
|
+ const { parentGoodsId, specs } = c.req.valid('json');
|
|
|
|
|
|
|
|
// 获取当前用户和租户
|
|
// 获取当前用户和租户
|
|
|
const user = c.get('user');
|
|
const user = c.get('user');
|
|
@@ -529,6 +537,6 @@ app.openapi(batchCreateChildrenRoute, async (c) => {
|
|
|
} finally {
|
|
} finally {
|
|
|
await queryRunner.release();
|
|
await queryRunner.release();
|
|
|
}
|
|
}
|
|
|
-});
|
|
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
export const adminGoodsParentChildRoutesMt = app;
|
|
export const adminGoodsParentChildRoutesMt = app;
|