55 changed files with 454 additions and 853 deletions
			
			
		- 
					2LICENSE
 - 
					9README.en-US.md
 - 
					8README.md
 - 
					102build/plugins.ts
 - 
					1index.html
 - 
					5mock/asyncRoutes.ts
 - 
					21package.json
 - 
					242pnpm-lock.yaml
 - 
					18public/iconfont.css
 - 
					BINsrc/assets/car.png
 - 
					0src/assets/login/illustration.svg
 - 
					1src/assets/login/illustration0.svg
 - 
					1src/assets/login/illustration1.svg
 - 
					1src/assets/login/illustration3.svg
 - 
					1src/assets/login/illustration4.svg
 - 
					1src/assets/login/illustration5.svg
 - 
					1src/assets/login/illustration6.svg
 - 
					149src/components/ReIcon/index.ts
 - 
					97src/components/ReIcon/src/Icon.vue
 - 
					39src/components/ReIcon/src/hooks.ts
 - 
					48src/components/ReIcon/src/iconfont.ts
 - 
					25src/components/ReIcon/src/iconifyIconOffline.ts
 - 
					8src/components/ReIcon/src/iconifyIconOnline.ts
 - 
					6src/layout/components/navbar.vue
 - 
					6src/layout/components/notice/data.ts
 - 
					10src/layout/components/screenfull/index.vue
 - 
					10src/layout/components/setting/index.vue
 - 
					17src/layout/components/sidebar/horizontal.vue
 - 
					13src/layout/components/sidebar/logo.vue
 - 
					19src/layout/components/sidebar/sidebarItem.vue
 - 
					3src/layout/components/sidebar/vertical.vue
 - 
					28src/layout/components/tag/index.scss
 - 
					27src/layout/components/tag/index.vue
 - 
					4src/layout/theme/element-plus.ts
 - 
					3src/layout/types.ts
 - 
					15src/main.ts
 - 
					26src/plugins/element-plus/index.ts
 - 
					21src/plugins/fontawesome/index.ts
 - 
					17src/plugins/i18n/en/menus.ts
 - 
					17src/plugins/i18n/zh-CN/menus.ts
 - 
					7src/router/modules/error.ts
 - 
					2src/router/modules/externalLink.ts
 - 
					4src/router/modules/home.ts
 - 
					2src/router/utils.ts
 - 
					3src/store/modules/multiTags.ts
 - 
					3src/store/modules/user.ts
 - 
					4src/style/login.css
 - 
					21src/utils/algorithm/index.ts
 - 
					54src/utils/loaders/index.ts
 - 
					35src/utils/resize/index.ts
 - 
					3src/utils/storage/responsive.ts
 - 
					38src/views/login.vue
 - 
					1types/global.d.ts
 - 
					106vite.config.ts
 
@ -0,0 +1,102 @@ | 
				
			|||
import vue from "@vitejs/plugin-vue"; | 
				
			|||
import svgLoader from "vite-svg-loader"; | 
				
			|||
import legacy from "@vitejs/plugin-legacy"; | 
				
			|||
import vueJsx from "@vitejs/plugin-vue-jsx"; | 
				
			|||
import WindiCSS from "vite-plugin-windicss"; | 
				
			|||
import { viteMockServe } from "vite-plugin-mock"; | 
				
			|||
import liveReload from "vite-plugin-live-reload"; | 
				
			|||
import ElementPlus from "unplugin-element-plus/vite"; | 
				
			|||
import removeConsole from "vite-plugin-remove-console"; | 
				
			|||
import themePreprocessorPlugin from "@zougt/vite-plugin-theme-preprocessor"; | 
				
			|||
 | 
				
			|||
