refactor(projects): 去除vicons,统一使用iconify图标

This commit is contained in:
Soybean 2021-11-08 05:13:48 +08:00
parent e61ee32a88
commit cd6db3d491
26 changed files with 290 additions and 145 deletions

View File

@ -8,10 +8,3 @@ export default [
}),
Icons()
];
/**
* iconify用法(安装对应的vscode智能提示的插件: Iconify IntelliSense)
* https://icones.js.org/ 或者 vscode安装 icones插件
* mdi:ab-testing : <icon-mdi:ab-testing />
* html标签一样直接应用style属性或者class属性; color和font-size属性设置对应的颜色和大小
*/

View File

@ -0,0 +1,24 @@
iconify用法
一、静态用法:直接用图标的组件名称
1.安装vscode智能提示的插件: Iconify IntelliSense
2.找图标:网址 https://icones.js.org/ 或者 vscode安装 icones插件
3.确定图标名字:找到图标后复制名字 如:'mdi:emoticon' 组件为: <icon-mdi:emoticon />
4.设置样式同html标签一样直接应用style属性或者class属性; 通过设置color和font-size属性设置对应的颜色和大小
二、多个图标动态渲染
1.确定图标名字,如:'mdi:emoticon'
2.引入Icon组件
import { Icon } from '@iconify/vue';
3.动态渲染 <Icon icon="mdi:emoticon" />
psIcon组件属性 https://docs.iconify.design/icon-components/vue/
三、结合naiveUI组件动态渲染
1.确定图标名字,如:'mdi:emoticon'
2.引入vue的h函数
import { h } from 'vue';
3.引入Icon组件
import { Icon } from '@iconify/vue';
4.动态渲染
() => h(Icon, { icon: 'mdi:emoticon', style: { color: '#f00', fontSize: '16px' } })
ps@/uitls已封装好了函数iconifyRender

View File

@ -41,14 +41,6 @@
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"@vicons/antd": "^0.11.0",
"@vicons/carbon": "^0.11.0",
"@vicons/fa": "^0.11.0",
"@vicons/fluent": "^0.11.0",
"@vicons/ionicons4": "^0.11.0",
"@vicons/ionicons5": "^0.11.0",
"@vicons/material": "^0.11.0",
"@vicons/tabler": "^0.11.0",
"@vitejs/plugin-vue": "^1.9.4",
"@vue/compiler-sfc": "^3.2.21",
"@vue/eslint-config-prettier": "^6.0.0",

View File

