You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

437 lines
8.5 KiB
Vue

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.

<!-- pages/queue/business-select.vue -->
<template>
<view class="business-container">
<!-- 头部信息 -->
<view class="user-info">
<text class="info-title">您好{{ userName }}</text>
<text class="info-subtitle">请选择需要办理的业务类型</text>
</view>
<!-- 业务列表 -->
<scroll-view class="business-list" scroll-y>
<view v-for="(item, index) in businessList" :key="index" class="business-item"
:class="{ 'selected': selectedBusiness === item.value }" @click="selectBusiness(item)">
<view class="business-icon">{{ item.icon }}</view>
<view class="business-content">
<text class="business-name">{{ item.name }}</text>
<text class="business-desc">{{ item.description }}</text>
</view>
<view class="business-check" v-if="selectedBusiness === item.value">
<text>✓</text>
</view>
</view>
</scroll-view>
<!-- 操作按钮 -->
<view class="action-buttons">
<button class="btn-back" @click="goBack">返回修改</button>
<button class="btn-confirm" :disabled="!selectedBusiness" @click="handleConfirm">
确认取号
</button>
</view>
<!-- 取号结果弹窗 -->
<uni-popup ref="resultPopup" type="center" :is-mask-click="false">
<view class="result-popup">
<view class="result-header">
<text class="result-icon">✅</text>
<text class="result-title">取号成功</text>
</view>
<view class="result-content">
<view class="ticket-info">
<text class="ticket-label">您的排队号码</text>
<text class="ticket-number">{{ ticketInfo.ticketNumber }}</text>
</view>
<view class="ticket-details">
<view class="detail-item">
<text class="detail-label">业务类型</text>
<text class="detail-value">{{ ticketInfo.businessName }}</text>
</view>
<view class="detail-item">
<text class="detail-label">预计等候</text>
<text class="detail-value">{{ ticketInfo.waitingTime }}分钟</text>
</view>
<view class="detail-item">
<text class="detail-label">办理窗口</text>
<text class="detail-value">{{ ticketInfo.serviceWindow }}</text>
</view>
</view>
</view>
<view class="result-actions">
<button class="btn-print" @click="handlePrint">打印小票</button>
<button class="btn-notify" @click="handleNotify"></button>
</view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import {
ref
} from 'vue';
import {
onLoad,
onReady
} from '@dcloudio/uni-app'
// import {
// generateTicket,
// printTicket,
// sendNotification
// } from '@/utils/api';
const userName = ref('');
const selectedBusiness = ref('');
const businessList = ref([]);
const ticketInfo = ref({});
const resultPopup = ref(null);
// 获取页面参数
onLoad((options) => {
userName.value = decodeURIComponent(options.name || '');
// 模拟业务数据,实际应从接口获取
businessList.value = [{
icon: '🏦',
name: '税务登记',
value: 'tax_register',
description: '企业税务登记、变更、注销'
},
{
icon: '🧾',
name: '发票办理',
value: 'invoice',
description: '发票申领、开具、验旧'
},
{
icon: '📊',
name: '纳税申报',
value: 'tax_declare',
description: '各类税种申报缴纳'
},
{
icon: '🎯',
name: '税收优惠',
value: 'tax_preference',
description: '优惠政策咨询办理'
},
{
icon: '📝',
name: '证明开具',
value: 'certificate',
description: '完税证明、涉税证明'
},
{
icon: '🔍',
name: '税务查询',
value: 'tax_query',
description: '纳税记录、信用查询'
}
];
});
// 选择业务
const selectBusiness = (item) => {
selectedBusiness.value = item.value;
};
// 返回修改
const goBack = () => {
uni.navigateBack();
};
// 确认取号
const handleConfirm = async () => {
try {
// 调用取号接口
const result = await generateTicket({
businessType: selectedBusiness.value
});
if (result.code === 200) {
ticketInfo.value = {
ticketNumber: result.data.ticketNumber,
businessName: businessList.value.find(b => b.value === selectedBusiness.value).name,
waitingTime: result.data.waitingTime || '15-20',
serviceWindow: result.data.serviceWindow || '请等候叫号'
};
// 显示取号结果
resultPopup.value.open();
}
} catch (error) {
uni.showToast({
title: error.message || '取号失败',
icon: 'none'
});
}
};
// 打印小票
const handlePrint = async () => {
uni.showLoading({
title: '正在打印...'
});
try {
const result = await printTicket(ticketInfo.value);
if (result.code === 200) {
uni.showToast({
title: '打印指令已发送',
icon: 'success'
});
}
} catch (error) {
uni.showToast({
title: error.message || '打印失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
};
// 推送消息
const handleNotify = async () => {
uni.showLoading({
title: '正在推送...'
});
try {
const result = await sendNotification(ticketInfo.value);
if (result.code === 200) {
uni.showToast({
title: '消息已推送到手机',
icon: 'success'
});
}
} catch (error) {
uni.showToast({
title: error.message || '推送失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
};
</script>
<style scoped>
.business-container {
padding: 40rpx 32rpx;
min-height: 100vh;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.user-info {
text-align: center;
margin-bottom: 40rpx;
}
.info-title {
font-size: 36rpx;
font-weight: bold;
color: #1a1a1a;
display: block;
margin-bottom: 12rpx;
}
.info-subtitle {
font-size: 26rpx;
color: #666;
display: block;
}
.business-list {
height: 60vh;
margin-bottom: 40rpx;
}
.business-item {
background: white;
border-radius: 16rpx;
padding: 32rpx;
margin-bottom: 20rpx;
display: flex;
align-items: center;
border: 2rpx solid #e0e0e0;
transition: all 0.3s ease;
}
.business-item.selected {
border-color: #007AFF;
background: #f0f7ff;
box-shadow: 0 4rpx 20rpx rgba(0, 122, 255, 0.15);
}
.business-icon {
font-size: 48rpx;
margin-right: 24rpx;
}
.business-content {
flex: 1;
}
.business-name {
font-size: 30rpx;
font-weight: 600;
color: #333;
display: block;
margin-bottom: 8rpx;
}
.business-desc {
font-size: 24rpx;
color: #666;
display: block;
}
.business-check {
width: 40rpx;
height: 40rpx;
background: #007AFF;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24rpx;
}
.action-buttons {
display: flex;
gap: 20rpx;
}
.action-buttons button {
flex: 1;
height: 88rpx;
border-radius: 16rpx;
font-size: 30rpx;
font-weight: 500;
border: none;
}
.btn-back {
background: #f0f0f0;
color: #666;
}
.btn-confirm {
background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
color: white;
}
.btn-confirm:disabled {
background: #cccccc;
opacity: 0.6;
}
/* 取号结果弹窗 */
.result-popup {
width: 650rpx;
max-width: 90vw;
background: white;
border-radius: 24rpx;
overflow: hidden;
}
.result-header {
padding: 40rpx 40rpx 20rpx;
text-align: center;
background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
color: white;
}
.result-icon {
font-size: 80rpx;
display: block;
margin-bottom: 16rpx;
}
.result-title {
font-size: 36rpx;
font-weight: bold;
display: block;
}
.result-content {
padding: 40rpx;
}
.ticket-info {
text-align: center;
margin-bottom: 40rpx;
padding-bottom: 40rpx;
border-bottom: 2rpx dashed #e0e0e0;
}
.ticket-label {
font-size: 28rpx;
color: #666;
display: block;
margin-bottom: 16rpx;
}
.ticket-number {
font-size: 72rpx;
font-weight: bold;
color: #007AFF;
display: block;
letter-spacing: 4rpx;
}
.ticket-details {
display: flex;
flex-direction: column;
gap: 20rpx;
}
.detail-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.detail-label {
font-size: 28rpx;
color: #666;
}
.detail-value {
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.result-actions {
display: flex;
gap: 20rpx;
padding: 0 40rpx 40rpx;
}
.result-actions button {
flex: 1;
height: 80rpx;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 500;
border: none;
}
.btn-print {
background: #4CAF50;
color: white;
}
.btn-notify {
background: #2196F3;
color: white;
}
</style>