Merge branch 'order' of https://code.itechtop.cn/yangyang/dance-pc into order
Showing
41 changed files
with
3310 additions
and
79 deletions
| ... | @@ -30,6 +30,7 @@ | ... | @@ -30,6 +30,7 @@ |
| 30 | "jszip": "^3.10.1", | 30 | "jszip": "^3.10.1", |
| 31 | "katex": "^0.16.6", | 31 | "katex": "^0.16.6", |
| 32 | "lodash": "^4.17.21", | 32 | "lodash": "^4.17.21", |
| 33 | "md5js": "^1.0.7", | ||
| 33 | "nprogress": "0.2.0", | 34 | "nprogress": "0.2.0", |
| 34 | "pinia": "2.0.35", | 35 | "pinia": "2.0.35", |
| 35 | "qrcode": "^1.5.3", | 36 | "qrcode": "^1.5.3", | ... | ... |
pnpm-lock.yaml
0 → 100644
This diff could not be displayed because it is too large.
public/file/COMPETITION GUIDE 0520V1.pdf
0 → 100644
No preview for this file type
No preview for this file type
src/assets/sign/gl.png
0 → 100644
1.53 KB
| ... | @@ -1078,7 +1078,8 @@ img{display: block;} | ... | @@ -1078,7 +1078,8 @@ img{display: block;} |
| 1078 | text-decoration: underline;} | 1078 | text-decoration: underline;} |
| 1079 | } | 1079 | } |
| 1080 | .panel-title{font-size: 16px;line-height: 50px;margin: 0; | 1080 | .panel-title{font-size: 16px;line-height: 50px;margin: 0; |
| 1081 | color: var(--el-color-primary)} | 1081 | color: var(--el-color-primary) |
| 1082 | } | ||
| 1082 | .panel-body{padding: 20px;} | 1083 | .panel-body{padding: 20px;} |
| 1083 | &.border{border: 1px solid #EEEEEE;} | 1084 | &.border{border: 1px solid #EEEEEE;} |
| 1084 | } | 1085 | } | ... | ... |
| ... | @@ -12,12 +12,13 @@ | ... | @@ -12,12 +12,13 @@ |
| 12 | > | 12 | > |
| 13 | <el-menu-item index="/">{{ language==0?'首页':'HOME' }}</el-menu-item> | 13 | <el-menu-item index="/">{{ language==0?'首页':'HOME' }}</el-menu-item> |
| 14 | <el-menu-item index="/news">{{ language==0?'新闻资讯':'NEWS' }}</el-menu-item> | 14 | <el-menu-item index="/news">{{ language==0?'新闻资讯':'NEWS' }}</el-menu-item> |
| 15 | <el-menu-item index="/notice">{{ language==0?'通知公告':'NOTICEBOARD' }}</el-menu-item> | 15 | <el-menu-item index="/guide">{{ language==0?'参赛指南':'GUIDELINE' }}</el-menu-item> |
| 16 | <el-menu-item index="/match/list">{{ language==0?'大赛报名':'REGISTRATION' }}</el-menu-item> | 16 | <el-menu-item index="/match/list">{{ language==0?'大赛报名':'REGISTRATION' }}</el-menu-item> |
| 17 | <el-menu-item index="/saiC">{{ language==0?'赛程安排':'COMPETITIONS' }}</el-menu-item> | 17 | <el-menu-item index="/saiC">{{ language==0?'赛程安排':'COMPETITIONS' }}</el-menu-item> |
| 18 | <el-menu-item index="/meta">{{ language==0?'媒体中心':'MEDIA' }}</el-menu-item> | 18 | <el-menu-item index="/meta">{{ language==0?'媒体中心':'MEDIA' }}</el-menu-item> |
| 19 | <el-menu-item index="/guide">{{ language==0?'参赛指南':'GUIDELINE' }}</el-menu-item> | 19 | <el-menu-item index="/notice">{{ language==0?'通知公告':'NOTICEBOARD' }}</el-menu-item> |
| 20 | <!-- <el-sub-menu index="/about">--> | 20 | |
| 21 | <!-- <el-sub-menu index="/about">--> | ||
| 21 | <!-- <template #title>{{ language==0?'关于我们':'CONTACT & MORE' }}</template>--> | 22 | <!-- <template #title>{{ language==0?'关于我们':'CONTACT & MORE' }}</template>--> |
| 22 | <!-- <el-menu-item index="/about/wuDao">{{ language==0?'舞蹈节':'About Us' }}</el-menu-item>--> | 23 | <!-- <el-menu-item index="/about/wuDao">{{ language==0?'舞蹈节':'About Us' }}</el-menu-item>--> |
| 23 | <!-- <el-menu-item index="/about/regulations" v-if="language==1">Rules & Regulations</el-menu-item>--> | 24 | <!-- <el-menu-item index="/about/regulations" v-if="language==1">Rules & Regulations</el-menu-item>--> |
| ... | @@ -30,12 +31,13 @@ | ... | @@ -30,12 +31,13 @@ |
| 30 | > | 31 | > |
| 31 | <el-menu-item index="/">{{ language==0?'首页':'HOME' }}</el-menu-item> | 32 | <el-menu-item index="/">{{ language==0?'首页':'HOME' }}</el-menu-item> |
| 32 | <el-menu-item index="/news">{{ language==0?'新闻资讯':'NEWS' }}</el-menu-item> | 33 | <el-menu-item index="/news">{{ language==0?'新闻资讯':'NEWS' }}</el-menu-item> |
| 33 | <el-menu-item index="/notice">{{ language==0?'通知公告':'NOTICEBOARD' }}</el-menu-item> | 34 | <el-menu-item index="/guide">{{ language==0?'参赛指南':'GUIDELINE' }}</el-menu-item> |
| 34 | <el-menu-item index="/match/list">{{ language==0?'大赛报名':'REGISTRATION' }}</el-menu-item> | 35 | <el-menu-item index="/match/list">{{ language==0?'大赛报名':'REGISTRATION' }}</el-menu-item> |
| 35 | <el-menu-item index="/saiC">{{ language==0?'赛程安排':'COMPETITIONS' }}</el-menu-item> | 36 | <el-menu-item index="/saiC">{{ language==0?'赛程安排':'COMPETITIONS' }}</el-menu-item> |
| 36 | <el-menu-item index="/meta">{{ language==0?'媒体中心':'MEDIA' }}</el-menu-item> | 37 | <el-menu-item index="/meta">{{ language==0?'媒体中心':'MEDIA' }}</el-menu-item> |
| 37 | <el-menu-item index="/guide">{{ language==0?'参赛指南':'GUIDELINE' }}</el-menu-item> | 38 | <el-menu-item index="/notice">{{ language==0?'通知公告':'NOTICEBOARD' }}</el-menu-item> |
| 38 | <!-- <el-sub-menu index="/about">--> | 39 | |
| 40 | <!-- <el-sub-menu index="/about">--> | ||
| 39 | <!-- <template #title>{{ language==0?'关于我们':'CONTACT & MORE' }}</template>--> | 41 | <!-- <template #title>{{ language==0?'关于我们':'CONTACT & MORE' }}</template>--> |
| 40 | <!-- <el-menu-item index="/about/wuDaoEn">{{ language==0?'舞蹈节':'About Us' }}</el-menu-item>--> | 42 | <!-- <el-menu-item index="/about/wuDaoEn">{{ language==0?'舞蹈节':'About Us' }}</el-menu-item>--> |
| 41 | <!-- <el-menu-item index="/about/regulations" v-if="language==1">Rules & Regulations</el-menu-item>--> | 43 | <!-- <el-menu-item index="/about/regulations" v-if="language==1">Rules & Regulations</el-menu-item>--> | ... | ... |
| ... | @@ -13,6 +13,7 @@ NProgress.configure({ showSpinner: false }) | ... | @@ -13,6 +13,7 @@ NProgress.configure({ showSpinner: false }) |
| 13 | const whiteList = ['/login', '/register', '/regulations'] | 13 | const whiteList = ['/login', '/register', '/regulations'] |
| 14 | 14 | ||
| 15 | router.beforeEach((to, from, next) => { | 15 | router.beforeEach((to, from, next) => { |
| 16 | console.log('to2', to) | ||
| 16 | NProgress.start() | 17 | NProgress.start() |
| 17 | if (getToken()) { | 18 | if (getToken()) { |
| 18 | // debugger | 19 | // debugger | ... | ... |
| ... | @@ -9,6 +9,7 @@ import useUserStore from '@/store/modules/user' | ... | @@ -9,6 +9,7 @@ import useUserStore from '@/store/modules/user' |
| 9 | NProgress.configure({ showSpinner: false }) | 9 | NProgress.configure({ showSpinner: false }) |
| 10 | 10 | ||
| 11 | router.beforeEach((to, from, next) => { | 11 | router.beforeEach((to, from, next) => { |
| 12 | console.log('to', to) | ||
| 12 | NProgress.start() | 13 | NProgress.start() |
| 13 | if (getToken()) { | 14 | if (getToken()) { |
| 14 | // 判断当前用户是否已拉取完user_info信息 | 15 | // 判断当前用户是否已拉取完user_info信息 | ... | ... |
| ... | @@ -500,6 +500,71 @@ export const constantRoutes = [ | ... | @@ -500,6 +500,71 @@ export const constantRoutes = [ |
| 500 | meta: { title: 'System messages' } | 500 | meta: { title: 'System messages' } |
| 501 | } | 501 | } |
| 502 | ] | 502 | ] |
| 503 | }, | ||
| 504 | { | ||
| 505 | path: 'seat', | ||
| 506 | component: () => import('@/viewsPc/seat/seat'), | ||
| 507 | name: 'seat', | ||
| 508 | redirect: '/seat/detail', | ||
| 509 | children: [ | ||
| 510 | { | ||
| 511 | path: 'detail', | ||
| 512 | name: 'seat_detail', | ||
| 513 | component: () => import('@/viewsPc/seat/ticket-detail'), | ||
| 514 | meta: { title: '购票详情' }, | ||
| 515 | props: route => ({ | ||
| 516 | activityId:route.query.id, | ||
| 517 | }) | ||
| 518 | }, | ||
| 519 | { | ||
| 520 | path: 'seat_picker', | ||
| 521 | name: 'seat_picker', | ||
| 522 | component: () => import('@/viewsPc/seat/seat-picker'), | ||
| 523 | meta: { title: '选座' }, | ||
| 524 | props: route => ({ | ||
| 525 | activityId:route.query.id, | ||
| 526 | }) | ||
| 527 | }, | ||
| 528 | { | ||
| 529 | path: 'order', | ||
| 530 | name: 'seat_order', | ||
| 531 | component: () => import('@/viewsPc/seat/order-list'), | ||
| 532 | meta: { title: '我的订单' }, | ||
| 533 | props: route => ({ | ||
| 534 | activityId:route.query.id, | ||
| 535 | }) | ||
| 536 | }, | ||
| 537 | { | ||
| 538 | path: 'order_detail', | ||
| 539 | name: 'order_detail', | ||
| 540 | component: () => import('@/viewsPc/seat/order-detail'), | ||
| 541 | meta: { title: '订单详情' }, | ||
| 542 | props: route => ({ | ||
| 543 | activityId: route.query.id, | ||
| 544 | }) | ||
| 545 | }, | ||
| 546 | { | ||
| 547 | path: 'confirm_order', | ||
| 548 | name: 'confirm_order', | ||
| 549 | component: () => import('@/viewsPc/seat/confirm-order'), | ||
| 550 | meta: { title: '确认订单' }, | ||
| 551 | props: route => ({ | ||
| 552 | activityId:route.query.id, | ||
| 553 | }) | ||
| 554 | }, | ||
| 555 | { | ||
| 556 | path: 'add_watch_people', | ||
| 557 | name: 'add_watch_people', | ||
| 558 | component: () => import('@/viewsPc/seat/add-watch-people'), | ||
| 559 | meta: { title: '新增观影人' } | ||
| 560 | }, | ||
| 561 | { | ||
| 562 | path: 'people_manage', | ||
| 563 | name: 'people_manage', | ||
| 564 | component: () => import('@/viewsPc/seat/people-manage'), | ||
| 565 | meta: { title: '观影人管理' } | ||
| 566 | }, | ||
| 567 | ] | ||
| 503 | } | 568 | } |
| 504 | ] | 569 | ] |
| 505 | }, | 570 | }, | ... | ... |
| ... | @@ -108,6 +108,13 @@ const menus = ref([ | ... | @@ -108,6 +108,13 @@ const menus = ref([ |
| 108 | isActive: false | 108 | isActive: false |
| 109 | }, | 109 | }, |
| 110 | { | 110 | { |
| 111 | name: language.value==0?'票务预订':'Ticket Reservation', | ||
| 112 | routeName: 'seat_order', | ||
| 113 | picUrl1: '/img/nav_29.png', | ||
| 114 | picUrl2: '/img/nav_29_dwn.png', | ||
| 115 | isActive: false | ||
| 116 | }, | ||
| 117 | { | ||
| 111 | name: language.value==0?'系统消息':'System messages', | 118 | name: language.value==0?'系统消息':'System messages', |
| 112 | routeName: 'mySms', | 119 | routeName: 'mySms', |
| 113 | picUrl1: '/img/nav_30.png', | 120 | picUrl1: '/img/nav_30.png', | ... | ... |
| ... | @@ -24,7 +24,8 @@ | ... | @@ -24,7 +24,8 @@ |
| 24 | </el-form-item> | 24 | </el-form-item> |
| 25 | <el-form-item :label="language==0?'会员角色':'Role'"> | 25 | <el-form-item :label="language==0?'会员角色':'Role'"> |
| 26 | <el-select v-model="labelArr" multiple style="width: 100px;"> | 26 | <el-select v-model="labelArr" multiple style="width: 100px;"> |
| 27 | <el-option v-for="l in labels" :key="l.value" :value="l.value" :label="language==0?(l.label):(l.enlabel)"/> | 27 | <el-option v-if="group.type=='4'" v-for="l in labels" :key="l.value" :value="l.value" :label="language==0?(l.label):(l.enlabel)"/> |
| 28 | <el-option v-else v-for="l in labelsForType4" :key="l.value" :value="l.value" :label="language==0?(l.label):(l.enlabel)"/> | ||
| 28 | </el-select> | 29 | </el-select> |
| 29 | </el-form-item> | 30 | </el-form-item> |
| 30 | <el-form-item :label="language==0?'WDSF':'WDSF'"> | 31 | <el-form-item :label="language==0?'WDSF':'WDSF'"> |
| ... | @@ -73,6 +74,8 @@ import useUserStore from "@/store/modules/user"; | ... | @@ -73,6 +74,8 @@ import useUserStore from "@/store/modules/user"; |
| 73 | import {useStorage} from "@vueuse/core/index"; | 74 | import {useStorage} from "@vueuse/core/index"; |
| 74 | import AddWdsf from "@/viewsPc/match/components/addWdsf"; | 75 | import AddWdsf from "@/viewsPc/match/components/addWdsf"; |
| 75 | const language= useStorage('language',0) | 76 | const language= useStorage('language',0) |
| 77 | const group = useUserStore().group || {} | ||
| 78 | |||
| 76 | const tableData = ref([]) | 79 | const tableData = ref([]) |
| 77 | const labelArr = ref([]) | 80 | const labelArr = ref([]) |
| 78 | const labels = ref([ | 81 | const labels = ref([ |
| ... | @@ -84,6 +87,15 @@ const labels = ref([ | ... | @@ -84,6 +87,15 @@ const labels = ref([ |
| 84 | {value: '6', label: '官员', enlabel: 'Official'}, | 87 | {value: '6', label: '官员', enlabel: 'Official'}, |
| 85 | {value: '3', label: '其他', enlabel: 'Other'} | 88 | {value: '3', label: '其他', enlabel: 'Other'} |
| 86 | ]) | 89 | ]) |
| 90 | const labelsForType4 = ref([ | ||
| 91 | {value: '0', label: '运动员', enlabel: 'Sportsman'}, | ||
| 92 | {value: '1', label: '教练', enlabel: 'Coach'}, | ||
| 93 | {value: '2', label: '领队', enlabel: 'Head of team'}, | ||
| 94 | {value: '4', label: '管理', enlabel: 'Manager'}, | ||
| 95 | {value: '5', label: '翻译', enlabel: 'Interpreter'}, | ||
| 96 | {value: '6', label: '官员', enlabel: 'Official'}, | ||
| 97 | {value: '3', label: '其他', enlabel: 'Other'} | ||
| 98 | ]) | ||
| 87 | const certificates = ref([ | 99 | const certificates = ref([ |
| 88 | { | 100 | { |
| 89 | value: '0', | 101 | value: '0', |
| ... | @@ -102,7 +114,6 @@ const query = ref({ | ... | @@ -102,7 +114,6 @@ const query = ref({ |
| 102 | pageNum: 1, pageSize: 10 | 114 | pageNum: 1, pageSize: 10 |
| 103 | }) | 115 | }) |
| 104 | const total = ref(0) | 116 | const total = ref(0) |
| 105 | const group = useUserStore().group || {} | ||
| 106 | const props = defineProps({ | 117 | const props = defineProps({ |
| 107 | user: { | 118 | user: { |
| 108 | type: Object, | 119 | type: Object, |
| ... | @@ -193,6 +204,8 @@ function delperson(p) { | ... | @@ -193,6 +204,8 @@ function delperson(p) { |
| 193 | cancelButtonText: c, | 204 | cancelButtonText: c, |
| 194 | type: 'warning' | 205 | type: 'warning' |
| 195 | }).then(() => { | 206 | }).then(() => { |
| 207 | |||
| 208 | // This user has registered for the event and cannot be deleted. | ||
| 196 | match.delPerson(p.id).then(res => { | 209 | match.delPerson(p.id).then(res => { |
| 197 | ElMessage.success(msg) | 210 | ElMessage.success(msg) |
| 198 | getList(groupId.value) | 211 | getList(groupId.value) | ... | ... |
| ... | @@ -101,7 +101,8 @@ function popRemark(type){ | ... | @@ -101,7 +101,8 @@ function popRemark(type){ |
| 101 | building() | 101 | building() |
| 102 | return | 102 | return |
| 103 | } | 103 | } |
| 104 | if((form.value.isJdView == 0&&type=='1') || (form.value.isCarView == 0&&type=='2') || (form.value.isFoodView == 0&&type=='3') || type=='0' || (form.value.isMealView == 0&&type=='4') || (type=='5'&&form.value.isPhotoView == 0)){ | 104 | if((form.value.isJdView == 0&&type=='1') || (form.value.isCarView == 0&&type=='2') || (form.value.isFoodView == 0&&type=='3') || (form.value.isMealView == 0&&type=='4') || (type=='5'&&form.value.isPhotoView == 0)){ |
| 105 | //type == '0' | ||
| 105 | building() | 106 | building() |
| 106 | return | 107 | return |
| 107 | } | 108 | } |
| ... | @@ -116,8 +117,11 @@ function goBooking(n) { | ... | @@ -116,8 +117,11 @@ function goBooking(n) { |
| 116 | switch (n) { | 117 | switch (n) { |
| 117 | case 0: | 118 | case 0: |
| 118 | // 票务 | 119 | // 票务 |
| 119 | building() | 120 | router.push({ |
| 120 | router.push({path: `/booking/ticket/${props.matchId}`}) | 121 | path: `/seat/detail`, |
| 122 | params: {id: 1}, | ||
| 123 | query: {id: 1} | ||
| 124 | }) | ||
| 121 | break; | 125 | break; |
| 122 | case 1: | 126 | case 1: |
| 123 | //酒店 | 127 | //酒店 | ... | ... |
| ... | @@ -96,8 +96,8 @@ | ... | @@ -96,8 +96,8 @@ |
| 96 | 96 | ||
| 97 | <div class="content" v-if="activeName==8"> | 97 | <div class="content" v-if="activeName==8"> |
| 98 | <label>点击下载:</label> | 98 | <label>点击下载:</label> |
| 99 | <!-- <a target="_blank" class="text-primary" href="/file/COMPETITION_GUIDE_0511V1.pdf">--> | 99 | <a target="_blank" class="text-primary" href="/file/COMPETITION%20GUIDE%200520V1.pdf"> |
| 100 | <a @click="showBuilding" class="text-primary"> | 100 | <!-- <a @click="showBuilding" class="text-primary">--> |
| 101 | <el-icon style="position: relative;top: 2px"><download/></el-icon> | 101 | <el-icon style="position: relative;top: 2px"><download/></el-icon> |
| 102 | 2024 WDSF亚洲体育舞蹈节参赛指南 | 102 | 2024 WDSF亚洲体育舞蹈节参赛指南 |
| 103 | </a> | 103 | </a> |
| ... | @@ -200,8 +200,8 @@ | ... | @@ -200,8 +200,8 @@ |
| 200 | <div class="content" v-if="activeName==71"><el-empty description="no data"></el-empty></div> | 200 | <div class="content" v-if="activeName==71"><el-empty description="no data"></el-empty></div> |
| 201 | <div class="content" v-if="activeName==8"> | 201 | <div class="content" v-if="activeName==8"> |
| 202 | <label>Download:</label> | 202 | <label>Download:</label> |
| 203 | <!-- <a target="_blank" class="text-primary" href="/file/COMPETITION_GUIDE_0511V1.pdf">--> | 203 | <a target="_blank" class="text-primary" href="/file/COMPETITION%20GUIDE%200520V1.pdf"> |
| 204 | <a @click="showBuilding" class="text-primary"> | 204 | <!-- <a @click="showBuilding" class="text-primary">--> |
| 205 | <el-icon style="position: relative;top: 2px"><download/></el-icon> | 205 | <el-icon style="position: relative;top: 2px"><download/></el-icon> |
| 206 | 2024 WDSF ASIAN DANCESPORT FESTIVAL COMPETITION GUIDE | 206 | 2024 WDSF ASIAN DANCESPORT FESTIVAL COMPETITION GUIDE |
| 207 | </a> | 207 | </a> | ... | ... |
| ... | @@ -4,7 +4,7 @@ | ... | @@ -4,7 +4,7 @@ |
| 4 | <div class="box ph-30"> | 4 | <div class="box ph-30"> |
| 5 | <el-card v-if="user"> | 5 | <el-card v-if="user"> |
| 6 | <single-sign-step v-if="user.utype=='1'" activeStep="1" :language="language"/> | 6 | <single-sign-step v-if="user.utype=='1'" activeStep="1" :language="language"/> |
| 7 | <team-sign-step v-if="user.utype=='2'" activeStep="2" :language="language"/> | 7 | <team-sign-step v-if="user.utype=='2'" :activeStep="1" :language="language"/> |
| 8 | </el-card> | 8 | </el-card> |
| 9 | 9 | ||
| 10 | <el-card class="mt20"> | 10 | <el-card class="mt20"> |
| ... | @@ -73,10 +73,14 @@ | ... | @@ -73,10 +73,14 @@ |
| 73 | <el-col :lg="12"> | 73 | <el-col :lg="12"> |
| 74 | <el-card class="mt20" v-loading="loading"> | 74 | <el-card class="mt20" v-loading="loading"> |
| 75 | <template #header> | 75 | <template #header> |
| 76 | <div class="card-header"> | 76 | <div class="card-header" v-if="isNational"> |
| 77 | <img src="@/assets/sign/tag03.png"/> | 77 | <img src="@/assets/sign/tag03.png"/> |
| 78 | {{ language==0?'队医':'Team doctor' }} | 78 | {{ language==0?'队医':'Team doctor' }} |
| 79 | </div> | 79 | </div> |
| 80 | <div class="card-header" v-else> | ||
| 81 | <img src="@/assets/sign/gl.png"/> | ||
| 82 | 管理 | ||
| 83 | </div> | ||
| 80 | </template> | 84 | </template> |
| 81 | <div class="chooseForm"> | 85 | <div class="chooseForm"> |
| 82 | <el-checkbox-group v-model="form.doctor"> | 86 | <el-checkbox-group v-model="form.doctor"> |
| ... | @@ -198,7 +202,7 @@ import DialogAddCoach_En from './components/addCoach_en' | ... | @@ -198,7 +202,7 @@ import DialogAddCoach_En from './components/addCoach_en' |
| 198 | const {proxy} = getCurrentInstance() | 202 | const {proxy} = getCurrentInstance() |
| 199 | const router = useRouter() | 203 | const router = useRouter() |
| 200 | const route = useRoute() | 204 | const route = useRoute() |
| 201 | import {ElMessage} from 'element-plus' | 205 | import {ElMessage, ElMessageBox} from 'element-plus' |
| 202 | import {useRoute, useRouter} from 'vue-router' | 206 | import {useRoute, useRouter} from 'vue-router' |
| 203 | import useUserStore from "@/store/modules/user"; | 207 | import useUserStore from "@/store/modules/user"; |
| 204 | import {useStorage} from "@vueuse/core/index"; | 208 | import {useStorage} from "@vueuse/core/index"; |
| ... | @@ -242,7 +246,7 @@ onMounted(() => { | ... | @@ -242,7 +246,7 @@ onMounted(() => { |
| 242 | }) | 246 | }) |
| 243 | 247 | ||
| 244 | function getList() { | 248 | function getList() { |
| 245 | console.log(user.utype) | 249 | // console.log(user.utype) |
| 246 | if (user.utype == '1') { | 250 | if (user.utype == '1') { |
| 247 | geren() | 251 | geren() |
| 248 | } | 252 | } |
| ... | @@ -252,7 +256,7 @@ function getList() { | ... | @@ -252,7 +256,7 @@ function getList() { |
| 252 | } | 256 | } |
| 253 | 257 | ||
| 254 | function changecoachs(e) { | 258 | function changecoachs(e) { |
| 255 | console.log(e) | 259 | // console.log(e) |
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | // 获取报名时是否已选过 | 262 | // 获取报名时是否已选过 |
| ... | @@ -309,11 +313,31 @@ function geren() { | ... | @@ -309,11 +313,31 @@ function geren() { |
| 309 | } | 313 | } |
| 310 | 314 | ||
| 311 | function goNext() { | 315 | function goNext() { |
| 312 | console.log(form.value) | 316 | console.log(personAllList.value.teamDoctors,form.value) |
| 313 | // if ((form.value.coachs.length < 1) && (form.value.leader.length < 1)) { | 317 | // if ((form.value.coachs.length < 1) && (form.value.leader.length < 1)) { |
| 314 | // ElMessage.warning(language.value==0?'至少选一个教练或领队':'Coach/Team Leader, select at least one') | 318 | // ElMessage.warning(language.value==0?'至少选一个教练或领队':'Coach/Team Leader, select at least one') |
| 315 | // return | 319 | // return |
| 316 | // } | 320 | // } |
| 321 | if((personAllList.value.coaches.length>=0 && form.value.coachs?.toString().length == 0)&& | ||
| 322 | (personAllList.value.teamDoctors.length>=0 && form.value.doctor?.toString().length == 0)&& | ||
| 323 | (personAllList.value.translators.length>=0 && form.value.translator?.toString().length == 0)&& | ||
| 324 | (personAllList.value.others.length>=0 && form.value.other?.toString().length == 0)&& | ||
| 325 | (personAllList.value.officials.length>=0 && form.value.official?.toString().length == 0)&& | ||
| 326 | (personAllList.value.leaders.length>=0 && form.value.leader?.toString().length == 0) | ||
| 327 | ){ | ||
| 328 | ElMessageBox.confirm(language.value==0?'您已添加随行人员,但尚未选中,是否进行下一步?':'You have added a follower, but have not selected, do you want to continue?', { | ||
| 329 | confirmButtonText: language.value==0?'下一步':'Next', | ||
| 330 | cancelButtonText: language.value==0?'取消':'Cancel', | ||
| 331 | type: 'warning' | ||
| 332 | }).then(()=>{ | ||
| 333 | next() | ||
| 334 | }) | ||
| 335 | return | ||
| 336 | } | ||
| 337 | next() | ||
| 338 | } | ||
| 339 | |||
| 340 | function next() { | ||
| 317 | var obj = { | 341 | var obj = { |
| 318 | cptId: matchId, | 342 | cptId: matchId, |
| 319 | coachIds: form.value.coachs?.toString() || '', | 343 | coachIds: form.value.coachs?.toString() || '', |
| ... | @@ -332,7 +356,6 @@ function goNext() { | ... | @@ -332,7 +356,6 @@ function goNext() { |
| 332 | if (user.utype == '1') { | 356 | if (user.utype == '1') { |
| 333 | // 个人报名 | 357 | // 个人报名 |
| 334 | match.singleSignSavePerson(obj).then(res => { | 358 | match.singleSignSavePerson(obj).then(res => { |
| 335 | console.log(res) | ||
| 336 | router.push({ | 359 | router.push({ |
| 337 | name: 'chooseProject', | 360 | name: 'chooseProject', |
| 338 | query: { | 361 | query: { |
| ... | @@ -357,11 +380,8 @@ function goNext() { | ... | @@ -357,11 +380,8 @@ function goNext() { |
| 357 | }) | 380 | }) |
| 358 | } | 381 | } |
| 359 | 382 | ||
| 360 | console.log(form.value) | ||
| 361 | } | 383 | } |
| 362 | |||
| 363 | function goPrev() { | 384 | function goPrev() { |
| 364 | console.log(languageSource.value) | ||
| 365 | if(languageSource.value=='100'){ | 385 | if(languageSource.value=='100'){ |
| 366 | router.push({ | 386 | router.push({ |
| 367 | name: `teamSignCn`, | 387 | name: `teamSignCn`, | ... | ... |
| ... | @@ -38,7 +38,10 @@ | ... | @@ -38,7 +38,10 @@ |
| 38 | <div class="text-center mt20"> | 38 | <div class="text-center mt20"> |
| 39 | <el-button type="primary" plain @click="switchPerson">{{language==0?'切换':'Switch'}}</el-button> | 39 | <el-button type="primary" plain @click="switchPerson">{{language==0?'切换':'Switch'}}</el-button> |
| 40 | </div> | 40 | </div> |
| 41 | 41 | <div class="tip"> | |
| 42 | <span v-if="language==0">*如果您参加个人项目,或给其他组合/选手进行报名,请点击切换按钮重新选择人员</span> | ||
| 43 | <span v-else>*If you would like to register individual competitions for yourself or other couples/athletes, please click "Switch" button to re-select persons concerned.</span> | ||
| 44 | </div> | ||
| 42 | </div> | 45 | </div> |
| 43 | </div> | 46 | </div> |
| 44 | </el-col> | 47 | </el-col> |
| ... | @@ -46,7 +49,7 @@ | ... | @@ -46,7 +49,7 @@ |
| 46 | <el-col :lg="18"> | 49 | <el-col :lg="18"> |
| 47 | <div class="panel border"> | 50 | <div class="panel border"> |
| 48 | <div class="panel-header "> | 51 | <div class="panel-header "> |
| 49 | <h3 class="panel-title" v-if="language==0">可参与报名的项目</h3> | 52 | <h3 class="panel-title" v-if="language==0">可参与报名的项目 <span>已报项目在下方查看</span></h3> |
| 50 | <h3 class="panel-title" v-else>Search Events</h3> | 53 | <h3 class="panel-title" v-else>Search Events</h3> |
| 51 | <div class="fr"> | 54 | <div class="fr"> |
| 52 | <el-input size="small" v-model="projectQuery.name" :prefix-icon="Search" @change="getProjectList" | 55 | <el-input size="small" v-model="projectQuery.name" :prefix-icon="Search" @change="getProjectList" |
| ... | @@ -59,7 +62,7 @@ | ... | @@ -59,7 +62,7 @@ |
| 59 | <el-checkbox class="flexBetweenBox" v-for="c in projectList" :label="c.id" :key="c.id" :disabled="cantBao.flag"> | 62 | <el-checkbox class="flexBetweenBox" v-for="c in projectList" :label="c.id" :key="c.id" :disabled="cantBao.flag"> |
| 60 | <div class="flexBetween w100"> | 63 | <div class="flexBetween w100"> |
| 61 | <div class="l"> | 64 | <div class="l"> |
| 62 | {{ c.code }}:{{ c.name }} | 65 | {{ c.code }}:{{ c.name }} ({{c.danceType}}) |
| 63 | <div>{{ c.danceTypeDetailStr }}</div> | 66 | <div>{{ c.danceTypeDetailStr }}</div> |
| 64 | </div> | 67 | </div> |
| 65 | <div class="text-primary">{{ language == 0 ? '¥' : '€' }}{{ c.serviceFee }}</div> | 68 | <div class="text-primary">{{ language == 0 ? '¥' : '€' }}{{ c.serviceFee }}</div> |
| ... | @@ -793,4 +796,8 @@ function switchTabletype() { | ... | @@ -793,4 +796,8 @@ function switchTabletype() { |
| 793 | } | 796 | } |
| 794 | .mName{color: #000;font-size: 15px;display: inline-block;max-width: 6.5em;text-overflow: ellipsis; | 797 | .mName{color: #000;font-size: 15px;display: inline-block;max-width: 6.5em;text-overflow: ellipsis; |
| 795 | overflow: hidden;} | 798 | overflow: hidden;} |
| 799 | |||
| 800 | .panel h3.panel-title{ | ||
| 801 | span{ color: #999;font-size: 12px;} | ||
| 802 | } | ||
| 796 | </style> | 803 | </style> | ... | ... |
| ... | @@ -32,10 +32,10 @@ | ... | @@ -32,10 +32,10 @@ |
| 32 | 32 | ||
| 33 | {{c.representing}} | 33 | {{c.representing}} |
| 34 | {{c.ageGroup}} | 34 | {{c.ageGroup}} |
| 35 | {{c.division}} | 35 | {{c.division}}<span v-if="c.age"> -{{ c.age }}{{language==0 ? '岁' : 'years'}}</span> |
| 36 | <!-- @click="editPerson(c.id)"--> | 36 | <!-- @click="editPerson(c.id)"--> |
| 37 | <span v-if="c.disabled" class="text-danger po-right">需补全信息</span> | 37 | <span v-if="c.disabled" class="text-danger po-right">需补全信息</span> |
| 38 | <!-- -{{ c.age }}--> | 38 | |
| 39 | </div> | 39 | </div> |
| 40 | </el-option> | 40 | </el-option> |
| 41 | <!-- <template #tag>--> | 41 | <!-- <template #tag>--> |
| ... | @@ -78,7 +78,9 @@ | ... | @@ -78,7 +78,9 @@ |
| 78 | <el-col :lg="14"> | 78 | <el-col :lg="14"> |
| 79 | <div class="panel border"> | 79 | <div class="panel border"> |
| 80 | <div class="panel-header "> | 80 | <div class="panel-header "> |
| 81 | <h3 class="panel-title" v-if="language==0">可参与报名的项目</h3> | 81 | <h3 class="panel-title" v-if="language==0">可参与报名的项目 |
| 82 | <span>已报项目在下方查看</span> | ||
| 83 | </h3> | ||
| 82 | <h3 class="panel-title" v-else>Search Events</h3> | 84 | <h3 class="panel-title" v-else>Search Events</h3> |
| 83 | <div class="fr"> | 85 | <div class="fr"> |
| 84 | <el-input size="small" v-model="projectQuery.name" :prefix-icon="Search" | 86 | <el-input size="small" v-model="projectQuery.name" :prefix-icon="Search" |
| ... | @@ -91,7 +93,7 @@ | ... | @@ -91,7 +93,7 @@ |
| 91 | <el-checkbox class="flexBetweenBox" v-for="c in projectList" :value="c.id" :key="c.id"> | 93 | <el-checkbox class="flexBetweenBox" v-for="c in projectList" :value="c.id" :key="c.id"> |
| 92 | <div class="flexBetween w100"> | 94 | <div class="flexBetween w100"> |
| 93 | <div class="l"> | 95 | <div class="l"> |
| 94 | {{ c.code }}:{{ c.name }} | 96 | {{ c.code }}:{{ c.name }}({{c.danceType}}) |
| 95 | <div>{{ c.danceTypeDetailStr }}</div> | 97 | <div>{{ c.danceTypeDetailStr }}</div> |
| 96 | </div> | 98 | </div> |
| 97 | <div class="text-primary">{{ language == 0 ? '¥' : '€' }}{{ c.serviceFee }}</div> | 99 | <div class="text-primary">{{ language == 0 ? '¥' : '€' }}{{ c.serviceFee }}</div> |
| ... | @@ -868,4 +870,7 @@ watch(choosedchoosed, (newVal, oldVal) => { | ... | @@ -868,4 +870,7 @@ watch(choosedchoosed, (newVal, oldVal) => { |
| 868 | } | 870 | } |
| 869 | :deep(.el-select__tags-text){color: #000;font-size: 14px;} | 871 | :deep(.el-select__tags-text){color: #000;font-size: 14px;} |
| 870 | .po-right{position: absolute;right: 0;} | 872 | .po-right{position: absolute;right: 0;} |
| 873 | .panel h3.panel-title{ | ||
| 874 | span{ color: #999;font-size: 13px;} | ||
| 875 | } | ||
| 871 | </style> | 876 | </style> | ... | ... |
| ... | @@ -164,7 +164,7 @@ const data = reactive({ | ... | @@ -164,7 +164,7 @@ const data = reactive({ |
| 164 | {value: '0', label: '运动员', enlabel: 'Sportsman'}, | 164 | {value: '0', label: '运动员', enlabel: 'Sportsman'}, |
| 165 | {value: '1', label: '教练', enlabel: 'Coach'}, | 165 | {value: '1', label: '教练', enlabel: 'Coach'}, |
| 166 | {value: '2', label: '领队', enlabel: 'Head Of Team'}, | 166 | {value: '2', label: '领队', enlabel: 'Head Of Team'}, |
| 167 | {value: '4', label: '队医', enlabel: 'Team doctor'}, | 167 | {value: '4', label: '管理', enlabel: 'Team doctor'}, |
| 168 | {value: '5', label: '翻译', enlabel: 'Interpreter'}, | 168 | {value: '5', label: '翻译', enlabel: 'Interpreter'}, |
| 169 | {value: '6', label: '官员', enlabel: 'Official'}, | 169 | {value: '6', label: '官员', enlabel: 'Official'}, |
| 170 | {value: '3', label: '其他', enlabel: 'Other'} | 170 | {value: '3', label: '其他', enlabel: 'Other'} | ... | ... |
| ... | @@ -4,9 +4,9 @@ | ... | @@ -4,9 +4,9 @@ |
| 4 | <el-button type="primary" @click="addMember"> | 4 | <el-button type="primary" @click="addMember"> |
| 5 | {{ language == 0 ? '添加选手' : 'Add Player' }} | 5 | {{ language == 0 ? '添加选手' : 'Add Player' }} |
| 6 | </el-button> | 6 | </el-button> |
| 7 | <el-button type="primary" plain @click="importSportman" v-if="!isNational"> | 7 | <!-- <el-button type="primary" plain @click="importSportman" v-if="!isNational">--> |
| 8 | {{language == 0 ? '导入选手' : 'Import Player'}} | 8 | <!-- {{language == 0 ? '导入选手' : 'Import Player'}}--> |
| 9 | </el-button> | 9 | <!-- </el-button>--> |
| 10 | </div> | 10 | </div> |
| 11 | <div class="from-Card"> | 11 | <div class="from-Card"> |
| 12 | <el-form :inline="true" :model="query" class="mt20" label-width="60" size="small"> | 12 | <el-form :inline="true" :model="query" class="mt20" label-width="60" size="small"> | ... | ... |
| ... | @@ -25,7 +25,8 @@ | ... | @@ -25,7 +25,8 @@ |
| 25 | </el-col> | 25 | </el-col> |
| 26 | <el-col :lg="8"> | 26 | <el-col :lg="8"> |
| 27 | <div class="item"> | 27 | <div class="item"> |
| 28 | <label>{{ language == 0 ? '队医' : 'TEAM DOCTOR' }}</label> | 28 | <label v-if="group.type=='4'">{{ language == 0 ? '队医' : 'TEAM DOCTOR' }}</label> |
| 29 | <label v-else>{{ language == 0 ? '管理' : 'MANAGER' }}</label> | ||
| 29 | <span class="mr5" v-for="c in names.teamDoctorList"> | 30 | <span class="mr5" v-for="c in names.teamDoctorList"> |
| 30 | {{ c.realName }}, | 31 | {{ c.realName }}, |
| 31 | </span> | 32 | </span> | ... | ... |
| ... | @@ -43,7 +43,11 @@ | ... | @@ -43,7 +43,11 @@ |
| 43 | </div> | 43 | </div> |
| 44 | <div v-else> | 44 | <div v-else> |
| 45 | <div>{{ scope.row.birthPeriod.replace(',',language==0?' 至 ':' to ') }}</div> | 45 | <div>{{ scope.row.birthPeriod.replace(',',language==0?' 至 ':' to ') }}</div> |
| 46 | <div>{{scope.row.birthPeriodSecond?.replace(',',language==0?' 至 ':' to ')}}</div> | 46 | <div v-if="scope.row.birthPeriodSecond">{{scope.row.birthPeriodSecond?.replace(',',language==0?' 至 ':' to ')}}</div> |
| 47 | <div v-if="scope.row.birthPeriodThird">{{scope.row.birthPeriodThird?.replace(',',language==0?' 至 ':' to ')}}</div> | ||
| 48 | <div v-if="scope.row.birthPeriodFourth">{{scope.row.birthPeriodFourth?.replace(',',language==0?' 至 ':' to ')}}</div> | ||
| 49 | <div v-if="scope.row.birthPeriodFifth">{{scope.row.birthPeriodFifth?.replace(',',language==0?' 至 ':' to ')}}</div> | ||
| 50 | <div v-if="scope.row.birthPeriodSixth">{{scope.row.birthPeriodSixth?.replace(',',language==0?' 至 ':' to ')}}</div> | ||
| 47 | </div> | 51 | </div> |
| 48 | </template> | 52 | </template> |
| 49 | </el-table-column> | 53 | </el-table-column> | ... | ... |
| ... | @@ -27,7 +27,12 @@ | ... | @@ -27,7 +27,12 @@ |
| 27 | <span v-if="item==='0'" class="ml5">{{ language == 0 ? '运动员' : 'Athletes' }}</span> | 27 | <span v-if="item==='0'" class="ml5">{{ language == 0 ? '运动员' : 'Athletes' }}</span> |
| 28 | <span v-if="item==='1'" class="ml5">{{ language == 0 ? '教练' : 'Coach' }}</span> | 28 | <span v-if="item==='1'" class="ml5">{{ language == 0 ? '教练' : 'Coach' }}</span> |
| 29 | <span v-if="item==='2'" class="ml5">{{ language == 0 ? '领队' : 'Head of team' }}</span> | 29 | <span v-if="item==='2'" class="ml5">{{ language == 0 ? '领队' : 'Head of team' }}</span> |
| 30 | <span v-if="item==='4'" class="ml5">{{ language == 0 ? '队医' : 'Team Doctor' }}</span> | 30 | <span v-if="item==='4'&&group.type!='4'" class="ml5"> |
| 31 | {{ language == 0 ? '管理' : 'Manager' }} | ||
| 32 | </span> | ||
| 33 | <span v-if="item==='4'&&group.type=='4'" class="ml5"> | ||
| 34 | {{ language == 0 ? '队医' : 'Team Doctor' }} | ||
| 35 | </span> | ||
| 31 | <span v-if="item==='5'" class="ml5">{{ language == 0 ? '翻译' : 'Interpreter' }}</span> | 36 | <span v-if="item==='5'" class="ml5">{{ language == 0 ? '翻译' : 'Interpreter' }}</span> |
| 32 | <span v-if="item==='6'" class="ml5">{{ language == 0 ? '官员' : 'Official' }}</span> | 37 | <span v-if="item==='6'" class="ml5">{{ language == 0 ? '官员' : 'Official' }}</span> |
| 33 | <span v-if="item==='3'" class="ml5">{{ language == 0 ? '其他' : 'Other' }}</span> | 38 | <span v-if="item==='3'" class="ml5">{{ language == 0 ? '其他' : 'Other' }}</span> |
| ... | @@ -61,7 +66,8 @@ | ... | @@ -61,7 +66,8 @@ |
| 61 | <script setup> | 66 | <script setup> |
| 62 | import {ref} from "vue"; | 67 | import {ref} from "vue"; |
| 63 | import {useStorage} from "@vueuse/core/index"; | 68 | import {useStorage} from "@vueuse/core/index"; |
| 64 | 69 | import useUserStore from "@/store/modules/user"; | |
| 70 | const group = useUserStore().group || {} | ||
| 65 | const language = useStorage('language', 0) | 71 | const language = useStorage('language', 0) |
| 66 | const emit = defineEmits(['edit', 'delete']) | 72 | const emit = defineEmits(['edit', 'delete']) |
| 67 | let title = '' | 73 | let title = '' | ... | ... |
| ... | @@ -4,22 +4,22 @@ | ... | @@ -4,22 +4,22 @@ |
| 4 | </div> | 4 | </div> |
| 5 | <el-table :data="list" :sum-text="sumText" border style="width: 100%" v-loading="loading"> | 5 | <el-table :data="list" :sum-text="sumText" border style="width: 100%" v-loading="loading"> |
| 6 | <el-table-column :label="language==0?'序号':'Index'" type="index" width="70" align="center"/> | 6 | <el-table-column :label="language==0?'序号':'Index'" type="index" width="70" align="center"/> |
| 7 | <el-table-column v-if="!isNational" :label="language==0?'姓名':'Real Name'" prop="personInfo.realName" min-width="100"/> | 7 | <el-table-column v-if="!isNational" :label="language==0?'姓名':'Real Name'" prop="personInfo.realName" align="center" min-width="100"/> |
| 8 | <el-table-column v-if="isNational" :label="language==0?'姓氏':'Surname'" prop="personInfo.xing" min-width="100"/> | 8 | <el-table-column v-if="isNational" :label="language==0?'姓氏':'Surname'" prop="personInfo.xing" min-width="100"/> |
| 9 | <el-table-column v-if="isNational" :label="language==0?'名':'Name'" prop="personInfo.ming" min-width="100"/> | 9 | <el-table-column v-if="isNational" :label="language==0?'名':'Name'" prop="personInfo.ming" min-width="100"/> |
| 10 | <el-table-column :label="language==0?'所属国家/地区':'Country'" min-width="120"> | 10 | <el-table-column :label="language==0?'所属国家/地区':'Country'" min-width="120" header-align="center" align="center"> |
| 11 | <template #default="scope"> | 11 | <template #default="scope"> |
| 12 | <span v-if="scope.row.personInfo.countryName">{{scope.row.personInfo.countryName}}</span> | 12 | <span v-if="scope.row.personInfo.countryName">{{scope.row.personInfo.countryName}}</span> |
| 13 | <span v-if="scope.row.personInfo.representing">{{scope.row.personInfo.representing}}</span> | 13 | <span v-if="scope.row.personInfo.representing">{{scope.row.personInfo.representing}}</span> |
| 14 | </template> | 14 | </template> |
| 15 | </el-table-column> | 15 | </el-table-column> |
| 16 | <el-table-column :label="language==0?'性别':'Gender'" prop="personInfo.sexStr"/> | 16 | <el-table-column :label="language==0?'性别':'Gender'" prop="personInfo.sexStr" align="center"/> |
| 17 | <el-table-column v-if="!isNational" :label="language==0?'证件类型':'ID Type'" :width="language==0?'':'140'" prop="personInfo.idcTypeStr"/> | 17 | <el-table-column v-if="!isNational" :label="language==0?'证件类型':'ID Type'" align="center" :width="language==0?'':'140'" prop="personInfo.idcTypeStr" header-align="center"/> |
| 18 | <el-table-column v-if="!isNational" :label="language==0?'证件号码':'ID NO.'" prop="personInfo.idcCode" width="200"/> | 18 | <el-table-column v-if="!isNational" :label="language==0?'证件号码':'ID NO.'" prop="personInfo.idcCode" width="200" header-align="center"/> |
| 19 | <el-table-column v-if="isNational" :label="language==0?'WDSF 会员号':'WDSF MIN'" prop="personInfo.wdsfMin" width="200"/> | 19 | <el-table-column v-if="isNational" :label="language==0?'WDSF 会员号':'WDSF MIN'" prop="personInfo.wdsfMin" width="200" header-align="center"/> |
| 20 | <el-table-column v-if="!isNational" :label="language==0?'出生日期':'Date of Birth'" prop="personInfo.birth" width="130"/> | 20 | <el-table-column v-if="!isNational" :label="language==0?'出生日期':'Date of Birth'" align="center" prop="personInfo.birth" width="130" header-align="center"/> |
| 21 | <el-table-column v-if="isNational" :label="language==0?'年龄组':'Age group'" prop="personInfo.ageGroup" width="110"/> | 21 | <el-table-column v-if="isNational" :label="language==0?'年龄组':'Age group'" prop="personInfo.ageGroup" width="110" header-align="center"/> |
| 22 | <el-table-column v-if="isNational" :label="language==0?'舞种':'Division'" prop="personInfo.division" width="110"/> | 22 | <el-table-column v-if="isNational" :label="language==0?'舞种':'Division'" prop="personInfo.division" width="110" header-align="center"/> |
| 23 | <!-- <el-table-column :label="language==0?'会员角色':'Role'" width="150">--> | 23 | <!-- <el-table-column :label="language==0?'会员角色':'Role'" width="150">--> |
| 24 | <!-- <template #default="scope">--> | 24 | <!-- <template #default="scope">--> |
| 25 | <!-- <div class="esp">--> | 25 | <!-- <div class="esp">--> |
| ... | @@ -36,7 +36,7 @@ | ... | @@ -36,7 +36,7 @@ |
| 36 | <!-- </template>--> | 36 | <!-- </template>--> |
| 37 | <!-- </el-table-column>--> | 37 | <!-- </el-table-column>--> |
| 38 | <!-- <el-table-column :label="language==0?'详细地址':'Detailed Address'" prop="personInfo.address" min-width="140"/>--> | 38 | <!-- <el-table-column :label="language==0?'详细地址':'Detailed Address'" prop="personInfo.address" min-width="140"/>--> |
| 39 | <el-table-column :label="language==0?'报项':'REGISTERED COMPETITION'" min-width="300" :fixed="hasAction?false:'right'"> | 39 | <el-table-column :label="language==0?'报项':'REGISTERED COMPETITION'" min-width="300" header-align="center" :fixed="hasAction?false:'right'"> |
| 40 | <template #default="props"> | 40 | <template #default="props"> |
| 41 | <ol> | 41 | <ol> |
| 42 | <li v-for="s in props.row.signInfo"> | 42 | <li v-for="s in props.row.signInfo"> |
| ... | @@ -51,7 +51,7 @@ | ... | @@ -51,7 +51,7 @@ |
| 51 | </ol> | 51 | </ol> |
| 52 | </template> | 52 | </template> |
| 53 | </el-table-column> | 53 | </el-table-column> |
| 54 | <el-table-column :fixed="hasAction?false:'right'" min-width="100" :label="language==0?'保险费':'Premium'" prop="insuranceFee"> | 54 | <el-table-column :fixed="hasAction?false:'right'" min-width="100" align="center" :label="language==0?'保险费':'Premium'" prop="insuranceFee"> |
| 55 | <template #default="scope"> | 55 | <template #default="scope"> |
| 56 | <span class="text-primary">{{ language==0?'¥':'€' }}{{ scope.row.insuranceFee }}</span> | 56 | <span class="text-primary">{{ language==0?'¥':'€' }}{{ scope.row.insuranceFee }}</span> |
| 57 | </template> | 57 | </template> |
| ... | @@ -61,11 +61,11 @@ | ... | @@ -61,11 +61,11 @@ |
| 61 | <template #default="scope"> | 61 | <template #default="scope"> |
| 62 | <el-link v-if="scope.row.signInfo[0].extraPersonInfoMapList[index]?.type=='2'" | 62 | <el-link v-if="scope.row.signInfo[0].extraPersonInfoMapList[index]?.type=='2'" |
| 63 | target="_blank" | 63 | target="_blank" |
| 64 | :href="fillImgUrl(scope.row.signInfo[0].extraPersonInfoMapList[index].value.url)"> | 64 | :href="fillImgUrl(scope.row.signInfo[0].extraPersonInfoMapList[index]?.value?.url)"> |
| 65 | <span class="text-primary">{{ scope.row.signInfo[0].extraPersonInfoMapList[index].value.name }}</span> | 65 | <span class="text-primary">{{ scope.row.signInfo[0].extraPersonInfoMapList[index]?.value?.name }}</span> |
| 66 | </el-link> | 66 | </el-link> |
| 67 | <img v-else-if="scope.row.signInfo[0].extraPersonInfoMapList[index]?.type=='3'" style="width: 50px;" | 67 | <img v-else-if="scope.row.signInfo[0].extraPersonInfoMapList[index]?.type=='3'" style="width: 50px;" |
| 68 | :src="fillImgUrl(scope.row.signInfo[0].extraPersonInfoMapList[index].value.url||scope.row.signInfo[0].extraPersonInfoMapList[index].value)"> | 68 | :src="fillImgUrl(scope.row.signInfo[0].extraPersonInfoMapList[index]?.value?.url||scope.row.signInfo[0]?.extraPersonInfoMapList[index]?.value)"> |
| 69 | <span v-else>{{ scope.row.signInfo[0].extraPersonInfoMapList[index]?.value }}</span> | 69 | <span v-else>{{ scope.row.signInfo[0].extraPersonInfoMapList[index]?.value }}</span> |
| 70 | </template> | 70 | </template> |
| 71 | </el-table-column> | 71 | </el-table-column> | ... | ... |
| ... | @@ -2,22 +2,35 @@ | ... | @@ -2,22 +2,35 @@ |
| 2 | <div class="mt20"></div> | 2 | <div class="mt20"></div> |
| 3 | <el-table :data="list" border style="width: 100%"> | 3 | <el-table :data="list" border style="width: 100%"> |
| 4 | <el-table-column :label="language==0?'序号':'Index'" type="index" width="70" align="center"/> | 4 | <el-table-column :label="language==0?'序号':'Index'" type="index" width="70" align="center"/> |
| 5 | <el-table-column :label="language==0?'组别代码':'EVENT code'" width="120px" prop="project.code"/> | 5 | <el-table-column :label="language==0?'组别代码':'EVENT code'" width="120px" align="center" prop="project.code"/> |
| 6 | <el-table-column :label="language==0?'组别':'EVENT'" prop="project.name"/> | 6 | <el-table-column :label="language==0?'组别':'EVENT'" min-width="150px" header-align="center" prop="project.name"> |
| 7 | <el-table-column :label="language==0?'舞种':'DISCIPLINE'" width="120px" prop="project.danceType"/> | ||
| 8 | <el-table-column :label="language==0?'参赛说明':'Participation Instructions'" min-width="160px"> | ||
| 9 | <template #default="scope"> | 7 | <template #default="scope"> |
| 10 | <div v-html="scope.row.project.remarks"></div> | 8 | <el-tooltip effect="dark" :content="scope.row.project.name"> |
| 9 | <div class="esp">{{scope.row.project.name}}</div> | ||
| 10 | </el-tooltip> | ||
| 11 | </template> | 11 | </template> |
| 12 | </el-table-column> | 12 | </el-table-column> |
| 13 | <el-table-column :label="language==0?'参赛运动员':'PARTICIPATING ATHLETES'" min-width="140px"> | 13 | <el-table-column :label="language==0?'舞种':'DISCIPLINE'" align="center" width="120px" prop="project.danceType"/> |
| 14 | <el-table-column :label="language==0?'参赛说明':'Participation Instructions'" header-align="center" min-width="160px"> | ||
| 14 | <template #default="scope"> | 15 | <template #default="scope"> |
| 15 | <div> | 16 | <el-tooltip effect="dark" :content="scope.row.project.remarks"> |
| 17 | <div class="esp" v-html="scope.row.project.remarks"></div> | ||
| 18 | </el-tooltip> | ||
| 19 | </template> | ||
| 20 | </el-table-column> | ||
| 21 | <el-table-column :label="language==0?'参赛运动员':'PARTICIPATING ATHLETES'" header-align="center" min-width="140px"> | ||
| 22 | <template #default="scope"> | ||
| 23 | <el-tooltip effect="dark"> | ||
| 24 | <template #content> | ||
| 25 | <span v-for="s in scope.row.athletes">{{ s.name }},</span> | ||
| 26 | </template> | ||
| 27 | <div class="esp"> | ||
| 16 | <span v-for="s in scope.row.athletes">{{ s.name }},</span> | 28 | <span v-for="s in scope.row.athletes">{{ s.name }},</span> |
| 17 | </div> | 29 | </div> |
| 30 | </el-tooltip> | ||
| 18 | </template> | 31 | </template> |
| 19 | </el-table-column> | 32 | </el-table-column> |
| 20 | <el-table-column :label="language==0?'参赛服务费':'REGISTRATION FEE'" width="150px" prop=""> | 33 | <el-table-column :label="language==0?'参赛服务费':'REGISTRATION FEE'" align="center" width="150px" prop=""> |
| 21 | <template #default="scope"> | 34 | <template #default="scope"> |
| 22 | <div class="text-primary"> | 35 | <div class="text-primary"> |
| 23 | {{ language==0?'¥':'€' }}{{ scope.row.project.serviceFee }} | 36 | {{ language==0?'¥':'€' }}{{ scope.row.project.serviceFee }} | ... | ... |
| ... | @@ -116,8 +116,10 @@ | ... | @@ -116,8 +116,10 @@ |
| 116 | </el-col> | 116 | </el-col> |
| 117 | <el-col :lg="12" v-if="Number(form.totalFee)>0"> | 117 | <el-col :lg="12" v-if="Number(form.totalFee)>0"> |
| 118 | <div class="priceb" v-if="form.payStatus=='0'">{{ language==0?'待支付金额':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> | 118 | <div class="priceb" v-if="form.payStatus=='0'">{{ language==0?'待支付金额':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> |
| 119 | <div class="priceb" v-if="form.payStatus=='1'">{{ language==0?'已支付金额':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> | 119 | <div class="priceb" v-else-if="form.payStatus=='1'">{{ language==0?'线下支付待核销':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> |
| 120 | <div class="priceb" v-if="form.payStatus=='5'">{{ language==0?'已退款':'Refunded' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> | 120 | <div class="priceb" v-else-if="form.payStatus=='3'">{{ language==0?'已支付金额':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> |
| 121 | <div class="priceb" v-else-if="form.payStatus=='5'">{{ language==0?'已退款':'Refunded' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> | ||
| 122 | <div class="priceb" v-else>{{ language==0?'费用总计':'Amount Due' }}:<span class="price">{{ language==0?'¥':'€' }}{{ Number(totalFee).toFixed(2) }}</span></div> | ||
| 121 | </el-col> | 123 | </el-col> |
| 122 | </el-row> | 124 | </el-row> |
| 123 | </el-card> | 125 | </el-card> | ... | ... |
| ... | @@ -23,7 +23,7 @@ | ... | @@ -23,7 +23,7 @@ |
| 23 | </el-form-item> | 23 | </el-form-item> |
| 24 | </el-col> | 24 | </el-col> |
| 25 | <el-col :lg="10"> | 25 | <el-col :lg="10"> |
| 26 | <el-form-item :label="language==0?'代表国家/地区':'Representing'"> | 26 | <el-form-item :label="language==0?'代表国家/地区':'Representing'" required> |
| 27 | <el-select filterable v-model="form.countryId" @change="changeCountryId" | 27 | <el-select filterable v-model="form.countryId" @change="changeCountryId" |
| 28 | :disabled="form.type!='4'"> | 28 | :disabled="form.type!='4'"> |
| 29 | <!-- <el-option v-for="item in countryList" :key="item.id" :label="language==0?item.name:item.enName" :value="item.id"/>--> | 29 | <!-- <el-option v-for="item in countryList" :key="item.id" :label="language==0?item.name:item.enName" :value="item.id"/>--> | ... | ... |
| ... | @@ -26,7 +26,7 @@ | ... | @@ -26,7 +26,7 @@ |
| 26 | <el-form-item :label="language==0?'参赛队名称':'Name of participating team'" required prop="abreviations"> | 26 | <el-form-item :label="language==0?'参赛队名称':'Name of participating team'" required prop="abreviations"> |
| 27 | <el-input type="text" v-model="form.abreviations" :placeholder="language==0?'请输入内容':''"/> | 27 | <el-input type="text" v-model="form.abreviations" :placeholder="language==0?'请输入内容':''"/> |
| 28 | </el-form-item> | 28 | </el-form-item> |
| 29 | <el-form-item :label="language==0?'团体名称':'Team Name'" prop="name"> | 29 | <el-form-item :label="language==0?'团体名称':'Team Name'" prop="name" required> |
| 30 | <el-input v-model="form.name" :placeholder="language==0?'请输入团体名称':''" /> | 30 | <el-input v-model="form.name" :placeholder="language==0?'请输入团体名称':''" /> |
| 31 | </el-form-item> | 31 | </el-form-item> |
| 32 | <el-form-item :label="language==0?'所属国家/地区':'Country'" required> | 32 | <el-form-item :label="language==0?'所属国家/地区':'Country'" required> |
| ... | @@ -43,12 +43,12 @@ | ... | @@ -43,12 +43,12 @@ |
| 43 | <el-form-item :label="language==0?'邮箱':'Email'" required prop="contactEmail"> | 43 | <el-form-item :label="language==0?'邮箱':'Email'" required prop="contactEmail"> |
| 44 | <el-input v-model="form.contactEmail" type="email" :placeholder="language==0?'请输入内容':''"/> | 44 | <el-input v-model="form.contactEmail" type="email" :placeholder="language==0?'请输入内容':''"/> |
| 45 | </el-form-item> | 45 | </el-form-item> |
| 46 | <!-- <el-form-item :label="language==0?'专业/业余':'Professional/Amateur'" required prop="majorFlag">--> | 46 | <el-form-item :label="language==0?'专业/业余':'Professional/Amateur'" required prop="majorFlag"> |
| 47 | <!-- <el-select v-model="form.majorFlag">--> | 47 | <el-select v-model="form.majorFlag"> |
| 48 | <!-- <el-option :label="language==0?'专业':'Professional'" value="1" />--> | 48 | <el-option :label="language==0?'专业':'Professional'" value="1" /> |
| 49 | <!-- <el-option :label="language==0?'业余':'Amateur'" value="0" />--> | 49 | <el-option :label="language==0?'业余':'Amateur'" value="0" /> |
| 50 | <!-- </el-select>--> | 50 | </el-select> |
| 51 | <!-- </el-form-item>--> | 51 | </el-form-item> |
| 52 | <el-form-item :label="language==0?'团体类型':'Group type'" prop="type"> | 52 | <el-form-item :label="language==0?'团体类型':'Group type'" prop="type"> |
| 53 | <el-select :disabled="form.type=='4'" v-model="form.type" :placeholder="typeOptions[language].selectPlaceholder" style="width: 100%;"> | 53 | <el-select :disabled="form.type=='4'" v-model="form.type" :placeholder="typeOptions[language].selectPlaceholder" style="width: 100%;"> |
| 54 | <el-option v-for="(o,index) in typeOptions[language].options" :label="o.text" | 54 | <el-option v-for="(o,index) in typeOptions[language].options" :label="o.text" | ... | ... |
src/viewsPc/seat/add-watch-people.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { ElMessage } from "element-plus"; | ||
| 3 | import { addViewPeople } from "./api/index.js"; | ||
| 4 | import { languageFormat } from "./utils/language.js"; | ||
| 5 | import { useStorage } from "@vueuse/core/index"; | ||
| 6 | const language = useStorage("language", 0); | ||
| 7 | |||
| 8 | const router = useRouter(); | ||
| 9 | |||
| 10 | const people = reactive({ | ||
| 11 | form: { | ||
| 12 | name: "", | ||
| 13 | idCard: "", | ||
| 14 | }, | ||
| 15 | type: language.value == 0 ? "身份证" : "Identity Card", | ||
| 16 | onConfirm() { | ||
| 17 | if (!people.form.name) | ||
| 18 | return ElMessage({ | ||
| 19 | type: "warning", | ||
| 20 | message: languageFormat(language.value, "请输入姓名", "Name"), | ||
| 21 | }); | ||
| 22 | if (!people.form.idCard) | ||
| 23 | return ElMessage({ | ||
| 24 | type: "warning", | ||
| 25 | message: languageFormat(language.value, "请输入证件号", "ID Numbe"), | ||
| 26 | }); | ||
| 27 | |||
| 28 | // 使用正则验证身份证号码格式 | ||
| 29 | const idCardRegex = | ||
| 30 | /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$/; | ||
| 31 | if (!idCardRegex.test(people.form.idCard) && language.value == 0) | ||
| 32 | return ElMessage({ type: "warning", message: "身份证号格式不正确" }); | ||
| 33 | |||
| 34 | addViewPeople(people.form).then((res) => { | ||
| 35 | ElMessage({ | ||
| 36 | type: "success", | ||
| 37 | message: languageFormat(language.value, "操作成功", "Operate successfully"), | ||
| 38 | }); | ||
| 39 | router.go(-2); | ||
| 40 | }); | ||
| 41 | }, | ||
| 42 | }); | ||
| 43 | </script> | ||
| 44 | |||
| 45 | <template> | ||
| 46 | <div class="container"> | ||
| 47 | <div class="title"> | ||
| 48 | {{ languageFormat(language, "新增观影人", "Companion") }} | ||
| 49 | </div> | ||
| 50 | <div class="content"> | ||
| 51 | <div class="form-item"> | ||
| 52 | <div> | ||
| 53 | <div class="label"> | ||
| 54 | {{ languageFormat(language, "姓名", "Full Name") }} | ||
| 55 | </div> | ||
| 56 | <el-input | ||
| 57 | v-model="people.form.name" | ||
| 58 | style="width: 570px" | ||
| 59 | :placeholder="language == 0 ? '请输入姓名' : 'Nama'" | ||
| 60 | /> | ||
| 61 | </div> | ||
| 62 | <div> | ||
| 63 | <div class="label"> | ||
| 64 | {{ languageFormat(language, "证件类型", "Type of Document") }} | ||
| 65 | </div> | ||
| 66 | <el-input | ||
| 67 | v-model="people.type" | ||
| 68 | style="width: 570px" | ||
| 69 | placeholder="Please input" | ||
| 70 | readonly | ||
| 71 | /> | ||
| 72 | </div> | ||
| 73 | </div> | ||
| 74 | <div class="form-item"> | ||
| 75 | <div> | ||
| 76 | <div class="label"> | ||
| 77 | {{ languageFormat(language, "身份证号", "Identity Card") }} | ||
| 78 | </div> | ||
| 79 | <el-input | ||
| 80 | v-model="people.form.idCard" | ||
| 81 | style="width: 570px" | ||
| 82 | :placeholder="language == 0 ? '请输入身份证号' : 'ID Numbe'" | ||
| 83 | /> | ||
| 84 | </div> | ||
| 85 | </div> | ||
| 86 | </div> | ||
| 87 | |||
| 88 | <div class="footer"> | ||
| 89 | <div class="can_pay"> | ||
| 90 | {{ languageFormat(language, "取消", "Cancel") }} | ||
| 91 | </div> | ||
| 92 | <div class="pay" @click="people.onConfirm()"> | ||
| 93 | {{ languageFormat(language, "确认", "Confirm") }} | ||
| 94 | </div> | ||
| 95 | </div> | ||
| 96 | </div> | ||
| 97 | </template> | ||
| 98 | |||
| 99 | <style scoped lang="scss"> | ||
| 100 | div { | ||
| 101 | box-sizing: border-box; | ||
| 102 | } | ||
| 103 | .container { | ||
| 104 | padding: 20px 0; | ||
| 105 | width: 1200px; | ||
| 106 | margin: 0 auto; | ||
| 107 | |||
| 108 | .title { | ||
| 109 | padding: 11px; | ||
| 110 | text-align: center; | ||
| 111 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 112 | font-size: 18px; | ||
| 113 | color: #ffffff; | ||
| 114 | } | ||
| 115 | |||
| 116 | .content { | ||
| 117 | padding: 46px 20px 24px; | ||
| 118 | background-color: #fff; | ||
| 119 | :deep(.el-input) { | ||
| 120 | height: 48px; | ||
| 121 | border-radius: 24px !important; | ||
| 122 | } | ||
| 123 | .form-item { | ||
| 124 | display: flex; | ||
| 125 | gap: 20px; | ||
| 126 | margin-bottom: 36px; | ||
| 127 | &:last-child { | ||
| 128 | margin: 0; | ||
| 129 | } | ||
| 130 | .label { | ||
| 131 | font-size: 18px; | ||
| 132 | color: #333333; | ||
| 133 | margin-bottom: 16px; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | .footer { | ||
| 138 | display: flex; | ||
| 139 | justify-content: center; | ||
| 140 | align-items: center; | ||
| 141 | gap: 20px; | ||
| 142 | height: 70px; | ||
| 143 | background-color: #fff; | ||
| 144 | margin-top: 12px; | ||
| 145 | .pay { | ||
| 146 | width: 200px; | ||
| 147 | height: 40px; | ||
| 148 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 149 | border-radius: 20px; | ||
| 150 | font-weight: 500; | ||
| 151 | font-size: 16px; | ||
| 152 | color: #ffffff; | ||
| 153 | line-height: 40px; | ||
| 154 | text-align: center; | ||
| 155 | cursor: pointer; | ||
| 156 | } | ||
| 157 | .can_pay { | ||
| 158 | width: 200px; | ||
| 159 | height: 40px; | ||
| 160 | background: #f6f6f6; | ||
| 161 | border-radius: 20px; | ||
| 162 | font-weight: 500; | ||
| 163 | font-size: 16px; | ||
| 164 | color: #999; | ||
| 165 | line-height: 40px; | ||
| 166 | text-align: center; | ||
| 167 | box-sizing: border-box; | ||
| 168 | cursor: pointer; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | </style> |
src/viewsPc/seat/api/index.js
0 → 100644
| 1 | import request from "../utils/request"; | ||
| 2 | |||
| 3 | export const loginFree = (data) => request("POST", "/login/loginFree", data); | ||
| 4 | /** 活动详情 */ | ||
| 5 | export const activityDetail = (data) => | ||
| 6 | request("GET", `/api/activity/detail/${data.actId}`, data); | ||
| 7 | /** 场次详情 */ | ||
| 8 | export const sessionDetail = (data) => | ||
| 9 | request("GET", `/api/activity/sessionDetail/${data.actId}`, data); | ||
| 10 | /** 获取场馆信息 */ | ||
| 11 | export const getSitePlaceInfo = (data) => | ||
| 12 | request("GET", `/api/activity/getSitePlaceInfo`, data); | ||
| 13 | /** 获取票档信息 */ | ||
| 14 | export const getPriceLevelInfo = (data) => | ||
| 15 | request("GET", `/api/activity/getPriceLevelInfo`, data); | ||
| 16 | /** 获取座位信息 */ | ||
| 17 | export const getSiteConfig = (data) => | ||
| 18 | request("GET", `/api/activity/getSiteConfig`, data); | ||
| 19 | /** 确认订单 */ | ||
| 20 | export const confirmOrder = (data) => | ||
| 21 | request("POST", `/api/order/confirmOrder`, data); | ||
| 22 | /** 订单支付 */ | ||
| 23 | export const payOrder = (data) => | ||
| 24 | request("POST", `/api/order/payment`, data); | ||
| 25 | /** 观众列表 */ | ||
| 26 | export const viewPeopleList = (data) => | ||
| 27 | request("GET", `/api/customer/list`, data); | ||
| 28 | /** 删除观众 */ | ||
| 29 | export const deleteViewPeople = (data) => | ||
| 30 | request("POST", `/api/customer/delete/${data.id}`, data); | ||
| 31 | /** 新增观众 */ | ||
| 32 | export const addViewPeople = (data) => | ||
| 33 | request("POST", `/api/customer/add`, data); | ||
| 34 | /** 订单列表 */ | ||
| 35 | export const getOrderList = (data) => | ||
| 36 | request("GET", `/api/order/list`, data); | ||
| 37 | /** 立即支付 */ | ||
| 38 | export const immediatePay = (data) => | ||
| 39 | request("POST", `/api/order/immediatePay`, data); | ||
| 40 | /** 取消支付 */ | ||
| 41 | export const cancelPay = (data) => | ||
| 42 | request("POST", `/api/order/cancelPay/${data.orderSn}`, data); | ||
| 43 | /** 退单 */ | ||
| 44 | export const cancelOrder = (data) => | ||
| 45 | request("POST", `/api/order/cancelOrder/${data.orderSn}`, data); | ||
| 46 | /** 订单详情 */ | ||
| 47 | export const getOrderDetail = (data) => | ||
| 48 | request("GET", `/api/order/detail/${data.orderSn}`, data); | ||
| 49 | /** 检查是否支付成功 */ | ||
| 50 | export const checkPaySuccess = (data) => | ||
| 51 | request("POST", `/api/order/checkOrderIsPay/${data.orderSn}`, data); |
src/viewsPc/seat/components/qrCodeDialog.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | const props = defineProps({ | ||
| 3 | showCodeDialog: { | ||
| 4 | type: Boolean, | ||
| 5 | default: false, | ||
| 6 | }, | ||
| 7 | qrCode: { | ||
| 8 | type: String, | ||
| 9 | default: "", | ||
| 10 | }, | ||
| 11 | }); | ||
| 12 | |||
| 13 | const emit = defineEmits(["closeDialog"]); | ||
| 14 | const handleCloce = () => { | ||
| 15 | emit("closeDialog", false); | ||
| 16 | }; | ||
| 17 | </script> | ||
| 18 | |||
| 19 | <template> | ||
| 20 | <div> | ||
| 21 | <el-dialog | ||
| 22 | v-model="props.showCodeDialog" | ||
| 23 | title="支付" | ||
| 24 | width="300" | ||
| 25 | :before-close="handleCloce()" | ||
| 26 | > | ||
| 27 | <div> | ||
| 28 | <img class="qrcode" :src="props.qrCode" /> | ||
| 29 | </div> | ||
| 30 | </el-dialog> | ||
| 31 | </div> | ||
| 32 | </template> | ||
| 33 | |||
| 34 | <style scoped lang="scss"> | ||
| 35 | .qrcode { | ||
| 36 | width: 150px; | ||
| 37 | height: 150px; | ||
| 38 | background-color: #8623fc; | ||
| 39 | margin: 0 auto; | ||
| 40 | } | ||
| 41 | </style> |
src/viewsPc/seat/confirm-order.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { confirmOrder } from "./api/index.js"; | ||
| 3 | import { ElMessage } from "element-plus"; | ||
| 4 | import { payOrder, viewPeopleList, checkPaySuccess } from "./api/index.js"; | ||
| 5 | import qrCodeDialog from "./components/qrCodeDialog.vue"; | ||
| 6 | import qrcode from "qrcode"; | ||
| 7 | import { languageFormat } from "./utils/language.js"; | ||
| 8 | import { useStorage } from "@vueuse/core/index"; | ||
| 9 | const language = useStorage("language", 0); | ||
| 10 | |||
| 11 | const route = useRoute(); | ||
| 12 | const router = useRouter(); | ||
| 13 | |||
| 14 | const props = defineProps({ | ||
| 15 | activityId: [String, Number], | ||
| 16 | }); | ||
| 17 | |||
| 18 | let timer = null; | ||
| 19 | const startCheckSuccessListener = (orderSn, actId) => { | ||
| 20 | timer = setInterval(() => { | ||
| 21 | checkPaySuccess({ orderSn }).then((res) => { | ||
| 22 | if (res.data) { | ||
| 23 | clearInterval(timer); | ||
| 24 | timer = null; | ||
| 25 | // 支付成功 | ||
| 26 | payment.showCodeDialog = false; | ||
| 27 | ElMessage({ | ||
| 28 | type: "success", | ||
| 29 | message: anguageFormat( | ||
| 30 | language.value, | ||
| 31 | "支付成功", | ||
| 32 | "Payment succeeded" | ||
| 33 | ), | ||
| 34 | }); | ||
| 35 | router.replace({ | ||
| 36 | path: "/seat/order", | ||
| 37 | }); | ||
| 38 | } else { | ||
| 39 | return false; | ||
| 40 | } | ||
| 41 | }); | ||
| 42 | }, 3000); | ||
| 43 | }; | ||
| 44 | |||
| 45 | const payment = reactive({ | ||
| 46 | showCodeDialog: false, | ||
| 47 | btn_loading: false, | ||
| 48 | form: { | ||
| 49 | viewers: [], | ||
| 50 | phone: "", | ||
| 51 | }, | ||
| 52 | qrInfo: {}, | ||
| 53 | qrCodeData: "", | ||
| 54 | paymentHandle() { | ||
| 55 | if (payment.form.viewers.length != order.data?.seatInfo?.length) | ||
| 56 | return ElMessage({ | ||
| 57 | type: "warning", | ||
| 58 | message: languageFormat( | ||
| 59 | language.value, | ||
| 60 | "观看人与购买票数不符", | ||
| 61 | "The number of viewers does not match the number of tickets purchased." | ||
| 62 | ), | ||
| 63 | }); | ||
| 64 | if (!payment.form.phone) | ||
| 65 | return ElMessage({ | ||
| 66 | type: "warning", | ||
| 67 | message: languageFormat( | ||
| 68 | language.value, | ||
| 69 | "请输入联系电话", | ||
| 70 | "Please enter the contact phone number." | ||
| 71 | ), | ||
| 72 | }); | ||
| 73 | payOrder({ | ||
| 74 | contactPhone: payment.form.phone, | ||
| 75 | customerIds: payment.form.viewers, | ||
| 76 | orderToken: order.data?.orderToken, | ||
| 77 | payType: 1, | ||
| 78 | paymentAmount: order.data?.paymentAmount, | ||
| 79 | }).then((res) => { | ||
| 80 | if (res.data.language == "zh-cn") { | ||
| 81 | payment.qrInfo = res.data; | ||
| 82 | qrcode.toDataURL(res.data.scanCodeUrl, (err, url) => { | ||
| 83 | if (url) { | ||
| 84 | payment.qrCodeData = url; | ||
| 85 | } | ||
| 86 | }); | ||
| 87 | payment.showCodeDialog = true; | ||
| 88 | startCheckSuccessListener(res.data.orderSn, props.activityId); | ||
| 89 | } else { | ||
| 90 | // TODO: 这里是PayPal支付 | ||
| 91 | } | ||
| 92 | }); | ||
| 93 | }, | ||
| 94 | handleCloce() { | ||
| 95 | payment.showCodeDialog = false; | ||
| 96 | payment.qrCodeData = ""; | ||
| 97 | clearInterval(timer); | ||
| 98 | timer = null; | ||
| 99 | }, | ||
| 100 | }); | ||
| 101 | |||
| 102 | const order = reactive({ | ||
| 103 | data: null, | ||
| 104 | fetchData() { | ||
| 105 | confirmOrder({ | ||
| 106 | actId: props.activityId, | ||
| 107 | openType: route.query.openType, | ||
| 108 | sessionId: route.query.sessionId, | ||
| 109 | sitePlace: route.query.sitePlace, | ||
| 110 | ticketType: route.query.ticketType, | ||
| 111 | seatIds: route.query.seatIds.split(","), | ||
| 112 | }).then((res) => { | ||
| 113 | this.data = res.data; | ||
| 114 | }); | ||
| 115 | }, | ||
| 116 | }); | ||
| 117 | |||
| 118 | const audience = reactive({ | ||
| 119 | data: [], | ||
| 120 | fetchData() { | ||
| 121 | viewPeopleList().then((res) => { | ||
| 122 | audience.data = res.data; | ||
| 123 | }); | ||
| 124 | }, | ||
| 125 | }); | ||
| 126 | |||
| 127 | onUnmounted(() => { | ||
| 128 | clearInterval(timer); | ||
| 129 | }); | ||
| 130 | |||
| 131 | audience.fetchData(); | ||
| 132 | order.fetchData(); | ||
| 133 | </script> | ||
| 134 | |||
| 135 | <template> | ||
| 136 | <div class="container"> | ||
| 137 | <div class="title"> | ||
| 138 | {{ languageFormat(language, "订单确认", "Order confirmation") }} | ||
| 139 | </div> | ||
| 140 | <div class="content"> | ||
| 141 | <div class="left"> | ||
| 142 | <div class="info"> | ||
| 143 | <div class="name">{{ order.data?.activityName }}</div> | ||
| 144 | <div class="address">{{ order.data?.placeName }}</div> | ||
| 145 | </div> | ||
| 146 | |||
| 147 | <div class="ticket_info"> | ||
| 148 | <div class="tit_box"> | ||
| 149 | <div class="line"></div> | ||
| 150 | <div class="txt"> | ||
| 151 | {{ languageFormat(language, "订票信息", "Ticket Info") }} | ||
| 152 | </div> | ||
| 153 | </div> | ||
| 154 | |||
| 155 | <div class="form"> | ||
| 156 | <el-form> | ||
| 157 | <el-form-item :label="language == 0 ? '联系人' : 'contacts'"> | ||
| 158 | <el-input | ||
| 159 | v-model="payment.form.phone" | ||
| 160 | :placeholder=" | ||
| 161 | language == 0 | ||
| 162 | ? '请输入联系电话' | ||
| 163 | : 'Please enter the contact phone number' | ||
| 164 | " | ||
| 165 | style="width: 260px" | ||
| 166 | /> | ||
| 167 | </el-form-item> | ||
| 168 | <el-form-item :label="language == 0 ? '观看人' : 'contacts'"> | ||
| 169 | <div class="p_box"> | ||
| 170 | <div class="people"> | ||
| 171 | <el-checkbox-group | ||
| 172 | v-model="payment.form.viewers" | ||
| 173 | :max="order.data?.seatInfo?.length" | ||
| 174 | > | ||
| 175 | <div | ||
| 176 | v-for="(it, index) in audience.data" | ||
| 177 | :key="index" | ||
| 178 | class="prople_item" | ||
| 179 | > | ||
| 180 | <div> | ||
| 181 | <div class="name">{{ it.name }}</div> | ||
| 182 | <div class="idcard">{{ it.idCard }}</div> | ||
| 183 | </div> | ||
| 184 | <el-checkbox :value="it.id"> </el-checkbox> | ||
| 185 | </div> | ||
| 186 | </el-checkbox-group> | ||
| 187 | </div> | ||
| 188 | <!-- button --> | ||
| 189 | <div | ||
| 190 | class="btn" | ||
| 191 | @click="$router.push({ path: '/seat/people_manage' })" | ||
| 192 | > | ||
| 193 | {{ languageFormat(language, "新增", "Add") }} | ||
| 194 | </div> | ||
| 195 | </div> | ||
| 196 | </el-form-item> | ||
| 197 | </el-form> | ||
| 198 | </div> | ||
| 199 | </div> | ||
| 200 | </div> | ||
| 201 | |||
| 202 | <div class="right"> | ||
| 203 | <div class="tit_box"> | ||
| 204 | <div class="line"></div> | ||
| 205 | <div class="txt"> | ||
| 206 | {{ languageFormat(language, "订单明细", "Order summary") }} | ||
| 207 | </div> | ||
| 208 | </div> | ||
| 209 | |||
| 210 | <div class="detail"> | ||
| 211 | <div class="detail_top"> | ||
| 212 | <div class="time">{{ order.data?.dateStr }}</div> | ||
| 213 | <div class="ticket"> | ||
| 214 | {{ order.data?.singlePrice }}<span v-if="language == 0">元</span | ||
| 215 | >{{ languageFormat(language, "票档", "Ticket file") }} x{{ | ||
| 216 | order.data?.seatInfo?.length | ||
| 217 | }}{{ languageFormat(language, "张", "tickets") }} | ||
| 218 | </div> | ||
| 219 | </div> | ||
| 220 | <div class="detail_center"> | ||
| 221 | <div | ||
| 222 | v-for="(it, index) in order.data?.seatInfo" | ||
| 223 | :key="index" | ||
| 224 | class="ticket" | ||
| 225 | > | ||
| 226 | <span v-if="it.venueId == 1" | ||
| 227 | >{{ it.area }}{{ languageFormat(language, "区", "Zones") }} | ||
| 228 | </span> | ||
| 229 | {{ it.pai }}{{ languageFormat(language, "排", "Row") }} {{ it.no | ||
| 230 | }}{{ languageFormat(language, "座", "Seat") }} ({{ | ||
| 231 | it.venueId == 1 ? "B6" : "B4" | ||
| 232 | }}{{ languageFormat(language, "馆", "Venue") }}) | ||
| 233 | </div> | ||
| 234 | </div> | ||
| 235 | <div class="detail_b"> | ||
| 236 | <div class="sum_txt"> | ||
| 237 | {{ languageFormat(language, "共计", "Total") }} | ||
| 238 | </div> | ||
| 239 | <div class="price_num"> | ||
| 240 | <span v-if="language == 1">¥</span>{{ order.data?.paymentAmount }} | ||
| 241 | </div> | ||
| 242 | </div> | ||
| 243 | </div> | ||
| 244 | </div> | ||
| 245 | </div> | ||
| 246 | <div class="footer"> | ||
| 247 | <div> | ||
| 248 | <span class="label" | ||
| 249 | >{{ languageFormat(language, "共计金额", "Subtotal") }}:</span | ||
| 250 | ><span class="value">¥{{ order.data?.paymentAmount }}</span> | ||
| 251 | </div> | ||
| 252 | <div class="pay" @click="payment.paymentHandle()"> | ||
| 253 | {{ languageFormat(language, "立即支付", "Pay Now") }} | ||
| 254 | </div> | ||
| 255 | </div> | ||
| 256 | |||
| 257 | <el-dialog | ||
| 258 | v-model="payment.showCodeDialog" | ||
| 259 | title="支付" | ||
| 260 | width="300" | ||
| 261 | @closed="payment.handleCloce()" | ||
| 262 | > | ||
| 263 | <div> | ||
| 264 | <img class="qrcode" :src="payment.qrCodeData" /> | ||
| 265 | </div> | ||
| 266 | </el-dialog> | ||
| 267 | </div> | ||
| 268 | </template> | ||
| 269 | |||
| 270 | <style scoped lang="scss"> | ||
| 271 | div { | ||
| 272 | box-sizing: border-box; | ||
| 273 | } | ||
| 274 | .qrcode { | ||
| 275 | width: 200px; | ||
| 276 | height: 200px; | ||
| 277 | margin: 0 auto; | ||
| 278 | } | ||
| 279 | .container { | ||
| 280 | padding: 20px 0; | ||
| 281 | width: 1200px; | ||
| 282 | margin: 0 auto; | ||
| 283 | |||
| 284 | .title { | ||
| 285 | padding: 11px; | ||
| 286 | text-align: center; | ||
| 287 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 288 | font-size: 18px; | ||
| 289 | color: #ffffff; | ||
| 290 | } | ||
| 291 | |||
| 292 | .content { | ||
| 293 | display: flex; | ||
| 294 | background-color: #fff; | ||
| 295 | padding: 20px 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | .line { | ||
| 299 | width: 4px; | ||
| 300 | height: 18px; | ||
| 301 | background: linear-gradient(180deg, #493ceb 0%, #8623fc 100%); | ||
| 302 | border-radius: 4px; | ||
| 303 | } | ||
| 304 | |||
| 305 | .left { | ||
| 306 | padding-left: 20px; | ||
| 307 | .info { | ||
| 308 | width: 640px; | ||
| 309 | background: rgba(69, 61, 234, 0.04); | ||
| 310 | border-radius: 8px; | ||
| 311 | border: 1px solid #d3d1f6; | ||
| 312 | padding: 20px 0 28px 33px; | ||
| 313 | margin-bottom: 20px; | ||
| 314 | .name { | ||
| 315 | font-weight: 500; | ||
| 316 | font-size: 18px; | ||
| 317 | color: #000000; | ||
| 318 | margin-bottom: 20px; | ||
| 319 | } | ||
| 320 | .address { | ||
| 321 | font-weight: 400; | ||
| 322 | font-size: 14px; | ||
| 323 | color: #929aa0; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | .ticket_info { | ||
| 328 | .tit_box { | ||
| 329 | display: flex; | ||
| 330 | align-items: center; | ||
| 331 | gap: 10px; | ||
| 332 | margin-bottom: 14px; | ||
| 333 | .txt { | ||
| 334 | font-weight: bold; | ||
| 335 | font-size: 16px; | ||
| 336 | color: #493ceb; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | .form { | ||
| 340 | width: 640px; | ||
| 341 | min-height: 464px; | ||
| 342 | padding: 20px 60px; | ||
| 343 | border-radius: 5px; | ||
| 344 | border: 1px solid #dcdfe6; | ||
| 345 | |||
| 346 | .p_box { | ||
| 347 | display: flex; | ||
| 348 | gap: 10px; | ||
| 349 | .people { | ||
| 350 | width: 298px; | ||
| 351 | background: #fbfcfd; | ||
| 352 | border-radius: 2px; | ||
| 353 | border: 1px solid #dcdfe6; | ||
| 354 | padding: 0 14px; | ||
| 355 | .prople_item { | ||
| 356 | display: flex; | ||
| 357 | justify-content: space-between; | ||
| 358 | align-items: center; | ||
| 359 | padding: 14px 0; | ||
| 360 | border-bottom: 1px solid #dcdfe6; | ||
| 361 | &:last-child { | ||
| 362 | border: none; | ||
| 363 | } | ||
| 364 | .name { | ||
| 365 | font-size: 16px; | ||
| 366 | color: #929aa0; | ||
| 367 | margin-bottom: 20px; | ||
| 368 | } | ||
| 369 | .idcard { | ||
| 370 | font-size: 10px; | ||
| 371 | color: #929aa0; | ||
| 372 | } | ||
| 373 | } | ||
| 374 | } | ||
| 375 | .btn { | ||
| 376 | width: 90px; | ||
| 377 | height: 40px; | ||
| 378 | background: #fbfcfd; | ||
| 379 | border-radius: 20px; | ||
| 380 | border: 1px solid #493ceb; | ||
| 381 | margin-top: 10px; | ||
| 382 | font-size: 14px; | ||
| 383 | color: #493ceb; | ||
| 384 | line-height: 40px; | ||
| 385 | text-align: center; | ||
| 386 | cursor: pointer; | ||
| 387 | user-select: none; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | } | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | .right { | ||
| 395 | width: 460px; | ||
| 396 | margin-left: 36px; | ||
| 397 | .tit_box { | ||
| 398 | display: flex; | ||
| 399 | align-items: center; | ||
| 400 | gap: 10px; | ||
| 401 | margin-bottom: 20px; | ||
| 402 | .txt { | ||
| 403 | font-weight: bold; | ||
| 404 | font-size: 16px; | ||
| 405 | color: #493ceb; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | .detail { | ||
| 410 | padding: 15px 26px; | ||
| 411 | border-radius: 5px; | ||
| 412 | border: 1px solid #dcdfe6; | ||
| 413 | .detail_top { | ||
| 414 | padding-bottom: 13px; | ||
| 415 | border-bottom: 1px solid #dcdfe6; | ||
| 416 | .time { | ||
| 417 | font-weight: 500; | ||
| 418 | font-size: 18px; | ||
| 419 | color: #2d373f; | ||
| 420 | line-height: 25px; | ||
| 421 | margin-bottom: 8px; | ||
| 422 | } | ||
| 423 | .ticket { | ||
| 424 | font-size: 16px; | ||
| 425 | color: #2d373f; | ||
| 426 | } | ||
| 427 | } | ||
| 428 | .detail_center { | ||
| 429 | margin-top: 14px; | ||
| 430 | display: flex; | ||
| 431 | flex-direction: column; | ||
| 432 | padding-bottom: 13px; | ||
| 433 | border-bottom: 1px solid #dcdfe6; | ||
| 434 | gap: 8px; | ||
| 435 | .ticket { | ||
| 436 | font-size: 16px; | ||
| 437 | color: #2d373f; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | .detail_b { | ||
| 441 | display: flex; | ||
| 442 | justify-content: space-between; | ||
| 443 | align-items: center; | ||
| 444 | margin-top: 16px; | ||
| 445 | .sum_txt { | ||
| 446 | font-weight: 600; | ||
| 447 | font-size: 18px; | ||
| 448 | color: #2d373f; | ||
| 449 | line-height: 25px; | ||
| 450 | } | ||
| 451 | .price_num { | ||
| 452 | font-weight: 600; | ||
| 453 | font-size: 36px; | ||
| 454 | color: #ff8124; | ||
| 455 | line-height: 50px; | ||
| 456 | } | ||
| 457 | } | ||
| 458 | } | ||
| 459 | } | ||
| 460 | |||
| 461 | .footer { | ||
| 462 | display: flex; | ||
| 463 | justify-content: space-between; | ||
| 464 | height: 70px; | ||
| 465 | align-items: center; | ||
| 466 | background: #ffffff; | ||
| 467 | box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08); | ||
| 468 | margin-top: 9px; | ||
| 469 | padding: 0 30px; | ||
| 470 | .label { | ||
| 471 | font-size: 16px; | ||
| 472 | color: #7b7f83; | ||
| 473 | line-height: 22px; | ||
| 474 | } | ||
| 475 | .value { | ||
| 476 | font-size: 22px; | ||
| 477 | color: #ff8124; | ||
| 478 | line-height: 30px; | ||
| 479 | font-weight: 600; | ||
| 480 | } | ||
| 481 | .pay { | ||
| 482 | width: 200px; | ||
| 483 | height: 40px; | ||
| 484 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 485 | border-radius: 20px; | ||
| 486 | font-weight: 500; | ||
| 487 | font-size: 16px; | ||
| 488 | color: #ffffff; | ||
| 489 | line-height: 40px; | ||
| 490 | text-align: center; | ||
| 491 | cursor: pointer; | ||
| 492 | user-select: none; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | } | ||
| 496 | </style> |
src/viewsPc/seat/order-detail.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { onBeforeUnmount, reactive } from "vue"; | ||
| 3 | import { | ||
| 4 | cancelOrder, | ||
| 5 | getOrderDetail, | ||
| 6 | immediatePay, | ||
| 7 | cancelPay, | ||
| 8 | checkPaySuccess, | ||
| 9 | } from "./api/index.js"; | ||
| 10 | import qrCodeDialog from "./components/qrCodeDialog.vue"; | ||
| 11 | import { ElMessageBox, ElMessage } from "element-plus"; | ||
| 12 | import qrcode from "qrcode"; | ||
| 13 | import { languageFormat } from "./utils/language.js"; | ||
| 14 | import { useStorage } from "@vueuse/core/index"; | ||
| 15 | const language = useStorage("language", 0); | ||
| 16 | |||
| 17 | const route = useRoute(); | ||
| 18 | const router = useRouter(); | ||
| 19 | |||
| 20 | const status = reactive({ | ||
| 21 | 0: { | ||
| 22 | txt: "待支付", | ||
| 23 | color: "#F740A6", | ||
| 24 | bgColor: "#FFE2F2", | ||
| 25 | }, | ||
| 26 | 1: { | ||
| 27 | txt: "购票成功", | ||
| 28 | color: "#FFCC00", | ||
| 29 | bgColor: "#FFF7D9", | ||
| 30 | }, | ||
| 31 | 2: { | ||
| 32 | txt: "交易关闭", | ||
| 33 | color: "#757575", | ||
| 34 | bgColor: "#DDDDDD", | ||
| 35 | }, | ||
| 36 | 3: { | ||
| 37 | txt: "已退款", | ||
| 38 | color: "#757575", | ||
| 39 | bgColor: "#DDDDDD", | ||
| 40 | }, | ||
| 41 | 4: { | ||
| 42 | color: "#F740A6", | ||
| 43 | bgColor: "#FFE2F2", | ||
| 44 | }, | ||
| 45 | 5: { | ||
| 46 | txt: "完成", | ||
| 47 | color: "#34C759", | ||
| 48 | bgColor: "#D2FFDD", | ||
| 49 | }, | ||
| 50 | }); | ||
| 51 | |||
| 52 | const props = defineProps({ | ||
| 53 | activityId: [String, Number], | ||
| 54 | }); | ||
| 55 | |||
| 56 | let timer = null; | ||
| 57 | const startCheckSuccessListener = (orderSn, actId) => { | ||
| 58 | timer = setInterval(() => { | ||
| 59 | checkPaySuccess({ orderSn }).then((res) => { | ||
| 60 | if (res.data) { | ||
| 61 | clearInterval(timer); | ||
| 62 | timer = null; | ||
| 63 | // 支付成功 | ||
| 64 | detail.showCodeDialog = false; | ||
| 65 | detail.fetchData(); | ||
| 66 | ElMessage({ type: "success", message: "支付成功" }); | ||
| 67 | } else { | ||
| 68 | return false; | ||
| 69 | } | ||
| 70 | }); | ||
| 71 | }, 3000); | ||
| 72 | }; | ||
| 73 | |||
| 74 | const detail = reactive({ | ||
| 75 | showCodeDialog: false, | ||
| 76 | qrCodeData: "", | ||
| 77 | pay_loading: false, | ||
| 78 | qrInfo: {}, | ||
| 79 | data: null, | ||
| 80 | timer: null, | ||
| 81 | |||
| 82 | // 分钟 | ||
| 83 | minutes: 0, | ||
| 84 | seconds: 0, | ||
| 85 | fetchData() { | ||
| 86 | getOrderDetail({ orderSn: route.query.orderSn }).then((res) => { | ||
| 87 | detail.data = res.data; | ||
| 88 | detail.countDown(detail.data?.payEndTime); | ||
| 89 | }); | ||
| 90 | }, | ||
| 91 | // 倒计时 | ||
| 92 | countDown(time) { | ||
| 93 | // 当前时间 | ||
| 94 | let nowTime = new Date(); | ||
| 95 | let endTime = new Date(time); | ||
| 96 | // 两个日期相差的时间戳,以毫秒为单位(1000ms = 1s) | ||
| 97 | let totalTime = endTime - nowTime; | ||
| 98 | // 结束时间大于现在的时间 | ||
| 99 | if (totalTime > 0) { | ||
| 100 | detail.timer = setInterval(() => { | ||
| 101 | if (totalTime >= 0) { | ||
| 102 | //获取分钟数 | ||
| 103 | let minutes = Math.floor( | ||
| 104 | (((totalTime % (3600 * 24 * 1000)) / 1000) % 3600) / 60 | ||
| 105 | ); | ||
| 106 | //获取秒数 | ||
| 107 | let seconds = Math.floor( | ||
| 108 | (((totalTime % (3600 * 24 * 1000)) / 1000) % 3600) % 60 | ||
| 109 | ) | ||
| 110 | .toString() | ||
| 111 | .padStart(2, "0"); | ||
| 112 | |||
| 113 | detail.minutes = minutes; | ||
| 114 | detail.seconds = seconds; | ||
| 115 | |||
| 116 | totalTime -= 1000; | ||
| 117 | // console.log(totalTime) | ||
| 118 | } else { | ||
| 119 | clearInterval(detail.timer); // 停止调用函数 | ||
| 120 | detail.fetchData(); | ||
| 121 | } | ||
| 122 | }, 1000); | ||
| 123 | } | ||
| 124 | }, | ||
| 125 | payment() { | ||
| 126 | if (detail.pay_loading) return; | ||
| 127 | detail.pay_loading = true; | ||
| 128 | immediatePay({ orderSn: detail.data.orderSn, payType: 1 }) | ||
| 129 | .then((res) => { | ||
| 130 | if (res.data.language == "zh-cn") { | ||
| 131 | detail.qrInfo = res.data; | ||
| 132 | qrcode.toDataURL(res.data.scanCodeUrl, (err, url) => { | ||
| 133 | if (url) { | ||
| 134 | detail.qrCodeData = url; | ||
| 135 | } | ||
| 136 | }); | ||
| 137 | startCheckSuccessListener(detail.data.orderSn); | ||
| 138 | detail.showCodeDialog = true; | ||
| 139 | } else { | ||
| 140 | // TODO: 这里是PayPal支付 | ||
| 141 | } | ||
| 142 | }) | ||
| 143 | .finally(() => (detail.pay_loading = false)); | ||
| 144 | }, | ||
| 145 | handleClose() { | ||
| 146 | detail.showCodeDialog = false; | ||
| 147 | detail.qrCodeData = ""; | ||
| 148 | clearInterval(timer); | ||
| 149 | timer = null; | ||
| 150 | }, | ||
| 151 | // 取消支付 | ||
| 152 | cancelPay() { | ||
| 153 | ElMessageBox.confirm( | ||
| 154 | languageFormat( | ||
| 155 | language.value, | ||
| 156 | "确认取消支付吗?", | ||
| 157 | "Are you sure to cancel?" | ||
| 158 | ), | ||
| 159 | languageFormat(language.value, "提示", "tip"), | ||
| 160 | { | ||
| 161 | confirmButtonText: languageFormat(language.value, "确认", "confirm"), | ||
| 162 | cancelButtonText: languageFormat(language.value, "取消", "cancel"), | ||
| 163 | type: "warning", | ||
| 164 | draggable: true, | ||
| 165 | } | ||
| 166 | ) | ||
| 167 | .then(() => { | ||
| 168 | cancelPay({ orderSn: detail.data.orderSn }).then(() => { | ||
| 169 | detail.fetchData(); | ||
| 170 | ElMessage({ | ||
| 171 | type: "success", | ||
| 172 | message: languageFormat( | ||
| 173 | language.value, | ||
| 174 | "操作成功", | ||
| 175 | "Operate successfully" | ||
| 176 | ), | ||
| 177 | }); | ||
| 178 | }); | ||
| 179 | }) | ||
| 180 | .catch(() => {}); | ||
| 181 | }, | ||
| 182 | // 取消购票 | ||
| 183 | cancelOrder() { | ||
| 184 | ElMessageBox.confirm( | ||
| 185 | languageFormat( | ||
| 186 | language.value, | ||
| 187 | "确认取消购票吗?", | ||
| 188 | "Are you sure to cancel?" | ||
| 189 | ), | ||
| 190 | languageFormat(language.value, "提示", "tip"), | ||
| 191 | { | ||
| 192 | confirmButtonText: languageFormat(language.value, "确认", "confirm"), | ||
| 193 | cancelButtonText: languageFormat(language.value, "取消", "cancel"), | ||
| 194 | type: "warning", | ||
| 195 | draggable: true, | ||
| 196 | } | ||
| 197 | ) | ||
| 198 | .then(() => { | ||
| 199 | cancelOrder({ orderSn: detail.data.orderSn }).then((res) => { | ||
| 200 | detail.fetchData(); | ||
| 201 | ElMessage({ | ||
| 202 | type: "success", | ||
| 203 | message: languageFormat( | ||
| 204 | language.value, | ||
| 205 | "操作成功", | ||
| 206 | "Operate successfully" | ||
| 207 | ), | ||
| 208 | }); | ||
| 209 | }); | ||
| 210 | }) | ||
| 211 | .catch(() => {}); | ||
| 212 | }, | ||
| 213 | comeBack() { | ||
| 214 | router.push({ | ||
| 215 | path: "/seat/detail", | ||
| 216 | query: { | ||
| 217 | id: props.activityId, | ||
| 218 | }, | ||
| 219 | }); | ||
| 220 | }, | ||
| 221 | }); | ||
| 222 | |||
| 223 | onBeforeUnmount(() => { | ||
| 224 | clearInterval(detail.timer); | ||
| 225 | clearInterval(timer); | ||
| 226 | }); | ||
| 227 | |||
| 228 | detail.fetchData(); | ||
| 229 | </script> | ||
| 230 | |||
| 231 | <template> | ||
| 232 | <div class="container"> | ||
| 233 | <div class="left"> | ||
| 234 | <!-- 票务信息 --> | ||
| 235 | <div class="ticket"> | ||
| 236 | <div class="th"> | ||
| 237 | <div style="width: 33%" class="td"> | ||
| 238 | {{ languageFormat(language, "票务信息", "Ticket Info") }} | ||
| 239 | </div> | ||
| 240 | <div style="width: 25%" class="td"> | ||
| 241 | {{ languageFormat(language, "地点", "Venue") }} | ||
| 242 | </div> | ||
| 243 | <div style="width: 20%" class="td"> | ||
| 244 | {{ languageFormat(language, "单价", "Price") }} | ||
| 245 | </div> | ||
| 246 | <div style="width: 10%" class="td"> | ||
| 247 | {{ languageFormat(language, "数量", "Ticket Qty.") }} | ||
| 248 | </div> | ||
| 249 | <div style="width: 12%; text-align: right" class="td"> | ||
| 250 | {{ languageFormat(language, "小计", "Subtotal") }} | ||
| 251 | </div> | ||
| 252 | </div> | ||
| 253 | <div class="line"></div> | ||
| 254 | <div class="tr"> | ||
| 255 | <div style="width: 30%" class="td">{{ detail.data?.name }}</div> | ||
| 256 | <div style="width: 25%" class="td">{{ detail.data?.placeName }}</div> | ||
| 257 | <div style="width: 20%" class="td"> | ||
| 258 | ¥{{ detail.data?.singlePrice }} | ||
| 259 | </div> | ||
| 260 | <div style="width: 12%" class="td"> | ||
| 261 | x{{ detail.data?.seatList?.length }} | ||
| 262 | </div> | ||
| 263 | <div style="width: 13%; text-align: right" class="td"> | ||
| 264 | ¥{{ detail.data?.payAmount }} | ||
| 265 | </div> | ||
| 266 | </div> | ||
| 267 | </div> | ||
| 268 | <!-- 座位 --> | ||
| 269 | <div class="seat_box"> | ||
| 270 | <div class="th"> | ||
| 271 | <div style="width: 30.33%" class="td"> | ||
| 272 | {{ languageFormat(language, "时间座位", "Seat Info") }} | ||
| 273 | </div> | ||
| 274 | <div style="width: 30.33%" class="td"> | ||
| 275 | {{ languageFormat(language, "订单信息", "Summary") }} | ||
| 276 | </div> | ||
| 277 | <div style="width: 30.33%" class="td"> | ||
| 278 | {{ languageFormat(language, "联系方式", "Contact details") }} | ||
| 279 | </div> | ||
| 280 | </div> | ||
| 281 | <div class="tr"> | ||
| 282 | <div style="width: 30.33%" class="td flex-col"> | ||
| 283 | <div>{{ detail.data?.dateStr }}</div> | ||
| 284 | <div v-for="(it, index) in detail.data?.seatList" :key="index"> | ||
| 285 | <span v-if="it.venueId == 1" | ||
| 286 | >{{ it.area | ||
| 287 | }}{{ languageFormat(language, "区", "Zones") }}</span | ||
| 288 | >{{ it.pai }}{{ languageFormat(language, "排", "Row") }}{{ it.no | ||
| 289 | }}{{ languageFormat(language, "座", "Seat") }} ({{ | ||
| 290 | it.venueId == 1 ? "B6" : "B4" | ||
| 291 | }}{{ languageFormat(language, "馆", "Venue") }}) | ||
| 292 | </div> | ||
| 293 | </div> | ||
| 294 | <div style="width: 30.33%" class="td flex-col"> | ||
| 295 | <div> | ||
| 296 | {{ languageFormat(language, "订单编号", "Order No.") }}:{{ | ||
| 297 | detail.data?.orderSn | ||
| 298 | }} | ||
| 299 | </div> | ||
| 300 | <div> | ||
| 301 | {{ languageFormat(language, "创建时间", "Order Time") }}:{{ | ||
| 302 | detail.data?.orderTime | ||
| 303 | }} | ||
| 304 | </div> | ||
| 305 | </div> | ||
| 306 | <div style="width: 30.33%" class="td"> | ||
| 307 | <div> | ||
| 308 | {{ languageFormat(language, "联系电话", "Telephone") }}:{{ | ||
| 309 | detail.data?.contactPhone | ||
| 310 | }} | ||
| 311 | </div> | ||
| 312 | </div> | ||
| 313 | </div> | ||
| 314 | </div> | ||
| 315 | <!-- 购票人 --> | ||
| 316 | <div class="pay_ticket"> | ||
| 317 | <div class="title"> | ||
| 318 | {{ languageFormat(language, "购票人", "Full Name") }} | ||
| 319 | </div> | ||
| 320 | <div class="people"> | ||
| 321 | <div | ||
| 322 | v-for="(it, index) in detail.data?.customerList" | ||
| 323 | :key="index" | ||
| 324 | class="p_info" | ||
| 325 | > | ||
| 326 | <div>{{ it.name }}</div> | ||
| 327 | <div class="idcard"> | ||
| 328 | {{ languageFormat(language, "身份证", "ID number") }}:{{ | ||
| 329 | it.idCard | ||
| 330 | }} | ||
| 331 | </div> | ||
| 332 | </div> | ||
| 333 | </div> | ||
| 334 | </div> | ||
| 335 | </div> | ||
| 336 | |||
| 337 | <div class="right"> | ||
| 338 | <div class="balance"> | ||
| 339 | <div class="title"> | ||
| 340 | {{ languageFormat(language, "结算信息", "Payment details") }} | ||
| 341 | </div> | ||
| 342 | <div class="cell"> | ||
| 343 | <div class="label"> | ||
| 344 | {{ languageFormat(language, "订单状态", "Order Status") }} | ||
| 345 | </div> | ||
| 346 | <div | ||
| 347 | class="value" | ||
| 348 | :style="{ color: status[detail.data?.state]?.color }" | ||
| 349 | > | ||
| 350 | {{ status[detail.data?.state]?.txt }} | ||
| 351 | </div> | ||
| 352 | </div> | ||
| 353 | <div class="cell"> | ||
| 354 | <div class="label"> | ||
| 355 | {{ languageFormat(language, "订单金额", "Order amount") }} | ||
| 356 | </div> | ||
| 357 | <div | ||
| 358 | class="value" | ||
| 359 | :style="{ color: status[detail.data?.state]?.color }" | ||
| 360 | > | ||
| 361 | <span v-if="language == 0">¥</span>{{ detail.data?.payAmount }} | ||
| 362 | </div> | ||
| 363 | </div> | ||
| 364 | <!-- button --> | ||
| 365 | <div v-if="detail.data?.state == 0" class="btn_box"> | ||
| 366 | <div class="can_pay" @click="detail.cancelPay()"> | ||
| 367 | {{ languageFormat(language, "取消支付", "Cancel the payment") }} | ||
| 368 | </div> | ||
| 369 | <div class="pay" @click="detail.payment()"> | ||
| 370 | {{ languageFormat(language, "立即支付", "Pay Now") }} | ||
| 371 | </div> | ||
| 372 | </div> | ||
| 373 | <div v-else> | ||
| 374 | <!-- v-if="detail.data?.state == 1 && detail.data?.isRefund" --> | ||
| 375 | <div | ||
| 376 | v-if="detail.data?.state == 1 && detail.data?.isRefund" | ||
| 377 | class="btn_box" | ||
| 378 | > | ||
| 379 | <div class="can_pay" @click="detail.cancelOrder()"> | ||
| 380 | {{ | ||
| 381 | languageFormat( | ||
| 382 | language, | ||
| 383 | "取消购票", | ||
| 384 | "Cancel the ticket purchase" | ||
| 385 | ) | ||
| 386 | }} | ||
| 387 | </div> | ||
| 388 | <div class="pay" @click="detail.comeBack()"> | ||
| 389 | {{ languageFormat(language, "再来一单", "Make another order") }} | ||
| 390 | </div> | ||
| 391 | </div> | ||
| 392 | |||
| 393 | <div v-else class="btn_box"> | ||
| 394 | <div class="pay_dis"> | ||
| 395 | {{ | ||
| 396 | languageFormat( | ||
| 397 | language, | ||
| 398 | "请联系工作人员", | ||
| 399 | "Please contact the staff" | ||
| 400 | ) | ||
| 401 | }} | ||
| 402 | </div> | ||
| 403 | </div> | ||
| 404 | </div> | ||
| 405 | </div> | ||
| 406 | <div v-if="detail.data?.state == 0" class="tip"> | ||
| 407 | <span v-if="language == 0" | ||
| 408 | >请尽快完成支付,还剩{{ detail.minutes }}分{{ | ||
| 409 | detail.seconds | ||
| 410 | }}秒</span | ||
| 411 | > | ||
| 412 | <span v-if="language == 1" | ||
| 413 | >Time left {{ detail.minutes }}:{{ detail.seconds }}</span | ||
| 414 | > | ||
| 415 | </div> | ||
| 416 | </div> | ||
| 417 | |||
| 418 | <!-- <qrCodeDialog | ||
| 419 | :showCodeDialog="detail.showCodeDialog" | ||
| 420 | :qrCode="detail.qrCodeData" | ||
| 421 | /> --> | ||
| 422 | |||
| 423 | <el-dialog | ||
| 424 | v-model="detail.showCodeDialog" | ||
| 425 | title="支付" | ||
| 426 | width="300" | ||
| 427 | @closed="detail.handleClose()" | ||
| 428 | > | ||
| 429 | <div> | ||
| 430 | <img class="qrcode" :src="detail.qrCodeData" /> | ||
| 431 | </div> | ||
| 432 | </el-dialog> | ||
| 433 | </div> | ||
| 434 | </template> | ||
| 435 | |||
| 436 | <style scoped lang="scss"> | ||
| 437 | .qrcode { | ||
| 438 | width: 200px; | ||
| 439 | height: 200px; | ||
| 440 | margin: 0 auto; | ||
| 441 | } | ||
| 442 | .container { | ||
| 443 | width: 1200px; | ||
| 444 | margin: 0 auto; | ||
| 445 | padding: 20px 0; | ||
| 446 | display: flex; | ||
| 447 | gap: 20px; | ||
| 448 | .left { | ||
| 449 | width: 780px; | ||
| 450 | // 票务信息 | ||
| 451 | .ticket { | ||
| 452 | background-color: #fff; | ||
| 453 | padding: 0 20px; | ||
| 454 | .th { | ||
| 455 | display: flex; | ||
| 456 | justify-content: space-between; | ||
| 457 | padding: 20px 0; | ||
| 458 | .td { | ||
| 459 | font-weight: bold; | ||
| 460 | font-size: 16px; | ||
| 461 | color: #333333; | ||
| 462 | line-height: 24px; | ||
| 463 | } | ||
| 464 | } | ||
| 465 | .line { | ||
| 466 | width: 740px; | ||
| 467 | height: 1px; | ||
| 468 | background: #eee; | ||
| 469 | } | ||
| 470 | .tr { | ||
| 471 | display: flex; | ||
| 472 | justify-content: space-between; | ||
| 473 | padding: 20px 0; | ||
| 474 | .td { | ||
| 475 | font-weight: 400; | ||
| 476 | font-size: 16px; | ||
| 477 | color: #333333; | ||
| 478 | line-height: 24px; | ||
| 479 | } | ||
| 480 | } | ||
| 481 | } | ||
| 482 | // 座位 | ||
| 483 | .seat_box { | ||
| 484 | background-color: #fff; | ||
| 485 | padding: 0 20px; | ||
| 486 | margin-top: 20px; | ||
| 487 | .th { | ||
| 488 | display: flex; | ||
| 489 | justify-content: space-between; | ||
| 490 | padding: 20px 0; | ||
| 491 | .td { | ||
| 492 | font-weight: bold; | ||
| 493 | font-size: 16px; | ||
| 494 | color: #333333; | ||
| 495 | line-height: 24px; | ||
| 496 | } | ||
| 497 | } | ||
| 498 | .tr { | ||
| 499 | display: flex; | ||
| 500 | justify-content: space-between; | ||
| 501 | padding: 20px 0; | ||
| 502 | .td { | ||
| 503 | font-weight: 400; | ||
| 504 | font-size: 16px; | ||
| 505 | color: #333333; | ||
| 506 | line-height: 24px; | ||
| 507 | } | ||
| 508 | .flex-col { | ||
| 509 | display: flex; | ||
| 510 | flex-direction: column; | ||
| 511 | gap: 16px; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | // 购票人 | ||
| 516 | .pay_ticket { | ||
| 517 | background-color: #fff; | ||
| 518 | padding: 20px; | ||
| 519 | margin-top: 20px; | ||
| 520 | .title { | ||
| 521 | font-weight: bold; | ||
| 522 | font-size: 16px; | ||
| 523 | color: #333333; | ||
| 524 | margin-bottom: 28px; | ||
| 525 | } | ||
| 526 | .people { | ||
| 527 | display: flex; | ||
| 528 | justify-content: space-between; | ||
| 529 | flex-wrap: wrap; | ||
| 530 | gap: 15px 50px; | ||
| 531 | .p_info { | ||
| 532 | font-weight: 400; | ||
| 533 | font-size: 16px; | ||
| 534 | color: #333333; | ||
| 535 | line-height: 24px; | ||
| 536 | .idcard { | ||
| 537 | color: #999999; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | } | ||
| 541 | } | ||
| 542 | } | ||
| 543 | .right { | ||
| 544 | width: 400px; | ||
| 545 | .balance { | ||
| 546 | background-color: #fff; | ||
| 547 | padding: 20px; | ||
| 548 | .title { | ||
| 549 | font-weight: bold; | ||
| 550 | font-size: 20px; | ||
| 551 | color: #333333; | ||
| 552 | line-height: 30px; | ||
| 553 | margin-bottom: 28px; | ||
| 554 | } | ||
| 555 | .cell { | ||
| 556 | display: flex; | ||
| 557 | justify-content: space-between; | ||
| 558 | align-items: center; | ||
| 559 | margin-bottom: 20px; | ||
| 560 | &:last-child { | ||
| 561 | margin: 0; | ||
| 562 | } | ||
| 563 | .label { | ||
| 564 | font-weight: 400; | ||
| 565 | font-size: 16px; | ||
| 566 | color: #333333; | ||
| 567 | } | ||
| 568 | .value { | ||
| 569 | font-weight: 400; | ||
| 570 | font-size: 16px; | ||
| 571 | color: #ff8124; | ||
| 572 | } | ||
| 573 | } | ||
| 574 | .btn_box { | ||
| 575 | border-top: 1px solid #eee; | ||
| 576 | padding-top: 20px; | ||
| 577 | display: flex; | ||
| 578 | gap: 20px; | ||
| 579 | user-select: none; | ||
| 580 | .pay_dis { | ||
| 581 | width: 360px; | ||
| 582 | height: 40px; | ||
| 583 | background: #a09dff; | ||
| 584 | border-radius: 20px; | ||
| 585 | font-weight: 500; | ||
| 586 | font-size: 16px; | ||
| 587 | color: #ffffff; | ||
| 588 | line-height: 40px; | ||
| 589 | text-align: center; | ||
| 590 | cursor: pointer; | ||
| 591 | } | ||
| 592 | .pay { | ||
| 593 | width: 170px; | ||
| 594 | height: 40px; | ||
| 595 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 596 | border-radius: 20px; | ||
| 597 | font-weight: 500; | ||
| 598 | font-size: 16px; | ||
| 599 | color: #ffffff; | ||
| 600 | line-height: 40px; | ||
| 601 | text-align: center; | ||
| 602 | cursor: pointer; | ||
| 603 | } | ||
| 604 | .can_pay { | ||
| 605 | width: 170px; | ||
| 606 | height: 40px; | ||
| 607 | background: #f6f6f6; | ||
| 608 | border-radius: 20px; | ||
| 609 | font-weight: 500; | ||
| 610 | font-size: 16px; | ||
| 611 | color: #999; | ||
| 612 | line-height: 40px; | ||
| 613 | text-align: center; | ||
| 614 | box-sizing: border-box; | ||
| 615 | cursor: pointer; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | } | ||
| 619 | .tip { | ||
| 620 | font-weight: 400; | ||
| 621 | font-size: 16px; | ||
| 622 | color: #ea3d6b; | ||
| 623 | line-height: 24px; | ||
| 624 | margin-top: 20px; | ||
| 625 | text-align: center; | ||
| 626 | } | ||
| 627 | } | ||
| 628 | } | ||
| 629 | </style> |
src/viewsPc/seat/order-list.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { setToken, getToken } from "./utils/local-store.js"; | ||
| 3 | import useUserStore from "@/store/modules/user"; | ||
| 4 | import { | ||
| 5 | getOrderList, | ||
| 6 | immediatePay, | ||
| 7 | cancelPay, | ||
| 8 | loginFree, | ||
| 9 | } from "./api/index.js"; | ||
| 10 | import qrCodeDialog from "./components/qrCodeDialog.vue"; | ||
| 11 | import { ElMessageBox, ElMessage } from "element-plus"; | ||
| 12 | import qrcode from "qrcode"; | ||
| 13 | import { md5 } from "md5js"; | ||
| 14 | import { languageFormat } from "./utils/language.js"; | ||
| 15 | import { useStorage } from "@vueuse/core/index"; | ||
| 16 | const language = useStorage("language", 0); | ||
| 17 | |||
| 18 | const userStore = useUserStore(); | ||
| 19 | |||
| 20 | const status = reactive({ | ||
| 21 | 0: { | ||
| 22 | txt: "待支付", | ||
| 23 | text_en: "Pending Payment", | ||
| 24 | color: "#F740A6", | ||
| 25 | bgColor: "#FFE2F2", | ||
| 26 | }, | ||
| 27 | 1: { | ||
| 28 | txt: "购票成功", | ||
| 29 | text_en: "Transaction completed", | ||
| 30 | color: "#FFCC00", | ||
| 31 | bgColor: "#FFF7D9", | ||
| 32 | }, | ||
| 33 | 2: { | ||
| 34 | txt: "交易关闭", | ||
| 35 | text_en: "Transaction closed", | ||
| 36 | color: "#757575", | ||
| 37 | bgColor: "#DDDDDD", | ||
| 38 | }, | ||
| 39 | 3: { | ||
| 40 | txt: "已退款", | ||
| 41 | text_en: "Already refunded", | ||
| 42 | color: "#757575", | ||
| 43 | bgColor: "#DDDDDD", | ||
| 44 | }, | ||
| 45 | 4: { | ||
| 46 | txt: "退款中", | ||
| 47 | text_en: "In the process of refunding", | ||
| 48 | color: "#F740A6", | ||
| 49 | bgColor: "#FFE2F2", | ||
| 50 | }, | ||
| 51 | 5: { | ||
| 52 | txt: "完成", | ||
| 53 | text_en: "Finish", | ||
| 54 | color: "#34C759", | ||
| 55 | bgColor: "#D2FFDD", | ||
| 56 | }, | ||
| 57 | }); | ||
| 58 | const props = defineProps({ | ||
| 59 | activityId: [String, Number], | ||
| 60 | }); | ||
| 61 | |||
| 62 | const order = reactive({ | ||
| 63 | showCodeDialog: false, | ||
| 64 | qrInfo: {}, | ||
| 65 | pay_loading: false, | ||
| 66 | pageNo: 1, | ||
| 67 | pageSize: 10, | ||
| 68 | total: 0, | ||
| 69 | |||
| 70 | noPay: {}, | ||
| 71 | minutes: 0, | ||
| 72 | seconds: 0, | ||
| 73 | data: [], | ||
| 74 | timer: null, | ||
| 75 | qrCodeData: "", | ||
| 76 | fetchData() { | ||
| 77 | getOrderList({ pageNo: order.pageNo, pageSize: order.pageSize }).then( | ||
| 78 | (res) => { | ||
| 79 | order.noPay = res.data.lists.find((it) => it.state == 0); | ||
| 80 | order.data = res.data.lists; | ||
| 81 | order.total = res.data.count; | ||
| 82 | } | ||
| 83 | ); | ||
| 84 | }, | ||
| 85 | payment(it) { | ||
| 86 | if (order.pay_loading) return; | ||
| 87 | order.pay_loading = true; | ||
| 88 | immediatePay({ orderSn: it.orderSn, payType: 1 }) | ||
| 89 | .then((res) => { | ||
| 90 | order.qrInfo = res.data; | ||
| 91 | qrcode.toDataURL(res.data.scanCodeUrl, (err, url) => { | ||
| 92 | if (err) { | ||
| 93 | console.error(err); | ||
| 94 | } else { | ||
| 95 | order.qrCodeData = url; | ||
| 96 | } | ||
| 97 | }); | ||
| 98 | order.showCodeDialog = true; | ||
| 99 | }) | ||
| 100 | .finally(() => (order.pay_loading = false)); | ||
| 101 | }, | ||
| 102 | handleClose() { | ||
| 103 | order.showCodeDialog = false; | ||
| 104 | order.qrCodeData = ""; | ||
| 105 | }, | ||
| 106 | // 取消支付 | ||
| 107 | cancelPayment(it) { | ||
| 108 | ElMessageBox.confirm( | ||
| 109 | languageFormat( | ||
| 110 | language.value, | ||
| 111 | "确认取消支付吗?", | ||
| 112 | "Are you sure to cancel the payment?" | ||
| 113 | ), | ||
| 114 | languageFormat(language.value, "提示", "tip"), | ||
| 115 | { | ||
| 116 | confirmButtonText: languageFormat(language.value, "确认", "confirm"), | ||
| 117 | cancelButtonText: languageFormat(language.value, "取消", "cancel"), | ||
| 118 | type: "warning", | ||
| 119 | draggable: true, | ||
| 120 | } | ||
| 121 | ) | ||
| 122 | .then(() => { | ||
| 123 | cancelPay({ orderSn: it.orderSn }).then(() => { | ||
| 124 | order.fetchData(); | ||
| 125 | ElMessage({ | ||
| 126 | type: "success", | ||
| 127 | message: languageFormat( | ||
| 128 | language.value, | ||
| 129 | "操作成功", | ||
| 130 | "Operate successfully" | ||
| 131 | ), | ||
| 132 | }); | ||
| 133 | }); | ||
| 134 | }) | ||
| 135 | .catch(() => {}); | ||
| 136 | }, | ||
| 137 | countDown(time) { | ||
| 138 | // 当前时间 | ||
| 139 | let nowTime = new Date(); | ||
| 140 | let endTime = new Date(time); | ||
| 141 | // 两个日期相差的时间戳,以毫秒为单位(1000ms = 1s) | ||
| 142 | let totalTime = endTime - nowTime; | ||
| 143 | // 结束时间大于现在的时间 | ||
| 144 | if (totalTime > 0) { | ||
| 145 | order.timer = setInterval(() => { | ||
| 146 | if (totalTime >= 0) { | ||
| 147 | //获取分钟数 | ||
| 148 | let minutes = Math.floor( | ||
| 149 | (((totalTime % (3600 * 24 * 1000)) / 1000) % 3600) / 60 | ||
| 150 | ); | ||
| 151 | //获取秒数 | ||
| 152 | let seconds = Math.floor( | ||
| 153 | (((totalTime % (3600 * 24 * 1000)) / 1000) % 3600) % 60 | ||
| 154 | ) | ||
| 155 | .toString() | ||
| 156 | .padStart(2, "0"); | ||
| 157 | |||
| 158 | order.minutes = minutes; | ||
| 159 | order.seconds = seconds; | ||
| 160 | |||
| 161 | totalTime -= 1000; | ||
| 162 | // console.log(totalTime) | ||
| 163 | } else { | ||
| 164 | clearInterval(order.timer); // 停止调用函数 | ||
| 165 | } | ||
| 166 | }, 1000); | ||
| 167 | } | ||
| 168 | }, | ||
| 169 | }); | ||
| 170 | |||
| 171 | watch( | ||
| 172 | () => order.noPay, | ||
| 173 | (val) => { | ||
| 174 | if (val) { | ||
| 175 | order.countDown(val.payEndTime); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | ); | ||
| 179 | |||
| 180 | onUnmounted(() => { | ||
| 181 | clearInterval(order.timer); | ||
| 182 | }); | ||
| 183 | |||
| 184 | // 用户免登录 | ||
| 185 | const login = async () => { | ||
| 186 | const userId = userStore.user?.userId; | ||
| 187 | const sign = md5(`uid=${userId}lgo1acfkw51jfo`, 32); | ||
| 188 | return loginFree({ | ||
| 189 | userId: userId, | ||
| 190 | sign, | ||
| 191 | }).then((res) => { | ||
| 192 | setToken(res.data.token); | ||
| 193 | order.fetchData(); | ||
| 194 | }); | ||
| 195 | }; | ||
| 196 | onMounted(() => { | ||
| 197 | login(); | ||
| 198 | }); | ||
| 199 | </script> | ||
| 200 | |||
| 201 | <template> | ||
| 202 | <div class="container"> | ||
| 203 | <div | ||
| 204 | v-for="(it, index) in order.data" | ||
| 205 | :key="index" | ||
| 206 | @click=" | ||
| 207 | $router.push({ | ||
| 208 | path: '/seat/order_detail', | ||
| 209 | query: { orderSn: it.orderSn, id: it.actId }, | ||
| 210 | }) | ||
| 211 | " | ||
| 212 | class="order-item" | ||
| 213 | > | ||
| 214 | <div class="info_box"> | ||
| 215 | <img class="cover_img" :src="it.coverImg" /> | ||
| 216 | <div class="info"> | ||
| 217 | <div class="title">{{ it.name }}</div> | ||
| 218 | <div class="common"> | ||
| 219 | {{ languageFormat(language, "时间", "Event Date & Time") }}:{{ | ||
| 220 | it.dateStr | ||
| 221 | }} | ||
| 222 | </div> | ||
| 223 | <div class="common"> | ||
| 224 | {{ languageFormat(language, "地址", "Location") }}:{{ | ||
| 225 | it.placeName | ||
| 226 | }} | ||
| 227 | </div> | ||
| 228 | <div class="common"> | ||
| 229 | {{ languageFormat(language, "订单编号", "Order No.") }}:{{ | ||
| 230 | it.orderSn | ||
| 231 | }} | ||
| 232 | </div> | ||
| 233 | <div class="common"> | ||
| 234 | {{ languageFormat(language, "张数", "Location") }}:{{ it.ticketNum | ||
| 235 | }}{{ languageFormat(language, "张", "tickets") }} | ||
| 236 | </div> | ||
| 237 | <div class="common"> | ||
| 238 | {{ languageFormat(language, "金额", "Ticket Price") }}:<span | ||
| 239 | v-if="language == 0" | ||
| 240 | >¥</span | ||
| 241 | >{{ it.payAmount }} | ||
| 242 | </div> | ||
| 243 | <div class="status"> | ||
| 244 | <div class="label"> | ||
| 245 | {{ languageFormat(language, "订单状态", "Order Status") }}: | ||
| 246 | </div> | ||
| 247 | <div class="value"> | ||
| 248 | <div | ||
| 249 | :style="{ | ||
| 250 | borderColor: status[it.state].color, | ||
| 251 | background: status[it.state].bgColor, | ||
| 252 | color: status[it.state].color, | ||
| 253 | }" | ||
| 254 | class="tag" | ||
| 255 | > | ||
| 256 | {{ | ||
| 257 | language == 0 ? status[it.state].txt : status[it.state].txt_en | ||
| 258 | }} | ||
| 259 | </div> | ||
| 260 | <div v-if="it.state == 0" class="tip"> | ||
| 261 | <span v-if="language == 0" | ||
| 262 | >请尽快完成支付,还剩{{ order.minutes }}分{{ | ||
| 263 | order.seconds | ||
| 264 | }}秒</span | ||
| 265 | > | ||
| 266 | <span v-else | ||
| 267 | >Time left {{ order.minutes }}:{{ order.seconds }}</span | ||
| 268 | > | ||
| 269 | </div> | ||
| 270 | </div> | ||
| 271 | </div> | ||
| 272 | </div> | ||
| 273 | </div> | ||
| 274 | <div v-if="it.state == 0" class="btn_box"> | ||
| 275 | <div class="pay">立即支付</div> | ||
| 276 | <div class="can_pay" @click.stop="order.cancelPayment(it)"> | ||
| 277 | 取消支付 | ||
| 278 | </div> | ||
| 279 | </div> | ||
| 280 | </div> | ||
| 281 | |||
| 282 | <div class="pagination"> | ||
| 283 | <el-pagination | ||
| 284 | v-show="order.total > 0" | ||
| 285 | v-model:current-page="order.pageNo" | ||
| 286 | v-model:page-size="order.pageSize" | ||
| 287 | background | ||
| 288 | layout="prev, pager, next" | ||
| 289 | :total="order.total" | ||
| 290 | @current-change="order.fetchData()" | ||
| 291 | /> | ||
| 292 | </div> | ||
| 293 | |||
| 294 | <el-dialog | ||
| 295 | v-model="order.showCodeDialog" | ||
| 296 | title="支付" | ||
| 297 | width="300" | ||
| 298 | @closed="order.handleClose()" | ||
| 299 | > | ||
| 300 | <div> | ||
| 301 | <img class="qrcode" :src="order.qrCodeData" /> | ||
| 302 | </div> | ||
| 303 | </el-dialog> | ||
| 304 | </div> | ||
| 305 | </template> | ||
| 306 | |||
| 307 | <style scoped lang="scss"> | ||
| 308 | .qrcode { | ||
| 309 | width: 150px; | ||
| 310 | height: 150px; | ||
| 311 | margin: 0 auto; | ||
| 312 | } | ||
| 313 | .container { | ||
| 314 | width: 1200px; | ||
| 315 | margin: 0 auto; | ||
| 316 | padding: 26px 0; | ||
| 317 | font-family: SourceHanSansCN, SourceHanSansCN; | ||
| 318 | .order-item { | ||
| 319 | display: flex; | ||
| 320 | justify-content: space-between; | ||
| 321 | align-items: center; | ||
| 322 | padding: 36px; | ||
| 323 | background: #fff; | ||
| 324 | box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08); | ||
| 325 | border-radius: 8px; | ||
| 326 | margin-bottom: 30px; | ||
| 327 | cursor: pointer; | ||
| 328 | .info_box { | ||
| 329 | display: flex; | ||
| 330 | gap: 20px; | ||
| 331 | .cover_img { | ||
| 332 | width: 155px; | ||
| 333 | height: 200px; | ||
| 334 | object-fit: fill; | ||
| 335 | } | ||
| 336 | .info { | ||
| 337 | .title { | ||
| 338 | font-weight: bold; | ||
| 339 | font-size: 22px; | ||
| 340 | color: #000000; | ||
| 341 | line-height: 33px; | ||
| 342 | margin-bottom: 25px; | ||
| 343 | margin-bottom: 10px; | ||
| 344 | } | ||
| 345 | .common { | ||
| 346 | font-weight: 500; | ||
| 347 | font-size: 16px; | ||
| 348 | color: #4e4e4e; | ||
| 349 | margin-bottom: 6px; | ||
| 350 | } | ||
| 351 | .status { | ||
| 352 | display: flex; | ||
| 353 | |||
| 354 | .label { | ||
| 355 | font-weight: 500; | ||
| 356 | font-size: 16px; | ||
| 357 | color: #4e4e4e; | ||
| 358 | line-height: 24px; | ||
| 359 | } | ||
| 360 | .value { | ||
| 361 | display: flex; | ||
| 362 | align-items: center; | ||
| 363 | gap: 20px; | ||
| 364 | .tag { | ||
| 365 | padding: 6px 14px; | ||
| 366 | border-radius: 6px; | ||
| 367 | border: 1px solid #34c759; | ||
| 368 | } | ||
| 369 | .tip { | ||
| 370 | font-size: 16px; | ||
| 371 | color: #f740a6; | ||
| 372 | line-height: 24px; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | .btn_box { | ||
| 379 | display: flex; | ||
| 380 | flex-direction: column; | ||
| 381 | gap: 12px; | ||
| 382 | .pay { | ||
| 383 | width: 175px; | ||
| 384 | height: 40px; | ||
| 385 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 386 | border-radius: 20px; | ||
| 387 | font-weight: 500; | ||
| 388 | font-size: 16px; | ||
| 389 | color: #ffffff; | ||
| 390 | line-height: 40px; | ||
| 391 | text-align: center; | ||
| 392 | cursor: pointer; | ||
| 393 | } | ||
| 394 | .can_pay { | ||
| 395 | width: 175px; | ||
| 396 | height: 40px; | ||
| 397 | background: #fff; | ||
| 398 | border-radius: 20px; | ||
| 399 | font-weight: 500; | ||
| 400 | font-size: 16px; | ||
| 401 | color: #493ceb; | ||
| 402 | line-height: 40px; | ||
| 403 | border: 1px solid #493ceb; | ||
| 404 | text-align: center; | ||
| 405 | box-sizing: border-box; | ||
| 406 | cursor: pointer; | ||
| 407 | } | ||
| 408 | } | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | .pagination { | ||
| 413 | display: flex; | ||
| 414 | justify-content: center; | ||
| 415 | } | ||
| 416 | </style> |
src/viewsPc/seat/people-manage.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { deleteViewPeople, viewPeopleList } from "./api/index.js"; | ||
| 3 | import { ElMessageBox, ElMessage } from "element-plus"; | ||
| 4 | import { languageFormat } from "./utils/language.js"; | ||
| 5 | import { useStorage } from "@vueuse/core/index"; | ||
| 6 | const language = useStorage("language", 0); | ||
| 7 | |||
| 8 | const audience = reactive({ | ||
| 9 | data: [], | ||
| 10 | fetchData() { | ||
| 11 | viewPeopleList().then((res) => { | ||
| 12 | audience.data = res.data; | ||
| 13 | }); | ||
| 14 | }, | ||
| 15 | |||
| 16 | deletePeople(id) { | ||
| 17 | ElMessageBox.confirm( | ||
| 18 | languageFormat( | ||
| 19 | language.value, | ||
| 20 | "确认删除该观看人吗?", | ||
| 21 | "Are you sure to delete this viewer?" | ||
| 22 | ), | ||
| 23 | languageFormat(language.value, "提示", "Reminder"), | ||
| 24 | { | ||
| 25 | confirmButtonText: languageFormat(language.value, "确认", "confirm"), | ||
| 26 | cancelButtonText: languageFormat(language.value, "取消", "cancel"), | ||
| 27 | type: "warning", | ||
| 28 | draggable: true, | ||
| 29 | } | ||
| 30 | ) | ||
| 31 | .then(() => { | ||
| 32 | deleteViewPeople({ id }).then(() => { | ||
| 33 | audience.fetchData(); | ||
| 34 | ElMessage({ | ||
| 35 | type: "success", | ||
| 36 | message: languageFormat( | ||
| 37 | language.value, | ||
| 38 | "操作成功", | ||
| 39 | "Operate successfully" | ||
| 40 | ), | ||
| 41 | }); | ||
| 42 | }); | ||
| 43 | }) | ||
| 44 | .catch(() => {}); | ||
| 45 | }, | ||
| 46 | }); | ||
| 47 | |||
| 48 | audience.fetchData(); | ||
| 49 | </script> | ||
| 50 | |||
| 51 | <template> | ||
| 52 | <div class="container"> | ||
| 53 | <div class="title"> | ||
| 54 | <div | ||
| 55 | class="add_btn" | ||
| 56 | @click="$router.push({ path: '/seat/add_watch_people' })" | ||
| 57 | > | ||
| 58 | {{ languageFormat(language, "新增", "Add") }} | ||
| 59 | </div> | ||
| 60 | {{ languageFormat(language, "观影人管理", "Viewers") }} | ||
| 61 | </div> | ||
| 62 | <div class="content"> | ||
| 63 | <div class="people_box"> | ||
| 64 | <div | ||
| 65 | v-for="(it, index) in audience.data" | ||
| 66 | :key="index" | ||
| 67 | class="people_item" | ||
| 68 | > | ||
| 69 | <div class="name">{{ it.name }}</div> | ||
| 70 | <div class="idcard"> | ||
| 71 | {{ languageFormat(language, "身份证", "Identity Card") }}:{{ | ||
| 72 | it.idCard | ||
| 73 | }} | ||
| 74 | </div> | ||
| 75 | <div class="btn" @click="audience.deletePeople(it.id)"> | ||
| 76 | {{ languageFormat(language, "删除", "delete") }} | ||
| 77 | </div> | ||
| 78 | </div> | ||
| 79 | </div> | ||
| 80 | </div> | ||
| 81 | </div> | ||
| 82 | </template> | ||
| 83 | |||
| 84 | <style scoped lang="scss"> | ||
| 85 | div { | ||
| 86 | box-sizing: border-box; | ||
| 87 | } | ||
| 88 | .container { | ||
| 89 | padding: 20px 0; | ||
| 90 | width: 1200px; | ||
| 91 | margin: 0 auto; | ||
| 92 | |||
| 93 | .title { | ||
| 94 | position: relative; | ||
| 95 | padding: 11px; | ||
| 96 | text-align: center; | ||
| 97 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 98 | font-size: 18px; | ||
| 99 | color: #ffffff; | ||
| 100 | .add_btn { | ||
| 101 | position: absolute; | ||
| 102 | left: 20px; | ||
| 103 | top: 50%; | ||
| 104 | transform: translateY(-50%); | ||
| 105 | width: 68px; | ||
| 106 | height: 24px; | ||
| 107 | border-radius: 12px; | ||
| 108 | border: 1px solid #ffffff; | ||
| 109 | font-weight: 400; | ||
| 110 | font-size: 12px; | ||
| 111 | color: #ffffff; | ||
| 112 | text-align: center; | ||
| 113 | line-height: 24px; | ||
| 114 | box-sizing: border-box; | ||
| 115 | user-select: none; | ||
| 116 | cursor: pointer; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | .content { | ||
| 121 | min-height: 590px; | ||
| 122 | background-color: #fff; | ||
| 123 | box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08); | ||
| 124 | padding: 20px; | ||
| 125 | .people_box { | ||
| 126 | display: flex; | ||
| 127 | flex-wrap: wrap; | ||
| 128 | gap: 20px; | ||
| 129 | .people_item { | ||
| 130 | width: 275px; | ||
| 131 | height: 137px; | ||
| 132 | background: #ffffff; | ||
| 133 | border: 1px solid #dcdfe6; | ||
| 134 | padding: 16px; | ||
| 135 | .name { | ||
| 136 | font-weight: 600; | ||
| 137 | font-size: 16px; | ||
| 138 | color: #2d373f; | ||
| 139 | line-height: 22px; | ||
| 140 | } | ||
| 141 | .idcard { | ||
| 142 | font-size: 16px; | ||
| 143 | color: #95a1a6; | ||
| 144 | line-height: 22px; | ||
| 145 | margin-top: 12px; | ||
| 146 | margin-bottom: 17px; | ||
| 147 | } | ||
| 148 | .btn { | ||
| 149 | width: 69px; | ||
| 150 | height: 32px; | ||
| 151 | background: #e7e6ff; | ||
| 152 | font-weight: 400; | ||
| 153 | font-size: 16px; | ||
| 154 | color: #493ceb; | ||
| 155 | line-height: 32px; | ||
| 156 | text-align: center; | ||
| 157 | cursor: pointer; | ||
| 158 | user-select: none; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | } | ||
| 163 | } | ||
| 164 | </style> |
src/viewsPc/seat/seat-picker.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import { ElMessage } from "element-plus"; | ||
| 3 | import { getPriceLevelInfo, getSiteConfig, confirmOrder } from "./api/index.js"; | ||
| 4 | import { languageFormat } from "./utils/language.js"; | ||
| 5 | import { useStorage } from "@vueuse/core/index"; | ||
| 6 | const language = useStorage("language", 0); | ||
| 7 | |||
| 8 | const route = useRoute(); | ||
| 9 | const router = useRouter(); | ||
| 10 | |||
| 11 | const iframeRef = ref(); | ||
| 12 | |||
| 13 | const props = defineProps({ | ||
| 14 | activityId: [String, Number], | ||
| 15 | }); | ||
| 16 | |||
| 17 | // 获取票档 | ||
| 18 | const price = reactive({ | ||
| 19 | curPriceId: route.query.ticket_block, | ||
| 20 | data: [], | ||
| 21 | |||
| 22 | fetchData() { | ||
| 23 | getPriceLevelInfo({ | ||
| 24 | actId: props.activityId ?? 1, | ||
| 25 | sessionId: route.query.sessionId, | ||
| 26 | openType: route.query.openType, | ||
| 27 | sitePlace: route.query.sitePlace, | ||
| 28 | ticketType: route.query.ticketType, | ||
| 29 | }).then((res) => { | ||
| 30 | this.data = res.data; | ||
| 31 | // price.curPriceId = route.query.ticket_block | ||
| 32 | }); | ||
| 33 | }, | ||
| 34 | onClickPrice(e) { | ||
| 35 | if (selectedSeats.value?.length) { | ||
| 36 | return ElMessage({ type: "warning", message: "请先取消已选座位" }); | ||
| 37 | } | ||
| 38 | price.curPriceId = e.priceId; | ||
| 39 | }, | ||
| 40 | }); | ||
| 41 | |||
| 42 | // 座位禁用时图标地址 | ||
| 43 | const disabledIconUrl = | ||
| 44 | "https://radv4.gitliuyi.top/images/20240511/unselect_default.png"; | ||
| 45 | |||
| 46 | function onWindowMessage(e) { | ||
| 47 | const data = e.data; | ||
| 48 | |||
| 49 | if (data.type == "picker-ready") { | ||
| 50 | // apiPromise.then(() => {}) | ||
| 51 | |||
| 52 | siteConfig.fetchData().then((res) => { | ||
| 53 | const seat_arr = res.map((it) => { | ||
| 54 | let result = { | ||
| 55 | ...it, | ||
| 56 | active: 0, | ||
| 57 | }; | ||
| 58 | Object.assign(result, getSeatRenderState(result)); | ||
| 59 | return result; | ||
| 60 | }); | ||
| 61 | // 子页面加载完毕,这里iframeRef一定ok | ||
| 62 | sendMsg("load-seats", seat_arr); | ||
| 63 | setTimeout(() => { | ||
| 64 | moveToPriceArea(route.query.ticket_block); | ||
| 65 | }, 500); | ||
| 66 | }); | ||
| 67 | |||
| 68 | // 绘制舞台矩形 | ||
| 69 | sendMsg("draw-object-rectangle", { | ||
| 70 | x: 1800, | ||
| 71 | y: 960, | ||
| 72 | w: 4400, | ||
| 73 | h: 1300, | ||
| 74 | color: "#e0e0e0", | ||
| 75 | }); | ||
| 76 | // 绘制舞台文字 | ||
| 77 | sendMsg("draw-object-text", { | ||
| 78 | x: 3900, | ||
| 79 | y: 1500, | ||
| 80 | text: language.value == 0 ? "舞台" : "stage", | ||
| 81 | style: { fontSize: 160, fontWeight: "400", fill: "#6a6a6a" }, | ||
| 82 | }); | ||
| 83 | } else if (data.type == "seat-click") { | ||
| 84 | // 子页面点击了座位 | ||
| 85 | const seatData = data.data; | ||
| 86 | console.log("座位点击", seatData); | ||
| 87 | |||
| 88 | // 如果座位处于不可点击状态,就return | ||
| 89 | if (seatData.state != 1) return; | ||
| 90 | |||
| 91 | // 如果当前筛选了某种座位,点击的不是这种座位,也返回 | ||
| 92 | if (price.curPriceId && seatData.priceId != price.curPriceId) return; | ||
| 93 | |||
| 94 | if ( | ||
| 95 | selectedSeats.value && | ||
| 96 | selectedSeats.value?.length >= 5 && | ||
| 97 | seatData.active == 0 | ||
| 98 | ) | ||
| 99 | return ElMessage({ | ||
| 100 | type: "warning", | ||
| 101 | message: languageFormat( | ||
| 102 | language.value, | ||
| 103 | "最多选择5个座位", | ||
| 104 | "Selectt at most 5 seats" | ||
| 105 | ), | ||
| 106 | }); | ||
| 107 | |||
| 108 | const newActive = seatData.active == 0 ? 1 : 0; | ||
| 109 | const siteConfigItem = siteConfig.data.find((it) => it.id == seatData.id); | ||
| 110 | if (siteConfigItem) { | ||
| 111 | siteConfigItem.active = newActive; | ||
| 112 | } | ||
| 113 | sendMsg("update-seat", { | ||
| 114 | id: seatData.id, | ||
| 115 | data: { | ||
| 116 | active: newActive, | ||
| 117 | ...getSeatRenderState(siteConfigItem), | ||
| 118 | }, | ||
| 119 | }); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | const siteConfig = reactive({ | ||
| 124 | loading: false, | ||
| 125 | data: [], | ||
| 126 | fetchData() { | ||
| 127 | return getSiteConfig({ | ||
| 128 | actId: props.activityId ?? 1, | ||
| 129 | openType: route.query.openType, | ||
| 130 | sessionId: route.query.sessionId, | ||
| 131 | sitePlace: route.query.sitePlace, | ||
| 132 | ticketType: route.query.ticketType, | ||
| 133 | }).then((res) => { | ||
| 134 | const gridSize = 40; | ||
| 135 | const seat_arr = res.data.map((it, index) => { | ||
| 136 | return { | ||
| 137 | ...it, | ||
| 138 | // 这几个是iframe引擎渲染座位必须的属性,规定好的 | ||
| 139 | x: gridSize * it.x, | ||
| 140 | y: gridSize * it.y, | ||
| 141 | w: gridSize, | ||
| 142 | h: gridSize, | ||
| 143 | icon: it.state == 1 ? it.unSelectIcon : disabledIconUrl, // 图片的url | ||
| 144 | active: 0, // 是否选中 | ||
| 145 | priceId: route.query.openType == 0 ? it.dayPriceId : it.nightPriceId, | ||
| 146 | }; | ||
| 147 | }); | ||
| 148 | siteConfig.data = seat_arr; | ||
| 149 | return seat_arr; | ||
| 150 | }); | ||
| 151 | }, | ||
| 152 | }); | ||
| 153 | |||
| 154 | watch( | ||
| 155 | () => price.curPriceId, | ||
| 156 | (priceId) => { | ||
| 157 | siteConfig.data.forEach((it) => { | ||
| 158 | sendMsg("update-seat", { | ||
| 159 | id: it.id, | ||
| 160 | data: { | ||
| 161 | ...getSeatRenderState(it), | ||
| 162 | }, | ||
| 163 | }); | ||
| 164 | }); | ||
| 165 | moveToPriceArea(priceId); | ||
| 166 | console.log("update完成"); | ||
| 167 | } | ||
| 168 | // { immediate: true } | ||
| 169 | ); | ||
| 170 | |||
| 171 | const sendMsg = (type, data) => | ||
| 172 | iframeRef.value?.contentWindow.postMessage({ type: type, data: data }, "*"); | ||
| 173 | |||
| 174 | const getSeatRenderState = (seat) => { | ||
| 175 | const { state, selectIcon, unSelectIcon } = seat; | ||
| 176 | const opacity = state == 0 || price.curPriceId == seat.priceId ? 1 : 0.3; | ||
| 177 | if (state != 1) return { icon: disabledIconUrl, opacity }; | ||
| 178 | return { icon: seat?.active ? selectIcon : unSelectIcon, opacity }; | ||
| 179 | }; | ||
| 180 | |||
| 181 | /** 平移到某个价格区域 */ | ||
| 182 | const moveToPriceArea = (priceId) => { | ||
| 183 | const priceSeats = siteConfig.data.filter((it) => it.priceId == priceId); | ||
| 184 | // 计算出x和y最小的值 | ||
| 185 | const minX = Math.min(...priceSeats.map((it) => it.x)); | ||
| 186 | const minY = Math.min(...priceSeats.map((it) => it.y)); | ||
| 187 | |||
| 188 | const offset = { | ||
| 189 | x: 40, | ||
| 190 | y: 200, | ||
| 191 | }; | ||
| 192 | |||
| 193 | sendMsg("stage-scale-to", { scale: 1 }); | ||
| 194 | setTimeout(() => { | ||
| 195 | sendMsg("stage-move-to", { x: offset.x - minX, y: offset.y - minY }); | ||
| 196 | }, 500); | ||
| 197 | }; | ||
| 198 | |||
| 199 | const deleteSiteConfigItem = (seatData) => { | ||
| 200 | const newActive = seatData.active == 0 ? 1 : 0; | ||
| 201 | const siteConfigItem = siteConfig.data.find((it) => it.id == seatData.id); | ||
| 202 | if (siteConfigItem) { | ||
| 203 | siteConfigItem.active = newActive; | ||
| 204 | } | ||
| 205 | sendMsg("update-seat", { | ||
| 206 | id: seatData.id, | ||
| 207 | data: { | ||
| 208 | active: newActive, | ||
| 209 | ...getSeatRenderState(siteConfigItem), | ||
| 210 | }, | ||
| 211 | }); | ||
| 212 | }; | ||
| 213 | |||
| 214 | /** 所选座位 */ | ||
| 215 | const selectedSeats = | ||
| 216 | computed(() => siteConfig.data.filter((it) => it.active == 1)) ?? []; | ||
| 217 | |||
| 218 | /** 所选座位价格 */ | ||
| 219 | const sumPrice = computed(() => { | ||
| 220 | return selectedSeats.value.reduce((total, item) => { | ||
| 221 | const price = | ||
| 222 | route.query.openType == 0 | ||
| 223 | ? Number(item.dayPrice) | ||
| 224 | : Number(item.nightPrice); | ||
| 225 | return total + price; | ||
| 226 | }, 0); | ||
| 227 | }); | ||
| 228 | |||
| 229 | const toConfirmOrder = () => { | ||
| 230 | const seatIds = selectedSeats.value.map((it) => it.id); | ||
| 231 | if (!seatIds.length) | ||
| 232 | return ElMessage({ | ||
| 233 | type: "warning", | ||
| 234 | message: languageFormat( | ||
| 235 | language, | ||
| 236 | "请先选择座位", | ||
| 237 | "Please select the seat first." | ||
| 238 | ), | ||
| 239 | }); | ||
| 240 | confirmOrder({ | ||
| 241 | actId: props.activityId, | ||
| 242 | openType: route.query.openType, | ||
| 243 | sessionId: route.query.sessionId, | ||
| 244 | sitePlace: route.query.sitePlace, | ||
| 245 | ticketType: route.query.ticketType, | ||
| 246 | seatIds: seatIds, | ||
| 247 | }) | ||
| 248 | .then((res) => { | ||
| 249 | router.push({ | ||
| 250 | path: "/seat/confirm_order", | ||
| 251 | query: { | ||
| 252 | id: props.activityId, | ||
| 253 | openType: route.query.openType, | ||
| 254 | sessionId: route.query.sessionId, | ||
| 255 | sitePlace: route.query.sitePlace, | ||
| 256 | ticketType: route.query.ticketType, | ||
| 257 | seatIds: seatIds.join(","), | ||
| 258 | }, | ||
| 259 | }); | ||
| 260 | }) | ||
| 261 | .catch((e) => { | ||
| 262 | if (e.code == "B001") { | ||
| 263 | router.push({ | ||
| 264 | path: "/seat/order", | ||
| 265 | query: { | ||
| 266 | id: props.activityId, | ||
| 267 | }, | ||
| 268 | }); | ||
| 269 | } | ||
| 270 | }); | ||
| 271 | }; | ||
| 272 | |||
| 273 | /** | ||
| 274 | * 1. 加載iframe 3. 请求API的数据 | ||
| 275 | * 2. 等待iframe里面资源加载完毕并触发picker-ready事件 | ||
| 276 | * 4. 传递数据给iframe,等待渲染 | ||
| 277 | */ | ||
| 278 | |||
| 279 | window.addEventListener("message", onWindowMessage); | ||
| 280 | |||
| 281 | onBeforeUnmount(() => { | ||
| 282 | window.removeEventListener("message", onWindowMessage); | ||
| 283 | }); | ||
| 284 | |||
| 285 | price.fetchData(); | ||
| 286 | </script> | ||
| 287 | |||
| 288 | <template> | ||
| 289 | <div class="container"> | ||
| 290 | <div class="top"> | ||
| 291 | <div class="time"> | ||
| 292 | <span>{{ route.query?.time_txt }}</span> | ||
| 293 | <span class="place">{{ route.query.sitePlace }}</span> | ||
| 294 | </div> | ||
| 295 | <div class="price_tab"> | ||
| 296 | <div | ||
| 297 | v-for="(it, index) in price.data" | ||
| 298 | class="tab_item" | ||
| 299 | :class="{ tabActive: it.priceId == price.curPriceId }" | ||
| 300 | @click="price.onClickPrice(it)" | ||
| 301 | > | ||
| 302 | <img class="seat" :src="it.unSelectIcon" /> | ||
| 303 | <span class="price" | ||
| 304 | >{{ it.price }}<span v-if="language == 0">¥</span></span | ||
| 305 | > | ||
| 306 | </div> | ||
| 307 | </div> | ||
| 308 | </div> | ||
| 309 | |||
| 310 | <div v-if="selectedSeats?.length" class="bottom"> | ||
| 311 | <div class="seat_box"> | ||
| 312 | <!-- v-for="(it, index) in selectedSeats" --> | ||
| 313 | <div v-for="(it, index) in selectedSeats" class="seat_item"> | ||
| 314 | <img class="seat_icon" :src="it.selectIcon" /> | ||
| 315 | <span class="num" | ||
| 316 | >{{ it.area }}{{ languageFormat(language, "区", "Zones") }} | ||
| 317 | {{ it.pai }}{{ languageFormat(language, "排", "Row") }} {{ it.no }} | ||
| 318 | {{ languageFormat(language, "座", "Seat") }}</span | ||
| 319 | > | ||
| 320 | <el-icon | ||
| 321 | style="cursor: pointer" | ||
| 322 | color="#ccc" | ||
| 323 | @click="deleteSiteConfigItem(it)" | ||
| 324 | ><CircleCloseFilled | ||
| 325 | /></el-icon> | ||
| 326 | </div> | ||
| 327 | </div> | ||
| 328 | <div class="pay"> | ||
| 329 | <div class="sum">¥{{ sumPrice?.toFixed(2) }}</div> | ||
| 330 | <div class="pay_btn" @click="toConfirmOrder()"> | ||
| 331 | {{ languageFormat(language, "立即购买", "Continue") }} | ||
| 332 | </div> | ||
| 333 | </div> | ||
| 334 | </div> | ||
| 335 | |||
| 336 | <div class="iframeBox"> | ||
| 337 | <iframe | ||
| 338 | ref="iframeRef" | ||
| 339 | class="iframe" | ||
| 340 | id="iframe" | ||
| 341 | src="https://seat-choose.parent4relax.com/#/seat-picker" | ||
| 342 | ></iframe> | ||
| 343 | </div> | ||
| 344 | </div> | ||
| 345 | </template> | ||
| 346 | |||
| 347 | <style scoped lang="scss"> | ||
| 348 | .container { | ||
| 349 | width: 1200px; | ||
| 350 | margin: 0 auto; | ||
| 351 | padding: 20px; | ||
| 352 | |||
| 353 | .top { | ||
| 354 | width: 100%; | ||
| 355 | background-color: #fff; | ||
| 356 | padding: 20px; | ||
| 357 | margin-bottom: 10px; | ||
| 358 | border-radius: 6px; | ||
| 359 | .time { | ||
| 360 | font-size: 18px; | ||
| 361 | font-weight: 600; | ||
| 362 | margin-bottom: 10px; | ||
| 363 | .place { | ||
| 364 | color: #7e8489; | ||
| 365 | margin-left: 15px; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | .price_tab { | ||
| 370 | display: flex; | ||
| 371 | align-items: center; | ||
| 372 | flex-wrap: wrap; | ||
| 373 | gap: 10px; | ||
| 374 | .tabActive { | ||
| 375 | background: #eeeeee !important; | ||
| 376 | border: 2px solid #7e8489 !important; | ||
| 377 | } | ||
| 378 | .tab_item { | ||
| 379 | display: flex; | ||
| 380 | align-items: center; | ||
| 381 | padding: 10px 14px; | ||
| 382 | background: #f5f7f8; | ||
| 383 | border-radius: 30px; | ||
| 384 | border: 2px solid #dcdedf; | ||
| 385 | font-size: 16px; | ||
| 386 | color: #646666; | ||
| 387 | cursor: pointer; | ||
| 388 | user-select: none; | ||
| 389 | |||
| 390 | .seat { | ||
| 391 | width: 14px; | ||
| 392 | height: 14px; | ||
| 393 | margin-right: 5px; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } | ||
| 397 | } | ||
| 398 | |||
| 399 | .iframeBox { | ||
| 400 | border-radius: 6px; | ||
| 401 | background-color: #fff; | ||
| 402 | padding: 20px; | ||
| 403 | margin-bottom: 20px; | ||
| 404 | } | ||
| 405 | |||
| 406 | .iframe { | ||
| 407 | width: 100%; | ||
| 408 | height: 500px; | ||
| 409 | border: none; | ||
| 410 | background-color: #f7f8fa; | ||
| 411 | } | ||
| 412 | |||
| 413 | .bottom { | ||
| 414 | border-radius: 6px; | ||
| 415 | background-color: #fff; | ||
| 416 | padding: 20px; | ||
| 417 | margin-bottom: 20px; | ||
| 418 | .seat_box { | ||
| 419 | display: flex; | ||
| 420 | flex-wrap: wrap; | ||
| 421 | gap: 10px; | ||
| 422 | width: 100%; | ||
| 423 | .seat_item { | ||
| 424 | display: flex; | ||
| 425 | align-items: center; | ||
| 426 | padding: 10px 14px; | ||
| 427 | font-size: 16px; | ||
| 428 | color: #29343c; | ||
| 429 | background: #eeeeee; | ||
| 430 | border-radius: 30px; | ||
| 431 | border: 2px solid #7e8489; | ||
| 432 | user-select: none; | ||
| 433 | .seat_icon { | ||
| 434 | width: 14px; | ||
| 435 | height: 14px; | ||
| 436 | margin-right: 5px; | ||
| 437 | } | ||
| 438 | .num { | ||
| 439 | margin-right: 5px; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | .pay { | ||
| 445 | display: flex; | ||
| 446 | justify-content: space-between; | ||
| 447 | align-items: center; | ||
| 448 | margin-top: 10px; | ||
| 449 | .sum { | ||
| 450 | font-weight: 600; | ||
| 451 | font-size: 22px; | ||
| 452 | color: #493ceb; | ||
| 453 | } | ||
| 454 | .pay_btn { | ||
| 455 | width: 200px; | ||
| 456 | height: 40px; | ||
| 457 | background: #493ceb; | ||
| 458 | border-radius: 20px; | ||
| 459 | margin-top: 10px; | ||
| 460 | font-size: 14px; | ||
| 461 | color: #fff; | ||
| 462 | line-height: 40px; | ||
| 463 | text-align: center; | ||
| 464 | cursor: pointer; | ||
| 465 | font-weight: 600; | ||
| 466 | user-select: none; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | } | ||
| 470 | } | ||
| 471 | </style> |
src/viewsPc/seat/seat.vue
0 → 100644
src/viewsPc/seat/ticket-detail.vue
0 → 100644
| 1 | <script setup> | ||
| 2 | import dayjs from "dayjs"; | ||
| 3 | import useUserStore from "@/store/modules/user"; | ||
| 4 | import { setToken, getToken } from "./utils/local-store.js"; | ||
| 5 | import { md5 } from "md5js"; | ||
| 6 | import { ElMessageBox, ElMessage } from "element-plus"; | ||
| 7 | import { | ||
| 8 | loginFree, | ||
| 9 | activityDetail, | ||
| 10 | sessionDetail, | ||
| 11 | getSitePlaceInfo, | ||
| 12 | getPriceLevelInfo, | ||
| 13 | } from "./api/index.js"; | ||
| 14 | import { languageFormat } from "./utils/language.js"; | ||
| 15 | import { useStorage } from "@vueuse/core/index"; | ||
| 16 | const language = useStorage("language", 0); | ||
| 17 | |||
| 18 | const route = useRoute(); | ||
| 19 | const router = useRouter(); | ||
| 20 | const userStore = useUserStore(); | ||
| 21 | |||
| 22 | const props = defineProps({ | ||
| 23 | activityId: [String, Number], | ||
| 24 | }); | ||
| 25 | |||
| 26 | // 用户免登录 | ||
| 27 | const login = async (userId) => { | ||
| 28 | const sign = md5(`uid=${userId}lgo1acfkw51jfo`, 32); | ||
| 29 | return loginFree({ | ||
| 30 | userId: userId, | ||
| 31 | sign, | ||
| 32 | }).then((res) => { | ||
| 33 | setToken(res.data.token); | ||
| 34 | }); | ||
| 35 | }; | ||
| 36 | |||
| 37 | const select_form = reactive({ | ||
| 38 | venueItem: { | ||
| 39 | id: 0, | ||
| 40 | dateStr: "", | ||
| 41 | dayOpen: 1, | ||
| 42 | nightOpen: 1, | ||
| 43 | type: 0, | ||
| 44 | }, // 所选场次 | ||
| 45 | session: -1, // 日/夜场 0:日场 1:夜场 | ||
| 46 | place: "", // 场馆 | ||
| 47 | ticket_block: 0, // 票档 | ||
| 48 | onClickVenue(e, index) { | ||
| 49 | if (e.state == 1) return; // 表示 | ||
| 50 | select_form.venueItem = e; | ||
| 51 | if ( | ||
| 52 | (e.dayOpen == 0 && select_form.session == 0) || | ||
| 53 | (e.nightOpen == 0 && select_form.session == 1) | ||
| 54 | ) { | ||
| 55 | select_form.session = -1; | ||
| 56 | select_form.place = ""; | ||
| 57 | select_form.ticket_block = 0; | ||
| 58 | } | ||
| 59 | }, | ||
| 60 | // 选择日/夜场 | ||
| 61 | onClickSession(e) { | ||
| 62 | if ( | ||
| 63 | (e == 0 && select_form.venueItem?.dayOpen == 1) || | ||
| 64 | (e == 1 && select_form.venueItem?.nightOpen == 1) | ||
| 65 | ) { | ||
| 66 | select_form.session = e; | ||
| 67 | // select_form.place = ""; | ||
| 68 | select_form.ticket_block = 0; | ||
| 69 | } | ||
| 70 | }, | ||
| 71 | // 选择场馆 | ||
| 72 | onClickPlace(e) { | ||
| 73 | if (e.state == 1) return; | ||
| 74 | select_form.place = e.placeName; | ||
| 75 | select_form.ticket_block = 0; | ||
| 76 | }, | ||
| 77 | // 选择票档 | ||
| 78 | onClickPrice(e) { | ||
| 79 | if (e.state == 1) return; | ||
| 80 | select_form.ticket_block = e.priceId; | ||
| 81 | }, | ||
| 82 | // 去选座 | ||
| 83 | async toSelectSeat() { | ||
| 84 | // 检查登录 | ||
| 85 | // const ticketUserToken = getToken(); | ||
| 86 | // if (!ticketUserToken) { | ||
| 87 | const userId = userStore.user?.userId; // userId | ||
| 88 | if (!userId) { | ||
| 89 | // 未登录,打开登录弹窗 | ||
| 90 | return userStore.setVisitor(); | ||
| 91 | } | ||
| 92 | // } | ||
| 93 | await login(userId); | ||
| 94 | |||
| 95 | if (!select_form.venueItem?.id) | ||
| 96 | return ElMessage({ | ||
| 97 | type: "warning", | ||
| 98 | message: languageFormat( | ||
| 99 | language.value, | ||
| 100 | "请选择时间", | ||
| 101 | "Please select the time" | ||
| 102 | ), | ||
| 103 | }); | ||
| 104 | if (select_form.session == -1) | ||
| 105 | return ElMessage({ | ||
| 106 | type: "warning", | ||
| 107 | message: languageFormat( | ||
| 108 | language.value, | ||
| 109 | "请选择场次", | ||
| 110 | "Please select the session" | ||
| 111 | ), | ||
| 112 | }); | ||
| 113 | if (!select_form.place) | ||
| 114 | return ElMessage({ | ||
| 115 | type: "warning", | ||
| 116 | message: languageFormat( | ||
| 117 | language.value, | ||
| 118 | "请选择场馆", | ||
| 119 | "Please choose the venue" | ||
| 120 | ), | ||
| 121 | }); | ||
| 122 | if (!select_form.ticket_block) | ||
| 123 | return ElMessage({ | ||
| 124 | type: "warning", | ||
| 125 | message: languageFormat( | ||
| 126 | language.value, | ||
| 127 | "请选择票档", | ||
| 128 | "Please choose the ticket category" | ||
| 129 | ), | ||
| 130 | }); | ||
| 131 | |||
| 132 | router.push({ | ||
| 133 | path: "/seat/seat_picker", | ||
| 134 | query: { | ||
| 135 | id: props.activityId, | ||
| 136 | openType: select_form.session, | ||
| 137 | sessionId: select_form.venueItem?.id, | ||
| 138 | sitePlace: select_form.place, | ||
| 139 | ticketType: select_form.venueItem?.type, | ||
| 140 | ticket_block: select_form.ticket_block, | ||
| 141 | time_txt: select_form.venueItem?.dateStr, | ||
| 142 | }, | ||
| 143 | }); | ||
| 144 | }, | ||
| 145 | }); | ||
| 146 | |||
| 147 | // 活动详情 | ||
| 148 | const detail = reactive({ | ||
| 149 | loading: false, | ||
| 150 | data: null, | ||
| 151 | fetchData() { | ||
| 152 | this.loading = true; | ||
| 153 | activityDetail({ actId: props.activityId }) | ||
| 154 | .then((res) => { | ||
| 155 | this.data = res.data; | ||
| 156 | }) | ||
| 157 | .finally(() => (this.loding = false)); | ||
| 158 | }, | ||
| 159 | }); | ||
| 160 | |||
| 161 | // 获取场次信息 | ||
| 162 | const timeVenue = reactive({ | ||
| 163 | loading: false, | ||
| 164 | data: [], | ||
| 165 | fetchData() { | ||
| 166 | this.loading = true; | ||
| 167 | sessionDetail({ actId: props.activityId }) | ||
| 168 | .then((res) => { | ||
| 169 | this.data = res.data; | ||
| 170 | }) | ||
| 171 | .finally(() => (this.loading = false)); | ||
| 172 | }, | ||
| 173 | }); | ||
| 174 | |||
| 175 | // 获取场馆 | ||
| 176 | const sitePlaceInfo = reactive({ | ||
| 177 | data: [ | ||
| 178 | { placeName: "B4", state: "0" }, | ||
| 179 | { placeName: "B6", state: "0" }, | ||
| 180 | ], | ||
| 181 | fetchData() { | ||
| 182 | console.log(select_form.venueItem?.id, select_form.session); | ||
| 183 | getSitePlaceInfo({ | ||
| 184 | sessionId: select_form.venueItem?.id, | ||
| 185 | openType: select_form.session, | ||
| 186 | }).then((res) => { | ||
| 187 | this.data = res.data; | ||
| 188 | }); | ||
| 189 | }, | ||
| 190 | }); | ||
| 191 | |||
| 192 | // 获取票档 | ||
| 193 | const price = reactive({ | ||
| 194 | data: [], | ||
| 195 | fetchData() { | ||
| 196 | getPriceLevelInfo({ | ||
| 197 | actId: props.activityId, | ||
| 198 | sessionId: select_form.venueItem?.id, | ||
| 199 | openType: select_form.session, | ||
| 200 | sitePlace: select_form.place, | ||
| 201 | ticketType: select_form.venueItem?.type, | ||
| 202 | }).then((res) => { | ||
| 203 | this.data = res.data; | ||
| 204 | }); | ||
| 205 | }, | ||
| 206 | }); | ||
| 207 | |||
| 208 | watchEffect(() => { | ||
| 209 | if (select_form.session != -1 && select_form.venueItem?.id) { | ||
| 210 | if (select_form.session == 1 && select_form.place == "B4") { | ||
| 211 | select_form.place = ""; | ||
| 212 | } | ||
| 213 | sitePlaceInfo.fetchData(); | ||
| 214 | } | ||
| 215 | }); | ||
| 216 | |||
| 217 | watchEffect(() => { | ||
| 218 | if ( | ||
| 219 | select_form.venueItem?.id && | ||
| 220 | select_form.session != -1 && | ||
| 221 | select_form.place | ||
| 222 | ) { | ||
| 223 | price.fetchData(); | ||
| 224 | } | ||
| 225 | }); | ||
| 226 | |||
| 227 | // 主流程开始 | ||
| 228 | watch( | ||
| 229 | () => props.activityId, | ||
| 230 | async (activityId) => { | ||
| 231 | if (!activityId) { | ||
| 232 | // [TODO] dialog提示缺少活動ID讓然後返回 | ||
| 233 | ElMessageBox.confirm("缺少活动id", "提示", { | ||
| 234 | confirmButtonText: "确认", | ||
| 235 | type: "warning", | ||
| 236 | showCancelButton: false, | ||
| 237 | draggable: true, | ||
| 238 | }).then((res) => { | ||
| 239 | router.push("/"); | ||
| 240 | }); | ||
| 241 | return; | ||
| 242 | } | ||
| 243 | |||
| 244 | detail.fetchData(); | ||
| 245 | timeVenue.fetchData(); | ||
| 246 | }, | ||
| 247 | { immediate: true } | ||
| 248 | ); | ||
| 249 | </script> | ||
| 250 | |||
| 251 | <template> | ||
| 252 | <div> | ||
| 253 | <!-- top --> | ||
| 254 | <div class="container top"> | ||
| 255 | <img class="cover_img" :src="detail.data?.coverImg" /> | ||
| 256 | <div class="info"> | ||
| 257 | <div class="title">{{ detail.data?.name }}</div> | ||
| 258 | <div class="time"> | ||
| 259 | {{ languageFormat(language, "时间", "Event Date & Time") }}:{{ | ||
| 260 | detail.data?.startTime | ||
| 261 | ? dayjs(detail.data?.startTime).format("YYYY.MM.DD ddd") | ||
| 262 | : "" | ||
| 263 | }} | ||
| 264 | — | ||
| 265 | {{ | ||
| 266 | detail.data?.endTime | ||
| 267 | ? dayjs(detail.data?.endTime).format("YYYY.MM.DD ddd") | ||
| 268 | : "" | ||
| 269 | }} | ||
| 270 | </div> | ||
| 271 | <div class="address"> | ||
| 272 | {{ languageFormat(language, "地址", "Location") }}:{{ | ||
| 273 | detail.data?.address | ||
| 274 | }} | ||
| 275 | </div> | ||
| 276 | <!-- 时间 --> | ||
| 277 | <div class="select_item_box"> | ||
| 278 | <div class="label"> | ||
| 279 | {{ languageFormat(language, "时间", "Event Date & Time") }} | ||
| 280 | </div> | ||
| 281 | <div class="select_item"> | ||
| 282 | <div | ||
| 283 | v-for="(it, index) in timeVenue.data" | ||
| 284 | :key="index" | ||
| 285 | :class="[ | ||
| 286 | it.id == select_form.venueItem?.id ? 'tagActive' : 'tag', | ||
| 287 | ]" | ||
| 288 | @click="select_form.onClickVenue(it)" | ||
| 289 | > | ||
| 290 | {{ it.dateStr }} | ||
| 291 | <div v-if="it.type == 1" class="tag_t">{{ languageFormat(language, "套票", "Package ticket") }}</div> | ||
| 292 | </div> | ||
| 293 | </div> | ||
| 294 | </div> | ||
| 295 | <!-- 场次 --> | ||
| 296 | <div class="select_item_box"> | ||
| 297 | <div class="label">{{ languageFormat(language, "场次", "Session") }}</div> | ||
| 298 | <div class="select_item"> | ||
| 299 | <div | ||
| 300 | :class="[ | ||
| 301 | select_form.venueItem?.dayOpen == 1 | ||
| 302 | ? select_form.session == 0 | ||
| 303 | ? 'tagActive' | ||
| 304 | : 'tag' | ||
| 305 | : 'tagDisabled', | ||
| 306 | ]" | ||
| 307 | @click="select_form.onClickSession(0)" | ||
| 308 | > | ||
| 309 | {{ languageFormat(language, "日场", "Day session") }} | ||
| 310 | </div> | ||
| 311 | <div | ||
| 312 | :class="[ | ||
| 313 | select_form.venueItem?.nightOpen == 1 | ||
| 314 | ? select_form.session == 1 | ||
| 315 | ? 'tagActive' | ||
| 316 | : 'tag' | ||
| 317 | : 'tagDisabled', | ||
| 318 | ]" | ||
| 319 | @click="select_form.onClickSession(1)" | ||
| 320 | > | ||
| 321 | {{ languageFormat(language, "夜场", "Night session") }} | ||
| 322 | </div> | ||
| 323 | </div> | ||
| 324 | </div> | ||
| 325 | <!-- 场馆 --> | ||
| 326 | <div class="select_item_box"> | ||
| 327 | <div class="label"> | ||
| 328 | {{ languageFormat(language, "场馆", "Venue") }} | ||
| 329 | </div> | ||
| 330 | <div class="select_item"> | ||
| 331 | <div | ||
| 332 | v-for="(it, index) in sitePlaceInfo.data" | ||
| 333 | :key="index" | ||
| 334 | :class="[ | ||
| 335 | it.state == 0 | ||
| 336 | ? it.placeName == select_form.place | ||
| 337 | ? 'tagActive' | ||
| 338 | : 'tag' | ||
| 339 | : 'tagDisabled', | ||
| 340 | ]" | ||
| 341 | @click="select_form.onClickPlace(it)" | ||
| 342 | > | ||
| 343 | {{ it.placeName }} | ||
| 344 | </div> | ||
| 345 | </div> | ||
| 346 | </div> | ||
| 347 | <!-- 票档 --> | ||
| 348 | <div | ||
| 349 | v-if="price.data?.length && select_form.place" | ||
| 350 | class="select_item_box" | ||
| 351 | > | ||
| 352 | <div class="label"> | ||
| 353 | {{ languageFormat(language, "票档", "Ticket Category") }} | ||
| 354 | </div> | ||
| 355 | <div class="select_item"> | ||
| 356 | <div | ||
| 357 | v-for="(it, index) in price.data" | ||
| 358 | :key="index" | ||
| 359 | :class="[ | ||
| 360 | it.state == 0 | ||
| 361 | ? it.priceId == select_form.ticket_block | ||
| 362 | ? 'tagActive' | ||
| 363 | : 'tag' | ||
| 364 | : 'tagDisabled', | ||
| 365 | ]" | ||
| 366 | @click="select_form.onClickPrice(it)" | ||
| 367 | > | ||
| 368 | {{ it.price }}元 | ||
| 369 | </div> | ||
| 370 | </div> | ||
| 371 | </div> | ||
| 372 | <!-- button --> | ||
| 373 | <div class="btn" @click="select_form.toSelectSeat()"> | ||
| 374 | {{ languageFormat(language, "选座购票", "Seat selection") }} | ||
| 375 | </div> | ||
| 376 | </div> | ||
| 377 | </div> | ||
| 378 | |||
| 379 | <!-- bottom --> | ||
| 380 | <div class="container bottom"> | ||
| 381 | <div class="title"> | ||
| 382 | {{ languageFormat(language, "活动介绍", "Event Details") }} | ||
| 383 | </div> | ||
| 384 | <div class="rich_content" v-html="detail.data?.introduceInfo"></div> | ||
| 385 | |||
| 386 | <div class="title" style="margin-top: 30px"> | ||
| 387 | {{ languageFormat(language, "购票须知", "Ticketing Information") }} | ||
| 388 | </div> | ||
| 389 | <div class="rich_content" v-html="detail.data?.buyNotice"></div> | ||
| 390 | </div> | ||
| 391 | </div> | ||
| 392 | </template> | ||
| 393 | |||
| 394 | <style scoped lang="scss"> | ||
| 395 | .container { | ||
| 396 | width: 1200px; | ||
| 397 | margin: 0 auto; | ||
| 398 | background-color: #fff; | ||
| 399 | box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08); | ||
| 400 | border-radius: 8px; | ||
| 401 | box-sizing: border-box; | ||
| 402 | font-family: SourceHanSansCN, SourceHanSansCN; | ||
| 403 | padding-bottom: 20px; | ||
| 404 | } | ||
| 405 | |||
| 406 | .top { | ||
| 407 | display: flex; | ||
| 408 | padding: 19px; | ||
| 409 | margin-top: 26px; | ||
| 410 | .cover_img { | ||
| 411 | width: 390px; | ||
| 412 | height: 517px; | ||
| 413 | object-fit: fill; | ||
| 414 | margin-right: 36px; | ||
| 415 | } | ||
| 416 | |||
| 417 | .info { | ||
| 418 | padding-top: 12px; | ||
| 419 | .title { | ||
| 420 | font-weight: bold; | ||
| 421 | font-size: 28px; | ||
| 422 | color: #000000; | ||
| 423 | line-height: 42px; | ||
| 424 | margin-bottom: 34px; | ||
| 425 | } | ||
| 426 | .time { | ||
| 427 | font-weight: 500; | ||
| 428 | font-size: 16px; | ||
| 429 | color: #4a4a4a; | ||
| 430 | line-height: 24px; | ||
| 431 | margin-bottom: 16px; | ||
| 432 | } | ||
| 433 | .address { | ||
| 434 | font-weight: 500; | ||
| 435 | font-size: 16px; | ||
| 436 | color: #4a4a4a; | ||
| 437 | line-height: 24px; | ||
| 438 | margin-bottom: 33px; | ||
| 439 | } | ||
| 440 | |||
| 441 | .select_item_box { | ||
| 442 | display: flex; | ||
| 443 | margin-bottom: 30px; | ||
| 444 | &:last-child { | ||
| 445 | margin-bottom: 0; | ||
| 446 | } | ||
| 447 | .label { | ||
| 448 | font-weight: 600; | ||
| 449 | font-size: 16px; | ||
| 450 | color: #000; | ||
| 451 | line-height: 24px; | ||
| 452 | margin-right: 12px; | ||
| 453 | flex-shrink: 0; | ||
| 454 | } | ||
| 455 | |||
| 456 | .select_item { | ||
| 457 | display: flex; | ||
| 458 | flex-wrap: wrap; | ||
| 459 | gap: 10px; | ||
| 460 | user-select: none; | ||
| 461 | .tag_t { | ||
| 462 | padding: 1px 15px; | ||
| 463 | font-weight: 400; | ||
| 464 | font-size: 14px; | ||
| 465 | color: #493ceb; | ||
| 466 | border-radius: 6px; | ||
| 467 | border: 1px solid #453dea; | ||
| 468 | margin-left: 5px; | ||
| 469 | } | ||
| 470 | .tag { | ||
| 471 | display: flex; | ||
| 472 | padding: 12px 18px; | ||
| 473 | background: #eeeeee; | ||
| 474 | border-radius: 4px; | ||
| 475 | border: 1px solid #29343c; | ||
| 476 | font-size: 14px; | ||
| 477 | color: #4a4a4a; | ||
| 478 | cursor: pointer; | ||
| 479 | } | ||
| 480 | |||
| 481 | .tagActive { | ||
| 482 | display: flex; | ||
| 483 | padding: 12px 18px; | ||
| 484 | background: #fff; | ||
| 485 | border-radius: 4px; | ||
| 486 | border: 1px solid #493ceb; | ||
| 487 | font-size: 14px; | ||
| 488 | color: #493ceb; | ||
| 489 | cursor: pointer; | ||
| 490 | } | ||
| 491 | .tagDisabled { | ||
| 492 | padding: 12px 18px; | ||
| 493 | background: #878787; | ||
| 494 | border-radius: 4px; | ||
| 495 | border: 1px solid #29343c; | ||
| 496 | font-size: 14px; | ||
| 497 | color: #4a4a4a; | ||
| 498 | cursor: no-drop; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | } | ||
| 502 | .btn { | ||
| 503 | width: 175px; | ||
| 504 | height: 40px; | ||
| 505 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 506 | border-radius: 20px; | ||
| 507 | line-height: 40px; | ||
| 508 | text-align: center; | ||
| 509 | font-weight: 500; | ||
| 510 | font-size: 16px; | ||
| 511 | color: #ffffff; | ||
| 512 | cursor: pointer; | ||
| 513 | } | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | .bottom { | ||
| 518 | padding: 50px; | ||
| 519 | margin-top: 30px; | ||
| 520 | margin-bottom: 30px; | ||
| 521 | .title { | ||
| 522 | padding: 20px 30px; | ||
| 523 | background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%); | ||
| 524 | font-weight: bold; | ||
| 525 | font-size: 20px; | ||
| 526 | color: #ffffff; | ||
| 527 | line-height: 30px; | ||
| 528 | margin-bottom: 30px; | ||
| 529 | } | ||
| 530 | .rich_content { | ||
| 531 | margin-top: 30px; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | </style> |
src/viewsPc/seat/utils/language.js
0 → 100644
src/viewsPc/seat/utils/local-store.js
0 → 100644
| 1 | /** 用户登录token储存的key */ | ||
| 2 | export const TOKEN_KEY = "SEAT_TOKEN"; | ||
| 3 | |||
| 4 | /** 设置token */ | ||
| 5 | export const setToken = (token) => localStorage.setItem(TOKEN_KEY, token); | ||
| 6 | |||
| 7 | /** | ||
| 8 | * 获取登录token | ||
| 9 | * @param drop 是否清空 | ||
| 10 | */ | ||
| 11 | export const getToken = (drop = false) => { | ||
| 12 | let token = localStorage.getItem(TOKEN_KEY); | ||
| 13 | if (!token) return null; | ||
| 14 | if (drop) localStorage.removeItem(TOKEN_KEY); | ||
| 15 | return token; | ||
| 16 | }; |
src/viewsPc/seat/utils/request.js
0 → 100644
| 1 | // http.js | ||
| 2 | |||
| 3 | // import axios from "axios"; | ||
| 4 | import axios from 'axios/dist/axios' | ||
| 5 | import { getToken } from "./local-store"; | ||
| 6 | import { ElMessage } from "element-plus"; | ||
| 7 | |||
| 8 | import { useStorage } from "@vueuse/core/index"; | ||
| 9 | const language = useStorage("language", 0); | ||
| 10 | |||
| 11 | const baseURL = "https://radv4.gitliuyi.top/ticket"; //"http://book.xiaojinyu.games"; // 这里填入你的基础 API URL | ||
| 12 | const timeout = 15000; // 请求超时时间 | ||
| 13 | |||
| 14 | const http = axios.create({ | ||
| 15 | baseURL, | ||
| 16 | timeout, | ||
| 17 | headers: { | ||
| 18 | "Content-Type": "application/json", | ||
| 19 | }, | ||
| 20 | }); | ||
| 21 | |||
| 22 | // 请求拦截器 | ||
| 23 | http.interceptors.request.use( | ||
| 24 | (config) => { | ||
| 25 | // 在发送请求之前做些什么 | ||
| 26 | if (language.value == 1) config.headers.Language = "en-us"; | ||
| 27 | const TOKEN = getToken(); | ||
| 28 | if (TOKEN) config.headers.Authorization = TOKEN; | ||
| 29 | if (config.method == "get") config.params = config.data; | ||
| 30 | console.log("config", config); | ||
| 31 | return config; | ||
| 32 | }, | ||
| 33 | (error) => { | ||
| 34 | return Promise.reject(error); | ||
| 35 | } | ||
| 36 | ); | ||
| 37 | |||
| 38 | // 响应拦截器 | ||
| 39 | http.interceptors.response.use( | ||
| 40 | (response) => { | ||
| 41 | // 判断是否有异常 | ||
| 42 | let error = null; // 若无异常此值为null | ||
| 43 | if (response.status !== 200) { | ||
| 44 | error = Error(`Request failed with statuCode ${response.status}`); | ||
| 45 | } | ||
| 46 | |||
| 47 | if (response.data.code != 200) { | ||
| 48 | ElMessage({ type: "error", message: response.data.msg }); | ||
| 49 | return Promise.reject(response.data); | ||
| 50 | } | ||
| 51 | |||
| 52 | return response.data; | ||
| 53 | }, | ||
| 54 | (error) => { | ||
| 55 | // 对响应错误做点什么 | ||
| 56 | return Promise.reject(error); | ||
| 57 | } | ||
| 58 | ); | ||
| 59 | |||
| 60 | // 封装请求函数 | ||
| 61 | const request = (method, url, data = null) => { | ||
| 62 | return http({ | ||
| 63 | method, | ||
| 64 | url, | ||
| 65 | data, | ||
| 66 | }); | ||
| 67 | }; | ||
| 68 | |||
| 69 | export default request; |
| ... | @@ -65,25 +65,25 @@ export default defineConfig(({ mode, command }) => { | ... | @@ -65,25 +65,25 @@ export default defineConfig(({ mode, command }) => { |
| 65 | // https://cn.vitejs.dev/config/#server-proxy | 65 | // https://cn.vitejs.dev/config/#server-proxy |
| 66 | '/dev-api/ztx-train': { | 66 | '/dev-api/ztx-train': { |
| 67 | // target: 'http://123.60.96.243:1896/stage-api', | 67 | // target: 'http://123.60.96.243:1896/stage-api', |
| 68 | target: 'http://192.168.1.25:8686', | 68 | target: 'https://jijin.wtwuxicenter.com/stage-api', |
| 69 | changeOrigin: true, | 69 | changeOrigin: true, |
| 70 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-train/, '') | 70 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-train/, '') |
| 71 | }, | 71 | }, |
| 72 | '/dev-api/ztx-match': { | 72 | '/dev-api/ztx-match': { |
| 73 | target: 'http://192.168.1.118:8083', | 73 | // target: 'http://192.168.1.118:8083', |
| 74 | // target: 'http://192.168.1.132:8081', | 74 | target: 'https://jijin.wtwuxicenter.com/stage-api', |
| 75 | changeOrigin: true, | 75 | changeOrigin: true, |
| 76 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-match/, '') | 76 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-match/, '') |
| 77 | }, | 77 | }, |
| 78 | '/dev-api/ztx-webSite': { | 78 | '/dev-api/ztx-webSite': { |
| 79 | // target: 'https://dance.itechtop.cn/stage-api', | 79 | // target: 'https://dance.itechtop.cn/stage-api', |
| 80 | target: 'http://192.168.1.118:8081/', | 80 | target: 'https://jijin.wtwuxicenter.com/stage-api', |
| 81 | changeOrigin: true, | 81 | changeOrigin: true, |
| 82 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-webSite/, '') | 82 | rewrite: (p) => p.replace(/^\/dev-api\/ztx-webSite/, '') |
| 83 | }, | 83 | }, |
| 84 | '/dev-api': { | 84 | '/dev-api': { |
| 85 | target: 'http://192.168.1.131:8081/', | 85 | // target: 'http://192.168.1.118:8081/', |
| 86 | // target: 'https://dance.itechtop.cn/stage-api', | 86 | target: 'https://jijin.wtwuxicenter.com/stage-api', |
| 87 | // target: 'https://wdsfwuxicenter.com/stage-api', | 87 | // target: 'https://wdsfwuxicenter.com/stage-api', |
| 88 | changeOrigin: true, | 88 | changeOrigin: true, |
| 89 | rewrite: (p) => p.replace(/^\/dev-api/, '') | 89 | rewrite: (p) => p.replace(/^\/dev-api/, '') | ... | ... |
-
Please register or sign in to post a comment