@ -11,14 +11,6 @@ specifiers:
'@types/qs': ^6.9.7
'@typescript-eslint/eslint-plugin': ^5.3.0
'@typescript-eslint/parser': ^5.3.0
'@vicons/antd': ^0.11.0
'@vicons/carbon': ^0.11.0
'@vicons/fa': ^0.11.0
'@vicons/fluent': ^0.11.0
'@vicons/ionicons4': ^0.11.0
'@vicons/ionicons5': ^0.11.0
'@vicons/material': ^0.11.0
'@vicons/tabler': ^0.11.0
'@vitejs/plugin-vue': ^1.9.4
'@vue/compiler-sfc': ^3.2.21
'@vue/eslint-config-prettier': ^6.0.0
@ -85,14 +77,6 @@ devDependencies:
'@types/qs': registry.nlark.com/@types/qs/6.9.7
'@typescript-eslint/eslint-plugin': registry.npmmirror.com/@typescript-eslint/eslint-plugin/5.3.0_f8873316f48f7781ccc3e081fc76e214
'@typescript-eslint/parser': registry.npmmirror.com/@typescript-eslint/parser/5.3.0_eslint@8.1.0+typescript@4.4.4
'@vicons/antd': registry.nlark.com/@vicons/antd/0.11.0
'@vicons/carbon': registry.nlark.com/@vicons/carbon/0.11.0
'@vicons/fa': registry.nlark.com/@vicons/fa/0.11.0
'@vicons/fluent': registry.nlark.com/@vicons/fluent/0.11.0
'@vicons/ionicons4': registry.nlark.com/@vicons/ionicons4/0.11.0
'@vicons/ionicons5': registry.nlark.com/@vicons/ionicons5/0.11.0
'@vicons/material': registry.nlark.com/@vicons/material/0.11.0
'@vicons/tabler': registry.nlark.com/@vicons/tabler/0.11.0
'@vitejs/plugin-vue': registry.npmmirror.com/@vitejs/plugin-vue/1.9.4_vite@2.5.10
'@vue/compiler-sfc': registry.npmmirror.com/@vue/compiler-sfc/3.2.21
'@vue/eslint-config-prettier': 6.0.0_91df2dbc49a694d3127d896fd063ef53
@ -902,54 +886,6 @@ packages:
name: '@types/yargs-parser'
version: 20.2.1
registry.nlark.com/@vicons/antd/0.11.0:
resolution: {integrity: sha1-PSiVLQKK7XEtymHLgdvbEUVMVUI=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/antd/download/@vicons/antd-0.11.0.tgz}
name: '@vicons/antd'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/carbon/0.11.0:
resolution: {integrity: sha1-UQ4B6IOnOx1DQ6PrHRAUFEZGOr4=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/carbon/download/@vicons/carbon-0.11.0.tgz}
name: '@vicons/carbon'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/fa/0.11.0:
resolution: {integrity: sha1-3GeAslt5Q3NOfHXXTfL0RDsFcq4=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/fa/download/@vicons/fa-0.11.0.tgz}
name: '@vicons/fa'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/fluent/0.11.0:
resolution: {integrity: sha1-hPPNolVTnLlvRcicFgHiiS15gm8=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/fluent/download/@vicons/fluent-0.11.0.tgz}
name: '@vicons/fluent'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/ionicons4/0.11.0:
resolution: {integrity: sha1-pg9erWYdRz8XEDrQBRzoKtdxu+Y=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/ionicons4/download/@vicons/ionicons4-0.11.0.tgz}
name: '@vicons/ionicons4'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/ionicons5/0.11.0:
resolution: {integrity: sha1-VBhb+lcqCd9wCU2xlU8ov78TY+0=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/ionicons5/download/@vicons/ionicons5-0.11.0.tgz}
name: '@vicons/ionicons5'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/material/0.11.0:
resolution: {integrity: sha1-LCCRIfP/akZFD0loOX32wwCN+NE=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/material/download/@vicons/material-0.11.0.tgz}
name: '@vicons/material'
version: 0.11.0
dev: true
registry.nlark.com/@vicons/tabler/0.11.0:
resolution: {integrity: sha1-nrBXnADKowQMLBz55cDHa6EgT7M=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@vicons/tabler/download/@vicons/tabler-0.11.0.tgz}
name: '@vicons/tabler'
version: 0.11.0
dev: true
registry.nlark.com/JSONStream/1.3.5:
resolution: {integrity: sha1-MgjB8I06TZkmGrZPkjArwV4RHKA=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/JSONStream/download/JSONStream-1.3.5.tgz}
name: JSONStream

View File

@ -3,7 +3,7 @@
<path
d="M0,158.86Q0,80,0,1.1C0,.2.2,0,1.1,0Q79.44,0,157.78,0c.9,0,1.1.2,1.1,1.1q0,78.35,0,156.68c0,.9-.2,1.1-1.1,1.1Q78.9,158.83,0,158.86Z"
transform="translate(0)"
style="fill: #ffffff"
style="fill: #ffffff00"
/>
<path
d="M81.28,55.9c-.1-11.67-2.93-22.55-9.37-32.38-1-1.5-2.14-2.86-2.5-4.71a8.1,8.1,0,0,1,4-8.61,7.89,7.89,0,0,1,9.3,1.23,36,36,0,0,1,5.9,8.83,75.18,75.18,0,0,1,8.44,28.58,83.21,83.21,0,0,1-5.23,36.74c-.91,2.47-1.91,4.9-3,7.28a1.2,1.2,0,0,0,0,1.41c9.58,13.3,21.76,23,37.85,27.24a54.35,54.35,0,0,0,19.68,1.57,7.72,7.72,0,0,1,8.36,6.9,7.9,7.9,0,0,1-6.7,9,64.74,64.74,0,0,1-23-1.33,77.68,77.68,0,0,1-36.93-19.88,93.64,93.64,0,0,1-11.91-13.71A2.18,2.18,0,0,0,73.87,103a72.75,72.75,0,0,0-27.38,7.55c-11.6,6-20.67,14.58-26.4,26.45a10.13,10.13,0,0,1-3.7,4.7A8,8,0,0,1,7.2,141a7.86,7.86,0,0,1-2.36-9.28,60.32,60.32,0,0,1,8.72-14.52c12.2-15.43,28.21-24.59,47.32-28.57A85.08,85.08,0,0,1,73.07,87a1.22,1.22,0,0,0,1.18-.8A76.06,76.06,0,0,0,80.78,63.9,57.87,57.87,0,0,0,81.28,55.9Z"

