Commit 11eda7a127760e269cf60108fbc65305feef62e6

Authored by fengtao
1 parent 39d018f8

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

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) => {
... ...
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 11 class="ml-2 md:opacity-100"
12 12 :class="getTitleClass"
13 13 v-show="showTitle"
14   - style="white-space: nowrap"
  14 + style="white-space: nowrap; font-size: small"
15 15 >
16 16 {{ getTitle }}
17 17 </span>
... ...
... ... @@ -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,
... ...