<script setup>
import ViewForm from './field/index.vue'
//  import {Table, TableColumn} from '@king-design/vue';//ssr打包报错，启动会注入ksconsole/components和kpc
const filedHeaders=[
  {key:"field",title:"属性"},
  {key:"desc",title:"说明"},
  {key:"type",title:"类型"},
  {key:"required",title:"是否必填"},
  {key:"defaultValue",title:"默认值"},
]
	
const filedData0= [
	{
		field: 'onSubmit',
		type: 'Function',
		defaultValue: "无",
		required: '否',
		desc: "提交事件，自定义底部按钮时候必传！配合submitloading（控制按钮loading状态）来控制确认按钮的相关逻辑"
	},
  {
		field: 'validate',
		type: 'Function',
		defaultValue: "false",
		required: '否',
		desc: "当无底部按钮，通过外部按钮处理表单逻辑时候，需要手动触发表单表单的验证"
	},
  {
		field: 'reset',
		type: 'Function',
		defaultValue: "无",
		required: '否',
		desc: "重置表单验证状态"
	},
  {
		field: 'addMethod',
		type: 'Function',
		defaultValue: "无",
		required: '否',
		desc: "添加全局验证规则，这样在所有 KsField 中如果需要使用该规则，只需要在rules中写上该规则名即可	"
	},
]
const filedData1= [
  {
		field: 'gColSpan',
		type: 'Number',
		required: '否',
		defaultValue: "24",
		desc: "控制全局的栅格布局，默认24展示为一栏"
	},
   {
		field: 'contWidth',
		type: 'String',
		required: '否',
		defaultValue: "无",
		desc: "控制全局右侧content宽度"
	},
   {
		field: 'labelWidth',
		type: 'String | number',
		required: '否',
		defaultValue: "无",
		desc: "定义所有子孙FormItem组件的label宽度，继承kpc form的原生方法"
	},
	{
		field: 'submitloading',
		type: 'Boolean',
		required: '否',
		defaultValue: "false",
		desc: "控制确认按钮 loading 状态"
	},
	{
		field: 'oktext',
		type: 'String',
		required: '否',
		defaultValue: "确认",
		desc: "确认按钮文本"
	},	
	{
		field: 'canceltext',
		type: 'String',
		required: '否',
		defaultValue: "取消",
		desc: "取消按钮文本"
	},
  {
		field: 'label',
		type: 'slot插槽',
		required: '否',
		defaultValue: "无",
		desc: "自定义label内容，插槽label优先级高于entity中配置的label属性"
	},
  {
		field: 'cont',
		type: 'slot插槽',
		required: '否',
		defaultValue: "无",
		desc: "自定义右侧内容, 适用于一些只读内容"
  },
	{
		field: 'unit',
		type: 'slot插槽',
		required: '否',
		defaultValue: "无",
		desc: "跟随在 field 后面的单位"
	},
	{
		field: 'tip',
		type: 'slot插槽',
		required: '否',
		defaultValue: "无",
		desc: "在 field 下面的描述语言，或者是一个组件"
	},
	{
		field: 'footer',
		type: 'slot插槽',
		required: '否',
		defaultValue: "无",
		desc: "form 表单自带 footer，如需要自己配置 footer, 可通过 footer 插槽自己写尾部按钮"
	},
  {
		field: 'nofooter',
		type: 'Boolean',
		required: '否',
		defaultValue: "false",
		desc: "去除底部按钮"
	},
  {
		field: 'queryKey / querykey',
		type: 'String',
		required: '否',
		defaultValue: "无",
		desc: "配置关闭弹框的key值，若表单在KsDialog弹框里且footer用KsForm自带的尾部按钮，则必须要传这个queryKey/querykey，其他情况不需要传"
	},
]

