Files
wordloop/deploy/install-production.sh
john 05e173b293 Ship native iOS app, Wiki/TTS backend, and skeleton loading UX.
Replace the WebView shell with SwiftUI screens, add account-scoped Wiki and TTS APIs with adaptive review and photo scan support, and keep web/iOS pages usable while data loads asynchronously.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 15:13:59 +08:00

142 lines
4.6 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 在 105 服务器上执行(/root/wordloop
set -euo pipefail
ROOT="${WORDLOOP_ROOT:-/root/wordloop}"
cd "$ROOT"
MYSQL_HOST="${MYSQL_HOST:?MYSQL_HOST required}"
MYSQL_PORT="${MYSQL_PORT:-3306}"
MYSQL_USER="${MYSQL_USER:?MYSQL_USER required}"
MYSQL_PASSWORD="${MYSQL_PASSWORD:?MYSQL_PASSWORD required}"
MYSQL_DATABASE="${MYSQL_DATABASE:-wordloop}"
if [ -z "${WORDLOOP_SECRET_KEY:-}" ] && [ -f "$ROOT/backend/.env" ]; then
WORDLOOP_SECRET_KEY="$(grep -E '^WORDLOOP_SECRET_KEY=' "$ROOT/backend/.env" | cut -d= -f2- || true)"
fi
WORDLOOP_SECRET_KEY="${WORDLOOP_SECRET_KEY:-$(openssl rand -hex 32)}"
DEEPSEEK_API_KEY="${DEEPSEEK_API_KEY:-}"
DEEPSEEK_BASE_URL="${DEEPSEEK_BASE_URL:-https://api.deepseek.com}"
DEEPSEEK_MODEL="${DEEPSEEK_MODEL:-deepseek-chat}"
AI_WIKI_DAILY_LLM_LIMIT="${AI_WIKI_DAILY_LLM_LIMIT:-20}"
TKMIND_TTS_BASE_URL="${TKMIND_TTS_BASE_URL:-http://127.0.0.1:19200}"
TKMIND_TTS_ENABLED="${TKMIND_TTS_ENABLED:-true}"
TKMIND_TTS_SPK_ID="${TKMIND_TTS_SPK_ID:-aitong}"
echo ">>> 写入 backend/.env"
cat > "$ROOT/backend/.env" <<EOF
MYSQL_HOST=${MYSQL_HOST}
MYSQL_PORT=${MYSQL_PORT}
MYSQL_USER=${MYSQL_USER}
MYSQL_PASSWORD=${MYSQL_PASSWORD}
MYSQL_DATABASE=${MYSQL_DATABASE}
WORDLOOP_SECRET_KEY=${WORDLOOP_SECRET_KEY}
DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
DEEPSEEK_BASE_URL=${DEEPSEEK_BASE_URL}
DEEPSEEK_MODEL=${DEEPSEEK_MODEL}
AI_WIKI_DAILY_LLM_LIMIT=${AI_WIKI_DAILY_LLM_LIMIT}
TKMIND_TTS_BASE_URL=${TKMIND_TTS_BASE_URL}
TKMIND_TTS_ENABLED=${TKMIND_TTS_ENABLED}
TKMIND_TTS_SPK_ID=${TKMIND_TTS_SPK_ID}
EOF
chmod 600 "$ROOT/backend/.env"
echo ">>> Python 虚拟环境与依赖"
cd "$ROOT/backend"
if [ ! -d venv ]; then
python3 -m venv venv
fi
source venv/bin/activate
pip install -q -r requirements.txt
echo ">>> OCR 依赖(iOS 拍照录入走服务端识别)"
if command -v tesseract >/dev/null 2>&1; then
echo "tesseract 已安装: $(tesseract --version 2>&1 | head -1)"
else
if command -v apt-get >/dev/null 2>&1; then
apt-get update -qq
apt-get install -y -qq tesseract-ocr tesseract-ocr-chi-sim tesseract-ocr-eng
elif command -v yum >/dev/null 2>&1; then
yum install -y tesseract tesseract-langpack-chi-sim 2>/dev/null || true
elif command -v dnf >/dev/null 2>&1; then
dnf install -y tesseract tesseract-langpack-chi-sim 2>/dev/null || true
fi
fi
if ! command -v tesseract >/dev/null 2>&1; then
echo "警告: 未安装 tesseractiOS 拍照录入将无法识别照片" >&2
fi
echo ">>> 创建数据库(若不存在)并建表"
python - <<'PY'
import pymysql
from config import get_settings
s = get_settings()
conn = pymysql.connect(
host=s.mysql_host,
port=s.mysql_port,
user=s.mysql_user,
password=s.mysql_password,
charset="utf8mb4",
)
try:
with conn.cursor() as cur:
cur.execute(
f"CREATE DATABASE IF NOT EXISTS `{s.mysql_database}` "
"CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
)
conn.commit()
print(f"database `{s.mysql_database}` ready")
finally:
conn.close()
from database import engine, Base
from sqlalchemy import text
import models # noqa: F401
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
Base.metadata.create_all(bind=engine)
print("tables ready")
PY
echo ">>> 导入词书目录(沪版 + 商务)"
cd "$ROOT/backend"
source venv/bin/activate
if [ -d "$ROOT/backend/data/books" ] && ls "$ROOT/backend/data/books"/*.json >/dev/null 2>&1; then
python -m scripts.import_word_books
else
echo "未找到 data/books/*.json,跳过词书导入"
fi
echo ">>> 构建前端"
cd "$ROOT/frontend"
if ! command -v npm >/dev/null 2>&1; then
echo "请先安装 Node.js/npm"
exit 1
fi
npm ci --silent
npm run build
echo ">>> Nginx 可读静态目录"
chmod 755 /root /root/wordloop /root/wordloop/frontend /root/wordloop/frontend/dist 2>/dev/null || true
echo ">>> 配置 Nginx + HTTPS (w.tkmind.cn)"
if command -v nginx >/dev/null 2>&1; then
cp "$ROOT/deploy/wordloop-locations.inc" /etc/nginx/conf.d/wordloop-locations.inc
chmod +x "$ROOT/deploy/ssl-w.tkmind.cn.sh"
bash "$ROOT/deploy/ssl-w.tkmind.cn.sh"
systemctl enable nginx 2>/dev/null || true
else
echo "警告: 未安装 nginx,请手动安装后执行 deploy/ssl-w.tkmind.cn.sh"
fi
echo ">>> 配置 systemd 后端服务"
cp "$ROOT/deploy/systemd/wordloop-backend-root.service" /etc/systemd/system/wordloop-backend.service
systemctl daemon-reload
systemctl enable wordloop-backend
systemctl restart wordloop-backend
echo ">>> 完成"
systemctl --no-pager status wordloop-backend || true
curl -sf http://127.0.0.1:18004/ >/dev/null && echo "API: ok" || echo "API: 请检查 journalctl -u wordloop-backend"