hookehuyr

api接口联调

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