# MatchProfileSet 个人资料设置

个人资料设置组件,提供用户头像、昵称等基本信息的编辑功能,支持头像上传和昵称修改。

# 引入

import PressMatchProfileSet from 'press-next/press-match-profile-set/press-match-profile-set.vue';

# 代码演示

# 基础用法

<template>
  <PressMatchProfileSet
    desc="为方便成绩等页面内容展示,授权我们获取您的账号昵称"
    :avatar-url="avatarUrl"
    :nickname="nickname"
    @avatar-click="handleAvatarClick"
    @nickname-change="handleNicknameChange"
    @account-click="handleAccountClick"
  />
</template>

<script setup>
import { ref } from 'vue';

const avatarUrl = ref('https://example.com/avatar.jpg');
const nickname = ref('用户昵称');

const handleAvatarClick = () => {
  console.log('点击头像');
};

const handleNicknameChange = (value) => {
  console.log('昵称变更:', value);
  nickname.value = value;
};

const handleAccountClick = () => {
  console.log('点击切换账号按钮');
};
</script>

# 头像上传

组件支持头像点击上传功能:

<template>
  <PressMatchProfileSet
    :avatar-url="avatarUrl"
    :nickname="nickname"
    @avatar-click="handleAvatarUpload"
  />
</template>

<script setup>
import { ref } from 'vue';

const avatarUrl = ref('');
const nickname = ref('请输入昵称');

const handleAvatarUpload = () => {
  // 调用图片选择器
  uni.chooseImage({
    count: 1,
    sizeType: ['compressed'],
    sourceType: ['album', 'camera'],
    success: (res) => {
      avatarUrl.value = res.tempFilePaths[0];
      // 上传到服务器
      uploadAvatar(res.tempFilePaths[0]);
    }
  });
};

const uploadAvatar = (filePath) => {
  uni.uploadFile({
    url: 'https://api.example.com/upload',
    filePath,
    name: 'avatar',
    success: (uploadRes) => {
      const data = JSON.parse(uploadRes.data);
      avatarUrl.value = data.url;
    }
  });
};
</script>

# 昵称编辑

支持昵称实时编辑和验证:

<template>
  <PressMatchProfileSet
    :avatar-url="avatarUrl"
    :nickname="nickname"
    nickname-placeholder="请输入您的昵称"
    @nickname-change="handleNicknameChange"
    @nickname-blur="handleNicknameBlur"
  />
</template>

<script setup>
import { ref } from 'vue';

const avatarUrl = ref('https://example.com/avatar.jpg');
const nickname = ref('');

const handleNicknameChange = (value) => {
  nickname.value = value;
};

const handleNicknameBlur = (value) => {
  // 昵称长度验证
  if (value.length > 20) {
    uni.showToast({
      title: '昵称不能超过20个字符',
      icon: 'none'
    });
    return;
  }
  
  // 敏感词过滤
  if (containsSensitiveWords(value)) {
    uni.showToast({
      title: '昵称包含敏感词',
      icon: 'none'
    });
    return;
  }
};

const containsSensitiveWords = (text) => {
  const sensitiveWords = ['违禁词1', '违禁词2'];
  return sensitiveWords.some(word => text.includes(word));
};
</script>

# 自定义底部按钮

<template>
  <PressMatchProfileSet
    :avatar-url="avatarUrl"
    :nickname="nickname"
    foot-button-text="退出登录"
    @account-click="handleLogout"
  >
    <template #confirm-btn>
      <PressButton
        type="primary"
        block
        @click="handleCustomAction"
      >
        自定义按钮
      </PressButton>
    </template>
  </PressMatchProfileSet>
</template>

<script setup>
import { ref } from 'vue';

const avatarUrl = ref('https://example.com/avatar.jpg');
const nickname = ref('用户昵称');

const handleLogout = () => {
  console.log('退出登录');
};

const handleCustomAction = () => {
  console.log('自定义操作');
};
</script>

# 完整示例

<template>
  <div class="profile-page">
    <PressMatchProfileSet
      desc="为方便成绩等页面内容展示,授权我们获取您的账号昵称"
      :avatar-url="avatarUrl"
      :nickname="nickname"
      :default-avatar-url="defaultAvatar"
      nickname-placeholder="请输入昵称"
      foot-button-text="切换QQ账号"
      custom-class="custom-profile"
      @avatar-click="handleAvatarClick"
      @nickname-change="handleNicknameChange"
      @nickname-blur="handleNicknameBlur"
      @nickname-auth="handleNicknameAuth"
      @account-click="handleAccountClick"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';

const avatarUrl = ref('');
const nickname = ref('');
const defaultAvatar = 'https://example.com/default-avatar.png';

