fix(Task1): seat展示截断 + 短码改名核销码 + barcode渲染函数化

- WalletService: 移除 getUserTickets() 中重复的 seat_number 字段
- ticket_card.html (PHP模板):
  - renderTickets(): seat_info → seat_number
  - 短码标签: 短码 → 核销码
  - showTicketBasic/Detail: seat_info → seat_number, 标签改名, canvas条码
  - 新增 renderBarcode() 独立函数
  - 清理 showTicketDetail/loadQrPayload/refreshQr 中的 inline try-catch JsBarcode
- ticket_card.js (静态JS): 同上修复, 同步跟上 PHP 模板的改动
  - renderBarcode() 在 refreshQr 中调用
feat/phase-b-verification
Council 2026-04-25 00:12:28 +08:00
parent 29f4c61110
commit 4c04b094e2
3 changed files with 63 additions and 16 deletions

View File

@ -96,7 +96,6 @@ class WalletService extends BaseService
'verify_status' => $ticket['verify_status'],
'issued_at' => $ticket['issued_at'],
'short_code' => $shortCode,
'seat_number' => self::parseSeatNumber($ticket['seat_info'] ?? ''),
];
}

View File

@ -244,7 +244,7 @@
</div>
</div>
<div class="vr-ticket-footer">
<div class="vr-ticket-short-code">码: {{short_code}}</div>
<div class="vr-ticket-short-code">核销码: {{short_code}}</div>
<a href="javascript:;" class="vr-ticket-view-btn" onclick="VrTicketWallet.viewTicket({{id}})">查看票码 →</a>
</div>
</div>
@ -366,11 +366,11 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-info">' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">📅</span><span>' + escapeHtml(ticket.session_time) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">📍</span><span>' + escapeHtml(ticket.venue_name) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">💺</span><span>' + escapeHtml(ticket.seat_info) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">💺</span><span>' + escapeHtml(ticket.seat_number) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">👤</span><span>' + escapeHtml(ticket.real_name) + ' ' + escapeHtml(ticket.phone) + '</span></div>' +
'</div>' +
'<div class="vr-ticket-footer">' +
'<div class="vr-ticket-short-code">码: ' + escapeHtml(ticket.short_code) + '</div>' +
'<div class="vr-ticket-short-code">核销码: ' + escapeHtml(ticket.short_code) + '</div>' +
'<a href="javascript:;" class="vr-ticket-view-btn" onclick="VrTicketWallet.viewTicket(' + ticket.id + ')">查看票码 →</a>' +
'</div>' +
'</div>';
@ -434,7 +434,7 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-qr-expire" id="vrQrExpire"></div>' +
'</div>' +
'<div class="vr-ticket-short-code-display">' +
'<div class="vr-ticket-short-code-label">短码(人工核销)</div>' +
'<div class="vr-ticket-short-code-label">核销码</div>' +
'<div class="vr-ticket-short-code-value">' + escapeHtml(ticket.short_code) + '</div>' +
'<canvas id="vrBarcodeCanvas" style="margin-top:8px;max-width:100%;display:block;"></canvas>' +
'</div>' +
@ -459,6 +459,7 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.real_name) + ' ' + escapeHtml(ticket.phone) + '</div>' +
'</div>' +
'<button class="vr-ticket-refresh-btn" id="vrRefreshBtn" onclick="VrTicketWallet.refreshQr(' + ticket.id + ')">刷新二维码</button>';
renderBarcode(ticket.short_code);
}
/**
@ -484,7 +485,7 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-qr-expire" id="vrQrExpire"></div>' +
'</div>' +
'<div class="vr-ticket-short-code-display">' +
'<div class="vr-ticket-short-code-label">短码(人工核销)</div>' +
'<div class="vr-ticket-short-code-label">核销码</div>' +
'<div class="vr-ticket-short-code-value">' + escapeHtml(ticket.short_code) + '</div>' +
'<canvas id="vrBarcodeCanvas" style="margin-top:8px;max-width:100%;display:block;"></canvas>' +
'</div>' +
@ -510,7 +511,7 @@ var VrTicketWallet = (function() {
// 渲染 QR 码
if (ticket.qr_payload) {
renderQrCode(ticket.qr_payload, ticket.qr_expires_in);
try { var bc = document.getElementById('vrBarcodeCanvas'); if (bc && ticket.short_code) { JsBarcode(bc, ticket.short_code, {format:'CODE128', width:2, height:60, displayValue:true, fontSize:14, margin:5}); } } catch(e){}
renderBarcode(ticket.short_code);
} else {
document.getElementById('vrQrcodeBox').innerHTML = '<div style="color:#999;">QR加载中...</div>';
}
@ -558,7 +559,7 @@ var VrTicketWallet = (function() {
}));
renderQrCode(ticket.qr_payload, expiresIn);
try { var bc = document.getElementById('vrBarcodeCanvas'); if (bc && ticket.short_code) { JsBarcode(bc, ticket.short_code, {format:'CODE128', width:2, height:60, displayValue:true, fontSize:14, margin:5}); } } catch(e){}
// barcode 由 showTicketBasic/showTicketDetail 单独调用
}
},
error: function() {
@ -597,6 +598,27 @@ var VrTicketWallet = (function() {
}
}
/**
* 渲染条形码CODE128
* @param {string} shortCode - 核销码
*/
function renderBarcode(shortCode) {
try {
var canvas = document.getElementById('vrBarcodeCanvas');
if (!canvas || !shortCode) return;
JsBarcode(canvas, shortCode, {
format: 'CODE128',
width: 2,
height: 60,
displayValue: true,
fontSize: 14,
margin: 5
});
} catch (e) {
console.warn('Barcode render failed:', e);
}
}
/**
* 刷新 QR
*/
@ -626,7 +648,7 @@ var VrTicketWallet = (function() {
// 重新渲染 QR
renderQrCode(ticket.qr_payload, ticket.qr_expires_in);
try { var bc = document.getElementById('vrBarcodeCanvas'); if (bc && ticket.short_code) { JsBarcode(bc, ticket.short_code, {format:'CODE128', width:2, height:60, displayValue:true, fontSize:14, margin:5}); } } catch(e){}
renderBarcode(ticket.short_code);
if (btn) {
btn.textContent = '已刷新';

View File

@ -98,11 +98,11 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-info">' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">📅</span><span>' + escapeHtml(ticket.session_time) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">📍</span><span>' + escapeHtml(ticket.venue_name) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">💺</span><span>' + escapeHtml(ticket.seat_info) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">💺</span><span>' + escapeHtml(ticket.seat_number) + '</span></div>' +
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">👤</span><span>' + escapeHtml(ticket.real_name) + ' ' + escapeHtml(ticket.phone) + '</span></div>' +
'</div>' +
'<div class="vr-ticket-footer">' +
'<div class="vr-ticket-short-code">码: ' + escapeHtml(ticket.short_code) + '</div>' +
'<div class="vr-ticket-short-code">核销码: ' + escapeHtml(ticket.short_code) + '</div>' +
'<a href="javascript:;" class="vr-ticket-view-btn" onclick="VrTicketWallet.viewTicket(' + ticket.id + ')">查看票码 →</a>' +
'</div>' +
'</div>';
@ -170,8 +170,9 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-qr-expire" id="vrQrExpire"></div>' +
'</div>' +
'<div class="vr-ticket-short-code-display">' +
'<div class="vr-ticket-short-code-label">短码(人工核销)</div>' +
'<div class="vr-ticket-short-code-label">核销码</div>' +
'<div class="vr-ticket-short-code-value">' + escapeHtml(ticket.short_code) + '</div>' +
'<canvas id="vrBarcodeCanvas" style="margin-top:8px;max-width:100%;display:block;"></canvas>' +
'</div>' +
'<div class="vr-ticket-detail-row">' +
'<div class="vr-ticket-detail-label">状态</div>' +
@ -187,13 +188,14 @@ var VrTicketWallet = (function() {
'</div>' +
'<div class="vr-ticket-detail-row">' +
'<div class="vr-ticket-detail-label">座位</div>' +
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.seat_info) + '</div>' +
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.seat_number) + '</div>' +
'</div>' +
'<div class="vr-ticket-detail-row">' +
'<div class="vr-ticket-detail-label">观演人</div>' +
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.real_name) + ' ' + escapeHtml(ticket.phone) + '</div>' +
'</div>' +
(ticket.verify_status === 0 ? '<button class="vr-ticket-refresh-btn" id="vrRefreshBtn" onclick="VrTicketWallet.refreshQr(' + ticket.id + ')">刷新二维码</button>' : '');
renderBarcode(ticket.short_code);
}
/**
@ -219,8 +221,9 @@ var VrTicketWallet = (function() {
'<div class="vr-ticket-qr-expire" id="vrQrExpire"></div>' +
'</div>' +
'<div class="vr-ticket-short-code-display">' +
'<div class="vr-ticket-short-code-label">短码(人工核销)</div>' +
'<div class="vr-ticket-short-code-label">核销码</div>' +
'<div class="vr-ticket-short-code-value">' + escapeHtml(ticket.short_code) + '</div>' +
'<canvas id="vrBarcodeCanvas" style="margin-top:8px;max-width:100%;display:block;"></canvas>' +
'</div>' +
verifiedBadge +
'<div class="vr-ticket-detail-row">' +
@ -233,7 +236,7 @@ var VrTicketWallet = (function() {
'</div>' +
'<div class="vr-ticket-detail-row">' +
'<div class="vr-ticket-detail-label">座位</div>' +
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.seat_info) + '</div>' +
'<div class="vr-ticket-detail-value">' + escapeHtml(ticket.seat_number) + '</div>' +
'</div>' +
'<div class="vr-ticket-detail-row">' +
'<div class="vr-ticket-detail-label">观演人</div>' +
@ -243,6 +246,7 @@ var VrTicketWallet = (function() {
if (ticket.qr_payload) {
renderQrCode(ticket.qr_payload, ticket.qr_expires_in);
renderBarcode(ticket.short_code);
} else {
document.getElementById('vrQrcodeBox').innerHTML = '<div style="color:#999;">QR加载中...</div>';
}
@ -323,6 +327,27 @@ var VrTicketWallet = (function() {
}
}
/**
* 渲染条形码CODE128
* @param {string} shortCode - 核销码
*/
function renderBarcode(shortCode) {
try {
var canvas = document.getElementById('vrBarcodeCanvas');
if (!canvas || !shortCode) return;
JsBarcode(canvas, shortCode, {
format: 'CODE128',
width: 2,
height: 60,
displayValue: true,
fontSize: 14,
margin: 5
});
} catch (e) {
console.warn('Barcode render failed:', e);
}
}
/**
* 刷新 QR
*/
@ -350,6 +375,7 @@ var VrTicketWallet = (function() {
}));
renderQrCode(ticket.qr_payload, ticket.qr_expires_in);
renderBarcode(ticket.short_code);
if (btn) {
btn.textContent = '已刷新';