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, | ... | ... |