Files
property-manager-side/wuye-manager-uniapp/pageSubPack/loginSub/pwd-login.vue
2026-08-17 15:31:17 +08:00

420 lines
10 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="login-page">
<view class="status_bar"></view>
<!-- 标题 -->
<view class="login-title">账号密码登录</view>
<!-- 手机号输入框 -->
<view class="input-item">
<view class="input-icon">
<!-- <uni-icons type="phone" size="24" color="#999"></uni-icons> -->
<image
src="https://wuyeadmin.bugtc.com/images/login/phone.png"
mode=""
style="height: 100%; width: 100%"
></image>
</view>
<uni-easyinput
class="input-content"
type="text"
v-model="phoneNumber"
placeholder="请输入帐号"
:inputBorder="false"
:placeholderStyle="placeholderStyle"
>
</uni-easyinput>
</view>
<!-- 密码输入框 -->
<view class="input-item">
<view class="input-icon">
<!-- <uni-icons type="locked" size="24" color="#999"></uni-icons> -->
<image
src="https://wuyeadmin.bugtc.com/images/login/password.png"
mode=""
style="height: 100%; width: 100%"
></image>
</view>
<uni-easyinput
class="input-content"
type="password"
v-model="password"
placeholder="请输入6-16位密码"
:inputBorder="false"
:placeholderStyle="placeholderStyle"
>
</uni-easyinput>
</view>
<!-- 记住密码 -->
<view class="remember-wrap" style="display: none">
<view class="remember-item" @click="toggleRemember">
<uni-icons type="checkbox-filled" size="18" color="#4D5DFA" v-if="rememberPwd"></uni-icons>
<uni-icons type="checkbox" size="18" color="#999" v-else></uni-icons>
<text class="remember-text">记住密码</text>
</view>
</view>
<!-- 协议勾选 + 忘记密码 -->
<view class="agreement-wrap">
<view class="agreement-item">
<view @click="toggleAgreement">
<uni-icons
type="checkbox-filled"
size="24"
color="#4D5DFA"
v-if="agreeAgreement"
></uni-icons>
<uni-icons type="checkbox" size="24" color="#999" v-else></uni-icons>
</view>
<text class="agreement-text"
>我已阅读并同意
<text class="agreePrivacy" @click.stop="goToUserAgreement">《用户协议》</text>和
<text class="agreePrivacy" @click.stop="goToPrivacy">《隐私政策》</text>
</text>
</view>
<navigator class="forget-pwd" url="/pageSubPack/loginSub/forget-pwd">忘记密码?</navigator>
</view>
<!-- 登录按钮 -->
<button class="login-btn" @click="handleLogin">登录</button>
<!-- 底部链接 -->
<view class="bottom-link">
<navigator class="link-item" url="/pageSubPack/loginSub/login">验证码登录</navigator>
<!-- <navigator class="link-item" url="/pageSubPack/loginSub/register-new-user">注册新用户</navigator> -->
</view>
</view>
<!-- 隐私协议弹窗 -->
<privacy-popup
v-model:show="showPrivacyPopup"
@agree="agreePrivacy"
@disagree="disagreePrivacy"
@close="showPrivacyPopup = false"
/>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad, onReady } from '@dcloudio/uni-app'
import { getLoginPassword } from '../../api/api.js'
import { clearAccountStorage } from '../../api/request.js'
import PrivacyPopup from '@/components/privacy-popup/privacy-popup.vue'
import { usePermStore } from '@/stores/usePermStore'
const permStore = usePermStore()
// 响应式数据
const phoneNumber = ref('')
const password = ref('')
const agreeAgreement = ref(false) // 默认勾选
const rememberPwd = ref(false)
const placeholderStyle = ref('font-size:24rpx')
const showPrivacyPopup = ref(false)
// 计算属性:是否可登录(帐号+密码+协议都满足)
const canLogin = computed(() => {
const phoneReg = /^[a-zA-Z0-9_-]{4,16}$/ // 4-16位
const pwdReg = /^.{6,16}$/ // 密码6-16位
return phoneReg.test(phoneNumber.value) && pwdReg.test(password.value) && agreeAgreement.value
})
// 切换协议勾选
const toggleAgreement = () => {
agreeAgreement.value = !agreeAgreement.value
}
// 切换记住密码
const toggleRemember = () => {
rememberPwd.value = !rememberPwd.value
}
// 打开用户协议
const goToUserAgreement = () => {
uni.navigateTo({
url: '/pageSubPack/loginSub/user-agreement'
})
}
// 打开隐私政策
const goToPrivacy = () => {
uni.navigateTo({
url: '/pageSubPack/loginSub/privacy'
})
}
// 打开隐私协议弹窗
// const goToPrivacy = () => {
// showPrivacyPopup.value = true
// }
// 不同意隐私协议
const disagreePrivacy = () => {
agreeAgreement.value = false
showPrivacyPopup.value = false
}
// 检查表单
const checkForm = () => {}
onLoad(() => {
const savedPhone = uni.getStorageSync('rememberPhone')
const savedPwd = uni.getStorageSync('rememberPassword')
const savedRemember = uni.getStorageSync('rememberPwd')
if (savedPhone) phoneNumber.value = savedPhone
if (savedPwd) password.value = savedPwd
if (savedRemember) rememberPwd.value = savedRemember
})
onReady(() => {
// 登录页渲染完成后关闭启动屏(登录过但未登录时直接进登录页)
// #ifdef APP-PLUS
plus.navigator.closeSplashscreen()
// #endif
})
// 登录逻辑
const handleLogin = () => {
if (!phoneNumber.value) {
uni.showToast({ title: '请输入账号', icon: 'none' })
return
}
if (phoneNumber.value.length < 4 || phoneNumber.value.length > 16) {
uni.showToast({ title: '账号长度需为 4-16 位', icon: 'none' })
return
}
if (!password.value) {
uni.showToast({ title: '请输入密码', icon: 'none' })
return
}
if (password.value.length < 6) {
uni.showToast({ title: '密码至少输入 6 位', icon: 'none' })
return
}
if (password.value.length > 16) {
uni.showToast({ title: '密码不能超过 16 位', icon: 'none' })
return
}
if (!agreeAgreement.value) {
showPrivacyPopup.value = true
return
}
uni.showLoading({ title: '登录中...', mask: true })
const push_cid = uni.getStorageSync('push_cid')
// console.log('登录cid',push_cid)
let params = {
username: phoneNumber.value,
password: password.value,
cid: push_cid
}
permStore.clearPerm()
// 清除上个账号的所有缓存,防止新账号显示旧数据
clearAccountStorage()
getLoginPassword(params)
.then(res => {
// console.log('33333',res)
if (res.code === 200) {
uni.setStorageSync('token', res.data.token)
// 存用户ID
// if(res.data) {
// // 存当前绑定的小区ID,0 表示未绑定
// // const currentVillageId = res.data.currentVillageId || 0;
// // uni.setStorageSync('currentVillageId', currentVillageId);
// }
uni.setStorage({
key: 'userPermission',
data: res.data.user.permissions
})
permStore.setPerm(res.data.user.permissions)
uni.hideLoading()
// 标记引导页已看过,下次启动跳过引导
uni.setStorageSync('hasShowGuide', true)
if (rememberPwd.value) {
uni.setStorageSync('rememberPhone', phoneNumber.value)
uni.setStorageSync('rememberPassword', password.value)
uni.setStorageSync('rememberPwd', true)
} else {
uni.removeStorageSync('rememberPhone')
uni.removeStorageSync('rememberPassword')
uni.removeStorageSync('rememberPwd')
}
uni.showToast({ title: '登录成功', icon: 'success' })
setTimeout(() => {
uni.switchTab(
{
url: '/pages/index/index'
},
1000
)
})
} else {
uni.showToast({ title: res.msg, icon: 'none' })
}
})
.catch(err => {
uni.showToast({
title: err.msg,
icon: 'none'
})
})
}
// 同意隐私协议(弹窗中点击同意 → 直接登录)
const agreePrivacy = () => {
agreeAgreement.value = true
showPrivacyPopup.value = false
handleLogin()
}
</script>
<style scoped>
.login-page {
padding: 80rpx 40rpx 40rpx;
/* background-color: #f8f9fa; */
min-height: 100vh;
background: repeating-linear-gradient(180deg, #e2f0ff, #f6faff);
}
.status_bar {
height: 160px;
width: 100%;
}
.login-title {
font-size: 52rpx;
font-weight: 600;
color: #333;
text-align: center;
margin-bottom: 142rpx;
}
.input-item {
display: flex;
align-items: center;
background-color: #fff;
border-radius: 40rpx;
padding: 0 30rpx;
height: 88rpx;
margin-bottom: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.input-icon {
margin-right: 20rpx;
width: 50rpx;
height: 50rpx;
}
.input-content {
flex: 1;
font-size: 28rpx;
color: #333;
display: flex;
align-items: center;
}
/* 清除 uni-easyinput 内部默认边距 */
:deep(.uni-easyinput__content) {
margin: 0 !important;
padding: 0 !important;
min-height: auto !important;
background-color: transparent !important;
}
:deep(.uni-easyinput__content-input) {
height: 60rpx !important;
min-height: 60rpx !important;
line-height: 60rpx !important;
padding: 0 !important;
margin: 0 !important;
font-size: 28rpx;
}
.remember-wrap {
display: flex;
align-items: center;
margin: 20rpx 0 0 0;
padding: 0 10rpx;
}
.remember-item {
display: flex;
align-items: center;
}
.remember-text {
font-size: 24rpx;
color: #666;
margin-left: 10rpx;
}
.agreement-wrap {
display: flex;
justify-content: space-between;
align-items: center;
margin: 40rpx 0 28rpx 0;
padding: 0 10rpx;
}
.agreement-item {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
}
.agreement-text {
font-size: 24rpx;
color: #666;
margin-left: 10rpx;
line-height: 1.5;
}
.agreePrivacy {
color: #4d5dfa;
}
/* .agreePrivacy.active{
color: #4D5DFA;
} */
.forget-pwd {
font-size: 24rpx;
color: #666;
text-decoration: none;
flex-shrink: 0;
margin-left: 16rpx;
line-height: 1.5;
}
.login-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background-color: #4d5dfa;
color: #fff;
border-radius: 8rpx;
font-size: 28rpx;
margin-bottom: 40rpx;
}
.login-btn:disabled {
background-color: #99c8ff;
color: #fff;
/* border-radius: 50px; */
}
/* 禁用按钮边框 */
button:after {
border-radius: 8px;
}
.bottom-link {
display: flex;
justify-content: center;
padding: 0 20rpx;
}
.link-item {
font-size: 28rpx;
color: #4d5dfa;
text-decoration: none;
}
</style>