refactor: 重构图标使用方式,集成自定应图标

This commit is contained in:
张传龙 2022-06-19 13:35:36 +08:00
parent 00ba77c15e
commit f88b4f52a1
19 changed files with 79 additions and 144 deletions

View File

@ -6,20 +6,6 @@ import vue from '@vitejs/plugin-vue'
*/
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
/**
* * 组件库按需引入插件
* usage: 直接使用组件,无需在任何地方导入组件
*/
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
/**
* * unplugin-icons插件自动引入iconify图标
* usage: https://github.com/antfu/unplugin-icons
* 图标库: https://icones.js.org/
*/
import Icons from 'unplugin-icons/vite'
/**
* * unocss插件原子css
* https://github.com/antfu/unocss
@ -31,20 +17,14 @@ import visualizer from 'rollup-plugin-visualizer'
import { configHtmlPlugin } from './html'
import { configMockPlugin } from './mock'
import unplugin from './unplugin'
export function createVitePlugins(viteEnv, isBuild) {
const plugins = [
vue(),
VueSetupExtend(),
Components({
resolvers: [NaiveUiResolver()],
}),
Icons({ compiler: 'vue3', autoInstall: true }),
configHtmlPlugin(viteEnv, isBuild),
Unocss(),
]
const plugins = [vue(), VueSetupExtend(), ...unplugin, configHtmlPlugin(viteEnv, isBuild), Unocss()]
viteEnv?.VITE_APP_USE_MOCK && plugins.push(configMockPlugin(isBuild))
if (viteEnv?.VITE_APP_USE_MOCK) {
plugins.push(configMockPlugin(isBuild))
}
if (isBuild) {
plugins.push(

28
build/plugin/unplugin.js Normal file
View File

@ -0,0 +1,28 @@
import Components from 'unplugin-vue-components/vite'
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import IconsResolver from 'unplugin-icons/resolver'
/**
* * unplugin-icons插件自动引入iconify图标
* usage: https://github.com/antfu/unplugin-icons
* 图标库: https://icones.js.org/
*/
import Icons from 'unplugin-icons/vite'
import { getRootPath } from '../utils'
const customIconPath = getRootPath('src', 'assets/icons')
export default [
Icons({
compiler: 'vue3',
customCollections: {
custom: FileSystemIconLoader(customIconPath),
},
scale: 1,
defaultClass: 'inline-block',
}),
Components({
resolvers: [NaiveUiResolver(), IconsResolver({ customCollections: ['custom'], componentPrefix: 'icon' })],
}),
]

View File

