- 菜品营养按食物成分表+烹饪方式校准(calibrate_nutrition 命令) - 后台接入 jazzmin 主题美化,移除 Google Fonts(模板覆盖) - 前端/后台静态资源指向 qnycdn 对象存储 CDN(vite base + DJANGO_STATIC_URL) - 菜单标题学校名称/周数可编辑,日期随周数计算 - admin 搜索支持拼音首字母/全拼(Dish.pinyin 索引,pypinyin) - Dockerfile 使用清华 pip 镜像源
135 lines
3.8 KiB
Bash
135 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# 学校订餐菜单生成器 - 一键部署脚本 (Ubuntu/Debian)
|
|
# 用法: bash deploy.sh <域名>
|
|
set -e
|
|
|
|
DOMAIN="${1:-_}"
|
|
APP_DIR=/opt/school-meal
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
echo "==> [1/8] 安装系统依赖"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -y
|
|
apt-get install -y python3 python3-venv python3-pip nginx curl
|
|
|
|
echo "==> [2/8] 安装 Node.js 20"
|
|
if ! command -v node >/dev/null 2>&1; then
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
|
apt-get install -y nodejs
|
|
fi
|
|
|
|
echo "==> [3/8] 放置代码到 $APP_DIR"
|
|
mkdir -p "$APP_DIR"
|
|
cp -r "$SCRIPT_DIR/backend" "$SCRIPT_DIR/frontend" "$APP_DIR/"
|
|
|
|
echo "==> [4/8] 后端环境、迁移与初始化"
|
|
cd "$APP_DIR/backend"
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -r requirements.txt -q
|
|
.venv/bin/python manage.py migrate
|
|
.venv/bin/python manage.py seed_dishes
|
|
.venv/bin/python manage.py collectstatic --noinput
|
|
.venv/bin/python manage.py shell -c "
|
|
from django.contrib.auth import get_user_model
|
|
U = get_user_model()
|
|
if not U.objects.filter(username='admin').exists():
|
|
U.objects.create_superuser('admin', 'admin@example.com', 'admin123')
|
|
print('已创建管理员 admin / admin123')
|
|
else:
|
|
print('管理员 admin 已存在')
|
|
"
|
|
|
|
echo "==> [5/8] 后端 systemd 服务 (gunicorn)"
|
|
cat > /etc/systemd/system/school-meal.service <<EOF
|
|
[Unit]
|
|
Description=School Meal Django
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=www-data
|
|
Group=www-data
|
|
WorkingDirectory=$APP_DIR/backend
|
|
ExecStart=$APP_DIR/backend/.venv/bin/gunicorn config.wsgi:application --bind 127.0.0.1:8000 --workers 3 --timeout 60
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
chown -R www-data:www-data "$APP_DIR/backend/db.sqlite3" "$APP_DIR/backend/staticfiles" 2>/dev/null || true
|
|
systemctl daemon-reload
|
|
systemctl enable --now school-meal.service
|
|
systemctl restart school-meal.service
|
|
|
|
echo "==> [6/8] 前端构建"
|
|
cd "$APP_DIR/frontend"
|
|
npm install --silent
|
|
npm run build
|
|
|
|
echo "==> [7/8] 配置 Nginx (域名: $DOMAIN)"
|
|
cat > /etc/nginx/sites-available/school-meal <<EOF
|
|
server {
|
|
listen 80;
|
|
server_name $DOMAIN;
|
|
|
|
client_max_body_size 20M;
|
|
gzip on;
|
|
gzip_types text/plain text/css application/javascript application/json;
|
|
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
}
|
|
|
|
location /admin/ {
|
|
proxy_pass http://127.0.0.1:8000;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
}
|
|
|
|
location /static/ {
|
|
alias $APP_DIR/backend/staticfiles/;
|
|
}
|
|
|
|
location /xx/web/ {
|
|
alias $APP_DIR/frontend/dist/;
|
|
index index.html;
|
|
expires 7d;
|
|
}
|
|
|
|
location /xx/web/assets/ {
|
|
alias $APP_DIR/frontend/dist/assets/;
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
expires 1y;
|
|
}
|
|
|
|
location /xx/admin/ {
|
|
alias $APP_DIR/backend/staticfiles/;
|
|
expires 7d;
|
|
}
|
|
|
|
location / {
|
|
root $APP_DIR/frontend/dist;
|
|
index index.html;
|
|
try_files \$uri /index.html;
|
|
}
|
|
}
|
|
EOF
|
|
ln -sf /etc/nginx/sites-available/school-meal /etc/nginx/sites-enabled/school-meal
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
nginx -t
|
|
systemctl enable nginx
|
|
systemctl reload nginx
|
|
|
|
echo "==> [8/8] 验证"
|
|
sleep 2
|
|
curl -s -o /dev/null -w "后端 API: HTTP %{http_code}\n" http://127.0.0.1:8000/api/dishes/
|
|
curl -s -o /dev/null -w "前端页面: HTTP %{http_code}\n" http://127.0.0.1/$DOMAIN
|
|
|
|
echo ""
|
|
echo "部署完成!"
|
|
echo " 前台页面: http://$DOMAIN/"
|
|
echo " 后台管理: http://$DOMAIN/admin/ (admin / admin123,请尽快修改密码)"
|
|
echo " 域名解析: 请确保 $DOMAIN 的 A 记录指向本服务器 IP"
|