Commit 52af1dd0d494e66c0af20f886dcc2b983cbb096f
1 parent
897bed97
feat(basic-table): add `ApiTreeSelect` edit component
为表格添加ApiTreeSelect编辑组件,修复一些其它的已知问题
Showing
8 changed files
with
50 additions
and
27 deletions
CHANGELOG.zh_CN.md
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | - **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能 |
4 | 4 | - **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致 |
5 | 5 | - **ApiTreeSelect** 扩展`antdv`的`TreeSelect`组件,支持远程数据源,用法类似`ApiSelect` |
6 | +- **BasicTable** 新增`ApiTreeSelect`编辑组件 | |
6 | 7 | - 可以为不同的用户指定不同的后台首页: |
7 | 8 | - 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径 |
8 | 9 | |
... | ... | @@ -14,6 +15,8 @@ |
14 | 15 | - 新增`headerTop`插槽 |
15 | 16 | - 修复操作列的按钮在 disabled 状态下的颜色显示 |
16 | 17 | - 修复可编辑单元格的值不能直接通过修改`dataSource`来更新显示的问题 |
18 | + - 修复使用`ApiSelect`编辑组件时的数据回显问题 | |
19 | + - 修复在部分场景下编辑组件可能会报`onXXX`类型错误的问题 | |
17 | 20 | - **TableAction** |
18 | 21 | - 仅在 `action.tooltip`存在的情况下 才创建 Tooltip 组件 |
19 | 22 | - 修复组件内的圆形按钮内容没有居中的问题 | ... | ... |
src/components/Form/index.ts
... | ... | @@ -8,5 +8,6 @@ export { useForm } from './src/hooks/useForm'; |
8 | 8 | |
9 | 9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; |
10 | 10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; |
11 | +export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; | |
11 | 12 | |
12 | 13 | export { BasicForm }; | ... | ... |
src/components/Table/src/componentMap.ts
... | ... | @@ -9,7 +9,7 @@ import { |
9 | 9 | TimePicker, |
10 | 10 | } from 'ant-design-vue'; |
11 | 11 | import type { ComponentType } from './types/componentType'; |
12 | -import { ApiSelect } from '/@/components/Form'; | |
12 | +import { ApiSelect, ApiTreeSelect } from '/@/components/Form'; | |
13 | 13 | |
14 | 14 | const componentMap = new Map<ComponentType, Component>(); |
15 | 15 | |
... | ... | @@ -17,6 +17,7 @@ componentMap.set('Input', Input); |
17 | 17 | componentMap.set('InputNumber', InputNumber); |
18 | 18 | componentMap.set('Select', Select); |
19 | 19 | componentMap.set('ApiSelect', ApiSelect); |
20 | +componentMap.set('ApiTreeSelect', ApiTreeSelect); | |
20 | 21 | componentMap.set('Switch', Switch); |
21 | 22 | componentMap.set('Checkbox', Checkbox); |
22 | 23 | componentMap.set('DatePicker', DatePicker); | ... | ... |
src/components/Table/src/components/editable/CellComponent.ts
... | ... | @@ -19,7 +19,7 @@ export const CellComponent: FunctionalComponent = ( |
19 | 19 | const Comp = componentMap.get(component) as typeof defineComponent; |
20 | 20 | |
21 | 21 | const DefaultComp = h(Comp, attrs); |
22 | - if (!rule) { | |
22 | + if (!rule || !popoverVisible) { | |
23 | 23 | return DefaultComp; |
24 | 24 | } |
25 | 25 | return h( | ... | ... |
src/components/Table/src/components/editable/EditableCell.vue
... | ... | @@ -45,6 +45,7 @@ |
45 | 45 | import { isString, isBoolean, isFunction, isNumber, isArray } from '/@/utils/is'; |
46 | 46 | import { createPlaceholderMessage } from './helper'; |
47 | 47 | import { set, omit } from 'lodash-es'; |
48 | + import { treeToList } from '/@/utils/helper/treeHelper'; | |
48 | 49 | |
49 | 50 | export default defineComponent({ |
50 | 51 | name: 'EditableCell', |
... | ... | @@ -276,9 +277,23 @@ |
276 | 277 | } |
277 | 278 | } |
278 | 279 | |
279 | - // only ApiSelect | |
280 | + // only ApiSelect or TreeSelect | |
280 | 281 | function handleOptionsChange(options: LabelValueOptions) { |
281 | - optionsRef.value = options; | |
282 | + const { replaceFields } = props.column?.editComponentProps ?? {}; | |
283 | + const component = unref(getComponent); | |
284 | + if (component === 'ApiTreeSelect') { | |
285 | + const { title = 'title', value = 'value', children = 'children' } = replaceFields || {}; | |
286 | + let listOptions: Recordable[] = treeToList(options, { children }); | |
287 | + listOptions = listOptions.map((item) => { | |
288 | + return { | |
289 | + label: item[title], | |
290 | + value: item[value], | |
291 | + }; | |
292 | + }); | |
293 | + optionsRef.value = listOptions as LabelValueOptions; | |
294 | + } else { | |
295 | + optionsRef.value = options; | |
296 | + } | |
282 | 297 | } |
283 | 298 | |
284 | 299 | function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) { | ... | ... |
src/components/Table/src/types/componentType.ts
src/views/demo/table/EditCellTable.vue
... | ... | @@ -8,12 +8,12 @@ |
8 | 8 | </div> |
9 | 9 | </template> |
10 | 10 | <script lang="ts"> |
11 | - import { defineComponent, ref } from 'vue'; | |
11 | + import { defineComponent } from 'vue'; | |
12 | 12 | import { BasicTable, useTable, BasicColumn } from '/@/components/Table'; |
13 | 13 | import { optionsListApi } from '/@/api/demo/select'; |
14 | 14 | |
15 | 15 | import { demoListApi } from '/@/api/demo/table'; |
16 | - const optionsData = ref([]); | |
16 | + import { treeOptionsListApi } from '/@/api/demo/tree'; | |
17 | 17 | const columns: BasicColumn[] = [ |
18 | 18 | { |
19 | 19 | title: '输入框', |
... | ... | @@ -88,17 +88,18 @@ |
88 | 88 | resultField: 'list', |
89 | 89 | labelField: 'name', |
90 | 90 | valueField: 'id', |
91 | - onOptionsChange(options) { | |
92 | - optionsData.value = options; | |
93 | - }, | |
94 | 91 | }, |
95 | - editValueMap(value: any) { | |
96 | - const found = optionsData.value.find((option) => option.id === value); | |
97 | - if (found) { | |
98 | - return found.name; | |
99 | - } else { | |
100 | - return value; | |
101 | - } | |
92 | + width: 200, | |
93 | + }, | |
94 | + { | |
95 | + title: '远程下拉树', | |
96 | + dataIndex: 'name7', | |
97 | + edit: true, | |
98 | + editComponent: 'ApiTreeSelect', | |
99 | + editRule: false, | |
100 | + editComponentProps: { | |
101 | + api: treeOptionsListApi, | |
102 | + resultField: 'list', | |
102 | 103 | }, |
103 | 104 | width: 200, |
104 | 105 | }, | ... | ... |
src/views/demo/table/EditRowTable.vue
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | import { optionsListApi } from '/@/api/demo/select'; |
21 | 21 | |
22 | 22 | import { demoListApi } from '/@/api/demo/table'; |
23 | - const optionsData = ref([]); | |
23 | + import { treeOptionsListApi } from '/@/api/demo/tree'; | |
24 | 24 | |
25 | 25 | const columns: BasicColumn[] = [ |
26 | 26 | { |
... | ... | @@ -100,17 +100,18 @@ |
100 | 100 | resultField: 'list', |
101 | 101 | labelField: 'name', |
102 | 102 | valueField: 'id', |
103 | - onOptionsChange(options) { | |
104 | - optionsData.value = options; | |
105 | - }, | |
106 | 103 | }, |
107 | - editValueMap(value: any) { | |
108 | - const found = optionsData.value.find((option) => option.id === value); | |
109 | - if (found) { | |
110 | - return found.name; | |
111 | - } else { | |
112 | - return value; | |
113 | - } | |
104 | + width: 200, | |
105 | + }, | |
106 | + { | |
107 | + title: '远程下拉树', | |
108 | + dataIndex: 'name7', | |
109 | + editRow: true, | |
110 | + editComponent: 'ApiTreeSelect', | |
111 | + editRule: false, | |
112 | + editComponentProps: { | |
113 | + api: treeOptionsListApi, | |
114 | + resultField: 'list', | |
114 | 115 | }, |
115 | 116 | width: 200, |
116 | 117 | }, | ... | ... |