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,6 +3,7 @@ | ||
3 | - **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能 | 3 | - **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能 |
4 | - **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致 | 4 | - **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致 |
5 | - **ApiTreeSelect** 扩展`antdv`的`TreeSelect`组件,支持远程数据源,用法类似`ApiSelect` | 5 | - **ApiTreeSelect** 扩展`antdv`的`TreeSelect`组件,支持远程数据源,用法类似`ApiSelect` |
6 | +- **BasicTable** 新增`ApiTreeSelect`编辑组件 | ||
6 | - 可以为不同的用户指定不同的后台首页: | 7 | - 可以为不同的用户指定不同的后台首页: |
7 | - 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径 | 8 | - 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径 |
8 | 9 | ||
@@ -14,6 +15,8 @@ | @@ -14,6 +15,8 @@ | ||
14 | - 新增`headerTop`插槽 | 15 | - 新增`headerTop`插槽 |
15 | - 修复操作列的按钮在 disabled 状态下的颜色显示 | 16 | - 修复操作列的按钮在 disabled 状态下的颜色显示 |
16 | - 修复可编辑单元格的值不能直接通过修改`dataSource`来更新显示的问题 | 17 | - 修复可编辑单元格的值不能直接通过修改`dataSource`来更新显示的问题 |
18 | + - 修复使用`ApiSelect`编辑组件时的数据回显问题 | ||
19 | + - 修复在部分场景下编辑组件可能会报`onXXX`类型错误的问题 | ||
17 | - **TableAction** | 20 | - **TableAction** |
18 | - 仅在 `action.tooltip`存在的情况下 才创建 Tooltip 组件 | 21 | - 仅在 `action.tooltip`存在的情况下 才创建 Tooltip 组件 |
19 | - 修复组件内的圆形按钮内容没有居中的问题 | 22 | - 修复组件内的圆形按钮内容没有居中的问题 |
src/components/Form/index.ts
@@ -8,5 +8,6 @@ export { useForm } from './src/hooks/useForm'; | @@ -8,5 +8,6 @@ export { useForm } from './src/hooks/useForm'; | ||
8 | 8 | ||
9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; | 9 | export { default as ApiSelect } from './src/components/ApiSelect.vue'; |
10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; | 10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue'; |
11 | +export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue'; | ||
11 | 12 | ||
12 | export { BasicForm }; | 13 | export { BasicForm }; |
src/components/Table/src/componentMap.ts
@@ -9,7 +9,7 @@ import { | @@ -9,7 +9,7 @@ import { | ||
9 | TimePicker, | 9 | TimePicker, |
10 | } from 'ant-design-vue'; | 10 | } from 'ant-design-vue'; |
11 | import type { ComponentType } from './types/componentType'; | 11 | import type { ComponentType } from './types/componentType'; |
12 | -import { ApiSelect } from '/@/components/Form'; | 12 | +import { ApiSelect, ApiTreeSelect } from '/@/components/Form'; |
13 | 13 | ||
14 | const componentMap = new Map<ComponentType, Component>(); | 14 | const componentMap = new Map<ComponentType, Component>(); |
15 | 15 | ||
@@ -17,6 +17,7 @@ componentMap.set('Input', Input); | @@ -17,6 +17,7 @@ componentMap.set('Input', Input); | ||
17 | componentMap.set('InputNumber', InputNumber); | 17 | componentMap.set('InputNumber', InputNumber); |
18 | componentMap.set('Select', Select); | 18 | componentMap.set('Select', Select); |
19 | componentMap.set('ApiSelect', ApiSelect); | 19 | componentMap.set('ApiSelect', ApiSelect); |
20 | +componentMap.set('ApiTreeSelect', ApiTreeSelect); | ||
20 | componentMap.set('Switch', Switch); | 21 | componentMap.set('Switch', Switch); |
21 | componentMap.set('Checkbox', Checkbox); | 22 | componentMap.set('Checkbox', Checkbox); |
22 | componentMap.set('DatePicker', DatePicker); | 23 | componentMap.set('DatePicker', DatePicker); |
src/components/Table/src/components/editable/CellComponent.ts
@@ -19,7 +19,7 @@ export const CellComponent: FunctionalComponent = ( | @@ -19,7 +19,7 @@ export const CellComponent: FunctionalComponent = ( | ||
19 | const Comp = componentMap.get(component) as typeof defineComponent; | 19 | const Comp = componentMap.get(component) as typeof defineComponent; |
20 | 20 | ||
21 | const DefaultComp = h(Comp, attrs); | 21 | const DefaultComp = h(Comp, attrs); |
22 | - if (!rule) { | 22 | + if (!rule || !popoverVisible) { |
23 | return DefaultComp; | 23 | return DefaultComp; |
24 | } | 24 | } |
25 | return h( | 25 | return h( |
src/components/Table/src/components/editable/EditableCell.vue
@@ -45,6 +45,7 @@ | @@ -45,6 +45,7 @@ | ||
45 | import { isString, isBoolean, isFunction, isNumber, isArray } from '/@/utils/is'; | 45 | import { isString, isBoolean, isFunction, isNumber, isArray } from '/@/utils/is'; |
46 | import { createPlaceholderMessage } from './helper'; | 46 | import { createPlaceholderMessage } from './helper'; |
47 | import { set, omit } from 'lodash-es'; | 47 | import { set, omit } from 'lodash-es'; |
48 | + import { treeToList } from '/@/utils/helper/treeHelper'; | ||
48 | 49 | ||
49 | export default defineComponent({ | 50 | export default defineComponent({ |
50 | name: 'EditableCell', | 51 | name: 'EditableCell', |
@@ -276,9 +277,23 @@ | @@ -276,9 +277,23 @@ | ||
276 | } | 277 | } |
277 | } | 278 | } |
278 | 279 | ||
279 | - // only ApiSelect | 280 | + // only ApiSelect or TreeSelect |
280 | function handleOptionsChange(options: LabelValueOptions) { | 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 | function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) { | 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,12 +8,12 @@ | ||
8 | </div> | 8 | </div> |
9 | </template> | 9 | </template> |
10 | <script lang="ts"> | 10 | <script lang="ts"> |
11 | - import { defineComponent, ref } from 'vue'; | 11 | + import { defineComponent } from 'vue'; |
12 | import { BasicTable, useTable, BasicColumn } from '/@/components/Table'; | 12 | import { BasicTable, useTable, BasicColumn } from '/@/components/Table'; |
13 | import { optionsListApi } from '/@/api/demo/select'; | 13 | import { optionsListApi } from '/@/api/demo/select'; |
14 | 14 | ||
15 | import { demoListApi } from '/@/api/demo/table'; | 15 | import { demoListApi } from '/@/api/demo/table'; |
16 | - const optionsData = ref([]); | 16 | + import { treeOptionsListApi } from '/@/api/demo/tree'; |
17 | const columns: BasicColumn[] = [ | 17 | const columns: BasicColumn[] = [ |
18 | { | 18 | { |
19 | title: '输入框', | 19 | title: '输入框', |
@@ -88,17 +88,18 @@ | @@ -88,17 +88,18 @@ | ||
88 | resultField: 'list', | 88 | resultField: 'list', |
89 | labelField: 'name', | 89 | labelField: 'name', |
90 | valueField: 'id', | 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 | width: 200, | 104 | width: 200, |
104 | }, | 105 | }, |
src/views/demo/table/EditRowTable.vue
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | import { optionsListApi } from '/@/api/demo/select'; | 20 | import { optionsListApi } from '/@/api/demo/select'; |
21 | 21 | ||
22 | import { demoListApi } from '/@/api/demo/table'; | 22 | import { demoListApi } from '/@/api/demo/table'; |
23 | - const optionsData = ref([]); | 23 | + import { treeOptionsListApi } from '/@/api/demo/tree'; |
24 | 24 | ||
25 | const columns: BasicColumn[] = [ | 25 | const columns: BasicColumn[] = [ |
26 | { | 26 | { |
@@ -100,17 +100,18 @@ | @@ -100,17 +100,18 @@ | ||
100 | resultField: 'list', | 100 | resultField: 'list', |
101 | labelField: 'name', | 101 | labelField: 'name', |
102 | valueField: 'id', | 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 | width: 200, | 116 | width: 200, |
116 | }, | 117 | }, |