Commit 11eda7a127760e269cf60108fbc65305feef62e6

Authored by fengtao
1 parent 39d018f8

fix:修复个人中心头上面的图标和名字不更新问题,修改个人中心后无法及时更新问题

1 -import { UploadApiResult } from './model/uploadModel'; 1 +import { FileUploadResponse } from './model/uploadModel';
2 import { IPutPersonal } from './model/index'; 2 import { IPutPersonal } from './model/index';
3 import { defHttp } from '/@/utils/http/axios'; 3 import { defHttp } from '/@/utils/http/axios';
4 -import { UploadFileParams } from '/#/axios';  
5 4
6 enum API { 5 enum API {
7 - BaseUploadUrl = '/api/yt/oss/upload', 6 + BaseUploadUrl = '/oss/upload',
8 PutPersonalUrl = '/user/center', 7 PutPersonalUrl = '/user/center',
9 GetPersonalUrl = '/user/', 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 export const personalGet = (id: string) => { 14 export const personalGet = (id: string) => {
1 -export interface UploadApiResult {  
2 - message: string;  
3 - code: number;  
4 - url: string; 1 +export interface FileUploadResponse {
  2 + fileName: string;
  3 + fileDownloadUri: string;
  4 + fileType: string;
  5 + size: number;
  6 + fileStaticUri: string;
5 } 7 }
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 class="ml-2 md:opacity-100" 11 class="ml-2 md:opacity-100"
12 :class="getTitleClass" 12 :class="getTitleClass"
13 v-show="showTitle" 13 v-show="showTitle"
14 - style="white-space: nowrap" 14 + style="white-space: nowrap; font-size: small"
15 > 15 >
16 {{ getTitle }} 16 {{ getTitle }}
17 </span> 17 </span>
@@ -22,15 +22,34 @@ @@ -22,15 +22,34 @@
22 ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div 22 ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div
23 > 23 >
24 <div class="change-avatar" style="text-align: center"> 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 </div> 53 </div>
35 <Description 54 <Description
36 class="mt-8" 55 class="mt-8"
@@ -66,13 +85,13 @@ @@ -66,13 +85,13 @@
66 import { BasicForm, useForm } from '/@/components/Form/index'; 85 import { BasicForm, useForm } from '/@/components/Form/index';
67 import { formSchema } from './config'; 86 import { formSchema } from './config';
68 import { Description, DescItem, useDescription } from '/@/components/Description/index'; 87 import { Description, DescItem, useDescription } from '/@/components/Description/index';
69 - import { CropperAvatar } from '/@/components/Cropper';  
70 - import defaultImage from '/@/assets/images/logo.png';  
71 import { uploadApi, personalPut } from '/@/api/personal/index'; 88 import { uploadApi, personalPut } from '/@/api/personal/index';
72 import { useMessage } from '/@/hooks/web/useMessage'; 89 import { useMessage } from '/@/hooks/web/useMessage';
73 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 90 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
74 import { getAuthCache } from '/@/utils/auth'; 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 const schema: DescItem[] = [ 96 const schema: DescItem[] = [
78 { 97 {
@@ -102,59 +121,91 @@ @@ -102,59 +121,91 @@
102 ]; 121 ];
103 export default defineComponent({ 122 export default defineComponent({
104 name: 'index', 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 const userInfo = getAuthCache(USER_INFO_KEY); 127 const userInfo = getAuthCache(USER_INFO_KEY);
109 const { createMessage } = useMessage(); 128 const { createMessage } = useMessage();
110 const getPersonalValue: any = ref({}); 129 const getPersonalValue: any = ref({});
111 const getPersonalDetailValue: any = ref({}); 130 const getPersonalDetailValue: any = ref({});
112 - const avatarUrl: any = ref(''); 131 + const updatePersonalData: any = ref({});
113 const getBackendV: any = ref({}); 132 const getBackendV: any = ref({});
114 const [registerDesc] = useDescription({ 133 const [registerDesc] = useDescription({
115 title: '个人详情', 134 title: '个人详情',
116 schema: schema, 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 const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({ 163 const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({
127 showActionButtonGroup: false, 164 showActionButtonGroup: false,
128 schemas: formSchema, 165 schemas: formSchema,
129 }); 166 });
130 167
131 const [registerModal, { closeModal }] = useModalInner(async (data) => { 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 const handleSubmit = async () => { 188 const handleSubmit = async () => {
140 const getUserInfo = await userInfo; 189 const getUserInfo = await userInfo;
141 getPersonalValue.value = await validate(); 190 getPersonalValue.value = await validate();
142 getPersonalValue.value.id = getUserInfo.userId; 191 getPersonalValue.value.id = getUserInfo.userId;
143 getPersonalValue.value.username = getBackendV.value.username; 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 createMessage.success('修改成功'); 196 createMessage.success('修改成功');
147 closeModal(); 197 closeModal();
148 resetFields(); 198 resetFields();
  199 + emit('refreshPersonl', updatePersonalData.value);
149 }; 200 };
150 const compHeight = computed(() => { 201 const compHeight = computed(() => {
151 return 1000; 202 return 1000;
152 }); 203 });
153 return { 204 return {
154 - uploadApi, 205 + peresonalPic,
  206 + beforeUploadqrcodePic,
  207 + customUploadqrcodePic,
155 compHeight, 208 compHeight,
156 - updateAvatar,  
157 - avatar,  
158 handleSubmit, 209 handleSubmit,
159 getPersonalDetailValue, 210 getPersonalDetailValue,
160 registerDesc, 211 registerDesc,
@@ -165,4 +216,22 @@ @@ -165,4 +216,22 @@
165 }, 216 },
166 }); 217 });
167 </script> 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 <template> 1 <template>
2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`"> 2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`">
3 <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex"> 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 <span :class="`${prefixCls}__info hidden md:block`"> 8 <span :class="`${prefixCls}__info hidden md:block`">
6 <span :class="`${prefixCls}__name `" class="truncate"> 9 <span :class="`${prefixCls}__name `" class="truncate">
7 - {{ getUserInfo.realName }} 10 + {{ refreshPersonlData.realName ? refreshPersonlData.realName : getUserInfo.realName }}
8 </span> 11 </span>
9 </span> 12 </span>
10 </span> 13 </span>
11 14
12 <template #overlay> 15 <template #overlay>
13 <Menu @click="handleMenuClick"> 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 <MenuItem 17 <MenuItem
22 key="personal" 18 key="personal"
23 :text="t('layout.header.dropdownItemPersonal')" 19 :text="t('layout.header.dropdownItemPersonal')"
@@ -38,13 +34,17 @@ @@ -38,13 +34,17 @@
38 </template> 34 </template>
39 </Dropdown> 35 </Dropdown>
40 <LockAction @register="register" /> 36 <LockAction @register="register" />
41 - <PersonalChild ref="personalRef" @register="registerPersonal" /> 37 + <PersonalChild
  38 + @refreshPersonl="refreshPersonlFunc"
  39 + ref="personalRef"
  40 + @register="registerPersonal"
  41 + />
42 </template> 42 </template>
43 <script lang="ts"> 43 <script lang="ts">
44 // components 44 // components
45 import { Dropdown, Menu } from 'ant-design-vue'; 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 import { DOC_URL } from '/@/settings/siteSetting'; 49 import { DOC_URL } from '/@/settings/siteSetting';
50 50
@@ -59,7 +59,6 @@ @@ -59,7 +59,6 @@
59 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; 59 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
60 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 60 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
61 import { getAuthCache } from '/@/utils/auth'; 61 import { getAuthCache } from '/@/utils/auth';
62 - import { useUserStore } from '/@/store/modules/user';  
63 type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal'; 62 type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal';
64 63
65 export default defineComponent({ 64 export default defineComponent({
@@ -75,6 +74,10 @@ @@ -75,6 +74,10 @@
75 theme: propTypes.oneOf(['dark', 'light']), 74 theme: propTypes.oneOf(['dark', 'light']),
76 }, 75 },
77 setup() { 76 setup() {
  77 + const refreshPersonlData = reactive({
  78 + avatar: '',
  79 + realName: '',
  80 + });
78 const userInfo = getAuthCache(USER_INFO_KEY); 81 const userInfo = getAuthCache(USER_INFO_KEY);
79 const { proxy } = getCurrentInstance(); 82 const { proxy } = getCurrentInstance();
80 const personalRef = ref(null); 83 const personalRef = ref(null);
@@ -84,8 +87,8 @@ @@ -84,8 +87,8 @@
84 const userStore = useUserStore(); 87 const userStore = useUserStore();
85 88
86 const getUserInfo = computed(() => { 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 const [register, { openModal }] = useModal(); 94 const [register, { openModal }] = useModal();
@@ -130,7 +133,14 @@ @@ -130,7 +133,14 @@
130 }, 10); 133 }, 10);
131 }; 134 };
132 135
  136 + const refreshPersonlFunc = (v) => {
  137 + refreshPersonlData.avatar = v.avatar;
  138 + refreshPersonlData.realName = v.realName;
  139 + };
  140 +
133 return { 141 return {
  142 + refreshPersonlData,
  143 + refreshPersonlFunc,
134 personalRef, 144 personalRef,
135 registerPersonal, 145 registerPersonal,
136 openPersonalFunc, 146 openPersonalFunc,