/** * 价格套餐管理API - 后台管理 * 提供价格套餐的增删改查功能 */ const Framework = require("../../framework/node-core-framework.js"); module.exports = { /** * @swagger * /admin_api/pricing_plans/list: * post: * summary: 获取价格套餐列表 * description: 分页获取所有价格套餐 * tags: [后台-价格套餐管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * pageOption: * type: object * properties: * page: * type: integer * description: 页码 * pageSize: * type: integer * description: 每页数量 * seachOption: * type: object * properties: * key: * type: string * description: 搜索字段 * value: * type: string * description: 搜索值 * is_active: * type: integer * description: 状态筛选(1=启用,0=禁用) * responses: * 200: * description: 获取成功 */ 'POST /pricing_plans/list': async (ctx) => { try { const models = Framework.getModels(); const { pricing_plans, op } = models; const body = ctx.getBody(); // 获取分页参数 const { limit, offset } = ctx.getPageSize(); // 构建查询条件 const where = { is_delete: 0 }; // 搜索条件 if (body.seachOption) { const { key, value, is_active } = body.seachOption; if (value && key) { if (key === 'name') { where.name = { [op.like]: `%${value}%` }; } else if (key === 'duration') { where.duration = { [op.like]: `%${value}%` }; } } // 状态筛选 if (is_active !== undefined && is_active !== null && is_active !== '') { where.is_active = is_active; } } const result = await pricing_plans.findAndCountAll({ where, limit, offset, order: [['sort_order', 'ASC'], ['id', 'ASC']] }); return ctx.success(result); } catch (error) { console.error('获取价格套餐列表失败:', error); return ctx.fail('获取价格套餐列表失败: ' + error.message); } }, /** * @swagger * /admin_api/pricing_plans/detail: * get: * summary: 获取价格套餐详情 * description: 根据ID获取价格套餐详细信息 * tags: [后台-价格套餐管理] * parameters: * - in: query * name: id * required: true * schema: * type: integer * description: 价格套餐ID * responses: * 200: * description: 获取成功 */ 'GET /pricing_plans/detail': async (ctx) => { try { const models = Framework.getModels(); const { pricing_plans } = models; const { id } = ctx.getQuery(); if (!id) { return ctx.fail('价格套餐ID不能为空'); } const plan = await pricing_plans.findOne({ where: { id, is_delete: 0 } }); if (!plan) { return ctx.fail('价格套餐不存在'); } return ctx.success(plan); } catch (error) { console.error('获取价格套餐详情失败:', error); return ctx.fail('获取价格套餐详情失败: ' + error.message); } }, /** * @swagger * /admin_api/pricing_plans/create: * post: * summary: 创建价格套餐 * description: 创建新的价格套餐 * tags: [后台-价格套餐管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - name * - duration * - days * - price * properties: * name: * type: string * description: 套餐名称 * duration: * type: string * description: 时长描述 * days: * type: integer * description: 天数(-1表示永久) * price: * type: number * description: 售价 * original_price: * type: number * description: 原价 * unit: * type: string * description: 单位 * discount: * type: string * description: 折扣描述 * features: * type: array * description: 功能特性列表 * featured: * type: integer * description: 是否推荐(1=推荐,0=普通) * is_active: * type: integer * description: 是否启用(1=启用,0=禁用) * sort_order: * type: integer * description: 排序顺序 * responses: * 200: * description: 创建成功 */ 'POST /pricing_plans/create': async (ctx) => { try { const models = Framework.getModels(); const { pricing_plans } = models; const body = ctx.getBody(); const { name, duration, days, price, original_price, unit, discount, features, featured, is_active, sort_order } = body; // 验证必填字段 if (!name) { return ctx.fail('套餐名称不能为空'); } if (!duration) { return ctx.fail('时长描述不能为空'); } if (days === undefined || days === null) { return ctx.fail('天数不能为空'); } if (!price && price !== 0) { return ctx.fail('价格不能为空'); } // 验证价格 if (price < 0) { return ctx.fail('价格不能为负数'); } // 验证天数 if (days < -1) { return ctx.fail('天数不能小于-1(-1表示永久)'); } // 处理 features 字段:转换为 JSON 字符串 let featuresStr = '[]'; if (features) { try { if (Array.isArray(features)) { featuresStr = JSON.stringify(features); } else if (typeof features === 'string') { // 验证是否为有效 JSON const parsed = JSON.parse(features); if (!Array.isArray(parsed)) { return ctx.fail('功能特性必须是数组格式'); } featuresStr = features; } else { return ctx.fail('功能特性格式错误'); } } catch (e) { return ctx.fail('功能特性JSON格式错误'); } } // 创建套餐 const plan = await pricing_plans.create({ name, duration, days, price, original_price: original_price !== undefined ? original_price : null, unit: unit || '元', discount: discount || null, features: featuresStr, featured: featured !== undefined ? featured : 0, is_active: is_active !== undefined ? is_active : 1, sort_order: sort_order !== undefined ? sort_order : 0, is_delete: 0, create_time: new Date(), last_modify_time: new Date() }); return ctx.success(plan); } catch (error) { console.error('创建价格套餐失败:', error); return ctx.fail('创建价格套餐失败: ' + error.message); } }, /** * @swagger * /admin_api/pricing_plans/update: * post: * summary: 更新价格套餐 * description: 更新价格套餐信息 * tags: [后台-价格套餐管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * properties: * id: * type: integer * description: 价格套餐ID * name: * type: string * description: 套餐名称 * duration: * type: string * description: 时长描述 * days: * type: integer * description: 天数 * price: * type: number * description: 售价 * original_price: * type: number * description: 原价 * unit: * type: string * description: 单位 * discount: * type: string * description: 折扣描述 * features: * type: array * description: 功能特性列表 * featured: * type: integer * description: 是否推荐 * is_active: * type: integer * description: 是否启用 * sort_order: * type: integer * description: 排序顺序 * responses: * 200: * description: 更新成功 */ 'POST /pricing_plans/update': async (ctx) => { try { const models = Framework.getModels(); const { pricing_plans } = models; const body = ctx.getBody(); const { id, name, duration, days, price, original_price, unit, discount, features, featured, is_active, sort_order } = body; if (!id) { return ctx.fail('价格套餐ID不能为空'); } const plan = await pricing_plans.findOne({ where: { id, is_delete: 0 } }); if (!plan) { return ctx.fail('价格套餐不存在'); } // 构建更新数据 const updateData = { last_modify_time: new Date() }; if (name !== undefined) updateData.name = name; if (duration !== undefined) updateData.duration = duration; if (days !== undefined) { if (days < -1) { return ctx.fail('天数不能小于-1(-1表示永久)'); } updateData.days = days; } if (price !== undefined) { if (price < 0) { return ctx.fail('价格不能为负数'); } updateData.price = price; } if (original_price !== undefined) updateData.original_price = original_price; if (unit !== undefined) updateData.unit = unit; if (discount !== undefined) updateData.discount = discount; if (featured !== undefined) updateData.featured = featured; if (is_active !== undefined) updateData.is_active = is_active; if (sort_order !== undefined) updateData.sort_order = sort_order; // 处理 features 字段 if (features !== undefined) { try { if (Array.isArray(features)) { updateData.features = JSON.stringify(features); } else if (typeof features === 'string') { const parsed = JSON.parse(features); if (!Array.isArray(parsed)) { return ctx.fail('功能特性必须是数组格式'); } updateData.features = features; } else { return ctx.fail('功能特性格式错误'); } } catch (e) { return ctx.fail('功能特性JSON格式错误'); } } await pricing_plans.update(updateData, { where: { id, is_delete: 0 } }); return ctx.success({ message: '价格套餐更新成功' }); } catch (error) { console.error('更新价格套餐失败:', error); return ctx.fail('更新价格套餐失败: ' + error.message); } }, /** * @swagger * /admin_api/pricing_plans/delete: * post: * summary: 删除价格套餐 * description: 软删除指定的价格套餐 * tags: [后台-价格套餐管理] * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - id * properties: * id: * type: integer * description: 价格套餐ID * responses: * 200: * description: 删除成功 */ 'POST /pricing_plans/delete': async (ctx) => { try { const models = Framework.getModels(); const { pricing_plans } = models; const { id } = ctx.getBody(); if (!id) { return ctx.fail('价格套餐ID不能为空'); } const plan = await pricing_plans.findOne({ where: { id, is_delete: 0 } }); if (!plan) { return ctx.fail('价格套餐不存在'); } // 软删除 await pricing_plans.update( { is_delete: 1, last_modify_time: new Date() }, { where: { id } } ); return ctx.success({ message: '价格套餐删除成功' }); } catch (error) { console.error('删除价格套餐失败:', error); return ctx.fail('删除价格套餐失败: ' + error.message); } } };