Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { listCars, listSites, listTracks } from '@/api/projection'
|
||||
import { reflectionApi } from '@/api/reflection'
|
||||
import { getWizardProfile } from '@/api/wizard'
|
||||
import type { SetupCarParamRow, SetupStatus } from '@/types/setup'
|
||||
|
||||
const IP_KEYS = ['address', 'ip']
|
||||
const PORT_KEYS = ['port', 'magport']
|
||||
|
||||
function pick(rows: Array<{ key: string; value: string }>, keys: string[]): string {
|
||||
const set = new Set(keys)
|
||||
const hit = rows.find((r) => set.has(r.key.toLowerCase()))
|
||||
return (hit?.value ?? '').trim()
|
||||
}
|
||||
|
||||
function ipOk(v: string): boolean {
|
||||
return v.length > 0 && v !== '0.0.0.0'
|
||||
}
|
||||
|
||||
function portOk(v: string): boolean {
|
||||
const n = Number(v)
|
||||
return Number.isFinite(n) && n > 0 && n <= 65535
|
||||
}
|
||||
|
||||
async function inspectCarParams(rawId: number, name: string): Promise<SetupCarParamRow> {
|
||||
try {
|
||||
const fields = await reflectionApi.getFields('car', rawId)
|
||||
const address = pick(fields, IP_KEYS)
|
||||
const port = pick(fields, PORT_KEYS)
|
||||
return { id: rawId, name, address, port, paramsReady: ipOk(address) && portOk(port) }
|
||||
} catch {
|
||||
return { id: rawId, name, address: '', port: '', paramsReady: false }
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadSetupStatus(): Promise<SetupStatus> {
|
||||
const empty: SetupStatus = {
|
||||
carCount: 0,
|
||||
carsWithParams: 0,
|
||||
siteCount: 0,
|
||||
trackCount: 0,
|
||||
carsReady: false,
|
||||
mapsReady: false,
|
||||
incomplete: true,
|
||||
cars: [],
|
||||
navigationKinds: [],
|
||||
scenarios: [],
|
||||
modules: []
|
||||
}
|
||||
|
||||
try {
|
||||
const [cars, sites, tracks, profile] = await Promise.all([
|
||||
listCars().catch(() => []),
|
||||
listSites().catch(() => []),
|
||||
listTracks().catch(() => []),
|
||||
getWizardProfile().catch(() => null)
|
||||
])
|
||||
|
||||
const inspected = await Promise.all(
|
||||
cars.slice(0, 40).map((c) => {
|
||||
const id = c.rawId ?? Number(String(c.id).replace(/^C/i, ''))
|
||||
if (!Number.isFinite(id) || id <= 0) {
|
||||
return Promise.resolve({
|
||||
id: 0,
|
||||
name: c.name,
|
||||
address: c.address ?? c.ip ?? '',
|
||||
port: '',
|
||||
paramsReady: ipOk(c.address ?? c.ip ?? '')
|
||||
} satisfies SetupCarParamRow)
|
||||
}
|
||||
return inspectCarParams(id, c.name)
|
||||
})
|
||||
)
|
||||
|
||||
const carsWithParams = inspected.filter((c) => c.paramsReady).length
|
||||
const couldReadParams = inspected.some((c) => c.address || c.port || c.paramsReady)
|
||||
const carsReady = cars.length >= 1 && (!couldReadParams || carsWithParams >= 1)
|
||||
const mapsReady = sites.length >= 1 && tracks.length >= 1
|
||||
|
||||
return {
|
||||
carCount: cars.length,
|
||||
carsWithParams,
|
||||
siteCount: sites.length,
|
||||
trackCount: tracks.length,
|
||||
carsReady,
|
||||
mapsReady,
|
||||
incomplete: !(carsReady && mapsReady),
|
||||
cars: inspected,
|
||||
navigationKinds: profile?.navigationKinds ?? [],
|
||||
scenarios: profile?.scenarios ?? [],
|
||||
modules: profile?.modules ?? []
|
||||
}
|
||||
} catch (e) {
|
||||
return {
|
||||
...empty,
|
||||
error: e instanceof Error ? e.message : String(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import http from './http'
|
||||
|
||||
const MOCK = import.meta.env.VITE_USE_MOCK === 'true'
|
||||
|
||||
export interface SignalColumn {
|
||||
key: string
|
||||
label: string
|
||||
type: 'string' | 'int' | 'bool' | 'enum' | string
|
||||
options?: string[] | null
|
||||
group?: string | null
|
||||
}
|
||||
|
||||
export interface SignalTableSummary {
|
||||
id: string
|
||||
title: string
|
||||
category: string
|
||||
fileName: string
|
||||
}
|
||||
|
||||
export interface SignalTableDto extends SignalTableSummary {
|
||||
exists: boolean
|
||||
error?: string | null
|
||||
columns: SignalColumn[]
|
||||
rows: Record<string, unknown>[]
|
||||
}
|
||||
|
||||
export interface SignalDataListDto {
|
||||
signalEnabled: boolean
|
||||
workingDirectory?: string | null
|
||||
tables: SignalTableSummary[]
|
||||
}
|
||||
|
||||
export async function listSignalTables(): Promise<SignalDataListDto> {
|
||||
if (MOCK) {
|
||||
return {
|
||||
signalEnabled: true,
|
||||
workingDirectory: 'D:\\工作\\stand\\SimpleLite',
|
||||
tables: [
|
||||
{ id: 'stations', title: 'PLC机构', category: 'PLC数据管理', fileName: 'stations.json' },
|
||||
{ id: 'docks', title: '机构工位', category: 'PLC数据管理', fileName: 'station-docks.json' },
|
||||
{ id: 'handshake', title: '握手点', category: '握手点数据管理', fileName: 'handshake-points.json' },
|
||||
{ id: 'release', title: '放行点', category: '放行点数据管理', fileName: 'release-points.json' },
|
||||
{ id: 'mag-control', title: '磁条管控区', category: '磁条交管', fileName: 'mag-control-areas.json' }
|
||||
]
|
||||
}
|
||||
}
|
||||
const { data } = await http.get<SignalDataListDto>('/signal-data', { params: { summary: true } })
|
||||
return data
|
||||
}
|
||||
|
||||
export async function getSignalTable(id: string): Promise<SignalTableDto> {
|
||||
if (MOCK) {
|
||||
const list = await listSignalTables()
|
||||
const meta = list.tables.find((t) => t.id === id)
|
||||
if (!meta) throw new Error(`未知数据表:${id}`)
|
||||
return { ...meta, exists: true, columns: [], rows: [] }
|
||||
}
|
||||
const { data } = await http.get<SignalTableDto>(`/signal-data/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
export async function saveSignalTable(id: string, rows: Record<string, unknown>[]): Promise<SignalTableDto> {
|
||||
if (MOCK) {
|
||||
const t = await getSignalTable(id)
|
||||
return { ...t, rows: JSON.parse(JSON.stringify(rows)) }
|
||||
}
|
||||
const { data } = await http.put<SignalTableDto>(`/signal-data/${id}`, { rows })
|
||||
return data
|
||||
}
|
||||
@@ -29,6 +29,24 @@ const MOCK_OPTIONS: WizardOptions = {
|
||||
}
|
||||
}
|
||||
|
||||
const NAV_SCENE: Record<string, string> = {
|
||||
magnetic: 'scene.mag',
|
||||
qrcode: 'scene.qrlidar',
|
||||
laser: 'scene.qrlidar'
|
||||
}
|
||||
|
||||
function toLauncherSceneIds(kinds: string[], scenarios: string[] = []): string[] {
|
||||
const result: string[] = []
|
||||
for (const k of kinds) {
|
||||
const id = NAV_SCENE[k] ?? `scene.${k}`
|
||||
if (!result.includes(id)) result.push(id)
|
||||
}
|
||||
const wantSignal = scenarios.some((s) => s === 'tpl-sps' || s === 'tpl-pack')
|
||||
if (wantSignal && !result.includes('scene.signal')) result.push('scene.signal')
|
||||
if (result.length > 0 && !result.includes('scene.device')) result.push('scene.device')
|
||||
return result
|
||||
}
|
||||
|
||||
let mockProfile: DeploymentProfileDto = {
|
||||
configured: false,
|
||||
platformType: 'standard',
|
||||
@@ -61,7 +79,7 @@ export async function saveWizardProfile(req: SaveWizardRequest): Promise<Deploym
|
||||
navigationKinds: req.navigationKinds ?? [],
|
||||
scenarios: req.scenarios ?? [],
|
||||
configured: true,
|
||||
activeSceneIds: (req.navigationKinds ?? []).map((k) => `scene.${k}`)
|
||||
activeSceneIds: toLauncherSceneIds(req.navigationKinds ?? [], req.scenarios ?? [])
|
||||
}
|
||||
return mockProfile
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user