diff --git a/README.md b/README.md index 8dcdda6..b179a51 100644 --- a/README.md +++ b/README.md @@ -1,97 +1,34 @@ # AutoLibrary Website -北京建筑大学图书馆自动化工具的官网、软件下载中心与社区主题市场。 +AutoLibrary 官网、软件下载中心与主题市场,使用 Vue 3、TypeScript、Go/Gin、SQLite 和 Casdoor。 -- 产品仓库: -- 用户手册: -- 发行版本: - -## 架构 - -前端采用 Vue 3、TypeScript、Vite、Vue Router、Pinia 和 Lucide 图标。所有字体、图标和图片随构建产物提供,无需第三方 CDN。页面使用统一的布局、表单和状态组件,深浅主题由 CSS 语义变量管理。 - -Go/Gin 前端服务提供构建产物并将 `/api/*` 代理到后端;后端保留 GORM/SQLite、Casdoor 和本地主题文件存储。既可一起启动,也可分别部署。当前面向单实例运行。 - -```text -frontend/ - src/ - api/ # 请求、响应、下载和错误处理 - components/ # 全站与业务共享组件 - composables/ # 画廊等可复用交互逻辑 - pages/ # 按路由拆分的页面 - stores/ # 账户与外观状态 - styles/ # 页面专用样式 - site.ts # 项目链接、URL 和日期工具 - types.ts # API 数据类型 - styles.css # 双主题变量与响应式样式 - public/assets/ # 原有品牌标识与实机截图 - dist/ # 生产构建产物(生成) -backend/ - handlers/themes_handler/ # 认证、查询、上传、更新、审核、下载 - services/ # 主题打包、文件存储、事务协调、用户缓存 - database/ # SQLite 初始化 - models/ # 数据模型 -``` +[官网](https://www.autolibrary.kenanzhu.com) · [用户手册](https://manuals.autolibrary.kenanzhu.com) · [产品发布](https://gitea.kenanzhu.com/KenanZhu/AutoLibrary/releases) ## 本地开发 -需要 Go 1.25.6+ 和 Node.js 22.13+(推荐当前 Node LTS,Vite 要求 Node 22.12+,ESLint 要求 22.13+)。从项目根目录运行: +需要 Go 1.25.6+、Node.js 22.13+ 和支持 CGO 的 C 编译器。 ```sh -# 首次配置;已有 config.json 时保留原文件 cp config.example.json config.json npm --prefix frontend ci go run . backend -``` - -在另一个终端启动前端: - -```sh +# 在另一个终端启动前端 npm --prefix frontend run dev ``` -开发地址为 `http://127.0.0.1:5173`。默认代理到 `http://127.0.0.1:8080`;后端端口不同时,在 `frontend/.env.local` 设置 `API_PROXY_TARGET=http://127.0.0.1:实际端口`。无需在前端添加服务器密钥。 +打开 `http://127.0.0.1:5173`。后端默认端口为 `8080`,登录功能需要配置 Casdoor。 -登录与注册需要配置并启动 Casdoor。未配置时,浏览下载和主题市场仍可用;账户操作会显示服务未启用。管理员审核统一使用 Casdoor 管理员账户。 - -## 构建与检查 +## 构建与发布 ```sh -npm --prefix frontend run typecheck -npm --prefix frontend run check npm --prefix frontend run build go test ./... -go build -o webserver . -./webserver start +docker build -t autolibrary-web:local . +bash deploy/smoke-container.sh autolibrary-web:local ``` -`build` 已包含类型、ESLint 和 Prettier 检查,产物位于 `frontend/dist`。使用 `npm --prefix frontend run format` 统一前端源码格式。没有增加测试用例或测试工具链。Go 检查用于验证已有包可以编译。 +推送 `main` 后,Gitea Actions 构建、测试并发布镜像到 `gitea.kenanzhu.com/autolibrary/website:<提交SHA>`。仓库 Secrets 需配置 `REGISTRY_USERNAME` 和具有软件包写入权限的 `REGISTRY_TOKEN`。 -生产环境默认访问 `http://127.0.0.1:3000`,实际地址以 `config.json` 为准。`frontend` 和 `backend` 子命令支持独立启动,均可使用 `--config /absolute/path/config.json`。请将工作目录设置为项目部署目录。 +使用 `compose.yaml` 部署,设置 `AUTOLIBRARY_IMAGE`、`AUTOLIBRARY_CONFIG`、`AUTOLIBRARY_DATA_DIR` 和 `AUTOLIBRARY_LOG_DIR`,并按宿主机权限设置 `AUTOLIBRARY_UID`、`AUTOLIBRARY_GID`。前端健康检查端口由 `AUTOLIBRARY_HTTP_PORT` 指定,默认 `3003`。 -## 发行与下载数据 - -版本数据库是官网版本信息的唯一来源。首页通过 `GET /api/download/latest` 获取最新已发布的稳定版(按 `releaseDate`、ID 降序;无稳定版时 `data: null`),下载列表保持原有分页接口。`/api` 前缀由 Go 前端或 Vite 代理移除,直接访问后端时使用 `/download/latest` 等路径。 - -版本模型新增以下字段,启动时由 GORM 增量添加列,不删除原字段或数据: - -| JSON 字段 | 用途 | -| --- | --- | -| `giteaZipUrl` | Gitea Windows 便携包 | -| `giteaInstallerUrl` | Gitea Windows 安装程序 | -| `giteaDmgUrl` | Gitea macOS 安装包 | -| `releaseNotesUrl` | 对应版本的发行说明 | - -使用已有受 API Key 保护的 `POST/PUT /download/versions` 接口维护这些字段。提供真实的 Gitea 附件地址;不要仅将历史 GitHub URL 替换域名。新页面没有可用附件地址时,提供 Gitea 发行列表入口,云盘下载照常保留。原 `github*Url` 字段继续供已有 API 调用使用,新页面不再展示 GitHub 下载入口。 - -独立更新日志已移除,`/changelog` 永久跳转 `/downloads`。发行说明在 Gitea 查看;公告接口及其数据库保留。个人下载历史尚未实现,本次没有扩展该功能。 - -## 发布与维护 - -网站源码推送到 Gitea 的 `main` 后,由专用 Runner 构建、验证并发布网站镜像到 Gitea。镜像运行、数据挂载和切换步骤见 [容器部署说明](docs/container-deployment.md)。使用原生 systemd 发布时,见 [Gitea 原生部署](docs/gitea-deployment.md)。 - -完整部署、备份和回滚步骤见 [Ubuntu 部署说明](docs/migration-to-ubuntu.md)。配置和运行时数据与前端构建分开保存;本地现有数据库、主题文件和 Casdoor 配置不需要重建。 - -迁移前的静态页面、脚本和混淆工具已保存在项目内 `.legacy/`,不参与构建或运行,可用于核对历史内容。 - -主题上传支持最大 8 MB 的 `.qss` 和最大 4 MB 的 PNG/JPG 预览图,后端总请求体上限 16 MB。主题和打包文件一起保存;文件、元数据或预览更新后重新进入审核队列。退出时先停止接收请求,再关闭数据库。 +配置只读挂载,数据库、主题文件和日志持久化在宿主机。上线前备份数据,更新 Compose 使用的镜像摘要后运行 `docker compose up -d --wait`。 diff --git a/docs/container-deployment.md b/docs/container-deployment.md deleted file mode 100644 index 214ff11..0000000 --- a/docs/container-deployment.md +++ /dev/null @@ -1,38 +0,0 @@ -# 网站容器 - -镜像在独立构建阶段编译 Vue 和启用 CGO 的 Go 程序。最终镜像运行单个 `webserver` 进程,同时提供静态资源和 API。容器配置、SQLite、上传文件和日志由部署机挂载。 - -## 构建和验证 - -需要 Linux Docker Engine 和 Buildx。在源码根目录运行: - -```sh -docker build -t autolibrary-web:local . -bash deploy/smoke-container.sh autolibrary-web:local -``` - -冒烟测试使用临时配置和空数据库,在无外部网络的容器里验证首页、后端健康检查、深层路由、静态资源、SQLite API 和 SIGTERM 退出。 - -Gitea Actions 在 `main` 和 `container-ci` 推送时执行同一套镜像构建和冒烟测试。专用 Runner `hk-vps-runner-02` 使用 `linux-amd64-docker-small` 标签,作业在 Docker CLI 容器中运行。工作流检查构建 daemon 的 rootless 标志。 - -冒烟测试通过后,工作流使用仓库 Secrets 中的 `REGISTRY_USERNAME` 和 `REGISTRY_TOKEN`,把镜像推送到 `gitea.kenanzhu.com/autolibrary/website:<提交SHA>`,并在日志中输出镜像摘要。令牌需要对 `AutoLibrary` 组织的软件包有写入权限。生产机按该摘要拉取镜像,生产切换单独执行。 - -## 使用现网配置 - -生产机运行 Compose v2。复制 `/home/autolibrary/config.json` 到独立文件,将 `frontend.static.path` 设置为 `./frontend/dist`。数据库路径使用 `./backend/data/` 下的现有相对路径。保留前端端口 `3003`、后端端口 `8080` 和 Casdoor 地址 `http://127.0.0.1:8000`。Compose 使用 Linux 宿主机网络,让 Nginx 和 Casdoor 继续通过原有地址连接。 - -从部署机设置以下环境变量。镜像可以用提交 SHA 标签或不可变的镜像摘要引用: - -```dotenv -AUTOLIBRARY_IMAGE=gitea.kenanzhu.com/autolibrary/website@sha256:<镜像摘要> -AUTOLIBRARY_CONFIG=/绝对路径/网站容器配置.json -AUTOLIBRARY_DATA_DIR=/home/autolibrary/backend/data -AUTOLIBRARY_LOG_DIR=/home/autolibrary/logs -AUTOLIBRARY_UID=996 -AUTOLIBRARY_GID=987 -AUTOLIBRARY_HTTP_PORT=3003 -``` - -配置文件对容器运行身份可读,数据目录及日志目录可写。Compose 会检查挂载源是否存在。 - -正式切换前,先用独立端口和数据库副本验证容器,并备份数据库和上传文件。切换时停止占用相同端口的 `autolibrary-webserver.service`,运行 `docker compose up -d --wait`,然后验证 Nginx 入口、登录及上传。若首次切换失败,停止网站容器,再启动原网站服务。后续发布可将 `AUTOLIBRARY_IMAGE` 指回上一个镜像,再运行 `docker compose up -d --wait`。程序回退继续使用同一份持久数据。 diff --git a/docs/design-notes.md b/docs/design-notes.md deleted file mode 100644 index 1c4bd4c..0000000 --- a/docs/design-notes.md +++ /dev/null @@ -1,16 +0,0 @@ -# 页面设计与交互约定 - -保留 AutoLibrary 的书本标识、绿色强调色、图书馆文案与真实软件截图。首页用紧凑功能带、横向标签与通栏截图、编号资源清单形成不同的信息层次,避免每节重复大标题与卡片网格。 - -参考 [Paco Coursey](https://paco.me/) 的克制排版与目录组织,以及 [Zed](https://zed.dev/) 对真实产品界面的呈现;不引入其品牌元素或外部素材。 - -- `ThemeToggle.vue` 以太阳/月亮图标切换当前主题,状态由 `stores/theme.ts` 统一维护并持久保存。首次访问仍跟随系统;图标旋转、淡入和缩放遵守减少动态效果偏好。 -- 顶部主题与登录按钮统一为 32px 高;键盘焦点保留清晰轮廓。 -- 功能与画廊板块标题共用 `home-section-title`:桌面端 22px、手机端 20px,字重、行高和标题下方间距一致。标题旁不添加辅助说明或装饰圆点。 -- `ProductGallery.vue` 管理截图与目录内容;`useGallery.ts` 管理自动播放。画廊至少 20% 可见且页面处于前台时,每 6 秒切换;鼠标悬停和控件获得焦点不暂停,手动选择后重新计时。提供播放/暂停、上一张/下一张和左右方向键操作;用户主动暂停后,手动选择不会重新开启播放。系统要求减少动态效果时默认停止自动播放。 -- 画廊样式放在 `styles/home.css`,桌面端标签位于通栏截图上方,手机端改为两列。保留当前标签底部的播放进度条,界面不展示切换间隔文案。第一张截图跟随网站深浅主题,其余保留原始实机截图。 -- 验证码始终使用明亮背景、接近原生的 150×50 比例,不反色或滤镜处理;输入框有明确标签,点击图片可刷新。 -- 首页与下载页的平台标识共用 `PlatformLogo.vue`。`DownloadSource.vue` 使用原生 `details/summary` 展开 Gitea、云盘资源;桌面悬停展开,也支持点击、键盘和 Escape,手机端点击后在页面内展开。同一时刻只展开一个入口,云盘提取码位于资源链接上方。 -- 主按钮悬停与键盘焦点使用独立的背景和文字颜色变量,不整体叠加亮度滤镜,以维持深浅主题下的清晰对比。 - -维护时运行 `npm --prefix frontend run build` 完成类型、代码风格与生产构建检查。另在浏览器检查双主题、手机宽度、自动轮播与验证码显示,无需新增测试用例。 diff --git a/docs/gitea-deployment.md b/docs/gitea-deployment.md deleted file mode 100644 index fda9762..0000000 --- a/docs/gitea-deployment.md +++ /dev/null @@ -1,95 +0,0 @@ -# 通过 Gitea Actions 部署原生网站服务 - -本页用于手动触发原生网站发布。推送触发的镜像构建见 [容器部署说明](container-deployment.md)。在 Gitea Actions 手动运行 `Deploy native AutoLibrary service` 时,任务由具备 `autolibrary-native-deploy` 标签的宿主机 Runner 接收。每次发布生成独立目录,原子切换 `current`,重启 systemd 服务并检查首页和 `/api/health`。检查失败时自动切回上一发布,并将本次任务标记为失败。 - -## 1. 准备 Ubuntu 部署机 - -安装 Bash、Git、curl、sudo、`build-essential`、`util-linux`、Go 1.25.6 或更新版本、Node.js 22.13 或更新版本。确认 Runner 的服务环境中能找到 `git`、`node`、`npm`、`go` 和 `gcc`,并能访问 Gitea、GitHub 上固定版本的 checkout Action、npm registry 和 Go 模块代理。 - -网站继续使用现有的 `autolibrary` 账号。首次接入时创建专用部署账号和发布目录。已有部署账号时复用,并确认组和权限与示例相符。 - -```sh -sudo useradd --system --user-group --create-home --home-dir /var/lib/autolibrary-runner autolibrary-deploy -sudo chmod 0700 /var/lib/autolibrary-runner -sudo install -d -o root -g autolibrary-deploy -m 1775 /opt/autolibrary -sudo install -d -o autolibrary-deploy -g autolibrary-deploy -m 0755 /opt/autolibrary/releases -sudo install -d -o root -g autolibrary -m 0751 /opt/autolibrary/shared -sudo ln -s /home/autolibrary/logs /opt/autolibrary/shared/logs -``` - -现网的基础 unit 为 `autolibrary-webserver.service`,运行账号为 `autolibrary`,原程序和配置位于 `/home/autolibrary`。按 [Ubuntu 部署说明](migration-to-ubuntu.md) 备份后,将原配置复制到 `/opt/autolibrary/shared/config.json`,设为 `root:autolibrary`、权限 `0640`。调整副本中的路径: - -- 将三个 SQLite 数据库和主题文件目录的路径改为现有 `/home/autolibrary/backend/data/` 下的绝对路径,继续使用原数据。运行用户需要对数据库所在目录和主题文件目录有写权限。 -- 将 `frontend.static.path` 改为 `./frontend/dist`,让程序从本次发布目录读取资源。沿用前端 `3003`、后端 `8080` 及现有监听地址。 -- 保留现有 API Key 和 `backend.casdoor` 配置。网站通过 `http://127.0.0.1:8000` 使用 Casdoor 处理账户和认证。现网的 `autolibrary-casdoor.service` 独立运行,发布任务只重启 `autolibrary-webserver.service`。 - -首次接入时,以部署账号创建指向原站的链接,作为首次发布失败时的回退目标。已有 `current` 时,确认链接指向可用的上一版并由部署账号拥有。 - -```sh -sudo -u autolibrary-deploy ln -s /home/autolibrary /opt/autolibrary/current -``` - -## 2. 安装网站服务和 Runner - -在现有网站 unit 上安装 drop-in,只调整工作目录和启动命令。原 unit 继续提供运行账号、重启策略和 `/home/autolibrary/logs/errors.log` 的 stderr 设置。新服务器可先按 [Ubuntu 部署说明](migration-to-ubuntu.md#4-systemd) 安装基础 unit。已有站点执行 `daemon-reload` 后,覆盖配置会在下一次网站服务启动时生效。 - -```sh -sudo install -d -m 0755 /etc/systemd/system/autolibrary-webserver.service.d -sudo install -m 0644 deploy/systemd/10-gitea-release.conf /etc/systemd/system/autolibrary-webserver.service.d/10-gitea-release.conf -sudo systemctl daemon-reload -sudo visudo -f /etc/sudoers.d/autolibrary-deploy -``` - -加入以下精确授权,使 Runner 可以操作网站 unit。 - -```sudoers -autolibrary-deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart autolibrary-webserver.service, /usr/bin/systemctl stop autolibrary-webserver.service -``` - -在 Gitea 创建一个空的网站源码仓库,启用仓库的 Actions 功能并保护 `main`。使用该网站仓库的 Runner 注册令牌,在部署机安装 [Gitea Runner](https://docs.gitea.com/runner/),然后以部署账号交互注册: - -```sh -sudo -u autolibrary-deploy -H sh -c 'cd "$HOME" && gitea-runner register' -``` - -输入实例地址和仓库级令牌,使用独立的原生发布 Runner 名称,标签只填写 `autolibrary-native-deploy:host`。以同一账号和工作目录运行 `gitea-runner daemon`。可用下面的 systemd unit 持久运行,将 `ExecStart` 与 `PATH` 调整到实际安装位置。 - -```ini -[Unit] -Description=AutoLibrary Gitea Runner -Wants=network-online.target -After=network-online.target - -[Service] -User=autolibrary-deploy -WorkingDirectory=/var/lib/autolibrary-runner -Environment=PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin -ExecStart=/usr/local/bin/gitea-runner daemon -Restart=on-failure - -[Install] -WantedBy=multi-user.target -``` - -例如保存为 `/etc/systemd/system/autolibrary-runner.service` 后,执行 `sudo systemctl daemon-reload` 和 `sudo systemctl enable --now autolibrary-runner.service`。旧版 Runner 的二进制名可能为 `act_runner`,按实际名称替换。确认仓库设置页中 Runner 在线,并且标签与工作流的 `runs-on` 一致。宿主机任务使用部署账号的权限直接运行,只将这个 Runner 分配给受信任的网站仓库。 - -## 3. 首次推送 - -在 Gitea 仓库的 Actions Variables 中将 `AUTOLIBRARY_PORT` 设为生产 `frontend.port`;省略时为 `3003`,若沿用通用示例配置则设置为 `3000`。 - -在本地网站源码目录绑定新建仓库的克隆地址并推送: - -```sh -git remote add origin -git push -u origin main -``` - -在 Gitea 的 Actions 页手动运行 `Deploy native AutoLibrary service`,选择 `main`,然后确认部署任务完成。发布脚本在切换前读取远端 `main`,已过时的任务会跳过部署。生产密钥、数据库、上传目录和 Casdoor 实例数据由部署机保存。 - -## 排查和回滚 - -- 任务排队时,检查仓库 Actions 设置、Runner 在线状态和标签。 -- 重启或健康检查失败时,检查 Actions 日志、`sudo journalctl -u autolibrary-webserver.service -n 100` 和 `/home/autolibrary/logs/errors.log`。检查端口、共享配置、数据路径和权限。 -- 网站发布检查覆盖首页和网站后端。排查账户或登录时,分别查看 `systemctl status autolibrary-casdoor.service` 和 `curl -fsS http://127.0.0.1:8000/.well-known/openid-configuration`。 -- 发生业务回归时,用 `git revert` 后推送 `main` 重新构建上一份可用代码。紧急切回已有目录时,先确保 Runner 没有在部署,再按 [Ubuntu 部署说明](migration-to-ubuntu.md#回滚) 切换 `current`。清理历史发布目录前确认其未被 `current` 使用,并至少保留一个可用的上一版。 -- 自动回滚切换的是程序和静态文件。涉及数据库结构变化时,上线前备份共享数据,并确认旧版本兼容变更后的结构。 diff --git a/docs/migration-to-ubuntu.md b/docs/migration-to-ubuntu.md deleted file mode 100644 index 549da8d..0000000 --- a/docs/migration-to-ubuntu.md +++ /dev/null @@ -1,122 +0,0 @@ -# AutoLibrary Ubuntu 部署与迁移 - -日常发布可交给 [Gitea 自动部署](gitea-deployment.md)。本页用于首次迁移、数据备份与人工恢复。 - -## 部署组成 - -- Go 服务器:`webserver frontend`、`webserver backend`,或 `webserver start` 同时运行。 -- 前端构建:Vue 应用的 `frontend/dist`,部署后无需 Node 服务。 -- 运行数据:现有的三个 SQLite 数据库、主题文件目录、Casdoor 数据与配置。 -- 入口:Nginx 继续反向代理 Go 前端;Go 将 `/api/*` 去掉 `/api` 前缀后代理到后端。 - -保留当前实际端口和域名。仓库内 Nginx 示例使用前端 3003、后端 8080,通用配置示例使用前端 3000。以部署机 `config.json` 为准。 - -## 1. 准备新版本 - -开发或构建机器需要 Go 1.25.6+ 和 Node.js 22.13+。推荐使用 Node 当前 LTS。 - -```sh -npm --prefix frontend ci -npm --prefix frontend run build -go test ./... -go build -o webserver . -``` - -SQLite 驱动使用 CGO;建议在 Ubuntu 上安装 `build-essential` 并在目标平台构建 Go 可执行文件,不要把 Windows 可执行文件直接部署到 Linux。 - -为每次发布准备单独目录,例如 `/opt/autolibrary/releases/20261016`。目录应包含: - -```text -webserver -frontend/dist/ -backend/templates/ -config.json # 部署机自己的配置,不用示例覆盖 -``` - -保留 `frontend/dist` 中的完整资源目录,包括字体、截图与品牌图标。 - -## 2. 备份运行数据 - -停止旧 AutoLibrary 服务,保证 SQLite 备份与主题文件一致,再备份: - -- 原部署程序和前端资源。 -- `config.json`。 -- `versions.db`、`bulletins.db`、`themes.db`,以及存在的 `-wal`、`-shm` 文件。 -- 整个 `themes_files` 目录。 -- Casdoor 数据库、证书和配置。 - -本次不重置数据库或 Casdoor。使用部署机既有账户;不要重新导入初始化数据覆盖账户。 - -## 3. 配置路径 - -推荐将持久数据放在 `/opt/autolibrary/shared/`,在 `config.json` 中使用绝对路径。例如: - -```json -{ - "backend": { - "host": "127.0.0.1", - "port": "8080", - "database": { - "versions": { "path": "/opt/autolibrary/shared/versions.db" }, - "bulletins": { "path": "/opt/autolibrary/shared/bulletins.db" }, - "themes": { "path": "/opt/autolibrary/shared/themes.db" }, - "themes_files": { "path": "/opt/autolibrary/shared/themes_files" } - } - }, - "frontend": { - "host": "127.0.0.1", - "port": "3003", - "static": { "path": "./frontend/dist" } - } -} -``` - -以上仅展示需调整的字段;合并至实际完整配置,保留原 API Key、Casdoor client ID、secret 和证书。完整无密钥模板见根目录 `config.example.json`。 - -旧配置若仍指向 `frontend/public`,服务器在其同级找到 `dist/index.html` 时会使用新构建;仍建议显式改为 `frontend/dist`。 - -启动会为版本表添加 `gitea_*_url` 和 `release_notes_url` 列,不删除旧字段。历史 GitHub 下载地址不会被盲目改写。通过原版本管理 API 填入真实 Gitea 下载地址;未填写时,新官网引导访问 Gitea 发行页,云盘仍按原数据提供。 - -## 4. systemd - -将 `/opt/autolibrary/current` 指向当前发布目录,并配置: - -```ini -[Unit] -Description=AutoLibrary Website -After=network.target - -[Service] -Type=simple -WorkingDirectory=/opt/autolibrary/current -ExecStart=/opt/autolibrary/current/webserver start --config /opt/autolibrary/shared/config.json -Restart=on-failure -RestartSec=5 -TimeoutStopSec=20 - -[Install] -WantedBy=multi-user.target -``` - -Go 服务收到 SIGTERM 后先等待请求结束,再关闭数据库。Casdoor 继续使用原独立服务运行;若配置了服务依赖,沿用现有的 Casdoor unit 名称。 - -Nginx 通常无需更改。检查 `proxy_pass` 指向的端口与当前配置一致。`/changelog` 的永久跳转和页面路由由 Go 处理;不要增加将所有未知资源重写到首页的规则。 - -## 5. 上线验证 - -```sh -curl -I http://127.0.0.1:3003/ -curl -I http://127.0.0.1:3003/marketplace/profile -curl -I http://127.0.0.1:3003/changelog -curl -i http://127.0.0.1:3003/not-a-real-page -curl http://127.0.0.1:3003/api/download/latest -curl http://127.0.0.1:8080/health -``` - -应分别得到页面成功、深层页面成功、301 跳转 `/downloads`、404、真实稳定版或空数据、健康状态。检查浏览器中的深浅主题、下载入口、市场筛选、登录、主题上传与管理员审核。 - -网站不再实时请求 GitHub 或 Gitea API 获取版本。发行说明与源码入口统一使用 Gitea;公告服务仍保留。 - -## 回滚 - -如需回滚,停止新服务,将 `current` 指回旧发布目录并恢复原配置,再启动旧程序。新增版本列属于增量改动,旧程序可忽略;若要恢复上线前的数据状态,应在停服后恢复同一批备份的数据库和主题文件。不要只回滚其中一部分。 diff --git a/frontend/src/components/DownloadSource.vue b/frontend/src/components/DownloadSource.vue index 3d9b26d..38526f4 100644 --- a/frontend/src/components/DownloadSource.vue +++ b/frontend/src/components/DownloadSource.vue @@ -50,12 +50,12 @@ async function copyPassword(password: string) { @keydown.esc.stop.prevent="close" > - {{ source === 'gitea' ? 'Gitea 下载' : '云盘下载' }} + {{ source === 'gitea' ? 'Gitea 发布' : '云盘下载' }}
diff --git a/frontend/src/pages/DownloadsPage.vue b/frontend/src/pages/DownloadsPage.vue index 625ca2f..37ccd86 100644 --- a/frontend/src/pages/DownloadsPage.vue +++ b/frontend/src/pages/DownloadsPage.vue @@ -17,9 +17,13 @@ const meta = ref({ page: 1, per_page: 9, total: 0, total_pages: 0, has const loading = ref(true), error = ref(''), notice = ref('') -const platform = ref<'windows' | 'macos'>( +const preferredPlatform = ref<'windows' | 'macos'>( /Mac|iPhone|iPad/i.test(navigator.userAgent) ? 'macos' : 'windows', ) +const hasMacOS = computed(() => + Boolean(safeUrl(selected.value?.giteaDmgUrl) || safeUrl(selected.value?.cloudDmgUrl)), +) +const platform = computed(() => (hasMacOS.value ? preferredPlatform.value : 'windows')) const cache = new Map() let generation = 0 const downloadSources = computed(() => { @@ -130,7 +134,7 @@ onMounted(() => load(1, true))