Ant Design

11/9/2022 前端reactantd
(adsbygoogle = window.adsbygoogle || []).push({});

# 新建项目

ts项目

npx create-react-app my-app --template typescript
yarn add antd
yarn add axios
1
2
3

# 表单

提交表单可以直接用回调函数里面的values获取值 重置表单数据 form.resetFields()

# 表格Table

  1. 默认key往往不是,需要自定义rowKey,否则控制台报错
 <Table columns={columns} dataSource={data.list} rowKey="id" pagination={false} />
1

# 单元格数据再处理(render)

如下图权限展示,是一个对象数组,需要再处理,展示为tag

image

  1. render里面参数可以用_,表示不用该参数
  2. value !== undefined 先判断下是否有值
  3. ts可以直接用?表示有值的情况再执行
render: (value) => {
    return (<>{value?.map((sysRole: any) => <Tag color="blue" key={sysRole.name}>{sysRole.name}</Tag>)}
    </>)
}
1
2
3
4
import { Space, Table, Button, Form, Input, Pagination, message, Modal, Popconfirm, Tag, Tree } from 'antd';
import type { TreeProps } from 'antd/es/tree';
import React, { useEffect, useState } from 'react';
import { pxRequest } from '../service/userService'
import './Role.css'

const Role: React.FC = () => {
  const [data, setData] = useState<API.PageInfo>({})
  const getList = (values: any) => {
    pxRequest("sys/role/list", values).then(res => {
      if (res.data.success) {
        setData(res.data.object)
      } else {
        message.info(res.data.message)
      }
    }).catch(err => {
      console.log(err)
    })
  }
  useEffect(() => {
    getList({})
  }, [])
  // 获取权限列表
  const [authList, setAuthList] = useState([])
  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
  useEffect(() => {
    getRoleList()
  }, [])
  const getRoleList = () => {
    pxRequest("sys/auth/list", {}).then(res => {
      if (res.data.success) {
        setAuthList(res.data.object)
      } else {
        message.info(res.data.message)
      }
    }).catch(err => {
      console.log(err)
    })
  }

  //搜索用的form
  const [form] = Form.useForm();
  const onChange = (pageNum: number, pageSize: number) => {
    let queryForm = { ...form.getFieldsValue() }
    queryForm.pageNum = pageNum
    queryForm.pageSize = pageSize
    getList(queryForm)
  }

  const onFinish = (values: any) => {
    getList(values)
  };

  // 新增及编辑
  const [addForm] = Form.useForm();
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [isAdd, setIsAdd] = useState(false);

  const handleOk = () => {
    let api = isAdd ? "sys/role/add" : "sys/role/edit"
    addForm.validateFields().then((res) => {
      pxRequest(api, addForm.getFieldsValue()).then(res => {
        if (res.data.success) {
          setIsModalOpen(false);
          getList({})
          message.info(res.data.message)
        } else {
          message.error(res.data.message)
        }
      }).catch(err => {
        console.log(err)
      })
    }).catch((err) => {
      console.log(err)
    })
  };
  const handleCancel = () => {
    setIsModalOpen(false);
  };
  const showAdd = () => {
    setIsAdd(true)
    addForm.resetFields()
    setCheckedKeys([])
    setIsModalOpen(true);
  }
  //编辑
  const showEdit = (record: any) => {
    setIsAdd(false)
    addForm.resetFields()
    addForm.setFieldsValue(record)
    setCheckedKeys([])
    if (record.sysAuthList !== undefined) {
      let keys = []
      for (let sysAuth of record.sysAuthList) {
        keys.push(sysAuth.id)
      }
      setCheckedKeys(keys)
    }
    setIsModalOpen(true);
  }

  //权限信息
  const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
  };

  // @ts-ignore 
  const onCheck: TreeProps['onCheck'] = (checkedKeys: React.Key[], info) => {
    setCheckedKeys(checkedKeys);
    addForm.setFieldValue("sysAuthList", info.checkedNodes);
  };

  //删除角色
  const showDel = (id: any) => {
    console.log(id)
    pxRequest("sys/role/delete/" + id, {}).then(res => {
      if (res.data.success) {
        message.info(res.data.message)
        getList({})
      } else {
        message.error(res.data.message)
      }
    }).catch(err => {
      console.log(err)
    })
  }

  const columns = [
    {
      title: '角色名称',
      dataIndex: 'name',
      key: 'name',

    },
    {
      title: '角色备注',
      dataIndex: 'mark',
      key: 'mark',
    },
    {
      title: "权限",
      dataIndex: "sysAuthList",
      key: "sysAuthList",
      render: (value: any) => {
        if (value !== undefined) {
          return (<>{value.map((sysRole: any) => <Tag color="blue" key={sysRole.name}>{sysRole.name}</Tag>)}
          </>)
        }
      }

    },
    {
      title: '新增人员',
      dataIndex: 'createId',
      key: 'createId',
    },
    {
      title: '新增时间',
      dataIndex: 'createTime',
      key: 'createTime',
    },
    {
      title: '修改人员',
      dataIndex: 'modifyId',
      key: 'modifyId',
    },
    {
      title: '修改时间',
      dataIndex: 'modifyTime',
      key: 'modifyTime',
    },
    {
      title: '操作',
      key: 'action',
      render: (_: any, record: any) => (
        <Space size="middle">
          <Button type="link" onClick={() => { showEdit(record) }}>编辑</Button>
          <Popconfirm title={`确定删除 ${record.name} 么?`} onConfirm={() => showDel(record.id)} placement="topRight">
            <Button type='link'>删除</Button>
          </Popconfirm>
        </Space>
      ),
    },
  ];

  return (<div className='userTable'>
    <Form className='search' form={form} name="horizontal_login" layout="inline" onFinish={onFinish} >
      <Form.Item
        name="sysAuthList"
        label="权限"
        rules={[{ required: false, message: '权限' }]}
        hidden={true}
      >
        <Input placeholder="权限" />
      </Form.Item>
      <Form.Item
        name="name"
        label="角色名称"
        rules={[{ required: false, message: '角色名称' }]}
      >
        <Input placeholder="角色名称" />
      </Form.Item>

      <Form.Item shouldUpdate>
        {() => (
          <Button type="primary" htmlType="submit"  > 查询 </Button>
        )}
      </Form.Item>
      <Form.Item shouldUpdate>
        {() => (
          <Button type="primary" onClick={showAdd}  > 新增 </Button>
        )}
      </Form.Item>
    </Form>
    <Modal
      title={isAdd ? "新增" : "编辑"}
      open={isModalOpen}
      onOk={handleOk}
      onCancel={handleCancel}
    >
      <Form className='addUser' form={addForm} autoComplete="off" initialValues={{
        status: "0"
      }}
        labelCol={
          { span: 5 }
        }
        wrapperCol={
          { span: 19 }
        }
      > <Form.Item
        name="id"
        rules={[{ required: !isAdd, message: 'id' }]}
        hidden
      >
          <Input />
        </Form.Item>
        <Form.Item
          name="name"
          label="角色名称"
          rules={[{ required: true, message: '角色名称' }]}
        >
          <Input placeholder="角色名称" allowClear={true} />
        </Form.Item>
        <Form.Item
          name="mark"
          label="角色备注"
          rules={[{ required: false, message: '角色备注' }]}
        >
          <Input
            placeholder="角色备注" allowClear={true} />
        </Form.Item>
        <Form.Item
          name="sysAuthList"
          label="拥有权限"
        >
          <Tree
            checkable
            onSelect={onSelect}
            onCheck={onCheck}
            treeData={authList}
            checkedKeys={checkedKeys}
            fieldNames={{ title: "name", key: "id", children: "pSysAuth" }}
            defaultExpandAll={true}
          />
        </Form.Item>
      </Form>
    </Modal>
    <Table columns={columns} dataSource={data.list} rowKey="id" pagination={false} />
    <Pagination onChange={onChange} showTotal={(total) => `${total}`} current={data.pageNum} total={data.total} showSizeChanger={true} />
  </div>)
};

