|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
@ -1,4 +1,5 @@
|
||||
import ajax from "./ajax";
|
||||
|
||||
export const login = async (params) => ajax(`/auth/login`, params, "POST", {requestBase:'sso'});
|
||||
export const login = async (params) => ajax(`/auth/login`, params, "POST", { requestBase: 'sso' });
|
||||
|
||||
export const sendVerify = async (username) => ajax(`/auth/sendVerify`, {username}, "POST", { requestBase: 'sso' });
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@ -1,269 +0,0 @@
|
||||
<template>
|
||||
<div class="login-container">
|
||||
<div class="box">
|
||||
<div class="title">
|
||||
SlashCard電子名片
|
||||
</div>
|
||||
<div class="main-section" @click="handleLogin">
|
||||
<button type="submit" class="btn">LINE登 入</button>
|
||||
</div>
|
||||
<div class="footer">
|
||||
copyright 2022
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import store from '@/store'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import router from '@/router'
|
||||
|
||||
import { Toast } from 'vant'
|
||||
|
||||
import { login } from '@/api'
|
||||
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
|
||||
const handleLogin = async()=>{
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
const handleLogin1 = async()=>{
|
||||
const client_id = '1657876696'
|
||||
const redirect_uri = ''
|
||||
let link = 'https://access.line.me/oauth2/v2.1/authorize?'
|
||||
link = link + 'response_type=code'
|
||||
link += '&client_id=' + client_id
|
||||
link += '&redirect_uri=' + redirect_uri
|
||||
link += '&state=login'
|
||||
link += '&scope=openid%20profile'
|
||||
window.location.href = link
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
*{
|
||||
font-family: 'Inter',Arial, Helvetica, sans-serif;
|
||||
box-sizing: border-box;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
*::selection{
|
||||
background-color: #c7c9ca;
|
||||
}
|
||||
body{
|
||||
background-color: #ecf0f3;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
.lead { font-size: 1.5rem; font-weight: 300; }
|
||||
.container { margin: 150px auto; max-width: 960px; }
|
||||
.box{
|
||||
margin: auto;
|
||||
box-sizing: border-box;
|
||||
margin-top: 100px;
|
||||
height:250px;
|
||||
padding: 80px 40px;
|
||||
width:340px;
|
||||
border-radius: 35px;
|
||||
background-color: #ecf0f3;
|
||||
box-shadow: -8px -8px 8px #feffff, 8px 8px 8px #161b1d2f;
|
||||
/* box-shadow: -5px -5px 5px #feffff, 5px 5px 5px #161b1d2f; */
|
||||
/* box-shadow: inset 5px 5px 5px #cbced1,
|
||||
inset -5px -5px 5px #ffffff; */
|
||||
}
|
||||
/* .box:hover{
|
||||
box-shadow: inset 5px 5px 5px #cbced1,
|
||||
inset -5px -5px 5px #ffffff;
|
||||
} */
|
||||
.box .title{
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
color:#858686;
|
||||
text-align: center;
|
||||
/* margin-bottom: 10px; */
|
||||
}
|
||||
|
||||
.box .footer{
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 100px;
|
||||
color:#858686;
|
||||
text-align: center;
|
||||
/* margin-bottom: 10px; */
|
||||
}
|
||||
|
||||
.box label{
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color:#858686;
|
||||
/* margin-bottom: 10px; */
|
||||
}
|
||||
.box .input-box{
|
||||
width:100%;
|
||||
height: 35px;
|
||||
padding-left: 20px;
|
||||
border: none;
|
||||
color:#858686;
|
||||
margin-top: 10px;
|
||||
background-color: #ecf0f3;
|
||||
outline: none;
|
||||
border-radius: 20px;
|
||||
box-shadow: inset 5px 5px 5px #cbced1,
|
||||
inset -5px -5px 5px #ffffff;
|
||||
}
|
||||
.box .input-box::placeholder{
|
||||
color:#9ea0a0;
|
||||
}
|
||||
.forget{
|
||||
margin-top:15px;
|
||||
}
|
||||
.forget .fg a{
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
color:#8f8c8c;
|
||||
line-height: 24px;
|
||||
}
|
||||
.forget .fg{
|
||||
display: inline-block;
|
||||
margin-left: 58%;
|
||||
font-size: 12px;
|
||||
}
|
||||
.forget .fg:hover{
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #b4b8b8;
|
||||
}
|
||||
.forget .checkbox-label{
|
||||
display:block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-size:22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
.label-text{
|
||||
color:#8f8c8c;
|
||||
display: inline-block;
|
||||
/* width: 100%; */
|
||||
position: absolute;
|
||||
font-weight: 500;
|
||||
left:12%;
|
||||
font-size: 13px;
|
||||
}
|
||||
.forget .checkbox-label input{
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox-label .checkbox-custom{
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0px;
|
||||
height:20px;
|
||||
width:20px;
|
||||
background-color: #ecf0f3;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
box-shadow:inset 3px 3px 3px #cbced1, inset -3px -3px 3px #ffff;
|
||||
}
|
||||
.checkbox-label input:checked ~ .checkbox-custom{
|
||||
background-color: #ecf0f3;
|
||||
border-radius: 5px;
|
||||
-webkit-transform: rotate(0deg) scale(1);
|
||||
-ms-transform: rotate(0deg) scale(1);
|
||||
transform:rotate(0deg) scale(1);
|
||||
opacity: 1;
|
||||
border:none;
|
||||
box-shadow: -4px -4px 4px #feffff, 4px 4px 4px #161b1d2f;
|
||||
}
|
||||
.checkbox-label .checkbox-custom::after{
|
||||
position: absolute;
|
||||
content:"";
|
||||
left:10px;
|
||||
top:10px;
|
||||
height:0px;
|
||||
width:0px;
|
||||
border-radius:5px;
|
||||
border:solid #635f5f;
|
||||
border-width: 0 3px 3px 0;
|
||||
-webkit-transform: rotate(0deg) scale(0);
|
||||
-ms-transform: rotate(0deg) scale(0);
|
||||
transform: rotate(0deg) scale(0);
|
||||
opacity:1;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.checkbox-label input:checked ~ .checkbox-custom::after {
|
||||
-webkit-transform: rotate(45deg) scale(1);
|
||||
-ms-transform: rotate(45deg) scale(1);
|
||||
transform: rotate(45deg) scale(1);
|
||||
opacity:1;
|
||||
left: 7px;
|
||||
top: 3px;
|
||||
width: 4px;
|
||||
height: 8px;
|
||||
border: solid #635f5f;
|
||||
border-width: 0 2px 2px 0;
|
||||
background-color: transparent;
|
||||
border-radius: 0;
|
||||
|
||||
}
|
||||
.btn{
|
||||
width:100%;
|
||||
margin-top: 20px;
|
||||
height: 38px;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 20px;
|
||||
background-color: #57BA18;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
box-shadow: -5px -5px 8px #d8e2e6, 5px 5px 10px #2c313378;
|
||||
transition: 0.8s;
|
||||
}
|
||||
.btn:hover{
|
||||
background-color: #535658;
|
||||
box-shadow: inset 5px 5px 10px #05050578,
|
||||
inset -5px -5px 10px #9e9c9c;
|
||||
}
|
||||
.social{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 14px;
|
||||
}
|
||||
.box-radius{
|
||||
border-radius:50%;
|
||||
width:40px;
|
||||
display: block;
|
||||
height:40px;
|
||||
margin: 6px;
|
||||
/* margin-top: 50px; */
|
||||
background-color: #ecf0f3;
|
||||
box-shadow: 5px 5px 6px #0d275023,-5px -5px 6px #ffffff;
|
||||
padding: 11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.box-radius:hover{
|
||||
box-shadow: inset 5px 5px 5px #cbced1,
|
||||
inset -5px -5px 5px #ffffff;
|
||||
}
|
||||
.box-radius img{
|
||||
width: 18px;
|
||||
margin: auto;
|
||||
height: 18px;
|
||||
}
|
||||
.option{
|
||||
display: block;
|
||||
margin-top: 35px;
|
||||
color: #6c6d6d;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
@ -1,226 +1,246 @@
|
||||
<template>
|
||||
<div class="reg-container">
|
||||
<van-nav-bar :title="title" />
|
||||
<van-form @submit="onSubmit">
|
||||
<van-cell-group inset>
|
||||
<van-field
|
||||
v-model="form.phone"
|
||||
label="手機號碼"
|
||||
name=""
|
||||
required
|
||||
placeholder="Ex. 0900000001 不要有空格"
|
||||
:rules="[{ required: true, message: '手機號必填' },{ pattern: /\d{10}/ , message: '手機號格式錯誤' }]"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<div style="margin: 16px;">
|
||||
<van-button round block type="primary" native-type="submit">
|
||||
送出註冊
|
||||
</van-button>
|
||||
<br/>
|
||||
<van-button round block type="default" @click="leaveReg">
|
||||
以後在說
|
||||
</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
<van-nav-bar :title="title" />
|
||||
<van-form @submit="onSubmit">
|
||||
<van-cell-group inset>
|
||||
<van-field
|
||||
v-model="form.real_name"
|
||||
label="真實姓名"
|
||||
name=""
|
||||
required
|
||||
:rules="[{ required: true, message: '真實姓名必填' }]"
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.phone"
|
||||
label="手機號碼"
|
||||
name=""
|
||||
required
|
||||
placeholder="Ex. 0900000001 不要有空格"
|
||||
:rules="[
|
||||
{ required: true, message: '手機號必填' },
|
||||
{ pattern: /\d{10}/, message: '手機號格式錯誤' },
|
||||
]"
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.email"
|
||||
label="Email"
|
||||
name=""
|
||||
required
|
||||
placeholder="Ex. example@gmail.com "
|
||||
:rules="[{ required: true, message: 'Email必填' }]"
|
||||
/>
|
||||
</van-cell-group>
|
||||
<div style="margin: 16px">
|
||||
<van-button round block type="primary" native-type="submit">
|
||||
送出註冊
|
||||
</van-button>
|
||||
<br />
|
||||
<van-button round block type="default" @click="leaveReg">
|
||||
以後在說
|
||||
</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
<van-overlay :show="crop.show" @click="crop.show = false" />
|
||||
<div class="cropper-section" v-if="crop.show">
|
||||
<div class="crop-area">
|
||||
<cropper
|
||||
class="cropper"
|
||||
ref="myCrop"
|
||||
:src="crop.img"
|
||||
:stencil-props="{
|
||||
aspectRatio: 1/1
|
||||
}"
|
||||
:auto-zoom="true"
|
||||
/>
|
||||
<cropper
|
||||
class="cropper"
|
||||
ref="myCrop"
|
||||
:src="crop.img"
|
||||
:stencil-props="{
|
||||
aspectRatio: 1 / 1,
|
||||
}"
|
||||
:auto-zoom="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="crop-btn">
|
||||
<van-button type="primary" size="small" plain @click="onClose">取消</van-button>
|
||||
<van-button type="success" size="small" plain @click="onCrop">剪裁</van-button>
|
||||
<van-button type="primary" size="small" plain @click="onClose"
|
||||
>取消</van-button
|
||||
>
|
||||
<van-button type="success" size="small" plain @click="onCrop"
|
||||
>剪裁</van-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import axios from 'axios'
|
||||
import Cookies from 'js-cookie'
|
||||
import axios from "axios";
|
||||
import Cookies from "js-cookie";
|
||||
|
||||
import { ref } from 'vue'
|
||||
import { ref } from "vue";
|
||||
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useStore } from "vuex";
|
||||
import router from "@/router";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
import {Toast} from 'vant'
|
||||
import { Toast } from "vant";
|
||||
|
||||
import { Cropper } from 'vue-advanced-cropper';
|
||||
import 'vue-advanced-cropper/dist/style.css';
|
||||
import { Cropper } from "vue-advanced-cropper";
|
||||
import "vue-advanced-cropper/dist/style.css";
|
||||
|
||||
import { register , checkLineId } from '@/api'
|
||||
import { register, checkLineId } from "@/api";
|
||||
|
||||
const URL = window.URL || window.webkitURL;
|
||||
|
||||
const route = useRoute()
|
||||
const route = useRoute();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const form = ref({
|
||||
verify: route.query.verify || null,
|
||||
aid: route.query.aid || undefined
|
||||
})
|
||||
aid: route.query.aid || undefined,
|
||||
});
|
||||
|
||||
const title = ref('註冊成為會員')
|
||||
const title = ref("註冊成為會員");
|
||||
|
||||
const myCrop = ref(null)
|
||||
const myCrop = ref(null);
|
||||
|
||||
const crop = ref({
|
||||
show: false,
|
||||
img: null,
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
if(route.query.verify){
|
||||
title.value = '會員開通'
|
||||
if (route.query.verify) {
|
||||
title.value = "會員開通";
|
||||
}
|
||||
|
||||
const validatorUrl = (val) => {
|
||||
if(val.length>0){
|
||||
return /(https?:\/\/|line:\/\/|tel:|mailto:)\S+/.test(val)
|
||||
}else{
|
||||
return true
|
||||
if (val.length > 0) {
|
||||
return /(https?:\/\/|line:\/\/|tel:|mailto:)\S+/.test(val);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const leaveReg = () => {
|
||||
window.location.replace("/error.html");
|
||||
};
|
||||
|
||||
const onCrop = () => {
|
||||
const { canvas } = myCrop.value.getResult();
|
||||
if (canvas) {
|
||||
const imgFile = new FormData();
|
||||
canvas.toBlob(async (blob) => {
|
||||
let ufile = new File([blob], "image.jpg");
|
||||
imgFile.append("user_id", form.value.user_id);
|
||||
imgFile.append("fileType", "IMAGE");
|
||||
imgFile.append("file", ufile);
|
||||
|
||||
crop.value.show = false;
|
||||
|
||||
Toast.loading({
|
||||
duration: 0,
|
||||
message: "圖片上傳中...",
|
||||
forbidClick: true,
|
||||
});
|
||||
|
||||
let res = await axios.post(
|
||||
`${process.env.VUE_APP_API_URL}/user/uploadAvatar`,
|
||||
imgFile,
|
||||
{}
|
||||
);
|
||||
|
||||
if (res.data.code == 200) {
|
||||
form.value.avatar = res.data.data;
|
||||
Toast.success("上傳成功");
|
||||
} else {
|
||||
Toast.fail("上傳失敗");
|
||||
}
|
||||
}, "image/jpeg");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const leaveReg = ()=>{
|
||||
window.location.replace('/error.html')
|
||||
}
|
||||
const onClose = () => {
|
||||
crop.value.show = false;
|
||||
};
|
||||
|
||||
const afterRead = async (file, name) => {
|
||||
crop.value.show = true;
|
||||
|
||||
const onCrop = () => {
|
||||
const { canvas } = myCrop.value.getResult();
|
||||
if (canvas) {
|
||||
const imgFile = new FormData();
|
||||
canvas.toBlob(async (blob) => {
|
||||
let ufile = new File([blob], "image.jpg");
|
||||
imgFile.append("user_id", form.value.user_id)
|
||||
imgFile.append("fileType", "IMAGE")
|
||||
imgFile.append('file', ufile)
|
||||
|
||||
crop.value.show = false
|
||||
|
||||
Toast.loading({
|
||||
duration: 0,
|
||||
message: '圖片上傳中...',
|
||||
forbidClick: true,
|
||||
});
|
||||
|
||||
let res = await axios.post(
|
||||
`${process.env.VUE_APP_API_URL}/user/uploadAvatar`,
|
||||
imgFile,
|
||||
{
|
||||
}
|
||||
)
|
||||
|
||||
if (res.data.code == 200) {
|
||||
form.value.avatar = res.data.data
|
||||
Toast.success('上傳成功');
|
||||
}else{
|
||||
Toast.fail('上傳失敗');
|
||||
}
|
||||
|
||||
}, 'image/jpeg');
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const onClose = () =>{
|
||||
crop.value.show = false
|
||||
}
|
||||
|
||||
const afterRead = async(file, name) => {
|
||||
crop.value.show = true
|
||||
|
||||
const ofile = file.file
|
||||
const ofile = file.file;
|
||||
|
||||
crop.value.img = URL.createObjectURL(ofile);
|
||||
return
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
const onSubmit = async () => {
|
||||
let { id_token } = JSON.parse(sessionStorage.getItem("reg"));
|
||||
|
||||
let { id_token } = JSON.parse(sessionStorage.getItem('line'))
|
||||
Toast.loading({
|
||||
duration: 0,
|
||||
message: "資料傳送中...",
|
||||
forbidClick: true,
|
||||
});
|
||||
|
||||
Toast.loading({
|
||||
duration: 0,
|
||||
message: '資料傳送中...',
|
||||
forbidClick: true,
|
||||
});
|
||||
if (Cookies.get("refer_code")) {
|
||||
form.value.refer_code = Cookies.get("refer_code");
|
||||
}
|
||||
|
||||
if(Cookies.get('refer_code')){
|
||||
form.value.refer_code = Cookies.get('refer_code')
|
||||
}
|
||||
|
||||
let regRes = await register({token: id_token , ...form.value})
|
||||
|
||||
if(regRes.code === 500){
|
||||
Toast('line 登入已過期')
|
||||
return router.push('/login')
|
||||
}else if(regRes.code === 200){
|
||||
Toast('註冊成功')
|
||||
Cookies.set('token',regRes.data.token, { expires: 365 ,domain: process.env.VUE_APP_DOMAIN})
|
||||
Cookies.set('uid',regRes.data.uid, { expires: 365 ,domain: process.env.VUE_APP_DOMAIN})
|
||||
return router.push('/')
|
||||
}else{
|
||||
Toast('註冊失敗')
|
||||
return router.push('/login')
|
||||
}
|
||||
}
|
||||
let regRes = await register({ token: id_token, ...form.value });
|
||||
|
||||
if (regRes.code === 500) {
|
||||
Toast("line 登入已過期");
|
||||
return router.push("/login");
|
||||
} else if (regRes.code === 200) {
|
||||
Toast("註冊成功");
|
||||
Cookies.set("token", regRes.data.token, {
|
||||
expires: 365,
|
||||
domain: store.state.domain,
|
||||
});
|
||||
Cookies.set("uid", regRes.data.uid, {
|
||||
expires: 365,
|
||||
domain: store.state.domain,
|
||||
});
|
||||
return router.push("/");
|
||||
} else {
|
||||
Toast("註冊失敗");
|
||||
return router.push("/login");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container{
|
||||
padding-bottom: 30px;
|
||||
.container {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
.title{
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
.title {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-img{
|
||||
.upload-img {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.cropper {
|
||||
height: 300px;
|
||||
// width: 300px;
|
||||
background: #DDD;
|
||||
height: 300px;
|
||||
// width: 300px;
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.cropper-section{
|
||||
.cropper-section {
|
||||
margin: 0 auto;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
top: 50px;
|
||||
// left: 0;
|
||||
height: 350px;
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
background: #DDD;
|
||||
background: #ddd;
|
||||
z-index: 8888;
|
||||
.crop-area{
|
||||
.crop-area {
|
||||
margin: 5 auto;
|
||||
width: 100%;
|
||||
height: 330px;
|
||||
}
|
||||
.crop-btn{
|
||||
.crop-btn {
|
||||
background-color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}
|
||||
</style>
|
||||
|
||||