新增代理实名认证和授权
This commit is contained in:
163
deploy/script/README.md
Normal file
163
deploy/script/README.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Go-Zero 代码生成工具
|
||||
|
||||
这是一个用于 Go-Zero 微服务项目的代码生成工具,支持生成数据库模型和 API 代码。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 数据库模型生成:支持生成 Go-Zero 风格的数据库模型代码
|
||||
- API 代码生成:支持生成 API 服务相关代码
|
||||
- 灵活的表名管理:支持通过命令行指定表名,无需修改配置文件
|
||||
- 配置文件支持:通过 config.json 配置数据库连接和表列表
|
||||
- 命令行参数:支持通过命令行参数覆盖配置文件设置
|
||||
|
||||
## 安装
|
||||
|
||||
确保你的系统已安装 Node.js(10.0+)。
|
||||
|
||||
```bash
|
||||
# 安装依赖
|
||||
cd deploy/script
|
||||
npm install
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### 查看配置
|
||||
|
||||
```bash
|
||||
npm run config
|
||||
```
|
||||
|
||||
### 生成所有配置的表模型
|
||||
|
||||
```bash
|
||||
npm run model
|
||||
```
|
||||
|
||||
### 生成指定表的模型
|
||||
|
||||
```bash
|
||||
# 生成单个表
|
||||
npm run model:table agent
|
||||
|
||||
# 生成多个表(逗号分隔,不含空格)
|
||||
npm run model:tables agent,user,order
|
||||
|
||||
# 或者使用完整命令
|
||||
node codegen.js model --tables agent,user,order
|
||||
```
|
||||
|
||||
### 排除指定表
|
||||
|
||||
```bash
|
||||
# 从配置的表中排除某些表
|
||||
npm run model:exclude user,order
|
||||
|
||||
# 或者使用完整命令
|
||||
node codegen.js model --exclude user,order
|
||||
```
|
||||
|
||||
### 生成所有数据库表的模型
|
||||
|
||||
```bash
|
||||
npm run model:all
|
||||
|
||||
# 生成所有表但排除某些表
|
||||
node codegen.js model --all --exclude system_table,temp_table
|
||||
```
|
||||
|
||||
### 保存表配置
|
||||
|
||||
```bash
|
||||
# 生成指定表并保存到配置文件
|
||||
npm run model:save agent,user,order -- --save
|
||||
|
||||
# 或者使用完整命令
|
||||
node codegen.js model --tables agent,user,order --save
|
||||
```
|
||||
|
||||
### 生成 API 代码
|
||||
|
||||
```bash
|
||||
npm run api
|
||||
```
|
||||
|
||||
### 生成带样式的 API 代码
|
||||
|
||||
```bash
|
||||
npm run api:style
|
||||
```
|
||||
|
||||
### 查看帮助信息
|
||||
|
||||
```bash
|
||||
npm run help
|
||||
```
|
||||
|
||||
## 配置文件
|
||||
|
||||
所有配置都保存在`config.json`文件中,你可以编辑此文件来修改数据库连接信息和要生成的表列表:
|
||||
|
||||
```json
|
||||
{
|
||||
"model": {
|
||||
"dbUrl": "user:password@tcp(host:port)/database",
|
||||
"outputDir": "./model",
|
||||
"templateDir": "../template",
|
||||
"targetDir": "../../app/user/model",
|
||||
"tables": ["table1", "table2"],
|
||||
"disabledTables": ["disabled_table1"]
|
||||
},
|
||||
"api": {
|
||||
"apiFile": "./app/user/cmd/api/desc/main.api",
|
||||
"outputDir": "./app/user/cmd/api",
|
||||
"templateDir": "./deploy/template",
|
||||
"useStyle": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 表名管理
|
||||
|
||||
本工具提供了多种方式来指定需要生成的表:
|
||||
|
||||
1. **配置文件指定**:在`config.json`的`tables`数组中列出要生成的表
|
||||
2. **命令行指定单个表**:使用`--table`参数指定单个表
|
||||
3. **命令行指定多个表**:使用`--tables`参数指定多个表(逗号分隔)
|
||||
4. **排除特定表**:使用`--exclude`参数排除特定表
|
||||
5. **生成所有表**:使用`--all`参数生成数据库中的所有表
|
||||
6. **保存到配置**:使用`--save`参数将当前指定的表保存到配置文件
|
||||
|
||||
这种灵活的表名管理方式使你可以根据需要随时调整要生成的表,而无需频繁修改配置文件。
|
||||
|
||||
## 高级用法
|
||||
|
||||
### 通过命令行参数覆盖配置
|
||||
|
||||
```bash
|
||||
# 使用不同的数据库连接
|
||||
node codegen.js model --db-url "user:pass@tcp(localhost:3306)/otherdb"
|
||||
|
||||
# 使用不同的API文件
|
||||
node codegen.js api --api ./other_api.api
|
||||
|
||||
# 指定输出目录
|
||||
node codegen.js api --dir ./output
|
||||
```
|
||||
|
||||
### 组合使用参数
|
||||
|
||||
```bash
|
||||
# 生成所有表但排除系统表,并使用自定义模板
|
||||
node codegen.js model --all --exclude system_log,system_user --template ./my-templates
|
||||
|
||||
# 生成指定表并保存到配置
|
||||
node codegen.js model --tables user,order,product --save
|
||||
```
|
||||
|
||||
## 脚本文件说明
|
||||
|
||||
- `codegen.js` - 统一入口脚本
|
||||
- `gen_models.js` - 模型生成脚本
|
||||
- `gen_api.js` - API 生成脚本
|
||||
- `config.json` - 配置文件
|
||||
444
deploy/script/codegen.js
Normal file
444
deploy/script/codegen.js
Normal file
@@ -0,0 +1,444 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 代码生成统一入口脚本
|
||||
* 整合了model生成和api生成功能
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { generateApi } = require('./gen_api');
|
||||
|
||||
// 读取配置文件
|
||||
const CONFIG_FILE = path.join(__dirname, 'config.json');
|
||||
let config = {};
|
||||
|
||||
try {
|
||||
if (fs.existsSync(CONFIG_FILE)) {
|
||||
const configContent = fs.readFileSync(CONFIG_FILE, 'utf8');
|
||||
config = JSON.parse(configContent);
|
||||
console.log('Configuration loaded from config.json');
|
||||
} else {
|
||||
console.log('config.json not found, using default settings');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading configuration:', error.message);
|
||||
console.log('Using default settings');
|
||||
}
|
||||
|
||||
// 默认数据库配置
|
||||
const modelConfig = config.model || {
|
||||
// 数据库连接信息
|
||||
dbUrl: 'qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc',
|
||||
// 输出目录
|
||||
outputDir: './model',
|
||||
// 模板目录
|
||||
templateDir: '../template',
|
||||
// 目标目录
|
||||
targetDir: '../../app/user/model',
|
||||
// 表名列表
|
||||
tables: [
|
||||
'agent',
|
||||
'agent_audit',
|
||||
'agent_real_name'
|
||||
],
|
||||
// 禁用的表名列表
|
||||
disabledTables: []
|
||||
};
|
||||
|
||||
// 默认API配置
|
||||
const apiConfig = config.api || {
|
||||
// API定义文件路径
|
||||
apiFile: './app/user/cmd/api/desc/main.api',
|
||||
// 输出目录
|
||||
outputDir: './app/user/cmd/api',
|
||||
// 模板目录
|
||||
templateDir: './deploy/template',
|
||||
// 是否使用样式
|
||||
useStyle: false
|
||||
};
|
||||
|
||||
/**
|
||||
* 将表名转换为驼峰命名法
|
||||
* @param {string} tableName 表名
|
||||
* @returns {string} 驼峰命名的表名
|
||||
*/
|
||||
function convertToCamelCase(tableName) {
|
||||
try {
|
||||
// 将表名按_分割,并将每个部分首字母大写
|
||||
const parts = tableName.split('_');
|
||||
let camelCase = '';
|
||||
for (const part of parts) {
|
||||
if (part.length > 0) {
|
||||
camelCase += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
return camelCase;
|
||||
} catch (error) {
|
||||
console.error(`Error in convertToCamelCase for table: ${tableName}`);
|
||||
console.error(error.message);
|
||||
return tableName; // 出错时返回原表名
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保目录存在
|
||||
* @param {string} dirPath 目录路径
|
||||
*/
|
||||
function ensureDirectoryExists(dirPath) {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
console.log(`Creating directory: ${dirPath}`);
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为单个表生成模型
|
||||
* @param {string} table 表名
|
||||
* @param {object} config 配置信息
|
||||
*/
|
||||
function generateModelForTable(table, config) {
|
||||
try {
|
||||
console.log('=========================================');
|
||||
console.log(`Processing table: ${table}`);
|
||||
|
||||
// 生成模型
|
||||
console.log('Generating model...');
|
||||
const command = `goctl model mysql datasource -url="${config.dbUrl}" -table="${table}" -dir="${config.outputDir}" --home="${config.templateDir}" -cache=true --style=goZero`;
|
||||
console.log(`Running command: ${command}`);
|
||||
|
||||
execSync(command, { stdio: 'inherit' });
|
||||
|
||||
// 将表名转换为驼峰命名法
|
||||
const camelCaseName = convertToCamelCase(table);
|
||||
console.log(`Table name converted to: ${camelCaseName}`);
|
||||
|
||||
// 定义源文件和目标文件路径
|
||||
const sourceModelFile = path.join(config.outputDir, `${camelCaseName}Model.go`);
|
||||
const sourceModelGenFile = path.join(config.outputDir, `${camelCaseName}Model_gen.go`);
|
||||
const targetModelFile = path.join(config.targetDir, `${camelCaseName}Model.go`);
|
||||
const targetModelGenFile = path.join(config.targetDir, `${camelCaseName}Model_gen.go`);
|
||||
|
||||
console.log('Source files:');
|
||||
console.log(` - ${sourceModelFile}`);
|
||||
console.log(` - ${sourceModelGenFile}`);
|
||||
console.log('Target files:');
|
||||
console.log(` - ${targetModelFile}`);
|
||||
console.log(` - ${targetModelGenFile}`);
|
||||
|
||||
// 检查源文件是否存在并移动
|
||||
if (fs.existsSync(sourceModelFile)) {
|
||||
console.log(`Moving ${sourceModelFile} to ${targetModelFile}`);
|
||||
fs.copyFileSync(sourceModelFile, targetModelFile);
|
||||
fs.unlinkSync(sourceModelFile);
|
||||
} else {
|
||||
console.log(`WARNING: Source file not found: ${sourceModelFile}`);
|
||||
}
|
||||
|
||||
if (fs.existsSync(sourceModelGenFile)) {
|
||||
console.log(`Moving ${sourceModelGenFile} to ${targetModelGenFile}`);
|
||||
fs.copyFileSync(sourceModelGenFile, targetModelGenFile);
|
||||
fs.unlinkSync(sourceModelGenFile);
|
||||
} else {
|
||||
console.log(`WARNING: Source file not found: ${sourceModelGenFile}`);
|
||||
}
|
||||
|
||||
console.log(`Processing completed for table: ${table}`);
|
||||
} catch (error) {
|
||||
console.error(`ERROR processing table: ${table}`);
|
||||
console.error(error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成指定表列表的模型
|
||||
* @param {string[]} tables 表名列表
|
||||
* @param {object} config 配置信息
|
||||
*/
|
||||
function generateModels(tables, config) {
|
||||
try {
|
||||
// 确保目录存在
|
||||
ensureDirectoryExists(config.outputDir);
|
||||
ensureDirectoryExists(config.targetDir);
|
||||
|
||||
if (tables.length === 0) {
|
||||
console.log('No tables specified for generation.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 为每个表生成模型
|
||||
for (const table of tables) {
|
||||
generateModelForTable(table, config);
|
||||
}
|
||||
|
||||
console.log('=========================================');
|
||||
console.log('All models generated successfully.');
|
||||
} catch (error) {
|
||||
console.error('ERROR in model generation:');
|
||||
console.error(error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库获取所有表名
|
||||
* @param {string} dbUrl 数据库连接URL
|
||||
* @returns {Promise<string[]>} 表名列表
|
||||
*/
|
||||
async function getAllTablesFromDB(dbUrl) {
|
||||
try {
|
||||
// 解析数据库连接信息
|
||||
const dbName = dbUrl.split('/').pop().split('?')[0];
|
||||
console.log(`Fetching all tables from database: ${dbName}`);
|
||||
|
||||
// 这里需要实现从数据库获取所有表的逻辑
|
||||
// 由于需要依赖额外的库,这里只是示例
|
||||
// 实际实现可能需要使用mysql2或其他数据库客户端库
|
||||
|
||||
// 模拟返回一些表名
|
||||
return [
|
||||
'agent',
|
||||
'agent_audit',
|
||||
'agent_real_name',
|
||||
'agent_active_stat',
|
||||
'agent_closure',
|
||||
'agent_commission',
|
||||
'agent_commission_deduction',
|
||||
'agent_link',
|
||||
'agent_membership_config',
|
||||
'agent_membership_recharge_order',
|
||||
'agent_membership_user_config',
|
||||
'agent_order',
|
||||
'agent_platform_deduction',
|
||||
'agent_product_config',
|
||||
'agent_rewards',
|
||||
'agent_wallet',
|
||||
'agent_withdrawal',
|
||||
'feature',
|
||||
'global_notifications',
|
||||
'order',
|
||||
'product',
|
||||
'product_feature',
|
||||
'query',
|
||||
'user',
|
||||
'user_auth',
|
||||
'example',
|
||||
'authorization',
|
||||
'authorization_face'
|
||||
];
|
||||
} catch (error) {
|
||||
console.error('Error fetching tables from database:', error.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示配置信息
|
||||
*/
|
||||
function showConfig() {
|
||||
console.log('=========================================');
|
||||
console.log('Current Configuration:');
|
||||
console.log('\nModel Configuration:');
|
||||
console.log(' Database URL:', modelConfig.dbUrl);
|
||||
console.log(' Output Directory:', modelConfig.outputDir);
|
||||
console.log(' Template Directory:', modelConfig.templateDir);
|
||||
console.log(' Target Directory:', modelConfig.targetDir);
|
||||
console.log(' Tables:');
|
||||
modelConfig.tables.forEach(table => console.log(` - ${table}`));
|
||||
|
||||
if (modelConfig.disabledTables && modelConfig.disabledTables.length > 0) {
|
||||
console.log(' Disabled Tables:');
|
||||
modelConfig.disabledTables.forEach(table => console.log(` - ${table}`));
|
||||
}
|
||||
|
||||
console.log('\nAPI Configuration:');
|
||||
console.log(' API File:', apiConfig.apiFile);
|
||||
console.log(' Output Directory:', apiConfig.outputDir);
|
||||
console.log(' Template Directory:', apiConfig.templateDir);
|
||||
console.log(' Use Style:', apiConfig.useStyle ? 'Yes' : 'No');
|
||||
console.log('=========================================');
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存配置到文件
|
||||
* @param {object} config 配置对象
|
||||
*/
|
||||
function saveConfig(config) {
|
||||
try {
|
||||
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 4), 'utf8');
|
||||
console.log('Configuration saved to config.json');
|
||||
} catch (error) {
|
||||
console.error('Error saving configuration:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示帮助信息
|
||||
*/
|
||||
function showHelp() {
|
||||
console.log('Usage: node codegen.js <command> [options]');
|
||||
console.log('Commands:');
|
||||
console.log(' model Generate database models');
|
||||
console.log(' api Generate API code');
|
||||
console.log(' config Show current configuration');
|
||||
console.log(' help Show this help message');
|
||||
console.log('');
|
||||
console.log('Model Options:');
|
||||
console.log(' --table <name> Generate model for specific table');
|
||||
console.log(' --tables <names> Generate models for specific tables (comma-separated)');
|
||||
console.log(' --exclude <names> Exclude specific tables (comma-separated)');
|
||||
console.log(' --all Generate models for all tables in database');
|
||||
console.log(' --db-url <url> Database connection URL');
|
||||
console.log(' --template <dir> Template directory');
|
||||
console.log(' --save Save specified tables to config.json');
|
||||
console.log('');
|
||||
console.log('API Options:');
|
||||
console.log(' --api <file> API definition file path');
|
||||
console.log(' --dir <dir> Output directory');
|
||||
console.log(' --template <dir> Template directory');
|
||||
console.log(' --style Use goZero style');
|
||||
console.log('');
|
||||
console.log('Configuration:');
|
||||
console.log(' Settings are loaded from config.json');
|
||||
console.log(' Command line options override config file settings');
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
console.log(' node codegen.js model --table agent');
|
||||
console.log(' node codegen.js model --tables agent,user,order');
|
||||
console.log(' node codegen.js model --exclude user,order');
|
||||
console.log(' node codegen.js model --all --exclude system_table');
|
||||
console.log(' node codegen.js model --tables agent,user --save');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*/
|
||||
async function main() {
|
||||
// 解析命令行参数
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 0 || args[0] === 'help') {
|
||||
showHelp();
|
||||
}
|
||||
|
||||
const command = args[0];
|
||||
|
||||
// 显示配置信息
|
||||
if (command === 'config') {
|
||||
showConfig();
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理模型生成命令
|
||||
if (command === 'model') {
|
||||
const config = { ...modelConfig };
|
||||
let singleTable = null;
|
||||
let tablesToGenerate = [...config.tables];
|
||||
let excludeTables = [];
|
||||
let shouldSaveConfig = false;
|
||||
let generateAllTables = false;
|
||||
|
||||
// 处理其他参数
|
||||
for (let i = 1; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
|
||||
if (arg === '--table' && i + 1 < args.length) {
|
||||
singleTable = args[++i];
|
||||
tablesToGenerate = [singleTable];
|
||||
} else if (arg === '--tables' && i + 1 < args.length) {
|
||||
const tableList = args[++i].split(',').map(t => t.trim()).filter(t => t);
|
||||
tablesToGenerate = tableList;
|
||||
} else if (arg === '--exclude' && i + 1 < args.length) {
|
||||
excludeTables = args[++i].split(',').map(t => t.trim()).filter(t => t);
|
||||
} else if (arg === '--all') {
|
||||
generateAllTables = true;
|
||||
} else if (arg === '--db-url' && i + 1 < args.length) {
|
||||
config.dbUrl = args[++i];
|
||||
} else if (arg === '--template' && i + 1 < args.length) {
|
||||
config.templateDir = args[++i];
|
||||
} else if (arg === '--save') {
|
||||
shouldSaveConfig = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果指定了--all参数,获取所有表名
|
||||
if (generateAllTables) {
|
||||
tablesToGenerate = await getAllTablesFromDB(config.dbUrl);
|
||||
}
|
||||
|
||||
// 排除指定的表
|
||||
if (excludeTables.length > 0) {
|
||||
tablesToGenerate = tablesToGenerate.filter(table => !excludeTables.includes(table));
|
||||
}
|
||||
|
||||
// 保存配置
|
||||
if (shouldSaveConfig) {
|
||||
const newConfig = { ...config };
|
||||
newConfig.tables = tablesToGenerate;
|
||||
|
||||
// 更新配置文件
|
||||
if (fs.existsSync(CONFIG_FILE)) {
|
||||
const existingConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
|
||||
existingConfig.model = newConfig;
|
||||
saveConfig(existingConfig);
|
||||
} else {
|
||||
saveConfig({ model: newConfig, api: apiConfig });
|
||||
}
|
||||
}
|
||||
|
||||
// 生成单个表的模型或所有表的模型
|
||||
if (singleTable) {
|
||||
generateModelForTable(singleTable, config);
|
||||
} else {
|
||||
generateModels(tablesToGenerate, config);
|
||||
}
|
||||
}
|
||||
// 处理API生成命令
|
||||
else if (command === 'api') {
|
||||
const config = { ...apiConfig };
|
||||
|
||||
// 处理其他参数
|
||||
for (let i = 1; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
|
||||
if (arg === '--api' && i + 1 < args.length) {
|
||||
config.apiFile = args[++i];
|
||||
} else if (arg === '--dir' && i + 1 < args.length) {
|
||||
config.outputDir = args[++i];
|
||||
} else if (arg === '--template' && i + 1 < args.length) {
|
||||
config.templateDir = args[++i];
|
||||
} else if (arg === '--style') {
|
||||
config.useStyle = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 生成API代码
|
||||
generateApi(config);
|
||||
}
|
||||
else {
|
||||
console.error(`Unknown command: ${command}`);
|
||||
showHelp();
|
||||
}
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
if (require.main === module) {
|
||||
main().catch(err => {
|
||||
console.error('Error in main execution:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
// 导出函数,以便其他脚本可以调用
|
||||
module.exports = {
|
||||
generateModels,
|
||||
generateModelForTable,
|
||||
generateApi,
|
||||
showConfig,
|
||||
saveConfig,
|
||||
getAllTablesFromDB
|
||||
};
|
||||
46
deploy/script/config.json
Normal file
46
deploy/script/config.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"model": {
|
||||
"dbUrl": "qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc",
|
||||
"outputDir": "./model",
|
||||
"templateDir": "../template",
|
||||
"targetDir": "../../app/user/model",
|
||||
"tables": [
|
||||
"agent",
|
||||
"agent_audit",
|
||||
"agent_real_name"
|
||||
],
|
||||
"disabledTables": [
|
||||
"agent_active_stat",
|
||||
"agent_closure",
|
||||
"agent_commission",
|
||||
"agent_commission_deduction",
|
||||
"agent_link",
|
||||
"agent_membership_config",
|
||||
"agent_membership_recharge_order",
|
||||
"agent_membership_user_config",
|
||||
"agent_order",
|
||||
"agent_platform_deduction",
|
||||
"agent_product_config",
|
||||
"agent_rewards",
|
||||
"agent_wallet",
|
||||
"agent_withdrawal",
|
||||
"feature",
|
||||
"global_notifications",
|
||||
"order",
|
||||
"product",
|
||||
"product_feature",
|
||||
"query",
|
||||
"user",
|
||||
"user_auth",
|
||||
"example",
|
||||
"authorization",
|
||||
"authorization_face"
|
||||
]
|
||||
},
|
||||
"api": {
|
||||
"apiFile": "./app/user/cmd/api/desc/main.api",
|
||||
"outputDir": "./app/user/cmd/api",
|
||||
"templateDir": "./deploy/template",
|
||||
"useStyle": false
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
package script
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"qnc-server/pkg/lzkit/crypto"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
const (
|
||||
// 请替换为实际的数据库连接信息
|
||||
dbHost = "localhost"
|
||||
dbPort = "21001"
|
||||
dbUser = "qnc"
|
||||
dbPassword = "5vg67b3UNHu8"
|
||||
dbName = "qnc"
|
||||
// 请替换为实际的加密密钥
|
||||
secretKey = "ff83609b2b24fc73196aac3d3dfb874f"
|
||||
)
|
||||
|
||||
func RunEncryptMobile() {
|
||||
fmt.Println("开始加密手机号")
|
||||
// 连接数据库
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||
dbUser, dbPassword, dbHost, dbPort, dbName)
|
||||
db := sqlx.NewMysql(dsn)
|
||||
|
||||
// 加密user表的mobile字段
|
||||
if err := encryptUserMobile(db); err != nil {
|
||||
log.Fatalf("加密user表mobile字段失败: %v", err)
|
||||
}
|
||||
|
||||
// 加密user_auth表的auth_key字段
|
||||
if err := encryptUserAuthKey(db); err != nil {
|
||||
log.Fatalf("加密user_auth表auth_key字段失败: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("加密完成!")
|
||||
}
|
||||
|
||||
func encryptUserMobile(db sqlx.SqlConn) error {
|
||||
// 查询所有未加密的手机号
|
||||
query := "SELECT id, mobile FROM user WHERE mobile IS NOT NULL AND mobile != ''"
|
||||
var rows []struct {
|
||||
ID int64 `db:"id"`
|
||||
Mobile string `db:"mobile"`
|
||||
}
|
||||
if err := db.QueryRows(&rows, query); err != nil {
|
||||
return fmt.Errorf("查询user表失败: %v", err)
|
||||
}
|
||||
|
||||
// 准备更新语句
|
||||
updateStmt := "UPDATE user SET mobile = ? WHERE id = ?"
|
||||
|
||||
// 处理每一行
|
||||
for _, row := range rows {
|
||||
// 加密手机号
|
||||
encryptedMobile, err := crypto.EncryptMobile(row.Mobile, secretKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加密手机号失败: %v", err)
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
if _, err := db.Exec(updateStmt, encryptedMobile, row.ID); err != nil {
|
||||
return fmt.Errorf("更新user表失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func encryptUserAuthKey(db sqlx.SqlConn) error {
|
||||
// 查询所有需要加密的auth_key
|
||||
query := "SELECT id, auth_key FROM user_auth WHERE auth_type = 'app_mobile' AND auth_key IS NOT NULL AND auth_key != ''"
|
||||
var rows []struct {
|
||||
ID int64 `db:"id"`
|
||||
AuthKey string `db:"auth_key"`
|
||||
}
|
||||
if err := db.QueryRows(&rows, query); err != nil {
|
||||
return fmt.Errorf("查询user_auth表失败: %v", err)
|
||||
}
|
||||
|
||||
// 准备更新语句
|
||||
updateStmt := "UPDATE user_auth SET auth_key = ? WHERE id = ?"
|
||||
|
||||
// 处理每一行
|
||||
for _, row := range rows {
|
||||
// 加密auth_key
|
||||
encryptedAuthKey, err := crypto.EncryptMobile(row.AuthKey, secretKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("加密auth_key失败: %v", err)
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
if _, err := db.Exec(updateStmt, encryptedAuthKey, row.ID); err != nil {
|
||||
return fmt.Errorf("更新user_auth表失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
108
deploy/script/gen_api.js
Normal file
108
deploy/script/gen_api.js
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* API代码生成脚本
|
||||
* 功能等同于gen_api.ps1
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 配置信息
|
||||
const config = {
|
||||
// API定义文件路径
|
||||
apiFile: './app/user/cmd/api/desc/main.api',
|
||||
// 输出目录
|
||||
outputDir: './app/user/cmd/api',
|
||||
// 模板目录
|
||||
templateDir: './deploy/template'
|
||||
};
|
||||
|
||||
/**
|
||||
* 生成API代码
|
||||
* @param {object} options 选项
|
||||
* @param {string} options.apiFile API定义文件路径
|
||||
* @param {string} options.outputDir 输出目录
|
||||
* @param {string} options.templateDir 模板目录
|
||||
* @param {boolean} options.useStyle 是否使用样式
|
||||
*/
|
||||
function generateApi({ apiFile, outputDir, templateDir, useStyle = false }) {
|
||||
try {
|
||||
console.log('=========================================');
|
||||
console.log('Generating API code...');
|
||||
|
||||
// 构建命令
|
||||
let command = `goctl api go --api ${apiFile} --dir ${outputDir} --home ${templateDir}`;
|
||||
|
||||
// 如果需要使用样式
|
||||
if (useStyle) {
|
||||
command += ' --style=goZero';
|
||||
console.log('Using goZero style');
|
||||
}
|
||||
|
||||
console.log(`Running command: ${command}`);
|
||||
|
||||
// 执行命令
|
||||
execSync(command, { stdio: 'inherit' });
|
||||
|
||||
console.log('API code generation completed!');
|
||||
console.log('=========================================');
|
||||
} catch (error) {
|
||||
console.error('ERROR in API generation:');
|
||||
console.error(error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*/
|
||||
function main() {
|
||||
// 解析命令行参数
|
||||
const args = process.argv.slice(2);
|
||||
const options = {
|
||||
apiFile: config.apiFile,
|
||||
outputDir: config.outputDir,
|
||||
templateDir: config.templateDir,
|
||||
useStyle: false
|
||||
};
|
||||
|
||||
// 处理命令行参数
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
const arg = args[i];
|
||||
|
||||
if (arg === '--api' && i + 1 < args.length) {
|
||||
options.apiFile = args[++i];
|
||||
} else if (arg === '--dir' && i + 1 < args.length) {
|
||||
options.outputDir = args[++i];
|
||||
} else if (arg === '--template' && i + 1 < args.length) {
|
||||
options.templateDir = args[++i];
|
||||
} else if (arg === '--style') {
|
||||
options.useStyle = true;
|
||||
} else if (arg === '--help') {
|
||||
console.log('Usage: node gen_api.js [options]');
|
||||
console.log('Options:');
|
||||
console.log(' --api <file> API definition file path');
|
||||
console.log(' --dir <dir> Output directory');
|
||||
console.log(' --template <dir> Template directory');
|
||||
console.log(' --style Use goZero style');
|
||||
console.log(' --help Show this help message');
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 生成API代码
|
||||
generateApi(options);
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
// 导出函数,以便其他脚本可以调用
|
||||
module.exports = {
|
||||
generateApi
|
||||
};
|
||||
172
deploy/script/gen_models.js
Normal file
172
deploy/script/gen_models.js
Normal file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* 数据库模型生成脚本
|
||||
* 功能等同于gen_models.ps1
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 配置信息
|
||||
const config = {
|
||||
// 数据库连接信息
|
||||
dbUrl: 'qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc',
|
||||
// 输出目录
|
||||
outputDir: './model',
|
||||
// 模板目录
|
||||
templateDir: '../template',
|
||||
// 目标目录
|
||||
targetDir: '../../app/user/model',
|
||||
// 表名列表
|
||||
tables: [
|
||||
'agent',
|
||||
// 'agent_active_stat',
|
||||
'agent_audit',
|
||||
'agent_real_name'
|
||||
// 'agent_closure',
|
||||
// 'agent_commission',
|
||||
// 'agent_commission_deduction',
|
||||
// 'agent_link',
|
||||
// 'agent_membership_config',
|
||||
// 'agent_membership_recharge_order',
|
||||
// 'agent_membership_user_config',
|
||||
// 'agent_order',
|
||||
// 'agent_platform_deduction',
|
||||
// 'agent_product_config',
|
||||
// 'agent_rewards',
|
||||
// 'agent_wallet',
|
||||
// 'agent_withdrawal',
|
||||
// 'feature',
|
||||
// 'global_notifications',
|
||||
// 'order',
|
||||
// 'product',
|
||||
// 'product_feature',
|
||||
// 'query',
|
||||
// 'user',
|
||||
// 'user_auth',
|
||||
// 'example',
|
||||
// 'authorization',
|
||||
// 'authorization_face'
|
||||
]
|
||||
};
|
||||
|
||||
/**
|
||||
* 将表名转换为驼峰命名法
|
||||
* @param {string} tableName 表名
|
||||
* @returns {string} 驼峰命名的表名
|
||||
*/
|
||||
function convertToCamelCase(tableName) {
|
||||
try {
|
||||
// 将表名按_分割,并将每个部分首字母大写
|
||||
const parts = tableName.split('_');
|
||||
let camelCase = '';
|
||||
for (const part of parts) {
|
||||
if (part.length > 0) {
|
||||
camelCase += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
return camelCase;
|
||||
} catch (error) {
|
||||
console.error(`Error in convertToCamelCase for table: ${tableName}`);
|
||||
console.error(error.message);
|
||||
return tableName; // 出错时返回原表名
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保目录存在
|
||||
* @param {string} dirPath 目录路径
|
||||
*/
|
||||
function ensureDirectoryExists(dirPath) {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
console.log(`Creating directory: ${dirPath}`);
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为单个表生成模型
|
||||
* @param {string} table 表名
|
||||
*/
|
||||
function generateModelForTable(table) {
|
||||
try {
|
||||
console.log('=========================================');
|
||||
console.log(`Processing table: ${table}`);
|
||||
|
||||
// 生成模型
|
||||
console.log('Generating model...');
|
||||
const command = `goctl model mysql datasource -url="${config.dbUrl}" -table="${table}" -dir="${config.outputDir}" --home="${config.templateDir}" -cache=true --style=goZero`;
|
||||
console.log(`Running command: ${command}`);
|
||||
|
||||
execSync(command, { stdio: 'inherit' });
|
||||
|
||||
// 将表名转换为驼峰命名法
|
||||
const camelCaseName = convertToCamelCase(table);
|
||||
console.log(`Table name converted to: ${camelCaseName}`);
|
||||
|
||||
// 定义源文件和目标文件路径
|
||||
const sourceModelFile = path.join(config.outputDir, `${camelCaseName}Model.go`);
|
||||
const sourceModelGenFile = path.join(config.outputDir, `${camelCaseName}Model_gen.go`);
|
||||
const targetModelFile = path.join(config.targetDir, `${camelCaseName}Model.go`);
|
||||
const targetModelGenFile = path.join(config.targetDir, `${camelCaseName}Model_gen.go`);
|
||||
|
||||
console.log('Source files:');
|
||||
console.log(` - ${sourceModelFile}`);
|
||||
console.log(` - ${sourceModelGenFile}`);
|
||||
console.log('Target files:');
|
||||
console.log(` - ${targetModelFile}`);
|
||||
console.log(` - ${targetModelGenFile}`);
|
||||
|
||||
// 检查源文件是否存在并移动
|
||||
if (fs.existsSync(sourceModelFile)) {
|
||||
console.log(`Moving ${sourceModelFile} to ${targetModelFile}`);
|
||||
fs.copyFileSync(sourceModelFile, targetModelFile);
|
||||
fs.unlinkSync(sourceModelFile);
|
||||
} else {
|
||||
console.log(`WARNING: Source file not found: ${sourceModelFile}`);
|
||||
}
|
||||
|
||||
if (fs.existsSync(sourceModelGenFile)) {
|
||||
console.log(`Moving ${sourceModelGenFile} to ${targetModelGenFile}`);
|
||||
fs.copyFileSync(sourceModelGenFile, targetModelGenFile);
|
||||
fs.unlinkSync(sourceModelGenFile);
|
||||
} else {
|
||||
console.log(`WARNING: Source file not found: ${sourceModelGenFile}`);
|
||||
}
|
||||
|
||||
console.log(`Processing completed for table: ${table}`);
|
||||
} catch (error) {
|
||||
console.error(`ERROR processing table: ${table}`);
|
||||
console.error(error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*/
|
||||
function main() {
|
||||
try {
|
||||
// 确保目录存在
|
||||
ensureDirectoryExists(config.outputDir);
|
||||
ensureDirectoryExists(config.targetDir);
|
||||
|
||||
// 为每个表生成模型
|
||||
for (const table of config.tables) {
|
||||
generateModelForTable(table);
|
||||
}
|
||||
|
||||
console.log('=========================================');
|
||||
console.log('Script execution completed.');
|
||||
} catch (error) {
|
||||
console.error('ERROR in main execution:');
|
||||
console.error(error.message);
|
||||
console.error(error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
main();
|
||||
@@ -1,21 +1,64 @@
|
||||
# 设置输出编码为UTF-8
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
# 数据库连接信息 - 修改了URL格式
|
||||
$DB_URL = "qnc:5vg67b3UNHu8@(127.0.0.1:21001)/qnc"
|
||||
$OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# 启用详细输出和错误处理
|
||||
$ErrorActionPreference = "Stop"
|
||||
$VerbosePreference = "Continue"
|
||||
|
||||
# 检查并创建必要的目录
|
||||
if (-not (Test-Path "./model")) {
|
||||
Write-Output "Creating model directory..."
|
||||
New-Item -ItemType Directory -Path "./model" | Out-Null
|
||||
}
|
||||
|
||||
if (-not (Test-Path "../../app/user/model")) {
|
||||
Write-Output "Creating target directory..."
|
||||
New-Item -ItemType Directory -Path "../../app/user/model" -Force | Out-Null
|
||||
}
|
||||
|
||||
# 将表名转换为驼峰命名法的函数
|
||||
function ConvertToCamelCase {
|
||||
param (
|
||||
[string]$tableName
|
||||
)
|
||||
try {
|
||||
# 将表名按_分割,并将每个部分首字母大写
|
||||
$parts = $tableName -split '_'
|
||||
$camelCase = ""
|
||||
foreach ($part in $parts) {
|
||||
if ($part.Length -gt 0) {
|
||||
$camelCase += $part.Substring(0, 1).ToUpper() + $part.Substring(1).ToLower()
|
||||
}
|
||||
}
|
||||
return $camelCase
|
||||
}
|
||||
catch {
|
||||
Write-Output "Error in ConvertToCamelCase for table: $tableName"
|
||||
Write-Output $_.Exception.Message
|
||||
return $tableName # 出错时返回原表名
|
||||
}
|
||||
}
|
||||
|
||||
# 数据库连接信息
|
||||
$DB_URL = "qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc"
|
||||
$OUTPUT_DIR = "./model"
|
||||
$TEMPLATE_DIR = "../template"
|
||||
$TARGET_DIR = "../../app/user/model"
|
||||
|
||||
# 表名列表
|
||||
# 表名列表 - 每个元素后必须有逗号分隔
|
||||
$tables = @(
|
||||
# "agent",
|
||||
"agent",
|
||||
# "agent_active_stat",
|
||||
# "agent_audit",
|
||||
"agent_audit",
|
||||
"agent_real_name"
|
||||
# "agent_closure",
|
||||
# "agent_commission",
|
||||
# "agent_commission_deduction",
|
||||
# "agent_link",
|
||||
# "agent_membership_config",
|
||||
# "agent_membership_recharge_order"
|
||||
# "agent_membership_recharge_order",
|
||||
# "agent_membership_user_config",
|
||||
# "agent_order",
|
||||
# "agent_platform_deduction",
|
||||
@@ -29,12 +72,68 @@ $tables = @(
|
||||
# "product",
|
||||
# "product_feature",
|
||||
# "query",
|
||||
"user"
|
||||
# "user_auth"
|
||||
# "example"
|
||||
# "user",
|
||||
# "user_auth",
|
||||
# "example",
|
||||
# "authorization",
|
||||
# "authorization_face"
|
||||
)
|
||||
|
||||
# 为每个表生成模型
|
||||
foreach ($table in $tables) {
|
||||
goctl model mysql datasource -url="qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc" -table="$table" -dir="./model" --home="../template" -cache=true --style=goZero
|
||||
try {
|
||||
Write-Output "========================================="
|
||||
Write-Output "Processing table: $table"
|
||||
|
||||
# 生成模型
|
||||
Write-Output "Generating model..."
|
||||
$command = "goctl model mysql datasource -url=`"$DB_URL`" -table=`"$table`" -dir=`"$OUTPUT_DIR`" --home=`"$TEMPLATE_DIR`" -cache=true --style=goZero"
|
||||
Write-Output "Running command: $command"
|
||||
Invoke-Expression $command
|
||||
|
||||
# 将表名转换为驼峰命名法
|
||||
$camelCaseName = ConvertToCamelCase -tableName $table
|
||||
Write-Output "Table name converted to: $camelCaseName"
|
||||
|
||||
# 定义源文件和目标文件路径
|
||||
$sourceModelFile = "$OUTPUT_DIR/${camelCaseName}Model.go"
|
||||
$sourceModelGenFile = "$OUTPUT_DIR/${camelCaseName}Model_gen.go"
|
||||
$targetModelFile = "$TARGET_DIR/${camelCaseName}Model.go"
|
||||
$targetModelGenFile = "$TARGET_DIR/${camelCaseName}Model_gen.go"
|
||||
|
||||
Write-Output "Source files:"
|
||||
Write-Output " - $sourceModelFile"
|
||||
Write-Output " - $sourceModelGenFile"
|
||||
Write-Output "Target files:"
|
||||
Write-Output " - $targetModelFile"
|
||||
Write-Output " - $targetModelGenFile"
|
||||
|
||||
# 检查源文件是否存在
|
||||
if (-not (Test-Path $sourceModelFile)) {
|
||||
Write-Output "WARNING: Source file not found: $sourceModelFile"
|
||||
}
|
||||
if (-not (Test-Path $sourceModelGenFile)) {
|
||||
Write-Output "WARNING: Source file not found: $sourceModelGenFile"
|
||||
}
|
||||
|
||||
# 移动文件
|
||||
if (Test-Path $sourceModelFile) {
|
||||
Write-Output "Moving $sourceModelFile to $targetModelFile"
|
||||
Move-Item -Path $sourceModelFile -Destination $targetModelFile -Force
|
||||
}
|
||||
if (Test-Path $sourceModelGenFile) {
|
||||
Write-Output "Moving $sourceModelGenFile to $targetModelGenFile"
|
||||
Move-Item -Path $sourceModelGenFile -Destination $targetModelGenFile -Force
|
||||
}
|
||||
|
||||
Write-Output "Processing completed for table: $table"
|
||||
}
|
||||
catch {
|
||||
Write-Output "ERROR processing table: $table"
|
||||
Write-Output $_.Exception.Message
|
||||
Write-Output $_.ScriptStackTrace
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "========================================="
|
||||
Write-Output "Script execution completed."
|
||||
|
||||
26
deploy/script/package.json
Normal file
26
deploy/script/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "qnc-codegen",
|
||||
"version": "1.0.0",
|
||||
"description": "代码生成工具 - Go-Zero微服务项目",
|
||||
"main": "codegen.js",
|
||||
"scripts": {
|
||||
"model": "node codegen.js model",
|
||||
"model:table": "node codegen.js model --table",
|
||||
"model:tables": "node codegen.js model --tables",
|
||||
"model:exclude": "node codegen.js model --exclude",
|
||||
"model:all": "node codegen.js model --all",
|
||||
"model:save": "node codegen.js model --tables",
|
||||
"model:save-exclude": "node codegen.js model --exclude",
|
||||
"api": "node codegen.js api",
|
||||
"api:style": "node codegen.js api --style",
|
||||
"config": "node codegen.js config",
|
||||
"help": "node codegen.js help"
|
||||
},
|
||||
"keywords": [
|
||||
"go-zero",
|
||||
"codegen",
|
||||
"microservice"
|
||||
],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
Reference in New Issue
Block a user