Compare commits

..

4 Commits

Author SHA1 Message Date
孟帅
42d5500941 发布v2.17.8版本,更新内容请查看:https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-update-log.md 2025-07-13 18:57:52 +08:00
孟帅
20a9e38fa8
Merge pull request #185 from rxrddd/v2.0
doc: 优化docsify文档体验
2025-07-13 18:42:08 +08:00
zjy
35c6387b4b doc: 优化docsify文档体验
1.调整在docsify下代码块乱掉的问题
2.新增docsify下的go/yaml/vue/json/sql代码高亮插件
3.新增docsify下的mermaid图解析插件
2025-07-13 18:29:28 +08:00
孟帅
17daeb9121 refactor 调整数据库初始数据,替换默认图片资源域名 2025-07-13 17:44:31 +08:00
36 changed files with 1048 additions and 948 deletions

View File

@ -1,6 +1,6 @@
# HotGo-V2
<div align="center">
<img width="140px" src="https://bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png">
<img width="140px" src="https://gmycos.facms.cn/hotgo/logo.sig.png">
<p>
<h1>HotGo V2</h1>
</p>
@ -12,7 +12,7 @@
<img src="https://img.shields.io/badge/vue.js-vue3.4-green" alt="vue">
</a>
<a href="https://www.naiveui.com" target="_blank">
<img src="https://img.shields.io/badge/naiveui-%3E2.41.0-blue" alt="naiveui">
<img src="https://img.shields.io/badge/naiveui-%3E2.42.0-blue" alt="naiveui">
</a>
<a href="https://www.tslang.cn/" target="_blank">
<img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
@ -124,8 +124,8 @@
## 交流QQ群
交流群①190966648 <a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=mJafkvme3VNyiQlCFIFNRtY8Xlr7pj9U&jump_from=webapi&authKey=jL10vIESr+vO8wpxwyd6DlChzkrbHpzN9uhAsIHgAinL/Vvd+nvuRyilf2UqUlCy"><img border="0" src="https://bufanyun.cn-bj.ufileos.com/hotgo/group.png" alt="HotGo框架交流1群" title="HotGo框架交流1群"></a>
> <img src="https://bufanyun.cn-bj.ufileos.com/hotgo/hotgo1qun.png" width="400px"/>
交流群①190966648 <a target="_blank" href="https://qm.qq.com/cgi-bin/qm/qr?k=mJafkvme3VNyiQlCFIFNRtY8Xlr7pj9U&jump_from=webapi&authKey=jL10vIESr+vO8wpxwyd6DlChzkrbHpzN9uhAsIHgAinL/Vvd+nvuRyilf2UqUlCy"><img border="0" src="https://gmycos.facms.cn/hotgo/group.png" alt="HotGo框架交流1群" title="HotGo框架交流1群"></a>
> <img src="https://gmycos.facms.cn/hotgo/hotgo1qun.png" width="400px"/>
## 商用说明

View File

