Blame view

ant-design-vue-jeecg/src/components/jeecg/JSuperQuery.vue 14.7 KB
1
<template>
2
3
<div class="j-super-query-box">
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  <div @click="visible=true">
    <slot>
      <a-tooltip v-if="superQueryFlag" :mouseLeaveDelay="0.2">
        <template slot="title">
          <span>已有高级查询条件生效</span>
          <a-divider type="vertical"/>
          <a @click="handleReset">清空</a>
        </template>
        <a-button type="primary">
          <a-icon type="appstore" theme="twoTone" :spin="true"></a-icon>
          <span>高级查询</span>
        </a-button>
      </a-tooltip>
      <a-button v-else type="primary" icon="filter" @click="visible=true">高级查询</a-button>
    </slot>
  </div>
20
21
22
  <a-modal
    title="高级查询构造器"
23
    :width="1000"
24
25
26
    :visible="visible"
    @cancel="handleCancel"
    :mask="false"
27
    class="j-super-query-modal"
28
    style="top:5%;max-height: 95%;">
29
30
    <template slot="footer">
31
32
33
34
35
36
      <div style="float: left">
        <a-button :loading="loading" @click="handleReset">重置</a-button>
        <a-button :loading="loading" @click="handleSave">保存查询条件</a-button>
      </div>
      <a-button :loading="loading" @click="handleCancel">关闭</a-button>
      <a-button :loading="loading" type="primary" @click="handleOk">查询</a-button>
37
38
    </template>
39
40
41
    <a-spin :spinning="loading">
      <a-row>
        <a-col :sm="24" :md="24-5">
42
43
44
45
46
47
48
49
50
51
52
53
          <a-empty v-if="queryParamsModel.length === 0">
            <div slot="description">
              <span>没有任何查询条件</span>
              <a-divider type="vertical"/>
              <a @click="handleAdd">点击新增</a>
            </div>
          </a-empty>

          <a-form v-else layout="inline">

            <a-form-item label="过滤条件匹配" style="margin-bottom: 12px;">
54
              <a-select v-model="selectValue" :getPopupContainer="node=>node.parentNode">
55
56
                <a-select-option value="and">AND(所有条件都要求匹配)</a-select-option>
                <a-select-option value="or">OR(条件中的任意一个匹配)</a-select-option>
57
              </a-select>
58
59
60
61
62
            </a-form-item>

            <a-row type="flex" style="margin-bottom:10px" :gutter="16" v-for="(item, index) in queryParamsModel" :key="index">

              <a-col :span="8">
63
64
65
66
67
68
69
70
71
72
73
74
75
                <a-tree-select
                  showSearch
                  v-model="item.field"
                  :treeData="fieldTreeData"
                  :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
                  placeholder="选择查询字段"
                  allowClear
                  treeDefaultExpandAll
                  :getPopupContainer="node=>node.parentNode"
                  style="width: 100%"
                  @select="(val,option)=>handleSelected(option,item)"
                >
                </a-tree-select>
76
77
78
              </a-col>

              <a-col :span="4">
79
                <a-select placeholder="匹配规则" v-model="item.rule" :getPopupContainer="node=>node.parentNode">
80
81
82
83
84
85
86
87
88
89
90
91
92
93
                  <a-select-option value="eq">等于</a-select-option>
                  <a-select-option value="ne">不等于</a-select-option>
                  <a-select-option value="gt">大于</a-select-option>
                  <a-select-option value="ge">大于等于</a-select-option>
                  <a-select-option value="lt">小于</a-select-option>
                  <a-select-option value="le">小于等于</a-select-option>
                  <a-select-option value="right_like">以..开始</a-select-option>
                  <a-select-option value="left_like">以..结尾</a-select-option>
                  <a-select-option value="like">包含</a-select-option>
                  <a-select-option value="in">在...中</a-select-option>
                </a-select>
              </a-col>

              <a-col :span="8">
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
                <template v-if="item.dictCode">
                  <template v-if="item.type === 'table-dict'">
                    <j-popup
                      v-model="item.val"
                      :code="item.dictTable"
                      :field="item.dictCode"
                      :orgFields="item.dictCode"
                      :destFields="item.dictCode"
                    ></j-popup>
                  </template>
                  <j-dict-select-tag v-else v-model="item.val" :dictCode="item.dictCode" placeholder="请选择"/>
                </template>
                <j-select-multi-user
                  v-else-if="item.type === 'select-user'"
                  v-model="item.val"
                  :buttons="false"
                  :multiple="false"
                  placeholder="请选择用户"
                  :returnKeys="['id', item.customReturnField || 'username']"
                />
                <j-select-depart
                  v-else-if="item.type === 'select-depart'"
                  v-model="item.val"
                  :multi="false"
                  placeholder="请选择部门"
                  :customReturnField="item.customReturnField || 'id'"
                />
