hookehuyr

api接口联调

...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
15 "@code-ts/cin": "^0.0.2", 15 "@code-ts/cin": "^0.0.2",
16 "@vant/area-data": "^1.3.1", 16 "@vant/area-data": "^1.3.1",
17 "@vant/touch-emulator": "^1.4.0", 17 "@vant/touch-emulator": "^1.4.0",
18 + "@vant/use": "^1.6.0",
18 "@vitejs/plugin-legacy": "^1.8.2", 19 "@vitejs/plugin-legacy": "^1.8.2",
19 "@vueuse/core": "^8.5.0", 20 "@vueuse/core": "^8.5.0",
20 "animate.css": "^4.1.1", 21 "animate.css": "^4.1.1",
......
1 /* 1 /*
2 * @Date: 2023-08-24 09:42:27 2 * @Date: 2023-08-24 09:42:27
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-18 10:31:15 4 + * @LastEditTime: 2024-01-19 18:20:39
5 * @FilePath: /xysBooking/src/api/index.js 5 * @FilePath: /xysBooking/src/api/index.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -13,6 +13,15 @@ const Api = { ...@@ -13,6 +13,15 @@ const Api = {
13 PERSON_LIST: '/srv/?a=api&t=person_list', 13 PERSON_LIST: '/srv/?a=api&t=person_list',
14 ADD_PERSON: '/srv/?a=api&t=add_person', 14 ADD_PERSON: '/srv/?a=api&t=add_person',
15 DEL_PERSON: '/srv/?a=api&t=del_person', 15 DEL_PERSON: '/srv/?a=api&t=del_person',
16 + ADD_RESERVE: '/srv/?a=api&t=add_reserve',
17 + PAY_PREPARE: '/srv/?a=api&t=pay_prepare',
18 + PAY_CALLBACK: '/srv/?a=api&t=pay_callback',
19 + BILL_INFO: '/srv/?a=api&t=bill_info',
20 + QRCODE_LIST: '/srv/?a=api&t=qrcode_list',
21 + QRCODE_STATUS: '/srv/?a=api&t=qrcode_status',
22 + BILL_LIST: '/srv/?a=api&t=bill_list',
23 + CANCEL_PREPARE: '/srv/?a=api&t=cancel_prepare',
24 + BILL_PREPARE: '/srv/?a=api&t=bill_person',
16 }; 25 };
17 26
18 /** 27 /**
...@@ -53,3 +62,69 @@ export const addPersonAPI = (params) => fn(fetch.post(Api.ADD_PERSON, params)); ...@@ -53,3 +62,69 @@ export const addPersonAPI = (params) => fn(fetch.post(Api.ADD_PERSON, params));
53 * @returns 62 * @returns
54 */ 63 */
55 export const delPersonAPI = (params) => fn(fetch.post(Api.DEL_PERSON, params)); 64 export const delPersonAPI = (params) => fn(fetch.post(Api.DEL_PERSON, params));
65 +
66 +/**
67 + * @description: 提交预约
68 + * @param {String} reserve_date
69 + * @param {String} begin_time
70 + * @param {String} end_time
71 + * @param {String} person_id_list
72 + * @returns {String} bill_id 预约单id
73 + */
74 +export const addReserveAPI = (params) => fn(fetch.post(Api.ADD_RESERVE, params));
75 +
76 +/**
77 + * @description: 支付准备(模拟)
78 + * @param {String} bill_id
79 + * @returns {String} bill_id 预约单id
80 + */
81 +export const payPrepareAPI = (params) => fn(fetch.post(Api.PAY_PREPARE, params));
82 +
83 +/**
84 + * @description: 支付回调(模拟)
85 + * @param {String} pay_id 预约单支付凭证
86 + * @param {String} pay_status 支付状态,1为成功,0为失败(缺省)
87 + * @returns {String} bill_id 预约单id
88 + */
89 +export const payCallbackAPI = (params) => fn(fetch.post(Api.PAY_CALLBACK, params));
90 +
91 +/**
92 + * @description: 预约单详情,参观者列表
93 + * @param {String} bill_id 预约单id
94 + * @returns {String}
95 + */
96 +export const billInfoAPI = (params) => fn(fetch.get(Api.BILL_INFO, params));
97 +
98 +/**
99 + * @description: 预约码列表
100 + * @returns {String}
101 + */
102 +export const qrcodeListAPI = (params) => fn(fetch.get(Api.QRCODE_LIST, params));
103 +
104 +/**
105 + * @description: 二维码使用状态
106 + * @param {String} qr_code 二维码编号
107 + * @returns {String} status 二维码状态 1=未激活(未支付),3=待使用(已支付),5=被取消,7=已使用
108 + */
109 +export const qrcodeStatusAPI = (params) => fn(fetch.get(Api.QRCODE_STATUS, params));
110 +
111 +/**
112 + * @description: 预约单列表
113 + * @param {String}
114 + * @returns {String}
115 + */
116 +export const billListAPI = (params) => fn(fetch.get(Api.BILL_LIST, params));
117 +
118 +/**
119 + * @description: 取消预约退款准备(模拟)
120 + * @param {String} bill_id 预约单id
121 + * @returns {String} bill_id 预约单id
122 + */
123 +export const cancelPrepareAPI = (params) => fn(fetch.post(Api.CANCEL_PREPARE, params));
124 +
125 +/**
126 + * @description: 预约单的参观者列表
127 + * @param {String}
128 + * @returns {String}
129 + */
130 +export const billPersonAPI = (params) => fn(fetch.get(Api.BILL_PREPARE, params));
......
1 <!-- 1 <!--
2 * @Date: 2024-01-16 10:06:47 2 * @Date: 2024-01-16 10:06:47
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-18 14:25:17 4 + * @LastEditTime: 2024-01-19 19:15:34
5 * @FilePath: /xysBooking/src/components/qrCode.vue 5 * @FilePath: /xysBooking/src/components/qrCode.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
8 <template> 8 <template>
9 <div class="qr-code-page"> 9 <div class="qr-code-page">
10 - <div v-if="has_qrcode" class="show-qrcode"> 10 + <div v-if="userList.length" class="show-qrcode">
11 <div class="qrcode-content"> 11 <div class="qrcode-content">
12 <div v-if="props.status" class="user-status"> 12 <div v-if="props.status" class="user-status">
13 <div :class="[formatStatus(props.status).key, 'status']">{{ formatStatus(props.status).value }}</div> 13 <div :class="[formatStatus(props.status).key, 'status']">{{ formatStatus(props.status).value }}</div>
14 </div> 14 </div>
15 <div class="user-info">{{ userinfo.name }}&nbsp;{{ userinfo.id }}</div> 15 <div class="user-info">{{ userinfo.name }}&nbsp;{{ userinfo.id }}</div>
16 + <div style="color: red; margin-bottom: 0.5rem;">{{ userinfo.datetime }}</div>
16 <div class="user-qrcode"> 17 <div class="user-qrcode">
17 <div class="left" @click="prevCode"> 18 <div class="left" @click="prevCode">
18 <img src="https://cdn.ipadbiz.cn/xys/booking/%E5%B7%A6@2x.png"> 19 <img src="https://cdn.ipadbiz.cn/xys/booking/%E5%B7%A6@2x.png">
19 </div> 20 </div>
20 <div class="center"> 21 <div class="center">
21 - <img src="https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg"> 22 + <img :src="userList[select_index].qr_code_url ">
22 - <div v-if="useStatus === '1'" class="qrcode-used"><p>二维码已使用</p></div> 23 + <div v-if="useStatus === '7'" class="qrcode-used"><p>二维码{{ qr_code_status[useStatus] }}</p></div>
23 </div> 24 </div>
24 <div class="right" @click="nextCode"> 25 <div class="right" @click="nextCode">
25 <img src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png"> 26 <img src="https://cdn.ipadbiz.cn/xys/booking/%E5%8F%B3@2x.png">
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
35 v-for="(item, index) in userList" 36 v-for="(item, index) in userList"
36 :key="index" 37 :key="index"
37 :class="['user-item', select_index === index ? 'checked' : '']"> 38 :class="['user-item', select_index === index ? 'checked' : '']">
38 - {{ item.username }} 39 + {{ item.name }}
39 </div> 40 </div>
40 </div> 41 </div>
41 </div> 42 </div>
...@@ -53,6 +54,8 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ ...@@ -53,6 +54,8 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@
53 //import { } from '@/utils/generateModules.js' 54 //import { } from '@/utils/generateModules.js'
54 //import { } from '@/utils/generateIcons.js' 55 //import { } from '@/utils/generateIcons.js'
55 //import { } from '@/composables' 56 //import { } from '@/composables'
57 +
58 +import { qrcodeListAPI, qrcodeStatusAPI, billPersonAPI } from '@/api/index'
56 const $route = useRoute(); 59 const $route = useRoute();
57 const $router = useRouter(); 60 const $router = useRouter();
58 useTitle($route.meta.title); 61 useTitle($route.meta.title);
...@@ -61,45 +64,15 @@ const props = defineProps({ ...@@ -61,45 +64,15 @@ const props = defineProps({
61 status: { 64 status: {
62 type: String, 65 type: String,
63 default: '' 66 default: ''
64 - } 67 + },
68 + type: {
69 + type: String,
70 + default: ''
71 + },
65 }); 72 });
66 73
67 -const id_number = ref('511522190103214279');
68 -
69 -const has_qrcode = ref(true);
70 -
71 const select_index = ref(0); 74 const select_index = ref(0);
72 -const userList = ref([{ 75 +const userList = ref([]);
73 - id: '1',
74 - username: '张雨燕',
75 - id_code: '511522190103214279',
76 - qrcode: 'https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg',
77 - status: '0'
78 -}, {
79 - id: '2',
80 - username: '李仁和',
81 - id_code: '311522190103214279',
82 - qrcode: 'https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg',
83 - status: '1'
84 -}, {
85 - id: '3',
86 - username: '王二虎',
87 - id_code: '411522190103214279',
88 - qrcode: 'https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg',
89 - status: '0'
90 -}, {
91 - id: '4',
92 - username: '张雨燕2',
93 - id_code: '611522190103214279',
94 - qrcode: 'https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg',
95 - status: '1'
96 -}, {
97 - id: '5',
98 - username: '张雨燕3',
99 - id_code: '211522190103214279',
100 - qrcode: 'https://cdn.ipadbiz.cn/xys/booking/WechatIMG576.jpg',
101 - status: '0'
102 -}]);
103 76
104 const prevCode = () => { 77 const prevCode = () => {
105 select_index.value = select_index.value - 1; 78 select_index.value = select_index.value - 1;
...@@ -118,17 +91,17 @@ const nextCode = () => { ...@@ -118,17 +91,17 @@ const nextCode = () => {
118 * 生成15位身份证号中间8位替换为*号 91 * 生成15位身份证号中间8位替换为*号
119 * @param {*} inputString 92 * @param {*} inputString
120 */ 93 */
121 - function replaceMiddleCharacters(inputString) { 94 +function replaceMiddleCharacters(inputString) {
122 - if (inputString.length < 15) { 95 + if (inputString?.length < 15) {
123 return inputString; // 字符串长度不足,不进行替换 96 return inputString; // 字符串长度不足,不进行替换
124 } 97 }
125 98
126 - const start = Math.floor((inputString.length - 8) / 2); // 开始替换的索引位置 99 + const start = Math.floor((inputString?.length - 8) / 2); // 开始替换的索引位置
127 const end = start + 8; // 结束替换的索引位置 100 const end = start + 8; // 结束替换的索引位置
128 101
129 const replacement = '*'.repeat(8); // 生成包含8个*号的字符串 102 const replacement = '*'.repeat(8); // 生成包含8个*号的字符串
130 103
131 - const replacedString = inputString.substring(0, start) + replacement + inputString.substring(end); 104 + const replacedString = inputString?.substring(0, start) + replacement + inputString?.substring(end);
132 return replacedString; 105 return replacedString;
133 } 106 }
134 107
...@@ -138,17 +111,26 @@ const formatId = (id) => { ...@@ -138,17 +111,26 @@ const formatId = (id) => {
138 111
139 const userinfo = computed(() => { 112 const userinfo = computed(() => {
140 return { 113 return {
141 - name: userList.value[select_index.value]['username'], 114 + name: userList.value[select_index.value]?.name,
142 - id: formatId(userList.value[select_index.value]['id_code']) 115 + id: formatId(userList.value[select_index.value]?.id_number),
116 + datetime: userList.value[select_index.value]?.datetime,
143 }; 117 };
144 }); 118 });
145 119
146 -const useStatus = computed(() => { 120 +const useStatus = ref('0');
147 - return userList.value[select_index.value]['status']; 121 +
148 -}); 122 +const qr_code_status = {
123 + '1': '未激活',
124 + '3': '待使用',
125 + '5': '被取消',
126 + '7': '已使用'
127 +};
149 128
150 -const refreshBtn = () => { 129 +const refreshBtn = async () => {
151 - console.warn('refreshBtn'); 130 + const { code, data } = await qrcodeStatusAPI({ qr_code: userList.value[select_index.value].qr_code });
131 + if (code) {
132 + useStatus.value = data.status;
133 + }
152 } 134 }
153 135
154 const formatStatus = (status) => { 136 const formatStatus = (status) => {
...@@ -175,26 +157,35 @@ const selectUser = (index) => { ...@@ -175,26 +157,35 @@ const selectUser = (index) => {
175 select_index.value = index; 157 select_index.value = index;
176 } 158 }
177 159
178 -// TODO: 轮询查二维码的使用 160 +const pay_id = $route.query.pay_id;
179 -
180 -// const count = ref(0);
181 -
182 -// // 定义轮询函数
183 -// const poll = () => {
184 -// // 每秒增加计数值
185 -// count.value++;
186 -// console.log(count.value);
187 -// };
188 -// // 在组件挂载时启动轮询
189 -// onMounted(() => {
190 -// // 每秒执行一次轮询函数
191 -// const intervalId = setInterval(poll, 1000);
192 161
193 -// // 在组件卸载时清除定时器 162 +onMounted(async () => {
194 -// onUnmounted(() => { 163 + if (!props.type) {
195 -// clearInterval(intervalId); 164 + const { code, data } = await qrcodeListAPI();
196 -// }); 165 + if (code) {
197 -// }); 166 + data.forEach(item => {
167 + // 生成二维码地址
168 + item.qr_code_url = 'http://oa.onwall.cn/admin?m=srv&a=get_qrcode&key=' + item.qr_code
169 + // 二维码使用时间
170 + let begin_time = item.begin_time.slice(0, -3);
171 + let end_time = item.end_time.slice(0, -3);
172 + let str = begin_time + ' ' + end_time;
173 + //
174 + item.datetime = `${str.split(' ')[0]} ${str.split(' ')[1]}-${str.split(' ')[3]}`
175 + });
176 + userList.value = data;
177 + }
178 + } else {
179 + const { code, data } = await billPersonAPI({ pay_id });
180 + if (code) {
181 + data.forEach(item => {
182 + // 生成二维码地址
183 + item.qr_code_url = 'http://oa.onwall.cn/admin?m=srv&a=get_qrcode&key=' + item.qr_code
184 + });
185 + userList.value = data;
186 + }
187 + }
188 +})
198 </script> 189 </script>
199 190
200 <style lang="less" scoped> 191 <style lang="less" scoped>
...@@ -233,7 +224,7 @@ const selectUser = (index) => { ...@@ -233,7 +224,7 @@ const selectUser = (index) => {
233 color: #A6A6A6; 224 color: #A6A6A6;
234 font-size: 1.15rem; 225 font-size: 1.15rem;
235 margin-top: 0.5rem; 226 margin-top: 0.5rem;
236 - margin-bottom: 1rem; 227 + margin-bottom: 0.5rem;
237 } 228 }
238 .user-qrcode { 229 .user-qrcode {
239 display: flex; 230 display: flex;
......
...@@ -27,10 +27,6 @@ const $route = useRoute(); ...@@ -27,10 +27,6 @@ const $route = useRoute();
27 const $router = useRouter(); 27 const $router = useRouter();
28 useTitle($route.meta.title); 28 useTitle($route.meta.title);
29 29
30 -
31 -onMounted(() => {
32 -
33 -})
34 </script> 30 </script>
35 31
36 <style lang="less" scoped> 32 <style lang="less" scoped>
......
1 <!-- 1 <!--
2 * @Date: 2024-01-16 13:19:23 2 * @Date: 2024-01-16 13:19:23
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-19 14:08:04 4 + * @LastEditTime: 2024-01-19 19:25:47
5 * @FilePath: /xysBooking/src/views/bookingDetail.vue 5 * @FilePath: /xysBooking/src/views/bookingDetail.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
8 <template> 8 <template>
9 <div class="booking-detail-page"> 9 <div class="booking-detail-page">
10 - <qrCode status="success"></qrCode> 10 + <qrCode :status="qrCodeStatus" type="detail"></qrCode>
11 <div class="detail-wrapper"> 11 <div class="detail-wrapper">
12 <div class="detail-item"> 12 <div class="detail-item">
13 <div>参访时间:</div> 13 <div>参访时间:</div>
14 - <div>2024-01-10 05:00-08:00</div> 14 + <div>{{ billInfo?.datetime }}</div>
15 </div> 15 </div>
16 <div class="detail-item"> 16 <div class="detail-item">
17 <div>参访人数:</div> 17 <div>参访人数:</div>
18 - <div>2 人</div> 18 + <div>{{ billInfo?.total_qty }} 人</div>
19 </div> 19 </div>
20 <div class="detail-item"> 20 <div class="detail-item">
21 <div>支付金额:</div> 21 <div>支付金额:</div>
22 - <div>¥ 50</div> 22 + <div>¥ {{ billInfo?.total_amt }}</div>
23 </div> 23 </div>
24 <div class="detail-item"> 24 <div class="detail-item">
25 <div>下单时间:</div> 25 <div>下单时间:</div>
26 - <div>2024-01-09 13:09</div> 26 + <div>{{ billInfo?.order_time }}</div>
27 </div> 27 </div>
28 <div class="detail-item"> 28 <div class="detail-item">
29 <div>订单编号:</div> 29 <div>订单编号:</div>
30 - <div>2024011012345</div> 30 + <div>{{ billInfo?.pay_id }}</div>
31 </div> 31 </div>
32 </div> 32 </div>
33 <div style="height: 5rem;"></div> 33 <div style="height: 5rem;"></div>
...@@ -48,13 +48,15 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ ...@@ -48,13 +48,15 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@
48 import qrCode from '@/components/qrCode'; 48 import qrCode from '@/components/qrCode';
49 import { showConfirmDialog } from 'vant'; 49 import { showConfirmDialog } from 'vant';
50 import { showSuccessToast, showFailToast } from 'vant'; 50 import { showSuccessToast, showFailToast } from 'vant';
51 +import { billInfoAPI, cancelPrepareAPI } from '@/api/index'
51 const $route = useRoute(); 52 const $route = useRoute();
52 const $router = useRouter(); 53 const $router = useRouter();
53 useTitle($route.meta.title); 54 useTitle($route.meta.title);
54 55
55 const go = useGo(); 56 const go = useGo();
56 - 57 +const pay_id = $route.query.pay_id;
57 const status = ref('预约成功'); 58 const status = ref('预约成功');
59 +const qrCodeStatus = ref('');
58 60
59 const cancelBooking = (item) => { 61 const cancelBooking = (item) => {
60 showConfirmDialog({ 62 showConfirmDialog({
...@@ -63,15 +65,53 @@ const cancelBooking = (item) => { ...@@ -63,15 +65,53 @@ const cancelBooking = (item) => {
63 confirmButtonColor: '#A67939', 65 confirmButtonColor: '#A67939',
64 width: '80vw' 66 width: '80vw'
65 }) 67 })
66 - .then(() => { 68 + .then(async () => {
67 // on confirm 69 // on confirm
68 - showSuccessToast('取消成功'); 70 + const { code, data } = await cancelPrepareAPI({ bill_id: billInfo.value.bill_id });
69 - $router.go(-1); 71 + if (code) {
72 + showSuccessToast('取消成功');
73 + $router.go(-1);
74 + }
70 }) 75 })
71 .catch(() => { 76 .catch(() => {
72 // on cancel 77 // on cancel
73 }); 78 });
74 } 79 }
80 +
81 +const billInfo = ref({});
82 +
83 +/**
84 + * 1=待支付(下单就立即支付,所以理论上不存在待支付的数据),
85 + * 2=支付中(支付前先把状态打成2;支付回调后应立即变更状态,支付中的状态不会持续很久),
86 + * 3=预约成功(已支付,且一个码都未被使用),
87 + * 5=已取消(用户手动取消成功,退款成功回调后打成5,否则打成3),
88 + * 7=已取消(支付超时或失败自动取消),
89 + * 9=已使用(明细里有一个码被使用),
90 + * 11=退款中(取消预约时先把状态打成11)
91 + */
92 +
93 +onMounted(async () => {
94 + const { code, data } = await billInfoAPI({ pay_id });
95 + if (code) {
96 + let begin_time = data.begin_time.slice(0, -3);
97 + let end_time = data.end_time.slice(0, -3);
98 + let str = begin_time + ' ' + end_time;
99 + //
100 + data.datetime = `${str.split(' ')[0]} ${str.split(' ')[1]}-${str.split(' ')[3]}`;
101 + data.order_time = data.created_time.slice(0, -3);
102 + billInfo.value = data;
103 + // 显示二维码状态
104 + if (billInfo.value.status === '3') {
105 + qrCodeStatus.value = 'success';
106 + }
107 + if (billInfo.value.status === '7') {
108 + qrCodeStatus.value = 'cancel';
109 + }
110 + if (billInfo.value.status === '9') {
111 + qrCodeStatus.value = 'used';
112 + }
113 + }
114 +})
75 </script> 115 </script>
76 116
77 <style lang="less" scoped> 117 <style lang="less" scoped>
......
1 <!-- 1 <!--
2 * @Date: 2024-01-16 11:37:10 2 * @Date: 2024-01-16 11:37:10
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-16 16:02:56 4 + * @LastEditTime: 2024-01-19 19:04:27
5 * @FilePath: /xysBooking/src/views/bookingList.vue 5 * @FilePath: /xysBooking/src/views/bookingList.vue
6 * @Description: 文件描述 6 * @Description: 文件描述
7 --> 7 -->
8 <template> 8 <template>
9 <div class="booking-list-page"> 9 <div class="booking-list-page">
10 - <div @click="() => { go('/bookingDetail', { id: 'test' }) }" v-for="(item, index) in bookingList" :key="index" class="booking-list-item"> 10 + <div @click="() => { go('/bookingDetail', { pay_id: item.pay_id }) }" v-for="(item, index) in bookingList" :key="index" class="booking-list-item">
11 <div class="booking-list-item-header"> 11 <div class="booking-list-item-header">
12 <div>{{ item.booking_time }}</div> 12 <div>{{ item.booking_time }}</div>
13 - <div :class="[formatStatus(item.status).key, 'status']">{{ formatStatus(item.status).value }}</div> 13 + <div :class="[formatStatus(item.status)?.key, 'status']">{{ formatStatus(item.status)?.value }}</div>
14 </div> 14 </div>
15 <div class="booking-list-item-body"> 15 <div class="booking-list-item-body">
16 <div class="booking-num"> 16 <div class="booking-num">
17 - <div class="num-body">预约人数:<span>{{ item.num }} 人</span></div> 17 + <div class="num-body">预约人数:<span>{{ item.total_qty }} 人</span></div>
18 <div><van-icon name="arrow" /></div> 18 <div><van-icon name="arrow" /></div>
19 </div> 19 </div>
20 - <div class="booking-price">支付金额:<span>¥ {{ item.price }}</span></div> 20 + <div class="booking-price">支付金额:<span>¥ {{ item.total_amt }}</span></div>
21 <div class="booking-time">下单时间:<span>{{ item.order_time }}</span></div> 21 <div class="booking-time">下单时间:<span>{{ item.order_time }}</span></div>
22 </div> 22 </div>
23 </div> 23 </div>
...@@ -32,54 +32,79 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ ...@@ -32,54 +32,79 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@
32 //import { } from '@/utils/generateModules.js' 32 //import { } from '@/utils/generateModules.js'
33 //import { } from '@/utils/generateIcons.js' 33 //import { } from '@/utils/generateIcons.js'
34 //import { } from '@/composables' 34 //import { } from '@/composables'
35 +import { billListAPI } from '@/api/index'
35 const $route = useRoute(); 36 const $route = useRoute();
36 const $router = useRouter(); 37 const $router = useRouter();
37 useTitle($route.meta.title); 38 useTitle($route.meta.title);
38 39
39 const go = useGo(); 40 const go = useGo();
40 41
41 -const bookingList = ref([{ 42 +const bookingList = ref([]);
42 - id: '1', 43 +
43 - booking_time: '2024-01-10 05:00-08:00', 44 +/**
44 - status: 'success', 45 + * 1=待支付(下单就立即支付,所以理论上不存在待支付的数据),
45 - num: '2', 46 + * 2=支付中(支付前先把状态打成2;支付回调后应立即变更状态,支付中的状态不会持续很久),
46 - price: '50', 47 + * 3=预约成功(已支付,且一个码都未被使用),
47 - order_time: '2024-01-09 13:09', 48 + * 5=已取消(用户手动取消成功,退款成功回调后打成5,否则打成3),
48 -}, { 49 + * 7=已取消(支付超时或失败自动取消),
49 - id: '2', 50 + * 9=已使用(明细里有一个码被使用),
50 - booking_time: '2024-01-11 05:00-08:00', 51 + * 11=退款中(取消预约时先把状态打成11)
51 - status: 'cancel', 52 + */
52 - num: '2',
53 - price: '350',
54 - order_time: '2024-01-09 13:09',
55 -}, {
56 - id: '3',
57 - booking_time: '2024-01-12 05:00-08:00',
58 - status: 'used',
59 - num: '2',
60 - price: '150',
61 - order_time: '2024-01-09 13:09',
62 -}]);
63 53
64 const formatStatus = (status) => { 54 const formatStatus = (status) => {
65 switch (status) { 55 switch (status) {
66 - case 'success': 56 + case '1':
57 + return {
58 + key: 'cancel',
59 + value: '待支付'
60 + }
61 + case '2':
62 + return {
63 + key: 'success',
64 + value: '支付中'
65 + }
66 + case '3':
67 return { 67 return {
68 key: 'success', 68 key: 'success',
69 value: '预约成功' 69 value: '预约成功'
70 } 70 }
71 - case 'cancel': 71 + case '5':
72 + return {
73 + key: 'cancel',
74 + value: '已取消'
75 + }
76 + case '7':
72 return { 77 return {
73 key: 'cancel', 78 key: 'cancel',
74 value: '已取消' 79 value: '已取消'
75 } 80 }
76 - case 'used': 81 + case '9':
77 return { 82 return {
78 key: 'used', 83 key: 'used',
79 value: '已使用' 84 value: '已使用'
80 } 85 }
86 + case '11':
87 + return {
88 + key: 'used',
89 + value: '退款中'
90 + }
81 } 91 }
82 } 92 }
93 +
94 +onMounted(async () => {
95 + const { code, data } = await billListAPI();
96 + if (code) {
97 + //
98 + data.forEach(item => {
99 + let begin_time = item.begin_time?.slice(0, -3);
100 + let end_time = item.end_time?.slice(0, -3);
101 + let str = begin_time + ' ' + end_time;
102 + item.booking_time = `${str.split(' ')[0]} ${str.split(' ')[1]}-${str.split(' ')[3]}`;
103 + item.order_time = item.created_time.slice(0, -3);
104 + });
105 + bookingList.value = data;
106 + }
107 +})
83 </script> 108 </script>
84 109
85 <style lang="less" scoped> 110 <style lang="less" scoped>
......
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-01-17 18:35:33 4 + * @LastEditTime: 2024-01-19 15:45:54
5 * @FilePath: /xysBooking/src/views/index.vue 5 * @FilePath: /xysBooking/src/views/index.vue
6 * @Description: 预约页首页 6 * @Description: 预约页首页
7 --> 7 -->
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 </van-swipe-item> 15 </van-swipe-item>
16 </van-swipe> 16 </van-swipe>
17 </div> 17 </div>
18 - <div class="index-control"> 18 + <div ref="root" class="index-control">
19 <div class="booking" @click="toBooking"> 19 <div class="booking" @click="toBooking">
20 <van-icon size="1.5rem" color="#FFFFFF" :name="icon_1" /> 20 <van-icon size="1.5rem" color="#FFFFFF" :name="icon_1" />
21 &nbsp;立即预约 21 &nbsp;立即预约
...@@ -61,6 +61,7 @@ import icon_3 from '@/assets/images/首页02@2x.png' ...@@ -61,6 +61,7 @@ import icon_3 from '@/assets/images/首页02@2x.png'
61 import icon_4 from '@/assets/images/二维码icon.png' 61 import icon_4 from '@/assets/images/二维码icon.png'
62 import icon_5 from '@/assets/images/我的01@2x.png' 62 import icon_5 from '@/assets/images/我的01@2x.png'
63 import { canReserveDateListAPI } from '@/api/index' 63 import { canReserveDateListAPI } from '@/api/index'
64 +import { useClickAway } from '@vant/use';
64 const $route = useRoute(); 65 const $route = useRoute();
65 const $router = useRouter(); 66 const $router = useRouter();
66 useTitle($route.meta.title); 67 useTitle($route.meta.title);
...@@ -86,6 +87,11 @@ onMounted(async () => { ...@@ -86,6 +87,11 @@ onMounted(async () => {
86 const { code, data } = await canReserveDateListAPI({ month: `${raw_date.getFullYear()}-${raw_date.getMonth() + 1}` }); 87 const { code, data } = await canReserveDateListAPI({ month: `${raw_date.getFullYear()}-${raw_date.getMonth() + 1}` });
87 }); 88 });
88 89
90 +const root = ref();
91 +useClickAway(root, () => {
92 + console.log('click outside!');
93 +});
94 +
89 </script> 95 </script>
90 96
91 <style lang="less" scoped> 97 <style lang="less" scoped>
......
1 <!-- 1 <!--
2 * @Date: 2024-01-15 16:25:51 2 * @Date: 2024-01-15 16:25:51
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-18 11:05:25 4 + * @LastEditTime: 2024-01-19 18:57:26
5 * @FilePath: /xysBooking/src/views/submit.vue 5 * @FilePath: /xysBooking/src/views/submit.vue
6 * @Description: 预约人员信息 6 * @Description: 预约人员信息
7 --> 7 -->
...@@ -54,7 +54,7 @@ import { useGo } from '@/hooks/useGo' ...@@ -54,7 +54,7 @@ import { useGo } from '@/hooks/useGo'
54 import { showSuccessToast, showFailToast, showToast } from 'vant'; 54 import { showSuccessToast, showFailToast, showToast } from 'vant';
55 import icon_check1 from '@/assets/images/多选01@2x.png' 55 import icon_check1 from '@/assets/images/多选01@2x.png'
56 import icon_check2 from '@/assets/images/多选02@2x.png' 56 import icon_check2 from '@/assets/images/多选02@2x.png'
57 -import { personListAPI } from '@/api/index' 57 +import { personListAPI, addReserveAPI, payPrepareAPI, payCallbackAPI } from '@/api/index'
58 const $route = useRoute(); 58 const $route = useRoute();
59 const $router = useRouter(); 59 const $router = useRouter();
60 useTitle($route.meta.title); 60 useTitle($route.meta.title);
...@@ -88,7 +88,7 @@ const formatId = (id) => { ...@@ -88,7 +88,7 @@ const formatId = (id) => {
88 const checked_visitors = ref([]); 88 const checked_visitors = ref([]);
89 const addVisitor = (item) => { 89 const addVisitor = (item) => {
90 if (item.is_reserve === '1') { // 今天已经预约 90 if (item.is_reserve === '1') { // 今天已经预约
91 - showToast('已预约过参观,请不要重复预约!') 91 + showToast('已预约过参观,请不要重复预约')
92 return; 92 return;
93 } 93 }
94 if (checked_visitors.value.includes(item.id)) { 94 if (checked_visitors.value.includes(item.id)) {
...@@ -113,12 +113,21 @@ const goToVisitor = () => { ...@@ -113,12 +113,21 @@ const goToVisitor = () => {
113 go('/addVisitor'); 113 go('/addVisitor');
114 } 114 }
115 115
116 -const submitBtn = () => { 116 +const submitBtn = async () => {
117 if (!checked_visitors.value.length) { 117 if (!checked_visitors.value.length) {
118 - showToast('请先添加参观者') 118 + showToast('请先添加参观者')
119 } else { 119 } else {
120 // TODO: 提交订单跳转到支付页面 120 // TODO: 提交订单跳转到支付页面
121 - go('/success'); 121 + const { code, data } = await addReserveAPI({ reserve_date: date, begin_time: time.split('-')[0], end_time: time.split('-')[1], person_id_list: JSON.stringify(checked_visitors.value) });
122 + if (code) {
123 + const { code: prepare_code, data: prepare_data } = await payPrepareAPI({ pay_id: data.pay_id });
124 + if (prepare_code) {
125 + const { code: callback_code, data: callback_data } = await payCallbackAPI({ pay_id: prepare_data.pay_id, pay_status: 1 });
126 + if (callback_code) {
127 + go('/success', { pay_id: prepare_data.pay_id });
128 + }
129 + }
130 + }
122 } 131 }
123 } 132 }
124 133
...@@ -196,6 +205,7 @@ onMounted(async () => { ...@@ -196,6 +205,7 @@ onMounted(async () => {
196 margin: 1rem; 205 margin: 1rem;
197 padding: 0.8rem 3rem; 206 padding: 0.8rem 3rem;
198 border-radius: 5px; 207 border-radius: 5px;
208 + font-size: 1.1rem;
199 } 209 }
200 } 210 }
201 } 211 }
......
1 <!-- 1 <!--
2 * @Date: 2024-01-15 18:28:25 2 * @Date: 2024-01-15 18:28:25
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2024-01-18 14:19:42 4 + * @LastEditTime: 2024-01-19 17:27:20
5 * @FilePath: /xysBooking/src/views/success.vue 5 * @FilePath: /xysBooking/src/views/success.vue
6 * @Description: 预约成功提示页面 6 * @Description: 预约成功提示页面
7 --> 7 -->
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
13 <div class="text">预约成功</div> 13 <div class="text">预约成功</div>
14 </div> 14 </div>
15 <div class="appointment-information"> 15 <div class="appointment-information">
16 - <div class="number-of-visitors">参观人数:<span>2人</span></div> 16 + <div class="number-of-visitors">参观人数:<span>{{ billInfo?.total_qty }} 人</span></div>
17 - <div class="visit-time">参访时间:<span>2024-01-10 05:00-08:00</span></div> 17 + <div class="visit-time">参访时间:<span>{{ billInfo?.datetime }}</span></div>
18 - <div class="payment-amount">支付金额:<span>¥50</span></div> 18 + <div class="payment-amount">支付金额:<span>¥ {{ billInfo?.total_amt }}</span></div>
19 </div> 19 </div>
20 <div class="appointment-notice"> 20 <div class="appointment-notice">
21 <p style="margin-bottom: 0.25rem;"><van-icon name="info-o" />&nbsp;温馨提示</p> 21 <p style="margin-bottom: 0.25rem;"><van-icon name="info-o" />&nbsp;温馨提示</p>
...@@ -38,6 +38,8 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ ...@@ -38,6 +38,8 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@
38 //import { } from '@/utils/generateModules.js' 38 //import { } from '@/utils/generateModules.js'
39 //import { } from '@/utils/generateIcons.js' 39 //import { } from '@/utils/generateIcons.js'
40 //import { } from '@/composables' 40 //import { } from '@/composables'
41 +import { billInfoAPI, payPrepareAPI } from '@/api/index'
42 +
41 const $route = useRoute(); 43 const $route = useRoute();
42 const $router = useRouter(); 44 const $router = useRouter();
43 useTitle($route.meta.title); 45 useTitle($route.meta.title);
...@@ -48,8 +50,24 @@ const goToHome = () => { ...@@ -48,8 +50,24 @@ const goToHome = () => {
48 go('/') 50 go('/')
49 } 51 }
50 const goToDetail = () => { 52 const goToDetail = () => {
51 - go('/bookingDetail', { id: 'test' }) 53 + go('/bookingDetail', { pay_id: $route.query.pay_id });
52 } 54 }
55 +
56 +const billInfo = ref({});
57 +
58 +onMounted(async () => {
59 + const { code, data } = await billInfoAPI({ pay_id: $route.query.pay_id });
60 + if (code) {
61 + let begin_time = data.begin_time.slice(0, -3);
62 + let end_time = data.end_time.slice(0, -3);
63 + let str = begin_time + ' ' + end_time;
64 + //
65 + data.datetime = `${str.split(' ')[0]} ${str.split(' ')[1]}-${str.split(' ')[3]}`
66 + billInfo.value = data;
67 + // TAG:支付翻状态
68 + const { code: prepare_code, data: prepare_data } = await payPrepareAPI({ pay_id: $route.query.pay_id });
69 + }
70 +})
53 </script> 71 </script>
54 72
55 <style lang="less" scoped> 73 <style lang="less" scoped>
......