张延森 5 anos atrás
pai
commit
2eb31b65b2

+ 0
- 82
src/components/XForm2/Form.jsx Ver arquivo

@@ -1,82 +0,0 @@
1
-import React from 'react';
2
-import PropTypes from 'prop-types';
3
-import { Form, Button, Select } from 'antd';
4
-import XItem2 from './Item';
5
-import { isFunction, isEmpty } from './utils';
6
-
7
-const formItemLayout = {
8
-  labelCol: {
9
-    xs: { span: 24 },
10
-    sm: { span: 8 },
11
-  },
12
-  wrapperCol: {
13
-    xs: { span: 24 },
14
-    sm: { span: 16 },
15
-  },
16
-};
17
-
18
-class Form2 extends React.PureComponent {
19
-  state = {}
20
-
21
-  handleSubmit = e => {
22
-    e.preventDefault();
23
-    const { form, onError, onSubmit } = this.props
24
-
25
-    form.validateFieldsAndScroll((err, values) => {
26
-      if (err) {
27
-        if (isFunction(onError)) {
28
-          onError(err)
29
-        } else {
30
-          window.console.error(err)
31
-        }
32
-      } else {
33
-        if (isFunction(onSubmit)) {
34
-          onSubmit(values)
35
-        }
36
-      }
37
-    });
38
-  }
39
-
40
-  handleCancel = e => {
41
-    e.preventDefault();
42
-
43
-    if (isFunction(this.props.onCancel)) {
44
-      this.props.onCancel()
45
-    }
46
-  }
47
-
48
-  renderDefaultAction = (submitBtn, cancelBtn) => {
49
-    let FieldSubmit = null
50
-    let FieldCancel = null
51
-    if (submitBtn !== false) {
52
-      FieldSubmit = <Button htmlType="submit" type="primary">提交</Button>
53
-    }
54
-    if (cancelBtn !== false) {
55
-      FieldCancel = <Button htmlType="button" onClick={this.handleCancel} style={{ marginLeft: '48px' }}>取消</Button>
56
-    }
57
-
58
-    return FieldSubmit || FieldCancel ? <XItem2 action render={() => (<>{FieldSubmit}{FieldCancel}</>)} /> : null
59
-  }
60
-
61
-  render () {
62
-    const {fields, form, children, submitBtn, cancelBtn, ...formProps} = this.props;
63
-
64
-    console.log('---------render parent------------')
65
-
66
-    return (
67
-      <Form {...formItemLayout} {...formProps} onSubmit={this.handleSubmit}>
68
-        {children}
69
-        {/* {FeildItems} */}
70
-        {this.renderDefaultAction(submitBtn, cancelBtn)}
71
-      </Form>
72
-    );
73
-  }
74
-}
75
-
76
-Form2.propTypes = {
77
-  fields: PropTypes.array.isRequired,
78
-  form: PropTypes.object.isRequired,
79
-  dataset: PropTypes.object,
80
-}
81
-
82
-export default Form2;

+ 0
- 185
src/components/XForm2/Item.jsx Ver arquivo

