• Java开发全终端实战租房项目——项目介绍以及开发后台系统


    好客租房

    项目背景

    近几年,我国经济的跨越性发展速度大家有目共睹,农村都在向城市化发展,农民都踊跃走出家乡投身城市的建设
    中,因此也推动城市房地产和租赁行业的新发展时机。房屋租赁行业的发展离不开房屋租赁政策的支持。
    财政部、国家发改委曾发布通知称,自2015年11月1日起,在全国统一取消和暂停征收包括房屋租赁手续费等在内
    的37项行政事业性收费,以及自2016年1月1日起,取消人力资源社会保障等部门所属公共就业和人才服务机构收
    取的人才集体户口管理服务费。取消和暂停征收上述收费后,有关部门及所属事业单位依法履行管理职能资金投入
    量,安排合理中央在房屋租赁方面的财政预算,保证工作顺利完成,各级政府相关价格管理部门要加强对房地产市
    场的价格监控,消除不合理乱收费现象,坚决取缔多于的政府公共事业单位,升级改革行政人员体系使其精英化,
    严厉杜绝各种乱收费现象。
    北上广地区的城市外来人口众多,租房问题急需解决,租房供不应求,根据数据分析,国内的一线都市每年对房屋
    的需求高达650套,我国在进行第六次人口普及调查中,在北上广和珠三角发达区域,外来人口户数占据成熟人口
    接近一半的比重。2015年北京和上海平均家庭规模约为2.42人。基于房产网站搜索的出租房源数据,北京出租房
    平均合租户数为2.04。如果按照一线城市标准,我国房屋租赁市场有着极大的发展前景

    项目介绍

    好客租房是直接促成房东与租户对接的生活服务平台,它包含房东发布房源,租户多维度寻找房源,智能匹配房
    源,近期行情查询等功能。减少中间环节产生的费用,提高房东与租户匹配的成功率。
    《好客租房项目》采用SOA架构思想进行设计,采用SpringBoot、SpringMVC、Mybaits、Dubbo等技术框架实
    现,好客租房是直接促成房东与租户对接的生活服务平台,他包含房东发布房源,租户多维度寻找房源,智能匹配
    房源,近期行情查询等功能。减少中间环节产生的费用,提高房东与租户匹配的成功率。
    《好客租房项目》融合了RPC、大数据等相技术,如SpringBoot、SpringMVC、Mybaits、Dubbo、React.js、
    GraphQL、RocketMQ、Flume、ELK等技术,实现了移动web应用、微信小程序应用、后台管理应用等功能

    技术架构

    后端架构:SpringBoot+StringMVC+Dubbo+Mybatis+ELK+区块链
    前端架构:React.js+html5+百度地图+微信小程序

    系统架构

    在这里插入图片描述

    后台系统搭建

    前端搭建

    创建工程

    第一步,将资料文件中的itcast-haoke-manage-web.zip解压到指定目录(我的是F:\code\itcast-haoke);
    第二步,导入到Idea中
    第三步,执行命令导入相关的依赖

    tyarn install #安装相关依赖
    #如果tyarn install安装失败(提示Integrity check failed for "antd" (computed integrity doesn't match our records),那么运行此命令
    yarn --update-checksums 
    tyarn start #启动服务
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    修改logo以及版权信息

    全局的布局文件在这,打开看代码,发现,左侧的菜单是自定义组件
    在这里插入图片描述
    打开/components/SiderMenu文件:
    在这里插入图片描述
    在Footer.js文件中修改版权信息:
    在这里插入图片描述

    编写左侧菜单

    根据需求,修改左侧的菜单:
    在这里插入图片描述

          { //房源管理
            path: '/house',
            name: 'house',
            icon: 'home',
            routes: [
              {
                path: '/house/resource',
                name: 'resource',
                component: './haoke/House/Resource'
              },
              {
                path: '/house/addResource',
                name: 'addResource',
                component: './haoke/House/AddResource'
              },
              {
                path: '/house/kanfang',
                name: 'kanfang',
                component: './haoke/House/KanFang'
              },
              {
                path: '/house/zufang',
                name: 'zufang',
                component: './haoke/House/ZuFang'
              }
            ]
          },
    
          { //房东管理
            path: '/fangdong',
            name: 'fangdong',
            icon: 'key',
            routes: [
              {
                path: '/fangdong/list',
                name: 'list',
                component: './haoke/FangDong/List'
              }
            ]
          },
    
          { //用户管理
            path: '/users',
            name: 'users',
            icon: 'user',
            routes: [
              {
                path: '/users/list',
                name: 'list',
                component: './haoke/Users/List'
              }
            ]
          },
    
          { //合约管理
            path: '/heyue',
            name: 'heyue',
            icon: 'file-text',
            routes: [
              {
                path: '/heyue/list',
                name: 'list',
                component: './haoke/HeYue/List'
              }
            ]
          },
    
          { //资讯管理
            path: '/news',
            name: 'news',
            icon: 'message',
            routes: [
              {
                path: '/news/list',
                name: 'list',
                component: './haoke/News/List'
              }
            ]
          },
    
          { //问答管理
            path: '/qa',
            name: 'qa',
            icon: 'question-circle',
            routes: [
              {
                path: '/news/list',
                name: 'list',
                component: './haoke/News/List'
              }
            ]
          },
    
          { //财务管理
            path: '/finance',
            name: 'finance',
            icon: 'money-collect',
            routes: [
              {
                path: '/finance/bill',
                name: 'bill',
                component: './haoke/Finance/Bill'
              },
              {
                path: '/finance/tixian',
                name: 'tixian',
                component: './haoke/Finance/TiXian'
              }
            ]
          },
    
          { //系统管理
            path: '/system',
            name: 'system',
            icon: 'laptop',
            routes: [
              {
                path: '/system/interface',
                name: 'interface',
                component: './haoke/System/Interface'
              },
              {
                path: '/system/dict',
                name: 'dict',
                component: './haoke/System/Dict'
              },
              {
                path: '/system/contract',
                name: 'contract',
                component: './haoke/System/Contract'
              }
            ]
          },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    在src/pages目录下创建haoke文件夹,项目中的页面代码均放在此目录中:
    在这里插入图片描述
    在这里插入图片描述
    修改,进入系统后,默认打开房源管理页面:
    在这里插入图片描述

    新增房源

    数据结构

    楼盘数据(estate)

    字段类型备注
    idLong楼盘id
    nameString楼盘名称
    provinceString所在省
    cityString所在市
    areaString所在区
    addressString具体地址
    yearString建筑年代
    typeString建筑类型
    propertyCostString物业费
    propertyCompanyString物业公司
    developersString开发商
    createddatetime创建时间
    updateddatetime更新时间

    房源数据(houseResources)

    字段类型备注
    idLong房源id
    titleString房源标题,如:南北通透,两室朝南,主卧带阳台
    estateIdLong楼盘id
    buildingNumString楼号(栋)
    buildingUnitString单元号
    buildingFloorNumString门牌号
    rentint租金
    rentMethodint租赁方式,1-整租,2-合租
    paymentMethodint支付方式,1-付一押一,2-付三押一,3-付六押一,4-年付押一,5-其它
    houseTypeString户型,如:2室1厅1卫
    coveredAreaString建筑面积
    useAreaString使用面积
    floorString楼层,如:8/26
    orientationint朝向:东、南、西、北
    decorationString装修,1-精装,2-简装,3-毛坯
    facilitiesString配套设施, 如:1,2,3
    picString图片,最多5张
    descString房源描述,如:出小区门,门口有时代联华超市,餐饮有川菜馆,淮南牛肉汤,黄焖鸡沙县小吃等;可到达亲水湾城市生活广场,里面有儿童乐园,台球室和康桥健身等休闲娱乐;生活广场往北沿御水路往北步行一公里就是御桥路,旁边就是御桥地铁站,地铁站商场…
    contactString联系人
    mobileString手机号
    timeint看房时间,1-上午,2-中午,3-下午,4-晚上,5-全天
    propertyCostString物业费
    createddatetime创建时间
    updateddatetime更新时间

    编写页面“新增房源”

    在这里插入图片描述

    form组件

    在页面中,通过@Form.create()对页面进行了包装,包装之后,会在this.props中增加form对象,该对象将包含有丰富的功能。
    在from表单中,需要通过getFieldDecorator(表单数据双向绑定)方法进行包装注册,才能获取到其值
    在这里插入图片描述

                            <FormItem {...formItemLayout} label="支付方式">
                              {getFieldDecorator('paymentMethod',{initialValue:'1',rules:[{ required: true, message:"此项为必填项" }]})
                              (
                                <Select style={{ width: '50%' }}>
                                  <Option value="1">付一押一</Option>
                                  <Option value="2">付三押一</Option>
                                  <Option value="3">付六押一</Option>
                                  <Option value="4">年付押一</Option>
                                  <Option value="5">其它</Option>
                                </Select>
                              )}
                            </FormItem>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    在getFieldDecorator的参数中可以增加校验规则

    {initialValue:'1',rules:[{ required: true, message:"此项为必填项" }]}
    
    • 1

    表单提交

    表单的提交通过submit按钮完成,通过onSubmit方法进行拦截处理。
    在这里插入图片描述

        handleSubmit = e => {
            const { dispatch, form } = this.props;
            e.preventDefault();
          console.log(this.state.fileList);
            form.validateFieldsAndScroll((err, values) => {
                if (!err) {
    
                  if(values.facilities){
                    values.facilities = values.facilities.join(",");
                  }
                  if(values.floor_1 && values.floor_2){
                    values.floor = values.floor_1 + "/" + values.floor_2;
    
                  }
    
                  values.houseType = values.houseType_1 + "室" + values.houseType_2 + "厅"
                                     + values.houseType_3 + "卫" + values.houseType_4 + "厨"
                                     + values.houseType_2 + "阳台";
                  delete values.floor_1;
                  delete values.floor_2;
                  delete values.houseType_1;
                  delete values.houseType_2;
                  delete values.houseType_3;
                  delete values.houseType_4;
                  delete values.houseType_5;
    
    
    
                  dispatch({
                        type: 'form/submitRegularForm',
                        payload: values,
                    });
                }
            });
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    通过form.validateFieldsAndScroll()对表单进行校验,通过values获取表单中输入的值。通过dispatch()调用model中定义的方法。

    自动完成

    在这里插入图片描述

    const estateMap = new Map([
      ['中远两湾城','1001|上海市,上海市,普陀区,远景路97弄'],
      ['上海康城','1002|上海市,上海市,闵行区,莘松路958弄'],
      ['保利西子湾','1003|上海市,上海市,松江区,广富林路1188弄'],
      ['万科城市花园','1004|上海市,上海市,闵行区,七莘路3333弄2区-15区'],
      ['上海阳城','1005|上海市,上海市,闵行区,罗锦路888弄']
    ]);
    
    <FormItem {...formItemLayout} label="楼盘名称">
                                <AutoComplete
                                  style={{ width: '100%' }}
                                  dataSource={this.state.estateDataSource}
                                  placeholder="搜索楼盘"
                                  onSelect={(value, option)=>{
                                    let v = estateMap.get(value);
                                    this.setState({
                                      estateAddress: v.substring(v.indexOf('|')+1),
                                      estateId : v.substring(0,v.indexOf('|'))
                                    });
                                  }}
                                  onSearch={this.handleSearch}
                                  filterOption={(inputValue, option) => option.props.children.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1}
                                />
                            </FormItem>
    
        handleSearch = (value)=>{
          let arr = new Array();
          if(value.length > 0 ){
            estateMap.forEach((v, k) => {
              if(k.startsWith(value)){
                arr.push(k);
              }
            });
          }
          this.setState({
            estateDataSource: arr
          });
        } ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述
    在这里插入图片描述

    图片上传

    图片上传通过自定义组件PicturesWall完成,在PicturesWall中,通过Upload组件实现

    在代码实现中,需要解决的问题是:父组件如何获取子组件中的数据。
    解决思路:父组件通过属性的方式进行引用子组件,在bind方法中改变this的引用为父组件,在子组件中,通过this.props获取传入的函数,进行调用,即可把数据传递到父组件中
    在这里插入图片描述

     <FormItem {...formItemLayout} label="上传室内图">
                                <PicturesWall handleFileList={this.handleFileList.bind(this)}/>
                            </FormItem>
    
    • 1
    • 2
    • 3
        handleChange = ({ fileList }) => {
          this.setState({ fileList });
          this.props.handleFileList(this.state.fileList);
        }
    
    • 1
    • 2
    • 3
    • 4
      handleFileList = (obj)=>{
        console.log(obj, "图片列表");
      }
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    源代码

    链接:https://pan.baidu.com/s/1VJZwJdnMGNzeuWH4nbBDRw?pwd=3i3x
    提取码:3i3x
    –来自百度网盘超级会员V3的分享

  • 相关阅读:
    黑马点评-07缓存击穿问题(热点key失效)及解决方案,互斥锁和设置逻辑过期时间
    NC52867 Highway (树的直径定理)
    Kafka - This server does not host this topic-partition
    mybatis-plus自动填充
    基于gunicorn部署flask项目
    【C# 调试】.net中的 .pdb文件是什么,有什么用
    聊聊复杂网络环境下hdfs的BlockMissingException异常|参数dfs.client.use.datanode.hostname
    兼容iphone(ios)圆角(border-radius)不起作用的问题
    数据结构—— AVL树
    Effective C++改善程序与设计的55个具体做法 3. 资源管理
  • 原文地址:https://blog.csdn.net/peacezhi/article/details/126001951