From 21251c6e0784ad2952807d362bd5643c51020af5 Mon Sep 17 00:00:00 2001 From: zhilv Date: Fri, 27 Mar 2026 18:39:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=89=8D=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E6=89=93=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- Taskfile.yml | 139 ++++++++++++++++++++++++++++++++++++++ cmd/{agent => }/main.go | 0 cmd/server/main.go | 5 -- internal/conf/var.go | 12 ++++ internal/router/router.go | 42 +++++++++++- web/.gitignore | 1 + web/web.go | 8 +++ 8 files changed, 201 insertions(+), 8 deletions(-) create mode 100644 Taskfile.yml rename cmd/{agent => }/main.go (100%) delete mode 100644 cmd/server/main.go create mode 100644 internal/conf/var.go create mode 100644 web/web.go diff --git a/.gitignore b/.gitignore index e6d928d..ba077a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -Taskfile.yml +bin diff --git a/Taskfile.yml b/Taskfile.yml new file mode 100644 index 0000000..19840ae --- /dev/null +++ b/Taskfile.yml @@ -0,0 +1,139 @@ +version: "3" + +vars: + FRONTEND_DIR: web/frontend + BIN_DIR: bin + SERVER_NAME: server + + # --- 全局 Git 信息 (关键修复:放这里才能被所有子任务读取) --- + GIT_AUTHOR: zhilv666 + GIT_EMAIL: zhilv666@qq.com + VERSION: + sh: git describe --tags --always --dirty 2>/dev/null || echo "dev" + BUILD_TIME: + sh: date '+%Y-%m-%d %H:%M:%S' + GIT_COMMIT: + sh: git rev-parse --short HEAD 2>/dev/null || echo "unknown" + + # --- 全局注入参数 (关键修复) --- + LDFLAGS: >- + -s -w + -X "ckwk/internal/conf.Version={{.VERSION}}" + -X "ckwk/internal/conf.BuildAt={{.BUILD_TIME}}" + -X "ckwk/internal/conf.GitAuthor={{.GIT_AUTHOR}}" + -X "ckwk/internal/conf.GitEmail={{.GIT_EMAIL}}" + -X "ckwk/internal/conf.GitCommit={{.GIT_COMMIT}}" + +tasks: + # ====================== + # 🎨 前端 + # ====================== + + fe:install: + desc: 安装前端依赖 📦 + dir: "{{.FRONTEND_DIR}}" + cmds: + - pnpm install + + fe:dev: + desc: 启动前端开发服务器 🚀 + dir: "{{.FRONTEND_DIR}}" + cmds: + - pnpm dev + + fe:build: + desc: 构建前端 🏗️ + dir: "{{.FRONTEND_DIR}}" + cmds: + - pnpm build + + fe:clean: + desc: 清理前端构建产物 🧹 + dir: "{{.FRONTEND_DIR}}" + cmds: + - rm -rf dist + + # ====================== + # ⚙️ 后端 + # ====================== + + be:run: + desc: 启动后端服务 🧠 + cmds: + - go run ./cmd + + be:build: + desc: 构建后端二进制 🔨 + cmds: + - mkdir -p {{.BIN_DIR}} + - go build -o {{.BIN_DIR}}/{{.SERVER_NAME}} ./cmd + + # ====================== + # 🔄 开发 / 构建流程 + # ====================== + + dev: + desc: 同时启动前后端(开发模式)🔥 + cmds: + - task fe:dev & + - task be:run + + dev:be: + desc: 只启动后端(配合前端 dev)⚡ + cmds: + - go run ./cmd + + build: + desc: 构建前端 + 后端 📦 + cmds: + - task fe:build + - task be:build + + rebuild: + desc: 清理并重建 🔁 + cmds: + - task fe:clean + - task build + + # ====================== + # 🚀 生产构建 + # ====================== + + release: + desc: 构建多平台二进制 🌍 + vars: + MODE: -X "ckwk/internal/conf.Mode=release" + cmds: + - task fe:build + - mkdir -p {{.BIN_DIR}} + + # 🐧 Linux + - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '{{.LDFLAGS}} {{.MODE}}' -o {{.BIN_DIR}}/{{.SERVER_NAME}}-linux-amd64 ./cmd + + # 🪟 Windows + - CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '{{.LDFLAGS}} {{.MODE}}' -o {{.BIN_DIR}}/{{.SERVER_NAME}}-windows-amd64.exe ./cmd + + # --- 压缩任务 (优化版) --- + upx: + desc: "压缩二进制文件 (智能跳过 macOS 和 Windows ARM)" + cmds: + - echo "* 开始压缩处理..." + - | + if ! command -v upx > /dev/null 2>&1; then + echo "⚠️ 未找到 UPX,跳过压缩。" + exit 0 + fi + + for file in {{.BIN_DIR}}/*; do + [ -f "$file" ] || continue + + if [[ "$file" == *"darwin"* ]]; then + echo "* [SKIP] 跳过 macOS: $(basename $file)" + elif [[ "$file" == *"windows_arm"* ]]; then + echo "* [SKIP] 跳过 Win ARM: $(basename $file)" + else + echo "* [UPX] 压缩: $(basename $file)" + upx --best --lzma "$file" >/dev/null 2>&1 || echo " ⚠️ 失败: $file" + fi + done + silent: true diff --git a/cmd/agent/main.go b/cmd/main.go similarity index 100% rename from cmd/agent/main.go rename to cmd/main.go diff --git a/cmd/server/main.go b/cmd/server/main.go deleted file mode 100644 index 7905807..0000000 --- a/cmd/server/main.go +++ /dev/null @@ -1,5 +0,0 @@ -package main - -func main() { - -} diff --git a/internal/conf/var.go b/internal/conf/var.go new file mode 100644 index 0000000..99b5369 --- /dev/null +++ b/internal/conf/var.go @@ -0,0 +1,12 @@ +package conf + +// 构建信息 +var ( + Mode string = "debug" + + Version string = "unknown" + BuildAt string = "unknown" + GitAuthor string = "unknown" + GitEmail string = "unknown" + GitCommit string = "unknown" +) diff --git a/internal/router/router.go b/internal/router/router.go index b7cc283..c0763e3 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -1,16 +1,27 @@ package router import ( + "ckwk/internal/conf" "ckwk/internal/handler" "ckwk/internal/middleware" - "ckwk/internal/schedule" + "ckwk/pkg/log" + "ckwk/web" + "io/fs" + "net/http" + "strings" "time" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" + "go.uber.org/zap" ) func SetupRouter() *gin.Engine { + if conf.Mode != gin.ReleaseMode { + gin.SetMode(gin.DebugMode) + } else { + gin.SetMode(gin.ReleaseMode) + } r := gin.Default() r.Use(cors.New(cors.Config{ AllowOrigins: []string{"*://*", "http://localhost:5173"}, @@ -22,7 +33,16 @@ func SetupRouter() *gin.Engine { })) wkHandler := handler.NewWKHandler() sessionMiddleware := middleware.SessionMiddleware(wkHandler.Session) - schedule.StartCron(wkHandler.Session) + // schedule.StartCron(wkHandler.Session) + + dist, err := fs.Sub(web.Public, web.DistDir) + if err != nil { + log.Fatal("failed to read dist dir", zap.Error(err)) + } + distHTTP := http.FS(dist) + r.StaticFS("/js", http.FS(mustSub(dist, "js"))) + r.StaticFS("/assets", http.FS(mustSub(dist, "assets"))) + r.StaticFileFS("/favicon.ico", "favicon.ico", distHTTP) api := r.Group("/api") { @@ -40,5 +60,23 @@ func SetupRouter() *gin.Engine { } } + r.NoRoute(func(ctx *gin.Context) { + if strings.HasPrefix(ctx.Request.URL.Path, "/api") { + ctx.JSON(404, gin.H{"code": 404, "msg": "API not found"}) + return + } + ctx.Header("Content-Type", "text/html; charset=utf-8") + http.ServeFileFS(ctx.Writer, ctx.Request, dist, "index.html") + }) + return r } + +// 辅助函数:简化 fs.Sub 的错误处理 +func mustSub(f fs.FS, dir string) fs.FS { + sub, err := fs.Sub(f, dir) + if err != nil { + panic("failed to find static dir: " + dir) + } + return sub +} diff --git a/web/.gitignore b/web/.gitignore index 1097e68..12a9d21 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1 +1,2 @@ frontend +dist diff --git a/web/web.go b/web/web.go new file mode 100644 index 0000000..c8519a2 --- /dev/null +++ b/web/web.go @@ -0,0 +1,8 @@ +package web + +import "embed" + +const DistDir = "frontend/dist" + +//go:embed all:frontend/dist +var Public embed.FS