diff --git a/.gitignore b/.gitignore
index 38dd725..171258a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,7 @@ frontend/node_modules/.vite/
# 本地启动/部署日志
backend.log
frontend.log
+.run/
# 临时文件
*.swp
diff --git a/frontend/src/components/AppShell.vue b/frontend/src/components/AppShell.vue
index 160e19b..52f8dee 100644
--- a/frontend/src/components/AppShell.vue
+++ b/frontend/src/components/AppShell.vue
@@ -29,18 +29,6 @@
>
Gallery
-
-
-
- Star
-
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 00aec21..2443820 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -4,10 +4,11 @@ import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
- port: 3000,
+ port: 31400,
+ strictPort: true,
proxy: {
'/api': {
- target: 'http://localhost:8000',
+ target: 'http://localhost:31401',
changeOrigin: true,
},
},
diff --git a/start.sh b/start.sh
index 8e8dd76..aaeca9c 100755
--- a/start.sh
+++ b/start.sh
@@ -1,54 +1,60 @@
#!/usr/bin/env bash
-# MiroSociety 启动脚本 (开发模式)
+# MiroSociety 后台启动 (开发模式)
# 前置: 请先执行 ./deploy.sh 安装依赖
# 前端: http://localhost:31400 后端: http://localhost:31401
+#
+# 直接 ./start.sh 即可启动;已在跑会自动重启。
set -euo pipefail
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
FRONTEND_PORT=31400
BACKEND_PORT=31401
-# 解析到脚本所在目录,并使用绝对路径避免子 shell cd 后路径重复
-SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
VENV_DIR="$SCRIPT_DIR/backend/.venv"
BACKEND_DIR="$SCRIPT_DIR/backend"
FRONTEND_DIR="$SCRIPT_DIR/frontend"
+RUN_DIR="$SCRIPT_DIR/.run"
+BACKEND_PID_FILE="$RUN_DIR/backend.pid"
+FRONTEND_PID_FILE="$RUN_DIR/frontend.pid"
+BACKEND_LOG="$SCRIPT_DIR/backend.log"
+FRONTEND_LOG="$SCRIPT_DIR/frontend.log"
-# 切到脚本所在目录,确保相对路径正确
-cd "$(dirname "$0")"
+cd "$SCRIPT_DIR"
# --- 颜色 ---
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-NC='\033[0m'
-
+RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GREEN}[start.sh]${NC} $*"; }
warn() { echo -e "${YELLOW}[start.sh]${NC} $*"; }
err() { echo -e "${RED}[start.sh]${NC} $*" >&2; }
-# --- 检查命令依赖 ---
+# --- 检查依赖 ---
for cmd in lsof npm node curl; do
- if ! command -v "$cmd" >/dev/null 2>&1; then
- err "缺少依赖命令: $cmd"
- exit 1
- fi
+ command -v "$cmd" >/dev/null 2>&1 || { err "缺少依赖命令: $cmd"; exit 1; }
done
+[[ -x "$VENV_DIR/bin/python3" ]] || { err "未检测到 $VENV_DIR/bin/python3,请先执行 ./deploy.sh"; exit 1; }
+"$VENV_DIR/bin/python3" -c "import uvicorn" 2>/dev/null || { err "venv 缺少 uvicorn,请先执行 ./deploy.sh"; exit 1; }
+[[ -d "$FRONTEND_DIR/node_modules" ]] || { err "未检测到 frontend/node_modules,请先执行 ./deploy.sh"; exit 1; }
+
+mkdir -p "$RUN_DIR"
+
+# --- 已在跑 → 先杀 ---
+read_pid() { [[ -f "$1" ]] && cat "$1" || echo ""; }
+kill_pid_file() {
+ local pid_file="$1" label="$2"
+ local pid
+ pid=$(read_pid "$pid_file")
+ if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
+ kill "$pid" 2>/dev/null || true
+ for _ in $(seq 1 10); do
+ kill -0 "$pid" 2>/dev/null || break
+ sleep 0.3
+ done
+ kill -9 "$pid" 2>/dev/null || true
+ log "$label 已停止 (pid=$pid)"
+ fi
+ rm -f "$pid_file"
+}
-# --- 检查依赖是否已部署 ---
-if [[ ! -x "$VENV_DIR/bin/python3" ]]; then
- err "未检测到 $VENV_DIR/bin/python3,请先执行 ./deploy.sh"
- exit 1
-fi
-if ! "$VENV_DIR/bin/python3" -c "import uvicorn" 2>/dev/null; then
- err "venv 缺少 uvicorn,请先执行 ./deploy.sh"
- exit 1
-fi
-if [[ ! -d frontend/node_modules ]]; then
- err "未检测到 frontend/node_modules,请先执行 ./deploy.sh"
- exit 1
-fi
-
-# --- 释放端口: kill 占用进程 ---
free_port() {
local port="$1"
local pids
@@ -61,39 +67,35 @@ free_port() {
fi
}
-free_port "$FRONTEND_PORT"
+# --- 启动后端 ---
free_port "$BACKEND_PORT"
-
-# --- 清理函数: 退出时杀掉所有子进程 ---
-cleanup() {
- log "正在关闭子进程..."
- if [[ -n "${BACKEND_PID:-}" ]]; then kill -9 "$BACKEND_PID" 2>/dev/null || true; fi
- if [[ -n "${FRONTEND_PID:-}" ]]; then kill -9 "$FRONTEND_PID" 2>/dev/null || true; fi
- exit 0
-}
-trap cleanup INT TERM EXIT
-
-# --- 启动后端 (后台, 使用 venv 内的 uvicorn) ---
-log "启动后端 FastAPI @ :$BACKEND_PORT"
+kill_pid_file "$BACKEND_PID_FILE" "后端"
+log "启动后端 FastAPI @ :$BACKEND_PORT (后台)"
+: >"$BACKEND_LOG"
(
cd "$BACKEND_DIR"
HOST=0.0.0.0 PORT="$BACKEND_PORT" \
- exec "$VENV_DIR/bin/python3" -m uvicorn app.main:app --host 0.0.0.0 --port "$BACKEND_PORT"
-) >"$SCRIPT_DIR/backend.log" 2>&1 &
-BACKEND_PID=$!
-
-# --- 启动前端 (后台, 端口固定为 31400) ---
-log "启动前端 Vite @ :$FRONTEND_PORT"
+ nohup "$VENV_DIR/bin/python3" -m uvicorn app.main:app \
+ --host 0.0.0.0 --port "$BACKEND_PORT" \
+ >>"$BACKEND_LOG" 2>&1 &
+ echo $! >"$BACKEND_PID_FILE"
+ disown || true
+)
+
+# --- 启动前端 ---
+free_port "$FRONTEND_PORT"
+kill_pid_file "$FRONTEND_PID_FILE" "前端"
+log "启动前端 Vite @ :$FRONTEND_PORT (后台)"
+: >"$FRONTEND_LOG"
(
cd "$FRONTEND_DIR"
- npx vite --port "$FRONTEND_PORT" --strictPort
-) >"$SCRIPT_DIR/frontend.log" 2>&1 &
-FRONTEND_PID=$!
-
-log "后端 pid=$BACKEND_PID 前端 pid=$FRONTEND_PID"
-log "等待服务就绪..."
+ nohup npx vite >>"$FRONTEND_LOG" 2>&1 &
+ echo $! >"$FRONTEND_PID_FILE"
+ disown || true
+)
# --- 健康检查 ---
+log "等待服务就绪..."
wait_for() {
local url="$1" name="$2"
for _ in $(seq 1 30); do
@@ -107,16 +109,11 @@ wait_for() {
return 1
}
-wait_for "http://localhost:$BACKEND_PORT/health" "后端"
-wait_for "http://localhost:$FRONTEND_PORT" "前端"
+wait_for "http://localhost:$BACKEND_PORT/health" "后端" || true
+wait_for "http://localhost:$FRONTEND_PORT" "前端" || true
echo
-log "全部就绪!"
+log "全部就绪 ✓"
echo -e " ${GREEN}前端:${NC} http://localhost:$FRONTEND_PORT"
echo -e " ${GREEN}后端:${NC} http://localhost:$BACKEND_PORT (健康检查: /health)"
-echo -e " ${GREEN}日志:${NC} backend.log / frontend.log"
-echo
-warn "按 Ctrl+C 终止所有服务"
-
-# --- 保持前台,跟随日志 ---
-tail -F "$SCRIPT_DIR/backend.log" "$SCRIPT_DIR/frontend.log"
\ No newline at end of file
+echo -e " ${GREEN}日志:${NC} backend.log / frontend.log"
\ No newline at end of file