diff --git a/server/api/v1/system/sys_auto_code.go b/server/api/v1/system/sys_auto_code.go
index e3e1bbc70..34ab8c34b 100644
--- a/server/api/v1/system/sys_auto_code.go
+++ b/server/api/v1/system/sys_auto_code.go
@@ -262,7 +262,7 @@ func (autoApi *AutoCodeApi) AutoPlug(c *gin.Context) {
// @Produce application/json
// @Param plug formData file true "this is a test file"
// @Success 200 {object} response.Response{data=[]interface{},msg=string} "安装插件成功"
-// @Router /autoCode/createPlug [post]
+// @Router /autoCode/installPlugin [post]
func (autoApi *AutoCodeApi) InstallPlugin(c *gin.Context) {
header, err := c.FormFile("plug")
if err != nil {
@@ -292,3 +292,24 @@ func (autoApi *AutoCodeApi) InstallPlugin(c *gin.Context) {
"msg": serverStr,
}}, c)
}
+
+// PubPlug
+// @Tags AutoCode
+// @Summary 打包插件
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body system.SysAutoCode true "打包插件"
+// @Success 200 {object} response.Response{data=map[string]interface{},msg=string} "打包插件成功"
+// @Router /autoCode/pubPlug [get]
+func (autoApi *AutoCodeApi) PubPlug(c *gin.Context) {
+ plugName := c.Query("plugName")
+ snake := strings.ToLower(plugName)
+ zipPath, err := autoCodeService.PubPlug(snake)
+ if err != nil {
+ global.GVA_LOG.Error("打包失败!", zap.Error(err))
+ response.FailWithMessage("打包失败"+err.Error(), c)
+ return
+ }
+ response.OkWithMessage(fmt.Sprintf("打包成功,文件路径为:%s", zipPath), c)
+}
diff --git a/server/initialize/ensure_tables.go b/server/initialize/ensure_tables.go
index a2eb3200b..720505296 100644
--- a/server/initialize/ensure_tables.go
+++ b/server/initialize/ensure_tables.go
@@ -48,6 +48,7 @@ func (e *ensureTables) MigrateTable(ctx context.Context) (context.Context, error
sysModel.SysBaseMenuBtn{},
sysModel.SysAuthorityBtn{},
sysModel.SysAutoCode{},
+ sysModel.SysChatGptOption{},
adapter.CasbinRule{},
@@ -83,7 +84,7 @@ func (e *ensureTables) TableCreated(ctx context.Context) bool {
sysModel.SysBaseMenuBtn{},
sysModel.SysAuthorityBtn{},
sysModel.SysAutoCode{},
-
+ sysModel.SysChatGptOption{},
adapter.CasbinRule{},
example.ExaFile{},
diff --git a/server/router/system/sys_auto_code.go b/server/router/system/sys_auto_code.go
index b9ddf0a1e..4f23a1d13 100644
--- a/server/router/system/sys_auto_code.go
+++ b/server/router/system/sys_auto_code.go
@@ -21,5 +21,6 @@ func (s *AutoCodeRouter) InitAutoCodeRouter(Router *gin.RouterGroup) {
autoCodeRouter.POST("delPackage", autoCodeApi.DelPackage) // 删除package包
autoCodeRouter.POST("createPlug", autoCodeApi.AutoPlug) // 自动插件包模板
autoCodeRouter.POST("installPlugin", autoCodeApi.InstallPlugin) // 自动安装插件
+ autoCodeRouter.POST("pubPlug", autoCodeApi.PubPlug) // 打包插件
}
}
diff --git a/server/service/system/sys_auto_code.go b/server/service/system/sys_auto_code.go
index 1e71e3f57..7b249960c 100644
--- a/server/service/system/sys_auto_code.go
+++ b/server/service/system/sys_auto_code.go
@@ -1,6 +1,7 @@
package system
import (
+ "archive/zip"
"encoding/json"
"errors"
"fmt"
@@ -780,3 +781,126 @@ func skipMacSpecialDocument(src string) (bool, error) {
}
return false, nil
}
+
+func (autoCodeService *AutoCodeService) PubPlug(plugName string) (zipPath string, err error) {
+ if plugName == "" {
+ return "", errors.New("插件名称不能为空")
+ }
+
+ // 防止路径穿越
+ plugName = filepath.Clean(plugName)
+
+ webPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Web, "plugin", plugName)
+ serverPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", plugName)
+ // 创建一个新的zip文件
+
+ // 判断目录是否存在
+ _, err = os.Stat(webPath)
+ if err != nil {
+ return "", errors.New("web路径不存在")
+ }
+ _, err = os.Stat(serverPath)
+ if err != nil {
+ return "", errors.New("server路径不存在")
+ }
+
+ fileName := plugName + ".zip"
+ // 创建一个新的zip文件
+ zipFile, err := os.Create(fileName)
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ defer zipFile.Close()
+
+ // 创建一个zip写入器
+ zipWriter := zip.NewWriter(zipFile)
+ defer zipWriter.Close()
+
+ // 遍历webPath目录并将所有非隐藏文件添加到zip归档中
+ err = filepath.Walk(webPath, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ // 跳过隐藏文件和目录
+ if strings.HasPrefix(info.Name(), ".") || info.IsDir() {
+ return nil
+ }
+
+ // 创建一个新的文件头
+ header, err := zip.FileInfoHeader(info)
+ if err != nil {
+ return err
+ }
+
+ // 将文件头的名称设置为文件的相对路径
+ rel, _ := filepath.Rel(webPath, path)
+ header.Name = filepath.Join(plugName, "web", "plugin", plugName, rel)
+
+ // 将文件添加到zip归档中
+ writer, err := zipWriter.CreateHeader(header)
+ if err != nil {
+ return err
+ }
+
+ // 打开文件并将其内容复制到zip归档中
+ file, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ _, err = io.Copy(writer, file)
+ if err != nil {
+ return err
+ }
+ return nil
+ })
+ if err != nil {
+ return
+ }
+
+ // 遍历serverPath目录并将所有非隐藏文件添加到zip归档中
+ err = filepath.Walk(serverPath, func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ // 跳过隐藏文件和目录
+ if strings.HasPrefix(info.Name(), ".") || info.IsDir() {
+ return nil
+ }
+
+ // 创建一个新的文件头
+ header, err := zip.FileInfoHeader(info)
+ if err != nil {
+ return err
+ }
+
+ // 将文件头的名称设置为文件的相对路径
+ rel, _ := filepath.Rel(serverPath, path)
+ header.Name = filepath.Join(plugName, "server", "plugin", plugName, rel)
+ // 将文件添加到zip归档中
+ writer, err := zipWriter.CreateHeader(header)
+ if err != nil {
+ return err
+ }
+
+ // 打开文件并将其内容复制到zip归档中
+ file, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer file.Close()
+ _, err = io.Copy(writer, file)
+ if err != nil {
+ return err
+ }
+
+ return nil
+ })
+ if err != nil {
+ return
+ }
+ return filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, fileName), nil
+}
diff --git a/server/source/system/api.go b/server/source/system/api.go
index a5a85789c..5db056aca 100644
--- a/server/source/system/api.go
+++ b/server/source/system/api.go
@@ -111,6 +111,7 @@ func (i *initApi) InitializeData(ctx context.Context) (context.Context, error) {
{ApiGroup: "代码生成器", Method: "GET", Path: "/autoCode/getColumn", Description: "获取所选table的所有字段"},
{ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/createPlug", Description: "自动创建插件包"},
{ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/installPlugin", Description: "安装插件"},
+ {ApiGroup: "代码生成器", Method: "POST", Path: "/autoCode/pubPlug", Description: "打包插件"},
{ApiGroup: "包(pkg)生成器", Method: "POST", Path: "/autoCode/createPackage", Description: "生成包(package)"},
{ApiGroup: "包(pkg)生成器", Method: "POST", Path: "/autoCode/getPackage", Description: "获取所有包(package)"},
diff --git a/server/source/system/casbin.go b/server/source/system/casbin.go
index bcb744731..7626d6bd2 100644
--- a/server/source/system/casbin.go
+++ b/server/source/system/casbin.go
@@ -121,6 +121,7 @@ func (i *initCasbin) InitializeData(ctx context.Context) (context.Context, error
{Ptype: "p", V0: "888", V1: "/autoCode/delPackage", V2: "POST"},
{Ptype: "p", V0: "888", V1: "/autoCode/createPlug", V2: "POST"},
{Ptype: "p", V0: "888", V1: "/autoCode/installPlugin", V2: "POST"},
+ {Ptype: "p", V0: "888", V1: "/autoCode/pubPlug", V2: "POST"},
{Ptype: "p", V0: "888", V1: "/sysDictionaryDetail/findSysDictionaryDetail", V2: "GET"},
{Ptype: "p", V0: "888", V1: "/sysDictionaryDetail/updateSysDictionaryDetail", V2: "PUT"},
diff --git a/server/source/system/menu.go b/server/source/system/menu.go
index 1d87bffdc..bd55178d4 100644
--- a/server/source/system/menu.go
+++ b/server/source/system/menu.go
@@ -78,7 +78,8 @@ func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, er
{MenuLevel: 0, Hidden: false, ParentId: "25", Path: "https://plugin.gin-vue-admin.com/", Name: "https://plugin.gin-vue-admin.com/", Component: "https://plugin.gin-vue-admin.com/", Sort: 0, Meta: Meta{Title: "插件市场", Icon: "shop"}},
{MenuLevel: 0, Hidden: false, ParentId: "25", Path: "installPlugin", Name: "installPlugin", Component: "view/systemTools/installPlugin/index.vue", Sort: 1, Meta: Meta{Title: "插件安装", Icon: "box"}},
{MenuLevel: 0, Hidden: false, ParentId: "25", Path: "autoPlug", Name: "autoPlug", Component: "view/systemTools/autoPlug/autoPlug.vue", Sort: 2, Meta: Meta{Title: "插件模板", Icon: "folder"}},
- {MenuLevel: 0, Hidden: false, ParentId: "25", Path: "plugin-email", Name: "plugin-email", Component: "plugin/email/view/index.vue", Sort: 3, Meta: Meta{Title: "邮件插件", Icon: "message"}},
+ {MenuLevel: 0, Hidden: false, ParentId: "25", Path: "pubPlug", Name: "pubPlug", Component: "view/systemTools/pubPlug/pubPlug.vue", Sort: 3, Meta: Meta{Title: "打包插件", Icon: "files"}},
+ {MenuLevel: 0, Hidden: false, ParentId: "25", Path: "plugin-email", Name: "plugin-email", Component: "plugin/email/view/index.vue", Sort: 4, Meta: Meta{Title: "邮件插件", Icon: "message"}},
{MenuLevel: 0, Hidden: false, ParentId: "16", Path: "chatTable", Name: "chatTable", Component: "view/chatgpt/chatTable.vue", Sort: 6, Meta: Meta{Title: "万用表格", Icon: "chat-dot-square"}},
}
if err = db.Create(&entities).Error; err != nil {
diff --git a/web/src/api/autoCode.js b/web/src/api/autoCode.js
index 08f456a37..abf1924e0 100644
--- a/web/src/api/autoCode.js
+++ b/web/src/api/autoCode.js
@@ -132,3 +132,11 @@ export const installPlug = (data) => {
data
})
}
+
+export const pubPlug = (params) => {
+ return service({
+ url: '/autoCode/pubPlug',
+ method: 'post',
+ params
+ })
+}
diff --git a/web/src/view/systemTools/pubPlug/pubPlug.vue b/web/src/view/systemTools/pubPlug/pubPlug.vue
new file mode 100644
index 000000000..3c8091aaf
--- /dev/null
+++ b/web/src/view/systemTools/pubPlug/pubPlug.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+