feat(ticket): 票务管理后台增强 - 订单信息展示、城市筛选修复、观影人管理
- Admin.php: 票详情页新增订单信息、用户信息展示 - Hook.php: 修复城市筛选只对票务商品生效 - Ticket.php: 核销记录新增短码、观演人手机号、订单号、购买者信息 - AdminGoodsSaveHandle.php: 新增商品保存后置处理 - SKU重建、价格刷新、缓存清理 - AdminGoodsSave.php: 观影人配置UI优化 - detail.html: 票详情页重构 - 新增订单信息展示面板 - list.html: 票列表新增订单号、手机号列,优化列宽fix/ticket-select-refresh
parent
2ceb7824aa
commit
e053e03c7c
|
|
@ -508,6 +508,7 @@ class Hook
|
||||||
* 触发位置:plugins_service_goods_list_begin
|
* 触发位置:plugins_service_goods_list_begin
|
||||||
*
|
*
|
||||||
* 向下兼容:无 user_lng/user_lat 参数时,不添加任何筛选,返回全部商品
|
* 向下兼容:无 user_lng/user_lat 参数时,不添加任何筛选,返回全部商品
|
||||||
|
* 修复:只对票务商品(vr_goods_config 非空)应用城市筛选,非票务商品不受影响
|
||||||
*
|
*
|
||||||
* @param array &$params 钩子参数引用 ['hook_name','is_backend','params','where','field','order_by','m','n']
|
* @param array &$params 钩子参数引用 ['hook_name','is_backend','params','where','field','order_by','m','n']
|
||||||
*/
|
*/
|
||||||
|
|
@ -540,12 +541,22 @@ class Hook
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注入 produce_region 城市筛选条件
|
// 修复:只对票务商品应用城市筛选
|
||||||
|
// 逻辑:(非票务商品 vr_goods_config='') OR (票务商品且城市匹配)
|
||||||
$where = &$params['where'];
|
$where = &$params['where'];
|
||||||
if (!is_array($where)) {
|
if (!is_array($where)) {
|
||||||
$where = [];
|
$where = [];
|
||||||
}
|
}
|
||||||
$where[] = ['g.produce_region', '=', $cityId];
|
|
||||||
|
// 使用闭包实现 OR 条件:vr_goods_config 为空(非票务) OR produce_region = 城市ID
|
||||||
|
$where[] = function($query) use ($cityId) {
|
||||||
|
$query->where(function($q) {
|
||||||
|
$q->where('g.vr_goods_config', '=', '');
|
||||||
|
})->whereOr(function($q) use ($cityId) {
|
||||||
|
$q->where('g.vr_goods_config', '<>', '')->where('g.produce_region', '=', $cityId);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// @file_put_contents($debugFile, date('Y-m-d H:i:s') . " OnGoodsListBegin: city filter applied to ticket goods only, cityId=$cityId\n", FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -553,6 +564,7 @@ class Hook
|
||||||
* 触发位置:plugins_service_search_goods_list_begin
|
* 触发位置:plugins_service_search_goods_list_begin
|
||||||
*
|
*
|
||||||
* 向下兼容:无 user_lng/user_lat 参数时,不添加任何筛选,返回全部商品
|
* 向下兼容:无 user_lng/user_lat 参数时,不添加任何筛选,返回全部商品
|
||||||
|
* 修复:只对票务商品(vr_goods_config 非空)应用城市筛选,非票务商品不受影响
|
||||||
*
|
*
|
||||||
* @param array &$params 钩子参数引用 ['hook_name','is_backend','params','where_base','where_keywords','where_screening_price','field','order_by','page','page_start','page_size']
|
* @param array &$params 钩子参数引用 ['hook_name','is_backend','params','where_base','where_keywords','where_screening_price','field','order_by','page','page_start','page_size']
|
||||||
*/
|
*/
|
||||||
|
|
@ -586,13 +598,23 @@ class Hook
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注入 produce_region 城市筛选条件(SearchService 使用 where_base 而非 where)
|
// 修复:只对票务商品应用城市筛选
|
||||||
|
// 逻辑:(非票务商品 vr_goods_config='') OR (票务商品且城市匹配)
|
||||||
|
// SearchService 使用 where_base 而非 where
|
||||||
$whereBase = &$params['where_base'];
|
$whereBase = &$params['where_base'];
|
||||||
if (!is_array($whereBase)) {
|
if (!is_array($whereBase)) {
|
||||||
$whereBase = [];
|
$whereBase = [];
|
||||||
}
|
}
|
||||||
$whereBase[] = ['g.produce_region', '=', $cityId];
|
|
||||||
// [调试代码] @file_put_contents($debugFile, date('Y-m-d H:i:s') . " OnSearchListBegin: city filter applied, cityId=$cityId\n", FILE_APPEND);
|
// 使用闭包实现 OR 条件:vr_goods_config 为空(非票务) OR produce_region = 城市ID
|
||||||
|
$whereBase[] = function($query) use ($cityId) {
|
||||||
|
$query->where(function($q) {
|
||||||
|
$q->where('g.vr_goods_config', '=', '');
|
||||||
|
})->whereOr(function($q) use ($cityId) {
|
||||||
|
$q->where('g.vr_goods_config', '<>', '')->where('g.produce_region', '=', $cityId);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// [调试代码] @file_put_contents($debugFile, date('Y-m-d H:i:s') . " OnSearchListBegin: city filter applied to ticket goods only, cityId=$cityId\n", FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,18 @@ class Admin extends Common
|
||||||
|
|
||||||
$goods = \think\facade\Db::name('Goods')->find($ticket['goods_id']);
|
$goods = \think\facade\Db::name('Goods')->find($ticket['goods_id']);
|
||||||
|
|
||||||
|
// 查询订单信息
|
||||||
|
$order = [];
|
||||||
|
$user = [];
|
||||||
|
if ($ticket['order_id'] > 0) {
|
||||||
|
$order = \think\facade\Db::name('Order')->find($ticket['order_id']);
|
||||||
|
|
||||||
|
// 查询用户信息
|
||||||
|
if (!empty($order) && $order['user_id'] > 0) {
|
||||||
|
$user = \think\facade\Db::name('User')->find($order['user_id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$verifier = [];
|
$verifier = [];
|
||||||
if ($ticket['verifier_id'] > 0) {
|
if ($ticket['verifier_id'] > 0) {
|
||||||
$verifier = \think\facade\Db::name('vr_verifiers')->find($ticket['verifier_id']);
|
$verifier = \think\facade\Db::name('vr_verifiers')->find($ticket['verifier_id']);
|
||||||
|
|
@ -204,6 +216,12 @@ class Admin extends Common
|
||||||
|
|
||||||
$ticket['qr_code_url'] = \app\plugins\vr_ticket\service\TicketService::getQrCodeUrl($ticket['ticket_code']);
|
$ticket['qr_code_url'] = \app\plugins\vr_ticket\service\TicketService::getQrCodeUrl($ticket['ticket_code']);
|
||||||
|
|
||||||
|
// 提取短码(从 qr_data 的前半部分)
|
||||||
|
$short_code = '';
|
||||||
|
if (!empty($ticket['qr_data']) && strpos($ticket['qr_data'], '|') !== false) {
|
||||||
|
$short_code = explode('|', $ticket['qr_data'], 2)[0];
|
||||||
|
}
|
||||||
|
|
||||||
$verifiers = \think\facade\Db::name('vr_verifiers')
|
$verifiers = \think\facade\Db::name('vr_verifiers')
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
->order('id', 'asc')
|
->order('id', 'asc')
|
||||||
|
|
@ -212,8 +230,11 @@ class Admin extends Common
|
||||||
return MyView('../../../plugins/vr_ticket/view/admin/ticket/detail', [
|
return MyView('../../../plugins/vr_ticket/view/admin/ticket/detail', [
|
||||||
'ticket' => $ticket,
|
'ticket' => $ticket,
|
||||||
'goods' => $goods,
|
'goods' => $goods,
|
||||||
|
'order' => $order,
|
||||||
|
'user' => $user,
|
||||||
'verifier' => $verifier,
|
'verifier' => $verifier,
|
||||||
'verifiers' => $verifiers,
|
'verifiers' => $verifiers,
|
||||||
|
'short_code'=> $short_code,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,8 @@ class Ticket
|
||||||
->where($where)
|
->where($where)
|
||||||
->order('id', 'desc')
|
->order('id', 'desc')
|
||||||
->page($page, $page_size)
|
->page($page, $page_size)
|
||||||
->select();
|
->select()
|
||||||
|
->toArray();
|
||||||
$total = \think\facade\Db::name('vr_verifications')
|
$total = \think\facade\Db::name('vr_verifications')
|
||||||
->where($where)
|
->where($where)
|
||||||
->count();
|
->count();
|
||||||
|
|
@ -389,12 +390,28 @@ class Ticket
|
||||||
// 关联票和商品信息
|
// 关联票和商品信息
|
||||||
$ticket_ids = array_filter(array_column($list, 'ticket_id'));
|
$ticket_ids = array_filter(array_column($list, 'ticket_id'));
|
||||||
$tickets_map = [];
|
$tickets_map = [];
|
||||||
|
$user_ids = [];
|
||||||
if (!empty($ticket_ids)) {
|
if (!empty($ticket_ids)) {
|
||||||
$tickets_raw = \think\facade\Db::name('vr_tickets')
|
$tickets_raw = \think\facade\Db::name('vr_tickets')
|
||||||
->where('id', 'in', $ticket_ids)
|
->where('id', 'in', $ticket_ids)
|
||||||
->select();
|
->select()
|
||||||
|
->toArray();
|
||||||
foreach ($tickets_raw as $t) {
|
foreach ($tickets_raw as $t) {
|
||||||
$tickets_map[$t['id']] = $t;
|
$tickets_map[$t['id']] = $t;
|
||||||
|
if (!empty($t['user_id'])) {
|
||||||
|
$user_ids[] = $t['user_id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$users_map = [];
|
||||||
|
if (!empty($user_ids)) {
|
||||||
|
$users_raw = \think\facade\Db::name('User')
|
||||||
|
->where('id', 'in', array_unique($user_ids))
|
||||||
|
->select()
|
||||||
|
->toArray();
|
||||||
|
foreach ($users_raw as $u) {
|
||||||
|
$users_map[$u['id']] = !empty($u['nickname']) ? $u['nickname'] : (!empty($u['username']) ? $u['username'] : '用户' . $u['id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,12 +427,27 @@ class Ticket
|
||||||
$result = [];
|
$result = [];
|
||||||
foreach ($list as $v) {
|
foreach ($list as $v) {
|
||||||
$ticket = $tickets_map[$v['ticket_id']] ?? [];
|
$ticket = $tickets_map[$v['ticket_id']] ?? [];
|
||||||
|
|
||||||
|
// 提取短码(从 qr_data 的前半部分)
|
||||||
|
$short_code = '';
|
||||||
|
if (!empty($ticket['qr_data']) && strpos($ticket['qr_data'], '|') !== false) {
|
||||||
|
$short_code = explode('|', $ticket['qr_data'], 2)[0];
|
||||||
|
} else {
|
||||||
|
$short_code = !empty($ticket['ticket_code']) ? substr($ticket['ticket_code'], 0, 8) : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$buyer_name = $users_map[$ticket['user_id'] ?? 0] ?? '';
|
||||||
|
|
||||||
$result[] = [
|
$result[] = [
|
||||||
'id' => $v['id'],
|
'id' => $v['id'],
|
||||||
'ticket_id' => $v['ticket_id'],
|
'ticket_id' => $v['ticket_id'],
|
||||||
'ticket_code' => $v['ticket_code'],
|
'ticket_code' => $v['ticket_code'],
|
||||||
|
'short_code' => $short_code,
|
||||||
'seat_info' => $ticket['seat_info'] ?? '',
|
'seat_info' => $ticket['seat_info'] ?? '',
|
||||||
'real_name' => $ticket['real_name'] ?? '',
|
'real_name' => $ticket['real_name'] ?? '',
|
||||||
|
'phone' => $ticket['phone'] ?? '',
|
||||||
|
'order_no' => $ticket['order_no'] ?? '',
|
||||||
|
'buyer_name' => $buyer_name,
|
||||||
'goods_title' => $goods_map[$v['goods_id']] ?? '已下架商品',
|
'goods_title' => $goods_map[$v['goods_id']] ?? '已下架商品',
|
||||||
'created_at' => $v['created_at'],
|
'created_at' => $v['created_at'],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ class AdminGoodsSave
|
||||||
<div v-show="config.viewer_config.require_viewer" style="margin-left:20px; margin-top:10px; padding-left:15px; border-left:3px solid #ddd;">
|
<div v-show="config.viewer_config.require_viewer" style="margin-left:20px; margin-top:10px; padding-left:15px; border-left:3px solid #ddd;">
|
||||||
<div style="margin-bottom:8px;">
|
<div style="margin-bottom:8px;">
|
||||||
<label class="am-checkbox-inline">
|
<label class="am-checkbox-inline">
|
||||||
<input type="checkbox" v-model="config.viewer_config.require_viewer_mobile" disabled checked />
|
<input type="checkbox" v-model="config.viewer_config.require_viewer_mobile" checked disabled />
|
||||||
<span style="margin-left:5px;">必填手机号</span>
|
<span style="margin-left:5px;">必填手机号</span>
|
||||||
<small style="color:#999; margin-left:8px;">(核心字段,默认必填)</small>
|
<small style="color:#999; margin-left:8px;">(核心字段,默认必填)</small>
|
||||||
</label>
|
</label>
|
||||||
|
|
@ -157,11 +157,11 @@ class AdminGoodsSave
|
||||||
<label class="am-checkbox-inline">
|
<label class="am-checkbox-inline">
|
||||||
<input type="checkbox" v-model="config.viewer_config.require_viewer_idcard" />
|
<input type="checkbox" v-model="config.viewer_config.require_viewer_idcard" />
|
||||||
<span style="margin-left:5px;">必填身份证号</span>
|
<span style="margin-left:5px;">必填身份证号</span>
|
||||||
<small style="color:#999; margin-left:8px;">(预留功能)</small>
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin-bottom:8px;">
|
<!-- 每个座位独立填写观影人(阶段2功能,暂时隐藏) -->
|
||||||
|
<div v-if="false" style="margin-bottom:8px;">
|
||||||
<label class="am-checkbox-inline">
|
<label class="am-checkbox-inline">
|
||||||
<input type="checkbox" v-model="config.viewer_config.require_viewer_per_seat" disabled />
|
<input type="checkbox" v-model="config.viewer_config.require_viewer_per_seat" disabled />
|
||||||
<span style="margin-left:5px;">每个座位独立填写观影人</span>
|
<span style="margin-left:5px;">每个座位独立填写观影人</span>
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,9 @@ class AdminGoodsSaveHandle
|
||||||
|
|
||||||
// c) 重新计算 goods.price / goods.inventory
|
// c) 重新计算 goods.price / goods.inventory
|
||||||
SeatSkuService::refreshGoodsBase($goodsId);
|
SeatSkuService::refreshGoodsBase($goodsId);
|
||||||
|
|
||||||
|
// d) 清除 Tree API 缓存(避免前端看到过期数据)
|
||||||
|
self::clearTreeCache($goodsId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,6 +240,37 @@ class AdminGoodsSaveHandle
|
||||||
return ['code' => 0];
|
return ['code' => 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return ['code' => 0];
|
return ['code' => 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除指定商品的 Tree API 缓存
|
||||||
|
*
|
||||||
|
* @param int $goodsId 商品ID
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function clearTreeCache($goodsId)
|
||||||
|
{
|
||||||
|
if ($goodsId <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tree API 缓存 key 格式:vr_tree_v4_{goods_id}_{md5(group_by)}
|
||||||
|
// 由于 group_by 参数可能有多种组合,清除所有可能的缓存
|
||||||
|
$possibleGroupBys = [
|
||||||
|
'venue,session,room,section', // 默认组合
|
||||||
|
'session,venue,room,section', // 按场次优先
|
||||||
|
'venue,room,session,section', // 其他可能组合
|
||||||
|
'session,room,section', // 简化组合
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($possibleGroupBys as $groupBy) {
|
||||||
|
$cacheKey = 'vr_tree_v4_' . $goodsId . '_' . md5($groupBy);
|
||||||
|
\think\facade\Cache::delete($cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录日志
|
||||||
|
\think\facade\Log::info('[VR Ticket] Cleared Tree API cache for goods: ' . $goodsId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,25 @@
|
||||||
<td width="100" class="am-text-gray">票码</td>
|
<td width="100" class="am-text-gray">票码</td>
|
||||||
<td>{{$ticket.ticket_code}}</td>
|
<td>{{$ticket.ticket_code}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">短码</td>
|
||||||
|
<td><strong style="font-size: 16px; color: #0e90d2; font-family: monospace; letter-spacing: 1px;">{{if !empty($short_code)}}{{$short_code}}{{else}}-{{/if}}</strong></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">订单号</td>
|
<td class="am-text-gray">订单号</td>
|
||||||
<td>{{$ticket.order_no}}</td>
|
<td>{{$ticket.order_no}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">商品名</td>
|
<td class="am-text-gray">商品名</td>
|
||||||
<td>{{$ticket.goods_name}}</td>
|
<td>{{if !empty($goods)}}{{$goods.title}}{{else}}已删除商品{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">观演人</td>
|
<td class="am-text-gray">观演人</td>
|
||||||
<td>{{$ticket.visitor_name}}</td>
|
<td>{{if !empty($ticket.real_name)}}{{$ticket.real_name}}{{else}}-{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">手机号</td>
|
<td class="am-text-gray">手机号</td>
|
||||||
<td>{{$ticket.mobile}}</td>
|
<td>{{if !empty($ticket.phone)}}{{$ticket.phone}}{{else}}-{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">身份证</td>
|
<td class="am-text-gray">身份证</td>
|
||||||
|
|
@ -46,27 +50,27 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">状态</td>
|
<td class="am-text-gray">状态</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>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">发放时间</td>
|
<td class="am-text-gray">发放时间</td>
|
||||||
<td>{{$ticket.create_time}}</td>
|
<td>{{if !empty($ticket.issued_at)}}{{:date('Y-m-d H:i:s', $ticket.issued_at)}}{{else}}-{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{if $ticket.status == 1}}
|
{{if $ticket.verify_status == 1}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">核销时间</td>
|
<td class="am-text-gray">核销时间</td>
|
||||||
<td>{{$ticket.verify_time}}</td>
|
<td>{{if !empty($ticket.verify_time)}}{{:date('Y-m-d H:i:s', $ticket.verify_time)}}{{else}}-{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="am-text-gray">核销人</td>
|
<td class="am-text-gray">核销人</td>
|
||||||
<td>{{if !empty($ticket.verifier_name)}}{{$ticket.verifier_name}}{{else}}未知{{/if}}</td>
|
<td>{{if !empty($verifier)}}{{$verifier.name}}{{else}}未知{{/if}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</table>
|
</table>
|
||||||
|
|
@ -74,89 +78,89 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 右侧:二维码 -->
|
<!-- 右侧:订单信息和核销操作 -->
|
||||||
<div class="am-u-sm-6">
|
<div class="am-u-sm-6">
|
||||||
|
<!-- 订单信息 -->
|
||||||
<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">订单信息</div>
|
||||||
<div class="am-panel-bd am-text-center">
|
|
||||||
<div id="qrcode-container" class="am-margin-bottom">
|
|
||||||
<!-- QR 码将由 JsBarcode 生成 -->
|
|
||||||
<svg id="qrcode-svg"></svg>
|
|
||||||
</div>
|
|
||||||
<p class="am-text-gray am-text-sm">票码:{{$ticket.ticket_code}}</p>
|
|
||||||
|
|
||||||
<!-- 条形码 -->
|
|
||||||
<div class="am-margin-top">
|
|
||||||
<svg id="barcode"></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 核销操作(仅未核销状态显示) -->
|
|
||||||
{{if $ticket.status == 0}}
|
|
||||||
<div class="am-panel am-panel-default am-margin-top">
|
|
||||||
<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">
|
{{if !empty($order)}}
|
||||||
<input type="hidden" name="ticket_code" value="{{$ticket.ticket_code}}" />
|
<table class="am-table am-text-sm">
|
||||||
<div class="am-form-group">
|
<tr>
|
||||||
<button type="submit" class="am-btn am-btn-primary am-btn-block am-radius" data-am-loading="{spinner: 'circle-o-notch', loadingText: '核销中...'}">
|
<td width="100" class="am-text-gray">订单号</td>
|
||||||
<i class="am-icon-check"></i> 立即核销
|
<td>{{$order.order_no}}</td>
|
||||||
</button>
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
</form>
|
<td class="am-text-gray">用户昵称</td>
|
||||||
|
<td>{{if !empty($user)}}{{$user.nickname|default=$user.username|default='未设置'}}{{else}}-{{/if}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">订单状态</td>
|
||||||
|
<td>
|
||||||
|
{{if $order.status == 0}}
|
||||||
|
<span class="am-badge am-badge-secondary">待确认</span>
|
||||||
|
{{elseif $order.status == 1}}
|
||||||
|
<span class="am-badge am-badge-warning">待支付</span>
|
||||||
|
{{elseif $order.status == 2}}
|
||||||
|
<span class="am-badge am-badge-primary">待发货</span>
|
||||||
|
{{elseif $order.status == 3}}
|
||||||
|
<span class="am-badge am-badge-primary">待收货</span>
|
||||||
|
{{elseif $order.status == 4}}
|
||||||
|
<span class="am-badge am-badge-success">已完成</span>
|
||||||
|
{{elseif $order.status == 5}}
|
||||||
|
<span class="am-badge am-badge-danger">已取消</span>
|
||||||
|
{{elseif $order.status == 6}}
|
||||||
|
<span class="am-badge am-badge-danger">已关闭</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="am-badge">未知</span>
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">支付状态</td>
|
||||||
|
<td>
|
||||||
|
{{if isset($order.pay_status) && $order.pay_status == 1}}
|
||||||
|
<span class="am-badge am-badge-success">已支付</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="am-badge am-badge-warning">未支付</span>
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">订单金额</td>
|
||||||
|
<td class="am-text-danger"><strong>¥{{$order.total_price|default='0.00'}}</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">购买数量</td>
|
||||||
|
<td><strong>{{$order.buy_number_count|default='0'}}</strong> 张票</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">支付方式</td>
|
||||||
|
<td>{{if !empty($order.payment_name)}}{{$order.payment_name}}{{else}}-{{/if}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">支付时间</td>
|
||||||
|
<td>{{if !empty($order.pay_time) && $order.pay_time > 0}}{{:date('Y-m-d H:i:s', $order.pay_time)}}{{else}}<span class="am-text-warning">未支付</span>{{/if}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">下单时间</td>
|
||||||
|
<td>{{if !empty($order.add_time)}}{{:date('Y-m-d H:i:s', $order.add_time)}}{{else}}-{{/if}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="am-text-gray">用户备注</td>
|
||||||
|
<td>{{if !empty($order.user_note)}}{{$order.user_note}}{{else}}<span class="am-text-gray">无</span>{{/if}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
{{else}}
|
||||||
|
<p class="am-text-center am-text-gray am-padding">订单信息不存在或已删除</p>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="{{$public_host}}static/common/lib/JsBarcode/JsBarcode.all.min.js"></script>
|
|
||||||
<script>
|
|
||||||
$(function() {
|
|
||||||
// 生成条形码
|
|
||||||
var ticketCode = '{{$ticket.ticket_code}}';
|
|
||||||
if (typeof JsBarcode !== 'undefined') {
|
|
||||||
JsBarcode('#barcode', ticketCode, {
|
|
||||||
format: 'CODE128',
|
|
||||||
width: 2,
|
|
||||||
height: 60,
|
|
||||||
displayValue: true,
|
|
||||||
fontSize: 14
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 核销表单提交
|
|
||||||
$('#verify-form').on('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
var $btn = $(this).find('button[type="submit"]');
|
|
||||||
|
|
||||||
$btn.button('loading');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '{{:PluginsAdminUrl("vr_ticket", "admin", "ticketverify")}}',
|
|
||||||
type: 'POST',
|
|
||||||
data: { ticket_code: ticketCode },
|
|
||||||
dataType: 'json',
|
|
||||||
success: function(res) {
|
|
||||||
$btn.button('reset');
|
|
||||||
|
|
||||||
if (res.code === 0) {
|
|
||||||
alert('核销成功');
|
|
||||||
location.reload();
|
|
||||||
} else {
|
|
||||||
alert(res.msg || '核销失败');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
$btn.button('reset');
|
|
||||||
alert('网络请求失败');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{:ModuleInclude('public/footer')}}
|
{{:ModuleInclude('public/footer')}}
|
||||||
|
|
@ -9,6 +9,20 @@
|
||||||
border-bottom: 2px solid #e8e8e8;
|
border-bottom: 2px solid #e8e8e8;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
/* 列宽优化 */
|
||||||
|
.ticket-list-table th:nth-child(4), /* 手机号 */
|
||||||
|
.ticket-list-table td:nth-child(4) {
|
||||||
|
width: 12%; /* 增加100% */
|
||||||
|
min-width: 110px;
|
||||||
|
}
|
||||||
|
.ticket-list-table th:nth-child(5), /* 座位信息 */
|
||||||
|
.ticket-list-table td:nth-child(5) {
|
||||||
|
width: 8%; /* 缩减30% */
|
||||||
|
max-width: 100px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="right-content">
|
<div class="right-content">
|
||||||
|
|
@ -89,11 +103,13 @@
|
||||||
<div class="am-panel am-panel-default">
|
<div class="am-panel am-panel-default">
|
||||||
<div class="am-panel-hd">电子票列表 <span class="am-text-xs am-padding-left">共 {{$count|default=0}} 条</span></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 ticket-list-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>订单号</th>
|
||||||
<th>票码</th>
|
<th>票码</th>
|
||||||
<th>观演人</th>
|
<th>观演人</th>
|
||||||
|
<th>手机号</th>
|
||||||
<th>座位信息</th>
|
<th>座位信息</th>
|
||||||
<th>商品名</th>
|
<th>商品名</th>
|
||||||
<th>状态</th>
|
<th>状态</th>
|
||||||
|
|
@ -105,8 +121,10 @@
|
||||||
{{if !empty($list)}}
|
{{if !empty($list)}}
|
||||||
{{volist name="list" id="ticket"}}
|
{{volist name="list" id="ticket"}}
|
||||||
<tr>
|
<tr>
|
||||||
|
<td>{{$ticket.order_no|default='—'}}</td>
|
||||||
<td>{{$ticket.ticket_code}}</td>
|
<td>{{$ticket.ticket_code}}</td>
|
||||||
<td>{{$ticket.real_name|default='—'}}</td>
|
<td>{{$ticket.real_name|default='—'}}</td>
|
||||||
|
<td>{{$ticket.phone|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_title|default='已删除商品'}}</td>
|
<td>{{$ticket.goods_title|default='已删除商品'}}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -121,7 +139,7 @@
|
||||||
<td>{{if !empty($ticket.issued_at)}}{{:date('Y-m-d H:i', $ticket.issued_at)}}{{else}}—{{/if}}
|
<td>{{if !empty($ticket.issued_at)}}{{:date('Y-m-d H:i', $ticket.issued_at)}}{{else}}—{{/if}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{:PluginsAdminUrl('vr_ticket', 'admin', 'ticketdetail')}}?id={{$ticket.id}}"
|
<a href="{{:PluginsAdminUrl('vr_ticket', 'admin', 'TicketDetail', ['id' => $ticket.id])}}"
|
||||||
class="am-btn am-btn-default am-btn-xs am-radius">
|
class="am-btn am-btn-default am-btn-xs am-radius">
|
||||||
<i class="am-icon-eye"></i> 查看详情
|
<i class="am-icon-eye"></i> 查看详情
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -130,7 +148,7 @@
|
||||||
{{/volist}}
|
{{/volist}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="7" class="am-text-center">暂无数据</td>
|
<td colspan="9" class="am-text-center">暂无数据</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue