lambo-design-bi 0.0.253 → 0.0.255
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/bi/widget/page/child-page-tm.vue +14 -6
- package/bi/widget/page/index-page-tm.vue +14 -6
- package/bi/widget/search/search-form.vue +388 -36
- package/bi/widget/search/search-item.vue +14 -2
- package/bi/widget/search/tag-select.vue +100 -0
- package/bi/widget/table/paging-table.vue +25 -1
- package/bi/widget/util/dimension-state.js +22 -0
- package/bi/widget/util/dimension-util.js +90 -0
- package/bi/widget/util/event-bus.js +3 -1
- package/package.json +1 -1
- package/pub/charts/factory/options.js +8 -6
- package/pub/number-info/number-info.vue +1 -11
|
@@ -30,6 +30,7 @@ import { deepCopy } from "@lambo-design/shared/utils/assist"
|
|
|
30
30
|
import { getWidgetName } from '../util/widget-map'
|
|
31
31
|
import { setRouteCfg2Search, getInitSearchRes, getSearchFormRes } from './util/common'
|
|
32
32
|
import { EventBus, EVENT_TYPES } from '../util/event-bus'
|
|
33
|
+
import { clearDimensionState } from '../util/dimension-state'
|
|
33
34
|
|
|
34
35
|
export default {
|
|
35
36
|
name: 'BiChildPageTm',
|
|
@@ -116,6 +117,9 @@ export default {
|
|
|
116
117
|
}
|
|
117
118
|
},
|
|
118
119
|
created() {
|
|
120
|
+
// 每页开始先清空维度列显隐单例,避免从上一个维度报表带入残留;
|
|
121
|
+
// 本页若有维度查询表单,其 created 会重新写入
|
|
122
|
+
clearDimensionState()
|
|
119
123
|
this.getConfig()
|
|
120
124
|
},
|
|
121
125
|
mounted() {
|
|
@@ -135,16 +139,20 @@ export default {
|
|
|
135
139
|
},
|
|
136
140
|
computed: {
|
|
137
141
|
shouldShowLamboIndicator() {
|
|
138
|
-
if (!this.childPageWidget ||
|
|
139
|
-
!this.childPageWidget.search ||
|
|
140
|
-
!this.childPageWidget.search.widgets) {
|
|
142
|
+
if (!this.childPageWidget || !this.childPageWidget.search) {
|
|
141
143
|
return false
|
|
142
144
|
}
|
|
143
|
-
// 过滤出searchType不等于'A0'
|
|
144
|
-
const
|
|
145
|
+
// 过滤出searchType不等于'A0'的普通查询条件
|
|
146
|
+
const normalWidgets = (this.childPageWidget.search.widgets || []).filter(item =>
|
|
145
147
|
item && item.options && item.options.searchType !== 'A0'
|
|
146
148
|
)
|
|
147
|
-
|
|
149
|
+
if (normalWidgets.length > 0) {
|
|
150
|
+
return true
|
|
151
|
+
}
|
|
152
|
+
// 只有维度条件时也展示(v1只取dims[0])
|
|
153
|
+
const dims = (this.childPageWidget.search.options && this.childPageWidget.search.options.dims) || []
|
|
154
|
+
return dims.length > 0 && (((dims[0].widgets || []).length > 0) ||
|
|
155
|
+
((dims[0].options && dims[0].options.dataList) || []).length > 0)
|
|
148
156
|
}
|
|
149
157
|
},
|
|
150
158
|
beforeDestroy() {
|
|
@@ -27,6 +27,7 @@ import { deepCopy } from "@lambo-design/shared/utils/assist"
|
|
|
27
27
|
import { getWidgetName } from '../util/widget-map'
|
|
28
28
|
import { setRouteCfg2Search, getInitSearchRes, getSearchFormRes } from './util/common'
|
|
29
29
|
import { EventBus, EVENT_TYPES } from '../util/event-bus'
|
|
30
|
+
import { clearDimensionState } from '../util/dimension-state'
|
|
30
31
|
|
|
31
32
|
export default {
|
|
32
33
|
name: 'BiIndexPageTm',
|
|
@@ -110,6 +111,9 @@ export default {
|
|
|
110
111
|
}
|
|
111
112
|
},
|
|
112
113
|
created() {
|
|
114
|
+
// 每页开始先清空维度列显隐单例,避免从上一个维度报表带入残留;
|
|
115
|
+
// 本页若有维度查询表单,其 created 会重新写入
|
|
116
|
+
clearDimensionState()
|
|
113
117
|
this.getConfig()
|
|
114
118
|
},
|
|
115
119
|
mounted() {
|
|
@@ -119,16 +123,20 @@ export default {
|
|
|
119
123
|
},
|
|
120
124
|
computed: {
|
|
121
125
|
shouldShowLamboIndicator() {
|
|
122
|
-
if (!this.pageWidget ||
|
|
123
|
-
!this.pageWidget.search ||
|
|
124
|
-
!this.pageWidget.search.widgets) {
|
|
126
|
+
if (!this.pageWidget || !this.pageWidget.search) {
|
|
125
127
|
return false
|
|
126
128
|
}
|
|
127
|
-
// 过滤出searchType不等于'A0'
|
|
128
|
-
const
|
|
129
|
+
// 过滤出searchType不等于'A0'的普通查询条件
|
|
130
|
+
const normalWidgets = (this.pageWidget.search.widgets || []).filter(item =>
|
|
129
131
|
item && item.options && item.options.searchType !== 'A0'
|
|
130
132
|
)
|
|
131
|
-
|
|
133
|
+
if (normalWidgets.length > 0) {
|
|
134
|
+
return true
|
|
135
|
+
}
|
|
136
|
+
// 只有维度条件时也展示(v1只取dims[0])
|
|
137
|
+
const dims = (this.pageWidget.search.options && this.pageWidget.search.options.dims) || []
|
|
138
|
+
return dims.length > 0 && (((dims[0].widgets || []).length > 0) ||
|
|
139
|
+
((dims[0].options && dims[0].options.dataList) || []).length > 0)
|
|
132
140
|
}
|
|
133
141
|
},
|
|
134
142
|
beforeDestroy() {
|
|
@@ -1,12 +1,39 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="bi-search-form" v-if="
|
|
2
|
+
<div class="bi-search-form" v-if="hasSearchContent">
|
|
3
3
|
<LamboQueryFilter :default-rows="2" :label-width="150" :span="8" :showSearchIcon="true" :autocomplete="'on'" :hideResetButton="true" @do-search="doSearch" @on-reset="onReset">
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
<!-- 普通查询条件 -->
|
|
5
|
+
<div v-for="(item, index) in normalWidgets" :key="'search-' + index">
|
|
6
|
+
<FormItem :label="item.name">
|
|
6
7
|
<BiSearchItem :widget="item"></BiSearchItem>
|
|
7
8
|
</FormItem>
|
|
8
9
|
</div>
|
|
9
10
|
</LamboQueryFilter>
|
|
11
|
+
<!-- 维度区固定在查询按钮下方:标签 + 明细下拉;明细默认收起,开关追加在标签后方 -->
|
|
12
|
+
<Form v-if="dimTagOptions.length > 0" class="bi-dim-form" label-position="right" :label-width="150">
|
|
13
|
+
<FormItem :label="dimensionLabel">
|
|
14
|
+
<div class="bi-dim-tags-row">
|
|
15
|
+
<div class="bi-dim-tags-row__tags">
|
|
16
|
+
<BiTagSelect v-model="dimSelected" :options="dimTagOptions" @on-change="onDimTagsChange"></BiTagSelect>
|
|
17
|
+
</div>
|
|
18
|
+
<Button type="text" class="bi-dim-detail-toggle" :title="dimDetailsCollapsed ? '展开维度明细' : '收起维度明细'"
|
|
19
|
+
@click="dimDetailsCollapsed = !dimDetailsCollapsed">
|
|
20
|
+
<Icon :type="'ios-arrow-down'" :size="16"
|
|
21
|
+
:class="{ 'bi-dim-detail-toggle__icon--open': !dimDetailsCollapsed }" />
|
|
22
|
+
</Button>
|
|
23
|
+
</div>
|
|
24
|
+
</FormItem>
|
|
25
|
+
<div v-show="!dimDetailsCollapsed" class="bi-dim-details">
|
|
26
|
+
<Row>
|
|
27
|
+
<!-- 栅格与普通查询条件一致:固定 span=8(QueryFilter 传 span=8),一行三个 -->
|
|
28
|
+
<Col v-for="(dim, index) in dimensionWidgets" :key="'dimension-' + (dim.id || index)" :span="8">
|
|
29
|
+
<!-- 下拉框始终展示,未选标签/未选明细时为空态,只控制列显隐,不上送查询参数 -->
|
|
30
|
+
<FormItem :label="dim.name">
|
|
31
|
+
<BiSearchItem :widget="dim" :data-list="getDimDataList(dim)"></BiSearchItem>
|
|
32
|
+
</FormItem>
|
|
33
|
+
</Col>
|
|
34
|
+
</Row>
|
|
35
|
+
</div>
|
|
36
|
+
</Form>
|
|
10
37
|
</div>
|
|
11
38
|
</template>
|
|
12
39
|
<script>
|
|
@@ -14,6 +41,7 @@ import LamboQueryFilter from "@lambo-design/query-filter"
|
|
|
14
41
|
import { deepCopy } from "@lambo-design/shared/utils/assist"
|
|
15
42
|
import moment from 'moment'
|
|
16
43
|
import BiSearchItem from "./search-item.vue"
|
|
44
|
+
import BiTagSelect from "./tag-select.vue"
|
|
17
45
|
import {
|
|
18
46
|
SEARCH_DICT,
|
|
19
47
|
DATE_RANGE_PFIX,
|
|
@@ -21,10 +49,12 @@ import {
|
|
|
21
49
|
DEFAULT_YEAR_FORMAT,
|
|
22
50
|
DEFAULT_MONTH_FORMAT
|
|
23
51
|
} from '../../../util/constants'
|
|
52
|
+
import { EventBus, EVENT_TYPES } from '../util/event-bus'
|
|
53
|
+
import { setDimensionBlock, clearDimensionState } from '../util/dimension-state'
|
|
24
54
|
|
|
25
55
|
export default {
|
|
26
56
|
name: 'BiSearchForm',
|
|
27
|
-
components: { LamboQueryFilter, BiSearchItem },
|
|
57
|
+
components: { LamboQueryFilter, BiSearchItem, BiTagSelect },
|
|
28
58
|
props: {
|
|
29
59
|
widget: {
|
|
30
60
|
type: Object,
|
|
@@ -33,49 +63,270 @@ export default {
|
|
|
33
63
|
},
|
|
34
64
|
data() {
|
|
35
65
|
return {
|
|
36
|
-
cacheWidget: {}
|
|
66
|
+
cacheWidget: {},
|
|
67
|
+
// 维度明细默认收起,开关在维度标签后方
|
|
68
|
+
dimDetailsCollapsed: true
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
computed: {
|
|
72
|
+
// 普通查询条件(隐形查询条件A0不展示,但仍参与传参)
|
|
73
|
+
normalWidgets() {
|
|
74
|
+
let list = this.widget.widgets || []
|
|
75
|
+
return list.filter(item => item && item.options && item.options.searchType !== SEARCH_DICT.NOT_SHOW_INPUT.id)
|
|
76
|
+
},
|
|
77
|
+
// 维度区块节点:后端输出在 search.options.dims,v1 只支持一个维度块
|
|
78
|
+
dimensionBlock() {
|
|
79
|
+
let dims = this.widget.options && this.widget.options.dims
|
|
80
|
+
return Array.isArray(dims) && dims.length > 0 ? dims[0] : null
|
|
81
|
+
},
|
|
82
|
+
dimensionWidgets() {
|
|
83
|
+
return (this.dimensionBlock && this.dimensionBlock.widgets) || []
|
|
84
|
+
},
|
|
85
|
+
dimensionLabel() {
|
|
86
|
+
return (this.dimensionBlock && this.dimensionBlock.name) || '统计维度'
|
|
87
|
+
},
|
|
88
|
+
hasSearchContent() {
|
|
89
|
+
return this.normalWidgets.length > 0 || this.dimTagOptions.length > 0
|
|
90
|
+
},
|
|
91
|
+
// 维度标签的可选项:取维度容器自身的 dataList(K 与明细的 pDimKey 对应)
|
|
92
|
+
dimTagOptions() {
|
|
93
|
+
let dataList = (this.dimensionBlock && this.dimensionBlock.options && this.dimensionBlock.options.dataList) || []
|
|
94
|
+
return dataList.map(item => ({ K: item.K, V: item.V }))
|
|
95
|
+
},
|
|
96
|
+
// 已选维度标识,代理到 dimension.options.val
|
|
97
|
+
dimSelected: {
|
|
98
|
+
get() {
|
|
99
|
+
let val = this.dimensionBlock && this.dimensionBlock.options && this.dimensionBlock.options.val
|
|
100
|
+
return Array.isArray(val) ? val : []
|
|
101
|
+
},
|
|
102
|
+
set(val) {
|
|
103
|
+
if (this.dimensionBlock && this.dimensionBlock.options) {
|
|
104
|
+
this.$set(this.dimensionBlock.options, 'val', val)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
watch: {
|
|
110
|
+
// 维度标签/明细值/级联变化后,修剪失效明细值并广播列显隐
|
|
111
|
+
'widget.options.dims': {
|
|
112
|
+
deep: true,
|
|
113
|
+
handler() {
|
|
114
|
+
if (!this.dimensionBlock) {
|
|
115
|
+
clearDimensionState()
|
|
116
|
+
EventBus.$emit(EVENT_TYPES.DIMENSION_COLUMNS_CHANGED, {})
|
|
117
|
+
return
|
|
118
|
+
}
|
|
119
|
+
this.syncCheckedTagsFromDetails()
|
|
120
|
+
this.syncEmptyDetailTags()
|
|
121
|
+
this.pruneInvalidDimVals()
|
|
122
|
+
this.scheduleDimPublish()
|
|
123
|
+
}
|
|
37
124
|
}
|
|
38
125
|
},
|
|
39
126
|
methods: {
|
|
127
|
+
// 维度标识:明细用 pDimKey 关联容器标签(容器 dataList 的 K),缺退化 qKey/id
|
|
128
|
+
getDimKey(item) {
|
|
129
|
+
return (item.options && (item.options.pDimKey || item.options.qKey)) || item.id
|
|
130
|
+
},
|
|
131
|
+
// 多选明细默认全选(取 dataList 全部 K;级联过滤仍在下拉数据与修剪环节生效)
|
|
132
|
+
fillDimDetailAll(dim) {
|
|
133
|
+
if (!dim.options || dim.options.searchType !== SEARCH_DICT.MUlTI_SELECT.id) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
let allKs = (dim.options.dataList || [])
|
|
137
|
+
.map(row => row && row.K)
|
|
138
|
+
.filter(k => k !== undefined && k !== null && k !== '')
|
|
139
|
+
this.$set(dim.options, 'val', allKs)
|
|
140
|
+
this.$set(dim.options, 'valName', '')
|
|
141
|
+
},
|
|
142
|
+
onDimTagsChange(selected) {
|
|
143
|
+
// 对比变更前的标签:取消勾选清空明细值;新勾选的多选明细默认全选
|
|
144
|
+
let prev = this._prevDimTags || []
|
|
145
|
+
this.dimensionWidgets.forEach(item => {
|
|
146
|
+
if (!item.options) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
149
|
+
let dimKey = this.getDimKey(item)
|
|
150
|
+
if (selected.indexOf(dimKey) === -1) {
|
|
151
|
+
let resetVal = Array.isArray(item.options.val) ? [] : ''
|
|
152
|
+
this.$set(item.options, 'val', resetVal)
|
|
153
|
+
this.$set(item.options, 'valName', '')
|
|
154
|
+
} else if (prev.indexOf(dimKey) === -1 && item.options.searchType === SEARCH_DICT.MUlTI_SELECT.id) {
|
|
155
|
+
this.fillDimDetailAll(item)
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
this._prevDimTags = selected.slice()
|
|
159
|
+
},
|
|
160
|
+
// 联动:明细下拉直接选择了值时,自动勾选对应维度标签(与清空明细取消标签对称)
|
|
161
|
+
syncCheckedTagsFromDetails() {
|
|
162
|
+
let selected = this.dimSelected.slice()
|
|
163
|
+
let changed = false
|
|
164
|
+
this.dimensionWidgets.forEach(item => {
|
|
165
|
+
if (!item.options) {
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
let dimKey = this.getDimKey(item)
|
|
169
|
+
if (selected.indexOf(dimKey) > -1) {
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
let val = item.options.val
|
|
173
|
+
let hasVal = Array.isArray(val) ? val.length > 0 : (val !== '' && val !== null && val !== undefined)
|
|
174
|
+
if (hasVal) {
|
|
175
|
+
selected.push(dimKey)
|
|
176
|
+
changed = true
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
if (changed) {
|
|
180
|
+
this.dimSelected = selected
|
|
181
|
+
this._prevDimTags = selected.slice()
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
// 联动:标签选中但多选明细被清空(一个都不选)时,自动取消该标签
|
|
185
|
+
syncEmptyDetailTags() {
|
|
186
|
+
let selected = this.dimSelected.slice()
|
|
187
|
+
let changed = false
|
|
188
|
+
this.dimensionWidgets.forEach(item => {
|
|
189
|
+
if (!item.options || item.options.searchType !== SEARCH_DICT.MUlTI_SELECT.id) {
|
|
190
|
+
return
|
|
191
|
+
}
|
|
192
|
+
let dimKey = this.getDimKey(item)
|
|
193
|
+
if (selected.indexOf(dimKey) === -1) {
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
if (Array.isArray(item.options.val) && item.options.val.length === 0) {
|
|
197
|
+
selected = selected.filter(k => k !== dimKey)
|
|
198
|
+
changed = true
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
if (changed) {
|
|
202
|
+
this.dimSelected = selected
|
|
203
|
+
this._prevDimTags = selected.slice()
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
/**
|
|
207
|
+
* 获取维度明细的下拉数据(级联时按父维度选中值静态过滤 dataList)
|
|
208
|
+
* cascade: { parentQKey: 父维度qKey, refKey: 本维度数据中关联父维度值的字段(缺省取parentQKey) }
|
|
209
|
+
* 父维度未选标签/未选明细值时不加约束;后续若改为接口级联可在此处扩展
|
|
210
|
+
*/
|
|
211
|
+
getDimDataList(dim, visiting) {
|
|
212
|
+
let rawList = (dim.options && dim.options.dataList) || []
|
|
213
|
+
let cascade = dim.options && dim.options.cascade
|
|
214
|
+
if (!cascade || !cascade.parentQKey) {
|
|
215
|
+
return rawList
|
|
216
|
+
}
|
|
217
|
+
visiting = visiting || []
|
|
218
|
+
let dimKey = this.getDimKey(dim)
|
|
219
|
+
if (visiting.indexOf(dimKey) > -1) {
|
|
220
|
+
return rawList // 级联环保护
|
|
221
|
+
}
|
|
222
|
+
let parent = this.dimensionWidgets.find(item => this.getDimKey(item) === cascade.parentQKey)
|
|
223
|
+
if (!parent || !parent.options) {
|
|
224
|
+
return rawList
|
|
225
|
+
}
|
|
226
|
+
// 父维度标签未选中时不加约束
|
|
227
|
+
if (this.dimSelected.indexOf(cascade.parentQKey) === -1) {
|
|
228
|
+
return rawList
|
|
229
|
+
}
|
|
230
|
+
let parentVals = parent.options.val
|
|
231
|
+
if (!Array.isArray(parentVals) || parentVals.length === 0) {
|
|
232
|
+
return rawList // 父维度没有选中明细值,不加约束
|
|
233
|
+
}
|
|
234
|
+
// 父级合法值需同时满足父级自身的级联过滤结果
|
|
235
|
+
let legalParentKs = this.getDimDataList(parent, visiting.concat(dimKey)).map(row => row && row.K)
|
|
236
|
+
let allowVals = parentVals.filter(v => legalParentKs.indexOf(v) > -1)
|
|
237
|
+
if (allowVals.length === 0) {
|
|
238
|
+
return rawList
|
|
239
|
+
}
|
|
240
|
+
let refKey = cascade.refKey || cascade.parentQKey
|
|
241
|
+
return rawList.filter(row => row && allowVals.indexOf(row[refKey]) > -1)
|
|
242
|
+
},
|
|
243
|
+
// 修剪维度明细中已不在有效下拉列表内的值(仅处理下拉类型10/20)
|
|
244
|
+
pruneInvalidDimVals() {
|
|
245
|
+
this.dimensionWidgets.forEach(item => {
|
|
246
|
+
if (!item.options) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
let searchType = item.options.searchType
|
|
250
|
+
if (searchType !== SEARCH_DICT.SINGLE_SELECT.id && searchType !== SEARCH_DICT.MUlTI_SELECT.id) {
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
let legalKs = this.getDimDataList(item).map(row => row && row.K)
|
|
254
|
+
let val = item.options.val
|
|
255
|
+
if (Array.isArray(val)) {
|
|
256
|
+
if (val.length === 0) {
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
let kept = val.filter(v => legalKs.indexOf(v) > -1)
|
|
260
|
+
if (kept.length !== val.length) {
|
|
261
|
+
this.$set(item.options, 'val', kept)
|
|
262
|
+
}
|
|
263
|
+
} else if (val !== '' && val !== null && val !== undefined) {
|
|
264
|
+
if (legalKs.indexOf(val) === -1) {
|
|
265
|
+
this.$set(item.options, 'val', '')
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
},
|
|
270
|
+
// 维度变化只影响列显隐,合并到 nextTick 广播一次,避免修剪引发的重复触发
|
|
271
|
+
scheduleDimPublish() {
|
|
272
|
+
if (this._dimPublishScheduled) {
|
|
273
|
+
return
|
|
274
|
+
}
|
|
275
|
+
this._dimPublishScheduled = true
|
|
276
|
+
this.$nextTick(() => {
|
|
277
|
+
this._dimPublishScheduled = false
|
|
278
|
+
this.publishDimensionState()
|
|
279
|
+
})
|
|
280
|
+
},
|
|
281
|
+
publishDimensionState() {
|
|
282
|
+
let visibility = setDimensionBlock(this.dimensionBlock)
|
|
283
|
+
console.log('publish visibility:', JSON.parse(JSON.stringify(visibility || {})))
|
|
284
|
+
EventBus.$emit(EVENT_TYPES.DIMENSION_COLUMNS_CHANGED, visibility)
|
|
285
|
+
},
|
|
286
|
+
// 按单个查询项配置组装查询参数(仅普通查询项;维度不上送)
|
|
287
|
+
appendItemParams(params, item) {
|
|
288
|
+
if (item.options && Object.prototype.hasOwnProperty.call(item.options, "qKey")) {
|
|
289
|
+
let qKey = item.options.qKey
|
|
290
|
+
if (Object.prototype.hasOwnProperty.call(item.options, "val") && item.options.val) {
|
|
291
|
+
let val = item.options.val
|
|
292
|
+
if (Array.isArray(val)) {
|
|
293
|
+
if (item.options.searchType === SEARCH_DICT.MUlTI_DATE.id) {
|
|
294
|
+
if (val && Array.isArray(val) && val.length === 2 && val[0] && val[1]) {
|
|
295
|
+
params[qKey + DATE_RANGE_PFIX.START] = moment(val[0]).format(DEFAULT_DATE_FORMAT)
|
|
296
|
+
params[qKey + DATE_RANGE_PFIX.END] = moment(val[1]).format(DEFAULT_DATE_FORMAT)
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
params[qKey] = val.join()
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
if (item.options.searchType === SEARCH_DICT.SINGLE_DATE.id) {
|
|
303
|
+
params[qKey] = moment(val).format(DEFAULT_DATE_FORMAT)
|
|
304
|
+
} else if (item.options.searchType === SEARCH_DICT.SINGLE_YEAR.id) {
|
|
305
|
+
params[qKey] = moment(val).format(DEFAULT_YEAR_FORMAT)
|
|
306
|
+
} else if (item.options.searchType === SEARCH_DICT.SINGLE_MONTH.id) {
|
|
307
|
+
params[qKey] = moment(val).format(DEFAULT_MONTH_FORMAT)
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
params[qKey] = val
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// TODO:这里传null还是不传后面看下
|
|
315
|
+
// else {
|
|
316
|
+
// params[qKey] = null
|
|
317
|
+
// }
|
|
318
|
+
}
|
|
319
|
+
},
|
|
40
320
|
doSearch() {
|
|
41
321
|
let params = {}
|
|
42
322
|
let searchList = this.widget.widgets
|
|
43
323
|
console.log("search-from doSearch this.widget.widgets:", searchList)
|
|
44
324
|
if (searchList) {
|
|
45
325
|
searchList.map(item => {
|
|
46
|
-
|
|
47
|
-
let qKey = item.options.qKey
|
|
48
|
-
if (Object.prototype.hasOwnProperty.call(item.options, "val") && item.options.val) {
|
|
49
|
-
let val = item.options.val
|
|
50
|
-
if (Array.isArray(val)) {
|
|
51
|
-
if (item.options.searchType === SEARCH_DICT.MUlTI_DATE.id) {
|
|
52
|
-
if (val && Array.isArray(val) && val.length === 2 && val[0] && val[1]) {
|
|
53
|
-
params[qKey + DATE_RANGE_PFIX.START] = moment(val[0]).format(DEFAULT_DATE_FORMAT)
|
|
54
|
-
params[qKey + DATE_RANGE_PFIX.END] = moment(val[1]).format(DEFAULT_DATE_FORMAT)
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
params[qKey] = val.join()
|
|
58
|
-
}
|
|
59
|
-
} else {
|
|
60
|
-
if (item.options.searchType === SEARCH_DICT.SINGLE_DATE.id) {
|
|
61
|
-
params[qKey] = moment(val).format(DEFAULT_DATE_FORMAT)
|
|
62
|
-
} else if (item.options.searchType === SEARCH_DICT.SINGLE_YEAR.id) {
|
|
63
|
-
params[qKey] = moment(val).format(DEFAULT_YEAR_FORMAT)
|
|
64
|
-
} else if (item.options.searchType === SEARCH_DICT.SINGLE_MONTH.id) {
|
|
65
|
-
params[qKey] = moment(val).format(DEFAULT_MONTH_FORMAT)
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
params[qKey] = val
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// TODO:这里传null还是不传后面看下
|
|
73
|
-
// else {
|
|
74
|
-
// params[qKey] = null
|
|
75
|
-
// }
|
|
76
|
-
}
|
|
326
|
+
this.appendItemParams(params, item)
|
|
77
327
|
})
|
|
78
328
|
}
|
|
329
|
+
// 维度(标签/明细)只控制表格列显隐,不进查询参数
|
|
79
330
|
console.log("search-from doSearch params:", params)
|
|
80
331
|
this.$emit("on-search", params)
|
|
81
332
|
},
|
|
@@ -87,11 +338,49 @@ export default {
|
|
|
87
338
|
this.$set(this.widget, 'widgets', cacheSearchList)
|
|
88
339
|
}
|
|
89
340
|
}
|
|
341
|
+
// 维度区块一并恢复缓存(含标签选中和明细值),watcher 会重新广播列显隐
|
|
342
|
+
if (this.cacheWidget && this.cacheWidget.options && Object.prototype.hasOwnProperty.call(this.cacheWidget.options, "dims")) {
|
|
343
|
+
this.$set(this.widget.options, 'dims', deepCopy(this.cacheWidget.options.dims))
|
|
344
|
+
let resetVal = this.dimensionBlock && this.dimensionBlock.options && this.dimensionBlock.options.val
|
|
345
|
+
this._prevDimTags = Array.isArray(resetVal) ? resetVal.slice() : []
|
|
346
|
+
}
|
|
90
347
|
this.doSearch()
|
|
91
348
|
}
|
|
92
349
|
},
|
|
93
350
|
created() {
|
|
94
351
|
console.log("search-form created -- widget:", this.widget)
|
|
352
|
+
let dims = this.widget.options && this.widget.options.dims
|
|
353
|
+
if (Array.isArray(dims) && dims.length > 1) {
|
|
354
|
+
console.warn("search-form -- v1仅支持一个维度块,忽略其余dims数量:", dims.length - 1)
|
|
355
|
+
}
|
|
356
|
+
if (this.dimensionBlock) {
|
|
357
|
+
if (!this.dimensionBlock.options) {
|
|
358
|
+
this.$set(this.dimensionBlock, 'options', {})
|
|
359
|
+
}
|
|
360
|
+
let blockOptions = this.dimensionBlock.options
|
|
361
|
+
if (!Array.isArray(blockOptions.val)) {
|
|
362
|
+
this.$set(blockOptions, 'val', blockOptions.val ? String(blockOptions.val).split(',') : [])
|
|
363
|
+
}
|
|
364
|
+
// 多选下拉的明细值规范为数组
|
|
365
|
+
this.dimensionWidgets.forEach(item => {
|
|
366
|
+
if (item.options && item.options.searchType === SEARCH_DICT.MUlTI_SELECT.id && !Array.isArray(item.options.val)) {
|
|
367
|
+
this.$set(item.options, 'val', item.options.val ? String(item.options.val).split(',') : [])
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
this._prevDimTags = (Array.isArray(blockOptions.val) ? blockOptions.val : []).slice()
|
|
371
|
+
// 默认已勾选标签(如 ALL_SELECT)的多选明细,空值补全为全选,保持初始全部列可见
|
|
372
|
+
this.dimensionWidgets.forEach(item => {
|
|
373
|
+
if (item.options && item.options.searchType === SEARCH_DICT.MUlTI_SELECT.id
|
|
374
|
+
&& this._prevDimTags.indexOf(this.getDimKey(item)) > -1
|
|
375
|
+
&& Array.isArray(item.options.val) && item.options.val.length === 0) {
|
|
376
|
+
this.fillDimDetailAll(item)
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
// 初始列显隐写入共享状态(表格创建时直接读取,无需等事件)
|
|
380
|
+
setDimensionBlock(this.dimensionBlock)
|
|
381
|
+
} else {
|
|
382
|
+
clearDimensionState()
|
|
383
|
+
}
|
|
95
384
|
},
|
|
96
385
|
mounted() {
|
|
97
386
|
this.cacheWidget = deepCopy(this.widget)
|
|
@@ -104,5 +393,68 @@ export default {
|
|
|
104
393
|
::v-deep .ivu-form-item {
|
|
105
394
|
margin-bottom: 8px;
|
|
106
395
|
}
|
|
396
|
+
|
|
397
|
+
/* 维度区与普通查询条件同属一个 Form 视觉流:
|
|
398
|
+
不额外加上间距(QueryFilter 末行 FormItem 的 margin-bottom 已提供行间距),
|
|
399
|
+
label 右对齐 150px、FormItem 8px 间距均沿用 iView/外层 scoped 规则 */
|
|
400
|
+
.bi-dim-form {
|
|
401
|
+
margin-top: 0;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* 覆盖 label-left 的左对齐为右对齐:仅作用于维度区,不影响其他表单;
|
|
405
|
+
!important 防止被 iView 内置 .ivu-form-label-left 规则压过 */
|
|
406
|
+
.bi-dim-form ::v-deep .ivu-form-item-label {
|
|
407
|
+
text-align: right !important;
|
|
408
|
+
padding-left: 0 !important;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* 标签复选框与明细折叠图标同一行:标签占满剩余空间,图标固定右侧 */
|
|
412
|
+
.bi-dim-tags-row {
|
|
413
|
+
display: flex;
|
|
414
|
+
align-items: center;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.bi-dim-tags-row__tags {
|
|
418
|
+
flex: 1;
|
|
419
|
+
min-width: 0;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.bi-dim-detail-toggle {
|
|
423
|
+
flex: none;
|
|
424
|
+
width: 24px;
|
|
425
|
+
height: 32px;
|
|
426
|
+
margin-left: 4px;
|
|
427
|
+
padding: 0;
|
|
428
|
+
line-height: 1;
|
|
429
|
+
color: #808695;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.bi-dim-detail-toggle:hover {
|
|
433
|
+
color: var(--primary-color, #2d8cf0);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.bi-dim-detail-toggle ::v-deep i {
|
|
437
|
+
line-height: 1;
|
|
438
|
+
transition: transform .2s ease;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.bi-dim-detail-toggle ::v-deep .bi-dim-detail-toggle__icon--open {
|
|
442
|
+
transform: rotate(180deg);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/* 明细区紧跟标签行,行距与普通条件行间距一致(8px 来自 FormItem margin) */
|
|
446
|
+
.bi-dim-details {
|
|
447
|
+
margin-top: 0;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* element-ui 多选下拉已选标签默认 12px,归一为 iView 控件文字 14px,
|
|
451
|
+
与普通查询条件视觉一致(仅作用于维度区,不改公共多选组件) */
|
|
452
|
+
.bi-dim-form ::v-deep .el-select__tags-text {
|
|
453
|
+
font-size: 14px;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.bi-dim-form ::v-deep .el-tag--mini {
|
|
457
|
+
font-size: 14px;
|
|
458
|
+
}
|
|
107
459
|
}
|
|
108
460
|
</style>
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
</div>
|
|
14
14
|
<div v-else-if="widget.options.searchType === searchDict.SINGLE_SELECT.id"> <!-- 单选下拉框 -->
|
|
15
15
|
<Select v-model="widget.options.val" class="lambo-query-class" filterable :clearable="true" placeholder="请选择">
|
|
16
|
-
<Option v-for="(item, index) in
|
|
16
|
+
<Option v-for="(item, index) in effectiveDataList" :key="index" :value="item.K"> {{ item.V }}</Option>
|
|
17
17
|
</Select>
|
|
18
18
|
</div>
|
|
19
19
|
<div v-else-if="widget.options.searchType === searchDict.MUlTI_SELECT.id"> <!-- 多选下拉框 -->
|
|
20
|
-
<LamboElMultiSelect v-model="widget.options.val" :data="
|
|
20
|
+
<LamboElMultiSelect v-model="widget.options.val" :data="effectiveDataList"></LamboElMultiSelect>
|
|
21
21
|
</div>
|
|
22
22
|
<div v-else-if="widget.options.searchType === searchDict.SINGLE_HELP.id"> <!-- 单选帮助框 -->
|
|
23
23
|
<Input class="lambo-display-none" v-model="helpVal" />
|
|
@@ -95,6 +95,18 @@ export default {
|
|
|
95
95
|
type: Object,
|
|
96
96
|
default: () => ({})
|
|
97
97
|
},
|
|
98
|
+
/**
|
|
99
|
+
* 外部传入的下拉数据(如维度级联过滤后的列表),不传时使用 widget.options.dataList
|
|
100
|
+
*/
|
|
101
|
+
dataList: {
|
|
102
|
+
type: Array,
|
|
103
|
+
default: null
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
computed: {
|
|
107
|
+
effectiveDataList() {
|
|
108
|
+
return this.dataList || (this.widget.options && this.widget.options.dataList) || []
|
|
109
|
+
}
|
|
98
110
|
},
|
|
99
111
|
data() {
|
|
100
112
|
return {
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<!-- eslint-disable -->
|
|
2
|
+
<template>
|
|
3
|
+
<div class="bi-tag-select">
|
|
4
|
+
<Checkbox class="bi-tag-select-item" :value="checkAll" :indeterminate="indeterminate"
|
|
5
|
+
:disabled="disabled || options.length === 0" @on-change="onCheckAllChange">全选</Checkbox>
|
|
6
|
+
<Checkbox v-for="item in options" :key="item.K" class="bi-tag-select-item" :value="isChecked(item.K)"
|
|
7
|
+
:disabled="disabled" @on-change="checked => onItemChange(item.K, checked)">{{ item.V }}</Checkbox>
|
|
8
|
+
</div>
|
|
9
|
+
</template>
|
|
10
|
+
<script>
|
|
11
|
+
/**
|
|
12
|
+
* 维度标签多选组件(基于 iView Checkbox,带全选/半选)
|
|
13
|
+
* 用法:<BiTagSelect v-model="selected" :options="[{K:'01',V:'区域'}]" />
|
|
14
|
+
* 说明:不使用 CheckboxGroup——其根节点是 block div 会把内容挤到下一行;
|
|
15
|
+
* 独立 Checkbox 作为行内元素排在同一行,沿用 FormItem 32px 行盒垂直对齐。
|
|
16
|
+
* 项目 viewUI(@lambo-design/core,iView 分支)无 TagSelect/Space,
|
|
17
|
+
* view-ui-plus 同名组件为 Vue3 实现,故在此实现
|
|
18
|
+
*/
|
|
19
|
+
export default {
|
|
20
|
+
name: 'BiTagSelect',
|
|
21
|
+
model: {
|
|
22
|
+
prop: 'value',
|
|
23
|
+
event: 'input'
|
|
24
|
+
},
|
|
25
|
+
props: {
|
|
26
|
+
// 选中值数组(元素为 options 的 K)
|
|
27
|
+
value: {
|
|
28
|
+
type: Array,
|
|
29
|
+
default: () => []
|
|
30
|
+
},
|
|
31
|
+
// 可选项 [{ K, V }]
|
|
32
|
+
options: {
|
|
33
|
+
type: Array,
|
|
34
|
+
default: () => []
|
|
35
|
+
},
|
|
36
|
+
disabled: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
default: false
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
computed: {
|
|
42
|
+
checkAll() {
|
|
43
|
+
return this.options.length > 0 && this.options.every(item => this.value.indexOf(item.K) > -1)
|
|
44
|
+
},
|
|
45
|
+
// 部分选中:半选态(浏览器对 indeterminate 复选框点击后为勾选,天然触发全选)
|
|
46
|
+
indeterminate() {
|
|
47
|
+
return this.value.length > 0 && !this.checkAll
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
methods: {
|
|
51
|
+
isChecked(k) {
|
|
52
|
+
return this.value.indexOf(k) > -1
|
|
53
|
+
},
|
|
54
|
+
emitValue(valArr) {
|
|
55
|
+
this.$emit('input', valArr)
|
|
56
|
+
this.$emit('on-change', valArr)
|
|
57
|
+
},
|
|
58
|
+
onCheckAllChange(checked) {
|
|
59
|
+
if (this.disabled) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
this.emitValue(checked ? this.options.map(item => item.K) : [])
|
|
63
|
+
},
|
|
64
|
+
onItemChange(k, checked) {
|
|
65
|
+
if (this.disabled) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
let valArr = (this.value || []).slice()
|
|
69
|
+
let idx = valArr.indexOf(k)
|
|
70
|
+
if (checked && idx === -1) {
|
|
71
|
+
valArr.push(k)
|
|
72
|
+
} else if (!checked && idx > -1) {
|
|
73
|
+
valArr.splice(idx, 1)
|
|
74
|
+
}
|
|
75
|
+
this.emitValue(valArr)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
</script>
|
|
80
|
+
<style scoped>
|
|
81
|
+
/* 不使用 flex:FormItem content 为 32px 行盒,checkbox 作为行内元素
|
|
82
|
+
靠 vertical-align:middle 与表单 label/其他控件对齐(同 iView 官方表现);
|
|
83
|
+
根容器仅负责超宽换行 */
|
|
84
|
+
/* 字号/颜色显式对齐 iView 输入框(14px/#515a6e):
|
|
85
|
+
旁边的多选下拉已选项是 element-ui mini tag 12px,
|
|
86
|
+
不随之缩小——14px 是表单正文标准,缩小反而与其他查询条件不一致 */
|
|
87
|
+
.bi-tag-select {
|
|
88
|
+
line-height: 32px;
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
color: #515a6e;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.bi-tag-select ::v-deep .bi-tag-select-item {
|
|
94
|
+
margin-right: 12px;
|
|
95
|
+
vertical-align: middle;
|
|
96
|
+
font-size: 14px;
|
|
97
|
+
font-weight: normal;
|
|
98
|
+
color: #515a6e;
|
|
99
|
+
}
|
|
100
|
+
</style>
|
|
@@ -28,6 +28,8 @@ import LamboDocPreview from '../../../pub/doc/preview/index.vue'
|
|
|
28
28
|
import { accAdd } from '../../../util/math-util'
|
|
29
29
|
import { fileGetUrl } from '../../../bi/widget/api/config'
|
|
30
30
|
import { EventBus, EVENT_TYPES } from '../util/event-bus'
|
|
31
|
+
import { getDimColumnVisibility } from '../util/dimension-state'
|
|
32
|
+
import { filterColumnsByDimension } from '../util/dimension-util'
|
|
31
33
|
|
|
32
34
|
export default {
|
|
33
35
|
name: 'BiPagingTable',
|
|
@@ -58,10 +60,16 @@ export default {
|
|
|
58
60
|
boxShow: false,
|
|
59
61
|
modelWidth: '78%',
|
|
60
62
|
tableBorder: true,
|
|
61
|
-
spanMap: {}
|
|
63
|
+
spanMap: {},
|
|
64
|
+
// 维度列显隐映射(列key -> 是否显示),由查询表单的维度区块驱动
|
|
65
|
+
dimColumnVisibility: {}
|
|
62
66
|
}
|
|
63
67
|
},
|
|
64
68
|
methods: {
|
|
69
|
+
// 维度选择变化:只切换列显隐,不重新查询数据
|
|
70
|
+
onDimColumnsChanged(visibility) {
|
|
71
|
+
this.dimColumnVisibility = visibility || {}
|
|
72
|
+
},
|
|
65
73
|
doSearch() {
|
|
66
74
|
// eslint-disable-next-line
|
|
67
75
|
this.widget.options.url = biConfig.dataServerContext + biConfig.dataServiceUri + this.widget.options.apiId
|
|
@@ -602,14 +610,26 @@ export default {
|
|
|
602
610
|
created() {
|
|
603
611
|
console.log("BiPagingTable -- created() -- this.widget:", this.widget)
|
|
604
612
|
this.initConfig()
|
|
613
|
+
// 仅参与维度过滤的表格(plat_table.is_dim=1)读取初始值并监听变化(不触发数据查询)
|
|
614
|
+
if (this.isDimTable) {
|
|
615
|
+
this.dimColumnVisibility = getDimColumnVisibility()
|
|
616
|
+
EventBus.$on(EVENT_TYPES.DIMENSION_COLUMNS_CHANGED, this.onDimColumnsChanged)
|
|
617
|
+
}
|
|
605
618
|
},
|
|
606
619
|
mounted() {
|
|
607
620
|
this.doSearch()
|
|
608
621
|
},
|
|
622
|
+
beforeDestroy() {
|
|
623
|
+
EventBus.$off(EVENT_TYPES.DIMENSION_COLUMNS_CHANGED, this.onDimColumnsChanged)
|
|
624
|
+
},
|
|
609
625
|
computed: {
|
|
610
626
|
isRowClick() {
|
|
611
627
|
return this.widget.options.isRowClick === 1 || this.widget.options.isRowClick === '1'
|
|
612
628
|
},
|
|
629
|
+
// 是否参与维度列过滤(plat_table.is_dim=1 才随维度标签/明细切换列显隐)
|
|
630
|
+
isDimTable() {
|
|
631
|
+
return this.widget.options.isDim === 1 || this.widget.options.isDim === '1'
|
|
632
|
+
},
|
|
613
633
|
hasSpanColumn() {
|
|
614
634
|
// 列配置中存在 isSpan 列则启用单元格合并
|
|
615
635
|
return (this.columns || []).some(column => this.isSpanColumn(column))
|
|
@@ -695,6 +715,10 @@ export default {
|
|
|
695
715
|
this.$Message.info("表格头配置数据解析异常")
|
|
696
716
|
columns = []
|
|
697
717
|
}
|
|
718
|
+
// 维度(标签/明细)只控制列显隐:仅参与维度过滤的表格执行,非维度列始终保留
|
|
719
|
+
if (this.isDimTable) {
|
|
720
|
+
columns = filterColumnsByDimension(columns, this.dimColumnVisibility)
|
|
721
|
+
}
|
|
698
722
|
}
|
|
699
723
|
}
|
|
700
724
|
return columns
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 维度列显隐状态(模块级单例)
|
|
3
|
+
*
|
|
4
|
+
* search-form 负责写入并通过 EventBus 广播;表格组件创建时先读一次初始值,
|
|
5
|
+
* 之后监听 DIMENSION_COLUMNS_CHANGED 事件增量更新,避免组件创建先后导致漏收事件。
|
|
6
|
+
*/
|
|
7
|
+
import { buildDimColumnVisibility } from './dimension-util'
|
|
8
|
+
|
|
9
|
+
let currentVisibility = {}
|
|
10
|
+
|
|
11
|
+
export function setDimensionBlock(block) {
|
|
12
|
+
currentVisibility = buildDimColumnVisibility(block)
|
|
13
|
+
return currentVisibility
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function getDimColumnVisibility() {
|
|
17
|
+
return currentVisibility
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function clearDimensionState() {
|
|
21
|
+
currentVisibility = {}
|
|
22
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 维度区块的列显隐规则(纯函数,便于单测)
|
|
3
|
+
*
|
|
4
|
+
* 维度只控制页面内表格列是否显示,不参与查询参数:
|
|
5
|
+
* - 维度标签未选中:该维度关联的列全部隐藏
|
|
6
|
+
* - 选中标签、明细不选:显示该维度关联的整组列(dataList 全部 K)
|
|
7
|
+
* - 选中标签、明细选了具体项:只显示选中项 K 对应的列
|
|
8
|
+
*
|
|
9
|
+
* dataList 每项的 K 直接对应表格 columns 中的 key,无需在列配置上额外标记
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 归一化维度明细值为数组(10单选为字符串、20多选为数组)
|
|
14
|
+
*/
|
|
15
|
+
function normalizeVals(val) {
|
|
16
|
+
if (Array.isArray(val)) {
|
|
17
|
+
return val
|
|
18
|
+
}
|
|
19
|
+
return val ? [val] : []
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 由维度区块配置和当前选择,构建 列key -> 是否显示 的映射
|
|
24
|
+
* 同一列 key 归属多个维度时,任一维度允许显示则显示(OR)
|
|
25
|
+
*
|
|
26
|
+
* @param {object} block search.options.dims[0]
|
|
27
|
+
* @returns {object} visibility 只包含归属维度的列 key
|
|
28
|
+
*/
|
|
29
|
+
export function buildDimColumnVisibility(block) {
|
|
30
|
+
const visibility = {}
|
|
31
|
+
if (!block || !block.widgets) {
|
|
32
|
+
return visibility
|
|
33
|
+
}
|
|
34
|
+
const selectedTags = block.options && Array.isArray(block.options.val) ? block.options.val : []
|
|
35
|
+
|
|
36
|
+
block.widgets.forEach(dim => {
|
|
37
|
+
if (!dim || !dim.options) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
const dimKey = dim.options.pDimKey || dim.options.qKey || dim.id
|
|
41
|
+
const tagSelected = selectedTags.indexOf(dimKey) > -1
|
|
42
|
+
const detailVals = normalizeVals(dim.options.val)
|
|
43
|
+
const colKeys = (dim.options.dataList || [])
|
|
44
|
+
.map(opt => opt && opt.K)
|
|
45
|
+
.filter(k => k !== undefined && k !== null && k !== '')
|
|
46
|
+
|
|
47
|
+
colKeys.forEach(k => {
|
|
48
|
+
const visible = tagSelected && (detailVals.length === 0 || detailVals.indexOf(k) > -1)
|
|
49
|
+
if (visibility[k] !== true) {
|
|
50
|
+
// 同一列被多个维度引用时取 OR
|
|
51
|
+
visibility[k] = visible
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
return visibility
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 按维度列显隐映射递归过滤表格列:
|
|
61
|
+
* - 叶子列:不属于任何维度(序号、固定列、年龄分布等非维度列)始终保留;属于维度的按映射决定
|
|
62
|
+
* - 多级表头分组列(含 children):递归过滤子列,子列全部隐藏时整组隐藏;
|
|
63
|
+
* 标签未选中时该组叶子在映射中均为 false,分组自然消失
|
|
64
|
+
* 入参 columns 由 columns 计算属性每次重新 JSON.parse 生成,可直接改写 children
|
|
65
|
+
*/
|
|
66
|
+
export function filterColumnsByDimension(columns, visibility) {
|
|
67
|
+
if (!columns || columns.length === 0) {
|
|
68
|
+
return columns || []
|
|
69
|
+
}
|
|
70
|
+
if (!visibility || Object.keys(visibility).length === 0) {
|
|
71
|
+
return columns
|
|
72
|
+
}
|
|
73
|
+
const filterCols = (cols) => cols.filter(col => {
|
|
74
|
+
if (!col) {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(col.children) && col.children.length > 0) {
|
|
78
|
+
col.children = filterCols(col.children)
|
|
79
|
+
return col.children.length > 0
|
|
80
|
+
}
|
|
81
|
+
if (col.key === undefined || col.key === null) {
|
|
82
|
+
return true
|
|
83
|
+
}
|
|
84
|
+
if (!Object.prototype.hasOwnProperty.call(visibility, col.key)) {
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
87
|
+
return visibility[col.key] === true
|
|
88
|
+
})
|
|
89
|
+
return filterCols(columns)
|
|
90
|
+
}
|
|
@@ -7,5 +7,7 @@ export const EventBus = new Vue()
|
|
|
7
7
|
export const EVENT_TYPES = {
|
|
8
8
|
NUM_IDX_ACTIVATED: 'num-idx-activated',
|
|
9
9
|
NUM_IDX_DEACTIVATED: 'num-idx-deactivated',
|
|
10
|
-
TABLE_ROW_ACTIVATED: 'table-row-activated'
|
|
10
|
+
TABLE_ROW_ACTIVATED: 'table-row-activated',
|
|
11
|
+
// 维度选择变化,payload 为 列key -> 是否显示 的映射
|
|
12
|
+
DIMENSION_COLUMNS_CHANGED: 'dimension-columns-changed'
|
|
11
13
|
}
|
package/package.json
CHANGED
|
@@ -1354,12 +1354,14 @@ export function getECharts(type, dataX, dataY, dataDim, dataZ) {
|
|
|
1354
1354
|
} else if (type === '33') {
|
|
1355
1355
|
let data = []
|
|
1356
1356
|
let sum = 0
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1357
|
+
if (dataY && dataY.length > 0) {
|
|
1358
|
+
for (let i = 0; i < dataY[0].length; i++) {
|
|
1359
|
+
data.push({
|
|
1360
|
+
name: dataX[i],
|
|
1361
|
+
value: dataY[0][i]
|
|
1362
|
+
})
|
|
1363
|
+
sum += dataY[0][i]
|
|
1364
|
+
}
|
|
1363
1365
|
}
|
|
1364
1366
|
let title33 = ''
|
|
1365
1367
|
if (dataDim && dataDim.length > 0) {
|
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
</div>
|
|
66
66
|
</template>
|
|
67
67
|
<script>
|
|
68
|
-
import { oneOf } from 'view-ui-plus/src/utils/assist'
|
|
69
68
|
import Trend from 'view-ui-plus/src/components/trend'
|
|
70
69
|
import 'view-ui-plus/dist/styles/viewuiplus.css'
|
|
71
70
|
import { EVENT_TYPES, EventBus } from '../../bi/widget/util/event-bus'
|
|
@@ -88,24 +87,15 @@ export default {
|
|
|
88
87
|
type: [String, Number]
|
|
89
88
|
},
|
|
90
89
|
trend1: {
|
|
91
|
-
validator(value) {
|
|
92
|
-
return oneOf(value, ['up', 'down']);
|
|
93
|
-
}
|
|
94
90
|
},
|
|
95
91
|
polar1: {
|
|
96
92
|
type: String,
|
|
97
|
-
required: false
|
|
98
|
-
validator(value) {
|
|
99
|
-
return !value || ['pos', 'neg'].includes(value);
|
|
100
|
-
}
|
|
93
|
+
required: false
|
|
101
94
|
},
|
|
102
95
|
subNum2: {
|
|
103
96
|
type: [String, Number]
|
|
104
97
|
},
|
|
105
98
|
trend2: {
|
|
106
|
-
validator(value) {
|
|
107
|
-
return oneOf(value, ['up', 'down']);
|
|
108
|
-
}
|
|
109
99
|
},
|
|
110
100
|
polar2: {
|
|
111
101
|
type: String,
|