魏熙美 5 年前
父节点
当前提交
884dd86cca

+ 57
- 0
src/components/XForm/FileUpload.jsx 查看文件

1
+import React, { useState, useEffect } from 'react'
2
+import { Upload, Button, Icon } from 'antd';
3
+import { uploaderProps } from '../../utils/upload';
4
+
5
+function fileUpload(props) {
6
+
7
+  const { value } = props
8
+  console.log('fileUploadProps: ', props)
9
+  // eslint-disable-next-line react-hooks/rules-of-hooks
10
+  const [defaultFileList, setDefaultFileList] = useState([])
11
+
12
+  // eslint-disable-next-line react-hooks/rules-of-hooks
13
+  useEffect(() => {
14
+    setDefaultValue()
15
+  }, [props.value]);
16
+
17
+
18
+  function getFileList() {
19
+    return (value || []).map((img, inx) => ({ uid: inx, url: img, name: img.substring(img.lastIndexOf('/') + 1, img.length), status: 'done' }))
20
+  }
21
+
22
+  function setDefaultValue() {
23
+    if (!value) {
24
+      return;
25
+    }
26
+
27
+    setDefaultFileList(getFileList())
28
+  }
29
+
30
+  function onFileChange({ file, fileList }) {
31
+    setDefaultFileList(fileList)
32
+    if (file.status === 'uploading') {
33
+      return
34
+    }
35
+
36
+    if (file.status === 'done') {
37
+      props.onChange([].concat(file.response))
38
+    }
39
+  }
40
+
41
+  return (
42
+    <>
43
+      <Upload
44
+        { ...uploaderProps }
45
+        {...props}
46
+        onChange={onFileChange}
47
+        fileList={defaultFileList}
48
+      >
49
+        <Button>
50
+          <Icon type="upload" /> {props.label}
51
+        </Button>
52
+      </Upload>
53
+    </>
54
+  )
55
+}
56
+
57
+export default fileUpload

+ 4
- 2
src/pages/building/list/add/components/amap.jsx 查看文件

92
       if (value) {
92
       if (value) {
93
         const temp = value.split(',')
93
         const temp = value.split(',')
94
         this.setState({ markerPosition: { longitude: temp[1], latitude: temp[0] } }, () => {
94
         this.setState({ markerPosition: { longitude: temp[1], latitude: temp[0] } }, () => {
95
-          // 需要在设置坐标成功后,重新设置 缩放级别
96
-          this.mapInstance.setZoom(15)
95
+          if (this.mapInstance) {
96
+            // 需要在设置坐标成功后,重新设置 缩放级别
97
+            this.mapInstance.setZoom(15)
98
+          }
97
         })
99
         })
98
       }
100
       }
99
     }
101
     }

+ 47
- 2
src/pages/building/list/add/components/base.jsx 查看文件

12
 import Amap from './amap'
12
 import Amap from './amap'
13
 import BudildingProjectType from './buildingProjectType'
13
 import BudildingProjectType from './buildingProjectType'
14
 import SelectCity from '../../../../../components/SelectButton/CitySelect'
14
 import SelectCity from '../../../../../components/SelectButton/CitySelect'
15
+import FileUpload from '@/components/XForm/FileUpload';
15
 
16
 
16
 const { Option } = Select
17
 const { Option } = Select
17
 const { TabPane } = Tabs;
18
 const { TabPane } = Tabs;
66
       }
67
       }
67
 
68
 
68
       res.avatarImage = res.buildingImg.map(item => item.url)
69
       res.avatarImage = res.buildingImg.map(item => item.url)
70
+      res.listImage = res.buildingListImg.map(item => item.url)
69
       res.mapCoordinate = res.coordinate
71
       res.mapCoordinate = res.coordinate
72
+      if (res.videoUrl) {
73
+        res.videoUrl = [].concat(res.videoUrl)
74
+      }
70
       props.form.setFieldsValue(res)
75
       props.form.setFieldsValue(res)
