fix: 更新token

This commit is contained in:
Daniel
2026-03-02 16:36:49 +08:00
parent a9caf6e7c0
commit ad73305ed1
11 changed files with 139 additions and 50 deletions

View File

@@ -2,45 +2,3 @@
# 免费申请: https://account.mapbox.com/access-tokens/ # 免费申请: https://account.mapbox.com/access-tokens/
# 复制本文件为 .env 并填入你的 token # 复制本文件为 .env 并填入你的 token
VITE_MAPBOX_ACCESS_TOKEN=your_mapbox_public_token_here VITE_MAPBOX_ACCESS_TOKEN=your_mapbox_public_token_here
27 个基地完整 JSON 数据
[
{ "id": 1, "name": "Al Udeid Air Base", "country": "Qatar", "lat": 25.117, "lng": 51.314 },
{ "id": 2, "name": "Camp As Sayliyah", "country": "Qatar", "lat": 25.275, "lng": 51.520 },
{ "id": 3, "name": "Naval Support Activity Bahrain", "country": "Bahrain", "lat": 26.236, "lng": 50.608 },
{ "id": 4, "name": "Camp Arifjan", "country": "Kuwait", "lat": 28.832, "lng": 47.799 },
{ "id": 5, "name": "Ali Al Salem Air Base", "country": "Kuwait", "lat": 29.346, "lng": 47.520 },
{ "id": 6, "name": "Camp Buehring", "country": "Kuwait", "lat": 29.603, "lng": 47.456 },
{ "id": 7, "name": "Al Dhafra Air Base", "country": "UAE", "lat": 24.248, "lng": 54.547 },
{ "id": 8, "name": "Prince Sultan Air Base", "country": "Saudi Arabia", "lat": 24.062, "lng": 47.580 },
{ "id": 9, "name": "Eskan Village", "country": "Saudi Arabia", "lat": 24.774, "lng": 46.738 },
{ "id": 10, "name": "Al Asad Airbase", "country": "Iraq", "lat": 33.785, "lng": 42.441 },
{ "id": 11, "name": "Erbil Air Base", "country": "Iraq", "lat": 36.237, "lng": 43.963 },
{ "id": 12, "name": "Baghdad Diplomatic Support Center", "country": "Iraq", "lat": 33.315, "lng": 44.366 },
{ "id": 13, "name": "Camp Taji", "country": "Iraq", "lat": 33.556, "lng": 44.256 },
{ "id": 14, "name": "Ain al-Asad", "country": "Iraq", "lat": 33.800, "lng": 42.450 },
{ "id": 15, "name": "Al-Tanf Garrison", "country": "Syria", "lat": 33.490, "lng": 38.618 },
{ "id": 16, "name": "Rmelan Landing Zone", "country": "Syria", "lat": 37.015, "lng": 41.885 },
{ "id": 17, "name": "Shaddadi Base", "country": "Syria", "lat": 36.058, "lng": 40.730 },
{ "id": 18, "name": "Conoco Gas Field Base", "country": "Syria", "lat": 35.336, "lng": 40.295 },
{ "id": 19, "name": "Muwaffaq Salti Air Base", "country": "Jordan", "lat": 32.356, "lng": 36.259 },
{ "id": 20, "name": "Incirlik Air Base", "country": "Turkey", "lat": 37.002, "lng": 35.425 },
{ "id": 21, "name": "Kurecik Radar Station", "country": "Turkey", "lat": 38.354, "lng": 37.794 },
{ "id": 22, "name": "Nevatim Air Base", "country": "Israel", "lat": 31.208, "lng": 35.012 },
{ "id": 23, "name": "Ramon Air Base", "country": "Israel", "lat": 30.776, "lng": 34.666 },
{ "id": 24, "name": "Thumrait Air Base", "country": "Oman", "lat": 17.666, "lng": 54.024 },
{ "id": 25, "name": "Masirah Air Base", "country": "Oman", "lat": 20.675, "lng": 58.890 },
{ "id": 26, "name": "West Cairo Air Base", "country": "Egypt", "lat": 30.915, "lng": 30.298 },
{ "id": 27, "name": "Camp Lemonnier", "country": "Djibouti", "lat": 11.547, "lng": 43.159 }
]

111
DEPLOY.md Normal file
View File