const handleAvatarClick = () => {
  uni.showActionSheet({
    itemList: ['拍照', '从相册选择'],
    success: (res) => {
      const sourceType = res.tapIndex === 0 ? ['camera'] : ['album'];
      
      uni.chooseImage({
        count: 1,
        sizeType: ['compressed'],
        sourceType,
        success: (chooseRes) => {
          uploadAvatar(chooseRes.tempFilePaths[0]);
        }
      });
    }
  });
};

const handleNicknameChange = (value) => {
  nickname.value = value;
};

const handleNicknameBlur = (value) => {
  if (!value.trim()) {
    uni.showToast({
      title: '请输入昵称',
      icon: 'none'
    });
    return;
  }
  
  if (value.length > 20) {
    uni.showToast({
      title: '昵称不能超过20个字符',
      icon: 'none'
    });
    return;
  }
};

const handleNicknameAuth = () => {
  console.log('触发微信昵称授权');
};

const handleAccountClick = () => {
  uni.showModal({
    title: '提示',
    content: '确定要切换账号吗?',
    success: (res) => {
      if (res.confirm) {
        // 执行切换账号逻辑
        console.log('切换账号');
      }
    }
  });
};

const uploadAvatar = (filePath) => {
  uni.showLoading({ title: '上传中...' });
  
  uni.uploadFile({
    url: 'https://api.example.com/upload/avatar',
    filePath,
    name: 'avatar',
    success: (res) => {
      const data = JSON.parse(res.data);
      avatarUrl.value = data.url;
      uni.hideLoading();
    },
    fail: () => {
      uni.hideLoading();
      uni.showToast({
        title: '上传失败',
        icon: 'none'
      });
    }
  });
};
</script>

# API

# Props

参数 说明 类型 默认值
foot-button-text 底部按钮文本 string '切换QQ账号'
custom-class 自定义样式类名 string ''
authorization-class 授权项自定义样式类名 string ''
desc 描述文本 string ''
avatar-url 头像URL string ''
nickname 昵称 string ''
default-avatar-url 默认头像URL string ''
nickname-placeholder 昵称输入框占位符 string ''

# Events

事件名 说明 回调参数
account-click 点击底部按钮时触发 -
avatar-click 点击头像时触发 -
nickname-change 昵称输入变化时触发 value: string
nickname-blur 昵称输入失焦时触发 value: string
nickname-auth 点击昵称右侧箭头时触发,用于拉起微信昵称授权 -

# Slots

名称 说明
confirm-btn 自定义底部按钮

# 样式变量

组件提供了下列 CSS 变量,可用于自定义样式。

名称 默认值 说明
--pmps-profile-foot-mt $spacing-xl 底部按钮上边距
--pmps-profile-padding-lr $spacing-lg 组件左右内边距
--pmps-profile-foot-padding-lr $spacing-md 底部按钮左右内边距
--pmps-foot-height 1.08rem 底部按钮高度
--pmps-profile-bg-color $color-surface-default 背景颜色

# 自定义样式示例

<template>
  <PressMatchProfileSet
    :avatar-url="avatarUrl"
    :nickname="nickname"
    class="custom-profile-set"
  />
</template>

<style>
.custom-profile-set {
  --pmps-profile-bg-color: #f8f9fa;
  --pmps-profile-padding-lr: 20px;
  --pmps-profile-foot-mt: 30px;
  --pmps-foot-height: 44px;
}
</style>

# 注意事项

  1. 该组件主要用于个人资料设置页面,提供头像和昵称的编辑功能
  2. 头像显示优先级: avatar-url > default-avatar-url
  3. 组件内部使用了 PressMatchAuthorizationItem 组件来渲染授权项
  4. 底部按钮默认文本为"切换QQ账号",可通过 foot-button-text 自定义
  5. 支持通过插槽完全自定义底部按钮

# 常见问题

# 如何获取微信小程序头像?

const handleAvatarClick = () => {
  wx.chooseMedia({
    count: 1,
    mediaType: ['image'],
    sourceType: ['album', 'camera'],
    success: (res) => {
      avatarUrl.value = res.tempFiles[0].tempFilePath;
    }
  });
};

# 如何验证昵称格式?

const handleNicknameBlur = (value) => {
  if (value.length < 2) {
    wx.showToast({ title: '昵称至少2个字符', icon: 'none' });
    return;
  }
  if (value.length > 20) {
    wx.showToast({ title: '昵称不能超过20个字符', icon: 'none' });
    return;
  }
  // 其他验证逻辑...
};

# 如何上传头像到服务器?

const uploadAvatar = (tempFilePath) => {
  wx.uploadFile({
    url: 'https://your-api.com/upload',
    filePath: tempFilePath,
    name: 'avatar',
    success: (res) => {
      const data = JSON.parse(res.data);
      avatarUrl.value = data.url;
    }
  });
};