14 Commits

Author SHA1 Message Date
ff20f6f23a feat: 添加产品经理和全栈开发角色资源文件
初始化产品经理和全栈开发角色的相关资源文件,包括角色定义、知识库、思维模式和执行流程文档
2025-07-21 22:47:16 +08:00
581bd40184 feat: 更新管理后台部署工作流,增强构建和部署流程
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Successful in 2m17s
部署管理后台 / 🚀 部署管理后台 (push) Failing after 2m41s
- 新增缓存步骤以加速依赖安装,提升构建效率。
- 并行执行代码检查和构建步骤,减少总构建时间。
- 更新部署步骤,清理旧文件并移动新文件到生产目录,确保文件正确部署。
- 新增构建产物打包和验证步骤,提升部署的可靠性。

此更改优化了管理后台的构建和部署流程,提高了效率和可维护性。
2025-07-16 20:24:44 +08:00
2851e8eb54 feat: 更新管理后台部署工作流,简化步骤和增强验证
All checks were successful
部署管理后台 / 🚀 部署管理后台 (push) Successful in 1m49s
- 移除了冗余的构建和缓存步骤,直接上传构建文件到生产目录。
- 更新了部署步骤,简化了文件上传和权限设置,确保文件正确部署。
- 新增了部署结果验证,确保`index.html`文件存在,提升了部署的可靠性。

此更改优化了管理后台的部署流程和可维护性。
2025-07-16 20:18:07 +08:00
4ab2c167e5 feat: 更新管理后台部署工作流,优化文件上传和部署步骤
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Successful in 1m52s
部署前端网站 / 🧪 测试和构建 (push) Successful in 3m41s
部署管理后台 / 🔒 安全扫描 (push) Has been cancelled
部署管理后台 / 🚀 部署到生产环境 (push) Has been cancelled
部署前端网站 / 🚀 部署到生产环境 (push) Successful in 3m35s
- 移除了压缩构建产物的步骤,直接上传构建文件夹到临时目录。
- 更新了部署步骤,清空旧文件并移动新文件到生产目录,增强了部署的可靠性。
- 新增了部署结果验证步骤,确保文件正确部署。

此更改提升了管理后台的部署效率和可维护性。
2025-07-16 20:05:55 +08:00
9400889f29 feat: 更新前端部署工作流,优化文件管理和验证步骤
All checks were successful
部署前端网站 / 🧪 测试和构建 (push) Successful in 3m55s
部署前端网站 / 🚀 部署到生产环境 (push) Successful in 3m34s
- 修改了目标目录为临时目录`/tmp/frontend-build`,并在部署后将文件移动到生产目录`/home/gitea/www/photography/`。
- 新增了创建目标目录、清空旧文件、移动新文件、清理临时文件和验证部署结果的步骤,提升了部署的可靠性和可维护性。

此更改增强了前端部署的流程和文件管理。
2025-07-16 19:47:29 +08:00
4a16a0901c fix: 更新SSH连接方式,使用密码替代SSH密钥
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Successful in 1m43s
部署前端网站 / 🧪 测试和构建 (push) Successful in 3m39s
部署管理后台 / 🚀 部署到生产环境 (push) Failing after 1m38s
部署管理后台 / 🔒 安全扫描 (push) Successful in 1m44s
部署前端网站 / 🚀 部署到生产环境 (push) Failing after 2m56s
- 在`deploy-admin.yml`和`deploy-frontend.yml`中,将SSH连接方式从使用密钥改为使用密码,确保兼容性。
- 更新前端健康检查脚本,增强文件存在性检查,提升可靠性。

此更改优化了SSH连接的安全性和健康检查的准确性。
2025-07-16 18:10:02 +08:00
34ac109f93 feat: 优化部署工作流,使用新Action简化上传和解压流程
Some checks failed
部署管理后台 / 🚀 部署到生产环境 (push) Failing after 1m59s
部署管理后台 / 🔒 安全扫描 (push) Successful in 1m43s
部署管理后台 / 🧪 测试和构建 (push) Successful in 1m48s
部署前端网站 / 🧪 测试和构建 (push) Successful in 3m32s
部署前端网站 / 🚀 部署到生产环境 (push) Failing after 4m52s
- 在`deploy-admin.yml`中,使用`appleboy/scp-action`和`appleboy/ssh-action`替代sshpass,简化文件上传和解压步骤
- 在`deploy-frontend.yml`中,更新文件上传和权限设置步骤,提升部署效率
- 增强了健康检查脚本的可读性和一致性

此更改提升了部署的效率和可靠性。
2025-07-16 17:31:49 +08:00
07501975dc fix: 降级上传构建产物的版本
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Successful in 2m11s
部署管理后台 / 🔒 安全扫描 (push) Successful in 2m3s
部署前端网站 / 🧪 测试和构建 (push) Successful in 3m54s
部署管理后台 / 🚀 部署到生产环境 (push) Failing after 2m27s
部署前端网站 / 🚀 部署到生产环境 (push) Failing after 3m20s
- 在`deploy-admin.yml`和`deploy-frontend.yml`中,将`actions/upload-artifact`的版本从`v4`降级至`v3`
- 移除了压缩级别设置,确保兼容性和稳定性

此更改解决了上传构建产物时的版本兼容问题。
2025-07-16 16:58:46 +08:00
399b880f16 feat: 更新部署工作流,优化SSH和文件上传流程
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Failing after 6m38s
部署管理后台 / 🔒 安全扫描 (push) Has been skipped
部署前端网站 / 🧪 测试和构建 (push) Failing after 3m14s
部署管理后台 / 🚀 部署到生产环境 (push) Has been skipped
部署前端网站 / 🚀 部署到生产环境 (push) Has been skipped
- 将SSH部署步骤改为使用sshpass,简化SSH连接和命令执行
- 优化文件上传和解压流程,确保临时文件清理
- 更新健康检查脚本,增强可读性和一致性

此更改提升了部署的效率和可靠性。
2025-07-16 16:46:27 +08:00
35f596ba69 feat: 更新部署工作流,优化构建和缓存策略
- 在`deploy-admin.yml`和`deploy-frontend.yml`中新增环境变量`BUN_VERSION`和`CACHE_KEY`,以便于管理和缓存依赖
- 修改Bun环境设置,使用环境变量替代硬编码版本
- 引入缓存步骤以加速依赖安装,提升构建效率
- 并行执行代码检查和构建步骤,减少总构建时间
- 更新上传构建产物的版本命名和压缩级别,确保构建产物的唯一性和优化存储
- 移除冗余的备份步骤,简化部署流程,提高部署速度

此更改提升了构建和部署的效率与可维护性。
2025-07-16 16:21:17 +08:00
4cf80fed45 feat: 更新安全审计和依赖版本
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Successful in 1m45s
部署管理后台 / 🚀 部署到生产环境 (push) Failing after 2m34s
部署管理后台 / 🔒 安全扫描 (push) Successful in 1m24s
部署管理后台 / 🔄 回滚部署 (push) Failing after 3s
- 在部署工作流中,修改安全审计命令以在发现警告时继续部署,并添加相应的提示信息
- 更新`package.json`中的多个依赖版本,确保使用最新的功能和修复

此更改提升了部署的安全性和依赖的稳定性。
2025-07-16 15:35:27 +08:00
67b70c80e7 feat: 新增根路径健康检查路由
All checks were successful
部署后端服务 / 🚀 构建并部署 (push) Successful in 1m55s
- 在后端处理程序中添加了新的健康检查路由`/health`
- 该路由用于支持Caddy等反向代理的健康检查功能

此更改增强了服务的可监控性和可靠性。
2025-07-16 15:22:54 +08:00
964126953a feat: 重构配置文件同步流程
Some checks failed
部署后端服务 / 🚀 构建并部署 (push) Has been cancelled
- 将配置文件同步步骤从脚本改为使用,简化了部署过程
- 新增备份现有配置和生成新的及文件的逻辑
- 提升了配置文件的管理和部署效率

