Files
ys-app/src/pages/deviceAuth/deviceAuth.vue
2025-08-12 14:46:20 +08:00

546 lines
16 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>
<view class="container" :style="{ height: `100vh` }">
<view class="bg"></view>
<view class="bg-con">
<view :style="{height: navBarPaddingTop + 'px'}"></view>
<view class="auth-title">
<image src="@/static/images/icon-lock@2x.png"/>
<text>设备授权</text>
</view>
<view class="login-con">
<!-- 登录 -->
<block v-if="!bindStatus">
<view class="login-form">
<uni-forms ref="form2" :model="formData2" :rules="rules2" label-position="top">
<uni-forms-item label="用户名" required name="username">
<view class="code-con">
<uni-easyinput prefixIcon="person" :inputBorder="false"
v-model="formData2.username" placeholder="请输入用户名"
/>
</view>
</uni-forms-item>
<uni-forms-item label="密码" required name="password" class="password">
<view class="code-con">
<uni-easyinput prefixIcon="locked" type="password" :inputBorder="false"
v-model="formData2.password" placeholder="请输入登录密码"
/>
</view>
</uni-forms-item>
</uni-forms>
</view>
<button type="primary" class="btn-submit" @click="submitForm" :loading="btnLoading" :disabled="btnLoading">设备授权申请</button>
</block>
<!-- 等待页面定时任务查询 10秒查询一次 -->
<view v-if="bindStatus==2" class="login-form approval">
<view class="approval-title">审核中请等待...</view>
<button type="primary" class="btn-refresh" @click="handleRefresh">刷新</button>
</view>
<!-- bindStatus=5-----显示授权失败联系管理员 -->
<view v-if="bindStatus==5" class="login-form approval-red-con">
<view class="approval-red">显示授权失败联系管理员</view>
</view>
<!-- bindStatus=3-----输入授权码页面 -->
<block v-if="bindStatus==3">
<view class="login-form approval" style="padding:110rpx 55rpx 150rpx;">
<view class="approval-title">审核通过请输入授权码</view>
<view class="auth-code">
<input password type="number" v-model="num1" auto-complete="off" :focus="pass1"
maxlength="1" @blur="handleBlur(1)" @input="handleInput($event,1)"
/>
<input password type="number" v-model="num2" auto-complete="off" :focus="pass2"
maxlength="1" @blur="handleBlur(2)" @input="handleInput($event,2)"
>
<input password type="number" v-model="num3" auto-complete="off" :focus="pass3"
maxlength="1" @blur="handleBlur(3)" @input="handleInput($event,3)"
>
<input password type="number" v-model="num4" auto-complete="off" :focus="pass4"
maxlength="1" @blur="handleBlur(4)" @input="handleInput($event,4)"
>
<input password type="number" v-model="num5" auto-complete="off" :focus="pass5"
maxlength="1" @blur="handleBlur(5)" @input="handleInput($event,5)"
>
<input password type="number" v-model="num6" auto-complete="off" :focus="pass6"
maxlength="1" @blur="handleBlur(6)" @input="handleInput($event,6)"
>
</view>
</view>
<button type="primary" class="btn-submit" @click="handleSubmit" :loading="subLoading" :disabled="subLoading">提交</button>
</block>
</view>
</view>
<view class="bottom-pic">
<image src="@/static/images/PicLogo@2x.png" class="pic-logo" />
<view class="bottom-bg"></view>
</view>
</view>
</view>
</template>
<script setup>
import { ref,nextTick,onMounted,onUnmounted,getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { v4 as uuidv4 } from 'uuid'
import { getNavBarPaddingTop} from '@/utils/system.js';
import { getBindStatus,authDeviceApply,authInputCode } from '@/api/auth.js';
import {showToast} from '@/utils/message.js'
import { CLIENT_ID,NETWORK_ENV } from '@/enums/cacheEnums';
import encryptObj from '@/utils/encrypt.js'
const { proxy } = getCurrentInstance();
import { useUserStore } from '@/stores/user';
const userStore = useUserStore();
onLoad(async(opt) => {
console.log("onLoad");
uni.setStorageSync('page_cache',true);
// uni.preloadPage({url: "/pages/login/login"});
// uni.preloadPage({url: "/pages/home/home"});
})
// 绑定状态1=已提交、2=等待审核、3=审核通过、4=绑定成功、5=审核拒绝)
let bindStatus = ref(undefined);
let deviceId = ref(undefined);
let timer = null;
// 获取导航栏高度用于内容区域padding
const navBarPaddingTop = ref(0);
onMounted(async () => {
navBarPaddingTop.value = getNavBarPaddingTop();
deviceId.value = uni.getStorageSync('app_device_id');// 本地设备ID
await selectBindStatus();
if(bindStatus.value==2){
// bindStatus=2-----到等待页面(定时任务查询 10秒查询一次
timer = setInterval(()=>{
refreshBindStatus()
},1000*10)//10秒刷新一次
}
})
// 组件卸载时清除定时器
onUnmounted(() => {
if (timer) clearInterval(timer)
})
// 根据设备ID查询设备状态
let selectBindStatus = async ()=>{
if(deviceId.value){
let res = await getBindStatus({uniqCode:deviceId.value})
bindStatus.value = res.bindStatus;
console.log("111bindStatus=>",bindStatus.value)
//bindStatus=4-----已绑定成功,跳转用户登录页面
if(bindStatus.value==4){
if (userStore.isLogin) {
uni.reLaunch({
url: '/pages/home/home',
});
}else{
uni.reLaunch({
url: '/pages/login/login',
});
}
}
}
}
// 刷新定时任务
let refreshBindStatus = async ()=>{
let res = await getBindStatus({uniqCode:deviceId.value})
bindStatus.value = res.bindStatus;
console.log("222bindStatus=>",bindStatus.value)
if(bindStatus.value==2){
}else{
if(bindStatus.value==4){
if (userStore.isLogin) {
uni.reLaunch({
url: '/pages/home/home',
});
}else{
uni.reLaunch({
url: '/pages/login/login',
});
}
}
if (timer) clearInterval(timer)
}
}
// 账号登录
const form2 = ref(null);
const formData2 = ref({
username: '',
password: ''
});
const rules2 = {
username: {
rules: [
{ required: true, errorMessage: '请输入用户名' },
// { minLength: 3, maxLength: 10, errorMessage: '用户名长度在3到10个字符之间' }
]
},
password: {
rules: [
{ required: true, errorMessage: '请输入密码' },
// { pattern: /^[a-zA-Z0-9]{6,12}$/, errorMessage: '密码必须是6-12位字母或数字' }
]
}
};
const btnLoading=ref(false)
// 登录提交
const submitForm = async() => {
// 用户名和密码登录
form2.value.validate().then(async param => {
btnLoading.value = true;
deviceId.value = uuidv4();
let cilentId = `${CLIENT_ID || 2}`;
let password = encryptObj.Encrypt(param.username + cilentId + "," + param.password);
console.log("password=>",password)
let systemInfo = uni.getSystemInfoSync()
let params = {
username:param.username,
password,
networkEnv:NETWORK_ENV,//1-内网2-外网
uniqCode:deviceId.value,//生成的设备唯一标识
...systemInfo,//设备信息
// #ifdef APP-PLUS
verId:systemInfo.appWgtVersion,//当前版本号
// #endif
// #ifdef H5
verId : systemInfo.appVersion,
// #endif
osAndroidApiLevel:systemInfo.osAndroidAPILevel
}
console.log("params=>",params)
let res = await authDeviceApply(params);
console.log("authDeviceApply=>",res)
btnLoading.value = false;
uni.setStorageSync('app_device_id', deviceId.value)
bindStatus.value = res.bindStatus;//默认为 2-等待审核
// 刷新状态
refreshBindStatus();
timer = setInterval(()=>{
refreshBindStatus()
},1000*10)//10秒刷新一次
}).catch(err => {
console.log('表单错误11:', err);
btnLoading.value = false;
});
};
// 在UniApp的APP端使用plus.netinfo
let getLocalIPInUniApp=()=>{
return new Promise((resolve) => {
plus.netinfo.getCurrentInfo((info) => {
const ips = [];
if (info.wifi && info.wifi.ipAddress) {
ips.push(info.wifi.ipAddress);
}
if (info.cellular && info.cellular.ipAddress) {
ips.push(info.cellular.ipAddress);
}
console.log(1111,ips)
resolve(ips.length ? ips : ['无法获取本地IP']);
});
});
}
// 刷新
const handleRefresh = ()=>{
selectBindStatus();
}
// 输入授权码内容
let num1=ref(''),num2=ref(''),num3=ref(''),num4=ref(''),num5=ref(''),num6=ref('');
let pass1=ref(false),pass2=ref(false),pass3=ref(false),pass4=ref(false),pass5=ref(false),pass6=ref(false);
// 获取值
const getValue=(num,value)=>{
let flag = false;
num = value.replace(/[^\d]/g, '');
if(num!=''){
flag=true
}
return {num,flag}
}
// input事件
const handleInput=(e,type)=>{
let value = e.detail.value;
if(type==6){
return;
}
switch (type) {
case 1:
let obj = getValue(num1.value,value);
num1.value = obj.num;
nextTick(() => {
pass2.value = true;
})
break;
case 2:
let obj2 = getValue(num2.value,value);
num2.value = obj2.num;
nextTick(() => {
pass3.value = true;
})
break;
case 3:
let obj3 = getValue(num3.value,value);
num3.value = obj3.num;
nextTick(() => {
pass4.value = true;
})
break;
case 4:
let obj4 = getValue(num4.value,value);
num4.value = obj4.num;
nextTick(() => {
pass5.value = true;
})
break;
case 5:
let obj5 = getValue(num5.value,value);
num5.value = obj5.num;
nextTick(() => {
pass6.value = true;
})
break;
case 6:
let obj6 = getValue(num6.value,value);
num6.value = obj6.num;
break;
}
}
let authCode = ref('')
const handleBlur = ()=>{
let pass1 = num1.value?num1.value:'';
let pass2 = num2.value?num2.value:'';
let pass3 = num3.value?num3.value:'';
let pass4 = num4.value?num4.value:'';
let pass5 = num5.value?num5.value:'';
let pass6 = num6.value?num6.value:'';
authCode.value = pass1+pass2+pass3+pass4+pass5+pass6;
}
// 执行设备绑定
let subLoading = ref(false)
const handleSubmit=()=>{
console.log("authCode=>",authCode.value)
if(!authCode.value){
showToast("请输入验证码")
return;
}
if(authCode.value.length!=6){
showToast("请正确输入验证码")
return;
}
let uniqCode = uni.getStorageSync('app_device_id');
let param={
uniqCode,
authCode:authCode.value
}
subLoading.value=true;
authInputCode(param).then(res=>{
uni.reLaunch({ url: '/pages/login/login' })
}).finally(()=>{
subLoading.value = false;
})
}
</script>
<style scoped>
.container {
background:#307AF5 !important;
height:100vh !important;
position: relative;
}
.container .bg{
background:url('@/static/images/bg@2x.png') no-repeat;
background-size:750rpx 663rpx;
width: 750rpx;
height: 663rpx;
margin:0 auto;
}
.container .bg-con{
position: absolute;
top:200rpx;
width:100%;
}
.container .bg-con .auth-title{
color:#fff;
margin:0 auto;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.container .bg-con .auth-title image{
width:52rpx;
height:64rpx;
margin-right: 30rpx;
}
.container .bg-con .auth-title text{
color:#fff;
font-size:56rpx;
font-weight: bold;
}
.container .login-con{
width:610rpx;
margin:70rpx auto;
}
:deep(uni-button:after){
border:none;
}
.container .login-form{
background: #fff;
border-radius: 30rpx;
padding:30rpx 55rpx 15rpx;
/* width:610rpx; */
width:500rpx;
margin:70rpx auto;
}
.container .login-form .code-con{
padding:0 0 10rpx;
margin:0 auto;
display: flex;
align-items: center;
color:#919191;
border-bottom: 1px solid #E7E7E7;
}
:deep(.uni-forms-item__label){
color:#239FDF;
font-weight: bold;
font-size:28rpx;
padding:0 !important;
}
:deep(.uni-easyinput__content){
color:#333;
font-weight: bold;
font-size:32rpx;
}
:deep(.uni-easyinput__content) .uni-icons{
font-weight: normal;
font-size:40rpx !important;
color:#239FDF !important;
}
:deep(.uni-input-placeholder){
background:none;
font-weight:normal;
color:#BFBFBF;
font-size:28rpx;
}
:deep(.uni-forms-item__error){
padding-left:60rpx;
}
:deep(.uni-forms-item .is-required){
display: none;
}
/* 使用深度选择器 */
:deep(.uni-easyinput__content .uni-icons.uniui-clear) {
color: #BFBFBF !important;
font-weight: normal !important;
font-size:40rpx !important;
}
:deep(.uni-easyinput__content .uni-icons.uniui-clear::before){
content: "\e66c" !important;
}
.btn-submit{
width:496rpx;
height:88rpx;
line-height: 88rpx;
background-color:#09BC48 !important;
margin:90rpx auto 0;
font-size:36rpx;
border-radius: 44rpx;
}
.btn-submit::after{
border:none;
}
.container .bottom-pic{
position: absolute;
bottom:48rpx;
width: 488rpx;
left:50%;
margin-left:-244rpx;
text-align: center;
}
.container .bottom-pic .pic-logo{
width:156rpx;
height:130rpx;
margin:0 auto 40rpx;
}
.container .bottom-pic .bottom-bg{
background:url('@/static/images/PicLogoTxt@2x.png') no-repeat;
background-size:488rpx 64rpx;
width: 488rpx;
height: 64rpx;
}
.container .login-con .approval{
padding:120rpx 55rpx;
}
.container .login-con .approval-red-con{
width:510rpx;
padding:120rpx 50rpx;
}
.container .login-con .approval-red{
color:#FF2B44;
font-size: 42rpx;
text-align: center;
font-weight: bold;
}
.container .login-con .approval-title{
color:#0395E0;
font-size: 42rpx;
text-align: center;
font-weight: bold;
}
.container .login-con .btn-refresh{
width:300rpx;
height:80rpx;
line-height: 80rpx;
background-color:#05A3F4 !important;
margin:90rpx auto 0;
font-size:36rpx;
border-radius: 44rpx;
}
.container .login-con .auth-code{
display: flex;
margin-top:50rpx;
justify-content: center;
}
.container .login-con .auth-code uni-input{
background:#E6E6E6;
margin-right:20rpx;
width:70rpx;
height:80rpx;
min-height: 80rpx;
border-radius: 5px;
text-align: center;
font-size: 70rpx;
font-weight: bold;
}
.container .login-con .auth-code uni-input:last-child{
margin-right: 0;
}
</style>