@ -21,10 +21,8 @@
"vue-router": "^4.0.15"
},
"devDependencies": {
"@iconify-json/ant-design": "^1.1.1",
"@iconify-json/ic": "^1.1.2",
"@iconify-json/mdi": "^1.1.9",
"@iconify-json/simple-icons": "^1.1.7",
"@iconify/json": "^2.1.63",
"@iconify/vue": "^3.2.1",
"@vitejs/plugin-vue": "^1.10.2",
"@vue/compiler-sfc": "^3.2.31",
"chalk": "^5.0.1",

43
pnpm-lock.yaml generated
View File

@ -1,10 +1,8 @@
lockfileVersion: 5.4
specifiers:
'@iconify-json/ant-design': ^1.1.1
'@iconify-json/ic': ^1.1.2
'@iconify-json/mdi': ^1.1.9
'@iconify-json/simple-icons': ^1.1.7
'@iconify/json': ^2.1.63
'@iconify/vue': ^3.2.1
'@vitejs/plugin-vue': ^1.10.2
'@vue/compiler-sfc': ^3.2.31
'@vueuse/core': ^8.4.2
@ -46,10 +44,8 @@ dependencies:
vue-router: 4.0.15_vue@3.2.31
devDependencies:
'@iconify-json/ant-design': 1.1.1
'@iconify-json/ic': 1.1.2
'@iconify-json/mdi': 1.1.9
'@iconify-json/simple-icons': 1.1.7
'@iconify/json': 2.1.63
'@iconify/vue': 3.2.1_vue@3.2.31
'@vitejs/plugin-vue': 1.10.2_vite@2.9.9
'@vue/compiler-sfc': 3.2.31
chalk: 5.0.1
@ -152,28 +148,11 @@ packages:
resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==}
dev: true
/@iconify-json/ant-design/1.1.1:
resolution: {integrity: sha512-aziSNNmMGe/BpDVn+LCi7BP1hBJq39kn0j9yk4ZHqKGytiF9JRF/0ziKjxvo0BvYFuPAjwMVJpFzhG0KMZ/DGw==}
dependencies:
'@iconify/types': 1.1.0
dev: true
/@iconify-json/ic/1.1.2:
resolution: {integrity: sha512-OXLXNMECrwg1N7HqG9z+p8eF9NleoV5tZvIH/W3ip3HdZsg1VbEWl0RpI9K5VJjT95xVn2n+gcAgLPD5HNAsXg==}
dependencies:
'@iconify/types': 1.1.0
dev: true
/@iconify-json/mdi/1.1.9:
resolution: {integrity: sha512-iZY3d7nLmEhSxLU5YBHIxVVPySqNjj6zYcf448TXGBPp2PyToITCOuLEaub0rQ9jBAPOlupQsuPX9ylBfgIJ1w==}
dependencies:
'@iconify/types': 1.1.0
dev: true
/@iconify-json/simple-icons/1.1.7:
resolution: {integrity: sha512-VsDh1AlVTJ2GYBBRD8oUmhFrMj00pzmz8oGRrTAdu5sWYOyrJ9f0sFnr+89ABjAnzXqS8z2lmA0SxFG3HGQzvQ==}
/@iconify/json/2.1.63:
resolution: {integrity: sha512-WQwTV6KUl0C+VkH3/j9kwlHLOHyPn0pM7f0kFmJgghQ9Ha672UHr/KTuwVqbqn3c+RxnJyY+jIap4ewawMeaZA==}
dependencies:
'@iconify/types': 1.1.0
pathe: 0.2.0
dev: true
/@iconify/types/1.1.0:
@ -193,6 +172,14 @@ packages:
- supports-color
dev: true
/@iconify/vue/3.2.1_vue@3.2.31:
resolution: {integrity: sha512-c4R6ZgFo1JrJ8aPMMgOPgfU7lBswihMGR+yWe/P4ZukC3kTkeT4+lkt9Pc/itVFMkwva/S/7u9YofmYv57fnNQ==}
peerDependencies:
vue: 3.x
dependencies:
vue: 3.2.31
dev: true
/@juggle/resize-observer/3.3.1:
resolution: {integrity: sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==}
dev: true

View File

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 825 B

View File

@ -1,9 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 448 512">
<path
d="M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-92.2 312.9c-63.4 0-85.4-28.6-97.1-64.1c-16.3-51-21.5-84.3-63-84.3c-22.4 0-45.1 16.1-45.1 61.2c0 35.2 18 57.2 43.3 57.2c28.6 0 47.6-21.3 47.6-21.3l11.7 31.9s-19.8 19.4-61.2 19.4c-51.3 0-79.9-30.1-79.9-85.8c0-57.9 28.6-92 82.5-92c73.5 0 80.8 41.4 100.8 101.9c8.8 26.8 24.2 46.2 61.2 46.2c24.9 0 38.1-5.5 38.1-19.1c0-19.9-21.8-22-49.9-28.6c-30.4-7.3-42.5-23.1-42.5-48c0-40 32.3-52.4 65.2-52.4c37.4 0 60.1 13.6 63 46.6l-36.7 4.4c-1.5-15.8-11-22.4-28.6-22.4c-16.1 0-26 7.3-26 19.8c0 11 4.8 17.6 20.9 21.3c32.7 7.1 71.8 12 71.8 57.5c.1 36.7-30.7 50.6-76.1 50.6z"
></path>
</svg>
</template>
<script setup name="IconLogo"></script>

