123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- import React, { useState } from 'react'
- import { Button, Spin, DatePicker, Form, Input, InputNumber, Radio, notification, Select,Switch} from 'antd'
- import FileUpload from '@/components/XForm/FileUpload'
- import ImageUpload from '@/components/XForm/ImageUpload'
- import ImageListUpload from '@/components/XForm/ImageListUpload'
- import SelectCity from '@/components/SelectButton/CitySelect'
- import AreaSelect from '@/components/SelectButton/AreaSelect'
- import { POI_TYPES_KETY, POI_TYPES, getPoiData } from '@/utils/map'
- import Amap from '../components/Amap'
- import BuildingType from '../components/BuildingTypeSelect'
- import OpenTimePicker from '../components/OpenTimePicker'
- import EditableArround from '../components/EditableArround'
- import FormGroupItem, { gourpItemLayout } from '../components/FormGroupItem'
- import { formItemLayout, validMinNum } from '../utils'
- import useArrounds from './useArrounds'
- import usePois from './usePois'
- import useQuery from './useQuery'
- import useBrands from './useBrands'
- import { initForm, saveData } from './form'
- import { router } from 'umi'
-
- const fullWidth= { width: '100%' }
- const Item = Form.Item
-
- const BuildingBasic = React.forwardRef((props, ref) => {
- const { form, history,setMarketingCode } = props;
- const { getFieldDecorator, getFieldValue, setFieldsValue } = form;
- const { query } = history.location;
- const { id } = query;
-
- const [ loading, setLoading ] = useState({ form: false, arround: false })
- const [brands] = useBrands()
- const [
- arrounds,
- initArrounds,
- updateArrounds,
- deleteArround,
- ] = useArrounds()
- const [
- pois,
- initPois,
- deletePoi,
- ] = usePois()
-
- const updateLoading = (key) => (state) => setLoading({ ...loading, [key]: state })
- const updateFormLoading = updateLoading('form')
-
- useQuery(id, updateFormLoading, (res) => {
- initPois(res.mapJson)
- initArrounds(res)
- initForm(form, res)
- setMarketingCode(res.marketingCode)
- })
-
- // 视频文件上传前 回调
- const fileUploadBeforeUpload = (file, fileList) => {
- return new Promise((resolve, reject) => {
- if (file.type === 'video/mp4' || file.type === '.mp4') {
- // setVideoImage(true)
- resolve(file)
- } else {
- notification.error({ message: '项目视频,仅支持MP4格式' })
- reject()
- }
- })
- }
-
- // 周边设施 回调
- function handleMapScopeChange(e) {
- const coordinateValue = getFieldValue('coordinate')
- if (!coordinateValue) {
- notification.error({ message: '请先选择项目坐标位置' })
- return
- }
-
- const lngLat = getFieldValue('coordinate').split(',')
-
- // 把支持的周边分类都去检索一遍
- setLoading({ ...loading, arround: true })
- Promise.all(POI_TYPES.map(({ key }) => getPoiData({ type: key, location: lngLat, radius: e }))).then((res) => {
- const pois = POI_TYPES.reduce((acc, { key }, inx) => {
- return {
- ...acc,
- [key]: (res[inx] || {}).pois || []
- }
- }, {})
-
- initPois(pois, true)
- setLoading({ ...loading, arround: false })
- }).catch((err) => {
- setLoading({ ...loading, arround: false })
- console.error(err)
- notification.error({ message: '周边数据获取异常' })
- })
- }
-
- function handleSubmit(e) {
- e.preventDefault();
- props.form.validateFieldsAndScroll((err, values) => {
- if (!err) {
- updateFormLoading(true)
- saveData({
- ...values,
- pois,
- arrounds,
- }).then((res) => {
- updateFormLoading(false)
- notification.success({ message: '保存项目基础信息成功' })
-
- if (!id) {
- router.replace(`/building/add?id=${res.buildingId}`)
- }
- }).catch((err) => {
- console.error(err)
- updateFormLoading(false)
- notification.error({ message: err.message || err })
- })
- }
- });
- }
-
- return (
- <Spin spinning={loading.form}>
- <Form {...formItemLayout} onSubmit={handleSubmit}>
- <Item label="项目Id" style={{ display: 'none' }}>
- {getFieldDecorator('buildingId')(<Input disabled />)}
- </Item>
- <Item label="楼盘编号" >
- {getFieldDecorator('code', {
- rules: [{ required: true, message: '请输入楼盘编号' }],
- })(<Input />)}
- </Item>
- <Item label="楼盘名称" >
- {getFieldDecorator('buildingName', {
- rules: [{ required: true, message: '请输入楼盘名' }],
- })(<Input />)}
- </Item>
- <Form.Item label="项目类型">
- {getFieldDecorator('buildingProjectType', {
- rules: [{ required: true, message: '请选择项目类型' }],
- })(<BuildingType />)}
- </Form.Item>
- <Form.Item label="是否文旅商办" help="是否将本项目归纳在【首页-文旅商办】中">
- {getFieldDecorator('isCommerce', {
- rules: [{ required: true, message: '请选择项目类型' }],
- })(<Switch />)}
- </Form.Item>
- <Form.Item label="列表均价" help="项目列表展示价格,示例:约10000元/㎡、约1000万元/套起">
- {getFieldDecorator('price')(<Input />)}
- </Form.Item>
- <FormGroupItem>
- <Form.Item label="开盘时间" {...gourpItemLayout.ab.a} >
- {getFieldDecorator('openingDate')(
- <OpenTimePicker placeholder="请选择开盘时间" style={fullWidth} />
- )}
- </Form.Item>
- <Form.Item label="电话" {...gourpItemLayout.ab.b } >
- {getFieldDecorator('tel', {
- rules: [
- {
- pattern: new RegExp('^[0-9]*$'),
- message: '请输入正确的电话号码',
- },
- ],
- })(<Input placeholder="手机或者座机号码" />)}
- </Form.Item>
- </FormGroupItem>
- <Form.Item label="项目说明" >
- {getFieldDecorator('dynamic')(<Input placeholder="项目动态等,不超过30个字" maxLength={30}/>)}
- </Form.Item>
- {/* <Form.Item label="物业类型" >
- {getFieldDecorator('propertyType')(<Input />)}
- </Form.Item> */}
- <Form.Item label="销售状态" >
- {getFieldDecorator('marketStatus', {
- rules: [{ required: true, message: '请选择销售状态' }],
- })(
- <Select placeholder="销售状态" style={fullWidth}>
- <Select.Option value="待售">待售</Select.Option>
- <Select.Option value="在售">在售</Select.Option>
- <Select.Option value="售罄">售罄</Select.Option>
- <Select.Option value="在租">在租</Select.Option>
- </Select>,
- )}
- </Form.Item>
- <Form.Item label="项目标签" >
- {getFieldDecorator('tag')(
- <Select mode="tags" placeholder="输入后选中" style={fullWidth} />
- )}
- </Form.Item>
-
- <FormGroupItem>
- <Form.Item label="项目视频" help="视频仅支持mp4格式,建议尺寸:750*600,比例5:4,用于楼盘详情" {...gourpItemLayout.ab.a} >
- {getFieldDecorator('videoUrl')(
- <FileUpload accept=".mp4" beforeUpload={fileUploadBeforeUpload} label="上传视频" size={1} />,
- )}
- </Form.Item>
- <Form.Item label="视频封面图" help="建议图片尺寸:750*600px,比例5:4,格式:jpg,用于视频封面" labelCol={{span: 8}} wrapperCol={{span:16}}>
- {getFieldDecorator('videoImage')(
- <ImageUpload />,
- )}
- </Form.Item>
- </FormGroupItem>
- <Form.Item label="楼盘主图" help="建议图片尺寸:750*600px,比例5:4,格式:jpg,用于楼盘详情">
- {getFieldDecorator('avatarImage', {
- rules: [{ required: true, message: '请选择项目主图' }],
- })(
- <ImageListUpload unlimited />,
- )}
- </Form.Item>
- <Form.Item label="楼盘封面图" help="建议图片尺寸:750*420px,比例16:9,格式:jpg,用于楼盘列表">
- {getFieldDecorator('listImage', {
- rules: [{ required: true, message: '请选择列表图' }],
- })(
- <ImageUpload />,
- )}
- </Form.Item>
- <FormGroupItem>
- <Form.Item label="首页推荐" {...gourpItemLayout.ab.a} >
- {getFieldDecorator('isMain', { initialValue: 1 })(
- <Radio.Group>
- <Radio value={1}>是</Radio>
- <Radio value={2}>否</Radio>
- </Radio.Group>,
- )}
- </Form.Item>
- <Form.Item label="排序" help="数值越大,楼盘在小程序列表页中展示越靠前" {...gourpItemLayout.ab.b}>
- {getFieldDecorator('orderNo')(<InputNumber min={0} style={fullWidth} />)}
- </Form.Item>
- </FormGroupItem>
- <FormGroupItem>
- <Form.Item label="所在城市" {...gourpItemLayout.ab.a } >
- {getFieldDecorator('cityId', {
- rules: [{ required: true, message: '请选择城市' }],
- })(
- <SelectCity style={fullWidth} />,
- )}
- </Form.Item>
- <Form.Item label="楼盘区域" {...gourpItemLayout.ab.b } >
- {getFieldDecorator('buildingArea', {
- rules: [{ required: true, message: '请输入楼盘区域' }],
- })(<AreaSelect style={fullWidth} />)}
- </Form.Item>
- </FormGroupItem>
- <Form.Item label="项目地址" >
- {getFieldDecorator('address', {
- rules: [{ required: true, message: '请输入项目地址' }],
- })(<Input />)}
- </Form.Item>
- <Form.Item label="项目坐标" >
- {getFieldDecorator('coordinate', {
- rules: [{ required: true, message: '请输入项目坐标' }],
- })(<Amap onChange={e => setFieldsValue({ coordinate: e })} />)}
- </Form.Item>
- <Form.Item label="周边范围" >
- {getFieldDecorator('mapScope', {
- rules: [{ required: true, message: '请选择周边设施搜索范围' }],
- })(
- <Select placeholder="周边设施搜索范围" style={fullWidth} onChange={handleMapScopeChange}>
- <Select.Option value={1000}>1公里</Select.Option>
- <Select.Option value={3000}>3公里</Select.Option>
- <Select.Option value={5000}>5公里</Select.Option>
- <Select.Option value={10000}>10公里</Select.Option>
- </Select>,
- )}
- </Form.Item>
- <Spin spinning={loading.arround}>
- <Form.Item label="周边交通" >
- <EditableArround
- type="Transport"
- pois={pois.Transport}
- tags={arrounds.buildingTransport}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- <Form.Item label="周边商业" >
- <EditableArround
- type="Mall"
- pois={pois.Mall}
- tags={arrounds.buildingMall}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- <Form.Item label="周边学校" >
- <EditableArround
- type="Edu"
- pois={pois.Edu}
- tags={arrounds.buildingEdu}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- <Form.Item label="周边医院" >
- <EditableArround
- type="Hospital"
- pois={pois.Hospital}
- tags={arrounds.buildingHospital}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- <Form.Item label="周边银行" >
- <EditableArround
- type="Bank"
- pois={pois.Bank}
- tags={arrounds.buildingBank}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- <Form.Item label="周边餐饮" >
- <EditableArround
- type="Restaurant"
- pois={pois.Restaurant}
- tags={arrounds.buildingRestaurant}
- onChange={updateArrounds}
- onDelete={deleteArround}
- onPoiDelete={deletePoi}
- />
- </Form.Item>
- </Spin>
- <FormGroupItem>
- <Form.Item label="绿化率" {...gourpItemLayout.ab.a } >
- {getFieldDecorator('greeningRate')(<Input />)}
- </Form.Item>
- <Form.Item label="容积率" {...gourpItemLayout.ab.b }>
- {getFieldDecorator('volumeRate')(<Input />)}
- </Form.Item>
- </FormGroupItem>
- <FormGroupItem>
- <Form.Item label="车位数量" {...gourpItemLayout.ab.a }>
- {getFieldDecorator('parkingRate', {
- rules: [{ validator: validMinNum }]
- })(<InputNumber min={0} style={fullWidth}/>)}
- </Form.Item>
- <Form.Item label="规划户数" {...gourpItemLayout.ab.b }>
- {getFieldDecorator('familyNum', {
- rules: [{ validator: validMinNum }]
- })(<InputNumber min={0} style={fullWidth}/>)}
- </Form.Item>
- </FormGroupItem>
- <FormGroupItem>
- <Form.Item label="供水" {...gourpItemLayout.abc.a }>
- {getFieldDecorator('waterSupply')(
- <Select style={fullWidth}>
- <Select.Option value="民水">民水</Select.Option>
- <Select.Option value="商用">商用</Select.Option>
- <Select.Option value="暂无">暂无</Select.Option>
- </Select>
- )}
- </Form.Item>
- <Form.Item label="供电" {...gourpItemLayout.abc.b }>
- {getFieldDecorator('powerSupply')(
- <Select style={fullWidth}>
- <Select.Option value="民电">民电</Select.Option>
- <Select.Option value="商用">商用</Select.Option>
- <Select.Option value="暂无">暂无</Select.Option>
- </Select>
- )}
- </Form.Item>
- <Form.Item label="供暖" {...gourpItemLayout.abc.c }>
- {getFieldDecorator('heatingSupply')(
- <Select style={fullWidth}>
- <Select.Option value="集中供暖">集中供暖</Select.Option>
- <Select.Option value="自采暖">自采暖</Select.Option>
- <Select.Option value="暂无">暂无</Select.Option>
- </Select>
- )}
- </Form.Item>
- </FormGroupItem>
- <Form.Item label="物业公司" >
- {getFieldDecorator('serviceCompany', {
- rules: [{ max: 30, message: '不超过30个字' }]
- })(<Input placeholder="不超过30个字"/>)}
- </Form.Item>
- <Form.Item label="物业费" >
- {getFieldDecorator('serviceFee', {
- rules: [{ max: 30, message: '不超过30个字' }]
- })(<Input placeholder="不超过30个字"/>)}
- </Form.Item>
- <FormGroupItem>
- <Form.Item label="装修标准" {...gourpItemLayout.ab.a }>
- {getFieldDecorator('decoration')(
- <Select style={fullWidth}>
- <Select.Option value="精装">精装</Select.Option>
- <Select.Option value="毛坯">毛坯</Select.Option>
- <Select.Option value="暂无">暂无</Select.Option>
- </Select>
- )}
- </Form.Item>
- <Form.Item label="楼栋总数" {...gourpItemLayout.ab.b }>
- {getFieldDecorator('buildingNum', {
- rules: [{ validator: validMinNum }]
- })(<InputNumber style={fullWidth}/>)}
- </Form.Item>
- </FormGroupItem>
- <FormGroupItem>
- <Form.Item label="交房时间" {...gourpItemLayout.ab.a }>
- {getFieldDecorator('receivedDate')(<DatePicker style={fullWidth}/>)}
- </Form.Item>
- <Form.Item label="产权年限" {...gourpItemLayout.ab.b }>
- {getFieldDecorator('rightsYear', {
- rules: [{ validator: validMinNum }]
- })(<InputNumber style={fullWidth}/>)}
- </Form.Item>
- </FormGroupItem>
- <Form.Item label="品牌开发商" help="【品牌开发商】与【开发商】二选一">
- {getFieldDecorator('brandId')(
- <Select style={fullWidth}>
- {
- brands.map((x) => (<Select.Option key={x.brandId} value={x.brandId}>{x.brandName}</Select.Option>))
- }
- </Select>
- )}
- </Form.Item>
- <Form.Item label="开发商" >
- {getFieldDecorator('propertyDeveloper', {
- rules: [{ max: 30, message: '不超过30个字' }]
- })(<Input placeholder="不超过30个字"/>)}
- </Form.Item>
- <Form.Item label="备案名" >
- {getFieldDecorator('recordName', {
- rules: [{ max: 30, message: '不超过30个字' }]
- })(<Input placeholder="不超过30个字" />)}
- </Form.Item>
- <Form.Item label="预售许可证" >
- {getFieldDecorator('preSalePermit')(
- <ImageUpload />,
- )}
- </Form.Item>
-
- <Form.Item label=" " colon={false}>
- <Button style={{marginLeft: '6em'}} type="primary" htmlType="submit">
- 确定
- </Button>
- <Button style={{marginLeft: '2em'}} onClick={() => router.go(-1)}>
- 取消
- </Button>
- </Form.Item>
- </Form>
- </Spin>
- )
- })
-
- export default Form.create()(BuildingBasic)
|