fix: 修复设备标识提取、单程票逻辑及前端行程块显示

- 调整后端设备标识提取优先级,优先使用machine_id/machineId字段
- 修复单程票检票时剩余乘车次数的计算逻辑,单程票使用后直接置0
- 前端为行程块添加ID,切换单程票模式时隐藏该块并重置乘车次数为1
This commit is contained in:
2026-07-10 00:46:06 +08:00
parent fc4fe5101c
commit 5a3d77d36d
4 changed files with 10 additions and 7 deletions
+5 -5
View File
@@ -792,7 +792,7 @@ router.post('/ic-cards/:id/sync', async (req, res) => {
const syncTypeRaw = String(body.type || body.event_type || body.last_event || 'sync').trim().toLowerCase();
const syncType = syncTypeRaw === 'refill' ? 'topup' : (syncTypeRaw || 'sync');
const action = String(body.action || body.last_action || '').trim().toLowerCase();
const device = String(body.device || body.source || 'device').trim() || 'device';
const device = String(body.machine_id || body.machineId || body.device || body.source || 'device').trim() || 'device';
const station_code = resolveCurrentStationCode(body, resolveStation);
const entry_station = resolveStation(body.entry_station || body.start_station || current.entry_station || '');
const exit_station = resolveStation(body.exit_station || current.exit_station || '');
@@ -859,7 +859,7 @@ router.post('/cards/open', async (req, res) => {
const body = req.body || {};
const now = Date.now();
const voucher_code = normalizeOrderCode(body.voucher_code || body.order_code || body.code);
const device = String(body.device || 'ticket_machine').trim() || 'ticket_machine';
const device = String(body.machine_id || body.machineId || body.device || 'ticket_machine').trim() || 'ticket_machine';
const station_code = String(body.station_code || '').trim();
const holder_name = String(body.holder_name || '').trim();
const note = String(body.note || '').trim();
@@ -1004,7 +1004,7 @@ router.post('/cards/check', async (req, res) => {
const body = req.body || {};
const card_id = normalizeIcCardId(body.card_id);
const action = String(body.action || '').trim().toLowerCase();
const device = String(body.device || 'gate').trim() || 'gate';
const device = String(body.machine_id || body.machineId || body.device || 'gate').trim() || 'gate';
const ts = toFiniteNumberOrUndef(body.ts) ?? Date.now();
if (!card_id || !action) return res.status(400).json({ ok: false, error: 'card_id and action required' });
if (action !== 'entry' && action !== 'exit') return res.status(400).json({ ok: false, error: 'action must be entry/exit' });
@@ -1240,7 +1240,7 @@ router.post('/tickets/check', async (req, res) => {
const body = req.body || {};
const ticket_id = normalizeTicketId(body.ticket_id);
const action = String(body.action || '').trim().toLowerCase();
const device = String(body.device || 'gate');
const device = String(body.machine_id || body.machineId || body.device || 'gate');
const tsIn = Number(body.ts);
const ts = Number.isFinite(tsIn) ? tsIn : Date.now();
const hintTripsTotal = body.trips_total;
@@ -1378,7 +1378,7 @@ router.post('/tickets/check', async (req, res) => {
if (!entered) return deny('not_entered');
if (exited) return deny('already_exited');
const newTripsRemaining = Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
const newTripsRemaining = isSingleTicket ? 0 : Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
const shouldSetUsed = isSingleTicket ? true : (newTripsRemaining <= 0);
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: exitCode, station_name: resolveStationName(exitCode), device, trips_remaining: newTripsRemaining };
await DataService.appendTicketEvent(ev);
+1 -1
View File
@@ -504,7 +504,7 @@ router.post('/tickets/record', async (req, res) => {
const train_type = String(b.train_type || b.trainType || b.type || '').trim();
const cost = Number(b.cost || 0) || 0;
const station_code = String(b.station_code || b.stationCode || '').trim();
const device = String(b.device || b.device_id || b.deviceId || 'unknown');
const device = String(b.machine_id || b.machineId || b.device || b.device_id || b.deviceId || 'unknown');
const trips_total = (b.trips_total == null) ? undefined : (Number(b.trips_total) || 0);
const trips_remaining = (b.trips_remaining == null) ? undefined : (Number(b.trips_remaining) || 0);
+1 -1
View File
@@ -136,7 +136,7 @@
</label>
</div>
</div>
<div class="jr-form-block jr-trip-block">
<div class="jr-form-block jr-trip-block" id="tripsBlock">
<div class="jr-field-head">
<label class="jr-field-label" for="trips">乘次数量</label>
<span class="jr-field-note">至少 1 次</span>
+3
View File
@@ -715,10 +715,13 @@
if (isSingle) {
document.getElementById('normalTicketView').style.display = 'none';
document.getElementById('singleTicketView').style.display = 'block';
document.getElementById('tripsBlock').style.display = 'none';
if (tripsEl) tripsEl.value = 1;
renderSingleSegments();
} else {
document.getElementById('normalTicketView').style.display = 'block';
document.getElementById('singleTicketView').style.display = 'none';
document.getElementById('tripsBlock').style.display = 'block';
}
previewPrice(true);
}