@netang/quasar 0.0.22 → 0.0.24

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.
@@ -1,54 +1,89 @@
1
1
  <template>
2
+ <!--:class="fieldFocused ? 'q-field&#45;&#45;float q-field&#45;&#45;focused q-field&#45;&#45;highlighted' : ''"-->
2
3
  <q-field
3
- :class="fieldFocused ? 'q-field--float q-field--focused q-field--highlighted' : ''"
4
+ class="n-field-table"
4
5
  :model-value="modelValue"
5
6
  :readonly="readonly"
6
- @clear="onClear"
7
+ :clearable="clearable && ! multiple"
8
+ @clear="onFieldClear"
7
9
  v-bind="$attrs"
8
10
  >
9
11
  <template v-slot:control>
10
12
 
11
- <!--&lt;!&ndash; 显示值 &ndash;&gt;-->
12
- <!--<div v-if="showValue">{{showValue}}</div>-->
13
+ <template v-if="multiple">
14
+
15
+ <!-- 多选插槽 -->
16
+ <slot
17
+ name="selected"
18
+ :selected="selected"
19
+ :remove="onRemoveSelected"
20
+ v-if="$slots.selected"
21
+ />
22
+
23
+ <!-- 多选标签 -->
24
+ <template v-else>
25
+ <q-chip
26
+ v-for="(item, index) in selected"
27
+ :key="`options-${index}`"
28
+ :label="item[labelKey || rowKey]"
29
+ removable
30
+ @remove="onRemoveSelected(item, index)"
31
+ dense
32
+ />
33
+ </template>
34
+ </template>
35
+
36
+ <!-- 显示文字 -->
37
+ <span v-else>
38
+ {{showValue}}
39
+ </span>
40
+
41
+ <!-- 筛选输入框 -->
42
+ <input
43
+ ref="inputRef"
44
+ class="q-field__input q-placeholder col q-field__input--padding"
45
+ v-model="inputValue"
46
+ v-if="filter"
47
+ />
13
48
 
14
- <!--&lt;!&ndash; 显示占位符 &ndash;&gt;-->
15
- <!--<div class="n-placeholder" v-else-if="placeholder">{{placeholder}}</div>-->
16
49
  </template>
17
50
 
18
- <template v-slot:append>
51
+ <!-- 弹出对话框图标 -->
52
+ <template v-slot:append v-if="! noDialog">
19
53
  <q-icon
20
54
  class="cursor-pointer"
21
55
  name="search"
22
- @click.prevent.stop="onDialog"
56
+ @click.prevent.stop="showDialog = true"
23
57
  />
24
58
  </template>
25
59
 
60
+ <!-- 弹出层代理 -->
26
61
  <q-popup-proxy
27
62
  ref="popupRef"
28
- @before-show="onPopupBeforeShow"
63
+ no-refocus
64
+ no-focus
29
65
  @show="onPopupShow"
30
- @before-hide="onPopupBeforeHide"
31
- @hide="onPopupHide"
66
+ @focus="onPopupFocus"
32
67
  v-if="! readonly"
33
68
  >
69
+ <!-- 快捷表格 -->
34
70
  <q-table
35
- ref="tableRef"
36
71
  class="n-table"
37
72
  style="min-width:500px;max-width:90vw;height: 300px;"
38
73
  v-model:pagination="tablePagination"
39
- v-model:selected="tableSelected"
74
+ v-model:selected="selected"
40
75
  :row-key="tableRowKey"
41
76
  :rows="tableRows"
42
- :columns="tableColumns"
43
- :selection="tableSelection"
77
+ :columns="columns"
78
+ :selection="multiple ? 'multiple' : 'none'"
44
79
  :loading="tableLoading"
45
80
  :rows-per-page-options="tableRowsPerPageOptions"
46
- @row-click="tableRowClick"
47
- @row-dblclick="tableRowDblclick"
81
+ @row-click="quickTableRowClick"
48
82
  @request="tableRequest"
49
83
  flat
50
84
  virtual-scroll
51
85
  dense
