code review

dev
Wayne 3 years ago
parent 6b309ed870
commit 1b16d983ea

@ -4,10 +4,10 @@ VITE_ENV = development
VITE_APP_BASE_URL = https://utel.zltest.com.tw
VITE_APP_LINE_LIFF_ID = 2000917272-PBWoXdOl
VITE_APP_LINE_LIFF_ID = 1656907652-p38ddKzQ
VITE_APP_SEND_URL = https://liff.line.me/2000917272-PBWoXdOl
VITE_APP_SEND_URL = https://liff.line.me/1656907652-VJq33Pdg
VITE_APP_API_URL = https://utel.zltest.com.tw/appapi/v1
VITE_APP_IMAGE_URL = https://utel.vip/storage
VITE_APP_IMAGE_URL = https://utel.zltest.com.tw/storage

@ -6,6 +6,7 @@
"scripts": {
"dev": "vite",
"build": "vite build",
"build:sta": "vite build --mode stage",
"preview": "vite preview"
},
"dependencies": {

@ -1,160 +1,212 @@
<script setup>
import moment from 'moment'
import QrcodeVue from 'qrcode.vue'
import { toClipboard } from '@soerenmartius/vue3-clipboard'
import moment from "moment";
import QrcodeVue from "qrcode.vue";
import { toClipboard } from "@soerenmartius/vue3-clipboard";
import { ref, computed, onBeforeMount, nextTick, inject } from "vue";
import { useRoute, useRouter } from 'vue-router';
import { useStore } from 'vuex';
import { ref, computed, onBeforeMount, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "vuex";
import { showToast,showSuccessToast, showConfirmDialog } from 'vant';
import { showToast, showSuccessToast, showConfirmDialog } from "vant";
import { Dialog } from 'vant';
import { Dialog } from "vant";
// import Footer from '@/components/Footer.vue'
import { login, bindCard, getMovie, getMarquee, toggleSendWithAD } from '@/api'
import { login, bindCard, getMovie, getMarquee, toggleSendWithAD } from "@/api";
const router = useRouter()
const route = useRoute()
const store = useStore()
const router = useRouter();
const route = useRoute();
const store = useStore();
const popShow = ref(false)
const showShare = ref(false)
const showNfcQrcode = ref(false)
const showShare = ref(false);
const showNfcQrcode = ref(false);
const checked = ref(true);
const imageUrl = ref(import.meta.env.VITE_APP_IMAGE_URL)
const imageUrl = ref(import.meta.env.VITE_APP_IMAGE_URL);
const userLevel = {
0: '基礎款',
1: '標準款',
2: '自製款',
3: '客製款'
}
0: "基礎款",
1: "標準款",
2: "自製款",
3: "客製款",
};
const is_due = ref(false)
const is_due = ref(false);
onBeforeMount(async () => {
const liff = window.liff;
try {
if (!liff.isLoggedIn())
liff.login({ redirectUri: window.location.href });
if (!liff.isLoggedIn()) liff.login({ redirectUri: window.location.href });
} catch (err) {
console.log(`liff.state init error ${err}`);
showToast('登入失敗。請聯絡管理員')
router.push('/login')
showToast("登入失敗。請聯絡管理員");
router.push("/login");
}
if (!sessionStorage.getItem('token')) {
const profile = await liff.getProfile()
if (!sessionStorage.getItem("token")) {
const profile = await liff.getProfile();
const id_token = liff.getIDToken()
const id_token = liff.getIDToken();
let loginRes = await login({ line_id: profile.userId, token: id_token })
let loginRes = await login({ line_id: profile.userId, token: id_token });
if (loginRes.code === 200) {
if (route.query.act === 'openright') {
showToast('您已經是本站會員')
if (route.query.act === "openright") {
showToast("您已經是本站會員");
}
sessionStorage.setItem('token', loginRes.data.token)
sessionStorage.setItem('uid', loginRes.data.uid)
sessionStorage.setItem("token", loginRes.data.token);
sessionStorage.setItem("uid", loginRes.data.uid);
} else if (loginRes.code === 202) {
if (route.query.act === 'openright') {
if (route.query.act === "openright") {
if (route.query.verify) {
//
Dialog.confirm({
title: '卡片綁定',
message: '確認是否綁定這張卡片'
}).then(async () => {
//
let bindRes = await bindCard({ uid: loginRes.data.uid, verify: route.query.verify })
if (bindRes.code === 200) {
showSuccessToast('綁定成功')
} else {
showToast.fail('綁定失敗')
}
}).catch(() => {
title: "卡片綁定",
message: "確認是否綁定這張卡片",
})
.then(async () => {
//
let bindRes = await bindCard({
uid: loginRes.data.uid,
verify: route.query.verify,
});
if (bindRes.code === 200) {
showSuccessToast("綁定成功");
} else {
showToast.fail("綁定失敗");
}
})
.catch(() => {});
}
}
sessionStorage.setItem('token', loginRes.data.token)
sessionStorage.setItem('uid', loginRes.data.uid)
sessionStorage.setItem("token", loginRes.data.token);
sessionStorage.setItem("uid", loginRes.data.uid);
} else if (loginRes.code === 201) {
if (route.query.act === 'openright') {
if (route.query.act === "openright") {
if (route.query.verify) {
router.push({
path: '/register',
path: "/register",
query: {
verify: route.query.verify
}
})
verify: route.query.verify,
},
});
return
return;
}
} else if (route.query.aid) {
router.push({
path: '/register',
path: "/register",
query: {
aid: route.query.aid
}
})
return
aid: route.query.aid,
},
});
return;
} else {
showToast('請先註冊成為本站會員')
showToast("請先註冊成為本站會員");
return router.push({
path: '/register',
query: { refer: route.query.refer }
})
path: "/register",
query: { refer: route.query.refer },
});
}
} else {
showToast("登入失敗。請聯絡管理員");
router.push("/login");
}
}
store.dispatch("user/getUserInfo");
} else {
showToast('登入失敗。請聯絡管理員')
router.push('/login')
}
});
/**
* title : 首頁廣告
* fixed : wayne
* date : 2023/10/26
*/
const noticeData = ref([]);
const adData = ref({});
onMounted(async () => {
let res;
res = await getMarquee();
if (res.code === 200) {
noticeData.value = res.data;
}
store.dispatch('user/getUserInfo')
const noticeClick = (num) => {
let url = noticeData.value[num].ad_link;
window.open(url, "_blank");
};
//
nextTick(() => {
res = await getMovie();
if (res.code === 200) {
adData.value = res.data;
popShow.value = true;
}
});
// if(userInfo.value.level===0 && userInfo.value.nc_type===0){
// showToast('')
// return router.push('/shop/inputsn')
// }
})
})
const popShow = ref(false);
const modalClose = ref(false);
const closeShow = () => {
modalClose.value = true;
};
// 使computed, userInfo.value.is_send_ad
// const adSwitchStatus = ref(Boolean(userInfo.value.is_send_ad));
const adSwitchStatus = computed(() => {
return Boolean(userInfo.value.is_send_ad);
});
const onUpdateValue = (newValue) => {
showConfirmDialog({
title: "提醒確認",
message: "是否切換開關?",
}).then(() => {
let res = toggleSendWithAD(newValue);
if (res.code === 200) {
showToast("切換成功");
} else {
showToast("切換失敗");
}
}).catch(() => {
// on cancel
});
};
const userInfo = computed(() => {
return store.state.user.userInfo
})
return store.state.user.userInfo;
});
const nfcurl = computed(() => {
return encodeURI(store.state.user.userInfo.ufcurl)
})
return encodeURI(store.state.user.userInfo.ufcurl);
});
const overdue = computed(() => {
if (store.state.user.userInfo.overdue_time > 0) {
return moment.unix(store.state.user.userInfo.overdue_time).format('YYYY-MM-DD')
return moment
.unix(store.state.user.userInfo.overdue_time)
.format("YYYY-MM-DD");
} else {
return '無期限'
return "無期限";
}
})
});
const goCardEdit = () => {
if (userInfo.value.nc_type < 2) {
router.push('/card/notice')
router.push("/card/notice");
} else {
router.push('/card/edit')
router.push("/card/edit");
}
}
};
const onSelect = (option) => {
showToast(option.name);
@ -162,67 +214,36 @@ const onSelect = (option) => {
};
const handleShowNfc = () => {
showNfcQrcode.value = true
}
showNfcQrcode.value = true;
};
const doCopy = () => {
toClipboard(userInfo.value.nfcurl)
showToast('已放入剪貼簿')
}
toClipboard(userInfo.value.nfcurl);
showToast("已放入剪貼簿");
};
const doCopyUid = () => {
toClipboard(userInfo.value.user_id)
showToast('已放入剪貼簿')
}
toClipboard(userInfo.value.user_id);
showToast("已放入剪貼簿");
};
const bindTggo = () => {
console.log(userInfo.value)
console.log(userInfo.value);
let url = `https://www.tggo.com.tw/u.cgi?&mnm=mybinding&ncode=${userInfo.value.uniqid}&name=${userInfo.value.real_name}&openExternalBrowser=1`;
window.open(url, '_blank');
}
window.open(url, "_blank");
};
const handleLogout = () => {
if (liff.isLoggedIn()) {
liff.logout();
}
sessionStorage.removeItem('token')
sessionStorage.removeItem('uid')
router.push('/login')
}
const noticeData = await getMarquee();
const noticeClick = (num) => {
let url = noticeData.data[num].ad_link;
window.open(url, '_blank');
}
const adData = await getMovie();
if (adData.code === 200) {
popShow.value = true;
}
const modalClose = ref(false)
const closeShow = () => {
modalClose.value = true;
}
const adSwitchStatus = ref(Boolean(userInfo.value.is_send_ad))
const onUpdateValue = (newValue) => {
showConfirmDialog({
title: '提醒確認',
message: '是否切換開關?',
}).then(() => {
toggleSendWithAD(newValue)
});
sessionStorage.removeItem("token");
sessionStorage.removeItem("uid");
router.push("/login");
};
</script>
<template>
<div class="home" v-cloak>
<div class="header">
@ -230,10 +251,24 @@ const onUpdateValue = (newValue) => {
<a href="javascript:;"><h5 class="umoney phone">歡迎來到會員中心</h5></a>
</div>
<van-notice-bar color="#ffffff" background="#e05338" left-icon="volume" mode="link" :scrollable="true">
<van-swipe class="notice-swipe" :touchable="false" :show-indicators="false">
<van-swipe-item v-for="(item, key, index) in noticeData.data" @click="noticeClick(key)">
{{item.ad_title}}
<van-notice-bar
color="#ffffff"
background="#e05338"
left-icon="volume"
mode="link"
:scrollable="true"
>
<van-swipe
class="notice-swipe"
:touchable="false"
:show-indicators="false"
>
<van-swipe-item
v-for="(item, key, index) in noticeData"
:key="index"
@click="noticeClick(key)"
>
{{ item.ad_title }}
</van-swipe-item>
</van-swipe>
</van-notice-bar>
@ -242,7 +277,9 @@ const onUpdateValue = (newValue) => {
<div class="avatar">
<div class="left">
<div class="imgCnt shadow-sm">
<img :src="userInfo.line_picture || import('@/assets/images/user.jpg')" />
<img
:src="userInfo.line_picture || import('@/assets/images/user.jpg')"
/>
</div>
<div class="info">
<h4 class="name">{{ userInfo.real_name }}</h4>
@ -250,8 +287,12 @@ const onUpdateValue = (newValue) => {
</div>
</div>
<div class="right">
<div class="btn btn-sm text-darkBlue" @click="handleLogout"><h4><i class="fa fa-share-alt" aria-hidden="true"></i></h4></div>
<div class="btn btn-sm text-darkBlue" @click="handleLogout"><h4><i class="fa fa-sign-out" aria-hidden="true"></i></h4></div>
<div class="btn btn-sm text-darkBlue" @click="handleLogout">
<h4><i class="fa fa-share-alt" aria-hidden="true"></i></h4>
</div>
<div class="btn btn-sm text-darkBlue" @click="handleLogout">
<h4><i class="fa fa-sign-out" aria-hidden="true"></i></h4>
</div>
</div>
</div>
@ -273,7 +314,9 @@ const onUpdateValue = (newValue) => {
<div class="bwtFlex px-3 mb-2">
<h5 class="font-weight-bold text-darkBlue">會員資料</h5>
<a href="javascript:;" @click="router.push('/member')"><h5><i class="fa fa-cog text-darkBlue" aria-hidden="true"></i></h5></a>
<a href="javascript:;" @click="router.push('/member')"
><h5><i class="fa fa-cog text-darkBlue" aria-hidden="true"></i></h5
></a>
</div>
<div class="content">
@ -292,7 +335,9 @@ const onUpdateValue = (newValue) => {
<i class="fa-solid fa-fw fa-fingerprint"></i> 會員編號
</div>
<div class="right text-right">
<a href="javascript:;" @click="doCopyUid">{{ userInfo.user_id }}</a>
<a href="javascript:;" @click="doCopyUid">{{
userInfo.user_id
}}</a>
<!-- <span class="btn btn-sm btn-tomatoRed" @click="doCopyUid"></span> -->
</div>
</div>
@ -320,7 +365,9 @@ const onUpdateValue = (newValue) => {
<i class="fa-solid fa-fw fa-qrcode"></i> 會員QRcode
</div>
<div class="right text-right">
<div class="btn btn-sm btn-darkBlue" @click="handleShowNfc"></div>
<div class="btn btn-sm btn-darkBlue" @click="handleShowNfc">
開啟掃描
</div>
</div>
</div>
<div class="item">
@ -328,7 +375,9 @@ const onUpdateValue = (newValue) => {
<i class="fa-solid fa-fw fa-link"></i> 名片連結
</div>
<div class="right text-right">
<div class="btn btn-sm btn-tomatoRed" @click="doCopy"></div>
<div class="btn btn-sm btn-tomatoRed" @click="doCopy">
複製連結
</div>
</div>
</div>
</div>
@ -353,9 +402,7 @@ const onUpdateValue = (newValue) => {
</div>
</div>
<div class="item">
<div class="left">
<i class="fa-solid fa-fw fa-phone"></i> 市話
</div>
<div class="left"><i class="fa-solid fa-fw fa-phone"></i> 市話</div>
<div class="right text-right">
{{ userInfo.tel }}
</div>
@ -386,7 +433,9 @@ const onUpdateValue = (newValue) => {
<i class="fa-solid fa-fw fa-user-tie"></i> 授權商務卡片編輯
</div>
<div class="right text-right">
<a href="javascript:;" @click="$router.push('/auth/auth')"></a>
<a href="javascript:;" @click="$router.push('/auth/auth')"
>授權</a
>
</div>
</div>
<div class="item">
@ -394,7 +443,9 @@ const onUpdateValue = (newValue) => {
<i class="fa-regular fa-fw fa-handshake"></i> 代客編輯商務卡片
</div>
<div class="right text-right">
<a href="javascript:;" @click="$router.push('/auth/getauth')"></a>
<a href="javascript:;" @click="$router.push('/auth/getauth')"
>編輯</a
>
</div>
</div>
<div class="item" v-if="userInfo.uniqid">
@ -410,7 +461,13 @@ const onUpdateValue = (newValue) => {
<i class="fa-regular fa-fw fa-paper-plane"></i> 發送名片帶廣告
</div>
<div class="right text-right">
<van-switch v-model="adSwitchStatus" @update:model-value="onUpdateValue" size="18px" active-color="#345068" inactive-color="#888888"/>
<van-switch
v-model="adSwitchStatus"
@update:model-value="onUpdateValue"
size="18px"
active-color="#345068"
inactive-color="#888888"
/>
</div>
</div>
</div>
@ -419,26 +476,59 @@ const onUpdateValue = (newValue) => {
<!-- <Footer /> -->
<van-dialog v-model:show="showNfcQrcode" title="電子名片二維碼" :show-cancel-button="true" cancel-button-text=""
:show-confirm-button="false">
<van-dialog
v-model:show="showNfcQrcode"
title="電子名片二維碼"
:show-cancel-button="true"
cancel-button-text="關閉"
:show-confirm-button="false"
>
<div class="qrcode text-center pt-3">
<qrcode-vue :value="userInfo.nfcurl" :size="200" level="M" />
</div>
</van-dialog>
<van-overlay :show="popShow" z-index="1000" :style="{background:'rgba(0, 0, 0, .85)'}">
<van-overlay
:show="popShow"
z-index="1000"
:style="{ background: 'rgba(0, 0, 0, .85)' }"
>
<div class="wrapper" @click.stop>
<div class="clip">
<van-icon :style="{display:'none',marginRight:'5px'}" @click="popShow = false" :class="{'d-block':modalClose}" name="cross" size="15"/>
<van-count-down :style="{color:'#fff'}" @finish="closeShow" :auto-start="true" :time="adData.data.play_sec*1000" format="ss 秒"/>
<van-icon
:style="{ display: 'none', marginRight: '5px' }"
@click="popShow = false"
:class="{ 'd-block': modalClose }"
name="cross"
size="15"
/>
<van-count-down
:style="{ color: '#fff' }"
@finish="closeShow"
:auto-start="true"
:time="adData.play_sec * 1000"
format="ss 秒"
/>
</div>
<div class="top">
<iframe width="100%" height="100%" :src="'https://utel.zltest.com.tw'+adData.data.ad_movie" title="YouTube video player" autoplay="true" frameborder="0" controls="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe
width="100%"
height="100%"
:src="'https://utel.zltest.com.tw' + adData.ad_movie"
title="YouTube video player"
autoplay="true"
frameborder="0"
controls="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
></iframe>
</div>
<div class="bottom">
<h5 class="title">{{adData.data.ad_title}}</h5>
<h6 class="desc ellipsis e3">{{adData.data.ad_desc}}</h6>
<van-button type="light" :url="adData.data.ad_link" block><i class="fa-solid fa-fw fa-link"></i> 前往連結</van-button>
<h5 class="title">{{ adData.ad_title }}</h5>
<h6 class="desc ellipsis e3">{{ adData.ad_desc }}</h6>
<van-button type="light" :url="adData.ad_link" block
><i class="fa-solid fa-fw fa-link"></i> 前往連結</van-button
>
</div>
</div>
</van-overlay>
@ -449,47 +539,46 @@ const onUpdateValue = (newValue) => {
<style src="@/assets/css/page/index.css"></style>
<style lang="less" scoped>
.wrapper{
.wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
.clip {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%;
.clip{
position:absolute;
display: flex;
align-items: center;
color:#ffffff;
background-color: rgba(#000000,.8);
top:5px;
right:5px;
margin-left:auto;
padding: 10px;
cursor: pointer;
z-index: 1005;
color: #ffffff;
background-color: rgba(#000000, 0.8);
top: 5px;
right: 5px;
margin-left: auto;
padding: 10px;
cursor: pointer;
z-index: 1005;
}
.top {
position: relative;
display: flex;
align-items: center;
width: 100%;
flex: 1 0 0;
}
.bottom {
position: relative;
width: 100%;
flex: 0 0 auto;
padding: 15px;
.title {
color: #ffffff;
font-weight: bold;
margin-bottom: 15px;
}
.top{
position: relative;
display: flex;
align-items: center;
width:100%;
flex: 1 0 0;
}
.bottom{
position: relative;
width:100%;
flex: 0 0 auto;
padding: 15px;
.title{
color: #ffffff;
font-weight: bold;
margin-bottom: 15px;
}
.desc{
color: #ffffff;
margin-bottom: 30px;
}
.desc {
color: #ffffff;
margin-bottom: 30px;
}
}
}
</style>
Loading…
Cancel
Save