ProComponent就是算是对antd的又一次集成和封装,缩小了前端对于细节和联动的解决,总之就是用起来特地爽。
那这里就不对ProComponent做过多介绍了,咱们直奔主题,如何应用,或者说如何更优雅、更不便的应用组件和编写代码始终是任何一位程序员的外围谋求,我也是PiuPiuPiu~!
columns的配置
treeSelect
request能够用来调接口获取值
labelInValue:是设置的取到的是这个表单项值的对象,不仅仅包含value,上面的例子取到的就是fieldNames对象
{ title: '区域', dataIndex: 'areaIds', hideInTable: true, valueType: 'treeSelect', request: async () => { let res = await areaSituation(); if (res?.status == '00') { return res.data; } }, fieldProps: { showArrow: false, filterTreeNode: true, showSearch: true, dropdownMatchSelectWidth: false, autoClearSearchValue: true, treeNodeFilterProp: 'title', labelInValue: true, fieldNames: { label: 'title', lvl: 'lvl', value: 'nodeId', children: 'childrenList', }, onSelect: (_, dataObj) => { setAreaIds([]); let arr = []; let getData = (data) => { arr = [...arr, data?.nodeId]; if (data?.childrenList.length > 0) { data?.childrenList?.forEach((item) => { getData(item); }); } }; getData(dataObj); setAreaIds(arr); }, }, },
dateTimeRange
ProFormDateTimePicker这个是可取值到年月日时分秒
ProFormDatePicker 是反对到年月日
可用moment设置初始值,
这个默认获得值是一个数组 如果搜寻后端须要的这个工夫字段不是数组而是其余的两个字段;可用上面的写法
{ title: '操作工夫', dataIndex: 'actTime', hideInTable: true, valueType: 'dateTimeRange', // initialValue: [moment().subtract(30, 'days'), moment()], fieldProps: { placeholder: ['入库开始工夫', '入库完结工夫'], }, search: { transform: (value) => { return { startTime: value[0], endTime: value[1], }; }, }, },
radio
status可设置渲染到table的状态
sorter表格的某一项排序
{ title: '提成形式', dataIndex: 'commissionMode', sorter: true, formItemProps:{ initialValue:1, }, valueType: 'radio', valueEnum: { 0: '固定', 1: '比例' }, },{ title: '状态', dataIndex: 'taskState', key: 'taskState', valueEnum: { false: { text: '失败', status: 'error' }, true: { text: '胜利', status: 'success' }, }, hideInSearch: true, },
renderFormItem
可用SelectAccount间接渲染组件在单列表框外面 比方在EditableProTable外面,
当然这里是用在搜寻框的(还是提倡用valueType的形式,然而如果在多个中央应用,封装成组件这样应用也是上选)
{ title: '冷藏费记账账户', dataIndex: 'coldStorageFeeAccountId', formItemProps: { rules: [{ required: true }] }, renderFormItem: (_, { type, ...rest }) => ( <SelectAccount labelInValue params={{ projectId: rest.recordKey }} /> ), },
digit
渲染成只能输出数字的搜寻框
{ title: '件数', dataIndex: 'quantity', valueType: 'digit', fieldProps: { precision: 0, min: 1 }, formItemProps: { rules: [{ required: true }] }, },
或者可自定义在search和table的title文字不一样
fieldProps:可设置搜素框的状态
{ title: (_, type) => (type === 'table' ? '操作账号' : ''), dataIndex: 'operatorMobile', key: 'operatorMobile', //fieldProps: { readOnly: true, placeholder: '请先抉择杂费' }, fieldProps: { placeholder: '操作人账号', }, },
ProForm表单项
ProFormDependency
可用来监听表单项的某一项扭转之后所做的操作,
name为什么是数组呢?
- 是因为在表单提交的时候呢contractType是作为inboundAppointment对象的一个属性值进行提交的,
- 这样写的益处就是前端在提交的函数中不必再从新组装一下这个提交参数了
<ProFormSelect width="sm" name={['inboundAppointment', 'contractType']} label="合同类型" rules={[{ required: true, message: '请抉择合同类型' }]} initialValue={'2'} options={[ // { value: '0', label: '零仓' }, { value: '1', label: '包仓' }, { value: '2', label: '无合同' }, ]} placeholder="包仓/零仓" /> <ProFormDependency name={[['inboundAppointment', 'contractType']]}> {({ inboundAppointment }) => { if ( inboundAppointment?.contractType == '1' || inboundAppointment?.contractType == '0' ) { return ( <ProFormSelect width="sm" name={['inboundAppointment', 'contractNo']} rules={[{ required: true, message: '请抉择合同' }]} label="合同" options={[ { value: '>', label: '大于' }, { value: '<', label: '小于' }, ]} placeholder="请抉择合同" /> ); } }} </ProFormDependency>
ProFormFieldSet
下面咱们说到name设置成数组的模式,能够帮咱们省略组装参数的操作。
那这个更厉害了,能够帮咱们提前组装或者拆分提交表单的参数。
那咱们看一下官网这里是怎么说的:“ProFormFieldSet 能够将外部的多个 children 的值组合并且存储在 ProForm 中,并且能够通过 transform 在提交时转化”,
言而简之,就是我刚说的意思,对吧~
上面的例子也就是将取到的SelectSubject 对象值进行拆分,保留在ProForm中。
<ProFormFieldSet width="md" name={['subject']} transform={(v) => ({ subjectName: v[0]?.label, subjectId: v[0]?.value })} label="费用类型" rules={[{ required: true }]} > <SelectSubject className="pro-field-md" labelInValue /> </ProFormFieldSet>
ProFormText ProForm.Group ProFormDateTimePicker
ProFormText一个简略的表单项
ProFormDateTimePicker:工夫选择器年月日可准确到时分秒
ProForm.Group: 可将表单项在空间范畴内容许的状况下,做一行展现
const [time, setTime] = useState([moment().startOf('year'), moment().endOf('year')])<ProForm.Group title="运输车辆"> <ProFormText width="sm" name={['outboundAppointment', 'plateNum']} label="车牌号" placeholder="请输出车牌号" /> <ProFormDateTimePicker width="sm" name={['outboundAppointment', 'expectArriveTime']} label="预计到场工夫" /> </ProForm.Group>
ProFormDigit
一个只能输出数字的表单项
<ProFormDigit label="预收天数" name="unitTotal" min={1} max={10} placeholder="请输出预收天数" fieldProps={{ precision: 0 }} />
ProFormGroup
列表项归类
<ProFormGroup label="甲方信息"> <ProFormText width="sm" name={'namejia'} label="甲方名称" placeholder="请输出甲方名称" /> <ProFormText width="sm" name={'namejia'} label="手机号" placeholder="请输出手机号" /> <ProFormText width="sm" name={'namejia'} label="身份证号" placeholder="请输出身份证号" /> </ProFormGroup>
DrawerForm
const [form] = ProForm.useForm();<DrawerForm submitter={{ render: () => { return [ <Button key="export" type="primary" onClick={async () => { await exportColdFeeList(exportData) }}> 导出 </Button>, ]; }, }} width={'70%'} layout="horizontal" form={form} title="客户账单明细" visible={visible} onVisibleChange={setVisible} drawerProps={{ destroyOnClose: true, }} />
ProDescriptions
官方言:高级形容列表组件,提供一个更加不便疾速的计划来构建形容列表。
我是用在列表项的详情外面的,通table的用法相似。
<ProDescriptions columns={[ { title: '客户', dataIndex: '' }, { title: '合同类型', dataIndex: '' }, { title: '移位日期', dataIndex: '' }, { title: '操作人', dataIndex: 'operator' }, { title: '操作工夫', dataIndex: '' }, { title: '确认人', dataIndex: '' }, { title: '确认工夫', dataIndex: '', span: 3 }, { span: 3, render: () => ( <ProTable headerTitle="移位商品" style={{ width: '100%' }} rowKey="id" dataSource={[{ id: 0 }]} options={false} search={false} columns={[ { title: '批次号', dataIndex: '' }, { title: '商品', dataIndex: '', sorter: true }, { title: '移出件数', dataIndex: '' }, { title: '移出分量', dataIndex: '', sorter: true }, { title: '移出板数', dataIndex: '', sorter: true }, { title: '移出库位', dataIndex: '' }, { title: '移入库位', dataIndex: '', sorter: true }, { title: '移入板数', dataIndex: '', sorter: true }, ]} /> ), }, { span: 3, render: () => ( <ProTable headerTitle="杂费我的项目" style={{ width: '100%' }} rowKey="id" dataSource={[{ id: 0 }]} options={false} search={false} columns={[ { title: '杂费名称', dataIndex: '' }, { title: '免费根据', dataIndex: '', sorter: true }, { title: '单价', dataIndex: '' }, { title: '件数', dataIndex: '', sorter: true }, { title: '小计', dataIndex: '', sorter: true }, ]} /> ), }, { span: 3, render: () => ( <ProTable headerTitle="作业人员" style={{ width: '100%' }} rowKey="id" dataSource={[{ id: 0 }]} options={false} search={false} columns={[ { title: '姓名', dataIndex: '' }, { title: '所属团队', dataIndex: '' }, { title: '作业类型', dataIndex: '' }, { title: '杂费名称', dataIndex: '' }, { title: '作业数量', dataIndex: '' }, { title: '作业费用', dataIndex: '' }, ]} /> ), }, { title: '相干附件', dataIndex: 'filePath', span: 3, render: (text) => { // let dataArr = text?.includes(',') ? text?.split(',') : [text]; // return ( // <> // {dataArr?.map((item, index) => { // return ( // <a key={index} href={item.url}> // {item.name} // </a> // ); // })} // </> // ); }, }, { title: '备注', dataIndex: 'remark', span: 3 }, ]} />
ProTable EditableProTable
两种表格, 一种用的最多的一般表格,一种是可编辑的表格
应用类似度很高。
ProTable
这个ProTable的配置有意思的中央有三:
- params自带pageSize,pageNumber
- rowSelection可做批量配置操作
- 只有单个条件搜寻的时候可search设置为false,options的search独自设置,那如果你须要多个条件搜寻的时候,可独自对搜寻框做一些定制化配置
当然作为一个高级定制化组件,只有这么些集成必定是不够的,
高级配置
tableExtraRender
这是配置table列表上部,搜寻区域的下部的两头区域,当然如果你有把这个挪动到最顶部的需要,可利用css款式去笼罩,倾囊写上
<ProTable tableExtraRender={() => ( <Row gutter={16}> <Col span={6}> <Card> <Statistic title="入库单总数" value={topData?.all?.totalCount} /> </Card> </Col> <Col span={6}> <Card> <Statistic title="入库吨重" value={topData?.all?.weight} /> </Card> </Col> <Col span={6}> <Card> <Statistic title="今日入库复数" value={topData?.today?.totalCount} /> </Card> </Col> <Col span={6}> <Card> <Statistic title="今日入库吨重" value={topData?.today?.weight} /> </Card> </Col> </Row> )} //search={{ //labelWidth: 0, // collapsed: false, // collapseRender: false, // }} rowKey="id" scroll={{ x: 960 }} columns={[ { title: '商品名称', dataIndex: 'goodsName' }, { title: '所属分类', dataIndex: 'category' }, ]} params={{ status: 0 }} request={async (params = {}) => { const json = await getGlobalCfgGoodsPageList(params); return { data: json.records, page: params.current, success: true, total: json.total, }; }} rowSelection={{ selectedRowKeys, onChange: (keys) => setSelectedRowKeys(keys), }} search={false} toolBarRender={false} options={{ search: { name: 'goodsName', placeholder: '请输出商品名称', }, }} />//css款式.inListContent { .ant-pro-table { display: flex; flex-direction: column; } .ant-pro-table-search { order: 2; } .ant-pro-table-extra { order: 1; } .ant-pro-card { order: 3; }}
EditableProTable
这个组件的应用场景个别是在批改或增加的弹框中应用居多,不要问我怎么晓得,因为我罕用~
1.trigger="onValuesChange":保障了我以后的诸如DrawerForm相似的form组件可实时拿到这个EditableProTable的值,比方上面在onfinsh中拿到的就是inboundGoodsList的值
2.recordCreatorProps:是手动填加列表的一些配置
3.editable:是编辑的一些配置
<ProForm.Item label="" name="inboundGoodsList" initialValue={[]} trigger="onValuesChange"> <EditableProTable headerTitle="入库商品" rowKey="id" columns={[ { title: '商品', dataIndex: 'goodsId', formItemProps: { rules: [{ required: true }] }, valueType: 'select', request: async () => { let res = await getBasicGoodsPageList({ current: 1, pageSize: 999, projectId: initialState?.project?.projectId, }); if (res.status == '00') { return res?.records?.map((item) => { return { label: item.goodsName, value: item.id, }; }); } }, fieldProps: () => { return { labelInValue: true, }; }, }, { title: '件重(件/kg)', dataIndex: 'packageUnit', formItemProps: { rules: [{ required: true }] }, valueType: 'digit', fieldProps: { precision: 0, min: 1 }, }, { title: '分量(kg)', dataIndex: 'weight', editable: false, valueType: 'digit', renderText: (_, record, index) => { if (record.quantity && record.packageUnit) { return Math.round(record.quantity * record.packageUnit); } }, }, { title: '生产日期', dataIndex: 'productionDate', valueType: 'date', width: 200 }, { title: '操作', width: 50, valueType: 'option' }, ]} recordCreatorProps={{ newRecordType: 'dataSource', record: () => ({ id: Date.now(), }), }} editable={{ type: 'multiple', form: tableForm, editableKeys, onChange: setEditableRowKeys, actionRender: (row, _, dom) => { return [dom.delete]; }, }} /> </ProForm.Item>
EditableProTable作为这个组件库我感觉最牛逼的组件,尽管应用起来很爽,然而还是有点点坑的存在的:
联动成果来说:当我联动的是一个设置了不能编辑的一项,那这个联动成果会生效,什么意思呢,好的,那上代码:
{ title: '杂费', dataIndex: 'poundage', valueType: "select", request: async () => { let res = await getPoundageList({ projectId: initialState?.project?.projectId }) if (res.status == "00") { return res?.data?.map(item => { return { label: item.name, value: item.id } }) } }, fieldProps: (_, { rowIndex }) => { return { onChange: async (value) => { debugger let res = await getPoundageDetail(value) if (res.status == "00") { let { mode, chargeDescribe } = res?.obj // tableRef?.current?.setRowData(rowIndex,{ // modeDescribe: mode.toString(), // chargeDescribe: chargeDescribe || "" // }) const data = form.getFieldValue('inboundPoundageItemList') data[rowIndex].modeDescribe = mode.toString() data[rowIndex].chargeDescribe = chargeDescribe form.setFieldsValue({ inboundPoundageItemList: data, }) } } } } },
一开始我尝试应用setRowData对以后这一行的其余项做联动数据批改,然而生效的,
这里艰深讲就是:他的编辑和不能编辑是对应的两个表单,当我编辑可编辑的这个表单,是设置不了数据到不可编辑的那个表单的,
对,那怎么办?
从数据源处下手呗:form.getFieldValue失去数据批改完之后
form.setFieldsValue从新赋值给这个EditableProTable对应的表单项
ModalForm
这样应用trigger的益处:是组件的状态visible不须要从内部传入了,
只有引入这个组件,这个组件外部保护这个状态。
submitter:能够自定义这个表单的确认按钮和勾销按钮的文字
<ModalForm width="400px" title="导入" modalProps={{ maskClosable: false, }} trigger={<Button key="add">导入</Button>} submitter={{ searchConfig: { submitText: '导入', resetText: '勾销', }, }} onFinish={async (values) => onSubmit()} >
这篇文章写的慢,有用心在写,如果帮忙到你,或者让你有所领悟,还心愿能够不吝 点赞关注~