mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 10:18:42 +08:00 
			
		
		
		
	feat: uploadImg 组件
This commit is contained in:
		| @@ -14,7 +14,7 @@ const { variables } = useDesign() | |||||||
| const appStore = useAppStore() | const appStore = useAppStore() | ||||||
|  |  | ||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   size: propTypes.oneOf<ElementPlusSize[]>(['default', 'small', 'large']).def('default') |   size: propTypes.oneOf<ElementPlusSize>(['default', 'small', 'large']).def('default') | ||||||
| }) | }) | ||||||
|  |  | ||||||
| provide('configGlobal', props) | provide('configGlobal', props) | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								yudao-ui-admin-vue3/src/components/UploadFile/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								yudao-ui-admin-vue3/src/components/UploadFile/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | import UploadImg from './src/UploadImg.vue' | ||||||
|  |  | ||||||
|  | export { UploadImg } | ||||||
							
								
								
									
										169
									
								
								yudao-ui-admin-vue3/src/components/UploadFile/src/UploadImg.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								yudao-ui-admin-vue3/src/components/UploadFile/src/UploadImg.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | |||||||
|  | <template> | ||||||
|  |   <el-upload | ||||||
|  |     ref="uploadRef" | ||||||
|  |     :multiple="limit > 1" | ||||||
|  |     name="file" | ||||||
|  |     list-type="picture-card" | ||||||
|  |     v-model:file-list="fileList" | ||||||
|  |     :show-file-list="true" | ||||||
|  |     :action="updateUrl" | ||||||
|  |     :headers="uploadHeaders" | ||||||
|  |     :limit="limit" | ||||||
|  |     :before-upload="beforeUpload" | ||||||
|  |     :on-exceed="handleExceed" | ||||||
|  |     :on-success="handleFileSuccess" | ||||||
|  |     :on-error="excelUploadError" | ||||||
|  |     :on-remove="handleRemove" | ||||||
|  |     :on-preview="handlePictureCardPreview" | ||||||
|  |     :class="{ hide: fileList.length >= limit }" | ||||||
|  |   > | ||||||
|  |     <Icon icon="ep:upload-filled" /> | ||||||
|  |   </el-upload> | ||||||
|  |   <!-- 文件列表 --> | ||||||
|  |   <Dialog v-model="dialogVisible" title="预览" width="800" append-to-body> | ||||||
|  |     <img :src="dialogImageUrl" style="display: block; max-width: 100%; margin: 0 auto" /> | ||||||
|  |   </Dialog> | ||||||
|  | </template> | ||||||
|  | <script setup lang="ts"> | ||||||
|  | import { ref, watch } from 'vue' | ||||||
|  | import { useMessage } from '@/hooks/web/useMessage' | ||||||
|  | import { propTypes } from '@/utils/propTypes' | ||||||
|  | import { getAccessToken, getTenantId } from '@/utils/auth' | ||||||
|  | import { ElUpload, UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from 'element-plus' | ||||||
|  |  | ||||||
|  | const message = useMessage() // 消息弹窗 | ||||||
|  | const emit = defineEmits(['input']) | ||||||
|  |  | ||||||
|  | const props = defineProps({ | ||||||
|  |   imgs: propTypes.oneOfType([String, Object, Array]), | ||||||
|  |   title: propTypes.string.def('图片上传'), | ||||||
|  |   updateUrl: propTypes.string.def(import.meta.env.VITE_UPLOAD_URL), | ||||||
|  |   fileType: propTypes.array.def(['jpg', 'png', 'gif', 'jpeg']), // 文件类型, 例如['png', 'jpg', 'jpeg'] | ||||||
|  |   fileSize: propTypes.number.def(5), // 大小限制(MB) | ||||||
|  |   limit: propTypes.number.def(1), // 数量限制 | ||||||
|  |   isShowTip: propTypes.bool.def(false) // 是否显示提示 | ||||||
|  | }) | ||||||
|  | // ========== 上传相关 ========== | ||||||
|  | const uploadRef = ref<UploadInstance>() | ||||||
|  | const uploadList = ref<UploadUserFile[]>([]) | ||||||
|  | const fileList = ref<UploadUserFile[]>([]) | ||||||
|  | const uploadNumber = ref<number>(0) | ||||||
|  | const dialogImageUrl = ref() | ||||||
|  | const dialogVisible = ref(false) | ||||||
|  | const uploadHeaders = ref({ | ||||||
|  |   Authorization: 'Bearer ' + getAccessToken(), | ||||||
|  |   'tenant-id': getTenantId() | ||||||
|  | }) | ||||||
|  | watch( | ||||||
|  |   () => props.imgs, | ||||||
|  |   (val) => { | ||||||
|  |     if (val) { | ||||||
|  |       // 首先将值转为数组, 当只穿了一个图片时,会报map方法错误 | ||||||
|  |       const list = Array.isArray(props.imgs) | ||||||
|  |         ? props.imgs | ||||||
|  |         : Array.isArray(props.imgs?.split(',')) | ||||||
|  |         ? props.imgs?.split(',') | ||||||
|  |         : Array.of(props.imgs) | ||||||
|  |       // 然后将数组转为对象数组 | ||||||
|  |       fileList.value = list.map((item) => { | ||||||
|  |         if (typeof item === 'string') { | ||||||
|  |           // edit by 芋道源码 | ||||||
|  |           item = { name: item, url: item } | ||||||
|  |         } | ||||||
|  |         return item | ||||||
|  |       }) | ||||||
|  |     } else { | ||||||
|  |       fileList.value = [] | ||||||
|  |       return [] | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     deep: true, | ||||||
|  |     immediate: true | ||||||
|  |   } | ||||||
|  | ) | ||||||
|  | // 文件上传之前判断 | ||||||
|  | const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => { | ||||||
|  |   let fileExtension = '' | ||||||
|  |   if (file.name.lastIndexOf('.') > -1) { | ||||||
|  |     fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1) | ||||||
|  |   } | ||||||
|  |   const isImg = props.fileType.some((type: string) => { | ||||||
|  |     if (file.type.indexOf(type) > -1) return true | ||||||
|  |     return !!(fileExtension && fileExtension.indexOf(type) > -1) | ||||||
|  |   }) | ||||||
|  |   const isLimit = file.size < props.fileSize * 1024 * 1024 | ||||||
|  |   if (!isImg) { | ||||||
|  |     message.error(`文件格式不正确, 请上传${props.fileType.join('/')}格式!`) | ||||||
|  |     return false | ||||||
|  |   } | ||||||
|  |   if (!isLimit) { | ||||||
|  |     message.error(`上传文件大小不能超过${props.fileSize}MB!`) | ||||||
|  |     return false | ||||||
|  |   } | ||||||
|  |   message.success('正在上传文件,请稍候...') | ||||||
|  |   uploadNumber.value++ | ||||||
|  | } | ||||||
|  | // 处理上传的文件发生变化 | ||||||
|  | // const handleFileChange = (uploadFile: UploadFile): void => { | ||||||
|  | //   uploadRef.value.data.path = uploadFile.name | ||||||
|  | // } | ||||||
|  | // 文件上传成功 | ||||||
|  | const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => { | ||||||
|  |   message.success('上传成功') | ||||||
|  |   console.info(uploadList.value) | ||||||
|  |   console.info(fileList.value) | ||||||
|  |   uploadList.value.push({ name: res.data, url: res.data }) | ||||||
|  |   if (uploadList.value.length == uploadNumber.value) { | ||||||
|  |     fileList.value = fileList.value.concat(uploadList.value) | ||||||
|  |     uploadList.value = [] | ||||||
|  |     uploadNumber.value = 0 | ||||||
|  |     emit('input', listToString(fileList.value)) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | // 文件数超出提示 | ||||||
|  | const handleExceed: UploadProps['onExceed'] = (): void => { | ||||||
|  |   message.error(`上传文件数量不能超过${props.limit}个!`) | ||||||
|  | } | ||||||
|  | // 上传错误提示 | ||||||
|  | const excelUploadError: UploadProps['onError'] = (): void => { | ||||||
|  |   message.error('导入数据失败,请您重新上传!') | ||||||
|  | } | ||||||
|  | // 删除上传文件 | ||||||
|  | const handleRemove = (file) => { | ||||||
|  |   const findex = fileList.value.map((f) => f.name).indexOf(file.name) | ||||||
|  |   if (findex > -1) { | ||||||
|  |     fileList.value.splice(findex, 1) | ||||||
|  |     emit('input', listToString(fileList.value)) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | // 对象转成指定字符串分隔 | ||||||
|  | const listToString = (list: UploadUserFile[], separator?: string) => { | ||||||
|  |   let strs = '' | ||||||
|  |   separator = separator || ',' | ||||||
|  |   for (let i in list) { | ||||||
|  |     strs += list[i].url + separator | ||||||
|  |   } | ||||||
|  |   return strs != '' ? strs.substr(0, strs.length - 1) : '' | ||||||
|  | } | ||||||
|  | // 预览 | ||||||
|  | const handlePictureCardPreview: UploadProps['onPreview'] = (file) => { | ||||||
|  |   dialogImageUrl.value = file.url | ||||||
|  |   dialogVisible.value = true | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | // .el-upload--picture-card 控制加号部分 | ||||||
|  | :deep(.hide .el-upload--picture-card) { | ||||||
|  |   display: none; | ||||||
|  | } | ||||||
|  | // 去掉动画效果 | ||||||
|  | :deep(.el-list-enter-active, .el-list-leave-active) { | ||||||
|  |   transition: all 0s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | :deep(.el-list-enter, .el-list-leave-active) { | ||||||
|  |   opacity: 0; | ||||||
|  |   transform: translateY(0); | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -12,7 +12,6 @@ export const rules = reactive({ | |||||||
|   clientId: [required], |   clientId: [required], | ||||||
|   secret: [required], |   secret: [required], | ||||||
|   name: [required], |   name: [required], | ||||||
|   logo: [required], |  | ||||||
|   status: [required], |   status: [required], | ||||||
|   accessTokenValiditySeconds: [required], |   accessTokenValiditySeconds: [required], | ||||||
|   refreshTokenValiditySeconds: [required], |   refreshTokenValiditySeconds: [required], | ||||||
|   | |||||||
| @@ -61,7 +61,11 @@ | |||||||
|       v-if="['create', 'update'].includes(actionType)" |       v-if="['create', 'update'].includes(actionType)" | ||||||
|       :schema="allSchemas.formSchema" |       :schema="allSchemas.formSchema" | ||||||
|       :rules="rules" |       :rules="rules" | ||||||
|     /> |     > | ||||||
|  |       <template #logo> | ||||||
|  |         <UploadImg :imgs="uploadLogo" :limit="1" /> | ||||||
|  |       </template> | ||||||
|  |     </Form> | ||||||
|     <!-- 表单:详情 --> |     <!-- 表单:详情 --> | ||||||
|     <Descriptions |     <Descriptions | ||||||
|       v-if="actionType === 'detail'" |       v-if="actionType === 'detail'" | ||||||
| @@ -138,6 +142,7 @@ import { useMessage } from '@/hooks/web/useMessage' | |||||||
| import { useVxeGrid } from '@/hooks/web/useVxeGrid' | import { useVxeGrid } from '@/hooks/web/useVxeGrid' | ||||||
| import { VxeGridInstance } from 'vxe-table' | import { VxeGridInstance } from 'vxe-table' | ||||||
| import { FormExpose } from '@/components/Form' | import { FormExpose } from '@/components/Form' | ||||||
|  | import { UploadImg } from '@/components/UploadFile' | ||||||
| // 业务相关的 import | // 业务相关的 import | ||||||
| import * as ClientApi from '@/api/system/oauth2/client' | import * as ClientApi from '@/api/system/oauth2/client' | ||||||
| import { rules, allSchemas } from './client.data' | import { rules, allSchemas } from './client.data' | ||||||
| @@ -159,7 +164,7 @@ const actionType = ref('') // 操作按钮的类型 | |||||||
| const actionLoading = ref(false) // 按钮 Loading | const actionLoading = ref(false) // 按钮 Loading | ||||||
| const formRef = ref<FormExpose>() // 表单 Ref | const formRef = ref<FormExpose>() // 表单 Ref | ||||||
| const detailRef = ref() // 详情 Ref | const detailRef = ref() // 详情 Ref | ||||||
|  | const uploadLogo = ref('') | ||||||
| // 设置标题 | // 设置标题 | ||||||
| const setDialogTile = (type: string) => { | const setDialogTile = (type: string) => { | ||||||
|   dialogTitle.value = t('action.' + type) |   dialogTitle.value = t('action.' + type) | ||||||
| @@ -169,6 +174,7 @@ const setDialogTile = (type: string) => { | |||||||
|  |  | ||||||
| // 新增操作 | // 新增操作 | ||||||
| const handleCreate = () => { | const handleCreate = () => { | ||||||
|  |   uploadLogo.value = '' | ||||||
|   setDialogTile('create') |   setDialogTile('create') | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -177,6 +183,7 @@ const handleUpdate = async (rowId: number) => { | |||||||
|   setDialogTile('update') |   setDialogTile('update') | ||||||
|   // 设置数据 |   // 设置数据 | ||||||
|   const res = await ClientApi.getOAuth2ClientApi(rowId) |   const res = await ClientApi.getOAuth2ClientApi(rowId) | ||||||
|  |   uploadLogo.value = res.logo | ||||||
|   unref(formRef)?.setValues(res) |   unref(formRef)?.setValues(res) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -202,6 +209,7 @@ const submitForm = async () => { | |||||||
|       // 提交请求 |       // 提交请求 | ||||||
|       try { |       try { | ||||||
|         const data = unref(formRef)?.formModel as ClientApi.OAuth2ClientVO |         const data = unref(formRef)?.formModel as ClientApi.OAuth2ClientVO | ||||||
|  |         data.logo = uploadLogo.value | ||||||
|         if (actionType.value === 'create') { |         if (actionType.value === 'create') { | ||||||
|           await ClientApi.createOAuth2ClientApi(data) |           await ClientApi.createOAuth2ClientApi(data) | ||||||
|           message.success(t('common.createSuccess')) |           message.success(t('common.createSuccess')) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 xingyu4j
					xingyu4j