diff --git a/urbanLifelineWeb/package-lock.json b/urbanLifelineWeb/package-lock.json index f691561..524d75e 100644 --- a/urbanLifelineWeb/package-lock.json +++ b/urbanLifelineWeb/package-lock.json @@ -3493,7 +3493,8 @@ "version": "1.0.0", "dependencies": { "ofetch": "^1.4.1", - "vue": "^3.5.13" + "vue": "^3.5.13", + "vue-router": "^4.2.0" }, "devDependencies": { "@originjs/vite-plugin-federation": "^1.3.6", diff --git a/urbanLifelineWeb/packages/shared/index.html b/urbanLifelineWeb/packages/shared/index.html new file mode 100644 index 0000000..f43cc28 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/index.html @@ -0,0 +1,12 @@ + + + + + + Shared Components Demo + + +
+ + + diff --git a/urbanLifelineWeb/packages/shared/package.json b/urbanLifelineWeb/packages/shared/package.json index 87b1217..092e8b8 100644 --- a/urbanLifelineWeb/packages/shared/package.json +++ b/urbanLifelineWeb/packages/shared/package.json @@ -5,6 +5,7 @@ "private": true, "scripts": { "dev": "vite", + "dev:demo": "vite", "build": "run-p build:*", "build:esm": "vite build --mode esm", "build:federation": "vite build --mode federation", @@ -12,7 +13,8 @@ }, "dependencies": { "vue": "^3.5.13", - "ofetch": "^1.4.1" + "ofetch": "^1.4.1", + "vue-router": "^4.2.0" }, "devDependencies": { "@types/node": "^20.10.0", diff --git a/urbanLifelineWeb/packages/shared/pnpm-lock.yaml b/urbanLifelineWeb/packages/shared/pnpm-lock.yaml index 5a3931b..d5487c0 100644 --- a/urbanLifelineWeb/packages/shared/pnpm-lock.yaml +++ b/urbanLifelineWeb/packages/shared/pnpm-lock.yaml @@ -5,9 +5,15 @@ settings: excludeLinksFromLockfile: false dependencies: + ofetch: + specifier: ^1.4.1 + version: 1.5.1 vue: specifier: ^3.5.13 version: 3.5.25(typescript@5.9.3) + vue-router: + specifier: ^4.2.0 + version: 4.6.3(vue@3.5.25) devDependencies: '@originjs/vite-plugin-federation': @@ -863,6 +869,10 @@ packages: '@vue/compiler-dom': 3.5.25 '@vue/shared': 3.5.25 + /@vue/devtools-api@6.6.4: + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + dev: false + /@vue/reactivity@3.5.25: resolution: {integrity: sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==} dependencies: @@ -1090,6 +1100,10 @@ packages: object-keys: 1.1.1 dev: true + /destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + dev: false + /dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1679,6 +1693,10 @@ packages: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true + /node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + dev: false + /node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} dev: true @@ -1730,6 +1748,14 @@ packages: object-keys: 1.1.1 dev: true + /ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.1 + dev: false + /own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -2149,6 +2175,10 @@ packages: engines: {node: '>=14.17'} hasBin: true + /ufo@1.6.1: + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + dev: false + /unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -2232,6 +2262,15 @@ packages: fsevents: 2.3.3 dev: true + /vue-router@4.6.3(vue@3.5.25): + resolution: {integrity: sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==} + peerDependencies: + vue: ^3.5.0 + dependencies: + '@vue/devtools-api': 6.6.4 + vue: 3.5.25(typescript@5.9.3) + dev: false + /vue@3.5.25(typescript@5.9.3): resolution: {integrity: sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==} peerDependencies: diff --git a/urbanLifelineWeb/packages/shared/src/App.vue b/urbanLifelineWeb/packages/shared/src/App.vue new file mode 100644 index 0000000..b276b96 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/App.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUpload.vue b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUpload.vue new file mode 100644 index 0000000..df1f34e --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUpload.vue @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadTest.vue b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadTest.vue new file mode 100644 index 0000000..3f462c7 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/components/fileupload/FileUploadTest.vue @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/urbanLifelineWeb/packages/shared/src/components/fileupload/index.ts b/urbanLifelineWeb/packages/shared/src/components/fileupload/index.ts new file mode 100644 index 0000000..7c158ff --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/components/fileupload/index.ts @@ -0,0 +1 @@ +export { default as FileUpload } from './FileUpload.vue' \ No newline at end of file diff --git a/urbanLifelineWeb/packages/shared/src/components/index.ts b/urbanLifelineWeb/packages/shared/src/components/index.ts new file mode 100644 index 0000000..a51d8a0 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/components/index.ts @@ -0,0 +1 @@ +export * from './fileupload' \ No newline at end of file diff --git a/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue b/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue new file mode 100644 index 0000000..5738760 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/layouts/DefaultLayout.vue @@ -0,0 +1,39 @@ + + + diff --git a/urbanLifelineWeb/packages/shared/src/main.ts b/urbanLifelineWeb/packages/shared/src/main.ts new file mode 100644 index 0000000..3e79677 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +createApp(App).use(router).mount('#app') diff --git a/urbanLifelineWeb/packages/shared/src/router/index.ts b/urbanLifelineWeb/packages/shared/src/router/index.ts new file mode 100644 index 0000000..5e71969 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/router/index.ts @@ -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 Promise> + } +} + +// 定义路由项类型 +interface RouteItem { + path: string + name: string +} + +// 布局组件 +const DefaultLayout = defineAsyncComponent( + () => import('../layouts/DefaultLayout.vue') +) + +// 首页组件 +const Home = { + props: { + routes: { + type: Array as () => RouteItem[], + required: true + } + }, + template: ` +
+

Welcome

+

This is the shared components demo home.

+
    +
  • + + {{ route.path === '/' ? 'Home' : route.path.slice(1) }} + +
  • +
+
+ ` +} + +// 生成路由配置 +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 diff --git a/urbanLifelineWeb/packages/shared/src/shims-vue.d.ts b/urbanLifelineWeb/packages/shared/src/shims-vue.d.ts new file mode 100644 index 0000000..91f80b1 --- /dev/null +++ b/urbanLifelineWeb/packages/shared/src/shims-vue.d.ts @@ -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 +} diff --git a/urbanLifelineWeb/packages/shared/vite.config.ts b/urbanLifelineWeb/packages/shared/vite.config.ts index 620b5af..70493e9 100644 --- a/urbanLifelineWeb/packages/shared/vite.config.ts +++ b/urbanLifelineWeb/packages/shared/vite.config.ts @@ -17,7 +17,11 @@ const __dirname = dirname(__filename) */ export default defineConfig({ plugins: [vue(), vueJsx()], - + define: { + __VUE_PROD_DEVTOOLS__: true, + // __VUE_OPTIONS_API__: true, // 确保启用 Options API + // __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true + }, resolve: { alias: [ { find: '@', replacement: resolve(__dirname, 'src') } @@ -98,7 +102,7 @@ export default defineConfig({ headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, OPTIONS', - 'Content-Type': 'application/javascript; charset=utf-8' + // 'Content-Type': 'application/javascript; charset=utf-8' } } })