Commit 11eda7a127760e269cf60108fbc65305feef62e6
1 parent
39d018f8
fix:修复个人中心头上面的图标和名字不更新问题,修改个人中心后无法及时更新问题
Showing
5 changed files
with
138 additions
and
70 deletions
| 1 | -import { UploadApiResult } from './model/uploadModel'; | |
| 1 | +import { FileUploadResponse } from './model/uploadModel'; | |
| 2 | 2 | import { IPutPersonal } from './model/index'; |
| 3 | 3 | import { defHttp } from '/@/utils/http/axios'; |
| 4 | -import { UploadFileParams } from '/#/axios'; | |
| 5 | 4 | |
| 6 | 5 | enum API { |
| 7 | - BaseUploadUrl = '/api/yt/oss/upload', | |
| 6 | + BaseUploadUrl = '/oss/upload', | |
| 8 | 7 | PutPersonalUrl = '/user/center', |
| 9 | 8 | GetPersonalUrl = '/user/', |
| 10 | 9 | } |
| 11 | -/** | |
| 12 | - * @description: Upload interface | |
| 13 | - */ | |
| 14 | -export const uploadApi = ( | |
| 15 | - params: UploadFileParams, | |
| 16 | - onUploadProgress: (progressEvent: ProgressEvent) => void | |
| 17 | -) => { | |
| 18 | - return defHttp.uploadFile<UploadApiResult>( | |
| 19 | - { | |
| 20 | - url: API.BaseUploadUrl, | |
| 21 | - onUploadProgress, | |
| 22 | - }, | |
| 23 | - params | |
| 24 | - ); | |
| 10 | +export const uploadApi = (file) => { | |
| 11 | + return defHttp.post<FileUploadResponse>({ url: API.BaseUploadUrl, params: file }); | |
| 25 | 12 | }; |
| 26 | 13 | |
| 27 | 14 | export const personalGet = (id: string) => { | ... | ... |
| ... | ... | @@ -22,15 +22,34 @@ |
| 22 | 22 | ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div |
| 23 | 23 | > |
| 24 | 24 | <div class="change-avatar" style="text-align: center"> |
| 25 | - <div class="mb-2">头像</div> | |
| 26 | - <CropperAvatar | |
| 27 | - :uploadApi="uploadApi" | |
| 28 | - :value="avatar" | |
| 29 | - btnText="更换头像" | |
| 30 | - :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" | |
| 31 | - @change="updateAvatar" | |
| 32 | - width="150" | |
| 33 | - /> | |
| 25 | + <div class="mb-2" style="font-weight: 700">个人头像</div> | |
| 26 | + <Upload | |
| 27 | + style="width: 20vw" | |
| 28 | + name="avatar" | |
| 29 | + list-type="picture-card" | |
| 30 | + class="avatar-uploader" | |
| 31 | + :show-upload-list="false" | |
| 32 | + :customRequest="customUploadqrcodePic" | |
| 33 | + :before-upload="beforeUploadqrcodePic" | |
| 34 | + > | |
| 35 | + <img | |
| 36 | + style="text-align: center; border-radius: 50%; width: 10vw; height: 15vh" | |
| 37 | + v-if="peresonalPic" | |
| 38 | + :src="peresonalPic" | |
| 39 | + alt="avatar" | |
| 40 | + /> | |
| 41 | + <div v-else> | |
| 42 | + <div style="margin-top: 30px"> | |
| 43 | + <PlusOutlined style="font-size: 30px" /> | |
| 44 | + </div> | |
| 45 | + <div | |
| 46 | + class="ant-upload-text flex" | |
| 47 | + style="width: 280px; height: 130px; align-items: center" | |
| 48 | + > | |
| 49 | + 支持.PNG、.JPG、.SVG格式,建议尺寸为300px × 300px(及以上),大小不超过2M。</div | |
| 50 | + > | |
| 51 | + </div> | |
| 52 | + </Upload> | |
| 34 | 53 | </div> |
| 35 | 54 | <Description |
| 36 | 55 | class="mt-8" |
| ... | ... | @@ -66,13 +85,13 @@ |
| 66 | 85 | import { BasicForm, useForm } from '/@/components/Form/index'; |
| 67 | 86 | import { formSchema } from './config'; |
| 68 | 87 | import { Description, DescItem, useDescription } from '/@/components/Description/index'; |
| 69 | - import { CropperAvatar } from '/@/components/Cropper'; | |
| 70 | - import defaultImage from '/@/assets/images/logo.png'; | |
| 71 | 88 | import { uploadApi, personalPut } from '/@/api/personal/index'; |
| 72 | 89 | import { useMessage } from '/@/hooks/web/useMessage'; |
| 73 | 90 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
| 74 | 91 | import { getAuthCache } from '/@/utils/auth'; |
| 75 | - import { useUserStore } from '/@/store/modules/user'; | |
| 92 | + import { Upload } from 'ant-design-vue'; | |
| 93 | + import { PlusOutlined } from '@ant-design/icons-vue'; | |
| 94 | + import type { FileItem } from '/@/components/Upload/src/typing'; | |
| 76 | 95 | |
| 77 | 96 | const schema: DescItem[] = [ |
| 78 | 97 | { |
| ... | ... | @@ -102,59 +121,91 @@ |
| 102 | 121 | ]; |
| 103 | 122 | export default defineComponent({ |
| 104 | 123 | name: 'index', |
| 105 | - components: { BasicModal, BasicForm, Description, CropperAvatar }, | |
| 106 | - setup() { | |
| 107 | - const userStore = useUserStore(); | |
| 124 | + components: { BasicModal, BasicForm, Description, Upload, PlusOutlined }, | |
| 125 | + emits: ['refreshPersonl'], | |
| 126 | + setup(_, { emit }) { | |
| 108 | 127 | const userInfo = getAuthCache(USER_INFO_KEY); |
| 109 | 128 | const { createMessage } = useMessage(); |
| 110 | 129 | const getPersonalValue: any = ref({}); |
| 111 | 130 | const getPersonalDetailValue: any = ref({}); |
| 112 | - const avatarUrl: any = ref(''); | |
| 131 | + const updatePersonalData: any = ref({}); | |
| 113 | 132 | const getBackendV: any = ref({}); |
| 114 | 133 | const [registerDesc] = useDescription({ |
| 115 | 134 | title: '个人详情', |
| 116 | 135 | schema: schema, |
| 117 | 136 | }); |
| 118 | 137 | |
| 119 | - const avatar = computed(() => { | |
| 120 | - const { avatar } = userStore.getUserInfo; | |
| 121 | - return avatarUrl.value || avatar || defaultImage; | |
| 122 | - }); | |
| 123 | - const updateAvatar = async (v) => { | |
| 124 | - avatarUrl.value = v.data.fileStaticUri; | |
| 138 | + const peresonalPic = ref(); | |
| 139 | + | |
| 140 | + const customUploadqrcodePic = async ({ file }) => { | |
| 141 | + if (beforeUploadqrcodePic(file)) { | |
| 142 | + const formData = new FormData(); | |
| 143 | + formData.append('file', file); | |
| 144 | + const response = await uploadApi(formData); | |
| 145 | + if (response.fileStaticUri) { | |
| 146 | + peresonalPic.value = response.fileStaticUri; | |
| 147 | + } | |
| 148 | + } | |
| 125 | 149 | }; |
| 150 | + | |
| 151 | + const beforeUploadqrcodePic = (file: FileItem) => { | |
| 152 | + const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; | |
| 153 | + if (!isJpgOrPng) { | |
| 154 | + createMessage.error('只能上传图片文件!'); | |
| 155 | + } | |
| 156 | + const isLt2M = (file.size as number) / 1024 / 1024 < 2; | |
| 157 | + if (!isLt2M) { | |
| 158 | + createMessage.error('图片大小不能超过2MB!'); | |
| 159 | + } | |
| 160 | + return isJpgOrPng && isLt2M; | |
| 161 | + }; | |
| 162 | + | |
| 126 | 163 | const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({ |
| 127 | 164 | showActionButtonGroup: false, |
| 128 | 165 | schemas: formSchema, |
| 129 | 166 | }); |
| 130 | 167 | |
| 131 | 168 | const [registerModal, { closeModal }] = useModalInner(async (data) => { |
| 132 | - setFieldsValue({ | |
| 133 | - realName: data.userInfo.realName, | |
| 134 | - phoneNumber: data.userInfo.phoneNumber, | |
| 135 | - email: data.userInfo.email, | |
| 136 | - }); | |
| 137 | - getPersonalDetailValue.value = data.userInfo; | |
| 169 | + (peresonalPic.value = data.userInfo.avatar), | |
| 170 | + setFieldsValue({ | |
| 171 | + realName: data.userInfo.realName, | |
| 172 | + phoneNumber: data.userInfo.phoneNumber, | |
| 173 | + email: data.userInfo.email, | |
| 174 | + }); | |
| 175 | + if (data.userInfo) { | |
| 176 | + getPersonalDetailValue.value = data.userInfo; | |
| 177 | + } | |
| 178 | + if (Object.keys(updatePersonalData.value).length != 0) { | |
| 179 | + getPersonalDetailValue.value = updatePersonalData.value; | |
| 180 | + peresonalPic.value = updatePersonalData.value.avatar; | |
| 181 | + setFieldsValue({ | |
| 182 | + realName: updatePersonalData.value.realName, | |
| 183 | + phoneNumber: updatePersonalData.value.phoneNumber, | |
| 184 | + email: updatePersonalData.value.email, | |
| 185 | + }); | |
| 186 | + } | |
| 138 | 187 | }); |
| 139 | 188 | const handleSubmit = async () => { |
| 140 | 189 | const getUserInfo = await userInfo; |
| 141 | 190 | getPersonalValue.value = await validate(); |
| 142 | 191 | getPersonalValue.value.id = getUserInfo.userId; |
| 143 | 192 | getPersonalValue.value.username = getBackendV.value.username; |
| 144 | - getPersonalValue.value.avatar = avatarUrl.value; | |
| 145 | - await personalPut(getPersonalValue.value); | |
| 193 | + getPersonalValue.value.avatar = peresonalPic.value; | |
| 194 | + const data = await personalPut(getPersonalValue.value); | |
| 195 | + updatePersonalData.value = data; | |
| 146 | 196 | createMessage.success('修改成功'); |
| 147 | 197 | closeModal(); |
| 148 | 198 | resetFields(); |
| 199 | + emit('refreshPersonl', updatePersonalData.value); | |
| 149 | 200 | }; |
| 150 | 201 | const compHeight = computed(() => { |
| 151 | 202 | return 1000; |
| 152 | 203 | }); |
| 153 | 204 | return { |
| 154 | - uploadApi, | |
| 205 | + peresonalPic, | |
| 206 | + beforeUploadqrcodePic, | |
| 207 | + customUploadqrcodePic, | |
| 155 | 208 | compHeight, |
| 156 | - updateAvatar, | |
| 157 | - avatar, | |
| 158 | 209 | handleSubmit, |
| 159 | 210 | getPersonalDetailValue, |
| 160 | 211 | registerDesc, |
| ... | ... | @@ -165,4 +216,22 @@ |
| 165 | 216 | }, |
| 166 | 217 | }); |
| 167 | 218 | </script> |
| 168 | -<style lang="less"></style> | |
| 219 | +<style scoped lang="less"> | |
| 220 | + .change-avatar { | |
| 221 | + /deep/ .ant-upload-select-picture-card { | |
| 222 | + display: inherit; | |
| 223 | + float: none; | |
| 224 | + width: 10vw; | |
| 225 | + height: 17vh; | |
| 226 | + margin-right: 8px; | |
| 227 | + margin-bottom: 8px; | |
| 228 | + text-align: center; | |
| 229 | + vertical-align: top; | |
| 230 | + background-color: #fafafa; | |
| 231 | + border: 1px dashed #d9d9d9; | |
| 232 | + border-radius: 50%; | |
| 233 | + cursor: pointer; | |
| 234 | + transition: border-color 0.3s ease; | |
| 235 | + } | |
| 236 | + } | |
| 237 | +</style> | ... | ... |
| 1 | 1 | <template> |
| 2 | 2 | <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`"> |
| 3 | 3 | <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex"> |
| 4 | - <img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" /> | |
| 4 | + <img | |
| 5 | + :class="`${prefixCls}__header`" | |
| 6 | + :src="refreshPersonlData.avatar ? refreshPersonlData.avatar : getUserInfo.avatar" | |
| 7 | + /> | |
| 5 | 8 | <span :class="`${prefixCls}__info hidden md:block`"> |
| 6 | 9 | <span :class="`${prefixCls}__name `" class="truncate"> |
| 7 | - {{ getUserInfo.realName }} | |
| 10 | + {{ refreshPersonlData.realName ? refreshPersonlData.realName : getUserInfo.realName }} | |
| 8 | 11 | </span> |
| 9 | 12 | </span> |
| 10 | 13 | </span> |
| 11 | 14 | |
| 12 | 15 | <template #overlay> |
| 13 | 16 | <Menu @click="handleMenuClick"> |
| 14 | - <!-- <MenuItem | |
| 15 | - key="doc" | |
| 16 | - :text="t('layout.header.dropdownItemDoc')" | |
| 17 | - icon="ion:document-text-outline" | |
| 18 | - v-if="getShowDoc" | |
| 19 | - /> | |
| 20 | - <MenuDivider v-if="getShowDoc" /> --> | |
| 21 | 17 | <MenuItem |
| 22 | 18 | key="personal" |
| 23 | 19 | :text="t('layout.header.dropdownItemPersonal')" |
| ... | ... | @@ -38,13 +34,17 @@ |
| 38 | 34 | </template> |
| 39 | 35 | </Dropdown> |
| 40 | 36 | <LockAction @register="register" /> |
| 41 | - <PersonalChild ref="personalRef" @register="registerPersonal" /> | |
| 37 | + <PersonalChild | |
| 38 | + @refreshPersonl="refreshPersonlFunc" | |
| 39 | + ref="personalRef" | |
| 40 | + @register="registerPersonal" | |
| 41 | + /> | |
| 42 | 42 | </template> |
| 43 | 43 | <script lang="ts"> |
| 44 | 44 | // components |
| 45 | 45 | import { Dropdown, Menu } from 'ant-design-vue'; |
| 46 | 46 | |
| 47 | - import { defineComponent, computed, getCurrentInstance, ref } from 'vue'; | |
| 47 | + import { defineComponent, computed, getCurrentInstance, ref, reactive } from 'vue'; | |
| 48 | 48 | |
| 49 | 49 | import { DOC_URL } from '/@/settings/siteSetting'; |
| 50 | 50 | |
| ... | ... | @@ -59,7 +59,6 @@ |
| 59 | 59 | import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
| 60 | 60 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
| 61 | 61 | import { getAuthCache } from '/@/utils/auth'; |
| 62 | - import { useUserStore } from '/@/store/modules/user'; | |
| 63 | 62 | type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal'; |
| 64 | 63 | |
| 65 | 64 | export default defineComponent({ |
| ... | ... | @@ -75,6 +74,10 @@ |
| 75 | 74 | theme: propTypes.oneOf(['dark', 'light']), |
| 76 | 75 | }, |
| 77 | 76 | setup() { |
| 77 | + const refreshPersonlData = reactive({ | |
| 78 | + avatar: '', | |
| 79 | + realName: '', | |
| 80 | + }); | |
| 78 | 81 | const userInfo = getAuthCache(USER_INFO_KEY); |
| 79 | 82 | const { proxy } = getCurrentInstance(); |
| 80 | 83 | const personalRef = ref(null); |
| ... | ... | @@ -84,8 +87,8 @@ |
| 84 | 87 | const userStore = useUserStore(); |
| 85 | 88 | |
| 86 | 89 | const getUserInfo = computed(() => { |
| 87 | - const { realName = '', avatar, desc } = userStore.getUserInfo || {}; | |
| 88 | - return { realName, avatar: avatar || headerImg, desc }; | |
| 90 | + const { realName = '', avatar } = userStore.getUserInfo || {}; | |
| 91 | + return { realName, avatar: avatar || headerImg }; | |
| 89 | 92 | }); |
| 90 | 93 | |
| 91 | 94 | const [register, { openModal }] = useModal(); |
| ... | ... | @@ -130,7 +133,14 @@ |
| 130 | 133 | }, 10); |
| 131 | 134 | }; |
| 132 | 135 | |
| 136 | + const refreshPersonlFunc = (v) => { | |
| 137 | + refreshPersonlData.avatar = v.avatar; | |
| 138 | + refreshPersonlData.realName = v.realName; | |
| 139 | + }; | |
| 140 | + | |
| 133 | 141 | return { |
| 142 | + refreshPersonlData, | |
| 143 | + refreshPersonlFunc, | |
| 134 | 144 | personalRef, |
| 135 | 145 | registerPersonal, |
| 136 | 146 | openPersonalFunc, | ... | ... |