Pārlūkot izejas kodu

Merge branch 'master' of http://git.ycjcjy.com/marketing/pc-admin into master

zlisen 4 gadus atpakaļ
vecāks
revīzija
1f77a8ff81

+ 6
- 1
config/routes.js Parādīt failu

@@ -115,7 +115,12 @@ export default [
115 115
                 component: './customer/customerlist/publicCustomerDetail',
116 116
               },
117 117
 
118
-              
118
+              {
119
+                path: '/building/add',
120
+                name: '项目维护',
121
+                component: './building/Edit',
122
+                hideInMenu: true,
123
+              },
119 124
             ],
120 125
           },
121 126
           {

+ 2
- 2
src/components/XForm/FileUpload.jsx Parādīt failu

@@ -7,7 +7,7 @@ import { uploaderProps } from '../../utils/upload';
7 7
  * size  参数限制可以上传多少个文件
8 8
  * @param { value, size } props
9 9
  */
10
-function fileUpload(props) {
10
+function fileUpload(props, ref) {
11 11
 
12 12
   const { value } = props
13 13
   // console.log('fileUploadProps: ', props)
@@ -81,4 +81,4 @@ function fileUpload(props) {
81 81
   )
82 82
 }
83 83
 
84
-export default fileUpload
84
+export default React.forwardRef(fileUpload)

+ 96
- 0
src/pages/building/Edit/Basic.jsx Parādīt failu

@@ -0,0 +1,96 @@
1
+import React from 'react'
2
+import { Form, Input, notification, Select } from 'antd'
3
+import FileUpload from '@/components/XForm/FileUpload';
4
+import BuildingType from './components/BuildingTypeSelect'
5
+import { formItemLayout } from './utils'
6
+
7
+const Item = Form.Item
8
+
9
+const BuildingBasic = (props) => {
10
+  const { form } = props;
11
+  const { getFieldDecorator } = form;
12
+
13
+  
14
+  // 视频文件上传前 回调
15
+  const fileUploadBeforeUpload = (file, fileList) => {
16
+    return new Promise((resolve, reject) => {
17
+      if (file.type === 'video/mp4' || file.type === '.mp4') {
18
+          // setVideoImage(true)
19
+          resolve(file)
20
+      } else {
21
+        notification.error({ message: '项目视频,仅支持MP4格式' })
22
+        reject()
23
+      }
24
+    })
25
+  }
26
+
27
+  return (
28
+    <Form {...formItemLayout}>
29
+      <Item label="项目Id" style={{ display: 'none' }}>
30
+        {getFieldDecorator('buildingId')(<Input disabled />)}
31
+      </Item>
32
+      <Item label="楼盘编号" >
33
+        {getFieldDecorator('code', {
34
+          rules: [{ required: true, message: '请输入楼盘编号' }],
35
+        })(<Input />)}
36
+      </Item>
37
+      <Item label="楼盘名称" >
38
+        {getFieldDecorator('buildingName', {
39
+          rules: [{ required: true, message: '请输入楼盘名' }],
40
+        })(<Input />)}
41
+      </Item>
42
+      <Form.Item label="项目类型">
43
+        {getFieldDecorator('buildingProjectType', {
44
+          rules: [{ required: true, message: '请选择项目类型' }],
45
+        })(<BuildingType />)}
46
+      </Form.Item>
47
+      <Form.Item label="列表均价" help="项目列表展示价格,示例:约10000元/㎡、约1000万元/套起">
48
+        {getFieldDecorator('price')(<Input />)}
49
+      </Form.Item>
50
+      <Form.Item label="开盘时间" >
51
+        {getFieldDecorator('openingDate')(<Input placeholder="预计xxxx年xx月开盘" />)}
52
+      </Form.Item>
53
+      <Form.Item label="电话" >
54
+        {getFieldDecorator('tel', {
55
+          rules: [
56
+            {
57
+              pattern: new RegExp('^[0-9]*$'),
58
+              message: '请输入正确的电话号码',
59
+            },
60
+          ],
61
+        })(<Input placeholder="手机或者座机号码" />)}
62
+      </Form.Item>
63
+      <Form.Item label="项目说明" >
64
+        {getFieldDecorator('dynamic')(<Input placeholder="项目动态等,不超过30个字" maxLength={30}/>)}
65
+      </Form.Item>
66
+      <Form.Item label="物业类型" >
67
+        {getFieldDecorator('propertyType')(<Input />)}
68
+      </Form.Item>
69
+      <Form.Item label="销售状态" >
70
+        {getFieldDecorator('marketStatus', {
71
+          rules: [{ required: true, message: '请选择销售状态' }],
72
+        })(
73
+          <Select placeholder="销售状态" style={{ width: '100%' }}>
74
+            <Select.Option value="待售">待售</Select.Option>
75
+            <Select.Option value="在售">在售</Select.Option>
76
+            <Select.Option value="售罄">售罄</Select.Option>
77
+            <Select.Option value="在租">在租</Select.Option>
78
+          </Select>,
79
+        )}
80
+      </Form.Item>
81
+      <Form.Item label="项目标签" >
82
+        {getFieldDecorator('tag')(
83
+          <Select mode="tags" placeholder="输入后选中" style={{ width: '100%' }} />
84
+        )}
85
+      </Form.Item>
86
+      <Form.Item label="项目视频" help="视频仅支持mp4格式,建议尺寸:750*600,比例5:4,用于楼盘详情">
87
+        {getFieldDecorator('videoUrl')(
88
+          <FileUpload accept=".mp4" beforeUpload={fileUploadBeforeUpload} label="上传视频" size={1} />,
89
+        )}
90
+      </Form.Item>
91
+
92
+    </Form>
93
+  )
94
+}
95
+
96
+export default Form.create({ onValuesChange: console.log })(BuildingBasic)

+ 96
- 0
src/pages/building/Edit/components/BuildingTypeDetail.jsx Parādīt failu

@@ -0,0 +1,96 @@
1
+import React, { useState } from 'react'
2
+import { Button, Drawer, Form, Radio, Input, Select } from 'antd'
3
+import { formItemLayout } from '../utils'
4
+import styles from '../style.less'
5
+
6
+const Item = Form.Item
7
+
8
+const priceUnit = {
9
+  average: '元/㎡',
10
+  total: '万元/套',
11
+  lease: '元/㎡/天',
12
+}
13
+
14
+const noBorderInput = {
15
+  width: '30px',
16
+  borderLeft: 0,
17
+  pointerEvents: 'none',
18
+  backgroundColor: '#fff',
19
+}
20
+
21
+const BuildingTypeDetail = (props) => {
22
+  const { title, dataset, form, visible, onClose, onSubmit } = props
23
+  const { getFieldDecorator, validateFieldsAndScroll } = form
24
+  const [priceType, setPriceType] = useState()
25
+
26
+  const handleSubmit = () => {
27
+    validateFieldsAndScroll((err, values) => {
28
+      if (err) {
29
+        console.error(err);
30
+        return;
31
+      };
32
+
33
+      const data = {
34
+        ...values,
35
+        ...dataset || {},
36
+      }
37
+
38
+      onSubmit(data)
39
+    })
40
+  }
41
+
42
+  return (
43
+    <Drawer
44
+      width={600}
45
+      title={title} 
46
+      visible={visible}
47
+      onClose={onClose}
48
+      bodyStyle={{ paddingBottom: 80 }}
49
+      >
50
+      <Form>
51
+        <Item label="价格类型" {...formItemLayout}>
52
+          {getFieldDecorator('priceType')(
53
+            <Radio.Group onChange={({target}) => setPriceType(target.value)}>
54
+              <Radio value="average">均价</Radio>
55
+              <Radio value="total">总价</Radio>
56
+              <Radio value="lease">租赁价</Radio>
57
+            </Radio.Group>
58
+          )}
59
+        </Item>
60
+        <Item label="价格区间" help='最高价与最低价一致时,只展示一个' {...formItemLayout}>
61
+          <Input.Group compact>
62
+            {getFieldDecorator('startPrice')(<Input placeholder="最低价" style={{width: 'calc(50% - 50px)'}} />)}
63
+            {<Input style={{...noBorderInput, borderRight: 0}} placeholder="~" disabled />}
64
+            {getFieldDecorator('endPrice')(
65
+              <Input placeholder="最高价" style={{width: 'calc(50% - 60px)', borderLeft: 0, borderRight: 0}} />
66
+              )}
67
+            {<Input style={{...noBorderInput, width: '80px', textAlign: 'right'}} placeholder={priceUnit[priceType]} disabled />}
68
+          </Input.Group>
69
+        </Item>
70
+        <Item label="销售状态" {...formItemLayout}>
71
+          {getFieldDecorator('marketStatus')(
72
+            <Select placeholder="销售状态">
73
+              <Select.Option value="待售">待售</Select.Option>
74
+              <Select.Option value="在售">在售</Select.Option>
75
+              <Select.Option value="售罄">售罄</Select.Option>
76
+              <Select.Option value="在租">在租</Select.Option>
77
+            </Select>,
78
+          )}
79
+        </Item>
80
+        <Item label="装修标准" {...formItemLayout}>
81
+          {getFieldDecorator('decoration')(<Input />)}
82
+        </Item>
83
+        <Item label="产权年限" {...formItemLayout}>
84
+          {getFieldDecorator('rightsYear', {
85
+            initialValue: 70,
86
+          })(<Input />)}
87
+        </Item>
88
+      </Form>
89
+      <div className={styles['drawer-form-action']}>
90
+        <Button type="primary" onClick={handleSubmit}>确定</Button>
91
+      </div>
92
+    </Drawer>
93
+  )
94
+}
95
+
96
+export default Form.create()(BuildingTypeDetail)

+ 104
- 0
src/pages/building/Edit/components/BuildingTypeSelect.jsx Parādīt failu

@@ -0,0 +1,104 @@
1
+import React, { useState, useEffect } from 'react'
2
+import { Button, Icon, Checkbox, Card, notification } from 'antd'
3
+import BuildingTypeDetail from './BuildingTypeDetail'
4
+import request, { apis } from '@/utils/request'
5
+
6
+const gridStyle = {
7
+  width: '25%',
8
+  // textAlign: 'center',
9
+};
10
+
11
+export default React.forwardRef((props, ref) => {
12
+  const {value, onChange} = props;
13
+  const [showDrawer, setShowDrawer] = useState(false)
14
+  const [curRow, setCurRow] = useState()
15
+  const [curBuildingType, setBuildingType] = useState()
16
+  const [typeList, setTypeList] = useState([])
17
+
18
+  const handleChange = (buildingType) => (e) => {
19
+    const current = (value || []).filter((it) => it.buildingTypeId === buildingType.buildingTypeId)[0] || {buildingTypeId: buildingType.buildingTypeId}
20
+    const checked = e.target.checked
21
+
22
+    // 打开 form 表单
23
+    if (checked) {
24
+      setCurRow(current)
25
+      setBuildingType(buildingType)
26
+      setShowDrawer(true)
27
+    } else {
28
+      // 取消选择
29
+      const data = (value || []).filter((it) => it.buildingTypeId !== buildingType.buildingTypeId)
30
+      onChange(data)
31
+    }
32
+  }
33
+
34
+  const handleClick = (buildingType) => () => {
35
+    const current = (value || []).filter((it) => it.buildingTypeId === buildingType.buildingTypeId)[0] || {buildingTypeId: buildingType.buildingTypeId}
36
+    
37
+    setCurRow(current)
38
+    setBuildingType(buildingType)
39
+    setShowDrawer(true)
40
+  }
41
+
42
+  const handleClose = () => {
43
+    setCurRow()
44
+    setBuildingType()
45
+    setShowDrawer(false)
46
+  }
47
+
48
+  const handleSubmit = (val) => {
49
+    const data = []
50
+    let found = false
51
+    for (let it of (value || [])) {
52
+      if (it.buildingTypeId === val.buildingTypeId) {
53
+        found = true
54
+        data.push(val)
55
+      } else {
56
+        data.push(it)
57
+      }
58
+    }
59
+
60
+    if (!found) {
61
+      data.push(val)
62
+    }
63
+
64
+    onChange(data)
65
+    setShowDrawer(false)
66
+  }
67
+
68
+  useEffect(() => {
69
+    // 请求类型列表
70
+    request({ ...apis.buildingType.getList, params: { pageNum: 1, pageSize: 999 } }).then(res => {
71
+      setTypeList(res.records)
72
+    }).catch((err) => {
73
+      notification.error({ message: err.message })
74
+    })
75
+  }, [])
76
+
77
+  return (
78
+    <Card bordered={false}>
79
+      {
80
+        typeList.map((it) => {
81
+          const checked = !!(value || []).filter((x) => it.buildingTypeId === x.buildingTypeId)[0]
82
+          return (
83
+            <Card.Grid style={gridStyle} key={it.buildingTypeId} hoverable={false}>
84
+              <Checkbox
85
+                checked={checked}
86
+                onChange={handleChange(it)}
87
+              >
88
+                {it.buildingTypeName}
89
+              </Checkbox>
90
+              {checked && <a href="#" onClick={handleClick(it)}><Icon type="edit" /></a>}              
91
+            </Card.Grid>
92
+          )
93
+        })
94
+      }
95
+      <BuildingTypeDetail
96
+        title={curBuildingType?.buildingTypeName}
97
+        dataset={curRow}
98
+        visible={showDrawer}
99
+        onClose={handleClose}
100
+        onSubmit={handleSubmit}
101
+      />
102
+    </Card>
103
+  )
104
+})

+ 38
- 0
src/pages/building/Edit/index.jsx Parādīt failu

@@ -0,0 +1,38 @@
1
+import React from 'react'
2
+import { Tabs, Card } from 'antd'
3
+import Basic from './Basic'
4
+import styles from './style.less'
5
+
6
+const { TabPane } = Tabs
7
+
8
+export default (props) => {
9
+  return (
10
+    <Card>
11
+      <Tabs defaultActiveKey="1">
12
+        <TabPane tab="基础信息" key="1">
13
+          <div className={styles['tab-wrapper']} style={{maxWidth: 1000}}>
14
+            <Basic />
15
+          </div>
16
+        </TabPane>
17
+        <TabPane tab="户型设置" key="2">
18
+          Content of Tab Pane 2
19
+        </TabPane>
20
+        <TabPane tab="项目相册" key="3">
21
+          Content of Tab Pane 3
22
+        </TabPane>
23
+        <TabPane tab="全景照片" key="4">
24
+          Content of Tab Pane 3
25
+        </TabPane>
26
+        <TabPane tab="海报图片" key="5">
27
+          Content of Tab Pane 3
28
+        </TabPane>
29
+        <TabPane tab="分享设置" key="6">
30
+          Content of Tab Pane 3
31
+        </TabPane>
32
+        <TabPane tab="渠道设置" key="7">
33
+          Content of Tab Pane 3
34
+        </TabPane>
35
+      </Tabs>
36
+    </Card>
37
+  )
38
+}

+ 15
- 0
src/pages/building/Edit/style.less Parādīt failu

@@ -0,0 +1,15 @@
1
+
2
+.tab-wrapper {
3
+  padding-top: 1em;
4
+}
5
+
6
+.drawer-form-action {
7
+  position: absolute;
8
+  right: 0;
9
+  bottom: 0;
10
+  width: 100%;
11
+  border-top: 1px solid #e9e9e9;
12
+  padding: 10px 16px;
13
+  background: #fff;
14
+  text-align: right;
15
+}

+ 11
- 0
src/pages/building/Edit/utils.js Parādīt failu

@@ -0,0 +1,11 @@
1
+
2
+export const formItemLayout = {
3
+  labelCol: {
4
+    xs: { span: 24 },
5
+    sm: { span: 3 },
6
+  },
7
+  wrapperCol: {
8
+    xs: { span: 24 },
9
+    sm: { span: 19 },
10
+  },
11
+}

+ 3
- 1
src/pages/building/List/index.jsx Parādīt failu

@@ -1,6 +1,7 @@
1 1
 import React, { useMemo, useRef, useCallback, useState } from 'react'
2 2
 // import { PageHeaderWrapper } from '@ant-design/pro-layout'
3 3
 import { Button, notification, Spin } from 'antd'
4
+import { router } from 'umi'
4 5
 import QueryTable from '@/components/QueryTable'
5 6
 import request from '@/utils/request'
6 7
 import apis from '@/services/apis'
@@ -45,7 +46,8 @@ export default (props) => {
45 46
   }, [page])
46 47
 
47 48
   const actionRender = () => {
48
-    return <Button type="primary" icon="plus">新增</Button>
49
+    const gotoAdd = () => router.push('/building/add')
50
+    return <Button type="primary" icon="plus" onClick={gotoAdd}>新增</Button>
49 51
   }
50 52
 
51 53
   return (

+ 1
- 1
src/pages/building/List/tableColumns.js Parādīt failu

@@ -34,7 +34,7 @@ export default ({page, onPublish, onDelete}) => [
34 34
         <Button
35 35
           type="link"
36 36
           onClick={() => router.push({
37
-            pathname: '/building/list/add',
37
+            pathname: '/building/add',
38 38
             query: {
39 39
               id: row.buildingId,
40 40
             },

+ 6
- 6
src/utils/upload.js Parādīt failu

@@ -1,7 +1,7 @@
1 1
 import { fetch, apis } from './request';
2
-// import mixStr from './mixStr';
2
+import mixStr from './mixStr';
3 3
 
4
-// const getToken = () => mixStr(window.localStorage.getItem('test-foobar'))
4
+const getToken = () => mixStr(window.localStorage.getItem('test-foobar'))
5 5
 
6 6
 const uploadImage = fetch(apis.image.upload)
7 7
 
@@ -13,13 +13,13 @@ const uploaderProps = {
13 13
   //   Authorization: `Bearer ${getToken()}`
14 14
   // },
15 15
   customRequest({
16
-    // action,
16
+    action,
17 17
     file,
18
-    // headers,
18
+    headers,
19 19
     onError,
20
-    // onProgress,
20
+    onProgress,
21 21
     onSuccess,
22
-    // withCredentials,
22
+    withCredentials,
23 23
   }) {
24 24
     const data = new FormData()
25 25
     data.append('file', file)