121
                <a-select v-else-if="item.options instanceof Array" v-model="item.val" :options="item.options" allowClear placeholder="请选择"/>
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
                <j-date v-else-if=" item.type=='date' " v-model="item.val" placeholder="请选择日期" style="width: 100%"></j-date>
                <j-date v-else-if=" item.type=='datetime' " v-model="item.val" placeholder="请选择时间" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"></j-date>
                <a-input-number v-else-if=" item.type=='int'||item.type=='number' " style="width: 100%" placeholder="请输入数值" v-model="item.val"/>
                <a-input v-else v-model="item.val" placeholder="请输入值"/>
              </a-col>

              <a-col :span="4">
                <a-button @click="handleAdd" icon="plus"></a-button>&nbsp;
                <a-button @click="handleDel( index )" icon="minus"></a-button>
              </a-col>

            </a-row>

          </a-form>
        </a-col>
        <a-col :sm="24" :md="5">
          <!-- 查询记录 -->

          <a-card class="j-super-query-history-card" :bordered="true">
            <div slot="title">
              保存的查询
            </div>
144
145

            <a-empty v-if="treeData.length === 0" class="j-super-query-history-empty" description="没有保存任何查询"/>
146
            <a-tree
147
              v-else
148
149
150
151
152
153
154
155
156
157
158
159
160
161
              class="j-super-query-history-tree"
              showIcon
              :treeData="treeData"
              @select="handleTreeSelect"
              @rightClick="handleTreeRightClick"
            >
            </a-tree>
          </a-card>


        </a-col>
      </a-row>
162
    </a-spin>
163
164
165
166
167

    <a-modal title="请输入保存的名称" :visible="prompt.visible" @cancel="prompt.visible=false" @ok="handlePromptOk">
      <a-input v-model="prompt.value"></a-input>
    </a-modal>
168
  </a-modal>
169
</div>
170
171
172
</template>

<script>
173
174
  import * as utils from '@/utils/util'
  import JDate from '@/components/jeecg/JDate.vue'
175
176
  import JSelectDepart from '@/components/jeecgbiz/JSelectDepart'
  import JSelectMultiUser from '@/components/jeecgbiz/JSelectMultiUser'
