Files
MrleeAdmin/frontend/app/pages/profile/edit.vue
T

326 lines
7.3 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="profile-form-page" :class="`theme-${themeMode}`">
<view class="form-card">
<view class="form-header">
<text class="form-title">修改资料</text>
<text class="form-desc">用户名、邮箱和手机号为账号信息,暂不支持修改</text>
</view>
<u-form :model="form" :border-bottom="false" label-position="top" label-width="120">
<u-form-item label="用户名" :border-bottom="false">
<view class="field-card locked">
<text class="field-text locked-text">{{ form.username || '-' }}</text>
</view>
</u-form-item>
<u-form-item label="邮箱" :border-bottom="false">
<view class="field-card locked">
<text class="field-text locked-text">{{ form.email || '-' }}</text>
</view>
</u-form-item>
<u-form-item label="手机号" :border-bottom="false">
<view class="field-card locked">
<text class="field-text locked-text">{{ form.phone || '暂未绑定手机号' }}</text>
</view>
</u-form-item>
<u-form-item label="昵称" prop="nickname" required :border-bottom="false">
<view class="field-card">
<u-input v-model="form.nickname" clearable placeholder="请输入昵称" placeholder-style="color: #a0a7b5;" />
</view>
</u-form-item>
<u-form-item label="性别" prop="gender" :border-bottom="false">
<view class="gender-options">
<view
v-for="item in genderOptions"
:key="item.value"
class="gender-option"
:class="{ active: form.gender === item.value }"
@tap="form.gender = item.value"
>
<view class="gender-dot"></view>
<text>{{ item.label }}</text>
</view>
</view>
</u-form-item>
<u-form-item label="生日" prop="birthday" :border-bottom="false">
<picker mode="date" :value="form.birthday || today" start="1900-01-01" :end="today" @change="handleBirthdayChange">
<view class="field-card picker-card">
<text class="field-text" :class="{ placeholder: !form.birthday }">{{ form.birthday || '请选择生日' }}</text>
<u-icon name="calendar" color="#a0a7b5" size="24" />
</view>
</picker>
</u-form-item>
<u-form-item label="个人简介" prop="bio" :border-bottom="false">
<view class="textarea-card">
<textarea v-model="form.bio" maxlength="120" placeholder="请输入个人简介" placeholder-style="color: #a0a7b5;" />
</view>
</u-form-item>
</u-form>
</view>
<view class="bottom-actions">
<u-button type="primary" shape="circle" size="large" :loading="submitting" @click="submitForm">保存资料</u-button>
</view>
</view>
</template>
<script>
import { getUserInfo, updateUserInfo } from '@/api/member.js'
export default {
data() {
return {
submitting: false,
today: '',
form: {
username: '',
email: '',
phone: '',
nickname: '',
gender: 0,
birthday: '',
bio: ''
},
genderOptions: [
{ label: '男', value: 1 },
{ label: '女', value: 2 },
{ label: '其他', value: 0 }
]
}
},
onLoad() {
this.today = this.getToday()
this.loadProfile()
},
methods: {
getToday() {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
async loadProfile() {
try {
const profile = await getUserInfo()
this.form = {
username: profile.username || '',
email: profile.email || '',
phone: profile.phone || '',
nickname: profile.nickname || profile.username || '',
gender: Number(profile.gender || 0),
birthday: profile.birthday || '',
bio: profile.bio || ''
}
} catch (error) {
console.error('[scanapp] 加载资料失败', error)
}
},
handleBirthdayChange(e) {
this.form.birthday = e.detail.value
},
validateForm() {
if (!this.form.nickname.trim()) {
uni.showToast({ title: '请输入昵称', icon: 'none' })
return false
}
return true
},
async submitForm() {
if (this.submitting || !this.validateForm()) {
return
}
this.submitting = true
try {
await updateUserInfo({
nickname: this.form.nickname.trim(),
gender: this.form.gender,
birthday: this.form.birthday,
bio: this.form.bio
})
const profile = await getUserInfo()
uni.setStorageSync('scanapp_user', profile)
uni.showToast({ title: '资料已保存', icon: 'none' })
setTimeout(() => {
uni.navigateBack()
}, 400)
} catch (error) {
console.error('[scanapp] 保存资料失败', error)
} finally {
this.submitting = false
}
}
}
}
</script>
<style lang="scss" scoped>
.profile-form-page {
min-height: 100vh;
padding: 28rpx 24rpx 48rpx;
box-sizing: border-box;
background: #f4f6fb;
}
.form-card {
padding: 34rpx 30rpx;
border: 1rpx solid rgba(255, 255, 255, 0.75);
border-radius: 28rpx;
background: #ffffff;
box-shadow: 0 16rpx 40rpx rgba(23, 35, 61, 0.06);
}
.form-header {
margin-bottom: 24rpx;
}
.form-title,
.form-desc,
.field-text {
display: block;
}
.form-title {
color: #17233d;
font-size: 28rpx;
font-weight: 700;
line-height: 1.35;
}
.form-desc {
margin-top: 10rpx;
color: #8a94a6;
font-size: 22rpx;
line-height: 1.45;
}
.field-card {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 88rpx;
padding: 0 24rpx;
box-sizing: border-box;
border: 1rpx solid #edf1f7;
border-radius: 22rpx;
background: #f8fbff;
}
.field-card.locked {
border-color: #edf0f5;
background: #f4f6fb;
}
.field-card.picker-card {
padding-right: 20rpx;
}
.field-text {
color: #17233d;
font-size: 22rpx;
line-height: 1.4;
}
.field-text.locked-text,
.field-text.placeholder {
color: #a0a7b5;
}
.gender-options {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 16rpx;
width: 100%;
}
.gender-option {
display: flex;
align-items: center;
justify-content: center;
height: 76rpx;
border: 1rpx solid #edf1f7;
border-radius: 20rpx;
background: #f8fbff;
color: #6b778c;
font-size: 22rpx;
font-weight: 600;
}
.gender-dot {
width: 14rpx;
height: 14rpx;
margin-right: 10rpx;
border: 3rpx solid #c5ccda;
border-radius: 50%;
box-sizing: border-box;
}
.gender-option.active {
border-color: #1677ff;
background: rgba(22, 119, 255, 0.1);
color: #1677ff;
}
.gender-option.active .gender-dot {
border-color: #1677ff;
background: #1677ff;
box-shadow: 0 0 0 4rpx rgba(22, 119, 255, 0.16);
}
.textarea-card {
width: 100%;
min-height: 156rpx;
padding: 20rpx 24rpx;
box-sizing: border-box;
border: 1rpx solid #edf1f7;
border-radius: 22rpx;
background: #f8fbff;
}
.textarea-card textarea {
width: 100%;
height: 116rpx;
color: #17233d;
font-size: 22rpx;
line-height: 1.5;
}
.bottom-actions {
margin-top: 36rpx;
}
.theme-dark.profile-form-page {
background: #151923;
}
.theme-dark .form-card,
.theme-dark .field-card,
.theme-dark .gender-option,
.theme-dark .textarea-card {
border-color: #364152;
background: #222936;
box-shadow: none;
}
.theme-dark .field-card.locked {
background: #1c2431;
}
.theme-dark .form-title,
.theme-dark .field-text,
.theme-dark .textarea-card textarea {
color: #f2f5fa;
}
.theme-dark .form-desc,
.theme-dark .field-text.locked-text,
.theme-dark .field-text.placeholder,
.theme-dark .gender-option {
color: #aeb9ca;
}
.theme-dark :deep(textarea),
.theme-dark :deep(.u-input__input) {
color: #f2f5fa !important;
}
</style>