2026-08-23 22:34:45 +08:00
|
|
|
|
/* =========================================================
|
|
|
|
|
|
运行配置 —— 后端地址 / MQTT Broker
|
|
|
|
|
|
优先级:window.__DPM_*__ 全局变量(运行时可被 /api/config 引导覆盖)
|
|
|
|
|
|
> Vite 环境变量(.env.local,构建时)> 内置默认
|
|
|
|
|
|
内置默认(打包部署):Tauri 内 WebView 的 hostname 为 tauri.localhost,
|
|
|
|
|
|
后端与 MQTT Broker 若与展播程序同机部署,回退到 192.168.1.9;
|
|
|
|
|
|
浏览器开发/局域网访问时回退到当前主机 hostname。
|
|
|
|
|
|
========================================================= */
|
|
|
|
|
|
|
|
|
|
|
|
const env = import.meta.env || {};
|
|
|
|
|
|
|
|
|
|
|
|
/* 运行期解析(惰性读取 window.__DPM_*__,供 main.jsx bootstrap 覆盖后再生效) */
|
|
|
|
|
|
function resolveHost() {
|
|
|
|
|
|
const h = window.location.hostname || '192.168.1.9';
|
|
|
|
|
|
// Tauri 打包 WebView(tauri.localhost / localhost)→ 服务同机部署用 192.168.1.9
|
|
|
|
|
|
if (h === 'tauri.localhost' || h === 'localhost' || h === '192.168.1.9' || h.includes('tauri')) {
|
|
|
|
|
|
return '192.168.1.9';
|
|
|
|
|
|
}
|
|
|
|
|
|
return h; // 浏览器开发/局域网:当前主机 IP
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-24 17:15:17 +08:00
|
|
|
|
// 园区后端已迁入 server-core 统一入口:API 由 /park 前缀子应用提供(相对 /api、/file 路径不变)
|
|
|
|
|
|
// 默认指向 server-core 开发端口 :8090 的 /park 前缀;生产用 window.__DPM_API__ 或 VITE_API_BASE 覆盖。
|
|
|
|
|
|
export const API_BASE = window.__DPM_API__ || env.VITE_API_BASE || `http://${resolveHost()}:8090/park`;
|
2026-08-23 22:34:45 +08:00
|
|
|
|
export const MQTT_URL = window.__DPM_MQTT__ || env.VITE_MQTT_URL || `ws://${resolveHost()}:8083/mqtt`;
|
|
|
|
|
|
export const MQTT_USERNAME = window.__DPM_MQTT_USER__ || env.VITE_MQTT_USERNAME || '';
|
|
|
|
|
|
export const MQTT_PASSWORD = window.__DPM_MQTT_PASS__ || env.VITE_MQTT_PASSWORD || '';
|
|
|
|
|
|
|
|
|
|
|
|
/** 惰性读取 API 基址(允许 bootstrap 从后端 /api/config 覆盖后再生效) */
|
|
|
|
|
|
export function getApiBase() {
|
|
|
|
|
|
return window.__DPM_API__ || API_BASE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 惰性读取 MQTT 地址(允许 bootstrap 覆盖后再生效) */
|
|
|
|
|
|
export function getMqttUrl() {
|
|
|
|
|
|
return window.__DPM_MQTT__ || MQTT_URL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function getMqttCredentials() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
username: window.__DPM_MQTT_USER__ || MQTT_USERNAME,
|
|
|
|
|
|
password: window.__DPM_MQTT_PASS__ || MQTT_PASSWORD,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 惰性读取 s2s 实时语音 WebSocket 地址。
|
|
|
|
|
|
* s2s 由 s2s_bridge 在后端同机启动(:8765)→ 语音地址**固定跟随 `api_base` 主机**,
|
|
|
|
|
|
* 不再被 config.json / /api/config 里可能过期的 voice_url 覆盖成错误主机(如 MQTT 的 .3)。
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function getVoiceWsUrl() {
|
|
|
|
|
|
let host;
|
|
|
|
|
|
try {
|
|
|
|
|
|
host = new URL(getApiBase()).hostname;
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
host = resolveHost();
|
|
|
|
|
|
}
|
|
|
|
|
|
return `ws://${host}:8765/v1/realtime`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const MQTT_TOPIC_COMMAND = 'opc/display/command';
|
|
|
|
|
|
export const MQTT_TOPIC_TICK = 'opc/dashboard/tick';
|
|
|
|
|
|
export const MQTT_TOPIC_HEARTBEAT = 'opc/display/heartbeat';
|
2026-08-24 20:14:15 +08:00
|
|
|
|
export const MQTT_TOPIC_BIND = 'opc/display/bind';
|
|
|
|
|
|
|
|
|
|
|
|
/* ---- 大屏永久设备 ID:首次生成并持久化,作为 MQTT 客户端名 / 绑定凭据 ---- */
|
|
|
|
|
|
const DEVICE_ID_KEY = 'dpm_device_id';
|
|
|
|
|
|
export function getDeviceId() {
|
|
|
|
|
|
let id = localStorage.getItem(DEVICE_ID_KEY);
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
id = 'DP-' + Math.random().toString(36).slice(2, 8).toUpperCase() + Date.now().toString(36).slice(-6).toUpperCase();
|
|
|
|
|
|
localStorage.setItem(DEVICE_ID_KEY, id);
|
|
|
|
|
|
}
|
|
|
|
|
|
return id;
|
|
|
|
|
|
}
|