@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.
Files changed (177) hide show
  1. package/.env +6 -0
  2. package/@vant-D4fmGxs6.js +3891 -0
  3. package/index.js +8419 -0
  4. package/package.json +59 -0
  5. package/packages/assets/devtools-detector.js +2 -0
  6. package/packages/components/xarray/index.js +64 -0
  7. package/packages/components/xarray/xarray.vue +57 -0
  8. package/packages/components/xautorows/index.js +35 -0
  9. package/packages/components/xautorows/xautorows.vue +29 -0
  10. package/packages/components/xbutton/mobile.js +3 -0
  11. package/packages/components/xbutton/mobile.vue +9 -0
  12. package/packages/components/xbutton/pc.js +3 -0
  13. package/packages/components/xbutton/pc.vue +9 -0
  14. package/packages/components/xbuttons/mobile.js +51 -0
  15. package/packages/components/xbuttons/mobile.vue +12 -0
  16. package/packages/components/xbuttons/pc.js +51 -0
  17. package/packages/components/xbuttons/pc.vue +16 -0
  18. package/packages/components/xchart/constants.js +58 -0
  19. package/packages/components/xchart/index.js +263 -0
  20. package/packages/components/xchart/utils.js +121 -0
  21. package/packages/components/xchart/xchart.vue +173 -0
  22. package/packages/components/xcheckboxs/mobile.js +58 -0
  23. package/packages/components/xcheckboxs/mobile.vue +38 -0
  24. package/packages/components/xcheckboxs/pc.js +49 -0
  25. package/packages/components/xcheckboxs/pc.vue +42 -0
  26. package/packages/components/xcol/mobile.js +10 -0
  27. package/packages/components/xcol/mobile.vue +9 -0
  28. package/packages/components/xcol/pc.js +10 -0
  29. package/packages/components/xcol/pc.vue +9 -0
  30. package/packages/components/xdatepicker/mobile.js +71 -0
  31. package/packages/components/xdatepicker/mobile.vue +44 -0
  32. package/packages/components/xdatepicker/pc.js +9 -0
  33. package/packages/components/xdatepicker/pc.vue +12 -0
  34. package/packages/components/xdialog/mobile.js +60 -0
  35. package/packages/components/xdialog/mobile.vue +43 -0
  36. package/packages/components/xdialog/pc.js +64 -0
  37. package/packages/components/xdialog/pc.vue +51 -0
  38. package/packages/components/xdict/index.js +47 -0
  39. package/packages/components/xdict/xdict.vue +9 -0
  40. package/packages/components/xdistrictselect/mobile.js +79 -0
  41. package/packages/components/xdistrictselect/mobile.vue +28 -0
  42. package/packages/components/xdistrictselect/pc.js +127 -0
  43. package/packages/components/xdistrictselect/pc.vue +32 -0
  44. package/packages/components/xform/mobile.js +29 -0
  45. package/packages/components/xform/mobile.vue +43 -0
  46. package/packages/components/xform/pc.js +42 -0
  47. package/packages/components/xform/pc.vue +76 -0
  48. package/packages/components/xform/utils.js +95 -0
  49. package/packages/components/xformitem/mobile.js +56 -0
  50. package/packages/components/xformitem/mobile.vue +3 -0
  51. package/packages/components/xformitem/pc.js +72 -0
  52. package/packages/components/xformitem/pc.vue +10 -0
  53. package/packages/components/xformitem/utils.jsx +181 -0
  54. package/packages/components/xicon/mobile.js +35 -0
  55. package/packages/components/xicon/mobile.vue +9 -0
  56. package/packages/components/xicon/pc.js +35 -0
  57. package/packages/components/xicon/pc.vue +11 -0
  58. package/packages/components/xinfo/index.js +100 -0
  59. package/packages/components/xinfo/xinfo.vue +140 -0
  60. package/packages/components/xlooper/index.js +7 -0
  61. package/packages/components/xlooper/xlooper.vue +20 -0
  62. package/packages/components/xpagination/mobile.js +21 -0
  63. package/packages/components/xpagination/mobile.vue +31 -0
  64. package/packages/components/xpagination/pc.js +21 -0
  65. package/packages/components/xpagination/pc.vue +16 -0
  66. package/packages/components/xpicker/index.js +38 -0
  67. package/packages/components/xpicker/xpicker.vue +29 -0
  68. package/packages/components/xradios/mobile.js +40 -0
  69. package/packages/components/xradios/mobile.vue +22 -0
  70. package/packages/components/xradios/pc.js +53 -0
  71. package/packages/components/xradios/pc.vue +43 -0
  72. package/packages/components/xrow/mobile.js +9 -0
  73. package/packages/components/xrow/mobile.vue +23 -0
  74. package/packages/components/xrow/pc.js +9 -0
  75. package/packages/components/xrow/pc.vue +22 -0
  76. package/packages/components/xscan/mobile.js +24 -0
  77. package/packages/components/xscan/mobile.vue +21 -0
  78. package/packages/components/xscan/pc.js +20 -0
  79. package/packages/components/xscan/pc.vue +18 -0
  80. package/packages/components/xsearcher/index.js +198 -0
  81. package/packages/components/xsearcher/xsearcher.vue +170 -0
  82. package/packages/components/xselect/mobile.js +86 -0
  83. package/packages/components/xselect/mobile.vue +24 -0
  84. package/packages/components/xselect/pc.js +114 -0
  85. package/packages/components/xselect/pc.vue +55 -0
  86. package/packages/components/xselect/util.js +66 -0
  87. package/packages/components/xselectv2/index.js +91 -0
  88. package/packages/components/xselectv2/xselectv2.vue +46 -0
  89. package/packages/components/xtable/mobile.js +108 -0
  90. package/packages/components/xtable/mobile.vue +246 -0
  91. package/packages/components/xtable/pc.js +143 -0
  92. package/packages/components/xtable/pc.vue +421 -0
  93. package/packages/components/xtable/searcher.js +477 -0
  94. package/packages/components/xtable/searcher.jsx +330 -0
  95. package/packages/components/xtable/searcher.vue +133 -0
  96. package/packages/components/xtable/settings.js +80 -0
  97. package/packages/components/xtable/settings.vue +77 -0
  98. package/packages/components/xtable/utils.js +692 -0
  99. package/packages/components/xtabletools/mobile.js +25 -0
  100. package/packages/components/xtabletools/mobile.vue +126 -0
  101. package/packages/components/xtabletools/pc.js +18 -0
  102. package/packages/components/xtabletools/pc.vue +135 -0
  103. package/packages/components/xtablev2/index.js +53 -0
  104. package/packages/components/xtablev2/utils.jsx +214 -0
  105. package/packages/components/xtablev2/xtablev2.vue +147 -0
  106. package/packages/components/xtags/mobile.js +17 -0
  107. package/packages/components/xtags/mobile.vue +21 -0
  108. package/packages/components/xtags/pc.js +17 -0
  109. package/packages/components/xtags/pc.vue +22 -0
  110. package/packages/components/xtinymce/index.js +71 -0
  111. package/packages/components/xtinymce/xtinymce.vue +9 -0
  112. package/packages/components/xuploader/xfileuploader.js +48 -0
  113. package/packages/components/xuploader/xfileuploader.vue +54 -0
  114. package/packages/components/xuploader/ximageuploader.js +53 -0
  115. package/packages/components/xuploader/ximageuploader.vue +52 -0
  116. package/packages/comps.js +108 -0
  117. package/packages/controllers/BaseController.js +125 -0
  118. package/packages/controllers/CrudController.js +907 -0
  119. package/packages/controllers/TempCrudController.js +32 -0
  120. package/packages/controllers/index.js +15 -0
  121. package/packages/directives/el-table-infinite-scroll.js +55 -0
  122. package/packages/directives/index.js +5 -0
  123. package/packages/index.js +81 -0
  124. package/packages/index.scss +4 -0
  125. package/packages/layout/breadcrumb/breadcrumb.vue +31 -0
  126. package/packages/layout/breadcrumb/index.js +41 -0
  127. package/packages/layout/header/header.vue +281 -0
  128. package/packages/layout/header/inner.js +11 -0
  129. package/packages/layout/header/inner.vue +3 -0
  130. package/packages/layout/mobile-menu.vue +83 -0
  131. package/packages/layout/mobile-tabs.vue +54 -0
  132. package/packages/layout/pc.vue +85 -0
  133. package/packages/layout/screenlock/index.js +129 -0
  134. package/packages/layout/screenlock/screenlock.vue +85 -0
  135. package/packages/layout/sidebar/item.js +16 -0
  136. package/packages/layout/sidebar/item.vue +16 -0
  137. package/packages/layout/sidebar/menu.js +72 -0
  138. package/packages/layout/sidebar/menu.vue +106 -0
  139. package/packages/layout/sidebar/sidebar.vue +147 -0
  140. package/packages/layout/tagsview/ScrollPane.js +65 -0
  141. package/packages/layout/tagsview/ScrollPane.vue +24 -0
  142. package/packages/layout/tagsview/index.js +169 -0
  143. package/packages/layout/tagsview/index.vue +124 -0
  144. package/packages/plop/actions/make-fill-admin-partials-action.js +95 -0
  145. package/packages/plop/generators/make-admin-page.js +39 -0
  146. package/packages/plop/generators/make-database-admin-pages.js +84 -0
  147. package/packages/plop/generators/make-page-generator.js +52 -0
  148. package/packages/plop/generators/make-simple-page.js +20 -0
  149. package/packages/plop/plopfile.js +24 -0
  150. package/packages/plop/templates/admin_page/controller.js +3 -0
  151. package/packages/plop/templates/admin_page/model.js +24 -0
  152. package/packages/plop/templates/admin_page/{{snakeCase pagename}}-scoped.scss +3 -0
  153. package/packages/plop/templates/admin_page/{{snakeCase pagename}}.vue +11 -0
  154. package/packages/plop/templates/simple_page/controller.js +3 -0
  155. package/packages/plop/templates/simple_page/model.js +6 -0
  156. package/packages/plop/templates/simple_page/{{snakeCase pagename}}-scoped.scss +3 -0
  157. package/packages/plop/templates/simple_page/{{snakeCase pagename}}.vue +7 -0
  158. package/packages/plop/utils/index.js +168 -0
  159. package/packages/plop/utils/plop-utils.js +86 -0
  160. package/packages/styles/common.scss +137 -0
  161. package/packages/styles/element-ui.scss +142 -0
  162. package/packages/styles/vant.scss +133 -0
  163. package/packages/styles/variables.scss +23 -0
  164. package/packages/utils/crypt.js +24 -0
  165. package/packages/utils/decorators.js +67 -0
  166. package/packages/utils/disallowDevtools.js +53 -0
  167. package/packages/utils/effects.js +173 -0
  168. package/packages/utils/funcs.js +78 -0
  169. package/packages/utils/index.js +95 -0
  170. package/packages/utils/message.js +110 -0
  171. package/packages/utils/middlewares.js +86 -0
  172. package/packages/utils/model.js +71 -0
  173. package/packages/utils/modelUtils.js +203 -0
  174. package/packages/utils/request.js +57 -0
  175. package/packages/utils/site.js +33 -0
  176. package/packages/vite-plugins.js +141 -0
  177. 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
+ }