cd-vue-filter 2.2.5 → 2.2.7

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.
@@ -0,0 +1,60 @@
1
+ export type FieldType = 'number' | 'money' | 'text' | 'date' | 'time' | 'select' | 'selectProvince' | 'basedata' | 'billdata';
2
+ export interface FieldOption {
3
+ key: string;
4
+ label: string;
5
+ value: string;
6
+ type: FieldType;
7
+ options?: {
8
+ key: string;
9
+ label: string;
10
+ value: string;
11
+ }[];
12
+ }
13
+ export interface FilterCondition {
14
+ field: string;
15
+ operator: string;
16
+ value: any;
17
+ }
18
+ export interface FilterComponentProps {
19
+ fieldOptions: FieldOption[];
20
+ filterCondition: FilterCondition;
21
+ selectOptions?: Record<string, any[]>;
22
+ }
23
+ export interface FilterDialogProps {
24
+ visible: boolean;
25
+ fieldOptions: FieldOption[];
26
+ initialFilterCards?: FilterCard[];
27
+ initialType1?: string;
28
+ }
29
+ export interface FilterCard {
30
+ id: number;
31
+ connector: 'and' | 'or';
32
+ conditions: FilterCondition[];
33
+ }
34
+ export interface OperatorOption {
35
+ key: string;
36
+ label: string;
37
+ value: string;
38
+ }
39
+ export interface CascaderOption {
40
+ label: string;
41
+ value: string;
42
+ children?: CascaderOption[];
43
+ }
44
+ export interface ProvinceData {
45
+ name: string;
46
+ city: CityData[];
47
+ }
48
+ export interface CityData {
49
+ name: string;
50
+ area: string[];
51
+ }
52
+ export interface ColorFilterRule {
53
+ field: string;
54
+ operator: string;
55
+ value: any;
56
+ backgroundColor: string;
57
+ isBold: boolean;
58
+ applyTo: 'cell' | 'row' | 'column';
59
+ }
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,gBAAgB,GAAG,UAAU,GAAG,UAAU,CAAC;AAG9H,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3D;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;CACZ;AAGD,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;CACvC;AAGD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,kBAAkB,CAAC,EAAE,UAAU,EAAE,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CAC7B;AAGD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAGD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;CACpC"}
@@ -0,0 +1,3 @@
1
+ import { ProvinceData } from '../types';
2
+ export declare const provinces: ProvinceData[];
3
+ //# sourceMappingURL=province.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"province.d.ts","sourceRoot":"","sources":["../../src/utils/province.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C,eAAO,MAAM,SAAS,EAAE,YAAY,EA03KjC,CAAA"}
package/package.json CHANGED
@@ -1,13 +1,20 @@
1
1
  {
2
2
  "name": "cd-vue-filter",
3
- "version": "2.2.5",
3
+ "version": "2.2.7",
4
4
  "type": "module",
5
5
  "description": "一个功能强大的 Vue 3 过滤器组件,支持多种字段类型和操作符",
6
- "main": "src/index.ts",
7
- "module": "src/index.ts",
8
- "types": "src/index.ts",
6
+ "main": "./dist/cd-vue-filter.umd.cjs",
7
+ "module": "./dist/cd-vue-filter.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/cd-vue-filter.js",
12
+ "require": "./dist/cd-vue-filter.umd.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
9
16
  "files": [
10
- "src"
17
+ "dist"
11
18
  ],
12
19
  "keywords": [
13
20
  "vue",
@@ -20,21 +27,24 @@
20
27
  "author": "CD",
21
28
  "license": "MIT",
22
29
  "peerDependencies": {
23
- "tdesign-vue-next": "^1.0.0",
24
- "vue": "^3.0.0",
25
30
  "cd-personselector": "^1.1.0",
26
- "cd-usercard": "^2.3.0"
31
+ "cd-usercard": "^2.3.0",
32
+ "remixicon": "^4.0.0",
33
+ "tdesign-vue-next": "^1.0.0",
34
+ "vue": "^3.0.0"
27
35
  },
28
36
  "devDependencies": {
29
37
  "@vitejs/plugin-vue": "^5.2.4",
38
+ "cd-personselector": "1.1.0",
39
+ "cd-usercard": "^2.3.0",
40
+ "remixicon": "^4.0.0",
30
41
  "sass-embedded": "^1.97.1",
31
42
  "tslib": "^2.6.0",
32
43
  "typescript": "^5.0.0",
33
44
  "vite": "^5.4.21",
45
+ "vite-plugin-dts": "^4.5.4",
34
46
  "vue": "^3.3.0",
35
- "vue-tsc": "^2.2.12",
36
- "cd-personselector": "1.1.0",
37
- "cd-usercard": "^2.3.0"
47
+ "vue-tsc": "^2.2.12"
38
48
  },
39
49
  "repository": {
40
50
  "type": "git",
@@ -49,7 +59,8 @@
49
59
  },
50
60
  "scripts": {
51
61
  "dev": "vite",
52
- "build": "vue-tsc --noEmit && vite build",
62
+ "build": "vite build",
63
+ "type-check": "vue-tsc --noEmit",
53
64
  "preview": "vite preview"
54
65
  }
55
66
  }
@@ -1,359 +0,0 @@
1
- <!-- 过滤器组件 -->
2
- <template>
3
- <div class="filter-component" >
4
- <t-select
5
- v-model="props.filterCondition.field"
6
- placeholder="请选择字段"
7
- :size="props.size"
8
- style="min-width: 80px; max-width: 110px;"
9
- @change="handleFieldChange"
10
- clearable
11
- filterable
12
- >
13
- <t-option
14
- v-for="option in props.fieldOptions"
15
- :key="option.key"
16
- :label="option.key"
17
- :value="option.value"
18
- />
19
- </t-select>
20
- <t-select
21
- v-model="props.filterCondition.operator"
22
- placeholder="请选择条件"
23
- :size="props.size"
24
- style="width: 80px;"
25
- :clearable="false"
26
- @change="handleOperatorChange"
27
- >
28
- <t-option
29
- v-for="option in operatorOptions"
30
- :key="option.key"
31
- :label="option.label"
32
- :value="option.value"
33
- />
34
- </t-select>
35
- <!-- 动态输入框 -->
36
- <template v-if="getFieldType(props.filterCondition.field) === 'number'">
37
- <t-input
38
- type="number"
39
- v-model="props.filterCondition.value"
40
- placeholder="请输入数字"
41
- :size="props.size"
42
- style="min-width: 80px; max-width: 120px;"
43
- @change="handleValueChange"
44
- clearable
45
- />
46
- </template>
47
- <template v-else-if="getFieldType(props.filterCondition.field) === 'money'">
48
- <t-input
49
- type="number"
50
- v-model="props.filterCondition.value"
51
- placeholder="请输入金额"
52
- :size="props.size"
53
- style="min-width: 80px; max-width: 120px;"
54
- @change="handleValueChange"
55
- clearable
56
- />
57
- </template>
58
- <template v-else-if="getFieldType(props.filterCondition.field) === 'date'">
59
- <t-date-picker
60
- v-if="!isPresetDateOperator(props.filterCondition.operator)"
61
- v-model="props.filterCondition.value"
62
- placeholder="请选择日期"
63
- :size="props.size"
64
- style="min-width: 80px; max-width: 120px;"
65
- @change="handleValueChange"
66
- clearable
67
- />
68
- <t-input
69
- v-else
70
- :value="operatorOptions.find(op => op.value === props.filterCondition.operator)?.label"
71
- disabled
72
- :size="props.size"
73
- style="min-width: 80px; max-width: 120px;"
74
- />
75
- </template>
76
- <template v-else-if="getFieldType(props.filterCondition.field) === 'time'">
77
- <t-date-picker
78
- v-model="props.filterCondition.value"
79
- placeholder="请选择日期时间"
80
- :size="props.size"
81
- style="min-width: 80px; max-width: 120px;"
82
- enable-time-picker
83
- format="YYYY-MM-DD HH:mm:ss"
84
- @change="handleValueChange"
85
- clearable
86
- />
87
- </template>
88
- <template v-else-if="getFieldType(props.filterCondition.field) === 'select'">
89
- <t-select
90
- v-model="props.filterCondition.value"
91
- :options="getSelectOptions(props.filterCondition.field)"
92
- placeholder="请选择"
93
- :size="props.size"
94
- style="min-width: 80px; max-width: 120px;"
95
- @change="handleValueChange"
96
- clearable
97
- />
98
- </template>
99
- <template v-else-if="getFieldType(props.filterCondition.field) === 'selectProvince'">
100
- <t-cascader
101
- v-model="props.filterCondition.value"
102
- :options="cascaderOptions"
103
- placeholder="请选择地区"
104
- :size="props.size"
105
- style="min-width: 80px; max-width: 120px;"
106
- clearable
107
- :loading="false"
108
- :checkStrictly="true"
109
- @change="handleValueChange"
110
- />
111
- </template>
112
- <template v-else>
113
- <t-input
114
- v-model="props.filterCondition.value"
115
- placeholder="请输入关键字"
116
- :size="props.size"
117
- style="min-width: 80px; max-width: 120px;"
118
- @change="handleValueChange"
119
- clearable
120
- />
121
- </template>
122
- </div>
123
- </template>
124
- <script setup lang="ts">
125
- import { ref, watch, computed } from 'vue';
126
- import { provinces } from '../utils/province';
127
- // 缓存处理后的省市区数据
128
- const municipalities = ['北京市', '上海市', '天津市', '重庆市','香港特别行政区','澳门特别行政区'];
129
- const cascaderOptions = computed(() => {
130
- return provinces.map(province => {
131
- // 如果是直辖市,直接返回省级选项,不包含下级
132
- if (municipalities.includes(province.name)) {
133
- return {
134
- label: province.name,
135
- value: province.name,
136
- children:province.city[0].area.map(area2 => ({
137
- label: area2,
138
- value: `${province.name}/${area2}`, // 使用省份名称作为前缀
139
- }))
140
- };
141
- }
142
- // 非直辖市,保持原有的三级结构
143
- return {
144
- label: province.name,
145
- value: province.name,
146
- children: province.city.map(city => ({
147
- label: city.name,
148
- value: `${province.name}/${city.name}`, // 使用省份名称作为前缀
149
- children: city.area.map(area => ({
150
- label: area,
151
- value: `${province.name}/${city.name}/${area}` // 使用省份和城市名称作为前缀
152
- }))
153
- }))
154
- };
155
- });
156
- });
157
- // 判断是否为预设日期操作符
158
- const isPresetDateOperator = (operator: string): boolean => {
159
- const presetOperators = [
160
- 'today', 'yesterday', 'tomorrow',
161
- 'this_week', 'last_week', 'next_week',
162
- 'this_month', 'last_month', 'next_month',
163
- 'this_year', 'last_year', 'next_year'
164
- ];
165
- return presetOperators.includes(operator);
166
- };
167
- // 字段类型定义
168
- type FieldType = 'number' | 'money' | 'text' | 'date' | 'time' | 'select' | 'selectProvince' | 'basedata' | 'billdata';
169
- // 字段选项接口
170
- interface FieldOption {
171
- key: string;
172
- label: string;
173
- value: string;
174
- type: FieldType;
175
- options?: { key: string; label: string; value: string }[];
176
- }
177
- // 过滤条件接口
178
- interface FilterCondition {
179
- field: string;
180
- operator: string;
181
- value: any;
182
- }
183
- // 定义组件属性
184
- interface Props {
185
- fieldOptions: FieldOption[];
186
- filterCondition: FilterCondition;
187
- selectOptions?: Record<string, any[]>; // 添加可选的selectOptions属性
188
- size?: string;
189
- }
190
- // 获取选择框的选项
191
- // 获取选择框的选项
192
- const getSelectOptions = (field: string) => {
193
- // 如果父组件传递了对应字段的选项,则使用父组件传递的选项
194
- if (props.selectOptions && (props.selectOptions as any)[field]) {
195
- return (props.selectOptions as any)[field];
196
- }
197
- // 尝试从父组件传来的字段列表中查找匹配的字段
198
- if (props.selectOptions && Array.isArray(props.selectOptions)){
199
- const fieldFromParent = (props.selectOptions as any[]).find((opt: any) =>
200
- opt.columnName === field
201
- );
202
- if (fieldFromParent && fieldFromParent.value) {
203
- return sortDepartments(fieldFromParent.value.map((item: any) => ({
204
- label: item,
205
- value: item
206
- })));
207
- }
208
- }
209
- // 如果都没有,返回空数组
210
- return [];
211
- };
212
- function sortDepartments(departments: any[]) {
213
- return [...departments].sort((a: any, b: any) => a.value.localeCompare(b.value, 'zh-CN'));
214
- }
215
- const props = defineProps<Props>();
216
- // Emits 定义
217
- const emit = defineEmits<{
218
- (e: 'search', condition: FilterCondition): void;
219
- }>();
220
- // 使用传入的筛选条件
221
- const filterCondition = ref<FilterCondition>({
222
- field: props.filterCondition?.field || '',
223
- operator: props.filterCondition?.operator || 'eq',
224
- value: props.filterCondition?.value || null
225
- });
226
- // 监听筛选条件变化
227
- watch(() => props.filterCondition, (newVal) => {
228
- if (newVal) {
229
- filterCondition.value = { ...newVal };
230
- }
231
- }, { deep: true });
232
- // 获取字段类型
233
- const getFieldType = (field: string) => {
234
- const option = props.fieldOptions.find(opt => opt.value === field);
235
- return option ? option.type : 'text';
236
- };
237
- // 处理值变化
238
- const handleValueChange = () => {
239
- // 将当前筛选条件直接发送给父组件
240
- emit('search', { ...filterCondition.value });
241
- };
242
- // 处理操作符变化
243
- const handleOperatorChange = () => {
244
- // 将当前筛选条件直接发送给父组件
245
- emit('search', { ...filterCondition.value });
246
- };
247
- // 操作符选项
248
- const operatorOptions = computed(() => {
249
- const field = props.filterCondition.field;
250
- const fieldType = props.fieldOptions.find(opt => opt.value === field)?.type || 'text';
251
- switch (fieldType) {
252
- case 'number':
253
- return [
254
- { key: 'eq', label: '等于', value: 'eq' },
255
- { key: 'ne', label: '不等于', value: 'ne' },
256
- { key: 'gt', label: '大于', value: 'gt' },
257
- { key: 'gte', label: '大于等于', value: 'gte' },
258
- { key: 'lt', label: '小于', value: 'lt' },
259
- { key: 'lte', label: '小于等于', value: 'lte' }
260
- ];
261
- case 'date':
262
- return [
263
- { key: 'eq', label: '等于', value: 'eq' },
264
- { key: 'ne', label: '不等于', value: 'ne' },
265
- { key: 'gt', label: '在此之后', value: 'gt' },
266
- { key: 'gte', label: '在此之后(含)', value: 'gte' },
267
- { key: 'lt', label: '在此之前', value: 'lt' },
268
- { key: 'lte', label: '在此之前(含)', value: 'lte' },
269
- { key: 'today', label: '今天', value: 'today' },
270
- { key: 'yesterday', label: '昨天', value: 'yesterday' },
271
- { key: 'tomorrow', label: '明天', value: 'tomorrow' },
272
- { key: 'this_week', label: '本周', value: 'this_week' },
273
- { key: 'last_week', label: '上周', value: 'last_week' },
274
- { key: 'next_week', label: '下周', value: 'next_week' },
275
- { key: 'this_month', label: '本月', value: 'this_month' },
276
- { key: 'last_month', label: '上月', value: 'last_month' },
277
- { key: 'next_month', label: '下月', value: 'next_month' },
278
- { key: 'this_year', label: '今年', value: 'this_year' },
279
- { key: 'last_year', label: '去年', value: 'last_year' },
280
- { key: 'next_year', label: '明年', value: 'next_year' }
281
- ];
282
- case 'time':
283
- return [
284
- { key: 'eq', label: '等于', value: 'eq' },
285
- { key: 'ne', label: '不等于', value: 'ne' },
286
- { key: 'gt', label: '在此之后', value: 'gt' },
287
- { key: 'gte', label: '在此之后(含)', value: 'gte' },
288
- { key: 'lt', label: '在此之前', value: 'lt' },
289
- { key: 'lte', label: '在此之前(含)', value: 'lte' }
290
- ];
291
- case 'select':
292
- return [
293
- { key: 'eq', label: '等于', value: 'eq' },
294
- { key: 'ne', label: '不等于', value: 'ne' }
295
- ];
296
- case 'selectProvince':
297
- return [
298
- { key: 'eq', label: '等于', value: 'eq' },
299
- { key: 'ne', label: '不等于', value: 'ne' },
300
- { key: 'contains', label: '包含', value: 'contains' },
301
- { key: 'not_contains', label: '不包含', value: 'not_contains' },
302
- { key: 'one_of', label: '等于其中之一', value: 'one_of' },
303
- ];
304
- case 'basedata':
305
- return [
306
- { key: 'eq', label: '等于', value: 'eq' },
307
- { key: 'ne', label: '不等于', value: 'ne' },
308
- { key: 'contains', label: '包含', value: 'contains' },
309
- { key: 'not_contains', label: '不包含', value: 'not_contains' },
310
- { key: 'one_of', label: '等于其中之一', value: 'one_of' },
311
- ];
312
- case 'billdata':
313
- return [
314
- { key: 'eq', label: '等于', value: 'eq' },
315
- { key: 'ne', label: '不等于', value: 'ne' },
316
- { key: 'contains', label: '包含', value: 'contains' },
317
- { key: 'not_contains', label: '不包含', value: 'not_contains' },
318
- { key: 'one_of', label: '等于其中之一', value: 'one_of' },
319
- ];
320
- default:
321
- return [
322
- { key: 'contains', label: '包含', value: 'contains' },
323
- { key: 'eq', label: '等于', value: 'eq' },
324
- { key: 'ne', label: '不等于', value: 'ne' },
325
- { key: 'starts_with', label: '开头是', value: 'starts_with' },
326
- { key: 'ends_with', label: '结尾是', value: 'ends_with' }
327
- ];
328
- }
329
- });
330
- // 处理字段变化
331
- const handleFieldChange = () => {
332
- };
333
- // 监听字段变化
334
- watch(() => props.filterCondition.field, (oldField,newField) => {
335
- if(oldField && newField){
336
- props.filterCondition.operator = 'eq';
337
- props.filterCondition.value = null;
338
- }
339
- });
340
- </script>
341
- <style scoped>
342
- .filter-component {
343
- display: flex;
344
- align-items: center;
345
- gap: 5px;
346
- flex: 1;
347
- border-radius: var(--td-radius-medium);
348
- }
349
- .filter-component :deep(.t-button) {
350
- margin-left: 8px;
351
- }
352
- .filter-component :deep(.t-input),
353
- .filter-component :deep(.t-select),
354
- .filter-component :deep(.t-date-picker),
355
- .filter-component :deep(.t-time-picker),
356
- .filter-component :deep(.t-cascader) {
357
- flex-shrink: 0;
358
- }
359
- </style>