fix: update code

This commit is contained in:
Daniel
2026-03-03 17:54:43 +08:00
parent 1764a44eb3
commit 0cbeaf59a5
6 changed files with 156 additions and 12 deletions

4
.gitignore vendored
View File

@@ -23,8 +23,8 @@ dist-ssr
*.sln
*.sw?
# API database
# server/data.db
# API databaseSQLite 文件,部署时应挂载卷持久化,勿提交)
server/data.db
# Env含 token勿提交
.env

Binary file not shown.

View File

@@ -8,9 +8,6 @@ const db = require('./db')
const routes = require('./routes')
const { getSituation } = require('./situationData')
const swaggerUi = require('swagger-ui-express')
const openApiSpec = require('./openapi')
const app = express()
const PORT = process.env.API_PORT || 3001
@@ -21,9 +18,6 @@ app.set('trust proxy', 1)
app.use(cors())
app.use(express.json())
// Swagger 文档
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(openApiSpec))
app.use('/api', routes)
app.get('/api/health', (_, res) => res.json({ ok: true }))
app.post('/api/crawler/notify', (req, res) => {

View File

@@ -155,6 +155,7 @@ export function WarMap() {
const fordPathsRef = useRef<[number, number][][]>([])
const israelPathsRef = useRef<[number, number][][]>([])
const hezbollahPathsRef = useRef<[number, number][][]>([])
const hormuzPathsRef = useRef<[number, number][][]>([])
const situation = useReplaySituation()
const { usForces, iranForces, conflictEvents = [] } = situation
@@ -220,10 +221,32 @@ export function WarMap() {
() => EXTENDED_WAR_ZONES.activeAttacks.map((t) => parabolaPath(HEZBOLLAH_SOURCE, t.coords, 1.5)),
[]
)
// 伊朗不同地点 → 霍尔木兹海峡多点攻击(黄色轨迹)
const hormuzTargetPoints = useMemo(
() =>
[
[55.7, 25.6],
[56.0, 26.0],
[56.4, 26.4],
] as [number, number][],
[]
)
const hormuzPaths = useMemo(() => {
// 使用更远的伊朗腹地/纵深位置,弧线更明显
const sources: [number, number][] = [
TEHRAN_SOURCE, // 德黑兰
[47.16, 34.35], // 克尔曼沙赫导弹阵地
[50.88, 34.64], // 库姆附近
]
return hormuzTargetPoints.map((target, idx) =>
parabolaPath(sources[idx % sources.length], target, 3)
)
}, [hormuzTargetPoints])
lincolnPathsRef.current = lincolnPaths
fordPathsRef.current = fordPaths
israelPathsRef.current = israelPaths
hezbollahPathsRef.current = hezbollahPaths
hormuzPathsRef.current = hormuzPaths
const lincolnLinesGeoJson = useMemo(
() => ({
@@ -270,6 +293,18 @@ export function WarMap() {
[hezbollahPaths]
)
const hormuzLinesGeoJson = useMemo(
() => ({
type: 'FeatureCollection' as const,
features: hormuzPaths.map((coords) => ({
type: 'Feature' as const,
properties: {},
geometry: { type: 'LineString' as const, coordinates: coords },
})),
}),
[hormuzPaths]
)
const attackLinesGeoJson = useMemo(
() => ({
type: 'FeatureCollection' as const,
@@ -295,6 +330,19 @@ export function WarMap() {
[]
)
// 霍尔木兹海峡被持续打击的海面目标(用于脉冲与标记)
const hormuzTargetsGeoJson = useMemo(
() => ({
type: 'FeatureCollection' as const,
features: hormuzTargetPoints.map((coords, idx) => ({
type: 'Feature' as const,
properties: { id: `H${idx + 1}` },
geometry: { type: 'Point' as const, coordinates: coords },
})),
}),
[hormuzTargetPoints]
)
// 霍尔木兹海峡交战区 & 真主党势力范围(静态面)
const hormuzZone = EXTENDED_WAR_ZONES.hormuzCombatZone
const hezbollahZone = EXTENDED_WAR_ZONES.hezbollahZone
@@ -461,6 +509,24 @@ export function WarMap() {
})
hezSrc.setData({ type: 'FeatureCollection', features })
}
// 伊朗对霍尔木兹海峡:黄色光点,沿海峡方向飞行
const hormuzSrc = map.getSource('iran-hormuz-dots') as
| { setData: (d: GeoJSON.FeatureCollection) => void }
| undefined
const hormuzPaths = hormuzPathsRef.current
if (hormuzSrc && hormuzPaths.length > 0) {
const features: GeoJSON.Feature<GeoJSON.Point>[] = hormuzPaths.map((path, i) => {
const progress =
(elapsed / FLIGHT_DURATION_MS + 0.15 + i / Math.max(hormuzPaths.length, 1)) % 1
const coord = interpolateOnPath(path, progress)
return {
type: 'Feature' as const,
properties: {},
geometry: { type: 'Point' as const, coordinates: coord },
}
})
hormuzSrc.setData({ type: 'FeatureCollection', features })
}
// 伊朗被打击目标:蓝色脉冲 (2s 周期), 半径随 zoom 缩放phase/r/opacity 钳位
if (map.getLayer('allied-strike-targets-pulse')) {
const cycle = 2000
@@ -493,6 +559,15 @@ export function WarMap() {
map.setPaintProperty('hezbollah-attack-targets-pulse', 'circle-radius', r)
map.setPaintProperty('hezbollah-attack-targets-pulse', 'circle-opacity', opacity)
}
// 霍尔木兹海峡被打击目标:琥珀黄脉冲,保持与其他被打击点一致但颜色区分
if (map.getLayer('iran-hormuz-targets-pulse')) {
const cycle = 2000
const phase = Math.max(0, Math.min(1, (elapsed % cycle) / cycle))
const r = Math.max(0, 32 * phase * zoomScale)
const opacity = Math.min(1, Math.max(0, 1 - phase * 1.1))
map.setPaintProperty('iran-hormuz-targets-pulse', 'circle-radius', r)
map.setPaintProperty('iran-hormuz-targets-pulse', 'circle-opacity', opacity)
}
} catch (_) {}
}
animRef.current = requestAnimationFrame(tick)
@@ -646,6 +721,74 @@ export function WarMap() {
/>
</Source>
{/* 伊朗对霍尔木兹海峡的打击路径(黄色轨迹) */}
<Source id="iran-hormuz-lines" type="geojson" data={hormuzLinesGeoJson}>
<Layer
id="iran-hormuz-lines"
type="line"
paint={{
'line-color': 'rgba(250, 204, 21, 0.55)',
'line-width': ['interpolate', ['linear'], ['zoom'], 4, 0.6, 8, 1.2, 12, 2],
}}
/>
</Source>
{/* 伊朗对霍尔木兹的打击光点(黄色) */}
<Source
id="iran-hormuz-dots"
type="geojson"
data={{
type: 'FeatureCollection',
features: hormuzPaths.map((path) => ({
type: 'Feature' as const,
properties: {},
geometry: { type: 'Point' as const, coordinates: path[0] },
})),
}}
>
<Layer
id="iran-hormuz-dots-glow"
type="circle"
paint={{
'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 3, 8, 5.5, 12, 9],
'circle-color': 'rgba(250, 204, 21, 0.65)',
'circle-blur': 0.3,
}}
/>
<Layer
id="iran-hormuz-dots-core"
type="circle"
paint={{
'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 1.2, 8, 2.2, 12, 3.8],
'circle-color': '#facc15',
'circle-stroke-width': 0.6,
'circle-stroke-color': '#fff',
}}
/>
</Source>
{/* 霍尔木兹海峡被打击目标点 + 脉冲(与其他被打击点风格一致,颜色区分为琥珀黄) */}
<Source id="iran-hormuz-targets" type="geojson" data={hormuzTargetsGeoJson}>
<Layer
id="iran-hormuz-targets-dot"
type="circle"
paint={{
'circle-radius': ['interpolate', ['linear'], ['zoom'], 4, 2, 8, 3.5, 12, 5],
'circle-color': '#fbbf24',
'circle-stroke-width': 0.5,
'circle-stroke-color': '#fff',
}}
/>
<Layer
id="iran-hormuz-targets-pulse"
type="circle"
paint={{
'circle-radius': 0,
'circle-color': 'rgba(251, 191, 36, 0.45)',
'circle-opacity': 0,
}}
/>
</Source>
<Source id="points-us-base-damaged" type="geojson" data={usBaseDamaged}>
<Layer
id="points-damaged"
@@ -1259,14 +1402,14 @@ export function WarMap() {
type="symbol"
layout={{
'text-field': ['get', 'name'],
// 字体尽量小一些,避免遮挡
'text-size': ['interpolate', ['linear'], ['zoom'], 4, 7, 7, 9, 10, 11],
// 字体进一步调小,避免与该区域多重效果叠加后显得拥挤
'text-size': ['interpolate', ['linear'], ['zoom'], 4, 5.5, 7, 7.5, 10, 9],
'text-anchor': 'center',
}}
paint={{
'text-color': '#FACC15',
'text-halo-color': '#1a1a1a',
'text-halo-width': 1,
'text-halo-width': 0.8,
}}
/>
</Source>

View File

@@ -20,7 +20,14 @@ echo "==> Checking crawler Python deps..."
pip install -q -r crawler/requirements.txt 2>/dev/null || true
echo "==> Seeding database (if needed)..."
[ ! -f server/data.db ] && npm run api:seed
# 若指定了 DB_PATH则以 DB_PATH 为准;否则默认使用 server/data.db
DB_FILE_PATH="${DB_PATH:-server/data.db}"
if [ ! -f "$DB_FILE_PATH" ]; then
echo " - DB file not found at $DB_FILE_PATH, running api:seed once"
npm run api:seed
else
echo " - Existing DB detected at $DB_FILE_PATH, skip seeding"
fi
echo "==> Starting API (http://localhost:3001)..."
npm run api &