2025-09-16
This commit is contained in:
@@ -13,18 +13,18 @@
|
||||
<u-form :model="userLogin.userForm" ref="userLoginRef" :border-bottom="false" :error-type="['message']"
|
||||
label-width="0">
|
||||
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/user.png" prop="username">
|
||||
<u-input v-model="userLogin.userForm.username" placeholder="请输入用户名或手机号"
|
||||
<u-input v-model="userLogin.userForm.username" placeholder="请输入用户名或手机号" type="number" maxlength="11"
|
||||
placeholder-style="color: #737373;" />
|
||||
</u-form-item>
|
||||
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Lock.png" prop="password">
|
||||
<u-input type="password" v-model="userLogin.userForm.password" placeholder="请输入密码"
|
||||
<u-input type="password" v-model="userLogin.userForm.password" placeholder="请输入密码" maxlength="20"
|
||||
placeholder-style="color: #737373;" />
|
||||
</u-form-item>
|
||||
<u-form-item :left-icon-style="inputIcon" left-icon="../../static/icon/Globe.png" prop="captcha">
|
||||
<u-input v-model="userLogin.userForm.captcha" placeholder="请输入验证码"
|
||||
<u-input v-model="userLogin.userForm.captcha" placeholder="请输入验证码" maxlength="4"
|
||||
placeholder-style="color: #737373;" />
|
||||
<template v-slot:right>
|
||||
<image class="captcha-img" :src="captcha" mode=""></image>
|
||||
<image @click="loadCaptcha" class="captcha-img" :src="captcha" mode=""></image>
|
||||
</template>
|
||||
</u-form-item>
|
||||
<view class="reflash" @click="reflash">
|
||||
@@ -51,6 +51,7 @@
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { onLoad, onReady } from '@dcloudio/uni-app';
|
||||
import { captchaAPI } from '@/api/captcha.js';
|
||||
import { authAPI } from '../../api/auth';
|
||||
|
||||
// 表单图标样式
|
||||
const inputIcon = {
|
||||
@@ -60,6 +61,7 @@
|
||||
|
||||
// 登录表单
|
||||
const captcha = ref()
|
||||
const captchaId = ref()
|
||||
const userLoginRef = ref()
|
||||
const userLogin = reactive({
|
||||
userForm: {
|
||||
@@ -74,6 +76,11 @@
|
||||
required: true,
|
||||
message: '请输入用户名或手机号',
|
||||
trigger: ['change']
|
||||
},
|
||||
{
|
||||
pattern: /^1[3-9]\d{9}$/,
|
||||
message: '请输入正确的手机号格式',
|
||||
trigger: ['blur']
|
||||
}
|
||||
],
|
||||
password: [
|
||||
@@ -83,13 +90,17 @@
|
||||
trigger: ['change']
|
||||
}
|
||||
],
|
||||
code: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入验证码',
|
||||
trigger: ['change']
|
||||
}
|
||||
]
|
||||
captcha: [{
|
||||
required: true,
|
||||
message: '请输入验证码',
|
||||
trigger: ['blur']
|
||||
},
|
||||
{
|
||||
min: 4,
|
||||
max: 4,
|
||||
message: '验证码长度为4位',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -100,6 +111,7 @@
|
||||
|
||||
onMounted(() => {
|
||||
loadCaptcha()
|
||||
loadCache()
|
||||
})
|
||||
|
||||
// 刷新
|
||||
@@ -112,14 +124,80 @@
|
||||
const loadCaptcha = () => {
|
||||
captchaAPI.generate().then(res => {
|
||||
captcha.value = res.data.image
|
||||
captchaId.value = res.data.captchaId
|
||||
})
|
||||
}
|
||||
|
||||
const loadCache = () =>{
|
||||
let is_rember = uni.getStorageSync("rember")
|
||||
if(is_rember){
|
||||
userLogin.userForm.is_rember = true
|
||||
let data = JSON.parse(is_rember)
|
||||
userLogin.userForm.username = data.username
|
||||
userLogin.userForm.password = data.password
|
||||
}
|
||||
}
|
||||
|
||||
// 登录处理
|
||||
const submit = () => {
|
||||
userLoginRef.value.validate((valid : any) => {
|
||||
if (valid) {
|
||||
console.log('验证通过');
|
||||
// 登录逻辑
|
||||
const loginData = {
|
||||
username: userLogin.userForm.username,
|
||||
password: userLogin.userForm.password,
|
||||
captchaId: captchaId.value,
|
||||
captchaText: userLogin.userForm.captcha
|
||||
}
|
||||
authAPI.login(loginData).then(response => {
|
||||
console.log('登录结果', response);
|
||||
if (response.success) {
|
||||
// 激活用户
|
||||
uni.setStorageSync("token", response.token)
|
||||
if (userLogin.userForm.is_rember) {
|
||||
uni.setStorageSync("rember", {
|
||||
username: userLogin.userForm.username,
|
||||
password: userLogin.userForm.password,
|
||||
})
|
||||
}
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
success() {
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
} else if (response.token) {
|
||||
// 未激活用户
|
||||
uni.setStorageSync("token", response.token)
|
||||
if (userLogin.userForm.is_rember) {
|
||||
uni.setStorageSync("rember", JSON.stringify({
|
||||
username: userLogin.userForm.username,
|
||||
password: userLogin.userForm.password,
|
||||
}))
|
||||
}
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success',
|
||||
success() {
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
setTimeout(() => {
|
||||
userLogin.userForm.captcha = ''
|
||||
loadCaptcha()
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,12 +1,222 @@
|
||||
<template>
|
||||
<Tabbar></Tabbar>
|
||||
<view class="message-container">
|
||||
<!-- 固定背景的容器 -->
|
||||
<view class="background-container"></view>
|
||||
|
||||
<!-- 可滚动的内容区域 -->
|
||||
<view class="content-container" :style="'height:'+height+'px'">
|
||||
<view class="message-title">
|
||||
容讯聊天室
|
||||
</view>
|
||||
<u-row class="message-search">
|
||||
<u-col span="9">
|
||||
<u-search placeholder="点击查询项目" v-model="keyword" :show-action="false"></u-search>
|
||||
</u-col>
|
||||
<u-col class="collection" span="3">
|
||||
<image class="collection-icon" src="/static/icon/Bookmark.png" mode=""></image>
|
||||
<view class="collection-text">
|
||||
我的收藏
|
||||
</view>
|
||||
</u-col>
|
||||
</u-row>
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" v-for="(item,index) in menuList" @click="handleMenuChange(index)">
|
||||
<view class="menu-title">{{item.name + '(' + item.count +')'}}
|
||||
</view>
|
||||
<image class="menu-icon"
|
||||
:src="currentMenu==index?'/static/icon/Chevron down.png':'/static/icon/Chevron right Menu.png'"
|
||||
mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="program-list">
|
||||
<view class="program-item" v-for="item in programList">
|
||||
{{item.programName}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<Tabbar id="tabbarId"></Tabbar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, getCurrentInstance } from 'vue';
|
||||
import {
|
||||
onReady
|
||||
} from '@dcloudio/uni-app';
|
||||
import { onReady as onUniReady } from '@dcloudio/uni-app';
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const height = ref(0)
|
||||
|
||||
const loadHeight = () => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
let screenHeight = res.screenHeight
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#tabbarId").boundingClientRect((data : any) => {
|
||||
height.value = screenHeight - data.height
|
||||
}).exec()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const keyword = ref('')
|
||||
|
||||
// 小菜单切换
|
||||
const menuList = ref([{
|
||||
name: '全部',
|
||||
count: 5
|
||||
}, {
|
||||
name: '已投资',
|
||||
count: 5
|
||||
}, {
|
||||
name: '未读',
|
||||
count: 0
|
||||
}, {
|
||||
name: '不感兴趣',
|
||||
count: 5
|
||||
}])
|
||||
// 当前小菜单
|
||||
const currentMenu = ref(0)
|
||||
// 切换小菜单
|
||||
const handleMenuChange = (val) => {
|
||||
currentMenu.value = val
|
||||
}
|
||||
|
||||
// 项目
|
||||
const programList = ref([])
|
||||
|
||||
const mockData = () => {
|
||||
for (var i = 0; i < 20; i++) {
|
||||
programList.value.push({
|
||||
programName: "test" + i
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onUniReady(() => {
|
||||
loadHeight()
|
||||
|
||||
// 模拟数据
|
||||
mockData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss" scoped>
|
||||
.message-container {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
/* 防止容器本身滚动 */
|
||||
|
||||
</style>
|
||||
/* 固定背景 */
|
||||
.background-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, #2F75F9 0%, #F0F3FF 34.13%);
|
||||
z-index: 1;
|
||||
/* 确保背景在内容下方 */
|
||||
}
|
||||
|
||||
/* 内容滚动区域 */
|
||||
.content-container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
/* 确保内容在背景上方 */
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
padding: 32rpx;
|
||||
|
||||
.message-title {
|
||||
margin-top: 40rpx;
|
||||
text-align: center;
|
||||
font-family: SF Pro;
|
||||
font-weight: 700;
|
||||
font-style: Bold;
|
||||
font-size: 40rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 48rpx;
|
||||
letter-spacing: 0%;
|
||||
color: #FFFFFF;
|
||||
|
||||
}
|
||||
|
||||
.message-search {
|
||||
margin-top: 20rpx;
|
||||
|
||||
.collection {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
.collection-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
.collection-text {
|
||||
font-family: SF Pro;
|
||||
font-weight: 30;
|
||||
font-style: Expanded Ultralight;
|
||||
font-size: 24rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 26px;
|
||||
letter-spacing: 0%;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.menu-title {
|
||||
font-family: SF Pro;
|
||||
font-weight: 30;
|
||||
font-style: Expanded Ultralight;
|
||||
font-size: 24rpx;
|
||||
leading-trim: NONE;
|
||||
line-height: 42rpx;
|
||||
letter-spacing: 0%;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 22rpx;
|
||||
height: 22rpx;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.program-list {
|
||||
margin-top: 10rpx;
|
||||
|
||||
.program-item {
|
||||
// border: 1px solid #000;
|
||||
padding: 20rpx 10px;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,26 @@
|
||||
<template>
|
||||
<view class="my-container">
|
||||
|
||||
<u-button @click="loginOut">退出登录</u-button>
|
||||
|
||||
</view>
|
||||
<Tabbar></Tabbar>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
|
||||
const loginOut = () => {
|
||||
uni.removeStorageSync("token")
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
.my-container {
|
||||
|
||||
}
|
||||
</style>
|
||||
73
pages/page_template/page_template.vue
Normal file
73
pages/page_template/page_template.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<view class="message-container">
|
||||
<!-- 固定背景的容器 -->
|
||||
<view class="background-container"></view>
|
||||
|
||||
<!-- 可滚动的内容区域 -->
|
||||
<view class="content-container" :style="'height:'+height+'px'">
|
||||
</view>
|
||||
|
||||
<Tabbar id="tabbarId"></Tabbar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, getCurrentInstance } from 'vue';
|
||||
import {
|
||||
onReady
|
||||
} from '@dcloudio/uni-app';
|
||||
import { onReady as onUniReady } from '@dcloudio/uni-app';
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const height = ref(0)
|
||||
|
||||
const loadHeight = () => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
let screenHeight = res.screenHeight
|
||||
uni.createSelectorQuery().in(instance.proxy).select("#tabbarId").boundingClientRect((data : any) => {
|
||||
height.value = screenHeight - data.height
|
||||
}).exec()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onUniReady(() => {
|
||||
loadHeight()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.message-container {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
/* 防止容器本身滚动 */
|
||||
|
||||
/* 固定背景 */
|
||||
.background-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, #2F75F9 0%, #F0F3FF 34.13%);
|
||||
z-index: 1;
|
||||
/* 确保背景在内容下方 */
|
||||
}
|
||||
|
||||
/* 内容滚动区域 */
|
||||
.content-container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
/* 确保内容在背景上方 */
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
height: 100%;
|
||||
padding: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -131,9 +131,11 @@
|
||||
|
||||
// 选择省市区
|
||||
const handleRegion = (e) => {
|
||||
console.log(e);
|
||||
userRegister.userRegisterForm.regionLabel = e[0].label + "/" + e[1].label + "/" + e[2].label
|
||||
userRegister.userRegisterForm.region = e[2].value
|
||||
userRegister.userRegisterForm.province = e[0].value
|
||||
userRegister.userRegisterForm.city = e[1].value
|
||||
userRegister.userRegisterForm.district = e[2].value
|
||||
userRegister.userRegisterForm.district_id = e[2].value
|
||||
}
|
||||
|
||||
|
||||
@@ -162,10 +164,11 @@
|
||||
callback(new Error('密码必须包含字母和数字'));
|
||||
} else {
|
||||
// 如果确认密码已输入,重新验证确认密码
|
||||
if (userRegister.userRegisterForm.confirmPassword) {
|
||||
userRegisterRef.value?.validateField('confirmPassword');
|
||||
}
|
||||
callback();
|
||||
// if (userRegister.userRegisterForm.confirmPassword && userRegister.userRegisterForm.confirmPassword == userRegister.userRegisterForm.password) {
|
||||
// return true
|
||||
// }
|
||||
// callback(new Error('两次输入的密码不一致'));
|
||||
return true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,14 +186,17 @@
|
||||
const userRegisterRef = ref()
|
||||
const userRegister = reactive({
|
||||
userRegisterForm: {
|
||||
username: '13758452159',
|
||||
phone: '13758452159',
|
||||
smsCode: 'asrfdv',
|
||||
region: '',
|
||||
username: '',
|
||||
phone: '',
|
||||
smsCode: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
district_id: '',
|
||||
regionLabel: '',
|
||||
password: 's123456s',
|
||||
confirmPassword: 's123456s',
|
||||
captcha: 'vfjs',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
captcha: '',
|
||||
},
|
||||
rules: {
|
||||
phone: [{
|
||||
@@ -238,8 +244,7 @@
|
||||
max: 4,
|
||||
message: '验证码长度为4位',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
}],
|
||||
}
|
||||
})
|
||||
|
||||
@@ -252,47 +257,54 @@
|
||||
})
|
||||
return
|
||||
}
|
||||
// 等待表单验证完成
|
||||
const valid = await userRegisterRef.value.validate();
|
||||
if (valid) {
|
||||
console.log(valid);
|
||||
|
||||
try {
|
||||
userRegisterRef.value.validate((valid : any) => {
|
||||
if (valid) {
|
||||
// 验证通过后执行的逻辑
|
||||
console.log('表单验证通过', userRegister.userRegisterForm);
|
||||
|
||||
// 提交注册
|
||||
const registerData = {
|
||||
username: userRegister.userRegisterForm.phone,
|
||||
phone: userRegister.userRegisterForm.phone,
|
||||
province: userRegister.userRegisterForm.province,
|
||||
city: userRegister.userRegisterForm.city,
|
||||
district: userRegister.userRegisterForm.district,
|
||||
district_id: userRegister.userRegisterForm.district_id,
|
||||
password: userRegister.userRegisterForm.password,
|
||||
smsCode: userRegister.userRegisterForm.smsCode,
|
||||
captchaId: captchaId.value,
|
||||
captchaText: userRegister.userRegisterForm.captcha,
|
||||
}
|
||||
authAPI.register(registerData).then(response => {
|
||||
if (response.success) {
|
||||
console.log('注册结果', response);
|
||||
uni.setStorageSync("token", response.token)
|
||||
uni.setStorageSync("user", response.user)
|
||||
uni.showToast({
|
||||
title: '注册成功',
|
||||
success() {
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/home/index'
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
setTimeout(() => {
|
||||
userRegister.userRegisterForm.captcha = ''
|
||||
loadCaptcha()
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
// 验证失败时会进入这里,无需额外处理(表单会自动显示错误信息)
|
||||
console.log('表单验证失败', error);
|
||||
}
|
||||
// userRegisterRef.value.validate((valid : any) => {
|
||||
// if (valid) {
|
||||
// // 验证验证码
|
||||
// captchaAPI.verify({
|
||||
// captchaId: captchaId.value,
|
||||
// captchaText: userRegister.userRegisterForm.captcha
|
||||
// }).then(verifyResponse => {
|
||||
// console.log(verifyResponse);
|
||||
// if (!verifyResponse.data.success) {
|
||||
// uni.showToast({
|
||||
// title: verifyResponse.data.message || '验证码错误',
|
||||
// icon: 'error'
|
||||
// })
|
||||
// // 重新加载验证码
|
||||
// loadCaptcha()
|
||||
// return
|
||||
// }
|
||||
// })
|
||||
// const registerData = {
|
||||
// username: userRegister.userRegisterForm.phone,
|
||||
// phone: userRegister.userRegisterForm.phone,
|
||||
// city: userRegister.userRegisterForm.region,
|
||||
// password: userRegister.userRegisterForm.password,
|
||||
// smsCode: userRegister.userRegisterForm.smsCode,
|
||||
// captchaId: captchaId.value,
|
||||
// captchaText: userRegister.userRegisterForm.captcha,
|
||||
// province: userRegister.userRegisterForm.region,
|
||||
// }
|
||||
// authAPI.register(registerData).then(response => {
|
||||
// // 直接注册成功的情况
|
||||
// // setToken(response.data.token)
|
||||
// // setUser(response.data.user)
|
||||
// console.log(response);
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
// 手机验证码
|
||||
@@ -314,8 +326,22 @@
|
||||
// 获取手机验证码
|
||||
const getMsgCode = () => {
|
||||
// 校验手机号
|
||||
console.log("发送验证码");
|
||||
if (msgCodeRef.value.canGetCode) {
|
||||
console.log("发送验证码");
|
||||
captchaAPI.smsSend(userRegister.userRegisterForm.phone).then(res => {
|
||||
const result = res.json();
|
||||
if (result.success) {
|
||||
uni.showToast({
|
||||
title: '验证码发送成功,请查收短信',
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.message || '发送失败,请重试',
|
||||
icon: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
msgCodeRef.value.start();
|
||||
} else {
|
||||
uni.showToast({
|
||||
@@ -434,7 +460,7 @@
|
||||
letter-spacing: -2%;
|
||||
text-align: center;
|
||||
color: #3781EF;
|
||||
|
||||
display: ruby;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user