This commit is contained in:
孟帅
2025-07-13 18:57:52 +08:00
parent 20a9e38fa8
commit 42d5500941
23 changed files with 91 additions and 27 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"/>
## 商用说明

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

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

@@ -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
}

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';