topfans/frontend/pages/profile/setNickname.vue
2026-04-07 23:08:49 +08:00

320 lines
5.8 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 Avatar from '../components/Avatar.vue';
import { checkNicknameApi } from '@/utils/api.js';
// 响应式数据
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 () => {
// 验证昵称
if (!nickname.value || !nickname.value.trim()) {
errorMessage.value = '请输入昵称';
uni.showToast({
title: '请输入昵称',
icon: 'none'
});
return;
}
if (nickname.value.trim().length > 20) {
errorMessage.value = '昵称不能超过20个字符';
uni.showToast({
title: '昵称不能超过20个字符',
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'
});
} catch (error) {
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>