From f254132e187606985b0a71832a7406735bfdd581 Mon Sep 17 00:00:00 2001
From: osi
Date: Fri, 19 Sep 2025 20:44:33 +0800
Subject: [PATCH] =?UTF-8?q?:art:=20:fire:=20:sparkles:=20:ambulance:=20?=
=?UTF-8?q?=E9=9B=86=E6=88=90=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81=E7=9A=84?=
=?UTF-8?q?&=E5=85=BC=E5=AE=B9=E5=AE=B9=E5=99=A8=E5=8C=96=E9=83=A8?=
=?UTF-8?q?=E7=BD=B2=E6=8F=92=E4=BB=B6=E7=9A=84=E6=8F=92=E4=BB=B6=E6=94=B9?=
=?UTF-8?q?=E9=80=A0&=E6=8F=90=E4=BE=9B=E4=BA=86=E4=B8=80=E4=B8=AA?=
=?UTF-8?q?=E6=96=B0=E7=9A=84=E8=BD=AE=E6=92=AD=E5=9B=BE=E6=8F=92=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
server/addons/flashbanner/README.MD | 45 +++++
.../flashbanner/api/admin/banner/banner.go | 65 +++++++
.../flashbanner/api/admin/config/config.go | 30 +++
.../api/admin/index/banner/banner.go | 33 ++++
.../flashbanner/api/admin/index/index.go | 23 +++
.../addons/flashbanner/api/api/index/index.go | 21 +++
.../flashbanner/api/home/index/index.go | 21 +++
.../flashbanner/api/websocket/index/index.go | 21 +++
server/addons/flashbanner/consts/consts.go | 9 +
.../controller/admin/banner/banner.go | 81 ++++++++
.../controller/admin/sys/banner.go | 14 ++
.../controller/admin/sys/config.go | 33 ++++
.../flashbanner/controller/admin/sys/index.go | 30 +++
.../controller/api/banner/banner.go | 41 ++++
.../flashbanner/controller/api/index.go | 31 +++
.../flashbanner/controller/home/index.go | 34 ++++
.../flashbanner/controller/websocket/index.go | 30 +++
server/addons/flashbanner/crons/crons.go | 9 +
server/addons/flashbanner/dao/banner.go | 12 ++
.../addons/flashbanner/dao/internal/banner.go | 89 +++++++++
server/addons/flashbanner/global/global.go | 12 ++
server/addons/flashbanner/global/init.go | 22 +++
server/addons/flashbanner/logic/.gitkeep | 0
server/addons/flashbanner/logic/logic.go | 9 +
server/addons/flashbanner/logic/sys/banner.go | 173 +++++++++++++++++
server/addons/flashbanner/logic/sys/config.go | 59 ++++++
server/addons/flashbanner/logic/sys/index.go | 35 ++++
server/addons/flashbanner/main.go | 176 ++++++++++++++++++
server/addons/flashbanner/model/config.go | 11 ++
.../addons/flashbanner/model/entity/banner.go | 22 +++
.../flashbanner/model/input/sysin/banner.go | 98 ++++++++++
.../flashbanner/model/input/sysin/config.go | 24 +++
.../flashbanner/model/input/sysin/index.go | 27 +++
server/addons/flashbanner/queues/queues.go | 9 +
.../flashbanner/resource/public/.gitkeep | 0
.../flashbanner/resource/public/default | 1 +
.../resource/template/home/index.html | 30 +++
server/addons/flashbanner/router/admin.go | 36 ++++
server/addons/flashbanner/router/api.go | 32 ++++
.../flashbanner/router/genrouter/init.go | 34 ++++
server/addons/flashbanner/router/home.go | 25 +++
server/addons/flashbanner/router/websocket.go | 39 ++++
server/addons/flashbanner/service/.gitkeep | 0
server/addons/flashbanner/service/sys.go | 71 +++++++
.../api/addons/flashbanner/config/index.ts | 17 ++
.../web/src/api/addons/flashbanner/index.ts | 33 ++++
.../addons/flashbanner/components/Edit.vue | 106 +++++++++++
.../addons/flashbanner/components/model.ts | 83 +++++++++
.../flashbanner/config/BasicSetting.vue | 74 ++++++++
.../addons/flashbanner/config/system.vue | 82 ++++++++
.../src/views/addons/flashbanner/index.vue | 151 +++++++++++++++
.../migrations/flashbanner/install.pg.sql | 167 +++++++++++++++++
.../addons/migrations/flashbanner/install.sql | 33 ++++
.../migrations/flashbanner/uninstall.pg.sql | 9 +
.../migrations/flashbanner/uninstall.sql | 9 +
server/addons/migrations/readme.md | 2 +
server/addons/migrations/sqlDo.go | 66 +++++++
server/addons/modules/flashbanner.go | 8 +
server/internal/library/addons/build.go | 49 +++--
.../generate/default/addon/README.MD.template | 11 ++
.../generate/default/addon/main.go.template | 68 ++++++-
61 files changed, 2569 insertions(+), 16 deletions(-)
create mode 100644 server/addons/flashbanner/README.MD
create mode 100644 server/addons/flashbanner/api/admin/banner/banner.go
create mode 100644 server/addons/flashbanner/api/admin/config/config.go
create mode 100644 server/addons/flashbanner/api/admin/index/banner/banner.go
create mode 100644 server/addons/flashbanner/api/admin/index/index.go
create mode 100644 server/addons/flashbanner/api/api/index/index.go
create mode 100644 server/addons/flashbanner/api/home/index/index.go
create mode 100644 server/addons/flashbanner/api/websocket/index/index.go
create mode 100644 server/addons/flashbanner/consts/consts.go
create mode 100644 server/addons/flashbanner/controller/admin/banner/banner.go
create mode 100644 server/addons/flashbanner/controller/admin/sys/banner.go
create mode 100644 server/addons/flashbanner/controller/admin/sys/config.go
create mode 100644 server/addons/flashbanner/controller/admin/sys/index.go
create mode 100644 server/addons/flashbanner/controller/api/banner/banner.go
create mode 100644 server/addons/flashbanner/controller/api/index.go
create mode 100644 server/addons/flashbanner/controller/home/index.go
create mode 100644 server/addons/flashbanner/controller/websocket/index.go
create mode 100644 server/addons/flashbanner/crons/crons.go
create mode 100644 server/addons/flashbanner/dao/banner.go
create mode 100644 server/addons/flashbanner/dao/internal/banner.go
create mode 100644 server/addons/flashbanner/global/global.go
create mode 100644 server/addons/flashbanner/global/init.go
create mode 100644 server/addons/flashbanner/logic/.gitkeep
create mode 100644 server/addons/flashbanner/logic/logic.go
create mode 100644 server/addons/flashbanner/logic/sys/banner.go
create mode 100644 server/addons/flashbanner/logic/sys/config.go
create mode 100644 server/addons/flashbanner/logic/sys/index.go
create mode 100644 server/addons/flashbanner/main.go
create mode 100644 server/addons/flashbanner/model/config.go
create mode 100644 server/addons/flashbanner/model/entity/banner.go
create mode 100644 server/addons/flashbanner/model/input/sysin/banner.go
create mode 100644 server/addons/flashbanner/model/input/sysin/config.go
create mode 100644 server/addons/flashbanner/model/input/sysin/index.go
create mode 100644 server/addons/flashbanner/queues/queues.go
create mode 100644 server/addons/flashbanner/resource/public/.gitkeep
create mode 100644 server/addons/flashbanner/resource/public/default
create mode 100644 server/addons/flashbanner/resource/template/home/index.html
create mode 100644 server/addons/flashbanner/router/admin.go
create mode 100644 server/addons/flashbanner/router/api.go
create mode 100644 server/addons/flashbanner/router/genrouter/init.go
create mode 100644 server/addons/flashbanner/router/home.go
create mode 100644 server/addons/flashbanner/router/websocket.go
create mode 100644 server/addons/flashbanner/service/.gitkeep
create mode 100644 server/addons/flashbanner/service/sys.go
create mode 100644 server/addons/flashbanner/web/src/api/addons/flashbanner/config/index.ts
create mode 100644 server/addons/flashbanner/web/src/api/addons/flashbanner/index.ts
create mode 100644 server/addons/flashbanner/web/src/views/addons/flashbanner/components/Edit.vue
create mode 100644 server/addons/flashbanner/web/src/views/addons/flashbanner/components/model.ts
create mode 100644 server/addons/flashbanner/web/src/views/addons/flashbanner/config/BasicSetting.vue
create mode 100644 server/addons/flashbanner/web/src/views/addons/flashbanner/config/system.vue
create mode 100644 server/addons/flashbanner/web/src/views/addons/flashbanner/index.vue
create mode 100644 server/addons/migrations/flashbanner/install.pg.sql
create mode 100644 server/addons/migrations/flashbanner/install.sql
create mode 100644 server/addons/migrations/flashbanner/uninstall.pg.sql
create mode 100644 server/addons/migrations/flashbanner/uninstall.sql
create mode 100644 server/addons/migrations/readme.md
create mode 100644 server/addons/migrations/sqlDo.go
create mode 100644 server/addons/modules/flashbanner.go
diff --git a/server/addons/flashbanner/README.MD b/server/addons/flashbanner/README.MD
new file mode 100644
index 0000000..76a4f7b
--- /dev/null
+++ b/server/addons/flashbanner/README.MD
@@ -0,0 +1,45 @@
+## 轮播图管理
+
+### 简介
+
+
+
+
+### 使用说明
+
+
+
+
+### 迁移或安装
+
+1、安装 HotGo (2.17.8及以上)
+
+项目介绍:https://github.com/bufanyun/hotgo
+
+2、将当前插件项目拷贝进 HotGo 根目录的 server/addons 目录下
+
+3、在 HotGo 根目录的 server/addons/modules 目录下创建go文件:flashbanner.go,内容如下:
+```go
+package modules
+
+import _ "hotgo/addons/flashbanner"
+```
+
+4、HotGo 后台进入 开发工具->插件管理->找到 轮播图管理 (flashbanner) 进行安装
+
+5、重启服务即可生效
+
+
+### 常用命令行
+
+```shell
+# 接口维护-gen service
+gf gen service -s=addons/flashbanner/logic -d=addons/flashbanner/service
+
+```
+
+### `gf gen dao` 之后迁移model文件
+```
+cp .\internal\dao\internal\banner* .\addons\flashbanner\dao\internal\
+cp .\internal\model\entity\banner* .\addons\flashbanner\model\entity\
+```
diff --git a/server/addons/flashbanner/api/admin/banner/banner.go b/server/addons/flashbanner/api/admin/banner/banner.go
new file mode 100644
index 0000000..9d75f55
--- /dev/null
+++ b/server/addons/flashbanner/api/admin/banner/banner.go
@@ -0,0 +1,65 @@
+// Package banner
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package banner
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+ "hotgo/internal/model/input/form"
+)
+
+// CreateReq 创建轮播图
+type CreateReq struct {
+ g.Meta `path:"/banner/create" method:"post" tags:"轮播图" summary:"创建轮播图"`
+ sysin.BannerCreateInp
+}
+
+type CreateRes struct{}
+
+// ListReq 查询列表
+type ListReq struct {
+ g.Meta `path:"/banner/list" method:"get" tags:"轮播图" summary:"获取轮播图列表"`
+ sysin.BannerListInp
+}
+
+type ListRes struct {
+ List []*sysin.BannerListModel `json:"list" dc:"数据列表"`
+ form.PageRes
+}
+
+// ViewReq 获取指定信息
+type ViewReq struct {
+ g.Meta `path:"/banner/view" method:"get" tags:"轮播图" summary:"获取指定轮播图信息"`
+ sysin.BannerViewInp
+}
+
+type ViewRes struct {
+ *sysin.BannerViewModel
+}
+
+// EditReq 修改/新增轮播图
+type EditReq struct {
+ g.Meta `path:"/banner/edit" method:"post" tags:"轮播图" summary:"修改/新增轮播图"`
+ sysin.BannerEditInp
+}
+
+type EditRes struct{}
+
+// DeleteReq 删除轮播图
+type DeleteReq struct {
+ g.Meta `path:"/banner/delete" method:"post" tags:"轮播图" summary:"删除轮播图"`
+ sysin.BannerDeleteInp
+}
+
+type DeleteRes struct{}
+
+// StatusReq 更新轮播图状态
+type StatusReq struct {
+ g.Meta `path:"/banner/status" method:"post" tags:"轮播图" summary:"更新轮播图状态"`
+ sysin.BannerStatusInp
+}
+
+type StatusRes struct{}
\ No newline at end of file
diff --git a/server/addons/flashbanner/api/admin/config/config.go b/server/addons/flashbanner/api/admin/config/config.go
new file mode 100644
index 0000000..e54dc78
--- /dev/null
+++ b/server/addons/flashbanner/api/admin/config/config.go
@@ -0,0 +1,30 @@
+// Package config
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package config
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+// GetReq 获取指定分组的配置
+type GetReq struct {
+ g.Meta `path:"/config/get" method:"get" tags:"轮播图管理" summary:"获取指定分组的配置"`
+ sysin.GetConfigInp
+}
+
+type GetRes struct {
+ *sysin.GetConfigModel
+}
+
+// UpdateReq 获取指定分组的配置
+type UpdateReq struct {
+ g.Meta `path:"/config/update" method:"post" tags:"轮播图管理" summary:"获取指定分组的配置"`
+ sysin.UpdateConfigInp
+}
+
+type UpdateRes struct {
+}
diff --git a/server/addons/flashbanner/api/admin/index/banner/banner.go b/server/addons/flashbanner/api/admin/index/banner/banner.go
new file mode 100644
index 0000000..8ef1cb2
--- /dev/null
+++ b/server/addons/flashbanner/api/admin/index/banner/banner.go
@@ -0,0 +1,33 @@
+// Package banner
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package banner
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+ "hotgo/internal/model/input/form"
+)
+
+// ListReq 查询列表
+type ListReq struct {
+ g.Meta `path:"/banner/list" method:"get" tags:"轮播图" summary:"获取轮播图列表"`
+ sysin.BannerListInp
+}
+
+type ListRes struct {
+ List []*sysin.BannerListModel `json:"list" dc:"数据列表"`
+ form.PageRes
+}
+
+// ViewReq 获取指定信息
+type ViewReq struct {
+ g.Meta `path:"/banner/view" method:"get" tags:"轮播图" summary:"获取指定轮播图信息"`
+ sysin.BannerViewInp
+}
+
+type ViewRes struct {
+ *sysin.BannerViewModel
+}
diff --git a/server/addons/flashbanner/api/admin/index/index.go b/server/addons/flashbanner/api/admin/index/index.go
new file mode 100644
index 0000000..9688324
--- /dev/null
+++ b/server/addons/flashbanner/api/admin/index/index.go
@@ -0,0 +1,23 @@
+// Package index
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package index
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+// TestReq 测试
+type TestReq struct {
+ g.Meta `path:"/index/test" method:"get" tags:"轮播图管理" summary:"测试后台API"`
+ sysin.IndexTestInp
+}
+
+type TestRes struct {
+ *sysin.IndexTestModel
+}
+
+
diff --git a/server/addons/flashbanner/api/api/index/index.go b/server/addons/flashbanner/api/api/index/index.go
new file mode 100644
index 0000000..763ef79
--- /dev/null
+++ b/server/addons/flashbanner/api/api/index/index.go
@@ -0,0 +1,21 @@
+// Package index
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package index
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+// TestReq 测试
+type TestReq struct {
+ g.Meta `path:"/index/test" method:"get" tags:"轮播图管理" summary:"测试前台API"`
+ sysin.IndexTestInp
+}
+
+type TestRes struct {
+ *sysin.IndexTestModel
+}
diff --git a/server/addons/flashbanner/api/home/index/index.go b/server/addons/flashbanner/api/home/index/index.go
new file mode 100644
index 0000000..31fce84
--- /dev/null
+++ b/server/addons/flashbanner/api/home/index/index.go
@@ -0,0 +1,21 @@
+// Package index
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package index
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+// TestReq 测试
+type TestReq struct {
+ g.Meta `path:"/index/test" method:"get" summary:"轮播图管理" tags:"测试首页"`
+ sysin.IndexTestInp
+}
+
+type TestRes struct {
+ g.Meta `mime:"text/html" type:"string" example:""`
+}
diff --git a/server/addons/flashbanner/api/websocket/index/index.go b/server/addons/flashbanner/api/websocket/index/index.go
new file mode 100644
index 0000000..c437577
--- /dev/null
+++ b/server/addons/flashbanner/api/websocket/index/index.go
@@ -0,0 +1,21 @@
+// Package index
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package index
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+// TestReq 测试
+type TestReq struct {
+ g.Meta `path:"/index/test" method:"get" tags:"轮播图管理" summary:"测试websocket"`
+ sysin.IndexTestInp
+}
+
+type TestRes struct {
+ *sysin.IndexTestModel
+}
diff --git a/server/addons/flashbanner/consts/consts.go b/server/addons/flashbanner/consts/consts.go
new file mode 100644
index 0000000..4306296
--- /dev/null
+++ b/server/addons/flashbanner/consts/consts.go
@@ -0,0 +1,9 @@
+// Package consts
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package consts
+
+// 常量枚举.
+// 插件中的常量枚举可以统一在这目录下
diff --git a/server/addons/flashbanner/controller/admin/banner/banner.go b/server/addons/flashbanner/controller/admin/banner/banner.go
new file mode 100644
index 0000000..45f2c2c
--- /dev/null
+++ b/server/addons/flashbanner/controller/admin/banner/banner.go
@@ -0,0 +1,81 @@
+// Package banner
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package banner
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/admin/banner"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ Banner = cBanner{}
+)
+
+type cBanner struct{}
+
+// Create 创建轮播图
+func (c *cBanner) Create(ctx context.Context, req *banner.CreateReq) (res *banner.CreateRes, err error) {
+ err = service.SysBanner().Create(ctx, &req.BannerCreateInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.CreateRes{}
+ return res, nil
+}
+
+// List 获取轮播图列表
+func (c *cBanner) List(ctx context.Context, req *banner.ListReq) (res *banner.ListRes, err error) {
+ list, totalCount, err := service.SysBanner().List(ctx, &req.BannerListInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.ListRes{
+ List: list,
+ }
+ res.PageRes.Pack(&req.BannerListInp, totalCount)
+ return res, nil
+}
+
+// View 获取指定轮播图信息
+func (c *cBanner) View(ctx context.Context, req *banner.ViewReq) (res *banner.ViewRes, err error) {
+ model, err := service.SysBanner().View(ctx, &req.BannerViewInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.ViewRes{model}
+ return res, nil
+}
+
+// Edit 修改/新增轮播图
+func (c *cBanner) Edit(ctx context.Context, req *banner.EditReq) (res *banner.EditRes, err error) {
+ err = service.SysBanner().Edit(ctx, &req.BannerEditInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.EditRes{}
+ return res, nil
+}
+
+// Delete 删除轮播图
+func (c *cBanner) Delete(ctx context.Context, req *banner.DeleteReq) (res *banner.DeleteRes, err error) {
+ err = service.SysBanner().Delete(ctx, &req.BannerDeleteInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.DeleteRes{}
+ return res, nil
+}
+
+// Status 更新轮播图状态
+func (c *cBanner) Status(ctx context.Context, req *banner.StatusReq) (res *banner.StatusRes, err error) {
+ err = service.SysBanner().Status(ctx, &req.BannerStatusInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.StatusRes{}
+ return res, nil
+}
\ No newline at end of file
diff --git a/server/addons/flashbanner/controller/admin/sys/banner.go b/server/addons/flashbanner/controller/admin/sys/banner.go
new file mode 100644
index 0000000..47dbe1e
--- /dev/null
+++ b/server/addons/flashbanner/controller/admin/sys/banner.go
@@ -0,0 +1,14 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "hotgo/addons/flashbanner/controller/admin/banner"
+)
+
+var (
+ Banner = banner.Banner
+)
\ No newline at end of file
diff --git a/server/addons/flashbanner/controller/admin/sys/config.go b/server/addons/flashbanner/controller/admin/sys/config.go
new file mode 100644
index 0000000..8d72a27
--- /dev/null
+++ b/server/addons/flashbanner/controller/admin/sys/config.go
@@ -0,0 +1,33 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/admin/config"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ Config = cConfig{}
+)
+
+type cConfig struct{}
+
+// GetConfig 获取指定分组的配置
+func (c *cConfig) GetConfig(ctx context.Context, req *config.GetReq) (res *config.GetRes, err error) {
+ data, err := service.SysConfig().GetConfigByGroup(ctx, &req.GetConfigInp)
+
+ res = new(config.GetRes)
+ res.GetConfigModel = data
+ return
+}
+
+// UpdateConfig 更新指定分组的配置
+func (c *cConfig) UpdateConfig(ctx context.Context, req *config.UpdateReq) (res *config.UpdateRes, err error) {
+ err = service.SysConfig().UpdateConfigByGroup(ctx, &req.UpdateConfigInp)
+ return
+}
diff --git a/server/addons/flashbanner/controller/admin/sys/index.go b/server/addons/flashbanner/controller/admin/sys/index.go
new file mode 100644
index 0000000..74fa221
--- /dev/null
+++ b/server/addons/flashbanner/controller/admin/sys/index.go
@@ -0,0 +1,30 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/admin/index"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ Index = cIndex{}
+)
+
+type cIndex struct{}
+
+// Test 测试
+func (c *cIndex) Test(ctx context.Context, req *index.TestReq) (res *index.TestRes, err error) {
+ data, err := service.SysIndex().Test(ctx, &req.IndexTestInp)
+ if err != nil {
+ return
+ }
+
+ res = new(index.TestRes)
+ res.IndexTestModel = data
+ return
+}
diff --git a/server/addons/flashbanner/controller/api/banner/banner.go b/server/addons/flashbanner/controller/api/banner/banner.go
new file mode 100644
index 0000000..bdbea11
--- /dev/null
+++ b/server/addons/flashbanner/controller/api/banner/banner.go
@@ -0,0 +1,41 @@
+// Package banner
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package banner
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/admin/banner"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ BannerIndex = cBanner{}
+)
+
+type cBanner struct{}
+
+// List 获取轮播图列表
+func (c *cBanner) List(ctx context.Context, req *banner.ListReq) (res *banner.ListRes, err error) {
+ list, totalCount, err := service.SysBanner().List(ctx, &req.BannerListInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.ListRes{
+ List: list,
+ }
+ res.PageRes.Pack(&req.BannerListInp, totalCount)
+ return res, nil
+}
+
+// View 获取指定轮播图信息
+func (c *cBanner) View(ctx context.Context, req *banner.ViewReq) (res *banner.ViewRes, err error) {
+ model, err := service.SysBanner().View(ctx, &req.BannerViewInp)
+ if err != nil {
+ return nil, err
+ }
+ res = &banner.ViewRes{model}
+ return res, nil
+}
diff --git a/server/addons/flashbanner/controller/api/index.go b/server/addons/flashbanner/controller/api/index.go
new file mode 100644
index 0000000..3e03d76
--- /dev/null
+++ b/server/addons/flashbanner/controller/api/index.go
@@ -0,0 +1,31 @@
+// Package api
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package api
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/api/index"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ Index = cIndex{}
+)
+
+type cIndex struct{}
+
+// Test 测试
+func (c *cIndex) Test(ctx context.Context, req *index.TestReq) (res *index.TestRes, err error) {
+ data, err := service.SysIndex().Test(ctx, &req.IndexTestInp)
+ if err != nil {
+ return
+ }
+
+ res = new(index.TestRes)
+ res.IndexTestModel = data
+ return
+}
+
diff --git a/server/addons/flashbanner/controller/home/index.go b/server/addons/flashbanner/controller/home/index.go
new file mode 100644
index 0000000..a615998
--- /dev/null
+++ b/server/addons/flashbanner/controller/home/index.go
@@ -0,0 +1,34 @@
+// Package home
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package home
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/addons/flashbanner/api/home/index"
+ "hotgo/addons/flashbanner/service"
+ "hotgo/internal/model"
+ isc "hotgo/internal/service"
+)
+
+// Index 基础
+var Index = cIndex{}
+
+type cIndex struct{}
+
+func (a *cIndex) Index(ctx context.Context, req *index.TestReq) (res *index.TestRes, err error) {
+ data, err := service.SysIndex().Test(ctx, &req.IndexTestInp)
+ if err != nil {
+ return
+ }
+
+ isc.View().RenderTpl(ctx, "home/index.html", model.View{Data: g.Map{
+ "name": data.Name,
+ "module": data.Module,
+ "time": data.Time,
+ }})
+ return
+}
diff --git a/server/addons/flashbanner/controller/websocket/index.go b/server/addons/flashbanner/controller/websocket/index.go
new file mode 100644
index 0000000..117b8b0
--- /dev/null
+++ b/server/addons/flashbanner/controller/websocket/index.go
@@ -0,0 +1,30 @@
+// Package websocket
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package websocket
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/api/websocket/index"
+ "hotgo/addons/flashbanner/service"
+)
+
+var (
+ Index = cIndex{}
+)
+
+type cIndex struct{}
+
+// Test 测试
+func (c *cIndex) Test(ctx context.Context, req *index.TestReq) (res *index.TestRes, err error) {
+ data, err := service.SysIndex().Test(ctx, &req.IndexTestInp)
+ if err != nil {
+ return
+ }
+
+ res = new(index.TestRes)
+ res.IndexTestModel = data
+ return
+}
diff --git a/server/addons/flashbanner/crons/crons.go b/server/addons/flashbanner/crons/crons.go
new file mode 100644
index 0000000..fd6a45f
--- /dev/null
+++ b/server/addons/flashbanner/crons/crons.go
@@ -0,0 +1,9 @@
+// Package crons
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package crons
+
+// 定时任务.
+// 插件中的定时任务可以统一在这里注册和处理
diff --git a/server/addons/flashbanner/dao/banner.go b/server/addons/flashbanner/dao/banner.go
new file mode 100644
index 0000000..82e8627
--- /dev/null
+++ b/server/addons/flashbanner/dao/banner.go
@@ -0,0 +1,12 @@
+// Package dao
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package dao
+
+import "hotgo/addons/flashbanner/dao/internal"
+
+var (
+ Banner = internal.NewBannerDao()
+)
\ No newline at end of file
diff --git a/server/addons/flashbanner/dao/internal/banner.go b/server/addons/flashbanner/dao/internal/banner.go
new file mode 100644
index 0000000..41250f1
--- /dev/null
+++ b/server/addons/flashbanner/dao/internal/banner.go
@@ -0,0 +1,89 @@
+// ==========================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package internal
+
+import (
+ "context"
+
+ "github.com/gogf/gf/v2/database/gdb"
+ "github.com/gogf/gf/v2/frame/g"
+)
+
+// BannerDao is the data access object for table hg_banner.
+type BannerDao struct {
+ table string // table is the underlying table name of the DAO.
+ group string // group is the database configuration group name of current DAO.
+ columns BannerColumns // columns contains all the column names of Table for convenient usage.
+}
+
+// BannerColumns defines and stores column names for table hg_banner.
+type BannerColumns struct {
+ Id string //
+ Name string // 轮播图名称
+ Cover string // 图片URL
+ Link string // 跳转链接,小程序内用相对地址
+ Type string // 类型默认不传
+ Status string // 1可用
+ Sort string // 排序,数字越大越靠前
+ CreatedAt string //
+ UpdatedAt string //
+}
+
+// bannerColumns holds the columns for table hg_banner.
+var bannerColumns = BannerColumns{
+ Id: "id",
+ Name: "name",
+ Cover: "cover",
+ Link: "link",
+ Type: "type",
+ Status: "status",
+ Sort: "sort",
+ CreatedAt: "created_at",
+ UpdatedAt: "updated_at",
+}
+
+// NewBannerDao creates and returns a new DAO object for table data access.
+func NewBannerDao() *BannerDao {
+ return &BannerDao{
+ group: "default",
+ table: "hg_banner",
+ columns: bannerColumns,
+ }
+}
+
+// DB retrieves and returns the underlying raw database management object of current DAO.
+func (dao *BannerDao) DB() gdb.DB {
+ return g.DB(dao.group)
+}
+
+// Table returns the table name of current dao.
+func (dao *BannerDao) Table() string {
+ return dao.table
+}
+
+// Columns returns all column names of current dao.
+func (dao *BannerDao) Columns() BannerColumns {
+ return dao.columns
+}
+
+// Group returns the configuration group name of database of current dao.
+func (dao *BannerDao) Group() string {
+ return dao.group
+}
+
+// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
+func (dao *BannerDao) Ctx(ctx context.Context) *gdb.Model {
+ return dao.DB().Model(dao.table).Safe().Ctx(ctx)
+}
+
+// Transaction wraps the transaction logic using function f.
+// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
+// It commits the transaction and returns nil if function f returns nil.
+//
+// Note that, you should not Commit or Rollback the transaction in function f
+// as it is automatically handled by this function.
+func (dao *BannerDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
+ return dao.Ctx(ctx).Transaction(ctx, f)
+}
diff --git a/server/addons/flashbanner/global/global.go b/server/addons/flashbanner/global/global.go
new file mode 100644
index 0000000..4dbc10a
--- /dev/null
+++ b/server/addons/flashbanner/global/global.go
@@ -0,0 +1,12 @@
+// Package global
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package global
+
+import "hotgo/internal/library/addons"
+
+var (
+ skeleton *addons.Skeleton // 插件架子
+)
diff --git a/server/addons/flashbanner/global/init.go b/server/addons/flashbanner/global/init.go
new file mode 100644
index 0000000..1cebca1
--- /dev/null
+++ b/server/addons/flashbanner/global/init.go
@@ -0,0 +1,22 @@
+// Package global
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package global
+
+import (
+ "context"
+ "hotgo/internal/library/addons"
+)
+
+func Init(ctx context.Context, sk *addons.Skeleton) {
+ skeleton = sk
+}
+
+func GetSkeleton() *addons.Skeleton {
+ if skeleton == nil {
+ panic("addon skeleton not initialized.")
+ }
+ return skeleton
+}
diff --git a/server/addons/flashbanner/logic/.gitkeep b/server/addons/flashbanner/logic/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/server/addons/flashbanner/logic/logic.go b/server/addons/flashbanner/logic/logic.go
new file mode 100644
index 0000000..bd63903
--- /dev/null
+++ b/server/addons/flashbanner/logic/logic.go
@@ -0,0 +1,9 @@
+// ==========================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// ==========================================================================
+
+package logic
+
+import (
+ _ "hotgo/addons/flashbanner/logic/sys"
+)
diff --git a/server/addons/flashbanner/logic/sys/banner.go b/server/addons/flashbanner/logic/sys/banner.go
new file mode 100644
index 0000000..d2d1f66
--- /dev/null
+++ b/server/addons/flashbanner/logic/sys/banner.go
@@ -0,0 +1,173 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/dao"
+ "hotgo/addons/flashbanner/model/entity"
+ "hotgo/addons/flashbanner/model/input/sysin"
+ "hotgo/addons/flashbanner/service"
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+type sSysBanner struct{}
+
+func NewSysBanner() *sSysBanner {
+ return &sSysBanner{}
+}
+
+func init() {
+ service.RegisterSysBanner(NewSysBanner())
+}
+
+// GetMaxSort 获取最大排序值
+func (s *sSysBanner) GetMaxSort(ctx context.Context) (maxSort int, err error) {
+ var result struct {
+ MaxSort int `json:"maxSort"`
+ }
+ err = dao.Banner.Ctx(ctx).Fields("MAX(sort) as maxSort").Scan(&result)
+ if err != nil {
+ return 0, gerror.Wrap(err, "获取最大排序值失败")
+ }
+ return result.MaxSort, nil
+}
+
+// Create 创建轮播图
+func (s *sSysBanner) Create(ctx context.Context, in *sysin.BannerCreateInp) (err error) {
+ // 如果没有设置排序值,自动设置为最大值+1
+ if in.Sort == 0 {
+ maxSort, err := s.GetMaxSort(ctx)
+ if err != nil {
+ return err
+ }
+ in.Sort = maxSort + 1
+ }
+
+ _, err = dao.Banner.Ctx(ctx).Data(g.Map{
+ dao.Banner.Columns().Name: in.Name,
+ dao.Banner.Columns().Cover: in.Cover,
+ dao.Banner.Columns().Link: in.Link,
+ dao.Banner.Columns().Type: in.Type,
+ dao.Banner.Columns().Status: 1, // 默认启用
+ dao.Banner.Columns().Sort: in.Sort,
+ dao.Banner.Columns().CreatedAt: gtime.Now(),
+ dao.Banner.Columns().UpdatedAt: gtime.Now(),
+ }).Insert()
+ if err != nil {
+ err = gerror.Wrap(err, "创建轮播图失败")
+ return
+ }
+ return
+}
+
+// Edit 修改/新增轮播图
+func (s *sSysBanner) Edit(ctx context.Context, in *sysin.BannerEditInp) (err error) {
+ if in.Id > 0 {
+ // 修改
+ _, err = dao.Banner.Ctx(ctx).Where(dao.Banner.Columns().Id, in.Id).Data(g.Map{
+ dao.Banner.Columns().Name: in.Name,
+ dao.Banner.Columns().Cover: in.Cover,
+ dao.Banner.Columns().Link: in.Link,
+ dao.Banner.Columns().Type: in.Type,
+ dao.Banner.Columns().Status: in.Status,
+ dao.Banner.Columns().Sort: in.Sort,
+ dao.Banner.Columns().UpdatedAt: gtime.Now(),
+ }).Update()
+ if err != nil {
+ err = gerror.Wrap(err, "修改轮播图失败")
+ return
+ }
+ } else {
+ // 新增
+ _, err = dao.Banner.Ctx(ctx).Data(g.Map{
+ dao.Banner.Columns().Name: in.Name,
+ dao.Banner.Columns().Cover: in.Cover,
+ dao.Banner.Columns().Link: in.Link,
+ dao.Banner.Columns().Type: in.Type,
+ dao.Banner.Columns().Status: in.Status,
+ dao.Banner.Columns().Sort: in.Sort,
+ dao.Banner.Columns().CreatedAt: gtime.Now(),
+ dao.Banner.Columns().UpdatedAt: gtime.Now(),
+ }).Insert()
+ if err != nil {
+ err = gerror.Wrap(err, "新增轮播图失败")
+ return
+ }
+ }
+ return
+}
+
+// Delete 删除轮播图
+func (s *sSysBanner) Delete(ctx context.Context, in *sysin.BannerDeleteInp) (err error) {
+ _, err = dao.Banner.Ctx(ctx).Where(dao.Banner.Columns().Id, in.Id).Delete()
+ if err != nil {
+ err = gerror.Wrap(err, "删除轮播图失败")
+ return
+ }
+ return
+}
+
+// View 获取指定轮播图信息
+func (s *sSysBanner) View(ctx context.Context, in *sysin.BannerViewInp) (res *sysin.BannerViewModel, err error) {
+ var banner entity.Banner
+ err = dao.Banner.Ctx(ctx).Where(dao.Banner.Columns().Id, in.Id).Scan(&banner)
+ if err != nil {
+ err = gerror.Wrap(err, "获取轮播图信息失败")
+ return
+ }
+ if banner.Id == 0 {
+ err = gerror.New("轮播图不存在")
+ return
+ }
+ res = &sysin.BannerViewModel{Banner: banner}
+ return
+}
+
+// List 获取轮播图列表
+func (s *sSysBanner) List(ctx context.Context, in *sysin.BannerListInp) (list []*sysin.BannerListModel, totalCount int, err error) {
+ m := dao.Banner.Ctx(ctx)
+
+ // 条件查询
+ if in.Name != "" {
+ m = m.WhereLike(dao.Banner.Columns().Name, "%"+in.Name+"%")
+ }
+ if in.Type > 0 {
+ m = m.Where(dao.Banner.Columns().Type, in.Type)
+ }
+
+ var banners []*entity.Banner
+ if in.Page > 0 && in.PerPage > 0 {
+ err = m.Page(in.Page, in.PerPage).OrderDesc(dao.Banner.Columns().Sort).OrderDesc(dao.Banner.Columns().Id).ScanAndCount(&banners, &totalCount, false)
+ } else {
+ err = m.OrderDesc(dao.Banner.Columns().Sort).OrderDesc(dao.Banner.Columns().Id).ScanAndCount(&banners, &totalCount, false)
+ }
+ if err != nil {
+ err = gerror.Wrap(err, "获取轮播图列表失败")
+ return
+ }
+
+ list = make([]*sysin.BannerListModel, len(banners))
+ for i, banner := range banners {
+ list[i] = &sysin.BannerListModel{Banner: *banner}
+ }
+ return
+}
+
+// Status 更新轮播图状态
+func (s *sSysBanner) Status(ctx context.Context, in *sysin.BannerStatusInp) (err error) {
+ _, err = dao.Banner.Ctx(ctx).Where(dao.Banner.Columns().Id, in.Id).Data(g.Map{
+ dao.Banner.Columns().Status: in.Status,
+ dao.Banner.Columns().UpdatedAt: gtime.Now(),
+ }).Update()
+ if err != nil {
+ err = gerror.Wrap(err, "更新轮播图状态失败")
+ return
+ }
+ return
+}
\ No newline at end of file
diff --git a/server/addons/flashbanner/logic/sys/config.go b/server/addons/flashbanner/logic/sys/config.go
new file mode 100644
index 0000000..958b35c
--- /dev/null
+++ b/server/addons/flashbanner/logic/sys/config.go
@@ -0,0 +1,59 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/util/gconv"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/addons/flashbanner/model"
+ "hotgo/addons/flashbanner/model/input/sysin"
+ "hotgo/addons/flashbanner/service"
+ isc "hotgo/internal/service"
+)
+
+type sSysConfig struct{}
+
+func NewSysConfig() *sSysConfig {
+ return &sSysConfig{}
+}
+
+func init() {
+ service.RegisterSysConfig(NewSysConfig())
+}
+
+// GetBasic 获取基础配置
+func (s *sSysConfig) GetBasic(ctx context.Context) (conf *model.BasicConfig, err error) {
+ var in sysin.GetConfigInp
+ in.GetAddonsConfigInp.AddonName = global.GetSkeleton().Name
+ in.GetAddonsConfigInp.Group = "basic"
+ models, err := isc.SysAddonsConfig().GetConfigByGroup(ctx, &in.GetAddonsConfigInp)
+ if err != nil {
+ return
+ }
+
+ err = gconv.Struct(models.List, &conf)
+ return
+}
+
+// GetConfigByGroup 获取指定分组配置
+func (s *sSysConfig) GetConfigByGroup(ctx context.Context, in *sysin.GetConfigInp) (res *sysin.GetConfigModel, err error) {
+ in.GetAddonsConfigInp.AddonName = global.GetSkeleton().Name
+ models, err := isc.SysAddonsConfig().GetConfigByGroup(ctx, &in.GetAddonsConfigInp)
+ if err != nil {
+ return
+ }
+
+ res = new(sysin.GetConfigModel)
+ res.List = models.List
+ return
+}
+
+// UpdateConfigByGroup 更新指定分组的配置
+func (s *sSysConfig) UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateConfigInp) error {
+ in.UpdateAddonsConfigInp.AddonName = global.GetSkeleton().Name
+ return isc.SysAddonsConfig().UpdateConfigByGroup(ctx, &in.UpdateAddonsConfigInp)
+}
diff --git a/server/addons/flashbanner/logic/sys/index.go b/server/addons/flashbanner/logic/sys/index.go
new file mode 100644
index 0000000..7b7878d
--- /dev/null
+++ b/server/addons/flashbanner/logic/sys/index.go
@@ -0,0 +1,35 @@
+// Package sys
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sys
+
+import (
+ "context"
+ "fmt"
+ "github.com/gogf/gf/v2/os/gtime"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/addons/flashbanner/model/input/sysin"
+ "hotgo/addons/flashbanner/service"
+ "hotgo/internal/library/contexts"
+)
+
+type sSysIndex struct{}
+
+func NewSysIndex() *sSysIndex {
+ return &sSysIndex{}
+}
+
+func init() {
+ service.RegisterSysIndex(NewSysIndex())
+}
+
+// Test 测试
+func (s *sSysIndex) Test(ctx context.Context, in *sysin.IndexTestInp) (res *sysin.IndexTestModel, err error) {
+ res = new(sysin.IndexTestModel)
+ res.Name = in.Name
+ res.Module = fmt.Sprintf("当前插件模块是:%s,当前应用模块是:%s", global.GetSkeleton().Name, contexts.Get(ctx).Module)
+ res.Time = gtime.Now()
+ return
+}
diff --git a/server/addons/flashbanner/main.go b/server/addons/flashbanner/main.go
new file mode 100644
index 0000000..b33799a
--- /dev/null
+++ b/server/addons/flashbanner/main.go
@@ -0,0 +1,176 @@
+// Package flashbanner
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package flashbanner
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "github.com/gogf/gf/v2/os/gctx"
+ _ "hotgo/addons/flashbanner/crons"
+ "hotgo/addons/flashbanner/global"
+ _ "hotgo/addons/flashbanner/logic"
+ _ "hotgo/addons/flashbanner/queues"
+ "hotgo/addons/flashbanner/router"
+ "hotgo/addons/migrations"
+ "hotgo/internal/library/addons"
+ "hotgo/internal/service"
+ "sync"
+
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gfile"
+
+
+)
+
+type module struct {
+ skeleton *addons.Skeleton
+ ctx context.Context
+ sync.Mutex
+}
+
+func init() {
+ newModule()
+}
+
+func newModule() {
+ m := &module{
+ skeleton: &addons.Skeleton{
+ Label: `轮播图管理`,
+ Name: `flashbanner`,
+ Group: 6,
+ Logo: "",
+ Brief: ``,
+ Description: ``,
+ Author: ``,
+ Version: `v1.0.0`, // 当该版本号高于已安装的版本号时,会提示可以更新
+ },
+ ctx: gctx.New(),
+ }
+ addons.RegisterModule(m)
+}
+
+// Start 启动模块
+func (m *module) Start(option *addons.Option) (err error) {
+ // 初始化模块
+ global.Init(m.ctx, m.skeleton)
+
+ // 注册插件路由
+ option.Server.Group("/", func(group *ghttp.RouterGroup) {
+ group.Middleware(service.Middleware().Addon)
+ router.Admin(m.ctx, group)
+ router.Api(m.ctx, group)
+ router.Home(m.ctx, group)
+ router.WebSocket(m.ctx, group)
+ })
+ return
+}
+
+// Stop 停止模块
+func (m *module) Stop() (err error) {
+ return
+}
+
+// Ctx 上下文
+func (m *module) Ctx() context.Context {
+ return m.ctx
+}
+
+// GetSkeleton 获取模块
+func (m *module) GetSkeleton() *addons.Skeleton {
+ return m.skeleton
+}
+
+// Install 安装模块
+func (m *module) Install(ctx context.Context) (err error) {
+ // 执行数据库安装文件
+ // 获取当前目录
+ sqlPath := gfile.Pwd() + gfile.Separator + "addons/migrations/flashbanner/install.sql"
+ g.Log().Debug(ctx, "安装模块", m.skeleton.Label, "路径", sqlPath)
+ result, err := migrations.DoSqlContent(ctx, sqlPath)
+ if err != nil {
+ g.Log().Error(ctx, "安装模块", m.skeleton.Label, "失败", err)
+ return
+ }
+ g.Log().Debug(ctx, "安装模块", m.skeleton.Label, "成功", result)
+ // 复制web目录下的文件到管理后台对应位置
+ // 插件的前端配置文件位于插件目录下的web子目录
+ sourceWebPath := gfile.Pwd() + gfile.Separator + "addons/" + m.skeleton.Name + "/web/src/views/addons/" + m.skeleton.Name
+ targetWebPath := "../web/src/views/addons/" + m.skeleton.Name
+ g.Log().Debug(ctx, "复制前端配置文件", "源路径:", sourceWebPath, "目标路径:", targetWebPath)
+
+ // 检查源路径是否存在
+ if gfile.Exists(sourceWebPath) {
+ err = gfile.CopyDir(sourceWebPath, targetWebPath)
+ if err != nil {
+ g.Log().Error(ctx, "复制前端配置文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "复制前端配置文件成功")
+ }
+ } else {
+ g.Log().Warning(ctx, "前端配置文件源路径不存在:", sourceWebPath)
+ }
+
+ // 复制API文件
+ sourceApiPath := gfile.Pwd() + gfile.Separator + "addons/" + m.skeleton.Name + "/web/src/api/addons/" + m.skeleton.Name
+ targetApiPath := "../web/src/api/addons/" + m.skeleton.Name
+ g.Log().Debug(ctx, "复制API文件", "源路径:", sourceApiPath, "目标路径:", targetApiPath)
+ if gfile.Exists(sourceApiPath) {
+ err = gfile.CopyDir(sourceApiPath, targetApiPath)
+ if err != nil {
+ g.Log().Error(ctx, "复制API文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "复制API文件成功")
+ }
+ } else {
+ g.Log().Warning(ctx, "API文件源路径不存在:", sourceApiPath)
+ }
+ return
+}
+
+// Upgrade 更新模块
+func (m *module) Upgrade(ctx context.Context) (err error) {
+ // ...
+ return
+}
+
+// UnInstall 卸载模块
+func (m *module) UnInstall(ctx context.Context) (err error) {
+ // ...
+ // 移除数据库安装文件
+ sqlPath := gfile.Pwd() + gfile.Separator + "addons/migrations/flashbanner/uninstall.sql"
+ g.Log().Debug(ctx, "卸载模块", m.skeleton.Label, "路径", sqlPath)
+ result, err := migrations.DoSqlContent(ctx, sqlPath)
+ if err != nil {
+ g.Log().Error(ctx, "卸载模块", m.skeleton.Label, "失败", err)
+ return
+ }
+ g.Log().Debug(ctx, "卸载模块", m.skeleton.Label, "成功", result)
+ // 删除前端文件
+ targetWebPath := "../web/src/views/addons/" + m.skeleton.Name
+ targetApiPath := "../web/src/api/addons/" + m.skeleton.Name
+
+ // 删除配置页面文件
+ if gfile.Exists(targetWebPath) {
+ err = gfile.Remove(targetWebPath)
+ if err != nil {
+ g.Log().Warning(ctx, "删除前端配置文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "删除前端配置文件成功")
+ }
+ }
+
+ // 删除API文件
+ if gfile.Exists(targetApiPath) {
+ err = gfile.Remove(targetApiPath)
+ if err != nil {
+ g.Log().Warning(ctx, "删除API文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "删除API文件成功")
+ }
+ }
+
+ return
+}
diff --git a/server/addons/flashbanner/model/config.go b/server/addons/flashbanner/model/config.go
new file mode 100644
index 0000000..7ad8505
--- /dev/null
+++ b/server/addons/flashbanner/model/config.go
@@ -0,0 +1,11 @@
+// Package model
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package model
+
+// BasicConfig 基础配置
+type BasicConfig struct {
+ Test string `json:"basicTest"`
+}
diff --git a/server/addons/flashbanner/model/entity/banner.go b/server/addons/flashbanner/model/entity/banner.go
new file mode 100644
index 0000000..bc5689d
--- /dev/null
+++ b/server/addons/flashbanner/model/entity/banner.go
@@ -0,0 +1,22 @@
+// =================================================================================
+// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
+// =================================================================================
+
+package entity
+
+import (
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// Banner is the golang structure for table banner.
+type Banner struct {
+ Id int `json:"id" orm:"id" description:""`
+ Name string `json:"name" orm:"name" description:"轮播图名称"`
+ Cover string `json:"cover" orm:"cover" description:"图片URL"`
+ Link string `json:"link" orm:"link" description:"跳转链接,小程序内用相对地址"`
+ Type int `json:"type" orm:"type" description:"类型默认不传"`
+ Status uint `json:"status" orm:"status" description:"1可用"`
+ Sort int `json:"sort" orm:"sort" description:"排序,数字越大越靠前"`
+ CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:""`
+ UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:""`
+}
diff --git a/server/addons/flashbanner/model/input/sysin/banner.go b/server/addons/flashbanner/model/input/sysin/banner.go
new file mode 100644
index 0000000..127f60e
--- /dev/null
+++ b/server/addons/flashbanner/model/input/sysin/banner.go
@@ -0,0 +1,98 @@
+// Package sysin
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sysin
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/model/entity"
+ "hotgo/internal/model/input/form"
+ "github.com/gogf/gf/v2/errors/gerror"
+)
+
+// BannerCreateInp 创建轮播图
+type BannerCreateInp struct {
+ Name string `json:"name" v:"required#轮播图名称不能为空" dc:"轮播图名称"`
+ Cover string `json:"cover" v:"required#轮播图封面不能为空" dc:"轮播图封面"`
+ Link string `json:"link" dc:"轮播图链接"`
+ Type int `json:"type" dc:"轮播图类型"`
+ Sort int `json:"sort" dc:"排序,数字越大越靠前"`
+}
+
+func (in *BannerCreateInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type BannerCreateModel struct{}
+
+// BannerEditInp 修改/新增轮播图
+type BannerEditInp struct {
+ entity.Banner
+}
+
+func (in *BannerEditInp) Filter(ctx context.Context) (err error) {
+ if in.Name == "" {
+ err = gerror.New("轮播图名称不能为空")
+ return
+ }
+ if in.Cover == "" {
+ err = gerror.New("轮播图封面不能为空")
+ return
+ }
+ return
+}
+
+type BannerEditModel struct{}
+
+// BannerDeleteInp 删除轮播图
+type BannerDeleteInp struct {
+ Id interface{} `json:"id" v:"required#轮播图ID不能为空" dc:"轮播图ID"`
+}
+
+func (in *BannerDeleteInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type BannerDeleteModel struct{}
+
+// BannerViewInp 获取指定轮播图信息
+type BannerViewInp struct {
+ Id int64 `json:"id" v:"required#轮播图ID不能为空" dc:"轮播图ID"`
+}
+
+func (in *BannerViewInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type BannerViewModel struct {
+ entity.Banner
+}
+
+// BannerListInp 获取轮播图列表
+type BannerListInp struct {
+ form.PageReq
+ Name string `json:"name" dc:"轮播图名称"`
+ Type int `json:"type" dc:"轮播图类型"`
+}
+
+func (in *BannerListInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type BannerListModel struct {
+ entity.Banner
+}
+
+// BannerStatusInp 更新轮播图状态
+type BannerStatusInp struct {
+ Id int64 `json:"id" v:"required#轮播图ID不能为空" dc:"轮播图ID"`
+ Status int `json:"status" v:"required#状态不能为空" dc:"状态"`
+}
+
+func (in *BannerStatusInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type BannerStatusModel struct{}
\ No newline at end of file
diff --git a/server/addons/flashbanner/model/input/sysin/config.go b/server/addons/flashbanner/model/input/sysin/config.go
new file mode 100644
index 0000000..de3b02c
--- /dev/null
+++ b/server/addons/flashbanner/model/input/sysin/config.go
@@ -0,0 +1,24 @@
+// Package sysin
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package sysin
+
+import (
+ "github.com/gogf/gf/v2/frame/g"
+ "hotgo/internal/model/input/sysin"
+)
+
+// UpdateConfigInp 更新指定配置
+type UpdateConfigInp struct {
+ sysin.UpdateAddonsConfigInp
+}
+
+type GetConfigInp struct {
+ sysin.GetAddonsConfigInp
+}
+
+type GetConfigModel struct {
+ List g.Map `json:"list"`
+}
diff --git a/server/addons/flashbanner/model/input/sysin/index.go b/server/addons/flashbanner/model/input/sysin/index.go
new file mode 100644
index 0000000..01d3bdc
--- /dev/null
+++ b/server/addons/flashbanner/model/input/sysin/index.go
@@ -0,0 +1,27 @@
+// Package sysin
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+//
+package sysin
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/os/gtime"
+)
+
+// IndexTestInp 测试
+type IndexTestInp struct {
+ Name string `json:"name" d:"HotGo" dc:"名称"`
+}
+
+func (in *IndexTestInp) Filter(ctx context.Context) (err error) {
+ return
+}
+
+type IndexTestModel struct {
+ Name string `json:"name" dc:"名称"`
+ Module string `json:"module" dc:"当前插件模块"`
+ Time *gtime.Time `json:"time" dc:"当前时间"`
+}
diff --git a/server/addons/flashbanner/queues/queues.go b/server/addons/flashbanner/queues/queues.go
new file mode 100644
index 0000000..4d0559c
--- /dev/null
+++ b/server/addons/flashbanner/queues/queues.go
@@ -0,0 +1,9 @@
+// Package queues
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package queues
+
+// 消息队列.
+// 插件中的消息队列消费者可以统一在这里注册和处理
diff --git a/server/addons/flashbanner/resource/public/.gitkeep b/server/addons/flashbanner/resource/public/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/server/addons/flashbanner/resource/public/default b/server/addons/flashbanner/resource/public/default
new file mode 100644
index 0000000..e3ad56a
--- /dev/null
+++ b/server/addons/flashbanner/resource/public/default
@@ -0,0 +1 @@
+Hello!这是创建插件 [轮播图管理] 时默认生成的一个静态目录文件,用于测试,当你看到这个提示时,说明已经联调成功啦!
diff --git a/server/addons/flashbanner/resource/template/home/index.html b/server/addons/flashbanner/resource/template/home/index.html
new file mode 100644
index 0000000..3502f4a
--- /dev/null
+++ b/server/addons/flashbanner/resource/template/home/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+ @{.Title}
+
+
+
+
+
+
Hello,@{.Data.name}!!
+
@{.Data.module}
+
服务器时间:@{.Data.time}
+
+
+
+
\ No newline at end of file
diff --git a/server/addons/flashbanner/router/admin.go b/server/addons/flashbanner/router/admin.go
new file mode 100644
index 0000000..030c212
--- /dev/null
+++ b/server/addons/flashbanner/router/admin.go
@@ -0,0 +1,36 @@
+// Package router
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package router
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "hotgo/addons/flashbanner/controller/admin/sys"
+ "hotgo/addons/flashbanner/controller/admin/banner"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/addons/flashbanner/router/genrouter"
+ "hotgo/internal/consts"
+ "hotgo/internal/library/addons"
+ "hotgo/internal/service"
+)
+
+// Admin 后台路由
+func Admin(ctx context.Context, group *ghttp.RouterGroup) {
+ prefix := addons.RouterPrefix(ctx, consts.AppAdmin, global.GetSkeleton().Name)
+ group.Group(prefix, func(group *ghttp.RouterGroup) {
+ group.Bind(
+ sys.Index,
+ )
+ group.Middleware(service.Middleware().AdminAuth)
+ group.Bind(
+ sys.Config,
+ banner.Banner,
+ )
+ })
+
+ // 注册生成路由
+ genrouter.Register(ctx, group)
+}
diff --git a/server/addons/flashbanner/router/api.go b/server/addons/flashbanner/router/api.go
new file mode 100644
index 0000000..c033649
--- /dev/null
+++ b/server/addons/flashbanner/router/api.go
@@ -0,0 +1,32 @@
+// Package router
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package router
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "hotgo/addons/flashbanner/controller/api/banner"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/internal/consts"
+ "hotgo/internal/library/addons"
+ "hotgo/internal/service"
+)
+
+// Api 前台路由
+func Api(ctx context.Context, group *ghttp.RouterGroup) {
+ prefix := addons.RouterPrefix(ctx, consts.AppApi, global.GetSkeleton().Name)
+ group.Group(prefix, func(group *ghttp.RouterGroup) {
+ group.Bind(
+ // 无需验证的路由
+ banner.BannerIndex,
+ )
+ group.Middleware(service.Middleware().ApiAuth)
+ group.Bind(
+ // 需要验证的路由
+ // ...
+ )
+ })
+}
diff --git a/server/addons/flashbanner/router/genrouter/init.go b/server/addons/flashbanner/router/genrouter/init.go
new file mode 100644
index 0000000..2441e7e
--- /dev/null
+++ b/server/addons/flashbanner/router/genrouter/init.go
@@ -0,0 +1,34 @@
+// Package genrouter
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package genrouter
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/internal/consts"
+ "hotgo/internal/library/addons"
+ "hotgo/internal/service"
+)
+
+var (
+ NoLoginRouter []interface{} // 无需登录
+ LoginRequiredRouter []interface{} // 需要登录
+)
+
+// Register 注册通过代码生成的后台路由
+func Register(ctx context.Context, group *ghttp.RouterGroup) {
+ prefix := addons.RouterPrefix(ctx, consts.AppAdmin, global.GetSkeleton().Name)
+ group.Group(prefix, func(group *ghttp.RouterGroup) {
+ if len(NoLoginRouter) > 0 {
+ group.Bind(NoLoginRouter...)
+ }
+ group.Middleware(service.Middleware().AdminAuth)
+ if len(LoginRequiredRouter) > 0 {
+ group.Bind(LoginRequiredRouter...)
+ }
+ })
+}
diff --git a/server/addons/flashbanner/router/home.go b/server/addons/flashbanner/router/home.go
new file mode 100644
index 0000000..fea7312
--- /dev/null
+++ b/server/addons/flashbanner/router/home.go
@@ -0,0 +1,25 @@
+// Package router
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package router
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "hotgo/addons/flashbanner/controller/home"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/internal/consts"
+ "hotgo/internal/library/addons"
+)
+
+// Home 前台页面路由
+func Home(ctx context.Context, group *ghttp.RouterGroup) {
+ prefix := addons.RouterPrefix(ctx, consts.AppHome, global.GetSkeleton().Name)
+ group.Group(prefix, func(group *ghttp.RouterGroup) {
+ group.Bind(
+ home.Index,
+ )
+ })
+}
diff --git a/server/addons/flashbanner/router/websocket.go b/server/addons/flashbanner/router/websocket.go
new file mode 100644
index 0000000..7ebfbd0
--- /dev/null
+++ b/server/addons/flashbanner/router/websocket.go
@@ -0,0 +1,39 @@
+// Package router
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2024 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package router
+
+import (
+ "context"
+ "github.com/gogf/gf/v2/net/ghttp"
+ "hotgo/addons/flashbanner/controller/websocket"
+ "hotgo/addons/flashbanner/global"
+ "hotgo/internal/consts"
+ "hotgo/internal/library/addons"
+ "hotgo/internal/service"
+ ws "hotgo/internal/websocket"
+)
+
+// WebSocket ws路由配置
+func WebSocket(ctx context.Context, group *ghttp.RouterGroup) {
+ prefix := addons.RouterPrefix(ctx, consts.AppWebSocket, global.GetSkeleton().Name)
+ group.Group(prefix, func(group *ghttp.RouterGroup) {
+ group.Bind(
+ // 无需验证的路由
+ websocket.Index,
+ )
+ // ws连接中间件
+ group.Middleware(service.Middleware().WebSocketAuth)
+ group.Bind(
+ // 需要验证的路由
+ // ..
+ )
+ })
+
+ // 注册消息路由
+ ws.RegisterMsg(ws.EventHandlers{
+ // ...
+ })
+}
diff --git a/server/addons/flashbanner/service/.gitkeep b/server/addons/flashbanner/service/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/server/addons/flashbanner/service/sys.go b/server/addons/flashbanner/service/sys.go
new file mode 100644
index 0000000..9a7f5b1
--- /dev/null
+++ b/server/addons/flashbanner/service/sys.go
@@ -0,0 +1,71 @@
+// ================================================================================
+// Code generated by GoFrame CLI tool. DO NOT EDIT.
+// You can delete these comments if you wish manually maintain this interface file.
+// ================================================================================
+
+package service
+
+import (
+ "context"
+ "hotgo/addons/flashbanner/model"
+ "hotgo/addons/flashbanner/model/input/sysin"
+)
+
+type (
+ ISysConfig interface {
+ GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
+ GetConfigByGroup(ctx context.Context, in *sysin.GetConfigInp) (res *sysin.GetConfigModel, err error)
+ UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateConfigInp) error
+ }
+ ISysIndex interface {
+ Test(ctx context.Context, in *sysin.IndexTestInp) (res *sysin.IndexTestModel, err error)
+ }
+ ISysBanner interface {
+ Create(ctx context.Context, in *sysin.BannerCreateInp) (err error)
+ Edit(ctx context.Context, in *sysin.BannerEditInp) (err error)
+ Delete(ctx context.Context, in *sysin.BannerDeleteInp) (err error)
+ View(ctx context.Context, in *sysin.BannerViewInp) (res *sysin.BannerViewModel, err error)
+ List(ctx context.Context, in *sysin.BannerListInp) (list []*sysin.BannerListModel, totalCount int, err error)
+ Status(ctx context.Context, in *sysin.BannerStatusInp) (err error)
+ GetMaxSort(ctx context.Context) (maxSort int, err error)
+ }
+)
+
+var (
+ localSysConfig ISysConfig
+ localSysIndex ISysIndex
+ localSysBanner ISysBanner
+)
+
+func SysConfig() ISysConfig {
+ if localSysConfig == nil {
+ panic("implement not found for interface ISysConfig, forgot register?")
+ }
+ return localSysConfig
+}
+
+func RegisterSysConfig(i ISysConfig) {
+ localSysConfig = i
+}
+
+func SysIndex() ISysIndex {
+ if localSysIndex == nil {
+ panic("implement not found for interface ISysIndex, forgot register?")
+ }
+ return localSysIndex
+}
+
+func RegisterSysIndex(i ISysIndex) {
+ localSysIndex = i
+}
+
+func SysBanner() ISysBanner {
+ if localSysBanner == nil {
+ panic("implement not found for interface ISysBanner, forgot register?")
+ }
+ return localSysBanner
+}
+
+func RegisterSysBanner(i ISysBanner) {
+ localSysBanner = i
+}
diff --git a/server/addons/flashbanner/web/src/api/addons/flashbanner/config/index.ts b/server/addons/flashbanner/web/src/api/addons/flashbanner/config/index.ts
new file mode 100644
index 0000000..f04d3fd
--- /dev/null
+++ b/server/addons/flashbanner/web/src/api/addons/flashbanner/config/index.ts
@@ -0,0 +1,17 @@
+import { http } from '@/utils/http/axios';
+
+export function getConfig(params) {
+ return http.request({
+ url: '/flashbanner/config/get',
+ method: 'get',
+ params,
+ });
+}
+
+export function updateConfig(params) {
+ return http.request({
+ url: '/flashbanner/config/update',
+ method: 'post',
+ params,
+ });
+}
diff --git a/server/addons/flashbanner/web/src/api/addons/flashbanner/index.ts b/server/addons/flashbanner/web/src/api/addons/flashbanner/index.ts
new file mode 100644
index 0000000..9e76033
--- /dev/null
+++ b/server/addons/flashbanner/web/src/api/addons/flashbanner/index.ts
@@ -0,0 +1,33 @@
+import { http } from '@/utils/http/axios';
+
+export function List(params) {
+ return http.request({
+ url: '/flashbanner/banner/list',
+ method: 'GET',
+ params,
+ });
+}
+
+export function Add(params) {
+ return http.request({
+ url: '/flashbanner/banner/create',
+ method: 'POST',
+ params,
+ });
+}
+
+export function Edit(params) {
+ return http.request({
+ url: '/flashbanner/banner/edit',
+ method: 'POST',
+ params,
+ });
+}
+
+export function Delete(params) {
+ return http.request({
+ url: '/flashbanner/banner/delete',
+ method: 'POST',
+ params,
+ });
+}
\ No newline at end of file
diff --git a/server/addons/flashbanner/web/src/views/addons/flashbanner/components/Edit.vue b/server/addons/flashbanner/web/src/views/addons/flashbanner/components/Edit.vue
new file mode 100644
index 0000000..de0e2a9
--- /dev/null
+++ b/server/addons/flashbanner/web/src/views/addons/flashbanner/components/Edit.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确定
+
+
+
+
+
+
+
+
+
diff --git a/server/addons/flashbanner/web/src/views/addons/flashbanner/components/model.ts b/server/addons/flashbanner/web/src/views/addons/flashbanner/components/model.ts
new file mode 100644
index 0000000..441cb19
--- /dev/null
+++ b/server/addons/flashbanner/web/src/views/addons/flashbanner/components/model.ts
@@ -0,0 +1,83 @@
+import { h, render } from 'vue';
+import { FormSchema, useForm } from '@/components/Form';
+import { NImage } from 'naive-ui';
+import { fallbackSrc } from '@/utils/hotgo';
+
+// **********查询表单********
+const detailSchemas: FormSchema[] = [
+ {
+ field: 'name',
+ component: 'NInput',
+ label: '图片名称',
+ defaultValue: null,
+ componentProps: {
+ placeholder: '请输入图片名称',
+ },
+ },
+];
+export const [register, {}] = useForm({
+ gridProps: { cols: '1 s:1 m:2 l:3 xl:4 2xl:4' },
+ labelWidth: 80,
+ schemas: detailSchemas,
+});
+
+// *********表格**********
+export const defaultColumns = [
+ {
+ title: 'ID',
+ key: 'id',
+ width: 100,
+ },
+ {
+ title: '图片名称',
+ key: 'name',
+ },
+ {
+ title: '图片',
+ key: 'cover',
+ render(row) {
+ if (row.cover !== '') {
+ return h(NImage, {
+ width: 40,
+ height: 40,
+ src: row.cover,
+ fallbackSrc: fallbackSrc(),
+ style: {
+ width: '40px',
+ height: '40px',
+ 'max-width': '100%',
+ 'max-height': '100%',
+ },
+ });
+ } else {
+ return '暂无图片'
+ }
+ },
+ },
+ {
+ title: '链接地址',
+ key: 'link',
+ render(row) {
+ return h('a', { href: row.link, target: '_blank' }, row.link);
+ }
+ },
+ {
+ title: '创建时间',
+ key: 'createdAt',
+ width: 180,
+ },
+];
+
+// *********编辑表单规则***********
+export const rules = {
+ name: {
+ required: true,
+ trigger: ['blur', 'input'],
+ message: '请输入图片名称',
+ },
+ cover: {
+ required: true,
+ trigger: ['blur', 'input'],
+ message: '请上传图片',
+ },
+};
\ No newline at end of file
diff --git a/server/addons/flashbanner/web/src/views/addons/flashbanner/config/BasicSetting.vue b/server/addons/flashbanner/web/src/views/addons/flashbanner/config/BasicSetting.vue
new file mode 100644
index 0000000..18f5f96
--- /dev/null
+++ b/server/addons/flashbanner/web/src/views/addons/flashbanner/config/BasicSetting.vue
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+ 这是一个测试参数,每个插件都可以有独立的配置项,可以按需添加
+
+
+
+
+ 保存更新
+
+
+
+
+
+
+
+
diff --git a/server/addons/flashbanner/web/src/views/addons/flashbanner/config/system.vue b/server/addons/flashbanner/web/src/views/addons/flashbanner/config/system.vue
new file mode 100644
index 0000000..863a69e
--- /dev/null
+++ b/server/addons/flashbanner/web/src/views/addons/flashbanner/config/system.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+ {{ item.name }}
+ {{ item.desc }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/addons/flashbanner/web/src/views/addons/flashbanner/index.vue b/server/addons/flashbanner/web/src/views/addons/flashbanner/index.vue
new file mode 100644
index 0000000..61e0804
--- /dev/null
+++ b/server/addons/flashbanner/web/src/views/addons/flashbanner/index.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 添加
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/addons/migrations/flashbanner/install.pg.sql b/server/addons/migrations/flashbanner/install.pg.sql
new file mode 100644
index 0000000..f8871d6
--- /dev/null
+++ b/server/addons/migrations/flashbanner/install.pg.sql
@@ -0,0 +1,167 @@
+-- 删除表(如果存在)
+DROP TABLE IF EXISTS hg_banner;
+
+-- 创建表
+CREATE TABLE hg_banner (
+ id SERIAL PRIMARY KEY,
+ name VARCHAR(255) NOT NULL,
+ cover VARCHAR(255) DEFAULT NULL,
+ link VARCHAR(255) DEFAULT NULL,
+ type INTEGER DEFAULT 0,
+ status SMALLINT DEFAULT 1,
+ sort INTEGER DEFAULT 0,
+ created_at TIMESTAMP DEFAULT NULL,
+ updated_at TIMESTAMP DEFAULT NULL
+);
+
+-- 添加表注释
+COMMENT ON TABLE hg_banner IS '轮播图表';
+
+-- 添加列注释
+COMMENT ON COLUMN hg_banner.name IS '轮播图名称';
+COMMENT ON COLUMN hg_banner.cover IS '图片URL';
+COMMENT ON COLUMN hg_banner.link IS '跳转链接,小程序内用相对地址';
+COMMENT ON COLUMN hg_banner.type IS '类型默认不传';
+COMMENT ON COLUMN hg_banner.status IS '1可用,2不可用';
+COMMENT ON COLUMN hg_banner.sort IS '排序,数字越大越靠前';
+
+-- 添加 updated_at 字段的更新触发器(模拟 MySQL 的 ON UPDATE CURRENT_TIMESTAMP)
+CREATE OR REPLACE FUNCTION update_updated_at_column()
+RETURNS TRIGGER AS $$
+BEGIN
+ NEW.updated_at = NOW();
+ RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE TRIGGER trigger_update_updated_at
+ BEFORE UPDATE ON hg_banner
+ FOR EACH ROW
+ EXECUTE FUNCTION update_updated_at_column();
+
+-- 添加菜单项
+-- 先查找或创建"内容管理"父菜单(如果不存在)
+INSERT INTO hg_admin_menu (pid, level, tree, title, name, path, icon, type, redirect, permissions, permission_name, component, always_show, active_menu, is_root, is_frame, frame_src, keep_alive, hidden, affix, sort, remark, status, updated_at, created_at)
+SELECT 0, 1, '', '内容管理', 'content', '/content', 'BookOutlined', 1, '/content', '', '', 'LAYOUT', 2, '', 1, 2, '', 2, 2, 2, 12, '内容管理模块', 1, NOW(), NOW()
+WHERE NOT EXISTS (SELECT 1 FROM hg_admin_menu WHERE name = 'content');
+
+-- 获取内容管理菜单ID并添加轮播图管理菜单
+WITH content_parent AS (
+ SELECT id FROM hg_admin_menu WHERE name = 'content' LIMIT 1
+),
+inserted_menu AS (
+ INSERT INTO hg_admin_menu (pid, level, tree, title, name, path, icon, type, redirect, permissions, permission_name, component, always_show, active_menu, is_root, is_frame, frame_src, keep_alive, hidden, affix, sort, remark, status, updated_at, created_at)
+ SELECT
+ cp.id,
+ 2,
+ 'tr_' || cp.id::text || ' ',
+ '轮播图管理',
+ 'flashbanner',
+ '/flashbanner',
+ '',
+ 2,
+ '',
+ '/flashbanner/banner/list',
+ '',
+ '/addons/flashbanner/index',
+ 2,
+ '',
+ 2,
+ 2,
+ '',
+ 1,
+ 2,
+ 2,
+ 10,
+ '轮播图管理模块',
+ 1,
+ NOW(),
+ NOW()
+ FROM content_parent cp
+ RETURNING id
+)
+-- 添加子菜单和按钮
+INSERT INTO hg_admin_menu (pid, level, tree, title, name, path, icon, type, redirect, permissions, permission_name, component, always_show, active_menu, is_root, is_frame, frame_src, keep_alive, hidden, affix, sort, remark, status, updated_at, created_at)
+SELECT
+ im.id,
+ 3,
+ 'tr_' || (SELECT id FROM content_parent)::text || ' tr_' || im.id::text || ' ',
+ '新增轮播',
+ 'addbanner',
+ '',
+ '',
+ 3,
+ '',
+ '/flashbanner/banner/create',
+ '',
+ '',
+ 2,
+ '',
+ 2,
+ 2,
+ '',
+ 2,
+ 2,
+ 2,
+ 10,
+ '新增轮播图权限',
+ 1,
+ NOW(),
+ NOW()
+FROM inserted_menu im
+UNION ALL
+SELECT
+ im.id,
+ 3,
+ 'tr_' || (SELECT id FROM content_parent)::text || ' tr_' || im.id::text || ' ',
+ '轮播编辑',
+ 'editbanner',
+ '',
+ '',
+ 3,
+ '',
+ '/flashbanner/banner/update',
+ '',
+ '',
+ 2,
+ '',
+ 2,
+ 2,
+ '',
+ 2,
+ 2,
+ 2,
+ 10,
+ '编辑轮播图权限',
+ 1,
+ NOW(),
+ NOW()
+FROM inserted_menu im
+UNION ALL
+SELECT
+ im.id,
+ 3,
+ 'tr_' || (SELECT id FROM content_parent)::text || ' tr_' || im.id::text || ' ',
+ '删除轮播',
+ 'delbanner',
+ '',
+ '',
+ 3,
+ '',
+ '/flashbanner/banner/delete',
+ '',
+ '',
+ 2,
+ '',
+ 2,
+ 2,
+ '',
+ 2,
+ 2,
+ 2,
+ 10,
+ '删除轮播图权限',
+ 1,
+ NOW(),
+ NOW()
+FROM inserted_menu im;
\ No newline at end of file
diff --git a/server/addons/migrations/flashbanner/install.sql b/server/addons/migrations/flashbanner/install.sql
new file mode 100644
index 0000000..86ec221
--- /dev/null
+++ b/server/addons/migrations/flashbanner/install.sql
@@ -0,0 +1,33 @@
+DROP TABLE IF EXISTS `hg_banner`;
+CREATE TABLE `hg_banner` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL COMMENT '轮播图名称',
+ `cover` varchar(255) DEFAULT NULL COMMENT '图片URL',
+ `link` varchar(255) DEFAULT NULL COMMENT '跳转链接,小程序内用相对地址',
+ `type` int(11) DEFAULT 0 COMMENT '类型默认不传',
+ `status` tinyint(1) DEFAULT 1 COMMENT '1可用,2不可用',
+ `sort` int(11) DEFAULT 0 COMMENT '排序,数字越大越靠前',
+ `created_at` datetime DEFAULT NULL,
+ `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='轮播图表';
+
+
+-- 添加菜单项
+-- 先查找或创建"内容管理"父菜单(如果不存在)
+INSERT IGNORE INTO `hg_admin_menu`(`pid`, `level`, `tree`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `sort`, `remark`, `status`, `updated_at`, `created_at`) VALUES
+(0, 1, '', '内容管理', 'content', '/content', 'BookOutlined', 1, '/content', '', '', 'LAYOUT', 2, '', 1, 2, '', 2, 2, 2, 12, '内容管理模块', 1, NOW(), NOW());
+
+-- 获取内容管理菜单ID并添加轮播图管理菜单
+SET @content_parent_id = (SELECT id FROM `hg_admin_menu` WHERE `name` = 'content' LIMIT 1);
+
+INSERT INTO `hg_admin_menu`(`pid`, `level`, `tree`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `sort`, `remark`, `status`, `updated_at`, `created_at`) VALUES
+(@content_parent_id, 2, CONCAT('tr_', @content_parent_id, ' '), '轮播图管理', 'flashbanner', '/flashbanner', '', 2, '', '/flashbanner/banner/list', '', '/addons/flashbanner/index', 2, '', 2, 2, '', 1, 2, 2, 10, '轮播图管理模块', 1, NOW(), NOW());
+
+-- 添加子菜单和按钮
+SET @flashbanner_menu_id = LAST_INSERT_ID();
+
+INSERT INTO `hg_admin_menu`(`pid`, `level`, `tree`, `title`, `name`, `path`, `icon`, `type`, `redirect`, `permissions`, `permission_name`, `component`, `always_show`, `active_menu`, `is_root`, `is_frame`, `frame_src`, `keep_alive`, `hidden`, `affix`, `sort`, `remark`, `status`, `updated_at`, `created_at`) VALUES
+(@flashbanner_menu_id, 3, CONCAT('tr_', @content_parent_id, ' tr_', @flashbanner_menu_id, ' '), '新增轮播', 'addbanner', '', '', 3, '', '/flashbanner/banner/create', '', '', 2, '', 2, 2, '', 2, 2, 2, 10, '新增轮播图权限', 1, NOW(), NOW()),
+(@flashbanner_menu_id, 3, CONCAT('tr_', @content_parent_id, ' tr_', @flashbanner_menu_id, ' '), '轮播编辑', 'editbanner', '', '', 3, '', '/flashbanner/banner/update', '', '', 2, '', 2, 2, '', 2, 2, 2, 10, '编辑轮播图权限', 1, NOW(), NOW()),
+(@flashbanner_menu_id, 3, CONCAT('tr_', @content_parent_id, ' tr_', @flashbanner_menu_id, ' '), '删除轮播', 'delbanner', '', '', 3, '', '/flashbanner/banner/delete', '', '', 2, '', 2, 2, '', 2, 2, 2, 10, '删除轮播图权限', 1, NOW(), NOW());
\ No newline at end of file
diff --git a/server/addons/migrations/flashbanner/uninstall.pg.sql b/server/addons/migrations/flashbanner/uninstall.pg.sql
new file mode 100644
index 0000000..6101a82
--- /dev/null
+++ b/server/addons/migrations/flashbanner/uninstall.pg.sql
@@ -0,0 +1,9 @@
+-- 删除表
+DROP TABLE IF EXISTS hg_banner;
+
+-- 删除 flashbanner 相关菜单
+-- 先删除子菜单(权限按钮)
+DELETE FROM hg_admin_menu WHERE name IN ('addbanner', 'editbanner', 'delbanner');
+
+-- 删除主菜单
+DELETE FROM hg_admin_menu WHERE name = 'flashbanner';
\ No newline at end of file
diff --git a/server/addons/migrations/flashbanner/uninstall.sql b/server/addons/migrations/flashbanner/uninstall.sql
new file mode 100644
index 0000000..78d971a
--- /dev/null
+++ b/server/addons/migrations/flashbanner/uninstall.sql
@@ -0,0 +1,9 @@
+-- 删除表
+DROP TABLE IF EXISTS `hg_banner`;
+
+-- 删除 flashbanner 相关菜单
+-- 先删除子菜单(权限按钮)
+DELETE FROM `hg_admin_menu` WHERE `name` IN ('addbanner', 'editbanner', 'delbanner');
+
+-- 删除主菜单
+DELETE FROM `hg_admin_menu` WHERE `name` = 'flashbanner';
\ No newline at end of file
diff --git a/server/addons/migrations/readme.md b/server/addons/migrations/readme.md
new file mode 100644
index 0000000..e56eeb7
--- /dev/null
+++ b/server/addons/migrations/readme.md
@@ -0,0 +1,2 @@
+# 为了在容器映射sql所以需要独立出来
+# 兼容数据库和前端文件的迁移
\ No newline at end of file
diff --git a/server/addons/migrations/sqlDo.go b/server/addons/migrations/sqlDo.go
new file mode 100644
index 0000000..04f80b9
--- /dev/null
+++ b/server/addons/migrations/sqlDo.go
@@ -0,0 +1,66 @@
+package migrations
+
+import (
+ "context"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/container/gvar"
+)
+func DoSqlContent(ctx context.Context, sqlPath string) (string, error) {
+ open, err := os.Open(sqlPath)
+ if err != nil {
+ return "fail", err
+ }
+ defer open.Close()
+ sqlContent, err := io.ReadAll(open)
+ if err != nil {
+ return "fail", err
+ }
+
+ // 首先尝试整个执行
+ _, err = g.DB().Exec(ctx, string(sqlContent))
+ if err != nil {
+ g.Log().Error(ctx, "整个执行SQL失败,尝试分句执行:", err)
+
+ // 整个执行失败,尝试按分号分割执行
+ sqls := strings.Split(string(sqlContent), ";")
+ for _, sql := range sqls {
+ sql = strings.TrimSpace(sql)
+ if sql != "" {
+ _, err := g.DB().Exec(ctx, sql)
+ if err != nil {
+ g.Log().Error(ctx, "执行SQL失败:", err, sql)
+ return "fail", err
+ }
+ }
+ }
+ }
+ return "success", nil
+}
+
+func GetDbLink(ctx context.Context) *gvar.Var {
+ link := g.Cfg().MustGet(ctx, "database.default")
+ //读写分离
+ if !link.IsSlice() {
+ return g.Cfg().MustGet(ctx, "database.default.link")
+ }
+ for _, v := range link.Array() {
+ // 只获取主库
+ val := v.(map[string]interface{})
+ if val["role"] == "master" {
+ return gvar.New(val["link"])
+ }
+ }
+ return gvar.New("database.default.0.link")
+}
+
+func GetDbType(ctx context.Context) string {
+ var (
+ link = GetDbLink(ctx)
+ )
+ config := strings.SplitN(link.String(), ":", 2)
+ return config[0]
+}
\ No newline at end of file
diff --git a/server/addons/modules/flashbanner.go b/server/addons/modules/flashbanner.go
new file mode 100644
index 0000000..af8ef7d
--- /dev/null
+++ b/server/addons/modules/flashbanner.go
@@ -0,0 +1,8 @@
+// Package modules
+// @Link https://github.com/bufanyun/hotgo
+// @Copyright Copyright (c) 2023 HotGo CLI
+// @Author Ms <133814250@qq.com>
+// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
+package modules
+
+import _ "hotgo/addons/flashbanner"
diff --git a/server/internal/library/addons/build.go b/server/internal/library/addons/build.go
index 6fab466..fa95e0d 100644
--- a/server/internal/library/addons/build.go
+++ b/server/internal/library/addons/build.go
@@ -8,14 +8,15 @@ package addons
import (
"context"
"fmt"
- "github.com/gogf/gf/v2/errors/gerror"
- "github.com/gogf/gf/v2/os/gfile"
- "github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/consts"
"hotgo/internal/model"
"hotgo/utility/validate"
"strconv"
"strings"
+
+ "github.com/gogf/gf/v2/errors/gerror"
+ "github.com/gogf/gf/v2/os/gfile"
+ "github.com/gogf/gf/v2/text/gstr"
)
type BuildOption struct {
@@ -27,12 +28,14 @@ type BuildOption struct {
// Build 构建新插件
func Build(ctx context.Context, option *BuildOption) (err error) {
var (
- resourcePath = GetResourcePath(ctx)
- buildPath = "./" + consts.AddonsDir + "/" + option.Skeleton.Name
- modulesPath = "./" + consts.AddonsDir + "/modules/" + option.Skeleton.Name + ".go"
- webApiPath = gstr.Replace(option.Config.WebApiPath, "{$name}", option.Skeleton.Name)
- webViewsPath = gstr.Replace(option.Config.WebViewsPath, "{$name}", option.Skeleton.Name)
- replaces = map[string]string{
+ resourcePath = GetResourcePath(ctx)
+ buildPath = "./" + consts.AddonsDir + "/" + option.Skeleton.Name
+ modulesPath = "./" + consts.AddonsDir + "/modules/" + option.Skeleton.Name + ".go"
+ webApiPath = "./" + consts.AddonsDir + "/" + option.Skeleton.Name + "/web/src/api/addons/" + option.Skeleton.Name
+ webViewsPath = "./" + consts.AddonsDir + "/" + option.Skeleton.Name + "/web/src/views/addons/" + option.Skeleton.Name
+ webApiPathBase = gstr.Replace(option.Config.WebApiPath, "{$name}", option.Skeleton.Name)
+ webViewsPathBase = gstr.Replace(option.Config.WebViewsPath, "{$name}", option.Skeleton.Name)
+ replaces = map[string]string{
"@{.label}": option.Skeleton.Label,
"@{.name}": option.Skeleton.Name,
"@{.group}": strconv.Itoa(option.Skeleton.Group),
@@ -94,16 +97,36 @@ func Build(ctx context.Context, option *BuildOption) (err error) {
if err = gfile.PutContents(webApiPath+"/config/index.ts", gstr.ReplaceByMap(webApiLayout, replaces)); err != nil {
return
}
-
- // web插件配置主页面
- if err = gfile.PutContents(webViewsPath+"/config/BasicSetting.vue", gstr.ReplaceByMap(webConfigBasicSetting, replaces)); err != nil {
+ if err = gfile.PutContents(webApiPathBase+"/config/index.ts", gstr.ReplaceByMap(webApiLayout, replaces)); err != nil {
return
}
- // web插件基础配置页面
+ // web插件配置主页面 - 插件
+ if err = gfile.PutContents(webViewsPath+"/config/BasicSetting.vue", gstr.ReplaceByMap(webConfigBasicSetting, replaces)); err != nil {
+ return
+ }
+ // web插件基础配置页面 - 插件
if err = gfile.PutContents(webViewsPath+"/config/system.vue", gstr.ReplaceByMap(webConfigSystem, replaces)); err != nil {
return
}
+ // web插件配置主页面
+ if err = gfile.PutContents(webViewsPathBase+"/config/BasicSetting.vue", gstr.ReplaceByMap(webConfigBasicSetting, replaces)); err != nil {
+ return
+ }
+ // web插件基础配置页面
+ if err = gfile.PutContents(webViewsPathBase+"/config/system.vue", gstr.ReplaceByMap(webConfigSystem, replaces)); err != nil {
+ return
+ }
+
+ // 创建迁移文件
+ sqlPath := gfile.Pwd() + gfile.Separator + "addons/migrations/" + option.Skeleton.Name + "/install.sql"
+ sqlPathUn := gfile.Pwd() + gfile.Separator + "addons/migrations/" + option.Skeleton.Name + "/uninstall.sql"
+ if err = gfile.PutContents(sqlPath, ""); err != nil {
+ return
+ }
+ if err = gfile.PutContents(sqlPathUn, ""); err != nil {
+ return
+ }
// 创建静态目录
if validate.InSlice(option.Extend, consts.AddonsExtendResourcePublic) {
diff --git a/server/resource/generate/default/addon/README.MD.template b/server/resource/generate/default/addon/README.MD.template
index 6d9080b..ef42a17 100644
--- a/server/resource/generate/default/addon/README.MD.template
+++ b/server/resource/generate/default/addon/README.MD.template
@@ -37,3 +37,14 @@ import _ "hotgo/addons/@{.name}"
gf gen service -s=addons/@{.name}/logic -d=addons/@{.name}/service
```
+
+```shell
+# 插件迁移
+cp .\internal\dao\internal\@{.name}* .\addons\@{.name}\dao\internal\
+cp .\internal\model\entity\@{.name}* .\addons\@{.name}\model\entity\
+```
+
+### 插件开发
+ - 直接在后台新建插件
+ - 创建迁移脚本
+ - 开发工具->代码生成:自动生成前后端模块
\ No newline at end of file
diff --git a/server/resource/generate/default/addon/main.go.template b/server/resource/generate/default/addon/main.go.template
index 3bffaa9..088b508 100644
--- a/server/resource/generate/default/addon/main.go.template
+++ b/server/resource/generate/default/addon/main.go.template
@@ -14,9 +14,15 @@ import (
_ "hotgo/addons/@{.name}/logic"
_ "hotgo/addons/@{.name}/queues"
"hotgo/addons/@{.name}/router"
+ "hotgo/addons/migrations"
"hotgo/internal/library/addons"
"hotgo/internal/service"
"sync"
+
+ "github.com/gogf/gf/v2/frame/g"
+ "github.com/gogf/gf/v2/os/gfile"
+
+
)
type module struct {
@@ -77,9 +83,54 @@ func (m *module) GetSkeleton() *addons.Skeleton {
return m.skeleton
}
+
// Install 安装模块
func (m *module) Install(ctx context.Context) (err error) {
- // ...
+ sqlExt := ".sql"
+ if migrations.GetDbType(ctx) == "pgsql" {
+ sqlExt = ".pg.sql"
+ }
+ // 执行数据库安装文件
+ sqlPath := gfile.Pwd() + gfile.Separator + "addons/migrations/@{.name}/uninstall"+sqlExt
+ result, err := migrations.DoSqlContent(ctx, sqlPath)
+ if err != nil {
+ g.Log().Error(ctx, "安装模块", m.skeleton.Label, "失败", err)
+ return
+ }
+ g.Log().Debug(ctx, "安装模块", m.skeleton.Label, "成功", result)
+
+ // 复制web目录下的文件到管理后台对应位置
+ // 插件的前端配置文件位于插件目录下的web子目录
+ sourceWebPath := gfile.Pwd() + gfile.Separator + "addons/@{.name}/web/src/views/addons/@{.name}"
+ targetWebPath := "../web/src/views/addons/@{.name}"
+ g.Log().Debug(ctx, "复制前端配置文件", "源路径:", sourceWebPath, "目标路径:", targetWebPath)
+
+ // 检查源路径是否存在
+ if gfile.Exists(sourceWebPath) {
+ err = gfile.CopyDir(sourceWebPath, targetWebPath)
+ if err != nil {
+ g.Log().Error(ctx, "复制前端配置文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "复制前端配置文件成功")
+ }
+ } else {
+ g.Log().Warning(ctx, "前端配置文件源路径不存在:", sourceWebPath)
+ }
+
+ // 复制API文件
+ sourceApiPath := gfile.Pwd() + gfile.Separator + "addons/@{.name}/web/src/api/addons/@{.name}"
+ targetApiPath := "../web/src/api/addons/@{.name}"
+ g.Log().Debug(ctx, "复制API文件", "源路径:", sourceApiPath, "目标路径:", targetApiPath)
+ if gfile.Exists(sourceApiPath) {
+ err = gfile.CopyDir(sourceApiPath, targetApiPath)
+ if err != nil {
+ g.Log().Error(ctx, "复制API文件失败:", err)
+ } else {
+ g.Log().Debug(ctx, "复制API文件成功")
+ }
+ } else {
+ g.Log().Warning(ctx, "API文件源路径不存在:", sourceApiPath)
+ }
return
}
@@ -91,6 +142,17 @@ func (m *module) Upgrade(ctx context.Context) (err error) {
// UnInstall 卸载模块
func (m *module) UnInstall(ctx context.Context) (err error) {
- // ...
+ sqlExt := ".sql"
+ if migrations.GetDbType(ctx) == "pgsql" {
+ sqlExt = ".pg.sql"
+ }
+ // 移除数据库安装文件
+ sqlPath := gfile.Pwd() + gfile.Separator + "addons/migrations/@{.name}/uninstall" + sqlExt
+ result, err := migrations.DoSqlContent(ctx, sqlPath)
+ if err != nil {
+ g.Log().Error(ctx, "卸载模块", m.skeleton.Label, "失败", err)
+ return
+ }
+ g.Log().Debug(ctx, "卸载模块", m.skeleton.Label, "成功", result)
return
-}
+}
\ No newline at end of file