From 4347b59e775874b9bf8dbccac81de3ea65999b00 Mon Sep 17 00:00:00 2001 From: wjiangwang <39005591+wjiangwang@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:27:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=BF=A1=E6=81=AF=E5=92=8C=E6=96=87=E6=A1=A3?= =?UTF-8?q?=20(#67)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: add database sql file * docs: update readme database * fix: fix error log * fix: fix token expire * feat: auto create database * docs: update pro readme * docs: update pro readme * docs: update pro readme * fix: pro init log info --- packages/toolkits/pro/README.md | 37 ++++++-- packages/toolkits/pro/package.json | 1 + packages/toolkits/pro/src/lib/init.ts | 87 +++++++++++++++++-- packages/toolkits/pro/src/lib/interfaces.ts | 4 +- .../toolkits/pro/template/server/eggJs/app.ts | 14 +++ .../server/eggJs/app/database/buryinfo.sql | 17 ---- .../server/eggJs/app/database/createuser.sql | 30 +++++++ .../eggJs/app/database/table/employee.sql | 19 ++++ .../eggJs/app/database/table/registeruser.sql | 9 ++ .../eggJs/app/database/table/userinfo.sql | 20 +++++ .../server/eggJs/app/model/employee.ts | 2 +- .../toolkits/pro/template/server/eggJs/egg.js | 0 .../template/tinyvue/src/api/interceptor.ts | 3 +- 13 files changed, 209 insertions(+), 34 deletions(-) create mode 100644 packages/toolkits/pro/template/server/eggJs/app.ts delete mode 100644 packages/toolkits/pro/template/server/eggJs/app/database/buryinfo.sql create mode 100644 packages/toolkits/pro/template/server/eggJs/app/database/createuser.sql create mode 100644 packages/toolkits/pro/template/server/eggJs/app/database/table/employee.sql create mode 100644 packages/toolkits/pro/template/server/eggJs/app/database/table/registeruser.sql create mode 100644 packages/toolkits/pro/template/server/eggJs/app/database/table/userinfo.sql delete mode 100644 packages/toolkits/pro/template/server/eggJs/egg.js diff --git a/packages/toolkits/pro/README.md b/packages/toolkits/pro/README.md index 2f1aa703..ecd3a302 100644 --- a/packages/toolkits/pro/README.md +++ b/packages/toolkits/pro/README.md @@ -12,21 +12,21 @@ tiny-toolkit-pro 套件,开箱即用的中后台前端/设计解决方案 tiny init pro ``` ### 配置项目名称、描述 -项目名称默认是当前所在文件夹名称 +项目名称默认是当前所在文件夹名称。 ``` ? 请输入项目名称: ? 请输入项目描述: (基于TinyPro套件创建的中后台系统) ``` ### 选择前端技术栈 -目前支持```vue``` ```angular```两种前端技术栈。 +目前支持`Vue` `Angular`两种前端技术栈。 ``` ? 请选择您希望使用的技术栈: (Use arrow keys) > vue angular ``` ### 选择服务端技术栈(可选配置) -**目前仅 ```vue```工程支持对接服务端,且只支持```Egg.js```,剩余功能正在开发中** +**目前仅 `Vue`工程支持对接服务端,且只支持`Egg.js`,剩余功能正在开发中。** 如果选择不对接服务端,全部接口将采用mock数据。 ``` ? 请选择您希望使用的服务端技术栈: (Use arrow keys) @@ -35,30 +35,51 @@ tiny init pro Nest.js 暂不配置 ``` -### 配置数据库信息(可选配置) - +### 选择数据库(可选配置) ``` ? 请选择数据库类型: (Use arrow keys) > mySQL 暂不配置 +``` +### 数据库准备工作 +可使用本地数据库或云数据库,请提前安装配置本地数据库服务或者云数据库服务,确保连接正常可用。 +- MySQL[下载链接](https://dev.mysql.com/downloads/) +- 云数据库推荐使用[华为云数据库RDS](https://support.huaweicloud.com/productdesc-rds/zh-cn_topic_dashboard.html),可参考[云服务最佳实践](https://opentiny.design/vue-pro/docs/advanced/practiced) 创建数据库。 + + +### 配置数据库信息 +- **初始化过程中会自动创建数据库和表,建议输入新的数据库名称以免造成数据库覆盖风险。** +``` ? 请输入数据库地址: (localhost) ? 请输入数据库端口: (3306) ? 请输入数据库名称: ? 请输入登录用户名: (root) ? 请输入密码: [input is hidden] ``` +- 此处配置也可在项目创建完成后在`server/config/config.default.ts`中进行配置修改。 +- pro套件会在初始化时自动创建数据库和表,如因配置等问题导致数据库初始化失败,有以下两种方式可帮助重新初始化数据库: + - 确认好正确配置后重新运行 `tiny init pro` 覆盖安装。 + - 进入 `server/app/databases` 目录下手动执行相关sql。 +- 数据库表中会自动插入一条用户信息(账号:admin@example.com 密码:admin),可直接用于登录。 +- 如server服务启动失败,请确保数据库服务的地址、名称、账号、密码等与`server/config/config.default.ts` 中配置一致。 +- `server/app.ts` 中会同步ORM模型到数据库帮助新建表但只建议在开发环境下使用。 ### 开启本地服务器 +Web +``` +cd web && npm run start ``` -tiny start +Egg +``` +cd server && npm run dev ``` ### 代码打包 - +进入对应目录下执行 ``` -tiny build +npm run build ``` ## 维护者 diff --git a/packages/toolkits/pro/package.json b/packages/toolkits/pro/package.json index d0682bb0..0c2c28c8 100644 --- a/packages/toolkits/pro/package.json +++ b/packages/toolkits/pro/package.json @@ -61,6 +61,7 @@ "ejs": "^3.1.9", "fs-extra": "^10.1.0", "inquirer": "^8.0.2", + "mysql2": "^3.4.2", "open": "^8.4.0" }, "devDependencies": { diff --git a/packages/toolkits/pro/src/lib/init.ts b/packages/toolkits/pro/src/lib/init.ts index 23a31001..de740ef8 100644 --- a/packages/toolkits/pro/src/lib/init.ts +++ b/packages/toolkits/pro/src/lib/init.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import chalk from 'chalk'; import spawn from 'cross-spawn'; import * as dotenv from 'dotenv'; +import mysql from 'mysql2/promise'; import inquirer, { QuestionCollection } from 'inquirer'; import { cliConfig, logs, fs } from '@opentiny/cli-devkit'; import { ProjectInfo, ServerFrameworks } from './interfaces'; @@ -112,6 +113,57 @@ const getProjectInfo = (): Promise => { return inquirer.prompt(question); }; +/** + * 创建数据库、表、并插入一条用户(admin)数据 + * @answers 询问客户端问题的选择值 + */ +const createDatabase = async (answers: ProjectInfo) => { + const { dialect, host, port, database, username, password } = answers; + if (!dialect) return; + + log.info('开始连接数据库服务...'); + const connection = await mysql.createConnection({ + host, + port, + user: username, + password, + multipleStatements: true, + }); + + // 连接数据库服务 + await connection.connect(); + log.info(`连接成功,准备创建数据库(${database})和用户数据表...`); + + // 新建数据库 + await connection.query(`CREATE DATABASE IF NOT EXISTS ${database}`); + await connection.query(` USE ${database}`); + + // 读取sql文件、新建表 + const serverPath = utils.getDistPath('server'); + const databaseSqlDir = path.join(serverPath, 'app', 'database'); + const tableSqlDirPath = path.join(databaseSqlDir, 'table'); + const files = fs.readdirSync(tableSqlDirPath); + for (const file of files) { + if (/\.sql$/.test(file)) { + const sqlFilePath = path.join(tableSqlDirPath, file); + const createTableSql = fs.readFileSync(sqlFilePath).toString(); + await connection.query(createTableSql); + } + } + log.info( + '创建成功,开始写入初始用户数据(账号:admin@example.com 密码:admin)...' + ); + + // 插入初始用户数据 + const createUserSqlPath = path.join(databaseSqlDir, 'createuser.sql'); + const createUserSql = fs.readFileSync(createUserSqlPath).toString(); + await connection.query(createUserSql); + log.success('数据库初始化成功!'); + + // 断开连接 + await connection.end(); +}; + /** * 同步创建服务端项目文件目录、文件 * @answers 询问客户端问题的选择值 @@ -131,6 +183,7 @@ const createServerSync = (answers: ProjectInfo) => { password: '123456', database: 'tiny_pro_server', }; + fs.copyTpl(serverFrom, serverTo, dialect ? answers : defaultConfig, { overwrite: true, }); @@ -214,11 +267,26 @@ export const installDependencies = (answers: ProjectInfo) => { '\n--------------------初始化成功,请按下面提示进行操作--------------------\n' ) ); - console.log( - chalk.green( - `${chalk.yellow(`$ ${prefix} start`)} # 可一键开启项目开发环境` - ) - ); + + if (answers.serverFramework) { + console.log( + chalk.green( + `${chalk.yellow('$ cd web && npm run start')} # 开启web开发环境` + ) + ); + console.log( + chalk.green( + `${chalk.yellow('$ cd server && npm run dev')} # 开启server开发环境` + ) + ); + } else { + console.log( + chalk.green( + `${chalk.yellow(`$ ${prefix} start`)} # 可一键开启项目开发环境` + ) + ); + } + console.log( chalk.green( `${chalk.yellow(`$ ${prefix} help`)} # 可查看当前套件的详细帮助` @@ -250,6 +318,15 @@ export default async () => { log.error('项目模板创建失败'); } + // 初始化数据库 + try { + await createDatabase(projectInfo); + } catch (e) { + log.error( + '数据库初始化失败,请确认数据库配置信息正确并手动初始化数据库' + e + ); + } + // 安装依赖 try { installDependencies(projectInfo); diff --git a/packages/toolkits/pro/src/lib/interfaces.ts b/packages/toolkits/pro/src/lib/interfaces.ts index 49134c25..9391c02d 100644 --- a/packages/toolkits/pro/src/lib/interfaces.ts +++ b/packages/toolkits/pro/src/lib/interfaces.ts @@ -13,7 +13,7 @@ export enum ServerFrameworks { EggJs = 'eggJs', NestJs = 'nestJs', SpringCloud = 'springCloud', - Skip = '' + Skip = '', } /** @@ -26,7 +26,7 @@ export interface ProjectInfo { serverFramework: ServerFrameworks; dialect?: string; host?: string; - port?: Number; + port?: number; database?: string; username?: string; password?: string; diff --git a/packages/toolkits/pro/template/server/eggJs/app.ts b/packages/toolkits/pro/template/server/eggJs/app.ts new file mode 100644 index 00000000..d2ac589a --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app.ts @@ -0,0 +1,14 @@ +import { Application } from 'egg'; + +export default (app: Application) => { + // 数据库模型同步,只建议在开发环境下使用 + if (app.config.env === 'local') { + try { + app.beforeStart(async () => { + await app.model.sync({ alter: true }); + }); + } catch (error) { + console.error('数据库同步失败,请检查数据库配置信息或手动创建数据库', error); + } + } +}; diff --git a/packages/toolkits/pro/template/server/eggJs/app/database/buryinfo.sql b/packages/toolkits/pro/template/server/eggJs/app/database/buryinfo.sql deleted file mode 100644 index e9fdb313..00000000 --- a/packages/toolkits/pro/template/server/eggJs/app/database/buryinfo.sql +++ /dev/null @@ -1,17 +0,0 @@ -CREATE TABLE buryinfo( - `_id` INT NOT NULL AUTO_INCREMENT COMMENT '自增id', - `type_id` VARCHAR(50) NOT NULL COMMENT '埋点ID', - `business_desc` VARCHAR(255) NOT NULL COMMENT '业务描述', - `parameter` VARCHAR(255) COMMENT '埋点自定义参数', - `user_email` VARCHAR(50) COMMENT '注册人邮箱', - `user_phone` VARCHAR(20) COMMENT '注册人电话', - `user_name` VARCHAR(50) NOT NULL COMMENT '注册人姓名', - `is_registered` TINYINT(3) DEFAULT 1 COMMENT '是否在鲁班上注册过', - `disable` TINYINT(3) DEFAULT 1 COMMENT '是否启用埋点', - `platform` VARCHAR(50) NOT NULL COMMENT '平台', - `category` VARCHAR(255) NOT NULL COMMENT '目录', - `created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - PRIMARY KEY (_id), - INDEX locktype (platform, category) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 diff --git a/packages/toolkits/pro/template/server/eggJs/app/database/createuser.sql b/packages/toolkits/pro/template/server/eggJs/app/database/createuser.sql new file mode 100644 index 00000000..1be2fc5a --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/database/createuser.sql @@ -0,0 +1,30 @@ +INSERT INTO registeruser +VALUES ( + null, + 'admin@example.com', + '$2b$10$W2NoJWWldrv4ksIalH7po.4vsczt3TlP8SepiEVNEanXzYTIxnIVu', + 'email' + ); + +INSERT INTO userinfo +VALUES ( + null, + (SELECT id + FROM registeruser + WHERE + user_name = 'admin@example.com') + +, +'admin@example.com', +'Tiny-Vue-Pro', +'social recruitment', +'admin', +'2023-06-01', +'2023-09-30', +'90', +'2023-06-01', +'2026-06-01', +'beijing', +'1', +'Front end' +) \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/eggJs/app/database/table/employee.sql b/packages/toolkits/pro/template/server/eggJs/app/database/table/employee.sql new file mode 100644 index 00000000..f9bbfa3e --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/database/table/employee.sql @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS `employee`; + +CREATE TABLE + `employee` ( + `id` bigint(16) NOT NULL, + `name` varchar(20) DEFAULT NULL COMMENT '姓名', + `employee_no` varchar(50) DEFAULT NULL COMMENT '工号', + `department` varchar(50) DEFAULT NULL COMMENT '部门', + `department_level` varchar(50) DEFAULT NULL COMMENT '部门层级', + `status` varchar(10) DEFAULT NULL COMMENT '状态', + `workbench_name` varchar(50) DEFAULT NULL COMMENT '工作台名称', + `project` varchar(50) DEFAULT NULL COMMENT '赋能项目', + `type` varchar(50) DEFAULT NULL COMMENT '人员类型', + `address` varchar(50) DEFAULT NULL COMMENT '研究所', + `roles` varchar(50) DEFAULT NULL COMMENT '角色', + `last_update_user` varchar(50) DEFAULT NULL COMMENT '最后更新人', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE + ) ENGINE = InnoDB DEFAULT CHARSET = utf8 ROW_FORMAT = DYNAMIC; \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/eggJs/app/database/table/registeruser.sql b/packages/toolkits/pro/template/server/eggJs/app/database/table/registeruser.sql new file mode 100644 index 00000000..f423507b --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/database/table/registeruser.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS `registeruser`; +CREATE TABLE + `registeruser` ( + `id` bigint(50) unsigned NOT NULL AUTO_INCREMENT, + `user_name` varchar(20) NOT NULL COMMENT '用户名', + `password` varchar(60) NOT NULL COMMENT '密码', + `register_type` varchar(10) DEFAULT NULL COMMENT '注册类型', + PRIMARY KEY (`id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/eggJs/app/database/table/userinfo.sql b/packages/toolkits/pro/template/server/eggJs/app/database/table/userinfo.sql new file mode 100644 index 00000000..97ff504b --- /dev/null +++ b/packages/toolkits/pro/template/server/eggJs/app/database/table/userinfo.sql @@ -0,0 +1,20 @@ +DROP TABLE IF EXISTS `userinfo`; + +CREATE TABLE + `userinfo` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `user_id` bigint(20) unsigned DEFAULT NULL, + `user_name` varchar(32) NOT NULL COMMENT '用户名', + `department` varchar(32) NOT NULL DEFAULT '' COMMENT '部门', + `employee_type` varchar(32) DEFAULT NULL COMMENT '招聘类型', + `role` varchar(32) DEFAULT NULL COMMENT '角色', + `probation_start` date DEFAULT NULL COMMENT '试用期开始时间', + `probation_end` date DEFAULT NULL COMMENT '试用期结束时间', + `probation_duration` bigint(11) unsigned DEFAULT NULL COMMENT '试用期时长', + `protocol_start` date DEFAULT NULL COMMENT '合同开始日期', + `protocol_end` date DEFAULT NULL COMMENT '合同结束日期', + `address` varchar(32) DEFAULT NULL COMMENT '地址', + `status` varchar(32) DEFAULT NULL COMMENT '状态', + `job` varchar(32) DEFAULT NULL COMMENT '职位', + PRIMARY KEY (`id`) + ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8; \ No newline at end of file diff --git a/packages/toolkits/pro/template/server/eggJs/app/model/employee.ts b/packages/toolkits/pro/template/server/eggJs/app/model/employee.ts index 771530d1..d226a632 100644 --- a/packages/toolkits/pro/template/server/eggJs/app/model/employee.ts +++ b/packages/toolkits/pro/template/server/eggJs/app/model/employee.ts @@ -72,7 +72,7 @@ module.exports = (app: any) => { field: 'create_time', type: DataTypes.TIME, allowNull: true, - defaultValue: DataTypes.literal('CURRENT_TIMESTAMP'), + defaultValue: DataTypes.NOW, }, }, { diff --git a/packages/toolkits/pro/template/server/eggJs/egg.js b/packages/toolkits/pro/template/server/eggJs/egg.js deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/toolkits/pro/template/tinyvue/src/api/interceptor.ts b/packages/toolkits/pro/template/tinyvue/src/api/interceptor.ts index 9dcec1ca..472b78ae 100644 --- a/packages/toolkits/pro/template/tinyvue/src/api/interceptor.ts +++ b/packages/toolkits/pro/template/tinyvue/src/api/interceptor.ts @@ -2,7 +2,7 @@ import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { Modal } from '@opentiny/vue'; import locale from '@opentiny/vue-locale'; import router from '@/router'; -import { getToken } from '@/utils/auth'; +import { getToken, clearToken } from '@/utils/auth'; export interface HttpResponse { errMsg: string; @@ -59,6 +59,7 @@ axios.interceptors.response.use( (error) => { const { status, data } = error.response; if (status === 401) { + clearToken(); router.replace({ name: 'login' }); Modal.message({ message: locale.t('http.error.TokenExpire'),