Otsuka-APP/pages/login.vue

398 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="normal-login-container">
<view class="logo-content align-center justify-center flex">
<image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
</image>
<text class="title">大冢APS Ultra管理平台</text>
</view>
<view class="login-form-content">
<view class="input-item flex align-center">
<view class="iconfont icon-user icon"></view>
<input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" />
</view>
<view class="input-item flex align-center">
<view class="iconfont icon-password icon"></view>
<input v-model="loginForm.password" :type="passwordVisible ? 'text' : 'password'" class="input" placeholder="请输入密码" maxlength="20" :show-password="false" />
<view class="password-eye" @click="togglePasswordVisible">
<uni-icons :type="passwordVisible ? 'eye-slash' : 'eye'" size="20" color="#999"></uni-icons>
</view>
</view>
<view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
<view class="iconfont icon-code icon"></view>
<input v-model="loginForm.code" type="number" class="input" placeholder="请输入验证码" maxlength="4" />
<view class="login-code">
<image :src="codeUrl" @click="getCode" class="login-code-img"></image>
</view>
</view>
<view class="action-btn">
<button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
</view>
<view class="reg text-center" v-if="register">
<text class="text-grey1">没有账号</text>
<text @click="handleUserRegister" class="text-blue">立即注册</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, getCurrentInstance } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { getToken, setToken } from '@/utils/auth'
import { getCodeImg, autoLogin, autobind } from '@/api/login'
import { useConfigStore, useUserStore } from '@/store'
const { proxy } = getCurrentInstance()
const globalConfig = useConfigStore().config
const codeUrl = ref("")
// 验证码开关
const captchaEnabled = ref(true)
// 用户注册开关
const register = ref(false)
// 密码可见性
const passwordVisible = ref(false)
// 存储从URL获取的weixinId
const weixinId = ref('')
// 防止重复自动登录
let autoLoginExecuted = false
// 标记是否已经清除过URL参数
let urlCleared = false
const loginForm = ref({
username: "",
password: "",
code: "",
uuid: ""
})
// 切换密码可见性
function togglePasswordVisible() {
passwordVisible.value = !passwordVisible.value
}
// 用户注册
function handleUserRegister() {
proxy.$tab.redirectTo(`/pages/register`)
}
// 获取图形验证码
function getCode() {
getCodeImg().then(res => {
captchaEnabled.value = res.captchaEnabled === undefined ? true : res.captchaEnabled
if (captchaEnabled.value) {
codeUrl.value = 'data:image/gif;base64,' + res.img
loginForm.value.uuid = res.uuid
}
})
}
// 登录方法
async function handleLogin() {
if (loginForm.value.username === "") {
proxy.$modal.msgError("请输入账号")
} else if (loginForm.value.password === "") {
proxy.$modal.msgError("请输入密码")
} else if (loginForm.value.code === "" && captchaEnabled.value) {
proxy.$modal.msgError("请输入验证码")
} else {
proxy.$modal.loading("登录中,请耐心等待...")
pwdLogin()
}
}
// 密码登录有微信ID时调用autobind无微信ID时调用普通登录
async function pwdLogin() {
// 从本地存储获取微信ID
const storedWeixinId = uni.getStorageSync('weixinId')
// 优先使用内存中的,如果没有则使用本地存储的
const currentWeixinId = weixinId.value || storedWeixinId
// proxy.$modal.msgSuccess("currentWeixinId微信ID" + currentWeixinId)
// 如果有微信ID调用绑定接口
if (currentWeixinId) {
const params = {
username: loginForm.value.username,
password: loginForm.value.password,
code: loginForm.value.code,
uuid: loginForm.value.uuid,
weixinId: currentWeixinId
}
autobind(params).then(res => {
proxy.$modal.closeLoading()
if (res && res.code === 200) {
// 保存token
if (res.data && res.data.token) {
setToken(res.data.token)
proxy.$modal.msgSuccess("绑定成功,登录中...")
// 绑定成功后清除本地存储中的微信ID
uni.removeStorageSync('weixinId')
setTimeout(() => {
loginSuccess()
}, 1500)
} else {
proxy.$modal.msgError("绑定失败,请重试")
if (captchaEnabled.value) {
getCode()
}
}
} else {
proxy.$modal.msgError(res.msg || "绑定失败,请重试")
if (captchaEnabled.value) {
getCode()
}
}
}).catch(() => {
proxy.$modal.closeLoading()
if (captchaEnabled.value) {
getCode()
}
})
} else {
// 普通密码登录
useUserStore().login(loginForm.value).then(() => {
proxy.$modal.closeLoading()
loginSuccess()
}).catch(() => {
proxy.$modal.closeLoading()
if (captchaEnabled.value) {
getCode()
}
})
}
}
// 登录成功后,处理函数
function loginSuccess() {
// 设置用户信息并跳转
useUserStore().getInfo().then(() => {
proxy.$tab.reLaunch('/pages/work/index')
}).catch(() => {
// 即使获取用户信息失败,也尝试跳转
proxy.$tab.reLaunch('/pages/work/index')
})
}
// 从URL中获取weixinId参数提取?weixinId=后面所有的内容,包括#
function getWeixinIdFromUrl() {
// #ifdef H5
const currentUrl = window.location.href
// 使用正则表达式匹配 weixinId 参数,提取后面所有内容(包括#和后面的所有字符)
const match = currentUrl.match(/[?&]weixinId=(.*)/)
if (match && match[1]) {
return decodeURIComponent(match[1])
}
return null
// #endif
// #ifndef H5
return null
// #endif
}
// 清除URL中的weixinId参数
function removeWeixinIdFromUrl() {
if (urlCleared) return
// #ifdef H5
try {
const currentUrl = window.location.href
if (currentUrl.includes('weixinId=')) {
const url = new URL(currentUrl)
url.searchParams.delete('weixinId')
window.history.replaceState({}, '', url.toString())
urlCleared = true
}
} catch (e) {
console.error('清除URL参数失败', e)
}
// #endif
}
onLoad(() => {
//#ifdef H5
// 检查是否已登录
const token = getToken()
if (token) {
proxy.$tab.reLaunch('/pages/work/index')
return
}
// 防止重复执行自动登录
if (autoLoginExecuted) {
return
}
// 获取URL中的weixinId
const id = getWeixinIdFromUrl()
if (id) {
// 保存weixinId到内存
weixinId.value = id
// 保存到本地存储(先删除旧的,再保存新的)
uni.removeStorageSync('weixinId')
uni.setStorageSync('weixinId', id)
autoLoginExecuted = true
// 清除URL参数防止跳转后再次触发
removeWeixinIdFromUrl()
// 调用自动登录接口
proxy.$modal.loading("微信自动登录中...")
const bodydata = {
weixinId: id
}
autoLogin(bodydata).then(res => {
proxy.$modal.closeLoading()
// 根据返回结果处理
if (res && res.code === 200) {
// 保存token
if (res.data && res.data.token) {
setToken(res.data.token)
proxy.$modal.msgSuccess("登录成功")
// 绑定成功后清除本地存储中的微信ID
uni.removeStorageSync('weixinId')
// 获取用户信息并跳转
useUserStore().getInfo().then(() => {
proxy.$tab.reLaunch('/pages/work/index')
}).catch(() => {
if (getToken()) {
proxy.$tab.reLaunch('/pages/work/index')
} else {
proxy.$modal.msgError("登录异常,请使用账号密码登录")
getCode()
}
})
} else {
proxy.$modal.msgError("登录异常,请使用账号密码登录")
getCode()
}
} else if (res && res.code === 500) {
proxy.$modal.msgError(res?.msg || "服务器错误")
getCode()
} else {
proxy.$modal.msgError(res?.msg || "自动登录失败")
getCode()
}
}).catch(() => {
proxy.$modal.closeLoading()
// 自动登录失败显示普通登录界面weixinId 已保存在本地存储)
getCode()
})
} else {
// 没有微信ID显示普通登录界面
getCode()
}
//#endif
//#ifndef H5
// 非H5环境直接获取验证码
getCode()
//#endif
})
</script>
<style lang="scss" scoped>
page {
background-color: #ffffff;
}
.normal-login-container {
width: 100%;
.logo-content {
width: 100%;
font-size: 21px;
text-align: center;
padding-top: 15%;
image {
border-radius: 4px;
}
.title {
margin-left: 10px;
}
}
.login-form-content {
text-align: center;
margin: 20px auto;
margin-top: 15%;
width: 80%;
.input-item {
margin: 20px auto;
background-color: #f5f6f7;
height: 45px;
border-radius: 20px;
position: relative;
.icon {
font-size: 38rpx;
margin-left: 10px;
color: #999;
}
.input {
width: 100%;
font-size: 14px;
line-height: 20px;
text-align: left;
padding-left: 15px;
padding-right: 45px;
}
.password-eye {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
z-index: 10;
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
&::after {
content: '';
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
}
}
}
.login-btn {
margin-top: 40px;
height: 45px;
}
.reg {
margin-top: 15px;
}
.xieyi {
color: #333;
margin-top: 20px;
}
.login-code {
height: 38px;
float: right;
.login-code-img {
height: 38px;
position: absolute;
margin-left: 10px;
width: 200rpx;
}
}
}
}
</style>