feat(table): 新增表格组件及示例

This commit is contained in:
Hooray
2026-06-08 15:00:38 +08:00
parent 29618d2816
commit 57f98e7bb1
46 changed files with 2570 additions and 8 deletions
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -302,6 +302,14 @@ const routes: RouteRecordRaw = {
title: '开关', title: '开关',
}, },
}, },
{
path: 'table',
name: 'componentExampleTable',
component: () => import('@/views/component_example/table.vue'),
meta: {
title: '表格',
},
},
{ {
path: 'tag', path: 'tag',
name: 'componentExampleTag', name: 'componentExampleTag',
+6
View File
@@ -21,6 +21,7 @@ declare module 'vue' {
AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
FaButton: typeof import('@fantastic-admin/components')['FaButton'] FaButton: typeof import('@fantastic-admin/components')['FaButton']
FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
FaCard: typeof import('@fantastic-admin/components')['FaCard'] FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -56,7 +57,9 @@ declare module 'vue' {
FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
FaTable: typeof import('@fantastic-admin/components')['FaTable']
FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
FaTag: typeof import('@fantastic-admin/components')['FaTag']
FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
FaToast: typeof import('@fantastic-admin/components')['FaToast'] FaToast: typeof import('@fantastic-admin/components')['FaToast']
FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -75,6 +78,7 @@ declare global {
const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default'] const AppSystemInfo: typeof import('./../components/AppSystemInfo/index.vue')['default']
const FaAlert: typeof import('@fantastic-admin/components')['FaAlert'] const FaAlert: typeof import('@fantastic-admin/components')['FaAlert']
const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar'] const FaAvatar: typeof import('@fantastic-admin/components')['FaAvatar']
const FaBadge: typeof import('@fantastic-admin/components')['FaBadge']
const FaButton: typeof import('@fantastic-admin/components')['FaButton'] const FaButton: typeof import('@fantastic-admin/components')['FaButton']
const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup'] const FaButtonGroup: typeof import('@fantastic-admin/components')['FaButtonGroup']
const FaCard: typeof import('@fantastic-admin/components')['FaCard'] const FaCard: typeof import('@fantastic-admin/components')['FaCard']
@@ -110,7 +114,9 @@ declare global {
const FaSelect: typeof import('@fantastic-admin/components')['FaSelect'] const FaSelect: typeof import('@fantastic-admin/components')['FaSelect']
const FaSlider: typeof import('@fantastic-admin/components')['FaSlider'] const FaSlider: typeof import('@fantastic-admin/components')['FaSlider']
const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch'] const FaSwitch: typeof import('@fantastic-admin/components')['FaSwitch']
const FaTable: typeof import('@fantastic-admin/components')['FaTable']
const FaTabs: typeof import('@fantastic-admin/components')['FaTabs'] const FaTabs: typeof import('@fantastic-admin/components')['FaTabs']
const FaTag: typeof import('@fantastic-admin/components')['FaTag']
const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea'] const FaTextarea: typeof import('@fantastic-admin/components')['FaTextarea']
const FaToast: typeof import('@fantastic-admin/components')['FaToast'] const FaToast: typeof import('@fantastic-admin/components')['FaToast']
const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip'] const FaTooltip: typeof import('@fantastic-admin/components')['FaTooltip']
@@ -0,0 +1,17 @@
<script setup lang="ts">
import { table } from '@fantastic-admin/components/examples'
</script>
<template>
<div>
<FaPageHeader title="表格" description="FaTable" />
<FaPageMain
v-for="example in table"
:key="example.title"
:code="example.componentRaw"
:title="example.title"
>
<component :is="example.component" />
</FaPageMain>
</div>
</template>
+1
View File
@@ -29,6 +29,7 @@
"dependencies": { "dependencies": {
"@iconify/vue": "catalog:", "@iconify/vue": "catalog:",
"@lucide/vue": "catalog:", "@lucide/vue": "catalog:",
"@tanstack/vue-table": "catalog:",
"axios": "catalog:", "axios": "catalog:",
"class-variance-authority": "catalog:", "class-variance-authority": "catalog:",
"clsx": "catalog:", "clsx": "catalog:",
+3
View File
@@ -8,6 +8,7 @@ const PACKAGE_NAME = createRequire(import.meta.url)('./package.json').name
const BASIC_COMPONENT_NAMES = [ const BASIC_COMPONENT_NAMES = [
'FaAlert', 'FaAlert',
'FaAvatar', 'FaAvatar',
'FaBadge',
'FaButton', 'FaButton',
'FaButtonGroup', 'FaButtonGroup',
'FaCard', 'FaCard',
@@ -43,7 +44,9 @@ const BASIC_COMPONENT_NAMES = [
'FaSelect', 'FaSelect',
'FaSlider', 'FaSlider',
'FaSwitch', 'FaSwitch',
'FaTable',
'FaTabs', 'FaTabs',
'FaTag',
'FaTextarea', 'FaTextarea',
'FaToast', 'FaToast',
'FaTooltip', 'FaTooltip',
@@ -1,6 +1,7 @@
<script setup lang="ts" generic="TOption extends CheckboxGroupOption"> <script setup lang="ts" generic="TOption extends CheckboxGroupOption">
import type { AcceptableValue } from 'reka-ui' import type { AcceptableValue, Direction } from 'reka-ui'
import type { HTMLAttributes } from 'vue' import type { HTMLAttributes } from 'vue'
import { useTextDirection } from '@vueuse/core'
import { computed, useId, watch } from 'vue' import { computed, useId, watch } from 'vue'
import { cn } from '#utils' import { cn } from '#utils'
import { Checkbox } from '../checkbox/checkbox' import { Checkbox } from '../checkbox/checkbox'
@@ -23,7 +24,7 @@ const props = defineProps<{
disabled?: boolean disabled?: boolean
min?: number min?: number
max?: number max?: number
dir?: 'ltr' | 'rtl' dir?: Direction
class?: HTMLAttributes['class'] class?: HTMLAttributes['class']
optionClass?: HTMLAttributes['class'] optionClass?: HTMLAttributes['class']
itemClass?: HTMLAttributes['class'] itemClass?: HTMLAttributes['class']
@@ -47,6 +48,11 @@ const value = defineModel<AcceptableValue[]>({
default: () => [], default: () => [],
}) })
const documentDir = useTextDirection({
observe: true,
})
const dir = computed<Direction>(() => props.dir ?? (documentDir.value === 'rtl' ? 'rtl' : 'ltr'))
const baseId = useId() const baseId = useId()
const checkedCount = computed(() => value.value.length) const checkedCount = computed(() => value.value.length)
@@ -5,6 +5,7 @@ import { createReusableTemplate, useTextDirection } from '@vueuse/core'
import Icon from '../icon/index.vue' import Icon from '../icon/index.vue'
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent, DropdownMenuContent,
DropdownMenuGroup, DropdownMenuGroup,
DropdownMenuItem, DropdownMenuItem,
@@ -41,10 +42,12 @@ const Option = createReusableTemplate<{
interface MenuItem { interface MenuItem {
label: string label: string
type?: 'checkbox'
icon?: string icon?: string
variant?: 'default' | 'destructive' variant?: 'default' | 'destructive'
disabled?: boolean disabled?: boolean
handle?: () => void checked?: boolean
handle?: (checked?: boolean) => void
} }
interface MenuSubItem { interface MenuSubItem {
@@ -62,9 +65,13 @@ function hasIcon(group: (MenuItem | MenuSubItem)[][]) {
})) }))
} }
function handleItemClick(item: { handle?: () => void }) { function handleItemClick(item: { handle?: (checked?: boolean) => void }) {
item.handle?.() item.handle?.()
} }
function handleCheckboxItemChange(item: MenuItem, checked: boolean) {
item.handle?.(checked)
}
</script> </script>
<template> <template>
@@ -83,7 +90,15 @@ function handleItemClick(item: { handle?: () => void }) {
<template v-for="(item, index) in its" :key="index"> <template v-for="(item, index) in its" :key="index">
<DropdownMenuGroup> <DropdownMenuGroup>
<template v-for="(v, i) in item" :key="i"> <template v-for="(v, i) in item" :key="i">
<DropdownMenuItem v-if="!('items' in v)" :variant="v.variant" :disabled="v.disabled" @click="handleItemClick(v)"> <DropdownMenuCheckboxItem
v-if="!('items' in v) && v.type === 'checkbox'"
:model-value="v.checked"
:disabled="v.disabled"
@update:model-value="value => handleCheckboxItemChange(v, value)"
>
{{ v.label }}
</DropdownMenuCheckboxItem>
<DropdownMenuItem v-else-if="!('items' in v)" :variant="v.variant" :disabled="v.disabled" @click="handleItemClick(v)">
<div v-if="hasIcon(its)" class="flex-center size-4"> <div v-if="hasIcon(its)" class="flex-center size-4">
<Icon v-if="v.icon" :name="v.icon" class="size-4" /> <Icon v-if="v.icon" :name="v.icon" class="size-4" />
</div> </div>
@@ -1,7 +1,8 @@
<script setup lang="ts" generic="TOption extends RadioGroupOption"> <script setup lang="ts" generic="TOption extends RadioGroupOption">
import type { AcceptableValue, RadioGroupRootProps } from 'reka-ui' import type { AcceptableValue, Direction, RadioGroupRootProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue' import type { HTMLAttributes } from 'vue'
import { useId, watch } from 'vue' import { useTextDirection } from '@vueuse/core'
import { computed, useId, watch } from 'vue'
import { cn } from '#utils' import { cn } from '#utils'
import { Label } from '../label/label' import { Label } from '../label/label'
import { RadioGroup, RadioGroupItem } from './radio-group' import { RadioGroup, RadioGroupItem } from './radio-group'
@@ -21,7 +22,7 @@ defineOptions({
const props = defineProps<{ const props = defineProps<{
options: TOption[] options: TOption[]
disabled?: RadioGroupRootProps['disabled'] disabled?: RadioGroupRootProps['disabled']
dir?: RadioGroupRootProps['dir'] dir?: Direction
class?: HTMLAttributes['class'] class?: HTMLAttributes['class']
optionClass?: HTMLAttributes['class'] optionClass?: HTMLAttributes['class']
itemClass?: HTMLAttributes['class'] itemClass?: HTMLAttributes['class']
@@ -41,6 +42,11 @@ const slots = defineSlots<{
}>() }>()
const value = defineModel<AcceptableValue | undefined>() const value = defineModel<AcceptableValue | undefined>()
const documentDir = useTextDirection({
observe: true,
})
const dir = computed<Direction>(() => props.dir ?? (documentDir.value === 'rtl' ? 'rtl' : 'ltr'))
const baseId = useId() const baseId = useId()
watch(value, (newValue) => { watch(value, (newValue) => {
@@ -0,0 +1,106 @@
# FaTable 表格
基于 TanStack Table 封装的数据表格组件,提供基础展示、树型数据、工具栏、列显示控制、排序、边框、斑马纹、固定列、固定高度、单选、多选和插槽自定义能力。
## 使用场景
- 常规数据列表展示
- 通过 `children` 或 `getSubRows` 展示树型层级数据
- 需要单选或多选的数据表格
- 固定列、固定高度等复杂表格布局
- 需要外部处理排序状态的数据表格
- 通过工具栏插槽放置新增、刷新、批量操作等自定义功能
- 通过插槽自定义单元格、表头、表尾和空状态
## Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `columns` | `TableColumn[]` | **必需** | 表格列配置 |
| `data` | `TData[]` | **必需** | 表格数据 |
| `border` | `boolean` | `false` | 是否显示外边框和单元格纵向分割线 |
| `caption` | `string` | - | 表格标题 |
| `columnVisibility` | `boolean` | `false` | 是否在工具栏右侧显示列显示控制按钮 |
| `defaultSorting` | `TableSortingState` | `[]` | 初始排序状态,仅在未受控时生效 |
| `defaultExpanded` | `TableExpandedState` | `{}` | 初始展开状态,仅在未受控时生效 |
| `emptyText` | `string` | `'暂无数据'` | 空数据文本 |
| `enableMultiSort` | `boolean` | `true` | 是否允许多列排序 |
| `enableSortingRemoval` | `boolean` | `true` | 是否允许清除排序 |
| `expanded` | `TableExpandedState` | - | 受控展开状态 |
| `getRowId` | `TableOptions<TData>['getRowId']` | - | 自定义行 ID 获取方法 |
| `getSubRows` | `TableOptions<TData>['getSubRows']` | - | 自定义子行获取方法,未设置时默认读取 `children` |
| `indentSize` | `number` | `20` | 树型数据每一级缩进像素 |
| `manualExpanding` | `boolean` | `false` | 是否由外部手动处理展开数据 |
| `multiple` | `boolean` | `false` | 是否为多选模式 |
| `rowKey` | `keyof TData \| string \| ((row: TData, index: number) => string \| number)` | - | 行唯一标识 |
| `selectable` | `boolean` | `false` | 是否启用选择列 |
| `sortable` | `boolean` | `false` | 是否启用排序交互 |
| `sorting` | `TableSortingState` | - | 受控排序状态 |
| `sortDescFirst` | `boolean` | `true` | 首次排序是否从降序开始 |
| `stripe` | `boolean` | `false` | 是否显示斑马纹 |
| `class` | `HTMLAttributes['class']` | - | 外层根节点 class,包含工具栏和表格 |
| `tableRootClass` | `HTMLAttributes['class']` | - | 表格根节点 class,仅作用于表格区域 |
| `tableClass` | `HTMLAttributes['class']` | - | 表格 class |
| `headerClass` | `HTMLAttributes['class']` | - | 表头 class |
| `headerRowClass` | `HTMLAttributes['class']` | - | 表头行 class |
| `bodyClass` | `HTMLAttributes['class']` | - | 表体 class |
| `rowClass` | `HTMLAttributes['class'] \| ((row: Row<TData>) => HTMLAttributes['class'])` | - | 表格行 class |
| `selectionColumnClass` | `HTMLAttributes['class']` | - | 选择列 class |
| `tree` | `boolean` | `false` | 是否启用树型数据展示,展开图标渲染在首列 |
## TableColumn
| 属性 | 类型 | 说明 |
|------|------|------|
| `accessorKey` | `string` | 数据字段名 |
| `header` | `string \| Function` | 表头内容 |
| `cell` | `string \| Function` | 单元格内容 |
| `columns` | `TableColumn[]` | 多级表头子列 |
| `align` | `'left' \| 'center' \| 'right'` | 对齐方式 |
| `fixed` | `boolean \| 'left' \| 'right'` | 固定列位置 |
| `enableSorting` | `boolean` | 是否允许当前列排序 |
| `enableMultiSort` | `boolean` | 是否允许当前列参与多列排序 |
| `sortDescFirst` | `boolean` | 当前列首次排序是否从降序开始 |
| `sortingFn` | `string \| Function` | 排序函数(组件内部不执行实际排序) |
| `width` | `number \| string` | 列宽 |
| `minWidth` | `number \| string` | 最小列宽 |
| `maxWidth` | `number \| string` | 最大列宽 |
| `class` | `HTMLAttributes['class']` | 列 class |
| `headerClass` | `HTMLAttributes['class'] \| Function` | 表头 class |
| `cellClass` | `HTMLAttributes['class'] \| Function` | 单元格 class |
选择列可配置 `{ type: 'selection' }`,并可通过 `disabled` 控制某一行是否禁用选择。
排序能力基于 TanStack Table 的 `SortingState` 实现。开启 `sortable` 后,支持单列排序与 `Shift + 点击` 多列排序;组件只维护排序状态并触发事件,不会对传入数据做实际排序,当前参与排序的列会显示独立背景。
树型数据能力基于 TanStack Table 的 Expanding Row Model 实现。开启 `tree` 后,组件默认读取每行的 `children` 字段作为子行,也可以通过 `getSubRows` 自定义子行来源;展开图标固定渲染在首个可见列。
## Slots
| 名称 | 说明 | 作用域参数 |
|------|------|------------|
| `caption` | 自定义表格标题 | - |
| `empty` | 自定义空状态 | `table` |
| `toolbar` | 自定义工具栏左侧内容 | `table` |
| `header-{columnId}` | 自定义指定列表头 | `column`、`header`、`table` |
| `cell-{columnId}` | 自定义指定列单元格 | `cell`、`column`、`index`、`row`、`table`、`value` |
| `footer-{columnId}` | 自定义指定列表尾 | `column`、`header`、`table` |
## Events
| 事件名 | 说明 | 回调参数 |
|--------|------|----------|
| `row-click` | 点击表格行时触发 | `(row: TData, index: number, event: MouseEvent)` |
| `selection-change` | 选择状态变化时触发 | `(rows: TData[], rowSelection: RowSelectionState)` |
| `sorting-change` | 排序状态变化时触发 | `(sorting: TableSortingState, table: TanStackTable<TData>)` |
| `expanded-change` | 展开状态变化时触发 | `(expanded: TableExpandedState, table: TanStackTable<TData>)` |
| `update:expanded` | 受控展开状态更新时触发 | `(expanded: TableExpandedState)` |
## 注意事项
1. 推荐为复杂表格设置 `rowKey` 或 `getRowId`,保证选择状态和行更新稳定。
2. 启用选择能力时需要设置 `selectable`,多选场景再配合 `multiple` 使用。
3. 固定列建议显式设置列宽,避免横向滚动时出现宽度计算不稳定。
4. 普通列默认可被列显示控制隐藏,设置 `enableHiding: false` 可禁止某列出现在列显示菜单中。
5. 排序仅负责状态管理,真正的数据排序请在外部根据 `sorting-change` 自行处理。
6. 树型数据建议设置 `rowKey` 或 `getRowId`,避免展开状态在数据更新后错位。
@@ -0,0 +1,41 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Task {
id: string
title: string
owner: string
status: string
updatedAt: string
}
const columns: TableColumn<Task>[] = [
{
accessorKey: 'title',
header: '任务',
},
{
accessorKey: 'owner',
header: '负责人',
},
{
accessorKey: 'status',
header: '状态',
},
{
accessorKey: 'updatedAt',
header: '更新时间',
},
]
const data: Task[] = [
{ id: 't-001', title: '完善组件文档', owner: '林舟', status: '进行中', updatedAt: '2026-05-23' },
{ id: 't-002', title: '同步设计变量', owner: '陈念', status: '待处理', updatedAt: '2026-05-22' },
{ id: 't-003', title: '整理示例数据', owner: '周衡', status: '已完成', updatedAt: '2026-05-21' },
{ id: 't-004', title: '回归交互状态', owner: '沈若', status: '进行中', updatedAt: '2026-05-20' },
]
</script>
<template>
<FaTable :columns :data />
</template>
@@ -0,0 +1,46 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Project {
id: string
name: string
owner: string
progress: string
status: string
}
const columns: TableColumn<Project>[] = [
{
accessorKey: 'name',
header: '项目',
width: 220,
},
{
accessorKey: 'owner',
header: '负责人',
width: 120,
},
{
accessorKey: 'progress',
header: '进度',
width: 120,
align: 'right',
},
{
accessorKey: 'status',
header: '状态',
width: 120,
},
]
const data: Project[] = [
{ id: 'p-001', name: '权限策略整理', owner: '林舟', progress: '72%', status: '进行中' },
{ id: 'p-002', name: '表格示例拆分', owner: '陈念', progress: '100%', status: '已完成' },
{ id: 'p-003', name: '数据导出流程', owner: '周衡', progress: '48%', status: '进行中' },
{ id: 'p-004', name: '菜单体验优化', owner: '沈若', progress: '16%', status: '待处理' },
]
</script>
<template>
<FaTable border row-key="id" :columns :data />
</template>
@@ -0,0 +1,47 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Task {
id: string
title: string
owner: string
priority: string
status: string
updatedAt: string
}
const columns: TableColumn<Task>[] = [
{
accessorKey: 'title',
header: '任务',
enableHiding: false,
},
{
accessorKey: 'owner',
header: '负责人',
},
{
accessorKey: 'priority',
header: '优先级',
},
{
accessorKey: 'status',
header: '状态',
},
{
accessorKey: 'updatedAt',
header: '更新时间',
},
]
const data: Task[] = [
{ id: 't-001', title: '完善组件文档', owner: '林舟', priority: '中', status: '进行中', updatedAt: '2026-05-23' },
{ id: 't-002', title: '同步设计变量', owner: '陈念', priority: '高', status: '待处理', updatedAt: '2026-05-22' },
{ id: 't-003', title: '整理示例数据', owner: '周衡', priority: '低', status: '已完成', updatedAt: '2026-05-21' },
{ id: 't-004', title: '回归交互状态', owner: '沈若', priority: '中', status: '进行中', updatedAt: '2026-05-20' },
]
</script>
<template>
<FaTable column-visibility :columns :data />
</template>
@@ -0,0 +1,54 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Metric {
id: string
name: string
today: string
yesterday: string
trend: string
}
const columns: TableColumn<Metric>[] = [
{
accessorKey: 'name',
label: '指标名称',
width: 180,
cellClass: 'font-medium bg-amber-200/80 dark:bg-amber-500/35',
},
{
accessorKey: 'today',
header: '今日',
align: 'right',
width: 120,
cellClass: 'tabular-nums',
},
{
accessorKey: 'yesterday',
header: '昨日',
align: 'right',
width: 120,
cellClass: 'tabular-nums text-muted-foreground',
},
{
accessorKey: 'trend',
title: '变化',
align: 'right',
width: 120,
headerClass: 'text-primary',
cellClass: ({ row }) => row.original.trend.startsWith('+')
? 'text-success font-medium tabular-nums'
: 'text-destructive font-medium tabular-nums',
},
]
const data: Metric[] = [
{ id: 'm-001', name: '访问量', today: '18,420', yesterday: '16,280', trend: '+13.1%' },
{ id: 'm-002', name: '转化率', today: '8.6%', yesterday: '9.1%', trend: '-0.5%' },
{ id: 'm-003', name: '新增客户', today: '326', yesterday: '304', trend: '+7.2%' },
]
</script>
<template>
<FaTable row-key="id" :columns :data />
</template>
@@ -0,0 +1,109 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Project {
id: string
name: string
owner: string
department: string
priority: string
status: string
deadline: string
budget: string
nextAction: string
}
const columns: TableColumn<Project>[] = [
{
accessorKey: 'name',
header: '项目',
fixed: 'left',
width: 220,
},
{
accessorKey: 'owner',
header: '负责人',
fixed: 'left',
width: 120,
},
{
accessorKey: 'department',
header: '所属部门',
width: 160,
},
{
accessorKey: 'priority',
header: '优先级',
width: 120,
},
{
accessorKey: 'status',
header: '状态',
width: 120,
},
{
accessorKey: 'deadline',
header: '截止日期',
width: 140,
},
{
accessorKey: 'budget',
header: '预算',
align: 'right',
fixed: 'right',
width: 120,
},
{
accessorKey: 'nextAction',
header: '下一步',
align: 'right',
fixed: 'right',
width: 140,
},
]
const data: Project[] = [
{
id: 'p-1001',
name: '权限中心改造',
owner: '林舟',
department: '基础平台部',
priority: '高',
status: '进行中',
deadline: '2026-06-12',
budget: '¥84,000',
nextAction: '查看详情',
},
{
id: 'p-1002',
name: '移动端适配',
owner: '陈念',
department: '体验技术部',
priority: '中',
status: '评审中',
deadline: '2026-06-18',
budget: '¥56,000',
nextAction: '排期',
},
{
id: 'p-1003',
name: '数据看板升级',
owner: '周衡',
department: '数据产品部',
priority: '中',
status: '已完成',
deadline: '2026-05-30',
budget: '¥126,000',
nextAction: '复盘',
},
]
</script>
<template>
<FaTable
row-key="id"
table-class="min-w-[1160px]"
:columns
:data
/>
</template>
@@ -0,0 +1,58 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface LogRecord {
id: string
event: string
operator: string
result: string
time: string
}
const columns: TableColumn<LogRecord>[] = [
{
accessorKey: 'event',
header: '事件',
width: 180,
},
{
accessorKey: 'operator',
header: '操作人',
width: 120,
},
{
accessorKey: 'result',
header: '结果',
width: 120,
},
{
accessorKey: 'time',
header: '时间',
width: 180,
},
]
const data: LogRecord[] = [
{ id: 'l-001', event: '创建项目', operator: '林舟', result: '成功', time: '2026-05-23 09:12' },
{ id: 'l-002', event: '提交审批', operator: '陈念', result: '成功', time: '2026-05-23 09:26' },
{ id: 'l-003', event: '同步成员', operator: '周衡', result: '成功', time: '2026-05-23 09:41' },
{ id: 'l-004', event: '导出报表', operator: '沈若', result: '排队中', time: '2026-05-23 10:05' },
{ id: 'l-005', event: '更新预算', operator: '梁一', result: '成功', time: '2026-05-23 10:18' },
{ id: 'l-006', event: '变更负责人', operator: '许知', result: '成功', time: '2026-05-23 10:39' },
{ id: 'l-007', event: '归档任务', operator: '林舟', result: '成功', time: '2026-05-23 11:02' },
{ id: 'l-008', event: '生成快照', operator: '陈念', result: '成功', time: '2026-05-23 11:27' },
{ id: 'l-009', event: '刷新缓存', operator: '周衡', result: '成功', time: '2026-05-23 11:48' },
{ id: 'l-010', event: '权限校验', operator: '沈若', result: '成功', time: '2026-05-23 12:13' },
{ id: 'l-011', event: '发布版本', operator: '梁一', result: '成功', time: '2026-05-23 12:45' },
{ id: 'l-012', event: '关闭工单', operator: '许知', result: '成功', time: '2026-05-23 13:08' },
]
</script>
<template>
<FaTable
class="h-80"
row-key="id"
:columns
:data
/>
</template>
@@ -0,0 +1,72 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
import { computed, shallowRef } from 'vue'
interface Member {
id: string
name: string
role: string
team: string
locked: boolean
}
const columns: TableColumn<Member>[] = [
{
type: 'selection',
fixed: 'left',
width: 50,
disabled: row => row.locked,
},
{
accessorKey: 'name',
header: '成员',
},
{
accessorKey: 'role',
header: '角色',
width: 120,
},
{
accessorKey: 'team',
header: '团队',
width: 140,
},
{
accessorKey: 'locked',
header: '锁定',
width: 120,
},
]
const data: Member[] = [
{ id: 'm-001', name: '沈若', role: '管理员', team: '平台组', locked: false },
{ id: 'm-002', name: '梁一', role: '开发者', team: '体验组', locked: false },
{ id: 'm-003', name: '许知', role: '访客', team: '运营组', locked: true },
{ id: 'm-004', name: '苏眠', role: '审计员', team: '风控组', locked: false },
]
const selectedRows = shallowRef<Member[]>([])
const selectedNames = computed(() => selectedRows.value.map(item => item.name).join('、') || '暂无')
function handleSelectionChange(rows: Member[]) {
selectedRows.value = rows
}
</script>
<template>
<div class="space-y-4">
<FaTable
selectable
multiple
row-key="id"
:columns
:data
@selection-change="handleSelectionChange"
/>
<div class="text-sm text-muted-foreground px-4 py-3 rounded-md bg-muted">
已选中:{{ selectedNames }}
</div>
</div>
</template>
@@ -0,0 +1,71 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
import { computed, shallowRef } from 'vue'
interface Member {
id: string
name: string
role: string
team: string
enabled: boolean
}
const columns: TableColumn<Member>[] = [
{
type: 'selection',
fixed: 'left',
width: 50,
disabled: row => !row.enabled,
},
{
accessorKey: 'name',
header: '成员',
},
{
accessorKey: 'role',
header: '角色',
width: 120,
},
{
accessorKey: 'team',
header: '团队',
width: 140,
},
{
accessorKey: 'enabled',
header: '是否可选',
width: 120,
},
]
const data: Member[] = [
{ id: 'm-001', name: '沈若', role: '管理员', team: '平台组', enabled: true },
{ id: 'm-002', name: '梁一', role: '开发者', team: '体验组', enabled: true },
{ id: 'm-003', name: '许知', role: '访客', team: '运营组', enabled: false },
{ id: 'm-004', name: '苏眠', role: '审计员', team: '风控组', enabled: true },
]
const selectedRows = shallowRef<Member[]>([])
const selectedName = computed(() => selectedRows.value[0]?.name || '暂无')
function handleSelectionChange(rows: Member[]) {
selectedRows.value = rows
}
</script>
<template>
<div class="space-y-4">
<FaTable
selectable
row-key="id"
:columns
:data
@selection-change="handleSelectionChange"
/>
<div class="text-sm text-muted-foreground px-4 py-3 rounded-md bg-muted">
当前选中:{{ selectedName }}
</div>
</div>
</template>
@@ -0,0 +1,105 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Product {
id: string
name: string
category: string
price: number
stock: number
status: 'available' | 'warning' | 'sold-out'
}
const columns: TableColumn<Product>[] = [
{
accessorKey: 'name',
header: '商品',
width: 220,
},
{
accessorKey: 'category',
header: '分类',
width: 120,
},
{
accessorKey: 'price',
header: '价格',
align: 'right',
width: 120,
},
{
accessorKey: 'stock',
header: '库存',
align: 'right',
width: 120,
},
{
accessorKey: 'status',
header: '状态',
width: 120,
},
]
const data: Product[] = [
{ id: 'sku-001', name: '协作空间专业版', category: '软件', price: 1280, stock: 42, status: 'available' },
{ id: 'sku-002', name: '团队数据大屏', category: '模板', price: 680, stock: 8, status: 'warning' },
{ id: 'sku-003', name: '年度支持服务', category: '服务', price: 3600, stock: 0, status: 'sold-out' },
]
const statusMap: Record<Product['status'], { label: string, class: string }> = {
'available': {
label: '可售',
class: 'bg-success/10 text-success',
},
'warning': {
label: '低库存',
class: 'bg-warning/10 text-warning',
},
'sold-out': {
label: '售罄',
class: 'bg-muted text-muted-foreground',
},
}
function formatCurrency(value: number) {
return new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY',
maximumFractionDigits: 0,
}).format(value)
}
</script>
<template>
<FaTable row-key="id" :columns :data>
<template #header-name>
<div class="flex flex-col">
<span>商品</span>
<span class="text-xs text-muted-foreground font-normal">名称 / 编号</span>
</div>
</template>
<template #cell-name="{ row }">
<div class="font-medium">
{{ row.original.name }}
</div>
<div class="text-xs text-muted-foreground">
{{ row.original.id }}
</div>
</template>
<template #cell-price="{ value }">
{{ formatCurrency(Number(value)) }}
</template>
<template #cell-stock="{ value }">
<span class="tabular-nums">{{ value }}</span>
</template>
<template #cell-status="{ value }">
<span class="text-xs font-medium px-2 py-0.5 rounded-full inline-flex" :class="statusMap[value as Product['status']].class">
{{ statusMap[value as Product['status']].label }}
</span>
</template>
</FaTable>
</template>
@@ -0,0 +1,116 @@
<script setup lang="ts">
import type { TableColumn, TableSortingState } from '../index.vue'
import { computed, shallowRef } from 'vue'
interface Task {
id: string
title: string
owner: string
priority: string
updatedAt: string
}
const columns: TableColumn<Task>[] = [
{
accessorKey: 'title',
header: '任务',
},
{
accessorKey: 'owner',
header: '负责人',
},
{
accessorKey: 'priority',
header: '优先级',
enableSorting: true,
},
{
accessorKey: 'updatedAt',
header: '更新时间',
enableSorting: true,
},
]
const data: Task[] = [
{ id: 't-001', title: '完善组件文档', owner: '林舟', priority: '中', updatedAt: '2026-05-23' },
{ id: 't-002', title: '同步设计变量', owner: '陈念', priority: '高', updatedAt: '2026-05-22' },
{ id: 't-003', title: '整理示例数据', owner: '周衡', priority: '低', updatedAt: '2026-05-21' },
{ id: 't-004', title: '回归交互状态', owner: '沈若', priority: '中', updatedAt: '2026-05-20' },
]
const priorityRank: Record<Task['priority'], number> = {
高: 3,
中: 2,
低: 1,
}
const sorting = shallowRef<TableSortingState>([])
function getSortValue(row: Task, key: keyof Task) {
if (key === 'priority') {
return priorityRank[row.priority]
}
return row[key]
}
function compareSortValue(a: string | number, b: string | number) {
if (typeof a === 'number' && typeof b === 'number') {
return a - b
}
return String(a).localeCompare(String(b), 'zh-CN', { numeric: true })
}
const sortedData = computed(() => {
if (!sorting.value.length) {
return data
}
return [...data].sort((a, b) => {
for (const sort of sorting.value) {
const key = sort.id as keyof Task
const aVal = getSortValue(a, key)
const bVal = getSortValue(b, key)
if (aVal === bVal) {
continue
}
const result = compareSortValue(aVal, bVal)
return sort.desc ? -result : result
}
return 0
})
})
const sortingText = computed(() => {
if (!sorting.value.length) {
return '暂无排序'
}
return sorting.value.map(item => `${item.id}: ${item.desc ? '降序' : '升序'}`).join(',')
})
function handleSortingChange(value: TableSortingState) {
sorting.value = value
}
</script>
<template>
<div class="space-y-4">
<FaTable
sortable
row-key="id"
:sorting
:columns
:data="sortedData"
@sorting-change="handleSortingChange"
/>
<div class="text-sm text-muted-foreground px-4 py-3 rounded-md bg-muted">
当前排序:{{ sortingText }}
</div>
</div>
</template>
@@ -0,0 +1,53 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Ticket {
id: string
title: string
owner: string
priority: string
status: string
updatedAt: string
}
const columns: TableColumn<Ticket>[] = [
{
accessorKey: 'title',
header: '事项',
width: 220,
},
{
accessorKey: 'owner',
header: '负责人',
width: 120,
},
{
accessorKey: 'priority',
header: '优先级',
width: 120,
},
{
accessorKey: 'status',
header: '状态',
width: 120,
},
{
accessorKey: 'updatedAt',
header: '更新时间',
width: 160,
},
]
const data: Ticket[] = [
{ id: 't-001', title: '补充表格文档', owner: '林舟', priority: '中', status: '进行中', updatedAt: '2026-05-23' },
{ id: 't-002', title: '优化筛选体验', owner: '陈念', priority: '高', status: '待处理', updatedAt: '2026-05-22' },
{ id: 't-003', title: '同步设计变量', owner: '周衡', priority: '低', status: '已完成', updatedAt: '2026-05-21' },
{ id: 't-004', title: '检查固定列阴影', owner: '沈若', priority: '中', status: '进行中', updatedAt: '2026-05-20' },
{ id: 't-005', title: '整理示例数据', owner: '梁一', priority: '低', status: '已完成', updatedAt: '2026-05-19' },
{ id: 't-006', title: '回归行选择交互', owner: '许知', priority: '高', status: '待处理', updatedAt: '2026-05-18' },
]
</script>
<template>
<FaTable stripe row-key="id" :columns :data />
</template>
@@ -0,0 +1,57 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
import FaButton from '../../../basic/button/index.vue'
import FaIcon from '../../../basic/icon/index.vue'
interface Task {
id: string
title: string
owner: string
status: string
updatedAt: string
}
const columns: TableColumn<Task>[] = [
{
accessorKey: 'title',
header: '任务',
},
{
accessorKey: 'owner',
header: '负责人',
},
{
accessorKey: 'status',
header: '状态',
},
{
accessorKey: 'updatedAt',
header: '更新时间',
},
]
const data: Task[] = [
{ id: 't-001', title: '完善组件文档', owner: '林舟', status: '进行中', updatedAt: '2026-05-23' },
{ id: 't-002', title: '同步设计变量', owner: '陈念', status: '待处理', updatedAt: '2026-05-22' },
{ id: 't-003', title: '整理示例数据', owner: '周衡', status: '已完成', updatedAt: '2026-05-21' },
{ id: 't-004', title: '回归交互状态', owner: '沈若', status: '进行中', updatedAt: '2026-05-20' },
]
</script>
<template>
<FaTable :columns :data>
<template #toolbar="{ table }">
<FaButton size="sm">
<FaIcon name="i-lucide:plus" />
新增
</FaButton>
<FaButton variant="outline" size="sm">
<FaIcon name="i-lucide:refresh-cw" />
刷新
</FaButton>
<span class="text-sm text-muted-foreground">
共 {{ table.getRowModel().rows.length }} 条
</span>
</template>
</FaTable>
</template>
@@ -0,0 +1,72 @@
<script setup lang="ts">
import type { TableColumn } from '../index.vue'
interface Task {
id: string
title: string
owner: string
status: string
updatedAt: string
children?: Task[]
}
const columns: TableColumn<Task>[] = [
{
accessorKey: 'title',
header: '任务',
},
{
accessorKey: 'owner',
header: '负责人',
width: 120,
},
{
accessorKey: 'status',
header: '状态',
width: 120,
},
{
accessorKey: 'updatedAt',
header: '更新时间',
width: 160,
},
]
const data: Task[] = [
{
id: 't-001',
title: '组件能力建设',
owner: '林舟',
status: '进行中',
updatedAt: '2026-05-23',
children: [
{ id: 't-001-1', title: '补充树型表格', owner: '林舟', status: '进行中', updatedAt: '2026-05-23' },
{ id: 't-001-2', title: '完善列显示控制', owner: '陈念', status: '待处理', updatedAt: '2026-05-22' },
],
},
{
id: 't-002',
title: '设计变量同步',
owner: '陈念',
status: '待处理',
updatedAt: '2026-05-22',
children: [
{
id: 't-002-1',
title: '整理主题色',
owner: '周衡',
status: '已完成',
updatedAt: '2026-05-21',
children: [
{ id: 't-002-1-1', title: '校验暗色模式', owner: '沈若', status: '已完成', updatedAt: '2026-05-20' },
],
},
],
},
{ id: 't-003', title: '回归交互状态', owner: '沈若', status: '进行中', updatedAt: '2026-05-20' },
]
</script>
<template>
<FaTable tree row-key="id" :columns :data />
</template>
@@ -0,0 +1,94 @@
import Basic from './_basic.vue'
import BasicRaw from './_basic.vue?raw'
import Border from './_border.vue'
import BorderRaw from './_border.vue?raw'
import ColumnVisibility from './_column-visibility.vue'
import ColumnVisibilityRaw from './_column-visibility.vue?raw'
import CustomColumn from './_custom-column.vue'
import CustomColumnRaw from './_custom-column.vue?raw'
import FixedColumn from './_fixed-column.vue'
import FixedColumnRaw from './_fixed-column.vue?raw'
import FixedHeight from './_fixed-height.vue'
import FixedHeightRaw from './_fixed-height.vue?raw'
import MultipleSelection from './_multiple-selection.vue'
import MultipleSelectionRaw from './_multiple-selection.vue?raw'
import SingleSelection from './_single-selection.vue'
import SingleSelectionRaw from './_single-selection.vue?raw'
import Slot from './_slot.vue'
import SlotRaw from './_slot.vue?raw'
import Sorting from './_sorting.vue'
import SortingRaw from './_sorting.vue?raw'
import Stripe from './_stripe.vue'
import StripeRaw from './_stripe.vue?raw'
import Toolbar from './_toolbar.vue'
import ToolbarRaw from './_toolbar.vue?raw'
import Tree from './_tree.vue'
import TreeRaw from './_tree.vue?raw'
export default [
{
title: '基础',
component: Basic,
componentRaw: BasicRaw,
},
{
title: '固定高度',
component: FixedHeight,
componentRaw: FixedHeightRaw,
},
{
title: '工具栏插槽',
component: Toolbar,
componentRaw: ToolbarRaw,
},
{
title: '固定列',
component: FixedColumn,
componentRaw: FixedColumnRaw,
},
{
title: '自定义列',
component: CustomColumn,
componentRaw: CustomColumnRaw,
},
{
title: '树型数据',
component: Tree,
componentRaw: TreeRaw,
},
{
title: '自定义插槽',
component: Slot,
componentRaw: SlotRaw,
},
{
title: '排序',
component: Sorting,
componentRaw: SortingRaw,
},
{
title: '行选择 - 单选',
component: SingleSelection,
componentRaw: SingleSelectionRaw,
},
{
title: '行选择 - 多选',
component: MultipleSelection,
componentRaw: MultipleSelectionRaw,
},
{
title: '斑马纹',
component: Stripe,
componentRaw: StripeRaw,
},
{
title: '边框',
component: Border,
componentRaw: BorderRaw,
},
{
title: '列可见性',
component: ColumnVisibility,
componentRaw: ColumnVisibilityRaw,
},
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,16 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<div data-slot="table-container" class="h-full w-full relative overflow-auto">
<table data-slot="table" :class="cn('w-full caption-bottom text-sm', props.class)">
<slot />
</table>
</div>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<tbody
data-slot="table-body"
:class="cn('[&_tr:last-child]:border-0 [&_tr:last-child]:shadow-[0_1px_0_0_oklch(var(--border))]', props.class)"
>
<slot />
</tbody>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<caption
data-slot="table-caption"
:class="cn('text-muted-foreground mt-4 text-sm', props.class)"
>
<slot />
</caption>
</template>
@@ -0,0 +1,22 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<td
data-slot="table-cell"
:class="
cn(
'p-2 align-middle whitespace-nowrap',
props.class,
)
"
>
<slot />
</td>
</template>
@@ -0,0 +1,34 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { cn } from '#utils'
import TableCell from './TableCell.vue'
import TableRow from './TableRow.vue'
const props = withDefaults(defineProps<{
class?: HTMLAttributes['class']
colspan?: number
}>(), {
colspan: 1,
})
const delegatedProps = reactiveOmit(props, 'class')
</script>
<template>
<TableRow class="h-full">
<TableCell
:class="
cn(
'h-full p-4 whitespace-nowrap align-middle text-sm text-foreground',
props.class,
)
"
v-bind="delegatedProps"
>
<div class="flex h-full min-h-40 items-center justify-center">
<slot />
</div>
</TableCell>
</TableRow>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<tfoot
data-slot="table-footer"
:class="cn('bg-muted/50 border-t font-medium [&>tr]:last:border-b-0', props.class)"
>
<slot />
</tfoot>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<th
data-slot="table-head"
:class="cn('text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap', props.class)"
>
<slot />
</th>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<thead
data-slot="table-header"
:class="cn(props.class)"
>
<slot />
</thead>
</template>
@@ -0,0 +1,17 @@
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '#utils'
const props = defineProps<{
class?: HTMLAttributes['class']
}>()
</script>
<template>
<tr
data-slot="table-row"
:class="cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', props.class)"
>
<slot />
</tr>
</template>
@@ -0,0 +1,9 @@
export { default as Table } from './Table.vue'
export { default as TableBody } from './TableBody.vue'
export { default as TableCaption } from './TableCaption.vue'
export { default as TableCell } from './TableCell.vue'
export { default as TableEmpty } from './TableEmpty.vue'
export { default as TableFooter } from './TableFooter.vue'
export { default as TableHead } from './TableHead.vue'
export { default as TableHeader } from './TableHeader.vue'
export { default as TableRow } from './TableRow.vue'
@@ -0,0 +1,9 @@
import type { Updater } from '@tanstack/vue-table'
import type { Ref } from 'vue'
import { isFunction } from '@tanstack/vue-table'
export function valueUpdater<T>(updaterOrValue: Updater<T>, ref: Ref<T>) {
ref.value = isFunction(updaterOrValue)
? updaterOrValue(ref.value)
: updaterOrValue
}
+1
View File
@@ -36,6 +36,7 @@ export { default as searchBar } from './basic/search-bar/_examples'
export { default as select } from './basic/select/_examples' export { default as select } from './basic/select/_examples'
export { default as slider } from './basic/slider/_examples' export { default as slider } from './basic/slider/_examples'
export { default as switch } from './basic/switch/_examples' export { default as switch } from './basic/switch/_examples'
export { default as table } from './basic/table/_examples'
export { default as tabs } from './basic/tabs/_examples' export { default as tabs } from './basic/tabs/_examples'
export { default as tag } from './basic/tag/_examples' export { default as tag } from './basic/tag/_examples'
export { default as textarea } from './basic/textarea/_examples' export { default as textarea } from './basic/textarea/_examples'
+2
View File
@@ -44,6 +44,8 @@ export { default as FaSearchBar } from './basic/search-bar/index.vue'
export { default as FaSelect } from './basic/select/index.vue' export { default as FaSelect } from './basic/select/index.vue'
export { default as FaSlider } from './basic/slider/index.vue' export { default as FaSlider } from './basic/slider/index.vue'
export { default as FaSwitch } from './basic/switch/index.vue' export { default as FaSwitch } from './basic/switch/index.vue'
export { default as FaTable } from './basic/table/index.vue'
export type { TableAlign, TableCellSlotProps, TableColumn, TableColumnFixed, TableEmptySlotProps, TableExpandedState, TableFooterSlotProps, TableHeaderSlotProps, TableProps, TableSelectionColumn, TableSelectionDisabled, TableSortingState, TableToolbarSlotProps } from './basic/table/index.vue'
export { default as FaTabs } from './basic/tabs/index.vue' export { default as FaTabs } from './basic/tabs/index.vue'
export { default as FaTag } from './basic/tag/index.vue' export { default as FaTag } from './basic/tag/index.vue'
export { default as FaTextarea } from './basic/textarea/index.vue' export { default as FaTextarea } from './basic/textarea/index.vue'
+26
View File
@@ -51,6 +51,9 @@ catalogs:
'@stylistic/stylelint-config': '@stylistic/stylelint-config':
specifier: ^5.0.0 specifier: ^5.0.0
version: 5.0.0 version: 5.0.0
'@tanstack/vue-table':
specifier: ^8.21.3
version: 8.21.3
'@tinymce/tinymce-vue': '@tinymce/tinymce-vue':
specifier: ^6.3.0 specifier: ^6.3.0
version: 6.3.0 version: 6.3.0
@@ -96,6 +99,9 @@ catalogs:
'@vue/tsconfig': '@vue/tsconfig':
specifier: ^0.9.1 specifier: ^0.9.1
version: 0.9.1 version: 0.9.1
'@vueuse/components':
specifier: ^14.3.0
version: 14.3.0
'@vueuse/core': '@vueuse/core':
specifier: ^14.3.0 specifier: ^14.3.0
version: 14.3.0 version: 14.3.0
@@ -2035,6 +2041,9 @@ importers:
'@lucide/vue': '@lucide/vue':
specifier: 'catalog:' specifier: 'catalog:'
version: 1.17.0(vue@3.5.35(typescript@6.0.3)) version: 1.17.0(vue@3.5.35(typescript@6.0.3))
'@tanstack/vue-table':
specifier: 'catalog:'
version: 8.21.3(vue@3.5.35(typescript@6.0.3))
'@vueuse/components': '@vueuse/components':
specifier: 'catalog:' specifier: 'catalog:'
version: 14.3.0(vue@3.5.35(typescript@6.0.3)) version: 14.3.0(vue@3.5.35(typescript@6.0.3))
@@ -4417,9 +4426,19 @@ packages:
'@sxzz/popperjs-es@2.11.8': '@sxzz/popperjs-es@2.11.8':
resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==} resolution: {integrity: sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==}
'@tanstack/table-core@8.21.3':
resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==}
engines: {node: '>=12'}
'@tanstack/virtual-core@3.13.23': '@tanstack/virtual-core@3.13.23':
resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==} resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==}
'@tanstack/vue-table@8.21.3':
resolution: {integrity: sha512-rusRyd77c5tDPloPskctMyPLFEQUeBzxdQ+2Eow4F7gDPlPOB1UnnhzfpdvqZ8ZyX2rRNGmqNnQWm87OI2OQPw==}
engines: {node: '>=12'}
peerDependencies:
vue: '>=3.2'
'@tanstack/vue-virtual@3.13.23': '@tanstack/vue-virtual@3.13.23':
resolution: {integrity: sha512-b5jPluAR6U3eOq6GWAYSpj3ugnAIZgGR0e6aGAgyRse0Yu6MVQQ0ZWm9SArSXWtageogn6bkVD8D//c4IjW3xQ==} resolution: {integrity: sha512-b5jPluAR6U3eOq6GWAYSpj3ugnAIZgGR0e6aGAgyRse0Yu6MVQQ0ZWm9SArSXWtageogn6bkVD8D//c4IjW3xQ==}
peerDependencies: peerDependencies:
@@ -11662,8 +11681,15 @@ snapshots:
'@sxzz/popperjs-es@2.11.8': {} '@sxzz/popperjs-es@2.11.8': {}
'@tanstack/table-core@8.21.3': {}
'@tanstack/virtual-core@3.13.23': {} '@tanstack/virtual-core@3.13.23': {}
'@tanstack/vue-table@8.21.3(vue@3.5.35(typescript@6.0.3))':
dependencies:
'@tanstack/table-core': 8.21.3
vue: 3.5.35(typescript@6.0.3)
'@tanstack/vue-virtual@3.13.23(vue@3.5.35(typescript@6.0.3))': '@tanstack/vue-virtual@3.13.23(vue@3.5.35(typescript@6.0.3))':
dependencies: dependencies:
'@tanstack/virtual-core': 3.13.23 '@tanstack/virtual-core': 3.13.23
+1
View File
@@ -22,6 +22,7 @@ catalog:
'@lucide/vue': ^1.17.0 '@lucide/vue': ^1.17.0
'@spiriit/vite-plugin-svg-spritemap': ^7.0.0 '@spiriit/vite-plugin-svg-spritemap': ^7.0.0
'@stylistic/stylelint-config': ^5.0.0 '@stylistic/stylelint-config': ^5.0.0
'@tanstack/vue-table': ^8.21.3
'@tinymce/tinymce-vue': ^6.3.0 '@tinymce/tinymce-vue': ^6.3.0
'@types/fs-extra': ^11.0.4 '@types/fs-extra': ^11.0.4
'@types/node': ^25.9.1 '@types/node': ^25.9.1