View File

@ -1,26 +0,0 @@
export { default as IconGitee } from '~icons/simple-icons/gitee'
export { default as IconChart } from '~icons/mdi/chart-bar'
export { default as IconGithub } from '~icons/mdi/github'
export { default as IconVue } from '~icons/mdi/vuejs'
export { default as IconHome } from '~icons/mdi/home'
export { default as IconLink } from '~icons/mdi/link-variant'
export { default as IconAlert } from '~icons/mdi/alert-circle-outline'
export { default as IconCircle } from '~icons/mdi/circle-outline'
export { default as IconMenu } from '~icons/mdi/menu'
export { default as IconRefresh } from '~icons/mdi/refresh'
export { default as IconClose } from '~icons/mdi/close'
export { default as IconExpand } from '~icons/mdi/arrow-expand-horizontal'
export { default as IconExpandLeft } from '~icons/mdi/arrow-expand-left'
export { default as IconExpandRight } from '~icons/mdi/arrow-expand-right'
export { default as IconMenuTable } from '~icons/mdi/table'
export { default as IconMenuCollapse } from '~icons/mdi/format-indent-decrease'
export { default as IconMenuExpand } from '~icons/mdi/format-indent-increase'
export { default as IconExit } from '~icons/mdi/exit-to-app'
export { default as IconFullscreen } from '~icons/ant-design/fullscreen-outlined'
export { default as IconFullscreenExit } from '~icons/ant-design/fullscreen-exit-outlined'
export { default as IconArrowLeft } from '~icons/ic/baseline-keyboard-arrow-left'
export { default as IconArrowRight } from '~icons/ic/baseline-keyboard-arrow-right'
export { default as IconLogo } from './IconLogo.vue'

View File

@ -2,10 +2,10 @@
<div ref="wrapper" class="tags-wrapper" @mousewheel.prevent="handleMouseWheel">
<template v-if="showArrow && isOverflow">
<div class="left" @click="handleMouseWheel({ wheelDelta: 50 })">
<IconArrowLeft />
<icon-ic:baseline-keyboard-arrow-left />
</div>
<div class="right" @click="handleMouseWheel({ wheelDelta: -50 })">
<IconArrowRight />
<icon-ic:baseline-keyboard-arrow-right />
</div>
</template>
@ -25,7 +25,6 @@
<script setup>
import { ref, onMounted } from 'vue'
import { IconArrowLeft, IconArrowRight } from '@/components/AppIcons'
import { debounce } from '@/utils'
import { isNullOrUndef } from '@/utils/is'

View File

@ -1,12 +1,11 @@
<template>
<n-icon mr20 size="18" style="cursor: pointer" @click="toggle">
<IconFullscreenExit v-if="isFullscreen" />
<IconFullscreen v-else />
<icon-ant-design:fullscreen-outlined v-if="isFullscreen" />
<icon-ant-design:fullscreen-outlined v-else />
</n-icon>
</template>
<script setup>
import { IconFullscreen, IconFullscreenExit } from '@/components/AppIcons'
import { useFullscreen } from '@vueuse/core'
const { isFullscreen, toggle } = useFullscreen()

View File

@ -1,11 +1,10 @@
<template>
<n-icon mr20 size="18" style="cursor: pointer" @click="handleLinkClick">
<IconGithub />
<icon-mdi:github />
</n-icon>
</template>
<script setup>
import { IconGithub } from '@/components/AppIcons'
function handleLinkClick() {
window.open('https://github.com/zclzone/vue-naive-admin')
}

View File

@ -1,12 +1,11 @@
<template>
<n-icon size="20" style="cursor: pointer" @click="appStore.switchCollapsed">
<IconMenuExpand v-if="appStore.collapsed" />
<IconMenuCollapse v-else />
<icon-mdi:format-indent-increase v-if="appStore.collapsed" />
<icon-mdi:format-indent-decrease v-else />
</n-icon>
</template>
<script setup>
import { IconMenuCollapse, IconMenuExpand } from '@/components/AppIcons'
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()

