import { GlobalConfig } from "../../config/GlobalConfig"; import { EventEmiter } from "../../event/EventEmiter"; import { PopsElementHandler } from "../../handler/PopsElementHandler"; import { PopsHandler } from "../../handler/PopsHandler"; import { PopsInstHandler } from "../../handler/PopsInstHandler"; import { PopsCSS } from "../../PopsCSS"; import type { EventMap } from "../../types/EventEmitter"; import type { PopsType } from "../../types/main"; import { popsDOMUtils } from "../../utils/PopsDOMUtils"; import { PopsSafeUtils } from "../../utils/PopsSafeUtils"; import { popsUtils } from "../../utils/PopsUtils"; import { PopsLoading } from "../loading"; import { PopsFolderDefaultConfig } from "./defaultConfig"; import { Folder_ICON } from "./folderIcon"; import type { PopsFolderConfig, PopsFolderDataConfig, PopsFolderDownloadOption } from "./types"; export const PopsFolder = { init(__config__: PopsFolderConfig) { const guid = popsUtils.getRandomGUID(); // 设置当前类型 const popsType: PopsType = "folder"; let config = PopsFolderDefaultConfig(); config = popsUtils.assign(config, GlobalConfig.getGlobalConfig()); config = popsUtils.assign(config, __config__); config = PopsHandler.handleOnly(popsType, config); const emitter = config.emitter ?? new EventEmiter(popsType); const { $shadowContainer, $shadowRoot } = PopsHandler.handlerShadow(config); PopsHandler.handleInit($shadowRoot, [ { name: "index", css: PopsCSS.index, }, { name: "ninePalaceGridPosition", css: PopsCSS.ninePalaceGridPosition, }, { name: "scrollbar", css: PopsCSS.scrollbar, }, { name: "button", css: PopsCSS.button, }, { name: "anim", css: PopsCSS.anim, }, { name: "common", css: PopsCSS.common, }, { name: "skeleton", css: PopsCSS.skeletonCSS, }, { name: "folderCSS", css: PopsCSS.folderCSS, }, ]); // 办公几件套 Reflect.set(Folder_ICON, "docx", Folder_ICON.doc); Reflect.set(Folder_ICON, "rtf", Folder_ICON.doc); Reflect.set(Folder_ICON, "xlsx", Folder_ICON.xls); Reflect.set(Folder_ICON, "pptx", Folder_ICON.ppt); Reflect.set(Folder_ICON, "dmg", Folder_ICON.ipa); Reflect.set(Folder_ICON, "json", Folder_ICON.js); // 压缩包 const zipIconList = [ "rar", "7z", "arj", "bz2", "cab", "iso", "jar", "lz", "lzh", "tar", "uue", "xz", "z", "zipx", "zst", "001", ]; // 图片 const imageIconList = ["jpg", "jpeg", "ico", "webp"]; // 代码语言 const codeLanguageIconList = ["htm", "py", "vue", "bat", "sh", "vbs", "java", "kt"]; // Android安装包 const androidIconList = ["apk", "apkm", "xapk"]; zipIconList.forEach((keyName) => { Folder_ICON[keyName as keyof typeof Folder_ICON] = Folder_ICON.zip; }); imageIconList.forEach((keyName) => { Folder_ICON[keyName as keyof typeof Folder_ICON] = Folder_ICON.png; }); codeLanguageIconList.forEach((keyName) => { Folder_ICON[keyName as keyof typeof Folder_ICON] = Folder_ICON.html; }); androidIconList.forEach((keyName) => { Folder_ICON[keyName as keyof typeof Folder_ICON] = Folder_ICON.apk; }); if (config?.folder) { Reflect.set(config, "folder", config.folder); } // 先把z-index提取出来 const zIndex = PopsHandler.getTargerOrFunctionValue(config.zIndex); const maskHTML = PopsElementHandler.createMask(guid, zIndex); const headerBtnHTML = PopsElementHandler.createHeader(popsType, config); const bottomBtnHTML = PopsElementHandler.createBottom(popsType, config); const { headerStyle, headerPStyle } = PopsElementHandler.createHeaderStyle(popsType, config); const animHTML = PopsElementHandler.createAnim( guid, popsType, config, /*html*/ `
${ config.title.html ? config.title.text : `

${config.title.text}

` }${headerBtnHTML}
文件名
修改时间
大小
${ popsUtils.isPhone() ? `` : ` ` }
${bottomBtnHTML}`, bottomBtnHTML, zIndex ); /** * 弹窗的主元素,包括动画层 */ const $anim = PopsElementHandler.parseElement(animHTML); const { $pops: $pops, $title: $title, $content: $content, // folderListElement, // folderListHeaderElement, // folderListHeaderRowElement, $folderTbody: folderListBodyElement, $folderHeaderBreadcrumbPrimary: folderFileListBreadcrumbPrimaryElement, $headerBtnClose: $btnCloseBtn, $btnOk: btnOkElement, $btnCancel: btnCancelElement, $btnOther: btnOtherElement, $folderSortFileName: folderListSortFileNameElement, $folderSortLatestTime: folderListSortLatestTimeElement, $folderSortFileSize: folderListSortFileSizeElement, } = PopsHandler.handleQueryElement($anim, popsType); /** * 遮罩层元素 */ let $mask: HTMLDivElement | undefined = void 0; /** * 已创建的元素列表 */ const $elList: HTMLElement[] = [$anim]; if (config.mask.enable) { const handleMask = PopsHandler.handleMask({ type: popsType, guid: guid, config: config, animElement: $anim, maskHTML: maskHTML, }); $mask = handleMask.maskElement; $elList.push($mask); } // 事件 const evtConfig = PopsHandler.handleEventConfig( config, guid, $shadowContainer, $shadowRoot, popsType, $anim, $pops, emitter, $mask ); const result = PopsHandler.handleResultConfig(evtConfig); PopsHandler.handleClickEvent("close", $btnCloseBtn, evtConfig, config.btn.close.callback); PopsHandler.handleClickEvent("ok", btnOkElement, evtConfig, config.btn.ok.callback); PopsHandler.handleClickEvent("cancel", btnCancelElement, evtConfig, config.btn.cancel.callback); PopsHandler.handleClickEvent("other", btnOtherElement, evtConfig, config.btn.other.callback); // 创建到页面中 popsDOMUtils.append($shadowRoot, $elList); emitter.emit("pops:before-append-to-page", $shadowRoot, $shadowContainer); popsDOMUtils.appendBody($shadowContainer); if ($mask != null) { $anim.after($mask); } class PopsFolder { init() { config.folder.sort(); this.initFolderView(config.folder); // 将数据存到全部文件的属性_config_中 const $allFiles = folderFileListBreadcrumbPrimaryElement.querySelector( ".pops-folder-list .pops-folder-file-list-breadcrumb-allFiles:first-child" )!; Reflect.set($allFiles, "data-config", config.folder); // 设置点击顶部的全部文件事件 popsDOMUtils.on($allFiles, "click", (event) => { this.setBreadcrumbClickEvent(event, true, config.folder); }); // 文件名的点击排序 popsDOMUtils.on( folderListSortFileNameElement.closest("th"), "click", (event) => { this.arrowToSortFolderInfoView(folderListSortFileNameElement, event, "fileName"); }, { capture: true, } ); // 修改事件的点击排序 popsDOMUtils.on( folderListSortLatestTimeElement.closest("th"), "click", (event) => { this.arrowToSortFolderInfoView(folderListSortLatestTimeElement, event, "latestTime"); }, { capture: true, } ); // 文件大小的点击排序 popsDOMUtils.on( folderListSortFileSizeElement.closest("th"), "click", (event) => { this.arrowToSortFolderInfoView(folderListSortFileSizeElement, event, "fileSize"); }, { capture: true, } ); // 设置默认触发的arrow if (config.sort.name === "fileName") { popsDOMUtils.emit(folderListSortFileNameElement, "click", { notChangeSortRule: true, }); } else if (config.sort.name === "latestTime") { popsDOMUtils.emit(folderListSortLatestTimeElement, "click", { notChangeSortRule: true, }); } else if (config.sort.name === "fileSize") { popsDOMUtils.emit(folderListSortFileSizeElement, "click", { notChangeSortRule: true, }); } } /** * 在创建文件|文件夹创建元素前处理东西 */ handlerWithBeforeCreateFileOrFolderInfoNode(folderData: PopsFolderDataConfig) { let { fileSize } = folderData; const { fileName, latestTime, isFolder = false } = folderData; folderData.latestTime = folderData.latestTime ?? "-"; folderData.fileSize = folderData.fileSize ?? "-"; const $folder = popsDOMUtils.createElement("tr"); const $fileName = popsDOMUtils.createElement("td"); const $fileTime = popsDOMUtils.createElement("td"); const $fileFormatSize = popsDOMUtils.createElement("td"); let show_latestTime = ""; let show_fileSize = ""; let fileType = ""; let fileIcon = ""; if (isFolder) { // 文件夹 fileType = ""; fileIcon = Folder_ICON.folder; show_latestTime = ""; fileSize = ""; show_fileSize = ""; } else { // 文件 if (typeof latestTime === "function") { const timeRet = latestTime(); show_latestTime = timeRet.showText; } else if (typeof latestTime === "number") { show_latestTime = popsUtils.formatTime(latestTime); } else if (typeof latestTime === "string") { show_latestTime = latestTime; } if (typeof fileSize === "number") { show_fileSize = popsUtils.formatByteToSize(fileSize, true); } else if (typeof fileSize === "string") { show_fileSize = fileSize; } // 找到对应的图标 const findIconKeyName = Object.keys(Folder_ICON).find((keyName) => { if (fileName.toLowerCase().endsWith("." + keyName)) { fileType = keyName; fileIcon = Reflect.get(Folder_ICON, keyName); return true; } }); if (findIconKeyName) { fileIcon = Reflect.get(Folder_ICON, findIconKeyName); fileType = findIconKeyName; } else { fileType = "Null"; fileIcon = Folder_ICON.Null; } } if (typeof folderData.fileIcon === "string") { // 强制使用自定义 fileIcon = folderData.fileIcon; } $folder.className = "pops-folder-list-table__body-row"; $fileName.className = "pops-folder-list-table__body-td"; $fileTime.className = "pops-folder-list-table__body-td"; $fileFormatSize.className = "pops-folder-list-table__body-td"; return { $folder, $fileName, $fileTime, $fileFormatSize, /** 经过处理后的数据 */ data: { fileType, fileIcon, show_latestTime, show_fileSize, }, }; } /** * 创建文件夹元素 * @param fileName 文件名 * @param latestTime 修改时间 * @param [fileSize="-"] 文件大小 * @param isFolder 是否是文件夹 */ createFolderRowElement(folderData: PopsFolderDataConfig) { const { $folder, $fileName, $fileTime, $fileFormatSize, data } = this.handlerWithBeforeCreateFileOrFolderInfoNode(folderData); const { fileName } = folderData; PopsSafeUtils.setSafeHTML( $fileName, /*html*/ ` ` ); PopsSafeUtils.setSafeHTML( $fileTime, /*html*/ `
${data.show_latestTime}
` ); PopsSafeUtils.setSafeHTML( $fileFormatSize, /*html*/ `
${data.show_fileSize}
` ); Reflect.set($fileName, "__value__", folderData); Reflect.set($fileTime, "__value__", folderData); Reflect.set($fileFormatSize, "__value__", folderData); Reflect.set($folder, "__value__", folderData); $folder.appendChild($fileName); $folder.appendChild($fileTime); $folder.appendChild($fileFormatSize); return { folderElement: $folder, fileNameElement: $fileName, fileTimeElement: $fileTime, fileFormatSize: $fileFormatSize, }; } /** * 创建移动端文件夹元素 * @param fileName 文件名 * @param latestTime 创建时间 * @param [fileSize="-"] 文件大小 * @param isFolder 是否是文件夹 */ createFolderRowElementByMobile(folderData: PopsFolderDataConfig) { const { $folder, $fileName, data } = this.handlerWithBeforeCreateFileOrFolderInfoNode(folderData); const { fileName } = folderData; PopsSafeUtils.setSafeHTML( $fileName, /*html*/ `
${data.fileType}
${fileName} ${data.show_latestTime} ${data.show_fileSize}
` ); // 存储原来的值 Reflect.set($fileName, "__value__", folderData); Reflect.set($folder, "__value__", folderData); $folder.appendChild($fileName); return { folderElement: $folder, /** * 超链接标签的容器 */ fileNameElement: $fileName, }; } /** * 清空文件夹信息页面 */ clearFolderInfoView() { PopsSafeUtils.setSafeHTML(folderListBodyElement, ""); } /** * 创建顶部导航的箭头图标 */ createHeaderArrowIcon() { const $arrowIcon = popsDOMUtils.createElement("div", { className: "iconArrow", }); return $arrowIcon; } /** * 添加顶部导航元素 * @param folderName 文件夹名 * @param folderDataConfig 文件夹配置 */ createBreadcrumb( folderName: string, folderDataConfig: PopsFolderDownloadOption | PopsFolderDataConfig[] | null | undefined | void ) { const $breadcrumb = popsDOMUtils.createElement( "span", { className: "pops-folder-file-list-breadcrumb-allFiles cursor-p", innerHTML: `${folderName}`, "data-config": folderDataConfig, }, { title: folderName, } ); return $breadcrumb; } /** * 顶部导航的点击事件 * @param clickEvent * @param isTop 是否是全部文件按钮 * @param dataConfigList 配置 */ setBreadcrumbClickEvent( clickEvent: MouseEvent | PointerEvent, isTop: boolean, dataConfigList: PopsFolderDataConfig[] ) { this.clearFolderInfoView(); // 获取当前的导航元素 const $click = clickEvent.target as HTMLElement; const currentBreadcrumb = $click.closest("span.pops-folder-file-list-breadcrumb-allFiles"); if (currentBreadcrumb) { while (currentBreadcrumb.nextElementSibling) { popsDOMUtils.remove(currentBreadcrumb.nextElementSibling); } } else { console.error("获取导航按钮失败"); } const loadingMask = PopsLoading.init({ $parent: $content, content: { text: "获取文件列表中...", }, mask: { enable: true, clickEvent: { toClose: false, toHide: false, }, }, addIndexCSS: false, }); this.initFolderView(dataConfigList); loadingMask.close(); } /** * 文件夹的点击事件 - 进入文件夹 * * 先情况页面元素 * @param clickEvent * @param dataConfig */ async enterFolder(clickEvent: MouseEvent | PointerEvent, dataConfig: PopsFolderDataConfig) { this.clearFolderInfoView(); const loadingMask = PopsLoading.init({ $parent: $content, content: { text: "获取文件列表中...", }, mask: { enable: true, }, addIndexCSS: false, }); let childConfig: PopsFolderDataConfig[] | undefined; if (typeof dataConfig.clickEvent === "function") { const result = await dataConfig.clickEvent(clickEvent, dataConfig); if (Array.isArray(result)) { childConfig = result; } } else if (Array.isArray(dataConfig.clickEvent)) { childConfig = dataConfig.clickEvent; } if (childConfig) { // 添加顶部导航的箭头 folderFileListBreadcrumbPrimaryElement.appendChild(this.createHeaderArrowIcon()); // 添加顶部导航的链接文字 const $breadcrumbAllFiles = this.createBreadcrumb(dataConfig.fileName, childConfig); folderFileListBreadcrumbPrimaryElement.appendChild($breadcrumbAllFiles); // 设置顶部导航点击事件 popsDOMUtils.on($breadcrumbAllFiles, "click", (event) => { this.setBreadcrumbClickEvent(event, false, childConfig as PopsFolderDataConfig[]); }); this.initFolderView(childConfig as PopsFolderDataConfig[]); } loadingMask.close(); } /** * 更新文件的显示的链接信息 * * 这里主要用于鼠标中键或者右键触发,左键触发方式会根据mode进行处理 * @returns 更新的文件的下载链接 */ updateFileLink($row: HTMLElement, downloadInfo: PopsFolderDownloadOption) { const downloadUrl = typeof downloadInfo?.url === "string" ? downloadInfo.url.trim() : ""; if (downloadUrl !== "" && downloadUrl !== "null" && downloadUrl !== "undefined") { const $link = $row.querySelector("a")!; $link.setAttribute("href", downloadUrl); return downloadUrl; } } /** * 文件的点击事件 - 下载文件 * @param evt 点击事件 * @param $row 列表项 * @param dataConfig */ async onFileClick(evt: MouseEvent | PointerEvent, $row: HTMLElement, dataConfig: PopsFolderDataConfig) { let downloadInfo: PopsFolderDownloadOption | undefined; if (typeof dataConfig.clickEvent === "function") { const result = await dataConfig.clickEvent(evt, dataConfig); if (typeof result === "object" && result != null && !Array.isArray(result)) { downloadInfo = result; } } else if ( typeof dataConfig.clickEvent === "object" && dataConfig.clickEvent != null && !Array.isArray(dataConfig.clickEvent) ) { downloadInfo = dataConfig.clickEvent; } if (downloadInfo) { const downloadUrl = this.updateFileLink($row, downloadInfo); if (downloadUrl) { if (typeof downloadInfo.mode === "string") { if (downloadInfo.mode === "a" || downloadInfo.mode === "aBlank") { // a标签下载 const $anchor = popsDOMUtils.createElement("a"); if (downloadInfo.mode === "aBlank") { $anchor.setAttribute("target", "_blank"); } $anchor.href = downloadUrl; $anchor.click(); } else if (downloadInfo.mode === "open" || downloadInfo.mode === "openBlank") { // window.open下载 if (downloadInfo.mode === "openBlank") { globalThis.open(downloadUrl, "_blank"); } else { globalThis.open(downloadUrl); } } else if (downloadInfo.mode === "iframe") { // iframe下载 const $downloadIframe = popsDOMUtils.createElement("iframe"); $downloadIframe.src = downloadUrl; $downloadIframe.onload = function () { popsUtils.setTimeout(() => { popsDOMUtils.remove($downloadIframe); }, 1000); }; $shadowRoot.appendChild($downloadIframe); popsUtils.setTimeout( () => { popsDOMUtils.remove($downloadIframe); }, 3 * 60 * 1000 ); } else { console.error("未知的下载模式", downloadInfo); } } } } } /** * 对配置进行排序 * @param folderDataConfigList * @param sortName 比较的属性,默认fileName * @param isDesc 是否降序,默认false(升序) */ sortFolderConfig( folderDataConfigList: PopsFolderDataConfig[], sortName: "fileName" | "fileSize" | "latestTime" = "fileName", isDesc = false ) { // 文件夹 const onlyFolderDataConfigList = folderDataConfigList.filter((value) => { return value.isFolder; }); // 文件 const onlyFileDataConfigList = folderDataConfigList.filter((value) => { return !value.isFolder; }); if (sortName === "fileName") { // 文件夹排序 onlyFolderDataConfigList.sort((leftConfig, rightConfig) => { const beforeVal = leftConfig[sortName].toString(); const afterVal = rightConfig[sortName].toString(); let compareVal = beforeVal.localeCompare(afterVal); if (isDesc) { // 降序 if (compareVal > 0) { compareVal = -1; } else if (compareVal < 0) { compareVal = 1; } } return compareVal; }); // 文件名排序 onlyFileDataConfigList.sort((leftConfig, rightConfig) => { const beforeVal = leftConfig[sortName].toString(); const afterVal = rightConfig[sortName].toString(); let compareVal = beforeVal.localeCompare(afterVal); if (isDesc) { // 降序 if (compareVal > 0) { compareVal = -1; } else if (compareVal < 0) { compareVal = 1; } } return compareVal; }); } else { // 文件夹排序 onlyFolderDataConfigList.sort((beforeConfig, afterConfig) => { let beforeVal = beforeConfig[sortName]; let afterVal = afterConfig[sortName]; if (typeof beforeVal === "function") { beforeVal = beforeVal().timeStamp; } if (typeof afterVal === "function") { afterVal = afterVal().timeStamp; } if (sortName === "fileSize") { // 文件大小,进行Float转换 beforeVal = parseFloat(beforeVal.toString()); afterVal = parseFloat(afterVal.toString()); } else if (sortName === "latestTime") { // 文件时间 beforeVal = new Date(beforeVal || "").getTime(); afterVal = new Date(afterVal || "").getTime(); } if (beforeVal > afterVal) { if (isDesc) { // 降序 return -1; } else { return 1; } } else if (beforeVal < afterVal) { if (isDesc) { // 降序 return 1; } else { return -1; } } else { return 0; } }); // 文件排序 onlyFileDataConfigList.sort((beforeConfig, afterConfig) => { let beforeVal = beforeConfig[sortName]; let afterVal = afterConfig[sortName]; if (typeof beforeVal === "function") { beforeVal = beforeVal().timeStamp; } if (typeof afterVal === "function") { afterVal = afterVal().timeStamp; } if (sortName === "fileSize") { // 文件大小,进行Float转换 beforeVal = parseFloat(beforeVal.toString()); afterVal = parseFloat(afterVal.toString()); } else if (sortName === "latestTime") { // 文件时间 beforeVal = new Date(beforeVal).getTime(); afterVal = new Date(afterVal).getTime(); } if (beforeVal > afterVal) { if (isDesc) { // 降序 return -1; } else { return 1; } } else if (beforeVal < afterVal) { if (isDesc) { // 降序 return 1; } else { return -1; } } else { return 0; } }); } // 文件夹始终优先放前面 return [...onlyFolderDataConfigList, ...onlyFileDataConfigList]; } /** * 添加文件夹/文件行元素 * @param dataConfig 配置 */ initFolderView(dataConfig: PopsFolderDataConfig[]) { // 先对文件夹、文件进行排序 const sortedConfigList = this.sortFolderConfig(dataConfig, config.sort.name, config.sort.isDesc); sortedConfigList.forEach((item) => { if (item.isFolder) { const { folderElement, fileNameElement } = popsUtils.isPhone() ? this.createFolderRowElementByMobile(item) : this.createFolderRowElement(item); // 文件夹 - 点击事件 popsDOMUtils.on(fileNameElement, "click", (event) => { // 进入文件夹 this.enterFolder(event, item); }); folderListBodyElement.appendChild(folderElement); } else { const { folderElement, fileNameElement } = popsUtils.isPhone() ? this.createFolderRowElementByMobile(item) : this.createFolderRowElement(item); // 文件 - 点击事件 popsDOMUtils.on(fileNameElement, "click", (event) => { // 下载文件 popsDOMUtils.preventEvent(event); this.onFileClick(event, fileNameElement, item); }); // 如果clickEvent不是函数,那么现在就可以进行配置 if (typeof item.clickEvent === "object" && item.clickEvent !== null && !Array.isArray(item.clickEvent)) { // {} 单文件配置 this.updateFileLink(fileNameElement, item.clickEvent); } folderListBodyElement.appendChild(folderElement); } }); } /** * 移除所有箭头的被访问状态 */ removeArrowActiveStatus() { [ ...Array.from(folderListSortFileNameElement.querySelectorAll(".pops-folder-icon-active")), ...Array.from(folderListSortLatestTimeElement.querySelectorAll(".pops-folder-icon-active")), ...Array.from(folderListSortFileSizeElement.querySelectorAll(".pops-folder-icon-active")), ].forEach(($elItem) => popsDOMUtils.removeClassName($elItem, "pops-folder-icon-active")); } /** * 修改导航箭头的状态 * @param arrowUp ↑ * @param arrowDown ↓ * @param isDesc 是否逆反 */ changeArrowActive(arrowUp: HTMLElement, arrowDown: HTMLElement, isDesc: boolean) { this.removeArrowActiveStatus(); const activeClassName = "pops-folder-icon-active"; popsDOMUtils.addClassName(isDesc ? arrowDown : arrowUp, activeClassName); } /** * 排序按钮的点击事件 * @param $target * @param event * @param sortName */ arrowToSortFolderInfoView($target: HTMLDivElement, event: MouseEvent | PointerEvent, sortName: string) { const notChangeSortRule = Reflect.get(event, "notChangeSortRule"); if (!notChangeSortRule) { config.sort.name = sortName as PopsFolderConfig["sort"]["name"]; config.sort.isDesc = !config.sort.isDesc; } const $arrowUp = $target.querySelector(".pops-folder-icon-arrow-up")!; const $arrowDown = $target.querySelector(".pops-folder-icon-arrow-down")!; this.changeArrowActive($arrowUp, $arrowDown, config.sort.isDesc); if ( typeof config.sort.callback === "function" && config.sort.callback($target, event, config.sort.name, config.sort.isDesc) ) { return; } const childrenList: PopsFolderDataConfig[] = []; Array.from(folderListBodyElement.children).forEach(($tr) => { const __value__ = Reflect.get($tr, "__value__"); Reflect.set(__value__, "target", $tr); childrenList.push(__value__); }); const sortedConfigList = this.sortFolderConfig(childrenList, config.sort.name, config.sort.isDesc); sortedConfigList.forEach((item) => { folderListBodyElement.appendChild((item as any).target); }); } } const popsFolder = new PopsFolder(); popsFolder.init(); Reflect.set($pops, "data-pops-folder", popsFolder); // 拖拽 if (config.drag) { PopsInstHandler.drag($pops, { dragElement: $title, limit: config.dragLimit, extraDistance: config.dragExtraDistance, moveCallBack: config.dragMoveCallBack, endCallBack: config.dragEndCallBack, }); } PopsHandler.handlePush(popsType, { guid: guid, $anim: $anim, $pops: $pops, $mask: $mask!, $shadowContainer: $shadowContainer, $shadowRoot: $shadowRoot, config: config, emitter, }); return result; }, };