From 1acc6d17c46eb8361a53f81fb3a694147b723fc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AD=9F=E5=B8=85?= <133814250@qq.com>
Date: Mon, 13 Mar 2023 17:00:46 +0800
Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83v2.3.5=E7=89=88=E6=9C=AC?=
=?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E5=86=85=E5=AE=B9=E8=AF=B7=E6=9F=A5?=
=?UTF-8?q?=E7=9C=8B=EF=BC=9Ahttps://github.com/bufanyun/hotgo/blob/v2.0/d?=
=?UTF-8?q?ocs/guide-zh-CN/start-update-log.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 9 +-
docs/guide-zh-CN/README.md | 1 +
docs/guide-zh-CN/start-installation.md | 2 +-
docs/guide-zh-CN/start-issue.md | 3 +-
docs/guide-zh-CN/start-update-log.md | 10 +
docs/guide-zh-CN/sys-code.md | 510 +++++++++-------
docs/guide-zh-CN/sys-db.md | 224 +++----
server/Makefile | 12 +
server/go.mod | 32 +-
server/go.sum | 67 +-
server/hack/config.yaml | 10 +-
server/internal/cmd/auth.go | 33 +
server/internal/cmd/cmd.go | 2 +-
server/internal/cmd/handler_shutdown.go | 10 -
server/internal/cmd/http.go | 15 +-
server/internal/consts/version.go | 2 +-
server/internal/crons/init.go | 5 +-
.../dao/internal/sys_serve_license.go | 109 ++++
server/internal/dao/sys_serve_license.go | 27 +
.../hggen/internal/cmd/gendao/gendao_clear.go | 4 +-
.../hggen/internal/cmd/gendao/gendao_dao.go | 2 +-
.../hggen/internal/cmd/gendao/gendao_do.go | 2 +-
.../internal/cmd/gendao/gendao_entity.go | 2 +-
server/internal/library/network/tcp/client.go | 322 ++++++++++
.../library/network/tcp/client_cron.go | 37 ++
.../library/network/tcp/client_handle.go | 61 ++
server/internal/library/network/tcp/model.go | 25 +
server/internal/library/network/tcp/router.go | 39 ++
server/internal/library/network/tcp/server.go | 278 +++++++++
.../library/network/tcp/server_cron.go | 35 ++
.../library/network/tcp/server_handle.go | 150 +++++
server/internal/library/network/tcp/sign.go | 41 ++
server/internal/logic/logic.go | 2 +
server/internal/logic/sys/blacklist.go | 95 +--
server/internal/logic/tcpclient/auth.go | 110 ++++
.../internal/logic/tcpserver/auth_handle.go | 73 +++
server/internal/logic/tcpserver/init.go | 68 +++
server/internal/model/do/sys_serve_license.go | 35 ++
.../model/entity/sys_serve_license.go | 33 +
server/internal/model/input/msgin/auth.go | 19 +
server/internal/model/input/msgin/common.go | 61 ++
server/internal/service/admin.go | 68 +--
server/internal/service/sys.go | 578 +++++++++---------
server/internal/service/tcpclient.go | 32 +
server/internal/service/tcpserver.go | 32 +
server/manifest/config/config.example.yaml | 4 +
server/storage/data/hotgo.sql | 344 ++++++-----
server/utility/convert/match.go | 102 ++++
web/package.json | 2 +-
web/src/views/system/config/BasicSetting.vue | 51 +-
web/src/views/system/dict/list.vue | 11 +-
51 files changed, 2777 insertions(+), 1024 deletions(-)
create mode 100644 server/internal/cmd/auth.go
create mode 100644 server/internal/dao/internal/sys_serve_license.go
create mode 100644 server/internal/dao/sys_serve_license.go
create mode 100644 server/internal/library/network/tcp/client.go
create mode 100644 server/internal/library/network/tcp/client_cron.go
create mode 100644 server/internal/library/network/tcp/client_handle.go
create mode 100644 server/internal/library/network/tcp/model.go
create mode 100644 server/internal/library/network/tcp/router.go
create mode 100644 server/internal/library/network/tcp/server.go
create mode 100644 server/internal/library/network/tcp/server_cron.go
create mode 100644 server/internal/library/network/tcp/server_handle.go
create mode 100644 server/internal/library/network/tcp/sign.go
create mode 100644 server/internal/logic/tcpclient/auth.go
create mode 100644 server/internal/logic/tcpserver/auth_handle.go
create mode 100644 server/internal/logic/tcpserver/init.go
create mode 100644 server/internal/model/do/sys_serve_license.go
create mode 100644 server/internal/model/entity/sys_serve_license.go
create mode 100644 server/internal/model/input/msgin/auth.go
create mode 100644 server/internal/model/input/msgin/common.go
create mode 100644 server/internal/service/tcpclient.go
create mode 100644 server/internal/service/tcpserver.go
create mode 100644 server/utility/convert/match.go
diff --git a/README.md b/README.md
index 0248cac..9a8ea14 100644
--- a/README.md
+++ b/README.md
@@ -67,10 +67,11 @@
14. 插件应用:支持一键生成插件模板,每个插件之间开发隔离,拥有独立多应用入口、独立配置。完美支持多人协同开发、插件插拔不会对原系统产生影响等。
15. 服务监控:监视当前系统CPU、内存、磁盘、网络、堆栈等相关信息。
16. 附件管理:文件上传,多种上传方式适配。
-17. 消息队列:同时兼容 kafka、redis、rocketmq、磁盘队列,一键配置切换到场景适用的MQ。
-18. 通知公告:采用websocket实时推送在线用户最新通知、公告、私信消息。
-19. 地区编码:整合国内通用省市区编码,运用于项目于一身,支持动态省市区选项。
-20. 常用工具:集成常用的工具包和命令行工具,可以快速开发自定义命令行,多种启动入口。
+17. TCP服务:基于gtcp的应用化实例,支持长连接、断线重连、自动维护心跳、服务登录、服务授权等。主要用于网络服务进程之间的消息通讯。
+18. 消息队列:同时兼容 kafka、redis、rocketmq、磁盘队列,一键配置切换到场景适用的MQ。
+19. 通知公告:采用websocket实时推送在线用户最新通知、公告、私信消息。
+20. 地区编码:整合国内通用省市区编码,运用于项目于一身,支持动态省市区选项。
+21. 常用工具:集成常用的工具包和命令行工具,可以快速开发自定义命令行,多种启动入口。
> HotGo开源以来得到了大家的很多支持,本项目初衷只为互相学习交流,没有任何盈利性目的!欢迎为HotGo贡献代码或提供建议!
diff --git a/docs/guide-zh-CN/README.md b/docs/guide-zh-CN/README.md
index eedc9fd..baeb720 100644
--- a/docs/guide-zh-CN/README.md
+++ b/docs/guide-zh-CN/README.md
@@ -26,6 +26,7 @@
- 工具方法
- RESTful Api
- Websocket服务器
+- TCP服务器
- 单元测试
#### 插件模块开发
diff --git a/docs/guide-zh-CN/start-installation.md b/docs/guide-zh-CN/start-installation.md
index b64d282..1f9694c 100644
--- a/docs/guide-zh-CN/start-installation.md
+++ b/docs/guide-zh-CN/start-installation.md
@@ -27,7 +27,7 @@ git clone https://github.com/bufanyun/hotgo.git && cd hotgo
1、服务端:
- 项目数据库文件 `storage/data/db.sql` 创建数据库并导入
-- 修改配置 `manifest/config/config.yaml.bak` 复制改为`manifest/config/config.yaml`
+- 将配置文件 `manifest/config/config.yaml.bak` 复制后改为`manifest/config/config.yaml`
- 将`manifest/config/config.yaml`中的数据库配置改为你自己的:
```yaml
database:
diff --git a/docs/guide-zh-CN/start-issue.md b/docs/guide-zh-CN/start-issue.md
index a8585fe..1298bb4 100644
--- a/docs/guide-zh-CN/start-issue.md
+++ b/docs/guide-zh-CN/start-issue.md
@@ -29,6 +29,7 @@
> 报错信息:panic: possible config files "config" or "config.toml/yaml/yml/json/ini/xml/properties" not found in resource manager or following system searching paths:
-这是因为系统没有找到配置文件,修改配置 `manifest/config/config.yaml.bak` 复制改为`manifest/config/config.yaml`
+这是因为系统没有找到配置文件,将配置文件 `manifest/config/config.yaml.bak` 复制后改为`manifest/config/config.yaml`
+
详细请参考 - [系统安装](start-installation.md)
diff --git a/docs/guide-zh-CN/start-update-log.md b/docs/guide-zh-CN/start-update-log.md
index 5e6361e..88ad0e7 100644
--- a/docs/guide-zh-CN/start-update-log.md
+++ b/docs/guide-zh-CN/start-update-log.md
@@ -11,6 +11,16 @@
> 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整
+### v2.4.2
+updated 2023.03.11
+- 修复:修复字典管理列表无法添加/编辑问题
+- 优化:优化代码生成文档
+- 优化:优化部门树形选项排序问题
+- 优化:优化基础设置中的LOGO图片上传组件
+- 优化:优化黑名单IP过滤策略
+- 增加:增加基于gtcp实现的C/S服务器,为后续多服务通讯建立基础库
+- 优化:gf版本升级到v2.3.3
+
### v2.3.5
updated 2023.02.26
diff --git a/docs/guide-zh-CN/sys-code.md b/docs/guide-zh-CN/sys-code.md
index 356e50a..0d6ca21 100644
--- a/docs/guide-zh-CN/sys-code.md
+++ b/docs/guide-zh-CN/sys-code.md
@@ -1,235 +1,275 @@
-## 代码生成
-
-目录
-
-- 使用条件
-- 生成配置
-- 一个生成增删改查列表例子
-- 内置gf-cli
-- 自定义生成模板
-
-
-> 在HotGo中可以通过后台开发工具快速的一键生成CRUD,自动生成Api、控制器、业务逻辑、Web页面、表单组件、菜单权限等。
-
-
-### 使用条件
-
-- hotgo 版本号 >= 2.2.10
-- 使用前必须先看 [数据库](sys-db.md)
-
-#### 增删改查列表
-
-- 表自增长字段为 `id`
-
-#### 关系树列表
-
-- 表自增长字段为 `id`
-
-
-### 生成配置
-
-- 注意:线上环境务必将allowedIPs参数设为空,考虑到项目安全问题请勿线上生成使用!
-
-```yaml
-hggen:
- allowedIPs: ["127.0.0.1", "*"] # 白名单,*代表所有,只有允许的IP后台才能使用生成代码功能
- selectDbs: [ "default" ] # 可选生成表的数据库配置名称,支持多库
- disableTables : ["hg_sys_gen_codes","hg_admin_role_casbin"] # 禁用的表,禁用以后将不会在选择表中看到
- delimiters: ["@{", "}"] # 模板引擎变量分隔符号
- # 生成应用模型,所有生成模板允许自定义,可以参考default模板进行改造
- application:
- # CRUD模板
- crud:
- templates:
- # 默认的主包模板
- - group: "default" # 分组名称
- isAddon: false # 是否为插件模板 false|true
- masterPackage: "sys" # 主包名称,需和controllerPath、logicPath、inputPath保持关联
- templatePath: "./resource/generate/default/curd" # 模板路径
- apiPath: "./api/admin" # gfApi生成路径
- controllerPath: "./internal/controller/admin/sys" # 控制器生成路径
- logicPath : "./internal/logic/sys" # 主要业务生成路径
- inputPath: "./internal/model/input/sysin" # 表单过滤器生成路径
- routerPath : "./internal/router/genrouter" # 生成路由表路径
- sqlPath : "./storage/data/generate" # 生成sql语句路径
- webApiPath: "../web/src/api" # webApi生成路径
- webViewsPath : "../web/src/views" # web页面生成路径
-
- # 默认的插件包模板
- - group: "addon" # 分组名称
- isAddon: true # 是否为插件模板 false|true
- masterPackage: "sys" # 主包名称,需和controllerPath、logicPath、inputPath保持关联
- templatePath: "./resource/generate/default/curd" # 模板路径
- apiPath: "./addons/{$name}/api/admin" # gfApi生成路径
- controllerPath: "./addons/{$name}/controller/admin/sys" # 控制器生成路径
- logicPath : "./addons/{$name}/logic/sys" # 主要业务生成路径
- inputPath: "./addons/{$name}/model/input/sysin" # 表单过滤器生成路径
- routerPath : "./addons/{$name}/router/genrouter" # 生成路由表路径
- sqlPath : "./storage/data/generate/addons" # 生成sql语句路径
- webApiPath: "../web/src/api/addons/{$name}" # webApi生成路径
- webViewsPath : "../web/src/views/addons/{$name}" # web页面生成路径
-
- # 关系树列表模板
- tree:
- templates:
- - group: "default"
- templatePath: "./resource/generate/default/tree"
-
- # 消息队列模板
- queue:
- templates:
- - group: "default"
- templatePath: "./resource/generate/default/queue"
-
- # 定时任务模板
- cron:
- templates:
- - group: "default"
- templatePath: "./resource/generate/default/cron"
-```
-
-
-### 一个生成增删改查列表例子
-
-- 推荐使用热编译方式启动HotGo,这样生成完成页面自动刷新即可看到新生成内容,无需手动重启
-- 服务端热编译启动:`gf run main.go`, web前端启动:`yarn dev`
-
-1、创建数据表
-
-1.1 创建测试表格表`hg_test_table`:
-```mysql
-CREATE TABLE `hg_test_table` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
- `category_id` bigint(20) NOT NULL COMMENT '分类ID',
- `title` varchar(64) NOT NULL COMMENT '标题',
- `description` varchar(255) NOT NULL COMMENT '描述',
- `content` text NOT NULL COMMENT '内容',
- `image` varchar(255) DEFAULT NULL COMMENT '单图',
- `attachfile` varchar(255) DEFAULT NULL COMMENT '附件',
- `city_id` bigint(20) DEFAULT '0' COMMENT '所在城市',
- `switch` int(11) DEFAULT '1' COMMENT '显示开关',
- `sort` int(11) NOT NULL COMMENT '排序',
- `status` tinyint(1) DEFAULT '1' COMMENT '状态',
- `created_by` bigint(20) DEFAULT '0' COMMENT '创建者',
- `updated_by` bigint(20) DEFAULT '0' COMMENT '更新者',
- `created_at` datetime DEFAULT NULL COMMENT '创建时间',
- `updated_at` datetime DEFAULT NULL COMMENT '修改时间',
- `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='测试表格';
-
-```
-
-1.2 测试分类表`hg_test_category`:
-- 注意:该表为了方便功能演示已经内置无需再次创建,此处提示表结构只是为了方便大家梳理关联表关系
-```mysql
-CREATE TABLE `hg_test_category` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类ID',
- `name` varchar(255) NOT NULL COMMENT '分类名称',
- `description` varchar(255) DEFAULT NULL COMMENT '描述',
- `sort` int(11) NOT NULL COMMENT '排序',
- `remark` varchar(255) DEFAULT NULL COMMENT '备注',
- `status` tinyint(1) DEFAULT '1' COMMENT '状态',
- `created_at` datetime DEFAULT NULL COMMENT '创建时间',
- `updated_at` datetime DEFAULT NULL COMMENT '修改时间',
- `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='测试分类';
-
-```
-
-1.3 插入测试数据
-```mysql
-INSERT INTO `hg_test_table` (`id`, `category_id`, `title`, `description`, `content`, `image`, `attachfile`, `city_id`, `switch`, `sort`, `status`, `created_by`, `updated_by`, `created_at`, `updated_at`, `deleted_at`) VALUES (1, 1, '测试标题', '描述', '
不知道写点啥!

', 'https://bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2022-12-30/cpf1x44idoycrtajf2.xlsx', 110102, 1, 10, 1, 0, 1, '2022-12-15 19:30:14', '2023-02-23 13:55:32', NULL);
-
-```
-
-
-2、创建生成配置
-- 登录HotGo后台 -> 开发工具 -> 代码生成 -> 找到立即生成按钮并打开,选择和填写如下参数:
-
-
-
-
-3、自定义配置
-- 确认配置无误后,点击生成配置会自动跳转到生成配置页面,如下:
-
-
-
-- 你可以在该页面点击`预览代码`查看生成的内容,如果无需调整亦可以直接点击`提交生成`,以下是预览代码效果:
-
-
-
-- 如果你对默认的生成配置不满意,可以根据页面表单提示,自定义表格属性和字段属性
-
-- 这里假设我们要一个关联表,让表`hg_test_table`字段`category_id`去关联 表`hg_test_category`字段`id`,我们可以这样做:
-
-
-
-
-- 如果你想调整主表每列字段的显示方式,可以点击上方导航栏中的 [主表字段] 进行调整
-- 这里我们不做任何调整直接进入下一步。目的是为了后续演示对最终生成结果不满意的再次调整方案
-
-
-
-4、以上内容都已配置无误后,点击提交生成即可。
-
-- 如果你使用的热编译,那么页面会在生成成功后立即刷新,刷新完成你即可在后台菜单栏中看到`测试表格`菜单。如果不是使用热编译启动,请手动重启服务后刷新。
-
-> 注意:热编译自动刷新时,考虑到实际开发环境电脑配置不同,web端可能会优先于服务端重启加载完成,此时会出现新生成菜单没有加载出来或某接口请求超时问题,这是服务端正在启动中导致的,一般稍等几秒再试即可。
-
-- 接下来让我们看看生成的表格页面,效果如下:
-
-
-
-
-5、假设我们对生成结果不满意,有新的优化需求如下:
-1. 把`单图`、`附件`改换成上传组件
-2. 把`创建者`、`更新者`隐藏
-3. 把`分类ID`隐藏,然后把关联表中的`分类名称`显示出来
-
-> 那么我们可以回到 开发工具 -> 代码生成 -> 找到刚刚生成的记录 -> 在右侧操作栏中点击生成配置,再次进入配置页面做如下操作即可:
-
-1. 点击上方导航栏[主表字段],调整字段选项:
-
-
-
-
-2. 点击上方导航栏[关联表],调整字段选项:
-
-
-
-
-3. 返回[基本信息],勾选强制覆盖,然后点击`预览代码`,确认生成代码无误后点击`提交生成`
-
-
-
-
-- 生成完成刷新页面后,再次来到`测试表格`,发现表格已经调整到了我们预期效果
-
-1. 列表效果:
-
-
-
-2. 编辑表单效果
-
-
-
-
-- 至此生成增删改查列表示例结束!
-
-
-### 内置gf-cli
-
-> 由于gf版本更新较常出现向下不兼容的情况,所以我们为了保证生成代码的依赖稳定性,我们将gf-cli工具内置到了系统中并做了一些在线执行的调整。
-
-- 我们会定期更新和gf最新版本生成功能保持一致,这样不论是你通过gf命令还是通过后台生成的代码格式都是一样的,遵循相同的代码规范和开发方式
-
-- 后续我们也将开放在线运行`gf gen dao`、`gf gen service`功能。在做插件开发时也会支持到在线生成插件下的service接口,这将会使得插件开发更加方便
-
-### 自定义生成模板
-
-> 系统内置了两组CURD生成模板,请参考[生成配置]。default:是默认的生成到主模块下;addon:是默认生成到指定的插件下
-
-- 如果你在实际的开发过程中默认模板需要调整的地方较多时,HotGo允许你新建新的模板分组来满足你的需求。新的模板可根据现有模板基础拷贝一份出来做改造,默认模板目录:[server/resource/generate/default](../../server/resource/generate/default)
-
+## 代码生成
+
+目录
+
+- 使用条件
+- 生成配置
+- 一个生成增删改查列表例子
+- 内置gf-cli
+- 自定义生成模板
+
+
+> 在HotGo中可以通过后台开发工具快速的一键生成CRUD,自动生成Api、控制器、业务逻辑、Web页面、表单组件、菜单权限等。
+
+
+### 使用条件
+
+- hotgo 版本号 >= 2.2.10
+- 使用前必须先看 [数据库](sys-db.md)
+
+#### 增删改查列表
+
+- 表自增长字段为 `id`
+
+#### 关系树列表
+
+- 表自增长字段为 `id`
+
+
+### 生成模板配置
+
+- 注意:线上环境务必将allowedIPs参数设为空,考虑到项目安全问题请勿线上生成使用!
+
+- 默认配置路径:server/manifest/config/config.yaml
+
+```yaml
+hggen:
+ allowedIPs: ["127.0.0.1", "*"] # 白名单,*代表所有,只有允许的IP后台才能使用生成代码功能
+ selectDbs: [ "default" ] # 可选生成表的数据库配置名称,支持多库
+ disableTables : ["hg_sys_gen_codes","hg_admin_role_casbin"] # 禁用的表,禁用以后将不会在选择表中看到
+ delimiters: ["@{", "}"] # 模板引擎变量分隔符号
+ # 生成应用模型,所有生成模板允许自定义,可以参考default模板进行改造
+ application:
+ # CRUD模板
+ crud:
+ templates:
+ # 默认的主包模板
+ - group: "default" # 分组名称
+ isAddon: false # 是否为插件模板 false|true
+ masterPackage: "sys" # 主包名称,需和controllerPath、logicPath、inputPath保持关联
+ templatePath: "./resource/generate/default/curd" # 模板路径
+ apiPath: "./api/admin" # gfApi生成路径
+ controllerPath: "./internal/controller/admin/sys" # 控制器生成路径
+ logicPath : "./internal/logic/sys" # 主要业务生成路径
+ inputPath: "./internal/model/input/sysin" # 表单过滤器生成路径
+ routerPath : "./internal/router/genrouter" # 生成路由表路径
+ sqlPath : "./storage/data/generate" # 生成sql语句路径
+ webApiPath: "../web/src/api" # webApi生成路径
+ webViewsPath : "../web/src/views" # web页面生成路径
+
+ # 默认的插件包模板
+ - group: "addon" # 分组名称
+ isAddon: true # 是否为插件模板 false|true
+ masterPackage: "sys" # 主包名称,需和controllerPath、logicPath、inputPath保持关联
+ templatePath: "./resource/generate/default/curd" # 模板路径
+ apiPath: "./addons/{$name}/api/admin" # gfApi生成路径
+ controllerPath: "./addons/{$name}/controller/admin/sys" # 控制器生成路径
+ logicPath : "./addons/{$name}/logic/sys" # 主要业务生成路径
+ inputPath: "./addons/{$name}/model/input/sysin" # 表单过滤器生成路径
+ routerPath : "./addons/{$name}/router/genrouter" # 生成路由表路径
+ sqlPath : "./storage/data/generate/addons" # 生成sql语句路径
+ webApiPath: "../web/src/api/addons/{$name}" # webApi生成路径
+ webViewsPath : "../web/src/views/addons/{$name}" # web页面生成路径
+
+ # 关系树列表模板
+ tree:
+ templates:
+ - group: "default"
+ templatePath: "./resource/generate/default/tree"
+
+ # 消息队列模板
+ queue:
+ templates:
+ - group: "default"
+ templatePath: "./resource/generate/default/queue"
+
+ # 定时任务模板
+ cron:
+ templates:
+ - group: "default"
+ templatePath: "./resource/generate/default/cron"
+```
+
+### 生成dao、service配置
+
+
+- hotgo在生成dao、service配置时,默认了和gf官方一致的配置方式和代码生成规则。所以无论你是通过hotgo亦或gf命令生成,最终代码格式完全一致,遵循一致的代码规范。
+
+- 默认配置路径:server/hack/config.yaml
+
+```yaml
+gfcli:
+ build:
+ name: "hotgo" # 编译后的可执行文件名称
+ # arch: "all" #不填默认当前系统架构,可选:386,amd64,arm,all
+ # system: "all" #不填默认当前系统平台,可选:linux,darwin,windows,all
+ mod: "none"
+ cgo: 0
+ packSrc: "resource" # 将resource目录打包进可执行文件,静态资源无需单独部署
+ packDst: "internal/packed/packed.go" # 打包后生成的Go文件路径,一般使用相对路径指定到本项目目录中
+ version: ""
+ output: "./temp/hotgo" # 可执行文件生成路径
+ extra: ""
+
+ gen:
+ dao:
+ - link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true"
+ group: "default" # 分组 使用hotgo代码生成功能时必须填
+ # tables: "" # 指定当前数据库中需要执行代码生成的数据表。如果为空,表示数据库的所有表都会生成。
+ tablesEx: "hg_sys_addons_install" # 指定当前数据库中需要排除代码生成的数据表。
+ removePrefix: "hg_"
+ descriptionTag: true
+ noModelComment: true
+ jsonCase: "CamelLower"
+ gJsonSupport: true
+ clear: true
+
+ service: # 生成业务配置
+ srcFolder: "internal/logic"
+ dstFolder: "internal/service"
+ dstFileNameCase: "CamelLower"
+ clear: true
+```
+
+### 一个生成增删改查列表例子
+
+- 推荐使用热编译方式启动HotGo,这样生成完成页面自动刷新即可看到新生成内容,无需手动重启
+- 服务端热编译启动:`gf run main.go`, web前端启动:`yarn dev`
+
+1、创建数据表
+
+1.1 创建测试表格表`hg_test_table`:
+```mysql
+CREATE TABLE `hg_test_table` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+ `category_id` bigint(20) NOT NULL COMMENT '分类ID',
+ `title` varchar(64) NOT NULL COMMENT '标题',
+ `description` varchar(255) NOT NULL COMMENT '描述',
+ `content` text NOT NULL COMMENT '内容',
+ `image` varchar(255) DEFAULT NULL COMMENT '单图',
+ `attachfile` varchar(255) DEFAULT NULL COMMENT '附件',
+ `city_id` bigint(20) DEFAULT '0' COMMENT '所在城市',
+ `switch` int(11) DEFAULT '1' COMMENT '显示开关',
+ `sort` int(11) NOT NULL COMMENT '排序',
+ `status` tinyint(1) DEFAULT '1' COMMENT '状态',
+ `created_by` bigint(20) DEFAULT '0' COMMENT '创建者',
+ `updated_by` bigint(20) DEFAULT '0' COMMENT '更新者',
+ `created_at` datetime DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime DEFAULT NULL COMMENT '修改时间',
+ `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='测试表格';
+
+```
+
+1.2 测试分类表`hg_test_category`:
+- 注意:该表为了方便功能演示已经内置无需再次创建,此处提示表结构只是为了方便大家梳理关联表关系
+```mysql
+CREATE TABLE `hg_test_category` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类ID',
+ `name` varchar(255) NOT NULL COMMENT '分类名称',
+ `description` varchar(255) DEFAULT NULL COMMENT '描述',
+ `sort` int(11) NOT NULL COMMENT '排序',
+ `remark` varchar(255) DEFAULT NULL COMMENT '备注',
+ `status` tinyint(1) DEFAULT '1' COMMENT '状态',
+ `created_at` datetime DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime DEFAULT NULL COMMENT '修改时间',
+ `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='测试分类';
+
+```
+
+1.3 插入测试数据
+```mysql
+INSERT INTO `hg_test_table` (`id`, `category_id`, `title`, `description`, `content`, `image`, `attachfile`, `city_id`, `switch`, `sort`, `status`, `created_by`, `updated_by`, `created_at`, `updated_at`, `deleted_at`) VALUES (1, 1, '测试标题', '描述', '不知道写点啥!

', 'https://bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2022-12-30/cpf1x44idoycrtajf2.xlsx', 110102, 1, 10, 1, 0, 1, '2022-12-15 19:30:14', '2023-02-23 13:55:32', NULL);
+
+```
+
+
+2、创建生成配置
+- 登录HotGo后台 -> 开发工具 -> 代码生成 -> 找到立即生成按钮并打开,选择和填写如下参数:
+
+
+
+
+3、自定义配置
+- 确认配置无误后,点击生成配置会自动跳转到生成配置页面,如下:
+
+
+
+- 你可以在该页面点击`预览代码`查看生成的内容,如果无需调整亦可以直接点击`提交生成`,以下是预览代码效果:
+
+
+
+- 如果你对默认的生成配置不满意,可以根据页面表单提示,自定义表格属性和字段属性
+
+- 这里假设我们要一个关联表,让表`hg_test_table`字段`category_id`去关联 表`hg_test_category`字段`id`,我们可以这样做:
+
+
+
+
+- 如果你想调整主表每列字段的显示方式,可以点击上方导航栏中的 [主表字段] 进行调整
+- 这里我们不做任何调整直接进入下一步。目的是为了后续演示对最终生成结果不满意的再次调整方案
+
+
+
+4、以上内容都已配置无误后,点击提交生成即可。
+
+- 如果你使用的热编译,那么页面会在生成成功后立即刷新,刷新完成你即可在后台菜单栏中看到`测试表格`菜单。如果不是使用热编译启动,请手动重启服务后刷新。
+
+> 注意:热编译自动刷新时,考虑到实际开发环境电脑配置不同,web端可能会优先于服务端重启加载完成,此时会出现新生成菜单没有加载出来或某接口请求超时问题,这是服务端正在启动中导致的,一般稍等几秒再试即可。
+
+- 接下来让我们看看生成的表格页面,效果如下:
+
+
+
+
+5、假设我们对生成结果不满意,有新的优化需求如下:
+1. 把`单图`、`附件`改换成上传组件
+2. 把`创建者`、`更新者`隐藏
+3. 把`分类ID`隐藏,然后把关联表中的`分类名称`显示出来
+
+> 那么我们可以回到 开发工具 -> 代码生成 -> 找到刚刚生成的记录 -> 在右侧操作栏中点击生成配置,再次进入配置页面做如下操作即可:
+
+1. 点击上方导航栏[主表字段],调整字段选项:
+
+
+
+
+2. 点击上方导航栏[关联表],调整字段选项:
+
+
+
+
+3. 返回[基本信息],勾选强制覆盖,然后点击`预览代码`,确认生成代码无误后点击`提交生成`
+
+
+
+
+- 生成完成刷新页面后,再次来到`测试表格`,发现表格已经调整到了我们预期效果
+
+1. 列表效果:
+
+
+
+2. 编辑表单效果
+
+
+
+
+- 至此生成增删改查列表示例结束!
+
+
+### 内置gf-cli
+
+> 由于gf版本更新较常出现向下不兼容的情况,所以我们为了保证生成代码的依赖稳定性,我们将gf-cli工具内置到了系统中并做了一些在线执行的调整。
+
+- 后续我们也将开放在线运行`gf gen dao`、`gf gen service`功能。在做插件开发时也会支持到在线生成插件下的service接口,这将会使得插件开发更加方便
+
+### 自定义生成模板
+
+> 系统内置了两组CURD生成模板,请参考[生成配置]。default:是默认的生成到主模块下;addon:是默认生成到指定的插件下
+
+- 如果你在实际的开发过程中默认模板需要调整的地方较多时,HotGo允许你新建新的模板分组来满足你的需求。新的模板可根据现有模板基础拷贝一份出来做改造,默认模板目录:[server/resource/generate/default](../../server/resource/generate/default)
+
diff --git a/docs/guide-zh-CN/sys-db.md b/docs/guide-zh-CN/sys-db.md
index 291c580..c9facb0 100644
--- a/docs/guide-zh-CN/sys-db.md
+++ b/docs/guide-zh-CN/sys-db.md
@@ -1,113 +1,113 @@
-## 数据库
-
-目录
-
-- 字段类型
-- 特殊字段默认表单组件
-- 特殊字段默认表单验证器
-- SQL默认查询方式
-- 其他默认选项
-- 常见问题
-
-### 字段类型
-
-- 创建数据库表当按如下的规则进行字段命名、类型、属性设置和备注后,再生成CRUD代码时会自动生成对应的Api、控制器、业务逻辑、Web页面、[表单组件](web-form.md)等的一些默认属性
-- 当你了解这些默认技巧后,会有效提高你在实际开发中的生产效率
-
-| 数据库类型 | 额外属性 | 转换Go类型 | 转换Ts类型 | 表单组件 |
-|---------------------------------------------------------------|--------------|--------------|---------|-----------------------|
-| int, tinyint,small_int,smallint,medium_int,mediumint,serial | / | int | number | InputNumber(数字输入框) |
-| int, tinyint,small_int,smallint,medium_int,mediumint,serial | unsigned | uint | number | InputNumber(数字输入框) |
-| big_int,bigint,bigserial | / | int64 | number | InputNumber(数字输入框) |
-| big_int,bigint,bigserial | unsigned | uint64 | number | InputNumber(数字输入框) |
-| real | / | float32 | number | InputNumber(数字输入框) |
-| float,double,decimal,money,numeric,smallmoney | / | float64 | number | InputNumber(数字输入框) |
-| bit(1) 、bit(true)、bit(false) | / | bool | boolean | Input(文本输入框,默认) |
-| bit | / | int64-bytes | array | InputDynamic(动态KV表单) |
-| bit | unsigned | uint64-bytes | array | InputDynamic (动态KV表单) |
-| bool | / | bool | boolean | Input(文本输入框,默认) |
-| date | / | *gtime.Time | string | Date(日期选择器) |
-| datetime,timestamp,timestamptz | / | *gtime.Time | string | Time(时间选择器) |
-| json | / | *gjson.Json | string | Input(文本输入框) |
-| jsonb | / | *gjson.Json | string | Input(文本输入框) |
-| 以下为物理类型中包含字段部分时的转换方式,默认情况 | / | / | / | / |
-| text,char,character | / | string | string | Input(文本输入框) |
-| float,double,numeric | / | string | string | Input(文本输入框) |
-| bool | / | bool | boolean | Input(文本输入框,默认) |
-| binary,blob | / | []byte | string | Input(文本输入框,默认) |
-| int | / | int | number | InputNumber(数字输入框) |
-| int | unsigned | int | number | InputNumber(数字输入框) |
-| time | / | *gtime.Time | string | Time(时间选择器) |
-| date | / | *gtime.Time | string | Date(日期选择器) |
-| 没有满足以上任何条件的 | / | string | string | Input(文本输入框) |
-
-
-### 特殊字段默认表单组件
-- 以下字段在不设置表单组件时会默认使用的表单组件
-
-| 数据库字段 | 字段名称 | 表单组件 |
-|--------------|----------------------|----------------------|
-| status | 状态字段(任意int类型) | Select (单选下拉框) |
-| created_at | 创建时间字段 | TimeRange (时间范围选择) |
-| province_id | 省份字段(任意int类型) | CitySelector (省市区选择) |
-| city_id | 省份字段(任意int类型) | CitySelector (省市区选择) |
-| 任意字串符字段 | 长度>= 200 and <= 500 | InputTextarea (文本域) |
-| 任意字串符字段 | 长度> 500 | InputEditor (富文本) |
-
-
-### 特殊字段默认表单验证器
-- 以下字段在不设置表单组件时会默认使用的表单验证器
-
-| 数据库字段/Go类型 | 字段名称 | 表单验证规则 |
-|-------------------|--------|-----------------------|
-| mobile | 手机号 | 不为空时必须是手机号码(国内) |
-| qq | QQ | 不为空时必须是QQ号码 |
-| email | 邮箱地址 | 不为空时必须是邮箱格式 |
-| id_card | 身份证号码 | 不为空时必须是15或18位身份证号码 |
-| bank_card | 银行卡号码 | 银行卡号码 |
-| password | 密码 | 密码验证,必须包含6-18为字母和数字 |
-| price | 价格 | 金额验证,最多允许输入10位整数及2位小数 |
-| Go类型为uint、uint64 | 正整数 | 非零正整数验证 |
-
-### SQL默认查询方式
-- Go类型取决于数据库物理类型,请参考 [字段类型] 部分
-
-| Go类型 | 查询方式 |
-|-------------------------|--------------------------------------|
-| string | LIKE |
-| date,datetime | = |
-| int,uint,int64,uint64 | = |
-| []int,[]int64,[]uint64 | IN (...) |
-| float32,float64 | = |
-| []byte4 | =(默认) |
-| time.Time,*gtime.Time | = |
-| *gjson.Json | JSON_CONTAINS(json_doc, val[, path]) |
-
-
-
-### 其他默认选项
-
-#### 默认字典选项
-
-- 数据库字段为 `status`且类型为任意数字类型的会使用系统默认的状态字典
-
-#### 默认属性
-
-- 默认必填,当数据库字段存在非空`IS_NULLABLE`属性时,默认勾选必填验证
-- 默认唯一,当数据库字段属性存在`UNI`时,默认勾选唯一值验证
-- 默认主键,当数据库字段属性存在`PRI`时,默认为主键,不允许编辑
-- 默认最大排序,当数据库字段存在`sort`时,默认开启排序,添加表单自动获取最大排序增量值并填充表单
-- 默认列名,默认使用字段注释作为表格的列名。当数据库字段未设置注释时,默认使用字段名称作为列名
-
-#### 自动更新/插入
-
-- 自动更新,当数据库字段为`updated_at`(更新时间),`updated_by`(更新者)
-- 自动插入,当数据库字段为`created_at`(创建时间),`created_by`(创建者)
-- 软删除,表存在字段`deleted_at`时,使用表的Orm模型查询条件将会自动加入[ `deleted_at` IS NULL ],删除时只更新删除时间而不会真的删除数据
-- 树表:不论更新插入,都会根据表中字段`pid`(上级ID)自动维护`level`(树等级)和`tree`(关系树)
-
-> 这里只列举了较为常用的默认规则,其他更多默认规则请参考:[server/internal/library/hggen/views/column_default.go](../../server/internal/library/hggen/views/column_default.go)
-
-#### 常见问题
-
+## 数据库
+
+目录
+
+- 字段类型
+- 特殊字段默认表单组件
+- 特殊字段默认表单验证器
+- SQL默认查询方式
+- 其他默认选项
+- 常见问题
+
+### 字段类型
+
+- 创建数据库表当按如下的规则进行字段命名、类型、属性设置和备注后,再生成CRUD代码时会自动生成对应的Api、控制器、业务逻辑、Web页面、[表单组件](web-form.md)等的一些默认属性
+- 当你了解这些默认技巧后,会有效提高你在实际开发中的生产效率
+
+| 数据库类型 | 额外属性 | 转换Go类型 | 转换Ts类型 | 表单组件 |
+|---------------------------------------------------------------|--------------|--------------|---------|-----------------------|
+| int, tinyint,small_int,smallint,medium_int,mediumint,serial | / | int | number | InputNumber(数字输入框) |
+| int, tinyint,small_int,smallint,medium_int,mediumint,serial | unsigned | uint | number | InputNumber(数字输入框) |
+| big_int,bigint,bigserial | / | int64 | number | InputNumber(数字输入框) |
+| big_int,bigint,bigserial | unsigned | uint64 | number | InputNumber(数字输入框) |
+| real | / | float32 | number | InputNumber(数字输入框) |
+| float,double,decimal,money,numeric,smallmoney | / | float64 | number | InputNumber(数字输入框) |
+| bit(1) 、bit(true)、bit(false) | / | bool | boolean | Input(文本输入框,默认) |
+| bit | / | int64-bytes | array | InputDynamic(动态KV表单) |
+| bit | unsigned | uint64-bytes | array | InputDynamic (动态KV表单) |
+| bool | / | bool | boolean | Input(文本输入框,默认) |
+| date | / | *gtime.Time | string | Date(日期选择器) |
+| datetime,timestamp,timestamptz | / | *gtime.Time | string | Time(时间选择器) |
+| json | / | *gjson.Json | string | Input(文本输入框) |
+| jsonb | / | *gjson.Json | string | Input(文本输入框) |
+| 以下为物理类型中包含字段部分时的转换方式,默认情况 | / | / | / | / |
+| text,char,character | / | string | string | Input(文本输入框) |
+| float,double,numeric | / | string | string | Input(文本输入框) |
+| bool | / | bool | boolean | Input(文本输入框,默认) |
+| binary,blob | / | []byte | string | Input(文本输入框,默认) |
+| int | / | int | number | InputNumber(数字输入框) |
+| int | unsigned | int | number | InputNumber(数字输入框) |
+| time | / | *gtime.Time | string | Time(时间选择器) |
+| date | / | *gtime.Time | string | Date(日期选择器) |
+| 没有满足以上任何条件的 | / | string | string | Input(文本输入框) |
+
+
+### 特殊字段默认表单组件
+- 以下字段在不设置表单组件时会默认使用的表单组件
+
+| 数据库字段 | 字段名称 | 表单组件 |
+|--------------|----------------------|----------------------|
+| status | 状态字段(任意int类型) | Select (单选下拉框) |
+| created_at | 创建时间字段 | TimeRange (时间范围选择) |
+| province_id | 省份ID字段(任意int类型) | CitySelector (省市区选择) |
+| city_id | 城市ID字段(任意int类型) | CitySelector (省市区选择) |
+| 任意字串符字段 | 长度>= 200 and <= 500 | InputTextarea (文本域) |
+| 任意字串符字段 | 长度> 500 | InputEditor (富文本) |
+
+
+### 特殊字段默认表单验证器
+- 以下字段在不设置表单组件时会默认使用的表单验证器
+
+| 数据库字段/Go类型 | 字段名称 | 表单验证规则 |
+|-------------------|--------|-----------------------|
+| mobile | 手机号 | 不为空时必须是手机号码(国内) |
+| qq | QQ | 不为空时必须是QQ号码 |
+| email | 邮箱地址 | 不为空时必须是邮箱格式 |
+| id_card | 身份证号码 | 不为空时必须是15或18位身份证号码 |
+| bank_card | 银行卡号码 | 银行卡号码 |
+| password | 密码 | 密码验证,必须包含6-18为字母和数字 |
+| price | 价格 | 金额验证,最多允许输入10位整数及2位小数 |
+| Go类型为uint、uint64 | 正整数 | 非零正整数验证 |
+
+### SQL默认查询方式
+- Go类型取决于数据库物理类型,请参考 [字段类型] 部分
+
+| Go类型 | 查询方式 |
+|-------------------------|--------------------------------------|
+| string | LIKE |
+| date,datetime | = |
+| int,uint,int64,uint64 | = |
+| []int,[]int64,[]uint64 | IN (...) |
+| float32,float64 | = |
+| []byte4 | =(默认) |
+| time.Time,*gtime.Time | = |
+| *gjson.Json | JSON_CONTAINS(json_doc, val[, path]) |
+
+
+
+### 其他默认选项
+
+#### 默认字典选项
+
+- 数据库字段为 `status`且类型为任意数字类型的会使用系统默认的状态字典
+
+#### 默认属性
+
+- 默认必填,当数据库字段存在非空`IS_NULLABLE`属性时,默认勾选必填验证
+- 默认唯一,当数据库字段属性存在`UNI`时,默认勾选唯一值验证
+- 默认主键,当数据库字段属性存在`PRI`时,默认为主键,不允许编辑
+- 默认最大排序,当数据库字段存在`sort`时,默认开启排序,添加表单自动获取最大排序增量值并填充表单
+- 默认列名,默认使用字段注释作为表格的列名。当数据库字段未设置注释时,默认使用字段名称作为列名
+
+#### 自动更新/插入
+
+- 自动更新,当数据库字段为`updated_at`(更新时间),`updated_by`(更新者)
+- 自动插入,当数据库字段为`created_at`(创建时间),`created_by`(创建者)
+- 软删除,表存在字段`deleted_at`时,使用表的Orm模型查询条件将会自动加入[ `deleted_at` IS NULL ],删除时只更新删除时间而不会真的删除数据
+- 树表:不论更新插入,都会根据表中字段`pid`(上级ID)自动维护`level`(树等级)和`tree`(关系树)
+
+> 这里只列举了较为常用的默认规则,其他更多默认规则请参考:[server/internal/library/hggen/views/column_default.go](../../server/internal/library/hggen/views/column_default.go)
+
+#### 常见问题
+
待补充。
\ No newline at end of file
diff --git a/server/Makefile b/server/Makefile
index 764fa23..6b7669f 100644
--- a/server/Makefile
+++ b/server/Makefile
@@ -17,6 +17,18 @@ build:
all:
gf run main.go --args "all"
+.PHONY: http
+http:
+ gf run main.go --args "http"
+
+.PHONY: queue
+queue:
+ gf run main.go --args "queue"
+
+.PHONY: auth
+auth:
+ gf run main.go --args "auth"
+
# 启动web服务
.PHONY: web
web:
diff --git a/server/go.mod b/server/go.mod
index 26800e3..40d9115 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -14,10 +14,11 @@ require (
github.com/casbin/casbin/v2 v2.55.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/forgoer/openssl v1.4.0
+ github.com/fwhezfwhez/errorx v1.1.0
github.com/go-resty/resty/v2 v2.7.0
- github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2
- github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.2
- github.com/gogf/gf/v2 v2.3.2
+ github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3
+ github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.3
+ github.com/gogf/gf/v2 v2.3.3
github.com/gomodule/redigo v1.8.8
github.com/gorilla/websocket v1.5.0
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794
@@ -26,8 +27,9 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shopspring/decimal v1.3.1
github.com/ufilesdk-dev/ufile-gosdk v1.0.3
+ github.com/xtaci/kcp-go v5.4.20+incompatible
github.com/xuri/excelize/v2 v2.6.0
- golang.org/x/tools v0.1.12
+ golang.org/x/tools v0.6.0
gopkg.in/yaml.v3 v3.0.1
)
@@ -56,6 +58,7 @@ require (
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
+ github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
@@ -71,6 +74,8 @@ require (
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.6 // indirect
+ github.com/klauspost/cpuid/v2 v2.1.1 // indirect
+ github.com/klauspost/reedsolomon v1.11.7 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
@@ -83,27 +88,30 @@ require (
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.1 // indirect
- github.com/rivo/uniseg v0.4.3 // indirect
+ github.com/rivo/uniseg v0.4.4 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
+ github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect
+ github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect
github.com/tidwall/gjson v1.2.1 // indirect
github.com/tidwall/match v1.0.1 // indirect
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
+ github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 // indirect
github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8 // indirect
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
- go.opentelemetry.io/otel v1.13.0 // indirect
- go.opentelemetry.io/otel/sdk v1.13.0 // indirect
- go.opentelemetry.io/otel/trace v1.13.0 // indirect
+ go.opentelemetry.io/otel v1.14.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.14.0 // indirect
+ go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
- golang.org/x/net v0.7.0 // indirect
- golang.org/x/sys v0.5.0 // indirect
- golang.org/x/text v0.7.0 // indirect
+ golang.org/x/mod v0.8.0 // indirect
+ golang.org/x/net v0.8.0 // indirect
+ golang.org/x/sys v0.6.0 // indirect
+ golang.org/x/text v0.8.0 // indirect
gopkg.in/ini.v1 v1.56.0 // indirect
stathat.com/c/consistent v1.0.0 // indirect
)
diff --git a/server/go.sum b/server/go.sum
index 83bface..333e3f6 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -135,6 +135,8 @@ github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fwhezfwhez/errorx v1.1.0 h1:795cMWZFM+thQfKaC5Cjnp/h6naUEbsoQxOb/yvwn0c=
+github.com/fwhezfwhez/errorx v1.1.0/go.mod h1:epOraH2nrfmf4JUao5290NFuXw9t6MZnzgwoW5guABE=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -161,13 +163,15 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
-github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2 h1:BZww6QOFgiN/YvovUtN64sgnq59TIg8vtkG8AL6eSl0=
-github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.2/go.mod h1:z+/0qiOwMroAnj5ESuobTv0l5P83rf+XR3r6Fj8WJyk=
-github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.2 h1:AsYganxtge0nz7eYDYdvGH6E2pRe5IuK45/OLHIFrj8=
-github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.2/go.mod h1:V9o2BF9ovJnaZhHImHAanqUgjX4kI51lgU45u5rPqvw=
+github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
+github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3 h1:McqosVS9Bm7SzmsMTwfVT0YX6i/Is2aRn/XfqW/0iSI=
+github.com/gogf/gf/contrib/drivers/mysql/v2 v2.3.3/go.mod h1:z+/0qiOwMroAnj5ESuobTv0l5P83rf+XR3r6Fj8WJyk=
+github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.3 h1:t1DA5NbyOk7FrDtFtJ5nS+RuGkmhJ9dUsQQKh5G3LOE=
+github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.3/go.mod h1:V9o2BF9ovJnaZhHImHAanqUgjX4kI51lgU45u5rPqvw=
github.com/gogf/gf/v2 v2.0.0/go.mod h1:apktt6TleWtCIwpz63vBqUnw8MX8gWKoZyxgDpXFtgM=
-github.com/gogf/gf/v2 v2.3.2 h1:nlJ0zuDWqFb93/faZmr7V+GADx/lzz5Unz/9x6OJ2u8=
-github.com/gogf/gf/v2 v2.3.2/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
+github.com/gogf/gf/v2 v2.3.3 h1:3iry6kybjvuryTtjypG9oUuxrQ0URMT7j0DVg7FFnaw=
+github.com/gogf/gf/v2 v2.3.3/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
@@ -286,6 +290,10 @@ github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794/go.mod h1:IwrOeG3O3K9v
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
+github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
+github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
+github.com/klauspost/reedsolomon v1.11.7 h1:9uaHU0slncktTEEg4+7Vl7q7XUNMBUOK4R9gnKhMjAU=
+github.com/klauspost/reedsolomon v1.11.7/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -376,8 +384,8 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
-github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
-github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
+github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -409,7 +417,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
+github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tidwall/gjson v1.2.1 h1:j0efZLrZUvNerEf6xqoi0NjWMK5YlLrR7Guo/dxY174=
github.com/tidwall/gjson v1.2.1/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
@@ -428,6 +440,10 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg=
+github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
+github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8 h1:3X7aE0iLKJ5j+tz58BpvIZkXNV7Yq4jC93Z/rbN2Fxk=
github.com/xuri/efp v0.0.0-20220407160117-ad0f7a785be8/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.6.0 h1:m/aXAzSAqxgt74Nfd+sNzpzVKhTGl7+S9nbG4A57mF4=
@@ -450,16 +466,16 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
-go.opentelemetry.io/otel v1.13.0 h1:1ZAKnNQKwBBxFtww/GwxNUyTf0AxkZzrukO8MeXqe4Y=
-go.opentelemetry.io/otel v1.13.0/go.mod h1:FH3RtdZCzRkJYFTCsAKDy9l/XYjMdNv6QrkFFB8DvVg=
+go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
+go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
-go.opentelemetry.io/otel/sdk v1.13.0 h1:BHib5g8MvdqS65yo2vV1s6Le42Hm6rrw08qU6yz5JaM=
-go.opentelemetry.io/otel/sdk v1.13.0/go.mod h1:YLKPx5+6Vx/o1TCUYYs+bpymtkmazOMT6zoRrC7AQ7I=
+go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
+go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
-go.opentelemetry.io/otel/trace v1.13.0 h1:CBgRZ6ntv+Amuj1jDsMhZtlAPT6gbyIRdaIzFhfBSdY=
-go.opentelemetry.io/otel/trace v1.13.0/go.mod h1:muCvmmO9KKpvuXSf3KKAXXB2ygNYHQ+ZfI5X08d3tds=
+go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
+go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -510,8 +526,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -551,8 +567,8 @@ golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
+golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -625,10 +641,11 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -639,8 +656,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
-golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
+golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -690,8 +707,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/server/hack/config.yaml b/server/hack/config.yaml
index c095890..1b02d63 100644
--- a/server/hack/config.yaml
+++ b/server/hack/config.yaml
@@ -13,20 +13,18 @@ gfcli:
output: "./temp/hotgo" # 可执行文件生成路径
extra: ""
-# gf生成代码,如果你想调整hotgo中代码生成的相关dao、service代码,同样也受用于此配置
gen:
dao:
- link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true"
- group: "default" # 分组。使用hotgo代码生成功能时必须填
- # path: "./app"
- # tables: "" #指定当前数据库中需要执行代码生成的数据表。如果为空,表示数据库的所有表都会生成。
- tablesEx: "hg_sys_addons_install" #指定当前数据库中需要排除代码生成的数据表。
+ group: "default" # 分组 使用hotgo代码生成功能时必须填
+ # tables: "" # 指定当前数据库中需要执行代码生成的数据表。如果为空,表示数据库的所有表都会生成。
+ tablesEx: "hg_sys_addons_install" # 指定当前数据库中需要排除代码生成的数据表。
removePrefix: "hg_"
descriptionTag: true
noModelComment: true
jsonCase: "CamelLower"
gJsonSupport: true
- clear: true
+ clear: false
# service: # 生成业务配置
# srcFolder: "internal/logic"
diff --git a/server/internal/cmd/auth.go b/server/internal/cmd/auth.go
new file mode 100644
index 0000000..29d8fec
--- /dev/null
+++ b/server/internal/cmd/auth.go
@@ -0,0 +1,33 @@
+package cmd
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/os/gcmd"
+ "hotgo/internal/service"
+ "os"
+)
+
+var (
+ Auth = &gcmd.Command{
+ Name: "auth",
+ Brief: "系统授权,当为第三方客户开发应用项目不想将源码和可执行文件让其随意使用时,可以通过授权的方式约束使用方。",
+ Description: `目前已实现,一对一、一对多、有效期授权,具体使用可以参考现有逻辑结合实际场景进行改造`,
+ Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
+ service.TCPAuth().Start(ctx)
+
+ // 退出信号监听
+ signalListen(ctx, func(sig os.Signal) {
+ service.TCPAuth().Stop(ctx)
+ })
+
+ // 信号监听
+ signalListen(ctx, signalHandlerForOverall)
+ select {
+ case <-serverCloseSignal:
+ // ...
+ }
+
+ return
+ },
+ }
+)
diff --git a/server/internal/cmd/cmd.go b/server/internal/cmd/cmd.go
index f4ec55f..22dea96 100644
--- a/server/internal/cmd/cmd.go
+++ b/server/internal/cmd/cmd.go
@@ -80,7 +80,7 @@ var (
)
func init() {
- if err := Main.AddCommand(Http, Queue, Tools, All, Help); err != nil {
+ if err := Main.AddCommand(Http, Queue, Tools, Auth, All, Help); err != nil {
panic(err)
}
serverCloseSignal = make(chan struct{}, 1)
diff --git a/server/internal/cmd/handler_shutdown.go b/server/internal/cmd/handler_shutdown.go
index 841bce6..bcdd9e2 100644
--- a/server/internal/cmd/handler_shutdown.go
+++ b/server/internal/cmd/handler_shutdown.go
@@ -9,20 +9,10 @@ package cmd
import (
"context"
"github.com/gogf/gf/v2/os/gproc"
- "hotgo/internal/crons"
- "hotgo/internal/websocket"
"hotgo/utility/simple"
"os"
)
-func signalHandlerForCron(sig os.Signal) {
- crons.StopALL()
-}
-
-func signalHandlerForWebSocket(sig os.Signal) {
- websocket.Stop()
-}
-
func signalHandlerForOverall(sig os.Signal) {
serverCloseSignal <- struct{}{}
}
diff --git a/server/internal/cmd/http.go b/server/internal/cmd/http.go
index 30abe7e..c238e15 100644
--- a/server/internal/cmd/http.go
+++ b/server/internal/cmd/http.go
@@ -10,10 +10,13 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcmd"
+ "hotgo/internal/crons"
"hotgo/internal/library/addons"
"hotgo/internal/library/casbin"
"hotgo/internal/router"
"hotgo/internal/service"
+ "hotgo/internal/websocket"
+ "os"
)
var (
@@ -68,12 +71,20 @@ var (
// 启动定时任务
service.SysCron().StartCron(ctx)
- // 信号监听
- signalListen(ctx, signalHandlerForCron, signalHandlerForWebSocket)
+ //// 启动TCP服务
+ //service.TCPServer().Start(ctx)
// https
setSSL(ctx, s)
+ // 退出信号监听
+ signalListen(ctx, func(sig os.Signal) {
+ s.Shutdown()
+ crons.StopALL()
+ websocket.Stop()
+ //service.TCPServer().Stop(ctx)
+ })
+
// Just run the server.
s.Run()
diff --git a/server/internal/consts/version.go b/server/internal/consts/version.go
index 656009a..61f1656 100644
--- a/server/internal/consts/version.go
+++ b/server/internal/consts/version.go
@@ -7,5 +7,5 @@ package consts
// VersionApp HotGo版本
const (
- VersionApp = "2.3.5"
+ VersionApp = "2.4.2"
)
diff --git a/server/internal/crons/init.go b/server/internal/crons/init.go
index 1cc2948..e141d99 100644
--- a/server/internal/crons/init.go
+++ b/server/internal/crons/init.go
@@ -16,6 +16,7 @@ import (
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/model/entity"
+ "hotgo/utility/simple"
"strings"
"sync"
)
@@ -161,7 +162,9 @@ func Stop(sysCron *entity.SysCron) (err error) {
func Once(ctx context.Context, sysCron *entity.SysCron) error {
for _, v := range cronList {
if v.GetName() == sysCron.Name {
- go v.Execute(ctx)
+ simple.SafeGo(ctx, func(ctx context.Context) {
+ v.Execute(ctx)
+ })
return nil
}
}
diff --git a/server/internal/dao/internal/sys_serve_license.go b/server/internal/dao/internal/sys_serve_license.go
new file mode 100644
index 0000000..0ec921f
--- /dev/null
+++ b/server/internal/dao/internal/sys_serve_license.go
@@ -0,0 +1,109 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// SysServeLicenseDao is the data access object for table hg_sys_serve_license.
+type SysServeLicenseDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns SysServeLicenseColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// SysServeLicenseColumns defines and stores column names for table hg_sys_serve_license.
+type SysServeLicenseColumns struct {
+ Id string // 许可ID
+ Group string // 分组
+ Name string // 许可名称
+ Appid string // 应用ID
+ SecretKey string // 应用秘钥
+ Desc string // 授权说明
+ RemoteAddr string // 最后连接地址
+ Online string // 在线数量
+ OnlineLimit string // 在线数量限制,默认1
+ LoginTimes string // 登录次数
+ LastLoginAt string // 最后登录时间
+ LastActiveAt string // 最后活跃时间
+ Routes string // 路由表,空使用默认分组路由
+ AllowedIps string // 白名单,*代表所有,只有允许的IP才能连接到tcp服务
+ EndAt string // 授权结束时间
+ Remark string // 备注
+ Status string // 状态
+ CreatedAt string // 创建时间
+ UpdatedAt string // 修改时间
+}
+
+// sysServeLicenseColumns holds the columns for table hg_sys_serve_license.
+var sysServeLicenseColumns = SysServeLicenseColumns{
+ Id: "id",
+ Group: "group",
+ Name: "name",
+ Appid: "appid",
+ SecretKey: "secret_key",
+ Desc: "desc",
+ RemoteAddr: "remote_addr",
+ Online: "online",
+ OnlineLimit: "online_limit",
+ LoginTimes: "login_times",
+ LastLoginAt: "last_login_at",
+ LastActiveAt: "last_active_at",
+ Routes: "routes",
+ AllowedIps: "allowed_ips",
+ EndAt: "end_at",
+ Remark: "remark",
+ Status: "status",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewSysServeLicenseDao creates and returns a new DAO object for table data access.
+func NewSysServeLicenseDao() *SysServeLicenseDao {
+ return &SysServeLicenseDao{
+ group: "default",
+ table: "hg_sys_serve_license",
+ columns: sysServeLicenseColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *SysServeLicenseDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *SysServeLicenseDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *SysServeLicenseDao) Columns() SysServeLicenseColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *SysServeLicenseDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *SysServeLicenseDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *SysServeLicenseDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/server/internal/dao/sys_serve_license.go b/server/internal/dao/sys_serve_license.go
new file mode 100644
index 0000000..a96edfa
--- /dev/null
+++ b/server/internal/dao/sys_serve_license.go
@@ -0,0 +1,27 @@
+// =================================================================================
+// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
+// =================================================================================
+
+package dao
+
+import (
+ "hotgo/internal/dao/internal"
+)
+
+// internalSysServeLicenseDao is internal type for wrapping internal DAO implements.
+type internalSysServeLicenseDao = *internal.SysServeLicenseDao
+
+// sysServeLicenseDao is the data access object for table hg_sys_serve_license.
+// You can define custom methods on it to extend its functionality as you wish.
+type sysServeLicenseDao struct {
+ internalSysServeLicenseDao
+}
+
+var (
+ // SysServeLicense is globally public accessible object for table hg_sys_serve_license operations.
+ SysServeLicense = sysServeLicenseDao{
+ internal.NewSysServeLicenseDao(),
+ }
+)
+
+// Fill with you ideas below.
diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_clear.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_clear.go
index 7deb1d7..fd7d51a 100644
--- a/server/internal/library/hggen/internal/cmd/gendao/gendao_clear.go
+++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_clear.go
@@ -9,13 +9,13 @@ import (
"hotgo/internal/library/hggen/internal/utility/utils"
)
-func doClear(ctx context.Context, dirPath string) {
+func doClear(ctx context.Context, dirPath string, force bool) {
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
if err != nil {
mlog.Fatal(err)
}
for _, file := range files {
- if utils.IsFileDoNotEdit(file) {
+ if force || utils.IsFileDoNotEdit(file) {
if err = gfile.Remove(file); err != nil {
mlog.Print(err)
}
diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go
index b7797b6..0760c81 100644
--- a/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go
+++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_dao.go
@@ -24,7 +24,7 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) {
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
)
if in.Clear {
- doClear(ctx, dirPathDao)
+ doClear(ctx, dirPathDao, true)
}
for i := 0; i < len(in.TableNames); i++ {
generateDaoSingle(ctx, generateDaoSingleInput{
diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go
index 26202be..c3686ea 100644
--- a/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go
+++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_do.go
@@ -18,7 +18,7 @@ import (
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
var dirPathDo = gfile.Join(in.Path, in.DoPath)
if in.Clear {
- doClear(ctx, dirPathDo)
+ doClear(ctx, dirPathDo, false)
}
in.NoJsonTag = true
in.DescriptionTag = false
diff --git a/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go b/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go
index 0d91747..0d21061 100644
--- a/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go
+++ b/server/internal/library/hggen/internal/cmd/gendao/gendao_entity.go
@@ -16,7 +16,7 @@ import (
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
if in.Clear {
- doClear(ctx, dirPathEntity)
+ doClear(ctx, dirPathEntity, false)
}
// Model content.
for i, tableName := range in.TableNames {
diff --git a/server/internal/library/network/tcp/client.go b/server/internal/library/network/tcp/client.go
new file mode 100644
index 0000000..052cbb5
--- /dev/null
+++ b/server/internal/library/network/tcp/client.go
@@ -0,0 +1,322 @@
+package tcp
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/encoding/gjson"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/gtcp"
+ "github.com/gogf/gf/v2/os/gctx"
+ "github.com/gogf/gf/v2/os/glog"
+ "github.com/gogf/gf/v2/os/gtime"
+ "hotgo/utility/simple"
+ "reflect"
+ "sync"
+ "time"
+)
+
+// ClientConfig 客户端配置
+type ClientConfig struct {
+ Addr string
+ Auth *AuthMeta
+ Timeout time.Duration
+ ConnectInterval time.Duration
+ MaxConnectCount uint
+ ConnectCount uint
+ AutoReconnect bool
+ LoginEvent CallbackEvent
+ CloseEvent CallbackEvent
+}
+
+// Client 客户端
+type Client struct {
+ Ctx context.Context
+ Logger *glog.Logger
+ IsLogin bool // 是否已登录
+ addr string
+ auth *AuthMeta
+ timeout time.Duration
+ connectInterval time.Duration
+ maxConnectCount uint
+ connectCount uint
+ autoReconnect bool
+ loginEvent CallbackEvent
+ closeEvent CallbackEvent
+ sync.Mutex
+ heartbeat int64
+ routers map[string]RouterHandler
+ conn *gtcp.Conn
+ wg sync.WaitGroup
+ closeFlag bool // 关闭标签,关闭以后可以重连
+ stopFlag bool // 停止标签,停止以后不能重连
+}
+
+func NewClient(config *ClientConfig) (client *Client, err error) {
+ client = new(Client)
+
+ if config == nil {
+ err = gerror.New("config is nil")
+ return
+ }
+
+ if config.Addr == "" {
+ err = gerror.New("client address is not set")
+ return
+ }
+
+ if config.Auth == nil {
+ err = gerror.New("client auth cannot be empty")
+ return
+ }
+
+ if config.Auth.Group == "" || config.Auth.Name == "" {
+ err = gerror.New("Auth.Group or Auth.Group is nil")
+ return
+ }
+
+ client.Ctx = gctx.New()
+ client.autoReconnect = true
+ client.addr = config.Addr
+ client.auth = config.Auth
+ client.loginEvent = config.LoginEvent
+ client.closeEvent = config.CloseEvent
+
+ logger := glog.New()
+ path := g.Cfg().MustGet(client.Ctx, "logger.path", "logs/logger").String()
+ if err = logger.SetPath(fmt.Sprintf("%s/tcp.client/%s.%s", path, config.Auth.Group, config.Auth.Name)); err != nil {
+ return
+ }
+ client.Logger = logger
+
+ if config.ConnectInterval <= 0 {
+ client.connectInterval = 5 * time.Second
+ client.Logger.Debugf(client.Ctx, "invalid connectInterval, reset to %v", client.connectInterval)
+ } else {
+ client.connectInterval = config.ConnectInterval
+ }
+
+ if config.Timeout <= 0 {
+ client.timeout = 10 * time.Second
+ client.Logger.Debugf(client.Ctx, "invalid timeout, reset to %v", client.timeout)
+ } else {
+ client.timeout = config.Timeout
+ }
+
+ return
+}
+
+// Start 启动
+func (client *Client) Start() (err error) {
+ client.Lock()
+ defer client.Unlock()
+
+ if client.stopFlag {
+ err = gerror.New("client is stop")
+ return
+ }
+
+ if client.conn != nil {
+ return gerror.New("client is running")
+ }
+
+ client.IsLogin = false
+ client.connectCount = 0
+ client.closeFlag = false
+ client.stopFlag = false
+
+ client.wg.Add(1)
+ simple.SafeGo(client.Ctx, func(ctx context.Context) {
+ client.connect()
+ })
+
+ return
+}
+
+// RegisterRouter 注册路由
+func (client *Client) RegisterRouter(routers map[string]RouterHandler) (err error) {
+ if client.conn != nil {
+ return gerror.New("client is running")
+ }
+
+ client.Lock()
+ defer client.Unlock()
+
+ if client.routers == nil {
+ client.routers = make(map[string]RouterHandler)
+ // 默认路由
+ client.routers = map[string]RouterHandler{
+ "ResponseServerHeartbeat": client.onResponseServerHeartbeat,
+ "ResponseServerLogin": client.onResponseServerLogin,
+ }
+ }
+
+ for i, router := range routers {
+ _, ok := client.routers[i]
+ if ok {
+ return gerror.Newf("client route duplicate registration:%v", i)
+ }
+ client.routers[i] = router
+ }
+ return
+}
+
+func (client *Client) dial() *gtcp.Conn {
+ for {
+ conn, err := gtcp.NewConn(client.addr, client.timeout)
+ if err == nil || client.closeFlag {
+ return conn
+ }
+
+ if client.maxConnectCount > 0 {
+ if client.connectCount < client.maxConnectCount {
+ client.connectCount += 1
+ } else {
+ return nil
+ }
+ }
+
+ client.Logger.Debugf(client.Ctx, "connect to %v error: %v", client.addr, err)
+ time.Sleep(client.connectInterval)
+ continue
+ }
+}
+
+func (client *Client) connect() {
+ defer client.wg.Done()
+
+ goto reconnect
+reconnect:
+ conn := client.dial()
+ if conn == nil {
+ client.Logger.Debugf(client.Ctx, "client dial failed")
+ return
+ }
+
+ client.Lock()
+ if client.closeFlag {
+ client.Unlock()
+ conn.Close()
+ client.Logger.Debugf(client.Ctx, "client connect but closeFlag is true")
+ return
+ }
+
+ client.conn = conn
+ client.connectCount = 0
+ client.heartbeat = gtime.Timestamp()
+
+ client.read()
+ client.Unlock()
+
+ client.serverLogin()
+ client.startCron()
+}
+
+func (client *Client) read() {
+ simple.SafeGo(client.Ctx, func(ctx context.Context) {
+ defer func() {
+ client.Close()
+ client.Logger.Debugf(client.Ctx, "client are about to be reconnected..")
+ time.Sleep(client.connectInterval)
+ client.Start()
+ }()
+
+ for {
+ if client.conn == nil {
+ client.Logger.Debugf(client.Ctx, "client client.conn is nil, server closed")
+ break
+ }
+
+ msg, err := RecvPkg(client.conn)
+ if err != nil {
+ client.Logger.Debugf(client.Ctx, "client RecvPkg err:%+v, server closed", err)
+ break
+ }
+
+ if client.routers == nil {
+ client.Logger.Debugf(client.Ctx, "client RecvPkg routers is nil")
+ break
+ }
+
+ if msg == nil {
+ client.Logger.Debugf(client.Ctx, "client RecvPkg msg is nil")
+ break
+ }
+
+ f, ok := client.routers[msg.Router]
+ if !ok {
+ client.Logger.Debugf(client.Ctx, "client RecvPkg invalid message: %+v", msg)
+ continue
+ }
+ f(msg.Data, client.conn)
+ }
+ })
+}
+
+// Close 关闭同服务器的链接
+func (client *Client) Close() {
+ client.Lock()
+ defer client.Unlock()
+
+ client.IsLogin = false
+ client.closeFlag = true
+ if client.conn != nil {
+ client.conn.Close()
+ client.conn = nil
+ }
+
+ if client.closeEvent != nil {
+ client.closeEvent()
+ }
+ client.wg.Wait()
+}
+
+// Stop 停止服务
+func (client *Client) Stop() {
+ if client.stopFlag {
+ return
+ }
+ client.stopFlag = true
+ client.stopCron()
+ client.Close()
+}
+
+// Destroy 销毁当前连接
+func (client *Client) Destroy() {
+ client.stopCron()
+ if client.conn != nil {
+ client.conn.Close()
+ client.conn = nil
+ }
+}
+
+// Write
+func (client *Client) Write(data interface{}) error {
+ client.Lock()
+ defer client.Unlock()
+
+ if client.conn == nil {
+ return gerror.New("client conn is nil")
+ }
+
+ if client.closeFlag {
+ return gerror.New("client conn is closed")
+ }
+
+ if data == nil {
+ return gerror.New("client Write message is nil")
+ }
+
+ // 签名
+ SetSign(data, gctx.CtxId(client.Ctx), client.auth.AppId, client.auth.SecretKey)
+
+ msgType := reflect.TypeOf(data)
+ if msgType == nil || msgType.Kind() != reflect.Ptr {
+ return gerror.Newf("client json message pointer required: %+v", data)
+ }
+ msg := &Message{Router: msgType.Elem().Name(), Data: data}
+
+ client.Logger.Debugf(client.Ctx, "client Write Router:%v, data:%+v", msg.Router, gjson.New(data).String())
+
+ return SendPkg(client.conn, msg)
+}
diff --git a/server/internal/library/network/tcp/client_cron.go b/server/internal/library/network/tcp/client_cron.go
new file mode 100644
index 0000000..6245c0f
--- /dev/null
+++ b/server/internal/library/network/tcp/client_cron.go
@@ -0,0 +1,37 @@
+package tcp
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/os/gcron"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+func (client *Client) getCronKey(s string) string {
+ return fmt.Sprintf("tcp.client_%s_%s:%s", s, client.auth.Group, client.auth.Name)
+}
+
+func (client *Client) stopCron() {
+ for _, v := range gcron.Entries() {
+ gcron.Remove(v.Name)
+ }
+}
+
+func (client *Client) startCron() {
+ // 心跳超时检查
+ if gcron.Search(client.getCronKey(cronHeartbeatVerify)) == nil {
+ gcron.AddSingleton(client.Ctx, "@every 600s", func(ctx context.Context) {
+ if client.heartbeat < gtime.Timestamp()-600 {
+ client.Logger.Debugf(client.Ctx, "client heartbeat timeout, about to reconnect..")
+ client.Destroy()
+ }
+ }, client.getCronKey(cronHeartbeatVerify))
+ }
+
+ // 心跳
+ if gcron.Search(client.getCronKey(cronHeartbeat)) == nil {
+ gcron.AddSingleton(client.Ctx, "@every 120s", func(ctx context.Context) {
+ client.serverHeartbeat()
+ }, client.getCronKey(cronHeartbeat))
+ }
+}
diff --git a/server/internal/library/network/tcp/client_handle.go b/server/internal/library/network/tcp/client_handle.go
new file mode 100644
index 0000000..4e91538
--- /dev/null
+++ b/server/internal/library/network/tcp/client_handle.go
@@ -0,0 +1,61 @@
+package tcp
+
+import (
+ "github.com/gogf/gf/v2/errors/gcode"
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/internal/model/input/msgin"
+)
+
+// serverLogin 心跳
+func (client *Client) serverHeartbeat() {
+ if err := client.Write(&msgin.ServerHeartbeat{}); err != nil {
+ client.Logger.Debugf(client.Ctx, "client WriteMsg ServerHeartbeat err:%+v", err)
+ return
+ }
+}
+
+// serverLogin 服务登陆
+func (client *Client) serverLogin() {
+ data := &msgin.ServerLogin{
+ Group: client.auth.Group,
+ Name: client.auth.Name,
+ }
+
+ if err := client.Write(data); err != nil {
+ client.Logger.Debugf(client.Ctx, "client WriteMsg ServerLogin err:%+v", err)
+ return
+ }
+
+ if client.loginEvent != nil {
+ client.loginEvent()
+ }
+}
+
+func (client *Client) onResponseServerLogin(args ...interface{}) {
+ var in *msgin.ResponseServerLogin
+ if err := gconv.Scan(args[0], &in); err != nil {
+ client.Logger.Infof(client.Ctx, "onResponseServerLogin message Scan failed:%+v, args:%+v", err, args[0])
+ return
+ }
+ client.Logger.Infof(client.Ctx, "onResponseServerLogin in:%+v", *in)
+
+ if in.Code != gcode.CodeOK.Code() {
+ client.IsLogin = false
+ client.Logger.Warningf(client.Ctx, "onResponseServerLogin quit err:%v", in.Message)
+ client.Destroy()
+ return
+ }
+ client.IsLogin = true
+}
+
+func (client *Client) onResponseServerHeartbeat(args ...interface{}) {
+ var in *msgin.ResponseServerHeartbeat
+ if err := gconv.Scan(args[0], &in); err != nil {
+ client.Logger.Infof(client.Ctx, "onResponseServerHeartbeat message Scan failed:%+v, args:%+v", err, args)
+ return
+ }
+
+ client.heartbeat = gtime.Timestamp()
+ client.Logger.Infof(client.Ctx, "onResponseServerHeartbeat in:%+v", *in)
+}
diff --git a/server/internal/library/network/tcp/model.go b/server/internal/library/network/tcp/model.go
new file mode 100644
index 0000000..4b002c8
--- /dev/null
+++ b/server/internal/library/network/tcp/model.go
@@ -0,0 +1,25 @@
+package tcp
+
+// 定时任务
+const (
+ cronHeartbeatVerify = "tcpHeartbeatVerify"
+ cronHeartbeat = "tcpHeartbeat"
+)
+
+// 认证分组
+const (
+ ClientGroupCron = "cron" // 定时任务
+ ClientGroupQueue = "queue" // 消息队列
+ ClientGroupAuth = "auth" // 服务授权
+)
+
+// AuthMeta 认证元数据
+type AuthMeta struct {
+ Group string `json:"group"`
+ Name string `json:"name"`
+ AppId string `json:"appId"`
+ SecretKey string `json:"secretKey"`
+}
+
+// CallbackEvent 回调事件
+type CallbackEvent func()
diff --git a/server/internal/library/network/tcp/router.go b/server/internal/library/network/tcp/router.go
new file mode 100644
index 0000000..338be24
--- /dev/null
+++ b/server/internal/library/network/tcp/router.go
@@ -0,0 +1,39 @@
+package tcp
+
+import (
+ "encoding/json"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/net/gtcp"
+ "github.com/gogf/gf/v2/util/gconv"
+)
+
+type RouterHandler func(args ...interface{})
+
+// Message 路由消息
+type Message struct {
+ Router string `json:"router"`
+ Data interface{} `json:"data"`
+}
+
+func SendPkg(conn *gtcp.Conn, message *Message) error {
+ b, err := json.Marshal(message)
+ if err != nil {
+ return err
+ }
+ return conn.SendPkg(b)
+}
+
+func RecvPkg(conn *gtcp.Conn) (*Message, error) {
+ if data, err := conn.RecvPkg(); err != nil {
+ return nil, err
+ } else {
+ var msg = new(Message)
+ if err = gconv.Scan(data, &msg); err != nil {
+ return nil, gerror.Newf("invalid package structure: %s", err.Error())
+ }
+ if msg.Router == "" {
+ return nil, gerror.Newf("message is not routed: %+v", msg)
+ }
+ return msg, err
+ }
+}
diff --git a/server/internal/library/network/tcp/server.go b/server/internal/library/network/tcp/server.go
new file mode 100644
index 0000000..cd3647a
--- /dev/null
+++ b/server/internal/library/network/tcp/server.go
@@ -0,0 +1,278 @@
+package tcp
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/encoding/gjson"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/gtcp"
+ "github.com/gogf/gf/v2/os/gctx"
+ "github.com/gogf/gf/v2/os/glog"
+ "reflect"
+ "sync"
+ "time"
+)
+
+type ClientConn struct {
+ Conn *gtcp.Conn
+ Auth *AuthMeta
+ heartbeat int64
+ mutex sync.Mutex
+}
+
+type ServerConfig struct {
+ Name string // 服务名称
+ Addr string // 监听地址
+}
+
+type Server struct {
+ Ctx context.Context
+ Logger *glog.Logger
+ addr string
+ name string
+ ln *gtcp.Server
+ wgLn sync.WaitGroup
+ mutex sync.Mutex
+ closeFlag bool
+ clients map[string]*ClientConn // 已登录的认证客户端
+ mutexConns sync.Mutex
+ wgConns sync.WaitGroup
+ cronRouters map[string]RouterHandler // 路由
+ queueRouters map[string]RouterHandler
+ authRouters map[string]RouterHandler
+}
+
+func NewServer(config *ServerConfig) (server *Server, err error) {
+ if config == nil {
+ err = gerror.New("config is nil")
+ return
+ }
+
+ if config.Addr == "" {
+ err = gerror.New("server address is not set")
+ return
+ }
+
+ if config.Name == "" {
+ config.Name = "hotgo"
+ }
+
+ server = new(Server)
+ server.Ctx = gctx.New()
+ server.addr = config.Addr
+ server.name = config.Name
+ server.ln = gtcp.NewServer(server.addr, server.accept, config.Name)
+ server.clients = make(map[string]*ClientConn)
+ server.closeFlag = false
+
+ logger := glog.New()
+ path := g.Cfg().MustGet(server.Ctx, "logger.path", "logs/logger").String()
+ if err = logger.SetPath(fmt.Sprintf("%s/tcp.server/%s", path, config.Name)); err != nil {
+ return
+ }
+ server.Logger = logger
+
+ server.startCron()
+
+ return
+}
+
+func (server *Server) accept(conn *gtcp.Conn) {
+ defer func() {
+ server.mutexConns.Lock()
+ conn.Close()
+ // 从登录列表中移除
+ if _, ok := server.clients[conn.RemoteAddr().String()]; ok {
+ delete(server.clients, conn.RemoteAddr().String())
+ }
+ server.mutexConns.Unlock()
+ }()
+
+ for {
+ msg, err := RecvPkg(conn)
+ if err != nil {
+ server.Logger.Debugf(server.Ctx, "RecvPkg err:%+v, client closed.", err)
+ break
+ }
+
+ client := server.getLoginConn(conn)
+
+ switch msg.Router {
+ case "ServerLogin": // 服务登录
+ server.onServerLogin(msg.Data, conn)
+ case "ServerHeartbeat": // 心跳
+ if client == nil {
+ server.Logger.Infof(server.Ctx, "conn not connected, ignore the heartbeat, msg:%+v", msg)
+ continue
+ }
+ server.onServerHeartbeat(msg, client)
+ default: // 通用路由消息处理
+ if client == nil {
+ server.Logger.Warningf(server.Ctx, "conn is not logged in but sends a routing message. actively conn disconnect, msg:%+v", msg)
+ time.Sleep(time.Second)
+ conn.Close()
+ return
+ }
+ server.handleRouterMsg(msg, client)
+ }
+ }
+}
+
+// handleRouterMsg 处理路由消息
+func (server *Server) handleRouterMsg(msg *Message, client *ClientConn) {
+
+ // 验证签名
+ err := VerifySign(msg.Data, client.Auth.AppId, client.Auth.SecretKey)
+ if err != nil {
+ server.Logger.Warningf(server.Ctx, "handleRouterMsg VerifySign err:%+v message: %+v", err, msg)
+ return
+ }
+
+ handle := func(routers map[string]RouterHandler, group string) {
+ if routers == nil {
+ server.Logger.Debugf(server.Ctx, "handleRouterMsg route is not initialized %v message: %+v", group, msg)
+ return
+ }
+ f, ok := routers[msg.Router]
+ if !ok {
+ server.Logger.Debugf(server.Ctx, "handleRouterMsg invalid %v message: %+v", group, msg)
+ return
+ }
+ f(msg.Data, client)
+ }
+
+ switch client.Auth.Group {
+ case ClientGroupCron:
+ handle(server.cronRouters, client.Auth.Group)
+ case ClientGroupQueue:
+ handle(server.queueRouters, client.Auth.Group)
+ case ClientGroupAuth:
+ handle(server.authRouters, client.Auth.Group)
+ default:
+ server.Logger.Warningf(server.Ctx, "group is not registered: %+v", client.Auth.Group)
+ }
+}
+
+// getLoginConn 获取指定已登录的连接
+func (server *Server) getLoginConn(conn *gtcp.Conn) *ClientConn {
+ client, ok := server.clients[conn.RemoteAddr().String()]
+ if !ok {
+ return nil
+ }
+ return client
+}
+
+// getLoginConn 获取指定appid的所有连接
+func (server *Server) getAppIdClients(appid string) (list []*ClientConn) {
+ for _, v := range server.clients {
+ if v.Auth.AppId == appid {
+ list = append(list, v)
+ }
+ }
+ return
+}
+
+// RegisterAuthRouter 注册授权路由
+func (server *Server) RegisterAuthRouter(routers map[string]RouterHandler) {
+ server.mutex.Lock()
+ defer server.mutex.Unlock()
+
+ if server.authRouters == nil {
+ server.authRouters = make(map[string]RouterHandler)
+ }
+
+ for i, router := range routers {
+ _, ok := server.authRouters[i]
+ if ok {
+ server.Logger.Debugf(server.Ctx, "server authRouters duplicate registration:%v", i)
+ continue
+ }
+ server.authRouters[i] = router
+ }
+}
+
+// RegisterCronRouter 注册任务路由
+func (server *Server) RegisterCronRouter(routers map[string]RouterHandler) {
+ server.mutex.Lock()
+ defer server.mutex.Unlock()
+
+ if server.cronRouters == nil {
+ server.cronRouters = make(map[string]RouterHandler)
+ }
+
+ for i, router := range routers {
+ _, ok := server.cronRouters[i]
+ if ok {
+ server.Logger.Debugf(server.Ctx, "server cronRouters duplicate registration:%v", i)
+ continue
+ }
+ server.cronRouters[i] = router
+ }
+}
+
+// RegisterQueueRouter 注册队列路由
+func (server *Server) RegisterQueueRouter(routers map[string]RouterHandler) {
+ server.mutex.Lock()
+ defer server.mutex.Unlock()
+
+ if server.queueRouters == nil {
+ server.queueRouters = make(map[string]RouterHandler)
+ }
+
+ for i, router := range routers {
+ _, ok := server.queueRouters[i]
+ if ok {
+ server.Logger.Debugf(server.Ctx, "server queueRouters duplicate registration:%v", i)
+ continue
+ }
+ server.queueRouters[i] = router
+ }
+}
+
+func (server *Server) Listen() (err error) {
+ server.wgLn.Add(1)
+ defer server.wgLn.Done()
+ return server.ln.Run()
+}
+
+// Close 关闭服务
+func (server *Server) Close() {
+ if server.closeFlag {
+ return
+ }
+ server.closeFlag = true
+
+ server.stopCron()
+
+ server.mutexConns.Lock()
+ for _, client := range server.clients {
+ client.Conn.Close()
+ }
+ server.clients = nil
+ server.mutexConns.Unlock()
+ server.wgConns.Wait()
+
+ if server.ln != nil {
+ server.ln.Close()
+ }
+ server.wgLn.Wait()
+}
+
+// Write 向指定客户端发送消息
+func (server *Server) Write(conn *gtcp.Conn, data interface{}) (err error) {
+ if server.closeFlag {
+ return gerror.New("service is down")
+ }
+
+ msgType := reflect.TypeOf(data)
+ if msgType == nil || msgType.Kind() != reflect.Ptr {
+ return gerror.Newf("json message pointer required: %+v", data)
+ }
+
+ msg := &Message{Router: msgType.Elem().Name(), Data: data}
+
+ server.Logger.Debugf(server.Ctx, "server Write Router:%v, data:%+v", msg.Router, gjson.New(data).String())
+
+ return SendPkg(conn, msg)
+}
diff --git a/server/internal/library/network/tcp/server_cron.go b/server/internal/library/network/tcp/server_cron.go
new file mode 100644
index 0000000..51af795
--- /dev/null
+++ b/server/internal/library/network/tcp/server_cron.go
@@ -0,0 +1,35 @@
+package tcp
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/os/gcron"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+func (server *Server) getCronKey(s string) string {
+ return fmt.Sprintf("tcp.server_%s_%s", s, server.name)
+}
+
+func (server *Server) stopCron() {
+ for _, v := range gcron.Entries() {
+ gcron.Remove(v.Name)
+ }
+}
+
+func (server *Server) startCron() {
+ // 心跳超时检查
+ if gcron.Search(server.getCronKey(cronHeartbeatVerify)) == nil {
+ gcron.AddSingleton(server.Ctx, "@every 300s", func(ctx context.Context) {
+ if server.clients == nil {
+ return
+ }
+ for _, client := range server.clients {
+ if client.heartbeat < gtime.Timestamp()-300 {
+ client.Conn.Close()
+ server.Logger.Debugf(server.Ctx, "client heartbeat timeout, about to reconnect.. auth:%+v", client.Auth)
+ }
+ }
+ }, server.getCronKey(cronHeartbeatVerify))
+ }
+}
diff --git a/server/internal/library/network/tcp/server_handle.go b/server/internal/library/network/tcp/server_handle.go
new file mode 100644
index 0000000..168619f
--- /dev/null
+++ b/server/internal/library/network/tcp/server_handle.go
@@ -0,0 +1,150 @@
+package tcp
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/net/gtcp"
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/internal/consts"
+ "hotgo/internal/model/entity"
+ "hotgo/internal/model/input/msgin"
+ "hotgo/utility/convert"
+)
+
+func (server *Server) onServerLogin(args ...interface{}) {
+ var (
+ in = new(msgin.ServerLogin)
+ conn = args[1].(*gtcp.Conn)
+ res = new(msgin.ResponseServerLogin)
+ models *entity.SysServeLicense
+ )
+
+ if err := gconv.Scan(args[0], &in); err != nil {
+ server.Logger.Infof(server.Ctx, "onServerLogin message Scan failed:%+v, args:%+v", err, args)
+ return
+ }
+ server.Logger.Infof(server.Ctx, "onServerLogin in:%+v", *in)
+
+ err := g.Model("sys_serve_license").
+ Ctx(server.Ctx).
+ Where("appid = ?", in.AppId).
+ Scan(&models)
+
+ if err != nil {
+ res.Code = 1
+ res.Message = err.Error()
+ server.Write(conn, res)
+ return
+ }
+
+ if models == nil {
+ res.Code = 2
+ res.Message = "授权信息不存在"
+ server.Write(conn, res)
+ return
+ }
+
+ // 验证签名
+ if err = VerifySign(in, models.Appid, models.SecretKey); err != nil {
+ res.Code = 3
+ res.Message = "签名错误,请联系管理员"
+ server.Write(conn, res)
+ return
+ }
+
+ if models.Status != consts.StatusEnabled {
+ res.Code = 4
+ res.Message = "授权已禁用,请联系管理员"
+ server.Write(conn, res)
+ return
+ }
+
+ if models.Group != in.Group {
+ res.Code = 5
+ res.Message = "你登录的授权分组未得到授权,请联系管理员"
+ server.Write(conn, res)
+ return
+ }
+
+ if models.EndAt.Before(gtime.Now()) {
+ res.Code = 6
+ res.Message = "授权已过期,请联系管理员"
+ server.Write(conn, res)
+ return
+ }
+
+ allowedIps := convert.IpFilterStrategy(models.AllowedIps)
+ if _, ok := allowedIps["*"]; !ok {
+ ip := gstr.StrTillEx(conn.RemoteAddr().String(), ":")
+ if _, ok2 := allowedIps[ip]; !ok2 {
+ res.Code = 7
+ res.Message = "IP(" + ip + ")未授权,请联系管理员"
+ server.Write(conn, res)
+ return
+ }
+ }
+
+ // 检查是否存在多地登录,如果连接超出上限,直接将所有已连接断开,然后在吧新的连接加入进来
+ clients := server.getAppIdClients(models.Appid)
+ online := len(clients) + 1
+ if online > models.OnlineLimit {
+ online = 1
+ res2 := new(msgin.ResponseServerLogin)
+ res2.Code = 8
+ res2.Message = "授权登录端超出上限,请联系管理员"
+ for _, client := range clients {
+ server.Write(client.Conn, res2)
+ client.Conn.Close()
+ }
+ }
+
+ server.mutexConns.Lock()
+ server.clients[conn.RemoteAddr().String()] = &ClientConn{
+ Conn: conn,
+ Auth: &AuthMeta{
+ Group: in.Group,
+ Name: in.Name,
+ AppId: in.AppId,
+ SecretKey: models.SecretKey,
+ },
+ heartbeat: gtime.Timestamp(),
+ }
+ server.mutexConns.Unlock()
+
+ server.Write(conn, res)
+
+ _, err = g.Model("sys_serve_license").
+ Ctx(server.Ctx).
+ Where("id = ?", models.Id).Data(g.Map{
+ "online": online,
+ "login_times": models.LoginTimes + 1,
+ "last_login_at": gtime.Now(),
+ "last_active_at": gtime.Now(),
+ "remote_addr": conn.RemoteAddr().String(),
+ }).Update()
+ if err != nil {
+ server.Logger.Warningf(server.Ctx, "onServerLogin Update err:%+v", err)
+ }
+}
+
+func (server *Server) onServerHeartbeat(args ...interface{}) {
+ var in *msgin.ServerHeartbeat
+ if err := gconv.Scan(args, &in); err != nil {
+ server.Logger.Infof(server.Ctx, "onServerHeartbeat message Scan failed:%+v, args:%+v", err, args)
+ return
+ }
+ client := args[1].(*ClientConn)
+ client.heartbeat = gtime.Timestamp()
+
+ server.Write(client.Conn, &msgin.ResponseServerHeartbeat{})
+
+ _, err := g.Model("sys_serve_license").
+ Ctx(server.Ctx).
+ Where("appid = ?", client.Auth.AppId).Data(g.Map{
+ "last_active_at": gtime.Now(),
+ }).Update()
+ if err != nil {
+ server.Logger.Warningf(server.Ctx, "onServerHeartbeat Update err:%+v", err)
+ }
+}
diff --git a/server/internal/library/network/tcp/sign.go b/server/internal/library/network/tcp/sign.go
new file mode 100644
index 0000000..dd56ff6
--- /dev/null
+++ b/server/internal/library/network/tcp/sign.go
@@ -0,0 +1,41 @@
+package tcp
+
+import (
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/internal/model/input/msgin"
+)
+
+type Sign interface {
+ SetSign(traceID, appId, secretKey string)
+}
+
+// SetSign 设置签名
+func SetSign(data interface{}, traceID, appId, secretKey string) {
+ if c, ok := data.(Sign); ok {
+ c.SetSign(traceID, appId, secretKey)
+ return
+ }
+}
+
+// VerifySign 验证签名
+func VerifySign(data interface{}, appId, secretKey string) (err error) {
+ // 无密钥,无需签名
+ if secretKey == "" {
+ return
+ }
+
+ var in *msgin.Request
+ if err = gconv.Scan(data, &in); err != nil {
+ return
+ }
+
+ if appId != in.AppId {
+ return gerror.New("appId invalid")
+ }
+
+ if in.Sign != in.GetSign(secretKey) {
+ return gerror.New("sign invalid")
+ }
+ return
+}
diff --git a/server/internal/logic/logic.go b/server/internal/logic/logic.go
index 8e2ca5a..aceda20 100644
--- a/server/internal/logic/logic.go
+++ b/server/internal/logic/logic.go
@@ -10,5 +10,7 @@ import (
_ "hotgo/internal/logic/hook"
_ "hotgo/internal/logic/middleware"
_ "hotgo/internal/logic/sys"
+ _ "hotgo/internal/logic/tcpclient"
+ _ "hotgo/internal/logic/tcpserver"
_ "hotgo/internal/logic/view"
)
diff --git a/server/internal/logic/sys/blacklist.go b/server/internal/logic/sys/blacklist.go
index 58ed9a5..271a544 100644
--- a/server/internal/logic/sys/blacklist.go
+++ b/server/internal/logic/sys/blacklist.go
@@ -3,7 +3,6 @@
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
-//
package sys
import (
@@ -11,13 +10,12 @@ import (
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
- "github.com/gogf/gf/v2/text/gstr"
- "github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/global"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
+ "hotgo/utility/convert"
"hotgo/utility/validate"
)
@@ -176,91 +174,12 @@ func (s *sSysBlacklist) Load(ctx context.Context) {
return
}
- matchStrategy := func(originIp string) {
- // 多个IP
- if gstr.Contains(originIp, ",") {
- ips := gstr.Explode(",", originIp)
- if len(ips) > 0 {
- for _, ip := range ips {
- if !validate.IsIp(ip) {
- continue
- }
- global.Blacklists[ip] = struct{}{}
- }
- }
-
- return
- }
-
- // IP段
- if gstr.Contains(originIp, "/24") {
- segment := gstr.Replace(originIp, "/24", "")
- if !validate.IsIp(segment) {
- return
- }
-
- var (
- start = gstr.Explode(".", segment)
- prefix = gstr.Implode(".", start[:len(start)-1]) + "."
- index = gconv.Int(start[len(start)-1])
- )
-
- if index < 1 {
- index = 1
- }
-
- for i := index; i <= 254; i++ {
- global.Blacklists[prefix+gconv.String(i)] = struct{}{}
- }
-
- return
- }
-
- // IP范围
- if gstr.Contains(originIp, "-") {
- originIps := gstr.Explode("-", originIp)
- if len(originIps) != 2 {
- return
- }
-
- if !validate.IsIp(originIps[0]) || !validate.IsIp(originIps[1]) {
- return
- }
-
- var (
- start = gstr.Explode(".", originIps[0])
- prefix = gstr.Implode(".", start[:len(start)-1]) + "."
- startIndex = gconv.Int(gstr.SubStrFromREx(originIps[0], "."))
- endIndex = gconv.Int(gstr.SubStrFromREx(originIps[1], "."))
- )
-
- if startIndex >= endIndex {
- global.Blacklists[originIps[0]] = struct{}{}
- return
- }
-
- if startIndex < 1 {
- startIndex = 1
- }
-
- if endIndex > 254 {
- endIndex = 254
- }
-
- for i := startIndex; i <= endIndex; i++ {
- global.Blacklists[prefix+gconv.String(i)] = struct{}{}
- }
- return
- }
-
- // 指定IP
- if validate.IsIp(originIp) {
- global.Blacklists[originIp] = struct{}{}
- return
- }
- }
-
for _, v := range array {
- matchStrategy(v.String())
+ list := convert.IpFilterStrategy(v.String())
+ if len(list) > 0 {
+ for k, _ := range list {
+ global.Blacklists[k] = struct{}{}
+ }
+ }
}
}
diff --git a/server/internal/logic/tcpclient/auth.go b/server/internal/logic/tcpclient/auth.go
new file mode 100644
index 0000000..7e305c3
--- /dev/null
+++ b/server/internal/logic/tcpclient/auth.go
@@ -0,0 +1,110 @@
+package tcpclient
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/errors/gcode"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gcron"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/internal/library/network/tcp"
+ "hotgo/internal/model/input/msgin"
+ "hotgo/internal/service"
+ "hotgo/utility/simple"
+)
+
+// tcp授权
+type sTCPAuth struct {
+ client *tcp.Client
+}
+
+func init() {
+ service.RegisterTCPAuth(newTCPAuth())
+}
+
+func newTCPAuth() *sTCPAuth {
+ return &sTCPAuth{}
+}
+
+// Start 启动服务
+func (s *sTCPAuth) Start(ctx context.Context) {
+ g.Log().Debug(ctx, "TCPAuth start..")
+ simple.SafeGo(ctx, func(ctx context.Context) {
+ client, err := tcp.NewClient(&tcp.ClientConfig{
+ Addr: "127.0.0.1:8099",
+ Auth: &tcp.AuthMeta{
+ Group: "auth",
+ Name: "auth1",
+ AppId: "mengshuai",
+ SecretKey: "123456",
+ },
+ LoginEvent: s.loginEvent,
+ CloseEvent: s.closeEvent,
+ })
+ if err != nil {
+ g.Log().Infof(ctx, "TCPAuth NewClient fail:%+v", err)
+ return
+ }
+
+ s.client = client
+
+ err = s.client.RegisterRouter(map[string]tcp.RouterHandler{
+ "ResponseAuthSummary": s.onResponseAuthSummary, // 获取授权信息
+ })
+
+ if err != nil {
+ g.Log().Infof(ctx, "TCPAuth RegisterRouter fail:%+v", err)
+ return
+ }
+
+ if err = s.client.Start(); err != nil {
+ g.Log().Infof(ctx, "TCPAuth Start fail:%+v", err)
+ return
+ }
+ })
+}
+
+// Stop 关闭服务
+func (s *sTCPAuth) Stop(ctx context.Context) {
+ if s.client != nil {
+ s.client.Stop()
+ g.Log().Debug(ctx, "TCPAuth stop..")
+ }
+}
+
+func (s *sTCPAuth) loginEvent() {
+ // 登录成功后立即请求一次授权信息
+ s.client.Write(&msgin.AuthSummary{})
+
+ // 定时检查授权
+ gcron.Add(s.client.Ctx, "@every 1200s", func(ctx context.Context) {
+ if !s.client.IsLogin {
+ g.Log().Infof(ctx, "TCPAuthVerify client is not logged in, skipped")
+ return
+ }
+ s.client.Write(&msgin.AuthSummary{})
+ }, "TCPAuthVerify")
+}
+
+func (s *sTCPAuth) closeEvent() {
+ // 关闭连接后,删除定时检查授权
+ gcron.Remove("TCPAuthVerify")
+}
+
+func (s *sTCPAuth) onResponseAuthSummary(args ...interface{}) {
+ var in *msgin.ResponseAuthSummary
+ if err := gconv.Scan(args[0], &in); err != nil {
+ s.client.Logger.Infof(s.client.Ctx, "ResponseAuthSummary message Scan failed:%+v, args:%+v", err, args[0])
+ return
+ }
+ s.client.Logger.Infof(s.client.Ctx, "onResponseAuthSummary in:%+v", *in)
+
+ // 授权异常
+ if in.Code != gcode.CodeOK.Code() {
+ s.client.Logger.Infof(s.client.Ctx, "onResponseAuthSummary authorization verification failed:%+v", in.Message)
+ s.client.Destroy()
+ return
+ }
+
+ // 授权通过
+ // 后续可以做一些操作...
+}
diff --git a/server/internal/logic/tcpserver/auth_handle.go b/server/internal/logic/tcpserver/auth_handle.go
new file mode 100644
index 0000000..8a15885
--- /dev/null
+++ b/server/internal/logic/tcpserver/auth_handle.go
@@ -0,0 +1,73 @@
+package tcpserver
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/internal/consts"
+ "hotgo/internal/dao"
+ "hotgo/internal/library/network/tcp"
+ "hotgo/internal/model/entity"
+ "hotgo/internal/model/input/msgin"
+)
+
+// onAuthSummary 获取授权信息
+func (s *sTCPServer) onAuthSummary(args ...interface{}) {
+ var (
+ in *msgin.AuthSummary
+ client = args[1].(*tcp.ClientConn)
+ res = new(msgin.ResponseAuthSummary)
+ models *entity.SysServeLicense
+ )
+
+ if err := gconv.Scan(args, &in); err != nil {
+ s.serv.Logger.Infof(s.serv.Ctx, "onAuthSummary message Scan failed:%+v, args:%+v", err, args)
+ return
+ }
+
+ if client.Auth == nil {
+ res.Code = 1
+ res.Message = "登录信息获取失败,请重新登录"
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ if err := dao.SysServeLicense.Ctx(s.serv.Ctx).Where("appid = ?", client.Auth.AppId).Scan(&models); err != nil {
+ res.Code = 2
+ res.Message = err.Error()
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ if models == nil {
+ res.Code = 3
+ res.Message = "授权信息不存在"
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ if models.Status != consts.StatusEnabled {
+ res.Code = 4
+ res.Message = "授权已禁用,请联系管理员"
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ if models.Group != client.Auth.Group {
+ res.Code = 5
+ res.Message = "你登录的授权分组未得到授权,请联系管理员"
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ if models.EndAt.Before(gtime.Now()) {
+ res.Code = 6
+ res.Message = "授权已过期,请联系管理员"
+ s.serv.Write(client.Conn, res)
+ return
+ }
+
+ res.Data = new(msgin.AuthSummaryData)
+ res.Data.EndAt = models.EndAt
+ res.Data.Online = models.Online
+ s.serv.Write(client.Conn, res)
+}
diff --git a/server/internal/logic/tcpserver/init.go b/server/internal/logic/tcpserver/init.go
new file mode 100644
index 0000000..9497fc6
--- /dev/null
+++ b/server/internal/logic/tcpserver/init.go
@@ -0,0 +1,68 @@
+package tcpserver
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/internal/library/network/tcp"
+ "hotgo/internal/service"
+ "hotgo/utility/simple"
+)
+
+type sTCPServer struct {
+ serv *tcp.Server
+}
+
+func init() {
+ service.RegisterTCPServer(newTCPServer())
+}
+
+func newTCPServer() *sTCPServer {
+ return &sTCPServer{}
+}
+
+// Start 启动服务
+func (s *sTCPServer) Start(ctx context.Context) {
+ simple.SafeGo(ctx, func(ctx context.Context) {
+ g.Log().Debug(ctx, "TCPServer start..")
+
+ server, err := tcp.NewServer(&tcp.ServerConfig{
+ Name: "hotgo",
+ Addr: g.Cfg().MustGet(ctx, "tcpServe.address").String(),
+ })
+
+ if err != nil {
+ g.Log().Warningf(ctx, "TCPServer start fail:%+v", err)
+ return
+ }
+
+ s.serv = server
+
+ // 消息队列路由
+ s.serv.RegisterQueueRouter(map[string]tcp.RouterHandler{
+ // ...
+ })
+
+ // 定时任务路由
+ s.serv.RegisterCronRouter(map[string]tcp.RouterHandler{
+ // ...
+ })
+
+ // 授权服务路由
+ s.serv.RegisterAuthRouter(map[string]tcp.RouterHandler{
+ "AuthSummary": s.onAuthSummary, // 获取授权信息
+ })
+
+ // 服务监听
+ if err := s.serv.Listen(); err != nil {
+ g.Log().Warningf(ctx, "TCPServer Listen err:%v", err)
+ }
+ })
+}
+
+// Stop 关闭服务
+func (s *sTCPServer) Stop(ctx context.Context) {
+ if s.serv != nil {
+ s.serv.Close()
+ g.Log().Debug(ctx, "TCPServer stop..")
+ }
+}
diff --git a/server/internal/model/do/sys_serve_license.go b/server/internal/model/do/sys_serve_license.go
new file mode 100644
index 0000000..c7cc423
--- /dev/null
+++ b/server/internal/model/do/sys_serve_license.go
@@ -0,0 +1,35 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package do
+
+import (
+ "github.com/gogf/gf/v2/encoding/gjson"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysServeLicense is the golang structure of table hg_sys_serve_license for DAO operations like Where/Data.
+type SysServeLicense struct {
+ g.Meta `orm:"table:hg_sys_serve_license, do:true"`
+ Id interface{} // 许可ID
+ Group interface{} // 分组
+ Name interface{} // 许可名称
+ Appid interface{} // 应用ID
+ SecretKey interface{} // 应用秘钥
+ Desc interface{} // 授权说明
+ RemoteAddr interface{} // 最后连接地址
+ Online interface{} // 在线数量
+ OnlineLimit interface{} // 在线数量限制,默认1
+ LoginTimes interface{} // 登录次数
+ LastLoginAt *gtime.Time // 最后登录时间
+ LastActiveAt *gtime.Time // 最后活跃时间
+ Routes *gjson.Json // 路由表,空使用默认分组路由
+ AllowedIps interface{} // 白名单,*代表所有,只有允许的IP才能连接到tcp服务
+ EndAt *gtime.Time // 授权结束时间
+ Remark interface{} // 备注
+ Status interface{} // 状态
+ CreatedAt *gtime.Time // 创建时间
+ UpdatedAt *gtime.Time // 修改时间
+}
diff --git a/server/internal/model/entity/sys_serve_license.go b/server/internal/model/entity/sys_serve_license.go
new file mode 100644
index 0000000..0492f97
--- /dev/null
+++ b/server/internal/model/entity/sys_serve_license.go
@@ -0,0 +1,33 @@
+// =================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/encoding/gjson"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// SysServeLicense is the golang structure for table sys_serve_license.
+type SysServeLicense struct {
+ Id int64 `json:"id" description:"许可ID"`
+ Group string `json:"group" description:"分组"`
+ Name string `json:"name" description:"许可名称"`
+ Appid string `json:"appid" description:"应用ID"`
+ SecretKey string `json:"secretKey" description:"应用秘钥"`
+ Desc string `json:"desc" description:"授权说明"`
+ RemoteAddr string `json:"remoteAddr" description:"最后连接地址"`
+ Online int `json:"online" description:"在线数量"`
+ OnlineLimit int `json:"onlineLimit" description:"在线数量限制,默认1"`
+ LoginTimes int64 `json:"loginTimes" description:"登录次数"`
+ LastLoginAt *gtime.Time `json:"lastLoginAt" description:"最后登录时间"`
+ LastActiveAt *gtime.Time `json:"lastActiveAt" description:"最后活跃时间"`
+ Routes *gjson.Json `json:"routes" description:"路由表,空使用默认分组路由"`
+ AllowedIps string `json:"allowedIps" description:"白名单,*代表所有,只有允许的IP才能连接到tcp服务"`
+ EndAt *gtime.Time `json:"endAt" description:"授权结束时间"`
+ Remark string `json:"remark" description:"备注"`
+ Status int `json:"status" description:"状态"`
+ CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
+ UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
+}
diff --git a/server/internal/model/input/msgin/auth.go b/server/internal/model/input/msgin/auth.go
new file mode 100644
index 0000000..542a137
--- /dev/null
+++ b/server/internal/model/input/msgin/auth.go
@@ -0,0 +1,19 @@
+package msgin
+
+import "github.com/gogf/gf/v2/os/gtime"
+
+// AuthSummary 授权摘要
+type AuthSummary struct {
+ Request
+}
+
+// ResponseAuthSummary 响应授权摘要
+type ResponseAuthSummary struct {
+ Response
+ Data *AuthSummaryData `json:"data,omitempty" description:"数据集"`
+}
+
+type AuthSummaryData struct {
+ EndAt *gtime.Time `json:"end_at" description:"授权过期时间"`
+ Online int `json:"online" description:"在线人数"`
+}
diff --git a/server/internal/model/input/msgin/common.go b/server/internal/model/input/msgin/common.go
new file mode 100644
index 0000000..7a9a88b
--- /dev/null
+++ b/server/internal/model/input/msgin/common.go
@@ -0,0 +1,61 @@
+package msgin
+
+import (
+ "fmt"
+ "github.com/gogf/gf/v2/os/gtime"
+ "hotgo/utility/encrypt"
+)
+
+type Request struct {
+ AppId string `json:"appID" v:"0" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"应用ID"`
+ TraceID string `json:"traceID" v:"0" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"链路ID"`
+ Timestamp int64 `json:"timestamp" example:"1640966400" description:"服务器时间戳"`
+ Sign string `json:"sign" example:"d0bb93048bc5c9164cdee845dcb7f820" description:"签名"`
+}
+
+func (i *Request) SetSign(traceID, appId, secretKey string) {
+ i.AppId = appId
+ i.TraceID = traceID
+ i.Timestamp = gtime.Timestamp()
+ i.Sign = i.GetSign(secretKey)
+}
+
+func (i *Request) GetSign(secretKey string) string {
+ return encrypt.Md5ToString(fmt.Sprintf("%s%s%s%s", i.AppId, i.TraceID, i.Timestamp, secretKey))
+}
+
+type Response struct {
+ Code int `json:"code" example:"0" description:"状态码"`
+ Message string `json:"message,omitempty" example:"操作成功" description:"提示消息"`
+ //Data interface{} `json:"data,omitempty" description:"数据集"`
+}
+
+// ServerHeartbeat 心跳
+type ServerHeartbeat struct {
+}
+
+// ResponseServerHeartbeat 响应心跳
+type ResponseServerHeartbeat struct {
+ Response
+}
+
+// ServerLogin 服务登录
+type ServerLogin struct {
+ Request
+ Group string
+ Name string
+}
+
+// ResponseServerLogin 响应服务登录
+type ResponseServerLogin struct {
+ Response
+}
+
+// ServerOffline 服务离线
+type ServerOffline struct {
+}
+
+// ResponseServerOffline 响应服务离线
+type ResponseServerOffline struct {
+ Response
+}
diff --git a/server/internal/service/admin.go b/server/internal/service/admin.go
index 5f63c18..7b505bd 100644
--- a/server/internal/service/admin.go
+++ b/server/internal/service/admin.go
@@ -114,7 +114,6 @@ type (
)
var (
- localAdminPost IAdminPost
localAdminRole IAdminRole
localAdminDept IAdminDept
localAdminMember IAdminMember
@@ -122,41 +121,9 @@ var (
localAdminMenu IAdminMenu
localAdminMonitor IAdminMonitor
localAdminNotice IAdminNotice
+ localAdminPost IAdminPost
)
-func AdminDept() IAdminDept {
- if localAdminDept == nil {
- panic("implement not found for interface IAdminDept, forgot register?")
- }
- return localAdminDept
-}
-
-func RegisterAdminDept(i IAdminDept) {
- localAdminDept = i
-}
-
-func AdminMember() IAdminMember {
- if localAdminMember == nil {
- panic("implement not found for interface IAdminMember, forgot register?")
- }
- return localAdminMember
-}
-
-func RegisterAdminMember(i IAdminMember) {
- localAdminMember = i
-}
-
-func AdminMemberPost() IAdminMemberPost {
- if localAdminMemberPost == nil {
- panic("implement not found for interface IAdminMemberPost, forgot register?")
- }
- return localAdminMemberPost
-}
-
-func RegisterAdminMemberPost(i IAdminMemberPost) {
- localAdminMemberPost = i
-}
-
func AdminMenu() IAdminMenu {
if localAdminMenu == nil {
panic("implement not found for interface IAdminMenu, forgot register?")
@@ -211,3 +178,36 @@ func AdminRole() IAdminRole {
func RegisterAdminRole(i IAdminRole) {
localAdminRole = i
}
+
+func AdminDept() IAdminDept {
+ if localAdminDept == nil {
+ panic("implement not found for interface IAdminDept, forgot register?")
+ }
+ return localAdminDept
+}
+
+func RegisterAdminDept(i IAdminDept) {
+ localAdminDept = i
+}
+
+func AdminMember() IAdminMember {
+ if localAdminMember == nil {
+ panic("implement not found for interface IAdminMember, forgot register?")
+ }
+ return localAdminMember
+}
+
+func RegisterAdminMember(i IAdminMember) {
+ localAdminMember = i
+}
+
+func AdminMemberPost() IAdminMemberPost {
+ if localAdminMemberPost == nil {
+ panic("implement not found for interface IAdminMemberPost, forgot register?")
+ }
+ return localAdminMemberPost
+}
+
+func RegisterAdminMemberPost(i IAdminMemberPost) {
+ localAdminMemberPost = i
+}
diff --git a/server/internal/service/sys.go b/server/internal/service/sys.go
index 637ddac..3fcda23 100644
--- a/server/internal/service/sys.go
+++ b/server/internal/service/sys.go
@@ -17,148 +17,6 @@ import (
)
type (
- ISysAddonsConfig interface {
- GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
- ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error)
- UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) error
- }
- ISysAttachment interface {
- Delete(ctx context.Context, in sysin.AttachmentDeleteInp) error
- Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
- Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
- MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (*sysin.AttachmentMaxSortModel, error)
- View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
- List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
- Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (data *entity.SysAttachment, err error)
- }
- ISysBlacklist interface {
- Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
- Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
- Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
- MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (*sysin.BlacklistMaxSortModel, error)
- View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
- List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
- VariableLoad(ctx context.Context, err error)
- Load(ctx context.Context)
- }
- ISysEmsLog interface {
- Delete(ctx context.Context, in sysin.EmsLogDeleteInp) error
- Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
- Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
- View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
- List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
- Send(ctx context.Context, in sysin.SendEmsInp) (err error)
- GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
- AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
- VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
- }
- ISysGenCodes interface {
- Delete(ctx context.Context, in sysin.GenCodesDeleteInp) error
- Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
- Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
- MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (*sysin.GenCodesMaxSortModel, error)
- View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
- List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
- Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
- TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
- ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
- ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
- Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
- Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
- }
- ISysServeLog interface {
- Model(ctx context.Context) *gdb.Model
- List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
- Export(ctx context.Context, in sysin.ServeLogListInp) (err error)
- Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error)
- View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
- RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
- }
- ISysSmsLog interface {
- Delete(ctx context.Context, in sysin.SmsLogDeleteInp) error
- Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error)
- Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error)
- MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (*sysin.SmsLogMaxSortModel, error)
- View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
- List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
- SendCode(ctx context.Context, in sysin.SendCodeInp) (err error)
- GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
- AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
- VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error)
- }
- ISysAddons interface {
- List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
- Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
- Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
- Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
- Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
- UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
- }
- ISysConfig interface {
- GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
- GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
- GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
- GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
- GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
- GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
- GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
- GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
- GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
- GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
- GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
- ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
- UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
- }
- ISysLog interface {
- Export(ctx context.Context, in sysin.LogListInp) (err error)
- RealWrite(ctx context.Context, commonLog entity.SysLog) (err error)
- AutoLog(ctx context.Context) error
- AnalysisLog(ctx context.Context) entity.SysLog
- View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
- Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
- List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
- }
- ISysLoginLog interface {
- Model(ctx context.Context) *gdb.Model
- List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
- Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
- Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
- View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
- Push(ctx context.Context, in sysin.LoginLogPushInp)
- RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
- }
- ISysCronGroup interface {
- Delete(ctx context.Context, in sysin.CronGroupDeleteInp) error
- Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
- Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
- MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (*sysin.CronGroupMaxSortModel, error)
- View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
- List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
- Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
- }
- ISysCurdDemo interface {
- Model(ctx context.Context, option ...*handler.Option) *gdb.Model
- List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
- Export(ctx context.Context, in sysin.CurdDemoListInp) (err error)
- Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error)
- Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error)
- MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
- View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
- Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error)
- Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error)
- }
- ISysDictData interface {
- Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
- Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
- List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
- Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
- }
- ISysDictType interface {
- Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error)
- Delete(ctx context.Context, in sysin.DictTypeDeleteInp) error
- Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error)
- TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
- }
ISysProvinces interface {
Tree(ctx context.Context) (list []g.Map, err error)
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) error
@@ -181,28 +39,302 @@ type (
List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error)
OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error)
}
+ ISysCronGroup interface {
+ Delete(ctx context.Context, in sysin.CronGroupDeleteInp) error
+ Edit(ctx context.Context, in sysin.CronGroupEditInp) (err error)
+ Status(ctx context.Context, in sysin.CronGroupStatusInp) (err error)
+ MaxSort(ctx context.Context, in sysin.CronGroupMaxSortInp) (*sysin.CronGroupMaxSortModel, error)
+ View(ctx context.Context, in sysin.CronGroupViewInp) (res *sysin.CronGroupViewModel, err error)
+ List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error)
+ Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error)
+ }
+ ISysEmsLog interface {
+ Delete(ctx context.Context, in sysin.EmsLogDeleteInp) error
+ Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error)
+ Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error)
+ View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error)
+ List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error)
+ Send(ctx context.Context, in sysin.SendEmsInp) (err error)
+ GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error)
+ AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error)
+ VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error)
+ }
+ ISysLoginLog interface {
+ Model(ctx context.Context) *gdb.Model
+ List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
+ Export(ctx context.Context, in sysin.LoginLogListInp) (err error)
+ Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error)
+ View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
+ Push(ctx context.Context, in sysin.LoginLogPushInp)
+ RealWrite(ctx context.Context, models entity.SysLoginLog) (err error)
+ }
+ ISysAddons interface {
+ List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error)
+ Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error)
+ Build(ctx context.Context, in sysin.AddonsBuildInp) (err error)
+ Install(ctx context.Context, in sysin.AddonsInstallInp) (err error)
+ Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error)
+ UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error)
+ }
+ ISysGenCodes interface {
+ Delete(ctx context.Context, in sysin.GenCodesDeleteInp) error
+ Edit(ctx context.Context, in sysin.GenCodesEditInp) (res *sysin.GenCodesEditModel, err error)
+ Status(ctx context.Context, in sysin.GenCodesStatusInp) (err error)
+ MaxSort(ctx context.Context, in sysin.GenCodesMaxSortInp) (*sysin.GenCodesMaxSortModel, error)
+ View(ctx context.Context, in sysin.GenCodesViewInp) (res *sysin.GenCodesViewModel, err error)
+ List(ctx context.Context, in sysin.GenCodesListInp) (list []*sysin.GenCodesListModel, totalCount int, err error)
+ Selects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error)
+ TableSelect(ctx context.Context, in sysin.GenCodesTableSelectInp) (res []*sysin.GenCodesTableSelectModel, err error)
+ ColumnSelect(ctx context.Context, in sysin.GenCodesColumnSelectInp) (res []*sysin.GenCodesColumnSelectModel, err error)
+ ColumnList(ctx context.Context, in sysin.GenCodesColumnListInp) (res []*sysin.GenCodesColumnListModel, err error)
+ Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error)
+ Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error)
+ }
+ ISysAddonsConfig interface {
+ GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error)
+ ConversionType(ctx context.Context, models *entity.SysAddonsConfig) (value interface{}, err error)
+ UpdateConfigByGroup(ctx context.Context, in sysin.UpdateAddonsConfigInp) error
+ }
+ ISysAttachment interface {
+ Delete(ctx context.Context, in sysin.AttachmentDeleteInp) error
+ Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
+ Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error)
+ MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (*sysin.AttachmentMaxSortModel, error)
+ View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error)
+ List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
+ Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (data *entity.SysAttachment, err error)
+ }
+ ISysServeLog interface {
+ Model(ctx context.Context) *gdb.Model
+ List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error)
+ Export(ctx context.Context, in sysin.ServeLogListInp) (err error)
+ Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error)
+ View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error)
+ RealWrite(ctx context.Context, models entity.SysServeLog) (err error)
+ }
+ ISysSmsLog interface {
+ Delete(ctx context.Context, in sysin.SmsLogDeleteInp) error
+ Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error)
+ Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error)
+ MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (*sysin.SmsLogMaxSortModel, error)
+ View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error)
+ List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error)
+ SendCode(ctx context.Context, in sysin.SendCodeInp) (err error)
+ GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error)
+ AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error)
+ VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error)
+ }
+ ISysDictType interface {
+ Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error)
+ Delete(ctx context.Context, in sysin.DictTypeDeleteInp) error
+ Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error)
+ TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error)
+ }
+ ISysLog interface {
+ Export(ctx context.Context, in sysin.LogListInp) (err error)
+ RealWrite(ctx context.Context, commonLog entity.SysLog) (err error)
+ AutoLog(ctx context.Context) error
+ AnalysisLog(ctx context.Context) entity.SysLog
+ View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error)
+ Delete(ctx context.Context, in sysin.LogDeleteInp) (err error)
+ List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
+ }
+ ISysBlacklist interface {
+ Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
+ Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
+ Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
+ MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (*sysin.BlacklistMaxSortModel, error)
+ View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
+ List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
+ VariableLoad(ctx context.Context, err error)
+ Load(ctx context.Context)
+ }
+ ISysConfig interface {
+ GetLoadCache(ctx context.Context) (conf *model.CacheConfig, err error)
+ GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
+ GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
+ GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
+ GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
+ GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
+ GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
+ GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
+ GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
+ GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
+ GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
+ ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
+ UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
+ }
+ ISysCurdDemo interface {
+ Model(ctx context.Context, option ...*handler.Option) *gdb.Model
+ List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error)
+ Export(ctx context.Context, in sysin.CurdDemoListInp) (err error)
+ Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error)
+ Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error)
+ MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error)
+ View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error)
+ Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error)
+ Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error)
+ }
+ ISysDictData interface {
+ Delete(ctx context.Context, in sysin.DictDataDeleteInp) error
+ Edit(ctx context.Context, in sysin.DictDataEditInp) (err error)
+ List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error)
+ Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error)
+ }
)
var (
- localSysCron ISysCron
+ localSysAddonsConfig ISysAddonsConfig
localSysAttachment ISysAttachment
- localSysBlacklist ISysBlacklist
- localSysEmsLog ISysEmsLog
- localSysGenCodes ISysGenCodes
localSysServeLog ISysServeLog
localSysSmsLog ISysSmsLog
- localSysAddonsConfig ISysAddonsConfig
+ localSysBlacklist ISysBlacklist
localSysConfig ISysConfig
- localSysLog ISysLog
- localSysLoginLog ISysLoginLog
- localSysAddons ISysAddons
localSysCurdDemo ISysCurdDemo
localSysDictData ISysDictData
localSysDictType ISysDictType
- localSysProvinces ISysProvinces
+ localSysLog ISysLog
+ localSysCron ISysCron
localSysCronGroup ISysCronGroup
+ localSysEmsLog ISysEmsLog
+ localSysLoginLog ISysLoginLog
+ localSysProvinces ISysProvinces
+ localSysAddons ISysAddons
+ localSysGenCodes ISysGenCodes
)
+func SysDictData() ISysDictData {
+ if localSysDictData == nil {
+ panic("implement not found for interface ISysDictData, forgot register?")
+ }
+ return localSysDictData
+}
+
+func RegisterSysDictData(i ISysDictData) {
+ localSysDictData = i
+}
+
+func SysDictType() ISysDictType {
+ if localSysDictType == nil {
+ panic("implement not found for interface ISysDictType, forgot register?")
+ }
+ return localSysDictType
+}
+
+func RegisterSysDictType(i ISysDictType) {
+ localSysDictType = i
+}
+
+func SysLog() ISysLog {
+ if localSysLog == nil {
+ panic("implement not found for interface ISysLog, forgot register?")
+ }
+ return localSysLog
+}
+
+func RegisterSysLog(i ISysLog) {
+ localSysLog = i
+}
+
+func SysBlacklist() ISysBlacklist {
+ if localSysBlacklist == nil {
+ panic("implement not found for interface ISysBlacklist, forgot register?")
+ }
+ return localSysBlacklist
+}
+
+func RegisterSysBlacklist(i ISysBlacklist) {
+ localSysBlacklist = i
+}
+
+func SysConfig() ISysConfig {
+ if localSysConfig == nil {
+ panic("implement not found for interface ISysConfig, forgot register?")
+ }
+ return localSysConfig
+}
+
+func RegisterSysConfig(i ISysConfig) {
+ localSysConfig = i
+}
+
+func SysCurdDemo() ISysCurdDemo {
+ if localSysCurdDemo == nil {
+ panic("implement not found for interface ISysCurdDemo, forgot register?")
+ }
+ return localSysCurdDemo
+}
+
+func RegisterSysCurdDemo(i ISysCurdDemo) {
+ localSysCurdDemo = i
+}
+
+func SysLoginLog() ISysLoginLog {
+ if localSysLoginLog == nil {
+ panic("implement not found for interface ISysLoginLog, forgot register?")
+ }
+ return localSysLoginLog
+}
+
+func RegisterSysLoginLog(i ISysLoginLog) {
+ localSysLoginLog = i
+}
+
+func SysProvinces() ISysProvinces {
+ if localSysProvinces == nil {
+ panic("implement not found for interface ISysProvinces, forgot register?")
+ }
+ return localSysProvinces
+}
+
+func RegisterSysProvinces(i ISysProvinces) {
+ localSysProvinces = i
+}
+
+func SysCron() ISysCron {
+ if localSysCron == nil {
+ panic("implement not found for interface ISysCron, forgot register?")
+ }
+ return localSysCron
+}
+
+func RegisterSysCron(i ISysCron) {
+ localSysCron = i
+}
+
+func SysCronGroup() ISysCronGroup {
+ if localSysCronGroup == nil {
+ panic("implement not found for interface ISysCronGroup, forgot register?")
+ }
+ return localSysCronGroup
+}
+
+func RegisterSysCronGroup(i ISysCronGroup) {
+ localSysCronGroup = i
+}
+
+func SysEmsLog() ISysEmsLog {
+ if localSysEmsLog == nil {
+ panic("implement not found for interface ISysEmsLog, forgot register?")
+ }
+ return localSysEmsLog
+}
+
+func RegisterSysEmsLog(i ISysEmsLog) {
+ localSysEmsLog = i
+}
+
+func SysAddons() ISysAddons {
+ if localSysAddons == nil {
+ panic("implement not found for interface ISysAddons, forgot register?")
+ }
+ return localSysAddons
+}
+
+func RegisterSysAddons(i ISysAddons) {
+ localSysAddons = i
+}
+
func SysGenCodes() ISysGenCodes {
if localSysGenCodes == nil {
panic("implement not found for interface ISysGenCodes, forgot register?")
@@ -214,17 +346,6 @@ func RegisterSysGenCodes(i ISysGenCodes) {
localSysGenCodes = i
}
-func SysServeLog() ISysServeLog {
- if localSysServeLog == nil {
- panic("implement not found for interface ISysServeLog, forgot register?")
- }
- return localSysServeLog
-}
-
-func RegisterSysServeLog(i ISysServeLog) {
- localSysServeLog = i
-}
-
func SysSmsLog() ISysSmsLog {
if localSysSmsLog == nil {
panic("implement not found for interface ISysSmsLog, forgot register?")
@@ -258,134 +379,13 @@ func RegisterSysAttachment(i ISysAttachment) {
localSysAttachment = i
}
-func SysBlacklist() ISysBlacklist {
- if localSysBlacklist == nil {
- panic("implement not found for interface ISysBlacklist, forgot register?")
+func SysServeLog() ISysServeLog {
+ if localSysServeLog == nil {
+ panic("implement not found for interface ISysServeLog, forgot register?")
}
- return localSysBlacklist
+ return localSysServeLog
}
-func RegisterSysBlacklist(i ISysBlacklist) {
- localSysBlacklist = i
-}
-
-func SysEmsLog() ISysEmsLog {
- if localSysEmsLog == nil {
- panic("implement not found for interface ISysEmsLog, forgot register?")
- }
- return localSysEmsLog
-}
-
-func RegisterSysEmsLog(i ISysEmsLog) {
- localSysEmsLog = i
-}
-
-func SysAddons() ISysAddons {
- if localSysAddons == nil {
- panic("implement not found for interface ISysAddons, forgot register?")
- }
- return localSysAddons
-}
-
-func RegisterSysAddons(i ISysAddons) {
- localSysAddons = i
-}
-
-func SysConfig() ISysConfig {
- if localSysConfig == nil {
- panic("implement not found for interface ISysConfig, forgot register?")
- }
- return localSysConfig
-}
-
-func RegisterSysConfig(i ISysConfig) {
- localSysConfig = i
-}
-
-func SysLog() ISysLog {
- if localSysLog == nil {
- panic("implement not found for interface ISysLog, forgot register?")
- }
- return localSysLog
-}
-
-func RegisterSysLog(i ISysLog) {
- localSysLog = i
-}
-
-func SysLoginLog() ISysLoginLog {
- if localSysLoginLog == nil {
- panic("implement not found for interface ISysLoginLog, forgot register?")
- }
- return localSysLoginLog
-}
-
-func RegisterSysLoginLog(i ISysLoginLog) {
- localSysLoginLog = i
-}
-
-func SysProvinces() ISysProvinces {
- if localSysProvinces == nil {
- panic("implement not found for interface ISysProvinces, forgot register?")
- }
- return localSysProvinces
-}
-
-func RegisterSysProvinces(i ISysProvinces) {
- localSysProvinces = i
-}
-
-func SysCronGroup() ISysCronGroup {
- if localSysCronGroup == nil {
- panic("implement not found for interface ISysCronGroup, forgot register?")
- }
- return localSysCronGroup
-}
-
-func RegisterSysCronGroup(i ISysCronGroup) {
- localSysCronGroup = i
-}
-
-func SysCurdDemo() ISysCurdDemo {
- if localSysCurdDemo == nil {
- panic("implement not found for interface ISysCurdDemo, forgot register?")
- }
- return localSysCurdDemo
-}
-
-func RegisterSysCurdDemo(i ISysCurdDemo) {
- localSysCurdDemo = i
-}
-
-func SysDictData() ISysDictData {
- if localSysDictData == nil {
- panic("implement not found for interface ISysDictData, forgot register?")
- }
- return localSysDictData
-}
-
-func RegisterSysDictData(i ISysDictData) {
- localSysDictData = i
-}
-
-func SysDictType() ISysDictType {
- if localSysDictType == nil {
- panic("implement not found for interface ISysDictType, forgot register?")
- }
- return localSysDictType
-}
-
-func RegisterSysDictType(i ISysDictType) {
- localSysDictType = i
-}
-
-func SysCron() ISysCron {
- if localSysCron == nil {
- panic("implement not found for interface ISysCron, forgot register?")
- }
- return localSysCron
-}
-
-func RegisterSysCron(i ISysCron) {
- localSysCron = i
+func RegisterSysServeLog(i ISysServeLog) {
+ localSysServeLog = i
}
diff --git a/server/internal/service/tcpclient.go b/server/internal/service/tcpclient.go
new file mode 100644
index 0000000..6baca21
--- /dev/null
+++ b/server/internal/service/tcpclient.go
@@ -0,0 +1,32 @@
+// ================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// You can delete these comments if you wish manually maintain this interface file.
+// ================================================================================
+
+package service
+
+import (
+ "context"
+)
+
+type (
+ ITCPAuth interface {
+ Start(ctx context.Context)
+ Stop(ctx context.Context)
+ }
+)
+
+var (
+ localTCPAuth ITCPAuth
+)
+
+func TCPAuth() ITCPAuth {
+ if localTCPAuth == nil {
+ panic("implement not found for interface ITCPAuth, forgot register?")
+ }
+ return localTCPAuth
+}
+
+func RegisterTCPAuth(i ITCPAuth) {
+ localTCPAuth = i
+}
diff --git a/server/internal/service/tcpserver.go b/server/internal/service/tcpserver.go
new file mode 100644
index 0000000..700e151
--- /dev/null
+++ b/server/internal/service/tcpserver.go
@@ -0,0 +1,32 @@
+// ================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// You can delete these comments if you wish manually maintain this interface file.
+// ================================================================================
+
+package service
+
+import (
+ "context"
+)
+
+type (
+ ITCPServer interface {
+ Start(ctx context.Context)
+ Stop(ctx context.Context)
+ }
+)
+
+var (
+ localTCPServer ITCPServer
+)
+
+func TCPServer() ITCPServer {
+ if localTCPServer == nil {
+ panic("implement not found for interface ITCPServer, forgot register?")
+ }
+ return localTCPServer
+}
+
+func RegisterTCPServer(i ITCPServer) {
+ localTCPServer = i
+}
diff --git a/server/manifest/config/config.example.yaml b/server/manifest/config/config.example.yaml
index d76efc7..44d13e2 100644
--- a/server/manifest/config/config.example.yaml
+++ b/server/manifest/config/config.example.yaml
@@ -51,6 +51,10 @@ server:
pprofPattern: "/pprof" # 开启PProf时有效,表示PProf特性的页面访问路径,对当前Server绑定的所有域名有效。
+tcpServe:
+ address: ":8099" # tcp服务监听地址
+
+
# Global logging.
logger:
level: "all"
diff --git a/server/storage/data/hotgo.sql b/server/storage/data/hotgo.sql
index 26117e5..ca35a33 100644
--- a/server/storage/data/hotgo.sql
+++ b/server/storage/data/hotgo.sql
@@ -1,13 +1,14 @@
-- phpMyAdmin SQL Dump
--- version 5.2.1
+-- version 4.9.0.1
-- https://www.phpmyadmin.net/
--
--- 主机: localhost
--- 生成日期: 2023-02-26 06:04:12
--- 服务器版本: 5.7.41
--- PHP 版本: 7.3.33
+-- 主机: localhost:3306
+-- 生成日期: 2023-03-13 16:58:42
+-- 服务器版本: 5.7.38-log
+-- PHP 版本: 5.6.40
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
@@ -72,8 +73,8 @@ CREATE TABLE `hg_addon_hgexample_table` (
--
INSERT INTO `hg_addon_hgexample_table` (`id`, `category_id`, `flag`, `title`, `description`, `content`, `image`, `images`, `attachfile`, `attachfiles`, `map`, `star`, `price`, `views`, `activity_at`, `start_at`, `end_at`, `switch`, `sort`, `avatar`, `sex`, `qq`, `email`, `mobile`, `hobby`, `channel`, `city_id`, `pid`, `level`, `tree`, `remark`, `status`, `created_by`, `updated_by`, `created_at`, `updated_at`, `deleted_at`) VALUES
-(1, 1, '[1, 2]', '测试标题', '描述', '这是内容............
', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg\", \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg\"]', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx\", \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc\"]', '[{\"key\": \"qwe\", \"value\": \"123\"}, {\"key\": \"asd\", \"value\": \"456\"}]', 3.0, 88.00, 10, '2022-12-23', '2022-12-01 00:00:00', '2022-12-31 23:59:59', 1, 20, '', 15, '133814250', '133814250@qq.com', '15303830571', '[3, 2, 1]', 1, 140406, 0, 1, '', '备注!', 1, 1, 1, '2022-12-15 19:30:14', '2023-02-23 13:59:00', NULL),
-(2, 0, '[1]', '测试2', '描述', '不知道写点啥!

', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg\"]', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc\"]', '{}', 2.5, 10.00, 0, '2023-02-18', NULL, NULL, 2, 30, '', 0, '', '1561561@qq.com', '15303830571', '[2, 1]', 3, 140214, 0, 1, '', '', 1, 1, 1, '2023-02-06 14:17:11', '2023-02-23 13:59:01', NULL);
+(1, 1, '[1, 2]', '测试标题', '描述', '这是内容............
', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg\", \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg\"]', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx\", \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc\"]', '[{\"key\": \"qwe\", \"value\": \"123\"}, {\"key\": \"asd\", \"value\": \"456\"}]', '3.0', '88.00', 10, '2022-12-23', '2022-12-01 00:00:00', '2022-12-31 23:59:59', 1, 20, '', 15, '133814250', '133814250@qq.com', '15303830571', '[3, 2, 1]', 1, 140406, 0, 1, '', '备注!', 1, 1, 1, '2022-12-15 19:30:14', '2023-02-23 15:08:14', NULL),
+(2, 0, '[1]', '测试2', '描述', '不知道写点啥!

', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg\"]', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx', '[\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc\"]', '{}', '2.5', '10.00', 0, '2023-02-18', NULL, NULL, 2, 30, '', 0, '', '1561561@qq.com', '15303830571', '[2, 1]', 3, 140214, 0, 1, '', '', 1, 1, 1, '2023-02-06 14:17:11', '2023-02-23 13:59:01', NULL);
-- --------------------------------------------------------
@@ -111,7 +112,7 @@ INSERT INTO `hg_admin_dept` (`id`, `pid`, `name`, `code`, `type`, `leader`, `pho
(106, 101, '财务部门', 'finance', 'dept', 'hotgo', '15888888888', 'hotgo@qq.com', 3, 'tr_100 tr_101 ', 4, 1, '2022-01-04 17:54:52', '2023-01-24 21:17:49'),
(107, 101, '运维部门', 'maintain', '', 'hotgo', '15888888888', 'hotgo@qq.com', 3, 'tr_100 tr_101 ', 5, 1, '2022-01-04 09:54:52', '2023-01-24 21:17:34'),
(108, 102, '市场部门', 'market', 'dept', 'hotgo', '15888888888', 'hotgo@qq.com', 3, 'tr_100 tr_102 ', 1, 1, '2022-01-04 17:54:52', '2023-01-24 21:18:04'),
-(112, 0, '测试', '测试', '', '', '', '', 1, NULL, 0, 1, '2022-08-14 19:38:54', '2022-08-14 19:38:54');
+(112, 0, '测试', '测试', '', '', '', '', 1, NULL, 0, 1, '2022-08-14 19:38:54', '2023-02-26 00:26:35');
-- --------------------------------------------------------
@@ -154,9 +155,9 @@ CREATE TABLE `hg_admin_member` (
--
INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `auth_key`, `password_reset_token`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES
-(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '9faedb6ee1154e382ac85ce6a7d48e74', '', 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '{\"name\": \"孟帅\", \"account\": \"15303830571\", \"payeeCode\": \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg\"}', '2023-02-23 23:19:12', NULL, 1, '2021-02-12 17:59:45', '2023-02-23 23:19:11'),
-(3, 100, 2, '测试账号', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '2c7db9eca4ed02a718e794ba4c904f56', '', 0.00, 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', NULL, NULL, '', 1, '2022-02-11 17:59:45', '2023-01-10 16:47:00'),
-(8, 105, 206, 'ameng', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', '936cbef93c8b9e879122604cea5ba5e6', '', 0.00, '', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', NULL, '2023-02-06 16:44:22', '', 1, '2023-02-03 17:34:31', '2023-02-09 14:11:02');
+(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '58d8b63af5f7fccd87b052539c0a090e', '', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '{\"name\": \"孟帅\", \"account\": \"15303830571\", \"payeeCode\": \"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg\"}', '2023-03-11 16:55:34', NULL, 1, '2021-02-12 17:59:45', '2023-03-11 16:55:33'),
+(3, 100, 2, '测试账号', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '2c7db9eca4ed02a718e794ba4c904f56', '', '0.00', 'http://alioss.qvnidaye.com//images/2021/03/12/image_1615529198_vMK4kwq2.jpg', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', NULL, NULL, '', 1, '2022-02-11 17:59:45', '2023-01-10 16:47:00'),
+(8, 105, 206, 'ameng', 'ameng', '4501790a9b89f4e66f4417c899836511', 'hfuUEb', '0d796b377f77f1e1d42278eedbab6110', '', '0.00', '', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', NULL, '2023-03-05 15:25:49', '', 1, '2023-02-03 17:34:31', '2023-02-26 00:31:13');
-- --------------------------------------------------------
@@ -178,7 +179,8 @@ INSERT INTO `hg_admin_member_post` (`member_id`, `post_id`) VALUES
(3, 4),
(7, 3),
(7, 4),
-(8, 2);
+(8, 2),
+(9, 3);
-- --------------------------------------------------------
@@ -278,7 +280,7 @@ INSERT INTO `hg_admin_menu` (`id`, `pid`, `title`, `name`, `path`, `icon`, `type
(2097, 0, '开发工具', 'Develops', '/develop', 'CodeOutlined', 1, '/develop/code', '', '', 'LAYOUT', 1, '', 0, 0, '', 0, 0, 0, 1, '', 120, '', 1, '2022-09-18 21:32:27', '2023-01-10 17:23:25'),
(2098, 2097, '代码生成', 'develop_code', 'code', '', 2, '', '', '', '/develop/code/index', 1, '', 0, 0, '', 0, 0, 0, 2, '', 10, '', 1, '2022-09-18 21:32:46', '2022-09-18 21:32:46'),
(2099, 2120, 'API文档', 'https://hotgo.facms.cn/swagger', '/docs', '', 1, '', '', '', 'LAYOUT', 1, '', 0, 1, 'https://hotgo.facms.cn/swagger', 0, 0, 0, 2, '', 1000, '', 1, '2022-09-18 21:34:09', '2023-02-22 18:55:13'),
-(2100, 2120, '使用文档', 'https://github.com/bufanyun/hotgo/tree/v2.0/docs', '/hotgo', '', 1, '', '', '', 'LAYOUT', 1, '', 0, 0, '', 0, 0, 0, 2, '', 1100, '', 1, '2022-09-18 21:35:17', '2023-02-22 18:53:21'),
+(2100, 2120, '使用文档', 'https://github.com/bufanyun/hotgo/tree/v2.0/docs/guide-zh-CN', '/hotgo', '', 1, '', '', '', 'LAYOUT', 1, '', 0, 0, '', 0, 0, 0, 2, '', 1100, '', 1, '2022-09-18 21:35:17', '2023-02-22 18:53:21'),
(2102, 0, '关于', 'about', '/about', 'ProjectOutlined', 1, '/about/index', '', '', 'LAYOUT', 1, 'about_index', 1, 0, '', 0, 0, 0, 1, '', 9000, '', 1, '2022-09-18 13:37:04', '2022-11-24 00:09:05'),
(2103, 2102, '关于详情', 'about_index', 'index', '', 2, '', '', '', '/about/index', 1, 'about_index', 0, 0, '', 0, 1, 0, 2, '', 10, '', 1, '2022-09-18 13:38:00', '2022-09-18 21:38:25'),
(2109, 2062, '编辑用户', 'org_user_edit', '', '', 3, '', '/member/edit', '', '/', 1, '', 0, 0, '', 0, 1, 0, 3, '', 10, '', 1, '2022-11-22 23:49:17', '2023-01-10 17:42:01'),
@@ -385,7 +387,8 @@ CREATE TABLE `hg_admin_notice_read` (
INSERT INTO `hg_admin_notice_read` (`id`, `notice_id`, `member_id`, `clicks`, `updated_at`, `created_at`) VALUES
(17, 31, 1, 7, '2023-02-19 23:24:24', '2023-02-09 14:06:04'),
(18, 32, 1, 8, '2023-02-19 15:46:16', '2023-02-19 15:45:56'),
-(19, 30, 1, 9, '2023-02-22 18:55:36', '2023-02-19 15:46:01');
+(19, 30, 1, 11, '2023-02-24 10:29:07', '2023-02-19 15:46:01'),
+(20, 29, 1, 0, '2023-02-24 10:29:08', '2023-02-24 10:29:08');
-- --------------------------------------------------------
@@ -411,7 +414,7 @@ CREATE TABLE `hg_admin_post` (
INSERT INTO `hg_admin_post` (`id`, `code`, `name`, `remark`, `sort`, `status`, `created_at`, `updated_at`) VALUES
(1, 'ceo', '董事长', '', 1, 1, '2022-01-04 17:54:52', '2023-01-18 00:00:00'),
(2, 'se', '项目经理', '', 2, 1, '2022-01-04 17:54:52', '2023-01-18 00:00:00'),
-(3, 'hr', '人力资源', '', 3, 1, '2022-01-04 17:54:52', '2023-01-18 00:00:00'),
+(3, 'hr', '人力资源', '', 3, 1, '2022-01-04 17:54:52', '2023-02-26 00:32:40'),
(4, 'user', '普通员工', '', 4, 1, '2022-01-04 17:54:52', '2022-05-15 22:33:09'),
(6, 'test', '测试', '测试..', 5, 1, '2022-08-14 11:41:22', '2023-01-24 21:21:42');
@@ -474,113 +477,110 @@ CREATE TABLE `hg_admin_role_casbin` (
--
INSERT INTO `hg_admin_role_casbin` (`id`, `p_type`, `v0`, `v1`, `v2`, `v3`, `v4`, `v5`) VALUES
-(6084, 'p', 'norm', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6085, 'p', 'norm', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6086, 'p', 'norm', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6087, 'p', 'norm', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6088, 'p', 'norm', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6089, 'p', 'norm', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6090, 'p', 'norm', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6091, 'p', 'norm', '/menu/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6092, 'p', 'norm', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6093, 'p', 'norm', '/log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6094, 'p', 'norm', '/log/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6095, 'p', 'norm', '/loginLog/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6096, 'p', 'norm', '/serve_log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6097, 'p', 'norm', '/notice/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6098, 'p', 'norm', '/attachment/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6099, 'p', 'norm', '/provinces/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6100, 'p', 'norm', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6101, 'p', 'norm', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6102, 'p', 'norm', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6103, 'p', 'norm', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6104, 'p', 'norm', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6105, 'p', 'norm', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6106, 'p', 'norm', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6107, 'p', 'norm', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6108, 'p', 'norm', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6109, 'p', 'norm', '/upload/image', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6110, 'p', 'norm', '/hgexample/test/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6111, 'p', 'norm', '/hgexample/test/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6112, 'p', 'test', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6113, 'p', 'test', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6114, 'p', 'test', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6115, 'p', 'test', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6116, 'p', 'test', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6117, 'p', 'test', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6118, 'p', 'test', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6119, 'p', 'test', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6120, 'p', 'test', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6121, 'p', 'test', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6122, 'p', 'test', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6123, 'p', 'test', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6124, 'p', 'test', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6125, 'p', 'test', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6126, 'p', 'test', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6127, 'p', 'test', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6128, 'p', 'test', '/hgexample/test/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6129, 'p', 'test', '/hgexample/test/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6130, 'p', 'gold_agent', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6131, 'p', 'gold_agent', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6132, 'p', 'gold_agent', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6133, 'p', 'silver_agent', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6134, 'p', 'silver_agent', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6135, 'p', 'silver_agent', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6136, 'p', 'copper_agent', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6137, 'p', 'copper_agent', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6138, 'p', 'copper_agent', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6139, 'p', 'finance', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6140, 'p', 'finance', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6141, 'p', 'finance', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6142, 'p', 'finance', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6143, 'p', 'finance', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6144, 'p', 'finance', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6145, 'p', 'finance', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6146, 'p', 'finance', '/menu/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6147, 'p', 'finance', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6148, 'p', 'finance', '/log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6149, 'p', 'finance', '/log/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6150, 'p', 'finance', '/loginLog/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6151, 'p', 'finance', '/serve_log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6152, 'p', 'finance', '/notice/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6153, 'p', 'finance', '/attachment/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6154, 'p', 'finance', '/provinces/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6155, 'p', 'finance', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6156, 'p', 'finance', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6157, 'p', 'finance', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6158, 'p', 'finance', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6159, 'p', 'finance', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6160, 'p', 'finance', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6161, 'p', 'finance', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6162, 'p', 'finance', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6163, 'p', 'finance', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6164, 'p', 'finance', '/upload/image', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6165, 'p', 'finance', '/hgexample/test/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6166, 'p', 'finance', '/hgexample/test/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6167, 'p', 'finance', '/loginLog/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6168, 'p', 'finance', '/loginLog/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6169, 'p', 'finance', '/serveLog/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6170, 'p', 'finance', '/serveLog/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6171, 'p', 'finance', '/notice/maxSort', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6172, 'p', 'finance', '/notice/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6173, 'p', 'finance', '/notice/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6174, 'p', 'finance', '/notice/switch', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6175, 'p', 'finance', '/notice/editNotify', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6176, 'p', 'finance', '/notice/editNotice', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6177, 'p', 'finance', '/notice/editLetter', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6178, 'p', 'finance', '/notice/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6179, 'p', 'finance', '/test/maxSort', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6180, 'p', 'finance', '/test/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6181, 'p', 'finance', '/test/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6182, 'p', 'finance', '/test/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6183, 'p', 'finance', '/test/switch', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6184, 'p', 'finance', '/test/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6185, 'p', 'business', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6186, 'p', 'business', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6187, 'p', 'business', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6188, 'p', 'science', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6189, 'p', 'science', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
-(6190, 'p', 'science', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', '');
+(8238, 'p', 'norm', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8239, 'p', 'norm', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8240, 'p', 'norm', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8241, 'p', 'norm', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8242, 'p', 'norm', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8243, 'p', 'norm', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8244, 'p', 'norm', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8245, 'p', 'norm', '/menu/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8246, 'p', 'norm', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8247, 'p', 'norm', '/log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8248, 'p', 'norm', '/log/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8249, 'p', 'norm', '/loginLog/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8250, 'p', 'norm', '/serve_log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8251, 'p', 'norm', '/notice/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8252, 'p', 'norm', '/attachment/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8253, 'p', 'norm', '/provinces/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8254, 'p', 'norm', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8255, 'p', 'norm', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8256, 'p', 'norm', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8257, 'p', 'norm', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8258, 'p', 'norm', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8259, 'p', 'norm', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8260, 'p', 'norm', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8261, 'p', 'norm', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8262, 'p', 'norm', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8263, 'p', 'norm', '/upload/image', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8264, 'p', 'norm', '/hgexample/table/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8265, 'p', 'norm', '/hgexample/table/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8266, 'p', 'test', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8267, 'p', 'test', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8268, 'p', 'test', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8269, 'p', 'test', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8270, 'p', 'test', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8271, 'p', 'test', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8272, 'p', 'test', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8273, 'p', 'test', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8274, 'p', 'test', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8275, 'p', 'test', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8276, 'p', 'test', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8277, 'p', 'test', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8278, 'p', 'test', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8279, 'p', 'test', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8280, 'p', 'test', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8281, 'p', 'test', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8282, 'p', 'test', '/hgexample/table/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8283, 'p', 'test', '/hgexample/table/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8284, 'p', 'gold_agent', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8285, 'p', 'gold_agent', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8286, 'p', 'gold_agent', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8287, 'p', 'silver_agent', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8288, 'p', 'silver_agent', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8289, 'p', 'silver_agent', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8290, 'p', 'finance', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8291, 'p', 'finance', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8292, 'p', 'finance', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8293, 'p', 'finance', '/dept/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8294, 'p', 'finance', '/post/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8295, 'p', 'finance', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8296, 'p', 'finance', '/member/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8297, 'p', 'finance', '/menu/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8298, 'p', 'finance', '/role/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8299, 'p', 'finance', '/log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8300, 'p', 'finance', '/log/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8301, 'p', 'finance', '/loginLog/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8302, 'p', 'finance', '/serve_log/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8303, 'p', 'finance', '/notice/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8304, 'p', 'finance', '/attachment/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8305, 'p', 'finance', '/provinces/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8306, 'p', 'finance', '/member/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8307, 'p', 'finance', '/member/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8308, 'p', 'finance', '/member/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8309, 'p', 'finance', '/dept/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8310, 'p', 'finance', '/dept/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8311, 'p', 'finance', '/dept/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8312, 'p', 'finance', '/post/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8313, 'p', 'finance', '/post/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8314, 'p', 'finance', '/post/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8315, 'p', 'finance', '/upload/image', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8316, 'p', 'finance', '/hgexample/table/list', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8317, 'p', 'finance', '/hgexample/table/view', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8318, 'p', 'finance', '/loginLog/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8319, 'p', 'finance', '/loginLog/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8320, 'p', 'finance', '/serveLog/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8321, 'p', 'finance', '/serveLog/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8322, 'p', 'finance', '/notice/maxSort', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8323, 'p', 'finance', '/notice/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8324, 'p', 'finance', '/notice/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8325, 'p', 'finance', '/notice/switch', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8326, 'p', 'finance', '/notice/editNotify', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8327, 'p', 'finance', '/notice/editNotice', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8328, 'p', 'finance', '/notice/editLetter', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8329, 'p', 'finance', '/notice/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8330, 'p', 'finance', '/test/maxSort', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8331, 'p', 'finance', '/test/export', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8332, 'p', 'finance', '/test/delete', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8333, 'p', 'finance', '/test/status', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8334, 'p', 'finance', '/test/switch', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8335, 'p', 'finance', '/test/edit', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8336, 'p', 'business', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8337, 'p', 'business', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8338, 'p', 'business', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8339, 'p', 'science', 'dashboard', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8340, 'p', 'science', '/console/stat', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', ''),
+(8341, 'p', 'science', 'dashboard_workplace', 'GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD', '', '', '');
-- --------------------------------------------------------
@@ -821,7 +821,7 @@ CREATE TABLE `hg_sys_addons_install` (
--
INSERT INTO `hg_sys_addons_install` (`id`, `name`, `version`, `status`, `created_at`, `updated_at`) VALUES
-(1, 'hgexample', 'v1.0.0', 1, '2023-02-02 00:00:00', '2023-02-23 21:59:22');
+(1, 'hgexample', 'v1.0.0', 1, '2023-02-02 00:00:00', '2023-02-24 11:00:08');
-- --------------------------------------------------------
@@ -857,13 +857,13 @@ INSERT INTO `hg_sys_attachment` (`id`, `app_id`, `member_id`, `cate_id`, `drive`
(38, 'admin', 1, 0, 'ucloud', 'logo.png', 'images', 'image/png', '', 'hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 'hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 38601, 'png', '492c0e0f0eb8e7e6c7b6901d32854d19', 1, '2023-02-09 11:54:12', '2023-02-09 11:54:12'),
(39, 'admin', 1, 0, 'ucloud', '8dfb227d9fd9e99caa884b1f450bcc1.jpg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg', 'hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg', 433261, 'jpg', '9c9d1077c59b7be96473b68226c2d875', 1, '2023-02-09 11:54:30', '2023-02-09 11:54:30'),
(40, 'admin', 1, 0, 'ucloud', 'image.png', 'images', 'image/png', '', 'hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png', 'hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png', 34850, 'png', '340f4c2f7a2d92c1d982bbecd58d01a9', 1, '2023-02-09 11:55:40', '2023-02-09 11:55:40'),
-(41, 'admin', 1, 0, 'ucloud', 'p8.itc.webp', 'images', 'image/webp', '', 'hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', 'hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', 78100, 'webp', 'f38a6aefccaa6c6aff6a8d73bce108e2', 1, '2023-02-09 11:57:07', '2023-02-09 11:57:07'),
+(41, 'admin', 1, 0, 'ucloud', 'p8.itc.webp', 'images', 'image/webp', '', 'hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', 'hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', 78100, 'webp', 'f38a6aefccaa6c6aff6a8d73bce108e2', 1, '2023-02-09 11:57:07', '2023-03-11 10:03:35'),
(42, 'admin', 1, 0, 'ucloud', 'pic4.zhimg.jpg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg', 'hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg', 59608, 'jpg', '4f7b441436d8f18d848c83df3d5fd77c', 1, '2023-02-09 11:57:12', '2023-02-09 11:57:12'),
(43, 'admin', 1, 0, 'ucloud', 'u=366042725,4290979312&fm=224&app=112&f=JPEG.jpg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg', 'hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg', 44488, 'jpg', '5a70496e61671cb9bea61c04144ed26a', 1, '2023-02-09 11:57:15', '2023-02-09 11:57:15'),
(44, 'admin', 1, 0, 'ucloud', '测试1.doc', 'document', 'application/msword', 'text/plain', 'hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc', 'hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc', 9216, 'doc', '7b82c3bdd93f2bd53dbb6bdb8220428a', 1, '2023-02-09 11:57:24', '2023-02-09 11:58:37'),
(45, 'admin', 1, 0, 'ucloud', '测试2.xlsx', 'document', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'text/plain', 'hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx', 'hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx', 9800, 'xlsx', 'df3457614fd455a6486a0c1dcf6e0603', 1, '2023-02-09 11:57:28', '2023-02-09 11:58:33'),
(46, 'admin', 1, 0, 'ucloud', 'image.png', 'images', 'image/png', '', 'hotgo/attachment/2023-02-09/cqdqbknawlkgdttuxl.png', 'hotgo/attachment/2023-02-09/cqdqbknawlkgdttuxl.png', 34427, 'png', '7aeffef602e92d4c51e1860be0e08321', 1, '2023-02-09 11:58:20', '2023-02-09 11:58:20'),
-(47, 'admin', 1, 0, 'ucloud', 'f9dcd100baa1cd11d3d39ced8c66dcf4c2ce2d16.jpeg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', 'hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', 64239, 'jpeg', 'd5f74ac9e8e96cbf12401f8e254d2652', 1, '2023-02-09 11:58:25', '2023-02-09 11:58:25'),
+(47, 'admin', 1, 0, 'ucloud', 'f9dcd100baa1cd11d3d39ced8c66dcf4c2ce2d16.jpeg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', 'hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', 64239, 'jpeg', 'd5f74ac9e8e96cbf12401f8e254d2652', 1, '2023-02-09 11:58:25', '2023-03-11 10:06:05'),
(48, 'admin', 1, 0, 'ucloud', '91ef76c6a7efce1bb8209a0a26e18bd9b58f651a.jpeg', 'images', 'image/jpeg', '', 'hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg', 'hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg', 24114, 'jpeg', '1a863f439969021a89783b55a68c8756', 1, '2023-02-09 11:58:29', '2023-02-09 11:58:29'),
(49, 'admin', 1, 0, 'ucloud', 'image.png', 'images', 'image/png', '', 'hotgo/attachment/2023-02-09/cqdr8ebbk6x4t9kdnc.png', 'hotgo/attachment/2023-02-09/cqdr8ebbk6x4t9kdnc.png', 51172, 'png', '1eff6a983d2758c23549ccc0fd530346', 1, '2023-02-09 12:41:13', '2023-02-09 12:41:13'),
(50, 'admin', 1, 0, 'ucloud', 'image.png', 'images', 'image/png', '', 'hotgo/attachment/2023-02-09/cqdr8lj1mpl0eu0jpn.png', 'hotgo/attachment/2023-02-09/cqdr8lj1mpl0eu0jpn.png', 34759, 'png', '0c17d9daec3550d5ecbf17ba9872f0a4', 1, '2023-02-09 12:41:28', '2023-02-09 12:41:28');
@@ -1150,25 +1150,25 @@ CREATE TABLE `hg_sys_dict_type` (
INSERT INTO `hg_sys_dict_type` (`id`, `pid`, `name`, `type`, `sort`, `remark`, `status`, `created_at`, `updated_at`) VALUES
(1, 27, '用户性别', 'sys_user_sex', 0, '用户性别列表', 1, '2021-01-30 13:27:43', '2021-03-24 11:38:47'),
-(2, 28, '菜单状态', 'sys_show_hide', 0, '菜单状态列表', 1, '2021-01-30 13:27:43', NULL),
+(2, 28, '菜单状态', 'sys_show_hide', 0, '', 1, '2021-01-30 13:27:43', '2023-02-26 00:46:18'),
(3, 28, '系统状态', 'sys_normal_disable', 0, '系统状态列表', 1, '2021-01-30 13:27:43', NULL),
(4, 26, '任务状态', 'sys_job_status', 0, '任务状态列表', 1, '2021-01-30 13:27:43', NULL),
(5, 26, '任务分组', 'sys_job_group', 0, '任务分组列表', 1, '2021-01-30 13:27:43', NULL),
(7, 29, '通知类型', 'sys_notice_type', 0, '通知类型列表', 1, '2021-01-30 13:27:43', NULL),
-(9, 28, '操作类型', 'sys_oper_type', 0, '操作类型列表', 1, '2021-01-30 13:27:43', NULL),
+(9, 28, '操作类型', 'sys_oper_type', 0, '', 1, '2021-01-30 13:27:43', '2023-02-26 00:48:01'),
(22, 25, '请求方式', 'sys_oper_method', 0, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
(23, 25, '请求状态码', 'req_code', 0, '', 1, '2022-01-25 10:22:40', '2022-01-25 10:22:40'),
(24, 25, '请求耗时', 'req_take_up_time', 0, '', 1, '2022-01-25 15:51:19', '2022-01-25 15:51:19'),
(25, 0, '请求枚举', 'req', 40, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
(26, 0, '任务枚举', 'job', 30, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
(27, 0, '组织枚举', 'org', 20, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
-(28, 0, '系统枚举', 'sys', 10, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
+(28, 0, '系统枚举', 'sys', 10, '', 1, '2022-01-24 11:33:16', '2023-02-26 00:33:13'),
(29, 0, '通知枚举', 'notice', 50, '', 1, '2022-01-24 11:33:16', '2022-01-24 11:33:16'),
(30, 27, '用户爱好', 'sys_user_hobby', 0, NULL, 1, '2021-03-01 11:41:07', '2021-03-01 11:41:07'),
(31, 27, '用户渠道', 'sys_user_channel', 0, NULL, 1, '2021-03-01 11:41:07', '2021-03-01 11:41:07'),
(32, 0, '配置枚举', 'config', 60, '', 1, '2022-12-30 17:55:42', '2022-12-30 17:55:53'),
(33, 32, '上传驱动', 'config_upload_drive', 10, '', 1, '2022-12-30 17:57:18', '2022-12-30 17:57:18'),
-(34, 28, '日志类型', 'sys_log_type', 50, '', 1, '2023-01-20 16:39:52', '2023-01-20 16:39:52'),
+(34, 28, '日志类型', 'sys_log_type', 50, '', 1, '2023-01-20 16:39:52', '2023-02-24 17:40:45'),
(35, 32, '短信驱动', 'config_sms_drive', 20, '', 1, '2023-01-21 10:27:01', '2023-01-21 10:27:01'),
(36, 32, '短信模板', 'config_sms_template', 30, '', 1, '2023-01-21 10:27:41', '2023-01-21 10:27:41'),
(37, 29, '通知标签', 'sys_notice_tag', 20, '', 1, '2023-01-26 12:09:46', '2023-01-26 12:09:46'),
@@ -1228,7 +1228,7 @@ CREATE TABLE `hg_sys_gen_codes` (
--
INSERT INTO `hg_sys_gen_codes` (`id`, `gen_type`, `gen_template`, `var_name`, `options`, `db_name`, `table_name`, `table_comment`, `dao_name`, `master_columns`, `addon_name`, `status`, `created_at`, `updated_at`) VALUES
-(1, 10, 0, 'CurdDemo', '{\"join\": [{\"uuid\": \"pgJsFoqfaGjqgKjy\", \"alias\": \"testCategory\", \"field\": \"id\", \"columns\": [{\"dc\": \"分类ID\", \"id\": 1, \"name\": \"id\", \"extra\": \"auto_increment\", \"index\": \"PRI\", \"goName\": \"TestCategoryId\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"分类名称\", \"id\": 2, \"name\": \"name\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryName\", \"goType\": \"string\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryName\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"描述\", \"id\": 3, \"name\": \"description\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryDescription\", \"goType\": \"string\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryDescription\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"排序\", \"id\": 4, \"name\": \"sort\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategorySort\", \"goType\": \"int\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategorySort\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"备注\", \"id\": 5, \"name\": \"remark\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryRemark\", \"goType\": \"string\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryRemark\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"状态\", \"id\": 6, \"name\": \"status\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryStatus\", \"goType\": \"int\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryStatus\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"tinyint(1)\", \"dataType\": \"tinyint\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"创建时间\", \"id\": 7, \"name\": \"created_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryCreatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryCreatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"修改时间\", \"id\": 8, \"name\": \"updated_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryUpdatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryUpdatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"删除时间\", \"id\": 9, \"name\": \"deleted_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryDeletedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryDeletedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}], \"daoName\": \"TestCategory\", \"linkMode\": 1, \"linkTable\": \"hg_test_category\", \"masterField\": \"category_id\"}], \"menu\": {\"pid\": 2097, \"icon\": \"MenuOutlined\", \"sort\": 200}, \"autoOps\": [\"genMenuPermissions\", \"runDao\", \"runService\", \"forcedCover\"], \"headOps\": [\"add\", \"batchDel\", \"export\"], \"columnOps\": [\"edit\", \"del\", \"view\", \"status\", \"switch\", \"check\"]}', 'default', 'hg_sys_gen_curd_demo', '生成演示', 'SysGenCurdDemo', '[{\"dc\": \"ID\", \"id\": 1, \"name\": \"id\", \"extra\": \"auto_increment\", \"index\": \"PRI\", \"goName\": \"Id\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": true, \"isSort\": true, \"length\": 0, \"tsName\": \"id\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"分类ID\", \"id\": 2, \"name\": \"category_id\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CategoryId\", \"goType\": \"int64\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"categoryId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"标题\", \"id\": 3, \"name\": \"title\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Title\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 64, \"tsName\": \"title\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(64)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"Input\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"描述\", \"id\": 4, \"name\": \"description\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Description\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"description\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"InputTextarea\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"内容\", \"id\": 5, \"name\": \"content\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Content\", \"goType\": \"string\", \"isEdit\": true, \"isList\": false, \"isSort\": false, \"length\": 65535, \"tsName\": \"content\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"text\", \"dataType\": \"text\", \"dictType\": 0, \"formMode\": \"InputEditor\", \"formRole\": \"none\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE %...%\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"单图\", \"id\": 6, \"name\": \"image\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Image\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"image\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"UploadImage\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"附件\", \"id\": 7, \"name\": \"attachfile\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Attachfile\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"attachfile\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"UploadFile\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"所在城市\", \"id\": 8, \"name\": \"city_id\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CityId\", \"goType\": \"int64\", \"isEdit\": true, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"cityId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"CitySelector\", \"formRole\": \"none\", \"isExport\": false, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"显示开关\", \"id\": 9, \"name\": \"switch\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Switch\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"switch\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"Switch\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"排序\", \"id\": 10, \"name\": \"sort\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Sort\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": true, \"length\": 0, \"tsName\": \"sort\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"状态\", \"id\": 11, \"name\": \"status\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Status\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"status\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"tinyint(1)\", \"dataType\": \"tinyint\", \"dictType\": 3, \"formMode\": \"Select\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"创建者\", \"id\": 12, \"name\": \"created_by\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CreatedBy\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"createdBy\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"更新者\", \"id\": 13, \"name\": \"updated_by\", \"extra\": \"\", \"index\": \"\", \"goName\": \"UpdatedBy\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"updatedBy\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"创建时间\", \"id\": 14, \"name\": \"created_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CreatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"createdAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"TimeRange\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"BETWEEN\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"修改时间\", \"id\": 15, \"name\": \"updated_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"UpdatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"updatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"Time\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"删除时间\", \"id\": 16, \"name\": \"deleted_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"DeletedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"deletedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"Time\", \"formRole\": \"none\", \"isExport\": false, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}]', '', 1, '2023-01-18 11:51:22', '2023-02-23 23:13:52');
+(1, 10, 0, 'CurdDemo', '{\"join\": [{\"uuid\": \"pgJsFoqfaGjqgKjy\", \"alias\": \"testCategory\", \"field\": \"id\", \"columns\": [{\"dc\": \"分类ID\", \"id\": 1, \"name\": \"id\", \"extra\": \"auto_increment\", \"index\": \"PRI\", \"goName\": \"TestCategoryId\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"分类名称\", \"id\": 2, \"name\": \"name\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryName\", \"goType\": \"string\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryName\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"描述\", \"id\": 3, \"name\": \"description\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryDescription\", \"goType\": \"string\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryDescription\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"排序\", \"id\": 4, \"name\": \"sort\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategorySort\", \"goType\": \"int\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategorySort\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"备注\", \"id\": 5, \"name\": \"remark\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryRemark\", \"goType\": \"string\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 255, \"tsName\": \"testCategoryRemark\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"状态\", \"id\": 6, \"name\": \"status\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryStatus\", \"goType\": \"int\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryStatus\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"tinyint(1)\", \"dataType\": \"tinyint\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"创建时间\", \"id\": 7, \"name\": \"created_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryCreatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryCreatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"修改时间\", \"id\": 8, \"name\": \"updated_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryUpdatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryUpdatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"删除时间\", \"id\": 9, \"name\": \"deleted_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"TestCategoryDeletedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"testCategoryDeletedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"\", \"formRole\": \"\", \"isExport\": false, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}], \"daoName\": \"TestCategory\", \"linkMode\": 1, \"linkTable\": \"hg_test_category\", \"masterField\": \"category_id\"}], \"menu\": {\"pid\": 2097, \"icon\": \"MenuOutlined\", \"sort\": 200}, \"autoOps\": [\"genMenuPermissions\", \"runDao\", \"runService\", \"forcedCover\"], \"headOps\": [\"add\", \"batchDel\", \"export\"], \"columnOps\": [\"edit\", \"del\", \"view\", \"status\", \"switch\", \"check\"]}', 'default', 'hg_sys_gen_curd_demo', '生成演示', 'SysGenCurdDemo', '[{\"dc\": \"ID\", \"id\": 1, \"name\": \"id\", \"extra\": \"auto_increment\", \"index\": \"PRI\", \"goName\": \"Id\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": true, \"isSort\": true, \"length\": 0, \"tsName\": \"id\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"分类ID\", \"id\": 2, \"name\": \"category_id\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CategoryId\", \"goType\": \"int64\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"categoryId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"标题\", \"id\": 3, \"name\": \"title\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Title\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 64, \"tsName\": \"title\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(64)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"Input\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"描述\", \"id\": 4, \"name\": \"description\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Description\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"description\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"InputTextarea\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"内容\", \"id\": 5, \"name\": \"content\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Content\", \"goType\": \"string\", \"isEdit\": true, \"isList\": false, \"isSort\": false, \"length\": 65535, \"tsName\": \"content\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"text\", \"dataType\": \"text\", \"dictType\": 0, \"formMode\": \"InputEditor\", \"formRole\": \"none\", \"isExport\": false, \"required\": false, \"queryWhere\": \"LIKE %...%\", \"isAllowNull\": \"NO\", \"defaultValue\": \"\"}, {\"dc\": \"单图\", \"id\": 6, \"name\": \"image\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Image\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"image\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"UploadImage\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"附件\", \"id\": 7, \"name\": \"attachfile\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Attachfile\", \"goType\": \"string\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 255, \"tsName\": \"attachfile\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"varchar(255)\", \"dataType\": \"varchar\", \"dictType\": 0, \"formMode\": \"UploadFile\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"LIKE\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"所在城市\", \"id\": 8, \"name\": \"city_id\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CityId\", \"goType\": \"int64\", \"isEdit\": true, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"cityId\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"CitySelector\", \"formRole\": \"none\", \"isExport\": false, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"显示开关\", \"id\": 9, \"name\": \"switch\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Switch\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"switch\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"Switch\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"排序\", \"id\": 10, \"name\": \"sort\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Sort\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": true, \"length\": 0, \"tsName\": \"sort\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"int(11)\", \"dataType\": \"int\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": false, \"queryWhere\": \"=\", \"isAllowNull\": \"NO\", \"defaultValue\": 0}, {\"dc\": \"状态\", \"id\": 11, \"name\": \"status\", \"extra\": \"\", \"index\": \"\", \"goName\": \"Status\", \"goType\": \"int\", \"isEdit\": true, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"status\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"tinyint(1)\", \"dataType\": \"tinyint\", \"dictType\": 3, \"formMode\": \"Select\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 1}, {\"dc\": \"创建者\", \"id\": 12, \"name\": \"created_by\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CreatedBy\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"createdBy\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"更新者\", \"id\": 13, \"name\": \"updated_by\", \"extra\": \"\", \"index\": \"\", \"goName\": \"UpdatedBy\", \"goType\": \"int64\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"updatedBy\", \"tsType\": \"number\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"bigint(20)\", \"dataType\": \"bigint\", \"dictType\": 0, \"formMode\": \"InputNumber\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": 0}, {\"dc\": \"创建时间\", \"id\": 14, \"name\": \"created_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"CreatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"createdAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": true, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"TimeRange\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"BETWEEN\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"修改时间\", \"id\": 15, \"name\": \"updated_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"UpdatedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": true, \"isSort\": false, \"length\": 0, \"tsName\": \"updatedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"Time\", \"formRole\": \"none\", \"isExport\": true, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}, {\"dc\": \"删除时间\", \"id\": 16, \"name\": \"deleted_at\", \"extra\": \"\", \"index\": \"\", \"goName\": \"DeletedAt\", \"goType\": \"*gtime.Time\", \"isEdit\": false, \"isList\": false, \"isSort\": false, \"length\": 0, \"tsName\": \"deletedAt\", \"tsType\": \"string\", \"unique\": false, \"isQuery\": false, \"sqlType\": \"datetime\", \"dataType\": \"datetime\", \"dictType\": 0, \"formMode\": \"Time\", \"formRole\": \"none\", \"isExport\": false, \"required\": true, \"queryWhere\": \"=\", \"isAllowNull\": \"YES\", \"defaultValue\": \"\"}]', '', 1, '2023-01-18 11:51:22', '2023-02-20 16:41:58');
-- --------------------------------------------------------
@@ -1314,18 +1314,6 @@ CREATE TABLE `hg_sys_login_log` (
`updated_at` datetime DEFAULT NULL COMMENT '修改时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统_登录日志';
---
--- 转存表中的数据 `hg_sys_login_log`
---
-
-INSERT INTO `hg_sys_login_log` (`id`, `req_id`, `member_id`, `username`, `response`, `login_at`, `login_ip`, `err_msg`, `status`, `created_at`, `updated_at`) VALUES
-(25, 'e01359e1b9b54517d74c624f18f6de6c', 1, 'admin', '{\"id\": 1, \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJhZG1pbiIsImF2YXRhciI6Imh0dHA6Ly9idWZhbnl1bi5jbi1iai51ZmlsZW9zLmNvbS9ob3Rnby9hdHRhY2htZW50LzIwMjMtMDItMDkvY3FkcThlcjluZmtjaGRvcGF2LnBuZyIsImRlcHRJZCI6MTAwLCJlbWFpbCI6IjEzMzgxNDI1MEBxcS5jb20iLCJleHAiOjE2Nzc4MTAyNDYsImV4cGlyZXMiOjg2NDAwMCwiaWQiOjEsImlzUmVmcmVzaCI6ZmFsc2UsImp3dFZlcnNpb24iOiIxLjAiLCJtb2JpbGUiOiIxNTMwMzgzMDU3MSIsInBpZCI6MCwicmVhbE5hbWUiOiLlrZ_luIUiLCJyb2xlSWQiOjEsInJvbGVLZXkiOiJzdXBlciIsInVzZXJuYW1lIjoiYWRtaW4ifQ.qEFHTDWIPP6c_haRB09nA12rmg9cv0-RW0FX0EHuT3g\", \"expires\": 864000}', '2023-02-21 10:24:06', '127.0.0.1', '', 1, '2023-02-21 10:24:06', '2023-02-21 10:24:06'),
-(26, '7ce85da64c244617a149930f0a4f2c09', 0, 'admin', '{}', '2023-02-22 20:10:22', '127.0.0.1', '验证码错误', 2, '2023-02-22 20:10:24', '2023-02-22 20:10:24'),
-(27, '100cac034e244617a749930f920cc4d0', 1, 'admin', '{\"id\": 1, \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJhZG1pbiIsImF2YXRhciI6Imh0dHA6Ly9idWZhbnl1bi5jbi1iai51ZmlsZW9zLmNvbS9ob3Rnby9hdHRhY2htZW50LzIwMjMtMDItMDkvY3FkcThlcjluZmtjaGRvcGF2LnBuZyIsImRlcHRJZCI6MTAwLCJlbWFpbCI6IjEzMzgxNDI1MEBxcS5jb20iLCJleHAiOjE2Nzc5MzE4MjgsImV4cGlyZXMiOjg2NDAwMCwiaWQiOjEsImlzUmVmcmVzaCI6ZmFsc2UsImp3dFZlcnNpb24iOiIxLjAiLCJtb2JpbGUiOiIxNTMwMzgzMDU3MSIsInBpZCI6MCwicmVhbE5hbWUiOiLlrZ_luIUiLCJyb2xlSWQiOjEsInJvbGVLZXkiOiJzdXBlciIsInVzZXJuYW1lIjoiYWRtaW4ifQ.I_CI7YenI0Ny-AglAXDU4J9H-6XBL0SNF7TQjvHn0Gc\", \"expires\": 864000}', '2023-02-22 20:10:28', '127.0.0.1', '', 1, '2023-02-22 20:10:29', '2023-02-22 20:10:29'),
-(28, '3045d835c9784617bf79ad5a98246c49', 0, 'admin', '{}', '2023-02-23 21:58:36', '::1', '验证码错误', 2, '2023-02-23 21:58:38', '2023-02-23 21:58:38'),
-(29, 'b84a86c7c9784617c179ad5ae28237a6', 1, 'admin', '{\"id\": 1, \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJhZG1pbiIsImF2YXRhciI6Imh0dHA6Ly9idWZhbnl1bi5jbi1iai51ZmlsZW9zLmNvbS9ob3Rnby9hdHRhY2htZW50LzIwMjMtMDItMDkvY3FkcThlcjluZmtjaGRvcGF2LnBuZyIsImRlcHRJZCI6MTAwLCJlbWFpbCI6IjEzMzgxNDI1MEBxcS5jb20iLCJleHAiOjE2NzgwMjQ3MTksImV4cGlyZXMiOjg2NDAwMCwiaWQiOjEsImlzUmVmcmVzaCI6ZmFsc2UsImp3dFZlcnNpb24iOiIxLjAiLCJtb2JpbGUiOiIxNTMwMzgzMDU3MSIsInBpZCI6MCwicmVhbE5hbWUiOiLlrZ_luIUiLCJyb2xlSWQiOjEsInJvbGVLZXkiOiJzdXBlciIsInVzZXJuYW1lIjoiYWRtaW4ifQ.z7VypWafEvrKoCGw6bwEF3IpXuv8_mRHgOifGQL3QIg\", \"expires\": 864000}', '2023-02-23 21:58:39', '::1', '', 1, '2023-02-23 21:58:40', '2023-02-23 21:58:40'),
-(30, '08c0bf62197b4617d0482e3751e81a20', 1, 'admin', '{\"id\": 1, \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOiJhZG1pbiIsImF2YXRhciI6Imh0dHA6Ly9idWZhbnl1bi5jbi1iai51ZmlsZW9zLmNvbS9ob3Rnby9hdHRhY2htZW50LzIwMjMtMDItMDkvY3FkcThlcjluZmtjaGRvcGF2LnBuZyIsImRlcHRJZCI6MTAwLCJlbWFpbCI6IjEzMzgxNDI1MEBxcS5jb20iLCJleHAiOjE2NzgwMjcyNjAsImV4cGlyZXMiOjg2NDAwMCwiaWQiOjEsImlzUmVmcmVzaCI6ZmFsc2UsImp3dFZlcnNpb24iOiIxLjAiLCJtb2JpbGUiOiIxNTMwMzgzMDU3MSIsInBpZCI6MCwicmVhbE5hbWUiOiLlrZ_luIUiLCJyb2xlSWQiOjEsInJvbGVLZXkiOiJzdXBlciIsInVzZXJuYW1lIjoiYWRtaW4ifQ.bgopyMH57XY_AOgdAGOH0gt7ZReYmlGfkKGOHaFHRmk\", \"expires\": 864000}', '2023-02-23 22:41:00', '::1', '', 1, '2023-02-23 22:41:01', '2023-02-23 22:41:01');
-
-- --------------------------------------------------------
--
@@ -5042,6 +5030,42 @@ INSERT INTO `hg_sys_provinces` (`id`, `title`, `pinyin`, `lng`, `lat`, `pid`, `l
-- --------------------------------------------------------
+--
+-- 表的结构 `hg_sys_serve_license`
+--
+
+CREATE TABLE `hg_sys_serve_license` (
+ `id` bigint(20) NOT NULL COMMENT '许可ID',
+ `group` varchar(50) NOT NULL COMMENT '分组',
+ `name` varchar(128) NOT NULL COMMENT '许可名称',
+ `appid` varchar(64) NOT NULL COMMENT '应用ID',
+ `secret_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥',
+ `desc` text COMMENT '授权说明',
+ `remote_addr` varchar(64) DEFAULT NULL COMMENT '连接地址',
+ `online` tinyint(4) DEFAULT '0' COMMENT '是否在线',
+ `login_times` bigint(20) DEFAULT NULL COMMENT '登录次数',
+ `last_login_at` datetime DEFAULT NULL COMMENT '最后登录时间',
+ `last_active_at` datetime DEFAULT NULL COMMENT '最后活跃时间',
+ `routes` json DEFAULT NULL COMMENT '路由表,空使用默认分组路由',
+ `allowed_ips` varchar(512) DEFAULT NULL COMMENT '白名单,*代表所有,只有允许的IP才能连接到tcp服务',
+ `end_at` datetime NOT NULL COMMENT '授权结束时间',
+ `remark` varchar(512) DEFAULT NULL COMMENT '备注',
+ `status` tinyint(1) DEFAULT '1' COMMENT '状态',
+ `created_at` datetime DEFAULT NULL COMMENT '创建时间',
+ `updated_at` datetime DEFAULT NULL COMMENT '修改时间'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统_服务许可';
+
+--
+-- 转存表中的数据 `hg_sys_serve_license`
+--
+
+INSERT INTO `hg_sys_serve_license` (`id`, `group`, `name`, `appid`, `secret_key`, `desc`, `remote_addr`, `online`, `login_times`, `last_login_at`, `last_active_at`, `routes`, `allowed_ips`, `end_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES
+(1, 'queue', '默认的消息队列', '1001', 'hotgo', '这是默认的消息队列TCP客户端授权凭证。', NULL, 0, 1, '2023-03-23 00:00:00', NULL, NULL, '127.0.0.1', '2033-03-09 00:00:00', '', 1, '2023-03-11 00:00:00', '2023-03-05 00:00:00'),
+(2, 'cron', '默认的定时任务', '1002', 'hotgo', '这是默认的定时任务TCP客户端授权凭证。', NULL, 0, 1, '2023-03-23 00:00:00', NULL, NULL, '127.0.0.1', '2033-03-09 00:00:00', '', 1, '2023-03-11 00:00:00', '2023-03-05 00:00:00'),
+(3, 'auth', '测试授权', 'mengshuai', '123456', '这是一个测试的授权服务,可以为第三方平台提供授权支持。', '127.0.0.1:54182', 1, 20, '2023-03-13 16:01:02', '2023-03-13 16:57:04', NULL, '127.0.0.1', '2033-03-09 00:00:00', '', 1, '2023-03-11 00:00:00', '2023-03-13 16:57:03');
+
+-- --------------------------------------------------------
+
--
-- 表的结构 `hg_sys_serve_log`
--
@@ -5059,6 +5083,13 @@ CREATE TABLE `hg_sys_serve_log` (
`updated_at` datetime DEFAULT NULL COMMENT '修改时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统_服务日志';
+--
+-- 转存表中的数据 `hg_sys_serve_log`
+--
+
+INSERT INTO `hg_sys_serve_log` (`id`, `trace_id`, `level_format`, `content`, `stack`, `line`, `trigger_ns`, `status`, `created_at`, `updated_at`) VALUES
+(3, 'ec3bc5835ce14d170412f80c95578ba6', 'ERRO', 'SafeGo failed err:[net.DialTimeout failed with network \"tcp\", address \"127.0.0.1:18999\", timeout \"30s\": dial tcp 127.0.0.1:18999: connectex: No connection could be made because the target machine actively refused it.\n1. net.DialTimeout failed with network \"tcp\", address \"127.0.0.1:18999\", timeout \"30s\"\n 1). github.com/gogf/gf/v2/net/gtcp.NewNetConn\n E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.2/net/gtcp/gtcp_func.go:42\n 2). github.com/gogf/gf/v2/net/gtcp.NewConn\n E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.3.2/net/gtcp/gtcp_conn.go:36\n 3). hotgo/internal/cmd.glob..func4\n E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/cmd/queue.go:29\n 4). hotgo/internal/cmd.glob..func2.1\n E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/cmd/cmd.go:57\n 5). hotgo/utility/simple.SafeGo.func1\n E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/utility/simple/simple.go:54\n2. dial tcp 127.0.0.1:18999: connectex: No connection could be made because the target machine actively refused it.\n]', '[\"1. hotgo/utility/simple.Logf\", \" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/utility/simple/simple.go:69\", \"2. hotgo/utility/simple.SafeGo.func1.1\", \" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/utility/simple/simple.go:50\", \"3. hotgo/internal/cmd.glob..func4\", \" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/cmd/queue.go:31\", \"4. hotgo/internal/cmd.glob..func2.1\", \" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/cmd/cmd.go:57\", \"5. hotgo/utility/simple.SafeGo.func1\", \" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/utility/simple/simple.go:54\", \"\"]', 'simple.go:69', 1679246100245609100, 1, '2023-03-20 01:15:02', '2023-03-20 01:15:02');
+
-- --------------------------------------------------------
--
@@ -5308,6 +5339,13 @@ ALTER TABLE `hg_sys_provinces`
ADD PRIMARY KEY (`id`),
ADD KEY `pid` (`pid`);
+--
+-- 表的索引 `hg_sys_serve_license`
+--
+ALTER TABLE `hg_sys_serve_license`
+ ADD PRIMARY KEY (`id`),
+ ADD UNIQUE KEY `appid` (`appid`);
+
--
-- 表的索引 `hg_sys_serve_log`
--
@@ -5355,7 +5393,7 @@ ALTER TABLE `hg_admin_member`
-- 使用表AUTO_INCREMENT `hg_admin_menu`
--
ALTER TABLE `hg_admin_menu`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜单ID', AUTO_INCREMENT=2260;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜单ID', AUTO_INCREMENT=2232;
--
-- 使用表AUTO_INCREMENT `hg_admin_notice`
@@ -5367,7 +5405,7 @@ ALTER TABLE `hg_admin_notice`
-- 使用表AUTO_INCREMENT `hg_admin_notice_read`
--
ALTER TABLE `hg_admin_notice_read`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '记录ID', AUTO_INCREMENT=20;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '记录ID', AUTO_INCREMENT=21;
--
-- 使用表AUTO_INCREMENT `hg_admin_post`
@@ -5385,7 +5423,7 @@ ALTER TABLE `hg_admin_role`
-- 使用表AUTO_INCREMENT `hg_admin_role_casbin`
--
ALTER TABLE `hg_admin_role_casbin`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6191;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8342;
--
-- 使用表AUTO_INCREMENT `hg_sys_addons_config`
@@ -5397,7 +5435,7 @@ ALTER TABLE `hg_sys_addons_config`
-- 使用表AUTO_INCREMENT `hg_sys_addons_install`
--
ALTER TABLE `hg_sys_addons_install`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', AUTO_INCREMENT=9;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', AUTO_INCREMENT=2;
--
-- 使用表AUTO_INCREMENT `hg_sys_attachment`
@@ -5421,7 +5459,7 @@ ALTER TABLE `hg_sys_config`
-- 使用表AUTO_INCREMENT `hg_sys_cron`
--
ALTER TABLE `hg_sys_cron`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID', AUTO_INCREMENT=4;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID', AUTO_INCREMENT=3;
--
-- 使用表AUTO_INCREMENT `hg_sys_cron_group`
@@ -5451,7 +5489,7 @@ ALTER TABLE `hg_sys_ems_log`
-- 使用表AUTO_INCREMENT `hg_sys_gen_codes`
--
ALTER TABLE `hg_sys_gen_codes`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '生成ID', AUTO_INCREMENT=9;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '生成ID', AUTO_INCREMENT=5;
--
-- 使用表AUTO_INCREMENT `hg_sys_gen_curd_demo`
@@ -5469,13 +5507,19 @@ ALTER TABLE `hg_sys_log`
-- 使用表AUTO_INCREMENT `hg_sys_login_log`
--
ALTER TABLE `hg_sys_login_log`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID', AUTO_INCREMENT=31;
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID';
+
+--
+-- 使用表AUTO_INCREMENT `hg_sys_serve_license`
+--
+ALTER TABLE `hg_sys_serve_license`
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '许可ID', AUTO_INCREMENT=4;
--
-- 使用表AUTO_INCREMENT `hg_sys_serve_log`
--
ALTER TABLE `hg_sys_serve_log`
- MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID';
+ MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID', AUTO_INCREMENT=4;
--
-- 使用表AUTO_INCREMENT `hg_sys_sms_log`
diff --git a/server/utility/convert/match.go b/server/utility/convert/match.go
new file mode 100644
index 0000000..cb2f781
--- /dev/null
+++ b/server/utility/convert/match.go
@@ -0,0 +1,102 @@
+package convert
+
+import (
+ "github.com/gogf/gf/v2/text/gstr"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/utility/validate"
+)
+
+// IpFilterStrategy ip过滤策略
+func IpFilterStrategy(originIp string) (list map[string]struct{}) {
+ list = make(map[string]struct{})
+
+ // 所有IP
+ if originIp == "*" {
+ list["*"] = struct{}{}
+ return
+ }
+
+ // 多个IP
+ if gstr.Contains(originIp, ",") {
+ ips := gstr.Explode(",", originIp)
+ if len(ips) > 0 {
+ for _, ip := range ips {
+ if !validate.IsIp(ip) {
+ continue
+ }
+ list[ip] = struct{}{}
+ }
+ }
+
+ return
+ }
+
+ // IP段
+ if gstr.Contains(originIp, "/24") {
+ segment := gstr.Replace(originIp, "/24", "")
+ if !validate.IsIp(segment) {
+ return
+ }
+
+ var (
+ start = gstr.Explode(".", segment)
+ prefix = gstr.Implode(".", start[:len(start)-1]) + "."
+ index = gconv.Int(start[len(start)-1])
+ )
+
+ if index < 1 {
+ index = 1
+ }
+
+ for i := index; i <= 254; i++ {
+ list[prefix+gconv.String(i)] = struct{}{}
+ }
+
+ return
+ }
+
+ // IP范围
+ if gstr.Contains(originIp, "-") {
+ originIps := gstr.Explode("-", originIp)
+ if len(originIps) != 2 {
+ return
+ }
+
+ if !validate.IsIp(originIps[0]) || !validate.IsIp(originIps[1]) {
+ return
+ }
+
+ var (
+ start = gstr.Explode(".", originIps[0])
+ prefix = gstr.Implode(".", start[:len(start)-1]) + "."
+ startIndex = gconv.Int(gstr.SubStrFromREx(originIps[0], "."))
+ endIndex = gconv.Int(gstr.SubStrFromREx(originIps[1], "."))
+ )
+
+ if startIndex >= endIndex {
+ list[originIps[0]] = struct{}{}
+ return
+ }
+
+ if startIndex < 1 {
+ startIndex = 1
+ }
+
+ if endIndex > 254 {
+ endIndex = 254
+ }
+
+ for i := startIndex; i <= endIndex; i++ {
+ list[prefix+gconv.String(i)] = struct{}{}
+ }
+ return
+ }
+
+ // 指定IP
+ if validate.IsIp(originIp) {
+ list[originIp] = struct{}{}
+ return
+ }
+
+ return list
+}
diff --git a/web/package.json b/web/package.json
index a0d1121..c715f94 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,6 +1,6 @@
{
"name": "hotgo",
- "version": "2.3.5",
+ "version": "2.4.2",
"author": {
"name": "MengShuai",
"email": "133814250@qq.com",
diff --git a/web/src/views/system/config/BasicSetting.vue b/web/src/views/system/config/BasicSetting.vue
index 918563b..2c6851c 100644
--- a/web/src/views/system/config/BasicSetting.vue
+++ b/web/src/views/system/config/BasicSetting.vue
@@ -7,15 +7,8 @@
-
- import { reactive, ref, unref, onMounted } from 'vue';
+ import { ref, onMounted } from 'vue';
import { useDialog, useMessage } from 'naive-ui';
- import { BasicUpload } from '@/components/Upload';
- import { useGlobSetting } from '@/hooks/setting';
- import { useUserStoreWidthOut } from '@/store/modules/user';
import componentSetting from '@/settings/componentSetting';
import { getConfig, updateConfig } from '@/api/sys/config';
const group = ref('basic');
-
const show = ref(false);
-
- const useUserStore = useUserStoreWidthOut();
-
- const globSetting = useGlobSetting();
-
- const { uploadUrl } = globSetting;
-
- const uploadHeaders = reactive({
- Authorization: useUserStore.token,
- });
-
- const rules = {
- basicName: {
- required: true,
- message: '请输入网站名称',
- trigger: 'blur',
- },
- };
-
const formRef: any = ref(null);
const message = useMessage();
const dialog = useDialog();
@@ -139,6 +109,14 @@
basicSystemOpen: true,
});
+ const rules = {
+ basicName: {
+ required: true,
+ message: '请输入网站名称',
+ trigger: 'blur',
+ },
+ };
+
function systemOpenChange(value) {
if (!value) {
dialog.warning({
@@ -169,15 +147,6 @@
});
}
- function uploadChange(list: string[]) {
- // 单图模式,只需要第一个索引
- if (list.length > 0) {
- formValue.value.basicLogo = unref(list[0]);
- } else {
- formValue.value.basicLogo = unref('');
- }
- }
-
onMounted(() => {
load();
});
diff --git a/web/src/views/system/dict/list.vue b/web/src/views/system/dict/list.vue
index 27026ba..4ad5b76 100644
--- a/web/src/views/system/dict/list.vue
+++ b/web/src/views/system/dict/list.vue
@@ -112,7 +112,7 @@
}
const props = withDefaults(defineProps(), { checkedId: 0 });
- const typeList = ref([]);
+ const typeList = ref([]);
const rules = {
label: {
required: true,
@@ -304,15 +304,16 @@
reloadTable();
}
- watch(props, (_newVal, _oldVal) => {
- params.value.typeId = _newVal.checkedId;
- formParams.value.typeId = _newVal.checkedId;
+ watch(props, (newVal, _oldVal) => {
+ params.value.typeId = newVal.checkedId;
+ formParams.value.typeId = newVal.checkedId;
actionRef.value.reload();
setDictSelect();
});
async function setDictSelect() {
- typeList.value = await getDictSelect({});
+ const tmp = await getDictSelect({});
+ typeList.value = tmp.list;
if (typeList.value === undefined || typeList.value === null) {
typeList.value = [];
}