fix: 更新token
This commit is contained in:
42
.env.example
42
.env.example
@@ -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
111
DEPLOY.md
Normal 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
|
||||||
|
```
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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**:使用开发模式挂载源码 + 热重载:
|
||||||
|
|||||||
@@ -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.
@@ -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}
|
||||||
|
|||||||
@@ -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
10
src/config.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* 应用配置(不依赖 .env)
|
||||||
|
*/
|
||||||
|
export const config = {
|
||||||
|
/** Mapbox 地图令牌 */
|
||||||
|
mapboxAccessToken:
|
||||||
|
'pk.eyJ1IjoiZDI5cTAiLCJhIjoiY21oaGRmcTkzMGltZzJscHR1N2FhZnY5dCJ9.7ueF2lS6-C9Mm_xon7NnIA',
|
||||||
|
/** 是否显示滚动情报 */
|
||||||
|
showNewsTicker: false,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user