177
178
179

  export default {
    name: 'JSuperQuery',
180
    components: { JDate, JSelectDepart, JSelectMultiUser },
181
182
183
184
185
186
187
188
189
    props: {
      /*
       fieldList: [{
          value:'',
          text:'',
          type:'',
          dictCode:'' // 只要 dictCode 有值,无论 type 是什么,都显示为字典下拉框
       }]
       type:date datetime int number string
190
      * */
191
192
193
      fieldList: {
        type: Array,
        required: true
194
195
196
197
      },
      /*
      * 这个回调函数接收一个数组参数 即查询条件
      * */
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
      callback: {
        type: String,
        required: false,
        default: 'handleSuperQuery'
      },

      // 当前是否在加载中
      loading: {
        type: Boolean,
        default: false
      },

      // 保存查询条件的唯一 code,通过该 code 区分
      saveCode: {
        type: String,
        default: 'testSaveCode'
      }

    },
    data() {
      return {
219
        fieldTreeData: [],
220
221
222
223
224
225
226
227
228
229
230
231
232

        prompt: {
          visible: false,
          value: ''
        },

        visible: false,
        queryParamsModel: [{}],
        treeIcon: <a-icon type="file-text"/>,
        treeData: [],
        // 保存查询条件的前缀名
        saveCodeBefore: 'JSuperQuerySaved_',
        selectValue: 'and',
233
        superQueryFlag: false
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
      }
    },
    watch: {
      // 当 saveCode 变化时,重新查询已保存的条件
      saveCode: {
        immediate: true,
        handler(val) {
          let list = this.$ls.get(this.saveCodeBefore + val)
          if (list instanceof Array) {
            this.treeData = list.map(item => {
              item.icon = this.treeIcon
              return item
            })
          }
        }
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
      },
      fieldList: {
        deep: true,
        immediate: true,
        handler(val) {
          let mainData = [], subData = []
          val.forEach(item => {
            let data = { ...item }
            data.label = data.label || data.text
            let hasChildren = (data.children instanceof Array)
            data.disabled = hasChildren
            data.selectable = !hasChildren
            if (hasChildren) {
              data.children = data.children.map(item2 => {
                let child = { ...item2 }
                child.label = child.label || child.text
                child.label = data.label + '-' + child.label
                child.value = data.value + ',' + child.value
                child.val = ''
                return child
              })
              data.val = ''
              subData.push(data)
            } else {
              mainData.push(data)
            }
          })
          this.fieldTreeData = mainData.concat(subData)
        }
278
279
      }
    },
280
281
282
283

    methods: {
      show() {
        if (!this.queryParamsModel || this.queryParamsModel.length == 0) {
284
285
          this.queryParamsModel = [{}]
        }
286
        this.visible = true
287
      },
288
289
290
291
292
293
      handleOk() {
        if (!this.isNullArray(this.queryParamsModel)) {
          let event = {
            matchType: this.selectValue,
            params: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
          }
294
295
          console.log('---高级查询参数--->', event)
          this.emitCallback(event.params, event.matchType)
296
        } else {
297
          this.emitCallback()
298
299
        }
      },
300
301
302
303
      emitCallback(params, matchType) {
        this.superQueryFlag = !!params
        this.$emit(this.callback, params, matchType)
      },
304
      handleCancel() {
305
306
        this.close()
      },
307
308
309
      close() {
        this.$emit('close')
        this.visible = false
310
      },
311
312
      handleAdd() {
        this.queryParamsModel.push({})
313
      },
314
315
      handleDel(index) {
        this.queryParamsModel.splice(index, 1)
316
      },
317
318
      handleSelected(node, item) {
        let { type, options, dictCode, dictTable, customReturnField } = node.dataRef
319
        item['type'] = type
320
        item['options'] = options
321
        item['dictCode'] = dictCode
322
323
        item['dictTable'] = dictTable
        item['customReturnField'] = customReturnField
324
        this.$set(item, 'val', undefined)
325
      },
326
      handleReset() {
327
        this.superQueryFlag = false
328
        this.queryParamsModel = [{}]
329
        this.emitCallback()
330
      },
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
      handleSave() {
        let queryParams = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
        if (this.isNullArray(queryParams)) {
          this.$message.warning('空条件不能保存')
        } else {
          this.prompt.value = ''
          this.prompt.visible = true
        }
      },
      handlePromptOk() {

        let { value } = this.prompt
        // 判断有没有重名

        let filterList = this.treeData.filter(i => i.title === value)
        if (filterList.length > 0) {
          this.$confirm({
            content: `${value} 已存在,是否覆盖?`,
            onOk: () => {
              this.prompt.visible = false
              filterList[0].records = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
              this.saveToLocalStore()
              this.$message.success('保存成功')
            }
          })
        } else {
          this.prompt.visible = false
          this.treeData.push({
            title: value,
            icon: this.treeIcon,
            records: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
          })
          this.saveToLocalStore()
          this.$message.success('保存成功')
        }


      },
      handleTreeSelect(idx, event) {
        if (event.selectedNodes[0]) {
          this.queryParamsModel = utils.cloneObject(event.selectedNodes[0].data.props.records)
        }
      },
      handleTreeRightClick(args) {
        this.$confirm({
          content: '是否删除当前查询?',
          onOk: () => {
            let { node: { eventKey } } = args
            this.treeData.splice(Number.parseInt(eventKey.substring(2)), 1)
            this.saveToLocalStore()
            this.$message.success('删除成功')
          },
        })
      },

      // 将查询保存到 LocalStore 里
      saveToLocalStore() {
        this.$ls.set(this.saveCodeBefore + this.saveCode, this.treeData.map(item => {
          return { title: item.title, records: item.records }
        }))
      },

      isNullArray(array) {
394
        //判断是不是空数组对象
395
        if (!array || array.length === 0) {
396
397
          return true
        }
398
399
        if (array.length === 1) {
          let obj = array[0]
400
          if (!obj.field || (obj.val == null || obj.val === '') || !obj.rule) {
401
402
403
            return true
          }
        }
404
405
406
407
408
409
410
411
        return false
      },
      // 去掉数组中的空对象
      removeEmptyObject(array) {
        for (let i = 0; i < array.length; i++) {
          let item = array[i]
          if (item == null || Object.keys(item).length <= 0) {
            array.splice(i--, 1)
412
413
414
          } else {
            // 去掉特殊属性
            delete item.options
415
416
417
          }
        }
        return array
418
419
420
421
422
      }
    }
  }
</script>
423
424
<style lang="scss" scoped>
425
426
427
  .j-super-query-box {
    display: inline-block;
  }
428
429
  .j-super-query-modal {
430
431
432
433
434
435
436
437
438
439
440
441
442

    .j-super-query-history-card /deep/ {
      .ant-card-body,
      .ant-card-head-title {
        padding: 0;
      }

      .ant-card-head {
        padding: 4px 8px;
        min-height: initial;
      }
    }
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
    .j-super-query-history-empty /deep/ {
      .ant-empty-image {
        height: 80px;
        line-height: 80px;
        margin-bottom: 0;
      }

      img {
        width: 80px;
        height: 65px;
      }

      .ant-empty-description {
        color: #afafaf;
        margin: 8px 0;
      }
    }
461
462
463
464
465
466
467
468
469
470
471
    .j-super-query-history-tree /deep/ {
      .ant-tree-switcher {
        display: none;
      }

      .ant-tree-node-content-wrapper {
        width: 100%;
      }
    }

  }
472
473

</style>