View File

@ -9,7 +9,6 @@
<script setup>
import { useUserStore } from '@/store/modules/user'
import { IconExit } from '@/components/AppIcons'
import { renderIcon } from '@/utils/icon'
const userStore = useUserStore()
@ -18,7 +17,7 @@ const options = [
{
label: '退出登录',
key: 'logout',
icon: renderIcon(IconExit, { size: '14px' }),
icon: renderIcon('mdi:exit-to-app', { size: '14px' }),
},
]

View File

@ -1,8 +1,6 @@
<template>
<router-link h-60 f-c-c to="/">
<n-icon size="36" color="#316c72">
<IconLogo />
</n-icon>
<icon-custom-logo text-36></icon-custom-logo>
<h2 v-show="!appStore.collapsed" ml-10 color-primary text-16 font-bold max-w-140 flex-shrink-0>
{{ title }}
</h2>
@ -10,7 +8,6 @@
</template>
<script setup>
import { IconLogo } from '@/components/AppIcons'
import { useAppStore } from '@/store/modules/app'
const title = import.meta.env.VITE_APP_TITLE

View File

@ -16,8 +16,6 @@ import { useRouter } from 'vue-router'
import { computed } from 'vue'
import { usePermissionStore } from '@/store/modules/permission'
import { IconCircle } from '@/components/AppIcons'
import { isExternal } from '@/utils/is'
import { useAppStore } from '@/store/modules/app'
import { renderIcon } from '@/utils/icon'
@ -47,7 +45,7 @@ function getMenuItem(route, basePath = '') {
label: (route.meta && route.meta.title) || route.name,
key: route.name,
path: resolvePath(basePath, route.path),
icon: route.meta?.icon ? renderIcon(route.meta?.icon, { size: 16 }) : renderIcon(IconCircle, { size: 8 }),
icon: route.meta?.icon ? renderIcon(route.meta?.icon, { size: 16 }) : renderIcon('mdi:circle-outline', { size: 8 }),
index: route.meta?.index || 0,
}
@ -64,7 +62,7 @@ function getMenuItem(route, basePath = '') {
path: resolvePath(menuItem.path, singleRoute.path),
icon: singleRoute.meta?.icon
? renderIcon(singleRoute.meta?.icon, { size: 16 })
: renderIcon(IconCircle, { size: 8 }),
: renderIcon('mdi:circle-outline', { size: 8 }),
index: menuItem.index,
}
const visibleItems = singleRoute.children ? singleRoute.children.filter((item) => item.name && !item.isHidden) : []

View File

@ -13,7 +13,6 @@
<script setup>
import { computed } from 'vue'
import { useTagsStore } from '@/store/modules/tags'
import { IconRefresh, IconClose, IconExpand, IconExpandLeft, IconExpandRight } from '@/components/AppIcons'
import { renderIcon } from '@/utils/icon'
import { useAppStore } from '@/store/modules/app'
@ -46,31 +45,31 @@ const options = computed(() => [
label: '重新加载',
key: 'reload',
disabled: props.currentPath !== tagsStore.activeTag,
icon: renderIcon(IconRefresh, { size: '14px' }),
icon: renderIcon('mdi:refresh', { size: '14px' }),
},
{
label: '关闭',
key: 'close',
disabled: tagsStore.tags.length <= 1,
icon: renderIcon(IconClose, { size: '14px' }),
icon: renderIcon('mdi:close', { size: '14px' }),
},
{
label: '关闭其他',
key: 'close-other',
disabled: tagsStore.tags.length <= 1,
icon: renderIcon(IconExpand, { size: '14px' }),
icon: renderIcon('mdi:arrow-expand-horizontal', { size: '14px' }),
},
{
label: '关闭左侧',
key: 'close-left',
disabled: tagsStore.tags.length <= 1 || props.currentPath === tagsStore.tags[0].path,
icon: renderIcon(IconExpandLeft, { size: '14px' }),
icon: renderIcon('mdi:arrow-expand-left', { size: '14px' }),
},
{
label: '关闭右侧',
key: 'close-right',
disabled: tagsStore.tags.length <= 1 || props.currentPath === tagsStore.tags[tagsStore.tags.length - 1].path,
icon: renderIcon(IconExpandRight, { size: '14px' }),
icon: renderIcon('mdi:arrow-expand-right', { size: '14px' }),
},
])

