diff --git a/doc/changes/showcase-dashboard.md b/doc/changes/showcase-dashboard.md
new file mode 100644
index 0000000..94ac8d0
--- /dev/null
+++ b/doc/changes/showcase-dashboard.md
@@ -0,0 +1,39 @@
+# 变更说明:Showcase Dashboard 交互式展示页
+
+## 概述
+
+新增 GitLink CLI Showcase Dashboard —— 一个基于 Go + HTML 的 Web 展示面板,展示 gitlink-cli 的模块功能,支持在线执行命令并查看结果。
+
+## 功能
+
+- **12 个模块卡片**:milestone、webhook、label、commit、wiki、file、member、watch、star、issue 批量操作、repo 批量操作、org 批量操作
+- **在线执行**:每个卡片可输入参数,点击执行按钮直接调用 gitlink-cli 命令
+- **实时输出**:命令结果以 JSON/表格形式展示在页面上
+- **Docker 部署**:提供 Dockerfile,一键容器化部署
+
+## 文件说明
+
+| 文件 | 说明 |
+|------|------|
+| `showcase/main.go` | Go HTTP 服务器,提供 `/api/run` 接口执行 CLI 命令 |
+| `showcase/index.html` | 前端页面,暗色主题,12 个模块卡片 |
+| `showcase/Dockerfile` | 多阶段构建,基于 golang:1.26 镜像 |
+| `showcase/deploy.sh` | 部署脚本 |
+| `showcase/pipeline.yml` | GitLink DevOps 流水线配置 |
+
+## 访问方式
+
+```bash
+# 本地运行
+cd showcase && go run main.go
+# 访问 http://localhost:9090
+
+# Docker 部署
+docker build -t gitlink-cli-showcase ./showcase
+docker run -p 9090:9090 -e GITLINK_TOKEN=xxx gitlink-cli-showcase
+```
+
+## 注意事项
+
+- 需要预编译 `gitlink-cli` 二进制文件放在同目录
+- 服务器环境需配置 `GITLINK_TOKEN` 环境变量
diff --git a/showcase/Dockerfile b/showcase/Dockerfile
new file mode 100644
index 0000000..8a24528
--- /dev/null
+++ b/showcase/Dockerfile
@@ -0,0 +1,30 @@
+# Stage 1: Build
+FROM golang:1.26-alpine AS builder
+
+ENV GOPROXY=https://goproxy.cn,direct
+
+WORKDIR /build
+COPY go.mod go.sum ./
+RUN go mod download
+
+COPY . .
+
+# Build gitlink-cli binary
+RUN CGO_ENABLED=0 GOOS=linux go build -o gitlink-cli .
+
+# Build showcase server binary
+RUN CGO_ENABLED=0 GOOS=linux go build -o showcase-server ./showcase/
+
+# Stage 2: Runtime
+FROM alpine:latest
+
+RUN apk add --no-cache ca-certificates git
+
+WORKDIR /app
+
+COPY --from=builder /build/gitlink-cli .
+COPY --from=builder /build/showcase-server .
+
+EXPOSE 9090
+
+CMD ["./showcase-server"]
diff --git a/showcase/deploy.sh b/showcase/deploy.sh
new file mode 100644
index 0000000..a63ddb9
--- /dev/null
+++ b/showcase/deploy.sh
@@ -0,0 +1,14 @@
+# 展示页部署命令(在本地终端手动执行)
+
+# 1. 用 SCP 上传展示页到 ECS(需要手动输入密码:pd1@YwC#WRFVHkXc8nvu!4)
+scp "d:/自用/self/word/大三下/软件演化/gitlink-cli/showcase/index.html" root@121.41.210.165:/opt/showcase/index.html
+
+# 2. SSH 到 ECS(密码:pd1@YwC#WRFVHkXc8nvu!4)
+ssh root@121.41.210.165
+
+# 登录后在 ECS 上执行:
+mkdir -p /opt/showcase
+docker run -d --name showcase -p 8080:80 -v /opt/showcase:/usr/share/nginx/html:ro --restart unless-stopped nginx:alpine
+
+# 3. 访问
+# 浏览器打开 http://121.41.210.165:8080
diff --git a/showcase/index.html b/showcase/index.html
new file mode 100644
index 0000000..9eedabc
--- /dev/null
+++ b/showcase/index.html
@@ -0,0 +1,417 @@
+
+
+
+
+
+ gitlink-cli 功能增强展示
+
+
+
+
+
+
+
+
+
+
diff --git a/showcase/main.go b/showcase/main.go
new file mode 100644
index 0000000..1d13340
--- /dev/null
+++ b/showcase/main.go
@@ -0,0 +1,149 @@
+package main
+
+import (
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+)
+
+//go:embed index.html
+var indexHTML []byte
+
+type RunResult struct {
+ OK bool `json:"ok"`
+ Command string `json:"command"`
+ Output interface{} `json:"output"`
+ Error string `json:"error,omitempty"`
+}
+
+func main() {
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "9090"
+ }
+ cliBin := findCLIBinary()
+
+ http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.Write(indexHTML)
+ })
+
+ http.HandleFunc("/api/run", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json; charset=utf-8")
+
+ module := r.URL.Query().Get("module")
+ command := r.URL.Query().Get("command")
+ owner := r.URL.Query().Get("owner")
+ repo := r.URL.Query().Get("repo")
+ format := r.URL.Query().Get("format")
+ extraArgs := r.URL.Query().Get("args")
+
+ if module == "" || command == "" {
+ json.NewEncoder(w).Encode(RunResult{Error: "missing module or command"})
+ return
+ }
+ if owner == "" {
+ owner = "chroe"
+ }
+ if repo == "" {
+ if module == "wiki" {
+ repo = "gitlink_help_center"
+ } else {
+ repo = "gitlink-cli"
+ }
+ }
+ if format == "" {
+ format = "json"
+ }
+
+ args := []string{module, "+" + command, "--owner", owner, "--repo", repo, "--format", format}
+ if extraArgs != "" {
+ args = append(args, parseShellArgs(extraArgs)...)
+ }
+
+ cmdStr := "gitlink-cli " + strings.Join(args, " ")
+ log.Printf("Running: %s", cmdStr)
+
+ cmd := exec.Command(cliBin, args...)
+ output, err := cmd.CombinedOutput()
+
+ result := RunResult{
+ Command: cmdStr,
+ }
+
+ if err != nil {
+ result.Error = strings.TrimSpace(string(output))
+ result.Output = nil
+ } else {
+ result.OK = true
+ var parsed interface{}
+ if json.Unmarshal(output, &parsed) == nil {
+ result.Output = parsed
+ } else {
+ result.Output = strings.TrimSpace(string(output))
+ }
+ }
+
+ json.NewEncoder(w).Encode(result)
+ })
+
+ fmt.Printf("Showcase Dashboard running at http://localhost:%s\n", port)
+ log.Fatal(http.ListenAndServe(":"+port, nil))
+}
+
+// parseShellArgs splits a shell-style argument string, respecting quoted values.
+// e.g. `--content "Hello Wiki!" --message "create page"` -> ["--content", "Hello Wiki!", "--message", "create page"]
+func parseShellArgs(s string) []string {
+ var args []string
+ var current strings.Builder
+ inQuote := false
+
+ for i := 0; i < len(s); i++ {
+ ch := s[i]
+ if ch == '"' {
+ inQuote = !inQuote
+ continue
+ }
+ if ch == ' ' && !inQuote {
+ if current.Len() > 0 {
+ args = append(args, current.String())
+ current.Reset()
+ }
+ continue
+ }
+ current.WriteByte(ch)
+ }
+ if current.Len() > 0 {
+ args = append(args, current.String())
+ }
+ return args
+}
+
+func findCLIBinary() string {
+ exe, _ := os.Executable()
+ exeDir := filepath.Dir(exe)
+
+ candidates := []string{
+ filepath.Join(exeDir, "gitlink-cli.exe"),
+ filepath.Join(exeDir, "gitlink-cli"),
+ filepath.Join(exeDir, "..", "gitlink-cli.exe"),
+ filepath.Join(exeDir, "..", "gitlink-cli"),
+ "./gitlink-cli.exe",
+ "./gitlink-cli",
+ "../gitlink-cli.exe",
+ "../gitlink-cli",
+ }
+ for _, c := range candidates {
+ if _, err := os.Stat(c); err == nil {
+ abs, _ := filepath.Abs(c)
+ return abs
+ }
+ }
+ return "gitlink-cli"
+}
diff --git a/showcase/pipeline.yml b/showcase/pipeline.yml
new file mode 100644
index 0000000..cfb3330
--- /dev/null
+++ b/showcase/pipeline.yml
@@ -0,0 +1,31 @@
+version: 2
+name: 构建部署Showcase
+description: "代码提交自动触发:在服务器上拉取代码、构建Docker镜像并部署"
+global:
+ concurrent: 1
+trigger:
+ webhook: gitlink@1.0.0
+ event:
+ - ref: push
+ ruleset-operator: AND
+workflow:
+ - ref: start
+ name: 开始
+ task: start
+ - ref: ssh_cmd_0
+ name: SSH部署到服务器
+ task: ssh_cmd@1.1.1
+ input:
+ ssh_pass: ((deploy_server.server_password))
+ ssh_ip: '"118.31.4.168"'
+ ssh_port: '"22"'
+ ssh_user: '"root"'
+ ssh_cmd: >-
+ "mkdir -p /opt/gitlink-cli && cd /opt/gitlink-cli && (git clone https://gitlink.org.cn/chroe/gitlink-cli.git . || git pull origin master) && docker build -f showcase/Dockerfile -t gitlink-cli-showcase . && docker stop gitlink-cli-showcase || true && docker rm gitlink-cli-showcase || true && docker run -d -p 9090:9090 --name gitlink-cli-showcase --restart unless-stopped gitlink-cli-showcase"
+ needs:
+ - start
+ - ref: end
+ name: 结束
+ task: end
+ needs:
+ - ssh_cmd_0