export default Role; 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

# 显示为html渲染后的结果

 {
      title: '消息内容',
      dataIndex: 'description',
      key: 'description',
      render: (record: string) => (
        <div dangerouslySetInnerHTML={{ "__html": BraftEditor.createEditorState(record).toHTML() }}></div>
      ),
    },
1
2
3
4
5
6
7
8

# 树形控件Tree

效果如下: onCheck是勾选前面的选择框 onSelect是点击后面的汉字,如系统管理

image 注意:

  1. 嵌套在表单里面时,addForm.getFieldsValue(),提交请求时不会抓取tree的值
  2. 提交数据方法,在onCheck方法里面对表单赋值
  3. 新建及编辑时先清空上一次选中的keys
  4. keys可以时字符串数组也可以时number数组,与关联的数据对应即可
<Tree
    checkable
    onSelect={onSelect}
    onCheck={onCheck}
    treeData={authList}
    checkedKeys={checkedKeys}
    fieldNames={{ title: "name", key: "id", children: "pSysAuth" }}
    defaultExpandAll={true}
/>
1
2
3
4
5
6
7
8
9
// 获取权限列表
const [authList, setAuthList] = useState([])
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
const onCheck: TreeProps['onCheck'] = (checkedKeys: React.Key[], info) => {
    setCheckedKeys(checkedKeys);
    addForm.setFieldValue("sysAuthList", info.checkedNodes);
};
const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
  };
