Commit 9bf9339a1103287024dd365d8a6980450ff7f65b
1 parent
07812d51
JVXETable提供三级联动简单方案,解决联动展示与选择BUG #2867
Showing
4 changed files
with
408 additions
and
120 deletions
ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/JVxeTable.js
... | ... | @@ -98,6 +98,8 @@ export default { |
98 | 98 | // 是否一直显示组件,如果为false则只有点击的时候才出现组件 |
99 | 99 | // 注:该参数不能动态修改;如果行、列字段多的情况下,会根据机器性能造成不同程度的卡顿。 |
100 | 100 | alwaysEdit: PropTypes.bool.def(false), |
101 | + // 联动配置,数组,详情配置见文档 | |
102 | + linkageConfig: PropTypes.array.def(() => []), | |
101 | 103 | }, |
102 | 104 | data() { |
103 | 105 | return { |
... | ... | @@ -151,7 +153,10 @@ export default { |
151 | 153 | // 允许执行刷新特效的行ID |
152 | 154 | reloadEffectRowKeysMap: {}, |
153 | 155 | //配置了但是没有授权的按钮和列 集合 |
154 | - excludeCode:[] | |
156 | + excludeCode:[], | |
157 | + // 联动下拉选项(用于隔离不同的下拉选项) | |
158 | + // 内部联动配置,map | |
159 | + _innerLinkageConfig: null, | |
155 | 160 | } |
156 | 161 | }, |
157 | 162 | computed: { |
... | ... | @@ -178,6 +183,18 @@ export default { |
178 | 183 | renderOptions.target = this |
179 | 184 | } |
180 | 185 | } |
186 | + // 处理联动列,联动列只能作用于 select 组件 | |
187 | + if (column.$type === JVXETypes.select && this._innerLinkageConfig != null) { | |
188 | + // 判断当前列是否是联动列 | |
189 | + if (this._innerLinkageConfig.has(column.key)) { | |
190 | + renderOptions.linkage = { | |
191 | + config: this._innerLinkageConfig.get(column.key), | |
192 | + getLinkageOptionsSibling: this.getLinkageOptionsSibling, | |
193 | + getLinkageOptionsAsync: this.getLinkageOptionsAsync, | |
194 | + linkageSelectChange: this.linkageSelectChange, | |
195 | + } | |
196 | + } | |
197 | + } | |
181 | 198 | if (column.editRender) { |
182 | 199 | Object.assign(column.editRender, renderOptions) |
183 | 200 | } |
... | ... | @@ -278,15 +295,21 @@ export default { |
278 | 295 | immediate: true, |
279 | 296 | async handler() { |
280 | 297 | let vxe = await getRefPromise(this, 'vxe') |
281 | - // 阻断vue监听大数据,提高性能 | |
282 | 298 | |
283 | - // 开启了排序就自动计算排序值 | |
284 | - if (this.dragSort) { | |
285 | - this.dataSource.forEach((data, idx) => { | |
299 | + this.dataSource.forEach((data, idx) => { | |
300 | + // 开启了排序就自动计算排序值 | |
301 | + if (this.dragSort) { | |
286 | 302 | this.$set(data, this.dragSortKey, idx + 1) |
287 | - }) | |
288 | - } | |
303 | + } | |
304 | + // 处理联动回显数据 | |
305 | + if (this._innerLinkageConfig != null) { | |
306 | + for (let configItem of this._innerLinkageConfig.values()) { | |
307 | + this.autoSetLinkageOptionsByData(data, '', configItem, 0) | |
308 | + } | |
309 | + } | |
310 | + }) | |
289 | 311 | |
312 | + // 阻断vue监听大数据,提高性能 | |
290 | 313 | vxe.loadData(this.dataSource) |
291 | 314 | |
292 | 315 | // TODO 解析disabledRows |
... | ... | @@ -469,7 +492,40 @@ export default { |
469 | 492 | this._innerColumns = _innerColumns |
470 | 493 | this._innerEditRules = _innerEditRules |
471 | 494 | } |
472 | - } | |
495 | + }, | |
496 | + // watch linkageConfig | |
497 | + // 整理多级联动配置 | |
498 | + linkageConfig: { | |
499 | + immediate: true, | |
500 | + handler() { | |
501 | + if (Array.isArray(this.linkageConfig) && this.linkageConfig.length > 0) { | |
502 | + // 获取联动的key顺序 | |
503 | + let getLcKeys = (key, arr) => { | |
504 | + let col = this._innerColumns.find(col => col.key === key) | |
505 | + if (col) { | |
506 | + arr.push(col.key) | |
507 | + if (col.linkageKey) { | |
508 | + return getLcKeys(col.linkageKey, arr) | |
509 | + } | |
510 | + } | |
511 | + return arr | |
512 | + } | |
513 | + let configMap = new Map() | |
514 | + this.linkageConfig.forEach(lc => { | |
515 | + let keys = getLcKeys(lc.key, []) | |
516 | + // 多个key共享一个,引用地址 | |
517 | + let configItem = { | |
518 | + ...lc, keys, | |
519 | + optionsMap: new Map() | |
520 | + } | |
521 | + keys.forEach(k => configMap.set(k, configItem)) | |
522 | + }) | |
523 | + this._innerLinkageConfig = configMap | |
524 | + } else { | |
525 | + this._innerLinkageConfig = null | |
526 | + } | |
527 | + } | |
528 | + }, | |
473 | 529 | }, |
474 | 530 | created() { |
475 | 531 | }, |
... | ... | @@ -671,6 +727,19 @@ export default { |
671 | 727 | // issues/2784 |
672 | 728 | // 先清空所有数据 |
673 | 729 | xTable.loadData([]) |
730 | + | |
731 | + dataSource.forEach((data, idx) => { | |
732 | + // 开启了排序就自动计算排序值 | |
733 | + if (this.dragSort) { | |
734 | + this.$set(data, this.dragSortKey, idx + 1) | |
735 | + } | |
736 | + // 处理联动回显数据 | |
737 | + if (this._innerLinkageConfig != null) { | |
738 | + for (let configItem of this._innerLinkageConfig.values()) { | |
739 | + this.autoSetLinkageOptionsByData(data, '', configItem, 0) | |
740 | + } | |
741 | + } | |
742 | + }) | |
674 | 743 | // 再新增 |
675 | 744 | return xTable.insertAt(dataSource) |
676 | 745 | } |
... | ... | @@ -797,6 +866,7 @@ export default { |
797 | 866 | * 添加一行或多行 |
798 | 867 | * |
799 | 868 | * @param rows |
869 | + * @param isOnlJs 是否是onlineJS增强触发的 | |
800 | 870 | * @return |
801 | 871 | */ |
802 | 872 | async addRows(rows = {}, isOnlJs) { |
... | ... | @@ -896,6 +966,89 @@ export default { |
896 | 966 | this.$emit(name, event) |
897 | 967 | }, |
898 | 968 | |
969 | + /** 【多级联动】获取同级联动下拉选项 */ | |
970 | + getLinkageOptionsSibling(row, col, config, request) { | |
971 | + // 如果当前列不是顶级列 | |
972 | + let key = '' | |
973 | + if (col.key !== config.key) { | |
974 | + // 就找出联动上级列 | |
975 | + let idx = config.keys.findIndex(k => col.key === k) | |
976 | + let parentKey = config.keys[idx - 1] | |
977 | + key = row[parentKey] | |
978 | + // 如果联动上级列没有选择数据,就直接返回空数组 | |
979 | + if (key === '' || key == null) { | |
980 | + return [] | |
981 | + } | |
982 | + } else { | |
983 | + key = 'root' | |
984 | + } | |
985 | + let options = config.optionsMap.get(key) | |
986 | + if (!Array.isArray(options)) { | |
987 | + if (request) { | |
988 | + let parent = key === 'root' ? '' : key | |
989 | + return this.getLinkageOptionsAsync(config, parent) | |
990 | + } else { | |
991 | + options = [] | |
992 | + } | |
993 | + } | |
994 | + return options | |
995 | + }, | |
996 | + /** 【多级联动】获取联动下拉选项(异步) */ | |
997 | + getLinkageOptionsAsync(config, parent) { | |
998 | + return new Promise(resolve => { | |
999 | + let key = parent ? parent : 'root' | |
1000 | + let options | |
1001 | + if (config.optionsMap.has(key)) { | |
1002 | + options = config.optionsMap.get(key) | |
1003 | + if (options instanceof Promise) { | |
1004 | + options.then(opt => { | |
1005 | + config.optionsMap.set(key, opt) | |
1006 | + resolve(opt) | |
1007 | + }) | |
1008 | + } else { | |
1009 | + resolve(options) | |
1010 | + } | |
1011 | + } else if (typeof config.requestData === 'function') { | |
1012 | + // 调用requestData方法,通过传入parent来获取子级 | |
1013 | + let promise = config.requestData(parent) | |
1014 | + config.optionsMap.set(key, promise) | |
1015 | + promise.then(opt => { | |
1016 | + config.optionsMap.set(key, opt) | |
1017 | + resolve(opt) | |
1018 | + }) | |
1019 | + } else { | |
1020 | + resolve([]) | |
1021 | + } | |
1022 | + }) | |
1023 | + }, | |
1024 | + // 【多级联动】 用于回显数据,自动填充 optionsMap | |
1025 | + autoSetLinkageOptionsByData(data, parent, config, level) { | |
1026 | + if (level === 0) { | |
1027 | + this.getLinkageOptionsAsync(config, '') | |
1028 | + } else { | |
1029 | + this.getLinkageOptionsAsync(config, parent) | |
1030 | + } | |
1031 | + if (config.keys.length - 1 > level) { | |
1032 | + let value = data[config.keys[level]] | |
1033 | + if (value) { | |
1034 | + this.autoSetLinkageOptionsByData(data, value, config, level + 1) | |
1035 | + } | |
1036 | + } | |
1037 | + }, | |
1038 | + // 【多级联动】联动组件change时,清空下级组件 | |
1039 | + linkageSelectChange(row, col, config, value) { | |
1040 | + if (col.linkageKey) { | |
1041 | + this.getLinkageOptionsAsync(config, value) | |
1042 | + let idx = config.keys.findIndex(k => k === col.key) | |
1043 | + let values = {} | |
1044 | + for (let i = idx; i < config.keys.length; i++) { | |
1045 | + values[config.keys[i]] = '' | |
1046 | + } | |
1047 | + // 清空后几列的数据 | |
1048 | + this.setValues([{rowKey: row.id, values}]) | |
1049 | + } | |
1050 | + }, | |
1051 | + | |
899 | 1052 | /** 加载数据字典并合并到 options */ |
900 | 1053 | _loadDictConcatToOptions(column) { |
901 | 1054 | initDictOptions(column.dictCode).then((res) => { |
... | ... | @@ -1088,6 +1241,15 @@ export default { |
1088 | 1241 | let createValue = getEnhancedMixins(col.$type || col.type, 'createValue') |
1089 | 1242 | record[col.key] = createValue({row: record, column, $table: xTable}) |
1090 | 1243 | } |
1244 | + // update-begin--author:sunjianlei---date:20210819------for: 处理联动列,联动列只能作用于 select 组件 | |
1245 | + if (col.$type === JVXETypes.select && this._innerLinkageConfig != null) { | |
1246 | + // 判断当前列是否是联动列 | |
1247 | + if (this._innerLinkageConfig.has(col.key)) { | |
1248 | + let configItem = this._innerLinkageConfig.get(col.key) | |
1249 | + this.getLinkageOptionsAsync(configItem, '') | |
1250 | + } | |
1251 | + } | |
1252 | + // update-end--author:sunjianlei---date:20210819------for: 处理联动列,联动列只能作用于 select 组件 | |
1091 | 1253 | }) |
1092 | 1254 | return record |
1093 | 1255 | }, |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JVxeTable/components/cells/JVxeSelectCell.vue
... | ... | @@ -7,11 +7,16 @@ |
7 | 7 | v-bind="selectProps" |
8 | 8 | style="width: 100%;" |
9 | 9 | @blur="handleBlur" |
10 | - @change="handleChangeCommon" | |
10 | + @change="handleChange" | |
11 | 11 | @search="handleSearchSelect" |
12 | 12 | > |
13 | 13 | |
14 | - <template v-for="option of originColumn.options"> | |
14 | + <div v-if="loading" slot="notFoundContent"> | |
15 | + <a-icon type="loading" /> | |
16 | + <span> 加载中…</span> | |
17 | + </div> | |
18 | + | |
19 | + <template v-for="option of selectOptions"> | |
15 | 20 | <a-select-option :key="option.value" :value="option.value" :disabled="option.disabled"> |
16 | 21 | <span>{{option.text || option.label || option.title|| option.value}}</span> |
17 | 22 | </a-select-option> |
... | ... | @@ -23,10 +28,18 @@ |
23 | 28 | <script> |
24 | 29 | import JVxeCellMixins, { dispatchEvent } from '@/components/jeecg/JVxeTable/mixins/JVxeCellMixins' |
25 | 30 | import { JVXETypes } from '@comp/jeecg/JVxeTable/index' |
31 | + import { filterDictText } from '@comp/dict/JDictSelectUtil' | |
26 | 32 | |
27 | 33 | export default { |
28 | 34 | name: 'JVxeSelectCell', |
29 | 35 | mixins: [JVxeCellMixins], |
36 | + data(){ | |
37 | + return { | |
38 | + loading: false, | |
39 | + // 异步加载的options(用于多级联动) | |
40 | + asyncOptions: null, | |
41 | + } | |
42 | + }, | |
30 | 43 | computed: { |
31 | 44 | selectProps() { |
32 | 45 | let props = {...this.cellProps} |
... | ... | @@ -37,6 +50,32 @@ |
37 | 50 | } |
38 | 51 | return props |
39 | 52 | }, |
53 | + // 下拉选项 | |
54 | + selectOptions() { | |
55 | + if (this.asyncOptions) { | |
56 | + return this.asyncOptions | |
57 | + } | |
58 | + let {linkage} = this.renderOptions | |
59 | + if (linkage) { | |
60 | + let {getLinkageOptionsSibling, config} = linkage | |
61 | + let res = getLinkageOptionsSibling(this.row, this.originColumn, config, true) | |
62 | + // 当返回Promise时,说明是多级联动 | |
63 | + if (res instanceof Promise) { | |
64 | + this.loading = true | |
65 | + res.then(opt => { | |
66 | + this.asyncOptions = opt | |
67 | + this.loading = false | |
68 | + }).catch(e => { | |
69 | + console.error(e) | |
70 | + this.loading = false | |
71 | + }) | |
72 | + } else { | |
73 | + this.asyncOptions = null | |
74 | + return res | |
75 | + } | |
76 | + } | |
77 | + return this.originColumn.options | |
78 | + }, | |
40 | 79 | }, |
41 | 80 | created() { |
42 | 81 | let multiple = [JVXETypes.selectMultiple, JVXETypes.list_multi] |
... | ... | @@ -54,6 +93,16 @@ |
54 | 93 | }, |
55 | 94 | methods: { |
56 | 95 | |
96 | + handleChange(value) { | |
97 | + debugger | |
98 | + // 处理下级联动 | |
99 | + let linkage = this.renderOptions.linkage | |
100 | + if (linkage) { | |
101 | + linkage.linkageSelectChange(this.row, this.originColumn, linkage.config, value) | |
102 | + } | |
103 | + this.handleChangeCommon(value) | |
104 | + }, | |
105 | + | |
57 | 106 | /** 处理blur失去焦点事件 */ |
58 | 107 | handleBlur(value) { |
59 | 108 | let {allowInput, options} = this.originColumn |
... | ... | @@ -120,7 +169,28 @@ |
120 | 169 | dispatchEvent.call(this, event, 'ant-select') |
121 | 170 | }, |
122 | 171 | }, |
123 | - translate: {enabled: true}, | |
172 | + translate: { | |
173 | + enabled: true, | |
174 | + async handler(value,) { | |
175 | + let options | |
176 | + let {linkage} = this.renderOptions | |
177 | + // 判断是否是多级联动,如果是就通过接口异步翻译 | |
178 | + if (linkage) { | |
179 | + let {getLinkageOptionsSibling, config} = linkage | |
180 | + options = getLinkageOptionsSibling(this.row, this.originColumn, config, true) | |
181 | + if (options instanceof Promise) { | |
182 | + return new Promise(resolve => { | |
183 | + options.then(opt => { | |
184 | + resolve(filterDictText(opt, value)) | |
185 | + }) | |
186 | + }) | |
187 | + } | |
188 | + } else { | |
189 | + options = this.column.own.options | |
190 | + } | |
191 | + return filterDictText(options, value) | |
192 | + }, | |
193 | + }, | |
124 | 194 | getValue(value) { |
125 | 195 | if (Array.isArray(value)) { |
126 | 196 | return value.join(',') |
... | ... |
ant-design-vue-jeecg/src/components/jeecg/JVxeTable/mixins/JVxeCellMixins.js
... | ... | @@ -102,7 +102,13 @@ export default { |
102 | 102 | |
103 | 103 | // 判断是否启用翻译 |
104 | 104 | if (this.renderType === JVXERenderType.spaner && this.enhanced.translate.enabled) { |
105 | - this.innerValue = this.enhanced.translate.handler.call(this, value) | |
105 | + let res = this.enhanced.translate.handler.call(this, value) | |
106 | + // 异步翻译,目前仅【多级联动】使用 | |
107 | + if (res instanceof Promise) { | |
108 | + res.then(value => this.innerValue = value) | |
109 | + } else { | |
110 | + this.innerValue = res | |
111 | + } | |
106 | 112 | } |
107 | 113 | }, |
108 | 114 | }, |
... | ... |
ant-design-vue-jeecg/src/views/jeecg/JVxeDemo/JVxeDemo3.vue
... | ... | @@ -8,123 +8,173 @@ |
8 | 8 | :height="484" |
9 | 9 | :dataSource="dataSource" |
10 | 10 | :columns="columns" |
11 | - @valueChange="handleValueChange" | |
11 | + :linkage-config="linkageConfig" | |
12 | 12 | /> |
13 | 13 | </template> |
14 | 14 | |
15 | 15 | <script> |
16 | - import moment from 'moment' | |
17 | - import { randomNumber, randomUUID } from '@/utils/util' | |
18 | - import { JVXETypes } from '@/components/jeecg/JVxeTable' | |
16 | +import { JVXETypes } from '@/components/jeecg/JVxeTable' | |
19 | 17 | |
20 | - export default { | |
21 | - name: 'JVxeDemo2', | |
22 | - data() { | |
23 | - return { | |
24 | - columns: [ | |
25 | - { | |
26 | - title: '省/直辖市/自治区', | |
27 | - key: 's1', | |
28 | - type: JVXETypes.select, | |
29 | - width: '240px', | |
30 | - options: [], | |
31 | - placeholder: '请选择${title}' | |
32 | - }, | |
33 | - { | |
34 | - title: '市', | |
35 | - key: 's2', | |
36 | - type: JVXETypes.select, | |
37 | - width: '240px', | |
38 | - options: [], | |
39 | - placeholder: '请选择${title}' | |
40 | - }, | |
41 | - { | |
42 | - title: '县/区', | |
43 | - key: 's3', | |
44 | - type: JVXETypes.select, | |
45 | - width: '240px', | |
46 | - options: [], | |
47 | - placeholder: '请选择${title}' | |
48 | - } | |
49 | - ], | |
50 | - dataSource: [], | |
51 | - | |
52 | - mockData: [ | |
53 | - { text: '北京市', value: '110000', parent: null }, | |
54 | - { text: '天津市', value: '120000', parent: null }, | |
55 | - { text: '河北省', value: '130000', parent: null }, | |
56 | - { text: '上海市', value: '310000', parent: null }, | |
57 | - | |
58 | - { text: '北京市', value: '110100', parent: '110000' }, | |
59 | - { text: '天津市市', value: '120100', parent: '120000' }, | |
60 | - { text: '石家庄市', value: '130100', parent: '130000' }, | |
61 | - { text: '唐山市', value: '130200', parent: '130000' }, | |
62 | - { text: '秦皇岛市', value: '130300', parent: '130000' }, | |
63 | - { text: '上海市', value: '310100', parent: '310000' }, | |
64 | - | |
65 | - { text: '东城区', value: '110101', parent: '110100' }, | |
66 | - { text: '西城区', value: '110102', parent: '110100' }, | |
67 | - { text: '朝阳区', value: '110105', parent: '110100' }, | |
68 | - { text: '和平区', value: '120101', parent: '120100' }, | |
69 | - { text: '河东区', value: '120102', parent: '120100' }, | |
70 | - { text: '河西区', value: '120103', parent: '120100' }, | |
71 | - { text: '黄浦区', value: '310101', parent: '310100' }, | |
72 | - { text: '徐汇区', value: '310104', parent: '310100' }, | |
73 | - { text: '长宁区', value: '310105', parent: '310100' }, | |
74 | - { text: '长安区', value: '130102', parent: '130100' }, | |
75 | - { text: '桥西区', value: '130104', parent: '130100' }, | |
76 | - { text: '新华区', value: '130105', parent: '130100' }, | |
77 | - { text: '路南区', value: '130202', parent: '130200' }, | |
78 | - { text: '路北区', value: '130203', parent: '130200' }, | |
79 | - { text: '古冶区', value: '130204', parent: '130200' }, | |
80 | - { text: '海港区', value: '130302', parent: '130300' }, | |
81 | - { text: '山海关区', value: '130303', parent: '130300' }, | |
82 | - { text: '北戴河区', value: '130304', parent: '130300' }, | |
83 | - ] | |
84 | - } | |
18 | +export default { | |
19 | + name: 'JVxeDemo2', | |
20 | + data() { | |
21 | + return { | |
22 | + // 联动配置 | |
23 | + linkageConfig: [ | |
24 | + {requestData: this.requestData, key: 's1'}, | |
25 | + // 可配置多个联动 | |
26 | + {requestData: this.loadData, key: 'level1',}, | |
27 | + ], | |
28 | + columns: [ | |
29 | + { | |
30 | + title: '性别', | |
31 | + key: 'sex', | |
32 | + type: JVXETypes.select, | |
33 | + dictCode: 'sex', | |
34 | + width: '180px', | |
35 | + placeholder: '请选择${title}', | |
36 | + }, | |
37 | + { | |
38 | + title: '省/直辖市/自治区', | |
39 | + key: 's1', | |
40 | + type: JVXETypes.select, | |
41 | + width: '180px', | |
42 | + placeholder: '请选择${title}', | |
43 | + // 联动字段(即下一级的字段) | |
44 | + linkageKey: 's2', | |
45 | + }, | |
46 | + { | |
47 | + title: '市', | |
48 | + key: 's2', | |
49 | + type: JVXETypes.select, | |
50 | + width: '180px', | |
51 | + placeholder: '请选择${title}', | |
52 | + // 联动字段(即下一级的字段) | |
53 | + linkageKey: 's3', | |
54 | + }, | |
55 | + { | |
56 | + title: '县/区', | |
57 | + key: 's3', | |
58 | + type: JVXETypes.select, | |
59 | + width: '180px', | |
60 | + options: [], | |
61 | + placeholder: '请选择${title}', | |
62 | + }, | |
63 | + { | |
64 | + title: '一级', | |
65 | + key: 'level1', | |
66 | + type: JVXETypes.select, | |
67 | + width: '180px', | |
68 | + placeholder: '请选择${title}', | |
69 | + // 联动字段(即下一级的字段) | |
70 | + linkageKey: 'level2', | |
71 | + }, | |
72 | + { | |
73 | + title: '二级', | |
74 | + key: 'level2', | |
75 | + type: JVXETypes.select, | |
76 | + width: '180px', | |
77 | + placeholder: '请选择${title}', | |
78 | + // 联动字段(即下一级的字段) | |
79 | + linkageKey: 'level3', | |
80 | + }, | |
81 | + { | |
82 | + title: '三级', | |
83 | + key: 'level3', | |
84 | + type: JVXETypes.select, | |
85 | + width: '180px', | |
86 | + placeholder: '请选择${title}', | |
87 | + } | |
88 | + ], | |
89 | + dataSource: [ | |
90 | + {sex: '1', s1: '110000', s2: '110100', s3: '110101', level1: '1', level2: '3', level3: '7'}, | |
91 | + {sex: '2', s1: '130000', s2: '130300', s3: '130303', level1: '2', level2: '6', level3: '14'}, | |
92 | + ], | |
93 | + // 模拟数据 | |
94 | + mockData: [ | |
95 | + {text: '北京市', value: '110000', parent: ''}, | |
96 | + {text: '天津市', value: '120000', parent: ''}, | |
97 | + {text: '河北省', value: '130000', parent: ''}, | |
98 | + {text: '上海市', value: '310000', parent: ''}, | |
85 | 99 | |
100 | + {text: '北京市', value: '110100', parent: '110000'}, | |
101 | + {text: '天津市市', value: '120100', parent: '120000'}, | |
102 | + {text: '石家庄市', value: '130100', parent: '130000'}, | |
103 | + {text: '唐山市', value: '130200', parent: '130000'}, | |
104 | + {text: '秦皇岛市', value: '130300', parent: '130000'}, | |
105 | + {text: '上海市', value: '310100', parent: '310000'}, | |
106 | + | |
107 | + {text: '东城区', value: '110101', parent: '110100'}, | |
108 | + {text: '西城区', value: '110102', parent: '110100'}, | |
109 | + {text: '朝阳区', value: '110105', parent: '110100'}, | |
110 | + {text: '和平区', value: '120101', parent: '120100'}, | |
111 | + {text: '河东区', value: '120102', parent: '120100'}, | |
112 | + {text: '河西区', value: '120103', parent: '120100'}, | |
113 | + {text: '黄浦区', value: '310101', parent: '310100'}, | |
114 | + {text: '徐汇区', value: '310104', parent: '310100'}, | |
115 | + {text: '长宁区', value: '310105', parent: '310100'}, | |
116 | + {text: '长安区', value: '130102', parent: '130100'}, | |
117 | + {text: '桥西区', value: '130104', parent: '130100'}, | |
118 | + {text: '新华区', value: '130105', parent: '130100'}, | |
119 | + {text: '路南区', value: '130202', parent: '130200'}, | |
120 | + {text: '路北区', value: '130203', parent: '130200'}, | |
121 | + {text: '古冶区', value: '130204', parent: '130200'}, | |
122 | + {text: '海港区', value: '130302', parent: '130300'}, | |
123 | + {text: '山海关区', value: '130303', parent: '130300'}, | |
124 | + {text: '北戴河区', value: '130304', parent: '130300'}, | |
125 | + ], | |
126 | + mockData1: [ | |
127 | + {id: '1', name: '图书馆', parentId: '0'}, | |
128 | + {id: '2', name: '电影院', parentId: '0'}, | |
129 | + | |
130 | + {id: '3', name: '一楼', parentId: '1'}, | |
131 | + {id: '4', name: '二楼', parentId: '1'}, | |
132 | + {id: '5', name: '中影星美', parentId: '2'}, | |
133 | + {id: '6', name: '万达国际', parentId: '2'}, | |
134 | + | |
135 | + {id: '7', name: '技术图书', parentId: '3'}, | |
136 | + {id: '8', name: '财务图书', parentId: '3'}, | |
137 | + {id: '9', name: '儿童图书', parentId: '4'}, | |
138 | + {id: '10', name: '励志图书', parentId: '4'}, | |
139 | + {id: '11', name: '1号厅', parentId: '5'}, | |
140 | + {id: '12', name: '2号厅', parentId: '5'}, | |
141 | + {id: '13', name: 'I-MAX厅', parentId: '6'}, | |
142 | + {id: '14', name: '3D厅', parentId: '6'}, | |
143 | + ], | |
144 | + } | |
145 | + }, | |
146 | + methods: { | |
147 | + /** | |
148 | + * 模拟从后台查询数据 | |
149 | + */ | |
150 | + requestData(parent) { | |
151 | + return new Promise((resolve, reject) => { | |
152 | + let data = this.mockData.filter(i => i.parent === parent) | |
153 | + setTimeout(() => { | |
154 | + resolve(data) | |
155 | + }, 500) | |
156 | + }) | |
86 | 157 | }, |
87 | - created() { | |
88 | - // 初始化数据 | |
89 | - this.columns[0].options = this.request(null) | |
90 | - }, | |
91 | - methods: { | |
92 | - | |
93 | - request(parentId) { | |
94 | - return this.mockData.filter(i => i.parent === parentId) | |
95 | - }, | |
96 | - | |
97 | - /** 当选项被改变时,联动其他组件 */ | |
98 | - handleValueChange(event) { | |
99 | - const { type, row, column, value, target } = event | |
100 | - console.log("event",event) | |
101 | - if (type === JVXETypes.select) { | |
102 | - | |
103 | - // 第一列 | |
104 | - if (column.key === 's1') { | |
105 | - // 设置第二列的 options | |
106 | - console.log('this.request(value)::',this.request(value)) | |
107 | - target.$refs.vxe.columns[3].options = this.request(value) | |
108 | - // 清空后两列的数据 | |
109 | - target.setValues([{ | |
110 | - rowKey: row.id, | |
111 | - values: { s2: '', s3: '' } | |
112 | - }]) | |
113 | - target.$refs.vxe.columns[4].options = [] | |
114 | - } else | |
115 | - // 第二列 | |
116 | - if (column.key === 's2') { | |
117 | - target.$refs.vxe.columns[4].options = this.request(value) | |
118 | - target.setValues([{ | |
119 | - rowKey: row.id, | |
120 | - values: { s3: '' } | |
121 | - }]) | |
158 | + | |
159 | + // 模拟加载数据,模拟数据格式不同的情况下如何组装数据 | |
160 | + async loadData(parent) { | |
161 | + return new Promise((resolve, reject) => { | |
162 | + let parentId = parent === '' ? '0' : parent | |
163 | + let data = this.mockData1.filter(i => i.parentId === parentId) | |
164 | + data = data.map(item => { | |
165 | + return { | |
166 | + // 必须包含以下两个字段 | |
167 | + value: item.id, | |
168 | + text: item.name, | |
122 | 169 | } |
123 | - } | |
124 | - | |
125 | - } | |
126 | - } | |
170 | + }) | |
171 | + setTimeout(() => { | |
172 | + resolve(data) | |
173 | + }, 500) | |
174 | + }) | |
175 | + }, | |
127 | 176 | } |
177 | +} | |
128 | 178 | </script> |
129 | 179 | |
130 | 180 | <style scoped> |
... | ... |