Commit 99def7931afd6f6c9797422d6a4a5fcc89b458ea

Authored by xp.Huang
2 parents ac6ad4c5 b28f82dd

Merge branch 'local_dev_ft' into 'main'

pref:优化产品Topic列表 移除不需要的文字;优化个人头像上传头像使用自带组件

See merge request yunteng/thingskit-front!491
@@ -179,14 +179,22 @@ @@ -179,14 +179,22 @@
179 cropper?.value?.[event]?.(arg); 179 cropper?.value?.[event]?.(arg);
180 } 180 }
181 181
  182 + const blobToFile = (blob, fileName) => {
  183 + const file = new File([blob], fileName, { type: blob.type });
  184 + const formData = new FormData();
  185 + formData.append('file', file);
  186 + return formData;
  187 + };
  188 +
182 async function handleOk() { 189 async function handleOk() {
183 const uploadApi = props.uploadApi; 190 const uploadApi = props.uploadApi;
184 if (uploadApi && isFunction(uploadApi)) { 191 if (uploadApi && isFunction(uploadApi)) {
185 const blob = dataURLtoBlob(previewSource.value); 192 const blob = dataURLtoBlob(previewSource.value);
  193 + const base64D = blobToFile(blob, filename);
186 try { 194 try {
187 setModalProps({ confirmLoading: true }); 195 setModalProps({ confirmLoading: true });
188 - const result = await uploadApi({ name: 'file', file: blob, filename });  
189 - emit('uploadSuccess', { source: previewSource.value, data: result.data }); 196 + const result = await uploadApi(base64D);
  197 + emit('uploadSuccess', { source: previewSource.value, data: result.fileStaticUri });
190 closeModal(); 198 closeModal();
191 } finally { 199 } finally {
192 setModalProps({ confirmLoading: false }); 200 setModalProps({ confirmLoading: false });
1 -<template>  
2 - <div :class="getClass" :style="getStyle">  
3 - <div :class="`${prefixCls}-image-wrapper`" :style="getImageWrapperStyle" @click="openModal">  
4 - <div :class="`${prefixCls}-image-mask`" :style="getImageWrapperStyle">  
5 - <Icon  
6 - icon="ant-design:cloud-upload-outlined"  
7 - :size="getIconWidth"  
8 - :style="getImageWrapperStyle"  
9 - color="#d6d6d6"  
10 - />  
11 - </div>  
12 - <img :src="sourceValue" v-if="sourceValue" alt="avatar" />  
13 - </div>  
14 - <a-button  
15 - :class="`${prefixCls}-upload-btn`"  
16 - @click="openModal"  
17 - v-if="showBtn"  
18 - v-bind="btnProps"  
19 - >  
20 - {{ btnText ? btnText : t('component.cropper.selectImage') }}  
21 - </a-button>  
22 -  
23 - <CopperModal  
24 - @register="register"  
25 - @uploadSuccess="handleUploadSuccess"  
26 - :uploadApi="uploadApi"  
27 - :src="sourceValue"  
28 - />  
29 - </div>  
30 -</template>  
31 -<script lang="ts">  
32 - import {  
33 - defineComponent,  
34 - computed,  
35 - CSSProperties,  
36 - unref,  
37 - ref,  
38 - watchEffect,  
39 - watch,  
40 - PropType,  
41 - } from 'vue';  
42 - import CopperModal from './CopperModal.vue';  
43 - import { useDesign } from '/@/hooks/web/useDesign';  
44 - import { useModal } from '/@/components/Modal';  
45 - import { useMessage } from '/@/hooks/web/useMessage';  
46 - import { useI18n } from '/@/hooks/web/useI18n';  
47 - import type { ButtonProps } from '/@/components/Button';  
48 - import Icon from '/@/components/Icon';  
49 -  
50 - const props = {  
51 - width: { type: [String, Number], default: '200px' },  
52 - value: { type: String },  
53 - showBtn: { type: Boolean, default: true },  
54 - btnProps: { type: Object as PropType<ButtonProps> },  
55 - btnText: { type: String, default: '' },  
56 - uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> },  
57 - };  
58 -  
59 - export default defineComponent({  
60 - name: 'CropperAvatar',  
61 - components: { CopperModal, Icon },  
62 - props,  
63 - emits: ['update:value', 'change'],  
64 - setup(props, { emit, expose }) {  
65 - const sourceValue = ref(props.value || '');  
66 - const { prefixCls } = useDesign('cropper-avatar');  
67 - const [register, { openModal, closeModal }] = useModal();  
68 - const { createMessage } = useMessage();  
69 - const { t } = useI18n();  
70 -  
71 - const getClass = computed(() => [prefixCls]);  
72 -  
73 - const getWidth = computed(() => `${props.width}`.replace(/px/, '') + 'px');  
74 -  
75 - const getIconWidth = computed(() => parseInt(`${props.width}`.replace(/px/, '')) / 2 + 'px');  
76 -  
77 - const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) }));  
78 -  
79 - const getImageWrapperStyle = computed(  
80 - (): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) })  
81 - );  
82 -  
83 - watchEffect(() => {  
84 - sourceValue.value = props.value || '';  
85 - });  
86 -  
87 - watch(  
88 - () => sourceValue.value,  
89 - (v: string) => {  
90 - emit('update:value', v);  
91 - }  
92 - );  
93 -  
94 - function handleUploadSuccess(source) {  
95 - sourceValue.value = source;  
96 - emit('change', source);  
97 - createMessage.success(t('component.cropper.uploadSuccess'));  
98 - }  
99 -  
100 - expose({ openModal: openModal.bind(null, true), closeModal });  
101 -  
102 - return {  
103 - t,  
104 - prefixCls,  
105 - register,  
106 - openModal,  
107 - getIconWidth,  
108 - sourceValue,  
109 - getClass,  
110 - getImageWrapperStyle,  
111 - getStyle,  
112 - handleUploadSuccess,  
113 - };  
114 - },  
115 - });  
116 -</script>  
117 -  
118 -<style lang="less" scoped>  
119 - @prefix-cls: ~'@{namespace}-cropper-avatar';  
120 -  
121 - .@{prefix-cls} {  
122 - display: inline-block;  
123 - text-align: center;  
124 -  
125 - &-image-wrapper {  
126 - overflow: hidden;  
127 - cursor: pointer;  
128 - background: @component-background;  
129 - border: 1px solid @border-color-base;  
130 - border-radius: 50%;  
131 -  
132 - img {  
133 - width: 100%;  
134 - }  
135 - }  
136 -  
137 - &-image-mask {  
138 - opacity: 0;  
139 - position: absolute;  
140 - width: inherit;  
141 - height: inherit;  
142 - border-radius: inherit;  
143 - border: inherit;  
144 - background: rgba(0, 0, 0, 0.4);  
145 - cursor: pointer;  
146 - -webkit-transition: opacity 0.4s;  
147 - transition: opacity 0.4s;  
148 -  
149 - :deep(svg) {  
150 - margin: auto;  
151 - }  
152 - }  
153 -  
154 - &-image-mask:hover {  
155 - opacity: 40;  
156 - }  
157 -  
158 - &-upload-btn {  
159 - margin: 10px auto;  
160 - }  
161 - }  
162 -</style> 1 +<template>
  2 + <div :class="getClass" :style="getStyle">
  3 + <div :class="`${prefixCls}-image-wrapper`" :style="getImageWrapperStyle" @click="openModal">
  4 + <div :class="`${prefixCls}-image-mask`" :style="getImageWrapperStyle">
  5 + <Icon
  6 + icon="ant-design:cloud-upload-outlined"
  7 + :size="getIconWidth"
  8 + :style="getImageWrapperStyle"
  9 + color="#d6d6d6"
  10 + />
  11 + </div>
  12 + <img :src="sourceValue" v-if="sourceValue" alt="avatar" />
  13 + </div>
  14 + <a-button
  15 + :class="`${prefixCls}-upload-btn`"
  16 + @click="openModal"
  17 + v-if="showBtn"
  18 + v-bind="btnProps"
  19 + >
  20 + {{ btnText ? btnText : t('component.cropper.selectImage') }}
  21 + </a-button>
  22 +
  23 + <CopperModal
  24 + @register="register"
  25 + @uploadSuccess="handleUploadSuccess"
  26 + :uploadApi="uploadApi"
  27 + :src="sourceValue"
  28 + />
  29 + </div>
  30 +</template>
  31 +<script lang="ts">
  32 + import {
  33 + defineComponent,
  34 + computed,
  35 + CSSProperties,
  36 + unref,
  37 + ref,
  38 + watchEffect,
  39 + watch,
  40 + PropType,
  41 + } from 'vue';
  42 + import CopperModal from './CopperModal.vue';
  43 + import { useDesign } from '/@/hooks/web/useDesign';
  44 + import { useModal } from '/@/components/Modal';
  45 + import { useMessage } from '/@/hooks/web/useMessage';
  46 + import { useI18n } from '/@/hooks/web/useI18n';
  47 + import type { ButtonProps } from '/@/components/Button';
  48 + import Icon from '/@/components/Icon';
  49 +
  50 + const props = {
  51 + width: { type: [String, Number], default: '200px' },
  52 + value: { type: String },
  53 + showBtn: { type: Boolean, default: true },
  54 + btnProps: { type: Object as PropType<ButtonProps> },
  55 + btnText: { type: String, default: '' },
  56 + uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> },
  57 + };
  58 +
  59 + export default defineComponent({
  60 + name: 'CropperAvatar',
  61 + components: { CopperModal, Icon },
  62 + props,
  63 + emits: ['update:value', 'change'],
  64 + setup(props, { emit, expose }) {
  65 + const sourceValue = ref(props.value || '');
  66 + const { prefixCls } = useDesign('cropper-avatar');
  67 + const [register, { openModal, closeModal }] = useModal();
  68 + const { createMessage } = useMessage();
  69 + const { t } = useI18n();
  70 +
  71 + const getClass = computed(() => [prefixCls]);
  72 +
  73 + const getWidth = computed(() => `${props.width}`.replace(/px/, '') + 'px');
  74 +
  75 + const getIconWidth = computed(() => parseInt(`${props.width}`.replace(/px/, '')) / 2 + 'px');
  76 +
  77 + const getStyle = computed((): CSSProperties => ({ width: unref(getWidth) }));
  78 +
  79 + const getImageWrapperStyle = computed(
  80 + (): CSSProperties => ({ width: unref(getWidth), height: unref(getWidth) })
  81 + );
  82 +
  83 + watchEffect(() => {
  84 + sourceValue.value = props.value || '';
  85 + });
  86 +
  87 + watch(
  88 + () => sourceValue.value,
  89 + (v: string) => {
  90 + emit('update:value', v);
  91 + }
  92 + );
  93 +
  94 + function handleUploadSuccess(source) {
  95 + sourceValue.value = source.data;
  96 + emit('change', source);
  97 + createMessage.success(t('component.cropper.uploadSuccess'));
  98 + }
  99 +
  100 + expose({ openModal: openModal.bind(null, true), closeModal });
  101 +
  102 + return {
  103 + t,
  104 + prefixCls,
  105 + register,
  106 + openModal,
  107 + getIconWidth,
  108 + sourceValue,
  109 + getClass,
  110 + getImageWrapperStyle,
  111 + getStyle,
  112 + handleUploadSuccess,
  113 + };
  114 + },
  115 + });
  116 +</script>
  117 +
  118 +<style lang="less" scoped>
  119 + @prefix-cls: ~'@{namespace}-cropper-avatar';
  120 +
  121 + .@{prefix-cls} {
  122 + display: inline-block;
  123 + text-align: center;
  124 +
  125 + &-image-wrapper {
  126 + overflow: hidden;
  127 + cursor: pointer;
  128 + background: @component-background;
  129 + border: 1px solid @border-color-base;
  130 + border-radius: 50%;
  131 +
  132 + img {
  133 + width: 100%;
  134 + }
  135 + }
  136 +
  137 + &-image-mask {
  138 + opacity: 0;
  139 + position: absolute;
  140 + width: inherit;
  141 + height: inherit;
  142 + border-radius: inherit;
  143 + border: inherit;
  144 + background: rgba(0, 0, 0, 0.4);
  145 + cursor: pointer;
  146 + -webkit-transition: opacity 0.4s;
  147 + transition: opacity 0.4s;
  148 +
  149 + :deep(svg) {
  150 + margin: auto;
  151 + }
  152 + }
  153 +
  154 + &-image-mask:hover {
  155 + opacity: 40;
  156 + }
  157 +
  158 + &-upload-btn {
  159 + margin: 10px auto;
  160 + }
  161 + }
  162 +</style>