View File

@ -1,4 +1,3 @@
import type { Component } from 'vue';
import type { RouteRecordRaw } from 'vue-router';
import type { MenuOption } from 'naive-ui';
import { EnumRoutePath, EnumLoginModule } from '@/enum';
@ -14,7 +13,7 @@ interface RouteMeta {
/** 不作为菜单 */
isNotMenu?: boolean;
/** 菜单和面包屑对应的图标 */
icon?: Component;
icon?: string;
/** 路由作为菜单时的排序 */
order?: number;
}

View File

@ -3,9 +3,23 @@
<template v-for="breadcrumb in breadcrumbList" :key="breadcrumb.key">
<n-breadcrumb-item>
<n-dropdown v-if="breadcrumb.hasChildren" :options="breadcrumb.children" @select="dropdownSelect">
<span>{{ breadcrumb.label }}</span>
<span>
<Icon
v-if="theme.crumbsStyle.showIcon && breadcrumb.iconName"
:icon="breadcrumb.iconName"
class="inline-block mr-4px text-16px"
/>
<span>{{ breadcrumb.label }}</span>
</span>
</n-dropdown>
<span v-else>{{ breadcrumb.label }}</span>
<template v-else>
<Icon
v-if="theme.crumbsStyle.showIcon && breadcrumb.iconName"
:icon="breadcrumb.iconName"
class="inline-block mr-4px text-16px"
/>
<span>{{ breadcrumb.label }}</span>
</template>
</n-breadcrumb-item>
</template>
</n-breadcrumb>
@ -14,10 +28,12 @@
<script lang="ts" setup>
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import type { RouteLocationMatched } from 'vue-router';
import { NBreadcrumb, NBreadcrumbItem, NDropdown } from 'naive-ui';
import type { DropdownOption } from 'naive-ui';
import type { RouteLocationMatched } from 'vue-router';
import { Icon } from '@iconify/vue';
import { EnumRoutePath } from '@/enum';
import { useThemeStore } from '@/store';
import type { RoutePathKey } from '@/interface';
type Breadcrumb = DropdownOption & {
@ -26,9 +42,11 @@ type Breadcrumb = DropdownOption & {
disabled: boolean;
routeName: RoutePathKey;
hasChildren: boolean;
iconName?: string;
children?: Breadcrumb[];
};
const theme = useThemeStore();
const route = useRoute();
const router = useRouter();
@ -52,6 +70,9 @@ function recursionBreadcrumb(routeMatched: RouteLocationMatched[]) {
routeName,
hasChildren: false
};
if (item.meta?.icon) {
breadcrumItem.iconName = item.meta.icon as string;
}
if (item.children && item.children.length) {
breadcrumItem.hasChildren = true;
breadcrumItem.children = recursionBreadcrumb(item.children as RouteLocationMatched[]);

View File

@ -9,11 +9,10 @@
<script lang="ts" setup>
import { NDropdown, useDialog } from 'naive-ui';
import { UserAvatar, Logout } from '@vicons/carbon';
import { dynamicIconRender, resetAuthStorage } from '@/utils';
import { HoverContainer } from '@/components';
import avatar from '@/assets/svg/avatar/avatar01.svg';
import { useRouterChange } from '@/hooks';
import { iconifyRender, resetAuthStorage } from '@/utils';
import avatar from '@/assets/svg/avatar/avatar01.svg';
type DropdownKey = 'user-center' | 'logout';
@ -24,7 +23,7 @@ const options = [
{
label: '用户中心',
key: 'user-center',
icon: dynamicIconRender(UserAvatar)
icon: iconifyRender('carbon:user-avatar')
},
{
type: 'divider',
@ -33,7 +32,7 @@ const options = [
{
label: '退出登录',
key: 'logout',
icon: dynamicIconRender(Logout)
icon: iconifyRender('carbon:logout')
}
];

View File

@ -14,12 +14,11 @@
import { computed, watch } from 'vue';
import { NDropdown } from 'naive-ui';
import type { DropdownOption } from 'naive-ui';
import { ReloadOutlined, CloseOutlined, ColumnWidthOutlined, MinusOutlined } from '@vicons/antd';
import { useAppStore } from '@/store';
import { useReloadInject } from '@/context';
import { useBoolean } from '@/hooks';
import { ROUTE_HOME } from '@/router';
import { useReloadInject } from '@/context';
import { dynamicIconRender } from '@/utils';
import { iconifyRender } from '@/utils';
interface Props {
/** 右键菜单可见性 */
@ -59,23 +58,23 @@ const options = computed<Option[]>(() => [
label: '重新加载',
key: 'reload-current',
disabled: props.currentPath !== app.multiTab.activeRoute,
icon: dynamicIconRender(ReloadOutlined)
icon: iconifyRender('ant-design:reload-outlined')
},
{
label: '关闭标签页',
key: 'close-current',
disabled: props.currentPath === ROUTE_HOME.path,
icon: dynamicIconRender(CloseOutlined)
icon: iconifyRender('ant-design:close-outlined')
},
{
label: '关闭其他标签页',
key: 'close-other',
icon: dynamicIconRender(ColumnWidthOutlined)
icon: iconifyRender('ant-design:column-width-outlined')
},
{
label: '关闭全部标签页',
key: 'close-all',
icon: dynamicIconRender(MinusOutlined)
icon: iconifyRender('ant-design:minus-outlined')
}
]);

View File

@ -1,4 +1,3 @@
import { BookInformation24Regular } from '@vicons/fluent';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { ROUTE_NAME_MAP, setRouterCacheName, setSingleRoute } from '@/utils';
@ -14,7 +13,7 @@ const ABOUT: CustomRoute = setSingleRoute(BasicLayout, {
meta: {
requiresAuth: true,
title: EnumRouteTitle.about,
icon: BookInformation24Regular
icon: 'fluent:book-information-24-regular'
}
});

View File

@ -1,4 +1,3 @@
import { AppStore24Regular } from '@vicons/fluent';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { BasicLayout } from '@/layouts';
@ -17,7 +16,7 @@ const COMPONENT: CustomRoute = {
meta: {
requiresAuth: true,
title: EnumRouteTitle.component,
icon: AppStore24Regular
icon: 'fluent:app-store-24-regular'
},
children: [
{

View File

@ -1,4 +1,3 @@
import { Dashboard } from '@vicons/carbon';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { BasicLayout } from '@/layouts';
@ -15,7 +14,7 @@ const DASHBOARD: CustomRoute = {
redirect: { name: ROUTE_NAME_MAP.get('dashboard_analysis') },
meta: {
title: EnumRouteTitle.dashboard,
icon: Dashboard
icon: 'carbon:dashboard'
},
children: [
ROUTE_HOME,

View File

@ -1,4 +1,3 @@
import { Document } from '@vicons/carbon';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { BasicLayout } from '@/layouts';
@ -19,7 +18,7 @@ const DOCUMENT: CustomRoute = {
meta: {
requiresAuth: true,
title: EnumRouteTitle.document,
icon: Document
icon: 'carbon:document'
},
children: [
{

View File

@ -1,4 +1,3 @@
import { ExceptionOutlined } from '@vicons/antd';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { BasicLayout } from '@/layouts';
@ -19,7 +18,7 @@ const EXCEPTION: CustomRoute = {
meta: {
requiresAuth: true,
title: EnumRouteTitle.exception,
icon: ExceptionOutlined
icon: 'ant-design:exception-outlined'
},
children: [
{

View File

@ -1,4 +1,3 @@
import { Menu } from '@vicons/carbon';
import type { CustomRoute } from '@/interface';
import { EnumRoutePath, EnumRouteTitle } from '@/enum';
import { BasicLayout, BasicChildLayout } from '@/layouts';
@ -14,7 +13,7 @@ const MULTI_MENU: CustomRoute = {
redirect: { name: ROUTE_NAME_MAP.get('multi-menu_first') },
meta: {
title: EnumRouteTitle['multi-menu'],
icon: Menu
icon: 'carbon:menu'
},
children: [
{

View File

@ -75,7 +75,7 @@
},
"crumbsStyle": {
"visible": true,
"showIcon": false
"showIcon": true
},
"pageStyle": {
"animate": true,

View File

@ -66,7 +66,7 @@ const defaultThemeSettings: ThemeSettings = {
},
crumbsStyle: {
visible: true,
showIcon: false
showIcon: true
},
pageStyle: {
animate: true,

View File

@ -1,12 +1,19 @@
import { h } from 'vue';
import type { Component } from 'vue';
import { NIcon } from 'naive-ui';
import { Icon } from '@iconify/vue';
/** 动态渲染vicon */
export function dynamicIconRender(icon: Component) {
return () => {
return h(NIcon, null, {
default: () => h(icon)
});
};
/**
* iconify
* @param icon -
* @param color -
* @param size -
*/
export function iconifyRender(icon: string, color?: string, size?: number) {
const style: { color?: string; size?: string } = {};
if (color) {
style.color = color;
}
if (size) {
style.size = `${size}px`;
}
return () => h(Icon, { icon, style });
}

View File

@ -1,6 +1,5 @@
import type { Component } from 'vue';
import type { CustomRoute, GlobalMenuOption } from '@/interface';
import { dynamicIconRender } from '@/utils';
import { iconifyRender } from '@/utils';
/** 判断路由是否作为菜单 */
function asMenu(route: CustomRoute) {
@ -8,10 +7,10 @@ function asMenu(route: CustomRoute) {
}
/** 给菜单添加可选属性 */
function addPartialProps(menuItem: GlobalMenuOption, icon?: Component, children?: GlobalMenuOption[]) {
function addPartialProps(menuItem: GlobalMenuOption, icon?: string, children?: GlobalMenuOption[]) {
const item = { ...menuItem };
if (icon) {
Object.assign(item, { icon: dynamicIconRender(icon) });
Object.assign(item, { icon: iconifyRender(icon) });
}
if (children) {
Object.assign(item, { children });

View File

@ -4,7 +4,7 @@
<gradient-bg class="h-100px" :start-color="item.colors[0]" :end-color="item.colors[1]">
<h3 class="text-16px">{{ item.title }}</h3>
<div class="flex justify-between pt-12px">
<component :is="item.icon" class="text-32px" />
<Icon :icon="item.icon" class="text-32px" />
<count-to
:prefix="item.unit"
:start-value="1"
@ -18,12 +18,9 @@
</template>
<script setup lang="ts">
import type { VNodeChild } from 'vue';
import { NGrid, NGridItem } from 'naive-ui';
import { BarChartOutlined, MoneyCollectOutlined, TrademarkOutlined } from '@vicons/antd';
import { DocumentDownload } from '@vicons/carbon';
import { Icon } from '@iconify/vue';
import { CountTo } from '@/components';
import { dynamicIconRender } from '@/utils';
import { GradientBg } from './components';
interface CardData {
@ -32,7 +29,7 @@ interface CardData {
value: number;
unit: string;
colors: [string, string];
icon: () => VNodeChild;
icon: string;
}
const cardData: CardData[] = [
@ -42,7 +39,7 @@ const cardData: CardData[] = [
value: 1000000,
unit: '',
colors: ['#ec4786', '#b955a4'],
icon: dynamicIconRender(BarChartOutlined)
icon: 'ant-design:bar-chart-outlined'
},
{
id: 'amount',
@ -50,7 +47,7 @@ const cardData: CardData[] = [
value: 234567.89,
unit: '$',
colors: ['#865ec0', '#5144b4'],
icon: dynamicIconRender(MoneyCollectOutlined)
icon: 'ant-design:money-collect-outlined'
},
{
id: 'download',
@ -58,7 +55,7 @@ const cardData: CardData[] = [
value: 666666,
unit: '',
colors: ['#56cdf3', '#719de3'],
icon: dynamicIconRender(DocumentDownload)
icon: 'carbon:document-download'
},
{
id: 'trade',
@ -66,7 +63,7 @@ const cardData: CardData[] = [
value: 999999,
unit: '',
colors: ['#fcbc25', '#f68057'],
icon: dynamicIconRender(TrademarkOutlined)
icon: 'ant-design:trademark-circle-outlined'
}
];
</script>

View File

@ -3,13 +3,13 @@
<div class="flex-y-center justify-between">
<div class="flex-y-center">
<img src="@/assets/svg/avatar/avatar01.svg" alt="" class="w-70px h-70px" />
<div class="pl-12px whitespace-nowrap">
<div class="pl-12px">
<h3 class="text-18px font-semibold">早安{{ auth.userInfo.userName }}, 今天又是充满活力的一天</h3>
<p class="leading-30px text-[#999]">今日多云转晴20 - 25</p>
</div>
</div>
<n-space :size="36">
<n-statistic v-for="item in statisticData" :key="item.id" v-bind="item"></n-statistic>
<n-space :size="24" :wrap="false">
<n-statistic v-for="item in statisticData" :key="item.id" class="whitespace-nowrap" v-bind="item"></n-statistic>
</n-space>
</div>
</n-card>

View File

@ -0,0 +1,32 @@
<template>
<div
class="
flex-col-center
p-12px
border-1px border-[#efeff5]
dark:border-[#ffffff17]
rounded-4px
hover:shadow-sm
cursor-pointer
"
>
<Icon :icon="icon" :style="{ color: iconColor }" class="text-30px" />
<p class="py-8px text-16px">{{ label }}</p>
</div>
</template>
<script setup lang="ts">
import { Icon } from '@iconify/vue';
interface Props {
/** 快捷操作名称 */
label: string;
/** 图标 */
icon: string;
/** 图标颜色 */
iconColor: string;
}
defineProps<Props>();
</script>
<style scoped></style>

View File

@ -0,0 +1,32 @@
<template>
<div class="p-4px border-1px border-[#efeff5] dark:border-[#ffffff17] rounded-4px hover:shadow-sm cursor-pointer">
<header class="flex-y-center">
<Icon :icon="icon" :style="{ color: iconColor }" class="text-30px" />
<h3 class="pl-12px text-18px font-semibold">{{ name }}</h3>
</header>
<p class="py-8px h-56px text-[#999]">{{ description }}</p>
<div class="flex justify-end">
<span>{{ author }}</span>
</div>
</div>
</template>
<script setup lang="ts">
import { Icon } from '@iconify/vue';
interface Props {
/** 技术名称 */
name: string;
/** 技术描述 */
description: string;
/** 技术作者 */
author: string;
/** 技术图标 */
icon: string;
/** 图标颜色 */
iconColor?: string;
}
defineProps<Props>();
</script>
<style scoped></style>

View File

@ -0,0 +1,4 @@
import TechnologyCard from './TechnologyCard.vue';
import ShortcutsCard from './ShortcutsCard.vue';
export { TechnologyCard, ShortcutsCard };

View File

@ -1,29 +1,145 @@
<template>
<n-grid cols="s:1 m:2" responsive="screen" :x-gap="16" :y-gap="16">
<n-grid-item>
<n-grid :item-responsive="true" responsive="screen" :x-gap="16" :y-gap="16">
<n-grid-item span="s:24 m:16">
<n-space :vertical="true" :size="16">
<n-card title="项目" :bordered="false" size="small" class="shadow-sm rounded-16px">
<n-card title="项目主要技术栈" :bordered="false" size="small" class="shadow-sm rounded-16px">
<template #header-extra>
<a class="g_text-primary" href="javascript:;">全部项目</a>
<a class="g_text-primary" href="javascript:;">更多技术栈</a>
</template>
<n-grid :item-responsive="true" responsive="screen" cols="m:2 l:3" :x-gap="8" :y-gap="8">
<n-grid-item v-for="item in technology" :key="item.id">
<technology-card v-bind="item" />
</n-grid-item>
</n-grid>
</n-card>
<n-card title="动态" :bordered="false" size="small" class="shadow-sm rounded-16px">
<template #header-extra>
<a class="g_text-primary" href="javascript:;">更多动态</a>
</template>
<n-list>
<n-list-item v-for="item in activity" :key="item.id">
<template #prefix>
<div class="w-48px h-48px">
<img src="@/assets/svg/avatar/avatar01.svg" alt="" class="wh-full" />
</div>
</template>
<n-thing :title="item.content" :description="item.time" />
</n-list-item>
</n-list>
</n-card>
</n-space>
</n-grid-item>
<n-grid-item>
<n-grid-item span="s:24 m:8">
<n-space :vertical="true" :size="16">
<n-card title="快捷操作" :bordered="false" size="small" class="shadow-sm rounded-16px"></n-card>
<n-card title="XX指数" :bordered="false" size="small" class="shadow-sm rounded-16px"></n-card>
<n-card title="快捷操作" :bordered="false" size="small" class="shadow-sm rounded-16px">
<n-grid :item-responsive="true" responsive="screen" cols="m:2 l:3" :x-gap="8" :y-gap="8">
<n-grid-item v-for="item in shortcuts" :key="item.id">
<shortcuts-card v-bind="item" />
</n-grid-item>
</n-grid>
</n-card>
<n-card title="创意" :bordered="false" size="small" class="shadow-sm rounded-16px">
<n-carousel :autoplay="true" :show-arrow="true">
<banner-svg type="1" />
<banner-svg type="2" />
<banner-svg type="3" />
</n-carousel>
</n-card>
</n-space>
</n-grid-item>
</n-grid>
</template>
<script setup lang="ts">
import { NGrid, NGridItem, NSpace, NCard } from 'naive-ui';
import { NGrid, NGridItem, NSpace, NCard, NList, NListItem, NThing, NCarousel } from 'naive-ui';
import { BannerSvg } from '@/components';
import { TechnologyCard, ShortcutsCard } from './components';
interface Technology {
id: number;
name: string;
description: string;
author: string;
icon: string;
iconColor?: string;
}
interface Activity {
id: number;
content: string;
time: string;
}
interface Shortcuts {
id: number;
label: string;
icon: string;
iconColor: string;
}
const technology: Technology[] = [
{
id: 0,
name: 'Vue',
description: '一套用于构建用户界面的渐进式框架',
author: '尤雨溪 - Evan You',
icon: 'vscode-icons:file-type-vue'
},
{
id: 1,
name: 'TypeScript',
description: 'JavaScript类型的超集它可以编译成纯JavaScript',
author: '微软 - Microsoft',
icon: 'vscode-icons:file-type-typescript-official'
},
{
id: 2,
name: 'Vite',
description: '下一代前端开发与构建工具',
author: '尤雨溪 - Evan You',
icon: 'vscode-icons:file-type-vite'
},
{
id: 3,
name: 'NaiveUI',
description: '一个 Vue 3 组件库',
author: '图森未来 - TuSimple',
icon: 'mdi:alpha-n-box-outline',
iconColor: '#5fbc22'
},
{
id: 4,
name: 'WindiCSS',
description: '下一代实用优先的CSS框架',
author: 'Windicss',
icon: 'file-icons:windi',
iconColor: '#48b0f1'
},
{
id: 5,
name: 'Pinia',
description: 'vue状态管理框架支持vue2、vue3',
author: 'Posva',
icon: 'mdi:fruit-pineapple',
iconColor: '#fecf48'
}
];
const activity: Activity[] = [
{ id: 4, content: 'Soybean 刚才把工作台页面随便写了一些,凑合能看了!', time: '2021-11-07 22:45:32' },
{ id: 3, content: 'Soybean 正在忙于为soybean-admin写项目说明文档', time: '2021-11-03 20:33:31' },
{ id: 2, content: 'Soybean 准备为soybean-admin 1.0的发布做充分的准备工作!', time: '2021-10-31 22:43:12' },
{ id: 1, content: '@yanbowe 向soybean-admin提交了一个bug多标签栏不会自适应。', time: '2021-10-27 10:24:54' },
{ id: 0, content: 'Soybean 在2021年5月28日创建了开源项目soybean-admin', time: '2021-05-28 22:22:22' }
];
const shortcuts: Shortcuts[] = [
{ id: 0, label: '主控台', icon: 'mdi:desktop-mac-dashboard', iconColor: '#409eff' },
{ id: 1, label: '系统管理', icon: 'ic:outline-settings', iconColor: '#7238d1' },
{ id: 2, label: '权限管理', icon: 'mdi:family-tree', iconColor: '#f56c6c' },
{ id: 3, label: '组件', icon: 'ion:layers', iconColor: '#8aca6b' },
{ id: 4, label: '表格', icon: 'mdi:table-large', iconColor: '#fab251' },
{ id: 5, label: '图表', icon: 'mdi:chart-areaspline', iconColor: '#1890ff' }
];
</script>
<style scoped></style>

View File

@ -15,6 +15,7 @@ export default defineConfig({
'wh-full': 'w-full h-full',
'center-layout': 'w-1280px mx-auto px-15px',
'flex-center': 'flex justify-center items-center',
'flex-col-center': 'flex flex-col justify-center items-center',
'flex-x-center': 'flex justify-center',
'flex-y-center': 'flex items-center',
'inline-flex-center': 'inline-flex justify-center items-center',