ol-base-components 3.1.4 → 3.2.0

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,867 @@
1
+ <template>
2
+ <el-dialog
3
+ title="搜索条件配置"
4
+ :visible.sync="dialogVisible"
5
+ width="60%"
6
+ :close-on-click-modal="false"
7
+ @close="handleClose"
8
+ >
9
+ <div class="search-config-container">
10
+ <div class="config-header">
11
+ <el-button
12
+ v-if="customs && customs.length > 0"
13
+ type="success"
14
+ size="small"
15
+ @click="customsDialogVisible = true"
16
+ >
17
+ <i class="el-icon-plus" />
18
+ 从预设添加
19
+ </el-button>
20
+ </div>
21
+
22
+ <el-table
23
+ ref="configTable"
24
+ :data="configList"
25
+ border
26
+ stripe
27
+ style="width: 100%; margin-top: 10px"
28
+ :row-class-name="tableRowClassName"
29
+ row-key="value"
30
+ :tree-props="{ children: '' }"
31
+ >
32
+ <el-table-column label="排序" width="80" align="center">
33
+ <template slot-scope="scope">
34
+ <i class="el-icon-rank sort-handle" style="cursor: move; font-size: 18px" />
35
+ </template>
36
+ </el-table-column>
37
+
38
+ <el-table-column label="字段名称" prop="label" align="center">
39
+ <template slot-scope="scope">
40
+ <el-input
41
+ v-model="scope.row.label"
42
+ size="small"
43
+ placeholder="请输入字段名称"
44
+ disabled
45
+ />
46
+ </template>
47
+ </el-table-column>
48
+
49
+ <el-table-column label="字段值" prop="value" align="center">
50
+ <template slot-scope="scope">
51
+ <el-input v-model="scope.row.value" size="small" placeholder="请输入字段值" disabled />
52
+ </template>
53
+ </el-table-column>
54
+
55
+ <el-table-column label="输入类型" prop="inputType" width="130" align="center">
56
+ <template slot-scope="scope">
57
+ <el-select
58
+ v-model="scope.row.inputType"
59
+ size="small"
60
+ placeholder="请选择类型"
61
+ @change="handleTypeChange(scope.row)"
62
+ disabled
63
+ >
64
+ <el-option label="文本输入" value="text" />
65
+ <el-option label="数字输入" value="number" />
66
+ <el-option label="下拉选择" value="select" />
67
+ <el-option label="日期选择" value="picker" />
68
+ </el-select>
69
+ </template>
70
+ </el-table-column>
71
+
72
+ <el-table-column label="日期类型" width="150" align="center">
73
+ <template slot-scope="scope">
74
+ <el-select
75
+ v-if="scope.row.inputType === 'picker'"
76
+ v-model="scope.row.dateType"
77
+ size="small"
78
+ placeholder="请选择日期类型"
79
+ @change="handleDateTypeChange(scope.row)"
80
+ >
81
+ <el-option label="日期" value="date" />
82
+ <el-option label="日期时间" value="datetime" />
83
+ <el-option label="日期范围" value="daterange" />
84
+ <el-option label="日期时间范围" value="datetimerange" />
85
+ <el-option label="月份" value="month" />
86
+ <el-option label="月份范围" value="monthrange" />
87
+ <el-option label="年份" value="year" />
88
+ </el-select>
89
+ <div v-else class="gray-text">-</div>
90
+ </template>
91
+ </el-table-column>
92
+
93
+ <el-table-column label="比较方式" width="130" align="center">
94
+ <template slot-scope="scope">
95
+ <el-select v-model="scope.row.compare" size="small" placeholder="请选择比较方式">
96
+ <el-option label="范围" value="range" />
97
+ <el-option label="包含于" value="in" />
98
+ <el-option label="不包含于" value="not in" />
99
+ <el-option label="等于" value="eq" />
100
+ <el-option label="不等于" value="ne" />
101
+ <el-option label="大于" value="gt" />
102
+ <el-option label="大于等于" value="ge" />
103
+ <el-option label="小于" value="lt" />
104
+ <el-option label="小于等于" value="le" />
105
+ <el-option label="包含" value="contains" />
106
+ <el-option label="以...开始" value="startswith" />
107
+ <el-option label="以...结束" value="endswith" />
108
+ </el-select>
109
+ </template>
110
+ </el-table-column>
111
+
112
+ <el-table-column label="配置" width="150" align="center">
113
+ <template slot-scope="scope">
114
+ <div v-if="scope.row.inputType === 'select'">
115
+ <el-button type="text" size="small" @click="handleConfigOptions(scope.$index)">
116
+ 配置选项
117
+ </el-button>
118
+ </div>
119
+ <div v-else class="gray-text">无需配置</div>
120
+ </template>
121
+ </el-table-column>
122
+
123
+ <el-table-column label="操作" width="100" align="center">
124
+ <template slot-scope="scope">
125
+ <el-button
126
+ type="text"
127
+ icon="el-icon-delete"
128
+ style="color: #f56c6c"
129
+ @click="handleDelete(scope.$index)"
130
+ >
131
+ 删除
132
+ </el-button>
133
+ </template>
134
+ </el-table-column>
135
+ </el-table>
136
+ </div>
137
+
138
+ <div class="dialog-footer">
139
+ <slot name="footer">
140
+ <el-button @click="handleClose">取消</el-button>
141
+ <el-button type="primary" @click="handleSave">确定</el-button>
142
+ </slot>
143
+ </div>
144
+
145
+ <el-dialog title="配置选项" :visible.sync="optionsDialogVisible" width="700px" append-to-body>
146
+ <el-form :model="currentOptionConfig" label-width="100px" size="small">
147
+ <el-form-item label="数据来源">
148
+ <el-radio-group v-model="currentOptionConfig.sourceType">
149
+ <el-radio label="manual">手动配置</el-radio>
150
+ <el-radio label="dict">本地字典</el-radio>
151
+ <el-radio label="api">接口获取</el-radio>
152
+ </el-radio-group>
153
+ </el-form-item>
154
+
155
+ <el-form-item v-if="currentOptionConfig.sourceType === 'dict'" label="字典Key">
156
+ <el-select
157
+ v-model="currentOptionConfig.dictKey"
158
+ filterable
159
+ remote
160
+ reserve-keyword
161
+ placeholder="请输入字典Key,如:orderTypeEnum"
162
+ :remote-method="remoteDictQuery"
163
+ :loading="dictLoading"
164
+ style="width: 100%"
165
+ @change="handleDictKeyChange"
166
+ >
167
+ <el-option
168
+ v-for="dict in allDictList"
169
+ :key="dict.key"
170
+ :label="dict.label"
171
+ :value="dict.key"
172
+ />
173
+ </el-select>
174
+ </el-form-item>
175
+
176
+ <el-form-item v-if="currentOptionConfig.sourceType === 'api'" label="接口地址">
177
+ <el-input
178
+ v-model="currentOptionConfig.apiUrl"
179
+ placeholder="请输入接口地址,如:/api/dict/list"
180
+ />
181
+ </el-form-item>
182
+
183
+ <el-form-item v-if="currentOptionConfig.sourceType === 'api'" label="请求方式">
184
+ <el-select v-model="currentOptionConfig.method" placeholder="请选择请求方式">
185
+ <el-option label="GET" value="get" />
186
+ <el-option label="POST" value="post" />
187
+ </el-select>
188
+ </el-form-item>
189
+
190
+ <el-form-item v-if="currentOptionConfig.sourceType === 'api'" label="文本字段">
191
+ <el-input v-model="currentOptionConfig.labelField" placeholder="如:name" />
192
+ </el-form-item>
193
+
194
+ <el-form-item v-if="currentOptionConfig.sourceType === 'api'" label="值字段">
195
+ <el-input v-model="currentOptionConfig.valueField" placeholder="如:id" />
196
+ </el-form-item>
197
+
198
+ <el-form-item v-if="currentOptionConfig.sourceType === 'manual'" label="选项列表">
199
+ <div class="options-config">
200
+ <div
201
+ v-for="(option, index) in currentOptionConfig.options"
202
+ :key="index"
203
+ class="option-item"
204
+ >
205
+ <el-input
206
+ v-model="option.value"
207
+ size="small"
208
+ placeholder="文本"
209
+ style="width: 150px"
210
+ />
211
+ <el-input
212
+ v-model="option.key"
213
+ size="small"
214
+ placeholder="值"
215
+ style="width: 150px; margin-left: 10px"
216
+ />
217
+ <el-button
218
+ type="text"
219
+ icon="el-icon-delete"
220
+ style="color: #f56c6c; margin-left: 10px"
221
+ @click="handleDeleteOption(index)"
222
+ />
223
+ </div>
224
+ <el-button
225
+ type="dashed"
226
+ size="small"
227
+ icon="el-icon-plus"
228
+ style="width: 100%; margin-top: 10px"
229
+ @click="handleAddOption"
230
+ >
231
+ 添加选项
232
+ </el-button>
233
+ </div>
234
+ </el-form-item>
235
+
236
+ <el-form-item v-if="currentOptionConfig.sourceType === 'dict'" label="预览">
237
+ <div class="preview-box">
238
+ <el-tag v-for="(item, index) in previewOptions" :key="index" style="margin: 5px">
239
+ {{ item.value }} ({{ item.key }})
240
+ </el-tag>
241
+ <el-empty
242
+ v-if="!previewOptions || previewOptions.length === 0"
243
+ description="暂无数据"
244
+ :image-size="60"
245
+ />
246
+ </div>
247
+ </el-form-item>
248
+ </el-form>
249
+ <slot name="footer">
250
+ <el-button @click="optionsDialogVisible = false">取消</el-button>
251
+ <el-button type="primary" @click="handleSaveOptions">确定</el-button>
252
+ </slot>
253
+ </el-dialog>
254
+
255
+ <el-dialog
256
+ title="从预设添加条件"
257
+ :visible.sync="customsDialogVisible"
258
+ width="600px"
259
+ append-to-body
260
+ >
261
+ <el-table :data="availableCustoms" border stripe style="width: 100%">
262
+ <el-table-column label="字段名称" prop="name" align="center" />
263
+ <el-table-column label="字段值" prop="key" align="center" />
264
+ <el-table-column label="数据类型" width="120" align="center">
265
+ <template slot-scope="scope">
266
+ <el-tag v-if="scope.row.keyType === 1" type="info">字符串</el-tag>
267
+ <el-tag v-else-if="scope.row.keyType === 2" type="warning">数字</el-tag>
268
+ <el-tag v-else-if="scope.row.keyType === 3" type="success">枚举</el-tag>
269
+ <el-tag v-else-if="scope.row.keyType === 4" type="primary">日期</el-tag>
270
+ </template>
271
+ </el-table-column>
272
+ <el-table-column label="操作" width="100" align="center">
273
+ <template slot-scope="scope">
274
+ <el-button type="text" size="small" @click="handleSelectCustom(scope.row)">
275
+ 添加
276
+ </el-button>
277
+ </template>
278
+ </el-table-column>
279
+ </el-table>
280
+ <div slot="footer" style="text-align: right">
281
+ <el-button @click="customsDialogVisible = false">取消</el-button>
282
+ </div>
283
+ </el-dialog>
284
+ </el-dialog>
285
+ </template>
286
+
287
+ <script>
288
+ import Sortable from "sortablejs";
289
+
290
+ // interface OptionItem {
291
+ // key: string;
292
+ // value: string;
293
+ // }
294
+
295
+ // interface OptionSource {
296
+ // sourceType: "manual" | "dict" | "api";
297
+ // dictKey?: string;
298
+ // apiUrl?: string;
299
+ // valueField?: string;
300
+ // labelField?: string;
301
+ // options?: OptionItem[];
302
+ // }
303
+
304
+ // interface TableSearchItem {
305
+ // label: string;
306
+ // value: string;
307
+ // inputType: "text" | "number" | "select";
308
+ // children?: OptionItem[];
309
+ // optionSource?: OptionSource;
310
+ // }
311
+
312
+ // interface DictItem {
313
+ // key: string;
314
+ // label: string;
315
+ // }
316
+
317
+ // interface WmsDictItem {
318
+ // desc?: string;
319
+ // enums?: Array<{ key: string; value: string }>;
320
+ // }
321
+
322
+ // interface WmsData {
323
+ // SET_enumsSelect?: Record<string, WmsDictItem>;
324
+ // }
325
+
326
+ // interface CurrentOptionConfig {
327
+ // sourceType: "manual" | "dict" | "api";
328
+ // dictKey: string;
329
+ // apiUrl: string;
330
+ // valueField: string;
331
+ // labelField: string;
332
+ // options: OptionItem[];
333
+ // }
334
+
335
+ export default {
336
+ name: "SearchConfigDialog",
337
+ props: {
338
+ visible: {
339
+ type: Boolean,
340
+ default: false,
341
+ },
342
+ tableSearch: {
343
+ type: Array,
344
+ default: () => [],
345
+ },
346
+ // interface ICustoms {
347
+ // key: string;//键名
348
+ // name: string; //显示的名称
349
+ // keyType: number; //数据类型 1字符串 2数字 3枚举 4日期
350
+ // }
351
+ //后端返回的可选的查询入参
352
+ customs: {
353
+ type: Array,
354
+ default: () => [],
355
+ },
356
+ },
357
+ data() {
358
+ return {
359
+ dialogVisible: false,
360
+ configList: [],
361
+ optionsDialogVisible: false,
362
+ customsDialogVisible: false,
363
+ currentEditIndex: -1,
364
+ currentOptionConfig: {
365
+ sourceType: "manual",
366
+ dictKey: "",
367
+ apiUrl: "",
368
+ method: "get",
369
+ valueField: "id",
370
+ labelField: "name",
371
+ options: [],
372
+ },
373
+ previewOptions: [],
374
+ allDictList: [],
375
+ dictLoading: false,
376
+ dictQuery: "",
377
+ sortable: null,
378
+ };
379
+ },
380
+ computed: {
381
+ availableCustoms() {
382
+ const selectedKeys = this.configList.map(item => item.value);
383
+ return this.customs.filter(custom => !selectedKeys.includes(custom.key));
384
+ },
385
+ },
386
+ watch: {
387
+ visible: {
388
+ handler(newVal) {
389
+ this.dialogVisible = newVal;
390
+ if (newVal) {
391
+ this.configList = JSON.parse(JSON.stringify(this.tableSearch));
392
+ this.loadAllDictList();
393
+ this.$nextTick(() => {
394
+ this.initSortable();
395
+ });
396
+ }
397
+ },
398
+ immediate: true,
399
+ },
400
+ dialogVisible(newVal) {
401
+ this.$emit("update:visible", newVal);
402
+ if (!newVal) {
403
+ this.destroySortable();
404
+ }
405
+ },
406
+ },
407
+ methods: {
408
+ initSortable() {
409
+ if (this.sortable) {
410
+ this.sortable.destroy();
411
+ }
412
+
413
+ const table = this.$refs.configTable;
414
+ if (!table) return;
415
+
416
+ const tbody = table.$el.querySelector(".el-table__body-wrapper tbody");
417
+ if (!tbody) return;
418
+
419
+ this.sortable = Sortable.create(tbody, {
420
+ animation: 150,
421
+ handle: ".sort-handle",
422
+ ghostClass: "sortable-ghost",
423
+ dragClass: "sortable-drag",
424
+ onEnd: ({ newIndex, oldIndex }) => {
425
+ if (newIndex !== oldIndex) {
426
+ const movedItem = this.configList[oldIndex];
427
+ this.configList.splice(oldIndex, 1);
428
+ this.configList.splice(newIndex, 0, movedItem);
429
+ }
430
+ },
431
+ });
432
+ },
433
+ destroySortable() {
434
+ if (this.sortable) {
435
+ this.sortable.destroy();
436
+ this.sortable = null;
437
+ }
438
+ },
439
+ handleClose() {
440
+ this.dialogVisible = false;
441
+ },
442
+ async handleSave() {
443
+ for (const item of this.configList) {
444
+ if (item.inputType === "select" && item.optionSource) {
445
+ await this.loadItemOptionsForSave(item);
446
+ }
447
+ }
448
+ this.$emit("save", this.configList);
449
+ this.dialogVisible = false;
450
+ },
451
+ async loadItemOptionsForSave(item) {
452
+ if (!item.optionSource) return;
453
+
454
+ const { sourceType } = item.optionSource;
455
+
456
+ if (sourceType === "dict") {
457
+ await this.loadDictOptionsForSave(item);
458
+ }
459
+ // else if (sourceType === "api") {
460
+ // await this.loadApiOptionsForSave(item);
461
+ // }
462
+ },
463
+ async loadDictOptionsForSave(item) {
464
+ try {
465
+ const dictKey = item.optionSource.dictKey;
466
+ if (!dictKey) return;
467
+
468
+ const dictData = await this.getDictData(dictKey);
469
+ if (dictData && Array.isArray(dictData)) {
470
+ item.children = dictData.map(d => ({
471
+ key: d.key,
472
+ value: d.value,
473
+ }));
474
+ }
475
+ } catch (error) {
476
+ console.error("加载字典数据失败:", error);
477
+ }
478
+ },
479
+ // async loadApiOptionsForSave(item) {
480
+ // try {
481
+ // const apiUrl = item.optionSource.apiUrl;
482
+ // const method = item.optionSource.method || "get";
483
+ // if (!apiUrl) return;
484
+
485
+ // let response;
486
+ // if (method === "post") {
487
+ // response = await this.$http.post(apiUrl);
488
+ // } else {
489
+ // response = await this.$http.get(apiUrl);
490
+ // }
491
+
492
+ // if (response.data && Array.isArray(response.data)) {
493
+ // const { valueField, labelField } = item.optionSource;
494
+ // item.children = response.data.map(d => ({
495
+ // key: d[valueField],
496
+ // value: d[labelField],
497
+ // }));
498
+ // }
499
+ // } catch (error) {
500
+ // console.error("加载接口数据失败:", error);
501
+ // }
502
+ // },
503
+
504
+ handleDelete(index) {
505
+ this.$confirm("确定要删除该条件吗?", "提示", {
506
+ confirmButtonText: "确定",
507
+ cancelButtonText: "取消",
508
+ type: "warning",
509
+ }).then(() => {
510
+ this.configList.splice(index, 1);
511
+ });
512
+ },
513
+ handleTypeChange(row) {
514
+ if (row.inputType === "select" && !row.children) {
515
+ row.children = [];
516
+ } else if (row.inputType === "picker") {
517
+ if (!row.props) {
518
+ row.props = {};
519
+ }
520
+ this.updateDatePickerProps(row);
521
+ } else {
522
+ row.dateType = "";
523
+ }
524
+ },
525
+ handleDateTypeChange(row) {
526
+ if (!row.props) {
527
+ row.props = {};
528
+ }
529
+ this.updateDatePickerProps(row);
530
+ },
531
+ updateDatePickerProps(row) {
532
+ const dateType = row.dateType || "date";
533
+ const props = row.props || {};
534
+
535
+ switch (dateType) {
536
+ case "date":
537
+ props.type = "date";
538
+ props.placeholder = "选择日期";
539
+ props.valueFormat = "yyyy-MM-dd";
540
+ props.format = "yyyy/MM/dd";
541
+ break;
542
+ case "datetime":
543
+ props.type = "datetime";
544
+ props.placeholder = "选择日期时间";
545
+ props.valueFormat = "yyyy-MM-dd HH:mm:ss";
546
+ props.format = "yyyy/MM/dd HH:mm:ss";
547
+ break;
548
+ case "daterange":
549
+ props.type = "daterange";
550
+ props.startPlaceholder = "开始日期";
551
+ props.endPlaceholder = "结束日期";
552
+ props.placeholder = "选择日期范围";
553
+ props.valueFormat = "yyyy-MM-dd";
554
+ props.format = "yyyy/MM/dd";
555
+ break;
556
+ case "datetimerange":
557
+ props.type = "datetimerange";
558
+ props.startPlaceholder = "开始时间";
559
+ props.endPlaceholder = "结束时间";
560
+ props.placeholder = "选择时间范围";
561
+ props.valueFormat = "yyyy-MM-dd HH:mm:ss";
562
+ props.format = "yyyy/MM/dd HH:mm:ss";
563
+ props.defaultTime = ["00:00:00", "23:59:59"];
564
+ break;
565
+ case "month":
566
+ props.type = "month";
567
+ props.placeholder = "选择月份";
568
+ props.valueFormat = "yyyy-MM";
569
+ props.format = "yyyy年MM月";
570
+ break;
571
+ case "monthrange":
572
+ props.type = "monthrange";
573
+ props.startPlaceholder = "开始月份";
574
+ props.endPlaceholder = "结束月份";
575
+ props.placeholder = "选择月份范围";
576
+ props.valueFormat = "yyyy-MM";
577
+ props.format = "yyyy年MM月";
578
+ break;
579
+ case "year":
580
+ props.type = "year";
581
+ props.placeholder = "选择年份";
582
+ props.valueFormat = "yyyy";
583
+ props.format = "yyyy年";
584
+ break;
585
+ default:
586
+ props.type = "date";
587
+ props.placeholder = "选择日期";
588
+ props.valueFormat = "yyyy-MM-dd";
589
+ props.format = "yyyy/MM/dd";
590
+ }
591
+
592
+ row.props = props;
593
+ },
594
+ handleConfigOptions(index) {
595
+ this.currentEditIndex = index;
596
+ const currentConfig = this.configList[index];
597
+
598
+ const optionSource = currentConfig.optionSource || {};
599
+ this.currentOptionConfig = {
600
+ sourceType: optionSource.sourceType || "manual",
601
+ dictKey: optionSource.dictKey || "",
602
+ apiUrl: optionSource.apiUrl || "",
603
+ method: optionSource.method || "get",
604
+ valueField: optionSource.valueField || "id",
605
+ labelField: optionSource.labelField || "name",
606
+ options: [],
607
+ };
608
+
609
+ if (this.currentOptionConfig.sourceType === "manual") {
610
+ this.currentOptionConfig.options = JSON.parse(JSON.stringify(currentConfig.children || []));
611
+ }
612
+
613
+ this.optionsDialogVisible = true;
614
+
615
+ this.loadPreviewOptions();
616
+ },
617
+ handleAddOption() {
618
+ this.currentOptionConfig.options.push({
619
+ key: "",
620
+ value: "",
621
+ });
622
+ },
623
+ handleDeleteOption(index) {
624
+ this.currentOptionConfig.options.splice(index, 1);
625
+ },
626
+ handleSaveOptions() {
627
+ const config = this.configList[this.currentEditIndex];
628
+ const configDefault = {
629
+ sourceType: "",
630
+ dictKey: "",
631
+ apiUrl: "",
632
+ valueField: "id",
633
+ labelField: "name",
634
+ options: [],
635
+ };
636
+ if (this.currentOptionConfig.sourceType === "manual") {
637
+ const options = JSON.parse(JSON.stringify(this.currentOptionConfig.options));
638
+ config.children = options;
639
+ config.optionSource = { ...configDefault, sourceType: "manual", options };
640
+ } else if (this.currentOptionConfig.sourceType === "dict") {
641
+ config.optionSource = {
642
+ ...configDefault,
643
+ sourceType: "dict",
644
+ dictKey: this.currentOptionConfig.dictKey,
645
+ };
646
+ config.children = [];
647
+ } else if (this.currentOptionConfig.sourceType === "api") {
648
+ config.optionSource = {
649
+ ...configDefault,
650
+ sourceType: "api",
651
+ apiUrl: this.currentOptionConfig.apiUrl,
652
+ method: this.currentOptionConfig.method,
653
+ valueField: this.currentOptionConfig.valueField,
654
+ labelField: this.currentOptionConfig.labelField,
655
+ };
656
+ config.children = [];
657
+ }
658
+ this.optionsDialogVisible = false;
659
+ },
660
+ tableRowClassName({ row, rowIndex }) {
661
+ return `row-${rowIndex}`;
662
+ },
663
+ async loadPreviewOptions() {
664
+ this.previewOptions = [];
665
+
666
+ if (this.currentOptionConfig.sourceType === "dict") {
667
+ await this.loadDictOptions();
668
+ }
669
+ },
670
+ async loadDictOptions() {
671
+ try {
672
+ const dictKey = this.currentOptionConfig.dictKey;
673
+ if (!dictKey) return;
674
+
675
+ const dictData = await this.getDictData(dictKey);
676
+ if (dictData && Array.isArray(dictData)) {
677
+ this.previewOptions = dictData.map(item => ({
678
+ key: item.key,
679
+ value: item.value,
680
+ }));
681
+ }
682
+ } catch (error) {
683
+ console.error("加载字典数据失败:", error);
684
+ this.$message.error("加载字典数据失败");
685
+ }
686
+ },
687
+ getDictData(dictKey) {
688
+ return new Promise(resolve => {
689
+ try {
690
+ const wmsStr = localStorage.getItem("wms") || "{}";
691
+ const wmsData = JSON.parse(wmsStr);
692
+ const dictData = wmsData.SET_enumsSelect || {};
693
+ const dictItem = dictData[dictKey];
694
+ const result = [];
695
+
696
+ if (dictItem && dictItem.enums && Array.isArray(dictItem.enums)) {
697
+ dictItem.enums.forEach(item => {
698
+ result.push({
699
+ key: item.key,
700
+ value: item.value,
701
+ });
702
+ });
703
+ }
704
+
705
+ resolve(result);
706
+ } catch (error) {
707
+ console.error("获取字典数据失败:", error);
708
+ resolve([]);
709
+ }
710
+ });
711
+ },
712
+ async loadAllDictList() {
713
+ try {
714
+ const wmsStr = localStorage.getItem("wms") || "{}";
715
+ const wmsData = JSON.parse(wmsStr);
716
+ const dictData = wmsData.SET_enumsSelect || {};
717
+
718
+ const dictList = [];
719
+ Object.keys(dictData).forEach(key => {
720
+ const dictItem = dictData[key];
721
+ if (dictItem && key) {
722
+ dictList.push({
723
+ key: String(key),
724
+ label: dictItem.desc || key,
725
+ });
726
+ }
727
+ });
728
+
729
+ this.allDictList = dictList;
730
+ } catch (error) {
731
+ console.error("加载字典列表失败:", error);
732
+ this.allDictList = [];
733
+ }
734
+ },
735
+ async remoteDictQuery(query) {
736
+ if (!query) {
737
+ this.allDictList = [];
738
+ return;
739
+ }
740
+
741
+ try {
742
+ this.dictLoading = true;
743
+ const wmsStr = localStorage.getItem("wms") || "{}";
744
+ const wmsData = JSON.parse(wmsStr);
745
+ const dictData = wmsData.SET_enumsSelect || {};
746
+
747
+ const dictList = [];
748
+ Object.keys(dictData).forEach(key => {
749
+ if (key && key.toLowerCase().includes(query.toLowerCase())) {
750
+ const dictItem = dictData[key];
751
+ if (dictItem) {
752
+ dictList.push({
753
+ key: String(key),
754
+ label: dictItem.desc || key,
755
+ });
756
+ }
757
+ }
758
+ });
759
+
760
+ this.allDictList = dictList;
761
+ } catch (error) {
762
+ console.error("搜索字典失败:", error);
763
+ this.$message.error("搜索字典失败");
764
+ } finally {
765
+ this.dictLoading = false;
766
+ }
767
+ },
768
+ handleDictKeyChange(dictKey) {
769
+ if (dictKey) {
770
+ this.loadPreviewOptions();
771
+ }
772
+ },
773
+ handleSelectCustom(custom) {
774
+ const inputTypeMap = {
775
+ 1: "text",
776
+ 2: "number",
777
+ 3: "select",
778
+ 4: "picker",
779
+ };
780
+
781
+ const compareTypeMap = {
782
+ 1: "contains",
783
+ 2: "eq",
784
+ 3: "eq",
785
+ 4: "eq",
786
+ };
787
+
788
+ const newItem = {
789
+ label: custom.name,
790
+ value: custom.key,
791
+ inputType: inputTypeMap[custom.keyType] || "text",
792
+ compare: compareTypeMap[custom.keyType] || "eq",
793
+ children: [],
794
+ props: {},
795
+ };
796
+
797
+ if (custom.keyType === 4) {
798
+ newItem.dateType = "date";
799
+ newItem.props = {
800
+ type: "date",
801
+ placeholder: "选择日期",
802
+ valueFormat: "yyyy-MM-dd",
803
+ format: "yyyy/MM/dd",
804
+ };
805
+ }
806
+
807
+ this.configList.push(newItem);
808
+ this.customsDialogVisible = false;
809
+ },
810
+ },
811
+ };
812
+ </script>
813
+
814
+ <style scoped>
815
+ .search-config-container {
816
+ padding-bottom: 10px;
817
+ }
818
+
819
+ .config-header {
820
+ display: flex;
821
+ justify-content: space-between;
822
+ align-items: center;
823
+ margin-bottom: 10px;
824
+ }
825
+
826
+ .option-item {
827
+ display: flex;
828
+ align-items: center;
829
+ margin-bottom: 10px;
830
+ }
831
+
832
+ .gray-text {
833
+ color: #909399;
834
+ font-size: 12px;
835
+ }
836
+
837
+ .sort-handle {
838
+ color: #909399;
839
+ transition: color 0.3s;
840
+ }
841
+
842
+ .sort-handle:hover {
843
+ color: #409eff;
844
+ }
845
+
846
+ .sortable-ghost {
847
+ opacity: 0.4;
848
+ background-color: #f5f7fa;
849
+ }
850
+
851
+ .sortable-drag {
852
+ opacity: 1;
853
+ background-color: #fff;
854
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
855
+ }
856
+
857
+ .dialog-footer {
858
+ display: flex;
859
+ align-items: center;
860
+ justify-content: center;
861
+ }
862
+
863
+ .options-config {
864
+ max-height: 400px;
865
+ overflow-y: auto;
866
+ }
867
+ </style>