topfans/frontend/pages/profile/setNickname.vue

382 lines
7.4 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="set-nickname-container">
<!-- 背景图片 -->
<image class="background-image" src="/static/background/starbook.jpg" mode="aspectFill"></image>
<view class="background-overlay"></view>
<!-- 内容区域 -->
<view class="content-wrapper">
<!-- 导航栏 -->
<view class="nav-bar">
<view class="nav-back" @click="goBack">
<text class="back-icon"></text>
</view>
<text class="nav-title">设置昵称</text>
</view>
<!-- 表单区域居中部分 -->
<view class="form-container">
<!-- 头像 -->
<view class="avatar-wrapper">
<Avatar :nickname="nickname" :size="200" :borderWidth="8" />
</view>
<!-- 昵称输入框 -->
<view class="input-wrapper">
<input
class="input-field"
type="text"
v-model="nickname"
placeholder="请输入昵称"
maxlength="20"
placeholder-class="input-placeholder"
/>
</view>
<!-- 错误提示 -->
<view v-if="errorMessage" class="error-message">
<text>{{ errorMessage }}</text>
</view>
<!-- 下一步按钮(圆形箭头) -->
<view class="next-button-wrapper">
<button class="btn-next" @click="handleNext">
<text class="arrow-icon"></text>
</button>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { useStore } from 'vuex';
import Avatar from '../components/Avatar.vue';
import { checkNicknameApi } from '@/utils/api.js';
import { validateNickname } from '@/utils/validator.js';
const store = useStore();
// 响应式数据
const nickname = ref('');
const errorMessage = ref('');
const isChecking = ref(false);
const goToAuthPage = () => {
const hasRegisterDraft = Boolean(uni.getStorageSync('temp_register_mobile'));
const authPageUrl = hasRegisterDraft ? '/pages/register/register' : '/pages/login/login';
uni.reLaunch({
url: authPageUrl
});
};
// 返回上一页
const goBack = () => {
const pages = getCurrentPages();
// 有上一页时正常返回,否则兜底回登录/注册页
if (pages.length > 1) {
uni.navigateBack({
fail: goToAuthPage
});
return;
}
goToAuthPage();
};
// 下一步
const handleNext = async () => {
// 验证昵称
const trimmedNickname = nickname.value.trim();
const validation = validateNickname(trimmedNickname);
if (!validation.valid) {
errorMessage.value = validation.message;
uni.showToast({
title: validation.message,
icon: 'none'
});
return;
}
errorMessage.value = '';
// 防止重复点击
if (isChecking.value) return;
isChecking.value = true;
try {
const trimmedNickname = nickname.value.trim();
// 检查昵称是否已被注册
const res = await checkNicknameApi(trimmedNickname);
if (res.data.exists === true) {
errorMessage.value = '该昵称已被注册';
uni.showToast({
title: '该昵称已被注册',
icon: 'none'
});
isChecking.value = false;
return;
}
// 暂存昵称到临时存储
uni.setStorageSync('temp_register_nickname', trimmedNickname);
// // 跳转到欢迎动画页面
// uni.navigateTo({
// url: '/pages/welcome/welcome'
// });
// // 跳转到粉丝身份选择页面
// uni.navigateTo({
// url: '/pages/profile/selectRole'
// });
// 获取临时存储的注册信息
const mobile = uni.getStorageSync('temp_register_mobile');
const password = uni.getStorageSync('temp_register_password');
const star_id = 87; // 默认身份
// 验证数据完整性
if (!mobile || !password || !trimmedNickname || !star_id) {
uni.showToast({
title: '注册信息不完整,请重新注册',
icon: 'none'
});
uni.removeStorageSync('temp_register_mobile');
uni.removeStorageSync('temp_register_password');
uni.removeStorageSync('temp_register_nickname');
setTimeout(() => {
uni.reLaunch({
url: '/pages/register/register'
});
}, 1500);
isChecking.value = false;
return;
}
// 显示加载提示
uni.showLoading({
title: '注册中...',
mask: true
});
// 调用注册 API
await store.dispatch('user/register', {
mobile,
password,
star_id,
nickname: trimmedNickname
});
uni.hideLoading();
// 清除临时数据
uni.removeStorageSync('temp_register_mobile');
uni.removeStorageSync('temp_register_password');
uni.removeStorageSync('temp_register_nickname');
// 设置新用户标记
uni.setStorageSync('is_new_user', true);
// 跳转到主页
uni.reLaunch({
url: '/pages/square/square'
});
} catch (error) {
uni.hideLoading();
// 处理昵称已存在的情况409错误
if (error.code === 409 || error.message.includes('昵称') || error.message.includes('已存在')) {
uni.showModal({
title: '昵称已存在',
content: '该昵称已被使用,请返回修改昵称',
showCancel: false,
confirmText: '知道了'
});
} else {
errorMessage.value = error.message || '注册失败,请重试';
uni.showToast({
title: errorMessage.value,
icon: 'none'
});
}
} finally {
isChecking.value = false;
}
};
</script>
<style scoped>
.set-nickname-container {
position: relative;
width: 100%;
min-height: 100vh;
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* filter: blur(20rpx); */
transform: scale(1.1);
}
.background-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
.content-wrapper {
position: relative;
z-index: 1;
width: 100%;
flex: 1;
min-height: 100%;
display: flex;
flex-direction: column;
padding-top: 80rpx;
box-sizing: border-box;
}
/* 导航栏 */
.nav-bar {
display: flex;
align-items: center;
padding: 0 40rpx 40rpx 40rpx;
position: relative;
}
.nav-back {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-icon {
font-size: 48rpx;
color: #000000;
font-weight: bold;
}
.nav-title {
flex: 1;
text-align: center;
font-size: 36rpx;
font-weight: 500;
color: #000000;
margin-right: 60rpx;
}
.form-container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
max-width: 600rpx;
margin: 0 auto;
padding: 0 60rpx;
}
.avatar-wrapper {
width: 100%;
margin-bottom: 80rpx;
display: flex;
justify-content: center;
align-items: center;
}
.input-wrapper {
position: relative;
width: 100%;
height: 100rpx;
margin-bottom: 40rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 50rpx;
display: flex;
align-items: center;
padding: 0 40rpx;
box-sizing: border-box;
}
.input-field {
flex: 1;
height: 100%;
font-size: 32rpx;
color: #333333;
}
.input-placeholder {
color: #999999;
}
.error-message {
width: 100%;
padding: 20rpx 0;
margin-bottom: 20rpx;
text-align: center;
}
.error-message text {
font-size: 28rpx;
color: #ff4444;
}
.next-button-wrapper {
width: 100%;
margin-top: 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
.btn-next {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background: #000000;
border: none;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.3);
padding: 0;
transition: transform 0.2s ease;
}
.btn-next:active {
transform: scale(1.15);
}
.btn-next::after {
border: none;
}
.arrow-icon {
font-size: 48rpx;
font-weight: 900;
color: #e6e6e6;
line-height: 1;
}
</style>