uniapp实战 -- 个人信息维护(含选择图片 uni.chooseMedia,上传文件 uni.uploadFile,获取和更新表单数据)
效果预览
相关代码
页面–我的
src\pages\my\my.vue
<!-- 个人资料 --><view class="profile" :style="{ paddingTop: safeAreaInsets!.top + 'px' }"><!-- 情况1:已登录 --><view class="overview" v-if="memberStore.profile"><navigator url="/pagesMember/profile/profile" hover-class="none"><image class="avatar" mode="aspectFill" :src="memberStore.profile.avatar"></image></navigator><view class="meta"><view class="nickname">{{ memberStore.profile.nickname || memberStore.profile.account }}</view><navigator class="extra" url="/pagesMember/profile/profile" hover-class="none"><text class="update">更新头像昵称</text></navigator></view></view><!-- 情况2:未登录 --><view class="overview" v-else><navigator url="/pages/login/login" hover-class="none"><imageclass="avatar gray"mode="aspectFill"src="http://yjy-xiaotuxian-dev.oss-cn-beijing.aliyuncs.com/picture/2021-04-06/db628d42-88a7-46e7-abb8-659448c33081.png"></image></navigator><view class="meta"><navigator url="/pages/login/login" hover-class="none" class="nickname">未登录</navigator><view class="extra"><text class="tips">点击登录账号</text></view></view></view><navigator class="settings" url="/pagesMember/settings/settings" hover-class="none">设置</navigator></view>
/* 用户信息 */
.profile {margin-top: 20rpx;position: relative;.overview {display: flex;height: 120rpx;padding: 0 36rpx;color: #fff;}.avatar {width: 120rpx;height: 120rpx;border-radius: 50%;background-color: #eee;}.gray {filter: grayscale(100%);}.meta {display: flex;flex-direction: column;justify-content: center;align-items: flex-start;line-height: 30rpx;padding: 16rpx 0;margin-left: 20rpx;}.nickname {max-width: 350rpx;margin-bottom: 16rpx;font-size: 30rpx;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}.extra {display: flex;font-size: 20rpx;}.tips {font-size: 22rpx;}.update {padding: 3rpx 10rpx 1rpx;color: rgba(255, 255, 255, 0.8);border: 1rpx solid rgba(255, 255, 255, 0.8);margin-right: 10rpx;border-radius: 30rpx;}.settings {position: absolute;bottom: 0;right: 40rpx;font-size: 30rpx;color: #fff;}
}
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()import { useMemberStore } from '@/stores'// 获取会员信息
const memberStore = useMemberStore()
页面–个人信息维护
src\pagesMember\profile\profile.vue
<script setup lang="ts">
import { getMemberProfileAPI, putMemberProfileAPI } from '@/apis/profile'
import type { Gender, ProfileDetail } from '@/types/member'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()// 获取个人信息,修改个人信息需提供初始值 (使用 as 进行类型断言,不用再声明类型)
const profile = ref({} as ProfileDetail)
const getMemberProfileData = async () => {const res = await getMemberProfileAPI()profile.value = res.result
}onLoad(() => {getMemberProfileData()
})import { useMemberStore } from '@/stores'// 获取会员信息
const memberStore = useMemberStore()// 修改头像
const onAvatarChange = () => {// 调用拍照/选择图片uni.chooseMedia({// 文件个数count: 1,// 文件类型mediaType: ['image'],success: (res) => {// 本地路径const { tempFilePath } = res.tempFiles[0]// 文件上传uni.uploadFile({url: '/member/profile/avatar',name: 'file', // 后端数据字段名filePath: tempFilePath, // 新头像success: (res) => {// 判断状态码是否上传成功if (res.statusCode === 200) {// 提取头像const { avatar } = JSON.parse(res.data).result// 当前页面更新头像profile.value!.avatar = avatar// 更新 Store 头像memberStore.profile!.avatar = avataruni.showToast({ icon: 'success', title: '更新成功' })} else {uni.showToast({ icon: 'error', title: '出现错误' })}},})},})
}// 修改性别
const onGenderChange: UniHelper.RadioGroupOnChange = (ev) => {profile.value.gender = ev.detail.value as Gender
}// 修改生日
const onBirthdayChange: UniHelper.DatePickerOnChange = (ev) => {profile.value.birthday = ev.detail.value
}// 修改城市
let fullLocationCode: [string, string, string] = ['', '', '']
const onFullLocationChange: UniHelper.RegionPickerOnChange = (ev) => {// 修改前端界面profile.value.fullLocation = ev.detail.value.join(' ')// 提交后端更新fullLocationCode = ev.detail.code!
}// 点击保存提交表单
const onSubmit = async () => {const { nickname, gender, birthday, profession } = profile.valueconst res = await putMemberProfileAPI({nickname,gender,birthday,profession,provinceCode: fullLocationCode[0],cityCode: fullLocationCode[1],countyCode: fullLocationCode[2],})// 更新Store昵称memberStore.profile!.nickname = res.result.nicknameuni.showToast({ icon: 'success', title: '保存成功' })setTimeout(() => {uni.navigateBack()}, 400)
}
</script><template><view class="viewport"><!-- 导航栏 --><view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"><navigator open-type="navigateBack" class="back icon-left" hover-class="none"></navigator><view class="title">个人信息</view></view><!-- 头像 --><view class="avatar"><view class="avatar-content" @tap="onAvatarChange"><image class="image" :src="profile?.avatar" mode="aspectFill" /><text class="text">点击修改头像</text></view></view><!-- 表单 --><view class="form"><!-- 表单内容 --><view class="form-content"><view class="form-item"><text class="label">账号</text><text class="account">{{ profile?.account }}</text></view><view class="form-item"><text class="label">昵称</text><input class="input" type="text" placeholder="请填写昵称" v-model="profile.nickname" /></view><view class="form-item"><text class="label">性别</text><radio-group @change="onGenderChange"><label class="radio"><radio value="男" color="#27ba9b" :checked="profile?.gender === '男'" />男</label><label class="radio"><radio value="女" color="#27ba9b" :checked="profile?.gender === '女'" />女</label></radio-group></view><view class="form-item"><text class="label">生日</text><pickerclass="picker"mode="date":value="profile?.birthday"start="1900-01-01":end="new Date()"@change="onBirthdayChange"><view v-if="profile?.birthday">{{ profile?.birthday }}</view><view class="placeholder" v-else>请选择日期</view></picker></view><view class="form-item"><text class="label">城市</text><picker@change="onFullLocationChange"class="picker":value="profile?.fullLocation?.split(' ')"mode="region"><view v-if="profile?.fullLocation">{{ profile.fullLocation }}</view><view class="placeholder" v-else>请选择城市</view></picker></view><view class="form-item"><text class="label">职业</text><input class="input" type="text" placeholder="请填写职业" v-model="profile.profession" /></view></view><!-- 提交按钮 --><button class="form-button" @tap="onSubmit">保 存</button></view></view>
</template>
<style lang="scss">
page {background-color: #f4f4f4;
}.viewport {display: flex;flex-direction: column;height: 100%;background-image: url(https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/order_bg.png);background-size: auto 420rpx;background-repeat: no-repeat;
}// 导航栏
.navbar {position: relative;.title {height: 40px;display: flex;justify-content: center;align-items: center;font-size: 16px;font-weight: 500;color: #fff;}.back {position: absolute;height: 40px;width: 40px;left: 0;font-size: 20px;color: #fff;display: flex;justify-content: center;align-items: center;}
}// 头像
.avatar {text-align: center;width: 100%;height: 260rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;.image {width: 160rpx;height: 160rpx;border-radius: 50%;background-color: #eee;}.text {display: block;padding-top: 20rpx;line-height: 1;font-size: 26rpx;color: #fff;}
}// 表单
.form {background-color: #f4f4f4;&-content {margin: 20rpx 20rpx 0;padding: 0 20rpx;border-radius: 10rpx;background-color: #fff;}&-item {display: flex;height: 96rpx;line-height: 46rpx;padding: 25rpx 10rpx;background-color: #fff;font-size: 28rpx;border-bottom: 1rpx solid #ddd;&:last-child {border: none;}.label {width: 180rpx;color: #333;}.account {color: #666;}.input {flex: 1;display: block;height: 46rpx;}.radio {margin-right: 20rpx;}.picker {flex: 1;}.placeholder {color: #808080;}}&-button {height: 80rpx;text-align: center;line-height: 80rpx;margin: 30rpx 20rpx;color: #fff;border-radius: 80rpx;font-size: 30rpx;background-color: #27ba9b;}
}
</style>
接口
src\apis\profile.ts
import type { ProfileDetail, ProfileParams } from '@/types/member'
import { http } from '@/utils/http'/*** 获取个人信息*/
export const getMemberProfileAPI = () => {return http<ProfileDetail>({method: 'GET',url: '/member/profile',})
}/*** 修改个人信息* @param data 请求体参数*/
export const putMemberProfileAPI = (data: ProfileParams) => {return http<ProfileDetail>({method: 'PUT',url: '/member/profile',data,})
}
类型声明
src\types\member.d.ts
/** 封装通用信息 */
type BaseProfile = {/** 用户ID */id: number/** 头像 */avatar: string/** 账户名 */account: string/** 昵称 */nickname?: string
}/** 小程序登录 登录用户信息 */
export type LoginResult = BaseProfile & {/** 用户ID */id: number/** 头像 */avatar: string/** 账户名 */account: string/** 昵称 */nickname?: string/** 手机号 */mobile: string/** 登录凭证 */token: string
}/** 个人信息 用户详情信息 */
export type ProfileDetail = BaseProfile & {/** 性别 */gender?: Gender/** 生日 */birthday?: string/** 省市区 */fullLocation?: string/** 职业 */profession?: string
}
/** 性别 */
export type Gender = '女' | '男'/** 个人信息 修改请求体参数 */
export type ProfileParams = Pick<ProfileDetail,'nickname' | 'gender' | 'birthday' | 'profession'
> & {/** 省份编码 */provinceCode?: string/** 城市编码 */cityCode?: string/** 区/县编码 */countyCode?: string
}
持久化本地存储 store
src\stores\index.ts
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)// 默认导出,给 main.ts 使用
export default pinia// 模块统一导出
export * from './modules/member'
src\stores\modules\member.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'// 定义 Store
export const useMemberStore = defineStore('member',() => {// 会员信息const profile = ref<any>()// 保存会员信息,登录时使用const setProfile = (val: any) => {profile.value = val}// 清理会员信息,退出时使用const clearProfile = () => {profile.value = undefined}// 记得 returnreturn {profile,setProfile,clearProfile,}},// 持久化{persist: {// 调整为兼容多端的APIstorage: {setItem(key, value) {uni.setStorageSync(key, value)},getItem(key) {return uni.getStorageSync(key)},},},},
)
相关文章:

uniapp实战 -- 个人信息维护(含选择图片 uni.chooseMedia,上传文件 uni.uploadFile,获取和更新表单数据)
效果预览 相关代码 页面–我的 src\pages\my\my.vue <!-- 个人资料 --><view class"profile" :style"{ paddingTop: safeAreaInsets!.top px }"><!-- 情况1:已登录 --><view class"overview" v-if"membe…...
企业如何建立价值评估体系?
企业绩效评价体系是指由一系列与绩效评价相关的评价制度、评价指标体系、评价方法、评价标准以及评价机构等形成的有机整体。企业的评价系统大致可以分为以下四个层次: 第一、岗位评价系统,主要针对不同岗位之间的评估。例如,企业中一般业务…...

华为安防监控摄像头
华为政企42 华为政企 目录 上一篇华为政企城市一张网研究报告下一篇华为全屋wifi6蜂鸟套装标准...
[node] Node.js 缓冲区Buffer
[node] Node.js 缓冲区Buffer 什么是BufferBuffer 与字符编码Buffer 的方法概览Buffer 的实例Buffer 的创建写入缓冲区从 Buffer 区读取数据将 Buffer 转换为 JSON 对象Buffer 的合并Buffer 的比较Buffer 的覆盖Buffer 的截取--sliceBuffer 的长度writeUIntLEwriteUIntBE 什么是…...

【ARM Cortex-M 系列 5 -- RT-Thread renesas/ra4m2-eco 移植编译篇】
文章目录 RT-Thread 移植编译篇编译os.environ 使用示例os.putenv使用示例python from 后指定路径 编译问题_POSIX_C_SOURCE 介绍编译结果 RT-Thread 移植编译篇 本文以瑞萨的ra4m2-eco 为例介绍如何下载rt-thread 及编译的设置。 RT-Thread 代码下载: git clone …...
功能强大的开源数据中台系统 DataCap 1.18.0 发布
推荐一套基于 SpringBoot 开发的简单、易用的开源权限管理平台,建议下载使用: https://github.com/devlive-community/authx 推荐一套为 Java 开发人员提供方便易用的 SDK 来与目前提供服务的的 Open AI 进行交互组件:https://github.com/devlive-commun…...

A Philosophy of Software Design 学习笔记
前言 高耦合,低内聚,降低复杂度:在软件迭代中,不关注软件系统结构,导致软件复杂度累加,软件缺乏系统设计,模块混乱,一旦需求增加、修改或者优化,改变的代价无法评估&…...

设计模式----解释器模式
一、简介 解释器模式使用频率并不高,通常用来构建一个简单语言的语法解释器,它只在一些非常特定的领域被用到,比如编译器、规则引擎、正则表达式、sql解析等。 解释器模式是行为型设计模式之一,它的原始定义为:用于定义…...
Linux常用命令(一):Conda、RPM、文件权限、apt-get(更新中...
文章目录 一、Conda二、RPM三、文件权限四、apt-get 一、Conda Conda是一个开源的软件包管理系统和环境管理系统,用于安装和管理软件包及其依赖项。它主要用于Python编程语言,但也可以用于其他语言的项目。Conda可以帮助用户创建不同版本的Python环境&a…...

3 个适用于 Mac 电脑操作的 Android 数据恢复最佳工具 [附步骤]
在当今的数字时代,无论是由于意外删除、系统故障还是其他原因,从 Android 设备中丢失数据不仅会带来不便,而且会造成非常严重的后果。特别是对于Mac用户来说,从Android手机恢复数据是一个很大的麻烦。幸运的是,随着许多…...

日志服务 SLS 深度解析:拥抱云原生和 AI,基于 SLS 的可观测分析创新
云布道师 10 月 31 日,杭州云栖大会上,日志服务 SLS 研发负责人简志和产品经理孟威等人发表了《日志服务 SLS 深度解析:拥抱云原生和 AI,基于 SLS 的可观测分析创新》的主题演讲,对阿里云日志服务 SLS 产品服务创新以…...
MinIO客户端之rm
MinIO提供了一个命令行程序mc用于协助用户完成日常的维护、管理类工作。 官方资料 mc rm 删除指定的对象。 准备待删除的对象,查看对象,命令如下: ./mc ls local1/bkt2/控制台的输出,如下: [2023-12-16 01:52:54 …...

【Linux笔记】文件和目录操作
🍎个人博客:个人主页 🏆个人专栏:Linux学习 ⛳️ 功不唐捐,玉汝于成 目录 前言 命令 ls (List): pwd (Print Working Directory): cp (Copy): mv (Move): rm (Remove): 结语 我的其他博客 前言 学习Linux命令…...

Vue-router 中hash模式和history模式的区别
Vue-router 中hash模式和history模式的区别 在通过vue-cli创建项目的时候,出现: 于是,去Google一遍。。 vue-router的model有两种模式:hash模式和history模式。 hash模式和history模式的不同 最直观的区别就是在url中 hash 带了一个很丑的…...

Debian在升级过程中报错
当我们在升级的过程中出现如下报错信息 报错信息如下所示: The following signatures couldnt be verified because the public key is not available: NO_PUBKEY ED444FF07D8D0BF6 W: GPG error: http://mirrors.jevincanders.net/kali kali-rolling InRelease: …...
IOS开发问题记录
1. xcode上传app store connect后testflight没有可构建版本的原因 查看你的邮箱, 里面有原因提示 一般为使用了某些权限, 但是plist没有声明 2. xcode 修改display name后名字并没有改变 原因是并没有修改到plist的CFBundleDisplayName的字段 将CFBundleDisplayName的值修改…...

数据流图_DFD图_精简易上手
数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输人移动到输出的过程中所经受的变换。 首先给出一个数据流图样例 基本的四种图形 直角矩形:代表源点或终点,一般来说,是人,如例图的仓库管理员和采购员圆形(也可以画成圆角矩形):是处理,一般来说,是动作,是动词名词的形式…...
使用 Xcode 创建一个新的项目并运行
启动 Xcode: 打开你的 Mac,然后启动 Xcode。你可以在应用程序文件夹中找到它,或者使用 Spotlight 搜索。 创建新项目: 当 Xcode 启动时,选择 “Create a new Xcode project”(创建一个新的 Xcode 项目)。 在项目模板…...

教师未来前景发展
教师是一个光荣而重要的职业,他们承担着培养下一代的责任和使命。随着社会的不断发展和变化,教师的前景也在不断扩大和改变。本文将探讨教师未来的前景发展,并提供一些思考和建议。 首先,教师的就业前景将继续扩大。随着人口的增长…...
【华为机试】2023年真题B卷(python)-采样过滤
一、题目 题目描述: 在做物理实验时,为了计算物体移动的速率,通过相机等工具周期性的采样物体移动能离。由于工具故障,采样数据存在误差甚至相误的情况。需要通过一个算法过滤掉不正确的采样值,不同工具的故意模式存在…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...

Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...