| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- <template>
- <view class="form-page">
- <view class="form-card">
- <view class="form-row">
- <text class="form-row__label">用户 ID</text>
- <text class="form-row__readonly">{{ profile.memberId || '—' }}</text>
- </view>
- <view class="form-row">
- <text class="form-row__label">会员名称</text>
- <text class="form-row__readonly">{{ profile.memberCode || '—' }}</text>
- </view>
- <view class="form-row">
- <text class="form-row__label">手机号</text>
- <text class="form-row__readonly">{{ profile.mobile || '—' }}</text>
- </view>
- <view class="form-row form-row--col">
- <text class="form-row__label form-row__label--req">头像</text>
- <image-upload v-model="form.avatar" placeholder="上传头像" />
- </view>
- <view class="form-row">
- <text class="form-row__label form-row__label--req">昵称</text>
- <input
- v-model="form.nickName"
- class="form-row__input"
- placeholder="请输入昵称"
- maxlength="30"
- />
- </view>
- <view class="form-row">
- <text class="form-row__label">邮箱</text>
- <input v-model="form.email" class="form-row__input" placeholder="选填" />
- </view>
- <view class="form-row">
- <text class="form-row__label">性别</text>
- <picker :range="genderLabels" :value="genderIndex" @change="onGenderChange">
- <view class="form-row__picker">
- <text :class="{ 'form-row__placeholder': genderIndex < 0 }">
- {{ genderIndex >= 0 ? genderLabels[genderIndex] : '请选择' }}
- </text>
- </view>
- </picker>
- </view>
- </view>
- <view class="form-footer">
- <button class="form-footer__btn" :disabled="saving" @click="handleSave">
- {{ saving ? '保存中…' : '保 存' }}
- </button>
- </view>
- </view>
- </template>
- <script setup>
- import { ref, reactive } from 'vue'
- import { onLoad } from '@dcloudio/uni-app'
- import { getMemberProfile, updateMemberProfile } from '@/api/member'
- import { useUserStore } from '@/store/user'
- import { ensureApiToken } from '@/utils/apiAuth'
- import { GENDER_OPTIONS } from '@/utils/entryConstants'
- import ImageUpload from '@/components/mine/ImageUpload.vue'
- import { useActionGuard } from '@/utils/actionGuard'
- const saveGuard = useActionGuard()
- const profile = reactive({
- memberId: '',
- memberCode: '',
- mobile: ''
- })
- const form = reactive({
- nickName: '',
- avatar: '',
- email: '',
- sex: ''
- })
- const saving = saveGuard.locked
- const genderLabels = GENDER_OPTIONS.map((g) => g.label)
- const genderIndex = ref(-1)
- /** 昵称最长 30 字(对齐功能需求 MS-P2) */
- const NICK_NAME_MAX = 30
- const userStore = useUserStore()
- onLoad(() => {
- if (!ensureApiToken()) return
- loadProfile()
- })
- function syncGenderIndex() {
- const idx = GENDER_OPTIONS.findIndex((g) => g.value === form.sex)
- genderIndex.value = idx >= 0 ? idx : -1
- }
- function loadProfile() {
- getMemberProfile()
- .then((res) => {
- const m = res.data || {}
- profile.memberId = m.memberId
- profile.memberCode = m.memberCode
- profile.mobile = m.mobile
- form.nickName = m.nickName || ''
- form.avatar = m.avatar || ''
- form.email = m.email || ''
- form.sex = m.sex != null ? String(m.sex) : ''
- syncGenderIndex()
- })
- .catch(() => {})
- }
- function onGenderChange(e) {
- const idx = Number(e.detail.value)
- genderIndex.value = idx
- form.sex = GENDER_OPTIONS[idx]?.value || ''
- }
- function validate() {
- const nick = (form.nickName || '').trim()
- if (!nick) {
- uni.showToast({ title: '请输入昵称', icon: 'none' })
- return false
- }
- if (nick.length > NICK_NAME_MAX) {
- uni.showToast({ title: `昵称不超过 ${NICK_NAME_MAX} 字`, icon: 'none' })
- return false
- }
- const email = (form.email || '').trim()
- if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
- uni.showToast({ title: '邮箱格式不正确', icon: 'none' })
- return false
- }
- return true
- }
- function handleSave() {
- saveGuard.run(async () => {
- if (!validate()) return
- await updateMemberProfile({
- nickName: form.nickName.trim(),
- avatar: form.avatar,
- email: (form.email || '').trim(),
- sex: form.sex
- })
- uni.showToast({ title: '保存成功', icon: 'none' })
- await userStore.fetchUserInfo()
- setTimeout(() => uni.navigateBack(), 800)
- })
- }
- </script>
- <style lang="scss" scoped>
- @import '@/styles/mine.scss';
- </style>
|