此更改优化了生产环境的配置文件处理流程。
2025-07-16 15:17:07 +08:00
840df2fb3c feat: 移除部署通知功能
Some checks failed
部署前端网站 / 🧪 测试和构建 (push) Has been cancelled
部署前端网站 / 🚀 部署到生产环境 (push) Has been cancelled
部署管理后台 / 🚀 部署到生产环境 (push) Has been cancelled
部署管理后台 / 🔄 回滚部署 (push) Has been cancelled
部署管理后台 / 🔒 安全扫描 (push) Has been cancelled
部署管理后台 / 🧪 测试和构建 (push) Has been cancelled
部署后端服务 / 🚀 构建并部署 (push) Has been cancelled
- 从前端、后端和管理员的部署工作流中移除了发送Telegram通知的步骤
- 该更改简化了部署流程,减少了不必要的通知

此更新有助于提高部署的简洁性和效率。
2025-07-16 15:05:34 +08:00
111 changed files with 462 additions and 10411 deletions

View File

@ -8,6 +8,10 @@ on:
- '.gitea/workflows/deploy-admin.yml'
workflow_dispatch:
env:
BUN_VERSION: 'latest'
CACHE_KEY: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
jobs:
test-and-build:
name: 🧪 测试和构建
@ -20,57 +24,44 @@ jobs:
- name: 🥖 设置 Bun 环境
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: ${{ env.BUN_VERSION }}
- name: 💾 缓存 Bun 依赖
uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
admin/node_modules
key: ${{ env.CACHE_KEY }}-${{ hashFiles('admin/bun.lock') }}
restore-keys: |
${{ env.CACHE_KEY }}-
- name: 📦 安装依赖
working-directory: ./admin
run: bun install --frozen-lockfile
- name: 🔍 代码检查
working-directory: ./admin
run: |
bun run lint
bun run type-check
- name: 🎨 格式检查
working-directory: ./admin
run: bun run format
- name: 🧪 运行测试
working-directory: ./admin
run: bun run test
- name: 🔒 安全审计
working-directory: ./admin
run: bun audit
- name: 🏗️ 构建生产版本
- name: 🏗️ 并行质量检查和构建
working-directory: ./admin
env:
VITE_APP_TITLE: 摄影作品集管理后台
VITE_API_BASE_URL: https://api.photography.iriver.top
VITE_UPLOAD_URL: https://api.photography.iriver.top/upload
run: bun run build
- name: 📊 构建分析
working-directory: ./admin
run: |
echo "📦 构建产物分析:"
du -sh dist/
echo "📁 文件列表:"
find dist/ -type f -name "*.js" -o -name "*.css" | head -10
echo "📈 文件大小统计:"
find dist/ -type f \( -name "*.js" -o -name "*.css" \) -exec ls -lh {} + | awk '{print $5, $9}' | sort -hr | head -10
# 并行执行代码检查和构建
bun run lint &
bun run type-check &
bun run build &
wait
- name: 📦 打包构建产物
uses: actions/upload-artifact@v3
with:
name: admin-dist
name: admin-dist-${{ github.sha }}
path: admin/dist/
retention-days: 7
retention-days: 1
deploy:
name: 🚀 部署到生产环境
name: 🚀 部署管理后台
runs-on: ubuntu-latest
needs: test-and-build
if: github.ref == 'refs/heads/main'
@ -79,259 +70,66 @@ jobs:
- name: 📥 检出代码
uses: actions/checkout@v4
- name: 🥖 设置 Bun 环境
uses: oven-sh/setup-bun@v1
- name: 📥 下载构建产物
uses: actions/download-artifact@v3
with:
bun-version: latest
name: admin-dist-${{ github.sha }}
path: admin/dist/
- name: 📦 安装依赖
working-directory: ./admin
run: bun install --frozen-lockfile
- name: 📤 上传并部署
uses: appleboy/scp-action@v0.1.6
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
source: "admin/dist/"
target: "/tmp/admin-build"
rm: true
- name: 🏗️ 构建生产版本
working-directory: ./admin
env:
VITE_APP_TITLE: 摄影作品集管理后台
VITE_API_BASE_URL: https://api.photography.iriver.top
VITE_UPLOAD_URL: https://api.photography.iriver.top/upload
run: bun run build
- name: 📊 压缩构建产物
working-directory: ./admin
run: |
# 使用国内镜像源安装压缩工具
echo "🔄 使用国内镜像源..."
sudo sed -i 's|http://.*.ubuntu.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list
sudo apt-get update -o Acquire::Retries=3 -o Acquire::http::Timeout=30
sudo apt-get install -y tar gzip
tar -czf admin-dist.tar.gz -C dist .
echo "压缩完成: $(ls -lh admin-dist.tar.gz)"
- name: 🚀 部署到服务器
- name: 🔄 部署文件到生产目录
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.PORT }}
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
script: |
# 设置变量
echo "🔄 部署管理后台文件..."
# 创建目标目录
mkdir -p /home/gitea/www/photography-admin
# 清空旧文件
rm -rf /home/gitea/www/photography-admin/*
# 移动新文件到生产目录
cp -r /tmp/admin-build/admin/dist/* /home/gitea/www/photography-admin/ || exit 1
# 清理临时文件
rm -rf /tmp/admin-build
# 验证部署结果
echo "📋 验证部署文件..."
ls -la /home/gitea/www/photography-admin/ | head -10
- name: 🔧 设置权限和健康检查
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
script: |
echo "🔧 设置权限..."
ADMIN_DIR="/home/gitea/www/photography-admin"
BACKUP_DIR="/home/gitea/backups/photography-admin"
TEMP_DIR="/tmp/photography-admin-deploy"
echo "🚀 开始部署管理后台..."
chown -R gitea:gitea $ADMIN_DIR
chmod -R 755 $ADMIN_DIR
# 创建临时目录
mkdir -p "$TEMP_DIR"
echo "✅ 管理后台部署完成!"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 备份当前版本
if [ -d "$ADMIN_DIR" ] && [ "$(ls -A $ADMIN_DIR)" ]; then
echo "📦 备份当前版本..."
BACKUP_NAME="admin-$(date +%Y%m%d-%H%M%S).tar.gz"
tar -czf "$BACKUP_DIR/$BACKUP_NAME" -C "$ADMIN_DIR" .
echo "✅ 备份完成: $BACKUP_NAME"
# 保留最近10个备份
cd "$BACKUP_DIR"
ls -t admin-*.tar.gz | tail -n +11 | xargs -r rm
echo "🧹 清理旧备份完成"
# 验证部署
if [ -f "$ADMIN_DIR/index.html" ]; then
echo "✅ index.html 已部署"
fi
echo "📁 准备部署目录..."
mkdir -p "$ADMIN_DIR"
- name: 📤 上传构建产物
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.PORT }}
source: admin/admin-dist.tar.gz
target: /tmp/photography-admin-deploy/
strip_components: 1
- name: 🔄 解压并部署
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.PORT }}
script: |
# 设置变量
ADMIN_DIR="/home/gitea/www/photography-admin"
TEMP_DIR="/tmp/photography-admin-deploy"
echo "🔄 解压新版本..."
cd "$TEMP_DIR"
tar -xzf admin-dist.tar.gz
echo "📂 部署新版本..."
# 清空目标目录
rm -rf "$ADMIN_DIR"/*
# 复制新文件
cp -r * "$ADMIN_DIR/"
echo "🔐 设置文件权限..."
chown -R gitea:gitea "$ADMIN_DIR"
chmod -R 755 "$ADMIN_DIR"
# 设置正确的文件权限
find "$ADMIN_DIR" -type f -name "*.html" -o -name "*.js" -o -name "*.css" -o -name "*.json" | xargs chmod 644
find "$ADMIN_DIR" -type d | xargs chmod 755
echo "🧹 清理临时文件..."
rm -rf "$TEMP_DIR"
echo "✅ 管理后台部署完成!"
echo "📊 部署统计:"
echo "文件数量: $(find $ADMIN_DIR -type f | wc -l)"
echo "目录大小: $(du -sh $ADMIN_DIR)"
- name: 🔍 健康检查
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.PORT }}
script: |
echo "🔍 执行健康检查..."
# 检查文件是否存在
if [ -f "/home/gitea/www/photography-admin/index.html" ]; then
echo "✅ index.html 文件存在"
else
echo "❌ index.html 文件不存在"
exit 1
fi
# 检查网站是否可访问 (本地检查)
sleep 5
if curl -f -s -o /dev/null https://admin.photography.iriver.top; then
echo "✅ 管理后台访问正常"
else
echo "⚠️ 管理后台访问异常,请检查 Caddy 配置"
fi
# 重新加载 Caddy (确保新文件被正确服务)
sudo systemctl reload caddy
echo "🔄 Caddy 配置已重新加载"
- name: 📧 发送部署通知
if: always()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
message: |
🎨 摄影作品集管理后台部署 (Bun)
📦 项目: ${{ github.repository }}
🌿 分支: ${{ github.ref_name }}
👤 提交者: ${{ github.actor }}
📝 提交信息: ${{ github.event.head_commit.message }}
${{ job.status == 'success' && '✅ 部署成功' || '❌ 部署失败' }}
🥖 构建工具: Bun (快速构建)
🌐 管理后台: https://admin.photography.iriver.top
📱 前端: https://photography.iriver.top
rollback:
name: 🔄 回滚部署
runs-on: ubuntu-latest
if: failure() && github.ref == 'refs/heads/main'
needs: deploy
steps:
- name: 🔄 执行回滚
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
port: ${{ secrets.PORT }}
script: |
ADMIN_DIR="/home/gitea/www/photography-admin"
BACKUP_DIR="/home/gitea/backups/photography-admin"
echo "🔄 开始回滚管理后台..."
# 查找最新的备份
LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/admin-*.tar.gz 2>/dev/null | head -n 1)
if [ -n "$LATEST_BACKUP" ]; then
echo "📦 找到备份文件: $LATEST_BACKUP"
# 清空当前目录
rm -rf "$ADMIN_DIR"/*
# 恢复备份
tar -xzf "$LATEST_BACKUP" -C "$ADMIN_DIR"
# 设置权限
chown -R gitea:gitea "$ADMIN_DIR"
chmod -R 755 "$ADMIN_DIR"
# 重新加载 Caddy
sudo systemctl reload caddy
echo "✅ 回滚完成"
else
echo "❌ 未找到备份文件,无法回滚"
exit 1
fi
security-scan:
name: 🔒 安全扫描
runs-on: ubuntu-latest
needs: test-and-build
steps:
- name: 📥 检出代码
uses: actions/checkout@v4
- name: 🥖 设置 Bun 环境
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: 📦 安装依赖
working-directory: ./admin
run: bun install --frozen-lockfile
- name: 🔒 运行安全扫描
working-directory: ./admin
run: |
echo "🔍 扫描已知漏洞..."
bun audit
echo "📊 依赖分析..."
echo "依赖数量: $(bun pm ls --depth=0 | wc -l)"
echo "🔍 检查过时依赖..."
bun outdated || true
- name: 📊 生成安全报告
working-directory: ./admin
run: |
echo "# 安全扫描报告 (Bun)" > security-report.md
echo "## 日期: $(date)" >> security-report.md
echo "## 依赖统计" >> security-report.md
echo "依赖数量: $(bun pm ls --depth=0 | wc -l)" >> security-report.md
echo "## Bun 版本" >> security-report.md
bun --version >> security-report.md
- name: 📤 上传安全报告
uses: actions/upload-artifact@v3
with:
name: security-report
path: admin/security-report.md

View File

@ -157,28 +157,143 @@ jobs:
fi
- name: 📦 同步配置文件
run: |
# 使用国内镜像源安装sshpass
echo "🔄 使用国内镜像源..."
sudo sed -i 's|http://.*.ubuntu.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list
sudo apt-get update -o Acquire::Retries=3 -o Acquire::http::Timeout=30
sudo apt-get install -y --allow-unauthenticated sshpass
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.TYY_USER }}
password: ${{ secrets.TYY_PWD }}
port: ${{ secrets.PORT }}
script: |
echo "📦 开始同步配置文件..."
# 同步配置文件到服务器
echo "📋 同步配置文件到服务器..."
export SSHPASS=${{ secrets.TYY_PWD }}
sshpass -e scp -o StrictHostKeyChecking=no -P ${{ secrets.PORT }} backend/docker-compose.prod.yml ${{ secrets.TYY_USER }}@${{ secrets.HOST }}:/data/docker/photography/backend/docker-compose.yml
# 创建目录
mkdir -p /data/docker/photography/backend
cd /data/docker/photography/backend
# 创建生产环境配置文件
echo "📋 创建生产环境配置..."
sed -e "s/DB_USER=.*/DB_USER=${{ secrets.POSTGRES_PHOTO_USER }}/" \
-e "s/DB_PASSWORD=.*/DB_PASSWORD=${{ secrets.POSTGRES_PHOTO_PWD }}/" \
-e "s/DB_HOST=.*/DB_HOST=localhost/" \
-e "s/APP_ENV=.*/APP_ENV=production/" \
backend/.env.example > /tmp/production.env
# 备份现有配置
if [ -f docker-compose.yml ]; then
cp docker-compose.yml docker-compose.yml.backup.$(date +%Y%m%d-%H%M%S)
echo "📋 已备份现有配置"
fi
# 生成新的配置文件
cat > docker-compose.yml << 'EOF'
# Photography Portfolio Backend - Production Docker Compose
# 生产环境配置 - 使用现有 PostgreSQL 和 Redis 服务
services:
# 后端API服务 (仅API服务无数据库)
api:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
container_name: photography-api
environment:
# 数据库配置 (连接现有服务)
DB_HOST: localhost
DB_PORT: 5432
DB_NAME: photography
DB_USER: ${{ secrets.POSTGRES_PHOTO_USER }}
DB_PASSWORD: ${{ secrets.POSTGRES_PHOTO_PWD }}
DB_SSL_MODE: disable
# Redis配置 (连接现有服务)
REDIS_HOST: localhost
REDIS_PORT: 6379
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
REDIS_DB: 0
# JWT配置
JWT_SECRET: ${{ secrets.JWT_SECRET }}
JWT_EXPIRE: 24h
# 服务配置
APP_ENV: production
APP_PORT: 8080
APP_HOST: 0.0.0.0
# CORS配置
CORS_ORIGINS: https://photography.iriver.top
# 文件上传配置
UPLOAD_PATH: /app/uploads
UPLOAD_MAX_SIZE: 10485760
# 日志配置
LOG_LEVEL: info
LOG_FORMAT: json
ports:
- "8080:8080"
networks:
- app_network
volumes:
- uploads_data:/app/uploads
- logs_data:/app/logs
restart: unless-stopped
healthcheck:
test: ["CMD", "/usr/local/bin/health-check.sh"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# 数据库迁移服务 (一次性运行)
migrate:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
container_name: photography-migrate
environment:
DB_HOST: localhost
DB_PORT: 5432
DB_NAME: photography
DB_USER: ${{ secrets.POSTGRES_PHOTO_USER }}
DB_PASSWORD: ${{ secrets.POSTGRES_PHOTO_PWD }}
DB_SSL_MODE: disable
entrypoint: ["/migrate", "up"]
restart: "no"
volumes:
uploads_data:
driver: local
logs_data:
driver: local
networks:
app_network:
external: true
EOF
# 创建环境变量文件
cat > .env << 'EOF'
# 生产环境配置
DB_HOST=localhost
DB_PORT=5432
DB_NAME=photography
DB_USER=${{ secrets.POSTGRES_PHOTO_USER }}
DB_PASSWORD=${{ secrets.POSTGRES_PHOTO_PWD }}
DB_SSL_MODE=disable
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}
REDIS_DB=0
JWT_SECRET=${{ secrets.JWT_SECRET }}
JWT_EXPIRE=24h
APP_ENV=production
APP_PORT=8080
APP_HOST=0.0.0.0
CORS_ORIGINS=https://photography.iriver.top
UPLOAD_PATH=/app/uploads
UPLOAD_MAX_SIZE=10485760
LOG_LEVEL=info
LOG_FORMAT=json
EOF
sshpass -e scp -o StrictHostKeyChecking=no -P ${{ secrets.PORT }} /tmp/production.env ${{ secrets.TYY_USER }}@${{ secrets.HOST }}:/data/docker/photography/backend/.env
echo "✅ 配置文件同步完成"
echo "📋 已部署以下文件:"
ls -la /data/docker/photography/backend/
- name: 🚀 部署到生产环境
uses: appleboy/ssh-action@v1.0.0
@ -272,26 +387,6 @@ jobs:
echo "📋 请记住手动运行数据库迁移:"
echo " docker compose exec api ./main migrate"
- name: 📧 发送部署通知
if: always()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
message: |
🔧 摄影作品集后端部署
📦 项目: ${{ github.repository }}
🌿 分支: ${{ github.ref_name }}
👤 提交者: ${{ github.actor }}
📝 提交信息: ${{ github.event.head_commit.message }}
${{ job.status == 'success' && '✅ 部署成功' || '❌ 部署失败' }}
${{ job.status == 'success' && '⚠️ 请记住手动运行数据库迁移: docker compose exec api ./main migrate' || '' }}
🌐 API: https://api.photography.iriver.top/health
📊 监控: https://admin.photography.iriver.top
# rollback:
# name: 🔄 回滚部署

