初始化 antd-pro
This commit is contained in:
323
admin-web/src/pages/Forms/AdvancedForm.js
Normal file
323
admin-web/src/pages/Forms/AdvancedForm.js
Normal file
@@ -0,0 +1,323 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Button,
|
||||
Form,
|
||||
Icon,
|
||||
Col,
|
||||
Row,
|
||||
DatePicker,
|
||||
TimePicker,
|
||||
Input,
|
||||
Select,
|
||||
Popover,
|
||||
} from 'antd';
|
||||
import { connect } from 'dva';
|
||||
import FooterToolbar from '@/components/FooterToolbar';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
import TableForm from './TableForm';
|
||||
import styles from './style.less';
|
||||
|
||||
const { Option } = Select;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const fieldLabels = {
|
||||
name: '仓库名',
|
||||
url: '仓库域名',
|
||||
owner: '仓库管理员',
|
||||
approver: '审批人',
|
||||
dateRange: '生效日期',
|
||||
type: '仓库类型',
|
||||
name2: '任务名',
|
||||
url2: '任务描述',
|
||||
owner2: '执行人',
|
||||
approver2: '责任人',
|
||||
dateRange2: '生效日期',
|
||||
type2: '任务类型',
|
||||
};
|
||||
|
||||
const tableData = [
|
||||
{
|
||||
key: '1',
|
||||
workId: '00001',
|
||||
name: 'John Brown',
|
||||
department: 'New York No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
workId: '00002',
|
||||
name: 'Jim Green',
|
||||
department: 'London No. 1 Lake Park',
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
workId: '00003',
|
||||
name: 'Joe Black',
|
||||
department: 'Sidney No. 1 Lake Park',
|
||||
},
|
||||
];
|
||||
|
||||
@connect(({ loading }) => ({
|
||||
submitting: loading.effects['form/submitAdvancedForm'],
|
||||
}))
|
||||
@Form.create()
|
||||
class AdvancedForm extends PureComponent {
|
||||
state = {
|
||||
width: '100%',
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.resizeFooterToolbar, { passive: true });
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.resizeFooterToolbar);
|
||||
}
|
||||
|
||||
getErrorInfo = () => {
|
||||
const {
|
||||
form: { getFieldsError },
|
||||
} = this.props;
|
||||
const errors = getFieldsError();
|
||||
const errorCount = Object.keys(errors).filter(key => errors[key]).length;
|
||||
if (!errors || errorCount === 0) {
|
||||
return null;
|
||||
}
|
||||
const scrollToField = fieldKey => {
|
||||
const labelNode = document.querySelector(`label[for="${fieldKey}"]`);
|
||||
if (labelNode) {
|
||||
labelNode.scrollIntoView(true);
|
||||
}
|
||||
};
|
||||
const errorList = Object.keys(errors).map(key => {
|
||||
if (!errors[key]) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<li key={key} className={styles.errorListItem} onClick={() => scrollToField(key)}>
|
||||
<Icon type="cross-circle-o" className={styles.errorIcon} />
|
||||
<div className={styles.errorMessage}>{errors[key][0]}</div>
|
||||
<div className={styles.errorField}>{fieldLabels[key]}</div>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<span className={styles.errorIcon}>
|
||||
<Popover
|
||||
title="表单校验信息"
|
||||
content={errorList}
|
||||
overlayClassName={styles.errorPopover}
|
||||
trigger="click"
|
||||
getPopupContainer={trigger => trigger.parentNode}
|
||||
>
|
||||
<Icon type="exclamation-circle" />
|
||||
</Popover>
|
||||
{errorCount}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
resizeFooterToolbar = () => {
|
||||
requestAnimationFrame(() => {
|
||||
const sider = document.querySelectorAll('.ant-layout-sider')[0];
|
||||
if (sider) {
|
||||
const width = `calc(100% - ${sider.style.width})`;
|
||||
const { width: stateWidth } = this.state;
|
||||
if (stateWidth !== width) {
|
||||
this.setState({ width });
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
validate = () => {
|
||||
const {
|
||||
form: { validateFieldsAndScroll },
|
||||
dispatch,
|
||||
} = this.props;
|
||||
validateFieldsAndScroll((error, values) => {
|
||||
if (!error) {
|
||||
// submit the values
|
||||
dispatch({
|
||||
type: 'form/submitAdvancedForm',
|
||||
payload: values,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
form: { getFieldDecorator },
|
||||
submitting,
|
||||
} = this.props;
|
||||
const { width } = this.state;
|
||||
|
||||
return (
|
||||
<PageHeaderWrapper
|
||||
title="高级表单"
|
||||
content="高级表单常见于一次性输入和提交大批量数据的场景。"
|
||||
wrapperClassName={styles.advancedForm}
|
||||
>
|
||||
<Card title="仓库管理" className={styles.card} bordered={false}>
|
||||
<Form layout="vertical" hideRequiredMark>
|
||||
<Row gutter={16}>
|
||||
<Col lg={6} md={12} sm={24}>
|
||||
<Form.Item label={fieldLabels.name}>
|
||||
{getFieldDecorator('name', {
|
||||
rules: [{ required: true, message: '请输入仓库名称' }],
|
||||
})(<Input placeholder="请输入仓库名称" />)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.url}>
|
||||
{getFieldDecorator('url', {
|
||||
rules: [{ required: true, message: '请选择' }],
|
||||
})(
|
||||
<Input
|
||||
style={{ width: '100%' }}
|
||||
addonBefore="http://"
|
||||
addonAfter=".com"
|
||||
placeholder="请输入"
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.owner}>
|
||||
{getFieldDecorator('owner', {
|
||||
rules: [{ required: true, message: '请选择管理员' }],
|
||||
})(
|
||||
<Select placeholder="请选择管理员">
|
||||
<Option value="xiao">付晓晓</Option>
|
||||
<Option value="mao">周毛毛</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col lg={6} md={12} sm={24}>
|
||||
<Form.Item label={fieldLabels.approver}>
|
||||
{getFieldDecorator('approver', {
|
||||
rules: [{ required: true, message: '请选择审批员' }],
|
||||
})(
|
||||
<Select placeholder="请选择审批员">
|
||||
<Option value="xiao">付晓晓</Option>
|
||||
<Option value="mao">周毛毛</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.dateRange}>
|
||||
{getFieldDecorator('dateRange', {
|
||||
rules: [{ required: true, message: '请选择生效日期' }],
|
||||
})(
|
||||
<RangePicker placeholder={['开始日期', '结束日期']} style={{ width: '100%' }} />
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.type}>
|
||||
{getFieldDecorator('type', {
|
||||
rules: [{ required: true, message: '请选择仓库类型' }],
|
||||
})(
|
||||
<Select placeholder="请选择仓库类型">
|
||||
<Option value="private">私密</Option>
|
||||
<Option value="public">公开</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Card>
|
||||
<Card title="任务管理" className={styles.card} bordered={false}>
|
||||
<Form layout="vertical" hideRequiredMark>
|
||||
<Row gutter={16}>
|
||||
<Col lg={6} md={12} sm={24}>
|
||||
<Form.Item label={fieldLabels.name2}>
|
||||
{getFieldDecorator('name2', {
|
||||
rules: [{ required: true, message: '请输入' }],
|
||||
})(<Input placeholder="请输入" />)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.url2}>
|
||||
{getFieldDecorator('url2', {
|
||||
rules: [{ required: true, message: '请选择' }],
|
||||
})(<Input placeholder="请输入" />)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.owner2}>
|
||||
{getFieldDecorator('owner2', {
|
||||
rules: [{ required: true, message: '请选择管理员' }],
|
||||
})(
|
||||
<Select placeholder="请选择管理员">
|
||||
<Option value="xiao">付晓晓</Option>
|
||||
<Option value="mao">周毛毛</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col lg={6} md={12} sm={24}>
|
||||
<Form.Item label={fieldLabels.approver2}>
|
||||
{getFieldDecorator('approver2', {
|
||||
rules: [{ required: true, message: '请选择审批员' }],
|
||||
})(
|
||||
<Select placeholder="请选择审批员">
|
||||
<Option value="xiao">付晓晓</Option>
|
||||
<Option value="mao">周毛毛</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 6, offset: 2 }} lg={{ span: 8 }} md={{ span: 12 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.dateRange2}>
|
||||
{getFieldDecorator('dateRange2', {
|
||||
rules: [{ required: true, message: '请输入' }],
|
||||
})(
|
||||
<TimePicker
|
||||
placeholder="提醒时间"
|
||||
style={{ width: '100%' }}
|
||||
getPopupContainer={trigger => trigger.parentNode}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col xl={{ span: 8, offset: 2 }} lg={{ span: 10 }} md={{ span: 24 }} sm={24}>
|
||||
<Form.Item label={fieldLabels.type2}>
|
||||
{getFieldDecorator('type2', {
|
||||
rules: [{ required: true, message: '请选择仓库类型' }],
|
||||
})(
|
||||
<Select placeholder="请选择仓库类型">
|
||||
<Option value="private">私密</Option>
|
||||
<Option value="public">公开</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Card>
|
||||
<Card title="成员管理" bordered={false}>
|
||||
{getFieldDecorator('members', {
|
||||
initialValue: tableData,
|
||||
})(<TableForm />)}
|
||||
</Card>
|
||||
<FooterToolbar style={{ width }}>
|
||||
{this.getErrorInfo()}
|
||||
<Button type="primary" onClick={this.validate} loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
</FooterToolbar>
|
||||
</PageHeaderWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AdvancedForm;
|
||||
247
admin-web/src/pages/Forms/BasicForm.js
Normal file
247
admin-web/src/pages/Forms/BasicForm.js
Normal file
@@ -0,0 +1,247 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { formatMessage, FormattedMessage } from 'umi/locale';
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
DatePicker,
|
||||
Select,
|
||||
Button,
|
||||
Card,
|
||||
InputNumber,
|
||||
Radio,
|
||||
Icon,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
import styles from './style.less';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const { Option } = Select;
|
||||
const { RangePicker } = DatePicker;
|
||||
const { TextArea } = Input;
|
||||
|
||||
@connect(({ loading }) => ({
|
||||
submitting: loading.effects['form/submitRegularForm'],
|
||||
}))
|
||||
@Form.create()
|
||||
class BasicForms extends PureComponent {
|
||||
handleSubmit = e => {
|
||||
const { dispatch, form } = this.props;
|
||||
e.preventDefault();
|
||||
form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
dispatch({
|
||||
type: 'form/submitRegularForm',
|
||||
payload: values,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { submitting } = this.props;
|
||||
const {
|
||||
form: { getFieldDecorator, getFieldValue },
|
||||
} = this.props;
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 7 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 24 },
|
||||
sm: { span: 12 },
|
||||
md: { span: 10 },
|
||||
},
|
||||
};
|
||||
|
||||
const submitFormLayout = {
|
||||
wrapperCol: {
|
||||
xs: { span: 24, offset: 0 },
|
||||
sm: { span: 10, offset: 7 },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<PageHeaderWrapper
|
||||
title={<FormattedMessage id="app.forms.basic.title" />}
|
||||
content={<FormattedMessage id="app.forms.basic.description" />}
|
||||
>
|
||||
<Card bordered={false}>
|
||||
<Form onSubmit={this.handleSubmit} hideRequiredMark style={{ marginTop: 8 }}>
|
||||
<FormItem {...formItemLayout} label={<FormattedMessage id="form.title.label" />}>
|
||||
{getFieldDecorator('title', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: formatMessage({ id: 'validation.title.required' }),
|
||||
},
|
||||
],
|
||||
})(<Input placeholder={formatMessage({ id: 'form.title.placeholder' })} />)}
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label={<FormattedMessage id="form.date.label" />}>
|
||||
{getFieldDecorator('date', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: formatMessage({ id: 'validation.date.required' }),
|
||||
},
|
||||
],
|
||||
})(
|
||||
<RangePicker
|
||||
style={{ width: '100%' }}
|
||||
placeholder={[
|
||||
formatMessage({ id: 'form.date.placeholder.start' }),
|
||||
formatMessage({ id: 'form.date.placeholder.end' }),
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label={<FormattedMessage id="form.goal.label" />}>
|
||||
{getFieldDecorator('goal', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: formatMessage({ id: 'validation.goal.required' }),
|
||||
},
|
||||
],
|
||||
})(
|
||||
<TextArea
|
||||
style={{ minHeight: 32 }}
|
||||
placeholder={formatMessage({ id: 'form.goal.placeholder' })}
|
||||
rows={4}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label={<FormattedMessage id="form.standard.label" />}>
|
||||
{getFieldDecorator('standard', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: formatMessage({ id: 'validation.standard.required' }),
|
||||
},
|
||||
],
|
||||
})(
|
||||
<TextArea
|
||||
style={{ minHeight: 32 }}
|
||||
placeholder={formatMessage({ id: 'form.standard.placeholder' })}
|
||||
rows={4}
|
||||
/>
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={
|
||||
<span>
|
||||
<FormattedMessage id="form.client.label" />
|
||||
<em className={styles.optional}>
|
||||
<FormattedMessage id="form.optional" />
|
||||
<Tooltip title={<FormattedMessage id="form.client.label.tooltip" />}>
|
||||
<Icon type="info-circle-o" style={{ marginRight: 4 }} />
|
||||
</Tooltip>
|
||||
</em>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('client')(
|
||||
<Input placeholder={formatMessage({ id: 'form.client.placeholder' })} />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={
|
||||
<span>
|
||||
<FormattedMessage id="form.invites.label" />
|
||||
<em className={styles.optional}>
|
||||
<FormattedMessage id="form.optional" />
|
||||
</em>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('invites')(
|
||||
<Input placeholder={formatMessage({ id: 'form.invites.placeholder' })} />
|
||||
)}
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={
|
||||
<span>
|
||||
<FormattedMessage id="form.weight.label" />
|
||||
<em className={styles.optional}>
|
||||
<FormattedMessage id="form.optional" />
|
||||
</em>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{getFieldDecorator('weight')(
|
||||
<InputNumber
|
||||
placeholder={formatMessage({ id: 'form.weight.placeholder' })}
|
||||
min={0}
|
||||
max={100}
|
||||
/>
|
||||
)}
|
||||
<span className="ant-form-text">%</span>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
{...formItemLayout}
|
||||
label={<FormattedMessage id="form.public.label" />}
|
||||
help={<FormattedMessage id="form.public.label.help" />}
|
||||
>
|
||||
<div>
|
||||
{getFieldDecorator('public', {
|
||||
initialValue: '1',
|
||||
})(
|
||||
<Radio.Group>
|
||||
<Radio value="1">
|
||||
<FormattedMessage id="form.public.radio.public" />
|
||||
</Radio>
|
||||
<Radio value="2">
|
||||
<FormattedMessage id="form.public.radio.partially-public" />
|
||||
</Radio>
|
||||
<Radio value="3">
|
||||
<FormattedMessage id="form.public.radio.private" />
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
<FormItem style={{ marginBottom: 0 }}>
|
||||
{getFieldDecorator('publicUsers')(
|
||||
<Select
|
||||
mode="multiple"
|
||||
placeholder={formatMessage({ id: 'form.publicUsers.placeholder' })}
|
||||
style={{
|
||||
margin: '8px 0',
|
||||
display: getFieldValue('public') === '2' ? 'block' : 'none',
|
||||
}}
|
||||
>
|
||||
<Option value="1">
|
||||
<FormattedMessage id="form.publicUsers.option.A" />
|
||||
</Option>
|
||||
<Option value="2">
|
||||
<FormattedMessage id="form.publicUsers.option.B" />
|
||||
</Option>
|
||||
<Option value="3">
|
||||
<FormattedMessage id="form.publicUsers.option.C" />
|
||||
</Option>
|
||||
</Select>
|
||||
)}
|
||||
</FormItem>
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem {...submitFormLayout} style={{ marginTop: 32 }}>
|
||||
<Button type="primary" htmlType="submit" loading={submitting}>
|
||||
<FormattedMessage id="form.submit" />
|
||||
</Button>
|
||||
<Button style={{ marginLeft: 8 }}>
|
||||
<FormattedMessage id="form.save" />
|
||||
</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
</PageHeaderWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BasicForms;
|
||||
115
admin-web/src/pages/Forms/StepForm/Step1.js
Normal file
115
admin-web/src/pages/Forms/StepForm/Step1.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { Form, Input, Button, Select, Divider } from 'antd';
|
||||
import router from 'umi/router';
|
||||
import styles from './style.less';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
span: 5,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 19,
|
||||
},
|
||||
};
|
||||
|
||||
@connect(({ form }) => ({
|
||||
data: form.step,
|
||||
}))
|
||||
@Form.create()
|
||||
class Step1 extends React.PureComponent {
|
||||
render() {
|
||||
const { form, dispatch, data } = this.props;
|
||||
const { getFieldDecorator, validateFields } = form;
|
||||
const onValidateForm = () => {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
dispatch({
|
||||
type: 'form/saveStepFormData',
|
||||
payload: values,
|
||||
});
|
||||
router.push('/form/step-form/confirm');
|
||||
}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Fragment>
|
||||
<Form layout="horizontal" className={styles.stepForm} hideRequiredMark>
|
||||
<Form.Item {...formItemLayout} label="付款账户">
|
||||
{getFieldDecorator('payAccount', {
|
||||
initialValue: data.payAccount,
|
||||
rules: [{ required: true, message: '请选择付款账户' }],
|
||||
})(
|
||||
<Select placeholder="test@example.com">
|
||||
<Option value="ant-design@alipay.com">ant-design@alipay.com</Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} label="收款账户">
|
||||
<Input.Group compact>
|
||||
<Select defaultValue="alipay" style={{ width: 100 }}>
|
||||
<Option value="alipay">支付宝</Option>
|
||||
<Option value="bank">银行账户</Option>
|
||||
</Select>
|
||||
{getFieldDecorator('receiverAccount', {
|
||||
initialValue: data.receiverAccount,
|
||||
rules: [
|
||||
{ required: true, message: '请输入收款人账户' },
|
||||
{ type: 'email', message: '账户名应为邮箱格式' },
|
||||
],
|
||||
})(<Input style={{ width: 'calc(100% - 100px)' }} placeholder="test@example.com" />)}
|
||||
</Input.Group>
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} label="收款人姓名">
|
||||
{getFieldDecorator('receiverName', {
|
||||
initialValue: data.receiverName,
|
||||
rules: [{ required: true, message: '请输入收款人姓名' }],
|
||||
})(<Input placeholder="请输入收款人姓名" />)}
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} label="转账金额">
|
||||
{getFieldDecorator('amount', {
|
||||
initialValue: data.amount,
|
||||
rules: [
|
||||
{ required: true, message: '请输入转账金额' },
|
||||
{
|
||||
pattern: /^(\d+)((?:\.\d+)?)$/,
|
||||
message: '请输入合法金额数字',
|
||||
},
|
||||
],
|
||||
})(<Input prefix="¥" placeholder="请输入金额" />)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
wrapperCol={{
|
||||
xs: { span: 24, offset: 0 },
|
||||
sm: {
|
||||
span: formItemLayout.wrapperCol.span,
|
||||
offset: formItemLayout.labelCol.span,
|
||||
},
|
||||
}}
|
||||
label=""
|
||||
>
|
||||
<Button type="primary" onClick={onValidateForm}>
|
||||
下一步
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<Divider style={{ margin: '40px 0 24px' }} />
|
||||
<div className={styles.desc}>
|
||||
<h3>说明</h3>
|
||||
<h4>转账到支付宝账户</h4>
|
||||
<p>
|
||||
如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。
|
||||
</p>
|
||||
<h4>转账到银行卡</h4>
|
||||
<p>
|
||||
如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。如果需要,这里可以放一些关于产品的常见问题说明。
|
||||
</p>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Step1;
|
||||
99
admin-web/src/pages/Forms/StepForm/Step2.js
Normal file
99
admin-web/src/pages/Forms/StepForm/Step2.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import React from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { Form, Input, Button, Alert, Divider } from 'antd';
|
||||
import router from 'umi/router';
|
||||
import { digitUppercase } from '@/utils/utils';
|
||||
import styles from './style.less';
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
span: 5,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 19,
|
||||
},
|
||||
};
|
||||
|
||||
@connect(({ form, loading }) => ({
|
||||
submitting: loading.effects['form/submitStepForm'],
|
||||
data: form.step,
|
||||
}))
|
||||
@Form.create()
|
||||
class Step2 extends React.PureComponent {
|
||||
render() {
|
||||
const { form, data, dispatch, submitting } = this.props;
|
||||
const { getFieldDecorator, validateFields } = form;
|
||||
const onPrev = () => {
|
||||
router.push('/form/step-form/info');
|
||||
};
|
||||
const onValidateForm = e => {
|
||||
e.preventDefault();
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
dispatch({
|
||||
type: 'form/submitStepForm',
|
||||
payload: {
|
||||
...data,
|
||||
...values,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Form layout="horizontal" className={styles.stepForm}>
|
||||
<Alert
|
||||
closable
|
||||
showIcon
|
||||
message="确认转账后,资金将直接打入对方账户,无法退回。"
|
||||
style={{ marginBottom: 24 }}
|
||||
/>
|
||||
<Form.Item {...formItemLayout} className={styles.stepFormText} label="付款账户">
|
||||
{data.payAccount}
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} className={styles.stepFormText} label="收款账户">
|
||||
{data.receiverAccount}
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} className={styles.stepFormText} label="收款人姓名">
|
||||
{data.receiverName}
|
||||
</Form.Item>
|
||||
<Form.Item {...formItemLayout} className={styles.stepFormText} label="转账金额">
|
||||
<span className={styles.money}>{data.amount}</span>
|
||||
<span className={styles.uppercase}>({digitUppercase(data.amount)})</span>
|
||||
</Form.Item>
|
||||
<Divider style={{ margin: '24px 0' }} />
|
||||
<Form.Item {...formItemLayout} label="支付密码" required={false}>
|
||||
{getFieldDecorator('password', {
|
||||
initialValue: '123456',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '需要支付密码才能进行支付',
|
||||
},
|
||||
],
|
||||
})(<Input type="password" autoComplete="off" style={{ width: '80%' }} />)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{ marginBottom: 8 }}
|
||||
wrapperCol={{
|
||||
xs: { span: 24, offset: 0 },
|
||||
sm: {
|
||||
span: formItemLayout.wrapperCol.span,
|
||||
offset: formItemLayout.labelCol.span,
|
||||
},
|
||||
}}
|
||||
label=""
|
||||
>
|
||||
<Button type="primary" onClick={onValidateForm} loading={submitting}>
|
||||
提交
|
||||
</Button>
|
||||
<Button onClick={onPrev} style={{ marginLeft: 8 }}>
|
||||
上一步
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Step2;
|
||||
74
admin-web/src/pages/Forms/StepForm/Step3.js
Normal file
74
admin-web/src/pages/Forms/StepForm/Step3.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { Button, Row, Col } from 'antd';
|
||||
import router from 'umi/router';
|
||||
import Result from '@/components/Result';
|
||||
import styles from './style.less';
|
||||
|
||||
@connect(({ form }) => ({
|
||||
data: form.step,
|
||||
}))
|
||||
class Step3 extends React.PureComponent {
|
||||
render() {
|
||||
const { data } = this.props;
|
||||
const onFinish = () => {
|
||||
router.push('/form/step-form/info');
|
||||
};
|
||||
const information = (
|
||||
<div className={styles.information}>
|
||||
<Row>
|
||||
<Col xs={24} sm={8} className={styles.label}>
|
||||
付款账户:
|
||||
</Col>
|
||||
<Col xs={24} sm={16}>
|
||||
{data.payAccount}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={24} sm={8} className={styles.label}>
|
||||
收款账户:
|
||||
</Col>
|
||||
<Col xs={24} sm={16}>
|
||||
{data.receiverAccount}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={24} sm={8} className={styles.label}>
|
||||
收款人姓名:
|
||||
</Col>
|
||||
<Col xs={24} sm={16}>
|
||||
{data.receiverName}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col xs={24} sm={8} className={styles.label}>
|
||||
转账金额:
|
||||
</Col>
|
||||
<Col xs={24} sm={16}>
|
||||
<span className={styles.money}>{data.amount}</span> 元
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
const actions = (
|
||||
<Fragment>
|
||||
<Button type="primary" onClick={onFinish}>
|
||||
再转一笔
|
||||
</Button>
|
||||
<Button>查看账单</Button>
|
||||
</Fragment>
|
||||
);
|
||||
return (
|
||||
<Result
|
||||
type="success"
|
||||
title="操作成功"
|
||||
description="预计两小时内到账"
|
||||
extra={information}
|
||||
actions={actions}
|
||||
className={styles.result}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Step3;
|
||||
46
admin-web/src/pages/Forms/StepForm/index.js
Normal file
46
admin-web/src/pages/Forms/StepForm/index.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { Card, Steps } from 'antd';
|
||||
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
|
||||
import styles from '../style.less';
|
||||
|
||||
const { Step } = Steps;
|
||||
|
||||
export default class StepForm extends PureComponent {
|
||||
getCurrentStep() {
|
||||
const { location } = this.props;
|
||||
const { pathname } = location;
|
||||
const pathList = pathname.split('/');
|
||||
switch (pathList[pathList.length - 1]) {
|
||||
case 'info':
|
||||
return 0;
|
||||
case 'confirm':
|
||||
return 1;
|
||||
case 'result':
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { location, children } = this.props;
|
||||
return (
|
||||
<PageHeaderWrapper
|
||||
title="分步表单"
|
||||
tabActiveKey={location.pathname}
|
||||
content="将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。"
|
||||
>
|
||||
<Card bordered={false}>
|
||||
<Fragment>
|
||||
<Steps current={this.getCurrentStep()} className={styles.steps}>
|
||||
<Step title="填写转账信息" />
|
||||
<Step title="确认转账信息" />
|
||||
<Step title="完成" />
|
||||
</Steps>
|
||||
{children}
|
||||
</Fragment>
|
||||
</Card>
|
||||
</PageHeaderWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
78
admin-web/src/pages/Forms/StepForm/style.less
Normal file
78
admin-web/src/pages/Forms/StepForm/style.less
Normal file
@@ -0,0 +1,78 @@
|
||||
@import '~antd/lib/style/themes/default.less';
|
||||
|
||||
.stepForm {
|
||||
max-width: 500px;
|
||||
margin: 40px auto 0;
|
||||
}
|
||||
|
||||
.stepFormText {
|
||||
margin-bottom: 24px;
|
||||
:global {
|
||||
.ant-form-item-label,
|
||||
.ant-form-item-control {
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.result {
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
padding: 24px 0 8px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
padding: 0 56px;
|
||||
color: @text-color-secondary;
|
||||
h3 {
|
||||
margin: 0 0 12px 0;
|
||||
color: @text-color-secondary;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
}
|
||||
h4 {
|
||||
margin: 0 0 4px 0;
|
||||
color: @text-color-secondary;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-md) {
|
||||
.desc {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.information {
|
||||
line-height: 22px;
|
||||
:global {
|
||||
.ant-row:not(:last-child) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
.label {
|
||||
padding-right: 8px;
|
||||
color: @heading-color;
|
||||
text-align: right;
|
||||
@media screen and (max-width: @screen-sm) {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.money {
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
font-family: 'Helvetica Neue', sans-serif;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.uppercase {
|
||||
font-size: 12px;
|
||||
}
|
||||
261
admin-web/src/pages/Forms/TableForm.js
Normal file
261
admin-web/src/pages/Forms/TableForm.js
Normal file
@@ -0,0 +1,261 @@
|
||||
import React, { PureComponent, Fragment } from 'react';
|
||||
import { Table, Button, Input, message, Popconfirm, Divider } from 'antd';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import styles from './style.less';
|
||||
|
||||
class TableForm extends PureComponent {
|
||||
index = 0;
|
||||
|
||||
cacheOriginData = {};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
data: props.value,
|
||||
loading: false,
|
||||
/* eslint-disable-next-line react/no-unused-state */
|
||||
value: props.value,
|
||||
};
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, preState) {
|
||||
if (isEqual(nextProps.value, preState.value)) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
data: nextProps.value,
|
||||
value: nextProps.value,
|
||||
};
|
||||
}
|
||||
|
||||
getRowByKey(key, newData) {
|
||||
const { data } = this.state;
|
||||
return (newData || data).filter(item => item.key === key)[0];
|
||||
}
|
||||
|
||||
toggleEditable = (e, key) => {
|
||||
e.preventDefault();
|
||||
const { data } = this.state;
|
||||
const newData = data.map(item => ({ ...item }));
|
||||
const target = this.getRowByKey(key, newData);
|
||||
if (target) {
|
||||
// 进入编辑状态时保存原始数据
|
||||
if (!target.editable) {
|
||||
this.cacheOriginData[key] = { ...target };
|
||||
}
|
||||
target.editable = !target.editable;
|
||||
this.setState({ data: newData });
|
||||
}
|
||||
};
|
||||
|
||||
newMember = () => {
|
||||
const { data } = this.state;
|
||||
const newData = data.map(item => ({ ...item }));
|
||||
newData.push({
|
||||
key: `NEW_TEMP_ID_${this.index}`,
|
||||
workId: '',
|
||||
name: '',
|
||||
department: '',
|
||||
editable: true,
|
||||
isNew: true,
|
||||
});
|
||||
this.index += 1;
|
||||
this.setState({ data: newData });
|
||||
};
|
||||
|
||||
remove(key) {
|
||||
const { data } = this.state;
|
||||
const { onChange } = this.props;
|
||||
const newData = data.filter(item => item.key !== key);
|
||||
this.setState({ data: newData });
|
||||
onChange(newData);
|
||||
}
|
||||
|
||||
handleKeyPress(e, key) {
|
||||
if (e.key === 'Enter') {
|
||||
this.saveRow(e, key);
|
||||
}
|
||||
}
|
||||
|
||||
handleFieldChange(e, fieldName, key) {
|
||||
const { data } = this.state;
|
||||
const newData = data.map(item => ({ ...item }));
|
||||
const target = this.getRowByKey(key, newData);
|
||||
if (target) {
|
||||
target[fieldName] = e.target.value;
|
||||
this.setState({ data: newData });
|
||||
}
|
||||
}
|
||||
|
||||
saveRow(e, key) {
|
||||
e.persist();
|
||||
this.setState({
|
||||
loading: true,
|
||||
});
|
||||
setTimeout(() => {
|
||||
if (this.clickedCancel) {
|
||||
this.clickedCancel = false;
|
||||
return;
|
||||
}
|
||||
const target = this.getRowByKey(key) || {};
|
||||
if (!target.workId || !target.name || !target.department) {
|
||||
message.error('请填写完整成员信息。');
|
||||
e.target.focus();
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
delete target.isNew;
|
||||
this.toggleEditable(e, key);
|
||||
const { data } = this.state;
|
||||
const { onChange } = this.props;
|
||||
onChange(data);
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
cancel(e, key) {
|
||||
this.clickedCancel = true;
|
||||
e.preventDefault();
|
||||
const { data } = this.state;
|
||||
const newData = data.map(item => ({ ...item }));
|
||||
const target = this.getRowByKey(key, newData);
|
||||
if (this.cacheOriginData[key]) {
|
||||
Object.assign(target, this.cacheOriginData[key]);
|
||||
delete this.cacheOriginData[key];
|
||||
}
|
||||
target.editable = false;
|
||||
this.setState({ data: newData });
|
||||
this.clickedCancel = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
const columns = [
|
||||
{
|
||||
title: '成员姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: '20%',
|
||||
render: (text, record) => {
|
||||
if (record.editable) {
|
||||
return (
|
||||
<Input
|
||||
value={text}
|
||||
autoFocus
|
||||
onChange={e => this.handleFieldChange(e, 'name', record.key)}
|
||||
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
||||
placeholder="成员姓名"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '工号',
|
||||
dataIndex: 'workId',
|
||||
key: 'workId',
|
||||
width: '20%',
|
||||
render: (text, record) => {
|
||||
if (record.editable) {
|
||||
return (
|
||||
<Input
|
||||
value={text}
|
||||
onChange={e => this.handleFieldChange(e, 'workId', record.key)}
|
||||
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
||||
placeholder="工号"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '所属部门',
|
||||
dataIndex: 'department',
|
||||
key: 'department',
|
||||
width: '40%',
|
||||
render: (text, record) => {
|
||||
if (record.editable) {
|
||||
return (
|
||||
<Input
|
||||
value={text}
|
||||
onChange={e => this.handleFieldChange(e, 'department', record.key)}
|
||||
onKeyPress={e => this.handleKeyPress(e, record.key)}
|
||||
placeholder="所属部门"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (text, record) => {
|
||||
const { loading } = this.state;
|
||||
if (!!record.editable && loading) {
|
||||
return null;
|
||||
}
|
||||
if (record.editable) {
|
||||
if (record.isNew) {
|
||||
return (
|
||||
<span>
|
||||
<a onClick={e => this.saveRow(e, record.key)}>添加</a>
|
||||
<Divider type="vertical" />
|
||||
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<a onClick={e => this.saveRow(e, record.key)}>保存</a>
|
||||
<Divider type="vertical" />
|
||||
<a onClick={e => this.cancel(e, record.key)}>取消</a>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
<a onClick={e => this.toggleEditable(e, record.key)}>编辑</a>
|
||||
<Divider type="vertical" />
|
||||
<Popconfirm title="是否要删除此行?" onConfirm={() => this.remove(record.key)}>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const { loading, data } = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Table
|
||||
loading={loading}
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
rowClassName={record => (record.editable ? styles.editable : '')}
|
||||
/>
|
||||
<Button
|
||||
style={{ width: '100%', marginTop: 16, marginBottom: 8 }}
|
||||
type="dashed"
|
||||
onClick={this.newMember}
|
||||
icon="plus"
|
||||
>
|
||||
新增成员
|
||||
</Button>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TableForm;
|
||||
47
admin-web/src/pages/Forms/models/form.js
Normal file
47
admin-web/src/pages/Forms/models/form.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { routerRedux } from 'dva/router';
|
||||
import { message } from 'antd';
|
||||
import { fakeSubmitForm } from '@/services/api';
|
||||
|
||||
export default {
|
||||
namespace: 'form',
|
||||
|
||||
state: {
|
||||
step: {
|
||||
payAccount: 'ant-design@alipay.com',
|
||||
receiverAccount: 'test@example.com',
|
||||
receiverName: 'Alex',
|
||||
amount: '500',
|
||||
},
|
||||
},
|
||||
|
||||
effects: {
|
||||
*submitRegularForm({ payload }, { call }) {
|
||||
yield call(fakeSubmitForm, payload);
|
||||
message.success('提交成功');
|
||||
},
|
||||
*submitStepForm({ payload }, { call, put }) {
|
||||
yield call(fakeSubmitForm, payload);
|
||||
yield put({
|
||||
type: 'saveStepFormData',
|
||||
payload,
|
||||
});
|
||||
yield put(routerRedux.push('/form/step-form/result'));
|
||||
},
|
||||
*submitAdvancedForm({ payload }, { call }) {
|
||||
yield call(fakeSubmitForm, payload);
|
||||
message.success('提交成功');
|
||||
},
|
||||
},
|
||||
|
||||
reducers: {
|
||||
saveStepFormData(state, { payload }) {
|
||||
return {
|
||||
...state,
|
||||
step: {
|
||||
...state.step,
|
||||
...payload,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
90
admin-web/src/pages/Forms/style.less
Normal file
90
admin-web/src/pages/Forms/style.less
Normal file
@@ -0,0 +1,90 @@
|
||||
@import '~antd/lib/style/themes/default.less';
|
||||
|
||||
.card {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin: 0 0 16px 0;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.steps:global(.ant-steps) {
|
||||
max-width: 750px;
|
||||
margin: 16px auto;
|
||||
}
|
||||
|
||||
.errorIcon {
|
||||
margin-right: 24px;
|
||||
color: @error-color;
|
||||
cursor: pointer;
|
||||
i {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.errorPopover {
|
||||
:global {
|
||||
.ant-popover-inner-content {
|
||||
min-width: 256px;
|
||||
max-height: 290px;
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.errorListItem {
|
||||
padding: 8px 16px;
|
||||
list-style: none;
|
||||
border-bottom: 1px solid @border-color-split;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
&:hover {
|
||||
background: @primary-1;
|
||||
}
|
||||
&:last-child {
|
||||
border: 0;
|
||||
}
|
||||
.errorIcon {
|
||||
float: left;
|
||||
margin-top: 4px;
|
||||
margin-right: 12px;
|
||||
padding-bottom: 22px;
|
||||
color: @error-color;
|
||||
}
|
||||
.errorField {
|
||||
margin-top: 2px;
|
||||
color: @text-color-secondary;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.editable {
|
||||
td {
|
||||
padding-top: 13px !important;
|
||||
padding-bottom: 12.5px !important;
|
||||
}
|
||||
}
|
||||
|
||||
// custom footer for fixed footer toolbar
|
||||
.advancedForm + div {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
.advancedForm {
|
||||
:global {
|
||||
.ant-form .ant-row:last-child .ant-form-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.ant-table td {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.optional {
|
||||
color: @text-color-secondary;
|
||||
font-style: normal;
|
||||
}
|
||||
Reference in New Issue
Block a user