@wp1001/ui 2.9.13
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.
- package/.env +6 -0
- package/@vant-D4fmGxs6.js +3891 -0
- package/index.js +8419 -0
- package/package.json +59 -0
- package/packages/assets/devtools-detector.js +2 -0
- package/packages/components/xarray/index.js +64 -0
- package/packages/components/xarray/xarray.vue +57 -0
- package/packages/components/xautorows/index.js +35 -0
- package/packages/components/xautorows/xautorows.vue +29 -0
- package/packages/components/xbutton/mobile.js +3 -0
- package/packages/components/xbutton/mobile.vue +9 -0
- package/packages/components/xbutton/pc.js +3 -0
- package/packages/components/xbutton/pc.vue +9 -0
- package/packages/components/xbuttons/mobile.js +51 -0
- package/packages/components/xbuttons/mobile.vue +12 -0
- package/packages/components/xbuttons/pc.js +51 -0
- package/packages/components/xbuttons/pc.vue +16 -0
- package/packages/components/xchart/constants.js +58 -0
- package/packages/components/xchart/index.js +263 -0
- package/packages/components/xchart/utils.js +121 -0
- package/packages/components/xchart/xchart.vue +173 -0
- package/packages/components/xcheckboxs/mobile.js +58 -0
- package/packages/components/xcheckboxs/mobile.vue +38 -0
- package/packages/components/xcheckboxs/pc.js +49 -0
- package/packages/components/xcheckboxs/pc.vue +42 -0
- package/packages/components/xcol/mobile.js +10 -0
- package/packages/components/xcol/mobile.vue +9 -0
- package/packages/components/xcol/pc.js +10 -0
- package/packages/components/xcol/pc.vue +9 -0
- package/packages/components/xdatepicker/mobile.js +71 -0
- package/packages/components/xdatepicker/mobile.vue +44 -0
- package/packages/components/xdatepicker/pc.js +9 -0
- package/packages/components/xdatepicker/pc.vue +12 -0
- package/packages/components/xdialog/mobile.js +60 -0
- package/packages/components/xdialog/mobile.vue +43 -0
- package/packages/components/xdialog/pc.js +64 -0
- package/packages/components/xdialog/pc.vue +51 -0
- package/packages/components/xdict/index.js +47 -0
- package/packages/components/xdict/xdict.vue +9 -0
- package/packages/components/xdistrictselect/mobile.js +79 -0
- package/packages/components/xdistrictselect/mobile.vue +28 -0
- package/packages/components/xdistrictselect/pc.js +127 -0
- package/packages/components/xdistrictselect/pc.vue +32 -0
- package/packages/components/xform/mobile.js +29 -0
- package/packages/components/xform/mobile.vue +43 -0
- package/packages/components/xform/pc.js +42 -0
- package/packages/components/xform/pc.vue +76 -0
- package/packages/components/xform/utils.js +95 -0
- package/packages/components/xformitem/mobile.js +56 -0
- package/packages/components/xformitem/mobile.vue +3 -0
- package/packages/components/xformitem/pc.js +72 -0
- package/packages/components/xformitem/pc.vue +10 -0
- package/packages/components/xformitem/utils.jsx +181 -0
- package/packages/components/xicon/mobile.js +35 -0
- package/packages/components/xicon/mobile.vue +9 -0
- package/packages/components/xicon/pc.js +35 -0
- package/packages/components/xicon/pc.vue +11 -0
- package/packages/components/xinfo/index.js +100 -0
- package/packages/components/xinfo/xinfo.vue +140 -0
- package/packages/components/xlooper/index.js +7 -0
- package/packages/components/xlooper/xlooper.vue +20 -0
- package/packages/components/xpagination/mobile.js +21 -0
- package/packages/components/xpagination/mobile.vue +31 -0
- package/packages/components/xpagination/pc.js +21 -0
- package/packages/components/xpagination/pc.vue +16 -0
- package/packages/components/xpicker/index.js +38 -0
- package/packages/components/xpicker/xpicker.vue +29 -0
- package/packages/components/xradios/mobile.js +40 -0
- package/packages/components/xradios/mobile.vue +22 -0
- package/packages/components/xradios/pc.js +53 -0
- package/packages/components/xradios/pc.vue +43 -0
- package/packages/components/xrow/mobile.js +9 -0
- package/packages/components/xrow/mobile.vue +23 -0
- package/packages/components/xrow/pc.js +9 -0
- package/packages/components/xrow/pc.vue +22 -0
- package/packages/components/xscan/mobile.js +24 -0
- package/packages/components/xscan/mobile.vue +21 -0
- package/packages/components/xscan/pc.js +20 -0
- package/packages/components/xscan/pc.vue +18 -0
- package/packages/components/xsearcher/index.js +198 -0
- package/packages/components/xsearcher/xsearcher.vue +170 -0
- package/packages/components/xselect/mobile.js +86 -0
- package/packages/components/xselect/mobile.vue +24 -0
- package/packages/components/xselect/pc.js +114 -0
- package/packages/components/xselect/pc.vue +55 -0
- package/packages/components/xselect/util.js +66 -0
- package/packages/components/xselectv2/index.js +91 -0
- package/packages/components/xselectv2/xselectv2.vue +46 -0
- package/packages/components/xtable/mobile.js +108 -0
- package/packages/components/xtable/mobile.vue +246 -0
- package/packages/components/xtable/pc.js +143 -0
- package/packages/components/xtable/pc.vue +421 -0
- package/packages/components/xtable/searcher.js +477 -0
- package/packages/components/xtable/searcher.jsx +330 -0
- package/packages/components/xtable/searcher.vue +133 -0
- package/packages/components/xtable/settings.js +80 -0
- package/packages/components/xtable/settings.vue +77 -0
- package/packages/components/xtable/utils.js +692 -0
- package/packages/components/xtabletools/mobile.js +25 -0
- package/packages/components/xtabletools/mobile.vue +126 -0
- package/packages/components/xtabletools/pc.js +18 -0
- package/packages/components/xtabletools/pc.vue +135 -0
- package/packages/components/xtablev2/index.js +53 -0
- package/packages/components/xtablev2/utils.jsx +214 -0
- package/packages/components/xtablev2/xtablev2.vue +147 -0
- package/packages/components/xtags/mobile.js +17 -0
- package/packages/components/xtags/mobile.vue +21 -0
- package/packages/components/xtags/pc.js +17 -0
- package/packages/components/xtags/pc.vue +22 -0
- package/packages/components/xtinymce/index.js +71 -0
- package/packages/components/xtinymce/xtinymce.vue +9 -0
- package/packages/components/xuploader/xfileuploader.js +48 -0
- package/packages/components/xuploader/xfileuploader.vue +54 -0
- package/packages/components/xuploader/ximageuploader.js +53 -0
- package/packages/components/xuploader/ximageuploader.vue +52 -0
- package/packages/comps.js +108 -0
- package/packages/controllers/BaseController.js +125 -0
- package/packages/controllers/CrudController.js +907 -0
- package/packages/controllers/TempCrudController.js +32 -0
- package/packages/controllers/index.js +15 -0
- package/packages/directives/el-table-infinite-scroll.js +55 -0
- package/packages/directives/index.js +5 -0
- package/packages/index.js +81 -0
- package/packages/index.scss +4 -0
- package/packages/layout/breadcrumb/breadcrumb.vue +31 -0
- package/packages/layout/breadcrumb/index.js +41 -0
- package/packages/layout/header/header.vue +281 -0
- package/packages/layout/header/inner.js +11 -0
- package/packages/layout/header/inner.vue +3 -0
- package/packages/layout/mobile-menu.vue +83 -0
- package/packages/layout/mobile-tabs.vue +54 -0
- package/packages/layout/pc.vue +85 -0
- package/packages/layout/screenlock/index.js +129 -0
- package/packages/layout/screenlock/screenlock.vue +85 -0
- package/packages/layout/sidebar/item.js +16 -0
- package/packages/layout/sidebar/item.vue +16 -0
- package/packages/layout/sidebar/menu.js +72 -0
- package/packages/layout/sidebar/menu.vue +106 -0
- package/packages/layout/sidebar/sidebar.vue +147 -0
- package/packages/layout/tagsview/ScrollPane.js +65 -0
- package/packages/layout/tagsview/ScrollPane.vue +24 -0
- package/packages/layout/tagsview/index.js +169 -0
- package/packages/layout/tagsview/index.vue +124 -0
- package/packages/plop/actions/make-fill-admin-partials-action.js +95 -0
- package/packages/plop/generators/make-admin-page.js +39 -0
- package/packages/plop/generators/make-database-admin-pages.js +84 -0
- package/packages/plop/generators/make-page-generator.js +52 -0
- package/packages/plop/generators/make-simple-page.js +20 -0
- package/packages/plop/plopfile.js +24 -0
- package/packages/plop/templates/admin_page/controller.js +3 -0
- package/packages/plop/templates/admin_page/model.js +24 -0
- package/packages/plop/templates/admin_page/{{snakeCase pagename}}-scoped.scss +3 -0
- package/packages/plop/templates/admin_page/{{snakeCase pagename}}.vue +11 -0
- package/packages/plop/templates/simple_page/controller.js +3 -0
- package/packages/plop/templates/simple_page/model.js +6 -0
- package/packages/plop/templates/simple_page/{{snakeCase pagename}}-scoped.scss +3 -0
- package/packages/plop/templates/simple_page/{{snakeCase pagename}}.vue +7 -0
- package/packages/plop/utils/index.js +168 -0
- package/packages/plop/utils/plop-utils.js +86 -0
- package/packages/styles/common.scss +137 -0
- package/packages/styles/element-ui.scss +142 -0
- package/packages/styles/vant.scss +133 -0
- package/packages/styles/variables.scss +23 -0
- package/packages/utils/crypt.js +24 -0
- package/packages/utils/decorators.js +67 -0
- package/packages/utils/disallowDevtools.js +53 -0
- package/packages/utils/effects.js +173 -0
- package/packages/utils/funcs.js +78 -0
- package/packages/utils/index.js +95 -0
- package/packages/utils/message.js +110 -0
- package/packages/utils/middlewares.js +86 -0
- package/packages/utils/model.js +71 -0
- package/packages/utils/modelUtils.js +203 -0
- package/packages/utils/request.js +57 -0
- package/packages/utils/site.js +33 -0
- package/packages/vite-plugins.js +141 -0
- package/publish.sh +12 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import render, { OPS, COMPONENT_OPS } from './searcher.jsx'
|
|
2
|
+
import { Message, Confirm, Prompt } from '../../utils/index.js'
|
|
3
|
+
|
|
4
|
+
const { storage } = StardustBrowser
|
|
5
|
+
const { deepCopy } = StardustJs.funcs
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
name: 'Searcher',
|
|
9
|
+
props: {
|
|
10
|
+
uid: String,
|
|
11
|
+
columns: Array,
|
|
12
|
+
config: Object
|
|
13
|
+
},
|
|
14
|
+
emits: ['search', 'save'],
|
|
15
|
+
data () {
|
|
16
|
+
return {
|
|
17
|
+
visible: false,
|
|
18
|
+
activeName: 'search',
|
|
19
|
+
sortableColumns: [],
|
|
20
|
+
sortOptions: [
|
|
21
|
+
{ text: '升序', value: 'asc' },
|
|
22
|
+
{ text: '降序', value: 'desc' }
|
|
23
|
+
],
|
|
24
|
+
sorts: [],
|
|
25
|
+
conditionNo: 1,
|
|
26
|
+
conditions: [],
|
|
27
|
+
expression: '',
|
|
28
|
+
viewName: '',
|
|
29
|
+
views: [],
|
|
30
|
+
tourGuide: {
|
|
31
|
+
visible: false,
|
|
32
|
+
steps: [
|
|
33
|
+
{
|
|
34
|
+
target: '.views-select', title: '1. 选择视图',
|
|
35
|
+
description: `
|
|
36
|
+
<div style="color: var(--el-color-danger)">视图,是一组查询条件。</div>
|
|
37
|
+
这里选择下拉框里的某个视图,然后可以利用此视图进行数据查询。<br><br>
|
|
38
|
+
如果还没有自定义的视图,则需要添加。鼠标放到下拉框上,点击下拉框右侧的小叉号,以取消选中当前的默认视图,然后才能去新增条件,并保存为新的视图。<br><br>
|
|
39
|
+
<div style="color: var(--el-color-success)">现在,请试着点击下拉框右侧的小叉号。</div>
|
|
40
|
+
`
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
target: '.add-condition', title: '2. 新增条件',
|
|
44
|
+
description: `
|
|
45
|
+
这里可添加任意多个查询条件,每个条件可:
|
|
46
|
+
<ol style="list-style: disc; padding-left: 13px;">
|
|
47
|
+
<li>选择任意字段</li>
|
|
48
|
+
<li>选择任意查询方式</li>
|
|
49
|
+
<li>填写任意值,或选择任意选项、时间</li>
|
|
50
|
+
</ol>
|
|
51
|
+
然后,任意组合这些查询条件,从而可进行任意查询。<br><br>
|
|
52
|
+
<div style="color: var(--el-color-success)">现在,请试着点击"新增条件"按钮。</div>
|
|
53
|
+
`
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
target: '.x-select.field-select', title: '3. 选择字段',
|
|
57
|
+
description: `
|
|
58
|
+
这里有所有你需要查看、操作的字段,可以选择其中任意一个。<br><br>
|
|
59
|
+
<div style="color: var(--el-color-success)">现在,请试着选择某个字段。</div>
|
|
60
|
+
`
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
target: '.x-select.condition-select', title: '4. 选择查询方式',
|
|
64
|
+
description: `
|
|
65
|
+
这里有所有你需要用到的查询方式,不同的字段类型对应着不同的查询方式,可选择提供的任意一个方式。<br><br>
|
|
66
|
+
<div style="color: var(--el-color-success)">现在,请试着选择某个查询方式。</div>
|
|
67
|
+
`
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
target: '.value-container', title: '5. 填写值/选择选项、时间',
|
|
71
|
+
description: `
|
|
72
|
+
这里填写你要查询的关键词,或选择对应的下拉选项,或选择时间。<br><br>
|
|
73
|
+
<div style="color: var(--el-color-success)">现在,请试着填写某个关键词,或选择某个选项、时间。</div>
|
|
74
|
+
`
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
target: '.condition-expression', title: '6. 组合查询条件',
|
|
78
|
+
description: `
|
|
79
|
+
鉴于你可以添加多个条件,每个条件可任意组合,且支持数学逻辑中的“与”、“或”关系。<br>
|
|
80
|
+
这里就需要明确表达出你想用哪几个条件来查询,并且这些条件是以什么样的方式来组合。<br>
|
|
81
|
+
示例如下:<br>
|
|
82
|
+
<ol style="list-style: disc; padding-left: 13px;">
|
|
83
|
+
<li>条件1、条件2、条件3同时成立,表达式为:<span style="color: var(--el-color-warning)">1 and 2 and 3</span></li>
|
|
84
|
+
<li>条件1、条件2同时成立,或者条件3成立,表达式为:<span style="color: var(--el-color-warning)">(1 and 2) or 3</span></li>
|
|
85
|
+
<li>条件1、条件2同时成立,或条件2、条件3同时成立,表达式为:<span style="color: var(--el-color-warning)">(1 and 2) or (2 and 3)</span></li>
|
|
86
|
+
</ol>
|
|
87
|
+
<div style="color: var(--el-color-primary)">你想简单查询,表达式就非常简单。如果你想复杂查询,那么表达式就需要按需填写了。</div>
|
|
88
|
+
<br>
|
|
89
|
+
<div style="color: var(--el-color-success)">
|
|
90
|
+
现在,请试着填写表达式。如果你刚刚只添加了一个条件,且其序号为1,那么这里的表达式暂时填写
|
|
91
|
+
<span style="color: var(--el-color-warning)">1</span>
|
|
92
|
+
就好
|
|
93
|
+
</div>
|
|
94
|
+
`
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
target: '.save-view', title: '7. 保存视图',
|
|
98
|
+
description: `
|
|
99
|
+
刚才你已经新增了若干个条件,并且填写了条件表达式。现在可以保存这些条件为视图,这样下次可以直接选择此视图方便地查询数据。<br><br>
|
|
100
|
+
<div style="color: var(--el-color-success)">现在,点击“保存当前视图”按钮,并为其填写一个合适的名字。</div>
|
|
101
|
+
`
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
target: '.searcher.pc-x-drawer .el-drawer__footer .el-button--primary', title: '8. 查询数据',
|
|
105
|
+
description: `
|
|
106
|
+
现在,上面已经有了查询条件,试着点击“查询”按钮,即可查询数据了。
|
|
107
|
+
`
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
computed: {
|
|
114
|
+
key () {
|
|
115
|
+
return `Searcher[${this.uid}]`
|
|
116
|
+
},
|
|
117
|
+
currentView () {
|
|
118
|
+
return this.views.find(v => v.name === this.viewName)
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
watch: {
|
|
122
|
+
config: 'init'
|
|
123
|
+
},
|
|
124
|
+
created () {
|
|
125
|
+
this.init()
|
|
126
|
+
},
|
|
127
|
+
render,
|
|
128
|
+
methods: {
|
|
129
|
+
init () {
|
|
130
|
+
let { views = [], viewName, ...others } = this.uid && storage.local.getJson(this.key, {}) || {}
|
|
131
|
+
if (this.config.views) {
|
|
132
|
+
this.config.views.forEach(view => view.is_system = true)
|
|
133
|
+
views = this.config.views.concat(views)
|
|
134
|
+
}
|
|
135
|
+
if (views.length && !viewName) viewName = views[0].name
|
|
136
|
+
Object.assign(this, { views, viewName })
|
|
137
|
+
|
|
138
|
+
const settings = storage.local.getJson('Settings[' + this.uid + ']')
|
|
139
|
+
if (settings?.viewName) this.viewName = settings.viewName
|
|
140
|
+
|
|
141
|
+
this.sortableColumns = this.columns.filter(col => !col.virtual)
|
|
142
|
+
|
|
143
|
+
if (this.viewName) {
|
|
144
|
+
this.handleSelectView(this.viewName)
|
|
145
|
+
} else {
|
|
146
|
+
this.setCurrentView(this.config.traditional ? this.config : others)
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
open () {
|
|
150
|
+
this.visible = true
|
|
151
|
+
},
|
|
152
|
+
close () {
|
|
153
|
+
this.visible = false
|
|
154
|
+
},
|
|
155
|
+
getCurrentView () {
|
|
156
|
+
return {
|
|
157
|
+
sorts: this.sorts,
|
|
158
|
+
conditionNo: this.conditionNo,
|
|
159
|
+
conditions: this.conditions.map(con => {
|
|
160
|
+
const { item, ops, component, ...others } = con
|
|
161
|
+
return others
|
|
162
|
+
}),
|
|
163
|
+
expression: this.expression
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
saveCache () {
|
|
167
|
+
const cache = { views: this.views.filter(view => !view.is_system) }
|
|
168
|
+
if (this.viewName && this.currentView) {
|
|
169
|
+
cache.viewName = this.viewName
|
|
170
|
+
Object.assign(this.currentView, this.getCurrentView())
|
|
171
|
+
} else {
|
|
172
|
+
Object.assign(cache, this.getCurrentView())
|
|
173
|
+
}
|
|
174
|
+
storage.local.setJson(this.key, cache)
|
|
175
|
+
},
|
|
176
|
+
setCurrentView (view) {
|
|
177
|
+
if (!view) return
|
|
178
|
+
view.conditions?.forEach(con => {
|
|
179
|
+
const { prop, op, value, universal } = con
|
|
180
|
+
con.item = this.columns.find(col => col.prop === prop)
|
|
181
|
+
this.handleSelectField(con, prop)
|
|
182
|
+
this.handleSelectOp(con, op)
|
|
183
|
+
con.value = value
|
|
184
|
+
const comp = con.item.comp || con.component
|
|
185
|
+
con.ops = COMPONENT_OPS[universal ? 'universal' : comp].map(key => OPS[key])
|
|
186
|
+
})
|
|
187
|
+
if (!view.conditionNo && view.conditions?.length) {
|
|
188
|
+
view.conditionNo = Math.max.apply(null, view.conditions.map(con => con.no)) + 1
|
|
189
|
+
}
|
|
190
|
+
this.viewName = view.name
|
|
191
|
+
Object.assign(this, view)
|
|
192
|
+
},
|
|
193
|
+
handleSearch () {
|
|
194
|
+
let params = null
|
|
195
|
+
try {
|
|
196
|
+
params = this.calcParams()
|
|
197
|
+
} catch (err) {
|
|
198
|
+
Message.w(err.toString())
|
|
199
|
+
return false
|
|
200
|
+
}
|
|
201
|
+
this.uid && params && this.saveCache()
|
|
202
|
+
params = params || { where: {} }
|
|
203
|
+
params.page = 1
|
|
204
|
+
this.$emit('search', params)
|
|
205
|
+
this.visible = false
|
|
206
|
+
return true
|
|
207
|
+
},
|
|
208
|
+
handleReset () {
|
|
209
|
+
const view = {
|
|
210
|
+
sorts: [],
|
|
211
|
+
conditionNo: 1,
|
|
212
|
+
conditions: [],
|
|
213
|
+
expression: ''
|
|
214
|
+
}
|
|
215
|
+
Object.assign(this, view)
|
|
216
|
+
this.setCurrentView(view)
|
|
217
|
+
},
|
|
218
|
+
calcParams () {
|
|
219
|
+
const tree = this.calcTree()
|
|
220
|
+
if (!tree) return
|
|
221
|
+
const parse = (tree, where) => {
|
|
222
|
+
const branch = []
|
|
223
|
+
const type = '[Op.' + tree.type + ']'
|
|
224
|
+
where[type] = branch
|
|
225
|
+
for (let item of tree.items) {
|
|
226
|
+
if (typeof item === 'string') {
|
|
227
|
+
const condition = this.conditions.find(con => con.no === item * 1)
|
|
228
|
+
if (!condition) {
|
|
229
|
+
throw '条件不存在: ' + item
|
|
230
|
+
} else {
|
|
231
|
+
if (!this.checkFilled(condition)) {
|
|
232
|
+
if (this.config.traditional || this.config.ignoreUnfilled) continue
|
|
233
|
+
throw '条件不完整: ' + item
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
branch.push(this.parseCondition(condition))
|
|
237
|
+
} else {
|
|
238
|
+
const sub = {}
|
|
239
|
+
branch.push(sub)
|
|
240
|
+
parse(item, sub)
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (!branch.length) delete where[type]
|
|
244
|
+
}
|
|
245
|
+
const where = {}
|
|
246
|
+
parse(tree, where)
|
|
247
|
+
const params = { where }
|
|
248
|
+
if (this.sorts.length) {
|
|
249
|
+
params.order = deepCopy(this.sorts)
|
|
250
|
+
}
|
|
251
|
+
return params
|
|
252
|
+
},
|
|
253
|
+
calcTree (normalize = true) {
|
|
254
|
+
const expression = this.expression.trim()
|
|
255
|
+
.replaceAll('&&', 'and')
|
|
256
|
+
.replaceAll('||', 'or')
|
|
257
|
+
.replace(/and/ig, 'and')
|
|
258
|
+
.replace(/or/ig, 'or')
|
|
259
|
+
if (!expression) return null
|
|
260
|
+
const symbols = expression.split(/(\(|\)|\s)/).filter(p => p.trim())
|
|
261
|
+
|
|
262
|
+
const calc = (tree, symbols) => {
|
|
263
|
+
while (symbols.length) {
|
|
264
|
+
const ele = symbols.shift()
|
|
265
|
+
if (['and', 'or'].includes(ele)) {
|
|
266
|
+
if (tree.type && tree.type !== ele) {
|
|
267
|
+
throw '串联不同逻辑表达式请使用小括号区分'
|
|
268
|
+
}
|
|
269
|
+
tree.type = ele
|
|
270
|
+
} else if (ele === '(') {
|
|
271
|
+
const item = { type: '', items: [] }
|
|
272
|
+
tree.items.push(item)
|
|
273
|
+
item._parent = tree
|
|
274
|
+
calc(item, symbols)
|
|
275
|
+
break
|
|
276
|
+
} else if (ele === ')') {
|
|
277
|
+
calc(tree._parent, symbols)
|
|
278
|
+
delete tree._parent
|
|
279
|
+
} else {
|
|
280
|
+
tree.items.push(ele)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const tree = { type: '', items: [] }
|
|
285
|
+
calc(tree, symbols)
|
|
286
|
+
if (normalize) {
|
|
287
|
+
tree.type ||= 'and'
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return tree
|
|
291
|
+
},
|
|
292
|
+
calcExpression (tree) {
|
|
293
|
+
const calc = (branch) => {
|
|
294
|
+
if (!branch) return ''
|
|
295
|
+
if (typeof branch === 'string') return branch
|
|
296
|
+
const { type, items } = branch
|
|
297
|
+
if (!items.length) return ''
|
|
298
|
+
return '(' + items.map(calc).filter(e => e).join(' ' + type + ' ') + ')'
|
|
299
|
+
}
|
|
300
|
+
let expression = calc(tree).slice(1, -1)
|
|
301
|
+
while (/\(\d+\)/.test(expression)) {
|
|
302
|
+
expression = expression.replace(/\((\d+)\)/g, '$1')
|
|
303
|
+
}
|
|
304
|
+
return expression
|
|
305
|
+
},
|
|
306
|
+
parseCondition (condition) {
|
|
307
|
+
let { item, component, prop, op, value } = condition
|
|
308
|
+
const where = {}
|
|
309
|
+
if (op === 'special') {
|
|
310
|
+
const isNot = value.startsWith('NOT_')
|
|
311
|
+
const isNe = value.startsWith('NE_')
|
|
312
|
+
if (value.includes('NULL')) {
|
|
313
|
+
value = null
|
|
314
|
+
} else if (value.includes('BLANK')) {
|
|
315
|
+
value = ''
|
|
316
|
+
}
|
|
317
|
+
if (isNot) {
|
|
318
|
+
value = { '[Op.not]': value }
|
|
319
|
+
} else if (isNe) {
|
|
320
|
+
value = { '[Op.ne]': value }
|
|
321
|
+
}
|
|
322
|
+
where[prop] = value
|
|
323
|
+
return where
|
|
324
|
+
}
|
|
325
|
+
if (op === 'like' || op === 'notLike') {
|
|
326
|
+
value = '%' + value + '%'
|
|
327
|
+
}
|
|
328
|
+
if (op === 'in' || op === 'notIn') {
|
|
329
|
+
if (!item.options) {
|
|
330
|
+
value = value.split(',')
|
|
331
|
+
if (component === 'ElInputNumber' || component === 'el-input-number' || condition.type === 'number') {
|
|
332
|
+
value = value.map(Number)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
where[prop] = { [`[Op.${op}]`]: value }
|
|
337
|
+
return where
|
|
338
|
+
},
|
|
339
|
+
checkFilled (condition) {
|
|
340
|
+
if (!condition.prop || !condition.op) {
|
|
341
|
+
return false
|
|
342
|
+
}
|
|
343
|
+
const value = Array.isArray(condition.value) ? condition.value : [condition.value]
|
|
344
|
+
return value.length && value.every(ele => {
|
|
345
|
+
return typeof ele !== 'string' || ele.length
|
|
346
|
+
})
|
|
347
|
+
},
|
|
348
|
+
handleAdd () {
|
|
349
|
+
this.conditions.push({
|
|
350
|
+
no: this.conditionNo ++,
|
|
351
|
+
prop: '',
|
|
352
|
+
op: '',
|
|
353
|
+
value: '',
|
|
354
|
+
component: 'ElInput',
|
|
355
|
+
ops: [],
|
|
356
|
+
item: {}
|
|
357
|
+
})
|
|
358
|
+
},
|
|
359
|
+
handleDelete (index) {
|
|
360
|
+
const no = this.conditions[index].no + ''
|
|
361
|
+
const tree = this.calcTree(false)
|
|
362
|
+
const remove = (branch) => {
|
|
363
|
+
if (!branch) return
|
|
364
|
+
for (let i = branch.items.length - 1; i >= 0; i--) {
|
|
365
|
+
if (branch.items[i] === no) {
|
|
366
|
+
branch.items.splice(i, 1)
|
|
367
|
+
} else if (typeof branch.items[i] === 'object') {
|
|
368
|
+
remove(branch.items[i])
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
remove(tree)
|
|
373
|
+
this.expression = this.calcExpression(tree)
|
|
374
|
+
this.conditions.splice(index, 1)
|
|
375
|
+
},
|
|
376
|
+
handleSelectField (condition, value) {
|
|
377
|
+
condition.value = ''
|
|
378
|
+
condition.prop = value
|
|
379
|
+
condition.item = this.columns.find(col => col.prop === condition.prop) || {}
|
|
380
|
+
const { options, type, formAttrs = {} } = condition.item
|
|
381
|
+
const config = { ...condition.item, ...formAttrs }
|
|
382
|
+
const {
|
|
383
|
+
comp, universal,
|
|
384
|
+
visible, canAdd, canEdit, required, slot, span,
|
|
385
|
+
tableAttrs, formAttrs: fa, tagTypes, tagValues, width, minWidth,
|
|
386
|
+
disabled, readonly,
|
|
387
|
+
...others
|
|
388
|
+
} = config
|
|
389
|
+
others.clearable ??= true
|
|
390
|
+
condition.config = others
|
|
391
|
+
condition.component = comp ||
|
|
392
|
+
options && 'XSelect' ||
|
|
393
|
+
type === 'number' && 'ElInputNumber' ||
|
|
394
|
+
'ElInput'
|
|
395
|
+
condition.ops = COMPONENT_OPS[universal ? 'universal' : condition.component].map(key => OPS[key])
|
|
396
|
+
condition.op = condition.ops[0].value
|
|
397
|
+
if (condition.component === 'ElDatePicker') {
|
|
398
|
+
condition.component = 'ElInput'
|
|
399
|
+
others.type = 'date'
|
|
400
|
+
}
|
|
401
|
+
if (others.type === 'textarea') delete others.type
|
|
402
|
+
},
|
|
403
|
+
handleSelectOp (condition, value) {
|
|
404
|
+
condition.op = value
|
|
405
|
+
if (value === 'between') {
|
|
406
|
+
condition.value = ['', '']
|
|
407
|
+
} else if (['in', 'notIn'].includes(value)) {
|
|
408
|
+
condition.value = []
|
|
409
|
+
}
|
|
410
|
+
if (
|
|
411
|
+
value === 'special'
|
|
412
|
+
|| !['between', 'in', 'notIn'].includes(value) && Array.isArray(value)
|
|
413
|
+
) {
|
|
414
|
+
condition.value = ''
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
handleSelectView (name) {
|
|
418
|
+
if (!name) {
|
|
419
|
+
this.handleReset()
|
|
420
|
+
} else {
|
|
421
|
+
const view = this.views.find(v => v.name === name)
|
|
422
|
+
if (!view) {
|
|
423
|
+
this.viewName = ''
|
|
424
|
+
this.handleReset()
|
|
425
|
+
return this.saveCache()
|
|
426
|
+
}
|
|
427
|
+
this.setCurrentView(deepCopy(view))
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
async handleSaveView () {
|
|
431
|
+
const view = this.getCurrentView()
|
|
432
|
+
let isSystem = false
|
|
433
|
+
if (this.viewName && this.currentView) {
|
|
434
|
+
isSystem = this.currentView.is_system
|
|
435
|
+
if (!isSystem) {
|
|
436
|
+
Object.assign(this.currentView, view)
|
|
437
|
+
this.saveCache()
|
|
438
|
+
Message.s('视图保存成功')
|
|
439
|
+
return
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
let name = await Prompt({
|
|
443
|
+
title: '提示',
|
|
444
|
+
message: (isSystem ? '系统视图不可修改,可保存为新视图,' : '') + '请输入新视图名称'
|
|
445
|
+
})
|
|
446
|
+
name = name.trim()
|
|
447
|
+
if (!name) return
|
|
448
|
+
if (this.views.some(v => v.name === name)) {
|
|
449
|
+
return Message.w('视图名称 ' + name + ' 已存在,请重新输入')
|
|
450
|
+
}
|
|
451
|
+
this.views.push({ name, ...view })
|
|
452
|
+
this.viewName = name
|
|
453
|
+
this.handleSelectView(name)
|
|
454
|
+
this.saveCache()
|
|
455
|
+
Message.s('视图保存成功')
|
|
456
|
+
},
|
|
457
|
+
async handleDeleteView (view, index, e) {
|
|
458
|
+
e.stopPropagation()
|
|
459
|
+
if (!await Confirm.w({ title: '提示', message: `确定删除查询视图 ${view.name} 吗?` })) return
|
|
460
|
+
if (this.viewName === view.name) {
|
|
461
|
+
this.viewName = ''
|
|
462
|
+
this.handleReset()
|
|
463
|
+
}
|
|
464
|
+
this.views.splice(index, 1)
|
|
465
|
+
this.saveCache()
|
|
466
|
+
Message.s(`视图 [${view.name}] 已删除`)
|
|
467
|
+
},
|
|
468
|
+
handleSearchView (view) {
|
|
469
|
+
this.setCurrentView(view)
|
|
470
|
+
if (!this.handleSearch()) return
|
|
471
|
+
this.$emit('save', { viewName: view.name })
|
|
472
|
+
},
|
|
473
|
+
handleAddSort () {
|
|
474
|
+
this.sorts.push([this.sortableColumns[0].prop, 'asc'])
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|