423 lines
10 KiB
Vue
423 lines
10 KiB
Vue
<template>
|
|
<view class="wechatLogin" v-if="flag">
|
|
<view class="topImg" v-if="meetingInfo.image">
|
|
<image :src="meetingInfo.image" style="width:100%;height:100%"/>
|
|
</view>
|
|
<view class="main">
|
|
<view class="title tn-text-2xl tn-text-bold tn-text-center tn-mt-lg tn-ml-sm tn-mr-sm tn-pb tn-border-bottom tn-grey-light_border">
|
|
{{meetingInfo.title}}
|
|
</view>
|
|
|
|
<view class="info tn-m">
|
|
<view class="option" v-if="meetingInfo.meeting_time">
|
|
<view class="time tn-flex tn-text-bold tn-text-lg">
|
|
<view class="icon tn-text-2xl">
|
|
<TnIcon name="time-fill" color="#19be6b"></TnIcon>
|
|
</view>
|
|
<view class="tn-flex tn-flex-center tn-pl-xs">
|
|
会议时间
|
|
</view>
|
|
</view>
|
|
<view class="text tn-p-sm tn-pl-xl">
|
|
{{meetingInfo.meeting_time}}
|
|
</view>
|
|
</view>
|
|
<view class="option">
|
|
<view class="address tn-flex tn-text-bold tn-text-lg">
|
|
<view class="icon tn-text-2xl">
|
|
<TnIcon name="map-fill" color="#ff9900"></TnIcon>
|
|
</view>
|
|
<view class="tn-flex tn-flex-center tn-pl-xs">
|
|
会议地点
|
|
</view>
|
|
</view>
|
|
|
|
<view class="text tn-p-sm tn-pl-xl">
|
|
{{meetingInfo.room}}
|
|
</view>
|
|
<view class="map">
|
|
<map :latitude="meetingInfo.latitude" :longitude="meetingInfo.longitude" :scale="14" :markers="markers" @tap="showMap" style="width: 100%;"></map>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="content tn-m">
|
|
<view class="label tn-flex tn-text-bold tn-text-lg">
|
|
<view class="icon tn-text-2xl">
|
|
<TnIcon name="tip-fill" color="#2979ff"></TnIcon>
|
|
</view>
|
|
<view class="tn-flex tn-flex-center tn-pl-xs">
|
|
会议详情
|
|
</view>
|
|
</view>
|
|
<view class="text tn-text">
|
|
<TnReadMore :height="350" expand-text="详情">
|
|
<mp-html :content="htmlNodes"></mp-html>
|
|
</TnReadMore>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="btns tn-pb-xl">
|
|
<view v-if="!storeUser.openid" @click="getWechatCode" class="tn-radius tn-text-center tn-p-sm tn-type-primary_bg">授权登录</view>
|
|
<view class="buttons">
|
|
<view v-if="storeUser.openid && isEntryTime && !hasEntry" class="tn-radius tn-text-center tn-p-sm tn-type-success_bg" @click="openModal">{{meetingInfo.mode === 0?'报名参会':'会议签到'}}</view>
|
|
<view v-if="storeUser.openid && isSignTime && hasEntry" @click="signIn" class="tn-radius tn-text-center tn-p-sm tn-type-warning_bg">{{signInfo.isSign === 1?'查看签到信息':'会议签到'}}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<TnModal ref="modalRef" />
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, reactive, ref, } from 'vue';
|
|
import request from '@/utils/request';
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
import TnReadMore from '@/uni_modules/tuniaoui-vue3/components/read-more/src/read-more.vue'
|
|
import TnModal from '@/uni_modules/tuniaoui-vue3/components/modal/src/modal.vue'
|
|
import type { TnModalInstance } from '@/uni_modules/tuniaoui-vue3/components/modal'
|
|
|
|
const modalRef = ref<TnModalInstance>()
|
|
|
|
const meetingId = ref()
|
|
|
|
const htmlNodes = ref()
|
|
|
|
const flag = ref(false)
|
|
|
|
const isEntryTime = ref(false)
|
|
|
|
const isSignTime = ref(false)
|
|
|
|
const hasEntry = ref(false)
|
|
|
|
const storeUser = reactive<{
|
|
openid?:string
|
|
}>({})
|
|
|
|
const appid = ref()
|
|
|
|
const dateNow = ref<number>()
|
|
|
|
const signInfo = reactive<{
|
|
isSign?:number
|
|
}>({})
|
|
|
|
const markers = ref([{
|
|
latitude: '',
|
|
longitude: '',
|
|
title: '',
|
|
iconPath: '/static/location.png',
|
|
width:40,
|
|
height:40
|
|
}])
|
|
|
|
const meetingInfo = reactive<{
|
|
title?:string,
|
|
room?:string,
|
|
image?:string,
|
|
mode?:string,
|
|
sign_time?:string,
|
|
entry_time?:string,
|
|
meeting_time?:string,
|
|
latitude?:string,
|
|
longitude?:string
|
|
}>({})
|
|
|
|
const openModal = () => {
|
|
modalRef.value?.showModal({
|
|
title: '操作提示',
|
|
content: meetingInfo.mode == '0'?'确定参会':'确定签到',
|
|
showCancel: true,
|
|
confirmText: '确定',
|
|
cancelText: '取消',
|
|
cancel: () => {
|
|
console.log('点击了取消按钮')
|
|
},
|
|
confirm: () => {
|
|
entry()
|
|
},
|
|
})
|
|
}
|
|
|
|
const getTime = () => {
|
|
let time = new Date().getTime()
|
|
dateNow.value = time
|
|
}
|
|
|
|
const getMeetingInfo = (id:number) =>{
|
|
request({
|
|
url:'/sign/meeting/'+id,
|
|
method:'GET'
|
|
}).then((res)=>{
|
|
meetingInfo.title = res.data.data.title
|
|
meetingInfo.room = markers.value[0].title = res.data.data.room
|
|
meetingInfo.image = res.data.data.image
|
|
meetingInfo.mode = res.data.data.mode
|
|
meetingInfo.sign_time = res.data.data.sign_time
|
|
meetingInfo.entry_time = res.data.data.entry_time
|
|
meetingInfo.meeting_time = res.data.data.meeting_time
|
|
meetingInfo.latitude = markers.value[0].latitude = res.data.data.location[0]
|
|
meetingInfo.longitude = markers.value[0].longitude = res.data.data.location[1]
|
|
if(res.data.data.content!=null){
|
|
let htmlString = res.data.data.content.replace(/\\/g, "").replace(/<img/g, "<img style=\"width:100%;height:auto\"");
|
|
htmlNodes.value = htmlString
|
|
}
|
|
isEntry(JSON.parse(res.data.data.entry_time))
|
|
isSign(JSON.parse(res.data.data.sign_time))
|
|
flag.value = true
|
|
uni.setNavigationBarTitle({title:res.data.data.title})
|
|
})
|
|
}
|
|
|
|
const isWechat = () => {
|
|
return String(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i)) === "micromessenger";
|
|
}
|
|
|
|
const isEntry = (timeArr:any) => {
|
|
if(!timeArr || timeArr === ''){
|
|
isEntryTime.value = true
|
|
}else{
|
|
isEntryTime.value = dateNow.value >= Date.parse(timeArr[0]) && dateNow.value <= Date.parse(timeArr[1])
|
|
}
|
|
}
|
|
|
|
const isSign = (timeArr:any) => {
|
|
isSignTime.value = dateNow.value >= Date.parse(timeArr[0]) && dateNow.value <= Date.parse(timeArr[1])
|
|
}
|
|
|
|
//获取appid
|
|
const getAppid = () =>{
|
|
request({
|
|
url:'/front/wechat/setting',
|
|
method:'GET'
|
|
}).then((res:any)=>{
|
|
appid.value = res.data.data
|
|
// appid.value = 'wx31fc3f85a64bc26f'
|
|
})
|
|
}
|
|
//通过code获取微信信息
|
|
const getUserInfo = (code:string) => {
|
|
request({
|
|
url:'/postCode',
|
|
method:'POST',
|
|
data:{code:code}
|
|
}).then(res=>{
|
|
if (res.statusCode != 200){
|
|
uni.showToast({
|
|
title:'出错了!',
|
|
duration:3000,
|
|
icon:'none'
|
|
})
|
|
}else{
|
|
afterLogin(res)
|
|
}
|
|
})
|
|
}
|
|
|
|
//保存微信信息
|
|
const afterLogin = (res:any) =>{
|
|
let user = {
|
|
avatar:res.data.headimgurl,
|
|
nickname:res.data.nickname,
|
|
openid:res.data.openid
|
|
}
|
|
uni.setStorageSync('user',user)
|
|
request({
|
|
url: '/sign/check/register',
|
|
method:'GET',
|
|
data:{'openid':res.data.openid}
|
|
}).then(result=>{
|
|
if(result.data.code === 1){
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/register?id=' + meetingId.value
|
|
})
|
|
}else{
|
|
uni.reLaunch({
|
|
url:'/pages/attendance/index?id=' + meetingId.value
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
//获取code
|
|
const getUrlCode = (name:string) =>{
|
|
return decodeURIComponent((new RegExp('[?|&]'+name+'='+'([^&;]+?)(&|#|;|$)').exec(location.href)||[,''])[1].replace(/\+/g,'%20'))||null
|
|
}
|
|
//检查code
|
|
const checkWechatCode = () =>{
|
|
let code = getUrlCode('code');
|
|
if (code) {
|
|
getUserInfo(code)
|
|
}
|
|
}
|
|
|
|
const getSignInfo = (meetingId:number) => {
|
|
request({
|
|
url: '/sign/signUser',
|
|
method:"GET",
|
|
data:{meetingId:meetingId,openid:storeUser.openid}
|
|
}).then(res=>{
|
|
if(res.data.code === 0){
|
|
hasEntry.value = true
|
|
Object.assign(signInfo,res.data.data)
|
|
}else{
|
|
console.log('没有报名')
|
|
}
|
|
})
|
|
}
|
|
|
|
//跳转获取code
|
|
const getWechatCode = () =>{
|
|
let local = encodeURI(window.location.href);
|
|
window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='
|
|
+ appid.value +
|
|
'&redirect_uri='
|
|
+ local +
|
|
'&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect';
|
|
}
|
|
|
|
const entry = () =>{
|
|
let data = {
|
|
mode:meetingInfo.mode,
|
|
openid:storeUser.openid,
|
|
meetingId:meetingId.value
|
|
}
|
|
request({
|
|
url:'/sign/check/entry',
|
|
method:'POST',
|
|
data:data
|
|
}).then( exist => {
|
|
if(exist.data.code === 1){
|
|
request({
|
|
url:'/sign/entry',
|
|
method:'POST',
|
|
data:data
|
|
}).then( res => {
|
|
uni.showToast({
|
|
title:res.data.message,
|
|
icon:'none'
|
|
})
|
|
if(res.data.code === 0){
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/entry_success?id='+meetingId.value
|
|
})
|
|
}
|
|
})
|
|
}else{
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/entry_success?id='+meetingId.value
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const signIn = () =>{
|
|
let data = {openid:storeUser.openid,meetingId:meetingId.value}
|
|
request({
|
|
url: '/sign/check/sign',
|
|
method:'POST',
|
|
data:data
|
|
}).then( exist => {
|
|
if(exist.data.code === 1){
|
|
request({
|
|
url: '/sign/sign',
|
|
method:'POST',
|
|
data:data
|
|
}).then( res => {
|
|
uni.showToast({
|
|
title:res.data.message,
|
|
icon:'none'
|
|
})
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/success?id=' + meetingId.value
|
|
})
|
|
})
|
|
}else{
|
|
uni.showToast({
|
|
title:"您已经签过到了",
|
|
icon:'none',
|
|
success: () => {
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/success?id=' + meetingId.value
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
const showMap = () => {
|
|
uni.openLocation({
|
|
latitude: parseFloat(meetingInfo.latitude),
|
|
longitude: parseFloat(meetingInfo.longitude),
|
|
name:meetingInfo.title,
|
|
address:meetingInfo.room,
|
|
success: function () {
|
|
console.log('success');
|
|
}
|
|
});
|
|
}
|
|
|
|
const getStoreUser = () =>{
|
|
Object.assign(storeUser,uni.getStorageSync('user'))
|
|
}
|
|
|
|
onMounted(()=>{
|
|
getMeetingInfo(meetingId.value)
|
|
getTime()
|
|
})
|
|
|
|
onLoad((options)=>{
|
|
meetingId.value = options.id
|
|
if (isWechat()) {
|
|
getStoreUser()
|
|
if(!storeUser.openid){
|
|
getAppid()
|
|
checkWechatCode()
|
|
}else{
|
|
getSignInfo(options.id)
|
|
}
|
|
}else{
|
|
uni.navigateTo({
|
|
url:'/pages/attendance/error'
|
|
})
|
|
}
|
|
})
|
|
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.wechatLogin{
|
|
background-color: #f5f5f5;
|
|
height: 100vh;
|
|
position: relative;
|
|
.topImg{
|
|
width: 100%;
|
|
height: 380rpx;
|
|
}
|
|
.main{
|
|
position: absolute;
|
|
top: 340rpx;
|
|
width: 100%;
|
|
background-color: #fff;
|
|
border-top-right-radius: 40rpx;
|
|
border-top-left-radius: 40rpx;
|
|
}
|
|
.info{
|
|
.option{
|
|
.map{
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.btns{
|
|
width: 60%;
|
|
margin: auto;
|
|
}
|
|
}
|
|
</style>
|