Browse Source

新需求

傅行帆 5 years ago
parent
commit
86a702d35a

+ 6
- 0
config/routes.js View File

@@ -49,6 +49,12 @@ export default [
49 49
                 name: 'H5样例',
50 50
                 component: './sample/h5/index',
51 51
               },
52
+              {
53
+                path: '/sample/h5/edit',
54
+                name: 'H5样例编辑',
55
+                hideInMenu: true,
56
+                component: './sample/h5/edit',
57
+              },
52 58
               {
53 59
                 path: '/sample/demand/list',
54 60
                 name: 'H5需求单',

+ 24
- 0
src/pages/sample/h5/components/H5Card.jsx View File

@@ -0,0 +1,24 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert, Card } from 'antd';
3
+import { FormattedMessage } from 'umi-plugin-react/locale';
4
+import router from 'umi/router';
5
+import apis from '../../../../services/apis';
6
+import request from '../../../../utils/request';
7
+import Wangedit from '../../../../components/Wangedit/Wangedit'
8
+import moment from 'moment';
9
+
10
+const { Meta } = Card
11
+
12
+const H5Card = props => {
13
+    return (
14
+    <Card
15
+      hoverable
16
+      style={{ width: 240 }}
17
+      cover={<img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" />}
18
+    >
19
+      <Meta title="Europe Street beat" description="www.instagram.com" />
20
+    </Card>
21
+    )
22
+  }
23
+ 
24
+  export default H5Card

+ 208
- 0
src/pages/sample/h5/components/SelectContact.jsx View File

@@ -0,0 +1,208 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Form, Select, Modal, Button, Table, Divider, Tag, Input,Row,Col,Icon,Pagination } from 'antd';
3
+import request from '../../../../utils/request';
4
+import apis from '../../../../services/apis';
5
+import styles from '../style.less';
6
+
7
+const { Column, ColumnGroup } = Table;
8
+const SelectContact = props => {
9
+
10
+  const [data, setData] = useState([]);
11
+  const [visible, setVisible] = useState(false);
12
+  const [group, setGroup] = useState({ groupId: undefined, groupName: '请选择' })
13
+  const [selectedData, setSelectedData ] = useState([]);
14
+
15
+  useEffect(() => {
16
+    if (props.value && props.value != selectedData) {
17
+      setSelectedData(props.value)
18
+    }
19
+  }, [props.value])
20
+
21
+  // 查询列表
22
+  const getList = (params) => {
23
+    request({ ...apis.contact.list, params: { ...params } }).then((data) => {
24
+        console.log(data)
25
+        setData(data)
26
+    })
27
+  }
28
+  
29
+  useEffect(() => {
30
+    getList({ pageNum: 1, pageSize: 10,})
31
+  }, []);
32
+
33
+  
34
+
35
+  const handleChange = val => {
36
+  }
37
+
38
+  const selectData = val => {
39
+    const list = selectedData.filter(x => x.contactId !== val.contactId).concat(val)
40
+    setSelectedData(list)
41
+    props.onSelected(list)
42
+    setVisible(false)
43
+  }
44
+
45
+  
46
+  // 提交事件
47
+  const handleSubmit = (e, props) => {
48
+    e.preventDefault();
49
+    e.stopPropagation();
50
+    props.form.validateFields((err, values) => {
51
+      if (!err) {
52
+        getList({ pageNum: 1, pageSize: 10, ...values })
53
+      }
54
+    });
55
+  }
56
+
57
+  function handleReset() {
58
+    props.form.resetFields();
59
+    getList({ pageNum: 1, pageSize: 10 })
60
+  }
61
+
62
+  const changePageNum = (pageNumber) => {
63
+    getList({ pageNum: pageNumber, pageSize: 10 })
64
+  }
65
+
66
+  const removeSelected = (val) => {
67
+    const list = selectedData.filter(x => x.contactId !== val.contactId)
68
+    setSelectedData(list)
69
+    props.onSelected(list)
70
+  }
71
+
72
+  const columns = [
73
+    {
74
+      title: '姓名',
75
+      dataIndex: 'contactName',
76
+      key: 'drainageId',
77
+      align: 'center',
78
+      ellipsis: true,
79
+      render: text => <a>{text}</a>,
80
+    },
81
+    {
82
+      title: '性别',
83
+      dataIndex: 'sex',
84
+      key: 'drainageId',
85
+      align: 'center',
86
+      ellipsis: true,
87
+      render: text => <a>{text}</a>,
88
+    },
89
+    {
90
+      title: '头像',
91
+      dataIndex: 'avatar',
92
+      key: 'drainageId',
93
+      align: 'center',
94
+      ellipsis: true,
95
+      render: text => <a>{text}</a>,
96
+    },
97
+    {
98
+      title: '固话',
99
+      dataIndex: 'telephone',
100
+      key: 'drainageId',
101
+      align: 'center',
102
+      ellipsis: true,
103
+      render: text => <a>{text}</a>,
104
+    },
105
+    {
106
+      title: '手机号',
107
+      dataIndex: 'phone',
108
+      key: 'drainageId',
109
+      align: 'center',
110
+      ellipsis: true,
111
+      render: text => <a>{text}</a>,
112
+    },
113
+    {
114
+      title: '内部岗位',
115
+      dataIndex: 'job',
116
+      key: 'drainageId',
117
+      align: 'center',
118
+      ellipsis: true,
119
+      render: text => <a>{text}</a>,
120
+    },
121
+    {
122
+      title: '操作',
123
+      align: 'center',
124
+      width: '20%',
125
+      render: (text, record) => (
126
+        <span>
127
+          <a onClick={() => selectData(record)} style={{ color: 'blue' }}>选择</a>
128
+        </span>
129
+      ),
130
+    },
131
+  ];
132
+
133
+  const { getFieldDecorator } = props.form
134
+
135
+  return (
136
+    <div>
137
+      <Row gutter={24}>
138
+        <Col span={2}><div onClick={() => setVisible(true)}>{group.groupName}</div></Col>
139
+        <Col span={16}><div>
140
+        {selectedData.map(x => {
141
+          return <Tag size="large" key={x.contactId} closable onClose={() => removeSelected(x)}>{x.contactName}</Tag>
142
+        })}
143
+      </div></Col>
144
+      </Row>     
145
+      
146
+      <Modal
147
+        title="请选择"
148
+        width="1200px"
149
+        visible={visible}
150
+        onCancel={() => setVisible(false)}
151
+        footer={[]}
152
+      >
153
+      
154
+        <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
155
+            <Form.Item>
156
+              {getFieldDecorator('contactName')(
157
+                <Input
158
+                  prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
159
+                  placeholder="姓名"
160
+                />,
161
+              )}
162
+            </Form.Item>
163
+            <Form.Item>
164
+              {getFieldDecorator('telephone')(
165
+                <Input
166
+                  prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
167
+                  placeholder="固话"
168
+                />,
169
+              )}
170
+            </Form.Item>
171
+            <Form.Item>
172
+              {getFieldDecorator('phone')(
173
+                <Input
174
+                  prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
175
+                  placeholder="手机号"
176
+                />,
177
+              )}
178
+            </Form.Item>
179
+            <Form.Item>
180
+              {getFieldDecorator('job')(
181
+                <Input
182
+                  prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
183
+                  placeholder="内部岗位"
184
+                />,
185
+              )}
186
+            </Form.Item>
187
+            <Form.Item>
188
+              <Button type="primary" htmlType="submit" className={styles.searchBtn}>
189
+                搜索
190
+              </Button>
191
+              <Button style={{ marginLeft: 8 }} onClick={handleReset}>
192
+                  重置
193
+              </Button>
194
+            </Form.Item>
195
+          </Form>
196
+    
197
+          <Table dataSource={data.records || []} columns={columns} pagination={false} />
198
+          <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
199
+            <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current}/>
200
+          </div>
201
+    
202
+      </Modal>
203
+    </div>
204
+  )
205
+}
206
+
207
+const WrappedRegistrationForm = Form.create()(SelectContact);
208
+export default WrappedRegistrationForm;

