8809a28e9c
- 新增医科高校智能学习中心汇报PPT(27页,面向高校管理者与广电领导) - 新增 pptxgenjs 生成脚本 scripts/gen-pptx.js - 新增 SYSTEM-OVERVIEW.md 系统功能全景文档 - 新增 deploy.sh 部署脚本 - 补充 rate-limit guard、ai-stream controller、exam-prep 仓储等后端模块 - 补充 exam-recommendations、markdown、mock-exam、offline-indicator 前端组件 - tsconfig.json: 显式设置 rootDir=./src,加 ignoreDeprecations=6.0 静音 baseUrl 弃用告警 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
165 lines
5.8 KiB
Bash
Executable File
165 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
#
|
||
# College AI Center — 一键部署脚本
|
||
#
|
||
# 用法:
|
||
# ./deploy.sh
|
||
#
|
||
# 作用:把本地代码同步到远程服务器,在服务器上安装依赖、构建前后端、
|
||
# 配置 PostgreSQL 数据库、systemd 服务与 nginx(域名 mc.all8ai.top),并启动。
|
||
#
|
||
# 与服务器上已有的 k12 应用互不影响(使用独立端口 3100/4100、独立目录、
|
||
# 名称匹配的 nginx server_name,不占用 default_server)。
|
||
#
|
||
# 依赖(本机):sshpass、rsync、ssh
|
||
# ---------------------------------------------------------------------------
|
||
set -euo pipefail
|
||
|
||
# ====== 可配置参数 ======
|
||
SERVER_IP="${SERVER_IP:-101.96.196.218}"
|
||
SERVER_USER="${SERVER_USER:-root}"
|
||
SERVER_PASS="${SERVER_PASS:-Why_701208}"
|
||
|
||
REMOTE_DIR="/opt/college-ai-center"
|
||
BACKEND_PORT=3100
|
||
FRONTEND_PORT=4100
|
||
|
||
# 数据库
|
||
DB_NAME="college_ai_center"
|
||
DB_USER="cac_user"
|
||
DB_PASS="${DB_PASS:-Cac_$(echo "$SERVER_PASS" | md5sum 2>/dev/null | cut -c1-12 || echo Pg88dev)}"
|
||
|
||
# 大模型配置(如需启用,部署后在服务器 .env 中填写 LLM_API_KEY)
|
||
LLM_API_KEY="${LLM_API_KEY:-}"
|
||
LLM_BASE_URL="${LLM_BASE_URL:-https://dashscope.aliyuncs.com/compatible-mode/v1}"
|
||
LLM_MODEL="${LLM_MODEL:-qwen-plus}"
|
||
|
||
JWT_SECRET="${JWT_SECRET:-cac-prod-$(openssl rand -hex 16 2>/dev/null || echo change-me-in-prod)}"
|
||
|
||
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=20"
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
|
||
ssh_run() { sshpass -p "$SERVER_PASS" ssh $SSH_OPTS "$SERVER_USER@$SERVER_IP" "$@"; }
|
||
|
||
echo "==> [1/6] 检查本机依赖"
|
||
for c in sshpass rsync ssh; do
|
||
command -v "$c" >/dev/null 2>&1 || { echo "缺少命令:$c,请先安装(mac: brew install $c)"; exit 1; }
|
||
done
|
||
|
||
echo "==> [2/6] 同步代码到 $SERVER_IP:$REMOTE_DIR"
|
||
ssh_run "mkdir -p $REMOTE_DIR"
|
||
sshpass -p "$SERVER_PASS" rsync -az --delete -e "ssh $SSH_OPTS" \
|
||
--exclude 'node_modules' \
|
||
--exclude 'web/node_modules' \
|
||
--exclude '.next' \
|
||
--exclude 'web/.next' \
|
||
--exclude 'dist' \
|
||
--exclude '.git' \
|
||
--exclude 'coverage' \
|
||
--exclude '*.log' \
|
||
"$SCRIPT_DIR/" "$SERVER_USER@$SERVER_IP:$REMOTE_DIR/"
|
||
|
||
echo "==> [3/6] 在服务器上准备数据库"
|
||
ssh_run "sudo -u postgres psql -tc \"SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'\" | grep -q 1 || sudo -u postgres psql -c \"CREATE ROLE $DB_USER LOGIN PASSWORD '$DB_PASS';\""
|
||
ssh_run "sudo -u postgres psql -tc \"SELECT 1 FROM pg_database WHERE datname='$DB_NAME'\" | grep -q 1 || sudo -u postgres psql -c \"CREATE DATABASE $DB_NAME OWNER $DB_USER;\""
|
||
ssh_run "sudo -u postgres psql -c \"ALTER DATABASE $DB_NAME OWNER TO $DB_USER;\" >/dev/null 2>&1 || true"
|
||
|
||
echo "==> [4/6] 写入后端 .env"
|
||
ssh_run "cat > $REMOTE_DIR/.env <<EOF
|
||
APP_PORT=$BACKEND_PORT
|
||
NODE_ENV=production
|
||
CORS_ORIGIN=*
|
||
|
||
DB_ENABLED=true
|
||
DB_HOST=127.0.0.1
|
||
DB_PORT=5432
|
||
DB_USERNAME=$DB_USER
|
||
DB_PASSWORD=$DB_PASS
|
||
DB_DATABASE=$DB_NAME
|
||
DB_SYNCHRONIZE=true
|
||
DB_LOGGING=false
|
||
|
||
JWT_SECRET=$JWT_SECRET
|
||
JWT_EXPIRES_IN_SECONDS=7200
|
||
|
||
LLM_API_KEY=$LLM_API_KEY
|
||
LLM_BASE_URL=$LLM_BASE_URL
|
||
LLM_MODEL=$LLM_MODEL
|
||
LLM_TIMEOUT_MS=30000
|
||
|
||
AI_RATE_LIMIT_PER_MINUTE=20
|
||
AI_RATE_LIMIT_PER_DAY=500
|
||
EOF"
|
||
|
||
echo "==> [5/6] 安装依赖并构建(后端 + 前端)"
|
||
ssh_run "set -e; cd $REMOTE_DIR && npm install --no-audit --no-fund && npm run build"
|
||
ssh_run "set -e; cd $REMOTE_DIR/web && npm install --no-audit --no-fund && BACKEND_URL=http://127.0.0.1:$BACKEND_PORT npm run build"
|
||
|
||
echo "==> [6/6] 配置 systemd 服务"
|
||
|
||
# 后端 systemd
|
||
ssh_run "cat > /etc/systemd/system/cac-backend.service <<EOF
|
||
[Unit]
|
||
Description=College AI Center Backend (NestJS)
|
||
After=network.target postgresql.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
WorkingDirectory=$REMOTE_DIR
|
||
ExecStart=/usr/bin/node dist/main
|
||
Restart=always
|
||
RestartSec=3
|
||
Environment=NODE_ENV=production
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF"
|
||
|
||
# 前端 systemd(监听 0.0.0.0:$FRONTEND_PORT,直接对外提供访问)
|
||
ssh_run "cat > /etc/systemd/system/cac-frontend.service <<EOF
|
||
[Unit]
|
||
Description=College AI Center Frontend (Next.js)
|
||
After=network.target cac-backend.service
|
||
|
||
[Service]
|
||
Type=simple
|
||
WorkingDirectory=$REMOTE_DIR/web
|
||
ExecStart=/usr/bin/npm run start
|
||
Restart=always
|
||
RestartSec=3
|
||
Environment=NODE_ENV=production
|
||
Environment=BACKEND_URL=http://127.0.0.1:$BACKEND_PORT
|
||
Environment=PORT=$FRONTEND_PORT
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF"
|
||
|
||
# 若曾配置过本应用的 nginx 站点,移除(改为直接端口访问)
|
||
ssh_run "rm -f /etc/nginx/sites-enabled/college-ai-center /etc/nginx/sites-available/college-ai-center; (nginx -t && systemctl reload nginx) >/dev/null 2>&1 || true"
|
||
|
||
# 若 ufw 启用,则放行端口
|
||
ssh_run "if ufw status 2>/dev/null | grep -q 'Status: active'; then ufw allow $BACKEND_PORT/tcp; ufw allow $FRONTEND_PORT/tcp; fi || true"
|
||
|
||
echo "==> 启动服务"
|
||
ssh_run "systemctl daemon-reload && systemctl enable cac-backend cac-frontend >/dev/null 2>&1 && systemctl restart cac-backend cac-frontend"
|
||
|
||
echo "==> 等待服务就绪"
|
||
sleep 6
|
||
ssh_run "systemctl is-active cac-backend cac-frontend; echo '--- backend health ---'; curl -s -o /dev/null -w 'backend(api/auth/login probe): %{http_code}\n' -X POST http://127.0.0.1:$BACKEND_PORT/api/auth/login -H 'Content-Type: application/json' -d '{}'; echo '--- frontend ---'; curl -s -o /dev/null -w 'frontend: %{http_code}\n' http://127.0.0.1:$FRONTEND_PORT"
|
||
|
||
echo ""
|
||
echo "============================================================"
|
||
echo " 部署完成!"
|
||
echo " 前端访问: http://${SERVER_IP}:$FRONTEND_PORT"
|
||
echo " 后端 API: http://${SERVER_IP}:$BACKEND_PORT/api"
|
||
echo " 数据库 : $DB_NAME (用户 $DB_USER)"
|
||
echo ""
|
||
echo " 测试账户:student / mentor / admin(密码同 *123,如 student123)"
|
||
echo ""
|
||
echo " 常用运维:"
|
||
echo " systemctl status cac-backend cac-frontend"
|
||
echo " journalctl -u cac-backend -f"
|
||
echo " journalctl -u cac-frontend -f"
|
||
echo "============================================================"
|