diff --git a/web-react/public/index.html b/web-react/public/index.html
index aa069f2..b92c542 100644
--- a/web-react/public/index.html
+++ b/web-react/public/index.html
@@ -25,6 +25,7 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
React App
+
You need to enable JavaScript to run this app.
diff --git a/web-react/src/assets/image/adorn/house-top-01.png b/web-react/src/assets/image/adorn/house-top-01.png
new file mode 100644
index 0000000..fbaee95
Binary files /dev/null and b/web-react/src/assets/image/adorn/house-top-01.png differ
diff --git a/web-react/src/assets/style/lib/input.less b/web-react/src/assets/style/lib/input.less
index 1417fec..d464a3c 100644
--- a/web-react/src/assets/style/lib/input.less
+++ b/web-react/src/assets/style/lib/input.less
@@ -1,10 +1,4 @@
@import (reference) '../extend.less';
-/* input前缀有2个字符的 */
-.yo-input-prefix-2 {
- .ant-input:not(:first-child) {
- padding-left: 45px;
- }
-}
.yo-addon {
padding: 0 @padding-xs;
}
diff --git a/web-react/src/assets/style/public.less b/web-react/src/assets/style/public.less
index c726287..d935b12 100644
--- a/web-react/src/assets/style/public.less
+++ b/web-react/src/assets/style/public.less
@@ -22,11 +22,14 @@
width: 25%;
min-width: 300px;
- padding: @padding-xxs @padding-sm;
- background: fade(@black, 20%);
box-shadow: @box-shadow-base;
-
- backdrop-filter: blur(5px);
+ }
+}
+.yo-adorn {
+ &--house-top {
+ height: 65px;
+
+ background: url('~assets/image/adorn/house-top-01.png') no-repeat bottom right;
}
}
diff --git a/web-react/src/components/component-dynamic/index.jsx b/web-react/src/components/component-dynamic/index.jsx
index 2ef2371..45d447c 100644
--- a/web-react/src/components/component-dynamic/index.jsx
+++ b/web-react/src/components/component-dynamic/index.jsx
@@ -8,14 +8,6 @@ export default class ComponentDynamic extends Component {
component: null
}
- shouldComponentUpdate() {
- if (this.props.onRef) {
- this.props.onRef(this)
- }
-
- return true
- }
-
componentDidMount() {
this.loadComponent()
}
diff --git a/web-react/src/pages/business/house/code/form/index.jsx b/web-react/src/pages/business/house/code/form/index.jsx
index 6814566..865b1b1 100644
--- a/web-react/src/pages/business/house/code/form/index.jsx
+++ b/web-react/src/pages/business/house/code/form/index.jsx
@@ -1,7 +1,8 @@
import React, { Component } from 'react'
-import { Button, Card } from 'antd'
+import { Button, Card, message as Message, Modal } from 'antd'
import { ComponentDynamic, Container } from 'components'
import { isEqual } from 'lodash'
+import { api } from 'common/api'
const parts = [{
component: () => import('./part')
@@ -9,37 +10,91 @@ const parts = [{
export default class index extends Component {
+ state = {
+ saving: false
+ }
+
+ children = []
+
+ formData = {}
shouldComponentUpdate(props, state) {
return !isEqual(this.state, state)
}
+ async onSubmit() {
+ for (const child of this.children) {
+ try {
+ const data = await child.getData()
+ this.formData = {
+ ...this.formData,
+ ...data
+ }
+ } catch {
+ return
+ }
+ }
+
+ this.setState({ saving: true })
+ if (!this.props.param.record) {
+ // 新增
+ try {
+ const { success } = await api.houseCodeAdd(this.formData)
+ if (success) {
+ Message.success('保存成功')
+ Modal.confirm({
+ content: '已添加成功,是否继续添加?',
+ onOk: () => {
+
+ },
+ onCancel: () => {
+ window.closeContentWindow()
+ }
+ })
+ }
+ } finally {
+ this.setState({ saving: false })
+ }
+ } else {
+ // 编辑
+ try {
+ const { success } = await api.houseCodeEdit(this.formData)
+ if (success) {
+ Message.success('保存成功')
+ }
+ } finally {
+ this.setState({ saving: false })
+ }
+ }
+ }
+
render() {
const { id, param } = this.props
return (
-
+
+
{
parts.map((item, i) => (
))
}
-
+
取消
- 保存
+ this.onSubmit()} loading={this.state.saving}>保存
diff --git a/web-react/src/pages/business/house/code/form/part.jsx b/web-react/src/pages/business/house/code/form/part.jsx
index dd76dec..ed86511 100644
--- a/web-react/src/pages/business/house/code/form/part.jsx
+++ b/web-react/src/pages/business/house/code/form/part.jsx
@@ -1,10 +1,15 @@
import React, { Component } from 'react'
-import { Form, Input, InputNumber, Radio, Spin } from 'antd'
-import { AntIcon, IconSelector } from 'components'
+import { Button, Cascader, Form, Input, InputNumber, Radio, Spin, Select, Row, Col, Tag, Alert, Tooltip } from 'antd'
+import { AntIcon, Auth } from 'components'
import { cloneDeep } from 'lodash'
import getDictData from 'util/dic'
+import { api } from 'common/api'
+import { CITY } from 'util/global'
-const initialValues = {}
+const initialValues = {
+ type: 1,
+ industry: 1
+}
const labelCol = { flex: '150px' }
const wrapperCol = { flex: '1' }
@@ -17,7 +22,15 @@ export default class form extends Component {
codes: {
dicHouseType: [],
dicHouseIndustry: []
- }
+ },
+ options: {
+ areaTree: [],
+ projects: [],
+ zones: []
+ },
+
+ houseCode: '',
+ showIndustry: false
}
// 表单实例
@@ -32,9 +45,16 @@ export default class form extends Component {
* mount后回调
*/
componentDidMount() {
+ if (this.props.onRef) {
+ this.props.onRef(this)
+ }
this.fillData(this.props.param)
}
+ componentWillUnmount() {
+ if (this.map) this.map.destroy()
+ }
+
/**
* 填充数据
* 可以在设置this.record之后对其作出数据结构调整
@@ -45,10 +65,37 @@ export default class form extends Component {
this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式
+ await this.initMap()
+ const options = { ...this.state.options }
+ // 有数据
+ if (this.record) {
+ const { type, areaCode } = this.record
+ // areaCode需要从字符串转为数组
+ this.record.areaCode = [
+ areaCode.substr(0, 4),
+ areaCode.substr(0, 6),
+ areaCode.substr(0, 9),
+ areaCode
+ ]
+ // 获取项目和片区列表
+ const data = await this.getProjectsAndZones({
+ areaCode: this.record.areaCode,
+ type
+ })
+ Object.assign(options, data)
+ // 定位
+ const position = [this.record.lng, this.record.lat]
+ this.setMarker(position)
+ this.map.setCenter(position)
+ }
const codes = await getDictData('dic_house_type', 'dic_house_industry')
+ const { data: areaTree } = await api.getAreaTree()
+ options.areaTree = areaTree
this.setState({
- codes
+ codes,
+ options
})
+ this.showHouseCode()
//#endregion
this.form.current.setFieldsValue(this.record)
@@ -73,50 +120,467 @@ export default class form extends Component {
postData.id = this.record.id
}
//#region 从前段转换后端所需格式
+ if (postData.areaCode) {
+ postData.areaCode = postData.areaCode[3]
+ }
//#endregion
return postData
}
}
//#region 自定义方法
+ initMap() {
+
+ // eslint-disable-next-line no-undef
+ const amap = AMap
+
+ return new Promise(resolve => {
+ const city = CITY
+
+ const district = new amap.DistrictSearch({
+ subdistrict: 0,
+ extensions: 'all',
+ level: 'city'
+ })
+
+ district.search(city, (status, result) => {
+ const bounds = result.districtList[0].boundaries,
+ mask = []
+ for (let i = 0; i < bounds.length; i += 1) {
+ mask.push([bounds[i]])
+ }
+
+ const geocoder = new amap.Geocoder({ city })
+ geocoder.getLocation(city, (status, result) => {
+
+ if (status !== 'complete' || !(result.geocodes && result.geocodes.length)) return
+
+ this.citycode = result.geocodes[0].addressComponent.citycode
+
+ this.map = new amap.Map(this.refs.map, {
+ mask,
+ zoom: 12,
+ center: result.geocodes[0].location
+ })
+
+ this.map.on('click', e => {
+ this.setMarker(e.lnglat, geocoder)
+ })
+
+ this.map.on('complete', () => {
+ this.map.setFitView()
+ this.map.setZoom(12)
+
+ for (const path of bounds) {
+ new amap.Polyline({
+ path,
+ strokeColor: '#ccc',
+ strokeWeight: 4,
+ map: this.map
+ })
+ }
+
+ resolve()
+ })
+
+ const auto = new amap.AutoComplete({
+ input: this.refs['map-search'].input,
+ city,
+ citylimit: true
+ })
+
+ const placeSearch = new amap.PlaceSearch({
+ city,
+ citylimit: true,
+ pageSize: 1
+ })
+
+ auto.on('select', ({ poi: { name: keywords, adcode } }) => {
+ placeSearch.search(keywords, async (status, result) => {
+ const {
+ poiList: { pois },
+ } = result
+ for (const poi of pois) {
+ await this.setMarker(poi.location, geocoder)
+ this.map.setCenter(poi.location)
+ }
+ })
+ })
+
+ })
+ })
+ })
+ }
+
+ setMarker(position, geocoder) {
+
+ const set = (position) => {
+ if (this.marker) {
+ this.marker.setPosition(position)
+ } else {
+ this.marker = new amap.Marker({
+ map: this.map,
+ icon: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png',
+ position,
+ offset: new amap.Pixel(-13, -30),
+ })
+ }
+ }
+
+ // eslint-disable-next-line no-undef
+ const amap = AMap
+
+ return new Promise((resolve, reject) => {
+ if (geocoder) {
+ geocoder.getAddress(position, (status, result) => {
+ if (status === 'complete' && result.regeocode) {
+ if (result.regeocode.addressComponent.citycode !== this.citycode) {
+ // 如果选到了别的城市,则中断
+ return
+ }
+ this.setPosition(result.regeocode.formattedAddress, position)
+
+ set(position)
+ resolve(position)
+
+ } else {
+ console.error('根据经纬度查询地址失败')
+
+ reject()
+ }
+ })
+ } else {
+ set(position)
+ resolve(position)
+ }
+ })
+ }
+
+ setPosition(address, { lng, lat }) {
+ this.form.current.setFieldsValue({
+ address,
+ lng,
+ lat
+ })
+ }
+
+ async getProjectsAndZones({ areaCode, type } = {}, mode = ['projects', 'zones']) {
+ if (!areaCode || !type) {
+ const value = this.form.current.getFieldsValue()
+ areaCode = value.areaCode
+ type = value.type
+ }
+
+ if (!(areaCode && areaCode.length === 4)) return null
+
+ try {
+ const result = {}
+
+ if (mode.includes('projects')) {
+ const { data: projects } = await api.houseProjectList({
+ areaCode: areaCode[3],
+ type
+ })
+ result.projects = projects
+ }
+ if (mode.includes('zones')) {
+ const { data: zones } = await api.houseZoneList({
+ areaCode: areaCode[3]
+ })
+ result.zones = zones
+ }
+
+ return result
+ } catch {
+ return null
+ }
+ }
+
+ async getCodeNo(projectId) {
+ this.setState({ loading: true })
+ const { data: no } = await api.houseCodeNo({ projectId })
+ this.form.current.setFieldsValue({
+ no
+ })
+ this.setState({ loading: false })
+ }
+
+ showHouseCode(values) {
+ if (this.record) {
+ this.setState({
+ houseCode: this.record.houseCode
+ })
+ } else if (values) {
+ const { type, industry, areaCode, projectId, no } = values
+ if (areaCode && areaCode.length === 4 && projectId && no) {
+ let houseCode = areaCode[3]
+ const projectSort = this.state.options.projects.find(p => p.id === projectId).sort
+ houseCode += projectSort.toString().padStart(3, '0')
+ houseCode += no.toString().padStart(3, '0')
+ if (type == 1) {
+ this.setState({ houseCode })
+ } else {
+ if (!industry) {
+ this.setState({ houseCode: '' })
+ } else {
+ const tag = this.state.codes.dicHouseIndustry.find(p => p.code == industry).extCode.tag
+ houseCode += `-${tag}`
+ this.setState({ houseCode })
+ }
+ }
+ } else {
+ this.setState({ houseCode: '' })
+ }
+ }
+ }
+
+ async onValuesChange(changedValues, allValues) {
+ const form = this.form.current
+ // 房屋性质
+ if (changedValues.hasOwnProperty('type')) {
+ this.setState({
+ showIndustry: changedValues.type == 2,
+ loading: true
+ })
+ const data = await this.getProjectsAndZones()
+ form.setFieldsValue({ projectId: undefined })
+ this.setState({
+ options: {
+ ...this.state.options,
+ ...data
+ },
+ loading: false
+ })
+ this.showHouseCode(form.getFieldsValue())
+ }
+
+ // 所属区域
+ else if (changedValues.hasOwnProperty('areaCode')) {
+ this.setState({ loading: true })
+ const data = await this.getProjectsAndZones()
+ form.setFieldsValue({ projectId: undefined, zoneId: undefined })
+ this.setState({
+ options: {
+ ...this.state.options,
+ ...data
+ },
+ loading: false
+ })
+ this.showHouseCode(form.getFieldsValue())
+ }
+
+ // 所属项目
+ else if (changedValues.hasOwnProperty('projectId')) {
+ await this.getCodeNo(changedValues.projectId)
+ this.showHouseCode(form.getFieldsValue())
+ }
+
+ // 所属行业
+ else if (changedValues.hasOwnProperty('industry')) {
+ this.showHouseCode(allValues)
+ }
+
+ // 编号
+ else if (changedValues.hasOwnProperty('no')) {
+ this.showHouseCode(allValues)
+ }
+ }
+
+ async onReloadProjectsOrZones(mode) {
+ this.setState({ loading: true })
+ const data = await this.getProjectsAndZones({}, [mode])
+ this.setState({
+ options: {
+ ...this.state.options,
+ ...data
+ },
+ loading: false
+ })
+ }
//#endregion
render() {
- const { loading, codes } = this.state
+ const { loading, codes, options, showIndustry, houseCode } = this.state
return (
-
- {codes.dicHouseType.map(item => (
- {item.value}
- ))}
-
-
-
-
- {codes.dicHouseIndustry.map(item => (
- {item.value}
- ))}
-
-
+
+
+
+
+
+
+
+ {codes.dicHouseType.map(item => (
+ {item.value}
+ ))}
+
+
+ {
+ showIndustry &&
+
+
+ {codes.dicHouseIndustry.map(item => (
+ {item.value}
+ ))}
+
+
+ }
+
+
+
+
+ labels.join(' - ')}
+ fieldNames={{
+ label: 'name',
+ value: 'code',
+ children: 'children'
+ }}
+ options={options.areaTree}
+ expandTrigger="hover"
+ />
+
+
+
+
+
+
+
+ {options.projects.map(item => (
+ {item.name}({item.note})
+ ))}
+
+
+
+
+
+
+ 项目管理
+
+ } onClick={() => this.onReloadProjectsOrZones('projects')}>
+
+
+
+
+
+
+
+
+ value.padStart(3, '0')}
+ max={999}
+ min={1}
+ precision={0}
+ step={1}
+ className="w-100-p"
+ placeholder="请输入房屋序号"
+ />
+
+
+ {
+ showIndustry &&
+ -
+ }
+
+
+ {
+ houseCode &&
+
+ {houseCode}
+
+ }
+ 房屋编码说明}
+ description={<>
+ 房屋所在市 —县(市、区) —街道(乡、镇) —社区、居(村)委会) —项目 —实物幢序号 。 根据省厅既有建筑物编号规则,房屋所在区域编号按照市、县(市、区)、街道(乡、镇)、社区、居(村)委会)、项目分类,其中市、县(市)区部分按照《中华人民共和国行政区划代码》(GB2260)标准编码,街道(乡、镇)按《县以下行政区划代码编码规则》(GB10114-88)标准编码,社区、居(村)委会部分按照统计局提供编码设定。各地上报各街道社区名称后,上述编号由系统自动生成。 各社区下辖项目由各地负责统一编码,住宅项目序号一般一个小区一号,采用3位数,001号起编,范围为001~999。实物幢序号由各地负责统一编码,以幢为单位,采用3位数,001号起编,范围为001~999。
+ >} />
+
+
+
+
+
+
+ {options.zones.map(item => (
+ {item.name}
+ ))}
+
+
+
+
+
+
+ 片区管理
+
+ } onClick={() => this.onReloadProjectsOrZones('zones')}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- this.form.current.setFieldsValue({
- icon
- })} />
)
}