diff --git a/admin/src/router/index.ts b/admin/src/router/index.ts index 19ec7ea..8f1bcc4 100644 --- a/admin/src/router/index.ts +++ b/admin/src/router/index.ts @@ -3,7 +3,7 @@ import { MenuEnum } from '@/enums/appEnums' import { isExternal } from '@/utils/validate' import { constantRoutes, INDEX_ROUTE_NAME, LAYOUT, Empty } from './routes' import useUserStore from '@/stores/modules/user' - +import qs from 'query-string' // 匹配views里面所有的.vue文件,动态引入 const modules = import.meta.glob('/src/views/**/*.vue') @@ -27,6 +27,18 @@ export function filterAsyncRoutes(routes: any[], firstRoute = true) { // 创建一条路由记录 export function createRouteRecord(route: any, firstRoute: boolean): RouteRecordRaw { + let query = route.params + + try { + if (route.params) { + // console.log(route.params) + // query = + query = qs.stringify(JSON.parse(route.params)) + // console.log(query) + } + } catch (error) { + // console.error(error) + } //@ts-ignore const routeRecord: RouteRecordRaw = { path: isExternal(route.paths) ? route.paths : firstRoute ? `/${route.paths}` : route.paths, @@ -35,8 +47,8 @@ export function createRouteRecord(route: any, firstRoute: boolean): RouteRecordR hidden: !route.isShow, keepAlive: !!route.isCache, title: route.menuName, - perms: route.perms, //逗号分隔的字符串 - query: route.params, + perms: route.perms, // + query: query, icon: route.menuIcon, type: route.menuType, activeMenu: route.selected diff --git a/admin/src/views/IframeComponent.vue b/admin/src/views/IframeComponent.vue new file mode 100644 index 0000000..7389799 --- /dev/null +++ b/admin/src/views/IframeComponent.vue @@ -0,0 +1,23 @@ +vue + + + diff --git a/admin/vite.config.ts b/admin/vite.config.ts index 3e546a4..8bf6ccc 100644 --- a/admin/vite.config.ts +++ b/admin/vite.config.ts @@ -108,8 +108,8 @@ export default ({ mode }) => { host: '0.0.0.0', port: 5180, proxy: { - '/api': { - target: env.VITE_APP_BASE_URL, + '/api/': { + target: env.VITE_APP_BASE_URL + '/', changeOrigin: true, ws: true } diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 5f03281..60d4a7c 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -45,6 +45,8 @@ export default defineConfig({ { text: 'nginx配置', link: '/admin/nginx配置.md' }, { text: '路由', link: '/admin/路由.md' }, + { text: '嵌入iframe', link: '/admin/嵌入iframe.md' }, + { text: '自定义hooks', link: '/admin/自定义hooks.md' }, ] } diff --git a/docs/admin/嵌入iframe.md b/docs/admin/嵌入iframe.md new file mode 100644 index 0000000..315a481 --- /dev/null +++ b/docs/admin/嵌入iframe.md @@ -0,0 +1,7 @@ +## 嵌入iframe +1. 添加菜单 +2. 选择组件路径:IframeComponent +3. 路由参数: +``` +{"url": "/api/static/api/index.html"}或者 url=/api/static/api/index.html +``` \ No newline at end of file diff --git a/docs/server/swaggo.md b/docs/server/swaggo.md index 9f38c94..41bee19 100644 --- a/docs/server/swaggo.md +++ b/docs/server/swaggo.md @@ -479,7 +479,7 @@ type Foo struct { | minLength | `integer` | 参看 https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.2. | | enums | [\*] | 参看 https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1. | | format | `string` | 上面提到的[类型](#parameterType)的扩展格式。有关更多详细信息,请参见[数据类型格式](https://swagger.io/specification/v2/#dataTypeFormat)。 | -| collectionFormat | `string` | 指定query数组参数的格式。 可能的值为: 默认值是 `csv`。 | +| collectionFormat | `string` | 指定query数组参数的格式。 可能的值为: 默认值是 `csv`。 | ### 进一步的 @@ -714,15 +714,4 @@ type Resp struct { // @scope.write Grants write access // @scope.admin Grants read and write access to administrative information ``` - -每个API操作。 - -```go -// @Security ApiKeyAuth -``` - -使用AND条件。 - -```go -// @Security ApiKeyAuth && OAuth2Application[write, admin] -``` + \ No newline at end of file diff --git a/docs/server/数据库null值.md b/docs/server/数据库null值.md index db080e0..3e22eec 100644 --- a/docs/server/数据库null值.md +++ b/docs/server/数据库null值.md @@ -1,51 +1,38 @@ -# 数据库null值 +## 数据库null值 -问题点:数据库在int,string等类型时,同时可能允许null值,但是go中int不允许null值,读取等操作可能报错。 +问题点:数据库在int,string等类型时,同时可能允许null值,但是go中int,string等类型不允许null值,数据类型不一致就会报错。 -注:数据库应尽量避免允许null值,避免不了时使用:https://github.com/guregu/null - -相关解读:https://blog.csdn.net/qq_15437667/article/details/78780945 - -第三方库:https://pkg.go.dev/database/sql#NullInt64 -```go -// 示例 -type NullInt64 struct { - Int64 int64 - Valid bool // Valid is true if Int64 is not NULL -} -func (n *NullInt64) Scan(value any) error -func (n NullInt64) Value() (driver.Value, error) +## 解决方法,自定义结构体实现以下接口 +用于Gorm等数据库插件的扫描和写入数据库。 +``` +func (i *NullString) Scan(value any) error +func (i NullString) Value() (driver.Value, error) +``` +可以实现JSON序列化和反序列化。 +``` +func (i NullString) MarshalJSON() ([]byte, error) +func (i *NullString) UnmarshalJSON(data []byte) error +``` +用于gin框架的地址栏param参数绑定接口 +``` +func (i *NullString) UnmarshalParam(param string) error +``` +用于fmt等格式化输出(可选) +``` +func (i NullString) String() string ``` -第三方库(继承database/sql并补充json等):https://github.com/guregu/null -```go -// 示例 -type Int struct { - sql.NullInt64 -} -func (i *Int) UnmarshalJSON(data []byte) error { - err := internal.UnmarshalIntJSON(data, &i.Int64, &i.Valid, 64, strconv.ParseInt) - if err != nil { - return err - } - i.Valid = i.Int64 != 0 - return nil -} -func (i Int) MarshalJSON() ([]byte, error) { - n := i.Int64 - if !i.Valid { - n = 0 - } - return []byte(strconv.FormatInt(n, 10)), nil -} -``` - -### 自带了三个可为null类型: -1. 相对于guregu/null的优点 -2. NullFloat、NullInt:支持前端传递null、字符串数字、数字 +### 扩展了四个可为null类型: +1. NullFloat、NullInt:支持前端传递null、字符串数字、数字 ```go core.NullFloat core.NullInt +core.NullString core.NullTime -``` \ No newline at end of file +``` + +### 参考: +1. https://blog.csdn.net/qq_15437667/article/details/78780945 +2. https://pkg.go.dev/database/sql#NullInt64 +3. https://github.com/guregu/null \ No newline at end of file diff --git a/docs/server/权限验证.md b/docs/server/权限验证.md index 8a896fc..9db9906 100644 --- a/docs/server/权限验证.md +++ b/docs/server/权限验证.md @@ -1,9 +1,12 @@ # 权限验证 +路由添加`LoginAuth`中间件,可实现登录验证, -路由添加`TokenAuth`中间件,可实现登录验证, +路由添加`TokenAuth`中间件,可实现登录、菜单授权验证, `权限标识`由`接口路径`确定,例如:`/api/admin/user`,标识位为`admin:user` +```go +// 表示该路由下的所有接口都需要登录 +r := rg.Group("/", middleware.LoginAuth()) -接口路径就是权限标识,例如:`/api/admin/user`,标识位为`admin:user` -``` +// 表示该路由下的所有接口都需要登录、菜单授权 r := rg.Group("/", middleware.TokenAuth()) ``` diff --git a/docs/server/环境变量.md b/docs/server/环境变量.md index 9d979e9..b1334d7 100644 --- a/docs/server/环境变量.md +++ b/docs/server/环境变量.md @@ -1,6 +1,6 @@ # 环境变量.env -文件`/server/config/config.go`读取.env文件然后合并 +文件`/server/config/init.go`读取.env文件然后合并 -有`mapstructure`tag的,名称以`mapstructure`为准 +有`mapstructure`tag的,名称以`mapstructure`为准,尽量以大驼峰命名 -<<< @/../server/config/config.go#envConfig \ No newline at end of file +<<< @/../server/config/init.go#envConfig \ No newline at end of file diff --git a/docs/server/结构说明.md b/docs/server/结构说明.md index 2373439..9225957 100644 --- a/docs/server/结构说明.md +++ b/docs/server/结构说明.md @@ -16,6 +16,7 @@ static目录:映射为`api/static/*`,通过`go:embed`嵌入到了二进制 │ │ ├──────controller //控制器 │ │ ├──────service // 服务 │ │ ├──────schema // 结构体 +│ │ ├──────cron // 定时任务 │ ├── config // 配置 │ ├── core // core │ ├── middleware // 中间件 diff --git a/docs/server/部署Go.md b/docs/server/部署Go.md index 7498f5c..8c444a2 100644 --- a/docs/server/部署Go.md +++ b/docs/server/部署Go.md @@ -1,9 +1,9 @@ # 打包 ## 方式一:直接打包 ```bash -# linux +# 在linux打包 go build -o x_admin . -# window +# 在window打包 go build -o x_admin.exe . ``` @@ -15,20 +15,25 @@ go install github.com/goreleaser/goreleaser@latest goreleaser release --snapshot --clean ``` - +## 方式三:运行pack.bat文件打包 +``` +在window运行pack.bat文件, 可以夸平台打包,压缩打包后产物;请按需取消注释 +``` # 部署 ## 上传所有需要的文件 - 打包后的二进制文件.exe -- resources/* +- public/* - .env ## 管理进程 -我是前端er,所以我推荐使用pm2管理进程 -https://pm2.io/ +1. 推荐使用pm2管理进程,因为我是前端 + ```bash +# https://pm2.io/ + # 需要node环境 npm install pm2 -g # 之前有一种不依赖node直接安装,好像不能用了,没找见 diff --git a/server/.env.example b/server/.env.example index dfe1ab7..97d7e02 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,7 +1,7 @@ # 属性大驼峰命名,不使用全大写 # 具体配置项参考:config\config.go的config结构体 -# APP.GIN_MODE='debug' +# APP.GinMode='debug' # 项目端口 APP.Port=8001 diff --git a/server/.gitignore b/server/.gitignore index f6c68a6..0c93270 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,6 +1,7 @@ ### Go ### # Binaries for programs and plugins *.exe +!upx.exe *.exe~ *.dll *.so diff --git a/server/pack.bat b/server/pack.bat index fd5848b..06ff328 100644 --- a/server/pack.bat +++ b/server/pack.bat @@ -13,9 +13,9 @@ xcopy ".env" ".\dist\bin\windows\" /Y /I @REM # 1 目标平台的体系架构(386、amd64、arm) set GOARCH=amd64 @REM #2 目标平台的操作系统(darwin、freebsd、linux、windows) -@REM set GOOS=linux -@REM go build -ldflags "-s -w" -o ./dist/bin/linux/x-admin -@REM .\upx.exe ./dist/bin/linux/x-admin +set GOOS=linux +go build -ldflags "-s -w" -o ./dist/bin/linux/x-admin +.\upx.exe ./dist/bin/linux/x-admin @REM 打包window set GOOS=windows diff --git a/server/upx.exe b/server/upx.exe new file mode 100644 index 0000000..7f89f50 Binary files /dev/null and b/server/upx.exe differ