feat(ticket): 新增单程票购票与检票功能,优化日志与接口
- 前端新增单程票购票界面,支持票种切换与区间选择、价格预览 - 完善后端检票接口,添加单程票的校验与处理逻辑 - 优化售票机脚本的车票类型映射,新增单程车票支持 - 简化前端售票日志输出,移除冗余站点信息字段 - 新增服务层付费区间计算字段,优化公共接口返回数据
This commit is contained in:
+23
-9
@@ -1336,18 +1336,23 @@ router.post('/tickets/check', async (req, res) => {
|
||||
toFiniteNumberOrUndef(hintTripsRemaining);
|
||||
const tripsRemainEffective = (tripsRemain0 == null) ? tripsTotal : tripsRemain0;
|
||||
|
||||
const isSingleTicket = String(cur.train_type || '').toLowerCase() === 'single';
|
||||
|
||||
if (action === 'entry') {
|
||||
if (!matchesStation(start)) return deny('wrong_station');
|
||||
if (!isSingleTicket && !matchesStation(start)) return deny('wrong_station');
|
||||
if (entered && !exited) return deny('already_entered');
|
||||
|
||||
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: start, station_name: resolveStationName(start), device };
|
||||
const entryCode = isSingleTicket ? (station_code_raw || start) : start;
|
||||
|
||||
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: entryCode, station_name: resolveStationName(entryCode), device };
|
||||
await DataService.appendTicketEvent(ev);
|
||||
await DataService.upsertTicketIndex({
|
||||
ticket_id,
|
||||
entered: true,
|
||||
exited: false,
|
||||
last_action: 'entry',
|
||||
last_station_code: start,
|
||||
last_station_code: entryCode,
|
||||
start: isSingleTicket ? entryCode : cur.start,
|
||||
last_result: 'pass',
|
||||
last_reason: '',
|
||||
last_event: 'check',
|
||||
@@ -1357,22 +1362,31 @@ router.post('/tickets/check', async (req, res) => {
|
||||
});
|
||||
io.emit('ticket:check', ev);
|
||||
appendReqLog(req, { category: 'device', type: 'ticket_check', detail: ev });
|
||||
return res.json({ ok: true, ticket_id, action, result: 'pass', station_code: start, trips_remaining: tripsRemainEffective, destroy_ticket: false });
|
||||
return res.json({ ok: true, ticket_id, action, result: 'pass', station_code: entryCode, trips_remaining: tripsRemainEffective, destroy_ticket: false });
|
||||
}
|
||||
|
||||
const exitCode = station_code_raw || terminal;
|
||||
if (isSingleTicket) {
|
||||
const fareInfo = LogicService.computeFareBoth(cur.start, exitCode);
|
||||
if (!fareInfo || fareInfo.paid_segments !== 1) {
|
||||
return deny('非单区间');
|
||||
}
|
||||
} else {
|
||||
if (!matchesStation(terminal)) return deny('wrong_station');
|
||||
}
|
||||
|
||||
if (!matchesStation(terminal)) return deny('wrong_station');
|
||||
if (!entered) return deny('not_entered');
|
||||
if (exited) return deny('already_exited');
|
||||
|
||||
const newTripsRemaining = Math.max(0, (Number(tripsRemainEffective) || 0) - 1);
|
||||
const shouldSetUsed = newTripsRemaining <= 0;
|
||||
const ev = { ts, type: 'check', ticket_id, action, result: 'pass', station_code: terminal, station_name: resolveStationName(terminal), device, trips_remaining: newTripsRemaining };
|
||||
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);
|
||||
await DataService.upsertTicketIndex({
|
||||
ticket_id,
|
||||
exited: true,
|
||||
last_action: 'exit',
|
||||
last_station_code: terminal,
|
||||
last_station_code: exitCode,
|
||||
last_result: 'pass',
|
||||
last_reason: '',
|
||||
last_event: 'check',
|
||||
@@ -1383,7 +1397,7 @@ router.post('/tickets/check', async (req, res) => {
|
||||
});
|
||||
io.emit('ticket:check', ev);
|
||||
appendReqLog(req, { category: 'device', type: 'ticket_check', detail: ev });
|
||||
return res.json({ ok: true, ticket_id, action, result: 'pass', station_code: terminal, trips_remaining: newTripsRemaining, destroy_ticket: shouldSetUsed });
|
||||
return res.json({ ok: true, ticket_id, action, result: 'pass', station_code: exitCode, trips_remaining: newTripsRemaining, destroy_ticket: shouldSetUsed });
|
||||
});
|
||||
|
||||
router.post('/tickets/status', async (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user