fix(admin): visitor_name→real_name, verify_status, TicketVerify GET handler, input filter null→s

- list.html: visitor_name→real_name, status→verify_status, 修复搜索字段名
- verify.html: visitor_name→real_name in JS showResult(), 移除form-validation class
- Admin.php TicketList: 搜索字段从keywords改为逐字段搜索(real_name/phone/order_no/ticket_code)
- Admin.php TicketVerify: 添加GET分支显示核销页面,POST分支保持原逻辑
- Admin.php TicketVerify: input() filter null→'s' 避免variable type error
feat/b-verification-clean
Council 2026-04-25 20:02:36 +08:00
parent 6fae406982
commit a5b2d00c8e
3 changed files with 62 additions and 43 deletions

View File

@ -316,20 +316,36 @@ class Admin extends Common
{ {
$where = []; $where = [];
$keywords = input('keywords', '', null, 'trim'); // 逐字段精确搜索(对应视图的独立搜索框)
if (!empty($keywords)) { $order_no = input('order_no', '', null, 'trim');
$where[] = ['order_no|ticket_code|real_name|phone', 'like', "%{$keywords}%"]; if ($order_no !== '') {
$where[] = ['order_no', 'like', "%{$order_no}%"];
}
$ticket_code = input('ticket_code', '', 's', 'trim');
if ($ticket_code !== '') {
$where[] = ['ticket_code', 'like', "%{$ticket_code}%"];
}
$real_name = input('real_name', '', null, 'trim');
if ($real_name !== '') {
$where[] = ['real_name', 'like', "%{$real_name}%"];
}
$phone = input('phone', '', null, 'trim');
if ($phone !== '') {
$where[] = ['phone', 'like', "%{$phone}%"];
} }
$verify_status = input('verify_status', '', null); $verify_status = input('verify_status', '', null);
if ($verify_status !== '' && $verify_status !== null) { if ($verify_status !== '' && $verify_status !== null) {
$where[] = ['verify_status', '=', intval($verify_status)]; $where[] = ['verify_status', '=', intval($verify_status)];
} }
$goods_id = input('goods_id', 0, 'intval'); // 搜索参数回传(用于表单值保持)
if ($goods_id > 0) { $params = [
$where[] = ['goods_id', '=', $goods_id]; 'order_no' => $order_no,
} 'ticket_code' => $ticket_code,
'real_name' => $real_name,
'phone' => $phone,
'verify_status' => $verify_status,
];
$list = \think\facade\Db::name('vr_tickets') $list = \think\facade\Db::name('vr_tickets')
->where($where) ->where($where)
@ -350,17 +366,11 @@ class Admin extends Common
unset($item); unset($item);
} }
$status_map = [
0 => ['text' => '未核销', 'color' => 'blue'],
1 => ['text' => '已核销', 'color' => 'green'],
2 => ['text' => '已退款', 'color' => 'red'],
];
return MyView('../../../plugins/vr_ticket/view/admin/ticket/list', [ return MyView('../../../plugins/vr_ticket/view/admin/ticket/list', [
'list' => $list_data['data'], 'list' => $list_data['data'],
'page' => $list->render() ?: '', 'page' => $list->render() ?: '',
'count' => $list_data['total'], 'count' => $list_data['total'],
'status_map' => $status_map, 'params'=> $params,
]); ]);
} }
@ -404,13 +414,24 @@ class Admin extends Common
/** /**
* 手动核销票JSON API * 手动核销票JSON API
*/ */
/**
* 扫码核销页面GET和核销处理AJAX POST
* GET: 显示核销表单
* POST: 处理核销 AJAX 请求
*/
public function TicketVerify() public function TicketVerify()
{ {
if (!(request()->isAjax() && request()->isPost())) { // GET 请求 — 显示核销表单页面
return DataReturn('非法请求', -1); if (!request()->isAjax()) {
return MyView('../../../plugins/vr_ticket/view/admin/ticket/verify', []);
} }
$ticket_code = input('ticket_code', '', null, 'trim'); // AJAX POST 处理核销
if (!request()->isPost()) {
return json(['code' => -1, 'msg' => '非法请求']);
}
$ticket_code = input('ticket_code', '', 's', 'trim');
// M-05: verifier_id 从 session 获取,禁止客户端伪造 // M-05: verifier_id 从 session 获取,禁止客户端伪造
// $this->admin 来自父类构造函数AdminService::LoginInfo() // $this->admin 来自父类构造函数AdminService::LoginInfo()

View File

@ -11,7 +11,7 @@
<!-- 搜索栏 --> <!-- 搜索栏 -->
<div class="am-panel am-panel-default am-margin-bottom"> <div class="am-panel am-panel-default am-margin-bottom">
<div class="am-panel-bd"> <div class="am-panel-bd">
<form class="am-form form-validation" action="{{:PluginsAdminUrl('vr_ticket', 'admin', 'ticketlist')}}" method="POST" request-type="ajax-url"> <form class="am-form" action="{{:PluginsAdminUrl('vr_ticket', 'admin', 'ticketlist')}}" method="GET">
<div class="am-g"> <div class="am-g">
<div class="am-u-sm-3 am-u-end"> <div class="am-u-sm-3 am-u-end">
<div class="am-input-group am-input-group-sm"> <div class="am-input-group am-input-group-sm">
@ -28,26 +28,26 @@
<div class="am-u-sm-3 am-u-end"> <div class="am-u-sm-3 am-u-end">
<div class="am-input-group am-input-group-sm"> <div class="am-input-group am-input-group-sm">
<span class="am-input-group-label">观演人</span> <span class="am-input-group-label">观演人</span>
<input type="text" name="visitor_name" value="{{if !empty($params.visitor_name)}}{{$params.visitor_name}}{{/if}}" placeholder="请输入观演人姓名" class="am-radius" /> <input type="text" name="real_name" value="{{if !empty($params.real_name)}}{{$params.real_name}}{{/if}}" placeholder="请输入观演人姓名" class="am-radius" />
</div> </div>
</div> </div>
<div class="am-u-sm-3 am-u-end"> <div class="am-u-sm-3 am-u-end">
<div class="am-input-group am-input-group-sm"> <div class="am-input-group am-input-group-sm">
<span class="am-input-group-label">手机号</span> <span class="am-input-group-label">手机号</span>
<input type="text" name="mobile" value="{{if !empty($params.mobile)}}{{$params.mobile}}{{/if}}" placeholder="请输入手机号" class="am-radius" /> <input type="text" name="phone" value="{{if !empty($params.phone)}}{{$params.phone}}{{/if}}" placeholder="请输入手机号" class="am-radius" />
</div> </div>
</div> </div>
</div> </div>
<div class="am-g am-margin-top"> <div class="am-g am-margin-top">
<div class="am-u-sm-3 am-u-end"> <div class="am-u-sm-3 am-u-end">
<div class="am-input-group am-input-group-sm"> <div class="am-input-group am-input-group-sm">
<span class="am-input-group-label">状态</span> <span class="am-input-group-label">状态</span>
<select name="status" class="am-radius"> <select name="verify_status" class="am-radius">
<option value="">全部</option> <option value="">全部</option>
<option value="0" {{if isset($params.status) && $params.status === '0'}}selected{{/if}}>未核销</option> <option value="0" {{if isset($params.verify_status) && $params.verify_status === '0'}}selected{{/if}}>未核销</option>
<option value="1" {{if isset($params.status) && $params.status == '1'}}selected{{/if}}>已核销</option> <option value="1" {{if isset($params.verify_status) && $params.verify_status == '1'}}selected{{/if}}>已核销</option>
<option value="2" {{if isset($params.status) && $params.status == '2'}}selected{{/if}}>已退款</option> <option value="2" {{if isset($params.verify_status) && $params.verify_status == '2'}}selected{{/if}}>已退款</option>
</select> </select>
</div> </div>
</div> </div>
@ -66,7 +66,7 @@
<!-- 票列表 --> <!-- 票列表 -->
<div class="am-panel am-panel-default"> <div class="am-panel am-panel-default">
<div class="am-panel-hd">电子票列表</div> <div class="am-panel-hd">电子票列表 <span class="am-text-xs am-padding-left">共 {{$count|default=0}} 条</span></div>
<div class="am-panel-bd"> <div class="am-panel-bd">
<table class="am-table am-table-striped am-table-hover am-text-middle"> <table class="am-table am-table-striped am-table-hover am-text-middle">
<thead> <thead>
@ -85,19 +85,19 @@
{{volist name="list" id="ticket"}} {{volist name="list" id="ticket"}}
<tr> <tr>
<td>{{$ticket.ticket_code}}</td> <td>{{$ticket.ticket_code}}</td>
<td>{{$ticket.visitor_name}}</td> <td>{{$ticket.real_name|default='—'}}</td>
<td>{{if !empty($ticket.seat_info)}}{{$ticket.seat_info}}{{else}}无{{/if}}</td> <td>{{if !empty($ticket.seat_info)}}{{$ticket.seat_info}}{{else}}无{{/if}}</td>
<td>{{$ticket.goods_name}}</td> <td>{{$ticket.goods_title|default='已删除商品'}}</td>
<td> <td>
{{if $ticket.status == 0}} {{if $ticket.verify_status == 0}}
<span class="am-badge am-badge-warning">未核销</span> <span class="am-badge am-badge-warning">未核销</span>
{{elseif $ticket.status == 1}} {{elseif $ticket.verify_status == 1}}
<span class="am-badge am-badge-success">已核销</span> <span class="am-badge am-badge-success">已核销</span>
{{elseif $ticket.status == 2}} {{elseif $ticket.verify_status == 2}}
<span class="am-badge am-badge-danger">已退款</span> <span class="am-badge am-badge-danger">已退款</span>
{{/if}} {{/if}}
</td> </td>
<td>{{$ticket.create_time}}</td> <td>{{if !empty($ticket.issued_at)}}{{:date('Y-m-d H:i', $ticket.issued_at)}}{{else}}—{{/if}}</td>
<td> <td>
<a href="{{:PluginsAdminUrl('vr_ticket', 'admin', 'ticketdetail')}}?id={{$ticket.id}}" class="am-btn am-btn-default am-btn-xs am-radius"> <a href="{{:PluginsAdminUrl('vr_ticket', 'admin', 'ticketdetail')}}?id={{$ticket.id}}" class="am-btn am-btn-default am-btn-xs am-radius">
<i class="am-icon-eye"></i> 查看详情 <i class="am-icon-eye"></i> 查看详情
@ -112,7 +112,7 @@
{{/if}} {{/if}}
</tbody> </tbody>
</table> </table>
<!-- 分页 --> <!-- 分页 -->
{{if !empty($page)}} {{if !empty($page)}}
<div class="am-margin-top"> <div class="am-margin-top">
@ -123,4 +123,4 @@
</div> </div>
</div> </div>
{{:ModuleInclude('public/footer')}} {{:ModuleInclude('public/footer')}}

View File

@ -34,7 +34,7 @@
<div class="am-panel am-panel-default am-margin-top"> <div class="am-panel am-panel-default am-margin-top">
<div class="am-panel-hd">扫码/输入核销</div> <div class="am-panel-hd">扫码/输入核销</div>
<div class="am-panel-bd"> <div class="am-panel-bd">
<form class="am-form form-validation" id="verify-form"> <form class="am-form" id="verify-form">
<div class="am-form-group"> <div class="am-form-group">
<label>票码/短码</label> <label>票码/短码</label>
<div class="am-input-group"> <div class="am-input-group">
@ -126,11 +126,9 @@ function showResult(res) {
var ticket = res.data; var ticket = res.data;
html = '<div class="am-alert am-alert-success am-margin-top">' + html = '<div class="am-alert am-alert-success am-margin-top">' +
'<h4><i class="am-icon-check-circle"></i> 核销成功</h4>' + '<h4><i class="am-icon-check-circle"></i> 核销成功</h4>' +
'<p><strong>票码:</strong>' + ticket.ticket_code + '</p>' + '<p><strong>观演人:</strong>' + (ticket.real_name || '—') + '</p>' +
'<p><strong>观演人:</strong>' + ticket.visitor_name + '</p>' +
'<p><strong>座位:</strong>' + (ticket.seat_info || '无') + '</p>' + '<p><strong>座位:</strong>' + (ticket.seat_info || '无') + '</p>' +
'<p><strong>商品名:</strong>' + ticket.goods_name + '</p>' + '<p><strong>商品名:</strong>' + (ticket.goods_name || '—') + '</p>' +
'<p><strong>核销时间:</strong>' + ticket.verify_time + '</p>' +
'</div>'; '</div>';
// 清空输入框 // 清空输入框