Explorar el Código

Merge branch 'master' of http://git.ycjcjy.com/estateagents/pc-channel

顾绍勇 hace 5 años
padre
commit
c79fa7841b

+ 6
- 0
config/routes.js Ver fichero

@@ -78,6 +78,12 @@ export default [
78 78
                 name: 'H5需求单',
79 79
                 component: './sample/demand/index',
80 80
               },
81
+              {
82
+                path: '/sample/demand/edit',
83
+                name: 'H5需求单详情',
84
+                hideInMenu: true,
85
+                component: './sample/demand/edit',
86
+              },
81 87
             ],
82 88
           },
83 89
           {

+ 2
- 1
package.json Ver fichero

@@ -61,7 +61,8 @@
61 61
     "umi": "^2.8.7",
62 62
     "umi-plugin-pro-block": "^1.3.2",
63 63
     "umi-plugin-react": "^1.9.5",
64
-    "umi-request": "^1.0.8"
64
+    "umi-request": "^1.0.8",
65
+    "wangeditor": "^3.1.1"
65 66
   },
66 67
   "devDependencies": {
67 68
     "@ant-design/colors": "^3.1.0",

+ 108
- 0
src/components/Wangedit/Wangedit.jsx Ver fichero

@@ -0,0 +1,108 @@
1
+import React from 'react';
2
+import E from 'wangeditor';
3
+import { fetch, apis } from '../../utils/request';
4
+
5
+/**
6
+ * @param {*} props
7
+ * @returns
8
+ */
9
+class Wangedit extends React.Component {
10
+  constructor(props, context) {
11
+    super(props, context);
12
+    this.state = {
13
+      html: undefined,
14
+      contenteditable: props.contenteditable == false ? false : true
15
+    }
16
+    this.editor = undefined;
17
+  }
18
+
19
+  render() {
20
+    return (
21
+      <div ref="editorElem" style={{ textAlign: 'left' }}>
22
+      </div>
23
+    );
24
+  }
25
+
26
+  componentDidMount() {
27
+    const elem = this.refs.editorElem
28
+    this.editor = new E(elem)
29
+    // 使用 onchange 函数监听内容的变化
30
+    this.editor.customConfig.onchange = html => {
31
+      this.setState({ html })
32
+
33
+      if (typeof this.props.onChange === 'function') {
34
+        this.props.onChange(html)
35
+      }
36
+    }
37
+    this.editor.customConfig.zIndex = 100
38
+    this.editor.customConfig.uploadImgMaxLength = 1
39
+    this.editor.customConfig.customUploadImg = function (files, insert) {
40
+      if (!files.length) return
41
+      
42
+      const data = new FormData()
43
+      data.append('file', files[0])
44
+
45
+      fetch(apis.image.upload)({data}).then(insert)
46
+    }
47
+    this.editor.customConfig.menus = [
48
+      'head',  // 标题
49
+      'bold',  // 粗体
50
+      'fontSize',  // 字号
51
+      'fontName',  // 字体
52
+      'italic',  // 斜体
53
+      'underline',  // 下划线
54
+      'strikeThrough',  // 删除线
55
+      'foreColor',  // 文字颜色
56
+      'backColor',  // 背景颜色
57
+      'list',  // 列表
58
+      'justify',  // 对齐方式
59
+      'quote',  // 引用
60
+      'image',  // 插入图片
61
+      'undo',  // 撤销
62
+      'redo'  // 重复
63
+    ]
64
+    
65
+    // 过滤 word 字符
66
+    this.editor.customConfig.pasteFilterStyle = false
67
+    this.editor.customConfig.pasteTextHandle = function(content) {
68
+      const regs = [
69
+        /<!--\[if [\s\S]*?endif\]-->/ig,
70
+        /<[a-zA-Z0-9]+\:[^>]+>[^>]*<\/[a-zA-Z0-9]+\:[^>]+>/ig,
71
+        /<[a-zA-Z0-9]+\:[^>]+\/>/ig,
72
+        /<style>[\s\S]*?<\/style>/ig,
73
+      ]
74
+
75
+      return regs.reduce((acc, reg) => {
76
+        return acc.replace(reg, '')
77
+      }, content)
78
+    }
79
+
80
+    this.editor.create()
81
+    this.editor.$textElem.attr('contenteditable',this.state.contenteditable);
82
+    this.editor.customConfig.uploadImgShowBase64 = true
83
+    this.editor.txt.html(this.props.value)
84
+  }
85
+
86
+  componentDidUpdate(props, state) {
87
+    if (this.props.value && !state.html) {
88
+      if (this.editor) {
89
+        this.editor.txt.html(this.props.value)
90
+      }
91
+    }
92
+  }
93
+
94
+  /**
95
+   *增加这个 shouldComponentUpdate 生命函数
96
+    处理自动聚焦到富文本上
97
+   *
98
+   * @param {*} nextProps
99
+   * @returns
100
+   * @memberof Wangedit
101
+   */
102
+  shouldComponentUpdate(nextProps) {
103
+    return nextProps.value !== this.editor.txt.html()
104
+  }
105
+}
106
+
107
+export default Wangedit
108
+

+ 113
- 0
src/pages/sample/demand/edit.jsx Ver fichero

@@ -0,0 +1,113 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import router from 'umi/router';
6
+import apis from '../../../services/apis';
7
+import request from '../../../utils/request';
8
+import Wangedit from '../../../components/Wangedit/Wangedit'
9
+import moment from 'moment';
10
+
11
+
12
+const header = props => {
13
+    const demandId = props.location.query.id
14
+  
15
+    const [ data, setData ] = useState({})
16
+    if(demandId){
17
+      useEffect(() => {
18
+        getDemandData(demandId);
19
+      },[])
20
+  
21
+    // 查询列表
22
+    const getDemandData = (demandId) => {
23
+      request({
24
+          ...apis.sample.get,
25
+          urlData: { id: demandId }
26
+      }).then((data) => {
27
+        setData(data)
28
+      }).catch((err) => {
29
+        message.error(err.msg || err.message)
30
+      })
31
+    }
32
+    }
33
+  
34
+    const fields = [
35
+      {
36
+        label: '样例名',
37
+        name: 'sampleName',
38
+        type: FieldTypes.Text,
39
+        value: data.sampleName,
40
+      },    
41
+      {
42
+        label: '下单组织',
43
+        name: 'orgName',
44
+        type: FieldTypes.Text,
45
+        value: data.orgName,
46
+      },
47
+      {
48
+        label: '下单人',
49
+        name: 'orderer',
50
+        value: data.orderer,
51
+        type: FieldTypes.Text,
52
+      },
53
+      {
54
+        label: '联系方式',
55
+        name: 'phone',
56
+        value: data.phone,
57
+        type: FieldTypes.Text,
58
+      },
59
+      {
60
+        label: '下单时间',
61
+        name: 'createDate',
62
+        type: FieldTypes.DatePicker ,
63
+        value: data.createDate != null ? moment(data.createDate, 'YYYY-MM-DD') : null,
64
+      },
65
+      {
66
+        label: '需求单状态',
67
+        name: 'demandStatus',
68
+        value: data.demandStatus+'',
69
+        render: <Select style={{ width: '180px' }} placeholder="需求单状态">
70
+                  <Select.Option value="1">已提交</Select.Option>
71
+                  <Select.Option value="2">处理中</Select.Option>
72
+                  <Select.Option value="3">已交付</Select.Option>
73
+                  <Select.Option value="4">作废</Select.Option>
74
+                </Select>,
75
+      },
76
+      {
77
+        label: '备注',
78
+        name: 'remark',
79
+        type: FieldTypes.Text,
80
+        value: data.remark,
81
+      },
82
+      {
83
+        label: '需求描述',
84
+        name: 'demandContent',
85
+        value: data.demandContent,
86
+        render: <Wangedit />
87
+      },
88
+    ]
89
+  
90
+     
91
+    const handleSubmit = (values) => {
92
+      if(demandId){
93
+          request({ ...apis.sample.update, urlData: { id: demandId }, data: { ...values }}).then((data) => {
94
+            cancelPage();
95
+          }).catch((err) => {
96
+            message.error(err.msg || err.message)
97
+          })
98
+        }
99
+    }
100
+  
101
+    const cancelPage = () => {
102
+      router.push({
103
+        pathname: '/sample/demand/list',
104
+      });
105
+    }
106
+  
107
+    return (
108
+      <XForm onSubmit={handleSubmit} onCancel={cancelPage} fields={fields}></XForm>
109
+    )
110
+  }
111
+  
112
+  const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
113
+  export default WrappedNormalLoginForm

+ 120
- 62
src/pages/sample/demand/index.jsx Ver fichero

@@ -1,6 +1,6 @@
1 1
 import React, { useState, useEffect } from 'react';
2 2
 import { PageHeaderWrapper } from '@ant-design/pro-layout';
3
-import { Form, Pagination, Card, Button, Icon, Tooltip, message,   notification, Modal, Table } from 'antd';
3
+import { Form, Pagination, Card, Button, Icon, Tooltip, message,   notification, Modal, Table, Select, Input, DatePicker } from 'antd';
4 4
 import router from 'umi/router';
5 5
 import moment from 'moment';
6 6
 import className from 'classnames';
@@ -10,11 +10,12 @@ import { fetch, apis } from '../../../utils/request';
10 10
 import request from '../../../utils/request';
11 11
 import AuthButton from '@/components/AuthButton';
12 12
 
13
-
13
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
14 14
 
15 15
 function header(props) {
16 16
   // 获取初始化数据
17 17
   const [ data, setData ] = useState({})
18
+  const [demandIdList, setDemandIdList] = useState([])
18 19
 
19 20
   useEffect(() => {
20 21
     getList({ pageNum: 1, pageSize: 10 });
@@ -22,7 +23,7 @@ function header(props) {
22 23
 
23 24
   // 查询列表
24 25
   const getList = (params) => {
25
-    request({ ...apis.channel.list, params: { ...params } }).then((data) => {
26
+    request({ ...apis.sample.list, params: { ...params } }).then((data) => {
26 27
         console.log(data)
27 28
         setData(data)
28 29
     })
@@ -34,7 +35,16 @@ function header(props) {
34 35
     e.preventDefault();
35 36
     props.form.validateFields((err, values) => {
36 37
       if (!err) {
37
-        getList({ pageNum: 1, pageSize: 10, ...values })
38
+        let {createDate, ...submitValue} = values
39
+        if(null != createDate && createDate.length > 0){
40
+          const [startCreateDate, endCreateDate] = createDate
41
+          submitValue.startCreateDate = moment(startCreateDate).format('YYYY-MM-DD');
42
+          submitValue.endCreateDate = moment(endCreateDate).format('YYYY-MM-DD');
43
+        }else{
44
+          submitValue.startCreateDate = null
45
+          submitValue.endCreateDate = null
46
+        }
47
+        getList({ pageNum: 1, pageSize: 10, ...submitValue })
38 48
       }
39 49
     });
40 50
   }
@@ -43,11 +53,18 @@ function header(props) {
43 53
     getList({ pageNum: pageNumber, pageSize: 10 })
44 54
   }
45 55
 
56
+  const rowSelection = {
57
+    onChange: (selectedRowKeys, selectedRows) => {
58
+      console.log('selectedRowKeys:', selectedRowKeys, 'selectedRows: ', selectedRows);
59
+      setDemandIdList(selectedRows)
60
+    },
61
+  };
62
+
46 63
 
47 64
   // 跳转到编辑资讯
48
-  const toEditNews = (id) => () => {
65
+  const toEditDemand = (id) => () => {
49 66
     router.push({
50
-      pathname: '/channel/edit',
67
+      pathname: '/sample/demand/edit',
51 68
       query: {
52 69
         id
53 70
       },
@@ -55,31 +72,25 @@ function header(props) {
55 72
   }
56 73
 
57 74
   
58
-  const changeNewsStatus = (row, newsId) => () => {
59
-    const title = row.status === 0 ? '确定启用吗': '停用后,此账号将无法登录渠道代理商后台'
75
+  const changeStatus = () => {
76
+    if(demandIdList.length < 1){
77
+      message.error('请先选择要删除的数据!')
78
+      return
79
+    }
80
+    const title = '确认将所选的' + demandIdList.length + '条数据删除?可删除条件:需求单阶段 为 作废。'
60 81
     Modal.confirm({
61 82
       title: title,
62 83
       okText: '确认',
63 84
       cancelText: '取消',
64 85
       onOk() {
65
-        if(row.status === 0){
66
-          request({ ...apis.channel.put, urlData: { id: newsId }, data: { ...row, status: 1 } }).then((data) => {
67
-            message.info('操作成功!')
68
-            getList({ pageNum: 1, pageSize: 10 });
69
-          }).catch((err) => {
70
-            console.log(err)
71
-            message.info(err.msg || err.message)
72
-          })
73
-        }else{
74
-          request({ ...apis.channel.put, urlData: { id: newsId }, data: { ...row, status: 0 } }).then((data) => {
75
-            message.info('操作成功!')
76
-            getList({ pageNum: 1, pageSize: 10 });
77
-          }).catch((err) => {
78
-            console.log(err)
79
-            message.info(err.msg || err.message)
80
-          })
81
-        }
82
-        
86
+        request({ ...apis.sample.put, data: { ids: demandIdList.map(x => x.demandId) } }).then((data) => {
87
+          const resultMessage = '操作成功,其中'+data.successNum+'条成功删除,'+data.failNum+'条非作废状态未删除。'
88
+          message.info(resultMessage)
89
+          getList({ pageNum: 1, pageSize: 10 });
90
+        }).catch((err) => {
91
+          console.log(err)
92
+          message.info(err.msg || err.message)
93
+        })
83 94
       }
84 95
     });
85 96
   }
@@ -91,45 +102,43 @@ function header(props) {
91 102
    */
92 103
   const columns = [
93 104
     {
94
-      title: '渠道代理',
95
-      dataIndex: 'channelProxyName',
96
-      key: 'channelProxyName',
105
+      title: '样例名',
106
+      dataIndex: 'sampleName',
107
+      key: 'sampleName',
97 108
       align: 'center',
98 109
     },
99 110
     {
100
-      title: '账号名',
101
-      dataIndex: 'userName',
102
-      key: 'userName',
111
+      title: '下单组织',
112
+      dataIndex: 'orgName',
113
+      key: 'orgName',
103 114
       align: 'center',
104
-      render: (x, row) => <span>{row.userName === null || row.userName === '' ? row.channelTel : row.userName}</span>,
105 115
     },
106 116
     {
107
-      title: '小程序总数',
108
-      dataIndex: 'appMaxNum',
109
-      key: 'appMaxNum',
117
+      title: '下单人',
118
+      dataIndex: 'orderer',
119
+      key: 'orderer',
110 120
       align: 'center',
111 121
 
112 122
     },
113 123
     {
114
-      title: '现有小程序',
115
-      dataIndex: 'appCurrentNum',
116
-      key: 'appCurrentNum',
124
+      title: '联系方式',
125
+      dataIndex: 'phone',
126
+      key: 'phone',
117 127
       align: 'center',
118
-      render: (appCurrentNum) => <span>{appCurrentNum === 0 || appCurrentNum == null ? 0 : appCurrentNum}</span>,
119 128
     },
120 129
     {
121
-      title: '服务到期时间',
122
-      dataIndex: 'expireDate',
123
-      key: 'expireDate',
130
+      title: '下单时间',
131
+      dataIndex: 'createDate',
132
+      key: 'createDate',
124 133
       align: 'center',
125
-      render: (x, row) => <><span>{`${moment(row.expireDate).format('YYYY-MM-DD')}`}</span></>,
134
+      render: (x, row) => <><span>{`${moment(row.createDate).format('YYYY-MM-DD')}`}</span></>,
126 135
     },
127 136
     {
128
-      title: '状态',
129
-      dataIndex: 'status',
130
-      key: 'status',
137
+      title: '需求单状态',
138
+      dataIndex: 'demandStatus',
139
+      key: 'demandStatus',
131 140
       align: 'center',
132
-      render: (status) => <span>{status === 1 ? '启动' : '停用'}</span>,
141
+      render: (demandStatus) => <span>{demandStatus === 1 ? '已提交' : demandStatus === 2 ? '处理中' : demandStatus === 3 ? '已交付' : demandStatus === 4 ? '作废' : ''}</span>,
133 142
     },
134 143
     {
135 144
       title: '操作',
@@ -137,18 +146,9 @@ function header(props) {
137 146
       key: 'handle',
138 147
       align: 'center',
139 148
       render: (x, row) => (
140
-        <>
141
-          <AuthButton name="admin.taNewsType.id.delete" noRight={null}>
142
-            <span style={{ color: '#EF273A', marginRight: '20px', cursor: 'pointer' }} onClick={changeNewsStatus(row, row.channelId)}>
143
-              {row.status == 1 ? '停用' : '启用'}<Icon type="shopping-cart" className={styles.shoppingCart} />
144
-            </span>
145
-          </AuthButton>
146
-          <AuthButton name="admin.taNewsType.id.put" noRight={null}>
147
-            <span style={{ color: '#FF925C', cursor: 'pointer' }} onClick={toEditNews(row.channelId)}>
148
-              编辑<Icon type="form" className={styles.edit} />
149
-            </span>
150
-          </AuthButton>
151
-        </>
149
+        <span style={{ color: '#FF925C', cursor: 'pointer' }} onClick={toEditDemand(row.demandId)}>
150
+          查看详情<Icon type="form" className={styles.edit} />
151
+        </span>
152 152
       ),
153 153
     },
154 154
   ];
@@ -161,10 +161,68 @@ function header(props) {
161 161
   return (
162 162
 
163 163
     <>
164
+    <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
165
+        <Form.Item>
166
+          {getFieldDecorator('sampleName')(
167
+            <Input
168
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
169
+              placeholder="样例名"
170
+            />,
171
+          )}
172
+        </Form.Item>
173
+        <Form.Item>
174
+          {getFieldDecorator('orgName')(
175
+            <Input
176
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
177
+              placeholder="下单组织"
178
+            />,
179
+          )}
180
+        </Form.Item>
181
+        <Form.Item>
182
+          {getFieldDecorator('orderer')(
183
+            <Input
184
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
185
+              placeholder="下单人"
186
+            />,
187
+          )}
188
+        </Form.Item>
189
+        <Form.Item>
190
+          {getFieldDecorator('phone')(
191
+            <Input
192
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
193
+              placeholder="联系方式"
194
+            />,
195
+          )}
196
+        </Form.Item>
197
+        <Form.Item>
198
+            <span style={{marginRight:'10px'}}>下单时间段:</span>
199
+                {getFieldDecorator('createDate')(
200
+                  <RangePicker placeholder={['开始时间','结束时间']} />
201
+                )}
202
+        </Form.Item>
203
+        <Form.Item>
204
+          {getFieldDecorator('demandStatus')(
205
+            <Select style={{ width: '180px' }} placeholder="需求单状态">
206
+              <Select.Option value="1">已提交</Select.Option>
207
+              <Select.Option value="2">处理中</Select.Option>
208
+              <Select.Option value="3">已交付</Select.Option>
209
+              <Select.Option value="4">作废</Select.Option>
210
+            </Select>,
211
+          )}
212
+        </Form.Item>
213
+        <Form.Item>
214
+          <Button type="primary" htmlType="submit" className={styles.searchBtn}>
215
+            搜索
216
+          </Button>
217
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
218
+              重置
219
+          </Button>
220
+        </Form.Item>
221
+      </Form>
164 222
       <AuthButton name="admin.taNewsType.post" noRight={null}>
165
-        <Button type="danger" className={styles.addBtn} onClick={toEditNews()}>新增</Button>
223
+        <Button type="danger" className={styles.addBtn} onClick={changeStatus}>删除</Button>
166 224
       </AuthButton>
167
-      <Table rowKey="newsType" dataSource={data.records} columns={columns} pagination={false} />
225
+      <Table rowSelection={rowSelection} rowKey="newsType" dataSource={data.records} columns={columns} pagination={false} />
168 226
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
169 227
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current}/>
170 228
       </div>

+ 22
- 0
src/services/apis.js Ver fichero

@@ -64,6 +64,28 @@ const apis = {
64 64
       action: 'channel',
65 65
     },
66 66
   },
67
+  sample: {
68
+    list: {
69
+      url: `${prefix}/taH5Demand`,
70
+      method: 'GET',
71
+      action: 'channel',
72
+    },
73
+    put: {
74
+      url: `${prefix}/taH5Demand/batch`,
75
+      method: 'PUT',
76
+      action: 'channel',
77
+    },
78
+    get: {
79
+      url: `${prefix}/taH5Demand/:id`,
80
+      method: 'GET',
81
+      action: 'channel',
82
+    },
83
+    update: {
84
+      url: `${prefix}/taH5Demand/update/:id`,
85
+      method: 'PUT',
86
+      action: 'channel',
87
+    },
88
+  },
67 89
   image: {
68 90
     uploadForAnt: {
69 91
       url: `${prefix}/antd/image`,