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.

339 lines
7.4 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.

<template>
<view>
<uni-popup ref="phonePopup" type="center" :is-mask-click="false">
<view class="phone-popup">
<view class="popup-header">
<text class="popup-title">请输入手机号码</text>
<view class="report-close" @click="closePhonePopup">×</view>
</view>
<view class="phone-popup-body">
<text class="phone-popup-tip">{{ phonePopupTip }}</text>
<input
v-model="inputPhone"
class="phone-popup-input"
type="number"
maxlength="11"
placeholder="请输入11位手机号码"
/>
</view>
<view class="phone-popup-actions">
<button class="btn btn-default popup-btn" @click="closePhonePopup">取消</button>
<button class="btn btn-primary popup-btn" @click="confirmPhoneForTakeTicket">确定</button>
</view>
</view>
</uni-popup>
<uni-popup ref="ticketPopup" type="center">
<view class="ticket-popup">
<view class="popup-header">
<text class="popup-title">选择业务直接取号</text>
<view class="report-close" @click="closeTicketPopup">×</view>
</view>
<view class="biz-grid">
<view
v-for="(item, index) in businessList"
:key="index"
class="biz-item"
:class="{ disabled: ticketLoading }"
@click="takeTicketByBusiness(item)"
>
<view class="biz-icon">
<uni-icons type="wallet" size="22" color="#111827"></uni-icons>
</view>
<view class="biz-name">{{ item.name }}</view>
<view class="biz-waiting">等候 {{ item.waitingCount ?? 0 }} 人</view>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import { getBizList } from "@/api/index.js";
import { takeTicket } from "@/api/ticket.js";
import { computed, ref, watch } from "vue";
import { validatePhoneNumber } from "@/utils/validator";
const emit = defineEmits(["success", "loading"]);
const phonePopup = ref(null);
const ticketPopup = ref(null);
const inputPhone = ref("");
const businessList = ref([]);
const ticketLoading = ref(false);
const currentRow = ref(null);
const tktType = ref("normal");
const rankUserPhone = ref("");
const phonePopupTip = computed(() =>
tktType.value === "normal"
? "普通取号请先填写手机号码"
: "当前记录无手机号,取号前请先填写",
);
const getTakeTicketPhone = () => {
if (currentRow.value) {
return String(currentRow.value.phone || "").trim();
}
return String(rankUserPhone.value || "").trim();
};
watch(ticketLoading, (value) => {
emit("loading", value);
});
const loadBusinessList = async () => {
try {
const res = await getBizList({ withWaiting: true });
const list = Array.isArray(res) ? res : [];
businessList.value = list.map((item, index) => ({
name: item.name || item.bizName || "",
value: item.value || item.uid || item.id || String(index),
waitingCount: Number(item.waitingCount ?? 0),
}));
} catch (error) {
console.log("获取业务列表失败:", error);
}
};
const openTicketBusinessPopup = async () => {
if (!businessList.value.length) {
await loadBusinessList();
}
ticketPopup.value?.open();
};
/** 普通取号:无核验记录,先填写手机号再选择业务 */
const open = () => {
currentRow.value = null;
tktType.value = "normal";
rankUserPhone.value = "";
inputPhone.value = "";
phonePopup.value?.open();
};
/** 预检取号:基于核验记录取号 */
const openWithRow = (row) => {
currentRow.value = row;
tktType.value = "realname";
rankUserPhone.value = "";
const phone = String(row?.phone || "").trim();
if (!phone) {
inputPhone.value = "";
phonePopup.value?.open();
return;
}
openTicketBusinessPopup();
};
const closePhonePopup = () => {
phonePopup.value?.close();
};
const confirmPhoneForTakeTicket = () => {
const phoneResult = validatePhoneNumber(inputPhone.value);
if (!phoneResult.valid) {
uni.showToast({
title: phoneResult.message || "请输入正确手机号",
icon: "none",
});
return;
}
if (currentRow.value) {
currentRow.value = {
...currentRow.value,
phone: inputPhone.value.trim(),
};
} else {
rankUserPhone.value = inputPhone.value.trim();
}
closePhonePopup();
openTicketBusinessPopup();
};
const closeTicketPopup = () => {
ticketPopup.value?.close();
};
const buildTakeTicketParams = (bizItem) => {
const params = {
bizUid: bizItem.value,
tktType: tktType.value,
rankUserPhone: getTakeTicketPhone(),
};
if (currentRow.value) {
params.uid = currentRow.value.uid;
params.idCard = currentRow.value.idCard;
params.rankUserName = currentRow.value.name;
}
return params;
};
const takeTicketByBusiness = async (bizItem) => {
if (ticketLoading.value) return;
if (!getTakeTicketPhone()) {
uni.showToast({
title: "请先填写手机号码",
icon: "none",
});
return;
}
ticketLoading.value = true;
try {
const result = await takeTicket(buildTakeTicketParams(bizItem));
const tktId = result?.tktId || result?.ticketNumber || "";
uni.showToast({
title: tktId ? `取号成功:${tktId}` : "取号成功",
icon: "success",
});
closeTicketPopup();
emit("success", result);
} catch (error) {
console.log("取号失败", error);
} finally {
ticketLoading.value = false;
}
};
defineExpose({
open,
openWithRow,
ticketLoading,
});
</script>
<style scoped lang="scss">
.ticket-popup,
.phone-popup {
width: 680rpx;
max-width: 90vw;
background: #fff;
border-radius: 12px;
overflow: hidden;
}
.phone-popup-body {
padding: 14px;
}
.phone-popup-tip {
display: block;
font-size: 14px;
color: #6b7280;
margin-bottom: 12px;
}
.phone-popup-input {
width: 100%;
height: 40px;
border: 1px solid #d1d5db;
border-radius: 8px;
padding: 0 12px;
font-size: 14px;
box-sizing: border-box;
}
.phone-popup-actions {
padding: 12px 14px 14px;
display: flex;
justify-content: flex-end;
gap: 10px;
}
.popup-header {
height: 48px;
padding: 0 14px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
justify-content: space-between;
}
.popup-title {
font-size: 15px;
color: #111827;
font-weight: 600;
}
.report-close {
width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
font-size: 22px;
color: #9ca3af;
cursor: pointer;
}
.biz-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 10px;
padding: 14px;
}
.biz-item {
border: 1px solid #e5e7eb;
border-radius: 10px;
min-height: 92px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
cursor: pointer;
}
.biz-item.disabled {
opacity: 0.6;
pointer-events: none;
}
.biz-icon {
margin-bottom: 6px;
display: flex;
align-items: center;
justify-content: center;
}
.biz-name {
font-size: 13px;
color: #111827;
text-align: center;
}
.biz-waiting {
margin-top: 6px;
font-size: 12px;
color: #fa541c;
text-align: center;
}
.btn {
min-width: 72px;
height: 32px;
line-height: 32px;
padding: 0 14px;
font-size: 14px;
border-radius: 6px;
border: none;
}
.popup-btn {
min-width: 72px;
}
.btn-primary {
background: #2563eb;
color: #fff;
}
.btn-default {
background: #fff;
color: #374151;
border: 1px solid #d1d5db;
}
</style>