魏熙美 5 лет назад
Родитель
Сommit
884dd86cca

+ 57
- 0
src/components/XForm/FileUpload.jsx Просмотреть файл

@@ -0,0 +1,57 @@
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,8 +92,10 @@ class Amap extends React.Component {
92 92
       if (value) {
93 93
         const temp = value.split(',')
94 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,6 +12,7 @@ import TagGroup from './tags'
12 12
 import Amap from './amap'
13 13
 import BudildingProjectType from './buildingProjectType'
14 14
 import SelectCity from '../../../../../components/SelectButton/CitySelect'
15
+import FileUpload from '@/components/XForm/FileUpload';
15 16
 
16 17
 const { Option } = Select
17 18
 const { TabPane } = Tabs;
@@ -66,7 +67,11 @@ function AddBuilding(props) {
66 67
       }
67 68
 
68 69
       res.avatarImage = res.buildingImg.map(item => item.url)
70
+      res.listImage = res.buildingListImg.map(item => item.url)
69 71
       res.mapCoordinate = res.coordinate
72
+      if (res.videoUrl) {
73
+        res.videoUrl = [].concat(res.videoUrl)
74
+      }
70 75
       props.form.setFieldsValue(res)
71 76
       props.onSuccess(res)
72 77
     })
@@ -86,6 +91,9 @@ function AddBuilding(props) {
86 91
     data.receivedDate = moment(data.receivedDate, 'yyyy-MM-dd HH:mm:ss')
87 92
     // 项目主图
88 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 97
     if (data.tag) {
90 98
       data.tag = data.tag.map((item, _) => ({ tagName: item }))
91 99
     }
@@ -100,6 +108,19 @@ function AddBuilding(props) {
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 124
   return (
104 125
         <Form {...formItemLayout} onSubmit={handleSubmit}>
105 126
           <Form.Item label="项目Id" style={{ display: 'none' }}>
@@ -169,6 +190,11 @@ function AddBuilding(props) {
169 190
               </Select>,
170 191
             )}
171 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 198
           <Form.Item label="项目主图" help="建议图片尺寸:640px*360px">
173 199
             {getFieldDecorator('avatarImage', {
174 200
               rules: [{ required: true, message: '请选择项目主图' }],
@@ -176,11 +202,18 @@ function AddBuilding(props) {
176 202
               <ImageListUpload />,
177 203
             )}
178 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 213
             {getFieldDecorator('mapImg')(
181 214
               <ImageUpload />,
182 215
             )}
183
-          </Form.Item>
216
+          </Form.Item> */}
184 217
           {/* <Form.Item label="海报底图" help="建议图片尺寸:640px*1136px" >
185 218
             {getFieldDecorator('poster')(
186 219
               <ImageUpload />,
@@ -227,6 +260,18 @@ function AddBuilding(props) {
227 260
           <Form.Item label="地图位置" >
228 261
             {getFieldDecorator('mapCoordinate')(<Amap onChange={e => props.form.setFieldsValue({ coordinate: e })}/>)}
229 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 275
           <Form.Item label="周边交通" >
231 276
             {getFieldDecorator('buildingTransport')(
232 277
               <TagGroup />,

+ 30
- 0
src/pages/building/list/add/components/buildingImage.jsx Просмотреть файл

@@ -0,0 +1,30 @@
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,5 +1,5 @@
1 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 3
 import moment from 'moment';
4 4
 import request from '../../../../../utils/request';
5 5
 import apis from '../../../../../services/apis';
@@ -7,6 +7,8 @@ import Styles from '../style.less';
7 7
 import { router } from 'umi';
8 8
 import ModalImage from './modalImage';
9 9
 
10
+const { confirm } = Modal;
11
+
10 12
 
11 13
 const saleType = [
12 14
   {
@@ -82,13 +84,22 @@ function imageSet(props) {
82 84
    * @param {*} record
83 85
    */
84 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,12 +109,6 @@ function imageSet(props) {
98 109
       dataIndex: 'apartmentName',
99 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 113
       title: '销售状态',
109 114
       dataIndex: 'marketStatus',
@@ -111,9 +116,16 @@ function imageSet(props) {
111 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 131
       title: '创建时间',
@@ -141,7 +153,7 @@ function imageSet(props) {
141 153
 
142 154
       {/* 编辑页 */}
143 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,7 +30,7 @@ const formItemLayout = {
30 30
 const saleType = [
31 31
   {
32 32
     id: 1,
33
-    name: '待',
33
+    name: '待',
34 34
   },
35 35
   {
36 36
     id: 2,
@@ -162,23 +162,18 @@ class ModalImage extends React.Component {
162 162
               <Form.Item label="编号" style={{ display: 'none' }}>
163 163
                   {getFieldDecorator('apartmentId')(<Input />)}
164 164
               </Form.Item>
165
-              <Form.Item label="名称">
165
+              <Form.Item label="户型名称">
166 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 172
               </Form.Item>
180 173
               <Form.Item label="销售状态">
181
-                {getFieldDecorator('marketStatus')(
174
+                {getFieldDecorator('marketStatus', {
175
+                  rules: [{ required: true, message: '请选择销售状态' }],
176
+                })(
182 177
                   <Select placeholder="销售状态">
183 178
                     {
184 179
                       saleType.map((item, _) => <Option value={item.id}>{item.name}</Option>)
@@ -188,27 +183,20 @@ class ModalImage extends React.Component {
188 183
               </Form.Item>
189 184
               <Form.Item label="图片">
190 185
               {getFieldDecorator('img', {
191
-                  rules: [{ required: true, message: '请选择图片' }],
186
+                  rules: [{ required: true, message: '请上传户型图片' }],
192 187
               })(
193 188
                 <ImageListUpload />,
194 189
               )}
195 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 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 200
               </Form.Item>
213 201
               <Form.Item style={{ width: '400px', margin: 'auto', display: 'flex', justifyContent: 'space-between' }}>
214 202
                 <Button type="primary" htmlType="submit">保存</Button>

+ 24
- 18
src/pages/building/list/add/index.jsx Просмотреть файл

@@ -1,5 +1,5 @@
1 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 3
 import moment from 'moment';
4 4
 import request from '../../../../utils/request';
5 5
 import apis from '../../../../services/apis';
@@ -11,9 +11,10 @@ import ImageUpload from '../../../../components/XForm/ImageUpload'
11 11
 import Wangedit from '../../../../components/Wangedit/Wangedit'
12 12
 import TagGroup from './components/tags'
13 13
 import Base from './components/base'
14
-import ImageSet from './components/imageSet'
14
+import Apartment from './components/imageSet'
15 15
 import Poster from './components/poster'
16 16
 import Share from './components/share'
17
+import BuildingImage from './components/buildingImage';
17 18
 
18 19
 
19 20
 const { Option } = Select
@@ -30,6 +31,14 @@ const formItemLayout = {
30 31
   },
31 32
 };
32 33
 
34
+function openNotificationWithIcon(type, message) {
35
+  notification[type]({
36
+    message,
37
+    description:
38
+      '',
39
+  });
40
+}
41
+
33 42
 function AddBuilding(props) {
34 43
 
35 44
   const [tab, setTab] = useState('base')
@@ -37,7 +46,11 @@ function AddBuilding(props) {
37 46
 
38 47
   function tabsCallback(e) {
39 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 56
   // building 回调
@@ -45,28 +58,21 @@ function AddBuilding(props) {
45 58
     setBuildingData(e)
46 59
   }
47 60
 
48
-  console.log('buildingData: ', buildingData)
49
-
50 61
   return (
51 62
     <>
52 63
       <Radio.Group value={ tab } buttonStyle="solid" onChange={e => tabsCallback(e)}>
53 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 69
       </Radio.Group>
65 70
       <div style={{ marginTop: '20px' }}>
66 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 76
       </div>
71 77
     </>
72 78
     // <Tabs defaultActiveKey="1" onChange={tabsCallback}>