@@ -1,185 +0,0 @@
1
-import React from 'react';
2
-import { Form, Select } from 'antd';
3
-import PropTypes from 'prop-types'; 
4
-import { hasOwnProperty, isFunction, isBoolean } from './utils';
5
-
6
-const AntFormItem = Form.Item
7
-
8
-const tailFormItemLayout = {
9
-  wrapperCol: {
10
-    xs: {
11
-      span: 24,
12
-      offset: 0,
13
-    },
14
-    sm: {
15
-      span: 16,
16
-      offset: 8,
17
-    },
18
-  },
19
-};
20
-
21
-class Item extends React.PureComponent {
22
-  state = {
23
-    allFieldValues: this.getFormValues(),
24
-  }
25
-
26
-  componentDidMount() {
27
-    if (this.props.formChange) {
28
-      this.props.formChange((p, c, values) => {
29
-        this.setState({ allFieldValues: values || this.getFormValues()})
30
-      })
31
-    }
32
-  }
33
-
34
-  getFormValues() {
35
-    if (this.props.form) {
36
-      return this.props.form.getFieldsValue() || {}
37
-    }
38
-
39
-    return {}
40
-  }
41
-
42
-  getActualValue(fn, defVal) {
43
-    const val = isFunction(fn) ? fn(this.state.allFieldValues, this.props) : fn
44
-    return val === undefined ? defVal : val
45
-  }
46
-
47
-  getValueFromEvent = e => {
48
-    if (hasOwnProperty(e, 'checked')) {
49
-      return e.checked;
50
-    } else if (hasOwnProperty(e, 'target')) {
51
-      return e.target.value;
52
-    } else {
53
-      return e;
54
-    }
55
-  }
56
-
57
-  renderSelectOptions (dict) {
58
-    return (dict || []).map(x => <Select.Option key={x.value} value={x.value}>{x.label}</Select.Option>)
59
-  }
60
-
61
-  renderField() {
62
-    const {
63
-      form,
64
-      name,
65
-      node,
66
-      children,
67
-      placeholder,
68
-      render,
69
-      rules,
70
-      value,
71
-      action,
72
-      props,
73
-      options,
74
-    } = this.props || {}
75
-
76
-    const config = {
77
-      rules,
78
-      initialValue: value,
79
-      getValueFromEvent: this.getValueFromEvent,
80
-    }
81
-
82
-    const fieldProps = {
83
-      placeholder: Array.isArray(placeholder) ? placeholder(this.state.allFieldValues, this.props) : placeholder,
84
-      style: { width: '100%' },
85
-      ...(props || {})
86
-    }
87
-
88
-    const Childs = Array.isArray(options) ? this.renderSelectOptions(options) : (isFunction(children) ? children() : (children || null));
89
-    const Field = isFunction(render) ? render(this.props) : React.createElement(node, fieldProps, Childs);
90
-
91
-    return action ? Field : form.getFieldDecorator(name, config)(Field)
92
-  }
93
-
94
-  render () {
95
-    const {
96
-      form,
97
-      label,
98
-      name,
99
-      node,
100
-      children,
101
-      placeholder,
102
-      render,
103
-      rules,
104
-      value,
105
-      action,
106
-      props = {},
107
-      hidden = false,
108
-      reportChange,
109
-      listenChange,
110
-      options,
111
-      ...restProps
112
-    } = this.props;
113
-
114
-    const initialValue = value === undefined ? {} : { initialValue: value }
115
-    
116
-    const config = {
117
-      rules,
118
-      getValueFromEvent: this.getValueFromEvent,
119
-      ...initialValue,
120
-    }
121
-    
122
-    // 以下支持可变内容
123
-    // 暂时只支持 hidden, disable, label 的可变
124
-    const hiddenActual = isFunction(hidden) ? hidden(this.state.allFieldValues, this.props) : (
125
-      isBoolean(hidden) ? hidden : false
126
-    );
127
-    const labelActual = isFunction(label) ? label(this.state.allFieldValues, this.props) : label
128
-    const disabledActual = isFunction(props.disabled) ? props.disabled(this.state.allFieldValues, this.props) : (
129
-      isBoolean(props.disabled) ? props.disabled : false
130
-    )
131
-
132
-    // 没有类型与组件, 生成隐藏字段
133
-    if (name && hiddenActual === true) {
134
-      if (form && form.getFieldDecorator) {
135
-        form.getFieldDecorator(name, config);
136
-      }
137
-      return null;
138
-    }
139
-
140
-    const Field = this.renderField()
141
-
142
-    if (!labelActual && !name && !action) return !hiddenActual ? Field : null;
143
-    
144
-    const itemProps = action ? { ...restProps, ...tailFormItemLayout, disabled: disabledActual } : { ...restProps, disabled: disabledActual }
145
-
146
-    return !hiddenActual ? (
147
-      <AntFormItem label={labelActual} {...itemProps}>{Field}</AntFormItem>
148
-    ) : null
149
-  }
150
-};
151
-
152
-Item.propTypes = {
153
-  formChange: PropTypes.func,
154
-  form: PropTypes.object,
155
-  label: PropTypes.oneOfType([
156
-    PropTypes.node,
157
-    PropTypes.func,
158
-  ]),
159
-  placeholder: PropTypes.oneOfType([
160
-    PropTypes.string,
161
-    PropTypes.func,
162
-  ]),
163
-  name: PropTypes.string,
164
-  node: PropTypes.oneOfType([
165
-    PropTypes.elementType,
166
-    PropTypes.func,
167
-  ]),
168
-  children: PropTypes.oneOfType([
169
-    PropTypes.element,
170
-    PropTypes.func,
171
-    PropTypes.arrayOf(PropTypes.element),
172
-  ]),
173
-  render: PropTypes.func,
174
-  rules: PropTypes.array,
175
-  value: PropTypes.any,
176
-  action: PropTypes.bool,
177
-  props: PropTypes.object,
178
-  options: PropTypes.array,
179
-  hidden: PropTypes.oneOfType([
180
-    PropTypes.bool,
181
-    PropTypes.func,
182
-  ]),
183
-}
184
-
185
-export default Item;

