鸿蒙对uview组件不支持吗
<template> <view class="min-h-full box-border"> <!-- :style="{ paddingTop: statusBarHeight + 44 + 'px', }" --> <!-- <view class="bg-white fixed w-[100%] top-[0]" :style="{ height: statusBarHeight + 44 + 'px', }"></view> --> <image class="myBacImg" src="@/static/images/self/loginBac.png" alt="" srcset="" /> <view class="" style="position: relative; z-index: 2;"> <view class="flex justify-between"> <view class="font-[500] text-[48rpx] text-[#333] pt-[60rpx] pl-[32rpx]"> <view class="">欢迎登陆</view> <view class="">供销员工端</view> </view> <view class="pt-[14rpx]"> <image class="w-[380rpx] h-[380rpx]" src="@/static/images/self/loginTop.png" alt="" srcset="" /> </view> </view> <view class="bg-white rounded-t-[16rpx] pt-[64rpx] relative" style="height: calc(100vh - 338rpx); margin-top: -64rpx;"> <view class="h-[88rpx] flex justify-center items-center"> <view @click="tabChange(index)" class="text-[#4D4D4D] text-[30rpx] relative" v-for="(item, index) in listLoginTabs" :key="index"style="{ fontWeight: tabActive==index ? '500' : '400'}">
{{ item.name }}
<!-- marginRight: index == 0 ? '64rpx' : '0', -->
<view v-show="tabActive==index"
class="absolute bottom-[-20rpx] left-[50%] h-[6rpx] w-[60rpx] bg-[#0065f4]"
style="transform: translateX(-50%);"></view>
</view>
</view>
<view class="px-[32rpx] mt-[48rpx]">
<view class="w-[686rpx]">
<u-form :model="loginForm" ref="loginFormRef">
<u-form-item label="" prop="tenantName">
<view class="bg-[#F5F7FB] h-[88rpx] rounded-[16rpx] flex items-center w-[100%]">
<image class="h-[32rpx] w-[32rpx] ml-[32rpx] mr-[24rpx]"
src="@/static/images/self/loginPhone.png" alt="" srcset="" />
<u-input @blur="phoneInput" style=" width: 100px; height: 50px;"
placeholder-style="color:#999999; font-size: 28rpx; font-weight: 400;"
class="h-[88rpx] flex-1" v-model="loginForm.tenantName" placeholder="请输入租户名称" />
</view>
</u-form-item>
<u-form-item label="" prop="username">
<view class="bg-[#F5F7FB] h-[88rpx] rounded-[16rpx] flex items-center w-[100%]">
<image class="h-[32rpx] w-[32rpx] ml-[32rpx] mr-[24rpx]"
src="@/static/images/self/loginPhone.png" alt="" srcset="" />
<u-input placeholder-style="color:#999999; font-size: 28rpx; font-weight: 400;"
class="h-[88rpx] flex-1" v-model="loginForm.username" placeholder="请输入账号" />
</view>
</u-form-item>
<u-form-item label="" prop="password">
<view class="bg-[#F5F7FB] h-[88rpx] rounded-[16rpx] flex items-center w-[100%]">
<image class="h-[32rpx] w-[32rpx] ml-[32rpx] mr-[24rpx]"
src="@/static/images/self/loginPwd.png" alt="" srcset="" />
<u-input placeholder-style="color:#999999; font-size: 28rpx; font-weight: 400; "
password="showPassword" type="password" style="padding-right: 10rpx;"
class="pwdContainer h-[88rpx] flex-1" v-model="loginForm.password"
placeholder="请输入密码" />
<!-- <u-icon class="ml-[24rpx] mr-[32rpx]" :name="showPassword ? 'eye-off' : 'eye-fill'"
color="#999" size="48" @click="changePassword"></u-icon> -->
</view>
</u-form-item>
<!-- <u-form-item label="" prop="mobile" v-if="tabActive == 1">
<view class="bg-[#F5F7FB] h-[88rpx] rounded-[16rpx] flex items-center w-[100%]">
<image class="h-[32rpx] w-[32rpx] ml-[32rpx] mr-[24rpx]"
src="@/static/images/self/loginPhone.png" alt="" srcset="" />
<u-input placeholder-style="color:#999999; font-size: 28rpx; font-weight: 400;"
class="h-[88rpx] flex-1" v-model="loginForm.mobile" placeholder="请输入手机号" />
</view>
</u-form-item>
<u-form-item label="" prop="code" v-if="tabActive == 1">
<view class="bg-[#F5F7FB] h-[88rpx] rounded-[16rpx] flex items-center w-[100%]">
<image class="h-[32rpx] w-[32rpx] ml-[32rpx] mr-[24rpx]"
src="@/static/images/self/loginPwd.png" alt="" srcset="" />
<u-input placeholder-style="color:#999999; font-size: 28rpx; font-weight: 400;"
class="h-[88rpx] flex-1" v-model="loginForm.code" placeholder="请输入验证码" />
<text v-if="!isCodeSend"
class="ml-[24rpx] mr-[32rpx] text-[#0065f4] text-[28rpx] font-[400]"
@click="sendCode">获取验证码</text>
<text v-else
class="ml-[24rpx] mr-[32rpx] text-[#999] text-[28rpx] font-[400]">{{ codeCountdown }}后重新获取</text>
</view>
</u-form-item> -->
</u-form>
</view>
<view class="flex justify-end mt-[16rpx]">
<!-- <text class="text-[#333] text-[28rpx] font-[400]" @click="forgetPwd">忘记密码?</text> -->
</view>
<button class="w-[686rpx] h-[88rpx] bg-[#0065f4] mt-[48rpx] text-[#fff] text-[32rpx] font-[500]"
@click="handleLogin">登录</button>
</view>
<view class="absolute bottom-[86rpx] left-[50%] w-[686rpx] flex justify-center"
style="transform: translateX(-50%);">
<u-checkbox v-model="isCheckAgreement" shape="circle" active-color="#0065f4">
<view class="flex text-[#999] text-[28rpx] font-[400]">
请您阅读并同意
<view @click.stop>
<navigator class="text-[#0065f4]" hover-class="none"
url="/pages/agreement/agreement?type=user_agreement">
《用户协议》
</navigator>
</view>
和
<view @click.stop>
<navigator class="text-[#0065f4]" hover-class="none"
url="/pages/agreement/agreement?type=privacy_policy">
《隐私协议》
</navigator>
</view>
</view>
</u-checkbox>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { useLockFn } from '@/hooks/useLockFn'
import { useAppStore } from '@/stores/app'
import { useUserStore } from '@/stores/user'
import { isWeixinClient } from '@/utils/client'
import { onLoad, onShow, onReady } from '@dcloudio/uni-app'
import { onMounted, computed, reactive, ref, shallowRef, } from 'vue'
import cache from '@/utils/cache'
// 接口引入
import { getBytenantName, getUserInfoAPI } from '@/api/newlogin.ts'
import { mobileLogin, accountLogin, mnpLogin, OALogin } from '@/api/account'
// 安全获取 store 的函数,延迟调用确保 pinia 就绪
const getUserStore = () => useUserStore()
let listLoginTabs = ref([{
name: '账号登录'
},
// {
// name: '验证码登录'
// },
])
const isCheckAgreement = ref(false)
let tabActive = ref(0)
let loginFormRef = ref()
let isCodeSend = ref(false)
let codeCountdown = ref(60)
let loginForm = reactive({
tenantName: "",
scene: 'account',
username: '',
password: '',
code: '',
mobile: ''
})
let showPassword = ref(true)
const changePassword = () => {
showPassword.value = !showPassword.value;
}
let loginRules = reactive({
tenantName: [
{
required: true,
message: '请输入租户名称',
// 可以单个或者同时写两个触发验证方式
trigger: ['change', 'blur'],
},
],
username: [
{
required: true,
message: '请输入账户',
// 可以单个或者同时写两个触发验证方式
trigger: ['change', 'blur'],
},
],
mobile: [
{
required: true,
message: '请输入手机号',
trigger: ['change', 'blur'],
},
{
pattern: /^1[3-9]\d{9}$/,
transform(value : any) {
return String(value);
},
message: '手机号不合法'
},
],
password: [
{
required: true,
message: '请输入密码',
trigger: ['change', 'blur']
}
],
code: [
{
required: true,
message: '请输入验证码',
trigger: ['change', 'blur']
}
],
})
const submit = () => {
if (!isCheckAgreement.value) {
uni.$u.toast('请您阅读并同意《用户协议》和《隐私协议》')
return
}
loginFormRef.value.validate(async (valid : any) => {
if (valid) {
console.log('验证通过');
const userStore = getUserStore()
userStore.login('111111111111111')
await userStore.getUser()
uni.reLaunch({
url: '/pages/index/index'
})
}
});
}
// tab栏 ( 登录方式 ) 切换
const tabChange = (index : any) => {
console.log("index", index);
tabActive.value = index
}
// 忘记密码
const forgetPwd = () => {
uni.navigateTo({
url: '/pages/newUser/forgetPwd?type=forget'
})
}
// 获取验证码
const sendCode = () => {
isCodeSend.value = true
codeCountdown.value = 60
let timer = setInterval(function () {
codeCountdown.value--
if (codeCountdown.value <= 0) {
clearInterval(timer)
}
}, 1000)
}
const checkAgreement = async () => {
if (!isCheckAgreement.value)
return Promise.reject('请勾选底部已阅读并同意《服务协议》和《隐私协议》')
}
const loginFun = async () => {
try {
await checkAgreement()
uni.showLoading({
title: '请稍后...'
})
let data
data = await accountLogin(loginForm)
if (data) {
loginHandle(data)
}
} catch (error : any) {
uni.hideLoading()
uni.$u.toast(error)
}
}
const loginHandle = async (data : any) => {
const { access_token } = data
const userStore = getUserStore()
userStore.login(access_token) // 存储 token
// await userStore.getUser()
uni.$u.toast('登录成功')
uni.hideLoading()
uni.reLaunch({
url: '/pages/index/index'
})
}
const getUserInfoFN = () => {
getUserInfoAPI().then(res => {
console.log('获取用户信息', res);
}).catch(err => {
console.log('获取用户信息失败', err);
})
}
// const getUserInfoFN = ()=>{
// getUserInfoAPI().then(res=>{
// console.log('获取用户信息', res);
// }).catch(err=>{
// console.log('获取用户信息失败', err);
// })
// }
const { lockFn: handleLogin } = useLockFn(loginFun)
// 获取租户id
let timer = ref(null)
const phoneInput = (e) => {
if (timer.value) {
clearTimeout(timer.value)
}
timer.value = setTimeout(() => {
console.log(1231231231, e);
getBytenantNameFn(e)
}, 500)
}
const getBytenantNameFn = (text) => {
getBytenantName(text).then(res => {
if (res.code == 0 && res.data && res.data.id) {
cache.set('Tenant-Id', res.data.id)
} else {
uni.showToast({
title: '未查到该租户',
icon: 'none',
})
}
}).catch(err => {
uni.showToast({
title: '查询租户失败,网络错误',
icon: 'none',
})
})
}
onReady(() => {
loginFormRef.value.setRules(loginRules);
})
onShow(async () => {
})
onLoad(async (options) => {
})
const statusBarHeight = ref(0)
const navBarHeight = ref(0)
const totalNavHeight = ref(0)
const getStatusBarHeight = () => {
// #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ || MP-KUAISHOU
try {
// 获取系统信息
const systemInfo = uni.getSystemInfoSync()
// 状态栏高度
statusBarHeight.value = systemInfo.statusBarHeight || 0
// 导航栏高度(状态栏 + 标题栏)
// 微信小程序标题栏高度通常是 44px
const titleBarHeight = 44
navBarHeight.value = statusBarHeight.value + titleBarHeight
// 总导航高度(包含状态栏)
totalNavHeight.value = navBarHeight.value
console.log('状态栏高度:', statusBarHeight.value)
console.log('导航栏高度:', navBarHeight.value)
} catch (error) {
console.error('获取状态栏高度失败:', error)
// 设置默认值
statusBarHeight.value = 20
navBarHeight.value = 64
totalNavHeight.value = 64
}
// #endif
// #ifdef H5
// H5 环境通常没有状态栏,设置为 0
statusBarHeight.value = 0
navBarHeight.value = 0
totalNavHeight.value = 0
// #endif
// #ifdef APP-PLUS
// APP 环境
try {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight || 0
navBarHeight.value = systemInfo.statusBarHeight || 0
totalNavHeight.value = systemInfo.statusBarHeight || 0
} catch (error) {
console.error('获取状态栏高度失败:', error)
statusBarHeight.value = 20
navBarHeight.value = 20
totalNavHeight.value = 20
}
// #endif
}
onMounted(() => {
getStatusBarHeight()
})
</script>
<style lang="scss">
page {
height: 100%;
background-color: #fff;
}
.myBacImg {
width: 100%;
height: 100%;
position: fixed;
background-size: 100% 100%;
z-index: 1;
}
.u-form-item__message {
padding-left: 4rpx !important;
}
.u-border-bottom:after {
border-bottom-width: 0;
}
.u-input {
height: 100%;
input {
height: 100%;
}
}
.pwdContainer {
.uicon-eye {
font-size: 48rpx !important;
}
.uicon-eye-fill {
font-size: 48rpx !important;
}
}
</style>