refactor(layouts): remove unused layout components from index export
Some checks failed
Build and Deploy / deploy (push) Has been cancelled
Some checks failed
Build and Deploy / deploy (push) Has been cancelled
Removed BasicLayout, CardLayout, FormLayout, and TabLayout components from the layouts index file since they are no longer being used in the application. Only FullWidthLayout and LayoutHeader remain exported.
This commit is contained in:
@@ -1,297 +0,0 @@
|
|||||||
# 统一布局组件
|
|
||||||
|
|
||||||
为项目提供5种不同类型的布局组件,保持设计一致性和代码复用性。
|
|
||||||
|
|
||||||
## 布局组件类型
|
|
||||||
|
|
||||||
### 1. BasicLayout - 基础布局
|
|
||||||
最通用的布局组件,适用于大多数页面。
|
|
||||||
|
|
||||||
**特点:**
|
|
||||||
- 标准页面头部(标题 + 副标题)
|
|
||||||
- 灵活的内容区域
|
|
||||||
- 支持返回按钮和额外操作
|
|
||||||
|
|
||||||
**使用场景:**
|
|
||||||
- 列表页面
|
|
||||||
- 详情页面
|
|
||||||
- 数据统计页面
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<BasicLayout
|
|
||||||
title="用户列表"
|
|
||||||
subtitle="管理系统中的所有用户"
|
|
||||||
:show-back="true"
|
|
||||||
@back="handleBack"
|
|
||||||
>
|
|
||||||
<template #extra>
|
|
||||||
<a-button type="primary">新增用户</a-button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a-table :columns="columns" :data-source="data" />
|
|
||||||
</BasicLayout>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. CardLayout - 卡片布局
|
|
||||||
内容包装在卡片中,提供更好的视觉层次。
|
|
||||||
|
|
||||||
**特点:**
|
|
||||||
- Ant Design Card 容器
|
|
||||||
- 可配置的边距
|
|
||||||
- 灵活的标题栏
|
|
||||||
|
|
||||||
**使用场景:**
|
|
||||||
- 表单页面
|
|
||||||
- 配置页面
|
|
||||||
- 详情展示页面
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<CardLayout
|
|
||||||
title="用户信息"
|
|
||||||
:show-back="true"
|
|
||||||
:show-padding="true"
|
|
||||||
>
|
|
||||||
<template #extra>
|
|
||||||
<a-button>编辑</a-button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a-form layout="vertical">
|
|
||||||
<a-form-item label="姓名">
|
|
||||||
<a-input v-model:value="form.name" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</CardLayout>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. TabLayout - 标签页布局
|
|
||||||
多标签页内容组织。
|
|
||||||
|
|
||||||
**特点:**
|
|
||||||
- 动态标签页
|
|
||||||
- 支持懒加载
|
|
||||||
- 自定义标签页内容
|
|
||||||
|
|
||||||
**使用场景:**
|
|
||||||
- 设置页面
|
|
||||||
- 数据对比
|
|
||||||
- 多模块内容
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<TabLayout
|
|
||||||
:tabs="tabs"
|
|
||||||
v-model:active-key="activeKey"
|
|
||||||
@change="handleTabChange"
|
|
||||||
>
|
|
||||||
<template #tab1>
|
|
||||||
<div>标签页1内容</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #tab2>
|
|
||||||
<div>标签页2内容</div>
|
|
||||||
</template>
|
|
||||||
</TabLayout>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const tabs = ref([
|
|
||||||
{ key: 'tab1', tab: '基础信息', forceRender: true },
|
|
||||||
{ key: 'tab2', tab: '高级设置', forceRender: false }
|
|
||||||
])
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. FullWidthLayout - 全宽布局
|
|
||||||
充分利用屏幕宽度的布局。
|
|
||||||
|
|
||||||
**特点:**
|
|
||||||
- 全宽度内容
|
|
||||||
- 自定义头部
|
|
||||||
- 无卡片包装
|
|
||||||
|
|
||||||
**使用场景:**
|
|
||||||
- 数据可视化
|
|
||||||
- 宽屏内容展示
|
|
||||||
- 全屏应用
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<FullWidthLayout :show-back="true">
|
|
||||||
<template #header>
|
|
||||||
<h2>数据分析仪表板</h2>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #extra>
|
|
||||||
<a-button-group>
|
|
||||||
<a-button>导出</a-button>
|
|
||||||
<a-button>刷新</a-button>
|
|
||||||
</a-button-group>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<div class="dashboard-grid">
|
|
||||||
<!-- 图表组件 -->
|
|
||||||
</div>
|
|
||||||
</FullWidthLayout>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. FormLayout - 表单布局
|
|
||||||
专门用于表单页面。
|
|
||||||
|
|
||||||
**特点:**
|
|
||||||
- 居中的表单容器
|
|
||||||
- 内置提交/取消按钮
|
|
||||||
- 加载状态管理
|
|
||||||
|
|
||||||
**使用场景:**
|
|
||||||
- 创建/编辑页面
|
|
||||||
- 复杂表单
|
|
||||||
- 向导式表单
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<FormLayout
|
|
||||||
title="创建用户"
|
|
||||||
:submit-loading="submitting"
|
|
||||||
@submit="handleSubmit"
|
|
||||||
@cancel="handleCancel"
|
|
||||||
>
|
|
||||||
<a-form layout="vertical">
|
|
||||||
<a-form-item label="姓名" required>
|
|
||||||
<a-input v-model:value="form.name" />
|
|
||||||
</a-form-item>
|
|
||||||
|
|
||||||
<a-form-item label="邮箱" required>
|
|
||||||
<a-input v-model:value="form.email" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</FormLayout>
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 设计特色
|
|
||||||
|
|
||||||
### 1. 统一的设计语言
|
|
||||||
- 使用项目的设计令牌(Design Tokens)
|
|
||||||
- 一致的颜色、字体、间距
|
|
||||||
- Notion 风格的标签页设计
|
|
||||||
|
|
||||||
### 2. 响应式设计
|
|
||||||
- 移动端友好
|
|
||||||
- 自适应布局
|
|
||||||
- 弹性内容区域
|
|
||||||
|
|
||||||
### 3. 可访问性
|
|
||||||
- 语义化 HTML
|
|
||||||
- 键盘导航支持
|
|
||||||
- 屏幕阅读器友好
|
|
||||||
|
|
||||||
### 4. 性能优化
|
|
||||||
- 懒加载支持
|
|
||||||
- keep-alive 兼容
|
|
||||||
- 轻量级实现
|
|
||||||
|
|
||||||
## 导入方式
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 单独导入
|
|
||||||
import BasicLayout from '@/layouts/components/BasicLayout.vue'
|
|
||||||
import CardLayout from '@/layouts/components/CardLayout.vue'
|
|
||||||
import TabLayout from '@/layouts/components/TabLayout.vue'
|
|
||||||
import FullWidthLayout from '@/layouts/components/FullWidthLayout.vue'
|
|
||||||
import FormLayout from '@/layouts/components/FormLayout.vue'
|
|
||||||
|
|
||||||
// 批量导入
|
|
||||||
import {
|
|
||||||
BasicLayout,
|
|
||||||
CardLayout,
|
|
||||||
TabLayout,
|
|
||||||
FullWidthLayout,
|
|
||||||
FormLayout
|
|
||||||
} from '@/layouts/components'
|
|
||||||
```
|
|
||||||
|
|
||||||
## Props 说明
|
|
||||||
|
|
||||||
### 通用 Props
|
|
||||||
|
|
||||||
| 属性 | 类型 | 默认值 | 说明 |
|
|
||||||
|------|------|--------|------|
|
|
||||||
| showBack | Boolean | false | 是否显示返回按钮 |
|
|
||||||
| title | String | '' | 页面标题 |
|
|
||||||
| subtitle | String | '' | 页面副标题 |
|
|
||||||
|
|
||||||
### TabLayout 特有 Props
|
|
||||||
|
|
||||||
| 属性 | 类型 | 必需 | 说明 |
|
|
||||||
|------|------|------|------|
|
|
||||||
| tabs | Array | 是 | 标签页配置数组 |
|
|
||||||
| activeKey | String | 否 | 当前激活的标签页 |
|
|
||||||
|
|
||||||
### FormLayout 特有 Props
|
|
||||||
|
|
||||||
| 属性 | 类型 | 默认值 | 说明 |
|
|
||||||
|------|------|--------|------|
|
|
||||||
| submitText | String | '提交' | 提交按钮文字 |
|
|
||||||
| cancelText | String | '取消' | 取消按钮文字 |
|
|
||||||
| showCancel | Boolean | true | 是否显示取消按钮 |
|
|
||||||
| submitLoading | Boolean | false | 提交按钮加载状态 |
|
|
||||||
|
|
||||||
## 插槽(Slots)
|
|
||||||
|
|
||||||
### 通用插槽
|
|
||||||
|
|
||||||
- `#extra` - 头部右侧额外操作区域
|
|
||||||
- `#header` - 自定义头部内容(某些布局)
|
|
||||||
|
|
||||||
### TabLayout 插槽
|
|
||||||
|
|
||||||
- `#tab1`, `#tab2`, ... - 标签页内容,名称为 tabs 中的 key
|
|
||||||
|
|
||||||
## 事件(Events)
|
|
||||||
|
|
||||||
### 通用事件
|
|
||||||
|
|
||||||
- `@back` - 点击返回按钮时触发
|
|
||||||
|
|
||||||
### TabLayout 事件
|
|
||||||
|
|
||||||
- `@change(key)` - 标签页切换时触发
|
|
||||||
|
|
||||||
### FormLayout 事件
|
|
||||||
|
|
||||||
- `@submit` - 点击提交按钮时触发
|
|
||||||
- `@cancel` - 点击取消按钮时触发
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
1. **选择合适的布局**
|
|
||||||
- 简单内容 → BasicLayout
|
|
||||||
- 需要卡片容器 → CardLayout
|
|
||||||
- 多标签内容 → TabLayout
|
|
||||||
- 宽屏内容 → FullWidthLayout
|
|
||||||
- 表单页面 → FormLayout
|
|
||||||
|
|
||||||
2. **保持一致性**
|
|
||||||
- 使用统一的设计令牌
|
|
||||||
- 遵循项目的设计规范
|
|
||||||
- 保持交互行为一致
|
|
||||||
|
|
||||||
3. **性能优化**
|
|
||||||
- 设置合适的 `forceRender` 属性
|
|
||||||
- 使用 `keep-alive` 缓存组件
|
|
||||||
- 避免不必要的重渲染
|
|
||||||
|
|
||||||
4. **可访问性**
|
|
||||||
- 为所有交互元素添加适当的标签
|
|
||||||
- 确保键盘导航正常工作
|
|
||||||
- 提供适当的焦点管理
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
defineOptions({ name: 'BasicLayout' })
|
|
||||||
defineProps({
|
|
||||||
title: { type: String, default: '' },
|
|
||||||
showBack: { type: Boolean, default: false },
|
|
||||||
extra: { type: Object, default: () => ({}) }
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['back'])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex flex-col h-full overflow-hidden">
|
|
||||||
<!-- 页面内容 -->
|
|
||||||
<div class="flex-1 flex flex-col overflow-x-hidden overflow-y-auto p-4">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
/* 使用 Tailwind 类,已移除旧样式 */
|
|
||||||
</style>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import LayoutHeader from './LayoutHeader.vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'CardLayout' })
|
|
||||||
|
|
||||||
// Props
|
|
||||||
const props = defineProps({
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
showBack: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
showPadding: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Emits
|
|
||||||
const emit = defineEmits(['back'])
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
const handleBack = () => {
|
|
||||||
emit('back')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex flex-col h-full overflow-hidden rounded-xl border bg-card">
|
|
||||||
<LayoutHeader
|
|
||||||
:title="title"
|
|
||||||
:show-back="showBack"
|
|
||||||
@back="handleBack"
|
|
||||||
>
|
|
||||||
<template #extra>
|
|
||||||
<slot name="extra"></slot>
|
|
||||||
</template>
|
|
||||||
</LayoutHeader>
|
|
||||||
|
|
||||||
<!-- 卡片内容 -->
|
|
||||||
<div class="flex-1 flex flex-col overflow-hidden bg-card">
|
|
||||||
<div
|
|
||||||
v-if="!$slots.title && title"
|
|
||||||
class="px-6 py-4 bg-muted/50 border-b text-sm font-medium text-muted-foreground uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{{ title }}
|
|
||||||
</div>
|
|
||||||
<slot v-else name="title"></slot>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex-1 overflow-auto bg-card"
|
|
||||||
:class="{ 'p-0': !showPadding, 'p-4': showPadding }"
|
|
||||||
>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
/* 使用 Tailwind 类,已移除旧样式 */
|
|
||||||
</style>
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { Icon } from '@iconify/vue'
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import LayoutHeader from './LayoutHeader.vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'FormLayout' })
|
|
||||||
|
|
||||||
// Props
|
|
||||||
const props = defineProps({
|
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
showBack: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
submitText: {
|
|
||||||
type: String,
|
|
||||||
default: '提交'
|
|
||||||
},
|
|
||||||
cancelText: {
|
|
||||||
type: String,
|
|
||||||
default: '取消'
|
|
||||||
},
|
|
||||||
showCancel: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
submitLoading: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
showFooter: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Emits
|
|
||||||
const emit = defineEmits(['submit', 'cancel', 'back'])
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex flex-col h-full overflow-hidden rounded-xl border bg-card">
|
|
||||||
<LayoutHeader
|
|
||||||
:title="title"
|
|
||||||
:show-back="showBack"
|
|
||||||
@back="emit('back')"
|
|
||||||
>
|
|
||||||
<template #extra>
|
|
||||||
<slot name="extra"></slot>
|
|
||||||
</template>
|
|
||||||
</LayoutHeader>
|
|
||||||
|
|
||||||
<!-- 表单内容 -->
|
|
||||||
<div class="flex-1 overflow-auto bg-muted/50 flex items-center justify-center p-4">
|
|
||||||
<div class="w-full max-w-[600px] rounded-xl border bg-card p-10">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 底部操作栏 -->
|
|
||||||
<div v-if="showFooter" class="shrink-0 border-t px-6 py-4 bg-card">
|
|
||||||
<div class="max-w-[600px] mx-auto flex justify-end gap-3">
|
|
||||||
<Button v-if="showCancel" variant="outline" @click="emit('cancel')">
|
|
||||||
{{ cancelText }}
|
|
||||||
</Button>
|
|
||||||
<Button :disabled="submitLoading" @click="emit('submit')">
|
|
||||||
<Icon v-if="submitLoading" icon="lucide:loader-2" class="mr-2 h-4 w-4 animate-spin" />
|
|
||||||
{{ submitText }}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
/* 已移除旧样式,使用 Tailwind 类 */
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
.form-layout {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
background: var(--color-bg-card);
|
|
||||||
border: 1px solid var(--color-gray-200);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-layout__content {
|
|
||||||
flex: 1;
|
|
||||||
overflow: auto;
|
|
||||||
padding: var(--space-4);
|
|
||||||
background: var(--color-gray-50);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 600px;
|
|
||||||
background: var(--color-bg-card);
|
|
||||||
border: 1px solid var(--color-gray-200);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
padding: var(--space-10);
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-layout__footer {
|
|
||||||
padding: var(--space-4) var(--space-6);
|
|
||||||
border-top: 1px solid var(--color-gray-200);
|
|
||||||
background: var(--color-bg-card);
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-content {
|
|
||||||
max-width: 600px;
|
|
||||||
margin: 0 auto;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ref, watch } from 'vue'
|
|
||||||
import { Icon } from '@iconify/vue'
|
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
|
||||||
import LayoutHeader from './LayoutHeader.vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'TabLayout' })
|
|
||||||
|
|
||||||
// Props
|
|
||||||
const props = defineProps({
|
|
||||||
tabs: {
|
|
||||||
type: Array,
|
|
||||||
required: true,
|
|
||||||
default: () => []
|
|
||||||
},
|
|
||||||
activeKey: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
showBack: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Emits
|
|
||||||
const emit = defineEmits(['update:activeKey', 'change', 'back'])
|
|
||||||
|
|
||||||
// State
|
|
||||||
const activeTabKey = ref(props.activeKey)
|
|
||||||
|
|
||||||
// Watch for external changes
|
|
||||||
watch(() => props.activeKey, (newKey) => {
|
|
||||||
if (newKey !== activeTabKey.value) {
|
|
||||||
activeTabKey.value = newKey
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Methods
|
|
||||||
const handleTabChange = (key) => {
|
|
||||||
activeTabKey.value = key
|
|
||||||
emit('update:activeKey', key)
|
|
||||||
emit('change', key)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleBack = () => {
|
|
||||||
emit('back')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="flex flex-col h-full overflow-hidden rounded-xl border bg-card">
|
|
||||||
<div v-if="$slots.header || showBack" class="shrink-0">
|
|
||||||
<LayoutHeader
|
|
||||||
:show-back="showBack"
|
|
||||||
@back="handleBack"
|
|
||||||
>
|
|
||||||
<template #header v-if="$slots.header">
|
|
||||||
<slot name="header"></slot>
|
|
||||||
</template>
|
|
||||||
<template #extra>
|
|
||||||
<slot name="extra"></slot>
|
|
||||||
</template>
|
|
||||||
</LayoutHeader>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 标签页导航 -->
|
|
||||||
<Tabs v-model="activeTabKey" class="w-full" @update:modelValue="handleTabChange">
|
|
||||||
<TabsList class="w-full justify-start border-b bg-muted/50 px-4">
|
|
||||||
<TabsTrigger
|
|
||||||
v-for="tab in tabs"
|
|
||||||
:key="tab.key"
|
|
||||||
:value="tab.key"
|
|
||||||
class="data-[state=active]:bg-card"
|
|
||||||
>
|
|
||||||
{{ tab.tab }}
|
|
||||||
</TabsTrigger>
|
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<!-- 标签页内容 -->
|
|
||||||
<TabsContent :value="activeTabKey" class="flex-1 overflow-auto p-4">
|
|
||||||
<slot :name="activeTabKey"></slot>
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
|
||||||
/* 使用 Tailwind + shadcn 组件,已移除旧样式 */
|
|
||||||
</style>
|
|
||||||
@@ -1,16 +1,7 @@
|
|||||||
|
|
||||||
import BasicLayout from './BasicLayout.vue'
|
|
||||||
import CardLayout from './CardLayout.vue'
|
|
||||||
import FormLayout from './FormLayout.vue'
|
|
||||||
import FullWidthLayout from './FullWidthLayout.vue'
|
import FullWidthLayout from './FullWidthLayout.vue'
|
||||||
import TabLayout from './TabLayout.vue'
|
|
||||||
import LayoutHeader from './LayoutHeader.vue'
|
import LayoutHeader from './LayoutHeader.vue'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
BasicLayout,
|
|
||||||
CardLayout,
|
|
||||||
FormLayout,
|
|
||||||
FullWidthLayout,
|
FullWidthLayout,
|
||||||
TabLayout,
|
|
||||||
LayoutHeader
|
LayoutHeader
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user