共享组件启动

This commit is contained in:
2025-12-06 17:04:49 +08:00
parent 39579ff75f
commit fd02caf921
14 changed files with 296 additions and 4 deletions

View File

@@ -0,0 +1,34 @@
<template>
<router-view />
</template>
<script setup lang="ts">
// 根组件只包含路由视图,布局和样式由 DefaultLayout 组件处理
</script>
<style>
/* 全局样式 */
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
line-height: 1.6;
}
/* 全局链接样式 */
a {
color: #2c3e50;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* 响应式设计 */
@media (max-width: 768px) {
.app-layout {
padding: 0 12px;
}
}
</style>

View File

@@ -0,0 +1,12 @@
<template>
<div>
</div>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,9 @@
<template>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1 @@
export { default as FileUpload } from './FileUpload.vue'

View File

@@ -0,0 +1 @@
export * from './fileupload'

View File

@@ -0,0 +1,39 @@
<template>
<div class="app-layout">
<header>
<h1>Shared Components Demo</h1>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/fileupload">FileUpload Demo</router-link>
</nav>
</header>
<main>
<router-view />
</main>
</div>
</template>
<style scoped>
.app-layout {
max-width: 1200px;
margin: 0 auto;
padding: 0 16px;
}
header {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #eaeaea;
}
nav {
margin: 12px 0;
}
nav a {
margin-right: 16px;
color: #2c3e50;
text-decoration: none;
}
nav a.router-link-exact-active {
color: #42b983;
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,5 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')

View File

@@ -0,0 +1,121 @@
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { defineAsyncComponent } from 'vue'
// 扩展 ImportMeta 接口
declare global {
interface ImportMeta {
glob: (pattern: string) => Record<string, () => Promise<any>>
}
}
// 定义路由项类型
interface RouteItem {
path: string
name: string
}
// 布局组件
const DefaultLayout = defineAsyncComponent(
() => import('../layouts/DefaultLayout.vue')
)
// 首页组件
const Home = {
props: {
routes: {
type: Array as () => RouteItem[],
required: true
}
},
template: `
<div>
<h2>Welcome</h2>
<p>This is the shared components demo home.</p>
<ul>
<li v-for="route in routes" :key="route.path">
<router-link :to="route.path">
{{ route.path === '/' ? 'Home' : route.path.slice(1) }}
</router-link>
</li>
</ul>
</div>
`
}
// 生成路由配置
const routes: RouteRecordRaw[] = [
{
path: '/',
component: DefaultLayout,
children: [
{
path: '',
component: Home,
props: {
routes: [] as RouteItem[]
}
}
]
}
]
// 自动导入所有以 Test.vue 结尾的组件
const testComponents = import.meta.glob('../components/**/*Test.vue')
// 为每个测试组件创建路由
Object.entries(testComponents).forEach(([path, component]) => {
// 从路径中提取路由路径
// 例如: ../components/fileupload/FileUploadTest.vue -> /fileupload
const routePath = path
.replace('../components/', '/') // 移除相对路径
.replace(/\/\w+Test\.vue$/, '') // 移除 Test.vue 部分
.toLowerCase() // 统一小写
const routeName = routePath.slice(1) || 'home'
const routeConfig: RouteRecordRaw = {
path: routePath,
name: routeName,
component: DefaultLayout,
children: [
{
path: '',
name: `${routeName}-content`,
component: defineAsyncComponent(component as any),
meta: { title: `${routeName} Demo` }
}
]
}
// 添加路由
if (routePath === '/') {
// 如果是根路径,合并到现有路由
const rootRoute = routes[0]
if (rootRoute.children) {
rootRoute.children.push(...routeConfig.children!)
}
} else {
routes.push(routeConfig)
}
// 将路由添加到首页的 props 中
const homeRoute = routes[0]
if (homeRoute.props && typeof homeRoute.props === 'object' && !Array.isArray(homeRoute.props)) {
const props = homeRoute.props as { routes: RouteItem[] }
props.routes.push({
path: routePath,
name: routeName
})
}
})
const router = createRouter({
history: createWebHistory(),
routes
})
// 设置页面标题
router.beforeEach((to) => {
document.title = (to.meta.title as string) || 'Component Demo'
})
export default router

View File

@@ -0,0 +1,12 @@
/* eslint-disable */
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
declare module '*.md' {
import type { ComponentOptions } from 'vue'
const Component: ComponentOptions
export default Component
}