const filedData2= [
   {
		field: 'iColSpan',
		type: 'Number',
		required: '否',
		defaultValue: "24",
		desc: "当前表单的栅格布局，优先级高于 gColSpan"
	},
  {
		field: 'itemClass',
		type: 'String',
		required: '否',
		defaultValue: "",
		desc: "控制当前整个FormItem的样式，itemClass和直接在KsField上添加的class的区别如下图所示"
	},
  
  {
		field: 'entityKey',
		type: 'String',
		required: '是',
		defaultValue: "无",
		desc: "<KsField entityKey='name'/>, entityKey取的就是entity每个对象的值",
	},
  {
		field: '当前表单支持的属性',
		type: 'String',
		required: '否',
		defaultValue: "无",
		desc: `比如Input组件支持的属性，都可以在KsField上添加, \n
    eg:<KsField entityKey='name'  showCount maxlength='10' />`,
	},
];
 
 const filedData3= [
	{
		field: 'name',
		type: 'String',
		required: '是',
		defaultValue: "无",
		desc: "表单 的key值（提交给后台的key值），必传"
	},
	{
		field: 'label',
		type: 'String',
		required: '是',
		defaultValue: "无",
		desc: "表单 label"
	},
	{
		field: 'valueType',
		type: 'ks_valueType',
		required: '是',
		defaultValue: "text",
		desc: "目前支持的表单类型: text,textarea,password,spinner,date,select,treeSelect,buttonGroup,radio,checkbox,switch,slider,cascader,rate,transfer,treeSelect,readOnly, inputCompose"
	},
	{
		field: 'placeholder',
		type: 'String',
		required: '否',
		defaultValue: "请输入/请选择",
		desc: "输入类和选择类的placeholder描述"
	},
	{
		field: 'rules',
		type: 'Oject',
		required: '否',
		defaultValue: "无",
		desc: "校验规则,除了kpc form表单内置的15个校验规则（required，digits，email。。。），又新增了常用的规则，见下方"
	},
	{
		field: 'request',
		type: 'Function | Array',
		required: '否',
		defaultValue: '[]',
		desc: "数据源，function的参数是当前所有表单数据"
	},
	{
		field: 'linkage',
		type: 'Array',
		required: '否',
		defaultValue: '[]',
		desc: "联动字段,若a字段里配置了linkage:[b,c]，则b,c字段的值变化会重置a的值"
	},
	{
		field: 'hidden',
		type: 'Function | Boolean',
		required: '否',
		defaultValue: '无',
		desc: "是否隐藏当前元素，支持函数或者boolean值"
	},
	{
		field: 'fieldProps',
		type: 'any',
		required: '否',
		defaultValue: "无",
		desc: "传递给 FormItem 的 props"
	},
];

const filedData4 = [
	{
		field: 'isUrl',
		message:'URL格式不正确',
		reg: `/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?"\\+&%$#=~_-]+))*$/`
	},
	{
		field: 'isPhone',
		message:'手机号格式输入有误',
		reg: `/^1[3-9]\d{9}$/`
	},
	{
		field: 'isPort',
		message:'端口格式错误',
		reg: `value > 0 && value < 65535`
	},
	{
		field: 'isIp',
		message:'ip地址格式错误',
		reg: `/^((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))$/`
	},
	{
		field: 'IdCard',
		message:'身份证号码输入有误',
		reg: `/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/`
	},
	{
		field: 'lowerCase',
		message:'只能输入小写字母',
		reg: `/^[a-z]+$/`
	},
	{
		field: 'upperCase',
		message:'只能输入大写字母',
		reg: `/^[A-Z]+$/`
	},
	{
		field: 'alphabets',
		message:'只能输入字母',
		reg: `/^[A-Za-z]+$/`
	},
	{
		field: 'isPassword',
		message:'必须包含大小写字母和数字，支持的特殊字符为!@#$%^&*()_+=-',
		reg: `/^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])[\d\w!@#$%^&*()_+=-]+$/`
	},
	{
		field: 'limitLength',
		message:'最少8位，最多64位',
		reg: `/^.{8,64}$/`
	},
	{
		field: 'isName',
		message:'名字不合法，只支持2个字以上中文或英文！',
		reg: `/^[a-zA-Z\u4e00-\u9fa5]+$/`
	},
]
const filedHeaders4 = [
  {key:"field",title:"属性"},
  {key:'message',title:'提示信息'},
  {key:"reg",title:"校验规则"},
]
</script>



