1
This commit is contained in:
138
scripts/add_pricing_plans_menu.js
Normal file
138
scripts/add_pricing_plans_menu.js
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 添加"价格套餐管理"菜单项到用户管理菜单下
|
||||
* 执行 SQL 插入操作
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function addPricingPlansMenu() {
|
||||
console.log('🔄 开始添加"价格套餐管理"菜单项...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models) {
|
||||
throw new Error('无法获取模型列表');
|
||||
}
|
||||
|
||||
// 从任意模型获取 sequelize 实例
|
||||
const Sequelize = require('sequelize');
|
||||
const firstModel = Object.values(models)[0];
|
||||
if (!firstModel || !firstModel.sequelize) {
|
||||
throw new Error('无法获取数据库连接');
|
||||
}
|
||||
const sequelize = firstModel.sequelize;
|
||||
|
||||
// 查找用户管理菜单的ID
|
||||
const [userMenu] = await sequelize.query(
|
||||
`SELECT id FROM sys_menu WHERE name = '用户管理' AND parent_id = 0 AND is_delete = 0 LIMIT 1`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
let parentId = 120; // 默认 fallback 值
|
||||
if (userMenu && userMenu.id) {
|
||||
parentId = userMenu.id;
|
||||
console.log(`找到用户管理菜单,ID: ${parentId}`);
|
||||
} else {
|
||||
console.log(`未找到用户管理菜单,使用默认 parent_id: ${parentId}`);
|
||||
}
|
||||
|
||||
// 检查是否已存在
|
||||
const [existing] = await sequelize.query(
|
||||
`SELECT id, name FROM sys_menu WHERE path = 'pricing_plans' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
if (existing) {
|
||||
console.log(`⚠️ 菜单项已存在 (ID: ${existing.id}, 名称: ${existing.name})`);
|
||||
console.log('✅ 无需重复添加\n');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取最大排序值
|
||||
const [maxSort] = await sequelize.query(
|
||||
`SELECT MAX(sort) as maxSort FROM sys_menu WHERE parent_id = ${parentId} AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
const nextSort = (maxSort && maxSort.maxSort ? maxSort.maxSort : 0) + 1;
|
||||
|
||||
// 执行插入
|
||||
await sequelize.query(
|
||||
`INSERT INTO sys_menu (
|
||||
name,
|
||||
parent_id,
|
||||
model_id,
|
||||
form_id,
|
||||
icon,
|
||||
path,
|
||||
component,
|
||||
api_path,
|
||||
is_show_menu,
|
||||
is_show,
|
||||
type,
|
||||
sort,
|
||||
create_time,
|
||||
last_modify_time,
|
||||
is_delete
|
||||
) VALUES (
|
||||
'价格套餐管理',
|
||||
${parentId},
|
||||
0,
|
||||
0,
|
||||
'md-pricetags',
|
||||
'pricing_plans',
|
||||
'system/pricing_plans.vue',
|
||||
'system/pricing_plans_server.js',
|
||||
1,
|
||||
1,
|
||||
'页面',
|
||||
${nextSort},
|
||||
NOW(),
|
||||
NOW(),
|
||||
0
|
||||
)`,
|
||||
{ type: Sequelize.QueryTypes.INSERT }
|
||||
);
|
||||
|
||||
console.log('✅ "价格套餐管理"菜单项添加成功!\n');
|
||||
|
||||
// 验证插入结果
|
||||
const [menu] = await sequelize.query(
|
||||
`SELECT id, name, parent_id, path, component, api_path, sort
|
||||
FROM sys_menu
|
||||
WHERE path = 'pricing_plans' AND is_delete = 0`,
|
||||
{ type: Sequelize.QueryTypes.SELECT }
|
||||
);
|
||||
|
||||
if (menu) {
|
||||
console.log('📋 菜单项详情:');
|
||||
console.log(` ID: ${menu.id}`);
|
||||
console.log(` 名称: ${menu.name}`);
|
||||
console.log(` 父菜单ID: ${menu.parent_id}`);
|
||||
console.log(` 路由路径: ${menu.path}`);
|
||||
console.log(` 组件路径: ${menu.component}`);
|
||||
console.log(` API路径: ${menu.api_path}`);
|
||||
console.log(` 排序: ${menu.sort}\n`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 添加失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行添加
|
||||
addPricingPlansMenu()
|
||||
.then(() => {
|
||||
console.log('✨ 操作完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
135
scripts/migrate_pricing_plans_data.js
Normal file
135
scripts/migrate_pricing_plans_data.js
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* 迁移现有价格套餐数据到数据库
|
||||
* 将 config.js 中硬编码的 4 个套餐数据导入到 pricing_plans 表
|
||||
*/
|
||||
|
||||
const Framework = require('../framework/node-core-framework.js');
|
||||
const frameworkConfig = require('../config/framework.config.js');
|
||||
|
||||
async function migratePricingPlans() {
|
||||
console.log('🔄 开始迁移价格套餐数据...\n');
|
||||
|
||||
try {
|
||||
// 初始化框架
|
||||
console.log('正在初始化框架...');
|
||||
const framework = await Framework.init(frameworkConfig);
|
||||
const models = Framework.getModels();
|
||||
|
||||
if (!models || !models.pricing_plans) {
|
||||
throw new Error('无法获取 pricing_plans 模型');
|
||||
}
|
||||
|
||||
const { pricing_plans } = models;
|
||||
|
||||
// 检查是否已有数据
|
||||
const existingCount = await pricing_plans.count({ where: { is_delete: 0 } });
|
||||
if (existingCount > 0) {
|
||||
console.log(`⚠️ 已存在 ${existingCount} 条套餐数据,跳过迁移\n`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 现有的4个套餐数据(来自 api/controller_front/config.js)
|
||||
const plans = [
|
||||
{
|
||||
name: '体验套餐',
|
||||
duration: '7天',
|
||||
days: 7,
|
||||
price: 28.00,
|
||||
original_price: 28.00,
|
||||
unit: '元',
|
||||
discount: null,
|
||||
features: JSON.stringify(['7天使用权限', '全功能体验', '技术支持']),
|
||||
featured: 0,
|
||||
is_active: 1,
|
||||
sort_order: 1,
|
||||
is_delete: 0,
|
||||
create_time: new Date(),
|
||||
last_modify_time: new Date()
|
||||
},
|
||||
{
|
||||
name: '月度套餐',
|
||||
duration: '30天',
|
||||
days: 30,
|
||||
price: 99.00,
|
||||
original_price: 120.00,
|
||||
unit: '元',
|
||||
discount: '约8.3折',
|
||||
features: JSON.stringify(['30天使用权限', '全功能使用', '优先技术支持', '性价比最高']),
|
||||
featured: 1,
|
||||
is_active: 1,
|
||||
sort_order: 2,
|
||||
is_delete: 0,
|
||||
create_time: new Date(),
|
||||
last_modify_time: new Date()
|
||||
},
|
||||
{
|
||||
name: '季度套餐',
|
||||
duration: '90天',
|
||||
days: 90,
|
||||
price: 269.00,
|
||||
original_price: 360.00,
|
||||
unit: '元',
|
||||
discount: '7.5折',
|
||||
features: JSON.stringify(['90天使用权限', '全功能使用', '优先技术支持', '更优惠价格']),
|
||||
featured: 0,
|
||||
is_active: 1,
|
||||
sort_order: 3,
|
||||
is_delete: 0,
|
||||
create_time: new Date(),
|
||||
last_modify_time: new Date()
|
||||
},
|
||||
{
|
||||
name: '终生套餐',
|
||||
duration: '永久',
|
||||
days: -1,
|
||||
price: 888.00,
|
||||
original_price: null,
|
||||
unit: '元',
|
||||
discount: '超值',
|
||||
features: JSON.stringify(['永久使用权限', '全功能使用', '终身技术支持', '一次购买,终身使用', '最划算选择']),
|
||||
featured: 0,
|
||||
is_active: 1,
|
||||
sort_order: 4,
|
||||
is_delete: 0,
|
||||
create_time: new Date(),
|
||||
last_modify_time: new Date()
|
||||
}
|
||||
];
|
||||
|
||||
// 批量插入
|
||||
await pricing_plans.bulkCreate(plans);
|
||||
console.log('✅ 成功迁移 4 条价格套餐数据!\n');
|
||||
|
||||
// 验证插入结果
|
||||
const result = await pricing_plans.findAll({
|
||||
where: { is_delete: 0 },
|
||||
order: [['sort_order', 'ASC']]
|
||||
});
|
||||
|
||||
console.log('📋 已迁移的套餐:');
|
||||
result.forEach(plan => {
|
||||
const planData = plan.toJSON();
|
||||
console.log(` ${planData.id}. ${planData.name} - ${planData.duration} - ¥${planData.price}`);
|
||||
if (planData.featured === 1) {
|
||||
console.log(` [推荐套餐]`);
|
||||
}
|
||||
});
|
||||
console.log('');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 迁移失败:', error.message);
|
||||
console.error('\n详细错误:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 执行迁移
|
||||
migratePricingPlans()
|
||||
.then(() => {
|
||||
console.log('✨ 迁移完成!');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('\n💥 执行失败:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user