@ -14,7 +14,7 @@
1、HotGo 后台进入 开发工具->插件管理->找到创建新插件,根据引导进行创建即可。
```
```shell
创建成功后默认情况下会在以下目录中生成插件文件假设新生成的插件名为hgexample
1. /server/addons/hgexample/ # 插件模块目录
@ -29,7 +29,7 @@
2、创建插件完毕重启服务端后插件管理中会出现你新创建的插件信息。操作栏有几个按钮在此进行说明
- 安装:会自动执行 server/hgexample/main.go 文件中的Install方法方法中的具体逻辑默认为空可以根据实际情况自行配置。如生成后台菜单、生成插件配置表初始化数据、迁移home页面、web项目文件等。
```
```go
// Install 安装模块
func (m *module) Install(ctx context.Context) (err error) {
// ...
@ -38,7 +38,7 @@ func (m *module) Install(ctx context.Context) (err error) {
```
- 更新:会自动执行 server/hgexample/main.go 文件中的Upgrade方法方法中的具体逻辑默认为空可以根据实际情况自行配置。
```
```go
// Upgrade 更新模块
func (m *module) Upgrade(ctx context.Context) (err error) {
// ...
@ -47,7 +47,7 @@ func (m *module) Upgrade(ctx context.Context) (err error) {
```
- 卸载:会自动执行 server/hgexample/main.go 文件中的UnInstall方法方法中的具体逻辑默认为空可以根据实际情况自行配置。如会清除所有的数据表和已安装的信息等。
```
```go
// UnInstall 卸载模块
func (m *module) UnInstall(ctx context.Context) (err error) {
// ...

View File

@ -9,6 +9,7 @@
#### 模块结构
- 文件路径server/internal/library/addons/module.go
```go
// Skeleton 模块骨架
type Skeleton struct {
@ -43,6 +44,7 @@ type Module interface {
#### 获取模块信息
- 在插件模块内
```go
package main
@ -57,6 +59,7 @@ func test() {
```
- 在插件模块外
```go
package main

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

View File

@ -78,7 +78,7 @@ pnpm run build 或 npm run build
### Nginx配置
```
# websocket
location ^~ /socket {
location = /socket {
proxy_pass http://127.0.0.1:8000/socket;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
@ -98,7 +98,9 @@ pnpm run build 或 npm run build
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8000/; # 设置代理服务器的协议和地址
proxy_pass http://127.0.0.1:8000/;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;

View File

@ -69,7 +69,7 @@ gfcli:
三、 启动服务
1、服务端
```shell script
```shell
cd server
# 设置国内代理,如果已经设置好了代理可以跳过
@ -86,7 +86,7 @@ gfcli:
```
2、web前端
```shell script
```shell
cd web
# 首先确定你以安装node16.0以上版本并安装了包[npm、pnpm],否则可能会出现一些未知报错

View File

@ -22,7 +22,7 @@
#### 1、安装数据库出现 json 报错不支持
请安装 mysql5.7 及以上版本的数据库
请安装 mysql5.7 及以上版本的数据库。如果你使用的是mariadb请确认版本号mariadb从 10.2 版本开始支持 json 数据类型。
@ -50,7 +50,31 @@
系统运行目录下配置hack/config.yaml文件。如果是生产环境运行并且不需要开发工具相关功能可以将`manifest/config/config.yaml`配置文件中的`system.mode`值改为`product`,这样启动时不会加载开发工具相关功能
#### 4、非超管角色提示你没有访问权限
![1.4.0.png](./images/issue/1.4.0.png)
此问题因当前角色访问的页面包含未分配权限的接口所致,在多角色场景中较为常见,解决步骤如下:
1. 定位缺失权限的接口
- 用超管账号进入系统应用 -> 日志管理 -> 全局日志,搜索状态码为`62 无访问权限`的记录
- 示例:若请求接口为`/admin/hgexample/treeTable/list`,需处理的权限路径为`/hgexample/treeTable/list`(去除`/admin`前缀)
![1.4.1.png](./images/issue/1.4.1.png)
假如查到请求接口是:`/admin/hgexample/treeTable/list`,那需要分配的菜单权限就是:`/hgexample/treeTable/list`,要把`/admin`去掉
2. 配置菜单权限
- 进入权限管理 -> 菜单权限:
- 若目标菜单不存在,先新增菜单
- 若菜单已存在但未配置接口权限就把步骤1中的权限路径添加到【分配权限】中已配置则跳过
![1.4.2.png](./images/issue/1.4.2.png)
3. 分配权限给角色
- 进入权限管理 -> 角色权限,找到对应角色并点击【菜单权限】
- 勾选步骤2中配置的菜单权限保存即可
![1.4.3.png](./images/issue/1.4.3.png)
### 四、前端相关

View File

@ -11,6 +11,20 @@
> 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整
### v2.17.8
updated 2025.7.13
- 优化:表格排序处理器兼容关联表别名
- 优化优化动态统计数字在0值时显示问题
- 优化:优化首页快捷菜单点击事件范围
- 优化:优化短信、邮件验证码相关验证类数据排序
- 优化优化Nginx配置支持流式请求和兼容部分版本无法匹配到websocket规则问题
- 优化naive-ui版本升级到2.42.0
- 优化vue3-json-viewer版本升级到2.4.1
- 修复:修复可选用户选项`Fields`生成错误问题
### v2.16.10
updated 2025.3.22

View File

@ -176,7 +176,7 @@ CREATE TABLE `hg_test_category` (
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, '测试标题', '描述', '<h2><strong>不知道写点啥!</strong></h2><p><br></p><iframe class=\"ql-video\" frameborder=\"0\" allowfullscreen=\"true\" src=\"https://media.w3.org/2010/05/sintel/trailer.mp4\"></iframe><p><br></p><p><img src=\"http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png\"></p>', '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);
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, '测试标题', '描述', '<h2><strong>不知道写点啥!</strong></h2><p><br></p><iframe class=\"ql-video\" frameborder=\"0\" allowfullscreen=\"true\" src=\"https://media.w3.org/2010/05/sintel/trailer.mp4\"></iframe><p><br></p><p><img src=\"https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png\"></p>', 'https://gmycos.facms.cn/hotgo/logo.sig.png', 'https://gmycos.facms.cn/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);
```

View File

@ -1,149 +1,150 @@
## 数据库
目录
- 字段类型
- 特殊字段默认表单组件
- 特殊字段默认表单验证器
- 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`(关系树)
#### 操作人字段维护
- 生成列表中存在并且勾选展示字段`created_by`(创建者)、`updated_by`(修改者)、`deleted_by`(删除者)时,会自动到表`hg_admin_member`中获取操作人的基本信息摘要,并渲染到列表中,效果如下:
![](images/sys-db-by.png)
- 生成列表中存在并且勾选查询字段`created_by`(创建者)、`updated_by`(修改者)、`deleted_by`(删除者)时,会强制将查询表单改为关键词查询,从`hg_admin_member`查询操作人。效果如下:
![](images/sys-db-by2.png)
- 查询代码片段,参考路径:[server/internal/logic/admin/member.go](../../server/internal/logic/admin/member.go)
```go
// 查询创建者
if in.CreatedBy != "" {
ids, err := service.AdminMember().GetIdsByKeyword(ctx, in.CreatedBy)
if err != nil {
return nil, 0, err
}
mod = mod.WhereIn(dao.SysGenCurdDemo.Columns().CreatedBy, ids)
}
// GetIdsByKeyword 根据关键词查找符合条件的用户ID
func (s *sAdminMember) GetIdsByKeyword(ctx context.Context, ks string) (res []int64, err error) {
ks = gstr.Trim(ks)
if len(ks) == 0 {
return
}
array, err := dao.AdminMember.Ctx(ctx).Fields("id").
Where("`id` = ? or `real_name` = ? or `username` = ? or `mobile` = ?", ks, ks, ks, ks).
Array()
if err != nil {
err = gerror.Wrap(err, "根据关键词获取用户ID失败请稍后重试")
}
res = gvar.New(array).Int64s()
return
}
```
> 这里只列举了较为常用的默认规则,其他更多默认规则请参考:[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`(关系树)
#### 操作人字段维护
- 生成列表中存在并且勾选展示字段`created_by`(创建者)、`updated_by`(修改者)、`deleted_by`(删除者)时,会自动到表`hg_admin_member`中获取操作人的基本信息摘要,并渲染到列表中,效果如下:
![](images/sys-db-by.png)
- 生成列表中存在并且勾选查询字段`created_by`(创建者)、`updated_by`(修改者)、`deleted_by`(删除者)时,会强制将查询表单改为关键词查询,从`hg_admin_member`查询操作人。效果如下:
![](images/sys-db-by2.png)
- 查询代码片段,参考路径:[server/internal/logic/admin/member.go](../../server/internal/logic/admin/member.go)
```go
// 查询创建者
if in.CreatedBy != "" {
ids, err := service.AdminMember().GetIdsByKeyword(ctx, in.CreatedBy)
if err != nil {
return nil, 0, err
}
mod = mod.WhereIn(dao.SysGenCurdDemo.Columns().CreatedBy, ids)
}
// GetIdsByKeyword 根据关键词查找符合条件的用户ID
func (s *sAdminMember) GetIdsByKeyword(ctx context.Context, ks string) (res []int64, err error) {
ks = gstr.Trim(ks)
if len(ks) == 0 {
return
}
array, err := dao.AdminMember.Ctx(ctx).Fields("id").
Where("`id` = ? or `real_name` = ? or `username` = ? or `mobile` = ?", ks, ks, ks, ks).
Array()
if err != nil {
err = gerror.Wrap(err, "根据关键词获取用户ID失败请稍后重试")
}
res = gvar.New(array).Int64s()
return
}
```
> 这里只列举了较为常用的默认规则,其他更多默认规则请参考:[server/internal/library/hggen/views/column_default.go](../../server/internal/library/hggen/views/column_default.go)

View File

@ -63,16 +63,17 @@
#### import
* 单行import不建议用圆括号包裹
* 按照`官方包`NEW LINE`当前工程包`NEW LINE`第三方依赖包`顺序引入
```go
import (
"context"
"string"
"greet/user/internal/config"
"google.golang.org/grpc"
)
```
```go
import (
"context"
"string"
"greet/user/internal/config"
"google.golang.org/grpc"
)
```
#### 函数返回
* 对象避免非指针返回
@ -84,7 +85,8 @@
#### 函数体编码
* 建议一个block结束空一行如if、for等
```go
```go
func main (){
if x==1{
// do something
@ -92,15 +94,16 @@
fmt.println("xxx")
}
```
```
* return前尽可能空一行
```go
func getUser(id string)(string,error){
....
return "xx",nil
}
```
```go
func getUser(id string)(string,error){
....
return "xx",nil
}
```
### 框架规范

View File

@ -1,316 +1,318 @@
## 功能扩展库
目录
- 缓存驱动
- 请求上下文
- JWT
- 数据字典
- 地理定位(待写)
- 通知(待写)
### 缓存驱动
> 系统默认的缓存驱动为file目前已支持memory|redis|file等多种驱动。请自行选择适合你的驱动使用。
- 配置文件server/manifest/config/config.yaml
```yaml
#缓存
cache:
adapter: "file" # 缓存驱动方式支持memory|redis|file不填默认memory
fileDir: "./storage/cache" # 文件缓存路径adapter=file时必填
```
#### 使用方式
```go
package main
import (
"hotgo/internal/library/cache"
"github.com/gogf/gf/v2/os/gctx"
)
func test() {
ctx := gctx.New()
// 添加/修改
cache.Instance().Set(ctx, "qwe", 123, 0)
// 查询
cache.Instance().Get(ctx, "qwe")
// 删除
cache.Instance().Remove(ctx, "qwe")
// 更多方法请参考https://goframe.org/pages/viewpage.action?pageId=27755640
}
```
### 请求上下文
- 主要用于在处理HTTP和websocket请求时通过中间件将用户、应用、插件等信息绑定到上下文中方便在做业务处理时用到这些信息
```go
package admin
import (
"fmt"
"context"
"hotgo/internal/library/contexts"
"hotgo/internal/library/addons"
)
func test(ctx context.Context) {
// 获取当前请求的所有上下文变量
var ctxModel = contexts.Get(ctx)
fmt.Printf("当前请求的所有上下文变量:%+v\n", ctxModel)
// 获取当前请求的应用模块
var module = contexts.GetModule(ctx)
fmt.Printf("当前请求的应用:%+v\n", module)
// 获取当前请求的用户信息
var member = contexts.GetUser(ctx)
fmt.Printf("当前访问用户信息:%+v\n", member)
// 获取当前请求的插件模块
fmt.Printf("当前是否为插件请求:%v", contexts.IsAddonRequest(ctx))
if contexts.IsAddonRequest(ctx) {
fmt.Printf("当前插件名称:%v", contexts.GetAddonName(ctx))
fmt.Printf("当前插件信息:%v", addons.GetModule(contexts.GetAddonName(ctx)))
}
}
```
### JWT
- 基于jwt+缓存驱动实现的用户登录令牌功能支持自动续约解决了jwt服务端无法退出问题和jwt令牌无法主动失效问题
#### 配置示例
```yaml
# 登录令牌
token:
secretKey: "hotgo123" # 令牌加密秘钥,考虑安全问题生产环境中请修改默认值
expires: 604800 # 令牌有效期单位秒。默认7天
autoRefresh: true # 是否开启自动刷新过期时间, false|true 默认为true
refreshInterval: 86400 # 刷新间隔单位秒。必须小于expires否则无法触发。默认1天内只允许刷新一次
maxRefreshTimes: 30 # 最大允许刷新次数,-1不限制。默认30次
multiLogin: true # 是否允许多端登录, false|true 默认为true
```
```go
package admin
import (
"fmt"
"context"
"hotgo/internal/library/token"
"hotgo/internal/model"
)
func test(ctx context.Context) {
// 登录
user := &model.Identity{
Id: mb.Id,
Pid: mb.Pid,
DeptId: mb.DeptId,
RoleId: ro.Id,
RoleKey: ro.Key,
Username: mb.Username,
RealName: mb.RealName,
Avatar: mb.Avatar,
Email: mb.Email,
Mobile: mb.Mobile,
App: consts.AppAdmin,
LoginAt: gtime.Now(),
}
loginToken, expires, err := token.Login(ctx, user)
if err != nil {
return nil, err
}
// gf请求对象
r := *ghttp.Request
// 获取登录用户信息
user, err := token.ParseLoginUser(r)
if err != nil {
return
}
// 注销登录
err = token.Logout(r)
}
```
### 数据字典
- hotgo增加了对枚举字典和自定义方法字典的内置支持从而在系统中经常使用的一些特定数据上做出了增强。
#### 字典数据选项
- 文件路径server/internal/model/dict.go
```go
package model
// Option 字典数据选项
type Option struct {
Key interface{} `json:"key"`
Label string `json:"label" description:"字典标签"`
Value interface{} `json:"value" description:"字典键值"`
ValueType string `json:"valueType" description:"键值数据类型"`
Type string `json:"type" description:"字典类型"`
ListClass string `json:"listClass" description:"表格回显样式"`
}
```
#### 枚举字典
- 适用于系统开发期间内置的枚举数据,这样即维护了枚举值,又关联了数据字典
##### 一个例子
- 定义枚举值和字典数据选项,并注册字典类型
- 文件路径server/internal/consts/credit_log.go
```go
package consts
import (
"hotgo/internal/library/dict"
"hotgo/internal/model"
)
func init() {
dict.RegisterEnums("creditType", "资金变动类型", CreditTypeOptions)
dict.RegisterEnums("creditGroup", "资金变动分组", CreditGroupOptions)
}
const (
CreditTypeBalance = "balance" // 余额
CreditTypeIntegral = "integral" // 积分
)
const (
CreditGroupDecr = "decr" // 扣款
CreditGroupIncr = "incr" // 加款
CreditGroupOpDecr = "op_decr" // 操作扣款
CreditGroupOpIncr = "op_incr" // 操作加款
CreditGroupBalanceRecharge = "balance_recharge" // 余额充值
CreditGroupBalanceRefund = "balance_refund" // 余额退款
CreditGroupApplyCash = "apply_cash" // 申请提现
)
// CreditTypeOptions 变动类型
var CreditTypeOptions = []*model.Option{
dict.GenSuccessOption(CreditTypeBalance, "余额"),
dict.GenInfoOption(CreditTypeIntegral, "积分"),
}
// CreditGroupOptions 变动分组
var CreditGroupOptions = []*model.Option{
dict.GenWarningOption(CreditGroupDecr, "扣款"),
dict.GenSuccessOption(CreditGroupIncr, "加款"),
dict.GenWarningOption(CreditGroupOpDecr, "操作扣款"),
dict.GenSuccessOption(CreditGroupOpIncr, "操作加款"),
dict.GenWarningOption(CreditGroupBalanceRefund, "余额退款"),
dict.GenSuccessOption(CreditGroupBalanceRecharge, "余额充值"),
dict.GenInfoOption(CreditGroupApplyCash, "申请提现"),
}
```
#### 自定义方法字典
- 适用于非固定选项,如数据是从某个表/文件读取或从第三方读取,数据需要进行转换时使用
##### 方法字典接口
- 文件路径server/internal/consts/credit_log.go
```go
package dict
// FuncDict 方法字典,实现本接口即可使用内置方法字典
type FuncDict func(ctx context.Context) (res []*model.Option, err error)
```
##### 一个例子
- 定义获取字典数据方法,并注册字典类型
- 文件路径server/internal/logic/admin/post.go
```go
package admin
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/dict"
"hotgo/internal/model"
"hotgo/internal/model/entity"
"hotgo/internal/service"
)
type sAdminPost struct{}
func NewAdminPost() *sAdminPost {
return &sAdminPost{}
}
func init() {
service.RegisterAdminPost(NewAdminPost())
dict.RegisterFunc("adminPostOption", "岗位选项", service.AdminPost().Option)
}
// Option 岗位选项
func (s *sAdminPost) Option(ctx context.Context) (opts []*model.Option, err error) {
var list []*entity.AdminPost
if err = dao.AdminPost.Ctx(ctx).OrderAsc(dao.AdminPost.Columns().Sort).Scan(&list); err != nil {
return nil, err
}
if len(list) == 0 {
opts = make([]*model.Option, 0)
return
}
for _, v := range list {
opts = append(opts, dict.GenHashOption(v.Id, v.Name))
}
return
}
```
#### 代码生成支持
- 内置的枚举字典和自定义方法字典在生成代码时可以直接进行选择,生成代码格式和系统字典管理写法一致
![最终编辑表单效果](images/sys-library-dict.png)
#### 内置字典和系统字典的区分
##### 主要区别
- 系统字典由表:`hg_sys_dict_type`和`hg_sys_dict_data`共同进行维护,使用时需通过后台到字典管理中进行添加
- 内置字典是系统开发期间在代码层面事先定义和注册好的数据选项
##### 数据格式区别
- 系统字典所有ID都是大于0的int64类型
- 内置字典ID都是小于0的int64类型。枚举字典以20000开头-200001381053496方法字典以30000开头-30000892528327开头以外数字是根据数据选项的`key`值进行哈希算法得出
### 地理定位
```go
// 待写
```
### 通知
```go
// 待写
## 功能扩展库
目录
- 缓存驱动
- 请求上下文
- JWT
- 数据字典
- 地理定位(待写)
- 通知(待写)
### 缓存驱动
> 系统默认的缓存驱动为file目前已支持memory|redis|file等多种驱动。请自行选择适合你的驱动使用。
- 配置文件server/manifest/config/config.yaml
```yaml
#缓存
cache:
adapter: "file" # 缓存驱动方式支持memory|redis|file不填默认memory
fileDir: "./storage/cache" # 文件缓存路径adapter=file时必填
```
#### 使用方式
```go
package main
import (
"hotgo/internal/library/cache"
"github.com/gogf/gf/v2/os/gctx"
)
func test() {
ctx := gctx.New()
// 添加/修改
cache.Instance().Set(ctx, "qwe", 123, 0)
// 查询
cache.Instance().Get(ctx, "qwe")
// 删除
cache.Instance().Remove(ctx, "qwe")
// 更多方法请参考https://goframe.org/pages/viewpage.action?pageId=27755640
}
```
### 请求上下文
- 主要用于在处理HTTP和websocket请求时通过中间件将用户、应用、插件等信息绑定到上下文中方便在做业务处理时用到这些信息
```go
package admin
import (
"fmt"
"context"
"hotgo/internal/library/contexts"
"hotgo/internal/library/addons"
)
func test(ctx context.Context) {
// 获取当前请求的所有上下文变量
var ctxModel = contexts.Get(ctx)
fmt.Printf("当前请求的所有上下文变量:%+v\n", ctxModel)
// 获取当前请求的应用模块
var module = contexts.GetModule(ctx)
fmt.Printf("当前请求的应用:%+v\n", module)
// 获取当前请求的用户信息
var member = contexts.GetUser(ctx)
fmt.Printf("当前访问用户信息:%+v\n", member)
// 获取当前请求的插件模块
fmt.Printf("当前是否为插件请求:%v", contexts.IsAddonRequest(ctx))
if contexts.IsAddonRequest(ctx) {
fmt.Printf("当前插件名称:%v", contexts.GetAddonName(ctx))
fmt.Printf("当前插件信息:%v", addons.GetModule(contexts.GetAddonName(ctx)))
}
}
```
### JWT
- 基于jwt+缓存驱动实现的用户登录令牌功能支持自动续约解决了jwt服务端无法退出问题和jwt令牌无法主动失效问题
#### 配置示例
```yaml
# 登录令牌
token:
secretKey: "hotgo123" # 令牌加密秘钥,考虑安全问题生产环境中请修改默认值
expires: 604800 # 令牌有效期单位秒。默认7天
autoRefresh: true # 是否开启自动刷新过期时间, false|true 默认为true
refreshInterval: 86400 # 刷新间隔单位秒。必须小于expires否则无法触发。默认1天内只允许刷新一次
maxRefreshTimes: 30 # 最大允许刷新次数,-1不限制。默认30次
multiLogin: true # 是否允许多端登录, false|true 默认为true
```
```go
package admin
import (
"fmt"
"context"
"hotgo/internal/library/token"
"hotgo/internal/model"
)
func test(ctx context.Context) {
// 登录
user := &model.Identity{
Id: mb.Id,
Pid: mb.Pid,
DeptId: mb.DeptId,
RoleId: ro.Id,
RoleKey: ro.Key,
Username: mb.Username,
RealName: mb.RealName,
Avatar: mb.Avatar,
Email: mb.Email,
Mobile: mb.Mobile,
App: consts.AppAdmin,
LoginAt: gtime.Now(),
}
loginToken, expires, err := token.Login(ctx, user)
if err != nil {
return nil, err
}
// gf请求对象
r := *ghttp.Request
// 获取登录用户信息
user, err := token.ParseLoginUser(r)
if err != nil {
return
}
// 注销登录
err = token.Logout(r)
}
```
### 数据字典
- hotgo增加了对枚举字典和自定义方法字典的内置支持从而在系统中经常使用的一些特定数据上做出了增强。
#### 字典数据选项
- 文件路径server/internal/model/dict.go
```go
package model
// Option 字典数据选项
type Option struct {
Key interface{} `json:"key"`
Label string `json:"label" description:"字典标签"`
Value interface{} `json:"value" description:"字典键值"`
ValueType string `json:"valueType" description:"键值数据类型"`
Type string `json:"type" description:"字典类型"`
ListClass string `json:"listClass" description:"表格回显样式"`
}
```
#### 枚举字典
- 适用于系统开发期间内置的枚举数据,这样即维护了枚举值,又关联了数据字典
##### 一个例子
- 定义枚举值和字典数据选项,并注册字典类型
- 文件路径server/internal/consts/credit_log.go
```go
package consts
import (
"hotgo/internal/library/dict"
"hotgo/internal/model"
)
func init() {
dict.RegisterEnums("creditType", "资金变动类型", CreditTypeOptions)
dict.RegisterEnums("creditGroup", "资金变动分组", CreditGroupOptions)
}
const (
CreditTypeBalance = "balance" // 余额
CreditTypeIntegral = "integral" // 积分
)
const (
CreditGroupDecr = "decr" // 扣款
CreditGroupIncr = "incr" // 加款
CreditGroupOpDecr = "op_decr" // 操作扣款
CreditGroupOpIncr = "op_incr" // 操作加款
CreditGroupBalanceRecharge = "balance_recharge" // 余额充值
CreditGroupBalanceRefund = "balance_refund" // 余额退款
CreditGroupApplyCash = "apply_cash" // 申请提现
)
// CreditTypeOptions 变动类型
var CreditTypeOptions = []*model.Option{
dict.GenSuccessOption(CreditTypeBalance, "余额"),
dict.GenInfoOption(CreditTypeIntegral, "积分"),
}
// CreditGroupOptions 变动分组
var CreditGroupOptions = []*model.Option{
dict.GenWarningOption(CreditGroupDecr, "扣款"),
dict.GenSuccessOption(CreditGroupIncr, "加款"),
dict.GenWarningOption(CreditGroupOpDecr, "操作扣款"),
dict.GenSuccessOption(CreditGroupOpIncr, "操作加款"),
dict.GenWarningOption(CreditGroupBalanceRefund, "余额退款"),
dict.GenSuccessOption(CreditGroupBalanceRecharge, "余额充值"),
dict.GenInfoOption(CreditGroupApplyCash, "申请提现"),
}
```
#### 自定义方法字典
- 适用于非固定选项,如数据是从某个表/文件读取或从第三方读取,数据需要进行转换时使用
##### 方法字典接口
- 文件路径server/internal/consts/credit_log.go
```go
package dict
// FuncDict 方法字典,实现本接口即可使用内置方法字典
type FuncDict func(ctx context.Context) (res []*model.Option, err error)
```
##### 一个例子
- 定义获取字典数据方法,并注册字典类型
- 文件路径server/internal/logic/admin/post.go
```go
package admin
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/dict"
"hotgo/internal/model"
"hotgo/internal/model/entity"
"hotgo/internal/service"
)
type sAdminPost struct{}
func NewAdminPost() *sAdminPost {
return &sAdminPost{}
}
func init() {
service.RegisterAdminPost(NewAdminPost())
dict.RegisterFunc("adminPostOption", "岗位选项", service.AdminPost().Option)
}
// Option 岗位选项
func (s *sAdminPost) Option(ctx context.Context) (opts []*model.Option, err error) {
var list []*entity.AdminPost
if err = dao.AdminPost.Ctx(ctx).OrderAsc(dao.AdminPost.Columns().Sort).Scan(&list); err != nil {
return nil, err
}
if len(list) == 0 {
opts = make([]*model.Option, 0)
return
}
for _, v := range list {
opts = append(opts, dict.GenHashOption(v.Id, v.Name))
}
return
}
```
#### 代码生成支持
- 内置的枚举字典和自定义方法字典在生成代码时可以直接进行选择,生成代码格式和系统字典管理写法一致
![最终编辑表单效果](images/sys-library-dict.png)
#### 内置字典和系统字典的区分
##### 主要区别
- 系统字典由表:`hg_sys_dict_type`和`hg_sys_dict_data`共同进行维护,使用时需通过后台到字典管理中进行添加
- 内置字典是系统开发期间在代码层面事先定义和注册好的数据选项
##### 数据格式区别
- 系统字典所有ID都是大于0的int64类型
- 内置字典ID都是小于0的int64类型。枚举字典以20000开头-200001381053496方法字典以30000开头-30000892528327开头以外数字是根据数据选项的`key`值进行哈希算法得出
### 地理定位
```go
// 待写
```
### 通知
```go
// 待写
```

View File

@ -1,249 +1,250 @@
## 中间件/拦截器
目录
- 介绍
- 全局中间件
- 鉴权中间件
- 响应中间件
- 更多
### 介绍
- 在hotgo中中间件/拦截器主要作用于web请求的上下文预设、跨域请求处理、鉴权处理、请求拦截和请求结束后统一响应处理等。
### 全局中间件
```go
package main
import (
"hotgo/internal/service"
)
func main() {
// 初始化请求上下文,一般需要第一个进行加载,后续中间件存在依赖关系
service.Middleware().Ctx()
// 跨域中间件,自动处理跨域问题
service.Middleware().CORS()
// IP黑名单中间件如果请求IP被后台拉黑所有请求将被拒绝
service.Middleware().Blacklist()
// 演示系統操作限制当开启演示模式时所有POST请求将被拒绝
service.Middleware().DemoLimit()
// 请求输入预处理api使用gf规范路由并且XxxReq结构体实现了validate.Filter接口即可隐式预处理
service.Middleware().PreFilter()
// HTTP响应预处理在业务处理完成后对响应结果进行格式化和错误过滤将处理后的数据发送给请求方
service.Middleware().ResponseHandler()
}
```
### 鉴权中间件
```go
package main
import (
"github.com/gogf/gf/v2/frame/g"
)
func main() {
// 在鉴权中间件下的路由如果没有通过权限验证,后续请求将被拒绝
// 在hotgo中鉴权中间件一般是配合一个业务模块下的路由组进行使用
// 目前admin、api、home、websocket模块都已接入
// 如果你需要创建一个新的模块也需要用到鉴权中间件可以参考server/internal/logic/middleware/admin_auth.go
// 一个简单例子
s := g.Server()
s.Group("/api", func(group *ghttp.RouterGroup) {
group.Middleware(service.Middleware().ApiAuth)
group.Bind(
member.Member, // 管理员
)
})
}
```
### 响应中间件
- 文件路径server/internal/logic/middleware/response.go
#### 常用响应类型
- hotgo为一些常用的响应类型做了统一格式封装例如`application/json`、`text/xml`、`text/html`、`text/event-stream`等,默认使用`application/json`。
- 下面我们以`text/xml`为例简单演示几种使用方法:
1. 当你使用规范化路由时可直接在XxxRes结构体的`g.Meta`中声明响应类型:
```go
type HelloReq struct {
g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"`
Name string `json:"name" d:"hotgo" dc:"名字"`
}
type HelloRes struct {
g.Meta `mime:"text/xml" type:"string"`
Tips string `json:"tips"`
}
```
2. 在响应前设置响应头:
```go
var (
Hello = cHello{}
)
type cHello struct{}
func (c *cHello) Hello(ctx context.Context, req *user.HelloReq) (res *user.HelloRes, err error) {
r := ghttp.RequestFromCtx(ctx)
r.Response.Header().Set("Content-Type", "text/xml")
res = &user.HelloRes{
Tips: fmt.Sprintf("hello %v, this is the api for %v applications.", req.Name, simple.AppName(ctx)),
}
return
}
```
- 浏览器中访问响应内容如下:
![./images/sys-middleware-com-response.png](./images/sys-middleware-com-response.png)
#### 自定义响应
- 在实际开发中,可能需要使用自定义的响应类型,由于响应中间件是全局的,因此您需要对其进行单独处理。
- 推荐以下几种处理方案,可做参考:
1. 使用`ghttp.ExitAll()`需要注意的是此方法会终止后续所有的http处理
```go
package main
import (
"github.com/gogf/gf/v2/net/ghttp"
)
func main() {
r := new(ghttp.Request) // 当前请求对象
// 清空响应
r.Response.ClearBuffer()
// 写入响应
r.Response.Write("自定义响应内容")
// 终止后续http处理
r.ExitAll()
}
```
2. 在`server/internal/logic/middleware/response.go`中根据请求的独有特征进行单独的处理兼容后续http处理。
#### 重写响应错误提示
- 在实际开发中我们可能想要隐藏一些敏感错误返回给客户端友好的错误提示但开发者同时又想需要看到真实的敏感错误。对此hotgo已经进行了过滤处理下面是一个简单的例子
```go
package main
import (
"github.com/gogf/gf/v2/errors/gerror"
)
func test() error {
err = gerror.New("这是一个sql执行错误")
err = gerror.Wrap(err, "用户创建失败,请稍后重试!~")
return err
}
```
- 开启debug时的客户端响应
```json
{
"code": -1,
"message": "用户创建失败,请稍后重试!~",
"error": [
"1. 用户创建失败,请稍后重试!~",
" 1). hotgo/internal/logic/admin.(*sAdminMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526",
"2. 这是一个sql执行错误", " 1). hotgo/internal/logic/admin.(*sAdminMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:525",
" 2). hotgo/internal/controller/admin/admin.(*cMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/controller/admin/admin/member.go:157", ""
],
"timestamp": 1684145107,
"traceID": "084022730d495f17f19e550140f3e1a8"
}
```
- 关闭debug时的客户端响应
```json
{
"code": -1,
"message": "用户创建失败,请稍后重试!~",
"timestamp": 1684145107,
"traceID": "084022730d495f17f19e550140f3e1a8"
}
```
- 控制台的输出日志:
```shell
2023-05-15 18:05:07.776 {084022730d495f17f19e550140f3e1a8} 200 "GET http localhost:8000 /admin/member/list?page=1&pageSize=10&roleId=-1 HTTP/1.1" 0.002, 127.0.0.1, "http://192.168.0.207:8001/login", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Co
re/1.94.197.400 QQBrowser/11.7.5287.400", -1, "", ""
Stack:
1. 用户创建失败,请稍后重试!~
1). hotgo/internal/logic/admin.(*sAdminMember).List
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526
2. 这是一个sql执行错误
1). hotgo/internal/logic/admin.(*sAdminMember).List
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/response.go:24
13). hotgo/internal/logic/middleware.(*sMiddleware).DemoLimit
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:90
```
- 如果你开启了访问日志,那么日志记录中会详细记录本次请求的相关信息,内容如下:
![./images/sys-middleware-error-log.png](./images/sys-middleware-error-log.png)
#### 重写错误码
- hotgo默认使用了gf内置的错误码进行业务处理通常情况下成功状态码为`0`,失败状态码为`-1`
- 查看gf内置错误码https://goframe.org/pages/viewpage.action?pageId=30739587
- 以下是自定义错误码的简单例子:
```go
package main
import (
"github.com/gogf/gf/v2/errors/gerror"
)
func test() error {
// 使用自定义状态码30001响应客户端
err = gerror.NewCode(gcode.New(30001, "用户创建失败,请稍后重试!~", nil))
return err
}
```
- 客户端响应如下:
```json
{
"code": 30001,
"message": "用户创建失败,请稍后重试!~",
"timestamp": 1684146313,
"traceID": "b4f90e16264a5f17cd3fc27141aba448"
}
```
### 更多
- 更多关于中间件/拦截器的介绍请参考https://goframe.org/pages/viewpage.action?pageId=55289881
## 中间件/拦截器
目录
- 介绍
- 全局中间件
- 鉴权中间件
- 响应中间件
- 更多
### 介绍
- 在hotgo中中间件/拦截器主要作用于web请求的上下文预设、跨域请求处理、鉴权处理、请求拦截和请求结束后统一响应处理等。
### 全局中间件
```go
package main
import (
"hotgo/internal/service"
)
func main() {
// 初始化请求上下文,一般需要第一个进行加载,后续中间件存在依赖关系
service.Middleware().Ctx()
// 跨域中间件,自动处理跨域问题
service.Middleware().CORS()
// IP黑名单中间件如果请求IP被后台拉黑所有请求将被拒绝
service.Middleware().Blacklist()
// 演示系統操作限制当开启演示模式时所有POST请求将被拒绝
service.Middleware().DemoLimit()
// 请求输入预处理api使用gf规范路由并且XxxReq结构体实现了validate.Filter接口即可隐式预处理
service.Middleware().PreFilter()
// HTTP响应预处理在业务处理完成后对响应结果进行格式化和错误过滤将处理后的数据发送给请求方
service.Middleware().ResponseHandler()
}
```
### 鉴权中间件
```go
package main
import (
"github.com/gogf/gf/v2/frame/g"
)
func main() {
// 在鉴权中间件下的路由如果没有通过权限验证,后续请求将被拒绝
// 在hotgo中鉴权中间件一般是配合一个业务模块下的路由组进行使用
// 目前admin、api、home、websocket模块都已接入
// 如果你需要创建一个新的模块也需要用到鉴权中间件可以参考server/internal/logic/middleware/admin_auth.go
// 一个简单例子
s := g.Server()
s.Group("/api", func(group *ghttp.RouterGroup) {
group.Middleware(service.Middleware().ApiAuth)
group.Bind(
member.Member, // 管理员
)
})
}
```
### 响应中间件
- 文件路径server/internal/logic/middleware/response.go
#### 常用响应类型
- hotgo为一些常用的响应类型做了统一格式封装例如`application/json`、`text/xml`、`text/html`、`text/event-stream`等,默认使用`application/json`。
- 下面我们以`text/xml`为例简单演示几种使用方法:
1. 当你使用规范化路由时可直接在XxxRes结构体的`g.Meta`中声明响应类型:
```go
type HelloReq struct {
g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"`
Name string `json:"name" d:"hotgo" dc:"名字"`
}
type HelloRes struct {
g.Meta `mime:"text/xml" type:"string"`
Tips string `json:"tips"`
}
```
2. 在响应前设置响应头:
```go
var (
Hello = cHello{}
)
type cHello struct{}
func (c *cHello) Hello(ctx context.Context, req *user.HelloReq) (res *user.HelloRes, err error) {
r := ghttp.RequestFromCtx(ctx)
r.Response.Header().Set("Content-Type", "text/xml")
res = &user.HelloRes{
Tips: fmt.Sprintf("hello %v, this is the api for %v applications.", req.Name, simple.AppName(ctx)),
}
return
}
```
- 浏览器中访问响应内容如下:
![./images/sys-middleware-com-response.png](./images/sys-middleware-com-response.png)
#### 自定义响应
- 在实际开发中,可能需要使用自定义的响应类型,由于响应中间件是全局的,因此您需要对其进行单独处理。
- 推荐以下几种处理方案,可做参考:
1. 使用`ghttp.ExitAll()`需要注意的是此方法会终止后续所有的http处理
```go
package main
import (
"github.com/gogf/gf/v2/net/ghttp"
)
func main() {
r := new(ghttp.Request) // 当前请求对象
// 清空响应
r.Response.ClearBuffer()
// 写入响应
r.Response.Write("自定义响应内容")
// 终止后续http处理
r.ExitAll()
}
```
2. 在`server/internal/logic/middleware/response.go`中根据请求的独有特征进行单独的处理兼容后续http处理。
#### 重写响应错误提示
- 在实际开发中我们可能想要隐藏一些敏感错误返回给客户端友好的错误提示但开发者同时又想需要看到真实的敏感错误。对此hotgo已经进行了过滤处理下面是一个简单的例子
```go
package main
import (
"github.com/gogf/gf/v2/errors/gerror"
)
func test() error {
err = gerror.New("这是一个sql执行错误")
err = gerror.Wrap(err, "用户创建失败,请稍后重试!~")
return err
}
```
- 开启debug时的客户端响应
```json
{
"code": -1,
"message": "用户创建失败,请稍后重试!~",
"error": [
"1. 用户创建失败,请稍后重试!~",
" 1). hotgo/internal/logic/admin.(*sAdminMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526",
"2. 这是一个sql执行错误", " 1). hotgo/internal/logic/admin.(*sAdminMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:525",
" 2). hotgo/internal/controller/admin/admin.(*cMember).List",
" E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/controller/admin/admin/member.go:157", ""
],
"timestamp": 1684145107,
"traceID": "084022730d495f17f19e550140f3e1a8"
}
```
- 关闭debug时的客户端响应
```json
{
"code": -1,
"message": "用户创建失败,请稍后重试!~",
"timestamp": 1684145107,
"traceID": "084022730d495f17f19e550140f3e1a8"
}
```
- 控制台的输出日志:
```shell
2023-05-15 18:05:07.776 {084022730d495f17f19e550140f3e1a8} 200 "GET http localhost:8000 /admin/member/list?page=1&pageSize=10&roleId=-1 HTTP/1.1" 0.002, 127.0.0.1, "http://192.168.0.207:8001/login", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Co
re/1.94.197.400 QQBrowser/11.7.5287.400", -1, "", ""
Stack:
1. 用户创建失败,请稍后重试!~
1). hotgo/internal/logic/admin.(*sAdminMember).List
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526
2. 这是一个sql执行错误
1). hotgo/internal/logic/admin.(*sAdminMember).List
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/response.go:24
13). hotgo/internal/logic/middleware.(*sMiddleware).DemoLimit
E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:90
```
- 如果你开启了访问日志,那么日志记录中会详细记录本次请求的相关信息,内容如下:
![./images/sys-middleware-error-log.png](./images/sys-middleware-error-log.png)
#### 重写错误码
- hotgo默认使用了gf内置的错误码进行业务处理通常情况下成功状态码为`0`,失败状态码为`-1`
- 查看gf内置错误码https://goframe.org/pages/viewpage.action?pageId=30739587
- 以下是自定义错误码的简单例子:
```go
package main
import (
"github.com/gogf/gf/v2/errors/gerror"
)
func test() error {
// 使用自定义状态码30001响应客户端
err = gerror.NewCode(gcode.New(30001, "用户创建失败,请稍后重试!~", nil))
return err
}
```
- 客户端响应如下:
```json
{
"code": 30001,
"message": "用户创建失败,请稍后重试!~",
"timestamp": 1684146313,
"traceID": "b4f90e16264a5f17cd3fc27141aba448"
}
```
### 更多
- 更多关于中间件/拦截器的介绍请参考https://goframe.org/pages/viewpage.action?pageId=55289881

View File

@ -44,6 +44,7 @@ SaaS系统多租户多应用设计已成为互联网企业的重要发展建
- 在用户登录成功后server端可通过上下文来获取用户部门类型来确定用户身份
- 文件路径server/internal/library/contexts/context.go
```go
package contexts
@ -87,6 +88,7 @@ func IsUserDept(ctx context.Context) bool {
- 在用户登录成功后web端可通`useUserStore`来获取用户部门类型来确定用户身份
- 文件路径web/src/store/modules/user.ts
```vue
<script lang="ts" setup>
import { useUserStore } from '@/store/modules/user';
@ -125,6 +127,7 @@ HotGo定位是中小型应用开发推荐采用一套数据库不同Schema。
下面是多租户功能演示例子代码中的使用片段
- 封装查询Model
```go
// Model 多租户功能演示ORM模型
func (s *sSysTenantOrder) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {

View File

@ -12,6 +12,7 @@
### 全局消息监听
- 所有全局的消息监听都在这里
- 文件路径web/src/utils/websocket/registerMessage.ts
```ts
import { TABS_ROUTES } from '@/store/mutation-types';
import { SocketEnum } from '@/enums/socketEnum';
@ -51,6 +52,7 @@ export function registerGlobalMessage() {
#### 单页面消息监听
- 当你只需要某个页面使用WebSocket这将是一个不错的选择下面是一个简单的演示例子
- 文件路径web/src/views/addons/hgexample/portal/websocketTest.vue
```vue
<template>
<div>
@ -190,6 +192,7 @@ export function registerGlobalMessage() {
#### 发送消息
- 向服务器发送一条消息
```ts
import { sendMsg } from '@/utils/websocket';

View File

@ -16,6 +16,7 @@
#### 1.消息处理接口
- 消息处理在设计上采用了接口化的思路。只需要实现以下接口即可进行WebSocket消息注册
- 文件路径server/internal/websocket/model.go
```go
package websocket
@ -26,6 +27,7 @@ type EventHandler func(client *Client, req *WRequest)
#### 2.定义消息处理方法
- 以下是功能案例中的一个简单演示,实现了消息处理接口,并将收到的消息原样发送给客户端
- 文件路径server/addons/hgexample/controller/websocket/handler/index.go
```go
package handler
@ -52,6 +54,7 @@ func (c *cIndex) TestMessage(client *websocket.Client, req *websocket.WRequest)
#### 3.注册消息
- 定义消息处理方法后需要将其注册到WebSocket消息处理器一般放在对应应用模块的`router/websocket.go`下即可
- 文件路径server/addons/hgexample/router/websocket.go
```go
package router
@ -80,6 +83,7 @@ func WebSocket(ctx context.Context, group *ghttp.RouterGroup) {
### 常用方法
- websocket服务器还提供了一些常用的方法下面只对部分进行说明
```go
func test() {
websocket.SendToAll() // 发送全部客户端
@ -105,6 +109,7 @@ func test() {
### 其他
- WebSocket被连接时需验证用户认证中间件所以用户必须登录成功后才能连接成功
- 参考文件server/internal/logic/middleware/weboscket_auth.go
```go
package middleware

View File

@ -4,168 +4,183 @@
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1.0, shrink-to-fit=no, viewport-fit=cover">
content="width=device-width, initial-scale=1, minimum-scale=1.0, shrink-to-fit=no, viewport-fit=cover">
<!-- Replace with your own title and description. -->
<title>HotGo-V2</title>
<meta name="description" content="基于全新GoFrame2+Vue3+NaiveUI+uniapp开发的全栖框架为二次开发而生适合中小型完整应用开发。">
<!-- Default Theme (see https://docsify.js.org/#/themes) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
<!-- Default Theme (see //docsify.js.org/#/themes) -->
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
</head>
<body>
<div id="app"></div>
<div id="app"></div>
<script>
// Docsify Configuration (see https://docsify.js.org/#/configuration)
window.$docsify = {
name: "HotGo-V2",
nameLink: {
'/': '/hotgo/',
<script>
// Docsify Configuration (see //docsify.js.org/#/configuration)
window.$docsify = {
name: "HotGo-V2",
nameLink: {
'/': '/hotgo/',
},
relativePath: true,
// alias: {
// "/.*/_navbar.md": "/_navbar.md",
// },
// themeColor: "#42b983",
// logo: "//bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png",
// coverpage: true,
// homepage: "README.md",
// Sidebar Configuration
auto2top: true,
loadSidebar: "sidebar.md",
// maxLevel: 2,
// Set subMaxLevel to 0 to remove automatic display of page table of contents (TOC) in Sidebar
// subMaxLevel: 3,
// Navbar Configuration
// loadNavbar: true,
// Search Plugin Configuration
search: {
placeholder: {
"/": "搜索",
// "/": "Type to search"
},
relativePath: true,
// alias: {
// "/.*/_navbar.md": "/_navbar.md",
// },
// themeColor: "#42b983",
// logo: "https://bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png",
// coverpage: true,
// homepage: "README.md",
// Sidebar Configuration
auto2top: true,
loadSidebar: "sidebar.md",
// maxLevel: 2,
// Set subMaxLevel to 0 to remove automatic display of page table of contents (TOC) in Sidebar
// subMaxLevel: 3,
// Navbar Configuration
// loadNavbar: true,
// Search Plugin Configuration
search: {
placeholder: {
"/": "搜索",
// "/": "Type to search"
},
noData: {
"/": "找不到结果",
// "/": "No Results"
},
// Headline depth, 1 - 6
// depth: 2,
noData: {
"/": "找不到结果",
// "/": "No Results"
},
// Headline depth, 1 - 6
// depth: 2,
},
// Flexible-alerts Plugin Configuration
"flexible-alerts": {
important: {
label: "Important",
// Flexible-alerts Plugin Configuration
"flexible-alerts": {
important: {
label: "Important",
// localization
label: {
// "/zh-cn": "重要",
"/": "Important"
},
// Assuming that we use Font Awesome
icon: "far fa-message",
className: "important"
// localization
label: {
// "/zh-cn": "重要",
"/": "Important"
},
warning: {
label: "Warning",
// localization
label: {
// "/zh-cn": "警告",
"/": "Warning"
},
// Assuming that we use Font Awesome
icon: "far fa-message",
className: "important"
},
warning: {
label: "Warning",
// Assuming that we use Font Awesome
icon: "fas fa-triangle-exclamation",
className: "warning"
// localization
label: {
// "/zh-cn": "警告",
"/": "Warning"
},
caution: {
label: "Caution",
// localization
label: {
// "/zh-cn": "注意",
"/": "Caution"
},
// Assuming that we use Font Awesome
icon: "fas fa-triangle-exclamation",
className: "warning"
},
caution: {
label: "Caution",
// Assuming that we use Font Awesome
icon: "fas fa-circle-exclamation",
className: "attention"
// localization
label: {
// "/zh-cn": "注意",
"/": "Caution"
},
// Assuming that we use Font Awesome
icon: "fas fa-circle-exclamation",
className: "attention"
},
},
// Hide-code Plugin Configuration
hideCode: {
// scroll: false, // Enable scrolling
height: 300 // Max height
},
// Hide-code Plugin Configuration
hideCode: {
// scroll: false, // Enable scrolling
height: 300 // Max height
},
// Versioned Plugin Configuration
// versions: [
// { folder: "/", label: "v2", default: true },
// ],
// versionSelectorLabel: "Version",
// Versioned Plugin Configuration
// versions: [
// { folder: "/", label: "v2", default: true },
// ],
// versionSelectorLabel: "Version",
// Progress Plugin Configuration
progress: {
position: "top",
// color: "var(--theme-color,#42b983)",
height: "3px",
},
};
</script>
// Progress Plugin Configuration
progress: {
position: "top",
// color: "var(--theme-color,#42b983)",
height: "3px",
},
};
</script>
<!-- Required -->
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
<!-- Required -->
<script src="//cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
<!-- Recommended -->
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/zoom-image.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-hide-code/dist/docsify-hide-code.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-progress@latest/dist/progress.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/docsify-example-panels"></script>
<!-- Recommended -->
<script src="//cdn.jsdelivr.net/npm/docsify@4/lib/plugins/zoom-image.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify@4/lib/plugins/search.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-hide-code/dist/docsify-hide-code.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-progress@latest/dist/progress.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/docsify-example-panels"></script>
<!-- Prism code highlight -->
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-matlab.min.js"></script>
<!-- Prism code highlight -->
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-bash.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-matlab.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-go.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-yaml.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-vue.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-json.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-sql.min.js"></script>
<!-- docsify-dark-switcher -->
<script src="https://cdn.jsdelivr.net/gh/LIGMATV/docsify-dark-switcher@latest/docsify-dark-switcher.js"></script>
<style>
:root {
--dark-base-background: #222;
--dark-base-color: #bbc0c4;
--dark-theme-color: var(--theme-color, #42b983);
--dark-code-color: var(--dark-color);
--dark-heading-color: var(--dark-theme-color);
--dark-cover-background: #000000a8;
--dark-code-background: #303030;
--dark-tip-background: #2c0000;
--dark-warn-background: #005842;
--dark-icon-size: 25px;
--dark-icon-transition: .1s ease-in-out .1s;
--dark-moon-color: #000000;
--dark-sun-color: #ffffff;
}
</style>
<!--mermaid插件-->
<script type="module">
import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
mermaid.initialize({ startOnLoad: true });
window.mermaid = mermaid;
</script>
<script src="//unpkg.com/docsify-mermaid@2.0.1/dist/docsify-mermaid.js"></script>
<!-- docsify-dark-switcher -->
<script src="//cdn.jsdelivr.net/gh/LIGMATV/docsify-dark-switcher@latest/docsify-dark-switcher.js"></script>
<style>
:root {
--dark-base-background: #222;
--dark-base-color: #bbc0c4;
--dark-theme-color: var(--theme-color, #42b983);
--dark-code-color: var(--dark-color);
--dark-heading-color: var(--dark-theme-color);
--dark-cover-background: #000000a8;
--dark-code-background: #303030;
--dark-tip-background: #2c0000;
--dark-warn-background: #005842;
--dark-icon-size: 25px;
--dark-icon-transition: .1s ease-in-out .1s;
--dark-moon-color: #000000;
--dark-sun-color: #ffffff;
}
</style>
<!-- docsify-plugin-flexible-alerts -->
<script src="//cdn.jsdelivr.net/npm/docsify-plugin-flexible-alerts/dist/docsify-plugin-flexible-alerts.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/js/all.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/fontawesome.min.css">
<!-- docsify-versioned-plugin -->
<!-- <script src="//cdn.jsdelivr.net/npm/docsify-versioned-plugin@0.0.1/index.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-versioned-plugin@0.0.1/styles.css"> -->
<!-- docsify-plugin-flexible-alerts -->
<script src="https://cdn.jsdelivr.net/npm/docsify-plugin-flexible-alerts/dist/docsify-plugin-flexible-alerts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/js/all.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/fontawesome.min.css">
<!-- docsify-versioned-plugin -->
<!-- <script src="https://cdn.jsdelivr.net/npm/docsify-versioned-plugin@0.0.1/index.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-versioned-plugin@0.0.1/styles.css"> -->
</body>

View File

@ -57,4 +57,5 @@ var HTTPHandlerTimeOptions = []*model.Option{
var HTTPApiCodeOptions = []*model.Option{
dict.GenSuccessOption(gcode.CodeOK.Code(), fmt.Sprintf("%v %v", gcode.CodeOK.Code(), "成功")),
dict.GenWarningOption(gcode.CodeNil.Code(), fmt.Sprintf("%v %v", gcode.CodeNil.Code(), "失败")),
dict.GenWarningOption(gcode.CodeSecurityReason.Code(), fmt.Sprintf("%v %v", gcode.CodeSecurityReason.Code(), "无访问权限")),
}

View File

@ -7,5 +7,5 @@ package consts
// VersionApp HotGo版本
const (
VersionApp = "2.16.10"
VersionApp = "2.17.8"
)

View File

@ -46,9 +46,13 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
var sorter2 []*form.Sorter
for k, sorter := range sorters {
if gstr.HasPrefix(sorter.ColumnKey, as) {
as2 := as
if gstr.Contains(sorter.ColumnKey, `.`) {
as2 += "."
}
if gstr.HasPrefix(sorter.ColumnKey, as2) {
sorter2 = append(sorter2, &form.Sorter{
ColumnKey: gstr.Replace(sorter.ColumnKey, as, ""),
ColumnKey: gstr.Replace(sorter.ColumnKey, as2, ""),
Order: sorter.Order,
})
removeIndex = append(removeIndex, k)

View File

@ -757,7 +757,8 @@ func (s *sAdminMember) GetIdByCode(ctx context.Context, in *adminin.GetIdByCodeI
// Select 获取可选的用户选项
func (s *sAdminMember) Select(ctx context.Context, in *adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) {
err = dao.AdminMember.Ctx(ctx).Fields(fmt.Printf("%s as value,%s as label,%s,%s", dao.AdminMember.Columns().Id, dao.AdminMember.Columns().RealName, dao.AdminMember.Columns().Username, dao.AdminMember.Columns().Avatar)).
fields := fmt.Sprintf("%s as value,%s as label,%s,%s", dao.AdminMember.Columns().Id, dao.AdminMember.Columns().RealName, dao.AdminMember.Columns().Username, dao.AdminMember.Columns().Avatar)
err = dao.AdminMember.Ctx(ctx).Fields(fields).
Handler(handler.FilterAuthWithField("id")).
Scan(&res)
if err != nil {

View File

@ -119,7 +119,11 @@ func (s *sSysEmsLog) List(ctx context.Context, in *sysin.EmsLogListInp) (list []
// Send 发送邮件
func (s *sSysEmsLog) Send(ctx context.Context, in *sysin.SendEmsInp) (err error) {
var models *entity.SysEmsLog
if err = dao.SysEmsLog.Ctx(ctx).Where("event", in.Event).Where("email", in.Email).Scan(&models); err != nil {
if err = dao.SysEmsLog.Ctx(ctx).
Where("event", in.Event).
Where("email", in.Email).
OrderDesc(dao.SysEmsLog.Columns().Id).
Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return
}
@ -239,7 +243,7 @@ func (s *sSysEmsLog) newView(ctx context.Context, in *sysin.SendEmsInp, config *
basic = new(model.BasicConfig)
basic.Name = simple.AppName(ctx)
basic.Domain = "https://hotgo.facms.cn"
basic.Logo = "http://bufanyun.cn-bj.ufileos.com/haoka/attachment/images/2023-02-04/cq9kf7s66jt7hkpvbh.png"
basic.Logo = "https://gmycos.facms.cn/haoka/attachment/images/2023-02-04/cq9kf7s66jt7hkpvbh.png"
basic.SystemOpen = true
}
@ -380,7 +384,11 @@ func (s *sSysEmsLog) VerifyCode(ctx context.Context, in *sysin.VerifyEmsCodeInp)
}
var models *entity.SysEmsLog
if err = dao.SysEmsLog.Ctx(ctx).Where(dao.SysEmsLog.Columns().Event, in.Event).Where(dao.SysEmsLog.Columns().Email, in.Email).Order(dao.SysEmsLog.Columns().Id, false).Scan(&models); err != nil {
if err = dao.SysEmsLog.Ctx(ctx).
Where(dao.SysEmsLog.Columns().Event, in.Event).
Where(dao.SysEmsLog.Columns().Email, in.Email).
OrderDesc(dao.SysEmsLog.Columns().Id).
Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}

View File

@ -103,7 +103,11 @@ func (s *sSysSmsLog) SendCode(ctx context.Context, in *sysin.SendCodeInp) (err e
}
var models *entity.SysSmsLog
if err = dao.SysSmsLog.Ctx(ctx).Where(dao.SysSmsLog.Columns().Event, in.Event).Where(dao.SysSmsLog.Columns().Mobile, in.Mobile).Scan(&models); err != nil {
if err = dao.SysSmsLog.Ctx(ctx).
Where(dao.SysSmsLog.Columns().Event, in.Event).
Where(dao.SysSmsLog.Columns().Mobile, in.Mobile).
OrderDesc(dao.SysSmsLog.Columns().Id).
Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return
}

View File

@ -1292,44 +1292,44 @@ INSERT INTO hg_addon_hgexample_table (
created_at, updated_at, deleted_at
) VALUES
(1, 0, 1, NULL, 1, '[1, 2]', '测试标题', '描述', '<p>这是内容............</p>',
'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"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg", "https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg"]',
'http://localhost:8000/attachment/2023-07-18/cu54ama4z54oejf5xx.mp3',
'["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"]',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx", "https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc"]',
'{"key": "qwe", "value": "123"}', 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, '备注', 1, 1, 1,
'2022-12-15 19:30:14', '2023-07-18 20:05:45', NULL),
(2, 0, 1, NULL, 0, '[1]', '测试2', '描述', '<h2><strong>不知道写点啥</strong></h2><p><br></p><p></p>',
'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"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqaup19k9oznyixz.doc"]',
'{}', 2.5, 10.00, 0,
'2023-02-18', NULL, NULL,
0, 30, '', 0, '', '1561561@qq.com',
'15303830571', '[2, 1]', 3, 140214, '', 1, 1, 1,
'2023-02-06 14:17:11', '2023-11-13 17:18:18', NULL),
(3, 1, 2, 'tr_1 ', 0, '[1]', 'AAA', '', '',
'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'', '{}', '{}', 1.0, 10.00, 0,
'2023-11-13', NULL, NULL,
1, 40, '', 0, '13311', '1331@qq.cc',
'15303830571', '{}', 0, 0, '', 1, 1, 1,
'2023-11-13 17:34:42', '2023-11-13 17:55:26', NULL),
(4, 1, 2, 'tr_1 ', 0, '[1]', 'BBB', '', '',
'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'', '{}', '{}', 2.5, 10.00, 0,
'2023-11-13', NULL, NULL,
0, 50, '', 0, '12212', '165165@q.cc',
'15303830561', '{}', 0, 0, '', 1, 1, 1,
'2023-11-13 17:43:58', '2023-11-13 17:43:58', NULL),
(5, 3, 3, 'tr_1 tr_3', 0, '[1]', 'A1', '', '',
'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp1',
'["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp',
'["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]',
'', '{}', '{}', 1.0, 10.00, 0,
'2023-11-13', NULL, NULL,
1, 60, '', 0, '10121212', '122112@qq.cc',
@ -1406,10 +1406,10 @@ INSERT INTO hg_admin_member (
created_at, updated_at
) VALUES
(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '',
88.00, 99289.78, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
88.00, 99289.78, 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号',
0, 1, '', '111',
'{"name": "孟帅", "account": "15303830571", "payeeCode": "http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg"}',
'{"name": "孟帅", "account": "15303830571", "payeeCode": "https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg"}',
'2024-08-27 19:02:49', NULL, 1,
'2021-02-12 17:59:45', '2024-08-27 19:02:49'),
@ -1426,28 +1426,28 @@ INSERT INTO hg_admin_member (
'2023-02-03 17:34:31', '2024-04-16 18:56:00'),
(9, 100, 206, '黄敏', 'test_finance', '151f5f6bb8b223fc7b589a32effb6f91', 'FhShzw', '',
0.00, 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
0.00, 0.00, 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1, '', '', '', NULL, 0, '',
1, 2, 'tr_1 ', '5jZUI3uWLfcj', NULL,
NULL, '', 1,
'2023-08-02 11:30:45', '2023-08-02 11:31:09'),
(11, 111, 209, '刘芳', 'abai', '5787c7a121190011fac8376b1d3e0396', 'puUFvx', '',
0.00, 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
0.00, 0.00, 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1, '', '', '', NULL, 0, '',
8, 3, 'tr_1 tr_8 ', 'SH5akjqInb2p', NULL,
'2024-04-16 18:56:02', '', 1,
'2023-08-02 14:24:50', '2024-04-16 18:56:02'),
(12, 110, 210, '李明', 'asong', '18d1e667e2e756c03186ff6d33b18fd4', 'ONYhgf', '',
1.00, 0.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1.00, 0.00, 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1, '', '', '', NULL, 0, '',
11, 4, 'tr_1 tr_8 tr_11 ', 'pHffclXhgeg9', NULL,
'2024-04-23 18:05:03', '', 1,
'2023-08-02 14:50:49', '2024-07-21 21:49:46'),
(13, 110, 210, '', 'user123', 'a67ec13a65125a6b2566c4229c6c496a', 'auQwMY', '',
0.00, 1.00, 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
0.00, 1.00, 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png',
1, '', '', '', NULL, 0, '',
1, 2, 'tr_1 ', 'bpZPxskFMBra', NULL,
'2024-04-12 11:52:31', '', 1,
@ -2856,7 +2856,7 @@ INSERT INTO hg_sys_config (id, "group", name, type, key, value, default_value, s
(2, 'theme', '默认系统主题', 'string', 'themeAppTheme', '#2d8cf0', '#2d8cf0', 60, '', 1, 1, '2021-01-30 13:27:43', '2022-09-05 20:29:05'),
(3, 'theme', '默认侧边栏风格', 'string', 'themeNavTheme', 'light', 'dark', 70, '', 1, 1, '2021-01-30 13:27:43', '2022-09-05 20:29:05'),
(6, 'basic', '网站名称', 'string', 'basicName', 'HotGo', 'HotGo!', 10, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(7, 'basic', '网站logo', 'string', 'basicLogo', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 20, '首页使用', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(7, 'basic', '网站logo', 'string', 'basicLogo', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 20, '首页使用', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(8, 'basic', '网站备案号', 'string', 'basicIcpCode', '豫ICP备16035288号', '', 30, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(9, 'basic', '网站开启访问', 'bool', 'basicSystemOpen', '1', 'true', 50, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(10, 'basic', '网站关闭提示', 'string', 'basicCloseText', '网站维护中暂时无法访问本网站正在进行系统维护和技术升级网站暂时无法访问敬请谅解', '网站维护中暂时无法访问本网站正在进行系统维护和技术升级网站暂时无法访问敬请谅解', 60, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:29'),
@ -2879,7 +2879,7 @@ INSERT INTO hg_sys_config (id, "group", name, type, key, value, default_value, s
(37, 'upload', 'UCloud地域API', 'string', 'uploadUCloudBucketHost', 'api.ucloud.cn', 'api.ucloud.cn', 390, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(38, 'upload', 'UCloud存储桶名称', 'string', 'uploadUCloudBucketName', 'bufanyun', '', 400, '存储空间名称', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(39, 'upload', 'UCloud存储桶地域host', 'string', 'uploadUCloudFileHost', 'cn-bj.ufileos.com', 'cn-bj.ufileos.com', 410, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(40, 'upload', 'UCloud访问域名', 'string', 'uploadUCloudEndpoint', 'http://bufanyun.cn-bj.ufileos.com', '', 420, '格式http://abc.com 或 https://abc.com不可为空', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(40, 'upload', 'UCloud访问域名', 'string', 'uploadUCloudEndpoint', 'https://gmycos.facms.cn', '', 420, '格式http://abc.com 或 https://abc.com不可为空', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(41, 'geo', '高德Web服务key', 'string', 'geoAmapWebKey', '', '', 500, '申请地址https://console.amap.com/dev/key/app', 1, 1, '2021-01-30 13:27:43', '2022-12-07 15:48:43'),
(42, 'sms', '短信驱动,aliyun阿里云;tencent腾讯云', 'string', 'smsDrive', 'tencent', '', 600, '', 1, 1, '2021-01-30 13:27:43', '2023-04-10 13:55:32'),
(43, 'sms', '阿里云AccessKeyID', 'string', 'smsAliYunAccessKeyID', '', '', 610, '应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak 获取', 1, 1, '2021-01-30 13:27:43', '2023-04-10 13:55:32'),
@ -2951,7 +2951,7 @@ INSERT INTO hg_sys_config (id, "group", name, type, key, value, default_value, s
(116, 'login', '默认注册角色', 'int64', 'loginRoleId', '210', '', 1140, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:49'),
(117, 'login', '默认注册部门', 'int64', 'loginDeptId', '110', '', 1150, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(118, 'login', '默认注册岗位', '[]int64', 'loginPostIds', '[4]', '', 1160, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(119, 'login', '默认注册头像', 'string', 'loginAvatar', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 1170, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(119, 'login', '默认注册头像', 'string', 'loginAvatar', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 1170, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(120, 'login', '强制邀请', 'int', 'loginForceInvite', '2', '1', 1190, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:49'),
(121, 'login', '自动获取openId', 'int', 'loginAutoOpenId', '2', '1', 1195, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(122, 'upload', 'minio AccessKey', 'string', 'uploadMinioAccessKey', '', '', 650, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
@ -3157,7 +3157,7 @@ INSERT INTO hg_sys_gen_codes (id, gen_type, gen_template, var_name, options, db_
--
INSERT INTO hg_sys_gen_curd_demo (id, category_id, title, description, content, image, attachfile, city_id, switch, sort, status, created_by, updated_by, deleted_by, created_at, updated_at, deleted_at) VALUES
(1, 1, '测试标题', '这是一个CRUD生成演示关联测试分类', '<h2><strong>不知道写点啥</strong></h2><p><br></p><iframe class="ql-video" frameborder="0" allowfullscreen="true" src="https://media.w3.org/2010/05/sintel/trailer.mp4"></iframe><p><br></p><p><img src="http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png"></p>', 'http://localhost:8000/attachment/2024-07-25/d2ygbofye7ogy6kf5b.png', '["http://localhost:8000/attachment/2024-07-25/d2yh86z5wxgoyuuyv7.png","http://localhost:8000/attachment/2024-07-25/d2yh88mewqkovxgk0l.png"]', 120102, 1, 10, 1, 1, 1, NULL, '2022-12-15 19:30:14', '2024-07-25 16:28:31', NULL);
(1, 1, '测试标题', '这是一个CRUD生成演示关联测试分类', '<h2><strong>不知道写点啥</strong></h2><p><br></p><iframe class="ql-video" frameborder="0" allowfullscreen="true" src="https://media.w3.org/2010/05/sintel/trailer.mp4"></iframe><p><br></p><p><img src="https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png"></p>', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["http://localhost:8000/attachment/2024-07-25/d2yh86z5wxgoyuuyv7.png","http://localhost:8000/attachment/2024-07-25/d2yh88mewqkovxgk0l.png"]', 120102, 1, 10, 1, 1, 1, NULL, '2022-12-15 19:30:14', '2024-07-25 16:28:31', NULL);
-- --------------------------------------------------------

View File

@ -71,11 +71,11 @@ CREATE TABLE IF NOT EXISTS `hg_addon_hgexample_table` (
--
INSERT INTO `hg_addon_hgexample_table` (`id`, `pid`, `level`, `tree`, `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`, `remark`, `status`, `created_by`, `updated_by`, `created_at`, `updated_at`, `deleted_at`) VALUES
(1, 0, 1, '', 1, '[1, 2]', '测试标题', '描述', '<p>这是内容............</p>', '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://localhost:8000/attachment/2023-07-18/cu54ama4z54oejf5xx.mp3', '["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, '备注!', 1, 1, 1, '2022-12-15 19:30:14', '2023-07-18 20:05:45', NULL),
(2, 0, 1, '', 0, '[1]', '测试2', '描述', '<h2><strong>不知道写点啥</strong></h2><p><br></p><p><img src="http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqbknawlkgdttuxl.png"></p>', '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, '', 1, 1, 1, '2023-02-06 14:17:11', '2023-11-13 17:18:18', NULL),
(3, 1, 2, 'tr_1 ', 0, '[1]', 'AAA', '', '', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '1.0', '10.00', 0, '2023-11-13', NULL, NULL, 1, 40, '', 0, '13311', '1331@qq.cc', '15303830571', '{}', 0, 0, '', 1, 1, 1, '2023-11-13 17:34:42', '2023-11-13 17:55:26', NULL),
(4, 1, 2, 'tr_1 ', 0, '[1]', 'BBB', '', '', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '2.5', '10.00', 0, '2023-11-13', NULL, NULL, 0, 50, '', 0, '12212', '165165@q.cc', '15303830561', '{}', 0, 0, '', 1, 1, 1, '2023-11-13 17:43:58', '2023-11-13 17:43:58', NULL),
(5, 3, 3, 'tr_1 tr_3', 0, '[1]', 'A1', '', '', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp1', '["http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '1.0', '10.00', 0, '2023-11-13', NULL, NULL, 1, 60, '', 0, '10121212', '122112@qq.cc', '15303830571', '{}', 3, 0, '', 1, 1, 1, '2023-11-13 17:45:22', '2024-07-21 21:55:01', NULL);
(1, 0, 1, '', 1, '[1, 2]', '测试标题', '描述', '<p>这是内容............</p>', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqap5l9brk2lkavu.jpg", "https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqaqua7fw8ukbbp5.jpg"]', 'http://localhost:8000/attachment/2023-07-18/cu54ama4z54oejf5xx.mp3', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx", "https://gmycos.facms.cn/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, '备注!', 1, 1, 1, '2022-12-15 19:30:14', '2023-07-18 20:05:45', NULL),
(2, 0, 1, '', 0, '[1]', '测试2', '描述', '<h2><strong>不知道写点啥</strong></h2><p><br></p><p><img src="https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqbknawlkgdttuxl.png"></p>', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqbmxmtaq06gbnqa.jpeg', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqawg96ba4cuezvv.xlsx', '["https://gmycos.facms.cn/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, '', 1, 1, 1, '2023-02-06 14:17:11', '2023-11-13 17:18:18', NULL),
(3, 1, 2, 'tr_1 ', 0, '[1]', 'AAA', '', '', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '1.0', '10.00', 0, '2023-11-13', NULL, NULL, 1, 40, '', 0, '13311', '1331@qq.cc', '15303830571', '{}', 0, 0, '', 1, 1, 1, '2023-11-13 17:34:42', '2023-11-13 17:55:26', NULL),
(4, 1, 2, 'tr_1 ', 0, '[1]', 'BBB', '', '', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '2.5', '10.00', 0, '2023-11-13', NULL, NULL, 0, 50, '', 0, '12212', '165165@q.cc', '15303830561', '{}', 0, 0, '', 1, 1, 1, '2023-11-13 17:43:58', '2023-11-13 17:43:58', NULL),
(5, 3, 3, 'tr_1 tr_3', 0, '[1]', 'A1', '', '', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', '["https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqborf529kf4cxbm.jpeg"]', '', '{}', '{}', '1.0', '10.00', 0, '2023-11-13', NULL, NULL, 1, 60, '', 0, '10121212', '122112@qq.cc', '15303830571', '{}', 3, 0, '', 1, 1, 1, '2023-11-13 17:45:22', '2024-07-21 21:55:01', NULL);
-- --------------------------------------------------------
@ -247,13 +247,13 @@ CREATE TABLE IF NOT EXISTS `hg_admin_member` (
--
INSERT INTO `hg_admin_member` (`id`, `dept_id`, `role_id`, `real_name`, `username`, `password_hash`, `salt`, `password_reset_token`, `integral`, `balance`, `avatar`, `sex`, `qq`, `email`, `mobile`, `birthday`, `city_id`, `address`, `pid`, `level`, `tree`, `invite_code`, `cash`, `last_active_at`, `remark`, `status`, `created_at`, `updated_at`) VALUES
(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '88.00', '99289.78', '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, '', '111', '{"name": "孟帅", "account": "15303830571", "payeeCode": "http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg"}', '2024-08-27 19:02:49', NULL, 1, '2021-02-12 17:59:45', '2024-08-27 19:02:49'),
(1, 100, 1, '孟帅', 'admin', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '88.00', '99289.78', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '133814250', '133814250@qq.com', '15303830571', '2016-04-16', 410172, '莲花街001号', 0, 1, '', '111', '{"name": "孟帅", "account": "15303830571", "payeeCode": "https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8mqal5isvcb58g.jpg"}', '2024-08-27 19:02:49', NULL, 1, '2021-02-12 17:59:45', '2024-08-27 19:02:49'),
(3, 100, 2, '测试管理员', 'test', 'a7c588fffeb2c1d99b29879d7fe97c78', '6541561', '', '0.00', '4.00', '', 1, '', 'c@qq.cc', '15303888888', '2016-04-13', 371100, '大潮街道666号', 1, 2, 'tr_1 ', '222', NULL, '2024-04-24 11:47:48', '', 1, '2022-02-11 17:59:45', '2024-04-24 11:47:48'),
(8, 102, 200, '阿萌', 'ameng', '382df3b083a27886edb94e669a857c33', 'hfuUEb', '', '11.00', '4.22', '', 2, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '333', NULL, '2024-04-16 18:56:00', '', 1, '2023-02-03 17:34:31', '2024-04-16 18:56:00'),
(9, 100, 206, '黄敏', 'test_finance', '151f5f6bb8b223fc7b589a32effb6f91', 'FhShzw', '', '0.00', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '5jZUI3uWLfcj', NULL, NULL, '', 1, '2023-08-02 11:30:45', '2023-08-02 11:31:09'),
(11, 111, 209, '刘芳', 'abai', '5787c7a121190011fac8376b1d3e0396', 'puUFvx', '', '0.00', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 8, 3, 'tr_1 tr_8 ', 'SH5akjqInb2p', NULL, '2024-04-16 18:56:02', '', 1, '2023-08-02 14:24:50', '2024-04-16 18:56:02'),
(12, 110, 210, '李明', 'asong', '18d1e667e2e756c03186ff6d33b18fd4', 'ONYhgf', '', '1.00', '0.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 11, 4, 'tr_1 tr_8 tr_11 ', 'pHffclXhgeg9', NULL, '2024-04-23 18:05:03', '', 1, '2023-08-02 14:50:49', '2024-07-21 21:49:46'),
(13, 110, 210, '', 'user123', 'a67ec13a65125a6b2566c4229c6c496a', 'auQwMY', '', '0.00', '1.00', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', 'bpZPxskFMBra', NULL, '2024-04-12 11:52:31', '', 1, '2024-04-12 10:50:46', '2024-07-21 21:49:40');
(9, 100, 206, '黄敏', 'test_finance', '151f5f6bb8b223fc7b589a32effb6f91', 'FhShzw', '', '0.00', '0.00', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', '5jZUI3uWLfcj', NULL, NULL, '', 1, '2023-08-02 11:30:45', '2023-08-02 11:31:09'),
(11, 111, 209, '刘芳', 'abai', '5787c7a121190011fac8376b1d3e0396', 'puUFvx', '', '0.00', '0.00', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 8, 3, 'tr_1 tr_8 ', 'SH5akjqInb2p', NULL, '2024-04-16 18:56:02', '', 1, '2023-08-02 14:24:50', '2024-04-16 18:56:02'),
(12, 110, 210, '李明', 'asong', '18d1e667e2e756c03186ff6d33b18fd4', 'ONYhgf', '', '1.00', '0.00', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 11, 4, 'tr_1 tr_8 tr_11 ', 'pHffclXhgeg9', NULL, '2024-04-23 18:05:03', '', 1, '2023-08-02 14:50:49', '2024-07-21 21:49:46'),
(13, 110, 210, '', 'user123', 'a67ec13a65125a6b2566c4229c6c496a', 'auQwMY', '', '0.00', '1.00', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', 1, '', '', '', NULL, 0, '', 1, 2, 'tr_1 ', 'bpZPxskFMBra', NULL, '2024-04-12 11:52:31', '', 1, '2024-04-12 10:50:46', '2024-07-21 21:49:40');
-- --------------------------------------------------------
@ -551,7 +551,7 @@ CREATE TABLE IF NOT EXISTS `hg_admin_notice` (
INSERT INTO `hg_admin_notice` (`id`, `title`, `type`, `tag`, `content`, `receiver`, `remark`, `sort`, `status`, `created_by`, `updated_by`, `created_at`, `updated_at`, `deleted_at`) VALUES
(29, '2023年春季学期开学工作通知', 1, 1, '1.学生2月11日2月12日报到2月13日起安排考试\n\n2.教职工2月10日周五起正式上班2月11日2月12日正常上班\n\n3.校内进行的各类社会服务项目主办部门单位须关注参与人员的健康状况如有异常第一时间报告感染后仍在康复期内的师生不参加剧烈活动开学后两周内原则上不组织各类竞技性较强的体育比赛等活动\n\n4.全校师生员工要牢固树立健康第一的观念切实增强个人责任感和防护意识掌握防护技能坚持戴口罩勤洗手等良好卫生习惯加强身体锻炼保持健康生活方式提升健康素养和自我防护能力当好自身健康第一责任人符合条件的师生积极有序接种第二剂次加强针疫苗', 'null', '', 10, 1, 1, 1, '2023-02-09 12:25:39', '2023-02-09 12:48:08', NULL),
(30, '国务院办公厅关于2023年部分节假日安排的通知', 1, 3, '新华社北京12月8日电 国务院办公厅关于2023年部分节假日安排的通知全文如下\n\n  各省自治区直辖市人民政府国务院\n\n  各部委各直属机构\n\n  经国务院批准现将2023年元旦春节清明节劳动节端午节中秋节和国庆节放假调休日期的具体安排通知如下\n\n  元旦2022年12月31日至2023年1月2日放假调休共3天\n\n  春节1月21日至27日放假调休共7天1月28日星期六1月29日星期日上班\n\n  清明节4月5日放假共1天\n\n  劳动节4月29日至5月3日放假调休共5天4月23日星期日5月6日星期六上班\n\n  端午节6月22日至24日放假调休共3天6月25日星期日上班\n\n  中秋节国庆节9月29日至10月6日放假调休共8天10月7日星期六10月8日星期日上班\n\n  节假日期间各地区各部门要妥善安排好值班和安全保卫疫情防控等工作遇有重大突发事件要按规定及时报告并妥善处置确保人民群众祥和平安度过节日假期', 'null', '', 20, 1, 1, 1, '2023-02-09 12:32:32', '2023-02-09 12:48:28', NULL),
(31, 'hotgo新版本发布啦', 2, 4, '<p><img src="http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdr8lj1mpl0eu0jpn.png"></p><h2><br></h2><h2>本次更新内容如下</h2><h2>1. 优化角色权限</h2><h2>2. 优化代码生成</h2><h2>3. ....</h2>', 'null', '', 30, 1, 1, 0, '2023-02-09 12:45:17', '2023-02-09 12:45:17', '2023-06-09 18:04:30'),
(31, 'hotgo新版本发布啦', 2, 4, '<p><img src="https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdr8lj1mpl0eu0jpn.png"></p><h2><br></h2><h2>本次更新内容如下</h2><h2>1. 优化角色权限</h2><h2>2. 优化代码生成</h2><h2>3. ....</h2>', 'null', '', 30, 1, 1, 0, '2023-02-09 12:45:17', '2023-02-09 12:45:17', '2023-06-09 18:04:30'),
(32, '新的好友', 3, 5, '<p><strong>哈喽你好呀</strong></p>', '[1, 3, 8]', '', 40, 1, 1, 3, '2023-02-09 12:45:54', '2023-08-11 15:19:04', NULL);
-- --------------------------------------------------------
@ -1423,7 +1423,7 @@ INSERT INTO `hg_sys_config` (`id`, `group`, `name`, `type`, `key`, `value`, `def
(2, 'theme', '默认系统主题', 'string', 'themeAppTheme', '#2d8cf0', '#2d8cf0', 60, '', 1, 1, '2021-01-30 13:27:43', '2022-09-05 20:29:05'),
(3, 'theme', '默认侧边栏风格', 'string', 'themeNavTheme', 'light', 'dark', 70, '', 1, 1, '2021-01-30 13:27:43', '2022-09-05 20:29:05'),
(6, 'basic', '网站名称', 'string', 'basicName', 'HotGo', 'HotGo!', 10, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(7, 'basic', '网站logo', 'string', 'basicLogo', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 20, '首页使用', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(7, 'basic', '网站logo', 'string', 'basicLogo', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 20, '首页使用', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(8, 'basic', '网站备案号', 'string', 'basicIcpCode', '豫ICP备16035288号', '', 30, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(9, 'basic', '网站开启访问', 'bool', 'basicSystemOpen', '1', 'true', 50, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:30'),
(10, 'basic', '网站关闭提示', 'string', 'basicCloseText', '网站维护中暂时无法访问本网站正在进行系统维护和技术升级网站暂时无法访问敬请谅解', '网站维护中暂时无法访问本网站正在进行系统维护和技术升级网站暂时无法访问敬请谅解', 60, '', 1, 1, '2021-01-30 13:27:43', '2024-04-21 22:58:29'),
@ -1446,7 +1446,7 @@ INSERT INTO `hg_sys_config` (`id`, `group`, `name`, `type`, `key`, `value`, `def
(37, 'upload', 'UCloud地域API', 'string', 'uploadUCloudBucketHost', 'api.ucloud.cn', 'api.ucloud.cn', 390, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(38, 'upload', 'UCloud存储桶名称', 'string', 'uploadUCloudBucketName', 'bufanyun', '', 400, '存储空间名称', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(39, 'upload', 'UCloud存储桶地域host', 'string', 'uploadUCloudFileHost', 'cn-bj.ufileos.com', 'cn-bj.ufileos.com', 410, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(40, 'upload', 'UCloud访问域名', 'string', 'uploadUCloudEndpoint', 'http://bufanyun.cn-bj.ufileos.com', '', 420, '格式http://abc.com 或 https://abc.com不可为空', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(40, 'upload', 'UCloud访问域名', 'string', 'uploadUCloudEndpoint', 'https://gmycos.facms.cn', '', 420, '格式http://abc.com 或 https://abc.com不可为空', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
(41, 'geo', '高德Web服务key', 'string', 'geoAmapWebKey', '', '', 500, '申请地址https://console.amap.com/dev/key/app', 1, 1, '2021-01-30 13:27:43', '2022-12-07 15:48:43'),
(42, 'sms', '短信驱动,aliyun阿里云;tencent腾讯云', 'string', 'smsDrive', 'tencent', '', 600, '', 1, 1, '2021-01-30 13:27:43', '2023-04-10 13:55:32'),
(43, 'sms', '阿里云AccessKeyID', 'string', 'smsAliYunAccessKeyID', '', '', 610, '应用key和密钥你可以通过 https://ram.console.aliyun.com/manage/ak 获取', 1, 1, '2021-01-30 13:27:43', '2023-04-10 13:55:32'),
@ -1518,7 +1518,7 @@ INSERT INTO `hg_sys_config` (`id`, `group`, `name`, `type`, `key`, `value`, `def
(116, 'login', '默认注册角色', 'int64', 'loginRoleId', '210', '', 1140, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:49'),
(117, 'login', '默认注册部门', 'int64', 'loginDeptId', '110', '', 1150, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(118, 'login', '默认注册岗位', '[]int64', 'loginPostIds', '[4]', '', 1160, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(119, 'login', '默认注册头像', 'string', 'loginAvatar', 'http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 1170, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(119, 'login', '默认注册头像', 'string', 'loginAvatar', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq8er9nfkchdopav.png', '', 1170, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(120, 'login', '强制邀请', 'int', 'loginForceInvite', '2', '1', 1190, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:49'),
(121, 'login', '自动获取openId', 'int', 'loginAutoOpenId', '2', '1', 1195, '', 1, 1, '2021-09-29 23:51:21', '2024-08-27 19:02:48'),
(122, 'upload', 'minio AccessKey', 'string', 'uploadMinioAccessKey', '', '', 650, '', 1, 1, '2021-01-30 13:27:43', '2024-02-28 16:56:35'),
@ -1842,7 +1842,7 @@ CREATE TABLE IF NOT EXISTS `hg_sys_gen_curd_demo` (
--
INSERT INTO `hg_sys_gen_curd_demo` (`id`, `category_id`, `title`, `description`, `content`, `image`, `attachfile`, `city_id`, `switch`, `sort`, `status`, `created_by`, `updated_by`, `deleted_by`, `created_at`, `updated_at`, `deleted_at`) VALUES
(1, 1, '测试标题', '这是一个CRUD生成演示关联测试分类', '<h2><strong>不知道写点啥</strong></h2><p><br></p><iframe class="ql-video" frameborder="0" allowfullscreen="true" src="https://media.w3.org/2010/05/sintel/trailer.mp4"></iframe><p><br></p><p><img src="http://bufanyun.cn-bj.ufileos.com/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png"></p>', 'http://localhost:8000/attachment/2024-07-25/d2ygbofye7ogy6kf5b.png', '["http://localhost:8000/attachment/2024-07-25/d2yh86z5wxgoyuuyv7.png","http://localhost:8000/attachment/2024-07-25/d2yh88mewqkovxgk0l.png"]', 120102, 1, 10, 1, 1, 1, NULL, '2022-12-15 19:30:14', '2024-07-25 16:28:31', NULL);
(1, 1, '测试标题', '这是一个CRUD生成演示关联测试分类', '<h2><strong>不知道写点啥</strong></h2><p><br></p><iframe class="ql-video" frameborder="0" allowfullscreen="true" src="https://media.w3.org/2010/05/sintel/trailer.mp4"></iframe><p><br></p><p><img src="https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdq9iuv0phsg8patk.png"></p>', 'https://gmycos.facms.cn/hotgo/attachment/2023-02-09/cqdqamvhlq4w3ki6bl.webp', 'http://localhost:8000/attachment/2024-07-25/d2yh86z5wxgoyuuyv7.png', 120102, 1, 10, 1, 1, 1, NULL, '2022-12-15 19:30:14', '2024-07-25 16:28:31', NULL);
-- --------------------------------------------------------

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{
"name": "hotgo",
"type": "module",
"version": "2.16.10",
"version": "2.17.8",
"author": {
"name": "MengShuai",
"email": "133814250@qq.com",
@ -44,7 +44,7 @@
"lodash-es": "^4.17.21",
"mint-filter": "^4.0.3",
"mitt": "^3.0.1",
"naive-ui": "^2.41.0",
"naive-ui": "^2.42.0",
"pinia": "^2.2.2",
"pinyin-pro": "^3.24.2",
"print-js": "^1.6.0",
@ -59,7 +59,7 @@
"vue-router": "^4.4.3",
"vue-types": "^5.1.3",
"vue-waterfall-plugin-next": "^2.6.0",
"vue3-json-viewer": "^2.2.2",
"vue3-json-viewer": "^2.4.1",
"vuedraggable": "^4.1.0",
"weixin-js-sdk": "^1.6.5"
},

View File

@ -1,7 +1,8 @@
<template>
<span :style="{ color }">
<span :style="{ color }" v-if="endVal > 0">
{{ value }}
</span>
<span :style="{ color }" v-else> 0 </span>
</template>
<script lang="ts">
import { defineComponent, ref, computed, watchEffect, unref, onMounted, watch } from 'vue';

View File

@ -46,7 +46,7 @@
import { ImportExcel } from '@/api/addons/hgexample/comp';
import type { UploadFileParams } from '@/utils/http/axios/types';
import { JsonViewer } from 'vue3-json-viewer';
import 'vue3-json-viewer/dist/index.css';
import 'vue3-json-viewer/dist/vue3-json-viewer.css';
const message = useMessage();
const response = ref<any>({});

View File

@ -199,14 +199,19 @@
<div class="mt-4">
<n-grid cols="1 s:2 m:3 l:8 xl:8 2xl:8" responsive="screen" :x-gap="16" :y-gap="8">
<n-grid-item v-for="(item, index) in iconList" :key="index" @click="item.eventObject || {}">
<NCard content-style="padding-top: 0;" size="small" :bordered="false">
<NCard
content-style="padding-top: 0;"
size="small"
:bordered="false"
v-on="item.eventObject || {}"
>
<template #footer>
<n-skeleton v-if="loading" size="medium" />
<div class="cursor-pointer" v-else>
<p class="flex justify-center">
<span>
<n-icon :size="item.size" class="flex-1" :color="item.color">
<component :is="item.icon" v-on="item.eventObject || {}" />
<component :is="item.icon" />
</n-icon>
</span>
</p>

View File

@ -107,7 +107,7 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { JsonViewer } from 'vue3-json-viewer';
import 'vue3-json-viewer/dist/index.css';
import 'vue3-json-viewer/dist/vue3-json-viewer.css';
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui';
import { View } from '@/api/log/log';

View File

@ -136,7 +136,7 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { JsonViewer } from 'vue3-json-viewer';
import 'vue3-json-viewer/dist/index.css';
import 'vue3-json-viewer/dist/vue3-json-viewer.css';
import { useRouter } from 'vue-router';
import { useMessage } from 'naive-ui';
import { View } from '@/api/log/log';

View File

@ -110,7 +110,7 @@
import { ExportOutlined, DeleteOutlined } from '@vicons/antd';
import { useRouter } from 'vue-router';
import { JsonViewer } from 'vue3-json-viewer';
import 'vue3-json-viewer/dist/index.css';
import 'vue3-json-viewer/dist/vue3-json-viewer.css';
import { adaTableScrollX } from '@/utils/hotgo';
import { loadOptions } from './model';