Explorar o código

feat(basic-table): add `ApiTreeSelect` edit component

为表格添加ApiTreeSelect编辑组件,修复一些其它的已知问题
无木 %!s(int64=3) %!d(string=hai) anos
pai
achega
52af1dd0d4

+ 3 - 0
CHANGELOG.zh_CN.md

@@ -3,6 +3,7 @@
 - **NoticeList** 添加分页、超长自动省略、标题点击事件、标题删除线等功能
 - **MixSider** 优化 Mix 菜单布局时 底部折叠按钮 的样式,与其它菜单布局时的风格保持一致
 - **ApiTreeSelect** 扩展`antdv`的`TreeSelect`组件,支持远程数据源,用法类似`ApiSelect`
+- **BasicTable** 新增`ApiTreeSelect`编辑组件
 - 可以为不同的用户指定不同的后台首页:
   - 在`getUserInfo`接口返回的用户信息中增加`homePath`字段(可选)即可为当前用户定制首页路径
 
@@ -14,6 +15,8 @@
   - 新增`headerTop`插槽
   - 修复操作列的按钮在 disabled 状态下的颜色显示
   - 修复可编辑单元格的值不能直接通过修改`dataSource`来更新显示的问题
+  - 修复使用`ApiSelect`编辑组件时的数据回显问题
+  - 修复在部分场景下编辑组件可能会报`onXXX`类型错误的问题
 - **TableAction**
   - 仅在 `action.tooltip`存在的情况下 才创建 Tooltip 组件
   - 修复组件内的圆形按钮内容没有居中的问题

+ 1 - 0
src/components/Form/index.ts

@@ -8,5 +8,6 @@ export { useForm } from './src/hooks/useForm';
 
 export { default as ApiSelect } from './src/components/ApiSelect.vue';
 export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue';
+export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue';
 
 export { BasicForm };

+ 2 - 1
src/components/Table/src/componentMap.ts

@@ -9,7 +9,7 @@ import {
   TimePicker,
 } from 'ant-design-vue';
 import type { ComponentType } from './types/componentType';
-import { ApiSelect } from '/@/components/Form';
+import { ApiSelect, ApiTreeSelect } from '/@/components/Form';
 
 const componentMap = new Map<ComponentType, Component>();
 
@@ -17,6 +17,7 @@ componentMap.set('Input', Input);
 componentMap.set('InputNumber', InputNumber);
 componentMap.set('Select', Select);
 componentMap.set('ApiSelect', ApiSelect);
+componentMap.set('ApiTreeSelect', ApiTreeSelect);
 componentMap.set('Switch', Switch);
 componentMap.set('Checkbox', Checkbox);
 componentMap.set('DatePicker', DatePicker);

+ 1 - 1
src/components/Table/src/components/editable/CellComponent.ts

@@ -19,7 +19,7 @@ export const CellComponent: FunctionalComponent = (
   const Comp = componentMap.get(component) as typeof defineComponent;
 
   const DefaultComp = h(Comp, attrs);
-  if (!rule) {
+  if (!rule || !popoverVisible) {
     return DefaultComp;
   }
   return h(

+ 17 - 2
src/components/Table/src/components/editable/EditableCell.vue

@@ -45,6 +45,7 @@
   import { isString, isBoolean, isFunction, isNumber, isArray } from '/@/utils/is';
   import { createPlaceholderMessage } from './helper';
   import { set, omit } from 'lodash-es';
+  import { treeToList } from '/@/utils/helper/treeHelper';
 
   export default defineComponent({
     name: 'EditableCell',
@@ -276,9 +277,23 @@
         }
       }
 
-      // only ApiSelect
+      // only ApiSelect or TreeSelect
       function handleOptionsChange(options: LabelValueOptions) {
-        optionsRef.value = options;
+        const { replaceFields } = props.column?.editComponentProps ?? {};
+        const component = unref(getComponent);
+        if (component === 'ApiTreeSelect') {
+          const { title = 'title', value = 'value', children = 'children' } = replaceFields || {};
+          let listOptions: Recordable[] = treeToList(options, { children });
+          listOptions = listOptions.map((item) => {
+            return {
+              label: item[title],
+              value: item[value],
+            };
+          });
+          optionsRef.value = listOptions as LabelValueOptions;
+        } else {
+          optionsRef.value = options;
+        }
       }
 
       function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) {

+ 1 - 0
src/components/Table/src/types/componentType.ts

@@ -3,6 +3,7 @@ export type ComponentType =
   | 'InputNumber'
   | 'Select'
   | 'ApiSelect'
+  | 'ApiTreeSelect'
   | 'Checkbox'
   | 'Switch'
   | 'DatePicker'

+ 13 - 12
src/views/demo/table/EditCellTable.vue

@@ -8,12 +8,12 @@
   </div>
 </template>
 <script lang="ts">
-  import { defineComponent, ref } from 'vue';
+  import { defineComponent } from 'vue';
   import { BasicTable, useTable, BasicColumn } from '/@/components/Table';
   import { optionsListApi } from '/@/api/demo/select';
 
   import { demoListApi } from '/@/api/demo/table';
-  const optionsData = ref([]);
+  import { treeOptionsListApi } from '/@/api/demo/tree';
   const columns: BasicColumn[] = [
     {
       title: '输入框',
@@ -88,17 +88,18 @@
         resultField: 'list',
         labelField: 'name',
         valueField: 'id',
-        onOptionsChange(options) {
-          optionsData.value = options;
-        },
       },
-      editValueMap(value: any) {
-        const found = optionsData.value.find((option) => option.id === value);
-        if (found) {
-          return found.name;
-        } else {
-          return value;
-        }
+      width: 200,
+    },
+    {
+      title: '远程下拉树',
+      dataIndex: 'name7',
+      edit: true,
+      editComponent: 'ApiTreeSelect',
+      editRule: false,
+      editComponentProps: {
+        api: treeOptionsListApi,
+        resultField: 'list',
       },
       width: 200,
     },

+ 12 - 11
src/views/demo/table/EditRowTable.vue

@@ -20,7 +20,7 @@
   import { optionsListApi } from '/@/api/demo/select';
 
   import { demoListApi } from '/@/api/demo/table';
-  const optionsData = ref([]);
+  import { treeOptionsListApi } from '/@/api/demo/tree';
 
   const columns: BasicColumn[] = [
     {
@@ -100,17 +100,18 @@
         resultField: 'list',
         labelField: 'name',
         valueField: 'id',
-        onOptionsChange(options) {
-          optionsData.value = options;
-        },
       },
-      editValueMap(value: any) {
-        const found = optionsData.value.find((option) => option.id === value);
-        if (found) {
-          return found.name;
-        } else {
-          return value;
-        }
+      width: 200,
+    },
+    {
+      title: '远程下拉树',
+      dataIndex: 'name7',
+      editRow: true,
+      editComponent: 'ApiTreeSelect',
+      editRule: false,
+      editComponentProps: {
+        api: treeOptionsListApi,
+        resultField: 'list',
       },
       width: 200,
     },