+ 169
- 0
src/pages/sample/h5/edit.jsx View File

@@ -0,0 +1,169 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Input, Menu, Dropdown, Button, Icon, message, Table, Divider, Tag, Select, Form, Alert, Radio } 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 ImageUpload from '../../../components/XForm/ImageUpload'
10
+import SelectContact from './components/SelectContact';
11
+import moment from 'moment';
12
+
13
+const formItemLayout = {
14
+  labelCol: {
15
+    xs: { span: 24 },
16
+    sm: { span: 2 },
17
+  },
18
+  wrapperCol: {
19
+    xs: { span: 24 },
20
+    sm: { span: 16 },
21
+  },
22
+};
23
+
24
+const header = props => {
25
+    const sampleId = props.location.query.id
26
+  
27
+    const [ data, setData ] = useState({})
28
+    const [typeState, setTypeState] = useState("rich")
29
+
30
+    if(sampleId){
31
+      useEffect(() => {
32
+        getH5Data(sampleId);
33
+      },[])
34
+  
35
+    // 查询列表
36
+    const getH5Data = (sampleId) => {
37
+      request({
38
+          ...apis.sample.get,
39
+          urlData: { id: sampleId }
40
+      }).then((data) => {
41
+        setData(data)
42
+      }).catch((err) => {
43
+        message.error(err.msg || err.message)
44
+      })
45
+    }
46
+    }
47
+     
48
+    const handleSubmit = (e) => {
49
+      e.preventDefault();
50
+      // e.stopPropagation();
51
+      props.form.validateFieldsAndScroll((err, values) => {
52
+        console.log(values,"valuesvaluesvaluesvaluesvaluesvaluesvalues")
53
+        debugger
54
+        if (!err) {
55
+          console.log(values,"h5Sample/addh5Sample/add")
56
+          if(sampleId){
57
+            request({ ...apis.sample.update, urlData: { id: sampleId }, data: { ...values }}).then((data) => {
58
+              cancelPage();
59
+            }).catch((err) => {
60
+              message.error(err.msg || err.message)
61
+            })
62
+          }else{
63
+            request({ ...apis.sample.addh5, data: { ...values }}).then((data) => {
64
+              cancelPage();
65
+            }).catch((err) => {
66
+              message.error(err.msg || err.message)
67
+            })
68
+          }
69
+        }
70
+      });
71
+      
72
+    }
73
+  
74
+    const cancelPage = () => {
75
+      router.push({
76
+        pathname: '/sample/h5/list',
77
+      });
78
+    }
79
+
80
+    function sampleTypeChange(e) {
81
+      setTypeState(e.target.value)
82
+    }
83
+  
84
+    const { getFieldDecorator } = props.form;
85
+    return (
86
+      <Form {...formItemLayout} onSubmit={handleSubmit}>
87
+            
88
+          <Form.Item label="样例名" >
89
+            {getFieldDecorator('sampleName',{
90
+              rules: [{ required: true, message: '请输入样例名' },
91
+              { max: 20, message: '样例名不超过20个字符' }],
92
+            })(<Input placeholder="H5活动主题或目的,如植树节引流活动"/>)}
93
+          </Form.Item>
94
+          <Form.Item label="样例体验链接" >
95
+            {getFieldDecorator('sampleTryLink',{
96
+              rules: [{ max: 300, message: '样例体验链接不超过300个字符' }],
97
+            })(<Input placeholder="若样例暂未发布到小程序,可直接粘贴网页链接"/>)}
98
+          </Form.Item>
99
+          <Form.Item label="样例体验二维码/小程序码" >
100
+            {getFieldDecorator('sampleTryCode')(
101
+              <ImageUpload />,
102
+            )}
103
+          </Form.Item>
104
+          <Form.Item label="封面图" help="建议尺寸:495*330px,比例:3:2,格式:jpg,大小:不超过300KB,用于样例列表封面">
105
+            {getFieldDecorator('coverImg', {
106
+              rules: [{ required: true, message: '请选择列表图' }],
107
+            })(
108
+              <ImageUpload />,
109
+            )}
110
+          </Form.Item>
111
+          <Form.Item label="方案/报价/技术联系人" >
112
+            {getFieldDecorator('taContactList',{
113
+              trigger: 'onSelected'
114
+            })(<SelectContact />)}
115
+          </Form.Item>
116
+          <Form.Item label="发布状态" >
117
+            {getFieldDecorator('status', {
118
+              initialValue: "1",
119
+            })(
120
+            <Select style={{ width: '180px' }}>
121
+              <Select.Option value="1">是</Select.Option>
122
+              <Select.Option value="0">否</Select.Option>
123
+            </Select>)}
124
+          </Form.Item>
125
+          <Form.Item label="权重" help="数值越大越靠前">
126
+            {getFieldDecorator('orderNo')(<Input />)}
127
+          </Form.Item>
128
+          <Form.Item label="标签" help="标签长度6个字,最多3个标签">
129
+            {getFieldDecorator('tags')(
130
+              <Select mode="tags" placeholder="输入后选中" style={{ width: '1016px' }}>
131
+
132
+              </Select>,
133
+            )}
134
+          </Form.Item>
135
+          <Form.Item label="样例类型">
136
+            {getFieldDecorator('sampleType',{
137
+              initialValue: "rich",
138
+            })(
139
+            <Radio.Group onChange={e => sampleTypeChange(e)}>
140
+              <Radio value="rich">富文本</Radio>
141
+              <Radio value="link">外部链接</Radio>
142
+            </Radio.Group>,
143
+            )}
144
+          </Form.Item>
145
+          {typeState === 'link' && <Form.Item label="外部链接">
146
+            {getFieldDecorator('sampleContentLink',{
147
+              rules: [{ max: 300, message: '外部链接不超过300个字符' }],
148
+            })(<Input placeholder="填写外部链接,如公众号链接或135编辑器生成的页面链接" />)}
149
+          </Form.Item>}
150
+          {typeState === 'rich' && <Form.Item label="样例内容" >
151
+            {getFieldDecorator('sampleContent')(
152
+              <Wangedit />,
153
+            )}
154
+          </Form.Item> }
155
+          <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
156
+            <Button type="primary" htmlType="submit">
157
+                确定
158
+            </Button>
159
+            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
160
+            <Button onClick={() => router.go(-1)}>
161
+                取消
162
+            </Button>
163
+          </Form.Item>
164
+        </Form>
165
+    )
166
+  }
167
+  
168
+  const WrappedNormalLoginForm = Form.create({ name: 'header' })(header);
169
+  export default WrappedNormalLoginForm

