shop_app/pages/user/login.vue

544 lines
15 KiB
Vue
Raw Normal View History

2025-05-08 09:16:37 +08:00
<template>
<view class="loginBox" v-if="!loading">
<view class="logo">
<up-avatar :src="logo" size="100"></up-avatar>
</view>
<!-- <view class="error">
<view>login错误日志{{login_error}}</view>
<view>接口错误日志{{error}}</view>
<view>返回信息{{authResult}}</view>
<view>用户信息{{infoRes}}</view>
<view>小程序返回参数{{args}}</view>
</view> -->
<view class="cont">
<view class="oneBox" v-if="first_method == 'wx'">
<view class="btn" @click="wxLogin">
<up-icon name="weixin-fill" color="#fff" size="26"></up-icon>
<text>&nbsp;微信登录</text>
</view>
</view>
<view class="twoBox" v-else-if="first_method == 'iphone'">
<view class="row">
<up-input v-model="mobile" placeholder="请输入手机号码" border="bottom" clearable>
<template #prefix><text class="iconfont icon-tel"></text></template>
</up-input>
</view>
<view class="row">
<up-input v-model="veri_code" placeholder="请输入短信验证码" border="bottom" clearable>
<template #prefix><text class="iconfont icon-code"></text></template>
<template #suffix>
<up-code ref="uCodeRef" @change="codeChange" seconds="60" changeText="X秒重新获取" :keep-running="true"></up-code>
<up-button @tap="getCode" :text="tips" type="error" size="mini"></up-button>
</template>
</up-input>
</view>
<view class="btn" @click="iphoneLogin">登录</view>
</view>
<view class="twoBox" v-else-if="first_method == 'mima'">
<view class="row">
<up-input v-model="mobile" placeholder="请输入手机号码" border="bottom" clearable>
<template #prefix><text class="iconfont icon-tel"></text></template>
</up-input>
</view>
<view class="row">
<up-input v-model="password" placeholder="请输入登录密码" border="bottom" clearable type="password">
<template #prefix><text class="iconfont icon-pwd"></text></template>
</up-input>
</view>
<view class="btn" @click="pwdLogin">登录</view>
</view>
<view class="text">
<up-checkbox @change="changeCheck"
label="登录即代表同意" name="agree" shape="circle" :activeColor="Color" :checked="Checked" :iconSize="10" :usedAlone="true" :size="14" :labelSize="12" labelColor="#444" />
<text @click="toPage(1, '用户协议')">用户协议</text><text @click="toPage(2, '隐私政策')">隐私政策</text>
</view>
</view>
<view class="btmBox" v-if="showOther">
<view class="title">其他登录方式</view>
<view class="link">
<view class="icon" @click="first_method = 'iphone'" v-if="first_method != 'iphone'">
<text class="iconfont icon-iphone"></text>&nbsp;
<text>短信验证码登录</text>
</view>
<view class="icon" @click="first_method = 'mima'" v-if="first_method != 'mima'">
<text class="iconfont icon-mima"></text>&nbsp;
<text>账号密码登录</text>
</view>
<view class="icon" @click="first_method = 'wx'" v-if="first_method != 'wx'">
<text class="iconfont icon-weixin"></text>&nbsp;
<text>微信登录</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { ref, reactive, toRefs } from 'vue'
import { get, post } from '@/api/request.js'
import { showToast, getShopInfo } from '@/components/common.js'
import API from '@/api/index'
export default {
setup() {
const data = reactive({
logo: uni.getStorageSync('logo'),
Checked: false,
Color: uni.getStorageSync('theme_color'),
error: '',
login_error: '',
authResult: '',
infoRes: '',
args: '',
showOther: false,
first_method: 'wx',
mobile: '',
veri_code: '',
tips: '',
loading: false,
password: ''
})
// 小程序登陆
const miniLogin = () => {
if(data.Checked) {
// 跳转小程序登陆
var shares = null
plus.share.getServices(function(s){
shares = {}
for(var i in s){
var t = s[i]
shares[t.id] = t
}
shares['weixin'].launchMiniProgram({
id: 'gh_ca74730c9f77',
type: 0, // 0 正式版, 1 测试版, 2 体验版
path: 'pages/index/interim?from=app'
})
}, function(e) {
console.log("获取分享服务列表失败:" + e.message)
})
} else {
showToast('请勾选《用户协议》和《隐私政策》')
}
}
// 微信登陆
const wxLogin = () => {
if(data.Checked) {
// 直接登录
uni.showLoading({
title: '正在登录...',
mask: true
})
uni.login({
provider: 'weixin',
onlyAuthorize: true,
success: (res) => {
const { code } = res
console.log(111, res)
data.authResult = JSON.stringify(res)
uni.request({
method: 'POST',
url: API.url + '/api/v1/auth/login',
data: { code, from: 'uni-app' },
header: {
Authorization: uni.getStorageSync('token') || '',
accept: "application/json",
appid: API.appId
},
success: (val) => {
console.log(val)
if(!Array.isArray(val.data)) {
data.infoRes = JSON.stringify(val.data)
if(val.data.access_token) {
let token = val.data.token_type + ' ' + val.data.access_token
uni.setStorageSync('token', token)
uni.setStorageSync('subscribe', val.data.is_subscribe)
uni.setStorageSync('avatar', val.data.avatar)
uni.setStorageSync('nickname', val.data.nickname)
uni.setStorageSync('role', 0)
uni.setStorageSync('login_type', 'mini-app')
uni.setStorageSync('is_vip', val.data.is_vip)
uni.setStorageSync('is_new', val.data.is_new)
uni.setStorageSync('is_authorized', val.data.is_authorized)
uni.setStorageSync('is_default_avatar', val.data.is_default_avatar)
uni.setStorageSync('sessionKey', val.data.session_key)
uni.setStorageSync('saveTime', Date.now()) // 存储时间
uni.setStorageSync('expires_in', val.data.expires_in * 1000) // 失效时间
getShopInfo().then((ress) => {
uni.reLaunch({
url: '/pages/index/index'
})
uni.hideLoading()
})
}
}
},
fail: (err) => {
console.log('uni.request fail', err)
data.error = JSON.stringify(err)
uni.hideLoading()
}
})
},
fail: (err) => {
console.log('uni.login fail', err)
data.login_error = JSON.stringify(err)
uni.hideLoading()
}
})
} else {
showToast('请勾选《用户协议》和《隐私政策》')
}
}
const toPage = (id, text) => {
uni.navigateTo({ url: '/pages/mine/aboutUs/article?type=' + id + '&text=' + text })
}
const changeCheck = (e) => {
data.Checked = e
}
function loginByUnionId(params) {
uni.login({
provider: 'weixin',
onlyAuthorize: true,
success: (res) => {
const { code } = res
unionidLogin(code, params.shop_id, params.unionid)
},
fail: (err) => {
console.log('uni.login fail', err)
data.login_error = JSON.stringify(err)
}
})
}
function unionidLogin(code, shop_id, unionid_open) {
uni.request({
method: 'POST',
url: API.url + '/api/v1/auth/login',
data: {
code: code,
from: 'mini-app',
shop_id: shop_id,
unionid_open: unionid_open
},
header: {
Authorization: uni.getStorageSync('token') || '',
accept: "application/json",
appid: API.appId
},
success: (val) => {
console.log('uni.request success', val)
if(val.data && val.data.access_token) {
let token = val.data.token_type + ' ' + val.data.access_token
uni.setStorageSync('token', token)
uni.setStorageSync('subscribe', val.data.is_subscribe)
uni.setStorageSync('avatar', val.data.avatar)
uni.setStorageSync('nickname', val.data.nickname)
uni.setStorageSync('role', 0)
uni.setStorageSync('login_type', 'mini-app')
uni.setStorageSync('is_vip', val.data.is_vip)
uni.setStorageSync('is_new', val.data.is_new)
uni.setStorageSync('is_authorized', val.data.is_authorized)
uni.setStorageSync('is_default_avatar', val.data.is_default_avatar)
uni.setStorageSync('sessionKey', val.data.session_key)
uni.setStorageSync('saveTime', Date.now()) // 存储时间
uni.setStorageSync('expires_in', val.data.expires_in * 1000) // 失效时间
getShopInfo().then((ress) => {
uni.reLaunch({
url: '/pages/index/index'
})
})
}
},
fail: (err) => {
data.error = JSON.stringify(err)
console.log('uni.request fail', err)
}
})
}
const uCodeRef = ref(null)
function iphoneLogin() {
if(!data.mobile) {
return showToast('请输入手机号码')
} else if(!data.veri_code) {
return showToast('请输入短信验证码')
}
if(data.Checked) {
uni.showLoading({
title: '正在登录...',
mask: true
})
let params = {
mobile: data.mobile,
uuid: uni.getStorageSync('uuid'),
code: data.veri_code
}
post('/api/app/login/mobile/code/validate', params).then(async(res) => {
if(res.data.from == 'mini-app') { // 已经注册过小程序
await unionidLogin('abcdefg', res.data.shop_id, res.data.unionid_open)
uni.hideLoading()
} else {
uni.setStorageSync('avatar', res.data.avatar)
uni.setStorageSync('nickname', res.data.nickname)
uni.setStorageSync('shop_id', res.data.shop_id)
uni.setStorageSync('login_type', res.data.from)
uni.setStorageSync('unionid_open', res.data.unionid_open)
uni.hideLoading()
uni.reLaunch({
url: '/pages/index/index'
})
}
})
} else {
showToast('请勾选《用户协议》和《隐私政策》')
}
}
function pwdLogin() {
if(!data.mobile) {
return showToast('请输入手机号码')
} else if(!data.password) {
return showToast('请输入登录密码')
}
if(data.Checked) {
uni.showLoading({
title: '正在登录...',
mask: true
})
let params = {
mobile: data.mobile,
password: data.password
}
post('/api/app/login/mobile/code/validate', params).then(async(res) => {
if(res.data.from == 'mini-app') { // 已经注册过小程序
await unionidLogin('abcdefg', res.data.shop_id, res.data.unionid_open)
uni.hideLoading()
} else {
uni.setStorageSync('avatar', res.data.avatar)
uni.setStorageSync('nickname', res.data.nickname)
uni.setStorageSync('shop_id', res.data.shop_id)
uni.setStorageSync('login_type', res.data.from)
uni.setStorageSync('unionid_open', res.data.unionid_open)
uni.hideLoading()
uni.reLaunch({
url: '/pages/index/index'
})
}
})
} else {
showToast('请勾选《用户协议》和《隐私政策》')
}
}
const getCode = () => {
var reg_tel = /(^1[3-9]\d{9}$)|(^((0\d{2,3})-)(\d{7,8})(-(\d{3,}))?$)|(^(400)-(\d{3})-(\d{4})(.)(\d{1,4})$)|(^(400)-(\d{3})-(\d{4}$))/
if (!data.mobile || !reg_tel.test(data.mobile)) {
showToast('请输入正确的手机号码')
return
}
if (uCodeRef.value.canGetCode) {
uni.showLoading({
title: '正在获取验证码',
mask: true
})
post('/api/app/login/mobile/code', {mobile: data.mobile}).then((res) => {
uni.hideLoading()
uni.setStorageSync('uuid', res.data.uuid)
showToast('验证码已发送')
uCodeRef.value.start()
}).catch(() => {
uni.hideLoading()
if(res.message) {
showToast(res.message)
}
})
}
}
const codeChange = (text) => {
data.tips = text
}
return {
uCodeRef,
...toRefs(data),
wxLogin,
toPage,
changeCheck,
loginByUnionId,
miniLogin,
iphoneLogin,
getCode,
codeChange,
unionidLogin,
pwdLogin
}
},
async onLoad(options) {
// await this.$onLaunched
this.showOther = true
// if (plus.os.name === 'iOS') {
// this.showOther = true
// }
let login_type = uni.getStorageSync('login_type')
if(login_type == 'mobile') { // 已经手机号登陆,未授权微信
uni.redirectTo({
url: '/pages/user/authorize'
})
} else {
this.loading = false
}
},
onShow() {
let args = plus.runtime.arguments
if (args) {
console.log(args)
this.args = args
this.loginByUnionId(JSON.parse(args))
plus.runtime.arguments = null
}
}
}
</script>
<style lang="scss" scoped>
.loginBox{
width: 100%;
height: 100vh;
overflow: hidden;
box-sizing: border-box;
padding-top: 100rpx;
position: relative;
.logo{
display: flex;
justify-content: center;
}
.cont{
.text{
font-size: 24rpx;
text-align: center;
color: #444;
display: flex;
align-items: center;
justify-content: center;
text{
color: #155BD4;
}
}
}
.oneBox{
padding-top: 45%;
.btn{
width: 90%;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #68CC46;
color: #fff;
border-radius: 100rpx;
margin: 24rpx auto;
}
}
.twoBox{
padding: 30% 20px 0;
.row{
margin-bottom: 15px;
.iconfont{
color: #666;
}
}
.btn{
width: 90%;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: v-bind('Color');
color: #fff;
border-radius: 80rpx;
margin: 24rpx auto;
}
}
.btmBox{
position: absolute;
bottom: 80rpx;
width: 100%;
left: 0;
.title{
font-size: 24rpx;
color: #999;
text-align: center;
}
.link{
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: #666;
margin-top: 20rpx;
.icon{
display: flex;
align-items: center;
font-size: 26rpx;
padding: 0 14rpx;
height: 30rpx;
&:first-child{
border-right: 1px solid #aaa;
}
.iconfont{
font-size: 36rpx;
&.icon-iphone{
color: #1890FF;
}
&.icon-mima{
color: #FFB300;
}
&.icon-weixin{
color: #28C445;
}
}
}
}
.box{
display: flex;
align-items: center;
justify-content: center;
margin-top: 30rpx;
.icon{
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
text{
color: #28C445;
font-size: 32px;
&.icon-iphone{
color: #1890FF;
}
}
}
}
}
}
</style>