Compare commits
37 Commits
bc15f9dd4c
...
main
Author | SHA1 | Date | |
---|---|---|---|
383d8deead | |||
fcf09d887b | |||
145baf5e16 | |||
866145591f | |||
33528d64a7 | |||
30559d749e | |||
57d07d3cd0 | |||
11f4587681 | |||
669cd7070f | |||
5487dc321e | |||
ec4906f441 | |||
ad8c187edd | |||
997df3a4d4 | |||
42560a4f2c | |||
8f9593957a | |||
0d26da85a1 | |||
a831d12cf8 | |||
55a634db68 | |||
ec7c877c93 | |||
382c0b79d0 | |||
167e9a55c1 | |||
3dcba6a1ef | |||
416faf42bf | |||
25f923e0c9 | |||
624984e8c0 | |||
8cd623996a | |||
c96a6ba984 | |||
6159caec26 | |||
4181110167 | |||
d359929003 | |||
6f2550a933 | |||
393cc3d9df | |||
7d1a250e06 | |||
0636256a32 | |||
e45fb54e92 | |||
c8db9d36da | |||
333d2e47fd |
9
.github/copilot-instructions.md
vendored
9
.github/copilot-instructions.md
vendored
@ -1,4 +1,11 @@
|
||||
# Project Conventions and Technical Guidelines
|
||||
---
|
||||
description:
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
# GitHub Copilot Instructions
|
||||
|
||||
本文件定义了项目的代码生成规范,GitHub Copilot 和其他 AI 助手应遵循这些指令。
|
||||
|
||||
This document outlines the core technical choices, coding conventions, and configuration details for this project. Adhering to these guidelines ensures consistency and leverages the project's setup effectively.
|
||||
|
||||
|
2
.github/workflows/lint.yaml
vendored
2
.github/workflows/lint.yaml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 🛠️ 设置Node环境
|
||||
uses: yanhao98/composite-actions/setup-node-environment@3bf07469124a5a7b9a06b6d07be36a116c5aa49e
|
||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
||||
- name: 🔍 静态代码分析
|
||||
run: pnpm run lint
|
||||
- name: 📦 构建项目
|
||||
|
8
.github/workflows/playwright.yaml
vendored
8
.github/workflows/playwright.yaml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
url: ${{ steps.surge_deploy.outputs.url }}
|
||||
steps:
|
||||
- name: ⚙️ 设置 Node 环境
|
||||
uses: yanhao98/composite-actions/setup-node-environment@3bf07469124a5a7b9a06b6d07be36a116c5aa49e
|
||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
||||
- name: 🔨 构建项目
|
||||
run: pnpm run build-only
|
||||
env:
|
||||
@ -30,15 +30,15 @@ jobs:
|
||||
- name: 🚀 部署到 Surge
|
||||
id: surge_deploy
|
||||
if: ${{ github.actor != 'nektos/act' }} # https://nektosact.com/usage/index.html#skipping-steps
|
||||
uses: yanhao98/composite-actions/deploy-dist-to-surge@3bf07469124a5a7b9a06b6d07be36a116c5aa49e
|
||||
uses: yanhao98/composite-actions/deploy-dist-to-surge@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
||||
|
||||
playwright:
|
||||
needs: surge
|
||||
runs-on: ubuntu-latest
|
||||
container: mcr.microsoft.com/playwright:v1.53.1-noble
|
||||
container: mcr.microsoft.com/playwright:v1.53.2-noble
|
||||
steps:
|
||||
- name: ⚙️ 设置 Node 环境
|
||||
uses: yanhao98/composite-actions/setup-node-environment@3bf07469124a5a7b9a06b6d07be36a116c5aa49e
|
||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
||||
# - name: 📥 安装 Playwright 浏览器
|
||||
# run: pnpm exec playwright install --with-deps
|
||||
- name: ▶️ 运行 Playwright 测试
|
||||
|
2
.github/workflows/vercel.yaml
vendored
2
.github/workflows/vercel.yaml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: ⚙️ 设置 Node 环境
|
||||
uses: yanhao98/composite-actions/setup-node-environment@3bf07469124a5a7b9a06b6d07be36a116c5aa49e
|
||||
uses: yanhao98/composite-actions/setup-node-environment@b4a2caa64aca72f8aeada59d0df3181a12df8268
|
||||
|
||||
- name: 📥 拉取 Vercel 环境信息
|
||||
run: pnpm dlx vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}
|
||||
|
64
package.json
64
package.json
@ -49,16 +49,16 @@
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
||||
"@pinia/colada": "^0.17.1",
|
||||
"@primeuix/themes": "^1.1.2",
|
||||
"@splinetool/runtime": "^1.10.16",
|
||||
"@splinetool/runtime": "^1.10.22",
|
||||
"@types/p5": "^1.7.6",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@unhead/vue": "^2.0.11",
|
||||
"@unhead/vue": "^2.0.12",
|
||||
"@vant/use": "^1.6.0",
|
||||
"@vueuse/core": "^13.4.0",
|
||||
"alova": "^3.3.3",
|
||||
"@vueuse/core": "^13.5.0",
|
||||
"alova": "^3.3.4",
|
||||
"ant-design-vue": "~4.2.6",
|
||||
"axios": "^1.10.0",
|
||||
"cesium": "^1.130.1",
|
||||
"cesium": "^1.131.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"consola": "^3.4.2",
|
||||
@ -71,26 +71,26 @@
|
||||
"p5": "^2.0.3",
|
||||
"page-stack-vue3": "^2.5.6",
|
||||
"pinia": "^3.0.3",
|
||||
"pinia-plugin-persistedstate": "^4.4.0",
|
||||
"pinia-plugin-persistedstate": "^4.4.1",
|
||||
"plotly.js-dist-min": "^3.0.1",
|
||||
"primeicons": "^7.0.0",
|
||||
"primelocale": "^2.1.4",
|
||||
"primevue": "^4.3.5",
|
||||
"radash": "^12.1.1",
|
||||
"radix-vue": "^1.9.17",
|
||||
"reka-ui": "^2.3.1",
|
||||
"satellite.js": "^6.0.0",
|
||||
"reka-ui": "^2.3.2",
|
||||
"satellite.js": "^6.0.1",
|
||||
"sortablejs": "^1.15.6",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tdesign-icons-vue-next": "^0.3.6",
|
||||
"three": "^0.177.0",
|
||||
"three": "^0.178.0",
|
||||
"ts-enum-util": "^4.1.0",
|
||||
"utils4u": "^4.2.3",
|
||||
"vant": "^4.9.20",
|
||||
"vue": "^3.5.17",
|
||||
"vue-data-ui": "^2.12.6",
|
||||
"vue-data-ui": "^2.12.7",
|
||||
"vue-draggable-plus": "^0.6.0",
|
||||
"vue-i18n": "^11.1.7",
|
||||
"vue-i18n": "^11.1.9",
|
||||
"vue-page-stack": "^3.2.0",
|
||||
"vue-router": "^4.5.1"
|
||||
},
|
||||
@ -98,67 +98,69 @@
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@commitlint/config-conventional": "^19.8.1",
|
||||
"@eslint/compat": "^1.3.1",
|
||||
"@faker-js/faker": "^9.8.0",
|
||||
"@faker-js/faker": "^9.9.0",
|
||||
"@iconify-json/carbon": "^1.2.10",
|
||||
"@iconify-json/logos": "^1.2.4",
|
||||
"@iconify-json/mdi": "^1.2.3",
|
||||
"@iconify/utils": "^2.3.0",
|
||||
"@playwright/test": "^1.53.1",
|
||||
"@playwright/test": "^1.53.2",
|
||||
"@primevue/auto-import-resolver": "^4.3.5",
|
||||
"@tsconfig/node22": "^22.0.2",
|
||||
"@types/archiver": "^6.0.3",
|
||||
"@types/mockjs": "^1.0.10",
|
||||
"@types/node": "^22.15.34",
|
||||
"@types/node": "^22.16.3",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/plotly.js-dist-min": "^2.3.4",
|
||||
"@types/three": "^0.177.0",
|
||||
"@types/three": "^0.178.1",
|
||||
"@vant/auto-import-resolver": "^1.3.0",
|
||||
"@vitejs/plugin-vue": "^6.0.0",
|
||||
"@vitejs/plugin-vue-jsx": "^5.0.0",
|
||||
"@vitest/eslint-plugin": "^1.3.3",
|
||||
"@vitejs/plugin-vue-jsx": "^5.0.1",
|
||||
"@vitest/eslint-plugin": "^1.3.4",
|
||||
"@vue/eslint-config-prettier": "^10.2.0",
|
||||
"@vue/eslint-config-typescript": "^14.5.1",
|
||||
"@vue/eslint-config-typescript": "^14.6.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/tsconfig": "^0.7.0",
|
||||
"archiver": "^7.0.1",
|
||||
"depcheck": "^1.4.7",
|
||||
"eruda": "^3.4.3",
|
||||
"eslint": "^9.30.0",
|
||||
"eslint": "^9.30.1",
|
||||
"eslint-plugin-import-x": "^4.16.1",
|
||||
"eslint-plugin-oxlint": "^1.3.0",
|
||||
"eslint-plugin-oxlint": "^1.6.0",
|
||||
"eslint-plugin-perfectionist": "^4.15.0",
|
||||
"eslint-plugin-unicorn": "^59.0.1",
|
||||
"eslint-plugin-vue": "^10.2.0",
|
||||
"eslint-plugin-vue": "^10.3.0",
|
||||
"husky": "^9.1.7",
|
||||
"less": "^4.3.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"mockjs": "^1.1.0",
|
||||
"naive-ui": "^2.42.0",
|
||||
"npm-run-all2": "^8.0.4",
|
||||
"oxlint": "^1.3.0",
|
||||
"oxlint": "^1.6.0",
|
||||
"prettier": "3.6.2",
|
||||
"typescript": "~5.8.3",
|
||||
"unocss": "66.3.2",
|
||||
"unocss": "66.3.3",
|
||||
"unocss-preset-animations": "^1.2.1",
|
||||
"unocss-preset-chinese": "^0.3.3",
|
||||
"unocss-preset-shadcn": "^0.5.0",
|
||||
"unplugin-auto-import": "^19.3.0",
|
||||
"unplugin-icons": "^22.1.0",
|
||||
"unplugin-vue-components": "^28.7.0",
|
||||
"unplugin-vue-components": "^28.8.0",
|
||||
"unplugin-vue-macros": "^2.14.5",
|
||||
"unplugin-vue-markdown": "^29.0.0",
|
||||
"unplugin-vue-router": "^0.12.0",
|
||||
"vite": "^7.0.0",
|
||||
"vite-plugin-checker": "^0.9.3",
|
||||
"unplugin-vue-markdown": "^29.1.0",
|
||||
"unplugin-vue-router": "^0.14.0",
|
||||
"vfonts": "^0.0.3",
|
||||
"vite": "^7.0.2",
|
||||
"vite-plugin-checker": "^0.10.0",
|
||||
"vite-plugin-fake-server": "^2.2.0",
|
||||
"vite-plugin-image-tools": "^2.0.2",
|
||||
"vite-plugin-purgecss-updated-v5": "^1.2.6",
|
||||
"vite-plugin-singlefile": "^2.2.0",
|
||||
"vite-plugin-singlefile": "^2.3.0",
|
||||
"vite-plugin-static-copy": "^3.1.0",
|
||||
"vite-plugin-vue-devtools": "^7.7.7",
|
||||
"vite-plugin-vue-layouts": "^0.11.0",
|
||||
"vite-plugin-vue-meta-layouts": "^0.5.1",
|
||||
"vite-plugin-webfont-dl": "^3.10.5",
|
||||
"vue-component-type-helpers": "^2.2.10",
|
||||
"vue-tsc": "^2.2.10"
|
||||
"vue-component-type-helpers": "^3.0.1",
|
||||
"vue-tsc": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
1669
pnpm-lock.yaml
generated
1669
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -15,9 +15,11 @@ const themeConfig = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider :theme="themeConfig">
|
||||
<RouterView />
|
||||
</a-config-provider>
|
||||
<n-config-provider preflight-style-disabled>
|
||||
<a-config-provider :theme="themeConfig">
|
||||
<RouterView />
|
||||
</a-config-provider>
|
||||
</n-config-provider>
|
||||
|
||||
<DynamicDialog /> <ConfirmDialog /> <Toast />
|
||||
</template>
|
||||
|
321
src/layouts/naive-ui/AppLayout.vue
Normal file
321
src/layouts/naive-ui/AppLayout.vue
Normal file
@ -0,0 +1,321 @@
|
||||
<script setup lang="ts">
|
||||
import type { MenuOption } from 'naive-ui';
|
||||
|
||||
import { createGetRoutes } from '@/plugins/router';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 响应式断点检测
|
||||
const isMobile = ref(false);
|
||||
const isTablet = ref(false);
|
||||
|
||||
// 检测屏幕尺寸
|
||||
const updateScreenSize = () => {
|
||||
const width = window.innerWidth;
|
||||
const wasMobile = isMobile.value;
|
||||
|
||||
isMobile.value = width < 768;
|
||||
isTablet.value = width >= 768 && width < 1024;
|
||||
|
||||
// 当从移动端切换到桌面端时,关闭抽屉并重置折叠状态
|
||||
if (wasMobile && !isMobile.value) {
|
||||
drawerVisible.value = false;
|
||||
collapsed.value = false;
|
||||
}
|
||||
// 当从桌面端切换到移动端时,关闭抽屉
|
||||
else if (!wasMobile && isMobile.value) {
|
||||
drawerVisible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 侧边栏状态管理
|
||||
const collapsed = ref(false);
|
||||
const drawerVisible = ref(false);
|
||||
|
||||
// 初始化屏幕尺寸检测
|
||||
onMounted(() => {
|
||||
updateScreenSize();
|
||||
window.addEventListener('resize', updateScreenSize);
|
||||
|
||||
// 移动端默认收起侧边栏
|
||||
if (isMobile.value) {
|
||||
collapsed.value = true;
|
||||
drawerVisible.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', updateScreenSize);
|
||||
});
|
||||
|
||||
// 菜单项类型定义
|
||||
type MenuItemWithRoute = MenuOption & {
|
||||
routeName?: string;
|
||||
parentId?: string;
|
||||
originalPath?: string;
|
||||
};
|
||||
|
||||
// 生成菜单项
|
||||
const menuOptions = computed(() => {
|
||||
let flatArray: MenuItemWithRoute[] = createGetRoutes(router)()
|
||||
.filter((route) => !route.path.includes('/:'))
|
||||
.filter((route) => !route.meta.hidden)
|
||||
.map((route) => ({
|
||||
key: route.path,
|
||||
label: route.meta.title || `${(route.name as string) || route.path}`,
|
||||
routeName: route.name as string,
|
||||
}));
|
||||
|
||||
flatArray = flatArray.map((item) => {
|
||||
const originalPath = item.key as string; // 保存原始路径
|
||||
let id = item.key as string;
|
||||
if (flatArray.some((item) => (item.key as string).startsWith(`${id}/`))) {
|
||||
id = `${id}/index`;
|
||||
}
|
||||
// 去掉最前面的 /
|
||||
id = id.replace(/^\//, '');
|
||||
|
||||
let parentId = id.replace(/\/[^/]+$/, '');
|
||||
if (parentId === id) {
|
||||
parentId = '_ROOT_';
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
key: id,
|
||||
parentId,
|
||||
originalPath, // 保存原始路径用于后续映射
|
||||
};
|
||||
});
|
||||
|
||||
const groupItems: MenuItemWithRoute[] = [];
|
||||
for (const flatArrayItem of flatArray) {
|
||||
if (!groupItems.some((item) => item.key === flatArrayItem.parentId) && flatArrayItem.parentId !== '_ROOT_') {
|
||||
let groupItemParentId = flatArrayItem.parentId!.replace(/\/[^/]+$/, '');
|
||||
if (groupItemParentId === flatArrayItem.parentId) groupItemParentId = '_ROOT_';
|
||||
groupItems.push({
|
||||
key: flatArrayItem.parentId!,
|
||||
label: `Group ${flatArrayItem.parentId}`,
|
||||
parentId: groupItemParentId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const tree = arrayToTree([...flatArray, ...groupItems], {
|
||||
id: 'key',
|
||||
parentId: 'parentId',
|
||||
rootId: '_ROOT_',
|
||||
});
|
||||
|
||||
// 递归转换树形结构为 naive-ui menu 格式
|
||||
function convertToMenuOptions(tree: MenuItemWithRoute[]): MenuOption[] {
|
||||
return tree.map((item) => {
|
||||
const menuItem: MenuOption = {
|
||||
key: item.key,
|
||||
label: item.label,
|
||||
};
|
||||
|
||||
if (item.children && item.children.length > 0) {
|
||||
menuItem.children = convertToMenuOptions(item.children);
|
||||
} else if (item.routeName) {
|
||||
// 叶子节点,存储路由映射
|
||||
menuRouteMap.set(item.key as string, item.routeName);
|
||||
// 同时存储路径到 key 的映射(用于高亮显示)
|
||||
if (item.originalPath) {
|
||||
pathToKeyMap.set(item.originalPath, item.key as string);
|
||||
}
|
||||
(menuItem as MenuItemWithRoute).routeName = item.routeName;
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
});
|
||||
}
|
||||
|
||||
// 清空之前的映射
|
||||
menuRouteMap.clear();
|
||||
pathToKeyMap.clear();
|
||||
const result = convertToMenuOptions(tree);
|
||||
|
||||
// 菜单生成后,重新设置当前选中的菜单项
|
||||
nextTick(() => {
|
||||
const currentPath = router.currentRoute.value.path;
|
||||
const menuKey = pathToKeyMap.get(currentPath);
|
||||
if (menuKey) {
|
||||
selectedKey.value = menuKey;
|
||||
} else {
|
||||
const pathWithoutSlash = currentPath.replace(/^\//, '');
|
||||
selectedKey.value = pathWithoutSlash;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// 当前选中的菜单项
|
||||
const selectedKey = ref<string>();
|
||||
|
||||
// 存储菜单项与路由名称的映射
|
||||
const menuRouteMap = new Map<string, string>();
|
||||
|
||||
// 存储路由路径与菜单 key 的映射(用于高亮显示)
|
||||
const pathToKeyMap = new Map<string, string>();
|
||||
|
||||
// 处理菜单点击
|
||||
const handleMenuSelect = (key: string, item: MenuOption) => {
|
||||
const routeName = menuRouteMap.get(key) || (item as MenuItemWithRoute).routeName;
|
||||
if (routeName) {
|
||||
router.push({ name: routeName as never });
|
||||
|
||||
// 移动端点击菜单项后自动收起侧边栏
|
||||
if (isMobile.value) {
|
||||
drawerVisible.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 监听路由变化,更新选中的菜单项
|
||||
watch(
|
||||
() => router.currentRoute.value.path,
|
||||
(newPath) => {
|
||||
// 使用路径到 key 的映射来找到对应的菜单项
|
||||
const menuKey = pathToKeyMap.get(newPath);
|
||||
if (menuKey) {
|
||||
selectedKey.value = menuKey;
|
||||
} else {
|
||||
// 如果没有找到精确匹配,尝试去掉前面的 / 再匹配
|
||||
const pathWithoutSlash = newPath.replace(/^\//, '');
|
||||
selectedKey.value = pathWithoutSlash;
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
// 切换侧边栏状态
|
||||
const toggleSidebar = () => {
|
||||
if (isMobile.value) {
|
||||
// 移动端使用抽屉模式
|
||||
drawerVisible.value = !drawerVisible.value;
|
||||
} else {
|
||||
// 桌面端使用折叠模式
|
||||
collapsed.value = !collapsed.value;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-layout :has-sider="!isMobile">
|
||||
<!-- 移动端抽屉 -->
|
||||
<n-drawer
|
||||
v-if="isMobile"
|
||||
v-model:show="drawerVisible"
|
||||
:width="280"
|
||||
placement="left"
|
||||
:trap-focus="false"
|
||||
:block-scroll="false"
|
||||
>
|
||||
<n-drawer-content title="菜单" :native-scrollbar="false">
|
||||
<n-menu :options="menuOptions" :value="selectedKey" @update:value="handleMenuSelect" />
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
|
||||
<!-- 桌面端侧边栏 -->
|
||||
<n-layout-sider
|
||||
v-if="!isMobile"
|
||||
:collapsed="collapsed"
|
||||
:native-scrollbar="false"
|
||||
bordered
|
||||
collapse-mode="width"
|
||||
:collapsed-width="64"
|
||||
:width="240"
|
||||
show-trigger
|
||||
@collapse="collapsed = true"
|
||||
@expand="collapsed = false"
|
||||
>
|
||||
<n-menu
|
||||
:collapsed="collapsed"
|
||||
:collapsed-width="64"
|
||||
:collapsed-icon-size="22"
|
||||
:options="menuOptions"
|
||||
:value="selectedKey"
|
||||
@update:value="handleMenuSelect"
|
||||
/>
|
||||
</n-layout-sider>
|
||||
|
||||
<n-layout>
|
||||
<n-layout-header
|
||||
bordered
|
||||
:style="{
|
||||
height: '64px',
|
||||
padding: isMobile ? '0 16px' : '0 24px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}"
|
||||
>
|
||||
<n-button
|
||||
quaternary
|
||||
@click="toggleSidebar"
|
||||
:style="{
|
||||
marginRight: isMobile ? '8px' : '12px',
|
||||
padding: isMobile ? '8px' : '6px',
|
||||
}"
|
||||
:size="isMobile ? 'medium' : 'small'"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon :size="isMobile ? 20 : 18">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path
|
||||
v-if="!isMobile && collapsed"
|
||||
fill="currentColor"
|
||||
d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"
|
||||
/>
|
||||
<path
|
||||
v-else-if="!isMobile && !collapsed"
|
||||
fill="currentColor"
|
||||
d="M3 18h13v-2H3v2zm0-5h10v-2H3v2zm0-7v2h13V6H3zm18 9.59L17.42 12 21 8.41 19.59 7l-5 5 5 5L21 15.59z"
|
||||
/>
|
||||
<!-- 移动端始终显示菜单图标 -->
|
||||
<path v-else fill="currentColor" d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z" />
|
||||
</svg>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<span
|
||||
:style="{
|
||||
fontSize: isMobile ? '16px' : '18px',
|
||||
fontWeight: '500',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
}"
|
||||
>
|
||||
Vue TS Example
|
||||
</span>
|
||||
</n-layout-header>
|
||||
|
||||
<n-layout-content
|
||||
:content-style="{
|
||||
padding: isMobile ? '16px' : '24px',
|
||||
minHeight: 'calc(100vh - 64px - 72px)', // 减去头部和底部高度
|
||||
}"
|
||||
>
|
||||
<router-view />
|
||||
</n-layout-content>
|
||||
|
||||
<n-layout-footer
|
||||
bordered
|
||||
:style="{
|
||||
padding: isMobile ? '16px' : '24px',
|
||||
textAlign: 'center',
|
||||
}"
|
||||
>
|
||||
<span
|
||||
:style="{
|
||||
color: 'var(--n-text-color-disabled)',
|
||||
fontSize: isMobile ? '12px' : '14px',
|
||||
}"
|
||||
>
|
||||
© 2025 Vue TS Example. All rights reserved.
|
||||
</span>
|
||||
</n-layout-footer>
|
||||
</n-layout>
|
||||
</n-layout>
|
||||
</template>
|
11
src/pages/UI-components/NaiveUI/index.page.vue
Normal file
11
src/pages/UI-components/NaiveUI/index.page.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<n-card>
|
||||
<n-divider title-placement="left">
|
||||
<n-text depth="3"> Naive UI Components Divider </n-text>
|
||||
</n-divider>
|
||||
</n-card>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -13,4 +13,9 @@ import 'primeicons/primeicons.css';
|
||||
import './reset/reset-primevue.css';
|
||||
import './reset/reset-antdv.less';
|
||||
|
||||
// 通用字体
|
||||
import 'vfonts/Lato.css';
|
||||
// 等宽字体
|
||||
import 'vfonts/FiraCode.css';
|
||||
//
|
||||
import 'virtual:uno.css';
|
||||
|
1
typed-router.d.ts
vendored
1
typed-router.d.ts
vendored
@ -47,6 +47,7 @@ declare module 'vue-router/auto-routes' {
|
||||
'UIComponentsInfiniteLoading': RouteRecordInfo<'UIComponentsInfiniteLoading', '/UI-components/infinite-loading', Record<never, never>, Record<never, never>>,
|
||||
'UIComponentsInfiniteLoadingDetail': RouteRecordInfo<'UIComponentsInfiniteLoadingDetail', '/UI-components/infinite-loading/detail', Record<never, never>, Record<never, never>>,
|
||||
'UIComponentsInspiraUI': RouteRecordInfo<'UIComponentsInspiraUI', '/UI-components/InspiraUI', Record<never, never>, Record<never, never>>,
|
||||
'UIComponentsNaiveUI': RouteRecordInfo<'UIComponentsNaiveUI', '/UI-components/NaiveUI', Record<never, never>, Record<never, never>>,
|
||||
'UIComponentsPrimeVue': RouteRecordInfo<'UIComponentsPrimeVue', '/UI-components/PrimeVue', Record<never, never>, Record<never, never>>,
|
||||
'UIComponentsShadcnVue': RouteRecordInfo<'UIComponentsShadcnVue', '/UI-components/ShadcnVue', Record<never, never>, Record<never, never>>,
|
||||
'VueMacrosDefineRender': RouteRecordInfo<'VueMacrosDefineRender', '/VueMacros/DefineRender', Record<never, never>, Record<never, never>>,
|
||||
|
@ -11,11 +11,11 @@ import Vue from '@vitejs/plugin-vue';
|
||||
import VueJsx from '@vitejs/plugin-vue-jsx';
|
||||
import path from 'node:path';
|
||||
import UnoCSS from 'unocss/vite';
|
||||
import UnpluginAutoImport from 'unplugin-auto-import/vite';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
import { FileSystemIconLoader } from 'unplugin-icons/loaders';
|
||||
import IconsResolver from 'unplugin-icons/resolver';
|
||||
import Icons from 'unplugin-icons/vite';
|
||||
import { AntDesignVueResolver, TDesignResolver } from 'unplugin-vue-components/resolvers';
|
||||
import { AntDesignVueResolver, NaiveUiResolver, TDesignResolver } from 'unplugin-vue-components/resolvers';
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import VueMacros from 'unplugin-vue-macros/vite';
|
||||
import Markdown from 'unplugin-vue-markdown/vite';
|
||||
@ -66,7 +66,8 @@ export function Plugins() {
|
||||
|
||||
// https://github.com/dishait/vite-plugin-vue-meta-layouts
|
||||
MetaLayouts({
|
||||
defaultLayout: 'sakai-vue/AppLayout',
|
||||
// defaultLayout: 'sakai-vue/AppLayout',
|
||||
defaultLayout: 'naive-ui/AppLayout',
|
||||
skipTopLevelRouteLayout: false, // 打开修复 https://github.com/JohnCampionJr/vite-plugin-vue-layouts/issues/134,默认为 false 关闭
|
||||
}),
|
||||
|
||||
@ -80,7 +81,7 @@ export function Plugins() {
|
||||
}),
|
||||
|
||||
// https://github.com/antfu/unplugin-auto-import
|
||||
UnpluginAutoImport({
|
||||
AutoImport({
|
||||
dirs: [
|
||||
// 'src/composables',
|
||||
'src/stores',
|
||||
@ -98,6 +99,7 @@ export function Plugins() {
|
||||
{
|
||||
'consola/browser': ['consola'],
|
||||
'vue-router/auto': ['useLink'],
|
||||
'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'],
|
||||
},
|
||||
],
|
||||
resolvers: [TDesignResolver({ esm: true, library: 'mobile-vue' }), VantResolver({ importStyle: true })],
|
||||
@ -124,6 +126,7 @@ export function Plugins() {
|
||||
TDesignResolver({ esm: true, library: 'mobile-vue' }),
|
||||
VantResolver({ importStyle: true }),
|
||||
PrimeVueResolver(/* { components: { prefix: 'P' } } */),
|
||||
NaiveUiResolver(),
|
||||
],
|
||||
}),
|
||||
|
||||
|
Reference in New Issue
Block a user