Skip to content

Commit 07eaee7

Browse files
committed
feat(shared): SectionLayout 组件增加 clone 方法
1 parent e5357b7 commit 07eaee7

File tree

14 files changed

+798
-244
lines changed

14 files changed

+798
-244
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ coverage
2020
*.njsproj
2121
*.sln
2222
*.sw?
23+
24+
playground/types/auto-imports.d.ts
25+
playground/types/components.d.ts

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,16 @@
8585
"tsx": "^4.20.3",
8686
"type-fest": "^5.1.0",
8787
"typescript": "^5.8.3",
88+
"unplugin-auto-import": "^20.2.0",
8889
"unplugin-raw": "^0.6.3",
8990
"unplugin-vue": "^7.0.3",
91+
"unplugin-vue-components": "^30.0.0",
9092
"unplugin-vue-jsx": "^0.8.1",
93+
"unplugin-vue-router": "^0.16.0",
9194
"vite": "npm:rolldown-vite@^7.1.19",
9295
"vitest": "^3.2.4",
9396
"vue": "^3.5.22",
97+
"vue-router": "^4.6.3",
9498
"vue-tsc": "^3.1.1"
9599
},
96100
"simple-git-hooks": {

playground/src/App.vue

Lines changed: 63 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -1,245 +1,85 @@
1-
<script setup lang="ts">
2-
import type { ColumnProps, SectionLayoutCardArea } from '@/element-plus'
3-
import { sleep } from '@antfu/utils'
4-
import { useAsyncState } from '@vueuse/core'
5-
import { reactive } from 'vue'
6-
import {
7-
ColumnsRender,
8-
PaginationRender,
9-
SectionLayout,
10-
Toolbar,
11-
usePagination,
12-
} from '@/element-plus'
1+
<script setup lang="tsx">
2+
import type { FunctionalComponent } from 'vue'
3+
import type { RouteRecordRaw } from 'vue-router'
4+
import { ElSubMenu } from 'element-plus'
5+
import { camelize } from 'vue'
6+
import { routes } from 'vue-router/auto-routes'
137
14-
interface DataItem {
15-
date: string
16-
name: string
17-
state: string
18-
city: string
19-
address: string
20-
zip: string
8+
function getMenuTitle(str: string) {
9+
const title = camelize(str.replaceAll('/', ' ').trim())
10+
return (title[0]?.toUpperCase() || '') + title.slice(1)
2111
}
2212
23-
// #region Layout
24-
SectionLayout.configure({
25-
cardClass: 'el-card el-card__body',
26-
})
27-
28-
const layoutProps = reactive({
29-
gap: '',
30-
card: [] as SectionLayoutCardArea[],
31-
})
32-
// #endregion
33-
34-
// #region Table
35-
PaginationRender.defaultProps = {
36-
background: true,
37-
layout: 'slot, prev, pager, next, jumper, sizes, total',
38-
pagerCount: 5,
39-
pageSizes: [10, 20, 30, 40, 50, 100],
13+
const ReMenuItem: FunctionalComponent<{
14+
route: RouteRecordRaw
15+
parentPath: string
16+
}> = ({ route: propRoute, parentPath }) => {
17+
const fullPath = `${parentPath}${parentPath ? '/' : ''}${propRoute.path}`
18+
if (propRoute.children?.length) {
19+
return (
20+
<ElSubMenu index={fullPath}>
21+
{{
22+
title: () => getMenuTitle(propRoute.path),
23+
default: () =>
24+
propRoute.children!.map((route) => (
25+
<ReMenuItem
26+
key={`${fullPath}/${route.path}`}
27+
route={route}
28+
parentPath={fullPath}
29+
/>
30+
)),
31+
}}
32+
</ElSubMenu>
33+
)
34+
}
35+
return (
36+
<ElMenuItem index={fullPath}>{getMenuTitle(propRoute.path)}</ElMenuItem>
37+
)
4038
}
4139
42-
const columns: ColumnProps<DataItem>[] = [
43-
{
44-
prop: 'date',
45-
label: 'Date',
46-
slots: {
47-
default({ row }) {
48-
return `${row.date} - ${Date.now()}`
49-
},
50-
header: 'date-header',
51-
},
52-
},
53-
{
54-
label: 'Delivery Info',
55-
children: [
56-
{
57-
prop: 'name',
58-
label: 'Name',
59-
},
60-
{
61-
label: 'Address Info',
62-
children: [
63-
{
64-
prop: 'state',
65-
label: 'State',
66-
},
67-
{
68-
prop: 'city',
69-
label: 'City',
70-
},
71-
{
72-
prop: 'address',
73-
label: 'Address',
74-
},
75-
{
76-
prop: 'zip',
77-
label: 'Zip',
78-
},
79-
],
80-
},
81-
],
40+
ReMenuItem.props = {
41+
route: {
42+
type: Object,
43+
required: true,
8244
},
83-
]
84-
85-
const { state, isLoading } = useAsyncState(
86-
async () => {
87-
await sleep(1e3)
88-
const rows = [
89-
{
90-
date: '2016-05-03',
91-
name: 'Tom',
92-
state: 'California',
93-
city: 'Los Angeles',
94-
address: 'No. 189, Grove St, Los Angeles',
95-
zip: 'CA 90036',
96-
},
97-
{
98-
date: '2016-05-02',
99-
name: 'Tom',
100-
state: 'California',
101-
city: 'Los Angeles',
102-
address: 'No. 189, Grove St, Los Angeles',
103-
zip: 'CA 90036',
104-
},
105-
{
106-
date: '2016-05-04',
107-
name: 'Tom',
108-
state: 'California',
109-
city: 'Los Angeles',
110-
address: 'No. 189, Grove St, Los Angeles',
111-
zip: 'CA 90036',
112-
},
113-
{
114-
date: '2016-05-01',
115-
name: 'Tom',
116-
state: 'California',
117-
city: 'Los Angeles',
118-
address: 'No. 189, Grove St, Los Angeles',
119-
zip: 'CA 90036',
120-
},
121-
{
122-
date: '2016-05-08',
123-
name: 'Tom',
124-
state: 'California',
125-
city: 'Los Angeles',
126-
address: 'No. 189, Grove St, Los Angeles',
127-
zip: 'CA 90036',
128-
},
129-
{
130-
date: '2016-05-06',
131-
name: 'Tom',
132-
state: 'California',
133-
city: 'Los Angeles',
134-
address: 'No. 189, Grove St, Los Angeles',
135-
zip: 'CA 90036',
136-
},
137-
{
138-
date: '2016-05-07',
139-
name: 'Tom',
140-
state: 'California',
141-
city: 'Los Angeles',
142-
address: 'No. 189, Grove St, Los Angeles',
143-
zip: 'CA 90036',
144-
},
145-
]
146-
return { total: rows.length, rows }
45+
parentPath: {
46+
type: String,
47+
required: true,
14748
},
148-
{ rows: [], total: 0 },
149-
)
150-
151-
const pagination = usePagination({
152-
total: () => state.value.total,
153-
})
154-
// #endregion
49+
}
15550
</script>
15651

15752
<template>
15853
<ElContainer class="layout">
159-
<ElMain>
160-
<SectionLayout
161-
v-loading="isLoading"
162-
v-bind="layoutProps"
163-
>
164-
<template #top>
165-
<ElAlert
166-
type="success"
167-
title="Top"
168-
description="This is top area."
169-
center
170-
:closable="false"
171-
/>
172-
</template>
173-
174-
<template #main-head>
175-
<Toolbar title="Test Table">
176-
<div :style="{ display: 'flex', gap: '0.5em' }">
177-
<ElText>Card Areas:</ElText>
178-
<ElCheckboxGroup v-model="layoutProps.card">
179-
<ElCheckbox value="top">
180-
Top
181-
</ElCheckbox>
182-
<ElCheckbox value="main">
183-
Main
184-
</ElCheckbox>
185-
<ElCheckbox value="bottom">
186-
Bottom
187-
</ElCheckbox>
188-
</ElCheckboxGroup>
189-
</div>
190-
191-
<div :style="{ display: 'flex', gap: '0.5em' }">
192-
<ElText>Gap:</ElText>
193-
<ElInput
194-
v-model="layoutProps.gap"
195-
placeholder="calc(1em * 0.8)"
196-
/>
197-
</div>
198-
199-
<template #extra>
200-
<ElButton>设置</ElButton>
201-
<ElButton>尺寸</ElButton>
202-
</template>
203-
</Toolbar>
204-
</template>
205-
206-
<ElTable
207-
border
208-
:data="state.rows"
54+
<ElAside
55+
style="border-right: 1px solid var(--el-border-color)"
56+
width="200px"
57+
>
58+
<ElScrollbar max-height="100%">
59+
<ElMenu
60+
style="border-right: 0"
61+
:default-active="$route.name"
62+
router
20963
>
210-
<ColumnsRender :columns />
211-
</ElTable>
212-
213-
<template #main-foot>
214-
<PaginationRender :pagination>
215-
<div style="flex: 1">
216-
<ElButton
217-
type="danger"
218-
tag="div"
219-
>
220-
批量删除
221-
</ElButton>
222-
</div>
223-
</PaginationRender>
224-
</template>
225-
226-
<template #bottom>
227-
<ElAlert
228-
type="info"
229-
title="Bottom"
230-
description="This is bottom area."
231-
center
232-
:closable="false"
64+
<ReMenuItem
65+
v-for="route in routes"
66+
:key="route.path"
67+
:route="route"
68+
parent-path=""
23369
/>
234-
</template>
235-
</SectionLayout>
70+
</ElMenu>
71+
</ElScrollbar>
72+
</ElAside>
73+
74+
<ElMain :style="{ backgroundColor: 'var(--el-bg-color-page)' }">
75+
<RouterView :key="$route.fullPath" />
23676
</ElMain>
23777
</ElContainer>
23878
</template>
23979

24080
<style scoped>
24181
.layout {
242-
position: fixed;
82+
position: absolute;
24383
top: 0;
24484
left: 0;
24585
right: 0;

playground/src/index.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1-
import ElementPlus from 'element-plus'
21
import { createApp } from 'vue'
2+
import { PaginationRender, SectionLayout } from '@/element-plus'
33
import App from './App.vue'
4-
import 'element-plus/dist/index.css'
4+
import router from './router'
5+
import 'element-plus/theme-chalk/index.css'
56

6-
createApp(App).use(ElementPlus).mount('#app')
7+
createApp(App)
8+
.use(router)
9+
.use(() => {
10+
SectionLayout.configure({
11+
cardClass: 'el-card el-card__body',
12+
})
13+
14+
PaginationRender.defaultProps = {
15+
background: true,
16+
layout: 'slot, prev, pager, next, jumper, sizes, total',
17+
pagerCount: 5,
18+
pageSizes: [10, 20, 30, 40, 50, 100],
19+
}
20+
})
21+
.mount('#app')

0 commit comments

Comments
 (0)