vr-shopxo-plugin/shopxo/app/plugins/vr_ticket/Hook.php

241 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace app\plugins\vr_ticket;
use app\plugins\vr_ticket\service\TicketService;
class Hook
{
public function handle($params = [])
{
if(!empty($params['hook_name']))
{
$ret = '';
switch($params['hook_name'])
{
// 后台左侧菜单钩子
case 'plugins_service_admin_menu_data':
$this->AdminSidebarInit($params['admin_left_menu']);
break;
// 订单支付成功处理
case 'plugins_service_order_pay_success_handle_end':
$ret = TicketService::onOrderPaid($params);
break;
case 'plugins_service_order_detail_page_info':
// C端订单详情页注入票夹入口
$ret = $this->InjectTicketCard($params);
break;
case 'plugins_service_order_delete_success':
// 如果有删除拦截等
break;
}
return $ret;
}
}
public function AdminSidebarInit(&$params)
{
$params[] = [
'id' => 'plugins-vr_ticket',
'name' => 'VR票务',
'title' => 'VR票务',
'icon' => 'am-icon-ticket',
'control' => 'admin',
'action' => 'index',
'is_show' => 1,
'power' => 'vr_ticket-admin',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'index'),
'item' => [
[
'id' => 'plugins-vr_ticket-venue',
'name' => '场馆配置',
'title' => '场馆配置',
'is_show' => 1,
'control' => 'admin',
'action' => 'VenueList',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'VenueList'),
'power' => 'vr_ticket-venueList',
],
[
'id' => 'plugins-vr_ticket-seat',
'name' => '座位模板',
'title' => '座位模板',
'is_show' => 1,
'control' => 'admin',
'action' => 'SeatTemplateList',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'SeatTemplateList'),
'power' => 'vr_ticket-seatTemplateList',
],
[
'id' => 'plugins-vr_ticket-ticket',
'name' => '电子票',
'title' => '电子票',
'is_show' => 1,
'control' => 'admin',
'action' => 'TicketList',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'TicketList'),
'power' => 'vr_ticket-ticketList',
],
[
'id' => 'plugins-vr_ticket-verifier',
'name' => '核销员',
'title' => '核销员',
'is_show' => 1,
'control' => 'admin',
'action' => 'VerifierList',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'VerifierList'),
'power' => 'vr_ticket-verifierList',
],
[
'id' => 'plugins-vr_ticket-varification',
'name' => '核销记录',
'title' => '核销记录',
'is_show' => 1,
'control' => 'admin',
'action' => 'VerificationList',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'VerificationList'),
'power' => 'vr_ticket-verificationList',
],
[
'id' => 'plugins-vr_ticket-setup',
'name' => '插件设置',
'title' => '插件设置',
'is_show' => 1,
'control' => 'admin',
'action' => 'Setup',
'url' => PluginsAdminUrl('vr_ticket', 'admin', 'Setup'),
'power' => 'vr_ticket-setup',
]
]
];
}
/**
* C端订单详情页注入票卡片
*/
public function InjectTicketCard(&$params)
{
$order = $params['order'] ?? [];
if (empty($order) || ($order['pay_status'] ?? 0) != 1) {
return;
}
$userId = session('user_id');
if (empty($userId)) {
return;
}
$tickets = \think\facade\Db::name('vr_tickets')
->where('order_id', $order['id'])
->select()
->toArray();
if (empty($tickets)) {
return;
}
$token = session('user_token') ?: '';
$hostUrl = \think\facade\Config::get('shopxo.host_url');
$ticketCardsHtml = '';
foreach ($tickets as $ticket) {
$shortCode = \app\plugins\vr_ticket\service\BaseService::shortCodeEncode($ticket['goods_id'], $ticket['id']);
$statusMap = [0 => ['text' => '未核销', 'class' => 'unverified'], 1 => ['text' => '已核销', 'class' => 'verified'], 2 => ['text' => '已退款', 'class' => 'refunded']];
$status = $statusMap[$ticket['verify_status']] ?? $statusMap[0];
$ticketCardsHtml .= '<div class="vr-ticket-card" data-ticket-id="' . $ticket['id'] . '">' .
'<div class="vr-ticket-card-header">' .
'<div class="vr-ticket-goods-title">电子票</div>' .
'<div class="vr-ticket-status ' . $status['class'] . '">' . $status['text'] . '</div>' .
'</div>' .
'<div class="vr-ticket-info">' .
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">💺</span><span>' . htmlspecialchars($ticket['seat_info'] ?? '') . '</span></div>' .
'<div class="vr-ticket-info-row"><span class="vr-ticket-info-icon">👤</span><span>' . htmlspecialchars($ticket['real_name'] ?? '') . '</span></div>' .
'</div>' .
'<div class="vr-ticket-footer">' .
'<div class="vr-ticket-short-code">短码: ' . htmlspecialchars($shortCode) . '</div>' .
'<a href="javascript:;" class="vr-ticket-view-btn" onclick="VrTicketWallet.viewTicket(' . $ticket['id'] . ')">查看票码 →</a>' .
'</div>' .
'</div>';
}
$style = '<style>
.vr-ticket-card { background: #fff; border-radius: 12px; padding: 16px; margin: 12px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.06); cursor: pointer; }
.vr-ticket-card:hover { box-shadow: 0 4px 16px rgba(0,0,0,0.12); }
.vr-ticket-card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px; }
.vr-ticket-goods-title { font-size: 16px; font-weight: 600; color: #333; }
.vr-ticket-status { font-size: 12px; padding: 2px 8px; border-radius: 4px; font-weight: 500; }
.vr-ticket-status.unverified { background: #e6f7ff; color: #1890ff; }
.vr-ticket-status.verified { background: #f6ffed; color: #52c41a; }
.vr-ticket-status.refunded { background: #fff1f0; color: #ff4d4f; }
.vr-ticket-info { font-size: 13px; color: #666; line-height: 1.6; }
.vr-ticket-info-row { display: flex; align-items: center; margin-bottom: 4px; }
.vr-ticket-info-icon { width: 16px; color: #999; margin-right: 6px; }
.vr-ticket-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; padding-top: 12px; border-top: 1px solid #f0f0f0; }
.vr-ticket-short-code { font-size: 14px; font-family: "Courier New", monospace; color: #333; font-weight: 600; letter-spacing: 1px; }
.vr-ticket-view-btn { font-size: 13px; color: #1890ff; text-decoration: none; }
.vr-ticket-view-btn:hover { text-decoration: underline; }
</style>';
$ticketHtml = '<div class="vr-order-ticket-section">' .
'<div style="font-size:16px;font-weight:600;margin-bottom:12px;">📋 我的电子票</div>' .
$ticketCardsHtml .
'</div>';
$params['page_data']['ticket_section'] = $ticketHtml;
$params['page_data']['ticket_css'] = $style;
// JS
$js = '<script>
(function() {
var apiBase = "' . $hostUrl . '?s=api/plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=";
var token = "' . htmlspecialchars($token) . '";
window.VrTicketWallet = {
viewTicket: function(ticketId) {
var modal = document.getElementById("vrTicketModal") || createModal();
modal.classList.add("active");
var body = document.getElementById("vrTicketModalBody");
body.innerHTML = \'<div style="text-align:center;padding:40px;">加载中...</div>\';
$.ajax({
url: apiBase + "detail&id=" + ticketId,
headers: token ? {"X-Token": token} : {},
success: function(res) {
if (res.code === 0 && res.data.ticket) {
var t = res.data.ticket;
var statusMap = {0:{text:"未核销",class:"unverified"},1:{text:"已核销",class:"verified"},2:{text:"已退款",class:"refunded"}};
var status = statusMap[t.verify_status] || statusMap[0];
body.innerHTML = \'<div style="text-align:center;padding:20px;background:#fafafa;border-radius:12px;"><div id="vrQrcodeBox"></div></div>\' +
\'<div style="text-align:center;margin:16px 0;padding:12px;background:#f5f5f5;border-radius:8px;">\' +
\'<div style="font-size:12px;color:#999;margin-bottom:4px;">短码(人工核销)</div>\' +
\'<div style="font-size:20px;font-family:monospace;font-weight:700;letter-spacing:2px;">\' + t.short_code + \'</div></div>\' +
\'<div style="text-align:center;"><span class="vr-ticket-status \' + status.class + \'">\' + status.text + \'</span></div>\';
if (t.qr_payload) {
$("#vrQrcodeBox").qrcode({text: atob(t.qr_payload), width: 180, height: 180});
}
}
}
});
},
closeModal: function() {
var modal = document.getElementById("vrTicketModal");
if (modal) modal.classList.remove("active");
}
};
function createModal() {
var html = \'<div id="vrTicketModal" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:9999;display:none;align-items:center;justify-content:center;">\' +
\'<div style="background:#fff;border-radius:16px;width:90%;max-width:400px;padding:24px;"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;">\' +
\'<div style="font-size:18px;font-weight:600;">电子票</div><button onclick="VrTicketWallet.closeModal()" style="width:28px;height:28px;border-radius:50%;background:#f0f0f0;border:none;cursor:pointer;">×</button></div>\' +
\'<div id="vrTicketModalBody"></div></div></div>\';
document.body.insertAdjacentHTML("beforeend", html);
var modal = document.getElementById("vrTicketModal");
modal.addEventListener("click", function(e) { if (e.target === modal) VrTicketWallet.closeModal(); });
return modal;
}
})();
</script>';
$params['page_data']['ticket_js'] = $js;
}
}
?>