Files
autoAiWorkSys/api/controller_admin/pricing_plans.js
张成 6e38ba6b38 1
2025-12-27 17:39:14 +08:00

456 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 价格套餐管理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);
}
}
};