### 支持 Vue2/Vue3 版本 无差别使用

#### 安装

```bash
npm i @blueking/ediatable
```

#### 使用

##### vue2/vue3框架下使用

```vue
<template>
  <Ediatable :thead-list="theadList">
    <!-- thead-list 等价写法 -->
    <!-- <template #default>
      <RenderTableHeadColumn
        required
        :min-width="120"
        :width="450"
      >
        <span>目标集群</span>
      </RenderTableHeadColumn>
      <RenderTableHeadColumn
        fixed="right"
        :required="false"
        :width="100"
      >
        操作
      </RenderTableHeadColumn>
    </template> -->
    <template #data>
      <RenderRow
        v-for="(item, index) in tableData"
        :key="item.rowKey"
        ref="rowRefs"
        :data="item"
        @add="payload => handleAppend(index, payload)"
        @remove="handleRemove(index)"
      />
    </template>
  </Ediatable>
  <Button
    theme="primary"
    @click="handleSubmit"
  >
    提交
  </Button>
</template>
<script setup lang="tsx">
  import { ref } from 'vue';

  import { Ediatable } from '@blueking/ediatable';
  import('@blueking/ediatable/vue3/vue3.css');

  const rowRefs = ref();
  const tableData = ref([createRowData()]);

  const theadList: IHead[] = [
    {
      minWidth: 120,
      title: '目标集群',
      width: 450,
      renderAppend: () => <span style='color: red;margin-left:5px;font-size:10px'>必填</span>,
    },
    {
      fixed: 'right',
      required: false,
      title: '操作',
      width: 100,
    },
  ];

  // 追加一个集群
  const handleAppend = (index: number, appendList: Array<IDataRow>) => {
    tableData.value.splice(index + 1, 0, ...appendList);
  };

  // 删除一个集群
  const handleRemove = (index: number) => {
    tableData.value.splice(index, 1);
  };

  const handleSubmit = async () => {
    const params = await Promise.all(rowRefs.value.map((item: { getValue: () => any }) => item.getValue()));
    console.log('params>>>', params);
  };
</script>
```

##### RenderRow.vue参考代码

推荐自定义表格的行组件，将每一列的组件纳入其中统一管理，便于后期的增删及交互处理。

```vue
<template>
  <tr>
    <td>
      <RenderTargetCluster
        ref="clusterRef"
        :data="data.cluster"
        @input-finish="handleInputFinish"
      />
    </td>
    <td>
      <TextPlainColumn
        :data="data.nodeType"
        :is-loading="data.isLoading"
        placeholder="输入集群后自动生成"
      />
    </td>
    <td>
      <RenderTargetNumber
        ref="numRef"
        :data="data.targetNum"
        :disabled="!data.cluster"
        :is-loading="data.isLoading"
      />
    </td>
    <td>
      <RenderKeyRelated
        required
        ref="includeKeyRef"
      />
    </td>
    <td>
      <RenderTargetDateTime
        ref="timeRef"
        :data="data.targetDateTime"
        :is-loading="data.isLoading"
      />
    </td>
    <td>
      <RenderSwitchMode
        ref="switchModeRef"
        :data="data.switchMode"
        :is-loading="data.isLoading"
      />
    </td>
    <OperationColumn
      :removeable="removeable"
      show-copy
      @add="handleAppend"
      @remove="handleRemove"
    />
  </tr>
</template>
<script lang="ts">
  import _ from 'lodash';
  import { OperationColumn, TextPlainColumn } from '@blueking/ediatable';
  // 下面这几个都是自定义列组件
  import RenderTargetCluster from './cluster-name.vue';
  import RenderSwitchMode from './switch-mode.vue';
  import RenderTargetNumber from './target-number.vue';
  import RenderKeyRelated from './regex-keys.vue';
  import RenderTargetDateTime from './target-datetime.vue';

  export interface IDataRow {
    rowKey?: string;
    isLoading?: boolean;
    cluster: string;
    nodeType?: string;
    switchMode?: string;
    targetNum?: number;
    targetDateTime?: string;
  }

  const random = () => `${_.random(0, 999999)}_${Date.now()}_${_.random(0, 999999)}`;

  // 创建表格行数据
  export const createRowData = (data?: IDataRow): IDataRow => ({
    rowKey: random(),
    isLoading: false,
    cluster: data?.cluster ?? '',
    nodeType: data?.nodeType ?? '',
    switchMode: data?.switchMode ?? '',
  });
</script>
<script setup lang="ts">
  import { ref } from 'vue';
  interface Props {
    data: IDataRow;
    removeable: boolean;
  }

  interface Emits {
    (e: 'add', params: Array<IDataRow>): void;
    (e: 'remove'): void;
    (e: 'clusterInputFinish', value: string): void;
  }

  interface Exposes {
    getValue: () => Promise<{
      cluster: string;
      target_num: number;
      include_keys: string[];
      target_time: string;
      mode: string;
    }>;
  }

  const props = defineProps<Props>();

  const emits = defineEmits<Emits>();

  const clusterRef = ref<InstanceType<typeof RenderTargetCluster>>();
  const numRef = ref<InstanceType<typeof RenderTargetNumber>>();
  const includeKeyRef = ref<InstanceType<typeof RenderKeyRelated>>();
  const timeRef = ref<InstanceType<typeof RenderTargetDateTime>>();
  const switchModeRef = ref<InstanceType<typeof RenderSwitchMode>>();

  const handleInputFinish = (value: string) => {
    emits('clusterInputFinish', value);
  };

  const handleAppend = () => {
    emits('add', [createRowData()]);
  };

  const handleRemove = () => {
    if (props.removeable) {
      return;
    }
    emits('remove');
  };

  defineExpose<Exposes>({
    async getValue() {
      return await Promise.all([
        clusterRef.value!.getValue(),
        numRef.value!.getValue(),
        includeKeyRef.value!.getValue(),
        timeRef.value!.getValue(),
        switchModeRef.value!.getValue(),
      ]).then(data => {
        const [cluster, target_num, include_keys, target_time, mode] = data;
        return {
          cluster,
          target_num,
          include_keys,
          target_time,
          mode,
        };
      });
    },
  });
</script>
```