# 表单

表单组件
目前支持的表单包括：**输入框 text, 数字输入框 spinner，密码框 password，文本域 textarea，时间 date，按钮组 buttonGroup，选择框 select，滑动输入 slider，多选框 checkbox，评分 rate，单选 radio，开关 switch，级联 cascader，穿梭框 transfer，下拉树选择 treeSelect，只读 readOnly，自定义组合input inputCompose**。
- `KsForm`: 外层 form，传入一个@onSubmit 事件，处理提交逻辑。
    > 自定义footer按钮时候，只需要给自定义确认按钮一个htmlType="submit"属性，提交事件@onSubmit还是需要放在ksForm上，这样才能触发form表单内部的校验逻辑 
- `KsField`: formItem 表单

## 示例
<ClientOnly>
  <ViewForm/>
</ClientOnly>

## 表单事件
<ClientOnly>
 <Table :data="filedData0" resizable checkType="none" type="grid">
 <TableColumn v-for="(header, index) in filedHeaders" :key="header.key"  :title="header.title" />
 </Table>
</ClientOnly>


## 表单 KsForm 配置属性
<ClientOnly>
 <Table :data="filedData1" resizable checkType="none" type="grid">
 <TableColumn v-for="(header, index) in filedHeaders" :key="header.key"  :title="header.title" />
 </Table>
</ClientOnly>

## KsForm 组件上的属性

<ClientOnly>
 <Table :data="filedData2" resizable checkType="none" type="grid">
 <TableColumn v-for="(header, index) in filedHeaders" :key="header.key"  :title="header.title" />
 </Table>
 <h5 :style='{margin:"20px 0px"}'>itemClass和class的区别如图所示</h5>
 <div :style='{border:"1px solid #ddd",padding:"20px"}'>
  <img src='./image.png'/>
 </div>
</ClientOnly>

## KsForm entity 对象配置属性

<ClientOnly>
 <Table :data="filedData3" resizable checkType="none" type="grid">
 <TableColumn v-for="(header, index) in filedHeaders" :key="header.key"  :title="header.title" />
 </Table>
</ClientOnly>

## rules的校验规则
同时支持kpc form内置的校验规则，规则如下：
1. kpc from内置校验
```js
required {boolean}：必须填写
digits {boolean}： 请输入数字
email {boolean}: 请输入正确的邮箱地址
url {boolean}: 请输入正确的网址
该规则可以验证IP地址，但是会排除192.168.X.X | 192.254.X.X | 172.16.0.0 - 172.31.255.255 | 10.X.X.X | 172.X.X.X这类保留IP地址

date {boolean}：请输入正确的日期
dateISO {boolean}：请输入正确的日期（YYYY-MM-DD）
number {boolean}：请输入正确的数
maxLength {number}：如果检验的值是数组：最多选择n项；如果检验的值是字符串：最多输入n个字符
minLength {number}：同上（检验最少长度）
rangeLength {Array<number>}：同上，检验长度的范围
max {number}：请输入不大于n的数
min {number}：请输入不小于n的数
range {Array<number>}：请输入min到max之间的数
step {number}：请输入步长为n的数
equal {string}：两次输入不一致
```
2. ksForm内置校验
<ClientOnly>
 <Table :data="filedData4" resizable checkType="none" type="grid">
 <TableColumn v-for="(header, index) in filedHeaders4" :key="header.key"  :title="header.title" />
 </Table>
</ClientOnly>


## 添加全局 addMethod
自定义的校验规则添加方式和kpc form添加方式一样，可以添加到全局，这样在表单校验的时候，就可以直接使用。
```js
<script setup>
import { KsForm,KsField } from '@ksconsole/components'

KsForm.addMethod('check', function (value) {
  return value === '1234'
}, '请输入1234')
</script>
```


## 基本使用

