@keqi.gress/plugin-ui 1.0.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/composables/useLoadingState.ts","../src/composables/useResponsive.ts","../src/components/LoadingState.vue","../src/components/EmptyState.vue","../src/components/ErrorState.vue"],"sourcesContent":["/**\n * 加载状态管理 Composable\n * 统一管理加载、错误和空状态\n */\n\nimport { ref, computed } from 'vue'\n\nexport interface LoadingState {\n loading: boolean\n error: Error | null\n isEmpty: boolean\n}\n\nexport interface UseLoadingStateOptions {\n initialLoading?: boolean\n onError?: (error: Error) => void\n}\n\nexport function useLoadingState(options: UseLoadingStateOptions = {}) {\n const { initialLoading = false, onError } = options\n\n const loading = ref(initialLoading)\n const error = ref<Error | null>(null)\n const isEmpty = ref(false)\n\n const isLoading = computed(() => loading.value)\n const hasError = computed(() => error.value !== null)\n const isEmptyState = computed(() => isEmpty.value && !loading.value && !error.value)\n\n /**\n * 开始加载\n */\n const startLoading = () => {\n loading.value = true\n error.value = null\n isEmpty.value = false\n }\n\n /**\n * 停止加载\n */\n const stopLoading = () => {\n loading.value = false\n }\n\n /**\n * 设置错误\n */\n const setError = (err: Error | string) => {\n loading.value = false\n error.value = err instanceof Error ? err : new Error(err)\n \n if (onError && error.value) {\n onError(error.value)\n }\n }\n\n /**\n * 清除错误\n */\n const clearError = () => {\n error.value = null\n }\n\n /**\n * 设置空状态\n */\n const setEmpty = (empty: boolean) => {\n isEmpty.value = empty\n }\n\n /**\n * 重置所有状态\n */\n const reset = () => {\n loading.value = false\n error.value = null\n isEmpty.value = false\n }\n\n /**\n * 执行异步操作并自动管理状态\n */\n const execute = async <T>(\n fn: () => Promise<T>,\n options?: {\n checkEmpty?: (result: T) => boolean\n onSuccess?: (result: T) => void\n onError?: (error: Error) => void\n }\n ): Promise<T | null> => {\n try {\n startLoading()\n const result = await fn()\n \n // 检查是否为空\n if (options?.checkEmpty) {\n isEmpty.value = options.checkEmpty(result)\n }\n \n // 成功回调\n if (options?.onSuccess) {\n options.onSuccess(result)\n }\n \n return result\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error(String(err))\n setError(errorObj)\n \n // 错误回调\n if (options?.onError) {\n options.onError(errorObj)\n }\n \n return null\n } finally {\n stopLoading()\n }\n }\n\n return {\n // 状态\n loading,\n error,\n isEmpty,\n \n // 计算属性\n isLoading,\n hasError,\n isEmptyState,\n \n // 方法\n startLoading,\n stopLoading,\n setError,\n clearError,\n setEmpty,\n reset,\n execute\n }\n}\n","/**\n * 响应式设计 Composable\n * 提供断点检测和响应式工具\n */\n\nimport { ref, computed, onMounted, onUnmounted, type ComputedRef, type Ref } from 'vue'\n\nexport type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nexport interface BreakpointValues {\n xs: number\n sm: number\n md: number\n lg: number\n xl: number\n '2xl': number\n}\n\nexport const breakpoints: BreakpointValues = {\n xs: 480,\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536\n}\n\nexport interface UseResponsiveReturn {\n // 状态\n windowWidth: Ref<number>\n currentBreakpoint: ComputedRef<Breakpoint>\n\n // 计算属性\n isMobile: ComputedRef<boolean>\n isTablet: ComputedRef<boolean>\n isDesktop: ComputedRef<boolean>\n\n // 方法\n isSmaller: (breakpoint: Breakpoint) => ComputedRef<boolean>\n isLarger: (breakpoint: Breakpoint) => ComputedRef<boolean>\n isBetween: (min: Breakpoint, max: Breakpoint) => ComputedRef<boolean>\n responsive: <T>(values: Partial<Record<Breakpoint, T>>, defaultValue: T) => T\n getResponsiveColumns: (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n '2xl'?: number\n }) => number\n getResponsiveSpacing: (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n }) => number\n\n // 断点值\n breakpoints: BreakpointValues\n}\n\nexport function useResponsive(): UseResponsiveReturn {\n const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1024)\n\n const updateWidth = () => {\n windowWidth.value = window.innerWidth\n }\n\n onMounted(() => {\n window.addEventListener('resize', updateWidth)\n })\n\n onUnmounted(() => {\n window.removeEventListener('resize', updateWidth)\n })\n\n // 当前断点\n const currentBreakpoint = computed<Breakpoint>(() => {\n const width = windowWidth.value\n \n if (width < breakpoints.xs) return 'xs'\n if (width < breakpoints.sm) return 'xs'\n if (width < breakpoints.md) return 'sm'\n if (width < breakpoints.lg) return 'md'\n if (width < breakpoints.xl) return 'lg'\n if (width < breakpoints['2xl']) return 'xl'\n return '2xl'\n })\n\n // 是否为移动设备\n const isMobile = computed(() => windowWidth.value < breakpoints.md)\n\n // 是否为平板设备\n const isTablet = computed(() => \n windowWidth.value >= breakpoints.md && windowWidth.value < breakpoints.lg\n )\n\n // 是否为桌面设备\n const isDesktop = computed(() => windowWidth.value >= breakpoints.lg)\n\n // 是否小于指定断点\n const isSmaller = (breakpoint: Breakpoint) => {\n return computed(() => windowWidth.value < breakpoints[breakpoint])\n }\n\n // 是否大于指定断点\n const isLarger = (breakpoint: Breakpoint) => {\n return computed(() => windowWidth.value >= breakpoints[breakpoint])\n }\n\n // 是否在指定断点范围内\n const isBetween = (min: Breakpoint, max: Breakpoint) => {\n return computed(() => \n windowWidth.value >= breakpoints[min] && windowWidth.value < breakpoints[max]\n )\n }\n\n // 根据断点返回不同的值\n const responsive = <T>(values: Partial<Record<Breakpoint, T>>, defaultValue: T): T => {\n const bp = currentBreakpoint.value\n \n // 从当前断点向下查找\n const breakpointOrder: Breakpoint[] = ['2xl', 'xl', 'lg', 'md', 'sm', 'xs']\n const currentIndex = breakpointOrder.indexOf(bp)\n \n for (let i = currentIndex; i < breakpointOrder.length; i++) {\n const key = breakpointOrder[i]\n if (values[key] !== undefined) {\n return values[key] as T\n }\n }\n \n return defaultValue\n }\n\n // 获取响应式列数\n const getResponsiveColumns = (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n '2xl'?: number\n }): number => {\n const defaultConfig = {\n xs: 1,\n sm: 1,\n md: 2,\n lg: 3,\n xl: 4,\n '2xl': 4\n }\n \n const finalConfig = { ...defaultConfig, ...config }\n return responsive(finalConfig, 1)\n }\n\n // 获取响应式间距\n const getResponsiveSpacing = (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n }): number => {\n const defaultConfig = {\n xs: 8,\n sm: 12,\n md: 16,\n lg: 24\n }\n \n const finalConfig = { ...defaultConfig, ...config }\n return responsive(finalConfig, 16)\n }\n\n return {\n // 状态\n windowWidth,\n currentBreakpoint,\n \n // 计算属性\n isMobile,\n isTablet,\n isDesktop,\n \n // 方法\n isSmaller,\n isLarger,\n isBetween,\n responsive,\n getResponsiveColumns,\n getResponsiveSpacing,\n \n // 断点值\n breakpoints\n }\n}\n","<template>\n <div class=\"loading-container\">\n <div class=\"loading-spinner\"></div>\n <p v-if=\"message\" class=\"loading-message\">{{ message }}</p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n message?: string\n}>()\n</script>\n\n<style scoped>\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n padding: var(--spacing-4xl, 40px);\n}\n\n.loading-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid var(--border-secondary, #f0f2f5);\n border-top-color: var(--primary, #6366f1);\n border-radius: var(--radius-full, 9999px);\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.loading-message {\n margin-top: var(--spacing-lg, 16px);\n font-size: var(--font-size-sm, 12px);\n color: var(--text-secondary, #4e5969);\n}\n</style>\n","<template>\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <slot name=\"icon\">\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M32 8C18.745 8 8 18.745 8 32s10.745 24 24 24 24-10.745 24-24S45.255 8 32 8zm0 44c-11.028 0-20-8.972-20-20s8.972-20 20-20 20 8.972 20 20-8.972 20-20 20z\" fill=\"currentColor\" opacity=\"0.3\"/>\n <path d=\"M32 24c-1.105 0-2 .895-2 2v12c0 1.105.895 2 2 2s2-.895 2-2V26c0-1.105-.895-2-2-2zm0 20c-1.105 0-2 .895-2 2s.895 2 2 2 2-.895 2-2-.895-2-2-2z\" fill=\"currentColor\"/>\n </svg>\n </slot>\n </div>\n <h3 class=\"empty-title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"empty-description\">{{ description }}</p>\n <div v-if=\"$slots.action\" class=\"empty-action\">\n <slot name=\"action\"></slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nwithDefaults(defineProps<{\n title?: string\n description?: string\n}>(), {\n title: '暂无数据'\n})\n</script>\n\n<style scoped>\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-5xl, 48px) var(--spacing-2xl, 24px);\n text-align: center;\n}\n\n.empty-icon {\n font-size: 48px;\n color: var(--text-quaternary, #c9cdd4);\n margin-bottom: var(--spacing-lg, 16px);\n}\n\n.empty-title {\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #4e5969);\n margin-bottom: var(--spacing-sm, 8px);\n}\n\n.empty-description {\n font-size: var(--font-size-sm, 12px);\n color: var(--text-tertiary, #86909c);\n max-width: 400px;\n margin: 0;\n}\n\n.empty-action {\n margin-top: var(--spacing-lg, 16px);\n}\n</style>\n","<template>\n <div class=\"error-container\">\n <div class=\"error-icon\">\n <slot name=\"icon\">\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M32 8C18.745 8 8 18.745 8 32s10.745 24 24 24 24-10.745 24-24S45.255 8 32 8zm0 44c-11.028 0-20-8.972-20-20s8.972-20 20-20 20 8.972 20 20-8.972 20-20 20z\" fill=\"currentColor\" opacity=\"0.3\"/>\n <path d=\"M38.828 22.172a2 2 0 00-2.828 0L32 26.172l-4-4a2 2 0 10-2.828 2.828L29.172 29l-4 4a2 2 0 102.828 2.828L32 31.828l4 4a2 2 0 102.828-2.828L34.828 29l4-4a2 2 0 000-2.828z\" fill=\"currentColor\"/>\n </svg>\n </slot>\n </div>\n <h3 class=\"error-title\">{{ title }}</h3>\n <p class=\"error-message\">{{ errorMessage }}</p>\n <div v-if=\"$slots.action || showRetry\" class=\"error-action\">\n <slot name=\"action\">\n <button v-if=\"showRetry\" @click=\"handleRetry\" class=\"error-retry-btn\">\n 重试\n </button>\n </slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nconst props = withDefaults(defineProps<{\n error?: Error | string\n title?: string\n showRetry?: boolean\n}>(), {\n title: '出错了',\n showRetry: false\n})\n\nconst emit = defineEmits<{\n retry: []\n}>()\n\nconst errorMessage = computed(() => {\n if (!props.error) return '发生了未知错误'\n if (typeof props.error === 'string') return props.error\n return props.error.message || '发生了未知错误'\n})\n\nconst handleRetry = () => {\n emit('retry')\n}\n</script>\n\n<style scoped>\n.error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-4xl, 40px) var(--spacing-2xl, 24px);\n text-align: center;\n}\n\n.error-icon {\n font-size: 48px;\n color: var(--error, #ef4444);\n margin-bottom: var(--spacing-lg, 16px);\n}\n\n.error-title {\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--error, #ef4444);\n margin-bottom: var(--spacing-sm, 8px);\n}\n\n.error-message {\n font-size: var(--font-size-sm, 12px);\n color: var(--text-secondary, #4e5969);\n max-width: 500px;\n margin: 0 0 var(--spacing-lg, 16px);\n}\n\n.error-action {\n margin-top: var(--spacing-lg, 16px);\n}\n\n.error-retry-btn {\n padding: var(--spacing-sm, 8px) var(--spacing-lg, 16px);\n font-size: var(--font-size-sm, 12px);\n color: white;\n background-color: var(--primary, #6366f1);\n border: none;\n border-radius: var(--radius-md, 8px);\n cursor: pointer;\n transition: opacity var(--transition-fast, 0.15s) ease;\n}\n\n.error-retry-btn:hover {\n opacity: 0.8;\n}\n\n.error-retry-btn:active {\n opacity: 0.6;\n}\n</style>\n"],"names":["ref","computed","options","onMounted","onUnmounted","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_toDisplayString","_renderSlot","_hoisted_3","_hoisted_4","$slots","_hoisted_5"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/composables/useLoadingState.ts","../src/composables/useResponsive.ts","../src/components/layout/PageContainer.vue","../src/components/layout/PageContent.vue","../src/components/layout/PageHeader.vue","../src/components/data/CardList.vue","../src/components/data/PagePagination.vue","../src/components/data/LogViewer.vue","../src/components/interaction/FilterPanel.vue","../src/components/interaction/UniversalModal.vue","../src/components/feedback/LoadingState.vue","../src/components/feedback/EmptyState.vue","../src/components/feedback/ErrorState.vue"],"sourcesContent":["/**\n * 加载状态管理 Composable\n * 统一管理加载、错误和空状态\n */\n\nimport { ref, computed } from 'vue'\n\nexport interface LoadingState {\n loading: boolean\n error: Error | null\n isEmpty: boolean\n}\n\nexport interface UseLoadingStateOptions {\n initialLoading?: boolean\n onError?: (error: Error) => void\n}\n\nexport function useLoadingState(options: UseLoadingStateOptions = {}) {\n const { initialLoading = false, onError } = options\n\n const loading = ref(initialLoading)\n const error = ref<Error | null>(null)\n const isEmpty = ref(false)\n\n const isLoading = computed(() => loading.value)\n const hasError = computed(() => error.value !== null)\n const isEmptyState = computed(() => isEmpty.value && !loading.value && !error.value)\n\n /**\n * 开始加载\n */\n const startLoading = () => {\n loading.value = true\n error.value = null\n isEmpty.value = false\n }\n\n /**\n * 停止加载\n */\n const stopLoading = () => {\n loading.value = false\n }\n\n /**\n * 设置错误\n */\n const setError = (err: Error | string) => {\n loading.value = false\n error.value = err instanceof Error ? err : new Error(err)\n \n if (onError && error.value) {\n onError(error.value)\n }\n }\n\n /**\n * 清除错误\n */\n const clearError = () => {\n error.value = null\n }\n\n /**\n * 设置空状态\n */\n const setEmpty = (empty: boolean) => {\n isEmpty.value = empty\n }\n\n /**\n * 重置所有状态\n */\n const reset = () => {\n loading.value = false\n error.value = null\n isEmpty.value = false\n }\n\n /**\n * 执行异步操作并自动管理状态\n */\n const execute = async <T>(\n fn: () => Promise<T>,\n options?: {\n checkEmpty?: (result: T) => boolean\n onSuccess?: (result: T) => void\n onError?: (error: Error) => void\n }\n ): Promise<T | null> => {\n try {\n startLoading()\n const result = await fn()\n \n // 检查是否为空\n if (options?.checkEmpty) {\n isEmpty.value = options.checkEmpty(result)\n }\n \n // 成功回调\n if (options?.onSuccess) {\n options.onSuccess(result)\n }\n \n return result\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error(String(err))\n setError(errorObj)\n \n // 错误回调\n if (options?.onError) {\n options.onError(errorObj)\n }\n \n return null\n } finally {\n stopLoading()\n }\n }\n\n return {\n // 状态\n loading,\n error,\n isEmpty,\n \n // 计算属性\n isLoading,\n hasError,\n isEmptyState,\n \n // 方法\n startLoading,\n stopLoading,\n setError,\n clearError,\n setEmpty,\n reset,\n execute\n }\n}\n","/**\n * 响应式设计 Composable\n * 提供断点检测和响应式工具\n */\n\nimport { ref, computed, onMounted, onUnmounted, type ComputedRef, type Ref } from 'vue'\n\nexport type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nexport interface BreakpointValues {\n xs: number\n sm: number\n md: number\n lg: number\n xl: number\n '2xl': number\n}\n\nexport const breakpoints: BreakpointValues = {\n xs: 480,\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n '2xl': 1536\n}\n\nexport interface UseResponsiveReturn {\n // 状态\n windowWidth: Ref<number>\n currentBreakpoint: ComputedRef<Breakpoint>\n\n // 计算属性\n isMobile: ComputedRef<boolean>\n isTablet: ComputedRef<boolean>\n isDesktop: ComputedRef<boolean>\n\n // 方法\n isSmaller: (breakpoint: Breakpoint) => ComputedRef<boolean>\n isLarger: (breakpoint: Breakpoint) => ComputedRef<boolean>\n isBetween: (min: Breakpoint, max: Breakpoint) => ComputedRef<boolean>\n responsive: <T>(values: Partial<Record<Breakpoint, T>>, defaultValue: T) => T\n getResponsiveColumns: (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n '2xl'?: number\n }) => number\n getResponsiveSpacing: (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n }) => number\n\n // 断点值\n breakpoints: BreakpointValues\n}\n\nexport function useResponsive(): UseResponsiveReturn {\n const windowWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 1024)\n\n const updateWidth = () => {\n windowWidth.value = window.innerWidth\n }\n\n onMounted(() => {\n window.addEventListener('resize', updateWidth)\n })\n\n onUnmounted(() => {\n window.removeEventListener('resize', updateWidth)\n })\n\n // 当前断点\n const currentBreakpoint = computed<Breakpoint>(() => {\n const width = windowWidth.value\n \n if (width < breakpoints.xs) return 'xs'\n if (width < breakpoints.sm) return 'xs'\n if (width < breakpoints.md) return 'sm'\n if (width < breakpoints.lg) return 'md'\n if (width < breakpoints.xl) return 'lg'\n if (width < breakpoints['2xl']) return 'xl'\n return '2xl'\n })\n\n // 是否为移动设备\n const isMobile = computed(() => windowWidth.value < breakpoints.md)\n\n // 是否为平板设备\n const isTablet = computed(() => \n windowWidth.value >= breakpoints.md && windowWidth.value < breakpoints.lg\n )\n\n // 是否为桌面设备\n const isDesktop = computed(() => windowWidth.value >= breakpoints.lg)\n\n // 是否小于指定断点\n const isSmaller = (breakpoint: Breakpoint) => {\n return computed(() => windowWidth.value < breakpoints[breakpoint])\n }\n\n // 是否大于指定断点\n const isLarger = (breakpoint: Breakpoint) => {\n return computed(() => windowWidth.value >= breakpoints[breakpoint])\n }\n\n // 是否在指定断点范围内\n const isBetween = (min: Breakpoint, max: Breakpoint) => {\n return computed(() => \n windowWidth.value >= breakpoints[min] && windowWidth.value < breakpoints[max]\n )\n }\n\n // 根据断点返回不同的值\n const responsive = <T>(values: Partial<Record<Breakpoint, T>>, defaultValue: T): T => {\n const bp = currentBreakpoint.value\n \n // 从当前断点向下查找\n const breakpointOrder: Breakpoint[] = ['2xl', 'xl', 'lg', 'md', 'sm', 'xs']\n const currentIndex = breakpointOrder.indexOf(bp)\n \n for (let i = currentIndex; i < breakpointOrder.length; i++) {\n const key = breakpointOrder[i]\n if (values[key] !== undefined) {\n return values[key] as T\n }\n }\n \n return defaultValue\n }\n\n // 获取响应式列数\n const getResponsiveColumns = (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n xl?: number\n '2xl'?: number\n }): number => {\n const defaultConfig = {\n xs: 1,\n sm: 1,\n md: 2,\n lg: 3,\n xl: 4,\n '2xl': 4\n }\n \n const finalConfig = { ...defaultConfig, ...config }\n return responsive(finalConfig, 1)\n }\n\n // 获取响应式间距\n const getResponsiveSpacing = (config?: {\n xs?: number\n sm?: number\n md?: number\n lg?: number\n }): number => {\n const defaultConfig = {\n xs: 8,\n sm: 12,\n md: 16,\n lg: 24\n }\n \n const finalConfig = { ...defaultConfig, ...config }\n return responsive(finalConfig, 16)\n }\n\n return {\n // 状态\n windowWidth,\n currentBreakpoint,\n \n // 计算属性\n isMobile,\n isTablet,\n isDesktop,\n \n // 方法\n isSmaller,\n isLarger,\n isBetween,\n responsive,\n getResponsiveColumns,\n getResponsiveSpacing,\n \n // 断点值\n breakpoints\n }\n}\n","<template>\n <div class=\"page-container\">\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * PageContainer 页面容器组件\n * \n * 提供标准的页面布局结构,包含固定高度和垂直布局\n * \n * @example\n * ```vue\n * <PageContainer>\n * <PageHeader title=\"页面标题\" />\n * <PageContent>\n * <!-- 页面内容 -->\n * </PageContent>\n * </PageContainer>\n * ```\n */\n</script>\n\n<style scoped lang=\"scss\">\n.page-container {\n height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--bg-secondary, #f7f8fa);\n}\n</style>\n","<template>\n <div class=\"page-content\">\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * PageContent 页面内容组件\n * \n * 提供可滚动的内容区域,自动处理滚动条样式\n * \n * @example\n * ```vue\n * <PageContent>\n * <div>内容区域</div>\n * </PageContent>\n * ```\n */\n</script>\n\n<style scoped lang=\"scss\">\n.page-content {\n flex: 1;\n overflow-y: auto;\n padding: var(--spacing-2xl, 24px);\n display: flex;\n flex-direction: column;\n gap: var(--spacing-lg, 16px);\n \n // 自定义滚动条\n &::-webkit-scrollbar {\n width: 6px;\n height: 6px;\n }\n\n &::-webkit-scrollbar-track {\n background: transparent;\n border-radius: var(--radius-full, 9999px);\n }\n\n &::-webkit-scrollbar-thumb {\n background: var(--gray-300, #d4d4d4);\n border-radius: var(--radius-full, 9999px);\n \n &:hover {\n background: var(--gray-400, #a3a3a3);\n }\n }\n}\n\n// 响应式设计\n@media (max-width: 768px) {\n .page-content {\n padding: var(--spacing-lg, 16px);\n }\n}\n</style>\n","<template>\n <div class=\"page-header\">\n <div class=\"page-header__content\">\n <!-- 前缀插槽或默认面包屑 -->\n <div v-if=\"$slots.prefix\" class=\"page-header__prefix\">\n <slot name=\"prefix\" />\n </div>\n <div v-else class=\"page-header__left\">\n <div class=\"page-header__breadcrumb\">\n <div v-if=\"breadcrumb\" class=\"breadcrumb-item\">\n <span>{{ breadcrumb }}</span>\n </div>\n <span v-if=\"breadcrumb\" class=\"breadcrumb-separator\">/</span>\n <div class=\"breadcrumb-item breadcrumb-item--current\">\n <span>{{ title }}</span>\n </div>\n </div>\n </div>\n \n <!-- 操作按钮插槽 -->\n <div v-if=\"$slots.actions\" class=\"page-header__actions\">\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { PageHeaderProps } from '../types'\n\n/**\n * PageHeader 页面头部组件\n * \n * 提供标准的页面头部布局,包含面包屑导航和操作按钮区域\n * \n * @example\n * ```vue\n * <PageHeader title=\"应用管理\" breadcrumb=\"系统管理\">\n * <template #actions>\n * <button>新建</button>\n * </template>\n * </PageHeader>\n * ```\n */\n\ndefineProps<PageHeaderProps>()\n</script>\n\n<style scoped lang=\"scss\">\n.page-header {\n background: var(--bg-primary, #ffffff);\n border-bottom: 1px solid var(--border-secondary, #f0f2f5);\n padding: 0 var(--spacing-3xl, 32px);\n height: 64px;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n\n &__content {\n display: flex;\n justify-content: space-between;\n align-items: center;\n width: 100%;\n }\n\n &__prefix {\n display: flex;\n align-items: center;\n gap: var(--spacing-md, 12px);\n flex: 1;\n }\n\n &__left {\n display: flex;\n align-items: center;\n gap: var(--spacing-md, 12px);\n }\n\n &__breadcrumb {\n display: flex;\n align-items: center;\n gap: var(--spacing-md, 12px);\n flex-wrap: wrap;\n }\n\n .breadcrumb-item {\n display: flex;\n align-items: center;\n gap: var(--spacing-xs, 4px);\n color: var(--text-tertiary, #86909c);\n font-size: var(--font-size-base, 13px);\n font-weight: var(--font-weight-medium, 500);\n transition: color 0.2s ease;\n\n &:hover {\n color: var(--text-secondary, #4e5969);\n }\n\n &--current {\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-semibold, 600);\n }\n }\n\n .breadcrumb-separator {\n color: var(--text-quaternary, #c9cdd4);\n font-size: var(--font-size-base, 13px);\n user-select: none;\n }\n\n &__actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-md, 12px);\n }\n}\n\n// 响应式设计\n@media (max-width: 768px) {\n .page-header {\n padding: var(--spacing-md, 12px);\n\n &__content {\n flex-direction: column;\n align-items: flex-start;\n gap: var(--spacing-md, 12px);\n }\n\n &__prefix {\n width: 100%;\n }\n\n &__actions {\n width: 100%;\n justify-content: flex-end;\n }\n }\n}\n\n@media (max-width: 640px) {\n .page-header {\n padding: var(--spacing-sm, 8px) var(--spacing-md, 12px);\n\n .breadcrumb-item {\n font-size: var(--font-size-sm, 12px);\n\n &--current {\n font-size: var(--font-size-base, 13px);\n }\n }\n\n .breadcrumb-separator {\n font-size: var(--font-size-sm, 12px);\n }\n }\n}\n</style>\n","<template>\n <div class=\"card-list\" :class=\"{ [`card-list--${size}`]: size }\">\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { CardListProps } from '../types'\n\n/**\n * CardList 卡片列表组件\n * \n * 提供响应式的卡片网格布局\n * \n * @example\n * ```vue\n * <CardList size=\"medium\">\n * <div class=\"card\">卡片 1</div>\n * <div class=\"card\">卡片 2</div>\n * </CardList>\n * ```\n */\n\nwithDefaults(defineProps<CardListProps>(), {\n size: 'medium',\n minWidth: '380px'\n})\n</script>\n\n<style scoped lang=\"scss\">\n.card-list {\n display: grid;\n gap: var(--spacing-lg, 16px);\n \n // 默认中等尺寸\n &--medium {\n grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));\n }\n \n // 小尺寸卡片\n &--small {\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n }\n \n // 大尺寸卡片\n &--large {\n grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));\n }\n}\n\n// 响应式设计\n@media (max-width: 768px) {\n .card-list {\n grid-template-columns: 1fr;\n }\n}\n</style>\n","<template>\n <div v-if=\"total > 0\" class=\"page-pagination\">\n <slot \n :page=\"page\"\n :page-size=\"pageSize\"\n :page-count=\"pageCount\"\n :total=\"total\"\n :on-page-change=\"handlePageChange\"\n :on-page-size-change=\"handlePageSizeChange\"\n >\n <!-- 默认分页UI(简单版本,不依赖 Naive UI) -->\n <div class=\"pagination-controls\">\n <button \n class=\"pagination-btn\"\n :disabled=\"page === 1\"\n @click=\"handlePageChange(page - 1)\"\n >\n 上一页\n </button>\n \n <span class=\"pagination-info\">\n 第 {{ page }} / {{ pageCount }} 页,共 {{ total }} 条\n </span>\n \n <button \n class=\"pagination-btn\"\n :disabled=\"page === pageCount\"\n @click=\"handlePageChange(page + 1)\"\n >\n 下一页\n </button>\n \n <select \n v-if=\"showSizePicker\"\n class=\"pagination-select\"\n :value=\"pageSize\"\n @change=\"handlePageSizeChange(Number(($event.target as HTMLSelectElement).value))\"\n >\n <option v-for=\"size in pageSizes\" :key=\"size\" :value=\"size\">\n {{ size }} 条/页\n </option>\n </select>\n </div>\n </slot>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { PagePaginationProps, PagePaginationEmits } from '../types'\n\n/**\n * PagePagination 分页组件\n * \n * 提供分页控制功能,支持自定义渲染\n * \n * @example\n * ```vue\n * <PagePagination\n * :page=\"currentPage\"\n * :page-size=\"pageSize\"\n * :total=\"totalCount\"\n * @update:page=\"handlePageChange\"\n * @update:page-size=\"handlePageSizeChange\"\n * />\n * ```\n * \n * 使用 Naive UI 的示例:\n * ```vue\n * <PagePagination\n * :page=\"currentPage\"\n * :page-size=\"pageSize\"\n * :total=\"totalCount\"\n * @update:page=\"handlePageChange\"\n * @update:page-size=\"handlePageSizeChange\"\n * >\n * <template #default=\"{ page, pageSize, pageCount, onPageChange, onPageSizeChange }\">\n * <n-pagination\n * :page=\"page\"\n * :page-size=\"pageSize\"\n * :page-count=\"pageCount\"\n * @update:page=\"onPageChange\"\n * @update:page-size=\"onPageSizeChange\"\n * />\n * </template>\n * </PagePagination>\n * ```\n */\n\nconst props = withDefaults(defineProps<PagePaginationProps>(), {\n pageSizes: () => [10, 20, 50, 100],\n showSizePicker: true\n})\n\nconst emit = defineEmits<PagePaginationEmits>()\n\nconst pageCount = computed(() => Math.ceil(props.total / props.pageSize))\n\nfunction handlePageChange(page: number) {\n if (page >= 1 && page <= pageCount.value) {\n emit('update:page', page)\n }\n}\n\nfunction handlePageSizeChange(pageSize: number) {\n emit('update:pageSize', pageSize)\n // 切换每页条数后,重置到第一页\n if (props.page > 1) {\n emit('update:page', 1)\n }\n}\n</script>\n\n<style scoped lang=\"scss\">\n.page-pagination {\n display: flex;\n justify-content: flex-end;\n padding: var(--spacing-lg, 16px) 0;\n margin-top: var(--spacing-lg, 16px);\n}\n\n.pagination-controls {\n display: flex;\n align-items: center;\n gap: var(--spacing-md, 12px);\n}\n\n.pagination-btn {\n padding: var(--spacing-sm, 8px) var(--spacing-lg, 16px);\n background: var(--bg-primary, #ffffff);\n border: 1px solid var(--border-primary, #e5e6eb);\n border-radius: var(--radius-md, 8px);\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-sm, 12px);\n cursor: pointer;\n transition: all 0.2s ease;\n \n &:hover:not(:disabled) {\n background: var(--bg-secondary, #f7f8fa);\n border-color: var(--primary, #6366f1);\n color: var(--primary, #6366f1);\n }\n \n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n}\n\n.pagination-info {\n color: var(--text-secondary, #4e5969);\n font-size: var(--font-size-sm, 12px);\n white-space: nowrap;\n}\n\n.pagination-select {\n padding: var(--spacing-sm, 8px) var(--spacing-md, 12px);\n background: var(--bg-primary, #ffffff);\n border: 1px solid var(--border-primary, #e5e6eb);\n border-radius: var(--radius-md, 8px);\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-sm, 12px);\n cursor: pointer;\n transition: all 0.2s ease;\n \n &:hover {\n border-color: var(--primary, #6366f1);\n }\n \n &:focus {\n outline: none;\n border-color: var(--primary, #6366f1);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n}\n</style>\n","<template>\n <div class=\"log-viewer\" :class=\"{ 'log-viewer--dark': theme === 'dark' }\">\n <div class=\"log-toolbar\">\n <div class=\"toolbar-group\">\n <button class=\"toolbar-btn\" @click=\"handleRefresh\">\n <span class=\"btn-icon\">↻</span>\n 刷新\n </button>\n <button class=\"toolbar-btn\" @click=\"handleClear\">\n <span class=\"btn-icon\">🗑</span>\n 清空\n </button>\n <select\n v-model=\"filterLevel\"\n class=\"toolbar-select\"\n >\n <option value=\"\">全部级别</option>\n <option value=\"TRACE\">TRACE</option>\n <option value=\"DEBUG\">DEBUG</option>\n <option value=\"INFO\">INFO</option>\n <option value=\"WARN\">WARN</option>\n <option value=\"ERROR\">ERROR</option>\n <option value=\"FATAL\">FATAL</option>\n </select>\n <button class=\"toolbar-btn\" @click=\"toggleTheme\">\n <span class=\"btn-icon\">{{ theme === 'dark' ? '☀' : '🌙' }}</span>\n {{ theme === 'dark' ? '浅色' : '深色' }}\n </button>\n </div>\n </div>\n \n <div class=\"log-content\" ref=\"scrollbarRef\">\n <div v-if=\"loading\" class=\"log-loading\">\n <div class=\"loading-spinner\" />\n <span>加载中...</span>\n </div>\n <div v-else-if=\"filteredLogs.length > 0\" class=\"log-list\">\n <div\n v-for=\"log in filteredLogs\"\n :key=\"log.id\"\n class=\"log-line\"\n :class=\"[`log-level-${getLogLevel(log)?.toLowerCase()}`]\"\n >\n <span class=\"log-timestamp\">{{ formatTimestamp(log.timestamp || log.createTime) }}</span>\n <span v-if=\"getThreadName(log)\" class=\"log-thread\">[{{ getThreadName(log) }}]</span>\n <span class=\"log-level\">{{ getLogLevel(log) }}</span>\n <span v-if=\"getLoggerName(log)\" class=\"log-class\">{{ getLoggerName(log) }}</span>\n <span class=\"log-separator\">-</span>\n <span class=\"log-message\">{{ log.message || log.logContent }}</span>\n <div v-if=\"log.errorMessage || log.body?.errorMessage\" class=\"log-error-detail\">\n <span class=\"log-error-label\">错误:</span>\n <span class=\"log-error-message\">{{ log.errorMessage || log.body?.errorMessage }}</span>\n </div>\n </div>\n </div>\n <div v-else class=\"log-empty\">\n <div class=\"empty-icon\">📋</div>\n <div class=\"empty-text\">暂无日志</div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport type { LogViewerProps, LogViewerEmits, LogItem } from '../types'\n\n/**\n * LogViewer 日志查看器组件\n * \n * 提供日志展示、过滤、主题切换等功能\n * \n * @example\n * ```vue\n * <LogViewer\n * :logs=\"logs\"\n * :loading=\"loading\"\n * @refresh=\"handleRefresh\"\n * @clear=\"handleClear\"\n * />\n * ```\n */\n\nconst props = withDefaults(defineProps<LogViewerProps>(), {\n logs: () => [],\n loading: false,\n autoScroll: true,\n defaultTheme: 'light'\n})\n\nconst emit = defineEmits<LogViewerEmits>()\n\nconst scrollbarRef = ref<HTMLElement>()\nconst filterLevel = ref<string>('')\nconst theme = ref<'light' | 'dark'>(props.defaultTheme)\n\nconst filteredLogs = computed(() => {\n if (!filterLevel.value || filterLevel.value === '') {\n return props.logs\n }\n return props.logs.filter(log => {\n const logLevel = getLogLevel(log)\n return logLevel === filterLevel.value\n })\n})\n\n// 自动滚动到底部\nwatch(\n () => props.logs.length,\n () => {\n if (props.autoScroll) {\n nextTick(() => {\n if (scrollbarRef.value) {\n scrollbarRef.value.scrollTop = scrollbarRef.value.scrollHeight\n }\n })\n }\n }\n)\n\nfunction handleRefresh() {\n emit('refresh')\n}\n\nfunction handleClear() {\n emit('clear')\n}\n\nfunction toggleTheme() {\n theme.value = theme.value === 'dark' ? 'light' : 'dark'\n}\n\nfunction getLogLevel(log: LogItem): string {\n if (log.level) return log.level.toUpperCase()\n if (log.body?.level) return String(log.body.level).toUpperCase()\n \n const content = log.message || log.logContent || ''\n const levelMatch = content.match(/\\b(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\\b/)\n if (levelMatch) return levelMatch[1]\n \n // 默认 INFO\n return 'INFO'\n}\n\nfunction getThreadName(log: LogItem): string {\n if (log.body?.threadName) return String(log.body.threadName)\n if (log.threadName) return log.threadName\n return ''\n}\n\nfunction getLoggerName(log: LogItem): string {\n if (log.logger) return log.logger\n if (log.body?.logger) return String(log.body.logger)\n if (log.className) return log.className\n if (log.body?.className) return String(log.body.className)\n return ''\n}\n\nfunction formatTimestamp(time?: string): string {\n if (!time) return '--'\n try {\n const date = new Date(time)\n const year = date.getFullYear()\n const month = String(date.getMonth() + 1).padStart(2, '0')\n const day = String(date.getDate()).padStart(2, '0')\n const hours = String(date.getHours()).padStart(2, '0')\n const minutes = String(date.getMinutes()).padStart(2, '0')\n const seconds = String(date.getSeconds()).padStart(2, '0')\n const ms = String(date.getMilliseconds()).padStart(3, '0')\n \n return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}`\n } catch (error) {\n return time\n }\n}\n</script>\n\n<style scoped lang=\"scss\">\n.log-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--bg-secondary, #f8f9fa);\n border-radius: var(--radius-md, 8px);\n overflow: hidden;\n border: 1px solid var(--border-secondary, #e8e8e8);\n\n &.log-viewer--dark {\n background: #1e1e1e;\n border-color: #3e3e3e;\n\n .log-toolbar {\n background: #2d2d2d;\n border-bottom-color: #3e3e3e;\n }\n\n .log-content {\n background: #1e1e1e;\n }\n\n .log-line {\n &:hover {\n background: rgba(255, 255, 255, 0.05);\n }\n }\n\n .log-timestamp {\n color: #8c8c8c;\n }\n\n .log-thread {\n color: #69c0ff;\n }\n\n .log-class {\n color: #b37feb;\n }\n\n .log-message {\n color: #d4d4d4;\n }\n\n .log-empty {\n color: #8c8c8c;\n }\n\n .toolbar-btn {\n background: #3e3e3e;\n color: #d4d4d4;\n border-color: #4e4e4e;\n\n &:hover {\n background: #4e4e4e;\n }\n }\n\n .toolbar-select {\n background: #3e3e3e;\n color: #d4d4d4;\n border-color: #4e4e4e;\n }\n }\n}\n\n.log-toolbar {\n padding: 12px;\n background: var(--bg-primary, #ffffff);\n border-bottom: 1px solid var(--border-secondary, #e8e8e8);\n flex-shrink: 0;\n}\n\n.toolbar-group {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-wrap: wrap;\n}\n\n.toolbar-btn {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 12px;\n background: var(--bg-primary, #ffffff);\n border: 1px solid var(--border-primary, #e5e6eb);\n border-radius: var(--radius-md, 8px);\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-sm, 12px);\n cursor: pointer;\n transition: all 0.2s ease;\n \n &:hover {\n background: var(--bg-secondary, #f7f8fa);\n border-color: var(--primary, #6366f1);\n }\n \n .btn-icon {\n font-size: 14px;\n }\n}\n\n.toolbar-select {\n padding: 6px 12px;\n background: var(--bg-primary, #ffffff);\n border: 1px solid var(--border-primary, #e5e6eb);\n border-radius: var(--radius-md, 8px);\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-sm, 12px);\n cursor: pointer;\n transition: all 0.2s ease;\n \n &:hover {\n border-color: var(--primary, #6366f1);\n }\n \n &:focus {\n outline: none;\n border-color: var(--primary, #6366f1);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n}\n\n.log-content {\n flex: 1;\n padding: 12px;\n overflow-y: auto;\n overflow-x: hidden;\n \n &::-webkit-scrollbar {\n width: 6px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: var(--gray-300, #d4d4d4);\n border-radius: var(--radius-full, 9999px);\n\n &:hover {\n background: var(--gray-400, #a3a3a3);\n }\n }\n}\n\n.log-loading {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n gap: 12px;\n color: var(--text-tertiary, #86909c);\n}\n\n.loading-spinner {\n width: 32px;\n height: 32px;\n border: 3px solid var(--border-secondary, #f0f2f5);\n border-top-color: var(--primary, #6366f1);\n border-radius: var(--radius-full, 9999px);\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.log-list {\n display: flex;\n flex-direction: column;\n gap: 0;\n}\n\n.log-line {\n padding: 4px 8px;\n font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-wrap;\n word-break: break-word;\n border-left: 2px solid transparent;\n transition: all 0.15s ease;\n\n &:hover {\n background: rgba(0, 0, 0, 0.03);\n border-left-color: var(--primary, #6366f1);\n }\n\n &.log-level-trace .log-level {\n color: #8c8c8c;\n }\n\n &.log-level-debug .log-level {\n color: #1890ff;\n }\n\n &.log-level-info .log-level {\n color: #52c41a;\n }\n\n &.log-level-warn {\n background: rgba(250, 173, 20, 0.05);\n \n .log-level {\n color: #faad14;\n }\n }\n\n &.log-level-error,\n &.log-level-fatal {\n background: rgba(245, 34, 45, 0.05);\n \n .log-level {\n color: #f5222d;\n font-weight: 600;\n }\n }\n}\n\n.log-timestamp {\n color: #8c8c8c;\n margin-right: 8px;\n font-weight: 500;\n}\n\n.log-thread {\n color: #1890ff;\n margin-right: 8px;\n font-style: italic;\n}\n\n.log-level {\n display: inline-block;\n min-width: 50px;\n margin-right: 8px;\n font-weight: 600;\n text-align: left;\n}\n\n.log-class {\n color: #722ed1;\n margin-right: 8px;\n}\n\n.log-separator {\n color: #8c8c8c;\n margin-right: 8px;\n}\n\n.log-message {\n color: var(--text-primary, #262626);\n flex: 1;\n}\n\n.log-error-detail {\n display: block;\n margin-top: 4px;\n padding-left: 24px;\n color: #f5222d;\n}\n\n.log-error-label {\n font-weight: 600;\n margin-right: 8px;\n}\n\n.log-error-message {\n font-style: italic;\n}\n\n.log-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 200px;\n gap: 12px;\n color: var(--text-tertiary, #86909c);\n}\n\n.empty-icon {\n font-size: 48px;\n opacity: 0.5;\n}\n\n.empty-text {\n font-size: var(--font-size-base, 13px);\n}\n</style>\n","<template>\n <div class=\"filter-card\">\n <div class=\"filter-inline\">\n <div class=\"filter-inline__fields\">\n <div\n v-for=\"field in basicFields\"\n :key=\"field.key\"\n class=\"filter-inline__field\"\n >\n <span v-if=\"field.label\" class=\"field-label\">{{ field.label }}:</span>\n <slot\n :name=\"field.slotName || `field-${field.key}`\"\n :field=\"field\"\n :value=\"getValue(field.key)\"\n :update=\"slotUpdater(field.key)\"\n >\n <!-- 默认输入框 -->\n <input\n v-if=\"!field.type || field.type === 'input'\"\n :value=\"(getValue(field.key) as string) ?? ''\"\n :placeholder=\"field.placeholder\"\n class=\"filter-input\"\n @input=\"updateField(field.key, ($event.target as HTMLInputElement).value)\"\n @keyup.enter=\"emitSearch\"\n />\n </slot>\n </div>\n </div>\n\n <div class=\"filter-inline__actions\" :class=\"`align-${actionAlign}`\">\n <slot name=\"actions\" :on-reset=\"emitReset\" :on-search=\"emitSearch\">\n <button class=\"filter-btn filter-btn--secondary\" @click=\"emitReset\">\n {{ resetText }}\n </button>\n <button class=\"filter-btn filter-btn--primary\" @click=\"emitSearch\">\n {{ searchText }}\n </button>\n </slot>\n\n <button\n v-if=\"hasAdvancedFields\"\n class=\"inline-toggle\"\n @click=\"toggleAdvanced\"\n >\n {{ showAdvanced ? collapseText : expandText }}\n <span class=\"toggle-icon\">{{ showAdvanced ? '▲' : '▼' }}</span>\n </button>\n </div>\n </div>\n\n <transition\n @before-enter=\"beforeExpand\"\n @enter=\"onExpand\"\n @after-enter=\"afterExpand\"\n @before-leave=\"beforeCollapse\"\n @leave=\"onCollapse\"\n @after-leave=\"afterCollapse\"\n >\n <div v-if=\"showAdvanced && hasAdvancedFields\" class=\"filter-grid\">\n <div\n v-for=\"field in advancedFields\"\n :key=\"field.key\"\n class=\"filter-grid__field\"\n :style=\"field.span ? { gridColumn: `span ${field.span}` } : undefined\"\n >\n <span v-if=\"field.label\" class=\"field-label\">{{ field.label }}:</span>\n <slot\n :name=\"field.slotName || `field-${field.key}`\"\n :field=\"field\"\n :value=\"getValue(field.key)\"\n :update=\"slotUpdater(field.key)\"\n >\n <!-- 默认输入框 -->\n <input\n v-if=\"!field.type || field.type === 'input'\"\n :value=\"(getValue(field.key) as string) ?? ''\"\n :placeholder=\"field.placeholder\"\n class=\"filter-input\"\n @input=\"updateField(field.key, ($event.target as HTMLInputElement).value)\"\n />\n </slot>\n </div>\n <div v-if=\"$slots['advanced-hint']\" class=\"filter-grid__hint\">\n <slot name=\"advanced-hint\" />\n </div>\n </div>\n </transition>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { FilterPanelProps, FilterPanelEmits } from '../types'\n\n/**\n * FilterPanel 过滤面板组件\n * \n * 提供灵活的过滤器布局,支持基础字段和高级字段展开/收起\n * \n * @example\n * ```vue\n * <FilterPanel\n * v-model:filters=\"filters\"\n * v-model:show-advanced=\"showAdvanced\"\n * :basic-fields=\"basicFields\"\n * :advanced-fields=\"advancedFields\"\n * @search=\"handleSearch\"\n * @reset=\"handleReset\"\n * >\n * <template #field-status=\"{ value, update }\">\n * <select :value=\"value\" @change=\"update($event.target.value)\">\n * <option value=\"\">全部</option>\n * <option value=\"active\">启用</option>\n * <option value=\"inactive\">禁用</option>\n * </select>\n * </template>\n * </FilterPanel>\n * ```\n */\n\nconst props = withDefaults(defineProps<FilterPanelProps>(), {\n advancedFields: () => [],\n showAdvanced: false,\n searchText: '查询',\n resetText: '重置',\n expandText: '展开',\n collapseText: '收起',\n actionAlign: 'right'\n})\n\nconst emit = defineEmits<FilterPanelEmits>()\n\nconst hasAdvancedFields = computed(\n () => (props.advancedFields?.length ?? 0) > 0\n)\n\nconst showAdvanced = computed(() => props.showAdvanced ?? false)\nconst actionAlign = computed(() => props.actionAlign ?? 'right')\n\nconst TRANSITION_DURATION = 220\n\nfunction getValue(key: string) {\n return props.filters?.[key]\n}\n\nfunction updateField(key: string, value: unknown) {\n emit('update:filters', {\n ...props.filters,\n [key]: value\n })\n}\n\nfunction slotUpdater(key: string) {\n return (value: unknown) => updateField(key, value)\n}\n\nfunction toggleAdvanced() {\n emit('update:showAdvanced', !showAdvanced.value)\n}\n\nfunction emitSearch() {\n emit('search')\n}\n\nfunction emitReset() {\n emit('reset')\n}\n\nfunction beforeExpand(el: Element) {\n const element = el as HTMLElement\n element.style.height = '0'\n element.style.opacity = '0'\n}\n\nfunction onExpand(el: Element) {\n const element = el as HTMLElement\n requestAnimationFrame(() => {\n element.style.transition = `height ${TRANSITION_DURATION}ms ease, opacity ${TRANSITION_DURATION}ms ease`\n element.style.height = `${element.scrollHeight}px`\n element.style.opacity = '1'\n })\n}\n\nfunction afterExpand(el: Element) {\n const element = el as HTMLElement\n element.style.height = ''\n element.style.opacity = ''\n element.style.transition = ''\n}\n\nfunction beforeCollapse(el: Element) {\n const element = el as HTMLElement\n element.style.height = `${element.scrollHeight}px`\n element.style.opacity = '1'\n}\n\nfunction onCollapse(el: Element, done: () => void) {\n const element = el as HTMLElement\n requestAnimationFrame(() => {\n element.style.transition = `height ${TRANSITION_DURATION}ms ease, opacity ${TRANSITION_DURATION}ms ease`\n element.style.height = '0'\n element.style.opacity = '0'\n setTimeout(done, TRANSITION_DURATION)\n })\n}\n\nfunction afterCollapse(el: Element) {\n const element = el as HTMLElement\n element.style.height = ''\n element.style.opacity = ''\n element.style.transition = ''\n}\n</script>\n\n<style scoped lang=\"scss\">\n.filter-card {\n background: var(--bg-primary, #ffffff);\n border-radius: var(--radius-lg, 12px);\n padding: var(--spacing-lg, 16px);\n \n display: flex;\n flex-direction: column;\n gap: var(--spacing-md, 12px);\n}\n\n.filter-inline {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-lg, 16px);\n flex-wrap: wrap;\n}\n\n.filter-inline__fields {\n display: flex;\n gap: var(--spacing-lg, 16px);\n flex: 1;\n min-width: 240px;\n flex-wrap: wrap;\n}\n\n.filter-inline__field {\n display: flex;\n align-items: center;\n gap: var(--spacing-sm, 8px);\n min-width: 220px;\n}\n\n.field-label {\n color: var(--text-secondary, #4e5969);\n font-size: var(--font-size-sm, 12px);\n white-space: nowrap;\n}\n\n.filter-input {\n flex: 1;\n padding: var(--spacing-sm, 8px) var(--spacing-md, 12px);\n border: 1px solid var(--border-primary, #e5e6eb);\n border-radius: var(--radius-md, 8px);\n background: var(--bg-primary, #ffffff);\n color: var(--text-primary, #1f2329);\n font-size: var(--font-size-base, 13px);\n transition: all 0.2s ease;\n \n &:hover {\n border-color: var(--border-tertiary, #dcdfe6);\n }\n \n &:focus {\n outline: none;\n border-color: var(--primary, #6366f1);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n }\n \n &::placeholder {\n color: var(--text-tertiary, #86909c);\n }\n}\n\n.filter-inline__actions {\n display: flex;\n align-items: center;\n gap: var(--spacing-sm, 8px);\n\n &.align-left {\n justify-content: flex-start;\n }\n\n &.align-right {\n justify-content: flex-end;\n }\n}\n\n.filter-btn {\n padding: var(--spacing-sm, 8px) var(--spacing-lg, 16px);\n border: none;\n border-radius: var(--radius-md, 8px);\n font-size: var(--font-size-sm, 12px);\n font-weight: var(--font-weight-medium, 500);\n cursor: pointer;\n transition: all 0.2s ease;\n white-space: nowrap;\n \n &--primary {\n background: linear-gradient(135deg, var(--primary, #6366f1) 0%, var(--secondary, #8b5cf6) 100%);\n color: var(--text-white, #ffffff);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.25);\n \n &:hover {\n box-shadow: 0 8px 20px rgba(99, 102, 241, 0.3);\n transform: translateY(-1px);\n }\n }\n \n &--secondary {\n background: var(--bg-secondary, #f7f8fa);\n color: var(--text-primary, #1f2329);\n border: 1px solid var(--border-primary, #e5e6eb);\n \n &:hover {\n background: var(--bg-tertiary, #f2f3f5);\n border-color: var(--border-tertiary, #dcdfe6);\n }\n }\n}\n\n.inline-toggle {\n display: flex;\n align-items: center;\n gap: var(--spacing-xs, 4px);\n padding: var(--spacing-xs, 4px) var(--spacing-sm, 8px);\n background: none;\n border: 1px solid rgba(99, 102, 241, 0.3);\n border-radius: var(--radius-full, 9999px);\n color: var(--primary, #6366f1);\n font-size: var(--font-size-sm, 12px);\n cursor: pointer;\n transition: all 0.2s ease;\n\n &:hover {\n background: rgba(99, 102, 241, 0.08);\n }\n \n .toggle-icon {\n font-size: 10px;\n }\n}\n\n.filter-grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: var(--spacing-md, 12px);\n padding-top: var(--spacing-sm, 8px);\n border-top: 1px dashed var(--border-secondary, #f0f2f5);\n overflow: hidden;\n}\n\n.filter-grid__field {\n display: flex;\n align-items: center;\n gap: var(--spacing-sm, 8px);\n}\n\n.filter-grid__hint {\n grid-column: 1 / -1;\n font-size: var(--font-size-xs, 11px);\n color: var(--text-tertiary, #86909c);\n}\n</style>\n","<template>\n <transition :name=\"transitionName\">\n <div \n v-if=\"show\" \n class=\"universal-modal-wrapper\" \n :class=\"wrapperClass\" \n :style=\"wrapperStyle\" \n @click.self=\"handleMaskClick\"\n >\n <div\n ref=\"modalRef\"\n class=\"universal-modal\"\n :class=\"modalClass\"\n :style=\"computedModalStyle\"\n >\n <!-- 调整大小的边框 -->\n <div \n v-if=\"!isFullscreen && resizable && (position === 'right' || position === 'left')\" \n class=\"resize-handle resize-handle-left\" \n @mousedown=\"startResize('left')\"\n />\n <div \n v-if=\"!isFullscreen && resizable && (position === 'right' || position === 'left')\" \n class=\"resize-handle resize-handle-right\" \n @mousedown=\"startResize('right')\"\n />\n <div \n v-if=\"!isFullscreen && resizable\" \n class=\"resize-handle resize-handle-top\" \n @mousedown=\"startResize('top')\"\n />\n <div \n v-if=\"!isFullscreen && resizable\" \n class=\"resize-handle resize-handle-bottom\" \n @mousedown=\"startResize('bottom')\"\n />\n \n <!-- 头部 -->\n <div v-if=\"!hideHeader\" class=\"modal-header\" :class=\"headerClass\">\n <slot name=\"header\">\n <div class=\"header-content\">\n <div v-if=\"iconUrl\" class=\"header-icon\">\n <img :src=\"iconUrl\" class=\"header-icon-img\" alt=\"icon\" />\n </div>\n <div class=\"header-info\">\n <div v-if=\"subtitle\" class=\"header-subtitle\">{{ subtitle }}</div>\n <div class=\"header-title\">{{ title }}</div>\n </div>\n </div>\n </slot>\n <div v-if=\"!hideClose\" class=\"header-actions\">\n <slot name=\"header-actions\" />\n <!-- 全屏按钮 -->\n <button \n v-if=\"showFullscreen\"\n class=\"header-btn\" \n @click=\"toggleFullscreen\"\n >\n {{ isFullscreen ? '⊡' : '⊞' }}\n </button>\n <!-- 关闭按钮 -->\n <button class=\"header-btn\" @click=\"handleClose\">\n ✕\n </button>\n </div>\n </div>\n\n <!-- 内容区域 -->\n <div class=\"modal-body\" :class=\"bodyClass\" :style=\"bodyStyle\">\n <slot />\n </div>\n\n <!-- 底部 -->\n <div v-if=\"shouldShowFooter\" class=\"modal-footer\" :class=\"footerClass\">\n <slot name=\"footer\">\n <div v-if=\"showCancel || showConfirm\" class=\"footer-actions\">\n <button v-if=\"showCancel\" class=\"footer-btn footer-btn--cancel\" @click=\"handleCancel\">\n {{ cancelText }}\n </button>\n <button v-if=\"showConfirm\" class=\"footer-btn footer-btn--confirm\" @click=\"handleConfirm\">\n {{ confirmText }}\n </button>\n </div>\n </slot>\n </div>\n </div>\n </div>\n </transition>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, useSlots, ref, onUnmounted } from 'vue'\nimport type { UniversalModalProps, UniversalModalEmits, PositionType } from '../types'\n\n/**\n * UniversalModal 通用弹窗组件\n * \n * 功能丰富的弹窗组件,支持多种位置、可调整大小、全屏等\n * \n * @example\n * ```vue\n * <UniversalModal\n * v-model:show=\"showModal\"\n * title=\"弹窗标题\"\n * position=\"right\"\n * width=\"600px\"\n * @confirm=\"handleConfirm\"\n * >\n * <div>弹窗内容</div>\n * </UniversalModal>\n * ```\n */\n\nconst props = withDefaults(defineProps<UniversalModalProps>(), {\n title: '',\n subtitle: '',\n width: '500px',\n height: 'auto',\n maxWidth: '90vw',\n maxHeight: '90vh',\n position: 'right',\n top: '24px',\n bottom: '24px',\n left: '24px',\n right: '24px',\n showMask: false,\n maskClosable: true,\n hideHeader: false,\n hideFooter: true,\n hideClose: false,\n showCancel: false,\n showConfirm: false,\n showFullscreen: true,\n resizable: true,\n cancelText: '取消',\n confirmText: '确定',\n zIndex: 9999,\n fullscreen: false\n})\n\nconst emit = defineEmits<UniversalModalEmits>()\nconst slots = useSlots()\n\n// 全屏状态\nconst isFullscreen = ref(false)\n\n// 可调整大小的状态\nconst modalRef = ref<HTMLElement | null>(null)\nconst resizing = ref(false)\nconst resizeDirection = ref('')\nconst modalSize = ref({\n width: 0,\n height: 0,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n})\n\n// 计算是否显示底部\nconst shouldShowFooter = computed(() => {\n if (props.hideFooter) return false\n if (slots.footer) return true\n if (props.showCancel || props.showConfirm) return true\n return false\n})\n\n// 计算过渡动画名称\nconst transitionName = computed(() => {\n switch (props.position) {\n case 'left': return 'slide-left'\n case 'right': return 'slide-right'\n case 'top': return 'slide-top'\n case 'bottom': return 'slide-bottom'\n case 'center':\n default: return 'fade-scale'\n }\n})\n\n// 计算包裹层类名\nconst wrapperClass = computed(() => {\n return [\n `position-${props.position}`,\n props.fullscreen ? 'fullscreen' : '',\n props.showMask ? 'with-mask' : 'no-mask'\n ]\n})\n\n// 计算包裹层样式\nconst wrapperStyle = computed(() => {\n const style: Record<string, string> = {}\n if (!props.showMask) {\n style.background = 'transparent'\n style.pointerEvents = 'none'\n }\n return style\n})\n\n// 计算弹窗类名\nconst modalClass = computed(() => {\n return [\n `modal-${props.position}`,\n props.customClass,\n props.fullscreen ? 'modal-fullscreen' : ''\n ]\n})\n\n// 计算弹窗样式\nconst modalStyle = computed(() => {\n const style: Record<string, string> = {\n zIndex: String(props.zIndex)\n }\n\n if (props.fullscreen) return style\n\n if (props.width) {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width\n }\n if (props.height && props.height !== 'auto') {\n style.height = typeof props.height === 'number' ? `${props.height}px` : props.height\n }\n if (props.maxWidth) {\n style.maxWidth = typeof props.maxWidth === 'number' ? `${props.maxWidth}px` : props.maxWidth\n }\n if (props.maxHeight) {\n style.maxHeight = typeof props.maxHeight === 'number' ? `${props.maxHeight}px` : props.maxHeight\n }\n\n // 位置\n if (props.position !== 'center') {\n if (props.top) style.top = typeof props.top === 'number' ? `${props.top}px` : props.top\n if (props.bottom) style.bottom = typeof props.bottom === 'number' ? `${props.bottom}px` : props.bottom\n if (props.left && props.position === 'left') style.left = typeof props.left === 'number' ? `${props.left}px` : props.left\n if (props.right && props.position === 'right') style.right = typeof props.right === 'number' ? `${props.right}px` : props.right\n }\n\n return style\n})\n\n// 计算内容区域样式\nconst bodyStyle = computed(() => {\n const style: Record<string, string> = {}\n if (props.height && props.height !== 'auto') {\n style.overflowY = 'auto'\n }\n return style\n})\n\n// 计算弹窗样式(包含调整大小后的尺寸)\nconst computedModalStyle = computed(() => {\n const style = { ...modalStyle.value }\n \n if (isFullscreen.value) {\n return {\n ...style,\n width: '100vw !important',\n height: '100vh !important',\n maxWidth: '100vw !important',\n maxHeight: '100vh !important',\n top: '0 !important',\n left: '0 !important',\n right: '0 !important',\n bottom: '0 !important'\n }\n }\n \n if (resizing.value || modalSize.value.width > 0) {\n if (modalSize.value.width > 0) style.width = `${modalSize.value.width}px`\n if (modalSize.value.height > 0) style.height = `${modalSize.value.height}px`\n if (props.position === 'right' && modalSize.value.right >= 0) style.right = `${modalSize.value.right}px`\n if (props.position === 'left' && modalSize.value.left >= 0) style.left = `${modalSize.value.left}px`\n if (modalSize.value.top >= 0) style.top = `${modalSize.value.top}px`\n if (modalSize.value.bottom >= 0) style.bottom = `${modalSize.value.bottom}px`\n }\n \n return style\n})\n\nfunction handleClose() {\n emit('update:show', false)\n emit('close')\n}\n\nfunction handleCancel() {\n emit('cancel')\n handleClose()\n}\n\nfunction handleConfirm() {\n emit('confirm')\n}\n\nfunction handleMaskClick() {\n if (props.maskClosable) {\n handleClose()\n }\n}\n\nfunction toggleFullscreen() {\n isFullscreen.value = !isFullscreen.value\n}\n\nfunction startResize(direction: string) {\n if (!modalRef.value) return\n \n resizing.value = true\n resizeDirection.value = direction\n \n const rect = modalRef.value.getBoundingClientRect()\n modalSize.value = {\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n right: window.innerWidth - rect.right,\n bottom: window.innerHeight - rect.bottom\n }\n \n document.addEventListener('mousemove', handleResize)\n document.addEventListener('mouseup', stopResize)\n document.body.style.cursor = getCursor(direction)\n document.body.style.userSelect = 'none'\n}\n\nfunction handleResize(e: MouseEvent) {\n if (!resizing.value || !modalRef.value) return\n \n const direction = resizeDirection.value\n \n if (direction === 'right') {\n if (props.position === 'right') {\n const newRight = window.innerWidth - e.clientX\n modalSize.value.right = Math.max(0, newRight)\n modalSize.value.width = e.clientX - modalSize.value.left\n } else {\n modalSize.value.width = e.clientX - modalSize.value.left\n }\n } else if (direction === 'left') {\n if (props.position === 'left') {\n modalSize.value.left = e.clientX\n modalSize.value.width = window.innerWidth - e.clientX - modalSize.value.right\n } else {\n const newWidth = modalSize.value.width + (modalSize.value.left - e.clientX)\n modalSize.value.width = newWidth\n modalSize.value.left = e.clientX\n }\n } else if (direction === 'top') {\n const newHeight = modalSize.value.height + (modalSize.value.top - e.clientY)\n modalSize.value.height = Math.max(200, newHeight)\n modalSize.value.top = e.clientY\n } else if (direction === 'bottom') {\n modalSize.value.height = e.clientY - modalSize.value.top\n modalSize.value.bottom = window.innerHeight - e.clientY\n }\n}\n\nfunction stopResize() {\n resizing.value = false\n resizeDirection.value = ''\n document.removeEventListener('mousemove', handleResize)\n document.removeEventListener('mouseup', stopResize)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n}\n\nfunction getCursor(direction: string): string {\n switch (direction) {\n case 'top':\n case 'bottom':\n return 'ns-resize'\n case 'left':\n case 'right':\n return 'ew-resize'\n default:\n return 'default'\n }\n}\n\nonUnmounted(() => {\n if (resizing.value) {\n stopResize()\n }\n})\n</script>\n\n<style scoped lang=\"scss\">\n// 过渡动画\n.fade-scale-enter-active,\n.fade-scale-leave-active {\n transition: opacity 0.25s ease, transform 0.25s ease;\n}\n\n.fade-scale-enter-from,\n.fade-scale-leave-to {\n opacity: 0;\n transform: scale(0.95);\n}\n\n.slide-left-enter-active,\n.slide-left-leave-active,\n.slide-right-enter-active,\n.slide-right-leave-active,\n.slide-top-enter-active,\n.slide-top-leave-active,\n.slide-bottom-enter-active,\n.slide-bottom-leave-active {\n transition: opacity 0.25s ease, transform 0.25s ease;\n}\n\n.slide-left-enter-from,\n.slide-left-leave-to {\n opacity: 0;\n transform: translateX(-20px);\n}\n\n.slide-right-enter-from,\n.slide-right-leave-to {\n opacity: 0;\n transform: translateX(20px);\n}\n\n.slide-top-enter-from,\n.slide-top-leave-to {\n opacity: 0;\n transform: translateY(-20px);\n}\n\n.slide-bottom-enter-from,\n.slide-bottom-leave-to {\n opacity: 0;\n transform: translateY(20px);\n}\n\n// 包裹层\n.universal-modal-wrapper {\n position: fixed;\n inset: 0;\n display: flex;\n z-index: 1000;\n\n &.with-mask {\n background: rgba(0, 0, 0, 0.45);\n }\n\n &.no-mask {\n background: transparent;\n pointer-events: none;\n }\n\n &.position-center {\n align-items: center;\n justify-content: center;\n padding: 24px;\n }\n\n &.position-left {\n justify-content: flex-start;\n }\n\n &.position-right {\n justify-content: flex-end;\n }\n\n &.position-top {\n align-items: flex-start;\n }\n\n &.position-bottom {\n align-items: flex-end;\n }\n\n &.fullscreen {\n padding: 0;\n }\n}\n\n// 弹窗主体\n.universal-modal {\n position: relative;\n background: var(--bg-primary, #ffffff);\n border-radius: var(--radius-xl, 16px);\n box-shadow: 0 20px 50px rgba(15, 23, 42, 0.14);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n pointer-events: auto;\n height: 100%;\n\n &.modal-center {\n margin: auto;\n height: auto;\n }\n\n &.modal-left,\n &.modal-right {\n position: absolute;\n }\n\n &.modal-top,\n &.modal-bottom {\n position: absolute;\n max-width: calc(100vw - 48px);\n height: auto;\n }\n\n &.modal-fullscreen {\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n border-radius: 0;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n }\n}\n\n// 调整大小的边框\n.resize-handle {\n position: absolute;\n z-index: 10;\n \n &-top,\n &-bottom {\n left: 0;\n right: 0;\n height: 4px;\n cursor: ns-resize;\n \n &:hover {\n background: rgba(99, 102, 241, 0.3);\n }\n }\n \n &-top {\n top: 0;\n }\n \n &-bottom {\n bottom: 0;\n }\n \n &-left,\n &-right {\n top: 0;\n bottom: 0;\n width: 4px;\n cursor: ew-resize;\n \n &:hover {\n background: rgba(99, 102, 241, 0.3);\n }\n }\n \n &-left {\n left: 0;\n }\n \n &-right {\n right: 0;\n }\n}\n\n// 头部\n.modal-header {\n padding: 16px 20px 12px;\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 12px;\n border-bottom: 1px solid var(--border-secondary, #f2f3f5);\n background: linear-gradient(180deg, rgba(248, 249, 255, 0.8), #fff);\n flex-shrink: 0;\n}\n\n.header-content {\n display: flex;\n gap: 12px;\n align-items: flex-start;\n flex: 1;\n min-width: 0;\n}\n\n.header-icon {\n width: 32px;\n height: 32px;\n border-radius: 10px;\n background: radial-gradient(circle at 30% 20%, #e6e8ff, #cdcfff);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n\n .header-icon-img {\n width: 24px;\n height: 24px;\n object-fit: contain;\n }\n}\n\n.header-info {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.header-subtitle {\n font-size: var(--font-size-sm, 12px);\n color: var(--text-tertiary, #86909c);\n line-height: 1.3;\n}\n\n.header-title {\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--text-primary, #1f2329);\n line-height: 1.3;\n word-break: break-word;\n}\n\n.header-actions {\n display: flex;\n gap: 8px;\n align-items: center;\n flex-shrink: 0;\n}\n\n.header-btn {\n width: 28px;\n height: 28px;\n border: none;\n background: transparent;\n border-radius: var(--radius-full, 9999px);\n color: var(--text-tertiary, #86909c);\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n \n &:hover {\n background: var(--bg-secondary, #f7f8fa);\n color: var(--text-primary, #1f2329);\n }\n}\n\n// 内容区域\n.modal-body {\n flex: 1;\n padding: 20px 24px;\n overflow-y: auto;\n overflow-x: hidden;\n min-height: 0;\n max-height: 100%;\n\n &::-webkit-scrollbar {\n width: 6px;\n }\n\n &::-webkit-scrollbar-thumb {\n background: var(--gray-300, #d4d4d4);\n border-radius: var(--radius-full, 9999px);\n\n &:hover {\n background: var(--gray-400, #a3a3a3);\n }\n }\n}\n\n// 底部\n.modal-footer {\n padding: 16px 24px;\n border-top: 1px solid var(--border-secondary, #f2f3f5);\n background: var(--bg-secondary, #f7f8fa);\n flex-shrink: 0;\n}\n\n.footer-actions {\n display: flex;\n justify-content: flex-end;\n gap: 12px;\n}\n\n.footer-btn {\n padding: var(--spacing-sm, 8px) var(--spacing-lg, 16px);\n border: none;\n border-radius: var(--radius-md, 8px);\n font-size: var(--font-size-sm, 12px);\n font-weight: var(--font-weight-medium, 500);\n cursor: pointer;\n transition: all 0.2s ease;\n \n &--cancel {\n background: var(--bg-secondary, #f7f8fa);\n color: var(--text-primary, #1f2329);\n border: 1px solid var(--border-primary, #e5e6eb);\n \n &:hover {\n background: var(--bg-tertiary, #f2f3f5);\n }\n }\n \n &--confirm {\n background: linear-gradient(135deg, var(--primary, #6366f1) 0%, var(--secondary, #8b5cf6) 100%);\n color: var(--text-white, #ffffff);\n box-shadow: 0 4px 12px rgba(99, 102, 241, 0.25);\n \n &:hover {\n box-shadow: 0 8px 20px rgba(99, 102, 241, 0.3);\n transform: translateY(-1px);\n }\n }\n}\n\n// 响应式\n@media (max-width: 768px) {\n .universal-modal-wrapper {\n &.position-center {\n padding: 16px;\n }\n }\n\n .universal-modal {\n &.modal-left,\n &.modal-right {\n max-height: calc(100vh - 32px);\n }\n\n &.modal-top,\n &.modal-bottom {\n max-width: calc(100vw - 32px);\n }\n }\n\n .modal-header {\n padding: 14px 16px 10px;\n }\n\n .modal-body {\n padding: 16px 20px;\n }\n\n .modal-footer {\n padding: 12px 20px;\n }\n}\n</style>\n","<template>\n <div class=\"loading-container\">\n <div class=\"loading-spinner\"></div>\n <p v-if=\"message\" class=\"loading-message\">{{ message }}</p>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefineProps<{\n message?: string\n}>()\n</script>\n\n<style scoped>\n.loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 200px;\n padding: var(--spacing-4xl, 40px);\n}\n\n.loading-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid var(--border-secondary, #f0f2f5);\n border-top-color: var(--primary, #6366f1);\n border-radius: var(--radius-full, 9999px);\n animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.loading-message {\n margin-top: var(--spacing-lg, 16px);\n font-size: var(--font-size-sm, 12px);\n color: var(--text-secondary, #4e5969);\n}\n</style>\n","<template>\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\n <slot name=\"icon\">\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M32 8C18.745 8 8 18.745 8 32s10.745 24 24 24 24-10.745 24-24S45.255 8 32 8zm0 44c-11.028 0-20-8.972-20-20s8.972-20 20-20 20 8.972 20 20-8.972 20-20 20z\" fill=\"currentColor\" opacity=\"0.3\"/>\n <path d=\"M32 24c-1.105 0-2 .895-2 2v12c0 1.105.895 2 2 2s2-.895 2-2V26c0-1.105-.895-2-2-2zm0 20c-1.105 0-2 .895-2 2s.895 2 2 2 2-.895 2-2-.895-2-2-2z\" fill=\"currentColor\"/>\n </svg>\n </slot>\n </div>\n <h3 class=\"empty-title\">{{ title }}</h3>\n <p v-if=\"description\" class=\"empty-description\">{{ description }}</p>\n <div v-if=\"$slots.action\" class=\"empty-action\">\n <slot name=\"action\"></slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nwithDefaults(defineProps<{\n title?: string\n description?: string\n}>(), {\n title: '暂无数据'\n})\n</script>\n\n<style scoped>\n.empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-5xl, 48px) var(--spacing-2xl, 24px);\n text-align: center;\n}\n\n.empty-icon {\n font-size: 48px;\n color: var(--text-quaternary, #c9cdd4);\n margin-bottom: var(--spacing-lg, 16px);\n}\n\n.empty-title {\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-medium, 500);\n color: var(--text-secondary, #4e5969);\n margin-bottom: var(--spacing-sm, 8px);\n}\n\n.empty-description {\n font-size: var(--font-size-sm, 12px);\n color: var(--text-tertiary, #86909c);\n max-width: 400px;\n margin: 0;\n}\n\n.empty-action {\n margin-top: var(--spacing-lg, 16px);\n}\n</style>\n","<template>\n <div class=\"error-container\">\n <div class=\"error-icon\">\n <slot name=\"icon\">\n <svg width=\"64\" height=\"64\" viewBox=\"0 0 64 64\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M32 8C18.745 8 8 18.745 8 32s10.745 24 24 24 24-10.745 24-24S45.255 8 32 8zm0 44c-11.028 0-20-8.972-20-20s8.972-20 20-20 20 8.972 20 20-8.972 20-20 20z\" fill=\"currentColor\" opacity=\"0.3\"/>\n <path d=\"M38.828 22.172a2 2 0 00-2.828 0L32 26.172l-4-4a2 2 0 10-2.828 2.828L29.172 29l-4 4a2 2 0 102.828 2.828L32 31.828l4 4a2 2 0 102.828-2.828L34.828 29l4-4a2 2 0 000-2.828z\" fill=\"currentColor\"/>\n </svg>\n </slot>\n </div>\n <h3 class=\"error-title\">{{ title }}</h3>\n <p class=\"error-message\">{{ errorMessage }}</p>\n <div v-if=\"$slots.action || showRetry\" class=\"error-action\">\n <slot name=\"action\">\n <button v-if=\"showRetry\" @click=\"handleRetry\" class=\"error-retry-btn\">\n 重试\n </button>\n </slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nconst props = withDefaults(defineProps<{\n error?: Error | string\n title?: string\n showRetry?: boolean\n}>(), {\n title: '出错了',\n showRetry: false\n})\n\nconst emit = defineEmits<{\n retry: []\n}>()\n\nconst errorMessage = computed(() => {\n if (!props.error) return '发生了未知错误'\n if (typeof props.error === 'string') return props.error\n return props.error.message || '发生了未知错误'\n})\n\nconst handleRetry = () => {\n emit('retry')\n}\n</script>\n\n<style scoped>\n.error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: var(--spacing-4xl, 40px) var(--spacing-2xl, 24px);\n text-align: center;\n}\n\n.error-icon {\n font-size: 48px;\n color: var(--error, #ef4444);\n margin-bottom: var(--spacing-lg, 16px);\n}\n\n.error-title {\n font-size: var(--font-size-lg, 16px);\n font-weight: var(--font-weight-semibold, 600);\n color: var(--error, #ef4444);\n margin-bottom: var(--spacing-sm, 8px);\n}\n\n.error-message {\n font-size: var(--font-size-sm, 12px);\n color: var(--text-secondary, #4e5969);\n max-width: 500px;\n margin: 0 0 var(--spacing-lg, 16px);\n}\n\n.error-action {\n margin-top: var(--spacing-lg, 16px);\n}\n\n.error-retry-btn {\n padding: var(--spacing-sm, 8px) var(--spacing-lg, 16px);\n font-size: var(--font-size-sm, 12px);\n color: white;\n background-color: var(--primary, #6366f1);\n border: none;\n border-radius: var(--radius-md, 8px);\n cursor: pointer;\n transition: opacity var(--transition-fast, 0.15s) ease;\n}\n\n.error-retry-btn:hover {\n opacity: 0.8;\n}\n\n.error-retry-btn:active {\n opacity: 0.6;\n}\n</style>\n"],"names":["ref","computed","options","onMounted","onUnmounted","_openBlock","_createElementBlock","_hoisted_1","_renderSlot","_createElementVNode","_hoisted_2","$slots","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_normalizeClass","_toDisplayString","_Fragment","_renderList","watch","nextTick","_createTextVNode","_hoisted_10","_createVNode","_Transition","_normalizeStyle","useSlots","_createBlock"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,24 @@
1
1
  /**
2
- * @gress/plugin-ui
2
+ * @keqi.gress/plugin-ui
3
3
  *
4
4
  * Gress 插件 UI 组件和样式包
5
5
  * 提供统一的设计系统和通用组件
6
6
  */
7
+ import './styles/main.scss';
7
8
  export { useLoadingState } from './composables/useLoadingState';
8
- export type { LoadingState, UseLoadingStateOptions } from './composables/useLoadingState';
9
+ export type { LoadingState as LoadingStateType, UseLoadingStateOptions } from './composables/useLoadingState';
9
10
  export { useResponsive, breakpoints } from './composables/useResponsive';
10
11
  export type { UseResponsiveReturn, Breakpoint, BreakpointValues } from './composables/useResponsive';
11
- export { default as LoadingStateComponent } from './components/LoadingState.vue';
12
- export { default as EmptyState } from './components/EmptyState.vue';
13
- export { default as ErrorState } from './components/ErrorState.vue';
12
+ export { default as PageContainer } from './components/layout/PageContainer.vue';
13
+ export { default as PageContent } from './components/layout/PageContent.vue';
14
+ export { default as PageHeader } from './components/layout/PageHeader.vue';
15
+ export { default as CardList } from './components/data/CardList.vue';
16
+ export { default as PagePagination } from './components/data/PagePagination.vue';
17
+ export { default as LogViewer } from './components/data/LogViewer.vue';
18
+ export { default as FilterPanel } from './components/interaction/FilterPanel.vue';
19
+ export { default as UniversalModal } from './components/interaction/UniversalModal.vue';
20
+ export { default as LoadingState } from './components/feedback/LoadingState.vue';
21
+ export { default as EmptyState } from './components/feedback/EmptyState.vue';
22
+ export { default as ErrorState } from './components/feedback/ErrorState.vue';
23
+ export type { PageHeaderProps, CardListProps, PagePaginationProps, PagePaginationEmits, LogItem, LogViewerProps, LogViewerEmits, FilterPanelProps, FilterPanelEmits, FilterFieldConfig, FilterFieldType, UniversalModalProps, UniversalModalEmits, PositionType } from './components/types';
14
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,YAAY,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAEzF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACxE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAKpG,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,6BAA6B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,oBAAoB,CAAA;AAS3B,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,YAAY,EAAE,YAAY,IAAI,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AAE7G,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACxE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAKpG,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,uCAAuC,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,qCAAqC,CAAA;AAC5E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,oCAAoC,CAAA;AAK1E,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sCAAsC,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAKtE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,6CAA6C,CAAA;AAKvF,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,wCAAwC,CAAA;AAChF,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,sCAAsC,CAAA;AAC5E,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,sCAAsC,CAAA;AAK5E,YAAY,EAEV,eAAe,EAGf,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,OAAO,EACP,cAAc,EACd,cAAc,EAGd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACb,MAAM,oBAAoB,CAAA"}