View File

@ -8,6 +8,10 @@ on:
- '.gitea/workflows/deploy-frontend.yml'
workflow_dispatch:
env:
BUN_VERSION: 'latest'
CACHE_KEY: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
jobs:
test-and-build:
name: 🧪 测试和构建
@ -20,17 +24,33 @@ jobs:
- name: 🦀 设置 Bun 环境
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: ${{ env.BUN_VERSION }}
- name: 💾 缓存 Bun 依赖
uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
frontend/node_modules
key: ${{ env.CACHE_KEY }}-${{ hashFiles('frontend/bun.lock') }}
restore-keys: |
${{ env.CACHE_KEY }}-
- name: 📦 安装依赖
working-directory: ./frontend
run: bun install
run: bun install --frozen-lockfile
- name: 🔍 代码检查
- name: 🏗️ 并行构建和检查
working-directory: ./frontend
run: |
bun run lint
bun run type-check
# 并行执行代码检查和构建
bun run lint &
bun run type-check &
wait
env:
NEXT_PUBLIC_API_URL: https://api.photography.iriver.top
NEXT_PUBLIC_SITE_URL: https://photography.iriver.top
NEXT_PUBLIC_SITE_NAME: 摄影作品集
- name: 🏗️ 构建生产版本
working-directory: ./frontend
@ -43,9 +63,9 @@ jobs:
- name: 📦 打包构建产物
uses: actions/upload-artifact@v3
with:
name: frontend-dist
name: frontend-dist-${{ github.sha }}
path: frontend/out/
retention-days: 7
retention-days: 1
deploy:
name: 🚀 部署到生产环境
@ -60,11 +80,19 @@ jobs:
- name: 🦀 设置 Bun 环境
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: ${{ env.BUN_VERSION }}
- name: 💾 缓存 Bun 依赖
uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
frontend/node_modules
key: ${{ env.CACHE_KEY }}-${{ hashFiles('frontend/bun.lock') }}
- name: 📦 安装依赖
working-directory: ./frontend
run: bun install
run: bun install --frozen-lockfile
- name: 🏗️ 构建生产版本
working-directory: ./frontend
@ -74,68 +102,91 @@ jobs:
NEXT_PUBLIC_SITE_NAME: 摄影作品集
run: bun run build
- name: 🚀 部署到服务器
run: |
# 使用国内镜像源安装部署工具
echo "🔄 使用国内镜像源..."
sudo sed -i 's|http://.*.ubuntu.com|https://mirrors.aliyun.com|g' /etc/apt/sources.list
sudo apt-get update -o Acquire::Retries=3 -o Acquire::http::Timeout=30
sudo apt-get install -y openssh-client rsync sshpass
- name: 📤 上传文件到服务器
uses: appleboy/scp-action@v0.1.6
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
source: "frontend/out/"
target: "/tmp/frontend-build"
rm: true
# 设置 SSH 环境
export SSHPASS=${{ secrets.ALIYUN_PWD }}
- name: 🔄 部署文件到生产目录
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
script: |
echo "🔄 部署文件到生产目录..."
echo "🔗 测试 SSH 连接..."
sshpass -e ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }} "echo 'SSH 连接成功'"
# 创建目标目录
mkdir -p /home/gitea/www/photography
echo "📁 创建部署目录..."
sshpass -e ssh -o StrictHostKeyChecking=no ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }} "mkdir -p /home/gitea/www/photography"
# 清空旧文件
rm -rf /home/gitea/www/photography/*
echo "📦 备份当前版本..."
sshpass -e ssh -o StrictHostKeyChecking=no ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }} "
if [ -d '/home/gitea/www/photography' ] && [ \"\$(ls -A /home/gitea/www/photography)\" ]; then
mkdir -p /home/gitea/backups/photography-frontend
tar -czf /home/gitea/backups/photography-frontend/frontend-\$(date +%Y%m%d-%H%M%S).tar.gz -C /home/gitea/www/photography .
echo '✅ 备份完成'
fi
"
# 移动新文件到生产目录
cp -r /tmp/frontend-build/frontend/out/* /home/gitea/www/photography/ || exit 1
echo "🚀 部署新版本..."
sshpass -e rsync -avz --delete --progress -e "ssh -o StrictHostKeyChecking=no" frontend/out/ ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }}:/home/gitea/www/photography/
# 清理临时文件
rm -rf /tmp/frontend-build
echo "🔐 设置文件权限..."
sshpass -e ssh -o StrictHostKeyChecking=no ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }} "
# 验证部署结果
echo "📋 验证部署文件..."
ls -la /home/gitea/www/photography/ | head -10
- name: 🔧 设置文件权限
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
script: |
echo "🔧 设置文件权限..."
# 设置所有者
chown -R gitea:gitea /home/gitea/www/photography
chmod -R 755 /home/gitea/www/photography
find /home/gitea/www/photography -type f -name '*.html' -o -name '*.js' -o -name '*.css' -o -name '*.json' | xargs chmod 644
"
echo "🔄 重新加载 Web 服务器..."
sshpass -e ssh -o StrictHostKeyChecking=no ${{ secrets.ALIYUN_USER_NAME }}@${{ secrets.ALIYUN_IP }} "sudo systemctl reload caddy"
# 设置权限
chmod -R 755 /home/gitea/www/photography
find /home/gitea/www/photography -type f \( -name '*.html' -o -name '*.js' -o -name '*.css' -o -name '*.json' \) -exec chmod 644 {} \;
# 重新加载 Caddy
if command -v sudo &> /dev/null; then
sudo systemctl reload caddy
else
systemctl reload caddy || true
fi
echo "✅ 前端部署完成!"
echo "📁 部署路径:/home/gitea/www/photography/"
echo "🌐 访问地址https://photography.iriver.top"
- name: 🔍 健康检查
run: |
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.ALIYUN_IP }}
username: ${{ secrets.ALIYUN_USER_NAME }}
password: ${{ secrets.ALIYUN_PWD }}
port: 22
script: |
echo "🔍 执行健康检查..."
sleep 10
# 检查网站是否可访问
if curl -f -s -o /dev/null https://photography.iriver.top; then
echo "前端网站访问正常"
# 检查文件是否存在
if [ -f '/home/gitea/www/photography/index.html' ]; then
echo 'index.html 文件存在'
else
echo "⚠️ 前端网站访问异常"
echo '❌ index.html 文件不存在'
exit 1
fi
- name: 📧 发送部署通知
if: always()
run: |
if [ "${{ job.status }}" = "success" ]; then
echo "✅ 摄影作品集前端部署成功!"
echo "🌐 访问地址: https://photography.iriver.top"
# 快速检查
sleep 3
if curl -f -s -o /dev/null https://photography.iriver.top; then
echo '✅ 前端网站访问正常'
else
echo "❌ 摄影作品集前端部署失败!"
echo '⚠️ 前端网站访问异常,请手动检查'
fi

23
.promptx/pouch.json Normal file
View File

@ -0,0 +1,23 @@
{
"currentState": "service_discovery",
"stateHistory": [
{
"from": "initial",
"command": "init",
"timestamp": "2025-07-21T14:37:13.506Z",
"args": [
{
"workingDirectory": "/Users/iriver/workspace/photography",
"ideType": "trae"
}
]
},
{
"from": "initialized",
"command": "welcome",
"timestamp": "2025-07-21T14:37:23.299Z",
"args": []
}
],
"lastUpdated": "2025-07-21T14:37:23.301Z"
}

View File

@ -0,0 +1,17 @@
{
"version": "2.0.0",
"source": "project",
"metadata": {
"version": "2.0.0",
"description": "project 级资源注册表",
"createdAt": "2025-07-21T14:37:13.518Z",
"updatedAt": "2025-07-21T14:37:13.519Z",
"resourceCount": 0
},
"resources": [],
"stats": {
"totalResources": 0,
"byProtocol": {},
"bySource": {}
}
}

View File

@ -20,49 +20,49 @@
"dependencies": {
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.5",
"@tanstack/react-query": "^5.17.19",
"@tanstack/react-query-devtools": "^5.17.21",
"axios": "^1.6.5",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-toast": "^1.2.14",
"@tanstack/react-query": "^5.83.0",
"@tanstack/react-query-devtools": "^5.83.0",
"axios": "^1.10.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.312.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.48.2",
"react-router-dom": "^6.20.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-hook-form": "^7.60.0",
"react-router-dom": "^6.30.1",
"sonner": "^2.0.6",
"tailwind-merge": "^2.2.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"zustand": "^4.4.7"
"zustand": "^4.5.7"
},
"devDependencies": {
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.16",
"eslint": "^8.55.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.5",
"@types/react": "^18.3.23",
"@types/react-dom": "^18.3.7",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-react": "^4.6.0",
"autoprefixer": "^10.4.21",
"eslint": "^8.57.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.20",
"husky": "^8.0.3",
"lint-staged": "^15.2.0",
"postcss": "^8.4.32",
"prettier": "^3.1.1",
"lint-staged": "^15.5.2",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"prettier-plugin-organize-imports": "^4.1.0",
"tailwindcss": "^3.4.0",
"typescript": "^5.2.2",
"vite": "^5.0.8"
"tailwindcss": "^3.4.17",
"typescript": "^5.8.3",
"vite": "^7.0.4"
},
"lint-staged": {
"*.{ts,tsx,js,jsx}": [

View File

@ -84,6 +84,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
rest.WithPrefix("/api/v1"),
)
// 额外的根路径健康检查用于Caddy等反向代理
server.AddRoutes(
[]rest.Route{
{
// 根路径健康检查
Method: http.MethodGet,
Path: "/health",
Handler: health.HealthHandler(serverCtx),
},
},
)
server.AddRoutes(
[]rest.Route{
{

View File

@ -2,211 +2,53 @@
## 📚 文档结构
本项目采用版本化的文档管理策略,按照功能迭代分为不同版本,便于开发和维护。
本项目文档采用清晰的模块化结构,便于快速查找和维护。
```
docs/
├── README.md # 文档总览(当前文件)
├── v1/ # v1.0 版本文档
│ ├── admin/ # 管理后台相关
│ ├── backend/ # 后端架构相关
│ ├── database/ # 数据库设计相关
│ ├── api/ # API接口相关
│ └── README.md # v1版本说明
├── v2/ # v2.0 版本文档(规划中)
│ ├── admin/ # 管理后台升级
│ ├── backend/ # 后端微服务化
│ ├── database/ # 数据库优化
│ ├── api/ # GraphQL接口
│ └── README.md # v2版本说明
├── 原始 prd/ # 原始需求文档
│ ├── UI设计需求文档.md
│ ├── 前端开发文档.md
│ ├── 后端开发文档.md
│ └── 测试需求文档.md
└── [传统目录结构] # 保留现有结构
├── design/ # 设计文档
├── api/ # API文档
├── user-guide/ # 用户指南
├── development/ # 开发文档
└── deployment/ # 部署文档
├── guides/ # 📖 用户指南
├── technical/ # 🔧 技术文档
├── operations/ # 🚀 运维部署
└── api/ # 📡 API文档
```
## 🚀 版本规划
## 🎯 快速导航
### v1.0 - 核心功能版本 (当前开发)
### 👥 普通用户
- [用户指南](./guides/) - 网站使用教程
**目标**: 实现完整的摄影作品集网站核心功能
### 💻 开发者
- [技术文档](./technical/) - 架构设计和开发指南
- [API文档](./api/) - 接口说明和示例
#### 📋 功能范围
- **前端展示**: Next.js 15 + React 19 静态网站
- 🔄 **管理后台**: React + TypeScript 管理界面
- 🔄 **后端API**: Golang + Gin + PostgreSQL
- 🔄 **图片处理**: 多格式转换和优化
- 🔄 **用户管理**: JWT认证和权限控制
- 🔄 **文件存储**: MinIO/S3 对象存储
### 🛠️ 运维人员
- [运维部署](./operations/) - 部署配置和运维指南
#### 📖 v1.0 文档
- [管理后台开发文档](./v1/admin/管理后台开发文档.md)
- [Golang项目架构文档](./v1/backend/Golang项目架构文档.md)
- [数据库设计文档](./v1/database/数据库设计文档.md)
- [API接口设计文档](./v1/api/API接口设计文档.md)
## 📁 目录说明
#### 🛠️ 技术栈
```yaml
前端:
- Next.js 15 + React 19
- TypeScript + Tailwind CSS
- TanStack Query + Zustand
| 目录 | 用途 | 目标用户 |
|---|---|---|
| `guides/` | 使用教程和帮助文档 | 所有用户 |
| `technical/` | 技术架构和开发文档 | 开发者 |
| `operations/` | 部署配置和运维文档 | 运维人员 |
| `api/` | API接口文档 | 前后端开发者 |
后端:
- Golang + Gin Framework
- GORM + PostgreSQL
- Redis + MinIO/S3
## 🚀 快速开始
部署:
- Docker + Docker Compose
- Caddy Web Server
- Gitea Actions CI/CD
```
### 新用户入门
1. 查看 [用户指南](./guides/) 了解网站功能
2. 阅读 [技术文档](./technical/) 了解项目架构
3. 参考 [运维部署](./operations/) 进行环境搭建
### v2.0 - 高级功能版本 (规划中)
### 开发者工作流
1. **前端开发**: 查看技术文档中的前端部分
2. **后端开发**: 查看技术文档中的后端部分
3. **API对接**: 查看api目录下的接口文档
4. **部署上线**: 参考运维部署文档
**目标**: 扩展高级功能,优化性能和用户体验
## 📞 技术支持
#### 🎯 规划功能
- 🔮 **AI增强**: 自动标签、智能分类、内容推荐
- 🔮 **社交功能**: 评论系统、点赞收藏、用户互动
- 🔮 **高级搜索**: ElasticSearch全文搜索、地理位置搜索
- 🔮 **性能优化**: CDN加速、图片懒加载、缓存优化
- 🔮 **移动端**: PWA支持、移动端优化
- 🔮 **多语言**: 国际化支持、多语言切换
#### 🏗️ 架构升级
- **微服务化**: 服务拆分,独立部署
- **GraphQL**: 统一数据查询接口
- **消息队列**: RabbitMQ/Redis Streams
- **监控体系**: Prometheus + Grafana
- **日志中心**: ELK Stack
## 📝 文档使用指南
### 开发者快速开始
1. **前端开发者**
```bash
# 阅读前端相关文档
cd docs/原始\ prd/
# 查看 前端开发文档.md 和 UI设计需求文档.md
```
2. **后端开发者**
```bash
# 阅读v1版本后端文档
cd docs/v1/
# 依次阅读:
# - backend/Golang项目架构文档.md
# - database/数据库设计文档.md
# - api/API接口设计文档.md
```
3. **全栈开发者**
```bash
# 完整了解项目
# 1. 先看原始需求: docs/原始\ prd/
# 2. 再看具体实现: docs/v1/
# 3. 了解未来规划: docs/v2/README.md
```
### 管理员和产品经理
1. **项目概览**: 从 `docs/README.md` (本文件) 开始
2. **功能规划**: 查看各版本的 README.md 了解功能范围
3. **进度跟踪**: 根据文档中的状态标识了解开发进度
## 🎯 当前开发状态
### v1.0 开发进度
| 模块 | 状态 | 完成度 | 负责人 | 备注 |
|------|------|---------|--------|------|
| 前端展示 | ✅ 已完成 | 100% | - | Next.js静态网站 |
| 管理后台 | 📋 设计中 | 20% | - | React管理界面 |
| 后端API | 📋 设计中 | 15% | - | Golang架构设计 |
| 数据库 | 📋 设计中 | 30% | - | PostgreSQL表设计 |
| 图片处理 | ⏳ 待开发 | 0% | - | 多格式转换 |
| 用户认证 | ⏳ 待开发 | 0% | - | JWT + 权限 |
| 文件存储 | ⏳ 待开发 | 0% | - | MinIO/S3集成 |
| 部署配置 | ⏳ 待开发 | 0% | - | Docker + CI/CD |
### 下一步计划
#### 近期计划 (1-2周)
1. **完成管理后台前端开发**
- React + TypeScript 管理界面
- 照片上传和管理功能
- 分类标签管理
2. **开始后端核心开发**
- Golang项目框架搭建
- 数据库表创建和迁移
- 基础API接口实现
#### 中期计划 (1个月)
1. **完善后端功能**
- 用户认证和权限系统
- 图片处理和存储
- 完整的CRUD操作
2. **前后端联调**
- API接口对接
- 数据流测试
- 功能完整性验证
#### 长期计划 (2-3个月)
1. **系统优化**
- 性能优化和缓存
- 安全性加固
- 错误处理完善
2. **部署上线**
- 生产环境配置
- CI/CD流程
- 监控和日志
## 📞 联系方式
### 项目维护者
- **项目负责人**: [待填写]
- **技术负责人**: [待填写]
- **项目地址**: https://photography.iriver.top
- **文档维护**: Claude Code Assistant
### 沟通渠道
- **技术讨论**: [GitHub Issues/Discussions]
- **进度同步**: [项目管理工具链接]
- **紧急联系**: [联系方式]
## 📋 文档维护
### 更新频率
- **设计文档**: 功能变更时及时更新
- **API文档**: 接口变更时同步更新
- **架构文档**: 重大架构调整时更新
- **状态跟踪**: 每周更新开发进度
### 贡献指南
1. 所有文档使用 Markdown 格式
2. 图片和图表存放在对应的 `assets/` 目录
3. 重大更新需要更新对应的 README.md
4. 保持文档结构清晰,便于检索
### 版本控制
- 文档跟随代码版本管理
- 重大版本升级创建新的版本目录
- 保留历史版本文档,便于回溯
---
📅 **最后更新**: 2024-01-15
📝 **文档版本**: v1.0
👨‍💻 **维护者**: Claude Code Assistant
- **最后更新**: 2024-12-21

View File

@ -1,212 +0,0 @@
# 使用现有服务的部署指南
本指南适用于已有 PostgreSQL 和 Redis 服务的情况。
## 📋 前提条件
确保你的服务器上已经安装并运行:
- **PostgreSQL** (推荐版本 14+)
- **Redis** (推荐版本 6+)
## ⚙️ 配置步骤
### 1. 环境变量配置
复制环境变量模板:
```bash
cp .env.example .env
```
编辑 `.env` 文件,配置你的现有服务:
```bash
# 数据库配置
DB_HOST=localhost # 或你的 PostgreSQL 服务器地址
DB_PORT=5432 # PostgreSQL 端口
DB_NAME=photography # 数据库名称
DB_USER=postgres # 数据库用户
DB_PASSWORD=your_actual_password # 数据库密码
# Redis 配置
REDIS_HOST=localhost # 或你的 Redis 服务器地址
REDIS_PORT=6379 # Redis 端口
REDIS_PASSWORD=your_redis_password # Redis 密码 (如果有)
# JWT 配置
JWT_SECRET=your_jwt_secret_at_least_32_characters_long
JWT_EXPIRES_IN=24h
```
### 2. 数据库准备
连接到你的 PostgreSQL创建数据库
```sql
-- 创建数据库
CREATE DATABASE photography;
-- 创建用户 (如果需要)
CREATE USER photography_user WITH ENCRYPTED PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE photography TO photography_user;
-- 使用数据库
\c photography;
-- 创建必要的扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
```
### 3. 后端服务部署
#### 方式一Docker 部署 (推荐)
```bash
# 构建并启动后端服务
docker-compose up -d backend
# 查看日志
docker-compose logs -f backend
# 检查健康状态
curl http://localhost:8080/health
```
#### 方式二:直接运行
```bash
# 进入后端目录
cd backend
# 安装依赖
go mod download
# 运行数据库迁移
go run cmd/server/main.go migrate
# 启动服务
go run cmd/server/main.go
```
### 4. 数据库迁移
如果你的后端支持自动迁移,服务启动时会自动创建表结构。
如果需要手动迁移:
```bash
# 使用 Docker
docker-compose exec backend ./main migrate
# 或者直接运行
cd backend && go run cmd/server/main.go migrate
```
### 5. 验证部署
```bash
# 检查后端健康状态
curl http://localhost:8080/health
# 检查数据库连接
curl http://localhost:8080/api/v1/health
# 检查 Redis 连接 (如果有相关接口)
curl http://localhost:8080/api/v1/cache/health
```
## 🔧 常见问题
### 数据库连接失败
1. **检查数据库是否运行**
```bash
sudo systemctl status postgresql
```
2. **检查连接权限**
```bash
psql -h localhost -U postgres -d photography
```
3. **检查防火墙**
```bash
sudo ufw status
```
### Redis 连接失败
1. **检查 Redis 状态**
```bash
sudo systemctl status redis
```
2. **测试 Redis 连接**
```bash
redis-cli ping
```
### 容器网络问题
如果容器无法访问宿主机服务,尝试:
1. **使用 host 网络模式** (已配置)
2. **检查服务绑定地址**
- PostgreSQL: 确保监听 `0.0.0.0:5432` 或 `localhost:5432`
- Redis: 确保监听 `0.0.0.0:6379` 或 `localhost:6379`
## 📊 监控和维护
### 日志查看
```bash
# 后端日志
docker-compose logs -f backend
# 系统日志
journalctl -u your-service-name -f
```
### 性能监控
```bash
# 运行监控脚本
./scripts/monitor.sh
# 手动检查资源使用
docker stats photography_backend
```
### 备份
```bash
# 手动备份数据库
./scripts/backup.sh
# 或者使用 Docker 备份服务
docker-compose --profile backup up backup
```
## 🚀 自动化部署
如果你使用 CI/CD确保在部署环境中设置正确的环境变量
```yaml
# .github/workflows 或 .gitea/workflows
env:
DB_HOST: your-db-host
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
REDIS_HOST: your-redis-host
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
```
## 🔒 安全建议
1. **使用强密码**
2. **限制数据库访问**:只允许必要的 IP 连接
3. **启用 SSL/TLS**:用于数据库和 Redis 连接
4. **定期更新**:保持服务和依赖的最新版本
5. **监控日志**:定期检查异常访问
---
这种配置更加轻量和实用,避免了重复安装已有服务的资源浪费。

View File

@ -1,760 +0,0 @@
# 摄影作品集项目部署文档
本文档详细说明了摄影作品集项目的完整部署流程,包括前端、管理后台、后端 API 和数据库的部署配置。
## 📋 目录
- [系统要求](#系统要求)
- [环境配置](#环境配置)
- [后端部署](#后端部署)
- [前端部署](#前端部署)
- [管理后台部署](#管理后台部署)
- [数据库配置](#数据库配置)
- [Web 服务器配置](#web-服务器配置)
- [SSL 证书配置](#ssl-证书配置)
- [监控和备份](#监控和备份)
- [故障排除](#故障排除)
## 🖥️ 系统要求
### 硬件要求
- **CPU**: 2 核心以上
- **内存**: 4GB 以上 (推荐 8GB)
- **存储**: 20GB 以上 SSD 存储
- **网络**: 稳定的互联网连接
### 软件要求
- **操作系统**: Ubuntu 20.04 LTS / CentOS 8 / Debian 11
- **Docker**: 20.10 或更高版本
- **Docker Compose**: 2.0 或更高版本
- **Git**: 2.20 或更高版本
- **域名**: 用于生产环境部署
## ⚙️ 环境配置
### 1. 安装 Docker 和 Docker Compose
```bash
# Ubuntu/Debian
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker --version
docker-compose --version
```
### 2. 克隆项目仓库
```bash
git clone <repository-url> photography
cd photography
```
### 3. 创建环境变量文件
```bash
# 复制环境变量模板
cp .env.example .env
# 编辑环境变量
nano .env
```
## 🚀 后端部署
### 1. 后端 Docker 配置
查看后端 Dockerfile
```dockerfile
# backend/Dockerfile
FROM golang:1.21-alpine AS builder
# 设置工作目录
WORKDIR /app
# 安装依赖
RUN apk add --no-cache git ca-certificates tzdata
# 复制 go mod 文件
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码
COPY . .
# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main cmd/server/main.go
# 生产环境镜像
FROM alpine:latest
# 安装必要的包
RUN apk --no-cache add ca-certificates wget
# 创建用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# 设置工作目录
WORKDIR /app
# 从构建阶段复制文件
COPY --from=builder /app/main .
COPY --from=builder /app/configs ./configs
COPY --from=builder /app/migrations ./migrations
# 创建必要的目录
RUN mkdir -p uploads logs && chown -R appuser:appgroup /app
# 切换到非 root 用户
USER appuser
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# 启动命令
CMD ["./main"]
```
### 2. 后端 Docker Compose 服务
```yaml
# docker-compose.yml - 后端部分
services:
# PostgreSQL 数据库
postgres:
image: postgres:15-alpine
container_name: photography_postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME:-photography}
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./backend/migrations:/docker-entrypoint-initdb.d
ports:
- "127.0.0.1:5432:5432"
networks:
- photography_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-photography}"]
interval: 30s
timeout: 10s
retries: 5
# Redis 缓存
redis:
image: redis:7-alpine
container_name: photography_redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
ports:
- "127.0.0.1:6379:6379"
networks:
- photography_network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 5
# 后端 API 服务
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: photography_backend
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
# 数据库配置
DB_HOST: postgres
DB_PORT: 5432
DB_NAME: ${DB_NAME:-photography}
DB_USER: ${DB_USER:-postgres}
DB_PASSWORD: ${DB_PASSWORD}
# Redis 配置
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD}
# JWT 配置
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h}
# 服务器配置
PORT: 8080
GIN_MODE: release
# 文件存储配置
STORAGE_TYPE: ${STORAGE_TYPE:-local}
STORAGE_PATH: /app/uploads
MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE:-10MB}
# 日志配置
LOG_LEVEL: ${LOG_LEVEL:-info}
LOG_FORMAT: json
volumes:
- ./backend/uploads:/app/uploads
- ./backend/logs:/app/logs
- ./backend/configs:/app/configs
ports:
- "127.0.0.1:8080:8080"
networks:
- photography_network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
volumes:
postgres_data:
driver: local
redis_data:
driver: local
networks:
photography_network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
```
### 3. 启动后端服务
```bash
# 构建并启动后端服务
docker-compose up -d postgres redis
docker-compose up -d backend
# 查看日志
docker-compose logs -f backend
# 验证服务状态
curl http://localhost:8080/health
```
## 🌐 前端部署
### 1. 前端构建配置
```bash
# 进入前端目录
cd frontend/
# 安装依赖
bun install
# 构建生产版本
bun run build
# 验证构建结果
ls -la out/
```
### 2. 前端部署脚本
创建前端部署脚本:
```bash
#!/bin/bash
# scripts/deploy-frontend.sh
set -e
echo "🚀 开始部署前端..."
# 配置变量
FRONTEND_DIR="/home/gitea/www/photography"
BACKUP_DIR="/home/gitea/backups/photography-frontend"
BUILD_DIR="./frontend/out"
# 创建备份
echo "📦 创建当前版本备份..."
mkdir -p "$BACKUP_DIR"
if [ -d "$FRONTEND_DIR" ]; then
tar -czf "$BACKUP_DIR/frontend-$(date +%Y%m%d-%H%M%S).tar.gz" -C "$FRONTEND_DIR" .
fi
# 创建部署目录
echo "📁 准备部署目录..."
mkdir -p "$FRONTEND_DIR"
# 部署新版本
echo "🔄 部署新版本..."
rsync -av --delete "$BUILD_DIR/" "$FRONTEND_DIR/"
# 设置权限
echo "🔐 设置文件权限..."
chown -R gitea:gitea "$FRONTEND_DIR"
chmod -R 755 "$FRONTEND_DIR"
# 清理旧备份 (保留最近5个)
echo "🧹 清理旧备份..."
cd "$BACKUP_DIR"
ls -t frontend-*.tar.gz | tail -n +6 | xargs -r rm
echo "✅ 前端部署完成!"
echo "🌐 访问地址: https://photography.iriver.top"
```
## 🛠️ 管理后台部署
### 1. 管理后台构建配置
```bash
# 进入管理后台目录
cd admin/
# 安装依赖
npm install
# 构建生产版本
npm run build
# 验证构建结果
ls -la dist/
```
### 2. 管理后台部署脚本
```bash
#!/bin/bash
# scripts/deploy-admin.sh
set -e
echo "🚀 开始部署管理后台..."
# 配置变量
ADMIN_DIR="/home/gitea/www/photography-admin"
BACKUP_DIR="/home/gitea/backups/photography-admin"
BUILD_DIR="./admin/dist"
# 创建备份
echo "📦 创建当前版本备份..."
mkdir -p "$BACKUP_DIR"
if [ -d "$ADMIN_DIR" ]; then
tar -czf "$BACKUP_DIR/admin-$(date +%Y%m%d-%H%M%S).tar.gz" -C "$ADMIN_DIR" .
fi
# 创建部署目录
echo "📁 准备部署目录..."
mkdir -p "$ADMIN_DIR"
# 部署新版本
echo "🔄 部署新版本..."
rsync -av --delete "$BUILD_DIR/" "$ADMIN_DIR/"
# 设置权限
echo "🔐 设置文件权限..."
chown -R gitea:gitea "$ADMIN_DIR"
chmod -R 755 "$ADMIN_DIR"
# 清理旧备份 (保留最近5个)
echo "🧹 清理旧备份..."
cd "$BACKUP_DIR"
ls -t admin-*.tar.gz | tail -n +6 | xargs -r rm
echo "✅ 管理后台部署完成!"
echo "🌐 访问地址: https://admin.photography.iriver.top"
```
## 🗄️ 数据库配置
### 1. 数据库初始化
```sql
-- 创建数据库
CREATE DATABASE photography;
CREATE USER photography_user WITH ENCRYPTED PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE photography TO photography_user;
-- 使用数据库
\c photography;
-- 创建必要的扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- 设置时区
SET timezone = 'Asia/Shanghai';
```
### 2. 数据库备份脚本
```bash
#!/bin/bash
# scripts/backup.sh
set -e
# 配置变量
DB_HOST="${DB_HOST:-postgres}"
DB_NAME="${DB_NAME:-photography}"
DB_USER="${DB_USER:-postgres}"
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d-%H%M%S)
echo "🗄️ 开始数据库备份..."
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 执行备份
pg_dump -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" \
--no-password --verbose --clean --no-acl --no-owner \
-f "$BACKUP_DIR/photography-$DATE.sql"
# 压缩备份文件
gzip "$BACKUP_DIR/photography-$DATE.sql"
# 清理旧备份 (保留最近7天)
find "$BACKUP_DIR" -name "photography-*.sql.gz" -mtime +7 -delete
echo "✅ 数据库备份完成: photography-$DATE.sql.gz"
```
## 🌐 Web 服务器配置
### Caddy 配置文件
```caddyfile
# docs/deployment/Caddyfile
# 前端网站
photography.iriver.top {
# 根目录
root * /home/gitea/www/photography
# 静态文件服务
file_server
# SPA 路由支持
try_files {path} /index.html
# 压缩
encode gzip
# 缓存配置
header {
# 静态资源缓存
Cache-Control "public, max-age=31536000" {
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.woff *.woff2
}
# HTML 文件不缓存
Cache-Control "no-cache" {
path *.html
}
# 安全头
X-Frame-Options "DENY"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
}
# 日志
log {
output file /var/log/caddy/photography.log
format json
}
}
# 管理后台
admin.photography.iriver.top {
# 根目录
root * /home/gitea/www/photography-admin
# 静态文件服务
file_server
# SPA 路由支持
try_files {path} /index.html
# 压缩
encode gzip
# 基本认证 (可选)
# basicauth {
# admin $2a$14$encrypted_password_hash
# }
# 缓存配置
header {
Cache-Control "public, max-age=31536000" {
path *.js *.css *.png *.jpg *.jpeg *.gif *.ico *.woff *.woff2
}
Cache-Control "no-cache" {
path *.html
}
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
# 日志
log {
output file /var/log/caddy/admin.photography.log
format json
}
}
# API 服务
api.photography.iriver.top {
# 反向代理到后端服务
reverse_proxy localhost:8080 {
# 健康检查
health_uri /health
health_interval 30s
health_timeout 10s
# 请求头
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote_host}
}
# CORS 处理
header {
Access-Control-Allow-Origin "https://photography.iriver.top, https://admin.photography.iriver.top"
Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers "Content-Type, Authorization"
Access-Control-Max-Age "86400"
}
# 预检请求处理
@options method OPTIONS
respond @options 204
# 上传文件大小限制
request_body {
max_size 10MB
}
# 日志
log {
output file /var/log/caddy/api.photography.log
format json
}
}
# 全局配置
{
# 自动 HTTPS
auto_https on
# Let's Encrypt 邮箱
email admin@iriver.top
# 日志级别
log {
level INFO
}
}
```
## 🔒 SSL 证书配置
Caddy 会自动处理 SSL 证书,但也可以手动配置:
```bash
# 手动获取证书 (如果需要)
certbot certonly --webroot -w /var/www/html -d photography.iriver.top -d admin.photography.iriver.top -d api.photography.iriver.top
# 设置自动续期
echo "0 3 * * * certbot renew --quiet && systemctl reload caddy" | crontab -
```
## 📊 监控和备份
### 1. 系统监控脚本
```bash
#!/bin/bash
# scripts/monitor.sh
# 检查服务状态
check_service() {
local service=$1
local url=$2
echo "检查 $service..."
if curl -f -s "$url" > /dev/null; then
echo "✅ $service 正常运行"
else
echo "❌ $service 服务异常"
# 发送告警 (可集成邮件、微信等)
# send_alert "$service 服务异常"
fi
}
# 检查磁盘空间
check_disk() {
local usage=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
echo "磁盘使用率: $usage%"
if [ "$usage" -gt 80 ]; then
echo "⚠️ 磁盘空间不足"
# send_alert "磁盘空间不足: $usage%"
fi
}
# 检查内存使用
check_memory() {
local usage=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
echo "内存使用率: $usage%"
}
# 执行检查
echo "🔍 开始系统监控..."
check_service "前端" "https://photography.iriver.top"
check_service "管理后台" "https://admin.photography.iriver.top"
check_service "API" "https://api.photography.iriver.top/health"
check_disk
check_memory
echo "✅ 监控检查完成"
```
### 2. 自动备份任务
```bash
# 设置定时任务
crontab -e
# 添加以下内容:
# 每天凌晨2点备份数据库
0 2 * * * /path/to/photography/scripts/backup.sh
# 每周日凌晨3点重启服务 (可选)
0 3 * * 0 cd /path/to/photography && docker-compose restart
# 每小时检查一次服务状态
0 * * * * /path/to/photography/scripts/monitor.sh
```
## 🐛 故障排除
### 常见问题和解决方案
#### 1. 后端服务无法启动
```bash
# 查看日志
docker-compose logs backend
# 检查配置
docker-compose config
# 重新构建
docker-compose build backend --no-cache
```
#### 2. 数据库连接失败
```bash
# 检查数据库状态
docker-compose ps postgres
# 检查数据库日志
docker-compose logs postgres
# 手动连接测试
docker-compose exec postgres psql -U postgres -d photography
```
#### 3. 前端/管理后台访问异常
```bash
# 检查文件权限
ls -la /home/gitea/www/photography/
ls -la /home/gitea/www/photography-admin/
# 检查 Caddy 配置
caddy validate --config /etc/caddy/Caddyfile
# 重新加载 Caddy
systemctl reload caddy
```
#### 4. SSL 证书问题
```bash
# 检查证书状态
curl -I https://photography.iriver.top
# 查看 Caddy 日志
tail -f /var/log/caddy/photography.log
# 手动重新申请证书
systemctl stop caddy
caddy run --config /etc/caddy/Caddyfile
```
### 日志文件位置
- **后端日志**: `./backend/logs/`
- **Caddy 日志**: `/var/log/caddy/`
- **数据库日志**: `docker-compose logs postgres`
- **系统日志**: `/var/log/syslog`
## 🚀 部署命令速查
```bash
# 完整部署流程
git pull origin main
cd photography
# 后端部署
docker-compose build backend
docker-compose up -d
# 前端部署
cd frontend && bun run build && cd ..
./scripts/deploy-frontend.sh
# 管理后台部署
cd admin && npm run build && cd ..
./scripts/deploy-admin.sh
# 重启 Web 服务器
sudo systemctl reload caddy
# 检查服务状态
docker-compose ps
curl https://photography.iriver.top
curl https://admin.photography.iriver.top
curl https://api.photography.iriver.top/health
```
## 📞 技术支持
如果在部署过程中遇到问题,请:
1. 查看相关日志文件
2. 检查系统资源使用情况
3. 验证配置文件语法
4. 联系技术支持团队
---
📝 **文档版本**: v1.0
🕒 **最后更新**: 2024年
👥 **维护团队**: 摄影作品集项目组

View File

View File

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 568 B

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Some files were not shown because too many files have changed in this diff Show More