diff --git a/.gitignore b/.gitignore index a5e2699..74f750b 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ bin/ .cache/ .idea/ *.swp + +web/dist/ +web/node_modules/ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 684318c..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 go-kratos - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/docs/ADMIN_BACKEND.md b/docs/ADMIN_BACKEND.md new file mode 100644 index 0000000..0b7531f --- /dev/null +++ b/docs/ADMIN_BACKEND.md @@ -0,0 +1,52 @@ +# Kra 管理后台 + +## 范围 + +Kra 管理后台由 Kratos 应用承载生命周期,Gin 提供兼容管理端的 HTTP 路由。后端按 `service -> biz -> data` 分层,前端位于 `web/`。 + +保留的业务模块: + +- 初始化、认证、用户和个人中心 +- 角色、菜单、API、Casbin 和按钮权限 +- 部门、岗位和数据范围 +- 字典、字典项和系统参数 +- 安全策略、系统配置和 API Token +- Excel 导入导出与版本管理 +- 操作日志、登录日志、数据访问日志、错误日志和文件日志 +- 定时任务、SSE、媒体上传和附件分类 +- 公告管理与邮件发送 + +不包含代码生成、智能辅助、模块安装发布、客户示例和测试页面。 + +## 目录 + +| 目录 | 职责 | +|---|---| +| `internal/server` | Gin 路由、中间件和 Kratos transport 生命周期 | +| `internal/service` | HTTP DTO 与领域对象转换、用例编排 | +| `internal/biz` | 领域对象、业务规则和仓储接口 | +| `internal/data` | GORM、MySQL、Redis 和本地文件存储实现 | +| `web` | Vue 3 管理端 | + +## 兼容约定 + +- HTTP 响应为 `{code, data, msg}`,成功码为 `0`。 +- JWT 接受 `x-token` Header 和同名 Cookie。 +- 初始化创建后台数据表、管理员、菜单,并从 Gin 路由同步 API 权限数据。 +- 超级管理员角色 `888` 保留全权限旁路,其他角色由 Casbin 控制。 +- SMTP 配置位于 `admin.email`;未配置时错误邮件告警保持关闭。 +- 媒体文件默认使用本地 `uploads/file` 存储。 + +## 验证 + +```bash +go generate ./cmd/kratos-admin +go test ./... +go vet ./... +go build ./... + +cd web +pnpm install +pnpm run lint +pnpm run build +``` diff --git a/docs/ADMIN_BACKEND_MIGRATION.md b/docs/ADMIN_BACKEND_MIGRATION.md deleted file mode 100644 index 1eb3a3c..0000000 --- a/docs/ADMIN_BACKEND_MIGRATION.md +++ /dev/null @@ -1,58 +0,0 @@ -# GVA 管理后端迁移清单 - -## 基线与范围 - -- 参考基线:工作区 `gva/server`,Git `02f37833`。 -- 目标:保留 GVA Vue 管理端使用的 HTTP 路径、方法、请求字段、统一响应结构和核心业务语义,同时按 Kratos 的 `service -> biz -> data` 分层落地。 -- 明确排除:代码生成、代码生成历史、插件打包/安装、AI/LLM、MCP、Skills,以及测试文件。 -- 公告与邮件位于 `gva/server/plugin`;两者均已按 Kratos 分层迁移,不保留 GVA 的插件式全局变量结构。 -- 推荐范围包含 177 个 GVA HTTP 路由,目标端全部覆盖;另增加 `GET /health`,目标实际注册路由总数为 178。 - -## 模块契约矩阵 - -| 模块 | 路由数 | 迁移内容 | -|---|---:|---| -| 初始化、登录、用户、个人中心 | 17 | 初始化、验证码、登录、JWT、用户 CRUD、多角色、个人资料、密码、菜单、注销 | -| 角色 | 9 | 角色树、创建、复制、更新、删除、用户关联、数据范围 | -| 菜单 | 10 | 菜单树、CRUD、角色菜单、菜单角色、菜单按钮 | -| API 与 Casbin | 19 | API CRUD/同步/忽略、角色 API、Casbin 策略、按钮权限 | -| 组织 | 16 | 部门树、岗位、用户关联、自定义数据范围 | -| 字典与参数 | 24 | 字典/字典项 CRUD、树、路径、导入导出、系统参数 | -| 安全、系统配置、API Token | 9 | 安全策略热更新、限流、锁定、密码策略、配置、服务器信息、Token 签发/作废 | -| Excel 导入导出 | 12 | 模板 CRUD、SQL 预览、一次性下载令牌、Excel 导入导出 | -| 版本管理 | 7 | 菜单/API/字典版本打包、记录、下载和导入 | -| 审计与日志 | 20 | 操作、登录、数据访问、错误日志以及安全的文件日志查看 | -| 定时任务与 SSE | 9 | Cron CRUD/启停/触发、HTTP/本地执行器、执行日志、失败告警 SSE | -| 媒体 | 15 | 文件库、附件分类、本地存储枚举、普通上传、秒传与分片续传 | -| 公告 | 8 | 公告 CRUD、批量删除、分页、发布者数据源和公开接口 | -| 邮件 | 2 | SMTP 测试、主动发送,以及失败请求邮件告警中间件 | - -## 分层映射 - -| Kratos 层 | 职责 | -|---|---| -| `internal/server` | Gin 路由、鉴权/审计中间件、HTTP 请求绑定与响应写出、Kratos transport 生命周期 | -| `internal/service` | HTTP DTO 与领域数据的适配、用例编排 | -| `internal/biz` | 用户、权限、设置、审计、任务、媒体等领域对象、仓储接口与业务规则 | -| `internal/data` | GORM PO、MySQL 仓储、Redis/内存缓存、本地文件存储 | -| `cmd/kratos-admin` | Wire 依赖注入与 Kratos 应用组装 | - -## 兼容性说明 - -- HTTP 响应保持 `{code, data, msg}`,成功码为 `0`。 -- JWT 继续接受 `x-token` Header 和同名 Cookie;角色切换返回 `new-token`、`new-expires-at`。 -- 初始化会自动迁移表、写入管理员与菜单,并从 Gin 实际路由同步 API 表。 -- 超级管理员角色 `888` 保留全权限旁路;其他角色由 Casbin 策略控制。 -- 代码中的 `*-gva` 字符串仅是原 Vue 图标库的图标标识,为页面显示兼容而保留;Go 文件、类型、变量和方法均使用实际职责命名。 -- 当前首先实现 MySQL、Redis(不可用时退化为进程缓存)和本地文件存储;云 OSS 驱动没有混入领域层。 -- SMTP 参数位于 `admin.email`;未配置服务器、发件人或密钥时错误告警保持关闭,邮件接口会返回明确的配置错误。 - -## 验证命令 - -```bash -go generate ./cmd/kratos-admin -go test ./... -go vet ./... -go build ./... -git diff --check -``` diff --git a/gva b/gva deleted file mode 160000 index 02f3783..0000000 --- a/gva +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 02f37833255e0e339c3d69199cb5a468f17de9fc diff --git a/internal/data/announcement.go b/internal/data/announcement.go index 2445e25..25d93cc 100644 --- a/internal/data/announcement.go +++ b/internal/data/announcement.go @@ -22,7 +22,7 @@ type announcementPO struct { Attachments []byte `gorm:"type:json"` } -func (announcementPO) TableName() string { return "gva_announcements_info" } +func (announcementPO) TableName() string { return "kra_announcements_info" } type announcementRepo struct{ data *Data } diff --git a/internal/data/system.go b/internal/data/system.go index 56045b8..0247743 100644 --- a/internal/data/system.go +++ b/internal/data/system.go @@ -419,13 +419,13 @@ func defaultMenus() []menuPO { } return []menuPO{ {Path: "dashboard", Name: "dashboard", Component: "view/dashboard/index.vue", Title: "仪表盘", Icon: "odometer", Sort: 1}, - root("permission", "permission", "权限管理", "perm-gva", 2), root("org", "org", "组织管理", "share", 3), root("systemConfig", "systemConfig", "系统设置", "config-gva", 4), root("monitor", "monitor", "运维监控", "monitor-gva", 5), root("media", "media", "媒体管理", "folder-opened", 6), root("plugin", "plugin", "插件系统", "cherry", 10), + root("permission", "permission", "权限管理", "perm-kra", 2), root("org", "org", "组织管理", "share", 3), root("systemConfig", "systemConfig", "系统设置", "config-kra", 4), root("monitor", "monitor", "运维监控", "monitor-kra", 5), root("media", "media", "媒体管理", "folder-opened", 6), root("extensions", "extensions", "扩展功能", "cherry", 10), {Path: "person", Name: "person", Component: "view/person/person.vue", Title: "个人信息", Icon: "postcard", Hidden: true, Sort: 13}, - child("permission", "authority", "authority", "view/superAdmin/authority/authority.vue", "角色管理", "role-gva", 1), child("permission", "menu", "menu", "view/superAdmin/menu/menu.vue", "菜单管理", "tickets", 2), child("permission", "api", "api", "view/superAdmin/api/api.vue", "api管理", "api-gva", 3), child("permission", "apiToken", "apiToken", "view/systemTools/apiToken/index.vue", "API Token", "key", 4), + child("permission", "authority", "authority", "view/superAdmin/authority/authority.vue", "角色管理", "role-kra", 1), child("permission", "menu", "menu", "view/superAdmin/menu/menu.vue", "菜单管理", "tickets", 2), child("permission", "api", "api", "view/superAdmin/api/api.vue", "api管理", "api-kra", 3), child("permission", "apiToken", "apiToken", "view/systemTools/apiToken/index.vue", "API Token", "key", 4), child("org", "user", "user", "view/superAdmin/user/user.vue", "用户管理", "user", 1), child("org", "department", "department", "view/superAdmin/department/department.vue", "部门管理", "office-building", 2), child("org", "position", "position", "view/superAdmin/position/position.vue", "岗位管理", "postcard", 3), - child("systemConfig", "system", "system", "view/systemTools/system/system.vue", "配置文件", "config-file-gva", 1), child("systemConfig", "dictionary", "dictionary", "view/superAdmin/dictionary/sysDictionary.vue", "字典管理", "notebook", 2), child("systemConfig", "sysParams", "sysParams", "view/superAdmin/params/sysParams.vue", "参数管理", "set-up", 3), child("systemConfig", "security", "security", "view/system/security/index.vue", "安全配置", "security-gva", 4), - child("monitor", "operation", "operation", "view/superAdmin/operation/sysOperationRecord.vue", "操作历史", "document", 1), child("monitor", "loginLog", "loginLog", "view/systemTools/loginLog/index.vue", "登录日志", "clock", 2), child("monitor", "sysError", "sysError", "view/systemTools/sysError/sysError.vue", "错误日志", "error-gva", 3), child("monitor", "sysVersion", "sysVersion", "view/systemTools/version/version.vue", "版本管理", "version-gva", 4), child("monitor", "state", "state", "view/system/state.vue", "服务器状态", "server", 5), child("monitor", "dataAccessLog", "dataAccessLog", "view/superAdmin/dataAccessLog/dataAccessLog.vue", "数据权限审计", "warning", 6), child("monitor", "timedTask", "timedTask", "view/systemTools/timedTask/index.vue", "定时任务", "timer", 7), child("monitor", "logViewer", "logViewer", "view/systemTools/logViewer/index.vue", "文件日志", "document", 8), + child("systemConfig", "system", "system", "view/systemTools/system/system.vue", "配置文件", "config-file-kra", 1), child("systemConfig", "dictionary", "dictionary", "view/superAdmin/dictionary/sysDictionary.vue", "字典管理", "notebook", 2), child("systemConfig", "sysParams", "sysParams", "view/superAdmin/params/sysParams.vue", "参数管理", "set-up", 3), child("systemConfig", "security", "security", "view/system/security/index.vue", "安全配置", "security-kra", 4), + child("monitor", "operation", "operation", "view/superAdmin/operation/sysOperationRecord.vue", "操作历史", "document", 1), child("monitor", "loginLog", "loginLog", "view/systemTools/loginLog/index.vue", "登录日志", "clock", 2), child("monitor", "sysError", "sysError", "view/systemTools/sysError/sysError.vue", "错误日志", "error-kra", 3), child("monitor", "sysVersion", "sysVersion", "view/systemTools/version/version.vue", "版本管理", "version-kra", 4), child("monitor", "state", "state", "view/system/state.vue", "服务器状态", "server", 5), child("monitor", "dataAccessLog", "dataAccessLog", "view/superAdmin/dataAccessLog/dataAccessLog.vue", "数据权限审计", "warning", 6), child("monitor", "timedTask", "timedTask", "view/systemTools/timedTask/index.vue", "定时任务", "timer", 7), child("monitor", "logViewer", "logViewer", "view/systemTools/logViewer/index.vue", "文件日志", "document", 8), child("media", "upload", "upload", "view/media/upload.vue", "媒体库(上传下载)", "upload", 1), child("media", "chunkUpload", "chunkUpload", "view/media/chunkUpload.vue", "大文件上传", "folder-add", 2), - child("plugin", "plugin-email", "plugin-email", "plugin/email/view/index.vue", "邮件插件", "message", 4), child("plugin", "anInfo", "anInfo", "plugin/announcement/view/info.vue", "公告管理[示例]", "bell", 5), + child("extensions", "email", "email", "modules/email/view/index.vue", "邮件发送", "message", 4), child("extensions", "anInfo", "anInfo", "modules/announcement/view/info.vue", "公告管理", "bell", 5), } } diff --git a/internal/server/audit_routes.go b/internal/server/audit_routes.go index 3bd0a8c..0a97967 100644 --- a/internal/server/audit_routes.go +++ b/internal/server/audit_routes.go @@ -216,15 +216,6 @@ func registerAuditRoutes(group, public *gin.RouterGroup, svc *service.AuditServi } writeResult(c, codeSuccess, pageResult{List: items, Total: total, Page: page, PageSize: size}, "获取成功") }) - errorsRoute.GET("/getSysErrorSolution", func(c *gin.Context) { - id, _ := strconv.ParseUint(c.Query("ID"), 10, 64) - item, err := svc.Error(c.Request.Context(), uint(id)) - if err != nil { - fail(c, "查询失败") - return - } - writeResult(c, codeSuccess, gin.H{"solution": item["solution"]}, "获取成功") - }) public.Group("/sysError").POST("/createSysError", func(c *gin.Context) { var req struct { Form string `json:"form"` diff --git a/web/.commitlintrc.js b/web/.commitlintrc.js deleted file mode 100644 index 422b194..0000000 --- a/web/.commitlintrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { extends: ['@commitlint/config-conventional'] }; diff --git a/web/.docker-compose/nginx/conf.d/my.conf b/web/.docker-compose/nginx/conf.d/my.conf new file mode 100644 index 0000000..9a1685d --- /dev/null +++ b/web/.docker-compose/nginx/conf.d/my.conf @@ -0,0 +1,26 @@ +server { + listen 8080; + server_name localhost; + + #charset koi8-r; + #access_log logs/host.access.log main; + + location / { + root /usr/share/nginx/html; + add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + rewrite ^/api/(.*)$ /$1 break; #重写 + proxy_pass http://177.7.0.12:8888; # 设置代理服务器的协议和地址 + } + + location /api/swagger/index.html { + proxy_pass http://127.0.0.1:8888/swagger/index.html; + } + } \ No newline at end of file diff --git a/web/.docker-compose/nginx/conf.d/nginx.conf b/web/.docker-compose/nginx/conf.d/nginx.conf new file mode 100644 index 0000000..29f68b8 --- /dev/null +++ b/web/.docker-compose/nginx/conf.d/nginx.conf @@ -0,0 +1,32 @@ +server { + listen 80; + server_name localhost; + + #charset koi8-r; + #access_log logs/host.access.log main; + + location / { + root /usr/share/nginx/html/dist; + add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + rewrite ^/api/(.*)$ /$1 break; #重写 + proxy_pass http://127.0.0.1:8888; # 设置代理服务器的协议和地址 + } + location /form-generator { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://127.0.0.1:8888; + } + location /api/swagger/index.html { + proxy_pass http://127.0.0.1:8888/swagger/index.html; + } + } \ No newline at end of file diff --git a/web/.dockerignore b/web/.dockerignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/web/.dockerignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/web/.editorconfig b/web/.editorconfig deleted file mode 100644 index 7e3649a..0000000 --- a/web/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# http://editorconfig.org -root = true - -[*] -indent_style = space -indent_size = 2 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false - -[Makefile] -indent_style = tab diff --git a/web/.env.development b/web/.env.development new file mode 100644 index 0000000..dcf5a27 --- /dev/null +++ b/web/.env.development @@ -0,0 +1,11 @@ +ENV = 'development' +VITE_CLI_PORT = 8080 +VITE_SERVER_PORT = 8000 +VITE_BASE_API = /api +VITE_FILE_API = /api +VITE_BASE_PATH = http://127.0.0.1 +VITE_POSITION = open +VITE_EDITOR = code +// VITE_EDITOR = webstorm 如果使用webstorm开发且要使用dom定位到代码行功能 请先自定添加 webstorm到环境变量 再将VITE_EDITOR值修改为webstorm +// 如果使用docker-compose开发模式,设置为下面的地址或本机主机IP +//VITE_BASE_PATH = http://177.7.0.12 diff --git a/web/.env.production b/web/.env.production new file mode 100644 index 0000000..87f863c --- /dev/null +++ b/web/.env.production @@ -0,0 +1,5 @@ +ENV = 'production' + +#下方为上线需要用到的程序代理前缀,一般用于nginx代理转发 +VITE_BASE_API = /api +VITE_FILE_API = /api diff --git a/web/.gitignore b/web/.gitignore index 7237b34..a79a8b2 100644 --- a/web/.gitignore +++ b/web/.gitignore @@ -1,41 +1,6 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -**/node_modules -# roadhog-api-doc ignore -/src/utils/request-temp.js -_roadhog-api-doc - -# production -/dist - -# misc -.DS_Store -npm-debug.log* -yarn-error.log - -/coverage -.idea -yarn.lock +/node_modules/ +/dist/ package-lock.json -*bak -.vscode - - -# visual studio code -.history -*.log -functions/* -.temp/** - -# umi -.umi -.umi-production -.umi-test -.turbopack - -# screenshot -screenshot -.firebase - -build +yarn.lock +bun.lockb +config.yaml diff --git a/web/.husky/commit-msg b/web/.husky/commit-msg deleted file mode 100644 index 0a4b97d..0000000 --- a/web/.husky/commit-msg +++ /dev/null @@ -1 +0,0 @@ -npx --no -- commitlint --edit $1 diff --git a/web/.husky/pre-commit b/web/.husky/pre-commit deleted file mode 100644 index c27d889..0000000 --- a/web/.husky/pre-commit +++ /dev/null @@ -1 +0,0 @@ -lint-staged diff --git a/web/.lintstagedrc b/web/.lintstagedrc deleted file mode 100644 index 1c2023c..0000000 --- a/web/.lintstagedrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "**/*.{js,jsx,tsx,ts,md,css,less,json}": [ - "npx @biomejs/biome check --write" - ] -} diff --git a/web/.npmrc b/web/.npmrc deleted file mode 100644 index 521a9f7..0000000 --- a/web/.npmrc +++ /dev/null @@ -1 +0,0 @@ -legacy-peer-deps=true diff --git a/web/.prettierrc b/web/.prettierrc new file mode 100644 index 0000000..bc61a53 --- /dev/null +++ b/web/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "semi": false, + "singleQuote": true, + "trailingComma": "none", + "bracketSpacing": true, + "arrowParens": "always", + "vueIndentScriptAndStyle": true, + "endOfLine": "lf" +} diff --git a/web/Dockerfile b/web/Dockerfile new file mode 100644 index 0000000..21a1d59 --- /dev/null +++ b/web/Dockerfile @@ -0,0 +1,24 @@ +# 如果需要用 cicd ,请设置环境变量: +# variables: +# DOCKER_BUILDKIT: 1 + +FROM node:20-slim AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable +COPY . /app +WORKDIR /app + + +FROM base AS prod-deps +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod + +FROM base AS build +COPY --from=prod-deps /app/node_modules /app/node_modules +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install && pnpm run build + + +FROM nginx:alpine +COPY --from=base /app/.docker-compose/nginx/conf.d/my.conf /etc/nginx/conf.d/my.conf +COPY --from=build /app/dist /usr/share/nginx/html +RUN ls -al /usr/share/nginx/html diff --git a/web/LICENSE b/web/LICENSE deleted file mode 100644 index b65958e..0000000 --- a/web/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019-present Alipay.inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..eb575d4 --- /dev/null +++ b/web/README.md @@ -0,0 +1,16 @@ +# Kra 管理后台 + +Kra 的 Vue 3 管理端,与仓库中的 Kratos + Gin 后端配套使用。 + +```bash +npm install +npm run dev +``` + +生产构建: + +```bash +npm run build +``` + +开发环境默认把 `/api` 代理到 `http://127.0.0.1:8000`。 diff --git a/web/babel.config.cjs b/web/babel.config.cjs new file mode 100644 index 0000000..14cfe04 --- /dev/null +++ b/web/babel.config.cjs @@ -0,0 +1,13 @@ +// Babel 配置 +// +// 用 .cjs 而非 .js:本项目 package.json 为 "type": "module",.js 会被当作 ESM, +// 而 @babel/eslint-parser 需要「同步」读取 babel 配置(ESLint 是同步解析的), +// ESM 配置无法同步加载。.cjs 强制 CommonJS,保证 eslint 能正常读取本文件。 +// +// 目前主要供 @babel/eslint-parser 解析 .js / .vue + + + +
+