```vue
<KsForm @onSubmit="submit">
	<KsField entityKey="userName" @change="onChange" showCount maxlength="10" />
</KsForm>
<script setup>
import { reactive, provide } from 'vue';
// 1. 引入组件
import { KsForm,KsField } from '@ksconsole/components'
// 2.配置表单的model信息
const formState = reactive({
	userName: undefined,
});
// 3. 配置表单的entity信息
// 这里需要配置一个对象，这个对象是用来描述表单的，比如表单的key，label，rules等
const PageEntity = {
  userName: {
		// form 的 key 属性 解析为 Entity.ITCode
		name: 'userName',
		// label 字段描述
		label: '用户名',
		rules: { required: true },
		messages: { required: '文案展示',  }
		valueType: ks_valueType.text, // 默认的，可以不用写
		linkage: ['password'], // 联动的，配置了就表示当前userName的值与 password 相关联，password改变会重置userName的值
	};
}

// 4. 注入的两项核心配置
provide('formInfo', {
	formState,
	PageEntity
});

const onChange = (v) => {
	console.log('🚀 ~ onChange ~ v:', v);
};
// 提交的逻辑
const submit = (formState) => {
	console.log("🚀 ~ submit ~ formState:", formState)
}
</script>

```

## 完整示例如下：

<div class="options-api" style="font-size:14px;">