@@ -13,30 +13,9 @@ @@ -13,30 +13,9 @@
13 <div class="text-center cursor-pointer"> 13 <div class="text-center cursor-pointer">
14 <div class="text-left text-lg border-gray-200 p-2 border">个人头像</div> 14 <div class="text-left text-lg border-gray-200 p-2 border">个人头像</div>
15 <div class="flex items-center justify-center mt-4"> 15 <div class="flex items-center justify-center mt-4">
16 - <Upload  
17 - name="avatar"  
18 - list-type="picture-card"  
19 - class="round !flex justify-center items-center"  
20 - :show-upload-list="false"  
21 - :customRequest="customUpload"  
22 - :before-upload="beforeUpload"  
23 - >  
24 - <img  
25 - class="round"  
26 - v-if="personalPicture || headerImg"  
27 - :src="personalPicture || headerImg"  
28 - alt="avatar"  
29 - />  
30 - <div v-else>  
31 - <div>  
32 - <LoadingOutlined class="text-3xl" v-if="loading" />  
33 - <PlusOutlined v-else class="text-3xl" />  
34 - </div>  
35 - </div>  
36 - </Upload> 16 + <CropperAvatar @change="handleChange" :uploadApi="uploadApi" :value="personalPicture" />
37 </div> 17 </div>
38 </div> 18 </div>
39 -  
40 <Description @register="registerDesc" class="mt-8 p-4" /> 19 <Description @register="registerDesc" class="mt-8 p-4" />
41 </div> 20 </div>
42 <div class="ml-4 border border-gray-200"> 21 <div class="ml-4 border border-gray-200">
@@ -49,22 +28,19 @@ @@ -49,22 +28,19 @@
49 </BasicModal> 28 </BasicModal>
50 </template> 29 </template>
51 <script lang="ts"> 30 <script lang="ts">
52 - import { defineComponent, ref, unref } from 'vue'; 31 + import { defineComponent, ref } from 'vue';
53 import { BasicModal, useModalInner } from '/@/components/Modal/index'; 32 import { BasicModal, useModalInner } from '/@/components/Modal/index';
54 import { BasicForm, useForm } from '/@/components/Form/index'; 33 import { BasicForm, useForm } from '/@/components/Form/index';
55 import { formSchema } from './config'; 34 import { formSchema } from './config';
56 import { Description, DescItem, useDescription } from '/@/components/Description/index'; 35 import { Description, DescItem, useDescription } from '/@/components/Description/index';
57 import { uploadApi, personalPut } from '/@/api/personal/index'; 36 import { uploadApi, personalPut } from '/@/api/personal/index';
58 import { useMessage } from '/@/hooks/web/useMessage'; 37 import { useMessage } from '/@/hooks/web/useMessage';
59 - import { Upload } from 'ant-design-vue';  
60 - import { PlusOutlined } from '@ant-design/icons-vue';  
61 import { useUserStore } from '/@/store/modules/user'; 38 import { useUserStore } from '/@/store/modules/user';
62 - import type { FileItem } from '/@/components/Upload/src/typing';  
63 - import { LoadingOutlined } from '@ant-design/icons-vue';  
64 import headerImg from '/@/assets/images/logo.png'; 39 import headerImg from '/@/assets/images/logo.png';
65 import { getMyInfo } from '/@/api/sys/user'; 40 import { getMyInfo } from '/@/api/sys/user';
66 import { UserInfoModel } from '/@/api/sys/model/userModel'; 41 import { UserInfoModel } from '/@/api/sys/model/userModel';
67 import { UserInfo } from '/#/store'; 42 import { UserInfo } from '/#/store';
  43 + import { CropperAvatar } from '/@/components/Cropper';