+ 0
- 101
src/components/XForm2/README.md Ver arquivo

@@ -1,101 +0,0 @@
1
-# XForm2
2
-基于原来的 XForm 思想, 重新封装了一个表单。主要解决以下几个问题
3
-
4
-* 支持任意的表单组件, 不再受限
5
-* 支持组件的动态显示
6
-
7
-## 引用
8
-```jsx
9
-import createForm from 'path/to/xform2';
10
-```
11
-
12
-## 使用
13
-### 创建 Form
14
-
15
-```jsx
16
-// https://ant.design/components/form-cn/#Form.create(options)
17
-const options = {}
18
-
19
-// options 也可以不传
20
-const Form = createForm(options)
21
-
22
-// 这样就可以使用 Form 了
23
-class MyComponent extends React.Component {
24
-  render() {
25
-    return (
26
-      <Form onSubmit={xxx}></Form>
27
-    );
28
-  }
29
-}
30
-
31
-```
32
-
33
-生成的 Form 有如下 Props 设置
34
-
35
-| prop | 说明 | 类型 |
36
-|---|---|---|
37
-| onSubmit | 表单提交 | function(allFieldValues) {} |
38
-| onCancel | 表单取消 | function() {} |
39
-| submitBtn | 是否显示提交按钮 | 布尔值: 默认 true |
40
-| cancelBtn | 是否显示取消按钮 | 布尔值: 默认 true |
41
-| ... | 其他 [Antd Form](https://ant.design/components/form-cn/#Form) 支持的属性 |  |
42
-
43
-### 添加表单字段
44
-
45
-```jsx
46
-import React from 'react';
47
-import { Input, Select } from 'antd';
48
-
49
-const fields = [
50
-        {
51
-          label: '标题',
52
-          name: 'title',
53
-          placeholder: '填写标题',
54
-          node: Input,
55
-          value: data.title,
56
-        },
57
-        {
58
-          label: '发布位置',
59
-          name: 'showPosition',
60
-          node: Select,
61
-          options: [
62
-            { 
63
-              label: '首页',
64
-              value: 'index',
65
-            },
66
-            {
67
-              label: '积分商城',
68
-              value: 'mall',
69
-            }
70
-          ],
71
-          value: data.showPosition,
72
-          hidden: values => values.title === 'foobar',
73
-        },
74
-      ];
75
-
76
-
77
-// some codes
78
-// <Form onSubmit={xxx} fields={fields}></Form>
79
-
80
-```
81
-
82
-表单字段是通过 `json` 配置实现的。支持的属性有
83
-
84
-| 属性 | 说明 | 类型 |
85
-|---|---|---|
86
-| label | 字段文字标题 | string 或者 function(allFieldValues, props), 非必填 |
87
-| name | 字段 name | string, 非必填 |
88
-| node | 字段节点, 注意不是 `React.Element`。也就是不能是 `<Input />`, 而是 `Input` | react elementType 或者 可以生成 `React.Element` 的函数, 非必填 |
89
-| children | 字段如果复杂, 需要子元素。 子元素不能是节点, 必须是 `React.Element` | react element 或者 函数, 非必填 |
90
-| options | 如果 node 是 `antd.Select`, 这里提供了一个快捷方式自定义 `option` 列表 | array, 元素格式 `{ label: xxx, value: xxx }`, 非必填 |
91
-| render | 自定义的字段渲染逻辑 | function(props) {}, 非必填 |
92
-| action | 是否为功能类组件, 比如按钮 | boolean: 默认 false |
93
-| value | 字段默认值 | any: 非必填 |
94
-| placeholder | 字段 placeholder | string 或者 function(allFieldValues, props), 非必填 |
95
-| rules | 字段校验规则, 与 [antd.Form](https://ant.design/components/form-cn/#%E6%A0%A1%E9%AA%8C%E8%A7%84%E5%88%99) 的约定一致 | 类型 array: 非必填 |
96
-| props | 其余需要传入字段组件的属性或者事件 | object: 非必填 |
97
-| hidden | 如果有 `name`, 此值又是 `true`. 那么该字段则为隐藏字段放入 form 中。另外, 则为设置组件的显示, 隐藏 | boolean 或者 function(allFieldValues, props) : 非必填, 默认 false |
98
-
99
-## 注意事项
100
-* 字段组件支持自定义封装, 但是封装组件必须满足2个条件。1、值传递通过 `value` 属性, 2、提供 `onChange` 事件
101
-* 字段组件必须支持 `ref` 传递. 因此函数式组件, 请使用 `React.forwardRef` 包裹起来

+ 0
- 53
src/components/XForm2/index.jsx Ver arquivo

@@ -1,53 +0,0 @@
1
-import React from 'react';
2
-import { Form } from 'antd';
3
-import Form2 from './Form';
4
-import Item from './Item';
5
-import { isFunction, isEmpty } from './utils';
6
-
7
-function withForm(option = {}) {
8
-
9
-  const createOption = {
10
-    ...option,
11
-    onValuesChange: (...args) => {
12
-
13
-      if (isFunction(option.onValuesChange)) {
14
-        option.onValuesChange(...args)
15
-      }
16
-      defaultListener(...args)
17
-    }
18
-  }
19
-
20
-  let listeners = []
21
-
22
-  function defaultListener(...args) {
23
-    listeners.map(fn => fn(...args))
24
-  }
25
-
26
-  function handleFormChange (fn) {
27
-    if (isFunction(fn)) {
28
-      listeners.push(fn)
29
-    }
30
-  }
31
-
32
-  class WrapperForm extends React.Component {
33
-    renderChildren() {
34
-      const { fields, form } = this.props;
35
-  
36
-      return (fields || []).filter(x => x).map((props, inx) => {  
37
-        return (<Item key={inx} {...props} form={form} formChange={handleFormChange} />)
38
-      })
39
-    }
40
-
41
-    render() {
42
-      return (
43
-        <Form2 {...this.props}>
44
-          {this.renderChildren()}
45
-        </Form2>
46
-      )
47
-    }
48
-  }
49
-
50
-  return Form.create(createOption)(WrapperForm)
51
-}
52
-
53
-export default withForm;

+ 0
- 30
src/components/XForm2/utils.js Ver arquivo

@@ -1,30 +0,0 @@
1
-
2
-export function hasOwnProperty(o, p) {
3
-  return Object.prototype.hasOwnProperty.call(o, p);
4
-}
5
-
6
-export function isFunction(fn) {
7
-  return typeof fn === 'function'
8
-}
9
-
10
-export function isBoolean(b) {
11
-  return typeof b === 'boolean'
12
-}
13
-
14
-export function isEmpty(t) {
15
-  if (t === undefined || t === null) {
16
-    return true
17
-  }
18
-
19
-  if (typeof t === 'object') {
20
-    return !Object.keys(t).length
21
-  }
22
-  
23
-  if (Array.isArray(t)) {
24
-    return t.length
25
-  }
26
-
27
-  return false
28
-}
29
-
30
-export function noop() {}

+ 3
- 0
src/pages/system/messageList.jsx Ver arquivo

@@ -43,18 +43,21 @@ const header = (props) => {
43 43
       dataIndex: 'phone',
44 44
       key: 'phone',
45 45
       align: 'center',
46
+      width: 200,
46 47
     },
47 48
     {
48 49
       title: '留言内容',
49 50
       dataIndex: 'message',
50 51
       key: 'message',
51 52
       align: 'center',
53
+      render: txt => (<p style={{ textAlign: 'left', lineHeight: '1.8em' }}>{txt}</p>)
52 54
     },
53 55
     {
54 56
       title: '创建时间',
55 57
       dataIndex: 'createDate',
56 58
       key: 'createDate',
57 59
       align: 'center',
60
+      width: 200,
58 61
       render: (x, row) => <><span>{moment(row.createDate).format('YYYY-MM-DD')}</span></>
59 62
     },
60 63
   ];