47440f2a by zhangmeng

票务

1 parent cf591983
...@@ -410,3 +410,56 @@ export function ppOtaReceipt(query) { ...@@ -410,3 +410,56 @@ export function ppOtaReceipt(query) {
410 params:query 410 params:query
411 }) 411 })
412 } 412 }
413 // 获取票务信息
414 export function getTicketInfoByActivityId(params) {
415 return request({
416 url: `/ota/activityTicket/getTicketInfoByActivityId`,
417 method: 'get',
418 params
419 })
420 }
421
422 // 根据赛事ID获取票档
423 export function getTicketListApi(params) {
424 return request({
425 url: `/ota/activityTicket/getTicketList`,
426 method: 'get',
427 params
428 })
429 }
430
431 // 根据赛事ID获取票档
432 export function listApi(params) {
433 return request({
434 url: `/ota/activityType/list`,
435 method: 'get',
436 params
437 })
438 }
439
440 // 获取当前用户的观影人列表
441 export function customerListApi(params) {
442 return request({
443 url: `/ota/customer/list`,
444 method: 'get',
445 params
446 })
447 }
448
449
450 // 新增观影人
451 export function aadCustomer(data) {
452 return request({
453 url: `/ota/customer`,
454 method: 'post',
455 data
456 })
457 }
458
459 // 删除观影人
460 export function delCustomer(id) {
461 return request({
462 url: `/ota/customer/${id}`,
463 method: 'delete',
464 })
465 }
......
...@@ -344,12 +344,24 @@ export const constantRoutes = [ ...@@ -344,12 +344,24 @@ export const constantRoutes = [
344 redirect: '/booking', 344 redirect: '/booking',
345 children: [ 345 children: [
346 { 346 {
347 path: 'ticket/:cptId', 347 path: 'ticket/:activeId',
348 component: () => import('@/viewsPc/booking/ticket'), 348 component: () => import('@/viewsPc/booking/ticket/index.vue'),
349 name: 'ticket', 349 name: 'ticket',
350 meta: { title: 'Ticket Booking' } 350 meta: { title: 'Ticket Booking' }
351 }, 351 },
352 { 352 {
353 path: 'ticket/:activeId/:latId',
354 component: () => import('@/viewsPc/booking/ticket/confirmOrder.vue'),
355 name: 'confirmOrder',
356 meta: { title: 'confirmOrder' }
357 },
358 {
359 path: 'ticket/peopleManage',
360 component: () => import('@/viewsPc/booking/ticket/peopleManage.vue'),
361 name: 'peopleManage',
362 meta: { title: 'peopleManage' }
363 },
364 {
353 path: 'hotel/:cptId', 365 path: 'hotel/:cptId',
354 component: () => import('@/viewsPc/booking/hotel'), 366 component: () => import('@/viewsPc/booking/hotel'),
355 name: 'hotel', 367 name: 'hotel',
......
1 <template>
2 <div>
3 <div class="box">
4 <el-card class="mt30">
5 票务预订
6 </el-card>
7 </div>
8
9 </div>
10 </template>
11
12 <script setup>
13
14 </script>
15
16 <style scoped>
17
18 </style>
1 <template>
2 <div>
3 <!-- top -->
4 <div class="container top">
5 <img :src="fillImgUrl(matchForm.ticketImg)" class="cover_img"/>
6 <div class="info">
7 <div class="title">{{ matchForm.name }}</div>
8 <div class="time">
9 {{ languageFormat(language, "时间", "Event Date & Time") }}{{
10 matchForm.ticketStart
11 ? dayjs(matchForm.ticketStart).format("YYYY.MM.DD")
12 : ""
13 }}
14 {{
15 matchForm.ticketStart
16 ? getDayName(
17 new Date(matchForm.ticketStart),
18 language == 1 ? "en-US" : "zh-CN"
19 )
20 : ""
21 }}
22
23 {{
24 matchForm.ticketEnd
25 ? dayjs(matchForm.ticketEnd).format("YYYY.MM.DD")
26 : ""
27 }}
28 {{
29 matchForm.ticketEnd
30 ? getDayName(
31 new Date(matchForm.ticketEnd),
32 language == 1 ? "en-US" : "zh-CN"
33 )
34 : ""
35 }}
36 </div>
37 <div class="address">
38 {{ languageFormat(language, "地址", "Location") }}{{
39 matchForm.address
40 }}
41 </div>
42 <!-- 时间 -->
43 <div class="select_item_box">
44 <div class="label">
45 {{ languageFormat(language, "票档", "Tickets") }}
46 </div>
47 <div class="select_item">
48 <div
49 v-for="(it, index) in tickClass"
50 :key="index"
51 :class="[
52 it.id == selectForm.latId ? 'tagActive' : 'tag',
53 ]"
54 @click="select(it)"
55 >
56 {{ it.name }}
57 </div>
58 </div>
59 </div>
60 <!-- 时间 -->
61 <div class="select_item_box">
62 <div class="label">
63 {{ languageFormat(language, "时间", "Event Date & Time") }}
64 </div>
65 <div class="select_item">
66 <div
67 v-for="(it, index) in tickList"
68 :key="index"
69 :class="[
70 it.id == selectForm.id ? 'tagActive' : 'tag',
71 ]"
72 @click="selectTick(it)"
73 >
74 {{ it.name }}
75 </div>
76 </div>
77 </div>
78
79 <!-- button -->
80 <div class="btn forPc" @click="toSelectSeat()">
81 {{ languageFormat(language, "添加观影人", "Add Moviegoers") }}
82 </div>
83 </div>
84 </div>
85
86 <div class="container bottom">
87 <div class="rich_content" v-html="matchForm.ticketDes"></div>
88 </div>
89 </div>
90 </template>
91
92
93 <script setup>
94 import {ref, reactive, onMounted, watch} from "vue";
95 import {listApi, getTicketInfoByActivityId, getTicketListApi} from '@/apiPc/booking'
96
97 import {dayjs} from "element-plus";
98 import useUserStore from "@/store/modules/user";
99 import {ElMessageBox, ElMessage} from "element-plus";
100 import {languageFormat, getDayName} from "@/viewsPc/seat/utils/language";
101 import {fillImgUrl} from "/@/utils/ruoyi";
102
103 const route = useRoute();
104 const router = useRouter();
105 const userStore = useUserStore();
106 const activeId = ref(route.params.activeId)
107 const props = defineProps({
108 activityId: [String, Number],
109 });
110
111 const matchForm = ref({})
112 const tickClass = ref([])
113 const selectForm = ref({
114 latId: null,
115 id: null
116 })
117 const tickList = ref([])
118
119 // 获取票务信息
120 getDetail()
121
122 async function getDetail() {
123 const res = await getTicketInfoByActivityId({activityId: activeId.value})
124 matchForm.value = res.data
125 }
126
127 // 根据赛事ID获取票档
128 getTicketList()
129
130 async function getTicketList() {
131 const res = await getTicketListApi({activityId: activeId.value})
132 tickClass.value = res.rows
133 selectForm.value.latId = tickClass.value?.[0]?.id
134 await getTicketListType()
135 }
136
137 // 根据票档获取场次
138 async function getTicketListType() {
139 const res = await listApi({latId: selectForm.value.latId})
140 tickList.value = res.rows
141 }
142
143 function select(v) {
144 selectForm.value.latId = v.id
145 getTicketListType()
146 }
147
148 function selectTick(v) {
149 selectForm.value.id = v.id
150 }
151
152 function toSelectSeat() {
153 if (!selectForm.value.latId) return ElMessage.error("请选择票档")
154 if (!selectForm.value.id) return ElMessage.error("请选择时间")
155 router.push({
156 name:'confirmOrder',
157 params: {
158 activeId: activeId.value,
159 latId: selectForm.value.latId,
160 id: selectForm.value.id
161 }
162 })
163 }
164
165 </script>
166
167
168 <style lang="scss" scoped>
169 .forWei {
170 display: none
171 }
172
173 .container {
174 width: 1200px;
175 margin: 0 auto;
176 background-color: #fff;
177 box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08);
178 border-radius: 8px;
179 box-sizing: border-box;
180 font-family: SourceHanSansCN, SourceHanSansCN;
181 padding-bottom: 20px;
182 }
183
184 .top {
185 display: flex;
186 padding: 19px;
187 margin-top: 26px;
188
189 .cover_img {
190 width: 390px;
191 height: 517px;
192 object-fit: fill;
193 margin-right: 36px;
194 }
195
196 .info {
197 padding-top: 12px;
198
199 .title {
200 font-weight: bold;
201 font-size: 28px;
202 color: #000000;
203 line-height: 42px;
204 margin-bottom: 34px;
205 }
206
207 .time {
208 font-weight: 500;
209 font-size: 16px;
210 color: #4a4a4a;
211 line-height: 24px;
212 margin-bottom: 16px;
213 }
214
215 .address {
216 font-weight: 500;
217 font-size: 16px;
218 color: #4a4a4a;
219 line-height: 24px;
220 margin-bottom: 33px;
221 }
222
223 .select_item_box {
224 display: flex;
225 margin-bottom: 30px;
226
227 &:last-child {
228 margin-bottom: 0;
229 }
230
231 .label {
232 font-weight: 600;
233 font-size: 16px;
234 color: #000;
235 line-height: 24px;
236 margin-right: 12px;
237 flex-shrink: 0;
238 }
239
240 .select_item {
241 display: flex;
242 flex-wrap: wrap;
243 gap: 10px;
244 user-select: none;
245
246 .tag_t {
247 padding: 1px 15px;
248 font-weight: 400;
249 font-size: 14px;
250 color: #493ceb;
251 border-radius: 6px;
252 border: 1px solid #453dea;
253 margin-left: 5px;
254 }
255
256 .tag {
257 display: flex;
258 padding: 12px 18px;
259 background: #eeeeee;
260 border-radius: 4px;
261 border: 1px solid #29343c;
262 font-size: 14px;
263 color: #4a4a4a;
264 cursor: pointer;
265 }
266
267 .tagActive {
268 display: flex;
269 padding: 12px 18px;
270 background: #fff;
271 border-radius: 4px;
272 border: 1px solid #493ceb;
273 font-size: 14px;
274 color: #493ceb;
275 cursor: pointer;
276 }
277
278 .tagDisabled {
279 padding: 12px 18px;
280 background: #878787;
281 border-radius: 4px;
282 border: 1px solid #29343c;
283 font-size: 14px;
284 color: #4a4a4a;
285 cursor: no-drop;
286 }
287 }
288 }
289
290 .btn {
291 width: 175px;
292 height: 40px;
293 background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
294 border-radius: 20px;
295 line-height: 40px;
296 text-align: center;
297 font-weight: 500;
298 font-size: 16px;
299 color: #ffffff;
300 cursor: pointer;
301 }
302 }
303 }
304
305 .bottom {
306 padding: 50px;
307 margin-top: 30px;
308 margin-bottom: 30px;
309
310 .title {
311 padding: 20px 30px;
312 background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
313 font-weight: bold;
314 font-size: 20px;
315 color: #ffffff;
316 line-height: 30px;
317 margin-bottom: 30px;
318 }
319
320 .rich_content {
321 margin-top: 30px;
322 }
323 }
324
325 @media screen and (max-width: 768px) {
326 .container {
327 width: 100%;
328 }
329 .forWei {
330 display: block
331 }
332 .top {
333 //transform: scale(0.5);transform-origin: left top;
334 .cover_img {
335 width: 120px;
336 height: 160px;
337 margin-right: 15px;
338 }
339
340 .info {
341 .title {
342 font-size: 14px;
343 }
344
345 .time, .address, .label, .tip {
346 font-size: 12px;
347 }
348
349 .title, .time, .address, .tip, .select_item_box {
350 margin-bottom: 3px;
351 }
352
353 .select_item_box {
354 .label {
355 font-size: 12px;
356 }
357
358 .select_item .tag {
359 padding: 2px 10px;
360 font-size: 12px;
361 }
362
363 .select_item .tagActive {
364 padding: 2px 10px;
365 font-size: 12px;
366 }
367
368 .select_item .tagDisabled {
369 padding: 2px 10px;
370 font-size: 12px;
371 }
372 }
373 }
374 }
375 .bottom {
376 padding: 0
377 }
378 }
379 </style>
1 <template>
2 <el-card class="container">
3 <div class="title">
4 <div
5 class="add_btn"
6 @click="addPeople"
7 >
8 {{ languageFormat(language, "新增", "Add") }}
9 </div>
10 {{ languageFormat(language, "观影人管理", "Viewers") }}
11 </div>
12 <div class="content">
13 <div class="people_box">
14 <div
15 v-for="(it, index) in cousList"
16 :key="index"
17 class="people_item"
18 >
19 <div class="name">{{ it.name }}</div>
20 <div class="idcard">
21 {{ languageFormat(language, "证件号", "Identity Card") }}{{
22 it.idCard
23 }}
24 </div>
25 <div class="btn" @click="deletePeople(it.id)">
26 {{ languageFormat(language, "删除", "delete") }}
27 </div>
28 </div>
29 </div>
30 </div>
31
32 <el-dialog
33 v-model="show"
34 center
35 title="新增观影人"
36 width="700"
37 >
38 <el-form ref="formRef" :model="form" :rules="rules" label-width="80px" size="large" style="margin: 80px">
39 <el-form-item label="姓名" required prop="name">
40 <el-input v-model="form.name" size=""></el-input>
41 </el-form-item>
42 <el-form-item label="证件号" required prop="idCard">
43 <el-input v-model="form.idCard"></el-input>
44 </el-form-item>
45 </el-form>
46
47 <br>
48 <br>
49 <span slot="footer" class="dialog-footer">
50 <div style="text-align: center">
51 <el-button class="can_pay" @click="show = false">取 消</el-button>
52 <el-button class="pay" type="primary" @click="submit">确 定</el-button>
53 </div>
54 </span>
55 <br>
56 <br>
57 <br>
58 </el-dialog>
59 </el-card>
60
61 </template>
62
63
64 <script setup>
65 import {reactive, ref} from "vue";
66 import {customerListApi,aadCustomer,delCustomer} from '@/apiPc/booking'
67
68 import {deleteViewPeople, viewPeopleList} from "@/viewsPc/seat/api/index.js";
69 import {ElMessageBox, ElMessage} from "element-plus";
70 import {languageFormat} from "@/viewsPc/seat/utils/language.js";
71 import {useStorage} from "@vueuse/core/index";
72
73 const language = useStorage("language", 0);
74
75 const audience = reactive({
76 data: [],
77 fetchData() {
78 viewPeopleList().then((res) => {
79 audience.data = res.data;
80 });
81 },
82
83 deletePeople(id) {
84 ElMessageBox.confirm(
85 languageFormat(
86 language.value,
87 "确认删除该观看人吗?",
88 "Are you sure to delete this viewer?"
89 ),
90 languageFormat(language.value, "提示", "Reminder"),
91 {
92 confirmButtonText: languageFormat(language.value, "确认", "confirm"),
93 cancelButtonText: languageFormat(language.value, "取消", "cancel"),
94 type: "warning",
95 draggable: true,
96 }
97 )
98 .then(() => {
99 deleteViewPeople({id}).then(() => {
100 audience.fetchData();
101 ElMessage({
102 type: "success",
103 message: languageFormat(
104 language.value,
105 "操作成功",
106 "Operate successfully"
107 ),
108 });
109 });
110 })
111 .catch(() => {
112 });
113 },
114 });
115
116 const cousList = ref([])
117 const show = ref(false)
118 const form = ref({})
119 const formRef = ref(null)
120 const rules = ref({
121 name: [
122 {required: true, message: "请输入姓名", trigger: "blur"},
123 ],
124 idCard: [
125 {required: true, message: "请输入证件号", trigger: "blur"},
126 ],
127 })
128
129 customerList()
130 async function customerList() {
131 const res = await customerListApi()
132 // cousList.value = res.rows
133 cousList.value = [{},{}]
134 }
135
136 function addPeople() {
137 show.value = true
138 formRef.value?.resetFields()
139 }
140
141 function submit() {
142 formRef.value.validate((valid) => {
143 if (valid) {
144 console.log(form.value);
145 aadCustomer(form.value).then(res=>{
146 show.value = false
147 customerList()
148 ElMessage.success('添加成功')
149 })
150 } else {
151 return ElMessage.waiting('请完善信息')
152 }
153 })
154 }
155
156 async function deletePeople(v){
157 const res =await delCustomer(v.id)
158 if(res.code===200){
159 ElMessage.success('删除成功')
160 await customerList()
161 }
162 }
163 </script>
164
165
166 <style lang="scss" scoped>
167 div {
168 box-sizing: border-box;
169 }
170
171 :deep(.el-dialog) {
172 padding: 0;
173
174 .el-dialog__header {
175 height: 50px;
176 line-height: 50px;
177 background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
178
179 .el-dialog__title {
180 color: #fff;
181 }
182 }
183 }
184
185 .pay {
186 width: 200px;
187 height: 40px;
188 background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
189 border-radius: 20px;
190 font-weight: 500;
191 font-size: 16px;
192 color: #ffffff;
193 line-height: 40px;
194 text-align: center;
195 cursor: pointer;
196 }
197
198 .can_pay {
199 width: 200px;
200 height: 40px;
201 background: #f6f6f6;
202 border-radius: 20px;
203 font-weight: 500;
204 font-size: 16px;
205 color: #999;
206 line-height: 40px;
207 text-align: center;
208 box-sizing: border-box;
209 cursor: pointer;
210 }
211
212 .container {
213 //padding: 20px 0;
214 //:deep(.el-card__body){
215 // padding: 0;
216 //}
217 width: 1200px;
218 margin: 20px auto;
219
220 .title {
221 position: relative;
222 padding: 11px;
223 text-align: center;
224 background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
225 font-size: 18px;
226 color: #ffffff;
227
228 .add_btn {
229 position: absolute;
230 left: 20px;
231 top: 50%;
232 transform: translateY(-50%);
233 width: 68px;
234 height: 24px;
235 border-radius: 12px;
236 border: 1px solid #ffffff;
237 font-weight: 400;
238 font-size: 12px;
239 color: #ffffff;
240 text-align: center;
241 line-height: 24px;
242 box-sizing: border-box;
243 user-select: none;
244 cursor: pointer;
245 }
246 }
247
248 .content {
249 min-height: 590px;
250 background-color: #fff;
251 box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08);
252 padding: 20px;
253
254 .people_box {
255 display: flex;
256 flex-wrap: wrap;
257 gap: 20px;
258
259 .people_item {
260 width: 275px;
261 height: 137px;
262 background: #ffffff;
263 border: 1px solid #dcdfe6;
264 padding: 16px;
265
266 .name {
267 font-weight: 600;
268 font-size: 16px;
269 color: #2d373f;
270 line-height: 22px;
271 }
272
273 .idcard {
274 font-size: 16px;
275 color: #95a1a6;
276 line-height: 22px;
277 margin-top: 12px;
278 margin-bottom: 17px;
279 }
280
281 .btn {
282 width: 69px;
283 height: 32px;
284 background: #e7e6ff;
285 font-weight: 400;
286 font-size: 16px;
287 color: #493ceb;
288 line-height: 32px;
289 text-align: center;
290 cursor: pointer;
291 user-select: none;
292 }
293 }
294 }
295 }
296 }
297
298 @media screen and (max-width: 768px) {
299 .container {
300 width: 100%;
301 }
302 }
303 </style>
...@@ -119,7 +119,7 @@ function popRemark(type) { ...@@ -119,7 +119,7 @@ function popRemark(type) {
119 || (form.value.isFoodView == 0 && type == '3') 119 || (form.value.isFoodView == 0 && type == '3')
120 || (form.value.isMealView == 0 && type == '4') 120 || (form.value.isMealView == 0 && type == '4')
121 || (form.value.isPhotoView == 0 && type == '5') 121 || (form.value.isPhotoView == 0 && type == '5')
122 // || (type == '0') 122 || (form.value.isTicket==0&&type == '0')
123 ) { 123 ) {
124 building() 124 building()
125 return 125 return
...@@ -138,9 +138,9 @@ function goBooking(n) { ...@@ -138,9 +138,9 @@ function goBooking(n) {
138 case 0: 138 case 0:
139 // 票务 139 // 票务
140 router.push({ 140 router.push({
141 path: `/seat/detail`, 141 path: `/booking/ticket/${props.matchId}`,
142 params: {id: 1}, 142 // params: {id:props.matchId},
143 query: {id: 1} 143 // query: {id: props.matchId}
144 }) 144 })
145 break; 145 break;
146 case 1: 146 case 1:
......
...@@ -135,8 +135,8 @@ function popRemark(type) { ...@@ -135,8 +135,8 @@ function popRemark(type) {
135 || (form.value.isCarView == 0 && type == '2') 135 || (form.value.isCarView == 0 && type == '2')
136 || (form.value.isFoodView == 0 && type == '3') 136 || (form.value.isFoodView == 0 && type == '3')
137 || (form.value.isMealView == 0 && type == '4') 137 || (form.value.isMealView == 0 && type == '4')
138 || (type == '5' && form.value.isPhotoView == 0) 138 || (form.value.isPhotoView == 0&&type == '5')
139 || (type == '0') 139 || (form.value.isTicket==0 &type == '0')
140 ) 140 )
141 { 141 {
142 building() 142 building()
...@@ -157,11 +157,8 @@ function goBooking(n) { ...@@ -157,11 +157,8 @@ function goBooking(n) {
157 switch (n) { 157 switch (n) {
158 case 0: 158 case 0:
159 // 票务 159 // 票务
160 // 票务
161 router.push({ 160 router.push({
162 path: `/seat/detail`, 161 path: `/booking/ticket/${props.matchId}`,
163 params: {id: 1},
164 query: {id: 1}
165 }) 162 })
166 break; 163 break;
167 case 1: 164 case 1:
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!