```vue
<template>
	<!-- <ViewFetail @onSubmit="submit"> -->
	<div class="app-field-box">
		<h3>1. form表单基本使用</h3>
		<KsForm @onSubmit="submit">
      <KsField entityKey="readOnly" />
      <KsField entityKey="project">
        <template #cont>
          <span v-if="!formState.project?.length">--</span>
          <Tag
            v-else
            v-for="($value, $key) in formState.project"
            type="default"
            :key="$key"
            style="margin-right: 10px;"
          >
            {{ $value }}
          </Tag>
        </template>
      </KsField>
      <!-- type='horizontal' 默认的可以不写 -->
      <KsField entityKey="inputCompose1" @change="onChange" type='horizontal' />
      <KsField entityKey="inputCompose2" @change="onChange" type='vertical'/>
			<KsField entityKey="spinner" @change="onChange" :max="10" :min="0" :step="1.2" >
				<template #unit>Mbps</template>
				<template #tip>文案：我是下面的tips</template>
			</KsField>
       <KsField entityKey="selectTransfer" >
				<template #tip>
          组件
          <Transfer v-model="tvalue"
            :data="data" 
            ref="__test"
        />
        </template>
			</KsField>
			
			<KsField entityKey="name" @change="onChange" showCount maxlength="10" >
				<template #tip>您还可以关联 0 个安全组，已关联 5 个</template>
			</KsField>
			<KsField entityKey="password" @change="onChange" type="password" showPassword />
			<KsField entityKey="textarea" @change="onChange" type="textarea" />
			<KsField entityKey="singletype" @change="onChange" />
			<KsField entityKey="multipletype" multiple />
			<KsField entityKey="switchType" on="11" off="22" />
			<KsField entityKey="switchType2" @change="onChange" />
			<KsField entityKey="radioType" @change="onChange"  />
			<KsField entityKey="checkboxType" @change="onChange" />
			<KsField entityKey="slider" @change="onChange" unit="MB" class="zy-demo" />
			<KsField entityKey="time" @change="onChange" range type="datetime" clearable  />
			<KsField entityKey="buttonGroup" @change="onChange" />
			<KsField entityKey="buttonGroup2" checkType="checkbox" @change="onChange" />
			<KsField entityKey="treeSelect"  />
		</KsForm>
		<div class="app-field-line"></div>
		<h3>2. 自定义footer</h3>
		<KsForm @onSubmit="submit">
			<KsField entityKey="name" @change="onChange" showCount maxlength="10" />
			<KsField entityKey="password" @change="onChange" type="password" showPassword />
			<KsField entityKey="textarea" @change="onChange" type="textarea" />
			<KsField entityKey="singletype" @change="onChange" />
			<KsField entityKey="multipletype" multiple />
			<!-- 用自己写的 -->
			<FormItem label="测试input" :value="formState.zyinput">
				<Input v-model="formState.zyinput" />
			</FormItem>
			<template #footer>
				<Button type="primary" htmlType="submit" >提交</Button>
			</template>
		</KsForm>
		<h3>3. 使用自带按钮，但是自定义 取消和确认按钮文本 </h3>
    	<KsForm @onSubmit="submit" oktext='我是确认' canceltext='我是取消'>
        <KsField entityKey="name3" @change="onChange" showCount maxlength="10" />
      </KsForm>
		<div class="app-field-line"></div>
    <h3>4. 珊格布局 </h3>
    	<KsForm @onSubmit="submit" :gColSpan='12'>
        <KsField entityKey="name3" @change="onChange" showCount maxlength="10" :iColSpan='8' class='w-100'/>
        <KsField entityKey="spinner" @change="onChange" :max="10" :min="0" :step="1.2"  class='w-100' :iColSpan='8'>
          <template #unit>Mbps</template>
          <template #tip>我是下面的tips</template>
        </KsField>
        <KsField entityKey="name"  :iColSpan='8' class='w-100'>
          <template #tip>我是提示信息</template>
        </KsField>
        <KsField entityKey="textarea" @change="onChange" type="textarea" />
        <KsField entityKey="singletype" @change="onChange"/>
        <KsField entityKey="multipletype" multiple />
        <KsField entityKey="switchType" on="11" off="22" />
        <KsField entityKey="switchType2" @change="onChange" />
        <KsField entityKey="radioType" @change="onChange"  />
        <KsField entityKey="checkboxType" @change="onChange" />
        <KsField entityKey="slider" @change="onChange" unit="MB" class="zy-demo" />
        <KsField entityKey="time" @change="onChange" range type="datetime" clearable  />
        <KsField entityKey="buttonGroup" @change="onChange" />
        <KsField entityKey="buttonGroup2" checkType="checkbox" @change="onChange" />
        <KsField entityKey="treeSelect"  />
      </KsForm>
		<div class="app-field-line"></div>
     <h3>5. 自定义label </h3>
    	<KsForm @onSubmit="submit" labelWidth='150'>
        <KsField entityKey="name3" @change="onChange" showCount maxlength="10" >
          <template v-slot:label><i class="ion-person"></i> 自定义名称</template>
        </KsField>
      </KsForm>
		<div class="app-field-line"></div>
	</div>
</template>
<script setup>
import { ref, reactive, provide } from 'vue';
import { Form, FormItem, Input,Button,Message } from '@king-design/vue';
import { PageEntity } from './entity';
import { KsForm,KsField } from '@ksconsole/components'

const tvalue = ref([0,1])
const data = [
    {label: '主机名0', key: 0},
    {label: '主机名1', key: 1, disabled: true},
    {label: '主机名2', key: 2},
    {label: '主机名3', key: 3, disabled: true},
    {label: '主机名4', key: 4},
];
KsForm.addMethod('check', function (value) {
  return value === '1234'
}, '请输入1234')
const formState = reactive({
	name: undefined,
	password: undefined,
	textarea: undefined,
	singletype: '1',
	multipletype: ['1', '2'],
	switchType: true,
	switchType2: false,
	radioType: '1',
	checkboxType: ['1', '2'],
	slider: 2,
	time: null,
	buttonGroup: undefined,
	buttonGroup2: [],
	transfer: [],
	zyinput: 1,
	name3: undefined,
	treeSelect: '0-0',
  readOnly: '我是只读的内容',
  inputCompose1: ['111','222'],
  inputCompose2: ['111','222'],
});

provide('formInfo', {
	formState,
	PageEntity
});

const onChange = (v) => {
	console.log('🚀 ~ onChange ~ v:', v);
};

const submit = (formState) => {
	console.log("🚀 ~ submit ~ formState:", formState)
	Message.info({
		content: JSON.stringify(formState),
		duration: 10000,
		closable: true
	});
}
</script>

<style scoped lang="less">
.p {
	line-height: 18px !important;
}
.app-field-line {
	margin: 24px;
	border-bottom: 1px dashed rgb(159, 223, 159);
}
.app-field-box {
	padding: 24px;
	h3 {
		margin-bottom: 20px;
	}
}
</style>
<style >
.w-100 {
  width: 150px;
}
</style>

```