export function getPluginsList(command, VITE_LEGACY) { | 
				
			|||
  const prodMock = true; | 
				
			|||
  return [ | 
				
			|||
    vue(), | 
				
			|||
    // jsx、tsx语法支持
 | 
				
			|||
    vueJsx(), | 
				
			|||
    WindiCSS(), | 
				
			|||
    // 线上环境删除console
 | 
				
			|||
    removeConsole(), | 
				
			|||
    // 修改layout文件夹下的文件时自动重载浏览器 解决 https://github.com/xiaoxian521/vue-pure-admin/issues/170
 | 
				
			|||
    liveReload(["src/layout/**/*", "src/router/**/*"]), | 
				
			|||
    // 自定义主题
 | 
				
			|||
    themePreprocessorPlugin({ | 
				
			|||
      scss: { | 
				
			|||
        multipleScopeVars: [ | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-default", | 
				
			|||
            path: "src/layout/theme/default-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-light", | 
				
			|||
            path: "src/layout/theme/light-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-dusk", | 
				
			|||
            path: "src/layout/theme/dusk-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-volcano", | 
				
			|||
            path: "src/layout/theme/volcano-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-yellow", | 
				
			|||
            path: "src/layout/theme/yellow-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-mingQing", | 
				
			|||
            path: "src/layout/theme/mingQing-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-auroraGreen", | 
				
			|||
            path: "src/layout/theme/auroraGreen-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-pink", | 
				
			|||
            path: "src/layout/theme/pink-vars.scss" | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            scopeName: "layout-theme-saucePurple", | 
				
			|||
            path: "src/layout/theme/saucePurple-vars.scss" | 
				
			|||
          } | 
				
			|||
        ], | 
				
			|||
        // 默认取 multipleScopeVars[0].scopeName
 | 
				
			|||
        defaultScopeName: "", | 
				
			|||
        // 在生产模式是否抽取独立的主题css文件,extract为true以下属性有效
 | 
				
			|||
        extract: true, | 
				
			|||
        // 独立主题css文件的输出路径,默认取 viteConfig.build.assetsDir 相对于 (viteConfig.build.outDir)
 | 
				
			|||
        outputDir: "", | 
				
			|||
        // 会选取defaultScopeName对应的主题css文件在html添加link
 | 
				
			|||
        themeLinkTagId: "head", | 
				
			|||
        // "head"||"head-prepend" || "body" ||"body-prepend"
 | 
				
			|||
        themeLinkTagInjectTo: "head", | 
				
			|||
        // 是否对抽取的css文件内对应scopeName的权重类名移除
 | 
				
			|||
        removeCssScopeName: false, | 
				
			|||
        // 可以自定义css文件名称的函数
 | 
				
			|||
        customThemeCssFileName: scopeName => scopeName | 
				
			|||
      } | 
				
			|||
    }), | 
				
			|||
    // svg组件化支持
 | 
				
			|||
    svgLoader(), | 
				
			|||
    ElementPlus({}), | 
				
			|||
    // mock支持
 | 
				
			|||
    viteMockServe({ | 
				
			|||
      mockPath: "mock", | 
				
			|||
      localEnabled: command === "serve", | 
				
			|||
      prodEnabled: command !== "serve" && prodMock, | 
				
			|||
      injectCode: `
 | 
				
			|||
          import { setupProdMockServer } from './mockProdServer'; | 
				
			|||
          setupProdMockServer(); | 
				
			|||
        `,
 | 
				
			|||
      logger: true | 
				
			|||
    }), | 
				
			|||
    // 是否为打包后的文件提供传统浏览器兼容性支持
 | 
				
			|||
    VITE_LEGACY | 
				
			|||
      ? legacy({ | 
				
			|||
          targets: ["ie >= 11"], | 
				
			|||
          additionalLegacyPolyfills: ["regenerator-runtime/runtime"] | 
				
			|||
        }) | 
				
			|||
      : null | 
				
			|||
  ]; | 
				
			|||
} | 
				
			|||
@ -1,18 +0,0 @@ | 
				
			|||