1
2
3
4
5
6
7
8
9
const handleOk = () => {
    let api = isAdd ? "sys/role/add" : "sys/role/edit"
    addForm.validateFields().then((res) => {
      pxRequest(api, addForm.getFieldsValue()).then(res => {
        if (res.data.success) {
          setIsModalOpen(false);
          getList({})
          message.info(res.data.message)
        } else {
          message.error(res.data.message)
        }
      }).catch(err => {
        console.log(err)
      })
    }).catch((err) => {
      console.log(err)
    })
  };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# TreeSelect

与tree类似,显示为下拉菜单的形式 image

<TreeSelect
  onSelect={onSelect}
  treeData={deptList}
  multiple={false}
  checkedKeys={checkedKeys}
  fieldNames={{ label: "deptName", value: "deptId", children: "children" }}
  defaultExpandAll={true}
  placeholder="请选择"
/>
1
2
3
4
5
6
7
8
9

# Select

# axios

# 配置全局header

ts里面注释也是起作用的

import axios from 'axios'

axios.interceptors.request.use(
    (config) => {
        // @ts-ignore 
        config.headers.Authorization = localStorage.getItem("token")
        return config
    },
    (error) => {
        return Promise.reject(error)
    }
)
1
2
3
4
5
6
7
8
9
10
11
12

# DatePicker

编辑操作回显时直接设置会报错,需要用moment,第二个参数是时间格式,最后字母Z解决时间差8个小时问题

record.datetime = moment(record.datetime, 'YYYY-MM-DD HH:mm:ss Z');
1

# api.d.ts

接口文档

  1. 规定了数据格式,注意接口只有在ts中存在
  2. 其它文件可以直接使用,eg: API.IUser
declare namespace API {
    interface IUser {
        id: number,
        userId: string,
        userName: string,
        password: string,
        status: string,
        createId: string,
        createTims: Date,
        modifyId: string,
        modifyTime: Date
    }
    interface TableParams {
        pagination?: TablePaginationConfig;
        sortField?: string;
        sortOrder?: string;
        filters?: Record<string, FilterValue>;
    }
    interface PageInfo {
        total?: number,
        pageSize?: number,
        pageNum?: number,
        list?: any[]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 赋值

defualt开头的只能赋值一次,后续不会跟着改变,例如: defaultChecked 初始是否选中,如果要改变应该使用checked

# 参考

  1. material-ui: http://www.material-ui.com/#/
  2. github: https://github.com/callemall/material-ui
  3. https://ant.design/components/overview-cn/