68 44
69 const schema: DescItem[] = [ 45 const schema: DescItem[] = [
70 { 46 {
@@ -95,7 +71,12 @@ @@ -95,7 +71,12 @@
95 71
96 export default defineComponent({ 72 export default defineComponent({
97 name: 'Index', 73 name: 'Index',
98 - components: { BasicModal, BasicForm, Description, Upload, PlusOutlined, LoadingOutlined }, 74 + components: {
  75 + BasicModal,
  76 + BasicForm,
  77 + Description,
  78 + CropperAvatar,
  79 + },
99 emits: ['refreshPersonal', 'register'], 80 emits: ['refreshPersonal', 'register'],
100 setup(_, { emit }) { 81 setup(_, { emit }) {
101 const loading = ref(false); 82 const loading = ref(false);
@@ -111,31 +92,8 @@ @@ -111,31 +92,8 @@
111 column: 1, 92 column: 1,
112 bordered: true, 93 bordered: true,
113 }); 94 });
114 -  
115 - const customUpload = async ({ file }) => {  
116 - if (beforeUpload(file)) {  
117 - personalPicture.value = '';  
118 - loading.value = true;  
119 - const formData = new FormData();  
120 - formData.append('file', file);  
121 - const response = await uploadApi(formData);  
122 - if (response.fileStaticUri) {  
123 - personalPicture.value = response.fileStaticUri;  
124 - loading.value = false;  
125 - }  
126 - }  
127 - };  
128 -  
129 - const beforeUpload = (file: FileItem) => {  
130 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
131 - if (!isJpgOrPng) {  
132 - createMessage.error('只能上传图片文件!');  
133 - }  
134 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
135 - if (!isLt2M) {  
136 - createMessage.error('图片大小不能超过5MB!');  
137 - }  
138 - return isJpgOrPng && isLt2M; 95 + const handleChange = (e) => {
  96 + personalPicture.value = e.data;
139 }; 97 };
140 98
141 const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({ 99 const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({
@@ -146,7 +104,7 @@ @@ -146,7 +104,7 @@
146 const [registerModal, { closeModal }] = useModalInner(async () => { 104 const [registerModal, { closeModal }] = useModalInner(async () => {
147 const info = await getMyInfo(); 105 const info = await getMyInfo();
148 personalInfo.value = info; 106 personalInfo.value = info;
149 - personalPicture.value = info.avatar; 107 + personalPicture.value = info.avatar || headerImg;
150 setFieldsValue(info); 108 setFieldsValue(info);
151 setDescProps({ data: info }); 109 setDescProps({ data: info });
152 }); 110 });
@@ -157,7 +115,7 @@ @@ -157,7 +115,7 @@
157 const record = await personalPut({ 115 const record = await personalPut({
158 ...value, 116 ...value,
159 id: userInfo.userId, 117 id: userInfo.userId,
160 - avatar: unref(personalPicture), 118 + avatar: personalPicture.value,
161 }); 119 });
162 120
163 userStore.setUserInfo(record as unknown as UserInfo); 121 userStore.setUserInfo(record as unknown as UserInfo);
@@ -171,13 +129,13 @@ @@ -171,13 +129,13 @@
171 personalInfo, 129 personalInfo,
172 registerDesc, 130 registerDesc,
173 personalPicture, 131 personalPicture,
174 - beforeUpload,  
175 - customUpload,  
176 handleSubmit, 132 handleSubmit,
177 registerModal, 133 registerModal,
178 registerForm, 134 registerForm,
179 loading, 135 loading,
180 headerImg, 136 headerImg,
  137 + uploadApi,
  138 + handleChange,
181 }; 139 };
182 }, 140 },
183 }); 141 });
@@ -55,7 +55,9 @@ export const topicTableColumn: BasicColumn[] = [ @@ -55,7 +55,9 @@ export const topicTableColumn: BasicColumn[] = [
55 customRender: ({ text }: { text: any }) => { 55 customRender: ({ text }: { text: any }) => {
56 return h( 56 return h(
57 'span', 57 'span',
  58 +
58 { 59 {
  60 + style: { cursor: 'pointer' },
59 onClick: () => { 61 onClick: () => {
60 handeleCopy(text); 62 handeleCopy(text);
61 }, 63 },
@@ -73,6 +75,7 @@ export const topicTableColumn: BasicColumn[] = [ @@ -73,6 +75,7 @@ export const topicTableColumn: BasicColumn[] = [
73 return h( 75 return h(
74 'span', 76 'span',
75 { 77 {
  78 + style: { cursor: 'pointer' },
76 onClick: () => { 79 onClick: () => {
77 handeleCopy(text); 80 handeleCopy(text);
78 }, 81 },
@@ -180,8 +183,8 @@ export const list = [ @@ -180,8 +183,8 @@ export const list = [
180 { 183 {
181 deviceType: '网关/直连/网关子设备', 184 deviceType: '网关/直连/网关子设备',
182 function: '事件上报', 185 function: '事件上报',
183 - release: 'v1/devices/event/${deviceId}/${identifier}/{$eventType}',  
184 - subscribe: 'v1/devices/event/${deviceId}/${identifier}/{$eventType}', 186 + release: 'v1/devices/event/${deviceId}/${identifier}',
  187 + subscribe: 'v1/devices/event/${deviceId}/${identifier}',
185 platform: '订阅', 188 platform: '订阅',
186 device: '发布', 189 device: '发布',
187 }, 190 },
@@ -6,52 +6,21 @@ @@ -6,52 +6,21 @@
6 <template #logoUpload> 6 <template #logoUpload>
7 <ContentUploadText> 7 <ContentUploadText>
8 <template #uploadImg> 8 <template #uploadImg>
9 - <Upload  
10 - name="avatar"  
11 - list-type="picture-card"  
12 - class="avatar-uploader"  
13 - :show-upload-list="false"  
14 - @preview="handlePreview"  
15 - :customRequest="customUploadLogoPic"  
16 - :before-upload="beforeUploadLogoPic"  
17 - >  
18 - <img v-if="logoPic" class="fill-img" :src="logoPic" alt="avatar" />  
19 - <div v-else>  
20 - <Spin v-if="loading" tip="正在上传中..." />  
21 - <PlusOutlined v-else />  
22 - <div class="ant-upload-text">上传</div>  
23 - </div>  
24 - </Upload> 9 + <CustomUploadComp :imgUrl="logoPic" @setImg="handleSetLogoImgUrl" />
25 </template> 10 </template>
26 <template #uploadText> 11 <template #uploadText>
27 - <div class="box-outline">  
28 - 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB  
29 - </div> 12 + <div class="box-outline"> 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过5M </div>
30 </template> 13 </template>
31 </ContentUploadText> 14 </ContentUploadText>
32 </template> 15 </template>
33 <template #bgUpload> 16 <template #bgUpload>
34 <ContentUploadText> 17 <ContentUploadText>
35 <template #uploadImg> 18 <template #uploadImg>
36 - <Upload  
37 - name="avatar"  
38 - list-type="picture-card"  
39 - class="avatar-uploader"  
40 - :show-upload-list="false"  
41 - :customRequest="customUploadBgPic"  
42 - :before-upload="beforeUploadBgPic"  
43 - >  
44 - <img v-if="bgPic" class="fill-img" :src="bgPic" alt="avatar" />  
45 - <div v-else>  
46 - <Spin v-if="loading1" tip="正在上传中..." />  
47 - <PlusOutlined v-else />  
48 - <div class="ant-upload-text">上传</div>  
49 - </div>  
50 - </Upload> 19 + <CustomUploadComp :imgUrl="bgPic" @setImg="handleSetBgImgUrl" />
51 </template> 20 </template>
52 <template #uploadText> 21 <template #uploadText>
53 <div class="box-outline"> 22 <div class="box-outline">
54 - 支持.PNG、.JPG格式,建议尺寸为1920*1080px,大小不超过2M 23 + 支持.PNG、.JPG格式,建议尺寸为1920*1080px,大小不超过5M
55 </div> 24 </div>
56 </template> 25 </template>
57 </ContentUploadText> 26 </ContentUploadText>
@@ -83,7 +52,7 @@ @@ -83,7 +52,7 @@
83 </template> 52 </template>
84 <template #uploadText> 53 <template #uploadText>
85 <div class="box-outline"> 54 <div class="box-outline">
86 - 支持.PNG、.JPG格式,建议尺寸为800*600px,大小不超过3M 55 + 支持.PNG、.JPG格式,建议尺寸为800*600px,大小不超过5M
87 </div> 56 </div>
88 </template> 57 </template>
89 </ContentUploadText> 58 </ContentUploadText>
@@ -108,15 +77,16 @@ @@ -108,15 +77,16 @@
108 import { defineComponent, ref, unref, onMounted } from 'vue'; 77 import { defineComponent, ref, unref, onMounted } from 'vue';
109 import { BasicForm, useForm } from '/@/components/Form/index'; 78 import { BasicForm, useForm } from '/@/components/Form/index';
110 import { Loading } from '/@/components/Loading/index'; 79 import { Loading } from '/@/components/Loading/index';
111 - import { Card, Upload, Input, Modal, Spin } from 'ant-design-vue'; 80 + import { Card, Upload, Input, Modal } from 'ant-design-vue';
112 import { PlusOutlined } from '@ant-design/icons-vue'; 81 import { PlusOutlined } from '@ant-design/icons-vue';
113 import { schemas } from '../config/AppDraw.config'; 82 import { schemas } from '../config/AppDraw.config';
114 import { FileItem, FileInfo } from '../types/index'; 83 import { FileItem, FileInfo } from '../types/index';
115 - import { logoUpload, bgUpload, resetAppInfo } from '/@/api/oem/index'; 84 + import { bgUpload, resetAppInfo } from '/@/api/oem/index';
116 import { useMessage } from '/@/hooks/web/useMessage'; 85 import { useMessage } from '/@/hooks/web/useMessage';
117 import { getAppDesign, updateAppDesign } from '/@/api/oem/index'; 86 import { getAppDesign, updateAppDesign } from '/@/api/oem/index';
118 import { Authority } from '/@/components/Authority'; 87 import { Authority } from '/@/components/Authority';
119 import ContentUploadText from './ContentUploadText.vue'; 88 import ContentUploadText from './ContentUploadText.vue';
  89 + import { CustomUploadComp } from './customUplaod/index';
120 90
121 export default defineComponent({ 91 export default defineComponent({
122 components: { 92 components: {
@@ -129,7 +99,7 @@ @@ -129,7 +99,7 @@
129 Modal, 99 Modal,
130 Authority, 100 Authority,
131 ContentUploadText, 101 ContentUploadText,
132 - Spin, 102 + CustomUploadComp,
133 }, 103 },
134 setup() { 104 setup() {
135 const loading = ref(false); 105 const loading = ref(false);
@@ -170,59 +140,20 @@ @@ -170,59 +140,20 @@
170 previewVisible.value = true; 140 previewVisible.value = true;
171 }; 141 };
172 142
  143 + const handleSetBgImgUrl = (d) => {
  144 + bgPic.value = d;
  145 + };
  146 +
  147 + const handleSetLogoImgUrl = (d) => {
  148 + logoPic.value = d;
  149 + };
  150 +
173 // logo图片上传 151 // logo图片上传
174 const logoPic = ref(); 152 const logoPic = ref();
175 - async function customUploadLogoPic({ file }) {  
176 - if (beforeUploadLogoPic(file)) {  
177 - logoPic.value = '';  
178 - loading.value = true;  
179 - const formData = new FormData();  
180 - formData.append('file', file);  
181 - const response = await logoUpload(formData);  
182 - if (response.fileStaticUri) {  
183 - logoPic.value = response.fileStaticUri;  
184 - loading.value = false;  
185 - }  
186 - }  
187 - }  
188 - const beforeUploadLogoPic = (file) => {  
189 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
190 - if (!isJpgOrPng) {  
191 - createMessage.error('只能上传图片文件!');  
192 - }  
193 - const isLt2M = (file.size as number) / 1024 < 500;  
194 - if (!isLt2M) {  
195 - createMessage.error('图片大小不能超过500KB!');  
196 - }  
197 - return isJpgOrPng && isLt2M;  
198 - };  
199 153
200 // 登录页背景上传 154 // 登录页背景上传
201 const bgPic = ref(); 155 const bgPic = ref();
202 - async function customUploadBgPic({ file }) {  
203 - if (beforeUploadBgPic(file)) {  
204 - bgPic.value = '';  
205 - loading1.value = true;  
206 - const formData = new FormData();  
207 - formData.append('file', file);  
208 - const response = await bgUpload(formData);  
209 - if (response.fileStaticUri) {  
210 - bgPic.value = response.fileStaticUri;  
211 - loading1.value = false;  
212 - }  
213 - }  
214 - }  
215 - const beforeUploadBgPic = (file) => {  
216 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
217 - if (!isJpgOrPng) {  
218 - createMessage.error('只能上传图片文件!');  
219 - }  
220 - const isLt2M = (file.size as number) / 1024 / 1024 < 2;  
221 - if (!isLt2M) {  
222 - createMessage.error('图片大小不能超过2MB!');  
223 - }  
224 - return isJpgOrPng && isLt2M;  
225 - }; 156 +
226 // 首页轮播图 157 // 首页轮播图
227 const fileList = ref<FileItem[]>([]); 158 const fileList = ref<FileItem[]>([]);
228 async function customUploadHomeSwiper({ file }) { 159 async function customUploadHomeSwiper({ file }) {
@@ -337,10 +268,6 @@ @@ -337,10 +268,6 @@
337 handleUpdateInfo, 268 handleUpdateInfo,
338 handleCancel, 269 handleCancel,
339 handlePreview, 270 handlePreview,
340 - customUploadLogoPic,  
341 - beforeUploadLogoPic,  
342 - customUploadBgPic,  
343 - beforeUploadBgPic,  
344 customUploadHomeSwiper, 271 customUploadHomeSwiper,
345 beforeUploadHomeSwiper, 272 beforeUploadHomeSwiper,
346 handleChange, 273 handleChange,
@@ -351,6 +278,8 @@ @@ -351,6 +278,8 @@
351 loading, 278 loading,
352 loading1, 279 loading1,
353 handleResetInfo, 280 handleResetInfo,
  281 + handleSetBgImgUrl,
  282 + handleSetLogoImgUrl,
354 }; 283 };
355 }, 284 },
356 }); 285 });
@@ -371,9 +300,4 @@ @@ -371,9 +300,4 @@
371 border: 1px dashed #d9d9d9; 300 border: 1px dashed #d9d9d9;
372 text-align: left; 301 text-align: left;
373 } 302 }
374 -  
375 - .fill-img {  
376 - width: 100%;  
377 - height: 100%;  
378 - }  
379 </style> 303 </style>
@@ -6,26 +6,10 @@ @@ -6,26 +6,10 @@
6 <template #logoUpload> 6 <template #logoUpload>
7 <ContentUploadText> 7 <ContentUploadText>
8 <template #uploadImg> 8 <template #uploadImg>
9 - <Upload  
10 - name="avatar"  
11 - list-type="picture-card"  
12 - class="avatar-uploader"  
13 - :show-upload-list="false"  
14 - :customRequest="customUploadLogoPic"  
15 - :before-upload="beforeUploadLogoPic"  
16 - >  
17 - <img class="fill-img" v-if="logoPic" :src="logoPic" alt="avatar" />  
18 - <div v-else>  
19 - <Spin v-if="loading" tip="正在上传中..." />  
20 - <PlusOutlined v-else />  
21 - <div class="ant-upload-text">上传</div>  
22 - </div>  
23 - </Upload> 9 + <CustomUploadComp :imgUrl="logoPic" @setImg="handleSetLogoImgUrl" />
24 </template> 10 </template>
25 <template #uploadText> 11 <template #uploadText>
26 - <div class="box-outline">  
27 - 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB  
28 - </div> 12 + <div class="box-outline"> 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过5M </div>
29 </template> 13 </template>
30 </ContentUploadText> 14 </ContentUploadText>
31 </template> 15 </template>
@@ -61,23 +45,7 @@ @@ -61,23 +45,7 @@
61 <template #bgUpload> 45 <template #bgUpload>
62 <ContentUploadText> 46 <ContentUploadText>
63 <template #uploadImg> 47 <template #uploadImg>
64 - <Upload  
65 - name="avatar"  
66 - list-type="picture-card"  
67 - class="avatar-uploader"  
68 - :show-upload-list="false"  
69 - :customRequest="customUploadBgPic"  
70 - :before-upload="beforeUploadBgPic"  
71 - >  
72 - <img class="fill-img" v-if="bgPic" :src="bgPic" alt="avatar" />  
73 - <div v-else>  
74 - <div>  
75 - <Spin v-if="loading2" tip="正在上传中..." />  
76 - <PlusOutlined v-else />  
77 - <div class="ant-upload-text">上传</div>  
78 - </div>  
79 - </div></Upload  
80 - > 48 + <CustomUploadComp :imgUrl="bgPic" @setImg="handleSetBgImgUrl" />
81 </template> 49 </template>
82 <template #uploadText> 50 <template #uploadText>
83 <div class="box-outline"> 51 <div class="box-outline">
@@ -112,19 +80,13 @@ @@ -112,19 +80,13 @@
112 import { Loading } from '/@/components/Loading/index'; 80 import { Loading } from '/@/components/Loading/index';
113 import { useMessage } from '/@/hooks/web/useMessage'; 81 import { useMessage } from '/@/hooks/web/useMessage';
114 import type { FileItem } from '/@/components/Upload/src/typing'; 82 import type { FileItem } from '/@/components/Upload/src/typing';
115 - import {  
116 - logoUpload,  
117 - iconUpload,  
118 - bgUpload,  
119 - getPlatForm,  
120 - updatePlatForm,  
121 - resetPlateInfo,  
122 - } from '/@/api/oem/index'; 83 + import { iconUpload, getPlatForm, updatePlatForm, resetPlateInfo } from '/@/api/oem/index';
123 import { PlusOutlined } from '@ant-design/icons-vue'; 84 import { PlusOutlined } from '@ant-design/icons-vue';
124 import { useUserStore } from '/@/store/modules/user'; 85 import { useUserStore } from '/@/store/modules/user';
125 import { createLocalStorage } from '/@/utils/cache/index'; 86 import { createLocalStorage } from '/@/utils/cache/index';
126 import { Authority } from '/@/components/Authority'; 87 import { Authority } from '/@/components/Authority';
127 import ContentUploadText from './ContentUploadText.vue'; 88 import ContentUploadText from './ContentUploadText.vue';
  89 + import { CustomUploadComp } from './customUplaod/index';
128 90
129 export default defineComponent({ 91 export default defineComponent({
130 components: { 92 components: {
@@ -137,6 +99,7 @@ @@ -137,6 +99,7 @@
137 Authority, 99 Authority,
138 ContentUploadText, 100 ContentUploadText,
139 Spin, 101 Spin,
  102 + CustomUploadComp,
140 }, 103 },
141 setup() { 104 setup() {
142 const loading = ref(false); 105 const loading = ref(false);
@@ -163,30 +126,13 @@ @@ -163,30 +126,13 @@
163 const logoPic = ref(); 126 const logoPic = ref();
164 const iconPic = ref(); 127 const iconPic = ref();
165 const bgPic = ref(); 128 const bgPic = ref();
166 - // logo图片上传  
167 - async function customUploadLogoPic({ file }) {  
168 - if (beforeUploadLogoPic(file)) {  
169 - logoPic.value = '';  
170 - loading.value = true;  
171 - const formData = new FormData();  
172 - formData.append('file', file);  
173 - const response = await logoUpload(formData);  
174 - if (response.fileStaticUri) {  
175 - logoPic.value = response.fileStaticUri;  
176 - loading.value = false;  
177 - }  
178 - }  
179 - }  
180 - const beforeUploadLogoPic = (file: FileItem) => {  
181 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
182 - if (!isJpgOrPng) {  
183 - createMessage.error('只能上传图片文件!');  
184 - }  
185 - const isLt2M = (file.size as number) / 1024 < 500;  
186 - if (!isLt2M) {  
187 - createMessage.error('图片大小不能超过500KB!');  
188 - }  
189 - return isJpgOrPng && isLt2M; 129 +
  130 + const handleSetBgImgUrl = (d) => {
  131 + bgPic.value = d;
  132 + };
  133 +
  134 + const handleSetLogoImgUrl = (d) => {
  135 + logoPic.value = d;
190 }; 136 };
191 // Icon上传 137 // Icon上传
192 async function customUploadIconPic({ file }) { 138 async function customUploadIconPic({ file }) {
@@ -213,32 +159,6 @@ @@ -213,32 +159,6 @@
213 } 159 }
214 return isJpgOrPng && isLt2M; 160 return isJpgOrPng && isLt2M;
215 }; 161 };
216 - // 登录页背景上传  
217 - async function customUploadBgPic({ file }) {  
218 - if (beforeUploadBgPic(file)) {  
219 - bgPic.value = '';  
220 - loading2.value = true;  
221 - const formData = new FormData();  
222 - formData.append('file', file);  
223 - const response = await bgUpload(formData);  
224 - if (response.fileStaticUri) {  
225 - bgPic.value = response.fileStaticUri;  
226 - loading2.value = false;  
227 - }  
228 - }  
229 - }  
230 - const beforeUploadBgPic = (file: FileItem) => {  
231 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
232 - if (!isJpgOrPng) {  
233 - createMessage.error('只能上传图片文件!');  
234 - }  
235 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
236 - if (!isLt2M) {  
237 - createMessage.error('图片大小不能超过5MB!');  
238 - }  
239 - return isJpgOrPng && isLt2M;  
240 - };  
241 -  
242 // 更新 162 // 更新
243 const handleUpdateInfo = async () => { 163 const handleUpdateInfo = async () => {
244 try { 164 try {
@@ -296,18 +216,16 @@ @@ -296,18 +216,16 @@
296 logoPic, 216 logoPic,
297 iconPic, 217 iconPic,
298 bgPic, 218 bgPic,
299 - customUploadLogoPic,  
300 - beforeUploadLogoPic,  
301 customUploadIconPic, 219 customUploadIconPic,
302 beforeUploadIconPic, 220 beforeUploadIconPic,
303 - customUploadBgPic,  
304 - beforeUploadBgPic,  
305 compState, 221 compState,
306 handleUpdateInfo, 222 handleUpdateInfo,
307 loading, 223 loading,
308 loading1, 224 loading1,
309 loading2, 225 loading2,
310 handleResetInfo, 226 handleResetInfo,
  227 + handleSetBgImgUrl,
  228 + handleSetLogoImgUrl,
311 }; 229 };
312 }, 230 },
313 }); 231 });
@@ -5,21 +5,7 @@ @@ -5,21 +5,7 @@
5 <template #qrcode> 5 <template #qrcode>
6 <ContentUploadText> 6 <ContentUploadText>
7 <template #uploadImg> 7 <template #uploadImg>
8 - <Upload  
9 - name="avatar"  
10 - list-type="picture-card"  
11 - class="avatar-uploader"  
12 - :show-upload-list="false"  
13 - :customRequest="customUploadqrcodePic"  
14 - :before-upload="beforeUploadqrcodePic"  
15 - >  
16 - <img class="fill-img" v-if="qrcodePic" :src="qrcodePic" alt="avatar" />  
17 - <div v-else>  
18 - <Spin v-if="loading" tip="正在上传中..." />  
19 - <PlusOutlined v-else />  
20 - <div class="ant-upload-text">上传</div>  
21 - </div></Upload  
22 - > 8 + <CustomUploadComp :imgUrl="qrcodePic" @setImg="handleSetCodeImgUrl" />
23 </template> 9 </template>
24 <template #uploadText> 10 <template #uploadText>
25 <div class="box-outline"> 支持.PNG、.JPG格式,建议尺寸为300*300px,大小不超过5M </div> 11 <div class="box-outline"> 支持.PNG、.JPG格式,建议尺寸为300*300px,大小不超过5M </div>
@@ -46,7 +32,7 @@ @@ -46,7 +32,7 @@
46 32
47 <script lang="ts"> 33 <script lang="ts">
48 import { defineComponent, onMounted, ref, computed } from 'vue'; 34 import { defineComponent, onMounted, ref, computed } from 'vue';
49 - import { Card, Upload, Spin } from 'ant-design-vue'; 35 + import { Card } from 'ant-design-vue';
50 import { BasicForm, useForm } from '/@/components/Form/index'; 36 import { BasicForm, useForm } from '/@/components/Form/index';
51 import { schemas, provSchemas } from '../config/enterPriseInfo.config'; 37 import { schemas, provSchemas } from '../config/enterPriseInfo.config';
52 import { getAreaList, getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index'; 38 import { getAreaList, getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index';
@@ -54,25 +40,21 @@ @@ -54,25 +40,21 @@
54 import { useMessage } from '/@/hooks/web/useMessage'; 40 import { useMessage } from '/@/hooks/web/useMessage';
55 import { useUserStore } from '/@/store/modules/user'; 41 import { useUserStore } from '/@/store/modules/user';
56 import { createLocalStorage } from '/@/utils/cache'; 42 import { createLocalStorage } from '/@/utils/cache';
57 - import { PlusOutlined } from '@ant-design/icons-vue';  
58 - import { qrcodeUpload } from '/@/api/oem/index';  
59 - import type { FileItem } from '/@/components/Upload/src/typing';  
60 import type { CityItem, Code } from '../types'; 43 import type { CityItem, Code } from '../types';
61 import { Authority } from '/@/components/Authority'; 44 import { Authority } from '/@/components/Authority';
62 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 45 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
63 import { getAuthCache } from '/@/utils/auth'; 46 import { getAuthCache } from '/@/utils/auth';
64 import ContentUploadText from './ContentUploadText.vue'; 47 import ContentUploadText from './ContentUploadText.vue';
  48 + import { CustomUploadComp } from './customUplaod/index';
65 49
66 export default defineComponent({ 50 export default defineComponent({
67 components: { 51 components: {
68 Card, 52 Card,
69 BasicForm, 53 BasicForm,
70 Loading, 54 Loading,
71 - Upload,  
72 - PlusOutlined,  
73 Authority, 55 Authority,
74 ContentUploadText, 56 ContentUploadText,
75 - Spin, 57 + CustomUploadComp,
76 }, 58 },
77 setup() { 59 setup() {
78 const userInfo: any = getAuthCache(USER_INFO_KEY); 60 const userInfo: any = getAuthCache(USER_INFO_KEY);
@@ -119,30 +101,8 @@ @@ -119,30 +101,8 @@
119 const { createMessage } = useMessage(); 101 const { createMessage } = useMessage();
120 102
121 const qrcodePic = ref(); 103 const qrcodePic = ref();
122 - const customUploadqrcodePic = async ({ file }) => {  
123 - clearValidate('qrcode');  
124 - if (beforeUploadqrcodePic(file)) {  
125 - qrcodePic.value = '';  
126 - loading.value = true;  
127 - const formData = new FormData();  
128 - formData.append('file', file);  
129 - const response = await qrcodeUpload(formData);  
130 - if (response.fileStaticUri) {  
131 - qrcodePic.value = response.fileStaticUri;  
132 - loading.value = false;  
133 - }  
134 - }  
135 - };  
136 - const beforeUploadqrcodePic = (file: FileItem) => {  
137 - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';  
138 - if (!isJpgOrPng) {  
139 - createMessage.error('只能上传图片文件!');  
140 - }  
141 - const isLt2M = (file.size as number) / 1024 / 1024 < 5;  
142 - if (!isLt2M) {  
143 - createMessage.error('图片大小不能超过5MB!');  
144 - }  
145 - return isJpgOrPng && isLt2M; 104 + const handleSetCodeImgUrl = (d) => {
  105 + qrcodePic.value = d;
146 }; 106 };
147 // 更新 107 // 更新
148 const handleUpdateInfo = async () => { 108 const handleUpdateInfo = async () => {
@@ -372,11 +332,10 @@ @@ -372,11 +332,10 @@
372 compState, 332 compState,
373 qrcodePic, 333 qrcodePic,
374 handleUpdateInfo, 334 handleUpdateInfo,
375 - customUploadqrcodePic,  
376 - beforeUploadqrcodePic,  
377 registerCustomForm, 335 registerCustomForm,
378 loading, 336 loading,
379 isWhereAdmin, 337 isWhereAdmin,
  338 + handleSetCodeImgUrl,
380 }; 339 };
381 }, 340 },
382 }); 341 });
  1 +<script setup name="CustomUploadComp" lang="ts">
  2 + import { PlusOutlined } from '@ant-design/icons-vue';
  3 + import { Upload, Spin } from 'ant-design-vue';
  4 + import { ref, watchEffect } from 'vue';
  5 + import { useUpload } from './hooks/useUploadFile.hook';
  6 + import { logoUpload } from '/@/api/oem';
  7 +
  8 + const props = withDefaults(
  9 + defineProps<{
  10 + imgUrl: string;
  11 + }>(),
  12 + {
  13 + imgUrl: '',
  14 + }
  15 + );
  16 + const emit = defineEmits(['setImg']);
  17 +
  18 + const { beforeUploadVerify } = useUpload();
  19 +
  20 + const uploadLoading = ref(false);
  21 +
  22 + const uploadImgUrl = ref('');
  23 +
  24 + //上传图片接口
  25 + const customUpload = async ({ file }) => {
  26 + try {
  27 + if (beforeUploadVerify(file)) {
  28 + uploadImgUrl.value = '';
  29 + uploadLoading.value = true;
  30 + const formData = new FormData();
  31 + formData.append('file', file);
  32 + const response = await logoUpload(formData);
  33 + if (response.fileStaticUri) {
  34 + uploadImgUrl.value = response.fileStaticUri;
  35 + emit('setImg', uploadImgUrl.value);
  36 + }
  37 + }
  38 + } finally {
  39 + uploadLoading.value = false;
  40 + }
  41 + };
  42 +
  43 + watchEffect(() => {
  44 + init();
  45 + });
  46 + function init() {
  47 + if (!props.imgUrl) uploadImgUrl.value = '';
  48 + uploadImgUrl.value = props.imgUrl;
  49 + }
  50 +</script>
  51 +
  52 +<template>
  53 + <div>
  54 + <Upload
  55 + name="avatar"
  56 + list-type="picture-card"
  57 + class="avatar-uploader"
  58 + :show-upload-list="false"
  59 + :customRequest="customUpload"
  60 + :before-upload="beforeUploadVerify"
  61 + >
  62 + <img v-if="uploadImgUrl" class="fill-img" :src="uploadImgUrl" alt="avatar" />
  63 + <div v-else>
  64 + <Spin v-if="uploadLoading" tip="正在上传中..." />
  65 + <PlusOutlined v-else />
  66 + <div class="ant-upload-text">上传</div>
  67 + </div>
  68 + </Upload>
  69 + </div>
  70 +</template>
  71 +
  72 +<style lang="less" scoped>
  73 + .fill-img {
  74 + width: 100%;
  75 + height: 100%;
  76 + }
  77 +</style>
  1 +import { useMessage } from '/@/hooks/web/useMessage';
  2 +
  3 +const { createMessage } = useMessage();
  4 +
  5 +export const useUpload = () => {
  6 + //验证图片类型和大小
  7 + const beforeUploadVerify = ({ type, size }) => {
  8 + const isJpgOrPng = type === 'image/jpeg' || type === 'image/png';
  9 + if (!isJpgOrPng) {
  10 + createMessage.error('只能上传图片文件!');
  11 + }
  12 + const limitImgSize = (size as number) / 1024 / 1024 < 5;
  13 + if (!limitImgSize) {
  14 + createMessage.error('图片大小不能超过5MB!');
  15 + }
  16 + return isJpgOrPng && limitImgSize;
  17 + };
  18 + return {
  19 + beforeUploadVerify,
  20 + };
  21 +};
  1 +import CustomUploadComp from './CustomUploadComp.vue';
  2 +export { CustomUploadComp };