+ 71
- 78
src/pages/sample/h5/index.jsx View File

@@ -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';
@@ -9,8 +9,9 @@ import styles from './style.less';
9 9
 import { fetch, apis } from '../../../utils/request';
10 10
 import request from '../../../utils/request';
11 11
 import AuthButton from '@/components/AuthButton';
12
+import H5Card from './components/H5Card';
12 13
 
13
-
14
+const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
14 15
 
15 16
 function header(props) {
16 17
   // 获取初始化数据
@@ -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.h5list, params: { ...params } }).then((data) => {
26 27
         console.log(data)
27 28
         setData(data)
28 29
     })
@@ -45,9 +46,9 @@ function header(props) {
45 46
 
46 47
 
47 48
   // 跳转到编辑资讯
48
-  const toEditNews = (id) => () => {
49
+  const toEditH5 = (id) => () => {
49 50
     router.push({
50
-      pathname: '/channel/edit',
51
+      pathname: '/sample/h5/edit',
51 52
       query: {
52 53
         id
53 54
       },
@@ -83,75 +84,7 @@ function header(props) {
83 84
       }
84 85
     });
85 86
   }
86
-  /**
87
-   *
88
-   *
89
-   * @param {*} props
90
-   * @returns
91
-   */
92
-  const columns = [
93
-    {
94
-      title: '渠道代理',
95
-      dataIndex: 'channelProxyName',
96
-      key: 'channelProxyName',
97
-      align: 'center',
98
-    },
99
-    {
100
-      title: '账号名',
101
-      dataIndex: 'userName',
102
-      key: 'userName',
103
-      align: 'center',
104
-      render: (x, row) => <span>{row.userName === null || row.userName === '' ? row.channelTel : row.userName}</span>,
105
-    },
106
-    {
107
-      title: '小程序总数',
108
-      dataIndex: 'appMaxNum',
109
-      key: 'appMaxNum',
110
-      align: 'center',
111
-
112
-    },
113
-    {
114
-      title: '现有小程序',
115
-      dataIndex: 'appCurrentNum',
116
-      key: 'appCurrentNum',
117
-      align: 'center',
118
-      render: (appCurrentNum) => <span>{appCurrentNum === 0 || appCurrentNum == null ? 0 : appCurrentNum}</span>,
119
-    },
120
-    {
121
-      title: '服务到期时间',
122
-      dataIndex: 'expireDate',
123
-      key: 'expireDate',
124
-      align: 'center',
125
-      render: (x, row) => <><span>{`${moment(row.expireDate).format('YYYY-MM-DD')}`}</span></>,
126
-    },
127
-    {
128
-      title: '状态',
129
-      dataIndex: 'status',
130
-      key: 'status',
131
-      align: 'center',
132
-      render: (status) => <span>{status === 1 ? '启动' : '停用'}</span>,
133
-    },
134
-    {
135
-      title: '操作',
136
-      dataIndex: 'handle',
137
-      key: 'handle',
138
-      align: 'center',
139
-      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
-        </>
152
-      ),
153
-    },
154
-  ];
87
+   
155 88
   function handleReset() {
156 89
     props.form.resetFields();
157 90
     getList({ pageNum: 1, pageSize: 10 })
@@ -161,10 +94,70 @@ function header(props) {
161 94
   return (
162 95
 
163 96
     <>
164
-      <AuthButton name="admin.taNewsType.post" noRight={null}>
165
-        <Button type="danger" className={styles.addBtn} onClick={toEditNews()}>新增</Button>
166
-      </AuthButton>
167
-      <Table rowKey="newsType" dataSource={data.records} columns={columns} pagination={false} />
97
+    <Form layout="inline" onSubmit={e => handleSubmit(e, props)}>
98
+        <Form.Item>
99
+          {getFieldDecorator('sampleName')(
100
+            <Input
101
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
102
+              placeholder="样例名"
103
+            />,
104
+          )}
105
+        </Form.Item>
106
+        <Form.Item>
107
+          {getFieldDecorator('orgName')(
108
+            <Input
109
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
110
+              placeholder="下单组织"
111
+            />,
112
+          )}
113
+        </Form.Item>
114
+        <Form.Item>
115
+          {getFieldDecorator('orderer')(
116
+            <Input
117
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
118
+              placeholder="下单人"
119
+            />,
120
+          )}
121
+        </Form.Item>
122
+        <Form.Item>
123
+          {getFieldDecorator('phone')(
124
+            <Input
125
+              prefix={<Icon type="text" style={{ color: 'rgba(0,0,0,.25)' }} />}
126
+              placeholder="联系方式"
127
+            />,
128
+          )}
129
+        </Form.Item>
130
+        <Form.Item>
131
+            <span style={{marginRight:'10px'}}>下单时间段:</span>
132
+                {getFieldDecorator('createDate')(
133
+                  <RangePicker placeholder={['开始时间','结束时间']} />
134
+                )}
135
+        </Form.Item>
136
+        <Form.Item>
137
+          {getFieldDecorator('demandStatus')(
138
+            <Select style={{ width: '180px' }} placeholder="需求单状态">
139
+              <Select.Option value="1">已提交</Select.Option>
140
+              <Select.Option value="2">处理中</Select.Option>
141
+              <Select.Option value="3">已交付</Select.Option>
142
+              <Select.Option value="4">作废</Select.Option>
143
+            </Select>,
144
+          )}
145
+        </Form.Item>
146
+        <Form.Item>
147
+          <Button type="primary" htmlType="submit" className={styles.searchBtn}>
148
+            搜索
149
+          </Button>
150
+          <Button style={{ marginLeft: 8 }} onClick={handleReset}>
151
+              重置
152
+          </Button>
153
+        </Form.Item>
154
+      </Form>
155
+      
156
+      <Button type="danger" className={styles.addBtn} onClick={toEditH5()}>新增</Button>
157
+ 
158
+      {(data.records || []).map(x => (
159
+          <H5Card />
160
+        ))}
168 161
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
169 162
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} current={data.current}/>
170 163
       </div>

+ 17
- 0
src/services/apis.js View File

@@ -85,6 +85,23 @@ const apis = {
85 85
       method: 'PUT',
86 86
       action: 'channel',
87 87
     },
88
+    h5list: {
89
+      url: `${prefix}/h5Sample/list`,
90
+      method: 'GET',
91
+      action: 'channel',
92
+    },
93
+    addh5: {
94
+      url: `${prefix}/h5Sample/add`,
95
+      method: 'POST',
96
+      action: 'channel',
97
+    },
98
+  },
99
+  contact: {
100
+    list: {
101
+      url: `${prefix}/taContact`,
102
+      method: 'GET',
103
+      action: 'channel',
104
+    },
88 105
   },
89 106
   image: {
90 107
     uploadForAnt: {