Commit 99def7931afd6f6c9797422d6a4a5fcc89b458ea
Merge branch 'local_dev_ft' into 'main'
pref:优化产品Topic列表 移除不需要的文字;优化个人头像上传头像使用自带组件 See merge request yunteng/thingskit-front!491
Showing
10 changed files
with
334 additions
and
464 deletions
| @@ -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 | +}; |