feat: upload avatar

This commit is contained in:
KUN1007 2023-10-15 22:26:01 +08:00
parent c425aac9b2
commit 5d271ac233
8 changed files with 105 additions and 63 deletions

View file

@ -1,4 +1,9 @@
import { fetchGet, fetchPut, fetchPost } from '@/utils/request' import {
fetchGet,
fetchPut,
fetchPost,
fetchPostWithFormData,
} from '@/utils/request'
// 将对象转为请求参数的函数 // 将对象转为请求参数的函数
import objectToQueryParams from '@/utils/objectToQueryParams' import objectToQueryParams from '@/utils/objectToQueryParams'
import * as User from './types/user' import * as User from './types/user'
@ -16,6 +21,19 @@ export async function getUserByUidApi(
return response return response
} }
// 更新用户头像
export async function updateUserAvatarApi(
request: User.UserUpdateAvatarRequestData
): Promise<User.UserUpdateAvatarResponseData> {
const url = `/user/${request.uid}/avatar`
const response =
await fetchPostWithFormData<User.UserUpdateAvatarResponseData>(
url,
request.avatar
)
return response
}
// 更新用户 bio // 更新用户 bio
export async function updateUserBioApi( export async function updateUserBioApi(
request: User.UserUpdateBioRequestData request: User.UserUpdateBioRequestData

View file

@ -19,6 +19,12 @@ export interface UserInfo {
upvote_topic: number[] upvote_topic: number[]
} }
// 用户更新头像
export interface UserUpdateAvatarRequestData {
uid: number
avatar: FormData
}
// 用户更新签名 // 用户更新签名
export interface UserUpdateBioRequestData { export interface UserUpdateBioRequestData {
uid: number uid: number
@ -86,6 +92,10 @@ export interface UserResetPasswordByEmailRequestData {
export type UserInfoResponseData = KUNGalgameResponseData<UserInfo> export type UserInfoResponseData = KUNGalgameResponseData<UserInfo>
export type UserUpdateAvatarResponseData = KUNGalgameResponseData<{
avatar: string
}>
export type UserUpdateBioResponseData = KUNGalgameResponseData<{}> export type UserUpdateBioResponseData = KUNGalgameResponseData<{}>
export type UserGetUserEmailResponseData = KUNGalgameResponseData<{ export type UserGetUserEmailResponseData = KUNGalgameResponseData<{

View file

@ -18,6 +18,8 @@ import {
import type { import type {
UserInfoResponseData, UserInfoResponseData,
UserUpdateAvatarRequestData,
UserUpdateAvatarResponseData,
UserUpdateBioRequestData, UserUpdateBioRequestData,
UserUpdateBioResponseData, UserUpdateBioResponseData,
UserGetUserEmailResponseData, UserGetUserEmailResponseData,
@ -38,6 +40,7 @@ import type {
import { import {
getUserByUidApi, getUserByUidApi,
updateUserAvatarApi,
updateUserBioApi, updateUserBioApi,
getUserEmailApi, getUserEmailApi,
getUserResetEmailCodeApi, getUserResetEmailCodeApi,
@ -139,13 +142,21 @@ export const useKUNGalgameUserStore = defineStore({
return getUserByUidApi(uid) return getUserByUidApi(uid)
}, },
// 更新用户 avatar
async updateAvatar(
avatar: FormData
): Promise<UserUpdateAvatarResponseData> {
const request: UserUpdateAvatarRequestData = {
uid: this.uid,
avatar: avatar,
}
return updateUserAvatarApi(request)
},
// 更新用户 bio // 更新用户 bio
async updateBio( async updateBio(bio: string): Promise<UserUpdateBioResponseData> {
uid: number,
bio: string
): Promise<UserUpdateBioResponseData> {
const request: UserUpdateBioRequestData = { const request: UserUpdateBioRequestData = {
uid, uid: this.uid,
bio, bio,
} }
return updateUserBioApi(request) return updateUserBioApi(request)

View file

@ -100,7 +100,7 @@ export const useKUNGalgameTopicStore = defineStore({
}, },
replyRequest: { replyRequest: {
page: 1, page: 1,
limit: 5, limit: 3,
sortField: 'floor', sortField: 'floor',
sortOrder: 'asc', sortOrder: 'asc',
}, },

View file

@ -103,4 +103,21 @@ const fetchDelete = async <T>(
return await kunFetchRequest<T>(url, options) return await kunFetchRequest<T>(url, options)
} }
export { fetchGet, fetchPost, fetchPut, fetchDelete } const fetchPostWithFormData = async <T>(
url: string,
formData: FormData,
headers?: Record<string, string>
): Promise<T> => {
const options: FetchOptions = {
method: 'POST',
credentials: 'include',
headers: {
...headers,
},
body: formData,
}
return await kunFetchRequest<T>(url, options)
}
export { fetchGet, fetchPost, fetchPut, fetchDelete, fetchPostWithFormData }

View file

@ -2,11 +2,8 @@
import { ref } from 'vue' import { ref } from 'vue'
import Message from '@/components/alert/Message' import Message from '@/components/alert/Message'
// //
import { import { checkImageValid, resizeImage } from '../utils/handleFileChange'
checkImageValid, import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
resizeImage,
handleUploadAvatar,
} from '../utils/handleFileChange'
// //
const uploadedImage = ref<Blob>() const uploadedImage = ref<Blob>()
@ -15,12 +12,28 @@ const selectedFileUrl = ref<string>('')
// input // input
const input = ref<HTMLElement>() const input = ref<HTMLElement>()
//
const uploadImage = async (file: File) => {
// 退
const isFileValid = checkImageValid(file)
if (!isFileValid) {
return
}
const resizedFile = await resizeImage(file)
uploadedImage.value = resizedFile
selectedFileUrl.value = URL.createObjectURL(resizedFile)
}
// //
const handleFileChange = async (event: Event) => { const handleFileChange = async (event: Event) => {
const imgUrl = await handleUploadAvatar(event) const input = event.target as HTMLInputElement
if (imgUrl) {
selectedFileUrl.value = imgUrl if (!input.files || !input.files[0]) {
return
} }
const file = input.files[0]
uploadImage(file)
} }
// //
@ -32,14 +45,7 @@ const handleDrop = async (event: DragEvent) => {
const dataTransfer = event.dataTransfer const dataTransfer = event.dataTransfer
if (dataTransfer && dataTransfer.files.length > 0) { if (dataTransfer && dataTransfer.files.length > 0) {
const file = dataTransfer.files[0] const file = dataTransfer.files[0]
uploadImage(file)
//
if (checkImageValid(file)) {
const resizedFile = await resizeImage(file)
uploadedImage.value = resizedFile
selectedFileUrl.value = URL.createObjectURL(resizedFile)
}
} }
} }
@ -49,20 +55,23 @@ const handleDragOver = (event: DragEvent) => {
event.dataTransfer!.dropEffect = 'copy' event.dataTransfer!.dropEffect = 'copy'
} }
// //
const handleChangeAvatar = () => { const handleClickUpload = () => {
Message( input.value?.click()
'Image API is not yet completed, stay tuned for updates',
'图片接口还未完成,敬请期待',
'warn'
)
if (uploadedImage.value) {
const formData = new FormData()
formData.append('avatar', uploadedImage.value)
// TODO:
//
} }
//
const handleChangeAvatar = async () => {
if (!uploadedImage.value) {
return
}
const formData = new FormData()
formData.append('avatar', uploadedImage.value, useKUNGalgameUserStore().name)
console.log(uploadedImage.value)
await useKUNGalgameUserStore().updateAvatar(formData)
} }
</script> </script>
@ -77,7 +86,7 @@ const handleChangeAvatar = () => {
class="avatar-upload" class="avatar-upload"
@drop="handleDrop($event)" @drop="handleDrop($event)"
@dragover="handleDragOver" @dragover="handleDragOver"
@click="input?.click()" @click="handleClickUpload"
> >
<!-- 加号提示 --> <!-- 加号提示 -->
<span class="plus" v-if="!selectedFileUrl"></span> <span class="plus" v-if="!selectedFileUrl"></span>

View file

@ -1,12 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue' import { ref } from 'vue'
import Avatar from '../components/Avatar.vue' import Avatar from '../components/Avatar.vue'
import Message from '@/components/alert/Message' import Message from '@/components/alert/Message'
// store // store
import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer' import { useKUNGalgameUserStore } from '@/store/modules/kungalgamer'
const currentUserUid = computed(() => useKUNGalgameUserStore().uid)
// //
const bioValue = ref('') const bioValue = ref('')
@ -22,10 +20,8 @@ const handleChangeBio = async () => {
return return
} }
const res = await useKUNGalgameUserStore().updateBio( const res = await useKUNGalgameUserStore().updateBio(bioValue.value)
currentUserUid.value,
bioValue.value
)
if (res.code === 200) { if (res.code === 200) {
Message('Rewrite bio successfully!', 'Rewrite 签名成功', 'success') Message('Rewrite bio successfully!', 'Rewrite 签名成功', 'success')
bioValue.value = '' bioValue.value = ''

View file

@ -70,22 +70,3 @@ export const resizeImage = (file: File): Promise<Blob> => {
} }
}) })
} }
// 上传头像
export const handleUploadAvatar = async (event: Event) => {
const input = event.target as HTMLInputElement
if (input.files && input.files[0]) {
const file = input.files[0]
// 检查图片是否合法,不合法则退出
const isFileValid = checkImageValid(file)
if (!isFileValid) {
return
}
// 处理图片
const resizedFile = await resizeImage(file)
return URL.createObjectURL(resizedFile)
}
}