Skip to content

Commit

Permalink
feat: 引入 unplugin-svg-component 插件代替 vite-plugin-svg-icons 插件 & elIco…
Browse files Browse the repository at this point in the history
…n 支持类型提示 (#220)

Co-authored-by: pany <[email protected]>
  • Loading branch information
heavenly-zy and pany-ang authored Dec 2, 2024
1 parent 503e2d8 commit ebb8e80
Show file tree
Hide file tree
Showing 18 changed files with 584 additions and 1,782 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@
"typescript": "5.6.3",
"unocss": "0.64.1",
"unplugin-auto-import": "0.18.6",
"unplugin-svg-component": "0.10.4",
"unplugin-vue-components": "0.27.5",
"vite": "6.0.1",
"vite-plugin-svg-icons": "2.0.1",
"vite-svg-loader": "5.1.0",
"vitest": "2.1.6",
"vue-tsc": "2.1.10"
Expand Down
2,208 changes: 484 additions & 1,724 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions src/common/assets/icons/preserve-color/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## 目录说明

- `common/assets/icons/preserve-color` 目录下存放带颜色的 svg icon

- `common/assets/icons` 目录存放的 svg icon 会被插件重写 `fill``stroke` 属性,使得图片自带的颜色丢失,从而继承父元素的颜色

## 使用说明

`common/assets/icons/preserve-color` 目录下需要添加 `preserve-color/` 前缀,像这样: `<SvgIcon name="preserve-color/name" />`

`common/assets/icons` 目录下则不需要,像这样: `<SvgIcon name="name" />`
4 changes: 2 additions & 2 deletions src/common/components/Screenfull/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ function handleContentFullClick() {
<div>
<!-- 全屏 -->
<el-tooltip v-if="!props.content" effect="dark" :content="fullscreenTips" placement="bottom">
<SvgIcon :name="fullscreenSvgName" @click="handleFullscreenClick" />
<SvgIcon :name="fullscreenSvgName" @click="handleFullscreenClick" class="svg-icon" />
</el-tooltip>
<!-- 内容区 -->
<el-dropdown v-else :disabled="isFullscreen">
<SvgIcon :name="contentLargeSvgName" />
<SvgIcon :name="contentLargeSvgName" class="svg-icon" />
<template #dropdown>
<el-dropdown-menu>
<!-- 内容区放大 -->
Expand Down
8 changes: 4 additions & 4 deletions src/common/components/SearchMenu/Footer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ const { isMobile } = useDevice()
<div class="search-footer">
<template v-if="!isMobile">
<span class="search-footer-item">
<SvgIcon name="keyboard-enter" />
<SvgIcon name="keyboard-enter" class="svg-icon" />
<span>确认</span>
</span>
<span class="search-footer-item">
<SvgIcon name="keyboard-up" />
<SvgIcon name="keyboard-down" />
<SvgIcon name="keyboard-up" class="svg-icon" />
<SvgIcon name="keyboard-down" class="svg-icon" />
<span>切换</span>
</span>
<span class="search-footer-item">
<SvgIcon name="keyboard-esc" />
<SvgIcon name="keyboard-esc" class="svg-icon" />
<span>关闭</span>
</span>
</template>
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/SearchMenu/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ function handleReleaseUpOrDown() {
>
<el-input ref="inputRef" v-model="keyword" placeholder="搜索菜单" size="large" clearable @input="handleSearch">
<template #prefix>
<SvgIcon name="search" />
<SvgIcon name="search" class="svg-icon" />
</template>
</el-input>
<el-empty v-if="result.length === 0" description="暂无搜索结果" :image-size="100" />
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/SearchMenu/Result.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ defineExpose({ getScrollTop })
:style="itemStyle(item)"
@mouseenter="handleMouseenter(item)"
>
<SvgIcon v-if="item.meta?.svgIcon" :name="item.meta.svgIcon" />
<SvgIcon v-if="item.meta?.svgIcon" :name="item.meta.svgIcon" class="svg-icon" />
<component v-else-if="item.meta?.elIcon" :is="item.meta.elIcon" class="el-icon" />
<span class="result-item-title">
{{ item.meta?.title }}
</span>
<SvgIcon v-if="modelValue && modelValue === item.name" name="keyboard-enter" />
<SvgIcon v-if="modelValue && modelValue === item.name" name="keyboard-enter" class="svg-icon" />
</div>
</div>
</template>
Expand Down
2 changes: 1 addition & 1 deletion src/common/components/SearchMenu/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function handleOpen() {
<template>
<div>
<el-tooltip effect="dark" content="搜索菜单" placement="bottom">
<SvgIcon name="search" @click="handleOpen" />
<SvgIcon name="search" @click="handleOpen" class="svg-icon" />
</el-tooltip>
<Modal v-model="visible" />
</div>
Expand Down
27 changes: 0 additions & 27 deletions src/common/components/SvgIcon/index.vue

This file was deleted.

4 changes: 2 additions & 2 deletions src/layouts/components/Sidebar/Item.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function resolvePath(routePath: string) {
<template v-if="!alwaysShowRootMenu && theOnlyOneChild && !theOnlyOneChild.children">
<Link v-if="theOnlyOneChild.meta" :to="resolvePath(theOnlyOneChild.path)">
<el-menu-item :index="resolvePath(theOnlyOneChild.path)">
<SvgIcon v-if="theOnlyOneChild.meta.svgIcon" :name="theOnlyOneChild.meta.svgIcon" />
<SvgIcon v-if="theOnlyOneChild.meta.svgIcon" :name="theOnlyOneChild.meta.svgIcon" class="svg-icon" />
<component v-else-if="theOnlyOneChild.meta.elIcon" :is="theOnlyOneChild.meta.elIcon" class="el-icon" />
<template v-if="theOnlyOneChild.meta.title" #title>
<span class="title">{{ theOnlyOneChild.meta.title }}</span>
Expand All @@ -62,7 +62,7 @@ function resolvePath(routePath: string) {
</template>
<el-sub-menu v-else :index="resolvePath(props.item.path)" teleported>
<template #title>
<SvgIcon v-if="props.item.meta?.svgIcon" :name="props.item.meta.svgIcon" />
<SvgIcon v-if="props.item.meta?.svgIcon" :name="props.item.meta.svgIcon" class="svg-icon" />
<component v-else-if="props.item.meta?.elIcon" :is="props.item.meta.elIcon" class="el-icon" />
<span v-if="props.item.meta?.title" class="title">{{ props.item.meta.title }}</span>
</template>
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { App } from "vue"
import { installElementPlusIcons } from "./element-plus-icons"
import { installPermissionDirective } from "./permission-directive"
import { installSvgIcons } from "./svg-icons"
import { installSvgIcon } from "./svg-icon"
import { installVxeTable } from "./vxe-table"

export function installPlugins(app: App) {
installElementPlusIcons(app)
installPermissionDirective(app)
installSvgIcons(app)
installSvgIcon(app)
installVxeTable(app)
}
6 changes: 6 additions & 0 deletions src/plugins/svg-icon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { App } from "vue"
import SvgIcon from "~virtual/svg-component"

export function installSvgIcon(app: App) {
app.component("SvgIcon", SvgIcon)
}
7 changes: 0 additions & 7 deletions src/plugins/svg-icons.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export const constantRoutes: RouteRecordRaw[] = [
path: "/link",
meta: {
title: "文档链接",
elIcon: "link"
elIcon: "Link"
},
children: [
{
Expand Down Expand Up @@ -196,7 +196,7 @@ export const dynamicRoutes: RouteRecordRaw[] = [
name: "Permission",
meta: {
title: "权限演示",
elIcon: "lock",
elIcon: "Lock",
// 可以在根路由中设置角色
roles: ["admin", "editor"],
alwaysShow: true
Expand Down
26 changes: 26 additions & 0 deletions types/auto/svg-component-global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable */
/* prettier-ignore */
// biome-ignore format: off
// biome-ignore lint: off
// @ts-nocheck
// Generated by unplugin-svg-component
import 'vue'
declare module 'vue' {
export interface GlobalComponents {
SvgIcon: import("vue").DefineComponent<{
name: {
type: import("vue").PropType<"dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search">;
default: string;
required: true;
};
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
name: {
type: import("vue").PropType<"dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search">;
default: string;
required: true;
};
}>>, {
name: "dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search";
}>;
}
}
26 changes: 26 additions & 0 deletions types/auto/svg-component.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable */
/* prettier-ignore */
// biome-ignore format: off
// biome-ignore lint: off
// @ts-nocheck
// Generated by unplugin-svg-component
declare module '~virtual/svg-component' {
const SvgIcon: import("vue").DefineComponent<{
name: {
type: import("vue").PropType<"dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search">;
default: string;
required: true;
};
}, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
name: {
type: import("vue").PropType<"dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search">;
default: string;
required: true;
};
}>>, {
name: "dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search";
}>;
export const svgNames: ["dashboard", "fullscreen-exit", "fullscreen", "keyboard-down", "keyboard-enter", "keyboard-esc", "keyboard-up", "search"];
export type SvgName = "dashboard" | "fullscreen-exit" | "fullscreen" | "keyboard-down" | "keyboard-enter" | "keyboard-esc" | "keyboard-up" | "search";
export default SvgIcon;
}
8 changes: 6 additions & 2 deletions types/vue-router.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type * as ElementPlusIconsVue from "@element-plus/icons-vue"
import type { SvgName } from "~virtual/svg-component"
import "vue-router"

export {}

type ElementPlusIconsName = keyof typeof ElementPlusIconsVue

declare module "vue-router" {
interface RouteMeta {
/**
Expand All @@ -11,11 +15,11 @@ declare module "vue-router" {
/**
* @description 设置该路由的图标,记得将 svg 导入 src/common/assets/icons
*/
svgIcon?: string
svgIcon?: SvgName
/**
* @description 设置该路由的图标,直接使用 Element Plus 的 Icon(与 svgIcon 同时设置时,svgIcon 将优先生效)
*/
elIcon?: string
elIcon?: ElementPlusIconsName
/**
* @description 默认 false,设置 true 的时候该路由不会在侧边栏出现
*/
Expand Down
13 changes: 8 additions & 5 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import vue from "@vitejs/plugin-vue"
import vueJsx from "@vitejs/plugin-vue-jsx"
import UnoCSS from "unocss/vite"
import AutoImport from "unplugin-auto-import/vite"
import UnpluginSvgComponent from "unplugin-svg-component/vite"
import { ElementPlusResolver } from "unplugin-vue-components/resolvers"
import Components from "unplugin-vue-components/vite"
import { defineConfig, loadEnv } from "vite"
import { createSvgIconsPlugin } from "vite-plugin-svg-icons"
import svgLoader from "vite-svg-loader"

// Configuring Vite: https://cn.vite.dev/config
Expand Down Expand Up @@ -94,10 +94,13 @@ export default defineConfig(({ mode }) => {
vueJsx(),
// 将 SVG 文件转化为 Vue 组件
svgLoader({ defaultImport: "url" }),
// 生成 SVG 雪碧图
createSvgIconsPlugin({
iconDirs: [resolve(root, "src/common/assets/icons")],
symbolId: "icon-[dir]-[name]"
// 自动生成 SvgIcon 组件和 SVG 雪碧图
UnpluginSvgComponent({
iconDir: [resolve(__dirname, "src/common/assets/icons")],
preserveColor: resolve(__dirname, "src/common/assets/icons/preserve-color"),
dts: true,
dtsDir: resolve(__dirname, "types/auto"),
treeShaking: false
}),
// 原子化 CSS
UnoCSS(),
Expand Down

0 comments on commit ebb8e80

Please sign in to comment.