diff --git a/src/http/apis.js b/src/http/apis.js index 164586bb..c3ad31e3 100644 --- a/src/http/apis.js +++ b/src/http/apis.js @@ -31,6 +31,18 @@ export const historicalTickets = (data) => { data }) } +export const sendCode = (data) => { + return uniReq.post({ + url: '/api/user/send/msg', + data + }) +} +export const reTicket = (data) => { + return uniReq.post({ + url: '/api/smart/appointment/book/ticket', + data + }) +} export const upload = (data) => { return uniReq.upload({ name: data.name, @@ -56,6 +68,7 @@ export const updateInfo = (data) => { export const extractingBlindBoxes= (data) => { return uniReq.post({ url: '/api/smart/appointment/draw/ticket/from/blind/box', - data + data, + isShowMsg:false, }) } diff --git a/src/http/init.js b/src/http/init.js index 116791fc..1a75ebfe 100644 --- a/src/http/init.js +++ b/src/http/init.js @@ -1,9 +1,12 @@ import {uniRequest} from "@/http/main"; const TEST_URL='http://172.16.100.93:9052' +const TY_URL='https://warehouse.szjixun.cn/ticket' +let configV const uniReq=uniRequest.created({ baseUrl: TEST_URL, interceptor: { request(config){ + configV=config config.header.Authorization=uni.getStorageSync('token')??'' if (config.isLoading){ uni.showLoading({ @@ -17,14 +20,19 @@ const uniReq=uniRequest.created({ return config }, response(response) { - uni.hideLoading() - if (response.data.code!==200){ - uni.showToast({ - title: response.data.msg, - icon: 'none', - duration: 50000 - }) + if (configV.isShowMsg){ + if (response.data.code!==200){ + uni.showToast({ + title: response.data.msg, + icon: 'none', + duration: 50000 + }) + } } + if (configV.isLoading){ + uni.hideLoading() + } + return response.data } } diff --git a/src/http/main.ts b/src/http/main.ts index feee0b10..3817d1c8 100644 --- a/src/http/main.ts +++ b/src/http/main.ts @@ -17,6 +17,7 @@ interface RequestOptions { baseUrl?: string; url?: string; isLoading?: boolean; + isShowMsg?: boolean; data?: Record<string, any>; method?: HttpMethod; header?: Record<string, string>; @@ -67,11 +68,13 @@ type ResponseInterceptor = (response: any) => any; class uniRequest { baseUrl?: string; isLoading: boolean; + isShowMsg: boolean; defaultHeader: Record<string, string>; interceptors: { request?: RequestInterceptor; response?: ResponseInterceptor }; constructor(request: RequestOptions) { this.isLoading= request.isLoading??true + this.isShowMsg= request.isShowMsg??true this.baseUrl = request.baseUrl; this.defaultHeader = { "Content-Type": "application/json;charset=UTF-8", @@ -94,6 +97,7 @@ class uniRequest { options = this.buildRequestOptions(options) options = options || {}; options.isLoading ??= this.isLoading; + options.isShowMsg ??= this.isShowMsg; options.baseUrl = options.baseUrl || this.baseUrl; options.url = `${options.baseUrl}${options.url}`; options.data = options.data || {}; diff --git a/src/pages.json b/src/pages.json index 20165b2f..5809ec76 100644 --- a/src/pages.json +++ b/src/pages.json @@ -90,6 +90,7 @@ { "path": "pages/setup/index", "style": { + "navigationStyle": "custom", "navigationBarTitleText": "", "enablePullDownRefresh": false, "app-plus": { diff --git a/src/pages/blind-box/index.vue b/src/pages/blind-box/index.vue index 40848441..7b8310a8 100644 --- a/src/pages/blind-box/index.vue +++ b/src/pages/blind-box/index.vue @@ -27,6 +27,14 @@ <div class="wrap4">*即将跳转实名页面</div> </div> </tm-drawer> + <tm-drawer hideHeader :width="510" :height="324" ref="calendarView" placement="center" v-model:show="showWin3"> + <div class="content7"> + <div class="wrap1">领取失败</div> + <div class="wrap2">失败原因:{{errMsg}}</div> + <div class="wrap3" @click="goHome">确定</div> + <div class="wrap4">**即将返回首页</div> + </div> + </tm-drawer> </div> </div> </template> @@ -35,28 +43,72 @@ import {ref} from 'vue' import {extractingBlindBoxes} from "@/http/apis"; const imgList=ref([{url:'https://cdns.fontree.cn/fonchain-main/prod/image/1833/avatar/8395f322-b677-4f24-a13d-b79474c09d35.png'},{url:'https://cdns.fontree.cn/fonchain-main/prod/image/1833/avatar/8395f322-b677-4f24-a13d-b79474c09d35.png'}]) const showWin2=ref(false) +const showWin3=ref(false) const userInfo=ref(uni.getStorageSync('userInfo')) +const goHome=()=>{ + uni.navigateTo({ + url: '/pages/index/index' + }) +} const goRealName=()=>{ uni.navigateTo({ url: '/pages/facial/index' }) } +const errMsg=ref('') const goGet=async ()=>{ - if (!userInfo.idNum){ + if (!userInfo.value.idNum){ showWin2.value=true return } const data={ - "userName": "邢雨杨", //用户姓名 - "idCard": "411527200009129056", //用户身份证号 - "phone": "18606216921", //预约电话 + "userName": userInfo.value.realName, //用户姓名 + "idCard": userInfo.value.idNum, //用户身份证号 + "phone": userInfo.value.telNum, //预约电话 "blindBoxName": "博物馆开馆纪念盲盒" //盲盒名称 } const res=await extractingBlindBoxes(data) + if (res.code===0){ + showWin3.value=true + errMsg.value=res.msg + } } </script> <style scoped lang="scss"> +.content7{ + display: flex; + flex-direction: column; + align-items: center; + .wrap4{ + margin-top: 6rpx; + font-size: 16rpx; + color: #fff; + } + .wrap3{ + margin-top: 32rpx; + display: flex; + justify-content: center; + align-items: center; + border-radius: 30rpx; + width: 436rpx; + height: 60rpx; + background-color: #E84030; + color: #fff; + font-size: 28rpx; + } + .wrap2{ + margin-top: 30rpx; + font-size: 24rpx; + color: #644D3F; + + } + .wrap1{ + margin-top: 58rpx; + font-size: 32rpx; + color: #B1292E; + } +} .content6{ display: flex; flex-direction: column; diff --git a/src/pages/mine/index.vue b/src/pages/mine/index.vue index 97dfde9e..f114b09b 100644 --- a/src/pages/mine/index.vue +++ b/src/pages/mine/index.vue @@ -4,7 +4,7 @@ <div class="content1"> <div class="wrap1"> <div class="wrap1_1"> - <image src="../../static/06.png" alt=""/> + <image :src="userInfo.avatar" alt=""/> </div> <div class="wrap1_2"> <div class="wrap1_2_1"> diff --git a/src/pages/setup/index.vue b/src/pages/setup/index.vue index dcca8f98..972d13fb 100644 --- a/src/pages/setup/index.vue +++ b/src/pages/setup/index.vue @@ -1,8 +1,10 @@ <template> + <custom-title class="title-block" title="智慧门票"> + </custom-title> <div class="large-container"> <div class="content1"> <div class="wrap1"> - <image :src="currentAvatar"></image> + <image :src="userInfo.avatar"></image> </div> <div class="wrap2"> <div class="wrap2_1">恢复默认头像</div> @@ -13,33 +15,34 @@ <div class="wrap1"> <div class="wrap1_1"> <div class="wrap1_1_1">姓名</div> - <div class="wrap1_1_2">已实名</div> + <div class="wrap1_1_2" v-if="userInfo.idNum">已实名</div> </div> - <div class="wrap1_2">xxx</div> + <div class="wrap1_2">{{userInfo.realName}}</div> </div> <div class="wrap1"> <div class="wrap1_1"> <div class="wrap1_1_1">身份证号</div> </div> - <div class="wrap1_2">292199922283726657</div> + <div class="wrap1_2">{{userInfo.idNum}}</div> </div> <div class="wrap1"> <div class="wrap1_1"> - <div class="wrap1_1_1">微信号</div> + <div class="wrap1_1_1">手机号</div> </div> - <div class="wrap1_2">12318881999</div> + <div class="wrap1_2">{{ userInfo.telNum }}</div> </div> </div> <div class="content3">*来自微信数据共享</div> <div class="content4"> <div class="wrap1">注销账号</div> - <div class="wrap2">退出登录</div> + <div class="wrap2" @click="logOut">退出登录</div> </div> </div> </template> <script setup> import {updateInfo, upload} from "@/http/apis"; import {nextTick, ref} from 'vue' +const userInfo=ref(uni.getStorageSync('userInfo')) const currentAvatar=ref('') const changeAvatar=()=>{ @@ -50,23 +53,47 @@ const changeAvatar=()=>{ name:'file', filePath:res.tempFilePaths[0] }) - currentAvatar.value=res1.data.path + userInfo.value.avatar=res1.data.path + reqAvatar() } }) } +const logOut=()=>{ + uni.showModal({ + title: '提示', // 确认框标题 + content: '确认退出登录吗', // 确认框内容 + showCancel: true, // 是否显示取消按钮,默认为 true + cancelText: '取消', // 取消按钮的文本,默认为"取消",最多 4 个字符 + cancelColor: '#000000', // 取消按钮的文本颜色,默认为"#000000" + confirmText: '确定', // 确认按钮的文本,默认为"确定",最多 4 个字符 + confirmColor: '#576B95', // 确认按钮的文本颜色,默认为"#576B95" + success: function (res) { + if (res.confirm) { + uni.clearStorageSync() + uni.navigateTo({ + url: '/pages/login/index' + }) + } else if (res.cancel) { + } + }, + fail: function (error) { + } + }); + +} const reqAvatar=async ()=>{ const res= await updateInfo({ avatar:currentAvatar.value }) if (res.code===200) { + uni.setStorageSync('userInfo',userInfo.value) uni.showToast({ title: '更换头像成功', icon: 'success', duration: 200 }) } - console.log(res,'res') } </script> <style scoped lang="scss"> diff --git a/src/pages/ticket/index.vue b/src/pages/ticket/index.vue index 25b45b5c..fbf5db8e 100644 --- a/src/pages/ticket/index.vue +++ b/src/pages/ticket/index.vue @@ -48,7 +48,7 @@ </template> <template #r1 > <div> - <input type="text" placeholder="填写手机号" placeholder-style="color:#DBDBDB;fontSize:24rpx"/> + <input type="text" v-model="phone" placeholder="填写手机号" placeholder-style="color:#DBDBDB;fontSize:24rpx"/> </div> </template> <template #l2 > @@ -59,10 +59,9 @@ <template #r2 > <div style="position: relative;width: 100%"> <div > - <input type="text" placeholder="填写验证码" placeholder-style="color:#DBDBDB;fontSize:24rpx"/> + <input v-model="code" type="text" placeholder="填写验证码" placeholder-style="color:#DBDBDB;fontSize:24rpx"/> </div> - - <div style="position: absolute;top: 50%;transform: translateY(-50%);right: 12rpx;color: #B1292E;font-size: 24rpx">获取验证码</div> + <div @click="getCode" style="z-index:11;position: absolute;top: 50%;transform: translateY(-50%);right: 12rpx;color: #B1292E;font-size: 24rpx">{{buttonText}}</div> </div> </template> </display-box> @@ -76,7 +75,7 @@ </template> <template #r1 > <div class="r1"> - <div class="r1_1">2023年12月16日</div> + <div class="r1_1">{{dateStr?dayjs(dateStr).format('YYYY年MM月DD日'):'暂无'}}</div> <div class="r1_2" @click="showWin=true"> <image src="https://cdns.fontree.cn/fonchain-main/prod/image/1833/avatar/2c4872f9-aee5-4b04-9494-94b08c282ed9.png"></image> </div> @@ -93,13 +92,13 @@ *单次最多可预约10人 </div> <div class="r2_2"> - <div class="r2_2_1"> + <div class="r2_2_1" @click="peoNumChange(-1)"> <image src="../../static/zu1149@3x.png"></image> </div> <div class="r2_2_2"> - <input type="text"> + <input disabled v-model="peoNum" :max="10" type="text"> </div> - <div class="r2_2_3"> + <div class="r2_2_3" @click="peoNumChange(1)"> <image src="../../static/zu1150@3x.png"></image> </div> </div> @@ -111,7 +110,7 @@ *请填写所有参观人的身份证信息 </div> <div class="content8"> - <div class="wrap1"> <display-box> + <div class="wrap1" v-for="(item,index) in userInfos" :key="index"> <display-box> <template #l1> <div class="box-left"> 真实姓名 @@ -119,7 +118,7 @@ </template> <template #r1> <div class="box-right"> - <input type="text" placeholder="请填写您的真实姓名" placeholder-style="color:#DBDBDB;font-size:24rpx"/> + <input type="text" v-model="item.userName" placeholder="请填写您的真实姓名" placeholder-style="color:#DBDBDB;font-size:24rpx"/> </div> </template> <template #l2> @@ -129,14 +128,14 @@ </template> <template #r2> <div class="box-right"> - <input type="text" placeholder="填写您的身份证号码" placeholder-style="color:#DBDBDB;font-size:24rpx"/> + <input type="text" v-model="item.idCard" placeholder="填写您的身份证号码" placeholder-style="color:#DBDBDB;font-size:24rpx"/> </div> </template> </display-box></div> </div> <div class="content9"> <div class="wrap1">*预约后信息不可更改,请仔细核对预约信息</div> - <div class="wrap2">预约</div> + <div class="wrap2" @click="goReservation">预约</div> </div> <tm-drawer :height="1054" :round="8" hideHeader inContent ref="calendarView" :placement="'bottom'" v-model:show="showWin"> @@ -153,7 +152,7 @@ :model="modeltype" ></tm-calendar> <div class="content10" > - <div class="wrap1"> + <div class="wrap1" @click="showWin=false"> <image src="../../static/Close@3x.png"></image> </div> <div class="wrap2"> @@ -184,10 +183,10 @@ </div> </div> <div class="wrap3"></div> - <div class="wrap6"> + <div class="wrap6" > 请选择参观时间 </div> - <div class="wrap7"> + <div class="wrap7" > <div class="wrap7_2" @click="selectTime(index)" :class="[isBeforeCurrentTime(`${showDay?.[currentSelectedData]?.day} ${item}`)?'wrap7_1':'',index===currentSelectedTime?'wrap7_3':'']" v-for="(item,index) in info?.admissionTime.split(',')" :key="item"> <div class="wrap7_2_1">{{item}}入场</div> <div class="wrap7_2_2"> @@ -201,7 +200,7 @@ 工作日08:30-18:00、节假日/双休09:00-20:00(具体时间以景区为准)<br/> </div> <div class="wrap3" style="margin-bottom: 30rpx"></div> - <div class="wrap9">确定</div> + <div class="wrap9" @click="showWin=false">确定</div> </div> </tm-drawer> </div> @@ -215,26 +214,112 @@ import displayBox from '@/components/display-box/index.vue' dayjs.extend(localizedFormat); dayjs.locale('zh-cn'); import {useMainStore} from "@/store" -import {ref} from 'vue' -const showWin=ref(true) +import {ref,onUnmounted} from 'vue' +import {reTicket, sendCode} from "@/http/apis"; +const showWin=ref(false) +const peoNum=ref(1) const store=useMainStore() const modeltype = ref('day') const multiple = ref(false) const dateStr = ref('') +const code=ref('') const showdate = ref(false) const currentData=ref(dayjs().format('YYYY-MM-DD')) const info=ref(uni.getStorageSync('currentBooking')) +const countdown = ref(5); +const isCounting = ref(false); +const buttonText = ref(`获取验证码`); +const userInfo=ref(uni.getStorageSync('userInfo')) const viewImg=()=>{ uni.previewImage({ urls:[info.value.ticketImage], indicator:'none' }) } +const goReservation=async ()=>{ + if (!phone.value){ + uni.showToast({ + title: '手机号码不能为空', + icon: 'none', + duration: 2000 + }) + return + } + if (!code.value){ + uni.showToast({ + title: '验证码不能为空', + icon: 'none', + duration: 2000 + }) + return + } + if (!dateStr.value){ + uni.showToast({ + title: '日期不能为空', + icon: 'none', + duration: 2000 + }) + return + } +/* if (!info.value?.admissionTime?.split(',')[currentSelectedTime.value]){ + uni.showToast({ + title: '时间不能为空', + icon: 'none', + duration: 2000 + }) + return + }*/ + const data={ + ticketUid:info.value.uuid, + userName:userInfo.value.realName, + idCard:userInfo.value.idNum, + phone:phone.value, + code:code.value, + date:dateStr.value?.replaceAll('-','/'), + time:info.value?.admissionTime?.split(',')[currentSelectedTime.value], + userInfo:userInfos.value + } +const res=await reTicket(data) + console.log(res,'goReservation') +} +const getCode=async ()=>{ + console.log(buttonText.value,'buttonText.value') + if (isCounting.value) return; + isCounting.value = true; + countdown.value = 5; + buttonText.value = `剩余 ${countdown.value} 秒`; + const res= await sendCode({telNum:phone.value}) + if (res.code===200){ + uni.showToast({ + title: '发送成功', + icon: 'none', + duration: 2000 + }) + } + const intervalId = setInterval(() => { + if (countdown.value > 0) { + countdown.value--; + buttonText.value = `剩余 ${countdown.value} 秒`; + } else { + clearInterval(intervalId); + isCounting.value = false; + buttonText.value = `重新获取验证码`; + } + }, 1000); + + onUnmounted(() => { + clearInterval(intervalId); + }); + +} +const userInfos=ref([{userName:'',idCard:''}]) +const phone=ref('') const currentSelectedData=ref(undefined) const selectData=(index)=>{ if (dayjs(showDay.value[index].day).isBefore(dayjs(), 'day')){ return } + dateStr.value=showDay.value[index].day currentSelectedTime.value=undefined currentSelectedData.value=index } @@ -250,6 +335,15 @@ const selectTime=(index)=>{ } currentSelectedTime.value=index } +const peoNumChange=(num)=>{ + + peoNum.value=peoNum.value+num + if (num>0){ + userInfos.value.push({userName:'',idCard:''}) + }else if (num<0){ + userInfos.value.pop() + } +} const confirmData=(data)=>{ currentSelectedData.value=1 showDay.value=weekDays(data?.[0]?.replaceAll('/', '-')) @@ -595,6 +689,7 @@ const goMore=()=>{ .content8{ margin-top: 12rpx; .wrap1{ + margin-bottom: 24rpx; .box-left{ color: #000; font-size: 24rpx;