# 项目概述 个人浏览器首页导航应用,支持书签分类管理、搜索引擎快捷搜索、 必应每日壁纸轮播、前后端分离部署,适配 1Panel 服务器(Docker 模式)。 # 技术栈 - 前端:Vue 3 + TypeScript + Vite + Pinia + Capacitor(Android 打包) - 后端:.NET 8 + SqlSugar(多数据库) + SQLite/MySQL + Swashbuckle - 部署:1Panel 应用商店自定义应用(Docker Compose 模式) # 项目结构 - backend/ .NET 8 API 后端(8 个 Controller + 15 个 Service) - frontend/ Vue 3 前端(19 个组件 + 9 个 API 模块 + 5 个 Store) - docker/ Docker 部署文件(后端镜像 + Nginx 反代) - docs/ 部署手册(1Panel 实战版) - scripts/ E2E 测试脚本 # 已实现功能 - 书签管理:增删改查 + 树形分类 + 拖拽排序 + 主色自适应 - 搜索引擎:8 个内置引擎 + 自定义引擎 + favicon 自动抓取 - 必应壁纸:每日轮播 + 多分辨率自动选择 + 1.6MP 质量优先 - 全局设置:主题/行为/数据/工具 4 分类 + 跨设备同步 - 文件上传:图标/书签/通用(容器持久化 + 跨域 URL 拼接) - 同步:基于变更日志的设备间数据同步 - 跨域部署:前后端分离 + runtime config.json 无需重新编译 # 进度记录 - 已完成 P0~P52 共 53 个开发节点(详细见 说明文档.md) - 当前版本:v1.0 部署就绪 # 部署文档 - README.md:项目说明 + 快速开始 - 说明文档.md:完整开发进度(中文) - docs/DEPLOY.md:1Panel 部署手册(Docker 模式)
12 KiB
MyHomePage 1Panel 部署手册
适用环境:服务器已装 1Panel(v2.x)+ 1Panel 内置 MySQL(已部署并启动) 全程不碰 Docker / nginx.conf / systemd —— 全部交给 1Panel 面板管理
一、部署架构
[公网/局域网]
│
┌───────────────┴───────────────┐
│ │
域名 A(前端) 域名 B(后端,可选)
│ │
▼ ▼
1Panel 静态网站 1Panel .NET 运行时
(Nginx 反代) (Kestrel)
│ │
│ /api/* 反代到 127.0.0.1:8080 │
└──────────────┐ ┌──────────────┘
▼ ▼
1Panel MySQL
(本机 127.0.0.1:3306)
一句话总结:MySQL 已部署 + 前端走静态网站 + 后端走 .NET 运行环境 = 三步上线。
二、前置准备
2.1 服务器侧
| 条件 | 说明 |
|---|---|
| 1Panel v2.x | 已装好(主人的情况) |
| MySQL 实例 | 1Panel 应用商店装的 MySQL,已 running |
| 域名 | 可选:解析 A 记录到服务器 IP;没域名也能用 IP+端口 |
| 1Panel 防火墙 | 默认放行 80/443;后端用 8080 需手动放行 |
2.2 本地编译
2.2.1 编译后端
cd d:\Code\MyHomePage\backend
dotnet publish -c Release -o ..\publish\backend
产物:publish\backend\(约 80MB,含 .dll / appsettings.json / wwwroot/ 等)。
2.2.2 编译前端
cd d:\Code\MyHomePage\frontend
npm install # 首次或依赖变化时
npm run build
产物:frontend\dist\(约 400KB,含 index.html / assets/)。
2.3 上传产物到服务器
方式 1:1Panel 文件管理(推荐,Web 拖拽)
- 1Panel → 文件 → 进入
/opt/1panel/apps/ - 新建两个文件夹:
myhomepage-backend/myhomepage-frontend - 分别拖入编译产物
方式 2:scp 上传(打 zip 后传一次)
cd d:\Code\MyHomePage
Compress-Archive -Path publish\backend,frontend\dist -DestinationPath myhomepage.zip
scp myhomepage.zip root@your-server:/opt/1panel/apps/
服务器侧:
cd /opt/1panel/apps/
unzip myhomepage.zip
mv publish/backend myhomepage-backend
mv frontend/dist myhomepage-frontend
三、第一步:1Panel 准备 MySQL
3.1 创建数据库
- 1Panel → 数据库 → MySQL → 你的实例 → 创建数据库
- 数据库名:
myhomepage - 字符集:
utf8mb4 - 排序规则:
utf8mb4_unicode_ci
3.2 创建用户并授权
- 1Panel → 数据库 → MySQL → 你的实例 → 创建用户
- 用户名:
myhomepage_user - 密码:自定义或自动生成(复制保存!)
- 主机:
localhost(只允许本机连接,禁止公网) - 授权:库
myhomepage,权限ALL
3.3 记录连接信息
| 字段 | 值 |
|---|---|
| host | 127.0.0.1 |
| port | 3306 |
| database | myhomepage |
| user | myhomepage_user |
| password | (你刚设的) |
四、第二步:部署后端
4.1 上传后端文件
把 publish\backend\ 内所有文件传到 /opt/1panel/apps/myhomepage-backend/。
最终目录结构(参考):
/opt/1panel/apps/myhomepage-backend/
├── MyHomePage.Api.dll
├── appsettings.json
├── appsettings.Production.json
├── web.config # 1Panel 运行环境会自动生成
├── Uploads/ # 后面建
├── wwwroot/ # 后端静态资源(如果有)
└── ...
4.2 创建 .NET 网站
- 1Panel → 网站 → 创建网站
- 类型:选择「运行环境」标签 → 选 .NET(如果应用商店没装 .NET Runtime,先去应用商店搜
.NET安装) - 主域名:填后端域名(如
api.example.com),或留空用IP:8080 - 端口:
8080 - 代号:
myhomepage-api - 网站目录:
/opt/1panel/apps/myhomepage-backend - 启动命令:
dotnet MyHomePage.Api.dll --urls http://0.0.0.0:8080
4.3 配置环境变量
在创建好的网站详情页 → 「环境变量」或「配置文件」tab,添加:
| 变量名 | 值 | 说明 |
|---|---|---|
ASPNETCORE_ENVIRONMENT |
Production |
启用生产配置 |
Database__Provider |
MySql |
切换到 MySQL |
Database__ConnectionString |
server=127.0.0.1;port=3306;database=myhomepage;user=myhomepage_user;password=你的密码;charset=utf8mb4; |
连接串 |
Upload__Path |
/opt/1panel/apps/myhomepage-backend/Uploads |
上传文件落盘路径 |
Upload__BaseUrl |
https://你的前端域名/uploads |
前端拼接 URL 前缀 |
Cors__Origins__0 |
https://你的前端域名 |
允许跨域的白名单(必须) |
双下划线
__是 ASP.NET Core 配置嵌套的语法,等价于 JSON 里的{ "Cors": { "Origins": [ ... ] } }。 如果主人在前端用VITE_API_BASE=https://api.example.com直接走独立域名,跨域问题更彻底。
4.4 创建上传目录
- 1Panel → 文件 → 在
/opt/1panel/apps/myhomepage-backend/下新建Uploads/ - 权限 755(默认即可)
4.5 启动后端
- 网站详情页 → 启动 按钮
- 等 5-10 秒 → 日志 tab 应该看到:
Now listening on: http://0.0.0.0:8080 Application started.
4.6 本地验证
# 服务器侧
curl http://127.0.0.1:8080/health
# 期望:OK
看到 200 = 后端已就绪 ✅
五、第三步:部署前端
5.1 上传前端文件
把 frontend\dist\ 内所有文件传到 /opt/1panel/apps/myhomepage-frontend/。
5.2 创建静态网站
- 1Panel → 网站 → 创建网站
- 类型:选择「静态网站」标签
- 主域名:填前端域名(如
home.example.com) - 端口:
80(HTTP)或443(HTTPS) - 代号:
myhomepage-web - 网站目录:
/opt/1panel/apps/myhomepage-frontend
5.3 申请 SSL(强烈推荐)
- 网站详情页 → SSL → 申请 → Let's Encrypt
- 1Panel 自动续期
5.4 配置反向代理(关键!)
网站详情页 → 反向代理 或直接编辑 配置文件(Nginx),加这段:
# /api/* 转发到后端
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 60s;
}
# /uploads/* 转发到后端(用户上传图片)
location /uploads/ {
proxy_pass http://127.0.0.1:8080;
}
如果前端
.env.production配了VITE_API_BASE=https://api.example.com,跳过本节(前后端走不同域名更干净)。
5.5 验证前端
浏览器打开 https://你的前端域名/ → 看到首页 = 成功 ✅
六、第四步:联调验证
6.1 必查清单
- 浏览器打开前端 → 首页正常渲染
- DevTools → Network → 5 个 API 请求(settings / categories / bookmarks / search-engines / wallpaper)全部 200
- 新建一个分类 + 一个链接 → 刷新页面看是否持久化
- 切换主题 / 主色调 → 刷新看是否持久化
- 上传一张图片 → 看是否显示
- 360 壁纸功能(在设置里启用)→ 切换间隔生效
6.2 Android APP 后端地址
主人后续会打包 Android。.env.production 或 Capacitor 配置里填:
# 同域名反代
https://你的前端域名/api
# 或独立后端域名
https://api.example.com
七、日常运维
7.1 看日志
- 1Panel → 网站 → 你的网站 → 日志 tab
- 实时滚动 / 可下载 .log 文件
- 排错先看这里 ✅
7.2 重启服务
- 1Panel → 网站 → 你的网站 → 重启 按钮
- 5-10 秒生效
7.3 备份数据库
- 1Panel → 数据库 → MySQL → 你的实例 → 备份
- 1Panel 默认每天自动备份到本地目录
- 也可「立即备份」→ 下载到本地双保险
7.4 更新后端
# 本地
cd d:\Code\MyHomePage\backend
dotnet publish -c Release -o ..\publish\backend
- 1Panel → 文件 →
/opt/1panel/apps/myhomepage-backend/→ 覆盖上传所有文件 - 1Panel → 网站 → myhomepage-api → 重启
7.5 更新前端
# 本地
cd d:\Code\MyHomePage\frontend
npm run build
- 1Panel → 文件 →
/opt/1panel/apps/myhomepage-frontend/→ 覆盖上传所有文件 - 静态网站无需重启,浏览器 Ctrl+F5 强刷即可
7.6 紧急回滚
| 想回滚 | 操作 |
|---|---|
| 后端代码 | 1Panel → 文件 → 把后端目录回退到上一版 → 重启 |
| 前端代码 | 1Panel → 文件 → 把前端目录回退到上一版 → 强刷 |
| 数据库 | 1Panel → 数据库 → 选昨天的备份 → 恢复(会覆盖当前数据) |
八、常见问题
Q1:前端打开是白屏
- 1Panel → 网站 → 静态网站 → 日志查 404
- 大概率是
index.html没传,或assets/目录没传全
Q2:API 全部 404
- 检查第五步 5.4 的反向代理是否生效
- 服务器本地
curl http://127.0.0.1:8080/health验证后端活着
Q3:CORS 跨域报错
- 检查第四步 4.3 的
Cors__Origins__0是否设了前端完整域名(含https://) - 重启后端
Q4:数据库连接失败
- 1Panel → 数据库 → MySQL → 看实例 running
- 服务器本地
mysql -u myhomepage_user -p验证能登 - 检查连接串的
password=是不是带特殊字符(需要 URL encode)
Q5:上传图片 500
- 检查
/opt/1panel/apps/myhomepage-backend/Uploads/权限 755 - 服务器
df -h看磁盘
Q6:移动端 / Android APP 访问不到
- 1Panel 防火墙放行 8080(如果不走反代)
- 或在 Android 里直接填
https://你的前端域名/api(走反代最稳)
Q7:360 壁纸不显示
- 后端环境变量里
Upload__BaseUrl和Cors__Origins__0都填前端完整域名 - 服务器能访问外网(curl
https://wallpaper.apc.360.cn验证)
附录 A:环境变量速查表
| 变量 | 必填 | 示例值 | 说明 |
|---|---|---|---|
ASPNETCORE_ENVIRONMENT |
是 | Production |
启用生产配置 |
Database__Provider |
是 | MySql |
固定值 |
Database__ConnectionString |
是 | server=127.0.0.1;port=3306;database=myhomepage;user=myhomepage_user;password=xxx;charset=utf8mb4; |
MySQL 连接串 |
Upload__Path |
是 | /opt/1panel/apps/myhomepage-backend/Uploads |
上传落盘绝对路径 |
Upload__BaseUrl |
是 | https://home.example.com/uploads |
前端拼接 URL 前缀 |
Cors__Origins__0 |
是 | https://home.example.com |
跨域白名单(多域名时加 Cors__Origins__1) |
附录 B:目录结构速查
/opt/1panel/apps/
├── myhomepage-backend/
│ ├── MyHomePage.Api.dll
│ ├── appsettings.json
│ ├── appsettings.Production.json
│ ├── Uploads/ # 用户上传
│ └── ...
└── myhomepage-frontend/
├── index.html
├── assets/
│ ├── index-xxxxxx.js
│ └── index-xxxxxx.css
└── ...