86
+ v-bind="tableProps"
52
87
  >
53
88
  <!-- 图片 -->
54
89
  <template
@@ -77,42 +112,37 @@
77
112
  </q-td>
78
113
  </template>
79
114
 
80
- <!-- 合计 -->
81
- <!--<template v-slot:bottom-row="props" v-if="tableSummary">-->
82
- <!-- <n-table-summary-->
83
- <!-- :props="props"-->
84
- <!-- :data="tableSummary"-->
85
- <!-- :selection="tableSelection"-->
86
- <!-- />-->
87
- <!--</template>-->
88
-
89
115
  <!-- 翻页 -->
90
116
  <template v-slot:pagination="props">
91
117
  <n-table-pagination
92
118
  :props="props"
93
- :table-refresh="tableRefresh"
119
+ no-power
120
+ dense
94
121
  />
95
122
  </template>
96
123
  </q-table>
97
124
  </q-popup-proxy>
98
125
  </q-field>
99
126
 
127
+ <!-- 弹出对话框 -->
100
128
  <n-dialog
101
- title="选择商品"
102
129
  v-model="showDialog"
130
+ width="80%"
131
+ :on-confirm="onDialogConfirm"
132
+ @before-show="onDialogBeforeShow"
133
+ @show="onDialogShow"
134
+ @hide="onDialogHide"
135
+ cancel
136
+ v-bind="dialogProps"
103
137
  >
104
138
  <q-page>
105
- <n-table
106
- page-status
107
- @load="onPopupShow"
108
- />
139
+ <n-table />
109
140
  </q-page>
110
141
  </n-dialog>
111
142
  </template>
112
143
 
113
144
  <script>
114
- import { ref, reactive, computed, provide, watch, nextTick, onMounted } from 'vue'
115
- import { NFieldTableKey } from '../../utils/symbols'
145
+ import { ref, computed, watch, onMounted } from 'vue'
116
146
 
