diff --git a/internal/controllers/env_controller.go b/internal/controllers/env_controller.go index 1d4dd9d..47692d8 100644 --- a/internal/controllers/env_controller.go +++ b/internal/controllers/env_controller.go @@ -18,6 +18,15 @@ func NewEnvController(envService *services.EnvService) *EnvController { } // CreateEnvVar 创建环境变量 +// @Summary 创建环境变量 +// @Description 创建一个新的环境变量 +// @Tags 环境变量 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param body body object true "环境变量信息" +// @Success 200 {object} utils.Response{data=vo.EnvVO} +// @Router /env [post] func (ec *EnvController) CreateEnvVar(c *gin.Context) { userID := c.GetString("userID") @@ -105,6 +114,17 @@ func (ec *EnvController) GetEnvVar(c *gin.Context) { } // UpdateEnvVar 更新环境变量 +// @Summary 更新环境变量 +// @Description 根据 ID 更新环境变量信息 +// @Tags 环境变量 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "环境变量ID" +// @Param body body object true "环境变量更新信息" +// @Success 200 {object} utils.Response{data=vo.EnvVO} +// @Failure 404 {object} utils.Response +// @Router /env/{id} [put] func (ec *EnvController) UpdateEnvVar(c *gin.Context) { id := c.Param("id") if id == "" { @@ -145,6 +165,18 @@ func (ec *EnvController) UpdateEnvVar(c *gin.Context) { } // DeleteEnvVar 删除环境变量 +// @Summary 删除环境变量 +// @Description 根据 ID 删除环境变量 +// @Tags 环境变量 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "环境变量ID" +// @Param force query boolean false "强制删除(忽略任务关联)" +// @Success 200 {object} utils.Response +// @Failure 404 {object} utils.Response +// @Failure 409 {object} utils.Response{data=[]vo.TaskVO} +// @Router /env/{id} [delete] func (ec *EnvController) DeleteEnvVar(c *gin.Context) { id := c.Param("id") if id == "" { diff --git a/internal/controllers/script_controller.go b/internal/controllers/script_controller.go index 4138e87..dc1e5fb 100644 --- a/internal/controllers/script_controller.go +++ b/internal/controllers/script_controller.go @@ -17,6 +17,16 @@ func NewScriptController(scriptService *services.ScriptService) *ScriptControlle return &ScriptController{scriptService: scriptService} } +// CreateScript 创建脚本 +// @Summary 创建脚本 +// @Description 创建一个新的脚本 +// @Tags 脚本管理 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param body body object true "脚本信息" +// @Success 200 {object} utils.Response{data=vo.ScriptVO} +// @Router /scripts [post] func (sc *ScriptController) CreateScript(c *gin.Context) { userID := c.GetString("userID") @@ -34,6 +44,15 @@ func (sc *ScriptController) CreateScript(c *gin.Context) { utils.Success(c, vo.ToScriptVO(script)) } +// GetScripts 获取脚本列表 +// @Summary 获取脚本列表 +// @Description 获取当前用户的所有脚本(内容字段为空) +// @Tags 脚本管理 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Success 200 {object} utils.Response{data=[]vo.ScriptVO} +// @Router /scripts [get] func (sc *ScriptController) GetScripts(c *gin.Context) { userID := c.GetString("userID") scripts := sc.scriptService.GetScriptsByUserID(userID) @@ -44,6 +63,17 @@ func (sc *ScriptController) GetScripts(c *gin.Context) { utils.Success(c, vos) } +// GetScript 获取脚本详情 +// @Summary 获取脚本详情 +// @Description 根据 ID 获取脚本详情 +// @Tags 脚本管理 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "脚本ID" +// @Success 200 {object} utils.Response{data=vo.ScriptVO} +// @Failure 404 {object} utils.Response +// @Router /scripts/{id} [get] func (sc *ScriptController) GetScript(c *gin.Context) { id := c.Param("id") if id == "" { @@ -60,6 +90,18 @@ func (sc *ScriptController) GetScript(c *gin.Context) { utils.Success(c, vo.ToScriptVO(script)) } +// UpdateScript 更新脚本 +// @Summary 更新脚本 +// @Description 根据 ID 更新脚本信息 +// @Tags 脚本管理 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "脚本ID" +// @Param body body object true "脚本更新信息" +// @Success 200 {object} utils.Response{data=vo.ScriptVO} +// @Failure 404 {object} utils.Response +// @Router /scripts/{id} [put] func (sc *ScriptController) UpdateScript(c *gin.Context) { id := c.Param("id") if id == "" { @@ -86,6 +128,17 @@ func (sc *ScriptController) UpdateScript(c *gin.Context) { utils.Success(c, vo.ToScriptVO(script)) } +// DeleteScript 删除脚本 +// @Summary 删除脚本 +// @Description 根据 ID 删除脚本 +// @Tags 脚本管理 +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path string true "脚本ID" +// @Success 200 {object} utils.Response +// @Failure 404 {object} utils.Response +// @Router /scripts/{id} [delete] func (sc *ScriptController) DeleteScript(c *gin.Context) { id := c.Param("id") if id == "" { diff --git a/internal/router/openapi.go b/internal/router/openapi.go index 86e7b67..fdaece5 100644 --- a/internal/router/openapi.go +++ b/internal/router/openapi.go @@ -16,6 +16,8 @@ func initOpenAPIV1Routes(root *gin.RouterGroup, c *Controllers) { registerOpenAPITaskRoutes(open, c) // 环境变量相关接口 registerOpenAPIEnvRoutes(open, c) + // 脚本相关接口 + registerOpenAPIScriptRoutes(open, c) // 日志相关接口 registerOpenAPILogRoutes(open, c) // 任务执行相关接口 @@ -39,10 +41,13 @@ func registerOpenAPITaskRoutes(g *gin.RouterGroup, c *Controllers) { func registerOpenAPIEnvRoutes(g *gin.RouterGroup, c *Controllers) { env := g.Group("/env") { + env.POST("", c.Env.CreateEnvVar) env.GET("", c.Env.GetEnvVars) env.GET("/all", c.Env.GetAllEnvVars) env.GET("/:id", c.Env.GetEnvVar) env.GET("/:id/tasks", c.Env.GetAssociatedTasks) + env.PUT("/:id", c.Env.UpdateEnvVar) + env.DELETE("/:id", c.Env.DeleteEnvVar) } } @@ -63,3 +68,15 @@ func registerOpenAPIExecutorRoutes(g *gin.RouterGroup, c *Controllers) { execution.GET("/results", c.Executor.GetLastResults) } } + +// registerOpenAPIScriptRoutes 注册 OpenAPI 脚本路由 +func registerOpenAPIScriptRoutes(g *gin.RouterGroup, c *Controllers) { + scripts := g.Group("/scripts") + { + scripts.POST("", c.Script.CreateScript) + scripts.GET("", c.Script.GetScripts) + scripts.GET("/:id", c.Script.GetScript) + scripts.PUT("/:id", c.Script.UpdateScript) + scripts.DELETE("/:id", c.Script.DeleteScript) + } +} diff --git a/web/src/main.ts b/web/src/main.ts index 1ea9bed..5a04f2c 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -10,11 +10,13 @@ window.addEventListener('vite:preloadError', () => { window.location.reload() }) +const BASE_URL = (window as any).__BASE_URL__ || '' + createApp(App) .use(router) .use(VueMonacoEditorPlugin, { paths: { - vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.52.0/min/vs' + vs: BASE_URL + '/vs' } }) .mount('#app') diff --git a/web/src/views/editor/Editor.vue b/web/src/views/editor/Editor.vue index 4c73307..ac6ba7e 100644 --- a/web/src/views/editor/Editor.vue +++ b/web/src/views/editor/Editor.vue @@ -97,7 +97,7 @@ function getLangIcon(plugin: string) { 'kubernetes': 'kubernetes/kubernetes-plain.svg', 'ansible': 'ansible/ansible-original.svg', } - return mapping[name] ? `https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` : '' + return mapping[name] ? `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` : '' } async function fetchPaths() { diff --git a/web/src/views/languages/Languages.vue b/web/src/views/languages/Languages.vue index 37e2663..049b71c 100644 --- a/web/src/views/languages/Languages.vue +++ b/web/src/views/languages/Languages.vue @@ -229,7 +229,7 @@ function getLangIcon(plugin: string) { } if (mapping[name]) { - return `https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` + return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` } return '' } diff --git a/web/src/views/tasks/TaskDialog.vue b/web/src/views/tasks/TaskDialog.vue index 238c1c4..2348f7e 100644 --- a/web/src/views/tasks/TaskDialog.vue +++ b/web/src/views/tasks/TaskDialog.vue @@ -184,7 +184,7 @@ function getLangIcon(plugin: string) { } if (mapping[name]) { - return `https://cdn.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` + return `https://fastly.jsdelivr.net/gh/devicons/devicon/icons/${mapping[name]}` } return '' } diff --git a/web/vite.config.ts b/web/vite.config.ts index c080d5f..7c6432c 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -1,10 +1,22 @@ import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import tailwindcss from '@tailwindcss/vite' +import { viteStaticCopy } from 'vite-plugin-static-copy' import { fileURLToPath, URL } from 'node:url' export default defineConfig({ - plugins: [vue(), tailwindcss()], + plugins: [ + vue(), + tailwindcss(), + viteStaticCopy({ + targets: [ + { + src: 'node_modules/monaco-editor/min/vs', + dest: '.' + } + ] + }) + ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url))