Commit e9904301 authored by 成旭东's avatar 成旭东

哇房1.1

parent 16d7e103
Pipeline #28688 passed with stage
in 2 minutes 1 second
......@@ -24,6 +24,7 @@
<meta name="referrer" content="no-referrer" />
<title>Ant Design Pro</title>
<link rel="icon" href="<%= context.config.publicPath +'favicon.png'%>" type="image/x-icon" />
<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77"></script>
</head>
<body>
<noscript>Out-of-the-box mid-stage front/design solution!</noscript>
......
......@@ -127,6 +127,28 @@ export default {
name: '上线',
}],
name: '在线状态',
}, {
key: 'is_hot',
type: 'select',
options: [{
key: '1',
name: '是',
}, {
key: '0',
name: '否',
}],
name: '热门楼盘',
}], [{
key: 'is_partner',
type: 'select',
options: [{
key: '1',
name: '是',
}, {
key: '0',
name: '否',
}],
name: '合作楼盘',
}]],
eidteSaleStatus: saleStatusData
......
export default {
projectDetailMap: [{
name: '项目名称',
key: 'name',
component: 'input'
}, {
name: '行政区划分名称',
key: 'region_name',
component: 'input'
}, {
name: '总户数',
key: 'house_amount',
component: 'inputNumber'
}, {
name: '参考均价/元',
key: 'list_price',
component: 'inputNumber'
}, {
name: '车位数',
key: 'parking_amount',
component: 'inputNumber'
}, {
name: '交房时间',
key: 'obtain_date',
component: 'date'
}, {
name: '物业类型/楼盘类型',
key: 'type',
disabled: true,
component: 'input'
}, {
name: '户梯比',
key: 'ladder_household_proportion',
component: 'input'
}, {
name: '开发商名称',
key: 'developer',
component: 'input'
}, {
name: '环线名称',
key: 'circle_name',
component: 'input'
}, {
name: '户型区间(最小值)',
key: 'house_area_range_min',
component: 'inputNumber'
}, {
name: '户型区间(最大值)',
key: 'house_area_range_max',
component: 'inputNumber'
}, {
name: '物业公司名称',
key: 'property_company',
component: 'input'
}, {
name: '建筑面积',
key: 'building_area',
component: 'inputNumber'
}, {
name: '经度/维度',
key: 'coordinate',
disabled: true,
component: 'input'
}, {
name: '售楼处地址',
key: 'sale_address',
component: 'input'
}, {
name: '容积率',
key: 'cub_percent',
component: 'inputNumber'
}, {
name: '物业费',
key: 'pro_management_fee',
component: 'inputNumber'
}, {
name: '项目地址',
key: 'address',
component: 'input'
}, {
name: '绿化率',
key: 'vir_percent',
component: 'inputNumber'
}, {
name: '产权年限',
key: 'rights_years',
component: 'inputNumber'
}],
houseOpenInfoMap: [{
name: '装修情况(是否精装)',
key: 'fitment',
......
.projectTagWrap, .houseOpenInfoWrap, .businessOpenInfoWrap, .projectTrendsWrap, .projectLayoutWrap, .projectHouseImageWrap {
.projectTagWrap, .projectDetailWrap, .houseOpenInfoWrap, .businessOpenInfoWrap, .projectTrendsWrap, .projectLayoutWrap, .projectHouseImageWrap {
.title {
font-size: 18px;
color: rgba(0, 0, 0, 0.85);
......@@ -200,11 +200,11 @@
}
}
.businessOpenInfoFormWrap, .officeOpenInfoFormWrap {
.businessOpenInfoFormWrap, .officeOpenInfoFormWrap, .projectDetailFormWrap {
display: flex;
flex-direction: column;
.formOpenInfoWrap, .formGroundWrap, .formSingleWrap, .formCentralizedWrap {
.formOpenInfoWrap, .formGroundWrap, .formSingleWrap, .formCentralizedWrap, .formProjectDetailWrap {
padding: 0 24px;
width: 100%;
......@@ -215,7 +215,7 @@
margin-bottom: 24px;
}
.content {
.content, .extraContent {
display: flex;
flex-wrap: wrap;
......@@ -235,6 +235,14 @@
}
}
}
.extraContent {
:global {
.ant-form-item {
width: 500px;
}
}
}
}
}
......@@ -384,3 +392,28 @@
.openInfoPanelImg {
background-size: 100% 100%!important;
}
.mapModalWrap {
.mapModalTitleWrap {
display: flex;
align-items: center;
.title {
color: rgba(0, 0, 0, 0.85);
font-weight: bold;
font-size: 16px;
}
.searchWrap {
margin-left: 100px;
display: flex;
:global {
.ant-input {
margin-right: 24px;
width: 300px;
}
}
}
}
}
/* eslint-disable no-nested-ternary */
/* eslint-disable no-plusplus */
/* eslint-disable react/no-array-index-key */
import React, { useState, useEffect, useRef } from 'react';
import { connect } from 'umi';
import moment from 'moment';
import { Form, Input, Button, message, DatePicker, InputNumber, Modal } from 'antd';
import configData from './config';
import Map from '../../map/index';
import styles from './index.less';
const FormItem = Form.Item;
const { TextArea } = Input;
const ProjectDetailComponent = (props: any) => {
const { baseData, isEdite } = props;
const [currentBaseData, setCurrentBaseData]: any = useState(baseData);
const [positionModal, setPositionModal]: any = useState(false);
const [mapSearchValue, setMapSearchValue]: any = useState('');
const [form] = Form.useForm();
useEffect(() => {
setCurrentBaseData(baseData);
}, [baseData]);
useEffect(() => {
form.setFieldsValue({
coordinate: currentBaseData.b_x && currentBaseData.b_y && `${currentBaseData.b_x},${currentBaseData.b_y}` || '',
});
}, [currentBaseData]);
// 更新数据
const updateData = (id: number, params: any = {}, callback?: any) => {
const { dispatch } = props;
dispatch({
type: `estateList/updateEstate`,
payload: {
id,
data: params
},
callback: (ret: any) => {
if (ret.error) {
message.error(ret.error);
} else {
message.success('房源更新成功');
if (callback) callback();
}
}
});
}
const saveData = async () => {
const { getBaseData } = props;
const fieldsValue = await form.validateFields();
delete fieldsValue.propertyType;
if (fieldsValue.coordinate) {
const [bx, by] = fieldsValue.coordinate.split(',');
fieldsValue.b_x = bx;
fieldsValue.b_y = by;
}
delete fieldsValue.coordinate;
fieldsValue.type = currentBaseData.type;
// 更新房源信息
updateData(currentBaseData.id, fieldsValue, () => {
getBaseData();
})
}
// 获取物业类型
const getPropertyType = (type: string) => {
const typeMap = {
house: '住宅',
business: '商业',
office: '办公'
}
return typeMap[type] || '';
}
// 获取formItem的name
const getFormName = (name: string) => {
const nameMap = {
type: 'propertyType'
}
return nameMap[name] || name;
}
const clickPosition = () => {
setPositionModal(!positionModal);
}
const mapRef: any = useRef();
// 校准定位确认
const positionOk = async () => {
const { position } = mapRef.current.getCurrentPosition();
setCurrentBaseData({
...currentBaseData,
b_x: position.lng,
b_y: position.lat,
});
setPositionModal(false);
setMapSearchValue('');
};
// 校准定位取消
const positionCancel = () => {
setPositionModal(false);
setMapSearchValue('');
};
// 获取formItm的label
const getFormLabel = (label: string) => {
if (label === '经度/维度') {
return (
<div>
<span>{label}</span>
<span style={{ marginLeft: '10px', color: '#1890ff', cursor: 'pointer' }} onClick={clickPosition}>调整坐标</span>
</div>
)
}
return label;
}
// 去掉html标签只展示文字
const deleteHtmlLabel = (str: string) => {
const htmlReg = /<\/?.+?\/?>/g;
return str.replace(htmlReg, '');
}
const changeMapSearchValue = (e: any) => {
const { value } = e.target;
setMapSearchValue(value);
}
const clickMapSearch = () => {
if (mapSearchValue) {
mapRef.current.searchAddressPosition(mapSearchValue);
} else {
message.error('搜索地址不能为空');
}
}
// modal的Header渲染
const renderModalHeader = () => {
return (
<div className={styles.mapModalTitleWrap}>
<span className={styles.title}>校准定位</span>
<div className={styles.searchWrap}>
<Input placeholder="请输入地址(**市**区****)" value={mapSearchValue} onChange={changeMapSearchValue} />
<Button type="primary" onClick={clickMapSearch}>查询</Button>
</div>
</div>
)
}
const formItemLayout = {
labelCol: {
xs: { span: 24 },
},
wrapperCol: {
xs: { span: 24 },
},
};
return (
<div className={styles.projectDetailWrap}>
<p className={styles.title}>项目详情编辑</p>
{isEdite && (
<Button loading={props.updateLoading} type="primary" style={{ width: '100%', marginBottom: '40px' }} onClick={saveData}>保存</Button>
)}
<Form
className={styles.projectDetailFormWrap}
form={form}
initialValues={{
...currentBaseData,
obtain_date: currentBaseData.obtain_date && currentBaseData.obtain_date !== 'Invalid date' ? moment(currentBaseData.obtain_date, 'YYYY-MM-DD HH:mm:ss') : '',
propertyType: getPropertyType(currentBaseData.type),
coordinate: currentBaseData.b_x && currentBaseData.b_y && `${currentBaseData.b_x},${currentBaseData.b_y}` || '',
description: deleteHtmlLabel(currentBaseData.description),
}}
{...formItemLayout}
>
<div className={styles.formProjectDetailWrap}>
<div className={styles.content}>
{configData.projectDetailMap.map((item: any, index: any) => (
<FormItem
key={index}
name={getFormName(item.key)}
label={getFormLabel(item.name)}
>
{item.component === 'inputNumber' ? (
<InputNumber />
) : (
item.component === 'input' ? (
<Input disabled={item.disabled} />
) : (
item.component === 'date' ? (
<DatePicker format="YYYY-MM-DD HH:mm:ss" />
) : (
<TextArea rows={5} />
)
)
)}
</FormItem>
))}
</div>
<div className={styles.extraContent}>
<FormItem
name="description"
label="项目简介"
>
<TextArea rows={5} />
</FormItem>
</div>
</div>
</Form>
<Modal
wrapClassName={styles.mapModalWrap}
width={748}
title={renderModalHeader()}
destroyOnClose
visible={positionModal}
onOk={positionOk}
onCancel={positionCancel}
>
<Map
ref={mapRef}
currentMapPoint={currentBaseData.b_x && currentBaseData.b_y && `${currentBaseData.b_x},${currentBaseData.b_y}` || ''}
currentMapAddress={currentBaseData.address}
/>
</Modal>
</div>
);
};
export default connect(({ estateList, loading }: any) => ({
estateList,
updateLoading: loading.effects['estateList/updateEstate'],
}))(ProjectDetailComponent);
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import React, { useEffect, useState } from 'react';
import { connect } from 'umi';
import { Card, message, Button, Tabs } from 'antd';
import { Card, message, Tabs } from 'antd';
import ProjectTag from './components/projectTag';
import ProjectDetail from './components/projectDetail';
import HouseOpenInfo from './components/houseOpenInfo';
import BusinessOpenInfo from './components/businessOpenInfo';
import OfficeOpenInfo from './components/officeOpenInfo';
......@@ -77,26 +78,29 @@ const VideoList: React.FC<any> = (props) => {
<TabPane tab="项目营销标签" key="1">
<ProjectTag baseData={baseData} getBaseData={getBaseData} isEdite={isEdite} />
</TabPane>
<TabPane tab="分期开盘信息" key="2">
<TabPane tab="楼盘详情" key="2">
<ProjectDetail baseData={baseData} getBaseData={getBaseData} isEdite={isEdite} />
</TabPane>
<TabPane tab="分期开盘信息" key="3">
{baseData.type === 'house' && (
<HouseOpenInfo baseData={baseData} isEdite={isEdite} />
<HouseOpenInfo baseData={baseData} getBaseData={getBaseData} isEdite={isEdite} />
)}
{baseData.type === 'business' && (
<BusinessOpenInfo baseData={baseData} isEdite={isEdite} />
<BusinessOpenInfo baseData={baseData} getBaseData={getBaseData} isEdite={isEdite} />
)}
{baseData.type === 'office' && (
<OfficeOpenInfo baseData={baseData} isEdite={isEdite} />
<OfficeOpenInfo baseData={baseData} getBaseData={getBaseData} isEdite={isEdite} />
)}
</TabPane>
<TabPane tab="楼盘动态" key="3">
<TabPane tab="楼盘动态" key="4">
<ProjectTrends baseData={baseData} isEdite={isEdite} />
</TabPane>
<TabPane tab="户型图" key="4">
<TabPane tab="户型图" key="5">
<HouseType baseData={baseData} isEdite={isEdite} />
</TabPane>
<TabPane tab="楼盘图片" key="5">
<TabPane tab="楼盘图片" key="6">
<HouseImage baseData={baseData} isEdite={isEdite} />
</TabPane>
</Tabs>
......
.container {
width: 700px;
height: 500px;
}
:global {
.BMap_cpyCtrl,
.anchorBL {
display: none;
}
}
/* eslint-disable no-restricted-syntax */
/* eslint-disable guard-for-in */
import React, { useState, useEffect, useImperativeHandle } from 'react';
import { message } from 'antd';
import styles from './index.less';
// 当前红点覆盖物的坐标
const markersArray: any[] = [];
const Map = React.forwardRef((props: any, ref: any) => {
const { currentMapPoint, currentMapAddress } = props;
const [map, setMap]: any = useState('');
// 清空所有覆盖物
const removeOverlay = () => {
if (markersArray) {
for (const i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
}
};
// 校准定位 创建地址解析器实例
const setGeocoder = (address: any, city: any) => {
const myGeo = new qq.maps.Geocoder();
myGeo.getLocation(address);
myGeo.setComplete((result: any) => {
if (result.detail && result.detail.location) {
map.panTo(result.detail.location);
map.zoomTo(18);
markersArray.push(new qq.maps.Marker({
position: result.detail.location,
animation: qq.maps.MarkerAnimation.DROP,
map,
}));
}
});
myGeo.setError(() => {
message.error('出错了,请输入正确的地址!!!');
});
};
// 重新设置中心点
const setMapCenter = (currentMapPointParam: any, currentMapAddressParam: any) => {
if (currentMapPointParam) {
const currentMapPointArr = currentMapPointParam.split(',');
// 经度
const lng = Number(currentMapPointArr[0].trim());
// 纬度
const lat = Number(currentMapPointArr[1].trim());
// 当前红点覆盖物的坐标
const currentOverlayPoint = new qq.maps.LatLng(lat, lng);
map.panTo(currentOverlayPoint);
map.zoomTo(18);
markersArray.push(new qq.maps.Marker({
position: currentOverlayPoint,
animation: qq.maps.MarkerAnimation.DROP,
map,
}));
}
if (!currentMapPointParam && currentMapAddressParam) {
setGeocoder(currentMapAddressParam.address, currentMapAddressParam.city);
}
};
useEffect(() => {
setMap(new qq.maps.Map(document.getElementById("container")));
}, []);
useEffect(() => {
if (map) {
if (currentMapPoint || currentMapAddress) {
removeOverlay();
setMapCenter(currentMapPoint, {
address: currentMapAddress,
city: '',
});
} else {
removeOverlay();
setMapCenter('', {
address: '成都市锦江区天府广场',
city: '成都市'
});
}
// 监听地图点击事件
qq.maps.event.addListener(map, 'click', (event: any) => {
if (event.latLng) {
removeOverlay();
markersArray.push(new qq.maps.Marker({
position: event.latLng,
animation: qq.maps.MarkerAnimation.DROP,
map,
}));
}
});
}
}, [currentMapPoint, currentMapAddress, map]);
useImperativeHandle(ref, () => {
return {
getCurrentPosition() {
return markersArray[0];
},
searchAddressPosition(address: string) {
removeOverlay();
setMapCenter('', {
address,
city: '',
});
}
}
})
return <div className={styles.container} id="container" ref={ref} />;;
});
export default Map;
......@@ -189,6 +189,23 @@ const DrawerForm = (props: any) => {
<Switch />
</FormItem>
<FormItem
name="order"
label="首页推荐排序"
rules={[
{
required: true,
message: '选择排序',
},
]}
>
<Select>
<Option value={999}>无排序</Option>
<Option value={1}>第一位</Option>
<Option value={2}>第二位</Option>
<Option value={3}>第三位</Option>
</Select>
</FormItem>
<FormItem
name="status"
label="在线状态"
rules={[
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment