新增代理实名认证和授权

This commit is contained in:
2025-05-24 14:26:20 +08:00
parent 16e57387db
commit 2d3ca4c18e
54 changed files with 4069 additions and 435 deletions

163
deploy/script/README.md Normal file
View File

@@ -0,0 +1,163 @@
# Go-Zero 代码生成工具
这是一个用于 Go-Zero 微服务项目的代码生成工具,支持生成数据库模型和 API 代码。
## 功能特性
- 数据库模型生成:支持生成 Go-Zero 风格的数据库模型代码
- API 代码生成:支持生成 API 服务相关代码
- 灵活的表名管理:支持通过命令行指定表名,无需修改配置文件
- 配置文件支持:通过 config.json 配置数据库连接和表列表
- 命令行参数:支持通过命令行参数覆盖配置文件设置
## 安装
确保你的系统已安装 Node.js10.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
View 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
View 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
}
}

View File

@@ -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
View 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
View 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();

View File

@@ -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."

View 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"
}