71
       props.onSuccess(res)
76
       props.onSuccess(res)
72
     })
77
     })
86
     data.receivedDate = moment(data.receivedDate, 'yyyy-MM-dd HH:mm:ss')
91
     data.receivedDate = moment(data.receivedDate, 'yyyy-MM-dd HH:mm:ss')
87
     // 项目主图
92
     // 项目主图
88
     data.img = data.avatarImage && data.avatarImage.map((item, index) => ({ imgType: 'banner', url: item, orderNo: index + 1 }))
93
     data.img = data.avatarImage && data.avatarImage.map((item, index) => ({ imgType: 'banner', url: item, orderNo: index + 1 }))
94
+    // 列表图
95
+    data.listImg = data.listImage && data.listImage.map((item, index) => ({ imgType: 'list', url: item, orderNo: index + 1 }))
96
+    data.videoUrl = data.videoUrl[0]
89
     if (data.tag) {
97
     if (data.tag) {
90
       data.tag = data.tag.map((item, _) => ({ tagName: item }))
98
       data.tag = data.tag.map((item, _) => ({ tagName: item }))
91
     }
99
     }
100
     })
108
     })
101
   }
109
   }
102
 
110
 
111
+  // 视频文件上传前 回调
112
+  function fileUploadBeforeUpload(file, fileList) {
113
+    console.log(file, fileList)
114
+    return new Promise((resolve, reject) => {
115
+      if (file.type === 'video/mp4' || file.type === '.mp4') {
116
+          resolve(file)
117
+      } else {
118
+        openNotificationWithIcon('error', '项目视频,仅支持MP4格式')
119
+        reject()
120
+      }
121
+    })
122
+  }
123
+
103
   return (
124
   return (
104
         <Form {...formItemLayout} onSubmit={handleSubmit}>
125
         <Form {...formItemLayout} onSubmit={handleSubmit}>
105
           <Form.Item label="项目Id" style={{ display: 'none' }}>
126
           <Form.Item label="项目Id" style={{ display: 'none' }}>
169
               </Select>,
190
               </Select>,
170
             )}
191
             )}
171
           </Form.Item>
192
           </Form.Item>
193
+          <Form.Item label="项目视频" help="视频仅支持mp4格式,建议尺寸:1920*1080,比例16:9">
194
+            {getFieldDecorator('videoUrl')(
195
+              <FileUpload accept=".mp4" beforeUpload={fileUploadBeforeUpload} label="上传视频"/>,
196
+            )}
197
+          </Form.Item>
172
           <Form.Item label="项目主图" help="建议图片尺寸:640px*360px">
198
           <Form.Item label="项目主图" help="建议图片尺寸:640px*360px">