##### RenderTargetCluster.vue参考代码

其他自定义列组件也可参考进行封装

```vue
<template>
  <InputColumn
    ref="editRef"
    v-model="localValue"
    placeholder=”请输入或选择集群"
    :rules="rules"
    @submit="value => handleInputFinish(value)"
  />
</template>
<script setup lang="ts">
  import { ref, watch } from 'vue';

  import { InputColumn } from '@blueking/ediatable';

  interface Props {
    data?: string;
  }

  interface Emits {
    (e: 'input-finish', value: string): void;
  }

  interface Exposes {
    getValue: () => Promise<string>;
  }

  const props = withDefaults(defineProps<Props>(), {
    data: '',
    inputed: () => [],
  });

  const emits = defineEmits<Emits>();

  const localValue = ref(props.data);
  const editRef = ref();

  const rules = [
    {
      validator: (value: string) => Boolean(value),
      message: '目标集群不能为空',
    },
  ];

  watch(
    () => props.data,
    data => {
      localValue.value = data;
    },
    {
      immediate: true,
    },
  );

  const handleInputFinish = (value: string) => {
    emits('input-finish', value);
  };

  defineExpose<Exposes>({
    getValue() {
      return editRef.value.getValue().then(() => localValue.value);
    },
  });
</script>
```

### 属性列表

| 属性名    | 描述         | 属性类型       | 默认值 |
| --------- | ------------ | -------------- | ------ |
| theadList | 表头列表配置 | `Array<IHead>` | []     |

#### IHead

| 属性名       | 描述                   | 属性类型                         | 默认值    |
| ------------ | ---------------------- | -------------------------------- | --------- |
| fixed        | 表头列是否固定         | `right 或 left 或 undefined`     | undefined |
| maxWidth     | 表头列最大宽度         | `number 或 undefined`            | undefined |
| minWidth     | 表头列最小宽度         | `number 或 undefined`            | undefined |
| memo         | 列名hover时的提示      | `string 或 undefined`            | undefined |
| required     | 是否必填标志           | `boolean`                        | true      |
| title        | 表头列名               | `string 或 undefined`            | undefined |
| width        | 表头列宽度             | `number 或 undefined`            | undefined |
| renderAppend | 表头列名之后追加的元素 | `() => JSX.Element 或 undefined` | undefined |

### Slots插槽

| 名称    | 描述 |
| ------- | ---- |
| default | 表头 |
| data    | 列表 |

### 可编辑列基础组件(基于bkui-vue3组件库)

#### IRule

| 属性名    | 描述         | 属性类型                                      | 默认值 |
| --------- | ------------ | --------------------------------------------- | ------ |
| validator | 校验函数     | `(value: any) => boolean 或 Promise<boolean>` | 无     |
| message   | 校验出错提示 | `string 或 (() => string)`                    | 无     |

#### 输入框组件

##### 组件引用

```vue
<script lang="ts">
  import { InputColumn } from '@blueking/ediatable';
</script>
```

##### 属性列表

| 属性名 | 描述         | 属性类型  | 默认值    |
| ------ | ------------ | --------- | --------- |
| rules  | 校验规则配置 | `IRule[]` | undefined |

其他配置同 `bkui-vue3` 的 `Input` 组件

##### Emits事件列表

| 事件名 | 参数  | 参数类型           | 描述         |
| ------ | ----- | ------------------ | ------------ |
| submit | value | `string 或 number` | 输入完成事件 |
| error  | value | `boolean`          | 校验报错事件 |
| clear  |       |                    | 清空事件 ｜  |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |
| focus    | 组件聚焦         |