@font-face { | 
				
			|||
  font-family: "iconfont"; /* project id 1098500 */ | 
				
			|||
  src: url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.eot"); | 
				
			|||
  src: url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.eot?#iefix") | 
				
			|||
      format("embedded-opentype"), | 
				
			|||
    url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.woff2") format("woff2"), | 
				
			|||
    url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.woff") format("woff"), | 
				
			|||
    url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.ttf") format("truetype"), | 
				
			|||
    url("//at.alicdn.com/t/font_1098500_3d6un9zwltz.svg#iconfont") format("svg"); | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.iconfont { | 
				
			|||
  font-family: "iconfont" !important; | 
				
			|||
  font-size: 16px; | 
				
			|||
  font-style: normal; | 
				
			|||
  -webkit-font-smoothing: antialiased; | 
				
			|||
  -moz-osx-font-smoothing: grayscale; | 
				
			|||
} | 
				
			|||
| 
		 Before Width: 36 | Height: 20 | Size: 1.4 KiB  | 
						
							
						
						
							1
	
						
						src/assets/login/illustration0.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						src/assets/login/illustration1.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						src/assets/login/illustration3.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						src/assets/login/illustration4.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						src/assets/login/illustration5.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						
						
							
						
						
							1
	
						
						src/assets/login/illustration6.svg
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						@ -1,154 +1,13 @@ | 
				
			|||
import { h, App, defineComponent } from "vue"; | 
				
			|||
import icon from "./src/Icon.vue"; | 
				
			|||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; | 
				
			|||
import iconifyIconOffline from "./src/iconifyIconOffline"; | 
				
			|||
import iconifyIconOnline from "./src/iconifyIconOnline"; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * find icon component | 
				
			|||
 * @param icon icon图标 | 
				
			|||
 * @returns component | 
				
			|||
 */ | 
				
			|||
export function findIconReg(icon: string) { | 
				
			|||
  // fontawesome4
 | 
				
			|||
  const fa4Reg = /^fa-/; | 
				
			|||
  // fontawesome5+
 | 
				
			|||
  const fa5Reg = /^FA-/; | 
				
			|||
  // iconfont
 | 
				
			|||
  const iFReg = /^IF-/; | 
				
			|||
  // remixicon
 | 
				
			|||
  const riReg = /^RI-/; | 
				
			|||
  // typeof icon === "function" 属于SVG
 | 
				
			|||
  if (fa5Reg.test(icon)) { | 
				
			|||
    const text = icon.split(fa5Reg)[1]; | 
				
			|||
    return findIcon( | 
				
			|||
      text.slice(0, text.indexOf(" ") == -1 ? text.length : text.indexOf(" ")), | 
				
			|||
      "FA", | 
				
			|||
      text.slice(text.indexOf(" ") + 1, text.length) | 
				
			|||
    ); | 
				
			|||
  } else if (fa4Reg.test(icon)) { | 
				
			|||
    return findIcon(icon.split(fa4Reg)[1], "fa"); | 
				
			|||
  } else if (iFReg.test(icon)) { | 
				
			|||
    return findIcon(icon.split(iFReg)[1], "IF"); | 
				
			|||
  } else if (typeof icon === "function") { | 
				
			|||
    return findIcon(icon, "SVG"); | 
				
			|||
  } else if (riReg.test(icon)) { | 
				
			|||
    return findIcon(icon.split(riReg)[1], "RI"); | 
				
			|||
  } else { | 
				
			|||
    return findIcon(icon, "EL"); | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
// 支持fontawesome、iconfont、remixicon、element-plus/icons、自定义svg
 | 
				
			|||
export function findIcon(icon: String, type = "EL", property?: string) { | 
				
			|||
  if (type === "FA") { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "FaIcon", | 
				
			|||
      data() { | 
				
			|||
        return { icon, property }; | 
				
			|||
      }, | 
				
			|||
      components: { FontAwesomeIcon }, | 
				
			|||
      render() { | 
				
			|||
        return h( | 
				
			|||
          FontAwesomeIcon, | 
				
			|||
          { | 
				
			|||
            icon: `${this.icon}`, | 
				
			|||
            [property]: true | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            default: () => [] | 
				
			|||
          } | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (type === "fa") { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "faIcon", | 
				
			|||
      data() { | 
				
			|||
        return { icon: `fa ${icon}` }; | 
				
			|||
      }, | 
				
			|||
      render() { | 
				
			|||
        return h( | 
				
			|||
          "i", | 
				
			|||
          { | 
				
			|||
            class: `${this.icon}` | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            default: () => [] | 
				
			|||
          } | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (type === "IF") { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "IfIcon", | 
				
			|||
      data() { | 
				
			|||
        return { icon: `iconfont ${icon}` }; | 
				
			|||
      }, | 
				
			|||
      render() { | 
				
			|||
        return h( | 
				
			|||
          "i", | 
				
			|||
          { | 
				
			|||
            class: `${this.icon}` | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            default: () => [] | 
				
			|||
          } | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (type === "RI") { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "RiIcon", | 
				
			|||
      data() { | 
				
			|||
        return { icon: `ri-${icon}` }; | 
				
			|||
      }, | 
				
			|||
      render() { | 
				
			|||
        return h( | 
				
			|||
          "i", | 
				
			|||
          { | 
				
			|||
            class: `${this.icon}` | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            default: () => [] | 
				
			|||
          } | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (type === "EL") { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "ElIcon", | 
				
			|||
      data() { | 
				
			|||
        return { icon }; | 
				
			|||
      }, | 
				
			|||
      render() { | 
				
			|||
        return h( | 
				
			|||
          IconifyIconOffline, | 
				
			|||
          { | 
				
			|||
            icon: `${this.icon}` | 
				
			|||
          }, | 
				
			|||
          { | 
				
			|||
            default: () => [] | 
				
			|||
          } | 
				
			|||
        ); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (type === "SVG") { | 
				
			|||
    return icon; | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
export const Icon = Object.assign(icon, { | 
				
			|||
  install(app: App) { | 
				
			|||
    app.component(icon.name, icon); | 
				
			|||
  } | 
				
			|||
}); | 
				
			|||
import fontIcon from "./src/iconfont"; | 
				
			|||
 | 
				
			|||
export const IconifyIconOffline = iconifyIconOffline; | 
				
			|||
export const IconifyIconOnline = iconifyIconOnline; | 
				
			|||
export const FontIcon = fontIcon; | 
				
			|||
 | 
				
			|||
export default { | 
				
			|||
  Icon, | 
				
			|||
  IconifyIconOffline, | 
				
			|||
  IconifyIconOnline | 
				
			|||
  IconifyIconOnline, | 
				
			|||
  FontIcon | 
				
			|||
}; | 
				
			|||
@ -1,97 +0,0 @@ | 
				
			|||
<script lang="ts"> | 
				
			|||
export default { | 
				
			|||
  name: "Icon" | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<script setup lang="ts"> | 
				
			|||
import { ref, computed } from "vue"; | 
				
			|||
 | 
				
			|||
const props = defineProps({ | 
				
			|||
  content: { | 
				
			|||
    type: String, | 
				
			|||
    default: "" | 
				
			|||
  }, | 
				
			|||
  size: { | 
				
			|||
    type: Number, | 
				
			|||
    default: 18 | 
				
			|||
  }, | 
				
			|||
  width: { | 
				
			|||
    type: Number, | 
				
			|||
    default: 20 | 
				
			|||
  }, | 
				
			|||
  height: { | 
				
			|||
    type: Number, | 
				
			|||
    default: 20 | 
				
			|||
  }, | 
				
			|||
  color: { | 
				
			|||
    type: String, | 
				
			|||
    default: "" | 
				
			|||
  }, | 
				
			|||
  svg: { | 
				
			|||
    type: Boolean, | 
				
			|||
    default: false | 
				
			|||
  } | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const emit = defineEmits<{ | 
				
			|||
  (e: "click"): void; | 
				
			|||
}>(); | 
				
			|||
 | 
				
			|||
let text = ref(""); | 
				
			|||
 | 
				
			|||
let className = computed(() => { | 
				
			|||
  if (props.content.indexOf("fa-") > -1) { | 
				
			|||
    return props.content.indexOf("fa ") === 0 | 
				
			|||
      ? props.content | 
				
			|||
      : ["fa", props.content]; | 
				
			|||
  } else if (props.content.indexOf("el-icon-") > -1) { | 
				
			|||
    return props.content; | 
				
			|||
  } else if (props.content.indexOf("#") > -1) { | 
				
			|||
    // eslint-disable-next-line vue/no-side-effects-in-computed-properties | 
				
			|||
    text.value = props.content; | 
				
			|||
    return "iconfont"; | 
				
			|||
  } else { | 
				
			|||
    // eslint-disable-next-line vue/no-side-effects-in-computed-properties | 
				
			|||
    text.value = props.content; | 
				
			|||
    return ""; | 
				
			|||
  } | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
let iconStyle = computed(() => { | 
				
			|||
  return ( | 
				
			|||
    "font-size: " + | 
				
			|||
    props.size + | 
				
			|||
    "px; color: " + | 
				
			|||
    props.color + | 
				
			|||
    "; width: " + | 
				
			|||
    props.width + | 
				
			|||
    "px; height: " + | 
				
			|||
    props.height + | 
				
			|||
    "px; font-style: normal;" | 
				
			|||
  ); | 
				
			|||
}); | 
				
			|||
 | 
				
			|||
const clickHandle = () => { | 
				
			|||
  emit("click"); | 
				
			|||
}; | 
				
			|||
</script> | 
				
			|||
 | 
				
			|||
<template> | 
				
			|||
  <i | 
				
			|||
    v-if="!props.svg" | 
				
			|||
    :class="className" | 
				
			|||
    :style="iconStyle" | 
				
			|||
    v-html="text" | 
				
			|||
    @click="clickHandle" | 
				
			|||
  ></i> | 
				
			|||
  <svg | 
				
			|||
    class="icon-svg" | 
				
			|||
    v-if="props.svg" | 
				
			|||
    aria-hidden="true" | 
				
			|||
    :style="iconStyle" | 
				
			|||
    @click="clickHandle" | 
				
			|||
  > | 
				
			|||
    <use :xlink:href="`#${props.content}`" /> | 
				
			|||
  </svg> | 
				
			|||
</template> | 
				
			|||
@ -0,0 +1,39 @@ | 
				
			|||
import { h, defineComponent, Component } from "vue"; | 
				
			|||
import { IconifyIconOffline, FontIcon } from "../index"; | 
				
			|||
 | 
				
			|||
// 支持fontawesome4、5+、iconfont、remixicon、element-plus的icons、自定义svg
 | 
				
			|||
export function useRenderIcon(icon: string): Component { | 
				
			|||
  // iconfont
 | 
				
			|||
  const ifReg = /^IF-/; | 
				
			|||
  // typeof icon === "function" 属于SVG
 | 
				
			|||
  if (ifReg.test(icon)) { | 
				
			|||
    // iconfont
 | 
				
			|||
    const name = icon.split(ifReg)[1]; | 
				
			|||
    const iconName = name.slice( | 
				
			|||
      0, | 
				
			|||
      name.indexOf(" ") == -1 ? name.length : name.indexOf(" ") | 
				
			|||
    ); | 
				
			|||
    const iconType = name.slice(name.indexOf(" ") + 1, name.length); | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "FontIcon", | 
				
			|||
      render() { | 
				
			|||
        return h(FontIcon, { | 
				
			|||
          icon: iconName, | 
				
			|||
          iconType | 
				
			|||
        }); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } else if (typeof icon === "function") { | 
				
			|||
    // svg
 | 
				
			|||
    return icon; | 
				
			|||
  } else { | 
				
			|||
    return defineComponent({ | 
				
			|||
      name: "Icon", | 
				
			|||
      render() { | 
				
			|||
        return h(IconifyIconOffline, { | 
				
			|||
          icon: icon | 
				
			|||
        }); | 
				
			|||
      } | 
				
			|||
    }); | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,48 @@ | 
				
			|||
import { h, defineComponent } from "vue"; | 
				
			|||
 | 
				
			|||
// 封装iconfont组件,默认`font-class`引用模式,支持`unicode`引用、`font-class`引用、`symbol`引用 (https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.20&helptype=code)
 | 
				
			|||
export default defineComponent({ | 
				
			|||
  name: "fontIcon", | 
				
			|||
  props: { | 
				
			|||
    icon: { | 
				
			|||
      type: String, | 
				
			|||
      default: "" | 
				
			|||
    } | 
				
			|||
  }, | 
				
			|||
  render() { | 
				
			|||
    const attrs = this.$attrs; | 
				
			|||
    if (Object.keys(attrs).includes("uni") || attrs?.iconType === "uni") { | 
				
			|||
      return h( | 
				
			|||
        "i", | 
				
			|||
        { | 
				
			|||
          class: "iconfont", | 
				
			|||
          ...attrs | 
				
			|||
        }, | 
				
			|||
        this.icon | 
				
			|||
      ); | 
				
			|||
    } else if ( | 
				
			|||
      Object.keys(attrs).includes("svg") || | 
				
			|||
      attrs?.iconType === "svg" | 
				
			|||
    ) { | 
				
			|||
      return h( | 
				
			|||
        "svg", | 
				
			|||
        { | 
				
			|||
          class: "icon-svg", | 
				
			|||
          "aria-hidden": true | 
				
			|||
        }, | 
				
			|||
        { | 
				
			|||
          default: () => [ | 
				
			|||
            h("use", { | 
				
			|||
              "xlink:href": `#${this.icon}` | 
				
			|||
            }) | 
				
			|||
          ] | 
				
			|||
        } | 
				
			|||
      ); | 
				
			|||
    } else { | 
				
			|||
      return h("i", { | 
				
			|||
        class: `iconfont ${this.icon}`, | 
				
			|||
        ...attrs | 
				
			|||
      }); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
}); | 
				
			|||
@ -1,21 +0,0 @@ | 
				
			|||
/** 兼容fontawesome4和5版本 | 
				
			|||
 * 4版本: www.fontawesome.com.cn/faicons/ | 
				
			|||
 * 5版本:https://fontawesome.com/v5.15/icons?d=gallery&p=2&m=free
 | 
				
			|||
 * https://github.com/FortAwesome/vue-fontawesome
 | 
				
			|||
 */ | 
				
			|||
import { App } from "vue"; | 
				
			|||
import "font-awesome/css/font-awesome.css"; | 
				
			|||
import { library } from "@fortawesome/fontawesome-svg-core"; | 
				
			|||
import { | 
				
			|||
  faUserSecret, | 
				
			|||
  faCoffee, | 
				
			|||
  faSpinner | 
				
			|||
} from "@fortawesome/free-solid-svg-icons"; | 
				
			|||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; | 
				
			|||
// github.com/Remix-Design/RemixIcon/blob/master/README_CN.md#%E5%AE%89%E8%A3%85%E5%BC%95%E5%85%A5
 | 
				
			|||
import "remixicon/fonts/remixicon.css"; | 
				
			|||
 | 
				
			|||
export function useFontawesome(app: App) { | 
				
			|||
  library.add(faUserSecret, faCoffee, faSpinner); | 
				
			|||
  app.component("font-awesome-icon", FontAwesomeIcon); | 
				
			|||
} | 
				
			|||
@ -1,21 +0,0 @@ | 
				
			|||
interface ProxyAlgorithm { | 
				
			|||
  increaseIndexes<T>(val: Array<T>): Array<T>; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
class algorithmProxy implements ProxyAlgorithm { | 
				
			|||
  constructor() {} | 
				
			|||
 | 
				
			|||
  // 数组每一项添加索引字段
 | 
				
			|||
  public increaseIndexes<T>(val: Array<T>): Array<T> { | 
				
			|||
    return Object.keys(val) | 
				
			|||
      .map(v => { | 
				
			|||
        return { | 
				
			|||
          ...val[v], | 
				
			|||
          key: v | 
				
			|||
        }; | 
				
			|||
      }) | 
				
			|||
      .filter(v => v.meta && v.meta.showLink); | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
export const algorithm = new algorithmProxy(); | 
				
			|||
@ -1,54 +0,0 @@ | 
				
			|||
interface ProxyLoader { | 
				
			|||
  loadCss(src: string): any; | 
				
			|||
  loadScript(src: string): Promise<any>; | 
				
			|||
  loadScriptConcurrent(src: Array<string>): Promise<any>; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
class loaderProxy implements ProxyLoader { | 
				
			|||
  constructor() {} | 
				
			|||
 | 
				
			|||
  protected scriptLoaderCache: Array<string> = []; | 
				
			|||
 | 
				
			|||
  public loadCss = (src: string): any => { | 
				
			|||
    const element: HTMLLinkElement = document.createElement("link"); | 
				
			|||
    element.rel = "stylesheet"; | 
				
			|||
    element.href = src; | 
				
			|||
    document.body.appendChild(element); | 
				
			|||
  }; | 
				
			|||
 | 
				
			|||
  public loadScript = async (src: string): Promise<any> => { | 
				
			|||
    if (this.scriptLoaderCache.includes(src)) { | 
				
			|||
      return src; | 
				
			|||
    } else { | 
				
			|||
      const element: HTMLScriptElement = document.createElement("script"); | 
				
			|||
      element.src = src; | 
				
			|||
      document.body.appendChild(element); | 
				
			|||
      element.onload = () => { | 
				
			|||
        return this.scriptLoaderCache.push(src); | 
				
			|||
      }; | 
				
			|||
    } | 
				
			|||
  }; | 
				
			|||
 | 
				
			|||
  public loadScriptConcurrent = async ( | 
				
			|||
    srcList: Array<string> | 
				
			|||
  ): Promise<any> => { | 
				
			|||
    if (Array.isArray(srcList)) { | 
				
			|||
      const len: number = srcList.length; | 
				
			|||
      if (len > 0) { | 
				
			|||
        let count = 0; | 
				
			|||
        srcList.map(src => { | 
				
			|||
          if (src) { | 
				
			|||
            this.loadScript(src).then(() => { | 
				
			|||
              count++; | 
				
			|||
              if (count === len) { | 
				
			|||
                return; | 
				
			|||
              } | 
				
			|||
            }); | 
				
			|||
          } | 
				
			|||
        }); | 
				
			|||
      } | 
				
			|||
    } | 
				
			|||
  }; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
export const loader = new loaderProxy(); | 
				
			|||
@ -1,35 +0,0 @@ | 
				
			|||
import ResizeObserver from "resize-observer-polyfill"; | 
				
			|||
 | 
				
			|||
const isServer = typeof window === "undefined"; | 
				
			|||
 | 
				
			|||
const resizeHandler = (entries: any[]): void => { | 
				
			|||
  for (const entry of entries) { | 
				
			|||
    const listeners = entry.target.__resizeListeners__ || []; | 
				
			|||
    if (listeners.length) { | 
				
			|||
      listeners.forEach((fn: () => any) => { | 
				
			|||
        fn(); | 
				
			|||
      }); | 
				
			|||
    } | 
				
			|||
  } | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
export const addResizeListener = (element: any, fn: () => any): any => { | 
				
			|||
  if (isServer) return; | 
				
			|||
  if (!element.__resizeListeners__) { | 
				
			|||
    element.__resizeListeners__ = []; | 
				
			|||
    element.__ro__ = new ResizeObserver(resizeHandler); | 
				
			|||
    element.__ro__.observe(element); | 
				
			|||
  } | 
				
			|||
  element.__resizeListeners__.push(fn); | 
				
			|||
}; | 
				
			|||
 | 
				
			|||
export const removeResizeListener = (element: any, fn: () => any): any => { | 
				
			|||
  if (!element || !element.__resizeListeners__) return; | 
				
			|||
  element.__resizeListeners__.splice( | 
				
			|||
    element.__resizeListeners__.indexOf(fn), | 
				
			|||
    1 | 
				
			|||
  ); | 
				
			|||
  if (!element.__resizeListeners__.length) { | 
				
			|||
    element.__ro__.disconnect(); | 
				
			|||
  } | 
				
			|||
}; | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue