feat(web, server): 更新品牌文案,新增IC卡批量查询并重构搜索页面
统一替换全站所有HTML页面的品牌标题为FarSight-T.N.E铁路运输,调整部分页面的中文显示文案,例如删除ticket-board.html中的冗余说明文字。格式化重构blog.html的代码结构与缩进,修复末尾无换行的问题。 后端完善/ic-cards/query接口:支持空查询返回全部IC卡列表,按创建时间倒序排序,添加卡片状态和类型的标准化标签,优化请求日志记录。 全面重构IC卡搜索页面的前端逻辑,新增批量查看所有IC卡功能,支持点击卡片查看详情与操作历史,优化状态管理与渲染流程。
This commit is contained in:
+10
-2
@@ -345,8 +345,16 @@ router.post('/orders/:code/consume', async (req, res) => {
|
|||||||
router.get('/ic-cards/query', async (req, res) => {
|
router.get('/ic-cards/query', async (req, res) => {
|
||||||
const q = String(req.query.q || '').trim();
|
const q = String(req.query.q || '').trim();
|
||||||
if (!q) {
|
if (!q) {
|
||||||
appendReqLog(req, { category: 'public', type: 'ic_card_query_invalid', level: 'warn', detail: { q } });
|
const cards = (DataService.getIcCards() || [])
|
||||||
return res.status(400).json({ ok: false, error: 'query required' });
|
.slice()
|
||||||
|
.sort((a, b) => Number(b?.created_ts || 0) - Number(a?.created_ts || 0))
|
||||||
|
.map((card) => ({
|
||||||
|
...presentIcCard(card),
|
||||||
|
status_label: mapIcCardStatus(card.status),
|
||||||
|
card_type_label: mapIcCardType(card.card_type)
|
||||||
|
}));
|
||||||
|
appendReqLog(req, { category: 'public', type: 'ic_card_query_all', detail: { total: cards.length } });
|
||||||
|
return res.json({ ok: true, cards });
|
||||||
}
|
}
|
||||||
const normCardId = normalizeIcCardId(q);
|
const normCardId = normalizeIcCardId(q);
|
||||||
const normOrderCode = String(q || '').trim().toUpperCase();
|
const normOrderCode = String(q || '').trim().toUpperCase();
|
||||||
|
|||||||
+14
-6
@@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
@@ -9,11 +10,13 @@
|
|||||||
<link rel="stylesheet" href="style.css?v=13">
|
<link rel="stylesheet" href="style.css?v=13">
|
||||||
<link rel="stylesheet" href="blog.css?v=2">
|
<link rel="stylesheet" href="blog.css?v=2">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="public-search">
|
<body class="public-search">
|
||||||
<div class="public-container">
|
<div class="public-container">
|
||||||
<header class="search-header" style="text-align: left;">
|
<header class="search-header" style="text-align: left;">
|
||||||
<div style="margin-bottom: 10px; text-align: left;">
|
<div style="margin-bottom: 10px; text-align: left;">
|
||||||
<a href="https://ticket.fse-media.group" id="homeLink" style="color: var(--primary); text-decoration: none; font-weight: 500;">
|
<a href="https://ticket.fse-media.group" id="homeLink"
|
||||||
|
style="color: var(--primary); text-decoration: none; font-weight: 500;">
|
||||||
<i class="fas fa-arrow-left"></i> 返回首页
|
<i class="fas fa-arrow-left"></i> 返回首页
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,15 +46,20 @@ FMG
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card" style="margin-top: 20px;">
|
<div class="card" style="margin-top: 20px;">
|
||||||
<div class="card-title" style="font-size: 1.25rem; font-weight: 700; margin-bottom: 20px; color: var(--text);">
|
<div class="card-title"
|
||||||
<i class="fas fa-server text-primary"></i> 服务器状态</div>
|
style="font-size: 1.25rem; font-weight: 700; margin-bottom: 20px; color: var(--text);">
|
||||||
|
<i class="fas fa-server text-primary"></i> 服务器状态
|
||||||
|
</div>
|
||||||
<div style="overflow-x: auto; width: 100%;">
|
<div style="overflow-x: auto; width: 100%;">
|
||||||
<iframe id="mc-status-traintown-online-" frameborder="0" width="1000" height="500" style="max-width:100%; border-radius: 8px;" scrolling="no" src="https://motd.minebbs.com/iframe?ip=traintown.online&stype=auto&dark=true"></iframe>
|
<iframe id="mc-status-traintown-online-" frameborder="0" width="1000" height="500"
|
||||||
|
style="max-width:100%; border-radius: 8px;" scrolling="no"
|
||||||
|
src="https://motd.minebbs.com/iframe?ip=traintown.online&stype=auto&dark=true"></iframe>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<footer style="margin-top: 60px; padding: 20px 0; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.85rem; text-align: center;">
|
<footer
|
||||||
|
style="margin-top: 60px; padding: 20px 0; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.85rem; text-align: center;">
|
||||||
<p>© 2026 FSE Media Group. All rights reserved.</p>
|
<p>© 2026 FSE Media Group. All rights reserved.</p>
|
||||||
</footer>
|
</footer>
|
||||||
<footer class="site-footer">
|
<footer class="site-footer">
|
||||||
@@ -62,5 +70,5 @@ FMG
|
|||||||
<script src="/custom-dialog.js?v=12"></script>
|
<script src="/custom-dialog.js?v=12"></script>
|
||||||
<script src="blog.js?v=2"></script>
|
<script src="blog.js?v=2"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<a href="/" class="jr-brand" id="icBrandLink">
|
<a href="/" class="jr-brand" id="icBrandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE 铁路运输</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>IC 卡管理后台</span>
|
<span>IC 卡管理后台</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE Railway</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>IC Card Detail</span>
|
<span>IC卡 详情</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<nav class="jr-nav" aria-label="站点导航">
|
<nav class="jr-nav" aria-label="站点导航">
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE Railway</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>IC Card Online Order</span>
|
<span>IC卡 线上预定</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<nav class="jr-nav" aria-label="站点导航">
|
<nav class="jr-nav" aria-label="站点导航">
|
||||||
|
|||||||
@@ -30,8 +30,8 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE Railway</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>IC Card Search</span>
|
<span>IC卡 查询</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<nav class="jr-nav" aria-label="站点导航">
|
<nav class="jr-nav" aria-label="站点导航">
|
||||||
|
|||||||
+125
-22
@@ -4,6 +4,10 @@
|
|||||||
const queryBtn = $('#queryBtn');
|
const queryBtn = $('#queryBtn');
|
||||||
const summaryBoxEl = $('#summaryBox');
|
const summaryBoxEl = $('#summaryBox');
|
||||||
const eventBoxEl = $('#eventBox');
|
const eventBoxEl = $('#eventBox');
|
||||||
|
const state = {
|
||||||
|
cards: [],
|
||||||
|
selectedQuery: ''
|
||||||
|
};
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
async request(url) {
|
async request(url) {
|
||||||
@@ -19,6 +23,15 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getStatusClass = (status) => {
|
||||||
|
const s = String(status || '').trim().toLowerCase();
|
||||||
|
if (s === 'active') return 'jr-status-valid';
|
||||||
|
if (s === 'pending_pickup') return 'jr-status-used';
|
||||||
|
return 'jr-status-expired';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLookupKey = (card) => String(card?.card_id || '').trim();
|
||||||
|
|
||||||
const escapeHtml = (value) => String(value == null ? '' : value)
|
const escapeHtml = (value) => String(value == null ? '' : value)
|
||||||
.replace(/&/g, '&')
|
.replace(/&/g, '&')
|
||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
@@ -44,18 +57,17 @@
|
|||||||
return map[String(event?.type || '').toLowerCase()] || (event?.type || '事件');
|
return map[String(event?.type || '').toLowerCase()] || (event?.type || '事件');
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderSummary = (card) => {
|
const buildCardPreview = (card) => {
|
||||||
const shownCardId = card.display_card_id || card.card_id || '---';
|
const shownCardId = card.display_card_id || card.card_id || '---';
|
||||||
summaryBoxEl.className = '';
|
return `
|
||||||
summaryBoxEl.innerHTML = `
|
|
||||||
<div class="jr-ticket-preview">
|
<div class="jr-ticket-preview">
|
||||||
<div class="jr-ticket-row-head">
|
<div class="jr-ticket-row-head">
|
||||||
<span class="jr-ticket-id mono">${escapeHtml(shownCardId)}</span>
|
<span class="jr-ticket-id mono">${escapeHtml(shownCardId)}</span>
|
||||||
<span class="jr-status-pill ${card.status === 'active' ? 'jr-status-valid' : (card.status === 'pending_pickup' ? 'jr-status-used' : 'jr-status-expired')}">${escapeHtml(card.status_label || card.status || '未知')}</span>
|
<span class="jr-status-pill ${getStatusClass(card.status)}">${escapeHtml(card.status_label || card.status || '未知')}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="jr-meta-grid">
|
<div class="jr-meta-grid">
|
||||||
<div class="jr-meta-item"><span>持卡人</span><strong>${escapeHtml(card.holder_name || '未登记')}</strong></div>
|
<div class="jr-meta-item"><span>持卡人</span><strong>${escapeHtml(card.holder_name || '未登记')}</strong></div>
|
||||||
<div class="jr-meta-item"><span>卡片类型</span><strong>IC 储值卡</strong></div>
|
<div class="jr-meta-item"><span>卡片类型</span><strong>${escapeHtml(card.card_type_label || 'IC 储值卡')}</strong></div>
|
||||||
<div class="jr-meta-item"><span>余额</span><strong>${escapeHtml(card.balance ?? 0)}</strong></div>
|
<div class="jr-meta-item"><span>余额</span><strong>${escapeHtml(card.balance ?? 0)}</strong></div>
|
||||||
<div class="jr-meta-item"><span>首次充值</span><strong>${escapeHtml(card.purchase_amount ?? card.balance ?? 0)}</strong></div>
|
<div class="jr-meta-item"><span>首次充值</span><strong>${escapeHtml(card.purchase_amount ?? card.balance ?? 0)}</strong></div>
|
||||||
<div class="jr-meta-item"><span>凭证码</span><strong>${escapeHtml(card.voucher_code || card.code || card.order_code || '---')}</strong></div>
|
<div class="jr-meta-item"><span>凭证码</span><strong>${escapeHtml(card.voucher_code || card.code || card.order_code || '---')}</strong></div>
|
||||||
@@ -65,12 +77,11 @@
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderEvents = (events) => {
|
const buildEventsHtml = (events) => {
|
||||||
if (!events.length) {
|
if (!events.length) {
|
||||||
eventBoxEl.innerHTML = '<div class="jr-center-empty" style="min-height:180px;"><p>暂无相关事件记录。</p></div>';
|
return '<div class="jr-center-empty" style="min-height:180px;"><p>暂无相关事件记录。</p></div>';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
eventBoxEl.innerHTML = events.map((event) => `
|
return events.map((event) => `
|
||||||
<div class="jr-history-item">
|
<div class="jr-history-item">
|
||||||
<div class="jr-history-row">
|
<div class="jr-history-row">
|
||||||
<span class="jr-history-title">${escapeHtml(eventTitle(event))}</span>
|
<span class="jr-history-title">${escapeHtml(eventTitle(event))}</span>
|
||||||
@@ -81,37 +92,129 @@
|
|||||||
`).join('');
|
`).join('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderError = (message) => {
|
const renderEventPrompt = (message) => {
|
||||||
|
eventBoxEl.innerHTML = `<div class="jr-center-empty" style="min-height:180px;"><p>${escapeHtml(message)}</p></div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderSelectedCard = (card, events) => {
|
||||||
|
if (!card) {
|
||||||
|
renderEventPrompt('请选择左侧卡片查看详情与事件记录。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eventBoxEl.innerHTML = `
|
||||||
|
${buildCardPreview(card)}
|
||||||
|
<div class="jr-panel-headline" style="margin:20px 0 14px;">
|
||||||
|
<h3>事件记录</h3>
|
||||||
|
<span class="jr-panel-note">Recent Events</span>
|
||||||
|
</div>
|
||||||
|
<div class="jr-history-list">${buildEventsHtml(events)}</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderCardList = () => {
|
||||||
|
if (!state.cards.length) {
|
||||||
summaryBoxEl.className = 'jr-center-empty';
|
summaryBoxEl.className = 'jr-center-empty';
|
||||||
summaryBoxEl.innerHTML = `<p>${escapeHtml(message)}</p>`;
|
summaryBoxEl.innerHTML = '<p>暂无可显示的 IC 卡记录。</p>';
|
||||||
eventBoxEl.innerHTML = '<div class="jr-center-empty" style="min-height:180px;"><p>暂无可显示的事件记录。</p></div>';
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
summaryBoxEl.className = 'jr-scroll-box';
|
||||||
|
summaryBoxEl.innerHTML = state.cards.map((card) => {
|
||||||
|
const lookupKey = getLookupKey(card);
|
||||||
|
const shownCardId = card.display_card_id || card.card_id || '---';
|
||||||
|
const voucherCode = card.voucher_code || card.code || card.order_code || '---';
|
||||||
|
const isSelected = lookupKey && state.selectedQuery === lookupKey;
|
||||||
|
return `
|
||||||
|
<div class="jr-ticket-row" data-card-query="${escapeHtml(lookupKey)}" style="${isSelected ? 'background:#f7faf7;border-left:4px solid #0b6b3a;padding-left:12px;padding-right:12px;' : ''}">
|
||||||
|
<div class="jr-ticket-row-head">
|
||||||
|
<span class="jr-ticket-id mono">${escapeHtml(shownCardId)}</span>
|
||||||
|
<span class="jr-status-pill ${getStatusClass(card.status)}">${escapeHtml(card.status_label || card.status || '未知')}</span>
|
||||||
|
</div>
|
||||||
|
<div class="jr-ticket-route">${escapeHtml(card.holder_name || '未登记持卡人')}</div>
|
||||||
|
<div class="text-muted" style="margin-top:6px; font-size:0.9rem;">
|
||||||
|
余额 ${escapeHtml(card.balance ?? 0)} · 凭证码 ${escapeHtml(voucherCode)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
|
summaryBoxEl.querySelectorAll('[data-card-query]').forEach((item) => {
|
||||||
|
item.addEventListener('click', () => {
|
||||||
|
const q = item.getAttribute('data-card-query');
|
||||||
|
if (q) {
|
||||||
|
loadCardDetail(q).catch((error) => {
|
||||||
|
renderEventPrompt(error.message || String(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadCardDetail = async (q, options = {}) => {
|
||||||
|
const { updateUrl = true } = options;
|
||||||
|
eventBoxEl.innerHTML = '<div class="jr-center-empty" style="min-height:180px;"><p>正在加载卡片详情...</p></div>';
|
||||||
|
const data = await api.query(q);
|
||||||
|
const card = data.card || null;
|
||||||
|
const events = data.events || [];
|
||||||
|
const lookupKey = getLookupKey(card) || q;
|
||||||
|
if (card) {
|
||||||
|
const existingIdx = state.cards.findIndex((item) => getLookupKey(item) === lookupKey);
|
||||||
|
if (existingIdx >= 0) state.cards[existingIdx] = card;
|
||||||
|
else state.cards = [card];
|
||||||
|
}
|
||||||
|
state.selectedQuery = lookupKey;
|
||||||
|
renderCardList();
|
||||||
|
renderSelectedCard(card, events);
|
||||||
|
if (updateUrl) {
|
||||||
|
const newUrl = `${window.location.origin}${window.location.pathname}?q=${encodeURIComponent(q)}`;
|
||||||
|
window.history.replaceState({ path: newUrl }, '', newUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadAllCards = async () => {
|
||||||
|
summaryBoxEl.className = 'jr-center-empty';
|
||||||
|
summaryBoxEl.innerHTML = '<p>正在加载全部 IC 卡...</p>';
|
||||||
|
renderEventPrompt('正在准备卡片详情...');
|
||||||
|
const data = await api.query('');
|
||||||
|
state.cards = Array.isArray(data.cards) ? data.cards : [];
|
||||||
|
state.selectedQuery = '';
|
||||||
|
renderCardList();
|
||||||
|
|
||||||
|
if (!state.cards.length) {
|
||||||
|
renderEventPrompt('当前暂无 IC 卡记录。');
|
||||||
|
const newUrl = `${window.location.origin}${window.location.pathname}`;
|
||||||
|
window.history.replaceState({ path: newUrl }, '', newUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await loadCardDetail(getLookupKey(state.cards[0]), { updateUrl: false });
|
||||||
|
const newUrl = `${window.location.origin}${window.location.pathname}`;
|
||||||
|
window.history.replaceState({ path: newUrl }, '', newUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
const doQuery = async () => {
|
const doQuery = async () => {
|
||||||
const q = inputEl.value.trim();
|
const q = inputEl.value.trim();
|
||||||
if (!q) {
|
if (!q) {
|
||||||
renderError('请输入卡号或凭证码');
|
await loadAllCards();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
summaryBoxEl.className = 'jr-center-empty';
|
summaryBoxEl.className = 'jr-center-empty';
|
||||||
summaryBoxEl.innerHTML = '<p>正在查询 IC 卡...</p>';
|
summaryBoxEl.innerHTML = '<p>正在查询 IC 卡...</p>';
|
||||||
eventBoxEl.innerHTML = '<div class="jr-center-empty" style="min-height:180px;"><p>正在加载事件记录...</p></div>';
|
state.cards = [];
|
||||||
const data = await api.query(q);
|
await loadCardDetail(q);
|
||||||
renderSummary(data.card || {});
|
|
||||||
renderEvents(data.events || []);
|
|
||||||
const newUrl = `${window.location.origin}${window.location.pathname}?q=${encodeURIComponent(q)}`;
|
|
||||||
window.history.replaceState({ path: newUrl }, '', newUrl);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
queryBtn.addEventListener('click', () => doQuery().catch((error) => renderError(error.message || String(error))));
|
queryBtn.addEventListener('click', () => doQuery().catch((error) => renderEventPrompt(error.message || String(error))));
|
||||||
inputEl.addEventListener('keydown', (event) => {
|
inputEl.addEventListener('keydown', (event) => {
|
||||||
if (event.key === 'Enter') doQuery().catch((error) => renderError(error.message || String(error)));
|
if (event.key === 'Enter') doQuery().catch((error) => renderEventPrompt(error.message || String(error)));
|
||||||
});
|
});
|
||||||
|
|
||||||
const params = new URLSearchParams(location.search);
|
const params = new URLSearchParams(location.search);
|
||||||
const q = params.get('q');
|
const q = params.get('q');
|
||||||
if (q) {
|
if (q) {
|
||||||
inputEl.value = q;
|
inputEl.value = q;
|
||||||
doQuery().catch((error) => renderError(error.message || String(error)));
|
doQuery().catch((error) => renderEventPrompt(error.message || String(error)));
|
||||||
|
} else {
|
||||||
|
loadAllCards().catch((error) => renderEventPrompt(error.message || String(error)));
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@
|
|||||||
<a href="/" class="jr-brand">
|
<a href="/" class="jr-brand">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE 铁路运输</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>控制台登录</span>
|
<span>控制台登录</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<a href="javascript:void(0)" @click="goHome" class="jr-brand">
|
<a href="javascript:void(0)" @click="goHome" class="jr-brand">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE铁路票务系统</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>电子客票信息</span>
|
<span>电子客票信息</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<section class="jr-page-intro">
|
<section class="jr-page-intro">
|
||||||
<span class="jr-kicker">ELECTRONIC TICKET</span>
|
<span class="jr-kicker">ELECTRONIC TICKET</span>
|
||||||
<h1>查看车票状态与最近流转记录</h1>
|
<h1>查看车票状态与最近流转记录</h1>
|
||||||
<p>用于查看单张电子客票的乘车信息、状态与进出站记录,便于旅客和工作人员快速确认票据状态。</p>
|
<p>用于查看单张电子客票的乘车信息、状态与进出站记录</p>
|
||||||
</section>
|
</section>
|
||||||
<div v-if="loading" class="jr-panel-card">
|
<div v-if="loading" class="jr-panel-card">
|
||||||
<div class="jr-center-empty">
|
<div class="jr-center-empty">
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE铁路票务系统</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>线上预定</span>
|
<span>线上预定</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="routeBrandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="routeBrandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE 铁路运输</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>线路规划后台</span>
|
<span>线路规划后台</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
<a href="https://ticket.fse-media.group" class="jr-brand" id="brandLink">
|
||||||
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
<img src="/FSE-ticket.png" alt="FSE Railway" class="jr-brand-logo" />
|
||||||
<div class="jr-brand-copy">
|
<div class="jr-brand-copy">
|
||||||
<strong>FSE铁路售票系统</strong>
|
<strong>FarSight-T.N.E铁路运输</strong>
|
||||||
<span>票务查询</span>
|
<span>票务查询</span>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user