#### 时间选择器组件

##### 组件引用

```vue
<script lang="ts">
  import { DateTimePickerColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名 | 描述         | 属性类型  | 默认值    |
| ------ | ------------ | --------- | --------- |
| rules  | 校验规则配置 | `IRule[]` | undefined |

其他配置同 `bkui-vue3` 的 `TimerPicker` 组件

##### Emits事件列表

| 事件名 | 参数  | 参数类型                     | 描述         |
| ------ | ----- | ---------------------------- | ------------ |
| change | value | `[string, string] 或 string` | 选择完成事件 |
| error  | value | `boolean`                    | 校验报错事件 |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |

#### 下拉选框组件

##### 组件引用

```vue
<script lang="ts">
  import { SelectColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名 | 描述         | 属性类型  | 默认值    |
| ------ | ------------ | --------- | --------- |
| rules  | 校验规则配置 | `IRule[]` | undefined |

其他配置同 `bkui-vue3` 的 `Select` 组件

##### Emits事件列表

| 事件名 | 参数  | 参数类型           | 描述         |
| ------ | ----- | ------------------ | ------------ |
| change | value | `string 或 number` | 选择完成事件 |
| error  | value | `boolean`          | 校验报错事件 |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |

#### TagInput输入框组件

##### 组件引用

```vue
<script lang="ts">
  import { TagInputColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名 | 描述         | 属性类型  | 默认值    |
| ------ | ------------ | --------- | --------- |
| rules  | 校验规则配置 | `IRule[]` | undefined |

其他配置同 `bkui-vue3` 的 `TagInput` 组件

##### Emits事件列表

| 事件名 | 参数  | 参数类型   | 描述         |
| ------ | ----- | ---------- | ------------ |
| change | value | `string[]` | 输入完成事件 |
| error  | value | `boolean`  | 校验报错事件 |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |

##### Slots插槽

| 名称 | 描述                  |
| ---- | --------------------- |
| tip  | 聚焦后的 popover 提示 |

#### 纯文本展示组件

##### 组件引用

```vue
<script lang="ts">
  import { TagInputColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名      | 描述         | 属性类型                        | 默认值    |
| ----------- | ------------ | ------------------------------- | --------- |
| data        | 文本内容     | `string 或 number 或 undefined` | undefined |
| isLoading   | 是否加载中   | `boolean 或 undefined`          | undefined |
| placeholder | 空白提示     | `string  或 undefined`          | undefined |
| rules       | 校验规则配置 | `IRule[] 或 undefined`          | undefined |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |

#### 复选框组件

##### 组件引用

```vue
<script lang="ts">
  import { CheckboxColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名   | 描述         | 属性类型  | 默认值    |
| -------- | ------------ | --------- | --------- |
| disabled | 是否禁用     | `boolean` | false     |
| rules    | 校验规则配置 | `IRule[]` | undefined |

其他配置同 `bkui-vue3` 的 `Checkbox` 组件

##### Emits事件列表

| 事件名 | 参数  | 参数类型  | 描述         |
| ------ | ----- | --------- | ------------ |
| submit | value | `boolean` | 选择完成事件 |
| error  | value | `boolean` | 校验报错事件 |

##### Exposes事件列表

| 事件名   | 描述             |
| -------- | ---------------- |
| getValue | 校验并获取最新值 |

#### 操作列组件

##### 组件引用

```vue
<script lang="ts">
  import { OperationColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名     | 描述               | 属性类型    | 默认值 |
| ---------- | ------------------ | ----------- | ------ |
| removeable | 删除图标是否可用   | `boolean`   | true   |
| showCopy   | 是否展示行克隆图标 | `boolean`   | false  |
| showAdd    | 是否展示添加图标   | `boolean  ` | true   |
| showRemove | 是否展示删除图标   | `boolean `  | true   |

##### Emits事件列表

| 事件名 | 参数 | 参数类型 | 描述     |
| ------ | ---- | -------- | -------- |
| add    |      |          | 添加事件 |
| copy   |      |          | 克隆事件 |
| remove |      |          | 删除事件 |

#### 固定列组件

##### 组件引用

```vue
<script lang="ts">
  import { FixedColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

| 属性名 | 描述       | 属性类型        | 默认值 |
| ------ | ---------- | --------------- | ------ |
| fixed  | 是否固定列 | `left 或 right` | right  |

#### 表头列组件

##### 组件引用

```vue
<script lang="ts">
  import { HeadColumn } from '@blueking/ediatable';
</script>
```

##### 组件属性

同 `IHead` 配置

##### Slots插槽

| 名称    | 描述         |
| ------- | ------------ |
| default | 表头         |
| append  | 表头追加元素 |