@@ -0,0 +1,111 @@
# Docker 部署到服务器
将 US-Iran 态势面板打包成 Docker 镜像,便于移植到任意服务器。
## 架构
| 服务 | 端口 | 说明 |
|--------|------|--------------------------|
| api | 3001 | 前端静态 + REST API + WebSocket |
| crawler| 8000 | RSS 爬虫 + GDELT内部服务 |
- 数据库SQLite挂载到 `app-data` volume`/data/data.db`
- 前端与 API 合并到同一镜像,访问 `http://主机:3001` 即可
## 快速部署
```bash
# 1. 克隆项目
git clone <repo> usa-dashboard && cd usa-dashboard
# 2. 构建并启动(需先配置 Mapbox Token见下方
docker compose up -d --build
# 3. 访问
# 前端 + API: http://localhost:3001
# 爬虫状态: http://localhost:8000/crawler/status
```
## Mapbox Token地图展示
构建时需将 Token 传入前端,否则地图为占位模式:
```bash
# 方式 1.env 文件
echo "VITE_MAPBOX_ACCESS_TOKEN=pk.xxx" > .env
docker compose up -d --build
# 方式 2环境变量
VITE_MAPBOX_ACCESS_TOKEN=pk.xxx docker compose up -d --build
```
## 推送到私有仓库并移植
```bash
# 1. 打标签(替换为你的仓库地址)
docker compose build
docker tag usa-dashboard-api your-registry/usa-dashboard-api:latest
docker tag usa-dashboard-crawler your-registry/usa-dashboard-crawler:latest
# 2. 推送
docker push your-registry/usa-dashboard-api:latest
docker push your-registry/usa-dashboard-crawler:latest
# 3. 在目标服务器拉取并启动
docker pull your-registry/usa-dashboard-api:latest
docker pull your-registry/usa-dashboard-crawler:latest
# 需准备 docker-compose.yml 或等效编排,见下方
```
## 仅用镜像启动(无 compose
```bash
# 1. 创建网络与数据卷
docker network create usa-net
docker volume create usa-data
# 2. 启动 API前端+接口)
docker run -d --name api --network usa-net \
-p 3001:3001 \
-v usa-data:/data \
-e DB_PATH=/data/data.db \
usa-dashboard-api
# 3. 启动爬虫(通过 usa-net 访问 api
docker run -d --name crawler --network usa-net \
-v usa-data:/data \
-e DB_PATH=/data/data.db \
-e API_BASE=http://api:3001 \
-e CLEANER_AI_DISABLED=1 \
-e GDELT_DISABLED=1 \
usa-dashboard-crawler
```
爬虫通过 `API_BASE` 调用 Node 的 `/api/crawler/notify`,两容器需在同一网络内。
## 国内服务器 / 镜像加速
拉取 `node``python` 等基础镜像慢时:
1. **Docker 镜像加速**:见 [docs/DOCKER_MIRROR.md](docs/DOCKER_MIRROR.md)
2. **构建时使用国内镜像源**
```bash
docker compose build --build-arg REGISTRY=docker.m.daocloud.io/library/
docker compose up -d
```
## 常用操作
```bash
# 查看日志
docker compose logs -f
# 重启
docker compose restart
# 停止并删除容器(数据卷保留)
docker compose down
# 回填战损数据(从 situation_update 重新提取)
curl -X POST http://localhost:8000/crawler/backfill
```

View File

@@ -1,5 +1,7 @@
# 前端 + API 一体化镜像(使用 DaoCloud 国内镜像源) # 前端 + API 一体化镜像
FROM docker.m.daocloud.io/library/node:20-alpine AS frontend-builder # 国内服务器拉取慢时,可加 --build-arg REGISTRY=docker.m.daocloud.io/library
ARG REGISTRY=
FROM ${REGISTRY}node:20-alpine AS frontend-builder
WORKDIR /app WORKDIR /app
ARG VITE_MAPBOX_ACCESS_TOKEN ARG VITE_MAPBOX_ACCESS_TOKEN
ENV VITE_MAPBOX_ACCESS_TOKEN=${VITE_MAPBOX_ACCESS_TOKEN} ENV VITE_MAPBOX_ACCESS_TOKEN=${VITE_MAPBOX_ACCESS_TOKEN}
@@ -8,7 +10,7 @@ RUN npm ci
COPY . . COPY . .
RUN npm run build RUN npm run build
FROM docker.m.daocloud.io/library/node:20-alpine FROM ${REGISTRY}node:20-alpine
WORKDIR /app WORKDIR /app
COPY package*.json ./ COPY package*.json ./
RUN npm ci --omit=dev RUN npm ci --omit=dev

View File

