功能(设备ID调试): 添加调试埋点与文档以定位设备ID缺失问题

创建调试环境配置文件与调试会话记录文档,在前端页面、票据面板以及后端公共接口的设备ID解析各阶段添加调试埋点,收集原始设备数据与处理后的结果,用于验证相关假设以定位设备ID不显示的根因。
This commit is contained in:
2026-07-10 21:07:37 +08:00
parent 4daa0b6185
commit 5f184bf184
5 changed files with 210 additions and 2 deletions
+2
View File
@@ -0,0 +1,2 @@
DEBUG_SERVER_URL=http://127.0.0.1:7777/event
DEBUG_SESSION_ID=device-id-missing
+28
View File
@@ -0,0 +1,28 @@
# Debug Session: device-id-missing
- **Status**: [OPEN]
- **Issue**: 数据记录中的设备 ID 当前全部未显示,界面只看到“机器ID:”后没有具体值。
- **Debug Server**: http://127.0.0.1:7777/event
- **Log File**: .dbg/trae-debug-log-device-id-missing.ndjson
## Reproduction Steps
1. 使用售票机完成一次售票。
2. 使用闸机完成一次进站或出站。
3. 打开后台或票据时间线页面查看“机器ID”字段。
4. 观察“机器ID:”后方是否为空。
## Hypotheses & Verification
| ID | Hypothesis | Likelihood | Effort | Evidence |
|----|------------|------------|--------|----------|
| A | 后端接口返回的事件对象里根本没有 `device` / `detail.device` 字段 | High | Low | Pending |
| B | 前端格式化函数读到了值,但后续字符串拼接或编码问题把值丢掉了 | High | Low | Pending |
| C | 售票与检票两类事件的数据结构不同,当前前端只兼容了其中一类 | Med | Low | Pending |
| D | 设备端 Lua 确实上报了 ID,但服务端在写库或对外返回时被覆盖成空串 | Med | Med | Pending |
| E | 页面实际运行的不是当前工作区这份前端代码,导致本地修改未生效 | Med | Med | Pending |
## Log Evidence
- 2026-07-10: 已启动 Debug Server `http://127.0.0.1:7777/event`
- 2026-07-10: 已在 `[public.js]` 的票据时间线组装处添加 A/C 埋点
- 2026-07-10: 已在 `[index.js]` 与 `[ticket-board.html]` 的设备 ID 格式化处添加 B 埋点
## Verification Conclusion
[Pending]
+94 -2
View File
@@ -694,8 +694,39 @@ router.get('/tickets/:id', async (req, res, next) => {
}; };
const formattedEvents = events.map(e => { const formattedEvents = events.map(e => {
// #region debug-point A:public-ticket-event-raw
(() => {
const fs = require('fs');
let u = 'http://127.0.0.1:7777/event';
let s = 'device-id-missing';
try {
const env = fs.readFileSync('.dbg/device-id-missing.env', 'utf8');
u = env.match(/DEBUG_SERVER_URL=(.+)/)?.[1] || u;
s = env.match(/DEBUG_SESSION_ID=(.+)/)?.[1] || s;
} catch {}
fetch(u, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: s,
runId: 'pre-fix',
hypothesisId: 'A',
location: 'server/routes/public.js:696',
msg: '[DEBUG] public ticket event raw',
data: {
type: e?.type || '',
action: e?.action || '',
ticket_id: e?.ticket_id || '',
device: e?.device ?? null,
detail_device: e?.detail?.device ?? null
},
ts: Date.now()
})
}).catch(() => {});
})();
// #endregion
if (e.type === 'sale') { if (e.type === 'sale') {
return { const mapped = {
type: 'sale', type: 'sale',
ts: e.ts, ts: e.ts,
station_name: e.station_name || nameFor(e.station_code), station_name: e.station_name || nameFor(e.station_code),
@@ -708,6 +739,36 @@ router.get('/tickets/:id', async (req, res, next) => {
trips_total: e.trips_total ?? 0, trips_total: e.trips_total ?? 0,
amount: e.cost ?? 0 amount: e.cost ?? 0
}; };
// #region debug-point A:public-ticket-event-sale-mapped
(() => {
const fs = require('fs');
let u = 'http://127.0.0.1:7777/event';
let s = 'device-id-missing';
try {
const env = fs.readFileSync('.dbg/device-id-missing.env', 'utf8');
u = env.match(/DEBUG_SERVER_URL=(.+)/)?.[1] || u;
s = env.match(/DEBUG_SESSION_ID=(.+)/)?.[1] || s;
} catch {}
fetch(u, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: s,
runId: 'pre-fix',
hypothesisId: 'A',
location: 'server/routes/public.js:701',
msg: '[DEBUG] public sale event mapped',
data: {
ticket_id: mapped.ticket_id || '',
device: mapped.device ?? null,
station_code: mapped.station_code || ''
},
ts: Date.now()
})
}).catch(() => {});
})();
// #endregion
return mapped;
} else if (e.type === 'status') { } else if (e.type === 'status') {
return { return {
type: 'status', type: 'status',
@@ -720,11 +781,42 @@ router.get('/tickets/:id', async (req, res, next) => {
trips_remaining: e.trips_remaining ?? e.rides_remaining ?? null trips_remaining: e.trips_remaining ?? e.rides_remaining ?? null
}; };
} else if (e.type === 'check') { } else if (e.type === 'check') {
return { const mapped = {
...e, ...e,
station_name: e.station_name || nameFor(e.station_code), station_name: e.station_name || nameFor(e.station_code),
station_en: e.station_code ? enNameFor(e.station_code) : (e.station_en || '') station_en: e.station_code ? enNameFor(e.station_code) : (e.station_en || '')
}; };
// #region debug-point C:public-ticket-event-check-mapped
(() => {
const fs = require('fs');
let u = 'http://127.0.0.1:7777/event';
let s = 'device-id-missing';
try {
const env = fs.readFileSync('.dbg/device-id-missing.env', 'utf8');
u = env.match(/DEBUG_SERVER_URL=(.+)/)?.[1] || u;
s = env.match(/DEBUG_SESSION_ID=(.+)/)?.[1] || s;
} catch {}
fetch(u, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: s,
runId: 'pre-fix',
hypothesisId: 'C',
location: 'server/routes/public.js:718',
msg: '[DEBUG] public check event mapped',
data: {
ticket_id: mapped.ticket_id || '',
action: mapped.action || '',
device: mapped.device ?? null,
station_code: mapped.station_code || ''
},
ts: Date.now()
})
}).catch(() => {});
})();
// #endregion
return mapped;
} }
return e; return e;
}); });
+43
View File
@@ -351,6 +351,29 @@ createApp({
let deviceId = String(ev?.device || ev?.device_id || ev?.detail?.device || ev?.detail?.device_id || ev?.["设备编号"] || ev?.["机器ID"] || '---').trim(); let deviceId = String(ev?.device || ev?.device_id || ev?.detail?.device || ev?.detail?.device_id || ev?.["设备编号"] || ev?.["机器ID"] || '---').trim();
const dStr = deviceId.toLowerCase(); const dStr = deviceId.toLowerCase();
// #region debug-point B:index-ticket-device-before-map
fetch('http://127.0.0.1:7777/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: 'device-id-missing',
runId: 'pre-fix',
hypothesisId: 'B',
location: 'web/index.js:351',
msg: '[DEBUG] admin ticket formatter raw device',
data: {
type,
action,
raw_device: ev?.device ?? null,
raw_device_id: ev?.device_id ?? null,
raw_detail_device: ev?.detail?.device ?? null,
resolved_before_map: deviceId
},
ts: Date.now()
})
}).catch(() => {});
// #endregion
if (dStr === 'gate') { if (dStr === 'gate') {
deviceId = '闸机'; deviceId = '闸机';
} else if (dStr === 'refill_machine') { } else if (dStr === 'refill_machine') {
@@ -364,6 +387,26 @@ createApp({
deviceId = '售票机'; deviceId = '售票机';
} }
} }
// #region debug-point B:index-ticket-device-after-map
fetch('http://127.0.0.1:7777/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: 'device-id-missing',
runId: 'pre-fix',
hypothesisId: 'B',
location: 'web/index.js:373',
msg: '[DEBUG] admin ticket formatter mapped device',
data: {
type,
action,
mapped_device: deviceId
},
ts: Date.now()
})
}).catch(() => {});
// #endregion
const timeStr = formatTime(ev?.ts || ev?.["时间戳"]); const timeStr = formatTime(ev?.ts || ev?.["时间戳"]);
if (type === 'sale' || type === '售票') { if (type === 'sale' || type === '售票') {
+43
View File
@@ -323,6 +323,29 @@
let deviceId = String(event.device || event.device_id || event.detail?.device || event.detail?.device_id || event['设备编号'] || event['机器ID'] || '').trim(); let deviceId = String(event.device || event.device_id || event.detail?.device || event.detail?.device_id || event['设备编号'] || event['机器ID'] || '').trim();
const dStr = deviceId.toLowerCase(); const dStr = deviceId.toLowerCase();
// #region debug-point B:ticket-board-device-before-map
fetch('http://127.0.0.1:7777/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: 'device-id-missing',
runId: 'pre-fix',
hypothesisId: 'B',
location: 'web/ticket-board.html:323',
msg: '[DEBUG] public ticket formatter raw device',
data: {
type,
action,
raw_device: event.device ?? null,
raw_device_id: event.device_id ?? null,
raw_detail_device: event.detail?.device ?? null,
resolved_before_map: deviceId
},
ts: Date.now()
})
}).catch(() => {});
// #endregion
if (dStr === 'gate') { if (dStr === 'gate') {
deviceId = '闸机'; deviceId = '闸机';
} else if (dStr === 'refill_machine') { } else if (dStr === 'refill_machine') {
@@ -339,6 +362,26 @@
} }
} }
// #region debug-point B:ticket-board-device-after-map
fetch('http://127.0.0.1:7777/event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: 'device-id-missing',
runId: 'pre-fix',
hypothesisId: 'B',
location: 'web/ticket-board.html:345',
msg: '[DEBUG] public ticket formatter mapped device',
data: {
type,
action,
mapped_device: deviceId
},
ts: Date.now()
})
}).catch(() => {});
// #endregion
if (stationEn && deviceId) return `${stationEn} (${deviceId})`; if (stationEn && deviceId) return `${stationEn} (${deviceId})`;
if (deviceId) return `设备:${deviceId}`; if (deviceId) return `设备:${deviceId}`;
return stationEn; return stationEn;