init
This commit is contained in:
540
miniprogram/pages/user/person-info/index.js
Normal file
540
miniprogram/pages/user/person-info/index.js
Normal file
@@ -0,0 +1,540 @@
|
||||
import { fetchPerson } from '../../../services/usercenter/fetchPerson';
|
||||
import { phoneEncryption } from '../../../utils/util';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
const weChatAuthService = require('../../../services/auth/wechat');
|
||||
|
||||
Page({
|
||||
data: {
|
||||
personInfo: {
|
||||
avatarUrl: '',
|
||||
nickName: '',
|
||||
gender: 0, // 默认为0(未设置)
|
||||
phoneNumber: '',
|
||||
level: 1
|
||||
},
|
||||
originalPersonInfo: null, // 保存原始数据
|
||||
displayPhoneNumber: '', // 用于显示的加密手机号
|
||||
defaultAvatarUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/usercenter/icon-user-center-avatar@2x.png',
|
||||
genderVisible: false,
|
||||
genderList: [
|
||||
{ label: '男', value: 1 },
|
||||
{ label: '女', value: 2 },
|
||||
{ label: '未设置', value: 0 }
|
||||
],
|
||||
// 性别映射
|
||||
genderMap: {
|
||||
0: '未设置',
|
||||
1: '男',
|
||||
2: '女'
|
||||
},
|
||||
|
||||
saving: false
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
fetchData() {
|
||||
console.log('=== 开始获取用户信息 ===');
|
||||
fetchPerson().then((personInfo) => {
|
||||
console.log('从API获取到的原始用户信息:', personInfo);
|
||||
|
||||
// 确保所有字段都有正确的类型和默认值
|
||||
const safePersonInfo = {
|
||||
avatarUrl: personInfo.avatarUrl || '',
|
||||
nickName: personInfo.nickName || '',
|
||||
gender: personInfo.gender || 0,
|
||||
phoneNumber: personInfo.phoneNumber || '',
|
||||
level: personInfo.level || 1,
|
||||
};
|
||||
|
||||
console.log('处理后的安全用户信息:', safePersonInfo);
|
||||
console.log('性别数据详细信息:', {
|
||||
原始性别: personInfo.gender,
|
||||
处理后性别: safePersonInfo.gender,
|
||||
性别类型: typeof safePersonInfo.gender
|
||||
});
|
||||
console.log('手机号数据详细信息:', {
|
||||
原始手机号: personInfo.phoneNumber,
|
||||
处理后手机号: safePersonInfo.phoneNumber,
|
||||
手机号类型: typeof safePersonInfo.phoneNumber
|
||||
});
|
||||
console.log('个人资料页 - 头像URL:', safePersonInfo.avatarUrl);
|
||||
console.log('个人资料页 - 默认头像URL:', this.data.defaultAvatarUrl);
|
||||
|
||||
// 保存原始数据用于编辑,显示数据用于界面展示
|
||||
this.setData({
|
||||
personInfo: safePersonInfo,
|
||||
originalPersonInfo: JSON.parse(JSON.stringify(safePersonInfo)), // 深拷贝保存原始数据
|
||||
originalNickname: safePersonInfo.nickName, // 保存原始昵称用于重置
|
||||
displayPhoneNumber: phoneEncryption(safePersonInfo.phoneNumber), // 仅用于显示的加密手机号
|
||||
});
|
||||
|
||||
console.log('设置到页面数据后的personInfo:', this.data.personInfo);
|
||||
console.log('原始数据originalPersonInfo:', this.data.originalPersonInfo);
|
||||
}).catch((error) => {
|
||||
console.error('获取用户信息失败:', error);
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '获取用户信息失败',
|
||||
theme: 'error',
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onClickCell({ currentTarget }) {
|
||||
const { dataset } = currentTarget;
|
||||
const { nickName } = this.data.personInfo;
|
||||
|
||||
switch (dataset.type) {
|
||||
case 'name':
|
||||
wx.navigateTo({
|
||||
url: `/pages/user/name-edit/index?name=${nickName}`,
|
||||
});
|
||||
break;
|
||||
case 'avatarUrl':
|
||||
this.toModifyAvatar();
|
||||
break;
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 保存性别设置
|
||||
async saveGender(gender) {
|
||||
this.setData({ saving: true });
|
||||
|
||||
try {
|
||||
const userInfo = {
|
||||
nickName: this.data.personInfo.nickName,
|
||||
avatarUrl: this.data.personInfo.avatarUrl,
|
||||
gender: gender
|
||||
};
|
||||
|
||||
await weChatAuthService.updateUserProfile(userInfo);
|
||||
|
||||
this.setData({ saving: false });
|
||||
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '性别设置成功',
|
||||
theme: 'success',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存性别失败:', error);
|
||||
this.setData({ saving: false });
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '性别设置失败,请重试',
|
||||
theme: 'error',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 处理头像昵称组件的回调(微信官方组件)- 自动保存
|
||||
async onChooseAvatar(e) {
|
||||
const { avatarUrl } = e.detail;
|
||||
console.log('从微信头像组件获取头像:', avatarUrl);
|
||||
|
||||
// 立即更新界面显示
|
||||
this.setData({
|
||||
'personInfo.avatarUrl': avatarUrl,
|
||||
});
|
||||
|
||||
// 自动保存头像
|
||||
await this.saveAvatar(avatarUrl);
|
||||
},
|
||||
|
||||
// 保存头像
|
||||
async saveAvatar(avatarUrl) {
|
||||
this.setData({ saving: true });
|
||||
|
||||
try {
|
||||
const userInfo = {
|
||||
nickName: this.data.personInfo.nickName,
|
||||
avatarUrl: avatarUrl,
|
||||
gender: this.data.personInfo.gender
|
||||
};
|
||||
|
||||
console.log('保存头像信息:', userInfo);
|
||||
await weChatAuthService.updateUserProfile(userInfo);
|
||||
|
||||
// 确保头像URL已保存到本地数据
|
||||
this.setData({
|
||||
saving: false,
|
||||
'personInfo.avatarUrl': avatarUrl
|
||||
});
|
||||
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '头像设置成功',
|
||||
theme: 'success',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存头像失败:', error);
|
||||
this.setData({ saving: false });
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '头像设置失败,请重试',
|
||||
theme: 'error',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 昵称输入变化
|
||||
onNicknameChange(e) {
|
||||
console.log('昵称输入变化:', e.detail.value);
|
||||
this.setData({
|
||||
'personInfo.nickName': e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
// 保存昵称(兼容旧方式)
|
||||
saveNickname(e) {
|
||||
console.log('保存昵称事件触发:', e);
|
||||
const nickname = e.detail.value || this.data.personInfo.nickName;
|
||||
console.log('要保存的昵称:', nickname);
|
||||
|
||||
if (!nickname || nickname.trim() === '') {
|
||||
wx.showToast({
|
||||
title: '昵称不能为空',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.saveNicknameToServer(nickname.trim());
|
||||
},
|
||||
|
||||
// 性别选择事件(radio-group change事件)
|
||||
onGenderChange(e) {
|
||||
const gender = parseInt(e.detail.value);
|
||||
console.log('性别选择变化:', gender);
|
||||
|
||||
this.setData({
|
||||
'personInfo.gender': gender
|
||||
});
|
||||
|
||||
// 自动保存性别
|
||||
this.saveGender(gender);
|
||||
},
|
||||
|
||||
// 手机号获得焦点事件
|
||||
onPhoneFocus(e) {
|
||||
console.log('手机号输入框获得焦点');
|
||||
// 确保显示原始手机号而不是加密的
|
||||
if (this.data.originalPersonInfo && this.data.originalPersonInfo.phoneNumber) {
|
||||
this.setData({
|
||||
displayPhoneNumber: this.data.originalPersonInfo.phoneNumber
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 手机号输入事件(实时输入)
|
||||
onPhoneInput(e) {
|
||||
const phoneNumber = e.detail.value.trim();
|
||||
|
||||
// 更新显示数据和实际数据
|
||||
this.setData({
|
||||
displayPhoneNumber: phoneNumber,
|
||||
'personInfo.phoneNumber': phoneNumber
|
||||
});
|
||||
|
||||
// 清除之前的定时器
|
||||
if (this.phoneInputTimer) {
|
||||
clearTimeout(this.phoneInputTimer);
|
||||
}
|
||||
|
||||
// 设置延迟自动保存(用户停止输入1.5秒后自动保存)
|
||||
this.phoneInputTimer = setTimeout(() => {
|
||||
this.updatePhoneNumber(phoneNumber, 'auto');
|
||||
}, 1500);
|
||||
},
|
||||
|
||||
// 手机号输入失焦事件
|
||||
onPhoneBlur(e) {
|
||||
const phoneNumber = e.detail.value.trim();
|
||||
|
||||
// 清除定时器,立即保存
|
||||
if (this.phoneInputTimer) {
|
||||
clearTimeout(this.phoneInputTimer);
|
||||
this.phoneInputTimer = null;
|
||||
}
|
||||
|
||||
this.updatePhoneNumber(phoneNumber, 'blur');
|
||||
|
||||
// 失焦后显示加密的手机号
|
||||
if (phoneNumber) {
|
||||
this.setData({
|
||||
displayPhoneNumber: phoneEncryption(phoneNumber)
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 手机号输入确认事件(回车)
|
||||
onPhoneConfirm(e) {
|
||||
const phoneNumber = e.detail.value.trim();
|
||||
|
||||
// 清除定时器,立即保存
|
||||
if (this.phoneInputTimer) {
|
||||
clearTimeout(this.phoneInputTimer);
|
||||
this.phoneInputTimer = null;
|
||||
}
|
||||
|
||||
this.updatePhoneNumber(phoneNumber, 'confirm');
|
||||
},
|
||||
|
||||
// 更新手机号
|
||||
updatePhoneNumber(phoneNumber, triggerType = 'manual') {
|
||||
console.log(`=== 手机号更新触发 (${triggerType}) ===`);
|
||||
console.log('输入的手机号:', phoneNumber);
|
||||
|
||||
// 如果手机号为空,直接保存(清空操作)
|
||||
if (!phoneNumber) {
|
||||
console.log('手机号为空,执行清空操作');
|
||||
this.setData({
|
||||
'personInfo.phoneNumber': phoneNumber
|
||||
});
|
||||
this.savePhoneNumber(phoneNumber, triggerType);
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证手机号格式
|
||||
if (!this.validatePhoneNumber(phoneNumber)) {
|
||||
// 只在非自动触发时显示错误提示
|
||||
if (triggerType !== 'auto') {
|
||||
wx.showToast({
|
||||
title: '手机号格式不正确',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
console.log('手机号格式验证失败:', phoneNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否与原始值相同,避免重复保存
|
||||
const originalPhoneNumber = this.data.originalPersonInfo ? this.data.originalPersonInfo.phoneNumber : '';
|
||||
if (phoneNumber === originalPhoneNumber) {
|
||||
console.log('手机号未变化,跳过保存');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新数据
|
||||
this.setData({
|
||||
'personInfo.phoneNumber': phoneNumber
|
||||
});
|
||||
|
||||
// 自动保存手机号
|
||||
this.savePhoneNumber(phoneNumber, triggerType);
|
||||
},
|
||||
|
||||
// 验证手机号格式
|
||||
validatePhoneNumber(phoneNumber) {
|
||||
const phoneRegex = /^1[3-9]\d{9}$/;
|
||||
return phoneRegex.test(phoneNumber);
|
||||
},
|
||||
|
||||
// 保存手机号
|
||||
async savePhoneNumber(phoneNumber, triggerType = 'manual') {
|
||||
if (this.data.saving) {
|
||||
console.log('正在保存中,跳过重复请求');
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ saving: true });
|
||||
|
||||
try {
|
||||
console.log(`=== 开始保存手机号到服务器 (${triggerType}) ===`);
|
||||
console.log('要保存的手机号:', phoneNumber);
|
||||
|
||||
// 构建用户信息对象,包含手机号
|
||||
const userInfo = {
|
||||
nickName: this.data.personInfo.nickName,
|
||||
avatarUrl: this.data.personInfo.avatarUrl,
|
||||
gender: this.data.personInfo.gender,
|
||||
phoneNumber: phoneNumber // 添加手机号字段
|
||||
};
|
||||
|
||||
console.log('发送到服务器的用户信息:', userInfo);
|
||||
|
||||
// 调用微信授权服务更新用户信息
|
||||
const result = await weChatAuthService.updateUserProfile(userInfo);
|
||||
console.log('服务器返回结果:', result);
|
||||
|
||||
// 根据触发方式显示不同的提示
|
||||
if (triggerType === 'auto') {
|
||||
// 自动保存时显示更简洁的提示
|
||||
console.log('自动保存成功');
|
||||
} else {
|
||||
// 手动触发时显示Toast提示
|
||||
wx.showToast({
|
||||
title: phoneNumber ? '手机号保存成功' : '手机号已清空',
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
});
|
||||
}
|
||||
|
||||
// 保存成功后,立即更新原始数据
|
||||
if (this.data.originalPersonInfo) {
|
||||
this.setData({
|
||||
'originalPersonInfo.phoneNumber': phoneNumber
|
||||
});
|
||||
}
|
||||
|
||||
// 重新获取用户信息验证是否真的更新了
|
||||
console.log('=== 重新获取用户信息验证更新 ===');
|
||||
this.fetchData();
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存手机号失败:', error);
|
||||
|
||||
// 只在非自动触发时显示错误提示
|
||||
if (triggerType !== 'auto') {
|
||||
wx.showToast({
|
||||
title: '保存失败,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
this.setData({ saving: false });
|
||||
}
|
||||
},
|
||||
|
||||
// 保存昵称到服务器
|
||||
async saveNicknameToServer(nickname) {
|
||||
this.setData({ saving: true });
|
||||
|
||||
try {
|
||||
console.log('=== 开始保存昵称到服务器 ===');
|
||||
|
||||
// 如果传入了昵称参数,使用传入的昵称;否则使用当前数据中的昵称
|
||||
const finalNickname = nickname || this.data.personInfo.nickName;
|
||||
console.log('要保存的昵称:', finalNickname);
|
||||
console.log('当前数据中的昵称:', this.data.personInfo.nickName);
|
||||
|
||||
// 更新本地数据
|
||||
if (nickname && nickname !== this.data.personInfo.nickName) {
|
||||
this.setData({
|
||||
'personInfo.nickName': nickname
|
||||
});
|
||||
}
|
||||
|
||||
const userInfo = {
|
||||
nickName: finalNickname,
|
||||
avatarUrl: this.data.personInfo.avatarUrl,
|
||||
gender: this.data.personInfo.gender
|
||||
};
|
||||
|
||||
console.log('发送到服务器的用户信息:', userInfo);
|
||||
|
||||
const result = await weChatAuthService.updateUserProfile(userInfo);
|
||||
console.log('服务器返回结果:', result);
|
||||
|
||||
// 保存成功后,重新获取用户信息验证是否真的更新了
|
||||
console.log('=== 重新获取用户信息验证更新 ===');
|
||||
this.fetchData();
|
||||
|
||||
this.setData({ saving: false });
|
||||
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '昵称设置成功',
|
||||
theme: 'success',
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存昵称失败:', error);
|
||||
this.setData({ saving: false });
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '昵称设置失败,请重试',
|
||||
theme: 'error',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 兼容旧版本的头像选择方式 - 自动保存
|
||||
async toModifyAvatar() {
|
||||
try {
|
||||
const tempFilePath = await new Promise((resolve, reject) => {
|
||||
wx.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
const { path, size } = res.tempFiles && res.tempFiles.length > 0 ? res.tempFiles[0] : {};
|
||||
if (size <= 10485760) {
|
||||
resolve(path);
|
||||
} else {
|
||||
reject({ errMsg: '图片大小超出限制,请重新上传' });
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
});
|
||||
|
||||
// 更新本地显示
|
||||
this.setData({
|
||||
'personInfo.avatarUrl': tempFilePath,
|
||||
});
|
||||
|
||||
// 自动保存头像
|
||||
await this.saveAvatar(tempFilePath);
|
||||
|
||||
} catch (error) {
|
||||
if (error.errMsg === 'chooseImage:fail cancel') return;
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: error.errMsg || error.msg || '选择头像出错了',
|
||||
theme: 'error',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 切换账号登录
|
||||
openUnbindConfirm() {
|
||||
wx.showModal({
|
||||
title: '切换账号',
|
||||
content: '确定要切换到其他微信账号登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 清除本地存储的用户信息
|
||||
wx.removeStorageSync('token');
|
||||
wx.removeStorageSync('userInfo');
|
||||
|
||||
// 跳转到登录页面
|
||||
wx.reLaunch({
|
||||
url: '/pages/login/index'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 页面卸载时清理定时器
|
||||
onUnload() {
|
||||
if (this.phoneInputTimer) {
|
||||
clearTimeout(this.phoneInputTimer);
|
||||
this.phoneInputTimer = null;
|
||||
console.log('页面卸载,清理手机号输入定时器');
|
||||
}
|
||||
}
|
||||
});
|
||||
16
miniprogram/pages/user/person-info/index.json
Normal file
16
miniprogram/pages/user/person-info/index.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"navigationBarTitleText": "个人资料",
|
||||
"usingComponents": {
|
||||
"t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
|
||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||
"t-button": "tdesign-miniprogram/button/button",
|
||||
"t-avatar": "tdesign-miniprogram/avatar/avatar",
|
||||
"t-image": "/components/webp-image/index",
|
||||
"t-dialog": "tdesign-miniprogram/dialog/dialog",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"t-picker": "tdesign-miniprogram/picker/picker",
|
||||
"t-picker-item": "tdesign-miniprogram/picker-item/picker-item",
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-select-picker": "../../usercenter/components/ui-select-picker/index"
|
||||
}
|
||||
}
|
||||
112
miniprogram/pages/user/person-info/index.wxml
Normal file
112
miniprogram/pages/user/person-info/index.wxml
Normal file
@@ -0,0 +1,112 @@
|
||||
<view class="person-info">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-title">个人信息</view>
|
||||
<view class="header-subtitle">完善您的个人资料</view>
|
||||
</view>
|
||||
|
||||
<!-- 信息设置卡片 -->
|
||||
<view class="info-card">
|
||||
<t-cell-group>
|
||||
<!-- 微信头像设置 -->
|
||||
<t-cell
|
||||
title="微信头像"
|
||||
center="{{true}}"
|
||||
t-class-left="order-group__left"
|
||||
>
|
||||
<view slot="note" class="avatar-container">
|
||||
<button
|
||||
class="avatar-button"
|
||||
open-type="chooseAvatar"
|
||||
bind:chooseavatar="onChooseAvatar"
|
||||
>
|
||||
<t-avatar
|
||||
image="{{personInfo.avatarUrl || defaultAvatarUrl}}"
|
||||
class="avatar-display"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="avatar-mask">
|
||||
<text class="avatar-text">点击更换微信头像</text>
|
||||
</view>
|
||||
</button>
|
||||
</view>
|
||||
</t-cell>
|
||||
|
||||
<!-- 微信昵称设置 -->
|
||||
<t-cell title="微信昵称" t-class="t-cell-class">
|
||||
<view slot="note" class="nickname-container">
|
||||
<input
|
||||
class="nickname-input"
|
||||
type="nickname"
|
||||
placeholder="请输入微信昵称"
|
||||
value="{{personInfo.nickName}}"
|
||||
bind:input="onNicknameChange"
|
||||
bind:blur="saveNickname"
|
||||
bind:confirm="saveNickname"
|
||||
maxlength="20"
|
||||
/>
|
||||
</view>
|
||||
</t-cell>
|
||||
|
||||
<!-- 性别设置 -->
|
||||
<t-cell
|
||||
title="性别"
|
||||
t-class="t-cell-class"
|
||||
t-class-left="order-group__left"
|
||||
>
|
||||
<view slot="note" class="gender-radio-container">
|
||||
<radio-group bind:change="onGenderChange">
|
||||
<label class="gender-radio-item">
|
||||
<radio value="1" checked="{{personInfo.gender == 1}}" color="#667eea"/>
|
||||
<text class="gender-text">男</text>
|
||||
</label>
|
||||
<label class="gender-radio-item">
|
||||
<radio value="2" checked="{{personInfo.gender == 2}}" color="#667eea"/>
|
||||
<text class="gender-text">女</text>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
</t-cell>
|
||||
|
||||
<!-- 手机号设置 -->
|
||||
<t-cell
|
||||
bordered="{{false}}"
|
||||
title="手机号"
|
||||
t-class="t-cell-class"
|
||||
t-class-left="order-group__left"
|
||||
>
|
||||
<view slot="note" class="phone-input-container">
|
||||
<input
|
||||
class="phone-input"
|
||||
type="number"
|
||||
placeholder="请输入手机号"
|
||||
value="{{displayPhoneNumber}}"
|
||||
bind:input="onPhoneInput"
|
||||
bind:blur="onPhoneBlur"
|
||||
bind:confirm="onPhoneConfirm"
|
||||
bind:focus="onPhoneFocus"
|
||||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- 保存状态提示 -->
|
||||
<view class="saving-status" wx:if="{{saving}}">
|
||||
<t-loading theme="circular" size="40rpx" />
|
||||
<text class="saving-text">正在保存...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 切换账号按钮 -->
|
||||
<view class="person-info__wrapper">
|
||||
<view class="person-info__btn" bind:tap="openUnbindConfirm"> 切换账号登录 </view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- Toast 提示 -->
|
||||
<t-toast id="t-toast" />
|
||||
376
miniprogram/pages/user/person-info/index.wxss
Normal file
376
miniprogram/pages/user/person-info/index.wxss
Normal file
@@ -0,0 +1,376 @@
|
||||
:host {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
page {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
page view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 个人信息页面样式 */
|
||||
.person-info {
|
||||
padding: 0;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 页面标题样式 */
|
||||
.page-header {
|
||||
text-align: center;
|
||||
padding: 80rpx 0 50rpx;
|
||||
animation: fadeIn 0.8s ease-out;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 52rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
text-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.25);
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
font-size: 30rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 400;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
/* 信息卡片样式 */
|
||||
.info-card {
|
||||
background: #fff;
|
||||
border-radius: 28rpx;
|
||||
margin: 32rpx 24rpx;
|
||||
box-shadow: 0 12rpx 40rpx rgba(102, 126, 234, 0.15);
|
||||
overflow: hidden;
|
||||
animation: slideUp 0.6s ease-out;
|
||||
padding: 40rpx 32rpx 50rpx;
|
||||
border: 1rpx solid rgba(102, 126, 234, 0.08);
|
||||
}
|
||||
|
||||
/* 通用按钮样式 */
|
||||
.person-info__btn {
|
||||
width: 100%;
|
||||
height: 96rpx;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
color: #ffffff;
|
||||
font-weight: 600;
|
||||
margin-top: 32rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
||||
backdrop-filter: blur(10rpx);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.person-info__btn:active {
|
||||
transform: translateY(2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.2);
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
.person-info__wrapper {
|
||||
padding: 0 32rpx 60rpx;
|
||||
}
|
||||
|
||||
/* 头像相关样式 */
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar-button {
|
||||
position: relative;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 3rpx solid #667eea;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.25);
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar-button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.avatar-button:active {
|
||||
transform: scale(0.96);
|
||||
box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.35);
|
||||
}
|
||||
|
||||
.avatarUrl {
|
||||
width: 114rpx;
|
||||
height: 114rpx;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
/* t-avatar 组件样式 */
|
||||
.avatar-display {
|
||||
width: 114rpx !important;
|
||||
height: 114rpx !important;
|
||||
border-radius: 50% !important;
|
||||
overflow: hidden !important;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.avatar-mask {
|
||||
position: absolute;
|
||||
top: 3rpx;
|
||||
left: 3rpx;
|
||||
width: calc(100% - 6rpx);
|
||||
height: calc(100% - 6rpx);
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.85), rgba(118, 75, 162, 0.85));
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(6rpx);
|
||||
}
|
||||
|
||||
.avatar-button:active .avatar-mask {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
text-shadow: 0 1rpx 4rpx rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
/* 昵称输入框样式 */
|
||||
.nickname-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
min-width: 300rpx;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
width: 100%;
|
||||
height: 76rpx;
|
||||
padding: 0 20rpx;
|
||||
border: 2rpx solid #e8eaed;
|
||||
border-radius: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
background: #f8f9fa;
|
||||
text-align: right;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.nickname-input:focus {
|
||||
border-color: #667eea;
|
||||
background: #fff;
|
||||
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.18);
|
||||
transform: translateY(-1rpx);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.nickname-input::placeholder {
|
||||
color: #aaa;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
/* 性别单选框样式 */
|
||||
.gender-radio-container {
|
||||
display: flex;
|
||||
gap: 40rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gender-radio-container radio-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 40rpx;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gender-radio-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
padding: 8rpx 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gender-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 手机号输入框样式 */
|
||||
.phone-input-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.phone-input {
|
||||
width: 100%;
|
||||
height: 76rpx;
|
||||
padding: 0 20rpx;
|
||||
border: 2rpx solid #e8eaed;
|
||||
border-radius: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
background: #f8f9fa;
|
||||
text-align: right;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.phone-input:focus {
|
||||
border-color: #667eea;
|
||||
background: #fff;
|
||||
box-shadow: 0 6rpx 20rpx rgba(102, 126, 234, 0.18);
|
||||
transform: translateY(-1rpx);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.phone-input::placeholder {
|
||||
color: #aaa;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 保存状态提示样式 */
|
||||
.saving-status {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.96), rgba(118, 75, 162, 0.96));
|
||||
color: #fff;
|
||||
padding: 28rpx 56rpx;
|
||||
border-radius: 60rpx;
|
||||
font-size: 30rpx;
|
||||
z-index: 1000;
|
||||
backdrop-filter: blur(12rpx);
|
||||
box-shadow: 0 12rpx 40rpx rgba(102, 126, 234, 0.35);
|
||||
border: 1rpx solid rgba(255, 255, 255, 0.25);
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.saving-text {
|
||||
font-weight: 600;
|
||||
letter-spacing: 1rpx;
|
||||
}
|
||||
|
||||
/* Cell组件样式优化 */
|
||||
.person-info .t-cell-class {
|
||||
height: 120rpx;
|
||||
background: transparent;
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.person-info .t-cell-class:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* 添加微妙的动画效果 */
|
||||
.info-card {
|
||||
animation: slideUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(80rpx);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.page-header {
|
||||
animation: fadeIn 0.8s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 375px) {
|
||||
.page-header {
|
||||
padding: 50rpx 24rpx 30rpx;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 42rpx;
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
margin: 0 24rpx 24rpx;
|
||||
}
|
||||
|
||||
.nickname-container {
|
||||
min-width: 250rpx;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.avatar-button,
|
||||
.avatar-display {
|
||||
width: 120rpx !important;
|
||||
height: 120rpx !important;
|
||||
}
|
||||
|
||||
.person-info__wrapper {
|
||||
padding: 0 24rpx 50rpx;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user