@@ -1,9 +1,11 @@
# Python 爬虫服务(使用 DaoCloud 国内镜像源 + 清华 PyPI 源) # Python 爬虫服务
FROM docker.m.daocloud.io/library/python:3.11-slim # 国内服务器可加 --build-arg REGISTRY=docker.m.daocloud.io/library
ARG REGISTRY=
FROM ${REGISTRY}python:3.11-slim
WORKDIR /app WORKDIR /app
COPY crawler/requirements.txt ./ COPY crawler/requirements.txt ./
RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
COPY crawler ./ COPY crawler ./
ENV DB_PATH=/data/data.db ENV DB_PATH=/data/data.db

View File

@@ -94,6 +94,8 @@ docker compose up -d
# 数据库与爬虫共享 volume首次启动自动 seed # 数据库与爬虫共享 volume首次启动自动 seed
``` ```
**迁移到服务器**:见 [DEPLOY.md](DEPLOY.md)(构建、推送、单机/多机部署说明)
**拉取镜像超时?** 在 Docker Desktop 配置镜像加速,见 [docs/DOCKER_MIRROR.md](docs/DOCKER_MIRROR.md) **拉取镜像超时?** 在 Docker Desktop 配置镜像加速,见 [docs/DOCKER_MIRROR.md](docs/DOCKER_MIRROR.md)
**开发时无需每次 rebuild**:使用开发模式挂载源码 + 热重载: **开发时无需每次 rebuild**:使用开发模式挂载源码 + 热重载:

View File

@@ -1,5 +1,6 @@
services: services:
api: api:
image: usa-dashboard-api:latest
build: build:
context: . context: .
args: args:
@@ -14,6 +15,7 @@ services:
restart: unless-stopped restart: unless-stopped
crawler: crawler:
image: usa-dashboard-crawler:latest
build: build:
context: . context: .
dockerfile: Dockerfile.crawler dockerfile: Dockerfile.crawler

Binary file not shown.

Binary file not shown.

View File

@@ -3,6 +3,7 @@ import { Play, Pause, SkipBack, SkipForward, History } from 'lucide-react'
import { usePlaybackStore, REPLAY_TICKS, REPLAY_START, REPLAY_END } from '@/store/playbackStore' import { usePlaybackStore, REPLAY_TICKS, REPLAY_START, REPLAY_END } from '@/store/playbackStore'
import { useSituationStore } from '@/store/situationStore' import { useSituationStore } from '@/store/situationStore'
import { NewsTicker } from './NewsTicker' import { NewsTicker } from './NewsTicker'
import { config } from '@/config'
function formatTick(iso: string): string { function formatTick(iso: string): string {
const d = new Date(iso) const d = new Date(iso)
@@ -78,7 +79,7 @@ export function TimelinePanel() {
</button> </button>
{!isReplayMode && ( {!isReplayMode && config.showNewsTicker && (
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<NewsTicker <NewsTicker
updates={situation.recentUpdates} updates={situation.recentUpdates}

View File

@@ -4,6 +4,7 @@ import type { MapRef } from 'react-map-gl'
import type { Map as MapboxMap } from 'mapbox-gl' import type { Map as MapboxMap } from 'mapbox-gl'
import 'mapbox-gl/dist/mapbox-gl.css' import 'mapbox-gl/dist/mapbox-gl.css'
import { useReplaySituation } from '@/hooks/useReplaySituation' import { useReplaySituation } from '@/hooks/useReplaySituation'
import { config } from '@/config'
import { import {
ATTACKED_TARGETS, ATTACKED_TARGETS,
ALLIED_STRIKE_LOCATIONS, ALLIED_STRIKE_LOCATIONS,
@@ -15,7 +16,7 @@ import {
ISRAEL_STRIKE_TARGETS, ISRAEL_STRIKE_TARGETS,
} from '@/data/mapLocations' } from '@/data/mapLocations'
const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN || '' const MAPBOX_TOKEN = config.mapboxAccessToken || ''
// 相关区域 bbox伊朗、以色列、胡塞区 (minLng, minLat, maxLng, maxLat),覆盖红蓝区域 // 相关区域 bbox伊朗、以色列、胡塞区 (minLng, minLat, maxLng, maxLat),覆盖红蓝区域
const THEATER_BBOX = [22, 11, 64, 41] as const const THEATER_BBOX = [22, 11, 64, 41] as const

10
src/config.ts Normal file
View File

@@ -0,0 +1,10 @@
/**
* 应用配置(不依赖 .env
*/
export const config = {
/** Mapbox 地图令牌 */
mapboxAccessToken:
'pk.eyJ1IjoiZDI5cTAiLCJhIjoiY21oaGRmcTkzMGltZzJscHR1N2FhZnY5dCJ9.7ueF2lS6-C9Mm_xon7NnIA',
/** 是否显示滚动情报 */
showNewsTicker: false,
}