From 283143e1bf59b8e4884344960e5f1febca95402e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?PiexlMax=28=E5=A5=87=E6=B7=BC?= <165128580+pixelmaxQm@users.noreply.github.com> Date: Sun, 8 Dec 2024 21:17:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=91=E5=B8=83v2.7.8Beta1=20(#1957)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * beta:2.7.8-a 增加自动化创建树形结构 (#1941) * feat: 支持创建树形结构 --------- Co-authored-by: piexlMax(奇淼 * 优化user store部分写法 * Update user.js * feat: 升级版本号 * Dev 278 beta2 (#1954) * 在关闭详情弹窗后 detailFrom为空对象,arr为undefined 使用slice控制台会报错 * 查询不重置pageSize * 优化主题模式相关内容 * 优化弹窗手机端显示 * bugfix:PostgreSQL initdb (#1953) * bugfix:postgresql增加显示指定template --------- Co-authored-by: PiexlMax(奇淼 <165128580+pixelmaxQm@users.noreply.github.com> --------- Co-authored-by: zayn <972858472@qq.com> Co-authored-by: Azir <2075125282@qq.com> Co-authored-by: Qing Liang <106448173+xue-ding-e@users.noreply.github.com> * docs:调整部分代码注释以及代码格式 * feat: 自动化代码字典支持多选 * fix:调整值接收器和指针接收器 * feat: 支持导出表格复制,优化增加方法页面。 * chore:初始化代码规范化。 --------- Co-authored-by: piexlMax(奇淼 Co-authored-by: Azir <2075125282@qq.com> Co-authored-by: zayn <972858472@qq.com> Co-authored-by: Qing Liang <106448173+xue-ding-e@users.noreply.github.com> Co-authored-by: cjb <75364055@qq.com> --- server/api/v1/system/auto_code_plugin.go | 4 +- server/api/v1/system/auto_code_template.go | 2 +- server/core/server.go | 2 +- server/docs/docs.go | 1121 ++++++++++++++++- server/docs/swagger.json | 1120 +++++++++++++++- server/docs/swagger.yaml | 644 +++++++++- server/initialize/ensure_tables.go | 2 +- server/initialize/gorm_mssql.go | 7 +- server/main.go | 2 +- server/model/common/basetypes.go | 7 + server/model/system/request/sys_auto_code.go | 2 + server/model/system/request/sys_casbin.go | 4 +- server/model/system/request/sys_init.go | 1 + server/model/system/request/sys_menu.go | 2 +- server/model/system/request/sys_user.go | 8 +- server/resource/package/server/api/api.go.tpl | 23 +- .../package/server/model/model.go.tpl | 27 +- .../package/server/service/service.go.tpl | 34 +- server/resource/package/web/view/form.vue.tpl | 54 +- .../resource/package/web/view/table.vue.tpl | 141 ++- .../plugin/server/api/api.go.template | 23 +- .../plugin/server/model/model.go.template | 31 +- .../plugin/server/service/service.go.template | 37 +- .../plugin/web/form/form.vue.template | 75 +- .../plugin/web/view/view.vue.template | 351 ++++-- .../example/exa_breakpoint_continue.go | 2 +- server/service/system/sys_casbin.go | 4 +- server/service/system/sys_initdb_pgsql.go | 7 +- server/source/example/file_upload_download.go | 2 +- server/source/system/api.go | 2 +- server/source/system/api_ignore.go | 2 +- server/source/system/authorities_menus.go | 7 +- server/source/system/authority.go | 2 +- server/source/system/casbin.go | 2 +- server/source/system/dictionary.go | 2 +- server/source/system/dictionary_detail.go | 4 +- server/source/system/excel_template.go | 2 +- server/source/system/menu.go | 2 +- server/source/system/user.go | 4 +- server/utils/ast/ast.go | 2 +- server/utils/ast/ast_gorm.go | 4 +- server/utils/fmt_plus.go | 28 +- server/utils/jwt.go | 4 +- server/utils/timer/timed_task.go | 4 +- web/package.json | 5 +- web/src/components/commandMenu/index.vue | 12 +- .../components/selectImage/selectImage.vue | 5 +- web/src/core/config.js | 2 +- web/src/core/gin-vue-admin.js | 2 +- web/src/hooks/charts.js | 2 +- web/src/pathInfo.json | 2 +- web/src/pinia/modules/app.js | 94 +- web/src/pinia/modules/user.js | 104 +- .../components/charts-content-numbers.vue | 3 +- web/src/view/init/index.vue | 9 +- web/src/view/layout/header/index.vue | 3 +- web/src/view/layout/header/tools.vue | 3 +- web/src/view/layout/index.vue | 4 +- web/src/view/layout/setting/index.vue | 2 +- web/src/view/superAdmin/api/api.vue | 9 +- .../view/superAdmin/authority/authority.vue | 7 +- .../superAdmin/dictionary/sysDictionary.vue | 5 +- .../dictionary/sysDictionaryDetail.vue | 7 +- web/src/view/superAdmin/menu/menu.vue | 7 +- web/src/view/superAdmin/user/user.vue | 7 +- .../autoCode/component/fieldDialog.vue | 2 +- web/src/view/systemTools/autoCode/index.vue | 31 + .../view/systemTools/autoCodeAdmin/index.vue | 103 +- .../exportTemplate/exportTemplate.vue | 33 +- 69 files changed, 3701 insertions(+), 572 deletions(-) diff --git a/server/api/v1/system/auto_code_plugin.go b/server/api/v1/system/auto_code_plugin.go index 30029feb2c..a3b5cf1ea7 100644 --- a/server/api/v1/system/auto_code_plugin.go +++ b/server/api/v1/system/auto_code_plugin.go @@ -70,7 +70,7 @@ func (a *AutoCodePluginApi) Packaged(c *gin.Context) { response.OkWithMessage(fmt.Sprintf("打包成功,文件路径为:%s", zipPath), c) } -// Packaged +// InitMenu // @Tags AutoCodePlugin // @Summary 打包插件 // @Security ApiKeyAuth @@ -94,7 +94,7 @@ func (a *AutoCodePluginApi) InitMenu(c *gin.Context) { response.OkWithMessage("文件变更成功", c) } -// Packaged +// InitAPI // @Tags AutoCodePlugin // @Summary 打包插件 // @Security ApiKeyAuth diff --git a/server/api/v1/system/auto_code_template.go b/server/api/v1/system/auto_code_template.go index af63522b99..0f6041cfb4 100644 --- a/server/api/v1/system/auto_code_template.go +++ b/server/api/v1/system/auto_code_template.go @@ -82,7 +82,7 @@ func (a *AutoCodeTemplateApi) Create(c *gin.Context) { } } -// Create +// AddFunc // @Tags AddFunc // @Summary 增加方法 // @Security ApiKeyAuth diff --git a/server/core/server.go b/server/core/server.go index 90092d04f8..796deb7a17 100644 --- a/server/core/server.go +++ b/server/core/server.go @@ -39,7 +39,7 @@ func RunWindowsServer() { fmt.Printf(` 欢迎使用 gin-vue-admin - 当前版本:v2.7.7 + 当前版本:v2.7.8-beta1 加群方式:微信号:shouzi_1994 QQ群:470239250 项目地址:https://github.com/flipped-aurora/gin-vue-admin 插件市场:https://plugin.gin-vue-admin.com diff --git a/server/docs/docs.go b/server/docs/docs.go index caf962a6b9..4ae77cef93 100644 --- a/server/docs/docs.go +++ b/server/docs/docs.go @@ -1,4 +1,5 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" @@ -331,7 +332,7 @@ const docTemplate = `{ } }, "/api/getApiGroups": { - "post": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -810,7 +811,7 @@ const docTemplate = `{ } }, "/authority/updateAuthority": { - "post": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -1281,7 +1282,7 @@ const docTemplate = `{ } } }, - "/autoCode/getDatabase": { + "/autoCode/getDB": { "get": { "security": [ { @@ -1560,6 +1561,92 @@ const docTemplate = `{ } } }, + "/autoCode/initAPI": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AutoCodePlugin" + ], + "summary": "打包插件", + "responses": { + "200": { + "description": "打包插件成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/autoCode/initMenu": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AutoCodePlugin" + ], + "summary": "打包插件", + "responses": { + "200": { + "description": "打包插件成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/autoCode/installPlugin": { "post": { "security": [ @@ -1669,7 +1756,7 @@ const docTemplate = `{ } }, "/autoCode/pubPlug": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -2407,6 +2494,55 @@ const docTemplate = `{ } }, "/fileUploadAndDownload/findFile": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExaFileUploadAndDownload" + ], + "summary": "查找文件", + "parameters": [ + { + "type": "file", + "description": "Find the file, 查找文件", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "查找文件,返回包括文件详情", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.FileResponse" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + }, "post": { "security": [ { @@ -2510,6 +2646,53 @@ const docTemplate = `{ } } }, + "/fileUploadAndDownload/importURL": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExaFileUploadAndDownload" + ], + "summary": "导入URL", + "parameters": [ + { + "description": "对象", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/example.ExaFileUploadAndDownload" + } + } + ], + "responses": { + "200": { + "description": "导入URL", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/fileUploadAndDownload/removeChunk": { "post": { "security": [ @@ -5081,23 +5264,37 @@ const docTemplate = `{ } } }, - "/system/getServerInfo": { + "/sysParams/createSysParams": { "post": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" + ], + "summary": "创建参数", + "parameters": [ + { + "description": "创建参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } ], - "summary": "获取服务器信息", "responses": { "200": { - "description": "获取服务器信息", + "description": "创建成功", "schema": { "allOf": [ { @@ -5106,10 +5303,6 @@ const docTemplate = `{ { "type": "object", "properties": { - "data": { - "type": "object", - "additionalProperties": true - }, "msg": { "type": "string" } @@ -5121,23 +5314,37 @@ const docTemplate = `{ } } }, - "/system/getSystemConfig": { - "post": { + "/sysParams/deleteSysParams": { + "delete": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" + ], + "summary": "删除参数", + "parameters": [ + { + "description": "删除参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } ], - "summary": "获取配置文件内容", "responses": { "200": { - "description": "获取配置文件内容,返回包括系统配置", + "description": "删除成功", "schema": { "allOf": [ { @@ -5146,9 +5353,6 @@ const docTemplate = `{ { "type": "object", "properties": { - "data": { - "$ref": "#/definitions/response.SysConfigResponse" - }, "msg": { "type": "string" } @@ -5160,23 +5364,26 @@ const docTemplate = `{ } } }, - "/system/reloadSystem": { - "post": { + "/sysParams/deleteSysParamsByIds": { + "delete": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" ], - "summary": "重启系统", + "summary": "批量删除参数", "responses": { "200": { - "description": "重启系统", + "description": "批量删除成功", "schema": { "allOf": [ { @@ -5196,43 +5403,484 @@ const docTemplate = `{ } } }, - "/system/setSystemConfig": { - "post": { + "/sysParams/findSysParams": { + "get": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" ], - "summary": "设置配置文件内容", + "summary": "用id查询参数", "parameters": [ { - "description": "设置配置文件内容", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/system.System" - } - } - ], - "responses": { - "200": { - "description": "设置配置文件内容", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.Response" + "type": "integer", + "description": "主键ID", + "name": "ID", + "in": "query" + }, + { + "type": "string", + "description": "创建时间", + "name": "createdAt", + "in": "query" + }, + { + "type": "string", + "description": "参数说明", + "name": "desc", + "in": "query" + }, + { + "type": "string", + "description": "参数键", + "name": "key", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "参数名称", + "name": "name", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "更新时间", + "name": "updatedAt", + "in": "query" + }, + { + "type": "string", + "description": "参数值", + "name": "value", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "查询成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysParams" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/getSysParam": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "根据key获取参数value", + "parameters": [ + { + "type": "string", + "description": "key", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysParams" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/getSysParamsList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "分页获取参数列表", + "parameters": [ + { + "type": "string", + "name": "endCreatedAt", + "in": "query" + }, + { + "type": "string", + "name": "key", + "in": "query" + }, + { + "type": "string", + "description": "关键字", + "name": "keyword", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "name": "startCreatedAt", + "in": "query" + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.PageResult" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/updateSysParams": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "更新参数", + "parameters": [ + { + "description": "更新参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } + ], + "responses": { + "200": { + "description": "更新成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/getServerInfo": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "获取服务器信息", + "responses": { + "200": { + "description": "获取服务器信息", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/getSystemConfig": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "获取配置文件内容", + "responses": { + "200": { + "description": "获取配置文件内容,返回包括系统配置", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.SysConfigResponse" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/reloadSystem": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "重启系统", + "responses": { + "200": { + "description": "重启系统", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/setSystemConfig": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "设置配置文件内容", + "parameters": [ + { + "description": "设置配置文件内容", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.System" + } + } + ], + "responses": { + "200": { + "description": "设置配置文件内容", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/user/SetSelfInfo": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysUser" + ], + "summary": "设置用户信息", + "parameters": [ + { + "description": "ID, 用户名, 昵称, 头像链接", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysUser" + } + } + ], + "responses": { + "200": { + "description": "设置用户信息", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" }, { "type": "object", "properties": { "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { "type": "string" } } @@ -5243,7 +5891,7 @@ const docTemplate = `{ } } }, - "/user/SetSelfInfo": { + "/user/SetSelfSetting": { "put": { "security": [ { @@ -5259,21 +5907,22 @@ const docTemplate = `{ "tags": [ "SysUser" ], - "summary": "设置用户信息", + "summary": "设置用户配置", "parameters": [ { - "description": "ID, 用户名, 昵称, 头像链接", + "description": "用户配置数据", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/system.SysUser" + "type": "object", + "additionalProperties": true } } ], "responses": { "200": { - "description": "设置用户信息", + "description": "设置用户配置", "schema": { "allOf": [ { @@ -5506,7 +6155,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/request.PageInfo" + "$ref": "#/definitions/request.GetUserList" } } ], @@ -5738,6 +6387,10 @@ const docTemplate = `{ } }, "definitions": { + "common.JSONMap": { + "type": "object", + "additionalProperties": true + }, "config.AliyunOSS": { "type": "object", "properties": { @@ -5965,6 +6618,32 @@ const docTemplate = `{ } } }, + "config.Minio": { + "type": "object", + "properties": { + "access-key-id": { + "type": "string" + }, + "access-key-secret": { + "type": "string" + }, + "base-path": { + "type": "string" + }, + "bucket-name": { + "type": "string" + }, + "bucket-url": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "use-ssl": { + "type": "boolean" + } + } + }, "config.Mongo": { "type": "object", "properties": { @@ -6317,6 +6996,10 @@ const docTemplate = `{ "description": "单实例模式下redis的哪个数据库", "type": "integer" }, + "name": { + "description": "代表当前实例的名字", + "type": "string" + }, "password": { "description": "密码", "type": "string" @@ -6390,6 +7073,9 @@ const docTemplate = `{ } ] }, + "minio": { + "$ref": "#/definitions/config.Minio" + }, "mongo": { "$ref": "#/definitions/config.Mongo" }, @@ -6416,6 +7102,12 @@ const docTemplate = `{ "redis": { "$ref": "#/definitions/config.Redis" }, + "redis-list": { + "type": "array", + "items": { + "$ref": "#/definitions/config.Redis" + } + }, "sqlite": { "$ref": "#/definitions/config.Sqlite" }, @@ -6590,6 +7282,10 @@ const docTemplate = `{ "use-redis": { "description": "使用redis", "type": "boolean" + }, + "use-strict-auth": { + "description": "使用树形角色分配模式", + "type": "boolean" } } }, @@ -6880,7 +7576,207 @@ const docTemplate = `{ } }, "request.AutoCode": { - "type": "object" + "type": "object", + "properties": { + "abbreviation": { + "description": "Struct简称", + "type": "string", + "example": "Struct简称" + }, + "autoCreateApiToSql": { + "description": "是否自动创建api", + "type": "boolean", + "example": false + }, + "autoCreateBtnAuth": { + "description": "是否自动创建按钮权限", + "type": "boolean", + "example": false + }, + "autoCreateMenuToSql": { + "description": "是否自动创建menu", + "type": "boolean", + "example": false + }, + "autoCreateResource": { + "description": "是否自动创建资源标识", + "type": "boolean", + "example": false + }, + "autoMigrate": { + "description": "是否自动迁移表结构", + "type": "boolean", + "example": false + }, + "businessDB": { + "description": "业务数据库", + "type": "string", + "example": "业务数据库" + }, + "description": { + "description": "Struct中文名称", + "type": "string", + "example": "Struct中文名称" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/definitions/request.AutoCodeField" + } + }, + "gvaModel": { + "description": "是否使用gva默认Model", + "type": "boolean", + "example": false + }, + "humpPackageName": { + "description": "go文件名称", + "type": "string", + "example": "go文件名称" + }, + "isAdd": { + "description": "是否新增", + "type": "boolean", + "example": false + }, + "isTree": { + "description": "是否树形结构", + "type": "boolean", + "example": false + }, + "onlyTemplate": { + "description": "是否只生成模板", + "type": "boolean", + "example": false + }, + "package": { + "type": "string" + }, + "packageName": { + "description": "文件名称", + "type": "string", + "example": "文件名称" + }, + "primaryField": { + "$ref": "#/definitions/request.AutoCodeField" + }, + "structName": { + "description": "Struct名称", + "type": "string", + "example": "Struct名称" + }, + "tableName": { + "description": "表名", + "type": "string", + "example": "表名" + }, + "treeJson": { + "description": "展示的树json字段", + "type": "string", + "example": "展示的树json字段" + } + } + }, + "request.AutoCodeField": { + "type": "object", + "properties": { + "checkDataSource": { + "description": "是否检查数据源", + "type": "boolean" + }, + "clearable": { + "description": "是否可清空", + "type": "boolean" + }, + "columnName": { + "description": "数据库字段", + "type": "string" + }, + "comment": { + "description": "数据库字段描述", + "type": "string" + }, + "dataSource": { + "description": "数据源", + "allOf": [ + { + "$ref": "#/definitions/request.DataSource" + } + ] + }, + "dataTypeLong": { + "description": "数据库字段长度", + "type": "string" + }, + "defaultValue": { + "description": "是否必填", + "type": "string" + }, + "desc": { + "description": "是否前端详情", + "type": "boolean" + }, + "dictType": { + "description": "字典", + "type": "string" + }, + "errorText": { + "description": "校验失败文字", + "type": "string" + }, + "excel": { + "description": "是否导入/导出", + "type": "boolean" + }, + "fieldDesc": { + "description": "中文名", + "type": "string" + }, + "fieldIndexType": { + "description": "索引类型", + "type": "string" + }, + "fieldJson": { + "description": "FieldJson", + "type": "string" + }, + "fieldName": { + "description": "Field名", + "type": "string" + }, + "fieldSearchHide": { + "description": "是否隐藏查询条件", + "type": "boolean" + }, + "fieldSearchType": { + "description": "搜索条件", + "type": "string" + }, + "fieldType": { + "description": "Field数据类型", + "type": "string" + }, + "form": { + "description": "Front bool ` + "`" + `json:\"front\"` + "`" + ` // 是否前端可见", + "type": "boolean" + }, + "primaryKey": { + "description": "是否主键", + "type": "boolean" + }, + "require": { + "description": "是否必填", + "type": "boolean" + }, + "sort": { + "description": "是否增加排序", + "type": "boolean" + }, + "table": { + "description": "是否前端表格列", + "type": "boolean" + } + } }, "request.CasbinInReceive": { "type": "object", @@ -6923,6 +7819,30 @@ const docTemplate = `{ } } }, + "request.DataSource": { + "type": "object", + "properties": { + "association": { + "description": "关联关系 1 一对一 2 一对多", + "type": "integer" + }, + "dbName": { + "type": "string" + }, + "hasDeletedAt": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "table": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "request.Empty": { "type": "object" }, @@ -6944,6 +7864,35 @@ const docTemplate = `{ } } }, + "request.GetUserList": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "keyword": { + "description": "关键字", + "type": "string" + }, + "nickName": { + "type": "string" + }, + "page": { + "description": "页码", + "type": "integer" + }, + "pageSize": { + "description": "每页大小", + "type": "integer" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "request.IdsReq": { "type": "object", "properties": { @@ -8001,6 +8950,44 @@ const docTemplate = `{ } } }, + "system.SysParams": { + "type": "object", + "required": [ + "key", + "name", + "value" + ], + "properties": { + "ID": { + "description": "主键ID", + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "desc": { + "description": "参数说明", + "type": "string" + }, + "key": { + "description": "参数键", + "type": "string" + }, + "name": { + "description": "参数名称", + "type": "string" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + }, + "value": { + "description": "参数值", + "type": "string" + } + } + }, "system.SysUser": { "type": "object", "properties": { @@ -8009,22 +8996,24 @@ const docTemplate = `{ "type": "integer" }, "authorities": { + "description": "多用户角色", "type": "array", "items": { "$ref": "#/definitions/system.SysAuthority" } }, "authority": { - "$ref": "#/definitions/system.SysAuthority" + "description": "用户角色", + "allOf": [ + { + "$ref": "#/definitions/system.SysAuthority" + } + ] }, "authorityId": { "description": "用户角色ID", "type": "integer" }, - "baseColor": { - "description": "基础颜色", - "type": "string" - }, "createdAt": { "description": "创建时间", "type": "string" @@ -8045,14 +9034,18 @@ const docTemplate = `{ "description": "用户昵称", "type": "string" }, + "originSetting": { + "description": "配置", + "allOf": [ + { + "$ref": "#/definitions/common.JSONMap" + } + ] + }, "phone": { "description": "用户手机号", "type": "string" }, - "sideMode": { - "description": "用户侧边主题", - "type": "string" - }, "updatedAt": { "description": "更新时间", "type": "string" @@ -8087,7 +9080,7 @@ const docTemplate = `{ // SwaggerInfo holds exported Swagger Info so clients can modify it var SwaggerInfo = &swag.Spec{ - Version: "v2.7.7", + Version: "v2.7.8-beta1", Host: "", BasePath: "", Schemes: []string{}, @@ -8095,8 +9088,6 @@ var SwaggerInfo = &swag.Spec{ Description: "使用gin+vue进行极速开发的全栈开发基础平台", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, - LeftDelim: "{{", - RightDelim: "}}", } func init() { diff --git a/server/docs/swagger.json b/server/docs/swagger.json index 80aa541c9f..e857454e6a 100644 --- a/server/docs/swagger.json +++ b/server/docs/swagger.json @@ -4,7 +4,7 @@ "description": "使用gin+vue进行极速开发的全栈开发基础平台", "title": "Gin-Vue-Admin Swagger API接口文档", "contact": {}, - "version": "v2.7.7" + "version": "v2.7.8-beta1" }, "paths": { "/api/createApi": { @@ -323,7 +323,7 @@ } }, "/api/getApiGroups": { - "post": { + "get": { "security": [ { "ApiKeyAuth": [] @@ -802,7 +802,7 @@ } }, "/authority/updateAuthority": { - "post": { + "put": { "security": [ { "ApiKeyAuth": [] @@ -1273,7 +1273,7 @@ } } }, - "/autoCode/getDatabase": { + "/autoCode/getDB": { "get": { "security": [ { @@ -1552,6 +1552,92 @@ } } }, + "/autoCode/initAPI": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AutoCodePlugin" + ], + "summary": "打包插件", + "responses": { + "200": { + "description": "打包插件成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/autoCode/initMenu": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "AutoCodePlugin" + ], + "summary": "打包插件", + "responses": { + "200": { + "description": "打包插件成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/autoCode/installPlugin": { "post": { "security": [ @@ -1661,7 +1747,7 @@ } }, "/autoCode/pubPlug": { - "get": { + "post": { "security": [ { "ApiKeyAuth": [] @@ -2399,6 +2485,55 @@ } }, "/fileUploadAndDownload/findFile": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExaFileUploadAndDownload" + ], + "summary": "查找文件", + "parameters": [ + { + "type": "file", + "description": "Find the file, 查找文件", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "查找文件,返回包括文件详情", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.FileResponse" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + }, "post": { "security": [ { @@ -2502,6 +2637,53 @@ } } }, + "/fileUploadAndDownload/importURL": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ExaFileUploadAndDownload" + ], + "summary": "导入URL", + "parameters": [ + { + "description": "对象", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/example.ExaFileUploadAndDownload" + } + } + ], + "responses": { + "200": { + "description": "导入URL", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, "/fileUploadAndDownload/removeChunk": { "post": { "security": [ @@ -5073,23 +5255,37 @@ } } }, - "/system/getServerInfo": { + "/sysParams/createSysParams": { "post": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" + ], + "summary": "创建参数", + "parameters": [ + { + "description": "创建参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } ], - "summary": "获取服务器信息", "responses": { "200": { - "description": "获取服务器信息", + "description": "创建成功", "schema": { "allOf": [ { @@ -5098,10 +5294,6 @@ { "type": "object", "properties": { - "data": { - "type": "object", - "additionalProperties": true - }, "msg": { "type": "string" } @@ -5113,23 +5305,37 @@ } } }, - "/system/getSystemConfig": { - "post": { + "/sysParams/deleteSysParams": { + "delete": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" + ], + "summary": "删除参数", + "parameters": [ + { + "description": "删除参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } ], - "summary": "获取配置文件内容", "responses": { "200": { - "description": "获取配置文件内容,返回包括系统配置", + "description": "删除成功", "schema": { "allOf": [ { @@ -5138,9 +5344,6 @@ { "type": "object", "properties": { - "data": { - "$ref": "#/definitions/response.SysConfigResponse" - }, "msg": { "type": "string" } @@ -5152,23 +5355,26 @@ } } }, - "/system/reloadSystem": { - "post": { + "/sysParams/deleteSysParamsByIds": { + "delete": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" ], - "summary": "重启系统", + "summary": "批量删除参数", "responses": { "200": { - "description": "重启系统", + "description": "批量删除成功", "schema": { "allOf": [ { @@ -5188,43 +5394,484 @@ } } }, - "/system/setSystemConfig": { - "post": { + "/sysParams/findSysParams": { + "get": { "security": [ { "ApiKeyAuth": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], "tags": [ - "System" + "SysParams" ], - "summary": "设置配置文件内容", + "summary": "用id查询参数", "parameters": [ { - "description": "设置配置文件内容", - "name": "data", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/system.System" - } - } - ], - "responses": { - "200": { - "description": "设置配置文件内容", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/response.Response" - }, + "type": "integer", + "description": "主键ID", + "name": "ID", + "in": "query" + }, + { + "type": "string", + "description": "创建时间", + "name": "createdAt", + "in": "query" + }, + { + "type": "string", + "description": "参数说明", + "name": "desc", + "in": "query" + }, + { + "type": "string", + "description": "参数键", + "name": "key", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "参数名称", + "name": "name", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "更新时间", + "name": "updatedAt", + "in": "query" + }, + { + "type": "string", + "description": "参数值", + "name": "value", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "查询成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysParams" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/getSysParam": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "根据key获取参数value", + "parameters": [ + { + "type": "string", + "description": "key", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/system.SysParams" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/getSysParamsList": { + "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "分页获取参数列表", + "parameters": [ + { + "type": "string", + "name": "endCreatedAt", + "in": "query" + }, + { + "type": "string", + "name": "key", + "in": "query" + }, + { + "type": "string", + "description": "关键字", + "name": "keyword", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "页码", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页大小", + "name": "pageSize", + "in": "query" + }, + { + "type": "string", + "name": "startCreatedAt", + "in": "query" + } + ], + "responses": { + "200": { + "description": "获取成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.PageResult" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/sysParams/updateSysParams": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysParams" + ], + "summary": "更新参数", + "parameters": [ + { + "description": "更新参数", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysParams" + } + } + ], + "responses": { + "200": { + "description": "更新成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/getServerInfo": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "获取服务器信息", + "responses": { + "200": { + "description": "获取服务器信息", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/getSystemConfig": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "获取配置文件内容", + "responses": { + "200": { + "description": "获取配置文件内容,返回包括系统配置", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/response.SysConfigResponse" + }, + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/reloadSystem": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "重启系统", + "responses": { + "200": { + "description": "重启系统", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "msg": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/system/setSystemConfig": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "System" + ], + "summary": "设置配置文件内容", + "parameters": [ + { + "description": "设置配置文件内容", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.System" + } + } + ], + "responses": { + "200": { + "description": "设置配置文件内容", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + } + } + } + ] + } + } + } + } + }, + "/user/SetSelfInfo": { + "put": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "SysUser" + ], + "summary": "设置用户信息", + "parameters": [ + { + "description": "ID, 用户名, 昵称, 头像链接", + "name": "data", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/system.SysUser" + } + } + ], + "responses": { + "200": { + "description": "设置用户信息", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/response.Response" + }, { "type": "object", "properties": { "data": { + "type": "object", + "additionalProperties": true + }, + "msg": { "type": "string" } } @@ -5235,7 +5882,7 @@ } } }, - "/user/SetSelfInfo": { + "/user/SetSelfSetting": { "put": { "security": [ { @@ -5251,21 +5898,22 @@ "tags": [ "SysUser" ], - "summary": "设置用户信息", + "summary": "设置用户配置", "parameters": [ { - "description": "ID, 用户名, 昵称, 头像链接", + "description": "用户配置数据", "name": "data", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/system.SysUser" + "type": "object", + "additionalProperties": true } } ], "responses": { "200": { - "description": "设置用户信息", + "description": "设置用户配置", "schema": { "allOf": [ { @@ -5498,7 +6146,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/request.PageInfo" + "$ref": "#/definitions/request.GetUserList" } } ], @@ -5730,6 +6378,10 @@ } }, "definitions": { + "common.JSONMap": { + "type": "object", + "additionalProperties": true + }, "config.AliyunOSS": { "type": "object", "properties": { @@ -5957,6 +6609,32 @@ } } }, + "config.Minio": { + "type": "object", + "properties": { + "access-key-id": { + "type": "string" + }, + "access-key-secret": { + "type": "string" + }, + "base-path": { + "type": "string" + }, + "bucket-name": { + "type": "string" + }, + "bucket-url": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "use-ssl": { + "type": "boolean" + } + } + }, "config.Mongo": { "type": "object", "properties": { @@ -6309,6 +6987,10 @@ "description": "单实例模式下redis的哪个数据库", "type": "integer" }, + "name": { + "description": "代表当前实例的名字", + "type": "string" + }, "password": { "description": "密码", "type": "string" @@ -6382,6 +7064,9 @@ } ] }, + "minio": { + "$ref": "#/definitions/config.Minio" + }, "mongo": { "$ref": "#/definitions/config.Mongo" }, @@ -6408,6 +7093,12 @@ "redis": { "$ref": "#/definitions/config.Redis" }, + "redis-list": { + "type": "array", + "items": { + "$ref": "#/definitions/config.Redis" + } + }, "sqlite": { "$ref": "#/definitions/config.Sqlite" }, @@ -6582,6 +7273,10 @@ "use-redis": { "description": "使用redis", "type": "boolean" + }, + "use-strict-auth": { + "description": "使用树形角色分配模式", + "type": "boolean" } } }, @@ -6872,7 +7567,207 @@ } }, "request.AutoCode": { - "type": "object" + "type": "object", + "properties": { + "abbreviation": { + "description": "Struct简称", + "type": "string", + "example": "Struct简称" + }, + "autoCreateApiToSql": { + "description": "是否自动创建api", + "type": "boolean", + "example": false + }, + "autoCreateBtnAuth": { + "description": "是否自动创建按钮权限", + "type": "boolean", + "example": false + }, + "autoCreateMenuToSql": { + "description": "是否自动创建menu", + "type": "boolean", + "example": false + }, + "autoCreateResource": { + "description": "是否自动创建资源标识", + "type": "boolean", + "example": false + }, + "autoMigrate": { + "description": "是否自动迁移表结构", + "type": "boolean", + "example": false + }, + "businessDB": { + "description": "业务数据库", + "type": "string", + "example": "业务数据库" + }, + "description": { + "description": "Struct中文名称", + "type": "string", + "example": "Struct中文名称" + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/definitions/request.AutoCodeField" + } + }, + "gvaModel": { + "description": "是否使用gva默认Model", + "type": "boolean", + "example": false + }, + "humpPackageName": { + "description": "go文件名称", + "type": "string", + "example": "go文件名称" + }, + "isAdd": { + "description": "是否新增", + "type": "boolean", + "example": false + }, + "isTree": { + "description": "是否树形结构", + "type": "boolean", + "example": false + }, + "onlyTemplate": { + "description": "是否只生成模板", + "type": "boolean", + "example": false + }, + "package": { + "type": "string" + }, + "packageName": { + "description": "文件名称", + "type": "string", + "example": "文件名称" + }, + "primaryField": { + "$ref": "#/definitions/request.AutoCodeField" + }, + "structName": { + "description": "Struct名称", + "type": "string", + "example": "Struct名称" + }, + "tableName": { + "description": "表名", + "type": "string", + "example": "表名" + }, + "treeJson": { + "description": "展示的树json字段", + "type": "string", + "example": "展示的树json字段" + } + } + }, + "request.AutoCodeField": { + "type": "object", + "properties": { + "checkDataSource": { + "description": "是否检查数据源", + "type": "boolean" + }, + "clearable": { + "description": "是否可清空", + "type": "boolean" + }, + "columnName": { + "description": "数据库字段", + "type": "string" + }, + "comment": { + "description": "数据库字段描述", + "type": "string" + }, + "dataSource": { + "description": "数据源", + "allOf": [ + { + "$ref": "#/definitions/request.DataSource" + } + ] + }, + "dataTypeLong": { + "description": "数据库字段长度", + "type": "string" + }, + "defaultValue": { + "description": "是否必填", + "type": "string" + }, + "desc": { + "description": "是否前端详情", + "type": "boolean" + }, + "dictType": { + "description": "字典", + "type": "string" + }, + "errorText": { + "description": "校验失败文字", + "type": "string" + }, + "excel": { + "description": "是否导入/导出", + "type": "boolean" + }, + "fieldDesc": { + "description": "中文名", + "type": "string" + }, + "fieldIndexType": { + "description": "索引类型", + "type": "string" + }, + "fieldJson": { + "description": "FieldJson", + "type": "string" + }, + "fieldName": { + "description": "Field名", + "type": "string" + }, + "fieldSearchHide": { + "description": "是否隐藏查询条件", + "type": "boolean" + }, + "fieldSearchType": { + "description": "搜索条件", + "type": "string" + }, + "fieldType": { + "description": "Field数据类型", + "type": "string" + }, + "form": { + "description": "Front bool `json:\"front\"` // 是否前端可见", + "type": "boolean" + }, + "primaryKey": { + "description": "是否主键", + "type": "boolean" + }, + "require": { + "description": "是否必填", + "type": "boolean" + }, + "sort": { + "description": "是否增加排序", + "type": "boolean" + }, + "table": { + "description": "是否前端表格列", + "type": "boolean" + } + } }, "request.CasbinInReceive": { "type": "object", @@ -6915,6 +7810,30 @@ } } }, + "request.DataSource": { + "type": "object", + "properties": { + "association": { + "description": "关联关系 1 一对一 2 一对多", + "type": "integer" + }, + "dbName": { + "type": "string" + }, + "hasDeletedAt": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "table": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, "request.Empty": { "type": "object" }, @@ -6936,6 +7855,35 @@ } } }, + "request.GetUserList": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "keyword": { + "description": "关键字", + "type": "string" + }, + "nickName": { + "type": "string" + }, + "page": { + "description": "页码", + "type": "integer" + }, + "pageSize": { + "description": "每页大小", + "type": "integer" + }, + "phone": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "request.IdsReq": { "type": "object", "properties": { @@ -7993,6 +8941,44 @@ } } }, + "system.SysParams": { + "type": "object", + "required": [ + "key", + "name", + "value" + ], + "properties": { + "ID": { + "description": "主键ID", + "type": "integer" + }, + "createdAt": { + "description": "创建时间", + "type": "string" + }, + "desc": { + "description": "参数说明", + "type": "string" + }, + "key": { + "description": "参数键", + "type": "string" + }, + "name": { + "description": "参数名称", + "type": "string" + }, + "updatedAt": { + "description": "更新时间", + "type": "string" + }, + "value": { + "description": "参数值", + "type": "string" + } + } + }, "system.SysUser": { "type": "object", "properties": { @@ -8001,22 +8987,24 @@ "type": "integer" }, "authorities": { + "description": "多用户角色", "type": "array", "items": { "$ref": "#/definitions/system.SysAuthority" } }, "authority": { - "$ref": "#/definitions/system.SysAuthority" + "description": "用户角色", + "allOf": [ + { + "$ref": "#/definitions/system.SysAuthority" + } + ] }, "authorityId": { "description": "用户角色ID", "type": "integer" }, - "baseColor": { - "description": "基础颜色", - "type": "string" - }, "createdAt": { "description": "创建时间", "type": "string" @@ -8037,14 +9025,18 @@ "description": "用户昵称", "type": "string" }, + "originSetting": { + "description": "配置", + "allOf": [ + { + "$ref": "#/definitions/common.JSONMap" + } + ] + }, "phone": { "description": "用户手机号", "type": "string" }, - "sideMode": { - "description": "用户侧边主题", - "type": "string" - }, "updatedAt": { "description": "更新时间", "type": "string" @@ -8075,4 +9067,4 @@ "in": "header" } } -} \ No newline at end of file +} diff --git a/server/docs/swagger.yaml b/server/docs/swagger.yaml index 430abdb260..1fac6d2521 100644 --- a/server/docs/swagger.yaml +++ b/server/docs/swagger.yaml @@ -1,4 +1,7 @@ definitions: + common.JSONMap: + additionalProperties: true + type: object config.AliyunOSS: properties: access-key-id: @@ -150,6 +153,23 @@ definitions: description: 本地文件存储路径 type: string type: object + config.Minio: + properties: + access-key-id: + type: string + access-key-secret: + type: string + base-path: + type: string + bucket-name: + type: string + bucket-url: + type: string + endpoint: + type: string + use-ssl: + type: boolean + type: object config.Mongo: properties: auth-source: @@ -409,6 +429,9 @@ definitions: db: description: 单实例模式下redis的哪个数据库 type: integer + name: + description: 代表当前实例的名字 + type: string password: description: 密码 type: string @@ -454,6 +477,8 @@ definitions: allOf: - $ref: '#/definitions/config.Local' description: oss + minio: + $ref: '#/definitions/config.Minio' mongo: $ref: '#/definitions/config.Mongo' mssql: @@ -470,6 +495,10 @@ definitions: $ref: '#/definitions/config.Qiniu' redis: $ref: '#/definitions/config.Redis' + redis-list: + items: + $ref: '#/definitions/config.Redis' + type: array sqlite: $ref: '#/definitions/config.Sqlite' system: @@ -597,6 +626,9 @@ definitions: use-redis: description: 使用redis type: boolean + use-strict-auth: + description: 使用树形角色分配模式 + type: boolean type: object config.TencentCOS: properties: @@ -800,6 +832,156 @@ definitions: type: array type: object request.AutoCode: + properties: + abbreviation: + description: Struct简称 + example: Struct简称 + type: string + autoCreateApiToSql: + description: 是否自动创建api + example: false + type: boolean + autoCreateBtnAuth: + description: 是否自动创建按钮权限 + example: false + type: boolean + autoCreateMenuToSql: + description: 是否自动创建menu + example: false + type: boolean + autoCreateResource: + description: 是否自动创建资源标识 + example: false + type: boolean + autoMigrate: + description: 是否自动迁移表结构 + example: false + type: boolean + businessDB: + description: 业务数据库 + example: 业务数据库 + type: string + description: + description: Struct中文名称 + example: Struct中文名称 + type: string + fields: + items: + $ref: '#/definitions/request.AutoCodeField' + type: array + gvaModel: + description: 是否使用gva默认Model + example: false + type: boolean + humpPackageName: + description: go文件名称 + example: go文件名称 + type: string + isAdd: + description: 是否新增 + example: false + type: boolean + isTree: + description: 是否树形结构 + example: false + type: boolean + onlyTemplate: + description: 是否只生成模板 + example: false + type: boolean + package: + type: string + packageName: + description: 文件名称 + example: 文件名称 + type: string + primaryField: + $ref: '#/definitions/request.AutoCodeField' + structName: + description: Struct名称 + example: Struct名称 + type: string + tableName: + description: 表名 + example: 表名 + type: string + treeJson: + description: 展示的树json字段 + example: 展示的树json字段 + type: string + type: object + request.AutoCodeField: + properties: + checkDataSource: + description: 是否检查数据源 + type: boolean + clearable: + description: 是否可清空 + type: boolean + columnName: + description: 数据库字段 + type: string + comment: + description: 数据库字段描述 + type: string + dataSource: + allOf: + - $ref: '#/definitions/request.DataSource' + description: 数据源 + dataTypeLong: + description: 数据库字段长度 + type: string + defaultValue: + description: 是否必填 + type: string + desc: + description: 是否前端详情 + type: boolean + dictType: + description: 字典 + type: string + errorText: + description: 校验失败文字 + type: string + excel: + description: 是否导入/导出 + type: boolean + fieldDesc: + description: 中文名 + type: string + fieldIndexType: + description: 索引类型 + type: string + fieldJson: + description: FieldJson + type: string + fieldName: + description: Field名 + type: string + fieldSearchHide: + description: 是否隐藏查询条件 + type: boolean + fieldSearchType: + description: 搜索条件 + type: string + fieldType: + description: Field数据类型 + type: string + form: + description: Front bool `json:"front"` // 是否前端可见 + type: boolean + primaryKey: + description: 是否主键 + type: boolean + require: + description: 是否必填 + type: boolean + sort: + description: 是否增加排序 + type: boolean + table: + description: 是否前端表格列 + type: boolean type: object request.CasbinInReceive: properties: @@ -829,6 +1011,22 @@ definitions: description: 密码 type: string type: object + request.DataSource: + properties: + association: + description: 关联关系 1 一对一 2 一对多 + type: integer + dbName: + type: string + hasDeletedAt: + type: boolean + label: + type: string + table: + type: string + value: + type: string + type: object request.Empty: type: object request.GetAuthorityId: @@ -843,6 +1041,26 @@ definitions: description: 主键ID type: integer type: object + request.GetUserList: + properties: + email: + type: string + keyword: + description: 关键字 + type: string + nickName: + type: string + page: + description: 页码 + type: integer + pageSize: + description: 每页大小 + type: integer + phone: + type: string + username: + type: string + type: object request.IdsReq: properties: ids: @@ -1577,23 +1795,51 @@ definitions: description: 用户id type: integer type: object + system.SysParams: + properties: + ID: + description: 主键ID + type: integer + createdAt: + description: 创建时间 + type: string + desc: + description: 参数说明 + type: string + key: + description: 参数键 + type: string + name: + description: 参数名称 + type: string + updatedAt: + description: 更新时间 + type: string + value: + description: 参数值 + type: string + required: + - key + - name + - value + type: object system.SysUser: properties: ID: description: 主键ID type: integer authorities: + description: 多用户角色 items: $ref: '#/definitions/system.SysAuthority' type: array authority: - $ref: '#/definitions/system.SysAuthority' + allOf: + - $ref: '#/definitions/system.SysAuthority' + description: 用户角色 authorityId: description: 用户角色ID type: integer - baseColor: - description: 基础颜色 - type: string createdAt: description: 创建时间 type: string @@ -1609,12 +1855,13 @@ definitions: nickName: description: 用户昵称 type: string + originSetting: + allOf: + - $ref: '#/definitions/common.JSONMap' + description: 配置 phone: description: 用户手机号 type: string - sideMode: - description: 用户侧边主题 - type: string updatedAt: description: 更新时间 type: string @@ -1634,7 +1881,7 @@ info: contact: {} description: 使用gin+vue进行极速开发的全栈开发基础平台 title: Gin-Vue-Admin Swagger API接口文档 - version: v2.7.7 + version: v2.7.8-beta1 paths: /api/createApi: post: @@ -1812,7 +2059,7 @@ paths: tags: - SysApi /api/getApiGroups: - post: + get: consumes: - application/json produces: @@ -2079,7 +2326,7 @@ paths: tags: - Authority /authority/updateAuthority: - post: + put: consumes: - application/json parameters: @@ -2347,7 +2594,7 @@ paths: summary: 获取当前表所有字段 tags: - AutoCode - /autoCode/getDatabase: + /autoCode/getDB: get: consumes: - application/json @@ -2504,6 +2751,54 @@ paths: summary: 获取package tags: - AutoCodePackage + /autoCode/initAPI: + post: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: 打包插件成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + additionalProperties: true + type: object + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 打包插件 + tags: + - AutoCodePlugin + /autoCode/initMenu: + post: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: 打包插件成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + additionalProperties: true + type: object + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 打包插件 + tags: + - AutoCodePlugin /autoCode/installPlugin: post: consumes: @@ -2567,7 +2862,7 @@ paths: tags: - AutoCodeTemplate /autoCode/pubPlug: - get: + post: consumes: - application/json parameters: @@ -2989,6 +3284,34 @@ paths: tags: - ExaFileUploadAndDownload /fileUploadAndDownload/findFile: + get: + consumes: + - multipart/form-data + parameters: + - description: Find the file, 查找文件 + in: formData + name: file + required: true + type: file + produces: + - application/json + responses: + "200": + description: 查找文件,返回包括文件详情 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/response.FileResponse' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 查找文件 + tags: + - ExaFileUploadAndDownload post: consumes: - multipart/form-data @@ -3047,6 +3370,32 @@ paths: summary: 分页文件列表 tags: - ExaFileUploadAndDownload + /fileUploadAndDownload/importURL: + post: + parameters: + - description: 对象 + in: body + name: data + required: true + schema: + $ref: '#/definitions/example.ExaFileUploadAndDownload' + produces: + - application/json + responses: + "200": + description: 导入URL + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 导入URL + tags: + - ExaFileUploadAndDownload /fileUploadAndDownload/removeChunk: post: consumes: @@ -4553,6 +4902,243 @@ paths: summary: 分页获取SysOperationRecord列表 tags: - SysOperationRecord + /sysParams/createSysParams: + post: + consumes: + - application/json + parameters: + - description: 创建参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/system.SysParams' + produces: + - application/json + responses: + "200": + description: 创建成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 创建参数 + tags: + - SysParams + /sysParams/deleteSysParams: + delete: + consumes: + - application/json + parameters: + - description: 删除参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/system.SysParams' + produces: + - application/json + responses: + "200": + description: 删除成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 删除参数 + tags: + - SysParams + /sysParams/deleteSysParamsByIds: + delete: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: 批量删除成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 批量删除参数 + tags: + - SysParams + /sysParams/findSysParams: + get: + consumes: + - application/json + parameters: + - description: 主键ID + in: query + name: ID + type: integer + - description: 创建时间 + in: query + name: createdAt + type: string + - description: 参数说明 + in: query + name: desc + type: string + - description: 参数键 + in: query + name: key + required: true + type: string + - description: 参数名称 + in: query + name: name + required: true + type: string + - description: 更新时间 + in: query + name: updatedAt + type: string + - description: 参数值 + in: query + name: value + required: true + type: string + produces: + - application/json + responses: + "200": + description: 查询成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/system.SysParams' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 用id查询参数 + tags: + - SysParams + /sysParams/getSysParam: + get: + consumes: + - application/json + parameters: + - description: key + in: query + name: key + required: true + type: string + produces: + - application/json + responses: + "200": + description: 获取成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/system.SysParams' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 根据key获取参数value + tags: + - SysParams + /sysParams/getSysParamsList: + get: + consumes: + - application/json + parameters: + - in: query + name: endCreatedAt + type: string + - in: query + name: key + type: string + - description: 关键字 + in: query + name: keyword + type: string + - in: query + name: name + type: string + - description: 页码 + in: query + name: page + type: integer + - description: 每页大小 + in: query + name: pageSize + type: integer + - in: query + name: startCreatedAt + type: string + produces: + - application/json + responses: + "200": + description: 获取成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + $ref: '#/definitions/response.PageResult' + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 分页获取参数列表 + tags: + - SysParams + /sysParams/updateSysParams: + put: + consumes: + - application/json + parameters: + - description: 更新参数 + in: body + name: data + required: true + schema: + $ref: '#/definitions/system.SysParams' + produces: + - application/json + responses: + "200": + description: 更新成功 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 更新参数 + tags: + - SysParams /system/getServerInfo: post: produces: @@ -4672,6 +5258,38 @@ paths: summary: 设置用户信息 tags: - SysUser + /user/SetSelfSetting: + put: + consumes: + - application/json + parameters: + - description: 用户配置数据 + in: body + name: data + required: true + schema: + additionalProperties: true + type: object + produces: + - application/json + responses: + "200": + description: 设置用户配置 + schema: + allOf: + - $ref: '#/definitions/response.Response' + - properties: + data: + additionalProperties: true + type: object + msg: + type: string + type: object + security: + - ApiKeyAuth: [] + summary: 设置用户配置 + tags: + - SysUser /user/admin_register: post: parameters: @@ -4786,7 +5404,7 @@ paths: name: data required: true schema: - $ref: '#/definitions/request.PageInfo' + $ref: '#/definitions/request.GetUserList' produces: - application/json responses: diff --git a/server/initialize/ensure_tables.go b/server/initialize/ensure_tables.go index daa79f3532..3ef33490fc 100644 --- a/server/initialize/ensure_tables.go +++ b/server/initialize/ensure_tables.go @@ -18,7 +18,7 @@ func init() { system.RegisterInit(initOrderEnsureTables, &ensureTables{}) } -func (ensureTables) InitializerName() string { +func (e *ensureTables) InitializerName() string { return "ensure_tables_created" } func (e *ensureTables) InitializeData(ctx context.Context) (next context.Context, err error) { diff --git a/server/initialize/gorm_mssql.go b/server/initialize/gorm_mssql.go index 0ec25a7f56..e1478ea418 100644 --- a/server/initialize/gorm_mssql.go +++ b/server/initialize/gorm_mssql.go @@ -1,3 +1,5 @@ +package initialize + /* * @Author: 逆光飞翔 191180776@qq.com * @Date: 2022-12-08 17:25:49 @@ -6,7 +8,6 @@ * @FilePath: \server\initialize\gorm_mssql.go * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE */ -package initialize import ( "github.com/flipped-aurora/gin-vue-admin/server/config" @@ -44,8 +45,8 @@ func GormMssqlByConfig(m config.Mssql) *gorm.DB { return nil } mssqlConfig := sqlserver.Config{ - DSN: m.Dsn(), // DSN data source name - DefaultStringSize: 191, // string 类型字段的默认长度 + DSN: m.Dsn(), // DSN data source name + DefaultStringSize: 191, // string 类型字段的默认长度 } if db, err := gorm.Open(sqlserver.New(mssqlConfig), internal.Gorm.Config(m.Prefix, m.Singular)); err != nil { panic(err) diff --git a/server/main.go b/server/main.go index 6f44448927..a01b4159d9 100644 --- a/server/main.go +++ b/server/main.go @@ -14,7 +14,7 @@ import ( //go:generate go mod download // @title Gin-Vue-Admin Swagger API接口文档 -// @version v2.7.7 +// @version v2.7.8-beta1 // @description 使用gin+vue进行极速开发的全栈开发基础平台 // @securityDefinitions.apikey ApiKeyAuth // @in header diff --git a/server/model/common/basetypes.go b/server/model/common/basetypes.go index 870d975c62..1a133d5ad2 100644 --- a/server/model/common/basetypes.go +++ b/server/model/common/basetypes.go @@ -34,3 +34,10 @@ func (m *JSONMap) Scan(value interface{}) error { } return nil } + +type TreeNode[T any] interface { + GetChildren() []T + SetChildren(children T) + GetID() int + GetParentID() int +} diff --git a/server/model/system/request/sys_auto_code.go b/server/model/system/request/sys_auto_code.go index ef70b8fcba..bea6b751c4 100644 --- a/server/model/system/request/sys_auto_code.go +++ b/server/model/system/request/sys_auto_code.go @@ -27,6 +27,8 @@ type AutoCode struct { AutoCreateMenuToSql bool `json:"autoCreateMenuToSql" example:"false"` // 是否自动创建menu AutoCreateBtnAuth bool `json:"autoCreateBtnAuth" example:"false"` // 是否自动创建按钮权限 OnlyTemplate bool `json:"onlyTemplate" example:"false"` // 是否只生成模板 + IsTree bool `json:"isTree" example:"false"` // 是否树形结构 + TreeJson string `json:"treeJson" example:"展示的树json字段"` // 展示的树json字段 IsAdd bool `json:"isAdd" example:"false"` // 是否新增 Fields []*AutoCodeField `json:"fields"` Module string `json:"-"` diff --git a/server/model/system/request/sys_casbin.go b/server/model/system/request/sys_casbin.go index ef8c823cbe..3ca421276a 100644 --- a/server/model/system/request/sys_casbin.go +++ b/server/model/system/request/sys_casbin.go @@ -1,12 +1,12 @@ package request -// Casbin info structure +// CasbinInfo Casbin info structure type CasbinInfo struct { Path string `json:"path"` // 路径 Method string `json:"method"` // 方法 } -// Casbin structure for input parameters +// CasbinInReceive Casbin structure for input parameters type CasbinInReceive struct { AuthorityId uint `json:"authorityId"` // 权限id CasbinInfos []CasbinInfo `json:"casbinInfos"` diff --git a/server/model/system/request/sys_init.go b/server/model/system/request/sys_init.go index 6882895d24..d04b1d249b 100644 --- a/server/model/system/request/sys_init.go +++ b/server/model/system/request/sys_init.go @@ -15,6 +15,7 @@ type InitDB struct { Password string `json:"password"` // 数据库密码 DBName string `json:"dbName" binding:"required"` // 数据库名 DBPath string `json:"dbPath"` // sqlite数据库文件路径 + Template string `json:"template"` // postgresql指定template } // MysqlEmptyDsn msyql 空数据库 建库链接 diff --git a/server/model/system/request/sys_menu.go b/server/model/system/request/sys_menu.go index 2f5c7c46e1..275f037bc9 100644 --- a/server/model/system/request/sys_menu.go +++ b/server/model/system/request/sys_menu.go @@ -5,7 +5,7 @@ import ( "github.com/flipped-aurora/gin-vue-admin/server/model/system" ) -// Add menu authority info structure +// AddMenuAuthorityInfo Add menu authority info structure type AddMenuAuthorityInfo struct { Menus []system.SysBaseMenu `json:"menus"` AuthorityId uint `json:"authorityId"` // 角色ID diff --git a/server/model/system/request/sys_user.go b/server/model/system/request/sys_user.go index 2e698d440c..45e478769d 100644 --- a/server/model/system/request/sys_user.go +++ b/server/model/system/request/sys_user.go @@ -18,7 +18,7 @@ type Register struct { Email string `json:"email" example:"电子邮箱"` } -// User login structure +// Login User login structure type Login struct { Username string `json:"username"` // 用户名 Password string `json:"password"` // 密码 @@ -26,19 +26,19 @@ type Login struct { CaptchaId string `json:"captchaId"` // 验证码ID } -// Modify password structure +// ChangePasswordReq Modify password structure type ChangePasswordReq struct { ID uint `json:"-"` // 从 JWT 中提取 user id,避免越权 Password string `json:"password"` // 密码 NewPassword string `json:"newPassword"` // 新密码 } -// Modify user's auth structure +// SetUserAuth Modify user's auth structure type SetUserAuth struct { AuthorityId uint `json:"authorityId"` // 角色ID } -// Modify user's auth structure +// SetUserAuthorities Modify user's auth structure type SetUserAuthorities struct { ID uint AuthorityIds []uint `json:"authorityIds"` // 角色ID diff --git a/server/resource/package/server/api/api.go.tpl b/server/resource/package/server/api/api.go.tpl index 9e5bed5dab..5aae0995ff 100644 --- a/server/resource/package/server/api/api.go.tpl +++ b/server/resource/package/server/api/api.go.tpl @@ -5,7 +5,9 @@ import ( "{{.Module}}/global" "{{.Module}}/model/common/response" "{{.Module}}/model/{{.Package}}" + {{- if not .IsTree}} {{.Package}}Req "{{.Module}}/model/{{.Package}}/request" + {{- end }} "github.com/gin-gonic/gin" "go.uber.org/zap" {{- if .AutoCreateResource}} @@ -142,6 +144,25 @@ func ({{.Abbreviation}}Api *{{.StructName}}Api) Find{{.StructName}}(c *gin.Conte response.OkWithData(re{{.Abbreviation}}, c) } +{{- if .IsTree }} +// Get{{.StructName}}List 分页获取{{.Description}}列表,Tree模式下不接受参数 +// @Tags {{.StructName}} +// @Summary 分页获取{{.Description}}列表 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功" +// @Router /{{.Abbreviation}}/get{{.StructName}}List [get] +func ({{.Abbreviation}}Api *{{.StructName}}Api) Get{{.StructName}}List(c *gin.Context) { + list, err := {{.Abbreviation}}Service.Get{{.StructName}}InfoList() + if err != nil { + global.GVA_LOG.Error("获取失败!", zap.Error(err)) + response.FailWithMessage("获取失败:" + err.Error(), c) + return + } + response.OkWithDetailed(list, "获取成功", c) +} +{{- else }} // Get{{.StructName}}List 分页获取{{.Description}}列表 // @Tags {{.StructName}} // @Summary 分页获取{{.Description}}列表 @@ -171,6 +192,7 @@ func ({{.Abbreviation}}Api *{{.StructName}}Api) Get{{.StructName}}List(c *gin.Co PageSize: pageInfo.PageSize, }, "获取成功", c) } +{{- end }} {{- if .HasDataSource }} // Get{{.StructName}}DataSource 获取{{.StructName}}的数据源 @@ -199,7 +221,6 @@ func ({{.Abbreviation}}Api *{{.StructName}}Api) Get{{.StructName}}DataSource(c * // @Summary 不需要鉴权的{{.Description}}接口 // @accept application/json // @Produce application/json -// @Param data query {{.Package}}Req.{{.StructName}}Search true "分页获取{{.Description}}列表" // @Success 200 {object} response.Response{data=object,msg=string} "获取成功" // @Router /{{.Abbreviation}}/get{{.StructName}}Public [get] func ({{.Abbreviation}}Api *{{.StructName}}Api) Get{{.StructName}}Public(c *gin.Context) { diff --git a/server/resource/package/server/model/model.go.tpl b/server/resource/package/server/model/model.go.tpl index f1f979c59a..82f33dab8c 100644 --- a/server/resource/package/server/model/model.go.tpl +++ b/server/resource/package/server/model/model.go.tpl @@ -72,6 +72,10 @@ type {{.StructName}} struct { UpdatedBy uint `gorm:"column:updated_by;comment:更新者"` DeletedBy uint `gorm:"column:deleted_by;comment:删除者"` {{- end }} + {{- if .IsTree }} + Children []*{{.StructName}} `json:"children" gorm:"-"` //子节点 + ParentID int `json:"parentID" gorm:"column:parent_id;comment:父节点"` + {{- end }} {{- end }} } @@ -82,5 +86,26 @@ func ({{.StructName}}) TableName() string { } {{ end }} +{{if .IsTree }} +// GetChildren 实现TreeNode接口 +func (s *{{.StructName}}) GetChildren() []*{{.StructName}} { + return s.Children +} + +// SetChildren 实现TreeNode接口 +func (s *{{.StructName}}) SetChildren(children *{{.StructName}}) { + s.Children = append(s.Children, children) +} + +// GetID 实现TreeNode接口 +func (s *{{.StructName}}) GetID() int { + return int({{if not .GvaModel}}*{{- end }}s.{{.PrimaryField.FieldName}}) +} -{{ end }} \ No newline at end of file +// GetParentID 实现TreeNode接口 +func (s *{{.StructName}}) GetParentID() int { + return s.ParentID +} +{{ end }} + +{{ end }} diff --git a/server/resource/package/server/service/service.go.tpl b/server/resource/package/server/service/service.go.tpl index ff42b4ee31..0d6e6a83c9 100644 --- a/server/resource/package/server/service/service.go.tpl +++ b/server/resource/package/server/service/service.go.tpl @@ -60,7 +60,12 @@ import ( {{- if not .OnlyTemplate }} "{{.Module}}/global" "{{.Module}}/model/{{.Package}}" + {{- if not .IsTree}} {{.Package}}Req "{{.Module}}/model/{{.Package}}/request" + {{- else }} + "{{.Module}}/utils" + "errors" + {{- end }} {{- if .AutoCreateResource }} "gorm.io/gorm" {{- end}} @@ -80,6 +85,17 @@ func ({{.Abbreviation}}Service *{{.StructName}}Service) Create{{.StructName}}({{ // Delete{{.StructName}} 删除{{.Description}}记录 // Author [yourname](https://github.com/yourname) func ({{.Abbreviation}}Service *{{.StructName}}Service)Delete{{.StructName}}({{.PrimaryField.FieldJson}} string{{- if .AutoCreateResource -}},userID uint{{- end -}}) (err error) { + {{- if .IsTree }} + var count int64 + err = {{$db}}.Find(&{{.Package}}.{{.StructName}}{},"parent_id = ?",{{.PrimaryField.FieldJson}}).Count(&count).Error + if count > 0 { + return errors.New("此节点存在子节点不允许删除") + } + if err != nil { + return err + } + {{- end }} + {{- if .AutoCreateResource }} err = {{$db}}.Transaction(func(tx *gorm.DB) error { if err := tx.Model(&{{.Package}}.{{.StructName}}{}).Where("{{.PrimaryField.ColumnName}} = ?", {{.PrimaryField.FieldJson}}).Update("deleted_by", userID).Error; err != nil { @@ -129,6 +145,20 @@ func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}({{.Pri return } + +{{- if .IsTree }} +// Get{{.StructName}}InfoList 分页获取{{.Description}}记录,Tree模式下不添加分页和搜索 +// Author [yourname](https://github.com/yourname) +func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}InfoList() (list []*{{.Package}}.{{.StructName}},err error) { + // 创建db + db := {{$db}}.Model(&{{.Package}}.{{.StructName}}{}) + var {{.Abbreviation}}s []*{{.Package}}.{{.StructName}} + + err = db.Find(&{{.Abbreviation}}s).Error + + return utils.BuildTree({{.Abbreviation}}s), err +} +{{- else }} // Get{{.StructName}}InfoList 分页获取{{.Description}}记录 // Author [yourname](https://github.com/yourname) func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}InfoList(info {{.Package}}Req.{{.StructName}}Search) (list []{{.Package}}.{{.StructName}}, total int64, err error) { @@ -193,6 +223,8 @@ func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}InfoLis return {{.Abbreviation}}s, total, err } +{{- end }} + {{- if .HasDataSource }} func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}DataSource() (res map[string][]map[string]any, err error) { res = make(map[string][]map[string]any) @@ -215,4 +247,4 @@ func ({{.Abbreviation}}Service *{{.StructName}}Service)Get{{.StructName}}Public( // 此方法为获取数据源定义的数据 // 请自行实现 } -{{- end }} \ No newline at end of file +{{- end }} diff --git a/server/resource/package/web/view/form.vue.tpl b/server/resource/package/web/view/form.vue.tpl index 8d8827fc67..e45b37558b 100644 --- a/server/resource/package/web/view/form.vue.tpl +++ b/server/resource/package/web/view/form.vue.tpl @@ -13,7 +13,7 @@ {{- end }} {{- if eq .FieldType "string" }} {{- if .DictType}} - + {{- else }} @@ -95,7 +95,7 @@ const {{ $element }}Options = ref([]) {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} -{{.FieldJson}}: {{- if or .DictType .DataSource}} undefined{{ else }} 0{{- end }}, +{{.FieldJson}}: {{- if or .DataSource}} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), @@ -165,6 +165,20 @@ getDataSourceFunc()
+ {{- if .IsTree }} + + + + {{- end }} {{- range .Fields}} {{- if .Form }} @@ -178,7 +192,7 @@ getDataSourceFunc() {{- end }} {{- if eq .FieldType "string" }} {{- if .DictType}} - + {{- else }} @@ -239,6 +253,9 @@ import { {{- if .HasDataSource }} get{{.StructName}}DataSource, {{- end }} + {{- if .IsTree }} + get{{.StructName}}List, + {{- end }} create{{.StructName}}, update{{.StructName}}, find{{.StructName}} @@ -277,6 +294,32 @@ import ArrayCtrl from '@/components/arrayCtrl/arrayCtrl.vue' const route = useRoute() const router = useRouter() +{{- if .IsTree }} +const tableData = ref([]) + +const defaultProps = { + children: "children", + label: "{{ .TreeJson }}", + value: "{{ .PrimaryField.FieldJson }}" +} + +const rootNode = { + {{ .PrimaryField.FieldJson }}: 0, + {{ .TreeJson }}: '根节点', + children: [] +} + +const getTableData = async() => { + const table = await get{{.StructName}}List() + if (table.code === 0) { + tableData.value = table.data || [] + } +} + +getTableData() + +{{- end }} + // 提交按钮loading const btnLoading = ref(false) @@ -285,6 +328,9 @@ const type = ref('') const {{ $element }}Options = ref([]) {{- end }} const formData = ref({ + {{- if .IsTree }} + parentID: undefined, + {{- end }} {{- range .Fields}} {{- if .Form }} {{- if eq .FieldType "bool" }} @@ -297,7 +343,7 @@ const formData = ref({ {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} - {{.FieldJson}}: {{- if or .DictType .DataSource }} undefined{{ else }} 0{{- end }}, + {{.FieldJson}}: {{- if or .DataSource }} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), diff --git a/server/resource/package/web/view/table.vue.tpl b/server/resource/package/web/view/table.vue.tpl index 7b4ca4199a..2ad31d83eb 100644 --- a/server/resource/package/web/view/table.vue.tpl +++ b/server/resource/package/web/view/table.vue.tpl @@ -19,7 +19,7 @@ {{- else if .DictType}} - + @@ -37,13 +37,7 @@ — {{- else}} - {{- if .DictType}} - - - - {{- else}} - {{- end }} {{- end}} {{- else if eq .FieldType "time.Time"}} {{if eq .FieldSearchType "BETWEEN" "NOT BETWEEN"}} @@ -86,7 +80,11 @@ {{- else if .DictType}} {{- else if eq .FieldType "bool" }} @@ -183,8 +181,14 @@ // 此字段为json结构,可以前端自行控制展示和数据绑定模式 需绑定json的key为 formData.{{.FieldJson}} 后端会按照json的类型进行存取 {{"{{"}} formData.{{.FieldJson}} {{"}}"}} {{- end }} - {{- if eq .FieldType "array" }} + {{- if eq .FieldType "array" }} + {{- if .DictType}} + + + + {{- else }} + {{- end }} {{- end }} {{- if eq .FieldType "int" }} @@ -291,7 +295,7 @@ const {{ $element }}Options = ref([]) {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} -{{.FieldJson}}: {{- if or .DictType .DataSource}} undefined{{ else }} 0{{- end }}, +{{.FieldJson}}: {{- if .DataSource}} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), @@ -363,6 +367,7 @@ getDataSourceFunc() {{- if not .OnlyTemplate}} + {{- else if .DictType}} + {{- else if and (ne .FieldType "picture" ) (ne .FieldType "pictures" ) (ne .FieldType "file" ) (ne .FieldType "array" ) }} {{"{{"}} detailFrom.{{.FieldJson}} {{"}}"}} {{- else }} @@ -821,6 +865,7 @@ import { ref, reactive } from 'vue' // 引入按钮权限标识 import { useBtnAuth } from '@/utils/btnAuth' {{- end }} +import { useAppStore } from "@/pinia" {{if .HasExcel -}} // 导出组件 @@ -843,6 +888,7 @@ defineOptions({ // 提交按钮loading const btnLoading = ref(false) +const appStore = useAppStore() // 控制更多查询条件显示/隐藏状态 const showAllQuery = ref(false) @@ -852,6 +898,9 @@ const showAllQuery = ref(false) const {{ $element }}Options = ref([]) {{- end }} const formData = ref({ + {{- if .IsTree }} + parentID:undefined, + {{- end }} {{- range .Fields}} {{- if .Form}} {{- if eq .FieldType "bool" }} @@ -864,7 +913,7 @@ const formData = ref({ {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} - {{.FieldJson}}: {{- if or .DictType .DataSource}} undefined{{ else }} 0{{- end }}, + {{.FieldJson}}: {{- if .DataSource}} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), @@ -999,6 +1048,7 @@ const sortChange = ({ prop, order }) => { } {{- end}} +{{- if not .IsTree }} // 重置 const onReset = () => { searchInfo.value = {} @@ -1040,6 +1090,28 @@ const getTableData = async() => { pageSize.value = table.data.pageSize } } +{{- else }} +// 树选择器配置 +const defaultProps = { + children: "children", + label: "{{ .TreeJson }}", + value: "{{ .PrimaryField.FieldJson }}" +} + +const rootNode = { + {{ .PrimaryField.FieldJson }}: 0, + {{ .TreeJson }}: '根节点', + children: [] +} + +// 查询 +const getTableData = async() => { + const table = await get{{.StructName}}List() + if (table.code === 0) { + tableData.value = table.data || [] + } +} +{{- end }} getTableData() @@ -1140,8 +1212,11 @@ const delete{{.StructName}}Func = async (row) => { const dialogFormVisible = ref(false) // 打开弹窗 -const openDialog = () => { +const openDialog = ({{- if .IsTree -}}row{{- end -}}) => { type.value = 'create' + {{- if .IsTree }} + formData.value.parentID = row ? row.{{.PrimaryField.FieldJson}} : undefined + {{- end }} dialogFormVisible.value = true } @@ -1161,7 +1236,7 @@ const closeDialog = () => { {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} - {{.FieldJson}}: {{- if or .DictType .DataSource }} undefined{{ else }} 0{{- end }}, + {{.FieldJson}}: {{- if .DataSource }} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), diff --git a/server/resource/plugin/server/api/api.go.template b/server/resource/plugin/server/api/api.go.template index edf4651801..bd6a5f27a6 100644 --- a/server/resource/plugin/server/api/api.go.template +++ b/server/resource/plugin/server/api/api.go.template @@ -5,7 +5,9 @@ import ( "{{.Module}}/global" "{{.Module}}/model/common/response" "{{.Module}}/plugin/{{.Package}}/model" + {{- if not .IsTree}} "{{.Module}}/plugin/{{.Package}}/model/request" + {{- end }} "github.com/gin-gonic/gin" "go.uber.org/zap" {{- if .AutoCreateResource}} @@ -142,6 +144,25 @@ func (a *{{.Abbreviation}}) Find{{.StructName}}(c *gin.Context) { response.OkWithData(re{{.Abbreviation}}, c) } +{{- if .IsTree }} +// Get{{.StructName}}List 分页获取{{.Description}}列表 +// @Tags {{.StructName}} +// @Summary 分页获取{{.Description}}列表 +// @Security ApiKeyAuth +// @accept application/json +// @Produce application/json +// @Success 200 {object} response.Response{data=response.PageResult,msg=string} "获取成功" +// @Router /{{.Abbreviation}}/get{{.StructName}}List [get] +func (a *{{.Abbreviation}}) Get{{.StructName}}List(c *gin.Context) { + list, err := service{{ .StructName }}.Get{{.StructName}}InfoList() + if err != nil { + global.GVA_LOG.Error("获取失败!", zap.Error(err)) + response.FailWithMessage("获取失败:" + err.Error(), c) + return + } + response.OkWithDetailed(list, "获取成功", c) +} +{{- else }} // Get{{.StructName}}List 分页获取{{.Description}}列表 // @Tags {{.StructName}} // @Summary 分页获取{{.Description}}列表 @@ -171,6 +192,7 @@ func (a *{{.Abbreviation}}) Get{{.StructName}}List(c *gin.Context) { PageSize: pageInfo.PageSize, }, "获取成功", c) } +{{- end }} {{- if .HasDataSource }} // Get{{.StructName}}DataSource 获取{{.StructName}}的数据源 @@ -197,7 +219,6 @@ func (a *{{.Abbreviation}}) Get{{.StructName}}DataSource(c *gin.Context) { // @Summary 不需要鉴权的{{.Description}}接口 // @accept application/json // @Produce application/json -// @Param data query request.{{.StructName}}Search true "分页获取{{.Description}}列表" // @Success 200 {object} response.Response{data=object,msg=string} "获取成功" // @Router /{{.Abbreviation}}/get{{.StructName}}Public [get] func (a *{{.Abbreviation}}) Get{{.StructName}}Public(c *gin.Context) { diff --git a/server/resource/plugin/server/model/model.go.template b/server/resource/plugin/server/model/model.go.template index 0f9528db3c..2f1d35dd13 100644 --- a/server/resource/plugin/server/model/model.go.template +++ b/server/resource/plugin/server/model/model.go.template @@ -71,6 +71,10 @@ type {{.StructName}} struct { UpdatedBy uint `gorm:"column:updated_by;comment:更新者"` DeletedBy uint `gorm:"column:deleted_by;comment:删除者"` {{- end }} + {{- if .IsTree }} + Children []*{{.StructName}} `json:"children" gorm:"-"` //子节点 + ParentID int `json:"parentID" gorm:"column:parent_id;comment:父节点"` + {{- end }} {{- end }} } @@ -80,4 +84,29 @@ func ({{.StructName}}) TableName() string { return "{{.TableName}}" } {{ end }} -{{ end }} \ No newline at end of file + + +{{if .IsTree }} +// GetChildren 实现TreeNode接口 +func (s *{{.StructName}}) GetChildren() []*{{.StructName}} { + return s.Children +} + +// SetChildren 实现TreeNode接口 +func (s *{{.StructName}}) SetChildren(children *{{.StructName}}) { + s.Children = append(s.Children, children) +} + +// GetID 实现TreeNode接口 +func (s *{{.StructName}}) GetID() int { + return int({{if not .GvaModel}}*{{- end }}s.{{.PrimaryField.FieldName}}) +} + +// GetParentID 实现TreeNode接口 +func (s *{{.StructName}}) GetParentID() int { + return s.ParentID +} +{{ end }} + + +{{ end }} diff --git a/server/resource/plugin/server/service/service.go.template b/server/resource/plugin/server/service/service.go.template index 4b1c814ea2..b0da0fa0b8 100644 --- a/server/resource/plugin/server/service/service.go.template +++ b/server/resource/plugin/server/service/service.go.template @@ -60,10 +60,17 @@ import ( {{- if not .OnlyTemplate }} "{{.Module}}/global" "{{.Module}}/plugin/{{.Package}}/model" + {{- if not .IsTree }} "{{.Module}}/plugin/{{.Package}}/model/request" + {{- else }} + "errors" + {{- end }} {{- if .AutoCreateResource }} "gorm.io/gorm" {{- end}} +{{- if .IsTree }} + "{{.Module}}/utils" +{{- end }} {{- end }} ) @@ -88,6 +95,18 @@ func (s *{{.Abbreviation}}) Create{{.StructName}}({{.Abbreviation}} *model.{{.St // Delete{{.StructName}} 删除{{.Description}}记录 // Author [yourname](https://github.com/yourname) func (s *{{.Abbreviation}}) Delete{{.StructName}}({{.PrimaryField.FieldJson}} string{{- if .AutoCreateResource -}},userID uint{{- end -}}) (err error) { + + {{- if .IsTree }} + var count int64 + err = {{$db}}.Find(&model.{{.StructName}}{},"parent_id = ?",{{.PrimaryField.FieldJson}}).Count(&count).Error + if count > 0 { + return errors.New("此节点存在子节点不允许删除") + } + if err != nil { + return err + } + {{- end }} + {{- if .AutoCreateResource }} err = {{$db}}.Transaction(func(tx *gorm.DB) error { if err := tx.Model(&model.{{.StructName}}{}).Where("{{.PrimaryField.ColumnName}} = ?", {{.PrimaryField.FieldJson}}).Update("deleted_by", userID).Error; err != nil { @@ -137,6 +156,20 @@ func (s *{{.Abbreviation}}) Get{{.StructName}}({{.PrimaryField.FieldJson}} strin return } + +{{- if .IsTree }} +// Get{{.StructName}}InfoList 分页获取{{.Description}}记录,Tree模式下不添加分页和搜索 +// Author [yourname](https://github.com/yourname) +func (s *{{.Abbreviation}}) Get{{.StructName}}InfoList() (list []*model.{{.StructName}},err error) { + // 创建db + db := {{$db}}.Model(&model.{{.StructName}}{}) + var {{.Abbreviation}}s []*model.{{.StructName}} + + err = db.Find(&{{.Abbreviation}}s).Error + + return utils.BuildTree({{.Abbreviation}}s), err +} +{{- else }} // Get{{.StructName}}InfoList 分页获取{{.Description}}记录 // Author [yourname](https://github.com/yourname) func (s *{{.Abbreviation}}) Get{{.StructName}}InfoList(info request.{{.StructName}}Search) (list []model.{{.StructName}}, total int64, err error) { @@ -199,7 +232,7 @@ func (s *{{.Abbreviation}}) Get{{.StructName}}InfoList(info request.{{.StructNam err = db.Find(&{{.Abbreviation}}s).Error return {{.Abbreviation}}s, total, err } - +{{- end }} {{- if .HasDataSource }} func (s *{{.Abbreviation}})Get{{.StructName}}DataSource() (res map[string][]map[string]any, err error) { res = make(map[string][]map[string]any) @@ -222,4 +255,4 @@ func (s *{{.Abbreviation}})Get{{.StructName}}DataSource() (res map[string][]map[ func (s *{{.Abbreviation}})Get{{.StructName}}Public() { } -{{- end }} \ No newline at end of file +{{- end }} diff --git a/server/resource/plugin/web/form/form.vue.template b/server/resource/plugin/web/form/form.vue.template index 2c221d912b..e45b37558b 100644 --- a/server/resource/plugin/web/form/form.vue.template +++ b/server/resource/plugin/web/form/form.vue.template @@ -13,7 +13,7 @@ {{- end }} {{- if eq .FieldType "string" }} {{- if .DictType}} - + {{- else }} @@ -95,7 +95,7 @@ const {{ $element }}Options = ref([]) {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} -{{.FieldJson}}: {{- if or .DictType .DataSource}} undefined{{ else }} 0{{- end }}, +{{.FieldJson}}: {{- if or .DataSource}} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), @@ -148,6 +148,7 @@ const {{ $element }}Options = ref([]) {{- if .HasDataSource }} // 请引用 get{{.StructName}}DataSource, + // 获取数据源 const dataSource = ref([]) const getDataSourceFunc = async()=>{ @@ -159,13 +160,27 @@ const getDataSourceFunc = async()=>{ getDataSourceFunc() {{- end }} {{- else }} -{{- if not .OnlyTemplate}} +{{- if not .OnlyTemplate }} @@ -805,7 +847,6 @@ import SelectImage from '@/components/selectImage/selectImage.vue' import RichEdit from '@/components/richtext/rich-edit.vue' {{- end }} - {{- if .HasFile }} // 文件选择组件 import SelectFile from '@/components/selectFile/selectFile.vue' @@ -844,6 +885,9 @@ defineOptions({ const btnAuth = useBtnAuth() {{- end }} +// 提交按钮loading +const btnLoading = ref(false) + // 控制更多查询条件显示/隐藏状态 const showAllQuery = ref(false) @@ -852,45 +896,48 @@ const showAllQuery = ref(false) const {{ $element }}Options = ref([]) {{- end }} const formData = ref({ - {{- range .Fields}} - {{- if .Form}} - {{- if eq .FieldType "bool" }} - {{.FieldJson}}: false, - {{- end }} - {{- if eq .FieldType "string" }} - {{.FieldJson}}: '', - {{- end }} - {{- if eq .FieldType "richtext" }} - {{.FieldJson}}: '', - {{- end }} - {{- if eq .FieldType "int" }} - {{.FieldJson}}: {{- if or .DictType .DataSource}} undefined{{ else }} 0{{- end }}, - {{- end }} - {{- if eq .FieldType "time.Time" }} - {{.FieldJson}}: new Date(), - {{- end }} - {{- if eq .FieldType "float64" }} - {{.FieldJson}}: 0, - {{- end }} - {{- if eq .FieldType "picture" }} - {{.FieldJson}}: "", - {{- end }} - {{- if eq .FieldType "video" }} - {{.FieldJson}}: "", - {{- end }} - {{- if eq .FieldType "pictures" }} - {{.FieldJson}}: [], - {{- end }} - {{- if eq .FieldType "file" }} - {{.FieldJson}}: [], - {{- end }} - {{- if eq .FieldType "json" }} - {{.FieldJson}}: {}, - {{- end }} - {{- if eq .FieldType "array" }} - {{.FieldJson}}: [], - {{- end }} + {{- if .IsTree }} + parentID:undefined, {{- end }} + {{- range .Fields}} + {{- if .Form}} + {{- if eq .FieldType "bool" }} + {{.FieldJson}}: false, + {{- end }} + {{- if eq .FieldType "string" }} + {{.FieldJson}}: '', + {{- end }} + {{- if eq .FieldType "richtext" }} + {{.FieldJson}}: '', + {{- end }} + {{- if eq .FieldType "int" }} + {{.FieldJson}}: {{- if .DataSource}} undefined{{ else }} 0{{- end }}, + {{- end }} + {{- if eq .FieldType "time.Time" }} + {{.FieldJson}}: new Date(), + {{- end }} + {{- if eq .FieldType "float64" }} + {{.FieldJson}}: 0, + {{- end }} + {{- if eq .FieldType "picture" }} + {{.FieldJson}}: "", + {{- end }} + {{- if eq .FieldType "video" }} + {{.FieldJson}}: "", + {{- end }} + {{- if eq .FieldType "pictures" }} + {{.FieldJson}}: [], + {{- end }} + {{- if eq .FieldType "file" }} + {{.FieldJson}}: [], + {{- end }} + {{- if eq .FieldType "json" }} + {{.FieldJson}}: {}, + {{- end }} + {{- if eq .FieldType "array" }} + {{.FieldJson}}: [], + {{- end }} + {{- end }} {{- end }} }) @@ -910,7 +957,7 @@ const formData = ref({ // 验证规则 const rule = reactive({ {{- range .Fields }} - {{- if .Form }} + {{- if .Form }} {{- if eq .Require true }} {{.FieldJson }} : [{ required: true, @@ -926,7 +973,7 @@ const rule = reactive({ {{- end }} ], {{- end }} - {{- end }} + {{- end }} {{- end }} }) @@ -978,13 +1025,13 @@ const searchInfo = ref({}) const sortChange = ({ prop, order }) => { const sortMap = { {{- range .Fields}} - {{- if .Table}} - {{- if and .Sort}} - {{- if not (eq .ColumnName "")}} - {{.FieldJson}}: '{{.ColumnName}}', - {{- end}} + {{- if .Table}} + {{- if and .Sort}} + {{- if not (eq .ColumnName "")}} + {{.FieldJson}}: '{{.ColumnName}}', {{- end}} {{- end}} + {{- end}} {{- end}} } @@ -999,6 +1046,7 @@ const sortChange = ({ prop, order }) => { } {{- end}} +{{- if not .IsTree }} // 重置 const onReset = () => { searchInfo.value = {} @@ -1040,6 +1088,28 @@ const getTableData = async() => { pageSize.value = table.data.pageSize } } +{{- else }} +// 树选择器配置 +const defaultProps = { + children: "children", + label: "{{ .TreeJson }}", + value: "{{ .PrimaryField.FieldJson }}" +} + +const rootNode = { + {{ .PrimaryField.FieldJson }}: 0, + {{ .TreeJson }}: '根节点', + children: [] +} + +// 查询 +const getTableData = async() => { + const table = await get{{.StructName}}List() + if (table.code === 0) { + tableData.value = table.data || [] + } +} +{{- end }} getTableData() @@ -1140,8 +1210,11 @@ const delete{{.StructName}}Func = async (row) => { const dialogFormVisible = ref(false) // 打开弹窗 -const openDialog = () => { +const openDialog = ({{- if .IsTree -}}row{{- end -}}) => { type.value = 'create' + {{- if .IsTree }} + formData.value.parentID = row ? row.{{.PrimaryField.FieldJson}} : undefined + {{- end }} dialogFormVisible.value = true } @@ -1161,7 +1234,7 @@ const closeDialog = () => { {{.FieldJson}}: '', {{- end }} {{- if eq .FieldType "int" }} - {{.FieldJson}}: {{- if or .DictType .DataSource }} undefined{{ else }} 0{{- end }}, + {{.FieldJson}}: {{- if .DataSource }} undefined{{ else }} 0{{- end }}, {{- end }} {{- if eq .FieldType "time.Time" }} {{.FieldJson}}: new Date(), @@ -1193,8 +1266,9 @@ const closeDialog = () => { } // 弹窗确定 const enterDialog = async () => { + btnLoading.value = true elFormRef.value?.validate( async (valid) => { - if (!valid) return + if (!valid) return btnLoading.value = false let res switch (type.value) { case 'create': @@ -1207,6 +1281,7 @@ const enterDialog = async () => { res = await create{{.StructName}}(formData.value) break } + btnLoading.value = false if (res.code === 0) { ElMessage({ type: 'success', @@ -1223,7 +1298,6 @@ const downloadFile = (url) => { } {{end}} - const detailFrom = ref({}) // 查看详情控制标记 @@ -1284,5 +1358,6 @@ defineOptions({ -{{- end}} -{{- end}} +{{- end }} + +{{- end }} diff --git a/server/service/example/exa_breakpoint_continue.go b/server/service/example/exa_breakpoint_continue.go index d0363bb5de..d2a85a3382 100644 --- a/server/service/example/exa_breakpoint_continue.go +++ b/server/service/example/exa_breakpoint_continue.go @@ -58,7 +58,7 @@ func (e *FileUploadAndDownloadService) CreateFileChunk(id uint, fileChunkPath st func (e *FileUploadAndDownloadService) DeleteFileChunk(fileMd5 string, filePath string) error { var chunks []example.ExaFileChunk var file example.ExaFile - err := global.GVA_DB.Where("file_md5 = ? ", fileMd5).First(&file). + err := global.GVA_DB.Where("file_md5 = ?", fileMd5).First(&file). Updates(map[string]interface{}{ "IsFinish": true, "file_path": filePath, diff --git a/server/service/system/sys_casbin.go b/server/service/system/sys_casbin.go index 32edc579e5..3a315efbaa 100644 --- a/server/service/system/sys_casbin.go +++ b/server/service/system/sys_casbin.go @@ -169,8 +169,8 @@ func (casbinService *CasbinService) AddPolicies(db *gorm.DB, rules [][]string) e return db.Create(&casbinRules).Error } -func (CasbinService *CasbinService) FreshCasbin() (err error) { - e := CasbinService.Casbin() +func (casbinService *CasbinService) FreshCasbin() (err error) { + e := casbinService.Casbin() err = e.LoadPolicy() return err } diff --git a/server/service/system/sys_initdb_pgsql.go b/server/service/system/sys_initdb_pgsql.go index f1a482f0cd..468fadd37c 100644 --- a/server/service/system/sys_initdb_pgsql.go +++ b/server/service/system/sys_initdb_pgsql.go @@ -54,7 +54,12 @@ func (h PgsqlInitHandler) EnsureDB(ctx context.Context, conf *request.InitDB) (n } // 如果没有数据库名, 则跳出初始化数据 dsn := conf.PgsqlEmptyDsn() - createSql := fmt.Sprintf("CREATE DATABASE %s;", c.Dbname) + var createSql string + if conf.Template != "" { + createSql = fmt.Sprintf("CREATE DATABASE %s WITH TEMPLATE %s;", c.Dbname, conf.Template) + } else { + createSql = fmt.Sprintf("CREATE DATABASE %s;", c.Dbname) + } if err = createDatabase(dsn, "pgx", createSql); err != nil { return nil, err } // 创建数据库 diff --git a/server/source/example/file_upload_download.go b/server/source/example/file_upload_download.go index f39dcf2e51..0f6f7a7fad 100644 --- a/server/source/example/file_upload_download.go +++ b/server/source/example/file_upload_download.go @@ -33,7 +33,7 @@ func (i *initExaFileMysql) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&example.ExaFileUploadAndDownload{}) } -func (i initExaFileMysql) InitializerName() string { +func (i *initExaFileMysql) InitializerName() string { return example.ExaFileUploadAndDownload{}.TableName() } diff --git a/server/source/system/api.go b/server/source/system/api.go index 3dc211d00c..e657f34f5c 100644 --- a/server/source/system/api.go +++ b/server/source/system/api.go @@ -17,7 +17,7 @@ func init() { system.RegisterInit(initOrderApi, &initApi{}) } -func (i initApi) InitializerName() string { +func (i *initApi) InitializerName() string { return sysModel.SysApi{}.TableName() } diff --git a/server/source/system/api_ignore.go b/server/source/system/api_ignore.go index 284a1cc0c2..c0fab56500 100644 --- a/server/source/system/api_ignore.go +++ b/server/source/system/api_ignore.go @@ -17,7 +17,7 @@ func init() { system.RegisterInit(initOrderApiIgnore, &initApiIgnore{}) } -func (i initApiIgnore) InitializerName() string { +func (i *initApiIgnore) InitializerName() string { return sysModel.SysIgnoreApi{}.TableName() } diff --git a/server/source/system/authorities_menus.go b/server/source/system/authorities_menus.go index 1c9058b888..e6799bc33e 100644 --- a/server/source/system/authorities_menus.go +++ b/server/source/system/authorities_menus.go @@ -26,7 +26,7 @@ func (i *initMenuAuthority) TableCreated(ctx context.Context) bool { return false // always replace } -func (i initMenuAuthority) InitializerName() string { +func (i *initMenuAuthority) InitializerName() string { return "sys_menu_authorities" } @@ -35,11 +35,12 @@ func (i *initMenuAuthority) InitializeData(ctx context.Context) (next context.Co if !ok { return ctx, system.ErrMissingDBContext } - authorities, ok := ctx.Value(initAuthority{}.InitializerName()).([]sysModel.SysAuthority) + initAuth := &initAuthority{} + authorities, ok := ctx.Value(initAuth.InitializerName()).([]sysModel.SysAuthority) if !ok { return ctx, errors.Wrap(system.ErrMissingDependentContext, "创建 [菜单-权限] 关联失败, 未找到权限表初始化数据") } - menus, ok := ctx.Value(initMenu{}.InitializerName()).([]sysModel.SysBaseMenu) + menus, ok := ctx.Value(new(initMenu).InitializerName()).([]sysModel.SysBaseMenu) if !ok { return next, errors.Wrap(errors.New(""), "创建 [菜单-权限] 关联失败, 未找到菜单表初始化数据") } diff --git a/server/source/system/authority.go b/server/source/system/authority.go index 0426f2a4fa..1157a19223 100644 --- a/server/source/system/authority.go +++ b/server/source/system/authority.go @@ -34,7 +34,7 @@ func (i *initAuthority) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&sysModel.SysAuthority{}) } -func (i initAuthority) InitializerName() string { +func (i *initAuthority) InitializerName() string { return sysModel.SysAuthority{}.TableName() } diff --git a/server/source/system/casbin.go b/server/source/system/casbin.go index 5a9cdbec1a..c4528336df 100644 --- a/server/source/system/casbin.go +++ b/server/source/system/casbin.go @@ -34,7 +34,7 @@ func (i *initCasbin) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&adapter.CasbinRule{}) } -func (i initCasbin) InitializerName() string { +func (i *initCasbin) InitializerName() string { var entity adapter.CasbinRule return entity.TableName() } diff --git a/server/source/system/dictionary.go b/server/source/system/dictionary.go index 001496327f..a0cf8e0cb8 100644 --- a/server/source/system/dictionary.go +++ b/server/source/system/dictionary.go @@ -33,7 +33,7 @@ func (i *initDict) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&sysModel.SysDictionary{}) } -func (i initDict) InitializerName() string { +func (i *initDict) InitializerName() string { return sysModel.SysDictionary{}.TableName() } diff --git a/server/source/system/dictionary_detail.go b/server/source/system/dictionary_detail.go index 3dea8b70ff..938cbc23ec 100644 --- a/server/source/system/dictionary_detail.go +++ b/server/source/system/dictionary_detail.go @@ -34,7 +34,7 @@ func (i *initDictDetail) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&sysModel.SysDictionaryDetail{}) } -func (i initDictDetail) InitializerName() string { +func (i *initDictDetail) InitializerName() string { return sysModel.SysDictionaryDetail{}.TableName() } @@ -43,7 +43,7 @@ func (i *initDictDetail) InitializeData(ctx context.Context) (context.Context, e if !ok { return ctx, system.ErrMissingDBContext } - dicts, ok := ctx.Value(initDict{}.InitializerName()).([]sysModel.SysDictionary) + dicts, ok := ctx.Value(new(initDict).InitializerName()).([]sysModel.SysDictionary) if !ok { return ctx, errors.Wrap(system.ErrMissingDependentContext, fmt.Sprintf("未找到 %s 表初始化数据", sysModel.SysDictionary{}.TableName())) diff --git a/server/source/system/excel_template.go b/server/source/system/excel_template.go index 00f3ed5f1a..20bf16dd4b 100644 --- a/server/source/system/excel_template.go +++ b/server/source/system/excel_template.go @@ -17,7 +17,7 @@ func init() { system.RegisterInit(initOrderExcelTemplate, &initExcelTemplate{}) } -func (i initExcelTemplate) InitializerName() string { +func (i *initExcelTemplate) InitializerName() string { return "sys_export_templates" } diff --git a/server/source/system/menu.go b/server/source/system/menu.go index 5b8ff0bdf7..30b177fde5 100644 --- a/server/source/system/menu.go +++ b/server/source/system/menu.go @@ -18,7 +18,7 @@ func init() { system.RegisterInit(initOrderMenu, &initMenu{}) } -func (i initMenu) InitializerName() string { +func (i *initMenu) InitializerName() string { return SysBaseMenu{}.TableName() } diff --git a/server/source/system/user.go b/server/source/system/user.go index b51c2fd44f..eb9ddfc473 100644 --- a/server/source/system/user.go +++ b/server/source/system/user.go @@ -35,7 +35,7 @@ func (i *initUser) TableCreated(ctx context.Context) bool { return db.Migrator().HasTable(&sysModel.SysUser{}) } -func (i initUser) InitializerName() string { +func (i *initUser) InitializerName() string { return sysModel.SysUser{}.TableName() } @@ -79,7 +79,7 @@ func (i *initUser) InitializeData(ctx context.Context) (next context.Context, er return ctx, errors.Wrap(err, sysModel.SysUser{}.TableName()+"表数据初始化失败!") } next = context.WithValue(ctx, i.InitializerName(), entities) - authorityEntities, ok := ctx.Value(initAuthority{}.InitializerName()).([]sysModel.SysAuthority) + authorityEntities, ok := ctx.Value(new(initAuthority).InitializerName()).([]sysModel.SysAuthority) if !ok { return next, errors.Wrap(system.ErrMissingDependentContext, "创建 [用户-权限] 关联失败, 未找到权限表初始化数据") } diff --git a/server/utils/ast/ast.go b/server/utils/ast/ast.go index b6f85d6d03..1cdfa4c1e5 100644 --- a/server/utils/ast/ast.go +++ b/server/utils/ast/ast.go @@ -158,7 +158,7 @@ func CreateApiStructAst(apis []system.SysApi) *[]ast.Expr { return &apiElts } -// 检查是否存在Import +// CheckImport 检查是否存在Import func CheckImport(file *ast.File, importPath string) bool { for _, imp := range file.Imports { // Remove quotes around the import path diff --git a/server/utils/ast/ast_gorm.go b/server/utils/ast/ast_gorm.go index d9c1beb3ef..4340721fe5 100644 --- a/server/utils/ast/ast_gorm.go +++ b/server/utils/ast/ast_gorm.go @@ -10,7 +10,7 @@ import ( "os" ) -// 自动为 gorm.go 注册一个自动迁移 +// AddRegisterTablesAst 自动为 gorm.go 注册一个自动迁移 func AddRegisterTablesAst(path, funcName, pk, varName, dbName, model string) { modelPk := fmt.Sprintf("github.com/flipped-aurora/gin-vue-admin/server/model/%s", pk) src, err := os.ReadFile(path) @@ -147,7 +147,7 @@ func addAutoMigrate(astBody *ast.BlockStmt, dbname string, pk string, model stri } } -// 为automigrate增加实参 +// NeedAppendModel 为automigrate增加实参 func NeedAppendModel(callNode ast.Node, pk string, model string) bool { flag := true ast.Inspect(callNode, func(node ast.Node) bool { diff --git a/server/utils/fmt_plus.go b/server/utils/fmt_plus.go index 8b77d4f265..6f34cb47c4 100644 --- a/server/utils/fmt_plus.go +++ b/server/utils/fmt_plus.go @@ -2,6 +2,7 @@ package utils import ( "fmt" + "github.com/flipped-aurora/gin-vue-admin/server/model/common" "math/rand" "reflect" "strings" @@ -67,7 +68,7 @@ func MaheHump(s string) string { return strings.Join(words, "") } -// 随机字符串 +// RandomString 随机字符串 func RandomString(n int) string { var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") b := make([]rune, n) @@ -80,3 +81,28 @@ func RandomString(n int) string { func RandomInt(min, max int) int { return min + rand.Intn(max-min) } + +// BuildTree 用于构建一个树形结构 +func BuildTree[T common.TreeNode[T]](nodes []T) []T { + nodeMap := make(map[int]T) + // 创建一个基本map + for i := range nodes { + nodeMap[nodes[i].GetID()] = nodes[i] + } + + for i := range nodes { + if nodes[i].GetParentID() != 0 { + parent := nodeMap[nodes[i].GetParentID()] + parent.SetChildren(nodes[i]) + } + } + + var rootNodes []T + + for i := range nodeMap { + if nodeMap[i].GetParentID() == 0 { + rootNodes = append(rootNodes, nodeMap[i]) + } + } + return rootNodes +} diff --git a/server/utils/jwt.go b/server/utils/jwt.go index c1298a870f..e8eb9721dc 100644 --- a/server/utils/jwt.go +++ b/server/utils/jwt.go @@ -43,7 +43,7 @@ func (j *JWT) CreateClaims(baseClaims request.BaseClaims) request.CustomClaims { return claims } -// 创建一个token +// CreateToken 创建一个token func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(j.SigningKey) @@ -57,7 +57,7 @@ func (j *JWT) CreateTokenByOldToken(oldToken string, claims request.CustomClaims return v.(string), err } -// 解析 token +// ParseToken 解析 token func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) { token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) { return j.SigningKey, nil diff --git a/server/utils/timer/timed_task.go b/server/utils/timer/timed_task.go index 9f761436f0..06865d25d0 100644 --- a/server/utils/timer/timed_task.go +++ b/server/utils/timer/timed_task.go @@ -72,7 +72,7 @@ func (t *timer) AddTaskByFunc(cronName string, spec string, fun func(), taskName return id, err } -// AddTaskByFuncWithSeconds 通过函数的方法使用WithSeconds添加任务 +// AddTaskByFuncWithSecond 通过函数的方法使用WithSeconds添加任务 func (t *timer) AddTaskByFuncWithSecond(cronName string, spec string, fun func(), taskName string, option ...cron.Option) (cron.EntryID, error) { t.Lock() defer t.Unlock() @@ -186,7 +186,7 @@ func (t *timer) StopCron(cronName string) { } } -// Remove 从cronName 删除指定任务 +// RemoveTask 从cronName 删除指定任务 func (t *timer) RemoveTask(cronName string, id int) { t.Lock() defer t.Unlock() diff --git a/web/package.json b/web/package.json index a12994ac05..02180cbb34 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "gin-vue-admin", - "version": "2.7.7", + "version": "2.7.8-beta1", "private": true, "scripts": { "serve": "node openDocument.js && vite --host --mode development", @@ -17,6 +17,7 @@ "@vue-office/excel": "^1.7.11", "@vue-office/pdf": "^2.0.2", "@vueuse/core": "^11.0.3", + "@vueuse/integrations": "^12.0.0", "@wangeditor/editor": "^5.1.23", "@wangeditor/editor-for-vue": "^5.1.12", "ace-builds": "^1.36.4", @@ -27,7 +28,6 @@ "echarts": "5.5.1", "element-plus": "^2.8.5", "highlight.js": "^11.10.0", - "js-cookie": "^3.0.5", "marked": "14.1.1", "marked-highlight": "^2.1.4", "mitt": "^3.0.1", @@ -39,6 +39,7 @@ "sortablejs": "^1.15.3", "spark-md5": "^3.0.2", "tailwindcss": "^3.4.10", + "universal-cookie": "^7", "vform3-builds": "^3.0.10", "vite-auto-import-svg": "^1.1.0", "vue": "^3.5.7", diff --git a/web/src/components/commandMenu/index.vue b/web/src/components/commandMenu/index.vue index 3d3b72395b..eb403d4a1e 100644 --- a/web/src/components/commandMenu/index.vue +++ b/web/src/components/commandMenu/index.vue @@ -90,11 +90,11 @@ const quickArr = [ { label: '亮色主题', - func: () => changeMode('light') + func: () => changeMode(false) }, { label: '暗色主题', - func: () => changeMode('dark') + func: () => changeMode(true) }, { label: '退出登录', @@ -135,12 +135,8 @@ dialogVisible.value = false } - const changeMode = (e) => { - if (e === null) { - appStore.toggleTheme(false) - return - } - appStore.toggleTheme(true) + const changeMode = (darkMode) => { + appStore.toggleTheme(darkMode) } const close = () => { diff --git a/web/src/components/selectImage/selectImage.vue b/web/src/components/selectImage/selectImage.vue index 2c08d88e5e..d8960254fb 100644 --- a/web/src/components/selectImage/selectImage.vue +++ b/web/src/components/selectImage/selectImage.vue @@ -23,7 +23,7 @@ />
- +
@@ -124,6 +124,9 @@ import { ElMessage, ElMessageBox } from 'element-plus' import { Picture as IconPicture } from '@element-plus/icons-vue' import selectComponent from '@/components/selectImage/selectComponent.vue' + import { useAppStore } from "@/pinia"; + + const appStore = useAppStore() const imageUrl = ref('') const imageCommon = ref('') diff --git a/web/src/core/config.js b/web/src/core/config.js index 847b68dc9b..9a03f26b00 100644 --- a/web/src/core/config.js +++ b/web/src/core/config.js @@ -17,7 +17,7 @@ export const viteLogo = (env) => { `> 欢迎使用Gin-Vue-Admin,开源地址:https://github.com/flipped-aurora/gin-vue-admin` ) ) - console.log(greenText(`> 当前版本:v2.7.7`)) + console.log(greenText(`> 当前版本:vv2.7.8-beta1`)) console.log(greenText(`> 加群方式:微信:shouzi_1994 QQ群:470239250`)) console.log( greenText(`> 项目地址:https://github.com/flipped-aurora/gin-vue-admin`) diff --git a/web/src/core/gin-vue-admin.js b/web/src/core/gin-vue-admin.js index 615ed30e5d..ae71f1b7f9 100644 --- a/web/src/core/gin-vue-admin.js +++ b/web/src/core/gin-vue-admin.js @@ -10,7 +10,7 @@ export default { register(app) console.log(` 欢迎使用 Gin-Vue-Admin - 当前版本:v2.7.7 + 当前版本:v2.7.8-beta1 加群方式:微信:shouzi_1994 QQ群:622360840 项目地址:https://github.com/flipped-aurora/gin-vue-admin 插件市场:https://plugin.gin-vue-admin.com diff --git a/web/src/hooks/charts.js b/web/src/hooks/charts.js index 9f03b0e6a4..b7f7bb3bbb 100644 --- a/web/src/hooks/charts.js +++ b/web/src/hooks/charts.js @@ -7,7 +7,7 @@ import { useAppStore } from '@/pinia' export default function useChartOption(sourceOption) { const appStore = useAppStore() const isDark = computed(() => { - return appStore.theme === 'dark' + return appStore.isDark }) const chartOption = computed(() => { return sourceOption(isDark.value) diff --git a/web/src/pathInfo.json b/web/src/pathInfo.json index 889d02a33f..e08798c046 100644 --- a/web/src/pathInfo.json +++ b/web/src/pathInfo.json @@ -64,4 +64,4 @@ "/src/plugin/announcement/form/info.vue": "InfoForm", "/src/plugin/announcement/view/info.vue": "Info", "/src/plugin/email/view/index.vue": "Email" -} +} \ No newline at end of file diff --git a/web/src/pinia/modules/app.js b/web/src/pinia/modules/app.js index 2a37f4d4d1..45b22227a0 100644 --- a/web/src/pinia/modules/app.js +++ b/web/src/pinia/modules/app.js @@ -1,8 +1,12 @@ import { defineStore } from 'pinia' import { ref, watchEffect, reactive } from 'vue' import { setBodyPrimaryColor } from '@/utils/format' +import { useDark, usePreferredDark } from '@vueuse/core' + export const useAppStore = defineStore('app', () => { const device = ref('') + const drawerSize = ref('') + const operateMinWith = ref('240') const config = reactive({ weakness: false, grey: false, @@ -16,14 +20,17 @@ export const useAppStore = defineStore('app', () => { side_mode: 'normal' }) - const theme = ref('auto') + const isDark = useDark({ + selector: 'html', + attribute: 'class', + valueDark: 'dark', + valueLight: 'light', + }) - const toggleTheme = (dark) => { - if (dark) { - theme.value = 'dark' - } else { - theme.value = 'light' - } + const preferredDark = usePreferredDark() + + const toggleTheme = (darkMode) => { + isDark.value = darkMode } const toggleWeakness = (e) => { @@ -43,6 +50,13 @@ export const useAppStore = defineStore('app', () => { } const toggleDevice = (e) => { + if(e === 'mobile'){ + drawerSize.value = '100%' + operateMinWith.value = '80' + }else { + drawerSize.value = '800' + operateMinWith.value = '240' + } device.value = e } @@ -50,15 +64,14 @@ export const useAppStore = defineStore('app', () => { config.darkMode = e } - const toggleDarkModeAuto = () => { - // 处理浏览器主题 - const darkQuery = window.matchMedia('(prefers-color-scheme: dark)') - const dark = darkQuery.matches - toggleTheme(dark) - darkQuery.addEventListener('change', (e) => { - toggleTheme(e.matches) - }) - } + // 监听系统主题变化 + watchEffect(() => { + if (config.darkMode === 'auto') { + isDark.value = preferredDark.value + return + } + isDark.value = config.darkMode === 'dark' + }) const toggleConfigSideWidth = (e) => { config.layout_side_width = e @@ -76,55 +89,26 @@ export const useAppStore = defineStore('app', () => { config.show_watermark = e } - const toggleSideModel = (e) => { + const toggleSideMode = (e) => { config.side_mode = e } + // 监听色弱模式和灰色模式 watchEffect(() => { - if (theme.value === 'dark') { - document.documentElement.classList.add('dark') - document.documentElement.classList.remove('light') - } else { - document.documentElement.classList.add('light') - document.documentElement.classList.remove('dark') - } - }) - watchEffect(() => { - // 色弱模式监听处理 - if (config.weakness) { - document.documentElement.classList.add('html-weakenss') - } else { - document.documentElement.classList.remove('html-weakenss') - } - }) - watchEffect(() => { - // 灰色模式监听处理 - if (config.grey) { - document.documentElement.classList.add('html-grey') - } else { - document.documentElement.classList.remove('html-grey') - } - }) - - watchEffect(() => { - if (config.darkMode === 'auto') { - toggleDarkModeAuto() - } - - if (config.darkMode === 'dark') { - toggleTheme(true) - } else { - toggleTheme(false) - } + document.documentElement.classList.toggle('html-weakenss', config.weakness) + document.documentElement.classList.toggle('html-grey', config.grey) }) + // 监听主题色 watchEffect(() => { - setBodyPrimaryColor(config.primaryColor, theme.value) + setBodyPrimaryColor(config.primaryColor, isDark.value ? 'dark' : 'light') }) return { - theme, + isDark, device, + drawerSize, + operateMinWith, config, toggleTheme, toggleDevice, @@ -137,6 +121,6 @@ export const useAppStore = defineStore('app', () => { toggleConfigSideCollapsedWidth, toggleConfigSideItemHeight, toggleConfigWatermark, - toggleSideModel + toggleSideMode } }) diff --git a/web/src/pinia/modules/user.js b/web/src/pinia/modules/user.js index 82d1cb08ef..2bcb7257bc 100644 --- a/web/src/pinia/modules/user.js +++ b/web/src/pinia/modules/user.js @@ -3,9 +3,10 @@ import { jsonInBlacklist } from '@/api/jwt' import router from '@/router/index' import { ElLoading, ElMessage } from 'element-plus' import { defineStore } from 'pinia' -import { ref, watch } from 'vue' +import { ref, computed } from 'vue' import { useRouterStore } from './router' -import cookie from 'js-cookie' +import { useCookies } from '@vueuse/integrations/useCookies' +import { useStorage } from '@vueuse/core' import { useAppStore } from '@/pinia' @@ -19,9 +20,10 @@ export const useUserStore = defineStore('user', () => { headerImg: '', authority: {} }) - const token = ref( - window.localStorage.getItem('token') || cookie.get('x-token') || '' - ) + const token = useStorage('token', '') + const xToken = useCookies('x-token') + const currentToken = computed(() => token.value || xToken.value || '') + const setUserInfo = (val) => { userInfo.value = val if (val.originSetting) { @@ -33,11 +35,11 @@ export const useUserStore = defineStore('user', () => { const setToken = (val) => { token.value = val + xToken.value = val } const NeedInit = async () => { - token.value = '' - window.localStorage.removeItem('token') + await ClearStorage() await router.push({ name: 'Init', replace: true }) } @@ -57,49 +59,49 @@ export const useUserStore = defineStore('user', () => { } /* 登录*/ const LoginIn = async (loginInfo) => { - loadingInstance.value = ElLoading.service({ - fullscreen: true, - text: '登录中,请稍候...' - }) - - const res = await login(loginInfo) - - // 登陆失败,直接返回 - if (res.code !== 0) { - loadingInstance.value.close() - return false - } - - // 登陆成功,设置用户信息和权限相关信息 - setUserInfo(res.data.user) - setToken(res.data.token) + try { + loadingInstance.value = ElLoading.service({ + fullscreen: true, + text: '登录中,请稍候...' + }) - // 初始化路由信息 - const routerStore = useRouterStore() - await routerStore.SetAsyncRouter() - const asyncRouters = routerStore.asyncRouters + const res = await login(loginInfo) + + if (res.code !== 0) { + ElMessage.error(res.message || '登录失败') + return false + } + // 登陆成功,设置用户信息和权限相关信息 + setUserInfo(res.data.user) + setToken(res.data.token) + + // 初始化路由信息 + const routerStore = useRouterStore() + await routerStore.SetAsyncRouter() + const asyncRouters = routerStore.asyncRouters + + // 注册到路由表里 + asyncRouters.forEach((asyncRouter) => { + router.addRoute(asyncRouter) + }) - // 注册到路由表里 - asyncRouters.forEach((asyncRouter) => { - router.addRoute(asyncRouter) - }) + if (!router.hasRoute(userInfo.value.authority.defaultRouter)) { + ElMessage.error('请联系管理员进行授权') + } else { + await router.replace({ name: userInfo.value.authority.defaultRouter }) + } - if (!router.hasRoute(userInfo.value.authority.defaultRouter)) { - ElMessage.error('请联系管理员进行授权') - } else { - await router.replace({ name: userInfo.value.authority.defaultRouter }) - } + const isWindows = /windows/i.test(navigator.userAgent) + window.localStorage.setItem('osType', isWindows ? 'WIN' : 'MAC') - const isWin = ref(/windows/i.test(navigator.userAgent)) - if (isWin.value) { - window.localStorage.setItem('osType', 'WIN') - } else { - window.localStorage.setItem('osType', 'MAC') + // 全部操作均结束,关闭loading并返回 + return true + } catch (error) { + console.error('LoginIn error:', error) + return false + } finally { + loadingInstance.value?.close() } - - // 全部操作均结束,关闭loading并返回 - loadingInstance.value.close() - return true } /* 登出*/ const LoginOut = async () => { @@ -119,22 +121,14 @@ export const useUserStore = defineStore('user', () => { /* 清理数据 */ const ClearStorage = async () => { token.value = '' + xToken.value = '' sessionStorage.clear() - window.localStorage.removeItem('token') - cookie.remove('x-token') localStorage.removeItem('originSetting') } - watch( - () => token.value, - () => { - window.localStorage.setItem('token', token.value) - } - ) - return { userInfo, - token, + token: currentToken, NeedInit, ResetUserInfo, GetUserInfo, diff --git a/web/src/view/dashboard/components/charts-content-numbers.vue b/web/src/view/dashboard/components/charts-content-numbers.vue index 950b3b4164..4d7fb9e852 100644 --- a/web/src/view/dashboard/components/charts-content-numbers.vue +++ b/web/src/view/dashboard/components/charts-content-numbers.vue @@ -25,8 +25,7 @@ } }) const dotColor = computed(() => { - console.log(appStore.theme) - return appStore.theme === 'dark' ? '#333' : '#E5E8EF' + return appStore.isDark ? '#333' : '#E5E8EF' }) const graphicFactory = (side) => { return { diff --git a/web/src/view/init/index.vue b/web/src/view/init/index.vue index c8b0155cf6..211ec4a881 100644 --- a/web/src/view/init/index.vue +++ b/web/src/view/init/index.vue @@ -111,6 +111,12 @@ placeholder="请输入sqlite数据库文件存放路径" /> + + +
立即初始化 @@ -192,7 +198,8 @@ userName: 'postgres', password: '', dbName: 'gva', - dbPath: '' + dbPath: '', + template: 'template0' }) break case 'oracle': diff --git a/web/src/view/layout/header/index.vue b/web/src/view/layout/header/index.vue index 858d2c6fd4..bf7b5be1c5 100644 --- a/web/src/view/layout/header/index.vue +++ b/web/src/view/layout/header/index.vue @@ -9,7 +9,8 @@ >
diff --git a/web/src/view/layout/index.vue b/web/src/view/layout/index.vue index 12d93260c1..c5d26fc8f2 100644 --- a/web/src/view/layout/index.vue +++ b/web/src/view/layout/index.vue @@ -62,7 +62,7 @@ import { useAppStore } from '@/pinia' import { storeToRefs } from 'pinia' const appStore = useAppStore() - const { config, theme, device } = storeToRefs(appStore) + const { config, isDark, device } = storeToRefs(appStore) defineOptions({ name: 'GvaLayout' @@ -75,7 +75,7 @@ watchEffect(() => { font.color = - theme.value === 'dark' ? 'rgba(255,255,255, .15)' : 'rgba(0, 0, 0, .15)' + isDark.value ? 'rgba(255,255,255, .15)' : 'rgba(0, 0, 0, .15)' }) const router = useRouter() diff --git a/web/src/view/layout/setting/index.vue b/web/src/view/layout/setting/index.vue index c2ed06cee2..2e5f5c7951 100644 --- a/web/src/view/layout/setting/index.vue +++ b/web/src/view/layout/setting/index.vue @@ -71,7 +71,7 @@ v-model="config.side_mode" :options="sideModes" size="default" - @change="appStore.toggleSideModel" + @change="appStore.toggleSideMode" /> - +