47440f2a by zhangmeng

票务

1 parent cf591983
......@@ -410,3 +410,56 @@ export function ppOtaReceipt(query) {
params:query
})
}
// 获取票务信息
export function getTicketInfoByActivityId(params) {
return request({
url: `/ota/activityTicket/getTicketInfoByActivityId`,
method: 'get',
params
})
}
// 根据赛事ID获取票档
export function getTicketListApi(params) {
return request({
url: `/ota/activityTicket/getTicketList`,
method: 'get',
params
})
}
// 根据赛事ID获取票档
export function listApi(params) {
return request({
url: `/ota/activityType/list`,
method: 'get',
params
})
}
// 获取当前用户的观影人列表
export function customerListApi(params) {
return request({
url: `/ota/customer/list`,
method: 'get',
params
})
}
// 新增观影人
export function aadCustomer(data) {
return request({
url: `/ota/customer`,
method: 'post',
data
})
}
// 删除观影人
export function delCustomer(id) {
return request({
url: `/ota/customer/${id}`,
method: 'delete',
})
}
......
......@@ -344,12 +344,24 @@ export const constantRoutes = [
redirect: '/booking',
children: [
{
path: 'ticket/:cptId',
component: () => import('@/viewsPc/booking/ticket'),
path: 'ticket/:activeId',
component: () => import('@/viewsPc/booking/ticket/index.vue'),
name: 'ticket',
meta: { title: 'Ticket Booking' }
},
{
path: 'ticket/:activeId/:latId',
component: () => import('@/viewsPc/booking/ticket/confirmOrder.vue'),
name: 'confirmOrder',
meta: { title: 'confirmOrder' }
},
{
path: 'ticket/peopleManage',
component: () => import('@/viewsPc/booking/ticket/peopleManage.vue'),
name: 'peopleManage',
meta: { title: 'peopleManage' }
},
{
path: 'hotel/:cptId',
component: () => import('@/viewsPc/booking/hotel'),
name: 'hotel',
......
<template>
<div>
<div class="box">
<el-card class="mt30">
票务预订
</el-card>
</div>
</div>
</template>
<script setup>
</script>
<style scoped>
</style>
<template>
<div>
<!-- top -->
<div class="container top">
<img :src="fillImgUrl(matchForm.ticketImg)" class="cover_img"/>
<div class="info">
<div class="title">{{ matchForm.name }}</div>
<div class="time">
{{ languageFormat(language, "时间", "Event Date & Time") }}{{
matchForm.ticketStart
? dayjs(matchForm.ticketStart).format("YYYY.MM.DD")
: ""
}}
{{
matchForm.ticketStart
? getDayName(
new Date(matchForm.ticketStart),
language == 1 ? "en-US" : "zh-CN"
)
: ""
}}
{{
matchForm.ticketEnd
? dayjs(matchForm.ticketEnd).format("YYYY.MM.DD")
: ""
}}
{{
matchForm.ticketEnd
? getDayName(
new Date(matchForm.ticketEnd),
language == 1 ? "en-US" : "zh-CN"
)
: ""
}}
</div>
<div class="address">
{{ languageFormat(language, "地址", "Location") }}{{
matchForm.address
}}
</div>
<!-- 时间 -->
<div class="select_item_box">
<div class="label">
{{ languageFormat(language, "票档", "Tickets") }}
</div>
<div class="select_item">
<div
v-for="(it, index) in tickClass"
:key="index"
:class="[
it.id == selectForm.latId ? 'tagActive' : 'tag',
]"
@click="select(it)"
>
{{ it.name }}
</div>
</div>
</div>
<!-- 时间 -->
<div class="select_item_box">
<div class="label">
{{ languageFormat(language, "时间", "Event Date & Time") }}
</div>
<div class="select_item">
<div
v-for="(it, index) in tickList"
:key="index"
:class="[
it.id == selectForm.id ? 'tagActive' : 'tag',
]"
@click="selectTick(it)"
>
{{ it.name }}
</div>
</div>
</div>
<!-- button -->
<div class="btn forPc" @click="toSelectSeat()">
{{ languageFormat(language, "添加观影人", "Add Moviegoers") }}
</div>
</div>
</div>
<div class="container bottom">
<div class="rich_content" v-html="matchForm.ticketDes"></div>
</div>
</div>
</template>
<script setup>
import {ref, reactive, onMounted, watch} from "vue";
import {listApi, getTicketInfoByActivityId, getTicketListApi} from '@/apiPc/booking'
import {dayjs} from "element-plus";
import useUserStore from "@/store/modules/user";
import {ElMessageBox, ElMessage} from "element-plus";
import {languageFormat, getDayName} from "@/viewsPc/seat/utils/language";
import {fillImgUrl} from "/@/utils/ruoyi";
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const activeId = ref(route.params.activeId)
const props = defineProps({
activityId: [String, Number],
});
const matchForm = ref({})
const tickClass = ref([])
const selectForm = ref({
latId: null,
id: null
})
const tickList = ref([])
// 获取票务信息
getDetail()
async function getDetail() {
const res = await getTicketInfoByActivityId({activityId: activeId.value})
matchForm.value = res.data
}
// 根据赛事ID获取票档
getTicketList()
async function getTicketList() {
const res = await getTicketListApi({activityId: activeId.value})
tickClass.value = res.rows
selectForm.value.latId = tickClass.value?.[0]?.id
await getTicketListType()
}
// 根据票档获取场次
async function getTicketListType() {
const res = await listApi({latId: selectForm.value.latId})
tickList.value = res.rows
}
function select(v) {
selectForm.value.latId = v.id
getTicketListType()
}
function selectTick(v) {
selectForm.value.id = v.id
}
function toSelectSeat() {
if (!selectForm.value.latId) return ElMessage.error("请选择票档")
if (!selectForm.value.id) return ElMessage.error("请选择时间")
router.push({
name:'confirmOrder',
params: {
activeId: activeId.value,
latId: selectForm.value.latId,
id: selectForm.value.id
}
})
}
</script>
<style lang="scss" scoped>
.forWei {
display: none
}
.container {
width: 1200px;
margin: 0 auto;
background-color: #fff;
box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08);
border-radius: 8px;
box-sizing: border-box;
font-family: SourceHanSansCN, SourceHanSansCN;
padding-bottom: 20px;
}
.top {
display: flex;
padding: 19px;
margin-top: 26px;
.cover_img {
width: 390px;
height: 517px;
object-fit: fill;
margin-right: 36px;
}
.info {
padding-top: 12px;
.title {
font-weight: bold;
font-size: 28px;
color: #000000;
line-height: 42px;
margin-bottom: 34px;
}
.time {
font-weight: 500;
font-size: 16px;
color: #4a4a4a;
line-height: 24px;
margin-bottom: 16px;
}
.address {
font-weight: 500;
font-size: 16px;
color: #4a4a4a;
line-height: 24px;
margin-bottom: 33px;
}
.select_item_box {
display: flex;
margin-bottom: 30px;
&:last-child {
margin-bottom: 0;
}
.label {
font-weight: 600;
font-size: 16px;
color: #000;
line-height: 24px;
margin-right: 12px;
flex-shrink: 0;
}
.select_item {
display: flex;
flex-wrap: wrap;
gap: 10px;
user-select: none;
.tag_t {
padding: 1px 15px;
font-weight: 400;
font-size: 14px;
color: #493ceb;
border-radius: 6px;
border: 1px solid #453dea;
margin-left: 5px;
}
.tag {
display: flex;
padding: 12px 18px;
background: #eeeeee;
border-radius: 4px;
border: 1px solid #29343c;
font-size: 14px;
color: #4a4a4a;
cursor: pointer;
}
.tagActive {
display: flex;
padding: 12px 18px;
background: #fff;
border-radius: 4px;
border: 1px solid #493ceb;
font-size: 14px;
color: #493ceb;
cursor: pointer;
}
.tagDisabled {
padding: 12px 18px;
background: #878787;
border-radius: 4px;
border: 1px solid #29343c;
font-size: 14px;
color: #4a4a4a;
cursor: no-drop;
}
}
}
.btn {
width: 175px;
height: 40px;
background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
border-radius: 20px;
line-height: 40px;
text-align: center;
font-weight: 500;
font-size: 16px;
color: #ffffff;
cursor: pointer;
}
}
}
.bottom {
padding: 50px;
margin-top: 30px;
margin-bottom: 30px;
.title {
padding: 20px 30px;
background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
font-weight: bold;
font-size: 20px;
color: #ffffff;
line-height: 30px;
margin-bottom: 30px;
}
.rich_content {
margin-top: 30px;
}
}
@media screen and (max-width: 768px) {
.container {
width: 100%;
}
.forWei {
display: block
}
.top {
//transform: scale(0.5);transform-origin: left top;
.cover_img {
width: 120px;
height: 160px;
margin-right: 15px;
}
.info {
.title {
font-size: 14px;
}
.time, .address, .label, .tip {
font-size: 12px;
}
.title, .time, .address, .tip, .select_item_box {
margin-bottom: 3px;
}
.select_item_box {
.label {
font-size: 12px;
}
.select_item .tag {
padding: 2px 10px;
font-size: 12px;
}
.select_item .tagActive {
padding: 2px 10px;
font-size: 12px;
}
.select_item .tagDisabled {
padding: 2px 10px;
font-size: 12px;
}
}
}
}
.bottom {
padding: 0
}
}
</style>
<template>
<el-card class="container">
<div class="title">
<div
class="add_btn"
@click="addPeople"
>
{{ languageFormat(language, "新增", "Add") }}
</div>
{{ languageFormat(language, "观影人管理", "Viewers") }}
</div>
<div class="content">
<div class="people_box">
<div
v-for="(it, index) in cousList"
:key="index"
class="people_item"
>
<div class="name">{{ it.name }}</div>
<div class="idcard">
{{ languageFormat(language, "证件号", "Identity Card") }}{{
it.idCard
}}
</div>
<div class="btn" @click="deletePeople(it.id)">
{{ languageFormat(language, "删除", "delete") }}
</div>
</div>
</div>
</div>
<el-dialog
v-model="show"
center
title="新增观影人"
width="700"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px" size="large" style="margin: 80px">
<el-form-item label="姓名" required prop="name">
<el-input v-model="form.name" size=""></el-input>
</el-form-item>
<el-form-item label="证件号" required prop="idCard">
<el-input v-model="form.idCard"></el-input>
</el-form-item>
</el-form>
<br>
<br>
<span slot="footer" class="dialog-footer">
<div style="text-align: center">
<el-button class="can_pay" @click="show = false">取 消</el-button>
<el-button class="pay" type="primary" @click="submit">确 定</el-button>
</div>
</span>
<br>
<br>
<br>
</el-dialog>
</el-card>
</template>
<script setup>
import {reactive, ref} from "vue";
import {customerListApi,aadCustomer,delCustomer} from '@/apiPc/booking'
import {deleteViewPeople, viewPeopleList} from "@/viewsPc/seat/api/index.js";
import {ElMessageBox, ElMessage} from "element-plus";
import {languageFormat} from "@/viewsPc/seat/utils/language.js";
import {useStorage} from "@vueuse/core/index";
const language = useStorage("language", 0);
const audience = reactive({
data: [],
fetchData() {
viewPeopleList().then((res) => {
audience.data = res.data;
});
},
deletePeople(id) {
ElMessageBox.confirm(
languageFormat(
language.value,
"确认删除该观看人吗?",
"Are you sure to delete this viewer?"
),
languageFormat(language.value, "提示", "Reminder"),
{
confirmButtonText: languageFormat(language.value, "确认", "confirm"),
cancelButtonText: languageFormat(language.value, "取消", "cancel"),
type: "warning",
draggable: true,
}
)
.then(() => {
deleteViewPeople({id}).then(() => {
audience.fetchData();
ElMessage({
type: "success",
message: languageFormat(
language.value,
"操作成功",
"Operate successfully"
),
});
});
})
.catch(() => {
});
},
});
const cousList = ref([])
const show = ref(false)
const form = ref({})
const formRef = ref(null)
const rules = ref({
name: [
{required: true, message: "请输入姓名", trigger: "blur"},
],
idCard: [
{required: true, message: "请输入证件号", trigger: "blur"},
],
})
customerList()
async function customerList() {
const res = await customerListApi()
// cousList.value = res.rows
cousList.value = [{},{}]
}
function addPeople() {
show.value = true
formRef.value?.resetFields()
}
function submit() {
formRef.value.validate((valid) => {
if (valid) {
console.log(form.value);
aadCustomer(form.value).then(res=>{
show.value = false
customerList()
ElMessage.success('添加成功')
})
} else {
return ElMessage.waiting('请完善信息')
}
})
}
async function deletePeople(v){
const res =await delCustomer(v.id)
if(res.code===200){
ElMessage.success('删除成功')
await customerList()
}
}
</script>
<style lang="scss" scoped>
div {
box-sizing: border-box;
}
:deep(.el-dialog) {
padding: 0;
.el-dialog__header {
height: 50px;
line-height: 50px;
background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
.el-dialog__title {
color: #fff;
}
}
}
.pay {
width: 200px;
height: 40px;
background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
border-radius: 20px;
font-weight: 500;
font-size: 16px;
color: #ffffff;
line-height: 40px;
text-align: center;
cursor: pointer;
}
.can_pay {
width: 200px;
height: 40px;
background: #f6f6f6;
border-radius: 20px;
font-weight: 500;
font-size: 16px;
color: #999;
line-height: 40px;
text-align: center;
box-sizing: border-box;
cursor: pointer;
}
.container {
//padding: 20px 0;
//:deep(.el-card__body){
// padding: 0;
//}
width: 1200px;
margin: 20px auto;
.title {
position: relative;
padding: 11px;
text-align: center;
background: linear-gradient(270deg, #493ceb 0%, #8623fc 100%);
font-size: 18px;
color: #ffffff;
.add_btn {
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
width: 68px;
height: 24px;
border-radius: 12px;
border: 1px solid #ffffff;
font-weight: 400;
font-size: 12px;
color: #ffffff;
text-align: center;
line-height: 24px;
box-sizing: border-box;
user-select: none;
cursor: pointer;
}
}
.content {
min-height: 590px;
background-color: #fff;
box-shadow: 0px 0px 46px 0px rgba(1, 16, 64, 0.08);
padding: 20px;
.people_box {
display: flex;
flex-wrap: wrap;
gap: 20px;
.people_item {
width: 275px;
height: 137px;
background: #ffffff;
border: 1px solid #dcdfe6;
padding: 16px;
.name {
font-weight: 600;
font-size: 16px;
color: #2d373f;
line-height: 22px;
}
.idcard {
font-size: 16px;
color: #95a1a6;
line-height: 22px;
margin-top: 12px;
margin-bottom: 17px;
}
.btn {
width: 69px;
height: 32px;
background: #e7e6ff;
font-weight: 400;
font-size: 16px;
color: #493ceb;
line-height: 32px;
text-align: center;
cursor: pointer;
user-select: none;
}
}
}
}
}
@media screen and (max-width: 768px) {
.container {
width: 100%;
}
}
</style>
......@@ -119,7 +119,7 @@ function popRemark(type) {
|| (form.value.isFoodView == 0 && type == '3')
|| (form.value.isMealView == 0 && type == '4')
|| (form.value.isPhotoView == 0 && type == '5')
// || (type == '0')
|| (form.value.isTicket==0&&type == '0')
) {
building()
return
......@@ -138,9 +138,9 @@ function goBooking(n) {
case 0:
// 票务
router.push({
path: `/seat/detail`,
params: {id: 1},
query: {id: 1}
path: `/booking/ticket/${props.matchId}`,
// params: {id:props.matchId},
// query: {id: props.matchId}
})
break;
case 1:
......
......@@ -135,8 +135,8 @@ function popRemark(type) {
|| (form.value.isCarView == 0 && type == '2')
|| (form.value.isFoodView == 0 && type == '3')
|| (form.value.isMealView == 0 && type == '4')
|| (type == '5' && form.value.isPhotoView == 0)
|| (type == '0')
|| (form.value.isPhotoView == 0&&type == '5')
|| (form.value.isTicket==0 &type == '0')
)
{
building()
......@@ -157,11 +157,8 @@ function goBooking(n) {
switch (n) {
case 0:
// 票务
// 票务
router.push({
path: `/seat/detail`,
params: {id: 1},
query: {id: 1}
path: `/booking/ticket/${props.matchId}`,
})
break;
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!