hookehuyr

feat: 添加预约引导弹窗组件

- 新增 BookingGuideDialog 组件,提示用户前往小程序预约
- 首页点击"开始预约"按钮时弹出引导框
- 弹窗包含"关闭"和"预约记录"两个按钮
- 点击"预约记录"跳转到预约记录页面

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 +{
2 + "permissions": {
3 + "allow": [
4 + "Bash(git add:*)",
5 + "Bash(git commit:*)"
6 + ]
7 + }
8 +}
...@@ -7,6 +7,7 @@ export {} ...@@ -7,6 +7,7 @@ export {}
7 7
8 declare module '@vue/runtime-core' { 8 declare module '@vue/runtime-core' {
9 export interface GlobalComponents { 9 export interface GlobalComponents {
10 + BookingGuideDialog: typeof import('./src/components/BookingGuideDialog.vue')['default']
10 QrCode: typeof import('./src/components/qrCode.vue')['default'] 11 QrCode: typeof import('./src/components/qrCode.vue')['default']
11 QrCodeSearch: typeof import('./src/components/qrCodeSearch.vue')['default'] 12 QrCodeSearch: typeof import('./src/components/qrCodeSearch.vue')['default']
12 ReserveCard: typeof import('./src/components/reserveCard.vue')['default'] 13 ReserveCard: typeof import('./src/components/reserveCard.vue')['default']
...@@ -18,6 +19,7 @@ declare module '@vue/runtime-core' { ...@@ -18,6 +19,7 @@ declare module '@vue/runtime-core' {
18 VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup'] 19 VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
19 VanCol: typeof import('vant/es')['Col'] 20 VanCol: typeof import('vant/es')['Col']
20 VanDatePicker: typeof import('vant/es')['DatePicker'] 21 VanDatePicker: typeof import('vant/es')['DatePicker']
22 + VanDialog: typeof import('vant/es')['Dialog']
21 VanField: typeof import('vant/es')['Field'] 23 VanField: typeof import('vant/es')['Field']
22 VanForm: typeof import('vant/es')['Form'] 24 VanForm: typeof import('vant/es')['Form']
23 VanIcon: typeof import('vant/es')['Icon'] 25 VanIcon: typeof import('vant/es')['Icon']
......
1 +<!--
2 + * @Date: 2026-02-13
3 + * @Description: 预约引导弹窗组件
4 + * @component BookingGuideDialog
5 + * @example
6 + * <BookingGuideDialog v-model:show="showDialog" />
7 +-->
8 +<template>
9 + <van-popup
10 + v-model:show="visible"
11 + round
12 + position="center"
13 + :style="{ width: '80vw', 'max-width': '320px' }"
14 + closeable
15 + @click-close-icon="handleClose"
16 + >
17 + <div class="booking-guide-popup">
18 + <!-- 标题 -->
19 + <div class="popup-title">预约提示</div>
20 +
21 + <!-- 内容 -->
22 + <div class="popup-content">
23 + <p>请前往小程序进行预约</p>
24 + <p class="highlight">如已在 H5 端完成预约,可在预约记录中查看,并进行核销</p>
25 + </div>
26 +
27 + <!-- 按钮组 -->
28 + <div class="popup-footer">
29 + <van-button
30 + class="footer-btn cancel-btn"
31 + @click="handleClose"
32 + >
33 + 关闭
34 + </van-button>
35 + <van-button
36 + class="footer-btn confirm-btn"
37 + type="primary"
38 + color="#A67939"
39 + @click="goToBookingList"
40 + >
41 + 预约记录
42 + </van-button>
43 + </div>
44 + </div>
45 + </van-popup>
46 +</template>
47 +
48 +<script setup>
49 +/**
50 + * 预约引导弹窗组件
51 + *
52 + * @description 提示用户前往小程序预约,H5 预约可在预约记录中查看
53 + * @component BookingGuideDialog
54 + * @example
55 + * <BookingGuideDialog v-model:visible="showDialog" />
56 + */
57 +import { computed } from 'vue'
58 +import { useRouter } from 'vue-router'
59 +
60 +const props = defineProps({
61 + /** 是否显示弹窗 */
62 + modelValue: {
63 + type: Boolean,
64 + default: false
65 + }
66 +})
67 +
68 +const emit = defineEmits({
69 + /** 更新显示状态 */
70 + 'update:modelValue': (value) => typeof value === 'boolean'
71 +})
72 +
73 +const router = useRouter()
74 +
75 +const visible = computed({
76 + get: () => props.modelValue,
77 + set: (val) => emit('update:modelValue', val)
78 +})
79 +
80 +/**
81 + * 关闭弹窗
82 + */
83 +const handleClose = () => {
84 + visible.value = false
85 +}
86 +
87 +/**
88 + * 跳转到预约记录页面
89 + */
90 +const goToBookingList = () => {
91 + visible.value = false
92 + router.push('/bookingList')
93 +}
94 +</script>
95 +
96 +<style lang="less" scoped>
97 +.booking-guide-popup {
98 + padding: 24px 20px 20px;
99 + text-align: center;
100 +
101 + .popup-title {
102 + font-size: 18px;
103 + font-weight: 600;
104 + color: #1E1E1E;
105 + margin-bottom: 16px;
106 + }
107 +
108 + .popup-content {
109 + line-height: 1.8;
110 + font-size: 15px;
111 + color: #595959;
112 + margin-bottom: 24px;
113 +
114 + p {
115 + margin: 0 0 12px 0;
116 + }
117 +
118 + p:last-child {
119 + margin-bottom: 0;
120 + }
121 +
122 + .highlight {
123 + color: #A67939;
124 + font-weight: 500;
125 + }
126 + }
127 +
128 + .popup-footer {
129 + display: flex;
130 + gap: 12px;
131 +
132 + .footer-btn {
133 + flex: 1;
134 + height: 44px;
135 + border-radius: 8px;
136 + font-size: 15px;
137 + border: none;
138 + }
139 +
140 + .cancel-btn {
141 + background-color: #F5F5F5;
142 + color: #595959;
143 +
144 + &:active {
145 + background-color: #E6E6E6;
146 + }
147 + }
148 +
149 + .confirm-btn {
150 + background-color: #A67939;
151 + color: #FFFFFF;
152 +
153 + &:active {
154 + background-color: #8A6B30;
155 + }
156 + }
157 + }
158 +}
159 +</style>
1 <!-- 1 <!--
2 * @Date: 2023-06-21 10:23:09 2 * @Date: 2023-06-21 10:23:09
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-02-05 18:36:21 4 + * @LastEditTime: 2026-02-13 09:26:05
5 * @FilePath: /xysBooking/src/views/index.vue 5 * @FilePath: /xysBooking/src/views/index.vue
6 * @Description: 预约页首页 6 * @Description: 预约页首页
7 --> 7 -->
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
31 </div> --> 31 </div> -->
32 <div ref="root" class="index-circular"> 32 <div ref="root" class="index-circular">
33 <div class="booking-wrapper"> 33 <div class="booking-wrapper">
34 - <div class="booking" @click="toBooking"> 34 + <div class="booking" @click="handleBookingClick">
35 <div><van-icon size="3rem" color="#FFFFFF" :name="icon_1" /></div> 35 <div><van-icon size="3rem" color="#FFFFFF" :name="icon_1" /></div>
36 <div style="color: #FFF;">开始预约</div> 36 <div style="color: #FFF;">开始预约</div>
37 </div> 37 </div>
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
39 </div> 39 </div>
40 <div class="logo"></div> 40 <div class="logo"></div>
41 </div> 41 </div>
42 +
43 + <!-- 预约引导弹窗 -->
44 + <BookingGuideDialog v-model:show="showGuideDialog" />
42 <div class="index-nav"> 45 <div class="index-nav">
43 <div class="nav-logo"> 46 <div class="nav-logo">
44 <van-icon size="1.5rem" :name="icon_3" color="#A67939" /> 47 <van-icon size="1.5rem" :name="icon_3" color="#A67939" />
...@@ -68,6 +71,7 @@ import { Cookies, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils ...@@ -68,6 +71,7 @@ import { Cookies, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils
68 import { showSuccessToast, showFailToast } from 'vant'; 71 import { showSuccessToast, showFailToast } from 'vant';
69 import { billListAPI } from '@/api/index'; 72 import { billListAPI } from '@/api/index';
70 import { useGo } from '@/hooks/useGo' 73 import { useGo } from '@/hooks/useGo'
74 +import BookingGuideDialog from '@/components/BookingGuideDialog.vue'
71 import icon_1 from '@/assets/images/立即预约@2x.png' 75 import icon_1 from '@/assets/images/立即预约@2x.png'
72 import icon_2 from '@/assets/images/预约记录@2x.png' 76 import icon_2 from '@/assets/images/预约记录@2x.png'
73 import icon_3 from '@/assets/images/首页02@2x.png' 77 import icon_3 from '@/assets/images/首页02@2x.png'
...@@ -82,6 +86,17 @@ useTitle($route.meta.title); ...@@ -82,6 +86,17 @@ useTitle($route.meta.title);
82 86
83 const go = useGo(); 87 const go = useGo();
84 88
89 +// 预约引导弹窗显示状态
90 +const showGuideDialog = ref(false);
91 +
92 +/**
93 + * 处理开始预约点击
94 + * @description 显示预约引导弹窗
95 + */
96 +const handleBookingClick = () => {
97 + showGuideDialog.value = true;
98 +}
99 +
85 const toBooking = () => { // 跳转到预约须知 100 const toBooking = () => { // 跳转到预约须知
86 go('/notice'); 101 go('/notice');
87 } 102 }
......