This commit is contained in:
张成
2025-12-27 17:39:14 +08:00
parent b17d08ffa8
commit 6e38ba6b38
11 changed files with 1450 additions and 77 deletions

View File

@@ -0,0 +1,455 @@
/**
* 价格套餐管理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);
}
}
};