UNPKG

yanzhen-design-vue

Version:

394 lines (393 loc) 12.3 kB
import { useModel, ref, reactive, unref, onMounted, onUnmounted, computed } from "vue"; import { useDynamicProps, createWatcher } from "@yanzhen-libs/utils-vue"; import { isString, mergeWith, pick, isFunction, flattenDeep } from "lodash-es"; import { isEmptyValue, isEmptyObject, generateObjId } from "@yanzhen-libs/utils"; import { isImageUrl } from "ant-design-vue/es/upload/utils"; import { uploadImageType } from "../constants/listType.mjs"; import { getBase64, getFileExtension } from "./utils.mjs"; function handleFileId(file, defaultValue) { var _a, _b, _c, _d; const url = (file == null ? void 0 : file.url) ?? ((_a = file == null ? void 0 : file.originInfo) == null ? void 0 : _a.url) ?? ((_b = file == null ? void 0 : file.originInfo) == null ? void 0 : _b.fileAddress); if (!isEmptyValue(url) && isString(url) && !url.startsWith("data:")) { try { const key = "./file/get/"; if (url.includes(key)) { const id = url.split(key)[1].split("/")[0]; if (!isEmptyValue(id)) return id; } } catch { } } if (!isEmptyValue(file == null ? void 0 : file.uid)) return file.uid; if (!isEmptyValue((_c = file == null ? void 0 : file.originFileObj) == null ? void 0 : _c.uid)) return (_d = file == null ? void 0 : file.originFileObj) == null ? void 0 : _d.uid; return url ?? defaultValue; } function isFileObject(file) { switch (true) { case file instanceof File: return true; case typeof file !== "object": case isEmptyValue(file): return false; } return false; } function handleFileUrl(file, options) { if (isString(file)) { return file; } if (isFileObject(file)) { return (file == null ? void 0 : file.thumbUrl) ?? (file == null ? void 0 : file.url); } const originFileObj = file.originFileObj; const originInfo = file.originInfo; const response = file.response; switch (true) { case (!isEmptyObject(response) && /^https?:\/\//i.test(response == null ? void 0 : response.url)): return response.url; case (!isEmptyValue(response) && /^https?:\/\//i.test(response)): return response; case (!isEmptyObject(originInfo) && !isEmptyValue(originInfo == null ? void 0 : originInfo.url)): return originInfo == null ? void 0 : originInfo.url; case (!isEmptyObject(originInfo) && !isEmptyValue(originInfo == null ? void 0 : originInfo.fileAddress)): return originInfo == null ? void 0 : originInfo.fileAddress; case isFileObject(originFileObj): if (!(file == null ? void 0 : file.thumbUrl)) { getBase64(originFileObj).then((url) => { file.thumbUrl = url; }).catch((e) => e); } return file == null ? void 0 : file.thumbUrl; default: return (file == null ? void 0 : file.url) ?? (file == null ? void 0 : file.thumbUrl); } } function handleFileUid(file, options) { if (isString(file)) { return handleFileId({ url: file }, generateObjId({ url: file })); } if (isFileObject(file)) { return file.uid; } return handleFileId(file, generateObjId({ url: file.url })); } function handleFileStatus(file, options) { if (isString(file)) { return "done"; } if (isFileObject(file)) { return file.status ?? "uploading"; } const url = handleFileUrl(file); switch (true) { case (url && url.startsWith("http")): return "done"; } return (file == null ? void 0 : file.status) ?? "done"; } const FileInfoCache = {}; function handleStrFileInfo(file, options) { var _a; if (FileInfoCache[file]) return { ...FileInfoCache[file] }; const fileInfo = {}; fileInfo.url = file; fileInfo.uid = handleFileUid(file); fileInfo.status = "done"; if (file.startsWith("data:")) { fileInfo.thumbUrl = file; fileInfo.type = (_a = file.split(";")[0]) == null ? void 0 : _a.replace("data:", ""); fileInfo.isImage = isImageUrl(fileInfo); } else { const names = file.split("?")[0].split("/"); let name = names[names.length - 1]; const ext = getFileExtension(name); if (isString(name)) { if (name.endsWith(`.${ext}`)) { name = name.replace(`.${ext}`, ""); } fileInfo.name = decodeURIComponent(name); } fileInfo.isImage = isImageUrl(fileInfo); fileInfo.type = fileInfo.isImage ? `image/${ext}` : `.${ext}`; } FileInfoCache[file] = { ...fileInfo }; return fileInfo; } function handleFileIsImage(file, options) { if (isString(file)) { return handleStrFileInfo(file).isImage; } return isImageUrl(file); } function handleFileName(file, options) { var _a; if (isString(file)) { file = handleStrFileInfo(file); } if (isFileObject(file)) { return file.name; } const name = ((_a = file == null ? void 0 : file.originFileObj) == null ? void 0 : _a.name) ?? file.name ?? file.fileName; if (!name && (file == null ? void 0 : file.url)) { return handleStrFileInfo(file.url).name; } return name; } function handleFileType(file, options) { var _a; if (isString(file)) { file = handleStrFileInfo(file); } if (isFileObject(file)) { return file.type; } let type = ((_a = file == null ? void 0 : file.originFileObj) == null ? void 0 : _a.type) ?? file.type; if (!type && (file == null ? void 0 : file.thumbUrl)) { type = handleStrFileInfo(file == null ? void 0 : file.thumbUrl).type; } if (!type && (file == null ? void 0 : file.url)) { type = handleStrFileInfo(file.url).type; } if (!type && (file == null ? void 0 : file.name)) { type = handleStrFileInfo(file == null ? void 0 : file.name).type; } return type; } function handleFilePercent(file, options) { var _a; if (isString(file)) { return 100; } const percent = options == null ? void 0 : options.percent; if (isFileObject(file)) { return (percent == null ? void 0 : percent[file.uid]) ?? file.percent ?? 0; } return (percent == null ? void 0 : percent[file.uid]) ?? ((_a = file == null ? void 0 : file.originFileObj) == null ? void 0 : _a.percent) ?? file.percent ?? 0; } var FileInfoFlag = /* @__PURE__ */ ((FileInfoFlag2) => { FileInfoFlag2["IS_FILE_INFO"] = "__v_file_info"; return FileInfoFlag2; })(FileInfoFlag || {}); function handleFileInfo(file, options) { const info = { uid: handleFileUid, url: handleFileUrl, name: handleFileName, type: handleFileType, isImage: handleFileIsImage, status: handleFileStatus, percent: handleFilePercent }; let fileInfo = Object.keys(info).reduce((prev, key) => { prev[key] = void 0; return prev; }, {}); if (isString(file)) { mergeWith(fileInfo, handleStrFileInfo(file)); } else { if (isFileObject(file)) { fileInfo = pick( file, "uid", "type", "size", "name", "fileName", "lastModified", "lastModifiedDate", "url", "status", "percent", "thumbUrl", "crossOrigin", "response" ); fileInfo.originFileObj = file; } else { if (file[ "__v_file_info" /* IS_FILE_INFO */ ]) return file; fileInfo = file; } for (const [prop, func] of Object.entries(info)) { const value = fileInfo[prop]; if (isEmptyValue(value) && isFunction(func)) { fileInfo[prop] = func(fileInfo, options); } } } return new Proxy(fileInfo, { get(target, p, receiver) { if (p === "__v_file_info") { return true; } if (isString(p) && Object.keys(info).includes(p)) { const func = info[p]; if (isFunction(func)) { target[p] = func(target, { ...options, actionType: "get" }); } } return Reflect.get(target, p, receiver); }, set(target, p, newValue, receiver) { if (p === "__v_file_info") { return false; } if (isString(p) && Object.keys(info).includes(p)) { const func = info[p]; if (isFunction(func)) { const value = func(target, { ...options, actionType: "set" }); return Reflect.set(target, p, value, receiver); } } return Reflect.set(target, p, newValue, receiver); }, deleteProperty(target, p) { if (p === "__v_file_info") { return false; } return Reflect.deleteProperty(target, p); } }); } function handleFileList(files, options) { const fileListMap = files.reduce((prev, file) => { if (isEmptyValue(file)) return prev; const fileInfo = handleFileInfo(file, options); const key = fileInfo.uid; if (!isEmptyValue(key)) { prev[key] = fileInfo; if (options == null ? void 0 : options.map) { options.map[key] = fileInfo; } } return prev; }, {}); return Object.values(fileListMap); } function useFileListConfig(props, emit) { const updatePropsKey = useDynamicProps({ update: true }); const filesModelValue = useModel(props, "modelValue"); const filesValue = useModel(props, "value"); const fileList = useModel(props, "fileList"); const fileListRef = ref([]); const fileInfos = reactive({}); const fileListMap = new Proxy(reactive({}), { get(target, p, receiver) { const value = Reflect.get(target, p, receiver); if (isEmptyObject(value) && isString(p)) { for (const [, fileInfo] of Object.entries(target)) { if ((fileInfo == null ? void 0 : fileInfo.url) && fileInfo.url.includes(p)) { Reflect.set(target, p, fileInfo, receiver); return fileInfo; } } const value2 = reactive({}); Reflect.set(target, p, value2, receiver); return value2; } return value; }, set(target, p, newValue, receiver) { return Reflect.set(target, p, newValue, receiver); } }); const fileListPercent = reactive({}); const watcher = createWatcher(); function handleFiles(force = false) { const files = []; const valueKey = updatePropsKey.find((key) => { return ["modelValue", "value", "fileList"].includes(key); }); const value = props == null ? void 0 : props[valueKey]; switch (true) { case force: case isEmptyValue(valueKey): files.push(props.modelValue, props.value, props.fileList); break; default: value && files.push(value); } const fileLists = flattenDeep(files); const list = handleFileList(fileLists, { isImageUrl: isImageUrl$1, percent: fileListPercent, originInfos: fileInfos, map: fileListMap }); unref(fileListRef).splice(0, unref(fileListRef).length, ...list); } watcher.set("fileListRef", { source: () => [unref(fileList), unref(filesValue), unref(filesModelValue)], handler: () => { handleFiles(); }, debounce: 300 }); watcher.set("fileList", { source: fileListRef, handler: (value, oldValue) => { if (oldValue === value) return; filesValue.value = value; fileList.value = value; filesModelValue.value = value; }, debounce: 500 }); onMounted(() => { handleFiles(true); }); onUnmounted(() => { watcher.stop(); fileListRef.value = []; }); const fileUrls = computed(() => { return unref(fileListRef).reduce((prev, value) => { if ((value == null ? void 0 : value.status) === "done" && (value == null ? void 0 : value.url) && !value.url.startsWith("data:")) { prev.push(value.url); } return prev; }, []); }); const isImageType = computed(() => { switch (true) { case (props.name && uploadImageType.includes(props.name)): case props.styleType === uploadImageType[0]: return true; } return false; }); function isImageUrl$1(file) { if (isEmptyObject(file)) return false; return [ props.isImageUrl, (file2) => { switch (true) { case (file2.type && file2.type.startsWith("image/")): case file2.isImage: return true; } return false; }, isImageUrl ].some((fun) => { return isFunction(fun) && fun(file); }); } return { handleFileList, fileListRef, fileUrls, fileInfos, isImageUrl: isImageUrl$1, isImageType, fileListMap }; } export { useFileListConfig };