173
             {getFieldDecorator('avatarImage', {
199
             {getFieldDecorator('avatarImage', {
174
               rules: [{ required: true, message: '请选择项目主图' }],
200
               rules: [{ required: true, message: '请选择项目主图' }],
176
               <ImageListUpload />,
202
               <ImageListUpload />,
177
             )}
203
             )}
178
           </Form.Item>
204
           </Form.Item>
179
-          <Form.Item label="地址图片" help="建议图片尺寸:750px*455px">
205
+          <Form.Item label="列表图" help="建议图片尺寸:640px*360px">
206
+            {getFieldDecorator('listImage', {
207
+              rules: [{ required: true, message: '请选择列表图' }],
208
+            })(
209
+              <ImageListUpload />,
210
+            )}
211
+          </Form.Item>
212
+          {/* <Form.Item label="地址图片" help="建议图片尺寸:750px*455px">
180
             {getFieldDecorator('mapImg')(
213
             {getFieldDecorator('mapImg')(
181
               <ImageUpload />,
214
               <ImageUpload />,
182
             )}
215
             )}
183
-          </Form.Item>
216
+          </Form.Item> */}
184
           {/* <Form.Item label="海报底图" help="建议图片尺寸:640px*1136px" >
217
           {/* <Form.Item label="海报底图" help="建议图片尺寸:640px*1136px" >
185
             {getFieldDecorator('poster')(
218
             {getFieldDecorator('poster')(
186
               <ImageUpload />,
219
               <ImageUpload />,
227
           <Form.Item label="地图位置" >
260
           <Form.Item label="地图位置" >
228
             {getFieldDecorator('mapCoordinate')(<Amap onChange={e => props.form.setFieldsValue({ coordinate: e })}/>)}
261
             {getFieldDecorator('mapCoordinate')(<Amap onChange={e => props.form.setFieldsValue({ coordinate: e })}/>)}
229
           </Form.Item>
262
           </Form.Item>
263
+          <Form.Item label="周边设施搜索范围" style={{ width: '2000px' }}>
264
+            {getFieldDecorator('mapScope', {
265
+              rules: [{ required: true, message: '请选择周边设施搜索范围' }],
266
+            })(
267
+              <Select placeholder="请选择周边设施搜索范围" style={{ width: '970px' }}>
268
+                <Option value={1000}>1公里</Option>
269
+                <Option value={3000}>3公里</Option>
270
+                <Option value={5000}>5公里</Option>
271
+                <Option value={10000}>10公里</Option>
272
+              </Select>,
273
+            )}
274
+          </Form.Item>
230
           <Form.Item label="周边交通" >
275
           <Form.Item label="周边交通" >
231
             {getFieldDecorator('buildingTransport')(
276
             {getFieldDecorator('buildingTransport')(
232
               <TagGroup />,
277
               <TagGroup />,

+ 30
- 0
src/pages/building/list/add/components/buildingImage.jsx 查看文件

1
+import React from 'react';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, Table, notification, Modal, Layout } from 'antd';
3
+
4
+const { Header, Footer, Sider, Content } = Layout;
5
+
6
+function BuildingImageModel() {
7
+  return (
8
+    <>
9
+      <span>效果图(10)</span>
10
+      <Button type="link">重命名</Button>
11
+      <Button type="link">删除相册</Button>
12
+    </>
13
+  )
14
+}
15
+
16
+
17
+function buildingImage() {
18
+  return (
19
+    <>
20
+      <Button type="primary">新增</Button>
21
+      <Layout>
22
+        <Content><BuildingImageModel /></Content>
23
+        <Content><BuildingImageModel /></Content>
24
+        <Content><BuildingImageModel /></Content>
25
+      </Layout>
26
+    </>
27
+  )
28
+}
29
+
30
+export default buildingImage

+ 30
- 18
src/pages/building/list/add/components/imageSet.jsx 查看文件

1
 import React, { useState, useEffect } from 'react';
1
 import React, { useState, useEffect } from 'react';
2
-import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, Table, notification } from 'antd';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, Table, notification, Modal } from 'antd';
3
 import moment from 'moment';
3
 import moment from 'moment';
4
 import request from '../../../../../utils/request';
4
 import request from '../../../../../utils/request';
5
 import apis from '../../../../../services/apis';
5
 import apis from '../../../../../services/apis';
7
 import { router } from 'umi';
7
 import { router } from 'umi';
8
 import ModalImage from './modalImage';
8
 import ModalImage from './modalImage';
9
 
9
 
10
+const { confirm } = Modal;
11
+
10
 
12
 
11
 const saleType = [
13
 const saleType = [
12
   {
14
   {
82
    * @param {*} record
84
    * @param {*} record
83
    */
85
    */
84
   function deleteApartment(record) {
86
   function deleteApartment(record) {
85
-    // 网路请求
86
-    request({ ...apis.building.buildingApartmentDelete, urlData: { id: record.apartmentId } }).then(res => {
87
-      getList()
88
-      openNotificationWithIcon('success', '操作成功')
89
-    }).catch(err => {
90
-      // openNotificationWithIcon('error', err.message)
91
-    })
87
+    confirm({
88
+      title: '确认删除当前数据?',
89
+      content: '确定后成功删除,点击取消则放弃当前操作',
90
+      okText: '确定',
91
+      cancelText: '取消',
92
+      onOk() {
93
+        // 网路请求
94
+        request({ ...apis.building.buildingApartmentDelete, urlData: { id: record.apartmentId } }).then(res => {
95
+          getList()
96
+          openNotificationWithIcon('success', '操作成功')
97
+        }).catch(err => {
98
+          // openNotificationWithIcon('error', err.message)
99
+        })
100
+      },
101
+      onCancel() {},
102
+    });
92
   }
103
   }
93
 
104
 
94
 
105
 
98
       dataIndex: 'apartmentName',
109
       dataIndex: 'apartmentName',
99
       key: 'apartmentName',
110
       key: 'apartmentName',
100
     },
111
     },
101
-    {
102
-      title: '类型',
103
-      dataIndex: 'apartmentType',
104
-      key: 'apartmentType',
105
-      render: (_, record) => <span>{ record.apartmentType === 'apart' ? '户型' : '相册' }</span>,
106
-    },
107
     {
112
     {
108
       title: '销售状态',
113
       title: '销售状态',
109
       dataIndex: 'marketStatus',
114
       dataIndex: 'marketStatus',
111
       render: (_, record) => <span>{ (saleType.filter(x => x.id == record.marketStatus)[0] || {}).name }</span>,
116
       render: (_, record) => <span>{ (saleType.filter(x => x.id == record.marketStatus)[0] || {}).name }</span>,
112
     },
117
     },
113
     {
118
     {
114
-      title: '备注',
115
-      dataIndex: 'remark',
116
-      key: 'remark',
119
+      title: '面积',
120
+      dataIndex: 'buildingArea',
121
+      key: 'buildingArea',
122
+      render: (buildingArea, _) => <span>{ `${buildingArea}m²` }</span>,
123
+    },
124
+    {
125
+      title: '套内面积',
126
+      dataIndex: 'insideArea',
127
+      key: 'insideArea',
128
+      render: (insideArea, _) => <span>{ `${insideArea}m²` }</span>,
117
     },
129
     },
118
     {
130
     {
119
       title: '创建时间',
131
       title: '创建时间',
141
 
153
 
142
       {/* 编辑页 */}
154
       {/* 编辑页 */}
143
       {/*  onSuccess是子组件传递事件信息  */}
155
       {/*  onSuccess是子组件传递事件信息  */}
144
-      <ModalImage visibleData={visibleData} key={1} onSuccess={() => onModalChange()}/>
156
+      <ModalImage visibleData={visibleData} key="ModalImage" onSuccess={() => onModalChange()}/>
145
     </>
157
     </>
146
   )
158
   )
147
 }
