refactor: 重构UI组件库

This commit is contained in:
2025-12-22 05:45:09 +07:00
parent de18ebf370
commit 66e2222c48
18 changed files with 38 additions and 54 deletions

52
components.d.ts vendored
View File

@@ -19,38 +19,24 @@ declare module 'vue' {
IonAvatar: typeof import('@ionic/vue')['IonAvatar'] IonAvatar: typeof import('@ionic/vue')['IonAvatar']
IonBackButton: typeof import('@ionic/vue')['IonBackButton'] IonBackButton: typeof import('@ionic/vue')['IonBackButton']
IonButton: typeof import('@ionic/vue')['IonButton'] IonButton: typeof import('@ionic/vue')['IonButton']
IonButtons: typeof import('@ionic/vue')['IonButtons']
IonCol: typeof import('@ionic/vue')['IonCol']
IonContent: typeof import('@ionic/vue')['IonContent'] IonContent: typeof import('@ionic/vue')['IonContent']
IonDatetime: typeof import('@ionic/vue')['IonDatetime'] IonDatetime: typeof import('@ionic/vue')['IonDatetime']
IonDatetimeButton: typeof import('@ionic/vue')['IonDatetimeButton'] IonDatetimeButton: typeof import('@ionic/vue')['IonDatetimeButton']
IonFooter: typeof import('@ionic/vue')['IonFooter']
IonGrid: typeof import('@ionic/vue')['IonGrid']
IonHeader: typeof import('@ionic/vue')['IonHeader'] IonHeader: typeof import('@ionic/vue')['IonHeader']
IonIcon: typeof import('@ionic/vue')['IonIcon'] IonIcon: typeof import('@ionic/vue')['IonIcon']
IonInfiniteScroll: typeof import('@ionic/vue')['IonInfiniteScroll']
IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent']
IonInput: typeof import('@ionic/vue')['IonInput']
IonItem: typeof import('@ionic/vue')['IonItem'] IonItem: typeof import('@ionic/vue')['IonItem']
IonLabel: typeof import('@ionic/vue')['IonLabel'] IonLabel: typeof import('@ionic/vue')['IonLabel']
IonList: typeof import('@ionic/vue')['IonList'] IonList: typeof import('@ionic/vue')['IonList']
IonListHeader: typeof import('@ionic/vue')['IonListHeader']
IonModal: typeof import('@ionic/vue')['IonModal'] IonModal: typeof import('@ionic/vue')['IonModal']
IonNote: typeof import('@ionic/vue')['IonNote']
IonPage: typeof import('@ionic/vue')['IonPage'] IonPage: typeof import('@ionic/vue')['IonPage']
IonRadio: typeof import('@ionic/vue')['IonRadio']
IonRadioGroup: typeof import('@ionic/vue')['IonRadioGroup']
IonRefresher: typeof import('@ionic/vue')['IonRefresher'] IonRefresher: typeof import('@ionic/vue')['IonRefresher']
IonRefresherContent: typeof import('@ionic/vue')['IonRefresherContent'] IonRefresherContent: typeof import('@ionic/vue')['IonRefresherContent']
IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet'] IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet']
IonRow: typeof import('@ionic/vue')['IonRow']
IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
IonSelect: typeof import('@ionic/vue')['IonSelect'] IonSelect: typeof import('@ionic/vue')['IonSelect']
IonSelectOption: typeof import('@ionic/vue')['IonSelectOption'] IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
IonTabBar: typeof import('@ionic/vue')['IonTabBar'] IonTabBar: typeof import('@ionic/vue')['IonTabBar']
IonTabButton: typeof import('@ionic/vue')['IonTabButton'] IonTabButton: typeof import('@ionic/vue')['IonTabButton']
IonTabs: typeof import('@ionic/vue')['IonTabs'] IonTabs: typeof import('@ionic/vue')['IonTabs']
IonText: typeof import('@ionic/vue')['IonText']
IonTitle: typeof import('@ionic/vue')['IonTitle'] IonTitle: typeof import('@ionic/vue')['IonTitle']
IonToolbar: typeof import('@ionic/vue')['IonToolbar'] IonToolbar: typeof import('@ionic/vue')['IonToolbar']
LayoutDefault: typeof import('./src/components/layout/default.vue')['default'] LayoutDefault: typeof import('./src/components/layout/default.vue')['default']
@@ -58,18 +44,6 @@ declare module 'vue' {
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default'] SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default']
UiAvatar: typeof import('./src/components/ui/avatar/index.vue')['default']
UiCollapse: typeof import('./src/components/ui/collapse/index.vue')['default']
UiDatetime: typeof import('./src/components/ui/datetime/index.vue')['default']
UiDivider: typeof import('./src/components/ui/divider/index.vue')['default']
UiFileUpload: typeof import('./src/components/ui/file-upload/index.vue')['default']
UiInput: typeof import('./src/components/ui/input/index.vue')['default']
UiInputLabel: typeof import('./src/components/ui/input-label/index.vue')['default']
UiResult: typeof import('./src/components/ui/result/index.vue')['default']
UiTabPane: typeof import('./src/components/ui/tab-pane/index.vue')['default']
UiTabs: typeof import('./src/components/ui/tabs/index.vue')['default']
UiTag: typeof import('./src/components/ui/tag/index.vue')['default']
UiTextareaLabel: typeof import('./src/components/ui/textarea-label/index.vue')['default']
} }
} }
@@ -82,38 +56,24 @@ declare global {
const IonAvatar: typeof import('@ionic/vue')['IonAvatar'] const IonAvatar: typeof import('@ionic/vue')['IonAvatar']
const IonBackButton: typeof import('@ionic/vue')['IonBackButton'] const IonBackButton: typeof import('@ionic/vue')['IonBackButton']
const IonButton: typeof import('@ionic/vue')['IonButton'] const IonButton: typeof import('@ionic/vue')['IonButton']
const IonButtons: typeof import('@ionic/vue')['IonButtons']
const IonCol: typeof import('@ionic/vue')['IonCol']
const IonContent: typeof import('@ionic/vue')['IonContent'] const IonContent: typeof import('@ionic/vue')['IonContent']
const IonDatetime: typeof import('@ionic/vue')['IonDatetime'] const IonDatetime: typeof import('@ionic/vue')['IonDatetime']
const IonDatetimeButton: typeof import('@ionic/vue')['IonDatetimeButton'] const IonDatetimeButton: typeof import('@ionic/vue')['IonDatetimeButton']
const IonFooter: typeof import('@ionic/vue')['IonFooter']
const IonGrid: typeof import('@ionic/vue')['IonGrid']
const IonHeader: typeof import('@ionic/vue')['IonHeader'] const IonHeader: typeof import('@ionic/vue')['IonHeader']
const IonIcon: typeof import('@ionic/vue')['IonIcon'] const IonIcon: typeof import('@ionic/vue')['IonIcon']
const IonInfiniteScroll: typeof import('@ionic/vue')['IonInfiniteScroll']
const IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent']
const IonInput: typeof import('@ionic/vue')['IonInput']
const IonItem: typeof import('@ionic/vue')['IonItem'] const IonItem: typeof import('@ionic/vue')['IonItem']
const IonLabel: typeof import('@ionic/vue')['IonLabel'] const IonLabel: typeof import('@ionic/vue')['IonLabel']
const IonList: typeof import('@ionic/vue')['IonList'] const IonList: typeof import('@ionic/vue')['IonList']
const IonListHeader: typeof import('@ionic/vue')['IonListHeader']
const IonModal: typeof import('@ionic/vue')['IonModal'] const IonModal: typeof import('@ionic/vue')['IonModal']
const IonNote: typeof import('@ionic/vue')['IonNote']
const IonPage: typeof import('@ionic/vue')['IonPage'] const IonPage: typeof import('@ionic/vue')['IonPage']
const IonRadio: typeof import('@ionic/vue')['IonRadio']
const IonRadioGroup: typeof import('@ionic/vue')['IonRadioGroup']
const IonRefresher: typeof import('@ionic/vue')['IonRefresher'] const IonRefresher: typeof import('@ionic/vue')['IonRefresher']
const IonRefresherContent: typeof import('@ionic/vue')['IonRefresherContent'] const IonRefresherContent: typeof import('@ionic/vue')['IonRefresherContent']
const IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet'] const IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet']
const IonRow: typeof import('@ionic/vue')['IonRow']
const IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
const IonSelect: typeof import('@ionic/vue')['IonSelect'] const IonSelect: typeof import('@ionic/vue')['IonSelect']
const IonSelectOption: typeof import('@ionic/vue')['IonSelectOption'] const IonSelectOption: typeof import('@ionic/vue')['IonSelectOption']
const IonTabBar: typeof import('@ionic/vue')['IonTabBar'] const IonTabBar: typeof import('@ionic/vue')['IonTabBar']
const IonTabButton: typeof import('@ionic/vue')['IonTabButton'] const IonTabButton: typeof import('@ionic/vue')['IonTabButton']
const IonTabs: typeof import('@ionic/vue')['IonTabs'] const IonTabs: typeof import('@ionic/vue')['IonTabs']
const IonText: typeof import('@ionic/vue')['IonText']
const IonTitle: typeof import('@ionic/vue')['IonTitle'] const IonTitle: typeof import('@ionic/vue')['IonTitle']
const IonToolbar: typeof import('@ionic/vue')['IonToolbar'] const IonToolbar: typeof import('@ionic/vue')['IonToolbar']
const LayoutDefault: typeof import('./src/components/layout/default.vue')['default'] const LayoutDefault: typeof import('./src/components/layout/default.vue')['default']
@@ -121,16 +81,4 @@ declare global {
const RouterLink: typeof import('vue-router')['RouterLink'] const RouterLink: typeof import('vue-router')['RouterLink']
const RouterView: typeof import('vue-router')['RouterView'] const RouterView: typeof import('vue-router')['RouterView']
const SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default'] const SubscribeRwa: typeof import('./src/components/subscribe-rwa/index.vue')['default']
const UiAvatar: typeof import('./src/components/ui/avatar/index.vue')['default']
const UiCollapse: typeof import('./src/components/ui/collapse/index.vue')['default']
const UiDatetime: typeof import('./src/components/ui/datetime/index.vue')['default']
const UiDivider: typeof import('./src/components/ui/divider/index.vue')['default']
const UiFileUpload: typeof import('./src/components/ui/file-upload/index.vue')['default']
const UiInput: typeof import('./src/components/ui/input/index.vue')['default']
const UiInputLabel: typeof import('./src/components/ui/input-label/index.vue')['default']
const UiResult: typeof import('./src/components/ui/result/index.vue')['default']
const UiTabPane: typeof import('./src/components/ui/tab-pane/index.vue')['default']
const UiTabs: typeof import('./src/components/ui/tabs/index.vue')['default']
const UiTag: typeof import('./src/components/ui/tag/index.vue')['default']
const UiTextareaLabel: typeof import('./src/components/ui/textarea-label/index.vue')['default']
} }

View File

@@ -1,6 +1,7 @@
import { IonicVue } from "@ionic/vue"; import { IonicVue } from "@ionic/vue";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import { createApp } from "vue"; import { createApp } from "vue";
import uiComponents from "@/ui";
import App from "./App.vue"; import App from "./App.vue";
import { authClient } from "./auth"; import { authClient } from "./auth";
import { i18n } from "./locales"; import { i18n } from "./locales";
@@ -49,7 +50,8 @@ authClient.getSession().then((session) => {
.use(IonicVue) .use(IonicVue)
.use(pinia) .use(pinia)
.use(router) .use(router)
.use(i18n); .use(i18n)
.use(uiComponents);
router.isReady().then(() => { router.isReady().then(() => {
app.mount("#app"); app.mount("#app");

34
src/ui/index.ts Normal file
View File

@@ -0,0 +1,34 @@
import type { App, Component } from "vue";
const modules: Record<string, { default: Component }> = import.meta.glob("./*/*.vue", { eager: true });
function setupUiGlobalComponents(app: App) {
for (const path in modules) {
const parts = path.replace(/^\.\//, "").replace(/\.vue$/, "").split("/");
const name = parts[parts.length - 1] === "index" ? parts[parts.length - 2] : parts[parts.length - 1];
const componentName = `Ui${name.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join("")}`;
app.component(componentName, modules[path].default);
}
}
export default {
install: setupUiGlobalComponents,
};
// Global component types
declare module "vue" {
export interface GlobalComponents {
UiAvatar: typeof import("./avatar/index.vue")["default"];
UiCollapse: typeof import("./collapse/index.vue")["default"];
UiDatetime: typeof import("./datetime/index.vue")["default"];
UiDivider: typeof import("./divider/index.vue")["default"];
UiFileUpload: typeof import("./file-upload/index.vue")["default"];
UiInput: typeof import("./input/index.vue")["default"];
UiInputLabel: typeof import("./input-label/index.vue")["default"];
UiResult: typeof import("./result/index.vue")["default"];
UiTabPane: typeof import("./tabs/tab-pane.vue")["default"];
UiTabs: typeof import("./tabs/index.vue")["default"];
UiTag: typeof import("./tag/index.vue")["default"];
UiTextareaLabel: typeof import("./textarea-label/index.vue")["default"];
}
}

View File

@@ -1,6 +1,6 @@
<script lang='ts' setup> <script lang='ts' setup>
import type { ComponentInstance } from "vue"; import type { ComponentInstance } from "vue";
import UiInput from "@/components/ui/input/index.vue"; import UiInput from "@/ui/input/index.vue";
defineProps<{ defineProps<{
label?: string; label?: string;