117
147
  export default {
118
148
 
@@ -126,40 +156,70 @@ export default {
126
156
  */
127
157
  props: {
128
158
  // 值
129
- modelValue: [String, Number],
130
- // 占位符
131
- placeholder: String,
132
- // 是否只读
133
- readonly: Boolean,
134
-
135
- // 表格请求地址
136
- url: String,
137
- // 路由组件路径
138
- route: String,
139
- // 值属性名称
159
+ modelValue: [ String, Number, Array ],
160
+ // 是否可清除
161
+ clearable: Boolean,
162
+ // 表格请求路径
163
+ path: String,
164
+ // 表格请求参数
165
+ query: Object,
166
+ // 附加请求数据
167
+ data: Object,
168
+ // 已选数据
169
+ selected: Array,
170
+ // 初始加载选择数据
171
+ loadSelected: {
172
+ type: Boolean,
173
+ default: true,
174
+ },
175
+ // 值字段(必填)
140
176
  valueKey: {
141
177
  type: String,
142
178
  required: true,
143
179
  },
144
- // 快捷表格显示的属性名称数组
145
- showKeys: {
146
- type: Array,
180
+ // 标签字段(必填)
181
+ labelKey: {
182
+ type: String,
147
183
  required: true,
148
184
  },
149
- // 默认搜索属性名称
150
- searchKey: String,
151
-
152
- // 表格列数据
153
- columns: Array,
154
185
  // 表格行唯一键值
155
186
  rowKey: {
156
187
  type: String,
157
188
  default: 'id',
158
189
  },
159
- // 是否多选
160
- multiple: Boolean,
190
+ // 快捷表格显示的字段数组(空为:[值字段, 标签字段])
191
+ showKeys: Array,
192
+ // 隐藏搜索字段数组
193
+ hideSearchKeys: Array,
194
+ // 默认筛选字段(空为:标签字段)
195
+ filterKey: String,
196
+ // 是否开启筛选
197
+ filter: Boolean,
198
+ // 表格声明属性
199
+ tableProps: Object,
200
+ // 对话框声明属性
201
+ dialogProps: Object,
202
+
203
+ // 占位符
204
+ placeholder: String,
205
+ // 是否只读
206
+ readonly: Boolean,
207
+ // 值是否为数组
208
+ valueArray: Boolean,
209
+ // 关闭对话框
210
+ noDialog: Boolean,
211
+
212
+ // 表格列数据
213
+ columns: Array,
161
214
  // 行数据
162
215
  rows: Array,
216
+ // 是否多选
217
+ multiple: Boolean,
218
+ // 输入防抖(毫秒)
219
+ inputDebounce: {
220
+ type: [ Number, String ],
221
+ default: 500
222
+ },
163
223
  },
164
224
 
165
225
  /**
@@ -167,6 +227,7 @@ export default {
167
227
  */
168
228
  emits: [
169
229
  'update:modelValue',
230
+ 'update:selected',
170
231
  ],
171
232
 
172
233
  /**
@@ -174,156 +235,427 @@ export default {
174
235
  */
175
236
  setup(props, { emit, slots }) {
176
237
 
238
+ // ==========【计算属性】=========================================================================================
177
239
 
178
- // ==========【数据】============================================================================================
240
+ /**
241
+ * 插槽标识
242
+ */
243
+ const slotNames = computed(function() {
244
+ return utils.isValidObject(slots) ? Object.keys(slots) : []
245
+ })
179
246
 
180
- // 字段组件获取焦点
181
- const fieldFocused = ref(false)
247
+ /**
248
+ * 当前显示字段
249
+ */
250
+ const currentShowKeys = computed(function() {
251
+ return utils.isValidArray(props.showKeys)
252
+ ? props.showKeys
253
+ : [ props.rowKey, props.labelKey ]
254
+ })
182
255
 
183
- // 弹出层节点
184
- const popupRef = ref(null)
256
+ /**
257
+ * 当前搜索字段
258
+ */
259
+ const currentFilterKeys = computed(function() {
260
+ return props.filterKey || props.labelKey
261
+ })
185
262
 
186
- // 是否显示对话框
187
- const showDialog = ref(false)
263
+ /**
264
+ * 显示值
265
+ */
266
+ const showValue = computed(function () {
267
+
268
+ // 如果是单选
269
+ if (! props.multiple && utils.isValidArray(selected.value)) {
270
+ return selected.value[0][props.labelKey || props.rowKey]
271
+ }
272
+
273
+ return ''
274
+ })
275
+
276
+ // ==========【数据】============================================================================================
188
277
 
189
- // 表格是否已加载
190
- let tableLoaded = false
278
+ // 创建权限实例
279
+ const $power = utils.$power.create({
280
+ // 路由路径
281
+ path: utils.isValidString(props.path) ? props.path : false,
282
+ // 路由参数
283
+ query: props.query,
284
+ // 关闭权限页面
285
+ power: false,
286
+ })
191
287
 
192
- // 创建表格
288
+ const {
289
+ // 当前路由路径
290
+ routePath,
291
+ } = $power
292
+
293
+ // 创建表格实例
193
294
  const $table = utils.$table.create({
194
- url: props.route ? props.route : props.url,
295
+ // 权限实例
296
+ $power,
297
+ // 附加请求数据
298
+ data: props.data,
195
299
  // 获取表格列数据
196
300
  columns: getTableColumns(),
197
301
  // 表格行唯一键值
198
302
  rowKey: props.rowKey,
303
+ // 行数据
304
+ rows: props.rows,
199
305
  // 选择类型, 可选值 single multiple none
200
- selection: props.multiple ? 'multiple' : 'none',
201
- // // 关闭宫格
202
- // showGrid: false,
203
- // // 关闭可见列
204
- // showVisibleColumns: false,
306
+ selection: props.multiple ? 'multiple' : 'single',
307
+ // 已选数据
308
+ selected: props.selected,
309
+ // http 设置
310
+ httpSettings: {
311
+ // 头部请求
312
+ headers: {
313
+ // 添加头部查看请求
314
+ Pview: 1,
315
+ },
316
+ },
317
+ // 刷新后清空已选数据
318
+ refreshResetSelected: false,
205
319
  })
206
320
 
207
- // ==========【注入】============================================================================================
321
+ // 创建防抖睡眠方法
322
+ const sleep = utils.debounceSleep()
208
323
 
209
- // 向后代注入数据
210
- provide(NFieldTableKey, {
211
- // 表格实例
212
- $table,
213
- })
324
+ // 输入框节点
325
+ const inputRef = ref(null)
214
326
 
215
- // ==========【计算属性】=========================================================================================
327
+ // 输入框值
328
+ const inputValue = ref('')
329
+
330
+ // 弹出层节点
331
+ const popupRef = ref(null)
332
+
333
+ // 是否显示对话框
334
+ const showDialog = ref(false)
335
+
336
+ // 当前已选数据
337
+ const selected = ref([...$table.tableSelected.value])
338
+
339
+ // 当前表格列数据
340
+ const columns = getQuickTableColumns()
341
+
342
+ // 如果有已选数据
343
+ if (utils.isValidArray(selected.value)) {
344
+ // 检查值更新
345
+ checkModelValueChange()
346
+ }
347
+
348
+ // ==========【监听数据】=========================================================================================
216
349
 
217
350
  /**
218
- * 插槽标识
351
+ * 监听声明值
219
352
  */
220
- const slotNames = computed(function() {
221
- if (utils.isValidObject(slots)) {
222
- return Object.keys(slots)
353
+ watch(()=>props.modelValue, async function() {
354
+
355
+ // 格式化值
356
+ let values = formatModelValue()
357
+
358
+ // 如果值不是有效数组
359
+ if (! utils.isValidArray(values)) {
360
+ // 则清空已选数据
361
+ selected.value = []
362
+ return
363
+ }
364
+ values = _.uniq(values)
365
+
366
+ // 已选数据值数组
367
+ const selectedValues = utils.isValidArray(selected.value)
368
+ // 如果有已选数据
369
+ ? _.uniq(selected.value.map(e => e[props.rowKey]))
370
+ // 否则为空
371
+ : []
372
+
373
+ // 需增删除的值
374
+ const removeValues = selectedValues.filter(e => values.indexOf(e) === -1)
375
+ if (removeValues.length) {
376
+ utils.forEachRight(selected.value, function (item, index) {
377
+ if (removeValues.indexOf(item[props.rowKey]) > -1) {
378
+ selected.value.splice(index, 1)
379
+ }
380
+ })
381
+ }
382
+
383
+ // 需增加的值
384
+ const addValues = values.filter(e => selectedValues.indexOf(e) === -1)
385
+ if (addValues.length) {
386
+ // 请求选择数据
387
+ selected.value.push(...await onRequestSelected(addValues))
223
388
  }
224
- return []
225
389
  })
226
390
 
227
391
  /**
228
- * 获取表格列数据
392
+ * 监听声明选择数据
229
393
  */
230
- // const tableColumns = computed(function () {
231
- //
232
- // // 获取原始表格列数据
233
- // const rawTableColumns = props.route
234
- // // 如果有路由组件路径
235
- // ? utils.$table.config(props.route, 'columns')
236
- // // 否则为自定义表格列数据
237
- // : props.columns
238
- //
239
- // // 如果有原始表格列数据
240
- // return utils.isValidArray(rawTableColumns)
241
- // // 克隆原始表格列数据
242
- // ? _.cloneDeep(rawTableColumns)
243
- // : []
244
- // })
394
+ watch(()=>props.selected, function(val) {
395
+ if (val !== selected.value) {
396
+ // 设置选择数据
397
+ selected.value = val
398
+ }
399
+ // 检查值更新
400
+ checkModelValueChange()
245
401
 
246
- // ==========【监听数据】=========================================================================================
402
+ // 设置输入框焦点
403
+ setInputFocus()
404
+
405
+ }, {
406
+ // 深度监听
407
+ deep: true
408
+ })
247
409
 
248
410
  /**
249
- * 获取快捷表格列数据
411
+ * 监听当前已选数据
250
412
  */
251
- // watch([()=>props.modelValue, ()=>props.end, ()=>props.type], function() {
252
- //
253
- // })
413
+ watch(selected, function(val) {
414
+ if (val !== props.selected) {
415
+ emit('update:selected', val)
416
+ }
417
+ }, {
418
+ // 深度监听
419
+ deep: true,
420
+ })
421
+
422
+ /**
423
+ * 监听输入框值
424
+ */
425
+ watch(inputValue, async function (val) {
426
+
427
+ // 取消延迟执行
428
+ sleep.cancel()
429
+
430
+ if (utils.isValidValue(val)) {
431
+
432
+ const n_search = {}
433
+ n_search[currentFilterKeys.value] = [
434
+ {
435
+ // 比较类型
436
+ type: dicts.SEARCH_TYPE__LIKE,
437
+ // 值
438
+ value: val || '',
439
+ }
440
+ ]
441
+
442
+ $table.tableQuery.value = {
443
+ n_search,
444
+ }
445
+
446
+ } else {
447
+ $table.tableQuery.value = {}
448
+ }
449
+
450
+ // 延迟执行
451
+ await sleep(props.inputDebounce)
452
+
453
+ // 表格重新加载
454
+ await $table.tableReload()
455
+ })
254
456
 
255
457
  // ==========【方法】=============================================================================================
256
458
 
459
+ /**
460
+ * 格式化值
461
+ */
462
+ function formatModelValue() {
463
+
464
+ // 如果值是数组
465
+ if (props.valueArray) {
466
+ return props.modelValue
467
+ }
468
+
469
+ // 否则值是字符串/数字
470
+ return utils.split(props.modelValue, ',')
471
+ }
472
+
473
+ /**
474
+ * 请求选择数据
475
+ */
476
+ async function onRequestSelected(value) {
477
+
478
+ // 请求数据
479
+ const { status, data } = await utils.http({
480
+ url: $table.routePath,
481
+ data: Object.assign(
482
+ // 获取表格请求数据
483
+ $table.getTableRequestData({
484
+ // filter,
485
+ pagination: {
486
+ // 页码
487
+ page: 1,
488
+ // 每页的数据条数
489
+ rowsPerPage: value.length,
490
+ // 排序字段
491
+ sortBy: null,
492
+ // 是否降序排列
493
+ descending: true,
494
+ }
495
+ }, false),
496
+ {
497
+ // 查看字段
498
+ n_view: {
499
+ // 查看字段
500
+ field: props.rowKey,
501
+ // 查看值
502
+ value,
503
+ },
504
+ }
505
+ ),
506
+ })
507
+
508
+ return status && utils.isValidArray(_.get(data, 'rows')) ? data.rows : []
509
+ }
510
+
511
+ /**
512
+ * 初始加载选择数据
513
+ */
514
+ async function onLoadSelected() {
515
+
516
+ if (
517
+ // 如果初始不加载选择数据
518
+ ! props.loadSelected
519
+ // 如果没有请求路由路径
520
+ || ! routePath
521
+ // 如果有选择数据
522
+ || utils.isValidArray(selected.value)
523
+ ) {
524
+ // 则无任何操作
525
+ return
526
+ }
527
+
528
+ // 格式化值
529
+ const value = formatModelValue()
530
+
531
+ // 如果值不是有效数组
532
+ if (! utils.isValidArray(value)) {
533
+ // 则无任何操作
534
+ return
535
+ }
536
+
537
+ // 设置已选数据
538
+ selected.value = await onRequestSelected(value)
539
+ }
540
+
541
+ /**
542
+ * 检查值更新
543
+ */
544
+ function checkModelValueChange() {
545
+
546
+ let newModelValue = utils.isValidArray(selected.value)
547
+ // 如果有已选数据
548
+ ? (
549
+ props.multiple
550
+ // 如果是多选
551
+ ? selected.value.map(e => e[props.rowKey])
552
+ // 否则是单选
553
+ : [ selected.value[0][props.rowKey] ]
554
+ )
555
+ // 否则为空
556
+ : []
557
+
558
+ // 如果值为字符串或数字
559
+ if (! props.valueArray) {
560
+ newModelValue = utils.numberDeep(utils.join(newModelValue, ','))
561
+ }
562
+
563
+ // 如果值发生改变
564
+ if (! _.isEqual(newModelValue, props.modelValue)) {
565
+
566
+ // 提交更新值
567
+ emit('update:modelValue', newModelValue)
568
+ }
569
+ }
570
+
257
571
  /**
258
572
  * 获取表格列数据
259
573
  */
260
574
  function getTableColumns() {
261
575
 
262
- // 获取原始表格列数据
263
- const rawTableColumns = props.route
264
- // 如果有路由组件路径
265
- ? utils.$table.config(props.route, 'columns')
266
- // 否则为自定义表格列数据
267
- : props.columns
576
+ let columns
577
+
578
+ // 如果有声明路由表格列数据
579
+ if (utils.isValidArray(props.columns)) {
580
+ columns = _.cloneDeep(props.columns)
581
+
582
+ // 如果有路由路径
583
+ } else if (routePath) {
584
+ // 否则如果有路由表格列数据
585
+ const rawTableColumns = utils.$table.config(routePath, 'columns')
586
+ if (utils.isValidArray(rawTableColumns)) {
587
+ columns = _.cloneDeep(rawTableColumns)
588
+ }
589
+ }
590
+
591
+ if (utils.isValidArray(columns)) {
592
+ if (utils.isValidArray(props.hideSearchKeys)) {
593
+ for (const item of columns) {
594
+ if (
595
+ props.hideSearchKeys.indexOf(item.name) > -1
596
+ && _.has(item, 'search')
597
+ ) {
598
+ item.search.hide = true
599
+ }
600
+ }
601
+ }
602
+ return columns
603
+ }
604
+
605
+ return []
606
+ }
607
+
608
+ /**
609
+ * 获取快捷表格列数据
610
+ */
611
+ function getQuickTableColumns() {
612
+
613
+ const columns = []
268
614
 
269
615
  // 如果有原始表格列数据
270
- return utils.isValidArray(rawTableColumns)
616
+ if (utils.isValidArray($table.tableColumns)) {
617
+
271
618
  // 克隆原始表格列数据
272
- ? _.cloneDeep(rawTableColumns)
273
- // 否则为空
274
- : []
619
+ const rawTableColumns = _.cloneDeep($table.tableColumns)
620
+
621
+ // 快捷表格显示的属性名称数组
622
+ utils.forEach(currentShowKeys.value, function (key) {
623
+ for (const item of rawTableColumns) {
624
+ if (item.name === key) {
625
+ // 删除搜索字段
626
+ if (_.has(item, 'search')) {
627
+ delete item.search
628
+ }
629
+ // 删除可见字段
630
+ if (_.has(item, 'visible')) {
631
+ delete item.visible
632
+ }
633
+ columns.push(item)
634
+ }
635
+ }
636
+ })
637
+ }
275
638
 
276
- // const columns = []
277
- //
278
- // // 获取原始表格列数据
279
- // let rawTableColumns = props.route
280
- // // 如果有路由组件路径
281
- // ? utils.$table.config(props.route, 'columns')
282
- // // 否则为自定义表格列数据
283
- // : props.columns
284
- //
285
- // // 如果有原始表格列数据
286
- // if (utils.isValidArray(rawTableColumns)) {
287
- //
288
- // // 克隆原始表格列数据
289
- // rawTableColumns = _.cloneDeep(rawTableColumns)
290
- //
291
- // // 快捷表格显示的属性名称数组
292
- // utils.forEach(props.showKeys, function (key) {
293
- // for (const item of rawTableColumns) {
294
- // if (item.name === key) {
295
- // // 删除搜索字段
296
- // if (_.has(item, 'search')) {
297
- // delete item.search
298
- // }
299
- // // 删除可见字段
300
- // if (_.has(item, 'visible')) {
301
- // delete item.visible
302
- // }
303
- // columns.push(item)
304
- // }
305
- // }
306
- // })
307
- // }
308
- //
309
- // return columns
639
+ return columns
310
640
  }
311
641
 
312
642
  /**
313
- * 取消
643
+ * 移除已选数据
314
644
  */
315
- function onCancel() {
316
- // 还原原始值
317
- // onEmit('update:modelValue', oldModelValue)
645
+ function onRemoveSelected(item, index) {
646
+ selected.value.splice(index, 1)
318
647
  }
319
648
 
320
649
  /**
321
- * 弹出层显示前回调
650
+ * 字段清空触发
322
651
  */
323
- function onPopupBeforeShow() {
652
+ function onFieldClear() {
324
653
 
325
- // 字段组件获取焦点
326
- fieldFocused.value = true
654
+ // 清空快捷表格已选数据
655
+ selected.value = []
656
+
657
+ // 关闭弹出层
658
+ popupRef.value.hide()
327
659
  }
328
660
 
329
661
  /**
@@ -331,46 +663,126 @@ export default {
331
663
  */
332
664
  function onPopupShow() {
333
665
 
334
- // 表格重新加载
335
- if (! tableLoaded) {
336
- $table.tableReload()
337
- tableLoaded = true
338
- }
666
+ // 表格加载(只加载一次)
667
+ $table.tableLoad()
668
+
669
+ // 设置输入框焦点
670
+ setInputFocus()
339
671
  }
340
672
 
341
673
  /**
342
- * 弹出层隐藏前回调
674
+ * 弹出层获取焦点触发
343
675
  */
344
- function onPopupBeforeHide() {
676
+ function onPopupFocus(e) {
677
+
678
+ // 停止冒泡
679
+ e.stopPropagation()
680
+
681
+ // 设置输入框焦点
682
+ setInputFocus()
345
683
 
346
- // 字段组件失去焦点
347
- fieldFocused.value = false
684
+ window.scrollTo(window.pageXOffset || window.scrollX || document.body.scrollLeft || 0, 0)
348
685
  }
349
686
 
350
687
  /**
351
- * 弹出层隐藏后回调
688
+ * 对话框显示前回调
352
689
  */
353
- function onPopupHide() {
690
+ function onDialogBeforeShow() {
354
691
 
692
+ // 设置当前已选数据
693
+ $table.tableSelected.value = [...selected.value]
694
+
695
+ popupRef.value.hide()
355
696
  }
356
697
 
357
698
  /**
358
- * 清空
699
+ * 对话框显示回调
359
700
  */
360
- function onClear() {
361
- emit('update:modelValue', null)
362
- popupRef.value.hide()
701
+ function onDialogShow() {
702
+ $table.tableLoad()
703
+ }
704
+
705
+ /**
706
+ * 对话框隐藏后回调
707
+ */
708
+ function onDialogHide() {
709
+
710
+ let isReload = true
711
+
712
+ // 清空输入框值
713
+ if (inputValue.value) {
714
+ // 此时清空输入框后, 会自动刷新表格
715
+ inputValue.value = ''
716
+
717
+ // 所以只需要重置搜索值即可, 不需要再重置后刷新表格
718
+ isReload = false
719
+ }
720
+
721
+ // 如果有表格搜索值
722
+ if ($table.hasTableSearchValue()) {
723
+ // 表格搜索重置
724
+ $table.tableSearchReset(isReload)
725
+ }
726
+ }
727
+
728
+ /**
729
+ * 对话框点击确认回调
730
+ */
731
+ function onDialogConfirm(data) {
732
+ selected.value = [...data]
733
+ }
734
+
735
+ /**
736
+ * 单击快捷表格行
737
+ */
738
+ function quickTableRowClick(e, row, index) {
739
+
740
+ // 如果为多选
741
+ if (props.multiple) {
742
+
743
+ const opt = {}
744
+ opt[props.rowKey] = row[props.rowKey]
745
+
746
+ // 获取当前数据索引
747
+ const itemIndex = _.findIndex(selected.value, opt)
748
+
749
+ // 如果不存在
750
+ if (itemIndex === -1) {
751
+ // 则添加
752
+ selected.value.push(row)
753
+
754
+ // 否则
755
+ } else {
756
+ // 删除
757
+ selected.value.splice(itemIndex, 1)
758
+ }
759
+
760
+ // 否则为单选
761
+ } else {
762
+ selected.value = [ row ]
763
+ popupRef.value.hide()
764
+ }
363
765
  }
364
766
 
365
767
  /**
366
- * 显示对话框
768
+ * 设置输入框焦点
367
769
  */
368
- function onDialog() {
369
- showDialog.value = true
770
+ function setInputFocus() {
771
+ if (inputRef.value) {
772
+ inputRef.value.focus()
773
+ }
370
774
  }
371
775
 
372
776
  // ==========【生命周期】=========================================================================================
373
777
 
778
+ /**
779
+ * 实例被挂载后调用
780
+ */
781
+ onMounted(async function() {
782
+
783
+ // 初始加载选择数据
784
+ await onLoadSelected()
785
+ })
374
786
 
375
787
  // ==========【返回】=============================================================================================
376
788
 
@@ -378,61 +790,58 @@ export default {
378
790
  // 解构表格实例
379
791
  ...$table,
380
792
 
381
- // 字段组件获取焦点
382
- fieldFocused,
793
+ // 插槽标识
794
+ slotNames,
795
+ // 显示值
796
+ showValue,
797
+
798
+ // 输入框节点
799
+ inputRef,
800
+ // 输入框值
801
+ inputValue,
383
802
  // 弹出层节点
384
803
  popupRef,
385
804
  // 是否显示对话框
386
805
  showDialog,
806
+ // 当前已选数据
807
+ selected,
808
+ // 当前表格列数据
809
+ columns,
387
810
 
388
- // 插槽 body 单元格标识
389
- slotNames,
811
+ // 移除已选数据
812
+ onRemoveSelected,
813
+ // 字段清空触发
814
+ onFieldClear,
390
815
 
391
- // 取消
392
- onCancel,
393
- // 弹出层显示前回调
394
- onPopupBeforeShow,
395
816
  // 弹出层显示回调
396
817
  onPopupShow,
397
- // 弹出层隐藏前回调
398
- onPopupBeforeHide,
399
- // 弹出层隐藏后回调
400
- onPopupHide,
401
- // 清空
402
- onClear,
403
-
404
- // 显示对话框
405
- onDialog,
818
+ // 弹出层获取焦点触发
819
+ onPopupFocus,
820
+
821
+ // 对话框显示前回调
822
+ onDialogBeforeShow,
823
+ // 对话框显示回调
824
+ onDialogShow,
825
+ // 对话框隐藏后回调
826
+ onDialogHide,
827
+ // 对话框点击确认回调
828
+ onDialogConfirm,
829
+
830
+ // 单击快捷表格行
831
+ quickTableRowClick,
406
832
  }
407
833
  },
408
834
  }
409
835
  </script>
410
836
 
411
- <style lang="scss" scoped>
837
+ <style lang="scss">
412
838
  @import "@/assets/sass/var.scss";
413
839
 
414
- .date {
415
-
416
- // 选择容器
417
- &__select {
418
- background-color: #ffffff;
419
- }
420
-
421
- // 时间容器
422
- &__time {
423
- + .date__settings {
424
- // 等同 q-pt-sm
425
- padding-top: map-get($space-sm, 'y');
426
- }
427
- }
428
- }
429
-
430
- /**
431
- * 暗色
432
- */
433
- .body--dark {
434
- .date__select {
435
- background-color: $color-gray-86;
840
+ .n-field-table {
841
+ .q-field__input--padding {
842
+ padding-left: 4px;
843
+ min-width: 50px !important;
844
+ cursor: text;
436
845
  }
437
846
  }
438
847
  </style>