View File

@ -1,17 +1,6 @@
import Layout from '@/layout/index.vue'
import Home from '@/views/dashboard/index.vue'
import {
IconAlert,
IconChart,
IconGitee,
IconGithub,
IconHome,
IconLink,
IconMenu,
IconVue,
} from '@/components/AppIcons'
export const basicRoutes = [
{
name: '404',
@ -49,7 +38,7 @@ export const basicRoutes = [
redirect: '/home',
meta: {
title: 'Dashboard',
icon: IconChart,
icon: 'mdi:chart-bar',
},
children: [
{
@ -58,7 +47,7 @@ export const basicRoutes = [
component: Home,
meta: {
title: '首页',
icon: IconHome,
icon: 'mdi:home',
},
},
],
@ -71,7 +60,7 @@ export const basicRoutes = [
redirect: '/error-page/404',
meta: {
title: '错误页',
icon: IconAlert,
icon: 'mdi:alert-circle-outline',
index: 4,
},
children: [
@ -81,7 +70,7 @@ export const basicRoutes = [
component: () => import('@/views/error-page/404.vue'),
meta: {
title: '404',
icon: IconAlert,
icon: 'mdi:alert-circle-outline',
},
},
],
@ -94,7 +83,7 @@ export const basicRoutes = [
redirect: '/test/unocss',
meta: {
title: '基础功能测试',
icon: IconMenu,
icon: 'mdi:menu',
},
children: [
{
@ -139,7 +128,7 @@ export const basicRoutes = [
component: Layout,
meta: {
title: '外部链接',
icon: IconLink,
icon: 'mdi:link-variant',
},
children: [
{
@ -147,7 +136,7 @@ export const basicRoutes = [
path: 'https://github.com/zclzone/vue-naive-admin',
meta: {
title: '源码 - github',
icon: IconGithub,
icon: 'mdi:github',
},
},
{
@ -155,7 +144,7 @@ export const basicRoutes = [
path: 'https://gitee.com/zclzone/vue-naive-admin',
meta: {
title: '源码 - gitee',
icon: IconGitee,
icon: 'simple-icons:gitee',
},
},
{
@ -163,7 +152,7 @@ export const basicRoutes = [
path: 'https://zclzone.github.io/vue-naive-admin-docs',
meta: {
title: '文档 - vuepress',
icon: IconVue,
icon: 'mdi:vuejs',
},
},
],

View File

@ -1,6 +1,4 @@
import { IconMenuTable } from '@/components/AppIcons'
import Layout from '@/layout/index.vue'
import { markRaw } from 'vue'
export default [
{
@ -21,7 +19,7 @@ export default [
meta: {
title: '表格',
role: ['admin'],
icon: markRaw(IconMenuTable),
icon: 'mdi:table',
},
children: [
{

View File

@ -1,6 +1,7 @@
import { h } from 'vue'
import { Icon } from '@iconify/vue'
import { NIcon } from 'naive-ui'
export function renderIcon(icon, props = { size: 12 }) {
return () => h(NIcon, { ...props }, { default: () => h(icon) })
return () => h(NIcon, props, { default: () => h(Icon, { icon }) })
}

View File

@ -7,7 +7,7 @@
<div w-full f-c-c flex-col>
<h5 f-c-c w-full p-15 text-24 font-normal color="#6a6a6a">
<img mr-15 src="@/assets/images/logo.svg" width="45" alt="logo" />
<icon-custom-logo mr30 text-50 />
{{ title }}
</h5>
<div mt-35 w-full max-w-360>