feat: 一键部署脚本 + Dashboard按钮移至标题下方 + 修复演示模式退出
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# 全国记者站管理系统 — 一键部署脚本
|
||||
# 用法: ./deploy.sh
|
||||
# 功能: 拉取最新代码 → 安装依赖 → 数据库迁移 → 构建 → 重启服务
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
|
||||
# ── 配置 ──────────────────────────────────────────────────
|
||||
DEPLOY_DIR="/var/www/rsms"
|
||||
GIT_REMOTE="origin"
|
||||
BRANCH="main"
|
||||
API_PORT="${API_PORT:-8787}"
|
||||
PM2_NAME="rsms-server"
|
||||
NGINX_SITE="r.all8ai.top"
|
||||
|
||||
# 颜色输出
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { echo -e "${GREEN}[deploy]${NC} $1"; }
|
||||
warn() { echo -e "${YELLOW}[warn]${NC} $1"; }
|
||||
err() { echo -e "${RED}[error]${NC} $1"; exit 1; }
|
||||
|
||||
# ── 前置检查 ──────────────────────────────────────────────
|
||||
check_deps() {
|
||||
log "检查依赖..."
|
||||
command -v git >/dev/null || err "git 未安装"
|
||||
command -v node >/dev/null || err "node 未安装"
|
||||
command -v npm >/dev/null || err "npm 未安装"
|
||||
command -v nginx >/dev/null || err "nginx 未安装"
|
||||
command -v pm2 >/dev/null || err "pm2 未安装 (运行: npm install -g pm2)"
|
||||
|
||||
NODE_MAJOR=$(node -v | sed 's/v\([0-9]*\).*/\1/')
|
||||
[ "$NODE_MAJOR" -ge 22 ] || err "Node.js 版本需 >= 22 (当前: $(node -v))"
|
||||
|
||||
log "依赖检查通过: node $(node -v), npm $(npm -v)"
|
||||
}
|
||||
|
||||
# ── 拉取最新代码 ──────────────────────────────────────────
|
||||
pull_code() {
|
||||
log "拉取最新代码..."
|
||||
cd "$DEPLOY_DIR"
|
||||
git fetch "$GIT_REMOTE" "$BRANCH"
|
||||
git reset --hard "$GIT_REMOTE/$BRANCH"
|
||||
log "代码已更新到 $(git log --oneline -1)"
|
||||
}
|
||||
|
||||
# ── 安装依赖 ──────────────────────────────────────────────
|
||||
install_deps() {
|
||||
log "安装依赖..."
|
||||
npm install --production=false
|
||||
log "依赖安装完成"
|
||||
}
|
||||
|
||||
# ── 数据库迁移 ────────────────────────────────────────────
|
||||
run_migrations() {
|
||||
log "执行数据库迁移..."
|
||||
npm run db:migrate
|
||||
log "数据库迁移完成"
|
||||
}
|
||||
|
||||
# ── 构建前端 ──────────────────────────────────────────────
|
||||
build_frontend() {
|
||||
log "构建前端..."
|
||||
npm run build
|
||||
log "前端构建完成: $(ls dist/assets/*.js | wc -l) 个 JS 文件"
|
||||
}
|
||||
|
||||
# ── 重启后端服务 ──────────────────────────────────────────
|
||||
restart_server() {
|
||||
log "重启后端服务 (pm2: $PM2_NAME)..."
|
||||
pm2 delete "$PM2_NAME" 2>/dev/null || true
|
||||
pm2 start npm --name "$PM2_NAME" -- run server:start
|
||||
pm2 save
|
||||
sleep 2
|
||||
|
||||
# 健康检查
|
||||
local health
|
||||
health=$(curl -s "http://127.0.0.1:${API_PORT}/api/health" 2>/dev/null || echo "FAIL")
|
||||
if echo "$health" | grep -q '"status":"ok"'; then
|
||||
log "后端服务健康检查通过"
|
||||
else
|
||||
warn "后端健康检查异常: $health"
|
||||
warn "查看日志: pm2 logs $PM2_NAME --lines 20"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 重载 nginx ────────────────────────────────────────────
|
||||
reload_nginx() {
|
||||
log "检查 nginx 配置..."
|
||||
nginx -t 2>&1 || err "nginx 配置检查失败"
|
||||
nginx -s reload
|
||||
log "nginx 已重载"
|
||||
}
|
||||
|
||||
# ── 验证站点 ──────────────────────────────────────────────
|
||||
verify_site() {
|
||||
log "验证站点..."
|
||||
local http_code
|
||||
http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://${NGINX_SITE}/" 2>/dev/null || echo "000")
|
||||
if [ "$http_code" = "200" ]; then
|
||||
log "站点验证通过: http://${NGINX_SITE} → 200"
|
||||
else
|
||||
warn "站点返回: $http_code (可能需要检查 DNS 或 nginx 配置)"
|
||||
fi
|
||||
|
||||
# HTTPS 检查(如果证书存在)
|
||||
if [ -d "/etc/letsencrypt/live/${NGINX_SITE}" ]; then
|
||||
local https_code
|
||||
https_code=$(curl -s -o /dev/null -w "%{http_code}" "https://${NGINX_SITE}/" 2>/dev/null || echo "000")
|
||||
log "HTTPS 验证: https://${NGINX_SITE} → $https_code"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── 主流程 ────────────────────────────────────────────────
|
||||
main() {
|
||||
echo ""
|
||||
echo "══════════════════════════════════════════════════"
|
||||
echo " 全国记者站管理系统 — 一键部署"
|
||||
echo "══════════════════════════════════════════════════"
|
||||
echo ""
|
||||
|
||||
check_deps
|
||||
pull_code
|
||||
install_deps
|
||||
run_migrations
|
||||
build_frontend
|
||||
restart_server
|
||||
reload_nginx
|
||||
verify_site
|
||||
|
||||
echo ""
|
||||
log "部署完成!"
|
||||
echo " 站点: https://${NGINX_SITE}"
|
||||
echo " API: https://${NGINX_SITE}/api/health"
|
||||
echo " 日志: pm2 logs ${PM2_NAME}"
|
||||
echo " 状态: pm2 list"
|
||||
echo ""
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -19,6 +19,12 @@ export function TopBar({ pageTitle, onMenuToggle }: TopBarProps) {
|
||||
const handleLogout = () => {
|
||||
if (isAuthenticated) {
|
||||
logout()
|
||||
} else {
|
||||
// 演示模式:清除 auth_role 退出到登录页
|
||||
localStorage.removeItem('auth_role')
|
||||
localStorage.removeItem('auth_name')
|
||||
localStorage.removeItem('auth_station')
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,13 +139,15 @@ export function Dashboard({ records, onNavigate, onCreate, onSelect }: Dashboard
|
||||
<span>{role === 'reporter' ? '这是你的个人工作概况。' : role === 'station' ? '这是本站今日运行概况。' : '这里是全国记者站今日运行概况。'}</span>
|
||||
</div>
|
||||
</div>
|
||||
{role !== 'headquarters' && (
|
||||
</div>
|
||||
{role !== 'headquarters' && (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<button className="primary-button" onClick={onCreate}>
|
||||
<Plus size={18} />
|
||||
新建工作记录
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="metric-grid">
|
||||
<div onClick={() => setDrillDown('pending')} style={{ cursor: 'pointer' }}>
|
||||
|
||||
Reference in New Issue
Block a user