Skip to content

Commit 5ba6d08

Browse files
committed
feat: 新增 FaCheckboxGrou 组件,并重构 FaCheckbox API
1 parent c0bc31f commit 5ba6d08

21 files changed

Lines changed: 704 additions & 65 deletions

File tree

apps/example/src/router/modules/component.example.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ const routes: RouteRecordRaw = {
5353
title: '复选框',
5454
},
5555
},
56+
{
57+
path: 'checkbox_group',
58+
name: 'componentExampleCheckboxGroup',
59+
component: () => import('@/views/component_example/checkbox_group/index.vue'),
60+
meta: {
61+
title: '复选框组',
62+
},
63+
},
5664
{
5765
path: 'collapsible',
5866
name: 'componentExampleCollapsible',

apps/example/src/types/components.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ declare module 'vue' {
2424
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
2525
FaCard: typeof import('@fantastic-admin/components')['FaCard']
2626
FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
27+
FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
2728
FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
2829
FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
2930
FaDivider: typeof import('@fantastic-admin/components')['FaDivider']
@@ -76,6 +77,7 @@ declare global {
7677
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
7778
const FaCard: typeof import('@fantastic-admin/components')['FaCard']
7879
const FaCheckbox: typeof import('@fantastic-admin/components')['FaCheckbox']
80+
const FaCheckboxGroup: typeof import('@fantastic-admin/components')['FaCheckboxGroup']
7981
const FaCollapsible: typeof import('@fantastic-admin/components')['FaCollapsible']
8082
const FaContextMenu: typeof import('@fantastic-admin/components')['FaContextMenu']
8183
const FaDivider: typeof import('@fantastic-admin/components')['FaDivider']

apps/example/src/views/component_example/checkbox/_demo1.vue

100755100644
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const checked = ref(false)
55
<template>
66
<div class="flex gap-4">
77
<FaCheckbox v-model="checked">
8-
Checkbox
8+
同意协议
99
</FaCheckbox>
1010
</div>
1111
</template>

apps/example/src/views/component_example/checkbox/_demo2.vue

100755100644
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ const checked = ref<'indeterminate' | boolean>('indeterminate')
44

55
<template>
66
<FaCheckbox v-model="checked">
7-
Checkbox
7+
部分选中
88
</FaCheckbox>
99
</template>

apps/example/src/views/component_example/checkbox/index.vue

100755100644
File mode changed.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script setup lang="ts">
2+
const value = ref(['music'])
3+
4+
const options = [
5+
{ label: '阅读', value: 'reading' },
6+
{ label: '音乐', value: 'music' },
7+
{ label: '运动', value: 'sports' },
8+
]
9+
10+
const currentText = computed(() =>
11+
options
12+
.filter(option => value.value.includes(option.value))
13+
.map(option => option.label)
14+
.join(''),
15+
)
16+
</script>
17+
18+
<template>
19+
<div class="gap-4 grid">
20+
<FaCheckboxGroup v-model="value" :options="options" />
21+
<FaCheckboxGroup v-model="value" :options="options" class="flex" />
22+
<div class="text-sm text-muted-foreground">
23+
当前值:{{ currentText }}
24+
</div>
25+
</div>
26+
</template>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script setup lang="ts">
2+
const value = ref(['dashboard', 'report'])
3+
4+
const options = [
5+
{
6+
label: '看板订阅',
7+
value: 'dashboard',
8+
description: '每天 8:00 推送核心经营指标。',
9+
},
10+
{
11+
label: '周报摘要',
12+
value: 'report',
13+
description: '每周一汇总关键数据变化。',
14+
},
15+
{
16+
label: '系统告警',
17+
value: 'alarm',
18+
description: '异常波动时立即通知处理人。',
19+
disabled: true,
20+
},
21+
]
22+
23+
const currentText = computed(() =>
24+
options
25+
.filter(option => value.value.includes(option.value))
26+
.map(option => option.label)
27+
.join(''),
28+
)
29+
</script>
30+
31+
<template>
32+
<div class="gap-4 grid">
33+
<FaCheckboxGroup v-model="value" :options="options" />
34+
<div class="text-sm text-muted-foreground">
35+
当前值:{{ currentText }}
36+
</div>
37+
</div>
38+
</template>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<script setup lang="ts">
2+
const value = ref(['focus', 'balanced'])
3+
4+
const options = [
5+
{
6+
label: '专注模式',
7+
value: 'focus',
8+
description: '突出主任务,弱化辅助信息,适合录入和审批场景。',
9+
},
10+
{
11+
label: '平衡模式',
12+
value: 'balanced',
13+
description: '信息密度与可读性保持平衡,适合作为默认配置。',
14+
},
15+
{
16+
label: '高密度模式',
17+
value: 'dense',
18+
description: '在大屏中同时承载更多信息,适合运营与监控看板。',
19+
},
20+
]
21+
22+
const currentText = computed(() =>
23+
options
24+
.filter(option => value.value.includes(option.value))
25+
.map(option => option.label)
26+
.join(''),
27+
)
28+
</script>
29+
30+
<template>
31+
<FaCheckboxGroup
32+
v-model="value"
33+
:options="options"
34+
class="gap-2 md:grid-cols-3"
35+
option-class="rounded-xl border border-transparent px-1 py-1"
36+
>
37+
<template #option="{ option, checked, disabled }">
38+
<div
39+
class="px-4 py-3 border rounded-xl flex gap-3 w-full transition-colors items-start justify-between" :class="[
40+
checked ? 'border-primary bg-primary/5' : 'border-border hover:border-primary/40',
41+
disabled && 'opacity-60',
42+
]"
43+
>
44+
<div class="gap-1 grid min-w-0">
45+
<div class="text-sm font-medium truncate">
46+
{{ option.label }}
47+
</div>
48+
<div
49+
v-if="option.description"
50+
class="text-xs text-muted-foreground leading-5"
51+
>
52+
{{ option.description }}
53+
</div>
54+
</div>
55+
<span
56+
class="text-xs font-medium shrink-0" :class="[
57+
checked ? 'text-primary' : 'text-muted-foreground',
58+
]"
59+
>
60+
{{ checked ? '已选中' : '可选择' }}
61+
</span>
62+
</div>
63+
</template>
64+
</FaCheckboxGroup>
65+
<div class="text-sm text-muted-foreground">
66+
当前模式:{{ currentText }}
67+
</div>
68+
</template>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<script setup lang="ts">
2+
const value = ref(['dashboard'])
3+
4+
const options = [
5+
{ label: '看板订阅', value: 'dashboard' },
6+
{ label: '周报摘要', value: 'report' },
7+
{ label: '系统告警', value: 'alarm' },
8+
]
9+
10+
const currentText = computed(() =>
11+
options
12+
.filter(option => value.value.includes(option.value))
13+
.map(option => option.label)
14+
.join(''),
15+
)
16+
</script>
17+
18+
<template>
19+
<div class="gap-4 grid">
20+
<FaCheckboxGroup
21+
v-model="value"
22+
:options="options"
23+
:min="1"
24+
:max="2"
25+
/>
26+
<div class="text-sm text-muted-foreground">
27+
当前值:{{ currentText }}
28+
</div>
29+
<div class="text-xs text-muted-foreground leading-5">
30+
已选数量小于等于 1 时,已选项会被禁用;已选数量大于等于 2 时,未选项会被禁用。
31+
</div>
32+
</div>
33+
</template>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
import Demo1 from './_demo1.vue'
3+
import Demo2 from './_demo2.vue'
4+
import Demo3 from './_demo3.vue'
5+
import Demo4 from './_demo4.vue'
6+
</script>
7+
8+
<template>
9+
<div>
10+
<FaPageHeader title="复选框组" description="FaCheckboxGroup" />
11+
<FaPageMain main-class="p-4">
12+
<Demo1 />
13+
</FaPageMain>
14+
<FaPageMain title="带描述和禁用态" main-class="p-4">
15+
<Demo2 />
16+
</FaPageMain>
17+
<FaPageMain title="自定义选项内容" main-class="p-4">
18+
<Demo3 />
19+
</FaPageMain>
20+
<FaPageMain title="最少 / 最多选择" main-class="p-4">
21+
<Demo4 />
22+
</FaPageMain>
23+
</div>
24+
</template>

0 commit comments

Comments
 (0)