Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions packages/toolkits/pro/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
```

## 维护者
Expand Down
1 change: 1 addition & 0 deletions packages/toolkits/pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
87 changes: 82 additions & 5 deletions packages/toolkits/pro/src/lib/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -112,6 +113,57 @@ const getProjectInfo = (): Promise<ProjectInfo> => {
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 询问客户端问题的选择值
Expand All @@ -131,6 +183,7 @@ const createServerSync = (answers: ProjectInfo) => {
password: '123456',
database: 'tiny_pro_server',
};

fs.copyTpl(serverFrom, serverTo, dialect ? answers : defaultConfig, {
overwrite: true,
});
Expand Down Expand Up @@ -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`)} # 可查看当前套件的详细帮助`
Expand Down Expand Up @@ -250,6 +318,15 @@ export default async () => {
log.error('项目模板创建失败');
}

// 初始化数据库
try {
await createDatabase(projectInfo);
} catch (e) {
log.error(
'数据库初始化失败,请确认数据库配置信息正确并手动初始化数据库' + e
);
}

// 安装依赖
try {
installDependencies(projectInfo);
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkits/pro/src/lib/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export enum ServerFrameworks {
EggJs = 'eggJs',
NestJs = 'nestJs',
SpringCloud = 'springCloud',
Skip = ''
Skip = '',
}

/**
Expand All @@ -26,7 +26,7 @@ export interface ProjectInfo {
serverFramework: ServerFrameworks;
dialect?: string;
host?: string;
port?: Number;
port?: number;
database?: string;
username?: string;
password?: string;
Expand Down
14 changes: 14 additions & 0 deletions packages/toolkits/pro/template/server/eggJs/app.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
};

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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'
)
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ module.exports = (app: any) => {
field: 'create_time',
type: DataTypes.TIME,
allowNull: true,
defaultValue: DataTypes.literal('CURRENT_TIMESTAMP'),
defaultValue: DataTypes.NOW,
},
},
{
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -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<T = unknown> {
errMsg: string;
Expand Down Expand Up @@ -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'),
Expand Down