今天说到的是个人资料的设置,首先就是准备好我们项目所需要的页面组件
首先是user-profile/index.vue
<template>
<div class="user-profile">
<!-- 导航栏 -->
<van-nav-bar
class="page-nav-bar"
title="个人信息"
left-arrow
@click-left="$router.back()"
/>
<!-- /导航栏 -->
<input type="file" hidden ref="file" @change="onChangeFile" />
<!-- 个人信息 -->
<van-cell
class="avatar-cell"
title="头像"
is-link
center
@click="$refs.file.click()"
>
<van-image class="avatar" round fit="cover" :src="user.photo" />
</van-cell>
<van-cell
@click="isUpdateNameShow = true"
title="昵称"
:value="user.name"
is-link
/>
<van-cell
@click="isUpdateGenderShow = true"
title="性别"
:value="user.gender === 0 ? '男' : '女'"
is-link
/>
<van-cell
@click="isUpdateBirthdayShow = true"
title="生日"
:value="user.birthday"
is-link
/>
<!-- /个人信息 -->
<!-- 编辑昵称 -->
<van-popup
v-model="isUpdateNameShow"
style="height: 100%"
position="bottom"
>
<UpdateName
v-model="user.name"
v-if="isUpdateNameShow"
@close="isUpdateNameShow = false"
></UpdateName>
</van-popup>
<!-- /编辑昵称 -->
<!-- 修改性别 -->
<van-popup
v-model="isUpdateGenderShow"
style="height: 50%"
position="bottom"
>
<UpdateGender
@close="isUpdateGenderShow = false"
v-model="user.gender"
v-if="isUpdateGenderShow"
></UpdateGender>
</van-popup>
<!-- /修改性别 -->
<!-- 修改生日 -->
<van-popup
v-model="isUpdateBirthdayShow"
style="height: 50%"
position="bottom"
>
<UpdateBirthday
@close="isUpdateBirthdayShow = false"
v-model="user.birthday"
></UpdateBirthday>
</van-popup>
<!-- /修改生日 -->
<!-- 修改个人头像 -->
<van-popup
v-model="isUpdatePhotoShow"
style="height: 100%"
position="bottom"
>
<updatePhoto :img="img" @close="isUpdatePhotoShow = false" @update-photo="user.photo = $event"></updatePhoto>
</van-popup>
<!-- /修改个人头像 -->
</div>
</template>
<script>
import { getUserProfileAPI } from "@/api";
import UpdateName from "./components/update-name";
import UpdateGender from "./components/update-gender";
import UpdateBirthday from "./components/update-birthday";
import updatePhoto from "./components/update-photo";
export default {
name: "UserProfile",
components: {
UpdateName,
UpdateGender,
UpdateBirthday,
updatePhoto,
},
props: {},
data() {
return {
user: {},
isUpdateNameShow: false,
isUpdateGenderShow: false,
isUpdateBirthdayShow: false,
isUpdatePhotoShow: false,
img: null,
};
},
computed: {},
watch: {},
created() {
this.loadUserProfile();
},
mounted() {},
methods: {
async loadUserProfile() {
try {
const { data } = await getUserProfileAPI();
console.log(data);
this.user = data.data;
} catch (error) {
console.log(error);
this.$toast("获取用户信息失败");
}
},
onChangeFile() {
const img = this.$refs.file.files[0];
this.img = window.URL.createObjectURL(img);
this.isUpdatePhotoShow = true;
this.$refs.file.value = "";
},
},
};
</script>
<style scoped lang="less">
.user-profile {
.avatar-cell {
.van-cell__value {
display: flex;
flex-direction: row-reverse;
}
.avatar {
width: 60px;
height: 60px;
}
}
.van-popup {
background-color: #f5f7f9;
}
}
</style>
然后就是user-profile/components/update-name.vue
<template>
<div class="update-name">
<!-- 导航栏 -->
<van-nav-bar
title="设置昵称"
left-text="取消"
right-text="完成"
@click-left="$emit('close')"
@click-right="onComfirm"
/>
<!-- /导航栏 -->
<!-- 输入框 -->
<div class="field-wrap">
<van-field
v-model.trim="message"
rows="2"
autosize
type="textarea"
maxlength="11"
placeholder="请输入昵称"
show-word-limit
/>
</div>
<!-- /输入框 -->
</div>
</template>
<script>
import { updateUserProfileAPI } from "@/api";
export default {
name: "UpdateName",
components: {},
props: {
value: {
type: String,
required: true,
},
},
data() {
return {
message: this.value,
};
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
async onComfirm() {
this.$toast.loading({
message: "更新中...",
forbidClick: true,
duration: 0,
});
const massage = this.message;
if (massage.trim().length === 0) {
return this.$toast("用户名的长度不能为空");
}
try {
await updateUserProfileAPI({
name: this.message,
});
this.$toast("更新成功");
this.$emit("input", massage);
this.$emit("close");
} catch (error) {
console.log(error);
this.$toast("更新失败");
this.$toast("更新用户名失败");
}
},
},
};
</script>
<style scoped lang="less">
.field-wrap {
padding: 20px;
}
</style>
然后就是user-profile/components/update-gender.vue
<template>
<div class="update-gender">
<van-picker
@cancel="$emit('close')"
title="设置性别"
show-toolbar
:columns="columns"
:default-index="value"
@change="onChange"
@confirm="onConfirm"
/>
</div>
</template>
<script>
import { updateUserProfileAPI } from "@/api";
export default {
name: "",
components: {},
props: {
value: {
type: Number,
required: true,
},
},
data() {
return {
columns: ["男", "女"],
localGender: 0,
};
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
onChange(picker, value, index) {
this.localGender = index;
},
async onConfirm() {
this.$toast.loading({
message: "更新中...",
forbidClick: true,
duration: 0,
});
const localGender = this.localGender;
try {
await updateUserProfileAPI({
gender: this.localGender,
});
this.$toast("更新成功");
this.$emit("input", localGender);
this.$emit("close");
} catch (error) {
console.log(error);
this.$toast("更新失败");
this.$toast("更新用户名失败");
}
},
},
};
</script>
<style lang="less" scoped></style>
然后就是user-profile/components/update-birthday.vue
<template>
<div class="update-birthday">
<van-datetime-picker
v-model="currentDate"
type="date"
title="选择年月日"
:min-date="minDate"
:max-date="maxDate"
@cancel="$emit('close')"
@confirm="onConfirm"
/>
</div>
</template>
<script>
import { updateUserProfileAPI } from "@/api";
import dayjs from "dayjs";
export default {
name: "UpdateBirthday",
components: {},
props: {
value: {
type: String,
required: true,
},
},
data() {
return {
minDate: new Date(1900, 0, 1),
maxDate: new Date(),
currentDate: new Date(this.value),
};
},
computed: {},
watch: {},
created() {},
mounted() {},
methods: {
async onConfirm() {
this.$toast.loading({
message: "更新中...",
forbidClick: true,
duration: 0,
});
const localBirthday = dayjs(this.currentDate).format("YYYY-MM-DD");
try {
await updateUserProfileAPI({
birthday: localBirthday,
});
this.$toast("更新成功");
this.$emit("input", localBirthday);
this.$emit("close");
} catch (error) {
console.log(error);
this.$toast("更新失败");
this.$toast("更新用户名失败");
}
},
},
};
</script>
<style lang="less" scoped></style>
然后就是user-profile/components/update-photo.vue
<template>
<div class="update-photo">
<img class="img" :src="img" ref="img" />
<div class="toolbar">
<div class="cancel" @click="$emit('close')">取消</div>
<div class="confirm" @click="onConfirm">完成</div>
</div>
</div>
</template>
<script>
import { updateUserPhotoAPI } from "@/api";
import "cropperjs/dist/cropper.css";
import Cropper from "cropperjs";
export default {
name: "UpdatePhoto",
components: {},
props: {
img: {
type: [String, Object],
required: true,
},
},
data() {
return {
cropper: null,
};
},
computed: {},
watch: {},
created() {},
mounted() {
const image = this.$refs.img;
this.cropper = new Cropper(image, {
viewMode: 1,
dragMode: "move",
aspectRatio: 1,
cropBoxMovable: false,
cropBoxResizable: false,
background: false,
});
},
methods: {
async onUpdatePhoto(blob) {
this.$toast.loading({
message: "更新中...",
forbidClick: true,
duration: 0,
});
const formData = new FormData();
formData.append("photo", blob);
try {
const { data } = await updateUserPhotoAPI(formData);
console.log(data);
this.$toast("更新成功");
this.$emit("update-photo", data.data.photo);
this.$emit("close");
} catch (error) {
console.log(error);
this.$toast("更新失败");
this.$toast("更新头像失败");
}
},
onConfirm() {
this.cropper.getCroppedCanvas().toBlob(
(blob) => {
console.log(blob);
this.onUpdatePhoto(blob);
}
);
},
},
};
</script>
<style scoped lang="less">
.update-photo {
background-color: #000;
height: 100%;
.toolbar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: space-between;
.cancel,
.confirm {
width: 90px;
height: 90px;
font-size: 30px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}
}
}
.img {
display: block;
max-width: 100%;
}
</style>
over!