159
 }

+ 19
- 31
src/pages/building/list/add/components/modalImage.jsx 查看文件

30
 const saleType = [
30
 const saleType = [
31
   {
31
   {
32
     id: 1,
32
     id: 1,
33
-    name: '待',
33
+    name: '待',
34
   },
34
   },
35
   {
35
   {
36
     id: 2,
36
     id: 2,
162
               <Form.Item label="编号" style={{ display: 'none' }}>
162
               <Form.Item label="编号" style={{ display: 'none' }}>
163
                   {getFieldDecorator('apartmentId')(<Input />)}
163
                   {getFieldDecorator('apartmentId')(<Input />)}
164
               </Form.Item>
164
               </Form.Item>
165
-              <Form.Item label="名称">
165
+              <Form.Item label="户型名称">
166
                 {getFieldDecorator('apartmentName', {
166
                 {getFieldDecorator('apartmentName', {
167
-                  rules: [{ required: true, message: '请输入名称' }],
168
-                })(<Input />)}
169
-              </Form.Item>
170
-              <Form.Item label="类型">
171
-                {getFieldDecorator('apartmentType', {
172
-                  rules: [{ required: true, message: '请选择类型' }],
173
-                })(
174
-                  <Select placeholder="类型">
175
-                    <Option value="apart">户型</Option>
176
-                    <Option value="photo">相册</Option>
177
-                  </Select>,
178
-                )}
167
+                  rules: [
168
+                    { required: true, message: '请填写户型名称' },
169
+                    { max: 10, message: '户型名称不超过10个字符' },
170
+                  ],
171
+                })(<Input placeholder="户型名称不超过10个字符"/>)}
179
               </Form.Item>
172
               </Form.Item>
180
               <Form.Item label="销售状态">
173
               <Form.Item label="销售状态">
181
-                {getFieldDecorator('marketStatus')(
174
+                {getFieldDecorator('marketStatus', {
175
+                  rules: [{ required: true, message: '请选择销售状态' }],
176
+                })(
182
                   <Select placeholder="销售状态">
177
                   <Select placeholder="销售状态">
183
                     {
178
                     {
184
                       saleType.map((item, _) => <Option value={item.id}>{item.name}</Option>)
179
                       saleType.map((item, _) => <Option value={item.id}>{item.name}</Option>)
188
               </Form.Item>
183
               </Form.Item>
189
               <Form.Item label="图片">
184
               <Form.Item label="图片">
190
               {getFieldDecorator('img', {
185
               {getFieldDecorator('img', {
191
-                  rules: [{ required: true, message: '请选择图片' }],
186
+                  rules: [{ required: true, message: '请上传户型图片' }],
192
               })(
187
               })(
193
                 <ImageListUpload />,
188
                 <ImageListUpload />,
194
               )}
189
               )}
195
               </Form.Item>
190
               </Form.Item>
196
-              <Form.Item label="面积">
197
-                {getFieldDecorator('buildingArea')(<Input />)}
198
-              </Form.Item>
199
-              <Form.Item label="套内面积">
200
-                {getFieldDecorator('insideArea')(<Input />)}
201
-              </Form.Item>
202
-              <Form.Item label="户型总价">
203
-                {getFieldDecorator('apartmentPrice')(<Input />)}
204
-              </Form.Item>
205
-              <Form.Item label="户型简介">
206
-                {getFieldDecorator('apartmentDescription')(
207
-                  <Wangedit />,
208
-                )}
191
+              <Form.Item label="面积" help="单位 ㎡">
192
+                {getFieldDecorator('buildingArea', {
193
+                  rules: [{ required: true, message: '请填写面积' }],
194
+                })(<Input type="number" />)}
209
               </Form.Item>
195
               </Form.Item>
210
-              <Form.Item label="备注">
211
-                {getFieldDecorator('remark')(<TextArea rows={10} />)}
196
+              <Form.Item label="套内面积" help="单位 ㎡">
197
+                {getFieldDecorator('insideArea', {
198
+                  rules: [{ required: true, message: '请填写套内面积' }],
199
+                })(<Input type="number" />)}
212
               </Form.Item>
200
               </Form.Item>
213
               <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
201
               <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
214
                 <Button type="primary" htmlType="submit">保存</Button>
202
                 <Button type="primary" htmlType="submit">保存</Button>

+ 24
- 18
src/pages/building/list/add/index.jsx 查看文件

1
 import React, { useState, useEffect } from 'react';
1
 import React, { useState, useEffect } from 'react';
2
-import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs } from 'antd';
2
+import { Form, Icon, Input, Button, DatePicker, Select, Card, Row, Col, Pagination, Alert, Radio, Tag, Tooltip, Tabs, notification } from 'antd';
3
 import moment from 'moment';
3
 import moment from 'moment';
4
 import request from '../../../../utils/request';
4
 import request from '../../../../utils/request';
5
 import apis from '../../../../services/apis';
5
 import apis from '../../../../services/apis';
11
 import Wangedit from '../../../../components/Wangedit/Wangedit'
11
 import Wangedit from '../../../../components/Wangedit/Wangedit'
12
 import TagGroup from './components/tags'
12
 import TagGroup from './components/tags'
13
 import Base from './components/base'
13
 import Base from './components/base'
14
-import ImageSet from './components/imageSet'
14
+import Apartment from './components/imageSet'
15
 import Poster from './components/poster'
15
 import Poster from './components/poster'
16
 import Share from './components/share'
16
 import Share from './components/share'
17
+import BuildingImage from './components/buildingImage';
17
 
18
 
18
 
19
 
19
 const { Option } = Select
20
 const { Option } = Select
30
   },
31
   },
31
 };
32
 };
32
 
33
 
34
+function openNotificationWithIcon(type, message) {
35
+  notification[type]({
36
+    message,
37
+    description:
38
+      '',
39
+  });
40
+}
41
+
33
 function AddBuilding(props) {
42
 function AddBuilding(props) {
34
 
43
 
35
   const [tab, setTab] = useState('base')
44
   const [tab, setTab] = useState('base')
37
 
46
 
38
   function tabsCallback(e) {
47
   function tabsCallback(e) {
39
     console.log(e);
48
     console.log(e);
40
-    setTab(e.target.value)
49
+    if (!buildingData.buildingId) {
50
+      openNotificationWithIcon('error', '请先保存基本信息')
51
+    } else {
52
+      setTab(e.target.value)
53
+    }
41
   }
54
   }
42
 
55
 
43
   // building 回调
56
   // building 回调
45
     setBuildingData(e)
58
     setBuildingData(e)
46
   }
59
   }
47
 
60
 
48
-  console.log('buildingData: ', buildingData)
49
-
50
   return (
61
   return (
51
     <>
62
     <>
52
       <Radio.Group value={ tab } buttonStyle="solid" onChange={e => tabsCallback(e)}>
63
       <Radio.Group value={ tab } buttonStyle="solid" onChange={e => tabsCallback(e)}>
53
         <Radio.Button value="base">基本信息</Radio.Button>
64
         <Radio.Button value="base">基本信息</Radio.Button>
54
-        {
55
-          buildingData.buildingId &&
56
-          (
57
-            <>
58
-              <Radio.Button value="image">户型库</Radio.Button>
59
-              <Radio.Button value="poster">海报图片</Radio.Button>
60
-              <Radio.Button value="share">分享设置</Radio.Button>
61
-            </>
62
-          )
63
-        }
65
+        <Radio.Button value="apartment">户型库</Radio.Button>
66
+        <Radio.Button value="image">项目相册</Radio.Button>
67
+        <Radio.Button value="poster">海报图片</Radio.Button>
68
+        <Radio.Button value="share">分享设置</Radio.Button>
64
       </Radio.Group>
69
       </Radio.Group>
65
       <div style={{ marginTop: '20px' }}>
70
       <div style={{ marginTop: '20px' }}>
66
         { tab === 'base' && <Base building={{ buildingId: buildingData.buildingId || (props.location.query && props.location.query.id) }} onSuccess={e => buildingOnSuccess(e)}/> }
71
         { tab === 'base' && <Base building={{ buildingId: buildingData.buildingId || (props.location.query && props.location.query.id) }} onSuccess={e => buildingOnSuccess(e)}/> }
67
-        { buildingData.buildingId && (tab === 'image' && <ImageSet building={buildingData} />)}
68
-        { buildingData.buildingId && (tab === 'poster' && <Poster building={buildingData} />)}
69
-        { buildingData.buildingId && (tab === 'share' && <Share building={buildingData} />)}
72
+        { (tab === 'apartment' && <Apartment building={buildingData} />)}
73
+        { (tab === 'image' && <BuildingImage building={buildingData} />)}
74
+        { (tab === 'poster' && <Poster building={buildingData} />)}
75
+        { (tab === 'share' && <Share building={buildingData} />)}
70
       </div>
76
       </div>
71
     </>
77
     </>
72
     // <Tabs defaultActiveKey="1" onChange={tabsCallback}>
78
     // <Tabs defaultActiveKey="1" onChange={tabsCallback}>