```js
// entity.js
import { ks_valueType } from "./config";
/**
 * 页面实体 class，用于配置表单的model信息
 * @class Entity
 */
class Entity {
  // 对象名称和对象里面的name建议统一，对象名称对应
  name = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "name",
    // label 字段描述
    label: "名称",
    rules: { required: true },
    valueType: ks_valueType.text, // 默认的，可以不用写
    messages: { required: "111选择" },
  };
  readOnly = {
		name: 'readOnly',
		label: '只读',
		valueType: ks_valueType.readOnly
	};

  project = {
    name: 'project',
    label: '所属项目',
    valueType: ks_valueType.readOnly,
  };
  textarea = {
    name: "textarea",
    // label 字段描述
    label: "文本",
    rules: { required: true },
    valueType: ks_valueType.textarea,
  };
   selectTransfer = {
    name:'selectTransfer',
    label:'穿梭框',
    valueType: ks_valueType.select,
    request: [
      {label:'服务器',value:'1'},{label:'数据库',value:'2'}
    ]
  },
  inputCompose1 = {
		name: 'inputCompose1',
		label: '组合input1',
		valueType: ks_valueType.inputCompose,
    placeholder: ['请输入开始', '请输入结束']
	};
  inputCompose2 = {
		name: 'inputCompose2',
		label: '组合input2',
		valueType: ks_valueType.inputCompose,
    placeholder: ['请输入开始', '请输入结束']
	};

  password = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "password",
    // label 字段描述
    label: "密码",
    // valueType: WTM_ValueType.dateRange,
     hidden: true,
  };
  singletype = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "singletype",
    // label 字段描述
    label: "下拉单选",
    valueType: ks_valueType.select,
    request: async () => this.getSalesList(),
  };
  multipletype = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "multipletype",
    // label 字段描述
    label: "下拉多选",
    valueType: ks_valueType.select,
    // fieldProps: {multiple: true},
    request: async () => {
      return [
        { value: "1", label: "测试1" },
        { value: "2", label: "测试2" },
        { value: "3", label: "测试3" },
      ];
    },
    hidden: function(formState){
      return formState.singletype === '2' 
    }
  };

  name2 = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "name2",
    // label 字段描述
    label: "名称",
    rules: { required: true },
    valueType: ks_valueType.text, // 默认的，可以不用写
    messages: { required: "111选择" },
  };
  textarea2 = {
    name: "textarea2",
    // label 字段描述
    label: "文本",
    rules: { required: true },
    valueType: ks_valueType.textarea, // 默认的，可以不用写
  };

  password2 = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "password2",
    // label 字段描述
    label: "密码",
    // valueType: WTM_ValueType.dateRange,
  };
  singletype2 = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "singletype2",
    // label 字段描述
    label: "下拉单选",
    valueType: ks_valueType.select,
    request: async () => this.getSalesList(),
  };
  multipletype2 = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "multipletype2",
    // label 字段描述
    label: "下拉多选",
    valueType: ks_valueType.select,
    // fieldProps: {multiple: true},
    request: async () => {
      return [
        { value: "1", label: "测试1" },
        { value: "2", label: "测试2" },
        { value: "3", label: "测试3" },
      ];
    },
  };
  name3 = {
    // form 的 key 属性 解析为 Entity.ITCode
    name: "name3",
    // label 字段描述
    label: "名称",
    rules: { required: true },
    valueType: ks_valueType.text, // 默认的，可以不用写
    messages: { required: "111选择" },
  };
  treeSelect = {
		label: '树形选择',
		name: 'treeSelect',
		valueType: ks_valueType.treeSelect,
		request: async () => {
			return [
				{
					label: 'Node1',
					key: '0-0',
					children: [
						{
							label: 'Child Node1',
							key: '0-0-1'
						},
						{
							label: 'Child Node2',
							key: '0-0-2'
						}
					]
				},
				{
					label: 'Node2',
					key: '1-1',
					children: [
						{
							label: 'Child Node3',
							key: '1-1-1'
						},
						{
							label: 'Child Node4',
							key: '1-1-2'
						}
					]
				}
			];
		}
	}

  async getSalesList() {
    const res = await new Promise((resolve) => {
      // setTimeout(() => {
      resolve([
        { label: "1", value: "1" },
        { label: "2", value: "2" },
      ]);
      // }, 100);
    });
    return res;
  }
}
export const PageEntity = new Entity();
// class使用说明
import { PageEntity } from './controllers/entity';
provide('formInfo', {
  ...
	PageEntity
});



/**
 * 页面实体 function,用于配置表单的model信息
 * @function Entity
 * 这里是拿的系统管理项目中的配置，主要是为了说明entity的核心是配置，形式是函数还是class都可以
 */
 export function useEntity(name, treeData, detail) {
  const projectName = {
    name: 'name',
    label: name + '名称',
    rules: {
      required: true,
      valiName: valiName,
    },
  };
  const parentId = {
    name: 'parentId',
    label: '上级' + name,
    valueType: ks_valueType.treeSelect,
    rules: { required: true },
    request: async () => treeData,
  };

  const organizationInfoList = {
    name: 'organizationInfoList',
    label: '所属组织',
    valueType: ks_valueType.select,
    rules: { required: true },
    request: async () => getOwnerList(),
  };

  const managerIds = {
    name: 'managerIds',
    label: name + '管理员',
    valueType: ks_valueType.select,
    rules: { required: true },
    request: [
    	{ label: '管理员1', value: 1 },
    	{ label: '管理员2', value: 2 },
    	{ label: '管理员3', value: 3 }
    ]
  };

  const description = {
    name: 'description',
    label: '描述',
    valueType: ks_valueType.textarea,
  };
  async function valiName(val, formState) {
    if (!isEmpty(detail)) {
      // 编辑时候，去重逻辑要排除自己
      if (detail.name === val) return true;
    }
    const res = { isExisted: 0 };
    if (get(res, 'isExisted', 0) === 1) {
      return '组织名称已存在';
    }
    return true;
  }
  async function getOwnerList() {
    const res = await new Promise((resolve) => {
      resolve([
        { label: '管理员1', value: 1 },
        { label: '管理员2', value: 2 },
        { label: '管理员3', value: 3 },
      ]);
    });
    return res;
  }
  
  return {
    projectName,
    parentId,
    organizationInfoList,
    managerIds,
    description,
  };
}
// 函数使用
import { useEntity } from './controllers/entity';
const PageEntity = useEntity(
  '组织',
  treeData.value,
  detailInfo.value,
);
provide('formInfo', {
  ...,
  PageEntity,
});


```

```js
// config.js
 // Description: 用于配置字段的类型 自己项目全局配置下
export const ks_valueType = {
	/** 密码框 */
	password: 'password',
	/** 文本域 */
	textarea: 'textarea',
	/** 时间 */
	date: 'date',
	/** 按钮组 */
	buttonGroup: 'buttonGroup',
	/** 文本 */
	text: 'text',
	/** 选择框 */
	select: 'select',
	/** 滑动输入 */
	slider: 'slider',
	/** 多选框 */
	checkbox: 'checkbox',
	/** 评分 */
	rate: 'rate',
	/** 单选 */
	radio: 'radio',
	/** 开关 */
	switch: 'switch',
	/**	数字输入框 */
	spinner : "spinner",
	/**	级联选择 */
	cascader: "cascader",
	/** 穿梭框 */
	transfer: 'transfer',
	/** 下拉树选择 */
	treeSelect: "treeSelect",
  /** 自定义组件-组合input */
	inputCompose: "inputCompose",
  /** 只读 */
  readOnly: 'readOnly',
	// todo: 以下类型未实现
	/** 图片上传 */
	image: 'image',
	/** 文件 */
	upload : "upload",
};

```
</div>
