qidian-vue-ui 2.0.33 → 2.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -105,6 +105,9 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
105
105
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
106
106
  size?: import("..").QdServiceTableProps["size"];
107
107
  bordered?: boolean;
108
+ filterItemInputPlaceholder?: string;
109
+ filterItemSearchPlaceholder?: string;
110
+ filterItemAllText?: string;
108
111
  };
109
112
  wrapper?: {
110
113
  attach?: import("..").QdDialogProps["attach"];
@@ -249,6 +252,9 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
249
252
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
250
253
  size?: import("..").QdServiceTableProps["size"];
251
254
  bordered?: boolean;
255
+ filterItemInputPlaceholder?: string;
256
+ filterItemSearchPlaceholder?: string;
257
+ filterItemAllText?: string;
252
258
  };
253
259
  wrapper?: {
254
260
  attach?: import("..").QdDialogProps["attach"];
@@ -378,6 +384,9 @@ export declare const QdConfigProvider: import("vue").DefineComponent<{
378
384
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
379
385
  size?: import("..").QdServiceTableProps["size"];
380
386
  bordered?: boolean;
387
+ filterItemInputPlaceholder?: string;
388
+ filterItemSearchPlaceholder?: string;
389
+ filterItemAllText?: string;
381
390
  };
382
391
  wrapper?: {
383
392
  attach?: import("..").QdDialogProps["attach"];
@@ -122,6 +122,9 @@ export interface QdConfigProviderProps {
122
122
  table?: Omit<NonNullable<NonNullable<TdConfigProviderProps['globalConfig']>['table']>, 'size'> & {
123
123
  size?: QdServiceTableProps['size'];
124
124
  bordered?: boolean;
125
+ filterItemInputPlaceholder?: string;
126
+ filterItemSearchPlaceholder?: string;
127
+ filterItemAllText?: string;
125
128
  };
126
129
  wrapper?: {
127
130
  attach?: QdDialogProps['attach'];
@@ -93,6 +93,9 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
93
93
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
94
94
  size?: import("..").QdServiceTableProps["size"];
95
95
  bordered?: boolean;
96
+ filterItemInputPlaceholder?: string;
97
+ filterItemSearchPlaceholder?: string;
98
+ filterItemAllText?: string;
96
99
  };
97
100
  wrapper?: {
98
101
  attach?: import("..").QdDialogProps["attach"];
@@ -220,6 +223,9 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
220
223
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
221
224
  size?: import("..").QdServiceTableProps["size"];
222
225
  bordered?: boolean;
226
+ filterItemInputPlaceholder?: string;
227
+ filterItemSearchPlaceholder?: string;
228
+ filterItemAllText?: string;
223
229
  };
224
230
  wrapper?: {
225
231
  attach?: import("..").QdDialogProps["attach"];
@@ -347,6 +353,9 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
347
353
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
348
354
  size?: import("..").QdServiceTableProps["size"];
349
355
  bordered?: boolean;
356
+ filterItemInputPlaceholder?: string;
357
+ filterItemSearchPlaceholder?: string;
358
+ filterItemAllText?: string;
350
359
  };
351
360
  wrapper?: {
352
361
  attach?: import("..").QdDialogProps["attach"];
@@ -475,6 +484,9 @@ export declare function useConfig<T extends keyof NonNullable<QdConfigProviderPr
475
484
  table?: Omit<NonNullable<NonNullable<import("tdesign-vue-next").TdConfigProviderProps["globalConfig"]>["table"]>, "size"> & {
476
485
  size?: import("..").QdServiceTableProps["size"];
477
486
  bordered?: boolean;
487
+ filterItemInputPlaceholder?: string;
488
+ filterItemSearchPlaceholder?: string;
489
+ filterItemAllText?: string;
478
490
  };
479
491
  wrapper?: {
480
492
  attach?: import("..").QdDialogProps["attach"];
@@ -0,0 +1,50 @@
1
+ import type { PropType, VNodeChild } from 'vue';
2
+ import type { QdServiceTableFilterOption } from './types';
3
+ type FilterValue = string | number | Array<string | number> | null;
4
+ type FilterOption = QdServiceTableFilterOption & {
5
+ render?: () => VNodeChild;
6
+ };
7
+ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
8
+ options: {
9
+ type: PropType<FilterOption[]>;
10
+ default: () => never[];
11
+ };
12
+ type: {
13
+ type: PropType<"single" | "multiple">;
14
+ default: string;
15
+ };
16
+ value: {
17
+ type: PropType<FilterValue>;
18
+ };
19
+ showConfirmAndReset: {
20
+ type: BooleanConstructor;
21
+ default: boolean;
22
+ };
23
+ onChange: {
24
+ type: PropType<(value: FilterValue) => void>;
25
+ };
26
+ }>, () => JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
27
+ options: {
28
+ type: PropType<FilterOption[]>;
29
+ default: () => never[];
30
+ };
31
+ type: {
32
+ type: PropType<"single" | "multiple">;
33
+ default: string;
34
+ };
35
+ value: {
36
+ type: PropType<FilterValue>;
37
+ };
38
+ showConfirmAndReset: {
39
+ type: BooleanConstructor;
40
+ default: boolean;
41
+ };
42
+ onChange: {
43
+ type: PropType<(value: FilterValue) => void>;
44
+ };
45
+ }>> & Readonly<{}>, {
46
+ type: "multiple" | "single";
47
+ options: FilterOption[];
48
+ showConfirmAndReset: boolean;
49
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
50
+ export default _default;
@@ -0,0 +1,170 @@
1
+ import { defineComponent, ref, computed, createVNode, onMounted, onBeforeUnmount } from "vue";
2
+ import { SearchIcon } from "tdesign-icons-vue-next";
3
+ import { Input, Checkbox, Radio } from "tdesign-vue-next";
4
+ import { useConfig } from "../../config-provider/useConfig.mjs";
5
+ const FilterOptionContent = /* @__PURE__ */ defineComponent({
6
+ props: {
7
+ render: {
8
+ type: Function,
9
+ required: true
10
+ },
11
+ onTextChange: {
12
+ type: Function,
13
+ required: true
14
+ }
15
+ },
16
+ setup(props) {
17
+ const content = ref();
18
+ let observer;
19
+ function syncText() {
20
+ props.onTextChange(content.value?.textContent?.trim() ?? "");
21
+ }
22
+ onMounted(() => {
23
+ syncText();
24
+ observer = new MutationObserver(syncText);
25
+ if (content.value) observer.observe(content.value, {
26
+ characterData: true,
27
+ childList: true,
28
+ subtree: true
29
+ });
30
+ });
31
+ onBeforeUnmount(() => observer?.disconnect());
32
+ return () => createVNode("span", {
33
+ "ref": content,
34
+ "class": "qd-service-table-filter-item__cell",
35
+ "inert": true
36
+ }, [props.render()]);
37
+ }
38
+ });
39
+ const QdServiceTableFilterItem = /* @__PURE__ */ defineComponent({
40
+ name: "QdServiceTableFilterItem",
41
+ props: {
42
+ options: {
43
+ type: Array,
44
+ default: () => []
45
+ },
46
+ type: {
47
+ type: String,
48
+ default: "multiple"
49
+ },
50
+ value: {
51
+ type: [String, Number, Array]
52
+ },
53
+ showConfirmAndReset: {
54
+ type: Boolean,
55
+ default: true
56
+ },
57
+ onChange: {
58
+ type: Function
59
+ }
60
+ },
61
+ setup(props) {
62
+ const {
63
+ t
64
+ } = useConfig("table");
65
+ const keyword = ref("");
66
+ const renderedTexts = ref(/* @__PURE__ */ new Map());
67
+ const selectedValues = computed(() => {
68
+ if (props.type === "multiple") return Array.isArray(props.value) ? props.value : [];
69
+ return props.value === "" || props.value === void 0 ? [] : [props.value];
70
+ });
71
+ const allSelected = computed(() => props.type === "multiple" && props.value !== null && (!selectedValues.value.length || props.options.every((option) => selectedValues.value.includes(option.value))));
72
+ const filteredOptions = computed(() => {
73
+ const keywords = keyword.value.trim().toLowerCase().split(/\s+/).filter(Boolean);
74
+ if (!keywords.length) return props.options;
75
+ return props.options.filter((option) => {
76
+ const label = (renderedTexts.value.get(option.value) || option.label).toLowerCase();
77
+ return keywords.some((item) => label.includes(item));
78
+ });
79
+ });
80
+ const totalCount = computed(() => props.options.reduce((total, option) => total + (option.count ?? 0), 0));
81
+ const selectedCount = computed(() => {
82
+ if (props.value === null) return 0;
83
+ if (allSelected.value || !selectedValues.value.length) return totalCount.value;
84
+ return props.options.reduce((total, option) => selectedValues.value.includes(option.value) ? total + (option.count ?? 0) : total, 0);
85
+ });
86
+ function selectAll() {
87
+ props.onChange?.(props.type === "multiple" ? [] : "");
88
+ }
89
+ function selectOption(value, checked) {
90
+ if (props.type === "single") {
91
+ props.onChange?.(value);
92
+ return;
93
+ }
94
+ const current = allSelected.value ? props.options.map((option) => option.value) : selectedValues.value;
95
+ const next = checked ? [.../* @__PURE__ */ new Set([...current, value])] : current.filter((item) => item !== value);
96
+ if (!next.length) {
97
+ if (!props.showConfirmAndReset) return;
98
+ props.onChange?.(null);
99
+ return;
100
+ }
101
+ const valueAllSelected = props.options.every((option) => next.includes(option.value));
102
+ props.onChange?.(valueAllSelected ? [] : next);
103
+ }
104
+ function renderOption(option) {
105
+ if (!option.render) return option.label;
106
+ return createVNode(FilterOptionContent, {
107
+ "render": option.render,
108
+ "onTextChange": (text) => {
109
+ option.label = text || option.label;
110
+ renderedTexts.value.set(option.value, text);
111
+ }
112
+ }, null);
113
+ }
114
+ function isOptionDisabled(option) {
115
+ if (option.disabled) return true;
116
+ if (props.showConfirmAndReset || allSelected.value) return false;
117
+ return selectedValues.value.length === 1 && selectedValues.value.includes(option.value);
118
+ }
119
+ return () => createVNode("div", {
120
+ "class": "qd-service-table-filter-item"
121
+ }, [createVNode("div", {
122
+ "class": "qd-service-table-filter-item__search"
123
+ }, [createVNode(Input, {
124
+ "modelValue": keyword.value,
125
+ "onUpdate:modelValue": ($event) => keyword.value = $event,
126
+ "clearable": true,
127
+ "placeholder": t("filterItemSearchPlaceholder"),
128
+ "prefixIcon": () => createVNode(SearchIcon, null, null)
129
+ }, null)]), createVNode("div", {
130
+ "class": "qd-service-table-filter-item__all"
131
+ }, [props.type === "multiple" ? createVNode(Checkbox, {
132
+ "checked": allSelected.value,
133
+ "onChange": selectAll
134
+ }, {
135
+ default: () => [t("filterItemAllText"), createVNode("span", {
136
+ "class": "qd-service-table-filter-item__count"
137
+ }, [`(${selectedCount.value}/${totalCount.value})`])]
138
+ }) : createVNode(Radio, {
139
+ "checked": !selectedValues.value.length,
140
+ "onChange": selectAll
141
+ }, {
142
+ default: () => [t("filterItemAllText"), createVNode("span", {
143
+ "class": "qd-service-table-filter-item__count"
144
+ }, [`(${selectedCount.value}/${totalCount.value})`])]
145
+ })]), createVNode("div", {
146
+ "class": "qd-service-table-filter-item__options"
147
+ }, [filteredOptions.value.map((option) => props.type === "multiple" ? createVNode(Checkbox, {
148
+ "key": option.value,
149
+ "checked": allSelected.value || selectedValues.value.includes(option.value),
150
+ "disabled": isOptionDisabled(option),
151
+ "onChange": (checked) => selectOption(option.value, checked)
152
+ }, {
153
+ default: () => [renderOption(option), createVNode("span", {
154
+ "class": "qd-service-table-filter-item__count"
155
+ }, [`(${option.count ?? 0})`])]
156
+ }) : createVNode(Radio, {
157
+ "key": option.value,
158
+ "checked": selectedValues.value.includes(option.value),
159
+ "disabled": option.disabled,
160
+ "onChange": () => selectOption(option.value, true)
161
+ }, {
162
+ default: () => [renderOption(option), createVNode("span", {
163
+ "class": "qd-service-table-filter-item__count"
164
+ }, [`(${option.count ?? 0})`])]
165
+ }))])]);
166
+ }
167
+ });
168
+ export {
169
+ QdServiceTableFilterItem as default
170
+ };
@@ -1,88 +1,156 @@
1
- .qd-service-table[data-v-92206ee3] {
1
+ .qd-service-table[data-v-1793b265] {
2
2
  height: 100%;
3
3
  display: flex;
4
4
  flex-direction: column;
5
5
  }
6
- .qd-service-table[data-v-92206ee3] > .t-table__content {
6
+ .qd-service-table[data-v-1793b265] > .t-table__content {
7
7
  flex: 1;
8
8
  }
9
- .qd-service-table--mini[data-v-92206ee3] {
9
+ .qd-service-table--mini[data-v-1793b265] {
10
10
  font: var(--td-font-body-small);
11
11
  }
12
- .qd-service-table--mini[data-v-92206ee3] th,
13
- .qd-service-table--mini[data-v-92206ee3] tr:not(.t-table__expanded-row) > td {
12
+ .qd-service-table--mini[data-v-1793b265] th,
13
+ .qd-service-table--mini[data-v-1793b265] tr:not(.t-table__expanded-row) > td {
14
14
  padding: var(--td-comp-paddingTB-xxs) var(--td-comp-paddingLR-xxs);
15
15
  line-height: var(--td-line-height-body-small);
16
16
  }
17
- .qd-service-table--mini[data-v-92206ee3] .t-table__row-full-element {
17
+ .qd-service-table--mini[data-v-1793b265] .t-table__row-full-element {
18
18
  padding: var(--td-comp-paddingTB-xs) var(--td-comp-paddingLR-s);
19
19
  }
20
- .qd-service-table--hide-empty-image[data-v-92206ee3] .t-table__empty {
20
+ .qd-service-table--hide-empty-image[data-v-1793b265] .t-table__empty {
21
21
  min-height: auto;
22
22
  }
23
- .qd-service-table--hide-empty-image[data-v-92206ee3] .t-table__empty .t-empty {
23
+ .qd-service-table--hide-empty-image[data-v-1793b265] .t-table__empty .t-empty {
24
24
  padding: 0 !important;
25
25
  }
26
- .qd-service-table--hide-empty-image[data-v-92206ee3] .t-table__empty .t-empty__image {
26
+ .qd-service-table--hide-empty-image[data-v-1793b265] .t-table__empty .t-empty__image {
27
27
  display: none;
28
28
  }
29
- .qd-service-table--hide-empty-image[data-v-92206ee3] .t-table__empty .t-empty__title {
29
+ .qd-service-table--hide-empty-image[data-v-1793b265] .t-table__empty .t-empty__title {
30
30
  margin-top: 0;
31
31
  }
32
- .qd-service-table[data-v-92206ee3] .t-table__tree-col:not(:has(.t-table__tree-op-icon)) {
32
+ .qd-service-table[data-v-1793b265] .t-table__tree-col:not(:has(.t-table__tree-op-icon)) {
33
33
  margin-left: calc(var(--td-font-size-body-large) + var(--td-comp-margin-s));
34
34
  }
35
- .qd-service-table[data-v-92206ee3] .t-table__tree-leaf-node .t-table__tree-op-icon:empty {
35
+ .qd-service-table[data-v-1793b265] .t-table__tree-leaf-node .t-table__tree-op-icon:empty {
36
36
  width: calc(var(--td-font-size-body-large) + var(--td-comp-margin-s));
37
37
  }
38
- .qd-service-table[data-v-92206ee3] .t-affix > .t-table__affixed-header-elm-wrap,
39
- .qd-service-table[data-v-92206ee3] .t-affix > .t-table__scrollbar--obvious {
40
- transform: var(--v48c62e9a);
38
+ .qd-service-table[data-v-1793b265] .t-affix > .t-table__affixed-header-elm-wrap,
39
+ .qd-service-table[data-v-1793b265] .t-affix > .t-table__scrollbar--obvious {
40
+ transform: var(--c120d096);
41
41
  }
42
- .qd-service-table--horizontal-bar-static[data-v-92206ee3] .t-table__scrollbar--obvious {
42
+ .qd-service-table--horizontal-bar-static[data-v-1793b265] .t-table__scrollbar--obvious {
43
43
  visibility: hidden;
44
44
  pointer-events: none;
45
45
  }
46
- .qd-service-table[data-v-92206ee3] .t-table__expanded-row .qd-service-table--horizontal-bar-static > div:has(> div > .t-table__scrollbar--obvious) {
46
+ .qd-service-table[data-v-1793b265] .t-table__expanded-row .qd-service-table--horizontal-bar-static > div:has(> div > .t-table__scrollbar--obvious) {
47
47
  display: none;
48
48
  }
49
- .qd-service-table[data-v-92206ee3] .t-table__expanded-row > td {
49
+ .qd-service-table[data-v-1793b265] .t-table__expanded-row > td {
50
50
  height: 0;
51
51
  }
52
- .qd-service-table[data-v-92206ee3] .t-table__affixed-header-elm-wrap {
52
+ .qd-service-table[data-v-1793b265] .t-table__affixed-header-elm-wrap {
53
53
  height: auto !important;
54
54
  }
55
- .qd-service-table[data-v-92206ee3] .t-table__affixed-header-elm {
55
+ .qd-service-table[data-v-1793b265] .t-table__affixed-header-elm {
56
56
  position: relative;
57
57
  scrollbar-width: none;
58
58
  }
59
- .qd-service-table[data-v-92206ee3] .t-table__affixed-header-elm::-webkit-scrollbar {
59
+ .qd-service-table[data-v-1793b265] .t-table__affixed-header-elm::-webkit-scrollbar {
60
60
  display: none;
61
61
  width: 0;
62
62
  height: 0;
63
63
  }
64
- .qd-service-table[data-v-92206ee3] .t-table__virtual-scroll-cursor + table {
64
+ .qd-service-table[data-v-1793b265] .t-table__virtual-scroll-cursor + table {
65
65
  border-collapse: separate;
66
66
  }
67
- .qd-service-table[data-v-92206ee3] .t-table__expanded-row-inner {
67
+ .qd-service-table[data-v-1793b265] .t-table__expanded-row-inner {
68
68
  display: block;
69
69
  position: sticky;
70
70
  left: 0;
71
- width: var(--v442c3de2) !important;
71
+ width: var(--b49a0b2c) !important;
72
72
  }
73
- .qd-service-table[data-v-92206ee3] .t-table__cell-wrap > .t-form__controls > .t-form__controls-content > *:not(.t-switch):not(.t-tag):not(.t-icon):not(.qd-file-icon) {
73
+ .qd-service-table[data-v-1793b265] .t-table__cell-wrap > .t-form__controls > .t-form__controls-content > *:not(.t-switch):not(.t-tag):not(.t-icon):not(.qd-file-icon) {
74
74
  width: 100%;
75
75
  }
76
- .qd-service-table[data-v-92206ee3] .qd-service-table__non-editable-col {
76
+ .qd-service-table[data-v-1793b265] .qd-service-table__non-editable-col {
77
77
  background-color: color-mix(in srgb, var(--td-bg-color-component) 50%, transparent);
78
78
  }
79
- .qd-service-table[data-v-92206ee3] .qd-service-table__non-editable-col:is(
79
+ .qd-service-table[data-v-1793b265] .qd-service-table__non-editable-col:is(
80
80
  .t-table__cell--fixed-left,
81
81
  .t-table__cell--fixed-right
82
82
  ) {
83
83
  background-color: inherit;
84
84
  background-image: linear-gradient(color-mix(in srgb, var(--td-bg-color-secondarycontainer) 50%, transparent), color-mix(in srgb, var(--td-bg-color-secondarycontainer) 50%, transparent));
85
85
  }
86
- .qd-service-table--disable-horizontal-scroll[data-v-92206ee3] colgroup > col {
86
+ .qd-service-table--disable-horizontal-scroll[data-v-1793b265] colgroup > col {
87
87
  width: auto !important;
88
88
  }
89
+ .qd-service-table[data-v-1793b265] .t-table__filter-pop-content-inner {
90
+ padding: var(--td-comp-paddingTB-s) var(--td-comp-paddingLR-s) 0;
91
+ }
92
+ .qd-service-table[data-v-1793b265] .t-table__filter-pop-content-inner:has(.qd-service-table-filter-item) {
93
+ padding: 0;
94
+ }
95
+ .qd-service-table[data-v-1793b265] .t-table__filter-pop-content-inner:has(
96
+ .qd-service-table-filter-input,
97
+ .qd-service-table-filter-custom
98
+ ) {
99
+ padding-bottom: var(--td-comp-paddingTB-s);
100
+ }
101
+ .qd-service-table[data-v-1793b265] .t-table__filter--bottom-buttons {
102
+ padding: var(--td-comp-paddingTB-s) var(--td-comp-paddingLR-s);
103
+ }
104
+ .qd-service-table--mini[data-v-1793b265] .t-table__filter-pop-content-inner {
105
+ padding: var(--td-comp-paddingTB-xs) var(--td-comp-paddingLR-xs) 0;
106
+ }
107
+ .qd-service-table--mini[data-v-1793b265] .t-table__filter--bottom-buttons {
108
+ padding: var(--td-comp-paddingTB-xs) var(--td-comp-paddingLR-xs);
109
+ }
110
+ .qd-service-table--mini[data-v-1793b265] .t-table__filter-pop-content-inner:has(.qd-service-table-filter-item) {
111
+ padding: 0;
112
+ }
113
+ .qd-service-table--mini[data-v-1793b265] .t-table__filter-pop-content-inner:has(
114
+ .qd-service-table-filter-input,
115
+ .qd-service-table-filter-custom
116
+ ) {
117
+ padding-bottom: var(--td-comp-paddingTB-xs);
118
+ }
119
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item {
120
+ width: 266px;
121
+ }
122
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__search,
123
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__all,
124
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__options {
125
+ padding: var(--td-comp-paddingTB-s) var(--td-comp-paddingLR-s) 0;
126
+ }
127
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__all {
128
+ padding: 0 var(--td-comp-paddingLR-s);
129
+ border-bottom: 1px solid var(--td-component-stroke);
130
+ }
131
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__options {
132
+ display: flex;
133
+ flex-direction: column;
134
+ height: 206px;
135
+ padding: 0 var(--td-comp-paddingLR-s);
136
+ overflow-y: auto;
137
+ }
138
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__count {
139
+ margin-left: var(--td-comp-margin-xs);
140
+ color: var(--td-text-color-placeholder);
141
+ }
142
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item__cell {
143
+ pointer-events: none;
144
+ }
145
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item .t-checkbox__label,
146
+ .qd-service-table[data-v-1793b265] .qd-service-table-filter-item .t-radio__label {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ }
150
+ .qd-service-table--mini[data-v-1793b265] .qd-service-table-filter-item__search {
151
+ padding: var(--td-comp-paddingTB-xs) var(--td-comp-paddingLR-xs) 0;
152
+ }
153
+ .qd-service-table--mini[data-v-1793b265] .qd-service-table-filter-item__all,
154
+ .qd-service-table--mini[data-v-1793b265] .qd-service-table-filter-item__options {
155
+ padding: 0 var(--td-comp-paddingLR-xs);
156
+ }
@@ -1,2 +1,2 @@
1
1
  export { default as QdServiceTable } from './index.vue';
2
- export type { QdServiceTableCol, QdServiceTableFormItem, QdServiceTableInstanceFunctions, QdServiceTableProps, QdServiceTableScroll, QdServiceTableSubmitRowContext, QdServiceTableSubmitTableContext, QdServiceTableValidateParams, QdServiceTableValidateRowContext, QdServiceTableValidateTableContext } from './types';
2
+ export type { QdServiceTableCol, QdServiceTableFilterItem, QdServiceTableFilterOption, QdServiceTableFormItem, QdServiceTableInstanceFunctions, QdServiceTableProps, QdServiceTableScroll, QdServiceTableSubmitRowContext, QdServiceTableSubmitTableContext, QdServiceTableValidateParams, QdServiceTableValidateRowContext, QdServiceTableValidateTableContext } from './types';
@@ -2,7 +2,7 @@ import './index.css'
2
2
  import _sfc_main from "./index.vue2.mjs";
3
3
  /* empty css */
4
4
  import _export_sfc from "../../../_virtual/_plugin-vue_export-helper.mjs";
5
- const QdServiceTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-92206ee3"]]);
5
+ const QdServiceTable = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1793b265"]]);
6
6
  export {
7
7
  QdServiceTable as default
8
8
  };
@@ -1,7 +1,7 @@
1
1
  import './index.css'
2
- import { defineComponent, mergeDefaults, useCssVars, computed, ref, useSlots, useTemplateRef, shallowRef, inject, getCurrentInstance, reactive, createVNode, watch, nextTick, onMounted, onActivated, onDeactivated, onBeforeUnmount, withDirectives, createBlock, openBlock, resolveDynamicComponent, unref, mergeProps, isRef, createSlots, withCtx, renderList, renderSlot, normalizeProps, guardReactiveProps, render, h } from "vue";
2
+ import { defineComponent, mergeDefaults, useCssVars, computed, ref, useSlots, useTemplateRef, shallowRef, inject, getCurrentInstance, reactive, createVNode, watch, nextTick, onMounted, onActivated, onDeactivated, onBeforeUnmount, withDirectives, createBlock, openBlock, resolveDynamicComponent, unref, mergeProps, isRef, createSlots, withCtx, renderList, renderSlot, normalizeProps, guardReactiveProps, h, render } from "vue";
3
3
  import { useVModels, useElementSize, useElementBounding, useIntersectionObserver } from "../../../node_modules/.pnpm/@vueuse_core@14.2.0_vue@3.5.26_typescript@5.9.3_/node_modules/@vueuse/core/dist/index.mjs";
4
- import { useActivated, useTimer, easyCopy, isEmpty, suspectedWrapperPromise, getScrollEl, useServicePagination, createExposeProxy, resizeDirective } from "qidian-shared";
4
+ import { useActivated, useTimer, useServicePagination, easyCopy, isEmpty, suspectedWrapperPromise, getScrollEl, createExposeProxy, resizeDirective } from "qidian-shared";
5
5
  import { LoadingIcon, AddRectangleIcon, MinusRectangleIcon } from "tdesign-icons-vue-next";
6
6
  import { EnhancedTable, Table, Empty } from "tdesign-vue-next";
7
7
  import { validate } from "tdesign-vue-next/es/form/utils/form-model.mjs";
@@ -10,9 +10,11 @@ import { getTransformOffset } from "../../../utils/tools.mjs";
10
10
  import { useConfig } from "../../config-provider/useConfig.mjs";
11
11
  import { resolveQdFormItemOptions, getQdFormComponentName } from "../../form/utils.mjs";
12
12
  import QdServiceTableEditCell from "./edit-cell.mjs";
13
+ import QdServiceTableFilterItem from "./filter-item.mjs";
13
14
  import { qdServiceTableTreeConfig, qdServiceTableProps, getSortParams } from "./props.mjs";
14
15
  import { PROVIDE_FORM_ADD_BEFORE_SUBMIT_QUEUE } from "../../form/config.mjs";
15
16
  import get from "../../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/get.mjs";
17
+ import _sfc_main$1 from "../../config-renderer/index.vue.mjs";
16
18
  import QdForm from "../../form/index.vue.mjs";
17
19
  import set from "../../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/set.mjs";
18
20
  const defaultMinWidth = 80;
@@ -325,8 +327,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
325
327
  emit: __emit
326
328
  }) {
327
329
  useCssVars((_ctx) => ({
328
- "v48c62e9a": affixedHeaderTransform.value,
329
- "v442c3de2": expandedRowWidth.value
330
+ "c120d096": affixedHeaderTransform.value,
331
+ "b49a0b2c": expandedRowWidth.value
330
332
  }));
331
333
  const props = __props;
332
334
  const emit = __emit;
@@ -495,7 +497,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
495
497
  let affixRefreshRafId = 0;
496
498
  let animatingAncestorCleanup = null;
497
499
  const adaptedColumns = computed(() => {
498
- const columns = wrapFormItemColumns(props.columns || []);
500
+ const columns = wrapColumns(props.columns || []);
499
501
  const selectType = props.selectType;
500
502
  if (!selectType) return columns;
501
503
  const selectIdx = columns.findIndex((item) => item.type === "single" || item.type === "multiple");
@@ -515,6 +517,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
515
517
  }
516
518
  return columns;
517
519
  });
520
+ const displayData = computed(() => {
521
+ if (props.onFilterChange) return data.value;
522
+ if (props.service && props.pagination !== false) return data.value;
523
+ const activeFilters = getActiveFilterEntries();
524
+ if (!activeFilters.length) return data.value;
525
+ return data.value.filter((row) => activeFilters.every(({
526
+ colKey,
527
+ type,
528
+ value
529
+ }) => {
530
+ const rowValue = get(row, colKey);
531
+ if (type === "input") {
532
+ return String(rowValue ?? "").toLowerCase().includes(String(value).toLowerCase());
533
+ }
534
+ if (Array.isArray(value)) return value.includes(rowValue);
535
+ return rowValue === value;
536
+ }));
537
+ });
518
538
  const {
519
539
  stop: tableContentStop,
520
540
  pause: tableContentPause,
@@ -550,7 +570,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
550
570
  columnControllerVisible: columnControllerVisible2,
551
571
  displayColumns: displayColumns2,
552
572
  expandedRowKeys: expandedRowKeys2,
553
- filterValue: filterValue2,
573
+ filterValue: inFilterValue,
554
574
  sort: sort2,
555
575
  searchData: _searchData,
556
576
  expandedTreeNodes: expandedTreeNodes2,
@@ -582,6 +602,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
582
602
  const reTableOptions = tableOptions;
583
603
  const onValidate = reTableOptions.onValidate;
584
604
  const onRowValidate = reTableOptions.onRowValidate;
605
+ const onFilterChange = reTableOptions.onFilterChange;
585
606
  reTableOptions.onValidate = (context) => {
586
607
  replaceTableValidationErrors(context.result);
587
608
  onValidate?.(context);
@@ -590,6 +611,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
590
611
  syncCellValidationErrors(context.result);
591
612
  onRowValidate?.(context);
592
613
  };
614
+ reTableOptions.onFilterChange = (value, context) => {
615
+ if (filterValue) filterValue.value = value;
616
+ onFilterChange?.(value, context);
617
+ if (onFilterChange) return;
618
+ if (!service || pagination === false) return;
619
+ changeCurrent(1);
620
+ };
593
621
  const expandedRow = reTableOptions.expandedRow;
594
622
  if (expandedRow) {
595
623
  reTableOptions.expandedRow = (h2, context) => expandedRow(h2, {
@@ -838,7 +866,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
838
866
  columnControllerVisible: columnControllerVisible2,
839
867
  displayColumns: displayColumns2,
840
868
  expandedRowKeys: expandedRowKeys2,
841
- filterValue: filterValue2,
869
+ filterValue: inFilterValue,
842
870
  sort: sort2,
843
871
  expandedTreeNodes: expandedTreeNodes2
844
872
  }
@@ -955,7 +983,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
955
983
  async function transformServiceParams(params) {
956
984
  const mergedParams = {
957
985
  ...params,
958
- ...searchData.value
986
+ ...searchData.value,
987
+ ...getActiveFilterParams()
959
988
  };
960
989
  if (props.transformParams) return props.transformParams(mergedParams);
961
990
  return mergedParams;
@@ -1654,20 +1683,186 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1654
1683
  rowData: row ? easyCopy(row) : void 0
1655
1684
  };
1656
1685
  }
1657
- function wrapFormItemColumns(columns) {
1686
+ function isActiveFilterValue(value) {
1687
+ if (Array.isArray(value)) return value.length > 0;
1688
+ return value !== void 0 && value !== null && value !== "";
1689
+ }
1690
+ function getActiveFilterParams() {
1691
+ return Object.fromEntries(Object.entries(filterValue?.value ?? {}).filter(([, value]) => isActiveFilterValue(value)));
1692
+ }
1693
+ function getFilterColumns(columns) {
1694
+ return columns.flatMap((column) => column.children ? getFilterColumns(column.children) : column.colKey ? [column] : []);
1695
+ }
1696
+ function getActiveFilterEntries() {
1697
+ const values = filterValue?.value ?? {};
1698
+ return getFilterColumns(props.columns || []).flatMap((column) => {
1699
+ if (!column.colKey) return [];
1700
+ const value = values[column.colKey];
1701
+ if (!isActiveFilterValue(value)) return [];
1702
+ const filterItem = column.filterItem === true ? {} : column.filterItem;
1703
+ const type = column.filter?.type ?? (filterItem?.component ? void 0 : filterItem?.type);
1704
+ return [{
1705
+ colKey: column.colKey,
1706
+ type,
1707
+ value
1708
+ }];
1709
+ });
1710
+ }
1711
+ function resolveFilterOptions(column, configuredOptions, reuseCell = true) {
1712
+ const counts = /* @__PURE__ */ new Map();
1713
+ const firstRows = /* @__PURE__ */ new Map();
1714
+ const colKey = column.colKey;
1715
+ data.value.forEach((row, rowIndex) => {
1716
+ const value = colKey ? get(row, colKey) : void 0;
1717
+ if (typeof value !== "string" && typeof value !== "number") return;
1718
+ if (value === "") return;
1719
+ counts.set(value, (counts.get(value) ?? 0) + 1);
1720
+ if (!firstRows.has(value)) firstRows.set(value, {
1721
+ row,
1722
+ rowIndex
1723
+ });
1724
+ });
1725
+ if (configuredOptions) {
1726
+ return configuredOptions.map((option) => ({
1727
+ ...option,
1728
+ count: option.count ?? counts.get(option.value) ?? 0
1729
+ }));
1730
+ }
1731
+ const colIndex = getFilterColumns(props.columns || []).indexOf(column);
1732
+ return [...counts].map(([value, count]) => {
1733
+ const firstRow = firstRows.get(value);
1734
+ return {
1735
+ label: String(value),
1736
+ value,
1737
+ count,
1738
+ ...reuseCell && firstRow ? {
1739
+ render: () => renderDisplayCell(h, column, {
1740
+ ...firstRow,
1741
+ col: column,
1742
+ colIndex
1743
+ })
1744
+ } : {}
1745
+ };
1746
+ });
1747
+ }
1748
+ function createConfigFilterComponent(component) {
1749
+ return /* @__PURE__ */ defineComponent({
1750
+ inheritAttrs: false,
1751
+ setup(_, {
1752
+ attrs
1753
+ }) {
1754
+ return () => {
1755
+ const filterAttrs = Object.fromEntries(Object.entries(attrs).filter(([, value]) => value !== void 0));
1756
+ return h(_sfc_main$1, {
1757
+ config: component,
1758
+ ...filterAttrs,
1759
+ class: ["qd-service-table-filter-custom", filterAttrs.class]
1760
+ });
1761
+ };
1762
+ }
1763
+ });
1764
+ }
1765
+ function resolveColumnFilter(column, filterItem, filter) {
1766
+ const config = filterItem === true ? {} : filterItem;
1767
+ const {
1768
+ component,
1769
+ options,
1770
+ reuseCell = true,
1771
+ type = "multiple",
1772
+ props: filterProps,
1773
+ ...filterOptions
1774
+ } = config;
1775
+ let generatedFilter;
1776
+ if (component) {
1777
+ generatedFilter = {
1778
+ resetValue: "",
1779
+ showConfirmAndReset: true,
1780
+ ...filterOptions,
1781
+ props: filterProps,
1782
+ component: createConfigFilterComponent(component)
1783
+ };
1784
+ } else if (type === "input") {
1785
+ generatedFilter = {
1786
+ resetValue: "",
1787
+ showConfirmAndReset: true,
1788
+ ...filterOptions,
1789
+ props: {
1790
+ placeholder: tableT("filterItemInputPlaceholder"),
1791
+ ...filterProps,
1792
+ class: "qd-service-table-filter-input"
1793
+ },
1794
+ type
1795
+ };
1796
+ } else {
1797
+ const resolvedOptions = resolveFilterOptions(column, options, reuseCell);
1798
+ generatedFilter = {
1799
+ resetValue: type === "multiple" ? [] : "",
1800
+ showConfirmAndReset: true,
1801
+ ...filterOptions,
1802
+ list: resolvedOptions,
1803
+ props: {
1804
+ ...filterProps,
1805
+ options: resolvedOptions,
1806
+ type
1807
+ },
1808
+ component: QdServiceTableFilterItem,
1809
+ ...type === "multiple" ? {
1810
+ confirmDisabled: (value) => value === null
1811
+ } : {},
1812
+ ...!options && reuseCell ? {
1813
+ renderFilterValue: (_h, {
1814
+ value
1815
+ }) => {
1816
+ const values = Array.isArray(value) ? value : [value];
1817
+ return values.map((item, index) => {
1818
+ const option = resolvedOptions.find((option2) => option2.value === item);
1819
+ const content = option?.render?.() ?? option?.label ?? String(item);
1820
+ return [index ? "," : null, h("span", {
1821
+ class: "qd-service-table-filter-item__cell",
1822
+ inert: true
1823
+ }, [content])];
1824
+ });
1825
+ }
1826
+ } : {}
1827
+ };
1828
+ }
1829
+ const resolvedFilter = {
1830
+ ...generatedFilter,
1831
+ ...filter,
1832
+ props: {
1833
+ ...generatedFilter.props,
1834
+ ...filter?.props
1835
+ }
1836
+ };
1837
+ if (resolvedFilter.component === QdServiceTableFilterItem) {
1838
+ resolvedFilter.props = {
1839
+ ...resolvedFilter.props,
1840
+ showConfirmAndReset: resolvedFilter.showConfirmAndReset !== false
1841
+ };
1842
+ }
1843
+ return resolvedFilter;
1844
+ }
1845
+ function wrapColumns(columns) {
1658
1846
  return columns.map((column) => {
1659
1847
  const {
1660
1848
  children,
1849
+ filter,
1850
+ filterItem,
1661
1851
  formItem,
1662
1852
  ...tableColumn
1663
1853
  } = column;
1664
1854
  const reColumn = {
1665
1855
  ...tableColumn,
1856
+ ...filterItem ? {
1857
+ filter: resolveColumnFilter(column, filterItem, filter)
1858
+ } : {
1859
+ filter
1860
+ },
1666
1861
  ...formItem ? {
1667
1862
  formItem
1668
1863
  } : {},
1669
1864
  ...children ? {
1670
- children: wrapFormItemColumns(children)
1865
+ children: wrapColumns(children)
1671
1866
  } : {}
1672
1867
  };
1673
1868
  const columnClassName = reColumn.className === void 0 ? [] : Array.isArray(reColumn.className) ? reColumn.className : [reColumn.className];
@@ -2120,7 +2315,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
2120
2315
  "on-sort-change": reOnSortChange,
2121
2316
  columns: autoWidthColumns.value,
2122
2317
  loading: tableLoad.value,
2123
- data: unref(data),
2318
+ data: displayData.value,
2124
2319
  pagination: rePagination.value
2125
2320
  }), createSlots({
2126
2321
  empty: withCtx(() => [createVNode(unref(Empty), mergeProps({
@@ -1,5 +1,6 @@
1
1
  import type { ServicePageParams, ServicePageRes, ServicePagination, ServicePaginationOptions, useServicePagination } from 'qidian-shared';
2
- import type { BaseTableCellParams, EnhancedTableInstanceFunctions, ErrorListObjectType, PrimaryTableInstanceFunctions, TableErrorListMap, TableRowData, TableRowValue, TableTreeNodeExpandOptions, TdEmptyProps, TdEnhancedTableProps, TNode } from 'tdesign-vue-next';
2
+ import type { BaseTableCellParams, EnhancedTableInstanceFunctions, ErrorListObjectType, OptionData, PrimaryTableInstanceFunctions, TableColumnFilter, TableErrorListMap, TableRowData, TableRowValue, TableTreeNodeExpandOptions, TdEmptyProps, TdEnhancedTableProps, TNode } from 'tdesign-vue-next';
3
+ import type { QdComponentConfig } from '../../config-renderer';
3
4
  import type { QdFormItemProps } from '../../form';
4
5
  type TDesignServiceTableCol<D extends TableRowData> = NonNullable<TdEnhancedTableProps<D>['columns']>[number];
5
6
  export type QdServiceTableScroll = NonNullable<TdEnhancedTableProps['scroll']> & {
@@ -9,8 +10,20 @@ export type QdServiceTableScroll = NonNullable<TdEnhancedTableProps['scroll']> &
9
10
  export interface QdServiceTableCol<D extends TableRowData = TableRowData> extends Omit<TDesignServiceTableCol<D>, 'children' | 'foot'> {
10
11
  children?: QdServiceTableCol<D>[];
11
12
  foot?: string | TNode<BaseTableCellParams<D>>;
13
+ filterItem?: true | QdServiceTableFilterItem;
12
14
  formItem?: QdServiceTableFormItem;
13
15
  }
16
+ export interface QdServiceTableFilterOption extends OptionData {
17
+ label: string;
18
+ value: NonNullable<OptionData['value']>;
19
+ count?: number;
20
+ }
21
+ export interface QdServiceTableFilterItem extends Omit<TableColumnFilter, 'component' | 'list' | 'type'> {
22
+ component?: QdComponentConfig;
23
+ options?: QdServiceTableFilterOption[];
24
+ reuseCell?: boolean;
25
+ type?: 'input' | 'single' | 'multiple';
26
+ }
14
27
  export type QdServiceTableFormItem = Omit<QdFormItemProps, 'name' | 'label' | 'context' | 'col' | 'row' | 'labelWidth' | 'labelAlign'> & {
15
28
  lazy?: boolean;
16
29
  virtualValidateRender?: boolean;
@@ -350,6 +350,11 @@ declare const _default: {
350
350
  uploadText: string;
351
351
  inputText: string;
352
352
  };
353
+ table: {
354
+ filterItemInputPlaceholder: string;
355
+ filterItemSearchPlaceholder: string;
356
+ filterItemAllText: string;
357
+ };
353
358
  columnsController: {
354
359
  titleText: string;
355
360
  columnNameText: string;
@@ -92,6 +92,11 @@ const enUS = merge(enUS$1, {
92
92
  uploadText: "Please upload",
93
93
  inputText: "Please enter"
94
94
  },
95
+ table: {
96
+ filterItemInputPlaceholder: "Enter keywords to filter",
97
+ filterItemSearchPlaceholder: "Search; separate keywords with spaces",
98
+ filterItemAllText: "All"
99
+ },
95
100
  columnsController: {
96
101
  titleText: "Column Configuration",
97
102
  columnNameText: "Column Name",
@@ -350,6 +350,11 @@ declare const _default: {
350
350
  uploadText: string;
351
351
  inputText: string;
352
352
  };
353
+ table: {
354
+ filterItemInputPlaceholder: string;
355
+ filterItemSearchPlaceholder: string;
356
+ filterItemAllText: string;
357
+ };
353
358
  columnsController: {
354
359
  titleText: string;
355
360
  columnNameText: string;
@@ -89,6 +89,11 @@ const zhCN = merge(zhCN$1, {
89
89
  uploadText: "请上传",
90
90
  inputText: "请输入"
91
91
  },
92
+ table: {
93
+ filterItemInputPlaceholder: "输入关键词过滤",
94
+ filterItemSearchPlaceholder: "搜索,支持用空格分隔多个关键词",
95
+ filterItemAllText: "全部"
96
+ },
92
97
  columnsController: {
93
98
  titleText: "列配置",
94
99
  columnNameText: "列名",
@@ -350,6 +350,11 @@ declare const _default: {
350
350
  uploadText: string;
351
351
  inputText: string;
352
352
  };
353
+ table: {
354
+ filterItemInputPlaceholder: string;
355
+ filterItemSearchPlaceholder: string;
356
+ filterItemAllText: string;
357
+ };
353
358
  columnsController: {
354
359
  titleText: string;
355
360
  columnNameText: string;
@@ -89,6 +89,11 @@ const zhTW = merge(zhTW$1, {
89
89
  uploadText: "請上傳",
90
90
  inputText: "請輸入"
91
91
  },
92
+ table: {
93
+ filterItemInputPlaceholder: "輸入關鍵詞過濾",
94
+ filterItemSearchPlaceholder: "搜尋,支援用空格分隔多個關鍵詞",
95
+ filterItemAllText: "全部"
96
+ },
92
97
  columnsController: {
93
98
  titleText: "列配置",
94
99
  columnNameText: "列名",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qidian-vue-ui",
3
- "version": "2.0.33",
3
+ "version": "2.0.34",
4
4
  "description": "基于 TDesign 的 QiDian Vue UI 组件库",
5
5
  "author": "qidian",
6
6
  "license": "MIT",