zhaogongxue 1 year ago
parent
commit
2c617ae215
100 changed files with 30885 additions and 0 deletions
  1. 26 0
      .hbuilderx/launch.json
  2. 0 0
      common/Easemob-chat-4.0.7.js
  3. 31 0
      common/amap-wx.js
  4. 97 0
      common/echartDate.js
  5. 76 0
      common/http.interceptor.js
  6. 35 0
      common/share.js
  7. 3 0
      common/url.js
  8. 348 0
      common/utils.js
  9. 23 0
      common/wss.js
  10. BIN
      components/.DS_Store
  11. 530 0
      components/biaofun-datetime-picker/biaofun-datetime-picker.vue
  12. 30 0
      components/biaofun-datetime-picker/使用说明.md
  13. 147 0
      components/gf-chat/gf-chat.vue
  14. 281 0
      components/gf-goods/gf-goods.vue
  15. 151 0
      components/gf-scroll/gf-scroll.vue
  16. 350 0
      components/gf-search/gf-search.vue
  17. 105 0
      components/gf-tabbar/gf-tabbar.vue
  18. 129 0
      components/gf-tel/gf-tel.vue
  19. 99 0
      components/gf-yinsi/gf-yinsi.vue
  20. BIN
      hybrid/html.zip
  21. BIN
      hybrid/html/img/chongzhi.png
  22. BIN
      hybrid/html/img/kefu.png
  23. BIN
      hybrid/html/img/rizhao.png
  24. BIN
      hybrid/html/img/share.png
  25. 49 0
      hybrid/html/index.html
  26. 449 0
      pages/baobei/baobei.vue
  27. 162 0
      pages/index/broker.vue
  28. 199 0
      pages/index/change-city.vue
  29. 251 0
      pages/index/chat.vue
  30. 216 0
      pages/index/fuli-info.vue
  31. 96 0
      pages/index/fuli.vue
  32. 55 0
      pages/index/home.vue
  33. 1030 0
      pages/index/houses-info.vue
  34. 735 0
      pages/index/index.vue
  35. 401 0
      pages/index/info.vue
  36. 75 0
      pages/index/news-info.vue
  37. 181 0
      pages/index/news.vue
  38. 392 0
      pages/index/pk-info.vue
  39. 292 0
      pages/index/pk-list.vue
  40. 183 0
      pages/index/pk-search.vue
  41. 439 0
      pages/index/report.vue
  42. 213 0
      pages/index/search.vue
  43. 117 0
      pages/index/video.vue
  44. 298 0
      pages/mine/baobei-info.vue
  45. 88 0
      pages/mine/baobei-list.vue
  46. 109 0
      pages/mine/jifen.vue
  47. 181 0
      pages/mine/login.vue
  48. 583 0
      pages/mine/mine.vue
  49. 124 0
      pages/mine/setting.vue
  50. 141 0
      pages/mine/userinfo.vue
  51. 74 0
      pages/mine/xieyi.vue
  52. 109 0
      pages/mine/yongjin.vue
  53. 25 0
      pages/video/info.vue
  54. 151 0
      pages/video/video.vue
  55. 242 0
      pagesA/components/echarts-uniapp/echarts-uniapp.vue
  56. 0 0
      pagesA/components/echarts-uniapp/echarts.min.js
  57. 105 0
      pagesA/components/echarts-uniapp/wx-canvas.js
  58. 172 0
      pagesA/index/allHouses.vue
  59. 221 0
      pagesA/index/counter-info.vue
  60. 704 0
      pagesA/index/counter.vue
  61. 734 0
      pagesA/index/dataCenter.vue
  62. 113 0
      pagesA/index/kefu.vue
  63. 169 0
      pagesA/index/newHouses.vue
  64. 751 0
      pagesA/index/rizhao.vue
  65. 116 0
      pagesA/index/webview.vue
  66. 482 0
      pagesA/index/wenda-info.vue
  67. 757 0
      pagesA/index/wenda-list.vue
  68. 659 0
      pagesA/index/yifang.vue
  69. BIN
      pagesA/static/3d-bg.png
  70. BIN
      pagesA/static/3d-btn.png
  71. BIN
      pagesA/static/chongzhi.png
  72. BIN
      pagesA/static/kefu.png
  73. BIN
      pagesA/static/rizhao.png
  74. BIN
      pagesA/static/share.png
  75. 1295 0
      platforms/h5/common/OrbitControls.js
  76. 568 0
      platforms/h5/common/obj/MTLLoader.js
  77. 905 0
      platforms/h5/common/obj/OBJLoader.js
  78. 13013 0
      platforms/h5/common/three.js
  79. BIN
      static/.DS_Store
  80. BIN
      static/images/.DS_Store
  81. BIN
      static/images/baobei-img.png
  82. BIN
      static/images/baobei.png
  83. BIN
      static/images/baobei1.png
  84. BIN
      static/images/code.png
  85. BIN
      static/images/dataCenter1-1.png
  86. BIN
      static/images/dijia-bg.png
  87. BIN
      static/images/explain.png
  88. BIN
      static/images/head.png
  89. BIN
      static/images/hot.png
  90. BIN
      static/images/huifu.png
  91. BIN
      static/images/index-img1.png
  92. BIN
      static/images/index-img2.png
  93. BIN
      static/images/index.png
  94. BIN
      static/images/index1.png
  95. BIN
      static/images/jifen.png
  96. BIN
      static/images/jindu.png
  97. BIN
      static/images/jindu1.png
  98. BIN
      static/images/mine-tabs1.png
  99. BIN
      static/images/mine-tabs2.png
  100. BIN
      static/images/mine-tabs3.png

+ 26 - 0
.hbuilderx/launch.json

@@ -0,0 +1,26 @@
+{
+    // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+    // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version" : "0.0",
+    "configurations" : [
+        {
+        	"default" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"mp-toutiao" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"mp-weixin" : 
+        	{
+        		"launchtype" : "local"
+        	},
+        	"type" : "uniCloud"
+        },
+        {
+            "playground" : "custom",
+            "type" : "uni-app:app-android"
+        }
+    ]
+}

File diff suppressed because it is too large
+ 0 - 0
common/Easemob-chat-4.0.7.js


+ 31 - 0
common/amap-wx.js

@@ -0,0 +1,31 @@
+function AMapWX(a){this.key=a.key;this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};this.MeRequestConfig={key:a.key,serviceName:"https://restapi.amap.com/rest/me"}}
+AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(c){c=c.longitude+","+c.latitude;wx.setStorage({key:"userLocation",data:c});b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(d){d.data&&b(d.data)}});a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getMEKeywordsSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.city&&(d.city=b.city);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);b.sig&&(d.sig=
+b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/local",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEIdSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.id&&(d.id=b.id);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/id",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&
+0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEPolygonSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.polygon&&(d.polygon=b.polygon);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);
+b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/polygon",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEaroundSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.center&&(d.center=b.center);b.radius&&(d.radius=b.radius);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&
+(d.pageSize=b.pageSize);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/around",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getGeo=function(a){var b=this.requestConfig,c=a.options;b={key:this.key,extensions:"all",s:b.s,platform:b.platform,appname:this.key,sdkversion:b.sdkversion,logversion:b.logversion};c.address&&(b.address=c.address);c.city&&(b.city=c.city);c.batch&&(b.batch=c.batch);c.sig&&(b.sig=c.sig);wx.request({url:"https://restapi.amap.com/v3/geocode/geo",data:b,method:"GET",header:{"content-type":"application/json"},success:function(d){(d=d.data)&&d.status&&"1"===d.status?a.success(d):a.fail({errCode:"0",
+errMsg:d})},fail:function(d){a.fail({errCode:"0",errMsg:d.errMsg||""})}})};
+AMapWX.prototype.getRegeo=function(a){function b(d){var e=c.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:c.key,location:d,extensions:"all",s:e.s,platform:e.platform,appname:c.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){g=g.data.regeocode;var h=g.addressComponent,f=[],k=g.roads[0].name+"\u9644\u8fd1",m=d.split(",")[0],n=d.split(",")[1];if(g.pois&&
+g.pois[0]){k=g.pois[0].name+"\u9644\u8fd1";var l=g.pois[0].location;l&&(m=parseFloat(l.split(",")[0]),n=parseFloat(l.split(",")[1]))}h.provice&&f.push(h.provice);h.city&&f.push(h.city);h.district&&f.push(h.district);h.streetNumber&&h.streetNumber.street&&h.streetNumber.number?(f.push(h.streetNumber.street),f.push(h.streetNumber.number)):f.push(g.roads[0].name);f=f.join("");a.success([{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:k,longitude:m,latitude:n,id:0,regeocodeData:g}])}else a.fail({errCode:g.data.infocode,
+errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this;a.location?b(a.location):c.getWxLocation(a,function(d){b(d)})};
+AMapWX.prototype.getWeather=function(a){function b(g){var h="base";a.type&&"forecast"==a.type&&(h="all");wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:d.key,city:g,extensions:h,s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(f){if(f.data.status&&"1"==f.data.status)if(f.data.lives){if((f=f.data.lives)&&0<f.length){f=f[0];var k={city:{text:"\u57ce\u5e02",data:f.city},
+weather:{text:"\u5929\u6c14",data:f.weather},temperature:{text:"\u6e29\u5ea6",data:f.temperature},winddirection:{text:"\u98ce\u5411",data:f.winddirection+"\u98ce"},windpower:{text:"\u98ce\u529b",data:f.windpower+"\u7ea7"},humidity:{text:"\u6e7f\u5ea6",data:f.humidity+"%"}};k.liveData=f;a.success(k)}}else f.data.forecasts&&f.data.forecasts[0]&&a.success({forecast:f.data.forecasts[0]});else a.fail({errCode:f.data.infocode,errMsg:f.data.info})},fail:function(f){a.fail({errCode:"0",errMsg:f.errMsg||""})}})}
+function c(g){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:d.key,location:g,extensions:"all",s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(h){if(h.data.status&&"1"==h.data.status){h=h.data.regeocode;if(h.addressComponent)var f=h.addressComponent.adcode;else h.aois&&0<h.aois.length&&(f=h.aois[0].adcode);b(f)}else a.fail({errCode:h.data.infocode,errMsg:h.data.info})},
+fail:function(h){a.fail({errCode:"0",errMsg:h.errMsg||""})}})}var d=this,e=d.requestConfig;a.city?b(a.city):d.getWxLocation(a,function(g){c(g)})};
+AMapWX.prototype.getPoiAround=function(a){function b(e){e={key:c.key,location:e,s:d.s,platform:d.platform,appname:c.key,sdkversion:d.sdkversion,logversion:d.logversion};a.querytypes&&(e.types=a.querytypes);a.querykeywords&&(e.keywords=a.querykeywords);wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){if((g=g.data)&&g.pois){for(var h=[],f=0;f<g.pois.length;f++){var k=0==
+f?a.iconPathSelected:a.iconPath;h.push({latitude:parseFloat(g.pois[f].location.split(",")[1]),longitude:parseFloat(g.pois[f].location.split(",")[0]),iconPath:k,width:22,height:32,id:f,name:g.pois[f].name,address:g.pois[f].address})}a.success({markers:h,poisData:g.pois})}}else a.fail({errCode:g.data.infocode,errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this,d=c.requestConfig;a.location?b(a.location):c.getWxLocation(a,function(e){b(e)})};
+AMapWX.prototype.getStaticmap=function(a){function b(e){c.push("location="+e);a.zoom&&c.push("zoom="+a.zoom);a.size&&c.push("size="+a.size);a.scale&&c.push("scale="+a.scale);a.markers&&c.push("markers="+a.markers);a.labels&&c.push("labels="+a.labels);a.paths&&c.push("paths="+a.paths);a.traffic&&c.push("traffic="+a.traffic);e="https://restapi.amap.com/v3/staticmap?"+c.join("&");a.success({url:e})}var c=[];c.push("key="+this.key);var d=this.requestConfig;c.push("s="+d.s);c.push("platform="+d.platform);
+c.push("appname="+d.appname);c.push("sdkversion="+d.sdkversion);c.push("logversion="+d.logversion);a.location?b(a.location):this.getWxLocation(a,function(e){b(e)})};
+AMapWX.prototype.getInputtips=function(a){var b=Object.assign({},this.requestConfig);a.location&&(b.location=a.location);a.keywords&&(b.keywords=a.keywords);a.type&&(b.type=a.type);a.city&&(b.city=a.city);a.citylimit&&(b.citylimit=a.citylimit);wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.tips&&a.success({tips:c.data.tips})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||
+""})}})};
+AMapWX.prototype.getDrivingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.waypoints&&(b.waypoints=a.waypoints);a.avoidpolygons&&(b.avoidpolygons=a.avoidpolygons);a.avoidroad&&(b.avoidroad=a.avoidroad);wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths,
+taxi_cost:c.data.route.taxi_cost||""})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getWalkingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getTransitRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.city&&(b.city=a.city);a.cityd&&(b.cityd=a.cityd);wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&(c=c.data.route,a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||
+"",transits:c.transits}))},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getRidingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/riding",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};module.exports.AMapWX=AMapWX;

+ 97 - 0
common/echartDate.js

@@ -0,0 +1,97 @@
+var getDataCenter = function(xAxis = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], yAxis = [820, 1132, 901, 1134, 890, 1330, 920, 1000, 800, 900, 800, 1000],name) {
+	// console.log((uni.getSystemInfoSync().screenWidth - 50) / yAxis.length);
+	return {
+		grid: {
+			top: '30px',
+			bottom: '30px',
+			left: '24px',
+			right: '24px'
+		},
+		tooltip: {
+			trigger: 'axis',
+			axisPointer: {
+				type: 'shadow'
+			}
+		},
+		xAxis: {
+			type: 'category',
+			boundaryGap: false,
+			data: xAxis, //['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
+			show: true,
+			axisLine: {
+				show: false,
+			},
+			axisLabel: {
+				fontSize: 9
+			},
+			splitLine: {
+				//x网格样式
+				show: true,
+				lineStyle: {
+					color: "rgba(31,126,255,0.4)",
+					type: "dashed",
+					width: "1",
+				},
+			},
+			axisTick: {
+				show: false
+			}
+		},
+		yAxis: {
+			type: 'value',
+			show: false
+		},
+		axisLine: {
+			//是否显示以及样式设置
+			show: true,
+			onZero: true, //表示 X 轴或者 Y 轴的轴线是否在另一个轴的 0 刻度上,只有在另一个轴为数值轴且包含 0 刻度时有效。
+			lineStyle: {
+				color: '#7E85AB',
+				type: 'dashed',
+			}
+		},
+		series: [{
+			name:name,
+			data: yAxis, //[820, 1132, 901, 1134, 890, 1330, 920, 1000, 800, 900, 800, 1000],
+			type: 'line',
+			areaStyle: {
+				color: {
+					type: 'linear',
+					x: 0,
+					y: 0,
+					x2: 0,
+					y2: 1,
+					colorStops: [{
+						offset: 0,
+						color: '#1F7EFF' // 0% 处的颜色
+					}, {
+						offset: 1,
+						color: '#F8F8F8' // 100% 处的颜色
+					}],
+					global: false // 缺省为 false
+				}
+			},
+			itemStyle: {
+				normal: {
+					label: {
+						show: true,
+						color: '#1F7EFF',
+						offset: [0, -2],
+						fontSize: 12,
+						width: (uni.getSystemInfoSync().screenWidth - 50) / yAxis.length,
+						overflow: 'truncate'
+					}
+				}
+			},
+			lineStyle: {
+				color: '#1F7EFF'
+			},
+			symbol: 'circle',
+			symbolSize: 6
+		}]
+	}
+}
+
+export default {
+	getDataCenter
+}

+ 76 - 0
common/http.interceptor.js

@@ -0,0 +1,76 @@
+import url from "./url.js"
+const install = (Vue, vm) => {
+	Vue.prototype.$u.http.setConfig({
+		baseUrl: url, // 请求的本域名
+		loadingText: '加载中...',
+		loadingTime: 800,
+		showLoading: true, // 是否显示请求中的loading
+		loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
+		originalData: true, // 是否在拦截器中返回服务端的原始数据
+		// 配置请求头信息
+		header: {
+			'content-type': 'application/json;charset=UTF-8',
+			'version': 'v1'
+		},
+	});
+	// 请求拦截部分,如配置,每次请求前都会执行
+	Vue.prototype.$u.http.interceptor.request = (config) => {
+		// 引用token
+		// 方式一,存放在vuex的token,假设使用了uView封装的vuex方式
+		// 见:https://uviewui.com/components/globalVariable.html
+		// config.header.token = vm.token;
+
+		// 方式二,如果没有使用uView封装的vuex方法,那么需要使用$store.state获取
+		// config.header.token = vm.$store.state.token;
+
+		// 方式三,如果token放在了globalData,通过getApp().globalData获取
+		// config.header.token = getApp().globalData.username;
+
+		// 方式四,如果token放在了Storage本地存储中,拦截是每次请求都执行的
+		// 所以哪怕您重新登录修改了Storage,下一次的请求将会是最新值
+		const token = uni.getStorageSync('token');
+		config.header.Authorization = token;
+
+		// 可以对某个url进行特别处理,此url参数为this.$u.get(url)中的url值
+		// if(config.url == '/user/login') config.header.noToken = true;
+		// 最后需要将config进行return
+		return config;
+		// 如果return一个false值,则会取消本次请求
+		// if(config.url == '/user/rest') return false; // 取消某次请求
+	}
+	// 响应拦截,如配置,每次请求结束都会执行本方法
+	Vue.prototype.$u.http.interceptor.response = (res) => {
+		if (res.statusCode == 200) {
+			// res为服务端返回值,可能有code,result等字段
+			// 这里对res.result进行返回,将会在this.$u.post(url).then(res => {})的then回调中的res的到
+			// 如果配置了originalData为true,请留意这里的返回值
+			return res.data;
+		} else {
+			// 假设201为token失效,这里跳转登录
+			if (res.statusCode == 500) {
+				// var html = res.data
+				// var start = html.indexOf('<h1>')
+				// var end = html.indexOf('</h1>')
+				// var title = html.substring(start + 4, end)
+
+				// var start1 = html.indexOf('</abbr> in <a class="toggle" title=')
+				// var end1 = html.indexOf('</a></h2>')
+				// var title1 = html.substring(start1 + 35, end1)
+
+				// uni.showModal({
+				// 	title: `网络错误:${res.statusCode}`,
+				// 	content: `位置:${title1}\r\n 标题:${title}`
+				// })
+			} else {
+				uni.showModal({
+					content: `未知错误:${res.statusCode}`
+				})
+			}
+			return false;
+		}
+	}
+}
+
+export default {
+	install
+}

+ 35 - 0
common/share.js

@@ -0,0 +1,35 @@
+export default {
+	data() {
+		return {
+			// 默认的全局分享内容
+			share: {
+				title: '晨照选房',//分享时标题名字
+				path: 'pages/index/index', // 全局分享的路径,比如 首页
+				imageUrl: '../../static/logo.jpg', // 全局分享的图片(路径可本地可网络)
+			}
+		}
+	},
+	// 定义全局分享
+	// 1.发送给朋友
+	onShareAppMessage(res) {
+		this.$u.get('/api/Member/transmit').then(res => {
+			
+		})
+		return {
+			title: this.share.title,
+			path: this.share.path,
+			imageUrl: this.share.imageUrl,
+		}
+	},
+	//2.分享到朋友圈
+	onShareTimeline(res) {
+		this.$u.get('/api/Member/transmit').then(res => {
+			
+		})
+		return {
+			title: this.share.title,
+			path: this.share.path,
+			imageUrl: this.share.imageUrl,
+		}
+	},
+}

+ 3 - 0
common/url.js

@@ -0,0 +1,3 @@
+// var url = 'https://jzgft.com'
+var url = 'https://goufangtong.hdlkeji.com'
+export default url

+ 348 - 0
common/utils.js

@@ -0,0 +1,348 @@
+/**
+ * @说明:工具集
+ * @作者:陈万照
+ * @公司:山东标梵互动技术有限公司
+ * @官网:http://biaofun.com/
+ * @版本:v1.0.0
+ * @时间:2020年4月28日11:28:13
+ */
+export default {
+	/**
+	 * 同步 try catch 的进一步封装处理
+	 * 使用方法:
+	 * let [err, res] = await this.$utils.asyncTasks(Promise函数);
+	 * if(res) 成功
+	 * if(err) 失败
+	 */
+	asyncTasks(promise) {
+		return promise.then(data => {
+			return [null, data];
+		}).catch(err => [err]);
+	},
+
+	/**
+	 * 精确判断数据是否是 Object 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isObject(val) {
+		return Object.prototype.toString.call(val) === '[object Object]' && val !== null && val !== undefined;
+	},
+
+	/**
+	 * 判断数据是否是 Array 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isArray(val) {
+		return Object.prototype.toString.call(val) === '[object Array]';
+	},
+
+	/**
+	 * 判断数据是否是 String 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isString(val) {
+		return Object.prototype.toString.call(val) === '[object String]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Date 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isDate(val) {
+		return Object.prototype.toString.call(val) === '[object Date]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Function 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isFunction(val) {
+		return Object.prototype.toString.call(val) === '[object Function]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Number 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isNumber(val) {
+		return Object.prototype.toString.call(val) === '[object Number]';
+	},
+
+	/**
+	 * 精确判断数据是否是 Boolean 类型
+	 * @param {Any} val 要判断的数据
+	 * @returns {Boolean} true:是;false:不是;
+	 */
+	isBoolean(val) {
+		return Object.prototype.toString.call(val) === '[object Boolean]';
+	},
+
+	/**
+	 * 判断 URL 是否是绝对 URL。
+	 * @param {String} url 要判断的 URL
+	 * @return {Boolean} true:是绝对URL;false:不是绝对URL;
+	 */
+	isAbsoluteURL(url) {
+		// 如果 URL 以 “<scheme>://” 或 “//”(协议相对URL)开头,则认为它是绝对的
+		// RFC 3986 将方案名称定义为以字母开头的字符序列,然后是字母,数字,加号,句点或连字符的任意组合
+		return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
+	},
+
+	/**
+	 * 合并 baseURL 和相对 URL 成一个完整的 URL
+	 * @param {String} baseURL baseURL
+	 * @param {String} relativeURL 相对 URL
+	 * @returns {String} 返回组合后的完整 URL
+	 */
+	combineURLs(baseURL, relativeURL) {
+		return relativeURL && this.isString(relativeURL) && this.isString(baseURL) ? baseURL.replace(/\/+$/, '') + '/' +
+			relativeURL.replace(/^\/+/, '') : baseURL;
+	},
+
+	/**
+	 * 深度合并对象,只支持合并两个对象,该方法不会改变原有的对象
+	 * @param {Object} FirstOBJ 第一个对象
+	 * @param {Object} SecondOBJ 第二个对象
+	 * @return {Object} 返回深度合并后的对象
+	 */
+	deepMargeObject(FirstOBJ, SecondOBJ) {
+		let ResultOBJ = {};
+		for (let key in FirstOBJ) {
+			ResultOBJ[key] = ResultOBJ[key] && ResultOBJ[key].toString() === "[object Object]" ? this.deepMargeObject(ResultOBJ[
+				key], FirstOBJ[key]) : ResultOBJ[key] = FirstOBJ[key];
+		}
+		for (let key in SecondOBJ) {
+			ResultOBJ[key] = ResultOBJ[key] && ResultOBJ[key].toString() === "[object Object]" ? this.deepMargeObject(ResultOBJ[
+				key], SecondOBJ[key]) : ResultOBJ[key] = SecondOBJ[key];
+		}
+		return ResultOBJ;
+	},
+	
+	/**
+	 * 生成指定长度的随机字符串
+	 * @param {Number} min 最小程度
+	 * @param {Number} max 最大长度 
+	 * @return {String} 返回生成的字符串
+	 */
+	randomString(min, max) {
+		let returnStr = "",
+			range = (max ? Math.round(Math.random() * (max - min)) + min : min),
+			arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+				'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
+				'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+			];
+		for (let i = 0; i < range; i++) {
+			let index = Math.round(Math.random() * (arr.length - 1));
+			returnStr += arr[index];
+		}
+		return returnStr;
+	},
+
+	/**
+	 * 格式化日期
+	 * @param {Date|String} date 日期或日期字符串
+	 */
+	formatDate(date) {
+		let YYYY = null;
+		let M = null;
+		let MM = null;
+		let D = null;
+		let DD = null;
+		let h = null;
+		let hh = null;
+		let m = null;
+		let mm = null;
+		let s = null;
+		let ss = null;
+		let ms = null;
+		let ms2 = null;
+		let ms3 = null;
+		let ms4 = null;
+		let dt = null;
+
+		// 如果 date 是 String 类型
+		if (date && this.isString(date)) {
+			// 真机运行时,如果直接用 new Date('YYYY-MM-DD hh:mm:ss') 会报 Invalid Date 错误,所以采用下面的方式创建日期
+			let dtArr = date.replace(/\//g, '.').replace(/-/g, '.').replace(/:/g, '.').replace(/T/g, ' ').replace(' ', '.').replace(
+				'Z', '').split('.');
+
+			let year = 2020;
+			let month = 12;
+			let day = 18;
+			let hour = 0;
+			let minute = 0;
+			let second = 0;
+			let millisecond = 0;
+			
+			// 年
+			if (dtArr.length > 0 && !isNaN(dtArr[0])) {
+				year = parseInt(dtArr[0]);
+			}
+			// 月
+			if (dtArr.length > 1 && !isNaN(dtArr[1])) {
+				month = parseInt(dtArr[1]);
+			}
+			// 日
+			if (dtArr.length > 2 && !isNaN(dtArr[2])) {
+				day = parseInt(dtArr[2]);
+			}
+			// 时
+			if (dtArr.length > 3 && !isNaN(dtArr[3])) {
+				hour = parseInt(dtArr[3]);
+			}
+			// 分
+			if (dtArr.length > 4 && !isNaN(dtArr[4])) {
+				minute = parseInt(dtArr[4]);
+			}
+			// 秒
+			if (dtArr.length > 5 && !isNaN(dtArr[5])) {
+				second = parseInt(dtArr[5]);
+			}
+			// 毫秒
+			if (dtArr.length > 6 && !isNaN(dtArr[6])) {
+				millisecond = parseInt(dtArr[6]);
+			}
+
+			date = new Date(year, month - 1, day, hour, minute, second, millisecond);
+		}
+
+		// 如果 date 是 Date 类型
+		if (date && this.isDate(date)) {
+			YYYY = date.getFullYear();
+			M = date.getMonth() + 1;
+			MM = M >= 10 ? M : '0' + M;
+			D = date.getDate();
+			DD = D >= 10 ? D : '0' + D;
+			h = date.getHours();
+			hh = h >= 10 ? h : '0' + h;
+			m = date.getMinutes();
+			mm = m >= 10 ? m : '0' + m;
+			s = date.getSeconds();
+			ss = s >= 10 ? s : '0' + s;
+			ms = date.getMilliseconds();
+			ms2 = ms;
+			ms3 = ms;
+			ms4 = ms;
+			if (ms < 10) {
+				ms2 = '0' + ms;
+				ms3 = '00' + ms;
+				ms4 = '000' + ms;
+			} else if (ms < 100) {
+				ms3 = '0' + ms;
+				ms4 = '00' + ms;
+			} else {
+				ms4 = '0' + ms;
+			}
+		}
+
+		// 返回的数据对象
+		let result = {
+			YYYY: YYYY,
+			MM: MM,
+			M: M,
+			DD: DD,
+			D: D,
+			hh: hh,
+			h: h,
+			mm: mm,
+			m: m,
+			ss: ss,
+			s: s,
+			ms: ms,
+			ms2: ms2,
+			ms3: ms3,
+			ms4: ms4,
+			dt: date,
+			f1: `${YYYY}-${MM}-${DD}`,
+			f2: `${YYYY}年${M}月${D}日`,
+			f3: `${YYYY}-${M}-${D} ${hh}:${mm}`,
+			f4: `${h}:${m}:${s}`,
+			f5: `${MM}-${DD}`,
+			f6: `${YYYY}-${MM}`,
+			f7: `${YYYY}年${M}月`,
+			f8: `${h}:${m}`,
+			f9: `${M}月${D}日`,
+			notes: 'YYYY(年),MM(月,补0),M(月,不补0),DD(日,补0),D(日,不补0),hh(时,补0),h(时,不补0),mm(分,补0),m(分,不补0),ss(秒,补0),s(秒,不补0),ms(毫秒,不补0),ms2(毫秒,补0到2位),ms3(毫秒,补0到3位),ms4(毫秒,补0到4位),其余的f1,f2,... 看格式就知道了!'
+		};
+		return result;
+	},
+
+	/**
+	 * 数字转中文
+	 * @param {Number} num 数字
+	 */
+	numberToChinese(num) {
+		if (!/^\d*(\.\d*)?$/.test(num)) return "Number is wrong!";
+		let AA = new Array("零", "一", "二", "三", "四", "五", "六", "七", "八", "九");
+		let BB = new Array("", "十", "百", "千", "万", "亿", "点", "");
+		let a = ("" + num).replace(/(^0*)/g, "").split("."),
+			k = 0,
+			re = "";
+		for (let i = a[0].length - 1; i >= 0; i--) {
+			switch (k) {
+				case 0:
+					re = BB[7] + re;
+					break;
+				case 4:
+					if (!new RegExp("0{4}\\d{" + (a[0].length - i - 1) + "}$").test(a[0]))
+						re = BB[4] + re;
+					break;
+				case 8:
+					re = BB[5] + re;
+					BB[7] = BB[5];
+					k = 0;
+					break;
+			}
+			if (k % 4 == 2 && a[0].charAt(i + 2) != 0 && a[0].charAt(i + 1) == 0) re = AA[0] + re;
+			if (a[0].charAt(i) != 0) re = AA[a[0].charAt(i)] + BB[k % 4] + re;
+			k++;
+		}
+		if (a.length > 1) //加上小数部分(如果有小数部分) 
+		{
+			re += BB[6];
+			for (let i = 0; i < a[1].length; i++) re += AA[a[1].charAt(i)];
+		}
+		return re;
+	},
+	
+	/**
+	 * 计算两个经纬度点之间的距离
+	 * @param {Number} lng1 第一个点的经度
+	 * @param {Number} lat1 第一个点的纬度
+	 * @param {Number} lng2 第二个点的经度
+	 * @param {Number} lat2 第二个点的纬度
+	 */
+	calcDistance(lng1, lat1, lng2, lat2) {
+		var radLat1 = lat1 * Math.PI / 180.0;
+		var radLat2 = lat2 * Math.PI / 180.0;
+		var a = radLat1 - radLat2;
+		var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
+		var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
+			Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
+		s = s * 6378.137; // EARTH_RADIUS;
+		s = Math.round(s * 10000) / 10000;
+		return s;
+	},
+	
+	/**
+	 * 获取数组最小值的下标
+	 * @param {Array} arr 数组
+	 */
+	getArrayMixValueIndex(arrar) {
+		let min = arrar[0];
+		let index = 0;
+		for (let i = 0; i < arrar.length; i++) {
+			if (min > arrar[i]) {
+				min = arrar[i];
+				index = i;
+			}
+		}
+		return index;
+	}
+}

+ 23 - 0
common/wss.js

@@ -0,0 +1,23 @@
+import SDK from "./Easemob-chat-4.0.7.js"; // 3.0sdk
+
+const install = (Vue, vm) => {
+	//实例化SDK对象
+	const WebIM = SDK;
+
+	WebIM.conn = new WebIM.connection({
+		appKey: "1132230508163855#demo",
+		https: true, //是否使用HTTPS
+		url: "wss://im-api-wechat.easecdn.com/websocket", // socket server (3.0 SDK)
+		apiUrl: "https://a1.easecdn.com", // rest server
+		heartBeatWait: 30000, //心跳间隔
+		autoReconnectNumMax: 5, //自动重连次数
+		useOwnUploadFun: false, // 是否使用自己的上传方式(如将图片文件等上传到自己的服务器,构建消息时只传url)
+		delivery:true
+	});
+	
+	Vue.prototype.$WebIM = WebIM
+}
+
+export default {
+	install
+}

BIN
components/.DS_Store


+ 530 - 0
components/biaofun-datetime-picker/biaofun-datetime-picker.vue

@@ -0,0 +1,530 @@
+<!-- 
+ * @插件:日期时间选择器
+ * @作者:陈万照
+ * @公司:山东标梵互动信息技术有限公司
+ * @官网:http://biaofun.com/
+ * @微信:C207668802
+ * @QQ:207668802
+ * @邮箱:cwz@biaofun.com || 207668802@qq.com
+ * @版本:v1.0.8
+ -->
+<template>
+	<view class="datatime">
+		<picker mode="multiSelector" :range="range" range-key="text" @change="change" @columnchange="columnchange" :value="value" :disabled="disabled">
+			<view class="content" :class="{ placeholder: !dateStr }">
+				<text>{{ dateStr ? dateStr : placeholder }}</text>
+			</view>
+		</picker>
+	</view>
+</template>
+
+<script>
+import utils from '@/common/utils.js'; // 封装的工具集
+export default {
+	/**
+	 * 数据
+	 */
+	props: {
+		// 是否禁用
+		disabled: {
+			type: Boolean,
+			default: false
+		},
+
+		// 占位符
+		placeholder: {
+			type: String,
+			default: '请选择日期时间'
+		},
+
+		// 表示有效日期时间范围的开始,
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		start: {
+			type: String,
+			default: '1970-1-1 00:00'
+		},
+		// 表示有效日期时间范围的结束
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		end: {
+			type: String,
+			default: '2300-1-1 00:00'
+		},
+
+		// 表示选择器的粒度,有效值:year | month | day | hour | minute
+		fields: {
+			type: String,
+			default: 'minute'
+		},
+
+		// 默认值
+		// 字符串格式为 "YYYY-MM-DD hh:mm"
+		defaultValue: {
+			type: String,
+			default: ''
+		}
+	},
+
+	/**
+	 * 数据
+	 */
+	data() {
+		return {
+			range: [],
+			value: [],
+			dateStr: '', // 最终显示的字符串
+			dtStart: null, // 有效范围开始
+			dtEnd: null, // 有效范围结束
+		};
+	},
+	
+	/**
+	 * 监听数据
+	 */ 
+	watch: {
+		// 默认值
+		defaultValue() {
+			// 设置默认值
+			this.setDefaultValue();
+		}
+	},
+
+	/**
+	 * 组件初次加载完成
+	 */
+	mounted() {
+		// 有效日期开始和结束
+		let start = this.start;
+		let end = this.end;
+		
+		// 验证是否是有效的开始和结束日期
+		if(!utils.isString(this.start)) {
+			console.log('开始日期需为String类型,格式为 "YYYY-MM-DD hh:mm"');
+			start = '1970-1-1 00:00';
+		}
+		if(!utils.isString(this.start)) {
+			console.log('结束日期需为String类型,格式为 "YYYY-MM-DD hh:mm"');
+			start = '2300-1-1 00:00';
+		}
+		
+		// 将开始日期和结束日期转为 Date 
+		let dtStart = utils.formatDate(start).dt;
+		let dtEnd = utils.formatDate(end).dt;
+		
+		// 判断有效日期结束是否大于有效日期开始,如果不是,则将有效日期结束修改为有效日期开始往后300年
+		if (dtEnd <= dtStart) {
+			dtEnd = utils.formatDate(start).dt;
+			dtEnd.setFullYear(dtStart.getFullYear() + 300);
+			dtEnd.setDate(dtEnd.getDate() - 1);
+		}
+		
+		// 更新开始日期和结束日期
+		this.dtStart = dtStart;
+		this.dtEnd = dtEnd;
+
+		// 设置默认值
+		this.setDefaultValue();
+	},
+
+	/**
+	 * 方法
+	 */
+	methods: {
+		/**
+		 * 清空
+		 */
+		clearTime(){
+			this.dateStr = ''
+		},
+		/**
+		 * 确认选择
+		 */
+		change(event) {
+			let year, month, day, hour, minute;
+			if(this.fields == 'year') {
+				year = this.range[0][this.value[0]].number; // 年
+				let dtStr = `${year}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'month') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				let dtStr = `${year}-${month}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'day') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				let dtStr = `${year}-${month}-${day}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'hour') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				hour = this.range[3][this.value[3]].number; // 时
+				day = this.range[2][this.value[2]].number; // 日
+				let dtStr = `${year}-${month}-${day} ${hour}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+			else if(this.fields == 'minute') {
+				year = this.range[0][this.value[0]].number; // 年
+				month = this.range[1][this.value[1]].number; // 月
+				day = this.range[2][this.value[2]].number; // 日
+				hour = this.range[3][this.value[3]].number; // 时
+				minute = this.range[4][this.value[4]].number; // 分
+				let dtStr = `${year}-${month}-${day} ${hour}:${minute}`;
+				this.setDateStr(dtStr);
+				this.$emit('change', utils.formatDate(dtStr));
+				return;
+			}
+		},
+
+		/**
+		 * 设置显示的值
+		 * @param {Date|String} date 日期字符串或日期对象
+		 */
+		setDateStr(date) {
+			let dt = utils.formatDate(date);
+			if(this.fields == 'year') {
+				this.dateStr = `${dt.YYYY}年`;
+				return;
+			}
+			if(this.fields == 'month') {
+				this.dateStr = `${dt.YYYY}年${dt.M}月`;
+				return;
+			}
+			if(this.fields == 'day') {
+				this.dateStr = `${dt.YYYY}年${dt.M}月${dt.D}日`;
+				return;
+			}
+			if(this.fields == 'hour') {
+				this.dateStr = `${dt.YYYY}年${dt.M}月${dt.D}日 ${dt.h}时`;
+				return;
+			}
+			this.dateStr = `${dt.YYYY}年${dt.M}月${dt.D}日 ${dt.h}时${dt.m}分`;
+		},
+		
+		/**
+		 * 设置年数据
+		 */ 
+		setYearData() {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let yearEnd = this.dtEnd.getFullYear();
+			// 年
+			let years = [];
+			for (let year = yearStart; year <= yearEnd; year++) {
+				let item = {
+					number: year,
+					text: `${year}年`,
+				};
+				years.push(item);
+			}
+			this.range.splice(0, 1, years);
+		},
+		
+		/**
+		 * 设置月数据
+		 * @param {Number} year 年 
+		 */ 
+		setMonthData(year) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			
+			// 月
+			let months = [];
+			let monthStartIndex = year == yearStart ? monthStart : 1;
+			let monthEndIndex = year == yearEnd ? monthEnd : 12;
+			for (let month = monthStartIndex; month <= monthEndIndex; month++) {
+				let item = {
+					number: month,
+					text: `${month}月`,
+				};
+				months.push(item);
+			}
+			this.range.splice(1, 1, months);
+		},
+		
+		/**
+		 * 设置日数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 */ 
+		setDayData(year, month) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			
+			// 日
+			let days = [];
+			let dayStartIndex = year == yearStart && month == monthStart ? dayStart : 1;
+			let dayEndIndex; 
+			if(year == yearEnd && month == monthEnd) {
+				dayEndIndex = dayEnd;
+			} else {
+				dayEndIndex = (new Date(year, month, 0)).getDate();
+			}
+			for (let day = dayStartIndex; day <= dayEndIndex; day++) {
+				let item = {
+					number: day,
+					text: `${day}日`,
+				};
+				days.push(item);
+			}
+			this.range.splice(2, 1, days);
+		},
+		
+		/**
+		 * 设置时数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 * @param {Number} day 日 
+		 */ 
+		setHourData(year, month, day) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let hourStart = this.dtStart.getHours();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			let hourEnd = this.dtEnd.getHours();
+			
+			// 时
+			let hours = [];
+			let hourStartIndex = year == yearStart && month == monthStart && day == dayStart ? hourStart : 0;
+			let hourEndIndex = year == yearEnd && month == monthEnd && day == dayEnd ? hourEnd : 23;
+			for (let hour = hourStartIndex; hour <= hourEndIndex; hour++) {
+				let item = {
+					number: hour,
+					text: `${hour}时`,
+				};
+				hours.push(item);
+			}
+			this.range.splice(3, 1, hours);
+		},
+		
+		/**
+		 * 设置分数据
+		 * @param {Number} year 年 
+		 * @param {Number} month 月 
+		 * @param {Number} day 日
+		 * @param {Number} hour 时
+		 */ 
+		setMinuteData(year, month, day, hour) {
+			// 有效日期
+			let yearStart = this.dtStart.getFullYear();
+			let monthStart = this.dtStart.getMonth() + 1;
+			let dayStart = this.dtStart.getDate();
+			let hourStart = this.dtStart.getHours();
+			let minuteStart = this.dtStart.getMinutes();
+			let yearEnd = this.dtEnd.getFullYear();
+			let monthEnd = this.dtEnd.getMonth() + 1;
+			let dayEnd = this.dtEnd.getDate();
+			let hourEnd = this.dtEnd.getHours();
+			let minuteEnd = this.dtEnd.getMinutes();
+			
+			// 分
+			let minutes = [];
+			let minuteStartIndex = year == yearStart && month == monthStart && day == dayStart && hour == hourStart ? minuteStart : 0;
+			let minuteEndIndex = year == yearEnd && month == monthEnd && day == dayEnd && hour == hourEnd ? minuteEnd : 59;
+			for(let minute = minuteStartIndex; minute <= minuteEndIndex; minute++) {
+				let item = {
+					number: minute,
+					text: `${minute}分`,
+				}
+				minutes.push(item);
+			}
+			this.range.splice(4, 1, minutes);
+		},
+		
+		/**
+		 * 设置默认值
+		 */
+		setDefaultValue() {
+			// 默认日期
+			let dtDefault;
+			// 开始日期和结束日期
+			let dtStart = this.dtStart;
+			let dtEnd = this.dtEnd;
+			
+			// 判断是否传了默认日期
+			// 传了默认日期,格式化默认日期为日期对象
+			if(this.defaultValue) {
+				/* 上一天 */
+				/* const curDate = new Date();
+				curDate.setDate(curDate.getDate() - 1);
+				dtDefault = utils.formatDate(curDate).dt; */
+				/* 上一月 */
+				/* const curDate = new Date();
+				let nowDate = curDate.getDate();
+				let lastMonth = new Date(curDate.getTime());
+				// 设置上一个月(这里不需要减1)
+				lastMonth.setMonth(lastMonth.getMonth());
+				// 设置为0,默认为当前月的最后一天
+				lastMonth.setDate(0);
+				// 上一个月的天数
+				let daysOflastMonth = lastMonth.getDate();
+				// 设置上一个月的日期,如果当前月的日期大于上个月的总天数,则为最后一天 
+				lastMonth.setDate(nowDate > daysOflastMonth ? daysOflastMonth : nowDate);
+				dtDefault = utils.formatDate(lastMonth).dt; */
+				/* 原先的 */
+				dtDefault = utils.formatDate(this.defaultValue).dt;
+			} 
+			// 如果没有传默认日期,将默认日期设置为当前日期
+			else {
+				dtDefault = new Date();
+				// dtDefault = new Date(new Date().getTi	me() - 24*60*60*1000);
+			}
+			// 如果默认日期不在有效日期范围内,设置默认日期为有效日期开始值
+			if (dtDefault < dtStart || dtDefault > dtEnd) {
+				dtDefault = dtStart;
+			}
+			// 更新 dateStr
+			if(this.defaultValue) this.setDateStr(dtDefault);
+			// 默认值相关数据
+			let dfYear = dtDefault.getFullYear();
+			let dfMonth = dtDefault.getMonth() + 1;
+			let dfDay = dtDefault.getDate();
+			let dfHour = dtDefault.getHours();
+			let dfMinute = dtDefault.getMinutes();
+			
+			// 设置年数据
+			this.setYearData();
+			// 设置 Year 这一列的 value 值
+			let yearIndex = this.range[0].findIndex(year => {
+				return dfYear == year.number;
+			});
+			this.value.splice(0, 1, yearIndex >= 0 ? yearIndex : 0);
+			
+			// 设置月数据
+			if(this.fields == 'year') return;
+			this.setMonthData(dfYear);
+			// 设置 Month 这一列的 value 值
+			let monthIndex = this.range[1].findIndex(month => {
+				return dfMonth == month.number;
+			});
+			this.value.splice(1, 1, monthIndex >=0 ? monthIndex : 0);
+			// 设置日数据
+			if(this.fields == 'month') return;
+			this.setDayData(dfYear, dfMonth);
+			// 设置 Day 这一列的 value 值
+			let dayIndex = this.range[2].findIndex(day => {
+				return dfDay == day.number;
+			});
+			this.value.splice(2, 1, dayIndex >=0 ? dayIndex : 0);
+			
+			// 设置时数据
+			if(this.fields == 'day') return;
+			this.setHourData(dfYear, dfMonth, dfDay);
+			// 设置 Hour 这一列的 value 值
+			let hourIndex = this.range[3].findIndex(hour => {
+				return dfHour == hour.number;
+			});
+			this.value.splice(3, 1, hourIndex >=0 ? hourIndex : 0);
+			
+			// 设置分数据
+			if(this.fields == 'hour') return;
+			this.setMinuteData(dfYear, dfMonth, dfDay, dfHour);
+			// 设置 Minute 这一列的 value 值
+			let minuteIndex = this.range[4].findIndex(minute => {
+				return dfMinute == minute.number;
+			});
+			this.value.splice(4, 1, minuteIndex >=0 ? minuteIndex : 0);
+		},
+
+		/**
+		 * 某一列的值改变时触发
+		 * @param {Number} event.detail.column 表示改变了第几列(下标从0开始)
+		 * @param {Number} event.detail.value 表示变更值的下标
+		 */
+		columnchange(event) {
+			let columnIndex = event.detail.column; // 改变的列的下标
+			let valueIndex = event.detail.value; // 变更值的下标
+			
+			// 更新改变列的 value
+			this.value.splice(columnIndex, 1, valueIndex);
+			
+			// 改变年要更新月数据
+			if(this.fields == 'year') return;
+			if (columnIndex == 0) {
+				// 当前选择的月
+				let monthBeforeUpdate = this.range[1][this.value[1]];
+				// 更新月数据
+				this.setMonthData(this.range[0][this.value[0]].number);
+				// 更新 Month Value
+				let monthIndex = this.range[1].findIndex(month => {
+					return month.number == monthBeforeUpdate.number;
+				});
+				this.value.splice(1, 1, monthIndex >= 0 ? monthIndex : 0);
+			}
+			
+			// 改变年、月都要更新日数据
+			if(this.fields == 'month') return;
+			if (columnIndex == 0 || columnIndex == 1) {
+				// 当前选择的日
+				let dayBeforeUpdate = this.range[2][this.value[2]];
+				// 更新日数据
+				this.setDayData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number);
+				// 更新 Day Value
+				let dayIndex = this.range[2].findIndex(day => {
+					return day.number == dayBeforeUpdate.number;
+				});
+				this.value.splice(2, 1, dayIndex >= 0 ? dayIndex : 0);
+			}
+			
+			// 改变年、月、日都要更新时数据
+			if(this.fields == 'day') return;
+			if (columnIndex == 0 || columnIndex == 1 || columnIndex == 2) {
+				// 当前选择的时
+				let hourBeforeUpdate = this.range[3][this.value[3]];
+				// 更新时数据
+				this.setHourData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number, this.range[2][this.value[2]].number);
+				// 更新 Hour Value
+				let hourIndex = this.range[3].findIndex(hour => {
+					return hour.number == hourBeforeUpdate.number;
+				});
+				this.value.splice(3, 1, hourIndex >= 0 ? hourIndex : 0);
+			}
+			
+			// 当前选择的分
+			if(this.fields == 'hour') return;
+			let minuteBeforeUpdate = this.range[4][this.value[4]];
+			// 更新分数据
+			this.setMinuteData(this.range[0][this.value[0]].number, this.range[1][this.value[1]].number, this.range[2][this.value[2]].number, this.range[3][this.value[3]].number);
+			// 更新 Minute Value
+			let minuteIndex = this.range[4].findIndex(minute => {
+				return minute.number == minuteBeforeUpdate.number;
+			});
+			this.value.splice(4, 1, minuteIndex >= 0 ? minuteIndex : 0);
+		},
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.content {
+	// text-align: right;
+}
+
+.placeholder {
+	color: #949596;
+}
+</style>

+ 30 - 0
components/biaofun-datetime-picker/使用说明.md

@@ -0,0 +1,30 @@
+### 组件说明
+* 日期时间选择器
+* 组件的默认日期有效期范围为:"1970-01-01 00:00" - "2300-01-01 00:00"。
+* 注意:如果您传递的日期有效范围的结束日期小于开始日期,则日期有效范围的结束日期会自动修正为开始日期+300年,比如,您传递的日期有效范围的开始日期为 "2020-11-11 18:30",
+* 结束日期为 "2018-11-11 18:30",则此时将会自动修正结束日期为 "2320-11-11 18:30"。
+* 注意:如果您传递的默认值不在日期有效范围内,则会自动修正默认值为当前日期时间,如果当前日期时间也不在日期有效范围内,则会再次修正为日期有效范围的开始日期。
+* 注意:该组件用到了我自己封装的 utils.js,位置在 '@/common/js/utils.js'。
+
+
+### 插件 props 属性
+* disabled: 是否禁用该组件?Boolean类型;
+* placeholder: 组件没有选中值时显示的内容,String类型;
+* start: 表示有效日期时间范围的开始,String类型,格式为 "YYYY-MM-DD hh:mm";
+* end: 表示有效日期时间范围的结束,String类型,格式必为 "YYYY-MM-DD hh:mm";
+* fields: 选择器的粒度,String类型,有效值为 year、month、day、hour、minute;
+* defaultValue: 默认值,String类型,格式为 "YYYY-MM-DD hh:mm";
+
+### 插件事件
+- change(date):选择日期时间后的回调事件。
+ * date.YYYY: 年;
+ * date.M: 月;
+ * date.MM: 月(补0);
+ * date.D: 日;
+ * date.DD: 日(补0);
+ * date.h: 时;
+ * date.hh: 时(补0);
+ * date.m: 分;
+ * date.mm: 分(补0);
+ * date.dt: Date对象;
+ * ... 还有一些其他的字段,具体看返回值吧!

+ 147 - 0
components/gf-chat/gf-chat.vue

@@ -0,0 +1,147 @@
+<template>
+	<view class="gf-chat">
+		<u-popup v-model="showchatlist" mode="center" border-radius="20" :closeable="true" @close="close">
+			<view class="chat-list">
+				<view class="worker-hrader">
+					<text>在线咨询</text>
+				</view>
+				<scroll-view scroll-y="true" style="height: 60vh;" v-if="worker_list.length > 0">
+					<view class="worker-item u-flex" v-for="(item,index) in worker_list" :key="index" @click="tochat(item)">
+						<image :src="item.headimg" class="img1" mode=""></image>
+						<text class="text1 u-flex-1">{{item.name}}</text>
+						<u-icon name="chat-fill" color="#1677FF" size="40"></u-icon>
+					</view>
+				</scroll-view>
+				<view v-else style="height: 60vh;">
+					<u-empty text="暂无数据" mode="list"></u-empty>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			type: {
+				type: String,
+				default: "1"
+			}
+		},
+		data() {
+			return {
+				id: '',
+				showchatlist: false,
+				worker_list: []
+			}
+		},
+		created() {
+
+		},
+		methods: {
+			close(e) {
+				this.$emit('close')
+			},
+			tochat(item) {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Member/bind_worker', {
+					worker_id: item.id
+				}).then(res => {
+					if (res.code == 1) {
+						if (this.type == 1) {
+							this.showchatlist = false
+						}
+						this.$emit('over')
+						this.$u.post('/api/Member/member_info').then(res => {
+							if (this.type == 1) {
+								uni.navigateTo({
+									url: "/pages/index/chat?hx_username=" + res.data.worker_hx_username + "&worker_id=" + item.id
+								})
+							} else {
+								uni.redirectTo({
+									url: "/pages/index/chat?hx_username=" + res.data.worker_hx_username + "&worker_id=" + item.id
+								})
+							}
+						})
+					} else {
+						this.$u.toast(res.msg)
+					}
+				})
+			},
+			getdata(type) {
+				if (type == 2) {
+					// 福利
+					this.$u.post('/api/welfare/welfare_detail', {
+						id: this.id
+					}).then(res => {
+						this.worker_list = res.data.worker_info
+						this.showchatlist = true
+					})
+				} else {
+					// 楼盘
+					this.$u.post('/api/Property/property_detail', {
+						id: this.id
+					}).then(res => {
+						this.worker_list = res.data.worker_info
+						this.showchatlist = true
+					})
+				}
+
+			},
+			open(id, type) {
+				this.id = id
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.getdata(type)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gf-chat {
+		.chat-list {
+			width: 650rpx;
+			background: #FFFFFF;
+			padding: 1rpx 0;
+
+			.worker-hrader {
+				line-height: 88rpx;
+				border-bottom: 2rpx solid #E5E5E5;
+				padding: 0 24rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+			}
+
+			.worker-item {
+				margin: 24rpx auto;
+				width: 602rpx;
+				height: 140rpx;
+				background: #F2F2F2;
+				border-radius: 20rpx;
+				padding: 0 20rpx;
+
+				.img1 {
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 100rpx;
+				}
+
+				.text1 {
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+					margin: 0 20rpx;
+				}
+			}
+		}
+	}
+</style>

+ 281 - 0
components/gf-goods/gf-goods.vue

@@ -0,0 +1,281 @@
+<template>
+	<view class="gf-goods">
+		<view :class="type == 1 ? 'row-item u-flex' : 'col-item'" @click="toinfo">
+			<view class="item-img">
+				<image :src="data.logo" class="logo" mode="aspectFill"></image>
+				<view class="logo-look u-flex">
+					<u-icon name="eye-fill" size="28" color="#fff"></u-icon>
+					<text class="text">{{getview(data.page_view || 0)}}</text>
+				</view>
+			</view>
+
+			<view class="item-box">
+				<view class="item-name u-line-1">
+					{{data.name}}
+				</view>
+				<view class="item-tips u-flex">
+					<text class="u-line-1" style="white-space: nowrap;" v-if="data.house_type">{{data.house_type.join('·')}}·</text>
+					<text style="white-space: nowrap;">{{data.house_min_area || 0}}-{{data.house_max_area || 0}}㎡</text>
+				</view>
+				<view class="item-tips">
+					{{data.area}}
+				</view>
+				<view class="price-box u-flex">
+					<text>参考均价</text>
+					<text v-if="Number(data.avg_price)">{{data.avg_price}}元/㎡</text>
+					<text v-else>{{data.avg_price}}</text>
+				</view>
+				<view class="u-flex label-box u-flex-wrap">
+					<text v-for="(item,index) in data.trait" :key="index" v-if="index < 2" :style="{color:color[index % 5],border:`2rpx solid ${color[index % 4]}`}">{{item}}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	export default {
+		props: {
+			// b布局1独占一行2一行两个
+			type: {
+				type: [Number, String],
+				default: 2
+			},
+			data: {
+				type: Object,
+				default () {
+					return {
+						area: "鹿城区",
+						avg_price: "27412",
+						house_max_area: 212.06,
+						house_min_area: 116.8,
+						house_type: ["三房两厅两卫", "四房两厅三卫", "四房两厅两卫", "四房两厅四卫"],
+						id: 1,
+						logo: "https://shujuhuifu.oss-cn-beijing.aliyuncs.com/af20f05b337db210/1c354234c4e49d6c.jpg",
+						name: "国鸿中心",
+						trait: ["超级综合体", "一线江景", "约350米摩天超高层", "内外双公园"]
+					}
+				}
+			}
+		},
+		data() {
+			return {
+
+			}
+		},
+		onLoad() {
+
+		},
+		computed: {
+			color() {
+				return this.$color
+			}
+		},
+		methods: {
+			getview(count) {
+				if (count > 10000) {
+					return Number((count / 10000).toFixed(2)) + 'w'
+				}
+				if (count > 1000) {
+					return Number((count / 1000).toFixed(2)) + 'k'
+				}
+				return count
+			},
+			toinfo() {
+				uni.navigateTo({
+					url: "/pages/index/houses-info?id=" + this.data.id
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gf-goods {
+		.row-item {
+			margin-bottom: 32rpx;
+
+			.item-img {
+				width: 280rpx;
+				height: 240rpx;
+				margin-right: 20rpx;
+				border-radius: 20rpx;
+				position: relative;
+				overflow: hidden;
+
+				.logo-look {
+					position: absolute;
+					bottom: 0;
+					left: 0;
+					width: 280rpx;
+					height: 52rpx;
+					background: rgba(0, 0, 0, 0.3);
+					padding: 0 20rpx;
+
+					.text {
+						font-size: 20rpx;
+						font-family: SourceHanSansSC-Heavy, SourceHanSansSC;
+						font-weight: 800;
+						color: rgba(256, 256, 256, 0.7);
+						margin-left: 12rpx;
+					}
+				}
+
+				.logo {
+					width: 280rpx;
+					height: 240rpx;
+				}
+			}
+
+			.item-box {
+				flex: 1;
+				min-width: 1rpx;
+
+				.label-box {
+					text {
+						margin-right: 10rpx;
+						padding: 0 12rpx;
+						line-height: 40rpx;
+						height: 40rpx;
+						background: #F5F5F5;
+						border-radius: 8rpx;
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						white-space: nowrap;
+					}
+				}
+
+				.price-box {
+					margin-bottom: 8rpx;
+
+					text:first-child {
+						font-size: 20rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						margin-right: 8rpx;
+					}
+
+					text:last-child {
+						font-size: 32rpx;
+						font-family: DINAlternate-Bold, DINAlternate;
+						font-weight: bold;
+						color: #FF3B30;
+					}
+				}
+
+				.item-name {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #131415;
+					margin: 10rpx 0;
+				}
+
+				.item-tips {
+					font-size: 18rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					margin-bottom: 12rpx;
+				}
+			}
+		}
+
+		.col-item {
+			width: 320rpx;
+			background: #F8FBFF;
+			border-radius: 20rpx;
+			margin-bottom: 20rpx;
+			padding-bottom: 24rpx;
+
+			.item-box {
+				padding: 0 20rpx;
+
+				.label-box {
+					text {
+						margin-right: 10rpx;
+						padding: 0 12rpx;
+						line-height: 40rpx;
+						height: 40rpx;
+						background: #F5F5F5;
+						border-radius: 8rpx;
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+				}
+
+				.price-box {
+					margin-bottom: 8rpx;
+
+					text:first-child {
+						font-size: 20rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						margin-right: 8rpx;
+					}
+
+					text:last-child {
+						font-size: 32rpx;
+						font-family: DINAlternate-Bold, DINAlternate;
+						font-weight: bold;
+						color: #FF3B30;
+					}
+				}
+
+				.item-name {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #131415;
+					margin: 10rpx 0;
+				}
+
+				.item-tips {
+					font-size: 18rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					margin-bottom: 12rpx;
+				}
+			}
+
+			.item-img {
+				width: 320rpx;
+				height: 240rpx;
+				border-radius: 20rpx;
+				overflow: hidden;
+				position: relative;
+
+				.logo-look {
+					position: absolute;
+					bottom: 0;
+					left: 0;
+					width: 320rpx;
+					height: 52rpx;
+					background: rgba(0, 0, 0, 0.3);
+					padding: 0 20rpx;
+
+					.text {
+						font-size: 20rpx;
+						font-family: SourceHanSansSC-Heavy, SourceHanSansSC;
+						font-weight: 800;
+						color: rgba(256, 256, 256, 0.7);
+						margin-left: 12rpx;
+					}
+				}
+
+				.logo {
+					width: 320rpx;
+					height: 240rpx;
+				}
+			}
+		}
+	}
+</style>

+ 151 - 0
components/gf-scroll/gf-scroll.vue

@@ -0,0 +1,151 @@
+<template>
+	<view class="scroll1-box">
+		<scroll-view scroll-x="true" @scroll="scroll" class="scroll-view" :bounces="false" enhanced="true" scroll-anchoring="true">
+			<view class="tabs-scroll-box u-flex u-flex-wrap" :style="{width:scrollWidth * 25 + '%'}">
+				<view class="tabs-item u-flex-col u-col-center" :style="{width:100 / scrollWidth + '%'}" v-for="(item,index) in list" :key="index" @click="tourl(item)">
+					<image :src="item.logo" mode=""></image>
+					<text>{{item.title}}</text>
+				</view>
+			</view>
+		</scroll-view>
+		<view class="hidescroll"></view>
+		<view class="scroll-box">
+			<view class="scroll" :style="{transform: `translateX(${sX})`,width:s_b_W}"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "rt-scroll",
+		props: {
+			list: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+			userinfo: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {
+				sX: '0%', //等比偏移量
+				c_W: 0, //最外围容器宽度
+				c_b_W: 0, //最外围容器内容宽度
+				s_b_W: '0px', //自定义滚动条移动盒子宽度
+				tablist: [],
+				scrollWidth: 0
+			};
+		},
+		watch: {
+			list: {
+				handler() {
+					this.getwidth()
+				},
+				deep: true
+			}
+		},
+		created() {
+			this.getwidth()
+		},
+		methods: {
+			getwidth() {
+				this.scrollWidth = Math.ceil(this.list.length / 2)
+				this.$nextTick(() => {
+					this.getdocument()
+				})
+				// console.log(this.scrollWidth);
+			},
+			tourl(item) {
+				this.$emit('click', item)
+			},
+			scroll(e) {
+				if ((this.c_b_W - this.c_W) < 0) {
+					return
+				}
+				let nX = e.detail.scrollLeft // 得到滑动的偏移量
+				var zong = this.c_b_W - this.c_W //总的偏移量
+				this.sX = nX / zong * 100 + '%'
+			},
+			getdocument() {
+				const query = uni.createSelectorQuery().in(this);
+				query.selectAll('.scroll-view,.tabs-scroll-box').boundingClientRect((data) => {
+					// dome元素从外到内依次获取数据,所以写法按顺序来才不会混
+					this.c_W = data[0].width
+					this.c_b_W = data[1].width
+					this.s_b_W = (this.c_b_W - this.c_W) <= 0 ? "100%" : "15px"
+					console.log(this.c_W, this.c_b_W);
+				}).exec();
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.scroll1-box {
+		padding-top: 2rpx;
+		width: 702rpx;
+		// height: 404rpx;
+		background: #FFFFFF;
+		border-radius: 20rpx;
+		padding-bottom: 28rpx;
+		position: relative;
+
+		.hidescroll {
+			position: absolute;
+			width: 702rpx;
+			height: 20rpx;
+			background-color: #fff;
+			left: 0;
+			bottom: 38rpx;
+			z-index: 10;
+		}
+
+		.scroll-view {
+			padding-top: 12rpx;
+
+
+			.tabs-scroll-box {
+				padding: 0 4rpx;
+
+				.tabs-item {
+					width: 25%;
+					margin: 20rpx 0 12rpx 0;
+
+					image {
+						width: 84rpx;
+						height: 84rpx;
+						margin-bottom: 20rpx;
+						border-radius: 20rpx;
+					}
+
+					text {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #131415;
+					}
+				}
+			}
+		}
+
+		.scroll-box {
+			width: 30px;
+			height: 10rpx;
+			background: rgba(30, 125, 255, 0.2);
+			border-radius: 5rpx;
+			margin: 10rpx auto 0 auto;
+
+			.scroll {
+				height: 100%;
+				background: #1E7DFF;
+				border-radius: 5rpx;
+			}
+		}
+	}
+</style>

+ 350 - 0
components/gf-search/gf-search.vue

@@ -0,0 +1,350 @@
+<template>
+	<view class="gf-search">
+		<u-popup v-model="show" mode="right">
+			<view class="search-popup">
+				<view class="search-item">
+					<view class="search-title">
+						区域筛选
+					</view>
+					<view class="u-flex">
+						<view class="select-box0 u-flex u-row-between" @click="showsheng = true">
+							<text class="text u-line-1">{{shengname || '选择省'}}</text>
+							<u-icon name="arrow-down" color="#D8D8D8" size="26"></u-icon>
+						</view>
+						<view class="select-box0 u-flex u-row-between" @click="showshi = true">
+							<text class="text u-line-1">{{shiname || '选择市'}}</text>
+							<u-icon name="arrow-down" color="#D8D8D8" size="26"></u-icon>
+						</view>
+						<view class="select-box0 u-flex u-row-between" @click="showqu = true">
+							<text class="text u-line-1">{{quname || '选择区'}}</text>
+							<u-icon name="arrow-down" color="#D8D8D8" size="26"></u-icon>
+						</view>
+					</view>
+
+				</view>
+				<view class="search-item">
+					<view class="search-title">
+						价格筛选
+					</view>
+					<view class="select-box1 u-flex">
+						<text :class="price == 1 ? 'text1 text1_active' : 'text1'" @click="price = 1">从低到高</text>
+						<text :class="price == 2 ? 'text1 text1_active' : 'text1'" @click="price = 2">从高到低</text>
+					</view>
+				</view>
+				<view class="search-item">
+					<view class="search-title">
+						面积筛选
+					</view>
+					<view class="select-box2 u-flex">
+						<view class="text1 u-flex">
+							<input type="number" placeholder="请输入" v-model="mianji1">
+							<text>㎡</text>
+						</view>
+						<text class="xian"></text>
+						<view class="text1 u-flex">
+							<input type="number" placeholder="请输入" v-model="mianji2">
+							<text>㎡</text>
+						</view>
+					</view>
+				</view>
+				<view class="search-item">
+					<view class="search-title">
+						户型筛选
+					</view>
+					<view class="select-box u-flex u-row-between" @click="showhuxing = true">
+						<text class="text">{{huxingname || '请选择'}}</text>
+						<u-icon name="arrow-down" color="#D8D8D8" size="26"></u-icon>
+					</view>
+				</view>
+				<view class="search-item">
+					<view class="search-title">
+						类别筛选
+					</view>
+					<view class="select-box u-flex u-row-between" @click="showleibie = true">
+						<text class="text">{{leibiename || '请选择'}}</text>
+						<u-icon name="arrow-down" color="#D8D8D8" size="26"></u-icon>
+					</view>
+				</view>
+				<view class="u-flex search-btn u-row-between">
+					<text @click="chongzhi">重置</text>
+					<text @click="shaixuan">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-select v-model="showsheng" :list="shenglist" label-name="name" value-name="id" @confirm="changesheng"></u-select>
+		<u-select v-model="showshi" :list="shilist" label-name="name" value-name="id" @confirm="changeshi"></u-select>
+		<u-select v-model="showqu" :list="qulist" label-name="name" value-name="id" @confirm="changequ"></u-select>
+		<u-select v-model="showhuxing" :list="huxinglist" label-name="title" value-name="id" @confirm="changehuxing"></u-select>
+		<u-select v-model="showleibie" :list="leibielist" label-name="title" @confirm="changeleibie"></u-select>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				show: false,
+
+				showsheng: false,
+				shenglist: [],
+				shengname: '',
+				shengid: '',
+
+				showshi: false,
+				shilist: [],
+				shiname: '',
+				shiid: '',
+
+				showqu: false,
+				qulist: [],
+				quname: '',
+				quid: '',
+
+				price: '',
+				mianji1: '',
+				mianji2: '',
+				showhuxing: false,
+				huxinglist: [],
+				huxingname: '',
+				huxingid: '',
+				showleibie: false,
+				leibielist: [],
+				leibiename: '',
+			}
+		},
+		created() {
+			this.getconfig()
+		},
+		methods: {
+			shaixuan() {
+				if(this.shengid && !this.quid){
+					this.$u.toast("请选择完整区域")
+					return
+				}
+				if ((this.mianji1 && this.mianji2) || (!this.mianji1 && !this.mianji2)) {
+					this.$emit('shaixuan', {
+						area_id: this.quid,
+						price_sort: this.price,
+						min_area: this.mianji1,
+						max_area: this.mianji2,
+						house_type_id: this.huxingid,
+						property_class: this.leibiename
+					})
+					this.show = false
+				} else {
+					this.$u.toast("面积有误")
+				}
+
+			},
+			chongzhi() {
+				this.shengid = ''
+				this.shengname = ''
+				this.shiid = ''
+				this.shiname = ''
+				this.quid = ''
+				this.quname = ''
+				this.price = ''
+				this.mianji1 = ''
+				this.mianji2 = ''
+				this.huxingid = ''
+				this.huxingname = ''
+				this.leibiename = ''
+				this.show = false
+			},
+			changeleibie(e) {
+				this.leibiename = e[0].label
+			},
+			changehuxing(e) {
+				this.huxingname = e[0].label
+				this.huxingid = e[0].value
+			},
+			changesheng(e) {
+				this.shengname = e[0].label
+				this.shengid = e[0].value
+				this.shilist = []
+				this.shiname = ''
+				this.shiid = ''
+				this.qulist = []
+				this.quname = ''
+				this.quid = ''
+				this.$u.post('/api/Data/area_list', {
+					level: 2,
+					province_id: this.shengid
+				}).then(res => {
+					this.shilist = res.data
+				})
+			},
+			changeshi(e) {
+				this.shiname = e[0].label
+				this.shiid = e[0].value
+				this.qulist = []
+				this.quname = ''
+				this.quid = ''
+				this.$u.post('/api/Data/area_list', {
+					level: 3,
+					city_id: this.shiid
+				}).then(res => {
+					this.qulist = res.data
+				})
+			},
+			changequ(e) {
+				this.quname = e[0].label
+				this.quid = e[0].value
+			},
+			getconfig() {
+				this.$u.post('/api/Data/area_list', {
+					level: 1
+				}).then(res => {
+					this.shenglist = res.data
+				})
+				this.$u.post('/api/Index/house_type_list').then(res => {
+					this.huxinglist = res.data
+				})
+				this.$u.post('/api/Index/property_class_list').then(res => {
+					this.leibielist = res.data
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gf-search {
+		.search-popup {
+			width: 448rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx;
+
+			.search-btn {
+				margin-top: 40rpx;
+
+				text:first-child {
+					width: 188rpx;
+					line-height: 76rpx;
+					background: #FFA120;
+					border-radius: 8rpx;
+					text-align: center;
+					font-size: 22rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 188rpx;
+					line-height: 76rpx;
+					background: #1F7EFF;
+					border-radius: 8rpx;
+					text-align: center;
+					font-size: 22rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+
+			.search-item {
+				padding: 40rpx 0 24rpx 0;
+				border-bottom: 1rpx solid #F5F5F5;
+
+				.select-box2 {
+					.text1 {
+						width: 128rpx;
+						height: 52rpx;
+						background: #FFFFFF;
+						border-radius: 8rpx;
+						border: 2rpx solid #CCCCCC;
+						padding: 0 10rpx;
+
+						input {
+							flex: 1;
+							text-align: center;
+							font-size: 24rpx;
+						}
+
+						text {
+							font-size: 22rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #CCCCCC;
+						}
+					}
+
+					.xian {
+						width: 32rpx;
+						height: 2rpx;
+						background: #CCCCCC;
+						border-radius: 8rpx;
+						margin: 0 10rpx;
+					}
+				}
+
+				.select-box1 {
+					.text1 {
+						width: 128rpx;
+						line-height: 52rpx;
+						background: #FFFFFF;
+						border-radius: 8rpx;
+						border: 2rpx solid #CCCCCC;
+						text-align: center;
+						font-size: 22rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #CCCCCC;
+						margin-right: 20rpx;
+					}
+
+					.text1_active {
+						border: 2rpx solid #1F7EFF;
+						color: #1F7EFF;
+					}
+				}
+
+				.search-title {
+					margin-bottom: 20rpx;
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+
+				.select-box0 {
+					flex: 1;
+					height: 52rpx;
+					background: #FFFFFF;
+					border-radius: 8rpx;
+					border: 2rpx solid #CCCCCC;
+					padding: 0 5rpx;
+					margin-right: 10rpx;
+
+					.text {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+						flex: 1;
+					}
+				}
+
+				.select-box {
+					width: 312rpx;
+					height: 52rpx;
+					background: #FFFFFF;
+					border-radius: 8rpx;
+					border: 2rpx solid #CCCCCC;
+					padding: 0 14rpx;
+
+					.text {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+						flex: 1;
+					}
+				}
+			}
+
+
+		}
+	}
+</style>

+ 105 - 0
components/gf-tabbar/gf-tabbar.vue

@@ -0,0 +1,105 @@
+<template>
+	<view>
+		<u-tabbar :list="list" active-color="#1E7DFF" inactive-color="#CCCCCC"></u-tabbar>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		name: "gf-tabbar",
+		data() {
+			return {
+				list: [{
+						"iconPath": "/static/images/index.png",
+						"pagePath": "/pages/index/index",
+						"selectedIconPath": "/static/images/index1.png",
+						"text": "首页"
+					},
+					{
+						"iconPath": "/static/images/video.png",
+						"pagePath": "/pages/video/video",
+						"selectedIconPath": "/static/images/video1.png",
+						"text": "视频"
+					},
+					{
+						"iconPath": "/static/images/mine.png",
+						"pagePath": "/pages/mine/mine",
+						"selectedIconPath": "/static/images/mine1.png",
+						"text": "我的"
+					}
+				]
+			};
+		},
+		created() {
+			if (this.config.report_switch == 1) {
+				this.list = [{
+						"iconPath": "/static/images/index.png",
+						"pagePath": "/pages/index/index",
+						"selectedIconPath": "/static/images/index1.png",
+						"text": "首页"
+					},
+					{
+						"iconPath": "/static/images/video.png",
+						"pagePath": "/pages/video/video",
+						"selectedIconPath": "/static/images/video1.png",
+						"text": "视频"
+					},
+					{
+						"iconPath": "/static/images/baobei.png",
+						"pagePath": "/pages/baobei/baobei",
+						"selectedIconPath": "/static/images/baobei1.png",
+						"text": "客户报备"
+					},
+					{
+						"iconPath": "/static/images/mine.png",
+						"pagePath": "/pages/mine/mine",
+						"selectedIconPath": "/static/images/mine1.png",
+						"text": "我的"
+					}
+				]
+			}
+		},
+		computed: {
+			...mapState(['config'])
+		},
+		watch: {
+			config: {
+				handler(val) {
+					if (val.report_switch == 1) {
+						this.list = [{
+								"iconPath": "/static/images/index.png",
+								"pagePath": "/pages/index/index",
+								"selectedIconPath": "/static/images/index1.png",
+								"text": "首页"
+							},
+							{
+								"iconPath": "/static/images/video.png",
+								"pagePath": "/pages/video/video",
+								"selectedIconPath": "/static/images/video1.png",
+								"text": "视频"
+							},
+							{
+								"iconPath": "/static/images/baobei.png",
+								"pagePath": "/pages/baobei/baobei",
+								"selectedIconPath": "/static/images/baobei1.png",
+								"text": "客户报备"
+							},
+							{
+								"iconPath": "/static/images/mine.png",
+								"pagePath": "/pages/mine/mine",
+								"selectedIconPath": "/static/images/mine1.png",
+								"text": "我的"
+							}
+						]
+					}
+				},
+				deep: true
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 129 - 0
components/gf-tel/gf-tel.vue

@@ -0,0 +1,129 @@
+<template>
+	<view class="gf-tel">
+		<u-popup v-model="showchatlist" mode="center" border-radius="20" :closeable="true">
+			<view class="chat-list">
+				<view class="worker-hrader">
+					<text>隐私电话</text>
+				</view>
+				<scroll-view scroll-y="true" style="height: 60vh;" v-if="worker_list.length > 0">
+					<view class="worker-item u-flex" v-for="(item,index) in worker_list" :key="index" @click="totel(item)">
+						<image :src="item.headimg" class="img1" mode=""></image>
+						<text class="text1 u-flex-1">{{item.name}}</text>
+						<u-icon name="phone-fill" color="#1677FF" size="40"></u-icon>
+					</view>
+				</scroll-view>
+				<view v-else style="height: 60vh;">
+					<u-empty text="暂无数据" mode="list"></u-empty>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				id: '',
+				showchatlist: false,
+				worker_list: []
+			}
+		},
+		created() {
+
+		},
+		methods: {
+			totel(item) {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Member/bind_worker', {
+					worker_id: item.id
+				}).then(res => {
+					if (res.code == 1) {
+						this.showchatlist = false
+						this.$emit('over')
+						this.$u.post('/api/Member/member_info').then(res => {
+							uni.makePhoneCall({
+								phoneNumber: res.data.worker_phone
+							})
+						})
+					} else {
+						this.$u.toast(res.msg)
+					}
+				})
+			},
+			getdata(type) {
+				if (type == 2) {
+					// 福利
+					this.$u.post('/api/welfare/welfare_detail', {
+						id: this.id
+					}).then(res => {
+						this.worker_list = res.data.worker_info
+						this.showchatlist = true
+					})
+				} else {
+					// 楼盘
+					this.$u.post('/api/Property/property_detail', {
+						id: this.id
+					}).then(res => {
+						this.worker_list = res.data.worker_info
+						this.showchatlist = true
+					})
+				}
+			},
+			open(id, type) {
+				this.id = id
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.getdata(type)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gf-tel {
+		.chat-list {
+			width: 650rpx;
+			background: #FFFFFF;
+			padding: 1rpx 0;
+
+			.worker-hrader {
+				line-height: 88rpx;
+				border-bottom: 2rpx solid #E5E5E5;
+				padding: 0 24rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+			}
+
+			.worker-item {
+				margin: 24rpx auto;
+				width: 602rpx;
+				height: 140rpx;
+				background: #F2F2F2;
+				border-radius: 20rpx;
+				padding: 0 20rpx;
+
+				.img1 {
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 100rpx;
+				}
+
+				.text1 {
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+					margin: 0 20rpx;
+				}
+			}
+		}
+	}
+</style>

+ 99 - 0
components/gf-yinsi/gf-yinsi.vue

@@ -0,0 +1,99 @@
+<template>
+	<view class="gf-yinsi">
+		<u-modal v-model="show" title="用户隐私保护提示" :show-cancel-button="true" confirm-text="同意并继续" cancel-text="不同意并退出" @cancel="handleDisagree">
+			<view class="xieyi-content">
+				<text class="text1">感谢您使用小程序,您使用小程序前应当阅并同意</text>
+				<text class="text2" @click="open">{{privacyContractName}}</text>
+				<text class="text1">当您点击同意并开始时用产品服务时,即表示你已理解并同息该条款内容,该条款将对您产生法律约束力。如您拒绝,将无法进入小程序。</text>
+			</view>
+			<button slot="confirm-button" open-type="agreePrivacyAuthorization" class="weui-btn" @agreeprivacyauthorization="handleAgree">同意并继续</button>
+		</u-modal>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "gf-yinsi",
+		data() {
+			return {
+				show: false,
+				privacyContractName: ''
+			};
+		},
+		created() {
+			if (wx.getPrivacySetting) {
+				wx.getPrivacySetting({
+					success: res => {
+						console.log("是否需要授权:", res.needAuthorization, "隐私协议的名称为:", res.privacyContractName)
+						if (res.needAuthorization) {
+							this.privacyContractName = res.privacyContractName
+							this.show = true
+						} else {
+							this.handleAgree()
+						}
+					},
+					fail: () => {},
+					complete: () => {},
+				})
+			} else {
+				// 低版本基础库不支持 wx.getPrivacySetting 接口,隐私接口可以直接调用
+				this.handleAgree()
+			}
+		},
+		methods: {
+			open() {
+				wx.openPrivacyContract({
+					success: res => {
+						console.log('openPrivacyContract success')
+					},
+					fail: res => {
+						console.error('openPrivacyContract fail', res)
+					}
+				})
+			},
+			handleDisagree(e) {
+				wx.exitMiniProgram()
+			},
+			handleAgree(e) {
+				this.$emit('handleAgree')
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.gf-yinsi {
+		.weui-btn {
+			padding: 0;
+			margin: 0;
+			background-color: #fff;
+			border: none;
+			height: 100rpx;
+			line-height: 100rpx;
+			font-size: 32rpx;
+			box-sizing: border-box;
+			cursor: pointer;
+			text-align: center;
+			border-radius: 4rpx;
+			color: #2979ff;
+		}
+
+		.weui-btn::after {
+			border: none;
+		}
+
+		.xieyi-content {
+			padding: 24rpx;
+
+			.text1 {
+				color: #666;
+				font-size: 28rpx;
+			}
+
+			.text2 {
+				font-size: 28rpx;
+				color: blue;
+			}
+		}
+	}
+</style>

BIN
hybrid/html.zip


BIN
hybrid/html/img/chongzhi.png


BIN
hybrid/html/img/kefu.png


BIN
hybrid/html/img/rizhao.png


BIN
hybrid/html/img/share.png


+ 49 - 0
hybrid/html/index.html

@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<meta charset="UTF-8">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0">
+		<title></title>
+	</head>
+	<style>
+		* {
+			margin: 0;
+			padding: 0;
+		}
+	</style>
+	<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
+	<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
+	<body>
+		<div style="position: relative;">
+			<iframe id="myiframe" src="" style="width: 100%;height: 100vh;" frameborder="0"></iframe>
+			<div style="position: absolute;top: 140px;right: 10px;border-radius: 100px;background-color: rgba(256,256,256,0.3);backdrop-filter: saturate(100%) blur(10px);-webkit-backdrop-filter: saturate(100%) blur(10px);padding: 1px 5px;display: flex;flex-direction: column;align-items: center;">
+				<img style="width:30px;height:30px;margin:10px 0;" onclick="chongzhi()" src="./img/chongzhi.png" alt="">
+				<img style="width:30px;height:30px;margin:10px 0;" onclick="back()" src="./img/rizhao.png" alt="">
+				<img style="width:30px;height:30px;margin:10px 0;" src="./img/kefu.png" alt="">
+				<img style="width:30px;height:30px;margin:10px 0;" src="./img/share.png" alt="">
+			</div>
+		</div>
+	</body>
+	<script>
+		function getQueryVariable(variable) {
+			var query = window.location.search.substring(1);
+			var vars = query.split("&");
+			for (var i = 0; i < vars.length; i++) {
+				var pair = vars[i].split("=");
+				if (pair[0] == variable) { return pair[1]; }
+			}
+			return (false);
+		}
+
+		function chongzhi() {
+			$("#myiframe")[0].contentWindow.ResetClick();
+		}
+
+		function back() {
+			wx.miniProgram.navigateBack()
+		}
+		if (getQueryVariable('url')) {
+			$('#myiframe').attr('src', decodeURIComponent(getQueryVariable('url')) + '?oss=' + encodeURIComponent('https://nikeshang.oss-cn-hangzhou.aliyuncs.com/shuxiang/sun/Build'));
+		}
+	</script>
+</html>

+ 449 - 0
pages/baobei/baobei.vue

@@ -0,0 +1,449 @@
+<template>
+	<view class="baobei">
+		<u-navbar :title="config.store_title" title-color="#fff" :background="{background:'#1F7EFF'}" :border-bottom="false" :isBack="false">
+			<view class="u-flex nav-left" slot="left">
+				<u-icon name="map-fill" size="34" color="#fff"></u-icon>
+				<text class="text">{{defaultcity.city || '定位中'}}</text>
+			</view>
+		</u-navbar>
+		<view class="" style="padding: 0 24rpx;">
+			<view class="broker-title">
+				基本信息
+			</view>
+			<view   class="broker-row u-flex" @click="quyushow = true">
+				<view class="broker-row-left u-flex">
+					<text>意向区域</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请选择您的意向区域" class="input-right" :disabled="true" v-model="quyuname">
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+			<view  class="broker-row u-flex" @click="loupanshow = true">
+				<view class="broker-row-left u-flex">
+					<text>意向项目</text>
+				</view>
+				<input type="text" placeholder="请选择您的意向楼盘" class="input-right" :disabled="true" v-model="loupanname">
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+			
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>客户姓名</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="kehuname">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="kehutel">
+			</view>
+		</view>
+		<u-gap bg-color="#F5F5F5" height="20"></u-gap>
+		<view class="" style="padding: 0 24rpx;">
+			<view class="broker-title">
+				其他信息
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>带看人姓名</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="name">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="tel">
+			</view>
+			<view class="broker-row u-flex" v-if="certification_type == 1">
+				<view class="broker-row-left u-flex">
+					<text>中介门店</text>
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="shop">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>预约看房日期</text>
+				</view>
+				<biaofunDatetimePicker ref="biaofunDatetimePicker" placeholder="请选择看房日期" class="input-right" :start="$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd hh:MM')" @change="changetime"></biaofunDatetimePicker>
+				<!-- <input type="text" placeholder="请选择看房日期" class="input-right" :disabled="true" v-model="time"> -->
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+		</view>
+		<view class="baobei-down u-flex-col u-col-center">
+			<view class="xieyi u-flex u-row-center">
+				<u-checkbox v-model="xieyi" active-color="#1F7EFF" size="26"></u-checkbox>
+				<view class="text" @click="xieyi = !xieyi">
+					勾选并同意<text @click.stop="totext(3)">《报备活动规则》</text>
+				</view>
+			</view>
+			<view class="tijiao" @click="save">
+				确认
+			</view>
+		</view>
+		<u-popup v-model="show" :maskCloseAble="false" mode="center" border-radius="20">
+			<view @click="clear" class="" style="font-weight: 400;text-align: right;padding: 30rpx 30rpx 0 0;box-sizing: border-box;">
+				X
+			</view>
+			<view class="baobei-popup u-flex-col u-col-center">
+				<image src="../../static/images/baobei-img.png" class="image" mode=""></image>
+				<view class="baobei-tips u-flex-col u-col-center">
+					<text>您还未进行信息认证</text>
+					<text>请您前去认证</text>
+				</view>
+				<view class="baobei-btn u-flex u-row-between">
+					<text @click="toshenqing(2)">全民经纪人</text>
+					<text @click="toshenqing(1)">中介经纪人</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showover" :closeable="true" mode="center" border-radius="20">
+			<view class="over-popup u-flex-col u-col-center u-row-center">
+				<u-icon name="checkmark-circle-fill" color="#14CB30" size="168"></u-icon>
+				<view class="over-text u-flex-col u-col-center">
+					<text>已提交客户资料,开发商审核中</text>
+					<text>防截客锁定中,请耐心等待</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-select v-model="quyushow" :list="quyulist" label-name="name" value-name="id" @confirm="changequyu"></u-select>
+		<u-select v-model="loupanshow" :list="loupanlist" label-name="name" value-name="id" @confirm="changeloupan"></u-select>
+		<gf-tabbar></gf-tabbar>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	import biaofunDatetimePicker from "../../components/biaofun-datetime-picker/biaofun-datetime-picker.vue"
+	export default {
+		data() {
+			return {
+				show: false,
+				xieyi: false,
+				showover: false,
+
+				quyulist: [],
+				quyushow: false,
+				quyuname: '',
+				quyuid: '',
+
+				loupanlist: [],
+				loupanshow: false,
+				loupanname: '',
+				loupanid: '',
+
+				kehuname: '',
+				kehutel: '',
+				name: '',
+				tel: '',
+				shop: '',
+				time: '',
+				certification_type: '',
+				quyuIpt:true,
+			}
+		},
+		onLoad(option) {
+			this.getquyu()
+		},
+		onShow() {
+			if(this.config.store_title){
+				uni.setNavigationBarTitle({
+					title: this.config.store_title
+				})
+			}
+			if (this.$islogin()) {
+				this.show = true
+			} else {
+				this.getuser()
+			}
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		components: {
+			biaofunDatetimePicker
+		},
+		methods: {
+			clear(){
+				uni.switchTab({
+					url: "/pages/index/index" 
+				})
+			},
+			totext(type) {
+				uni.navigateTo({
+					url: "/pages/mine/xieyi?type=" + type
+				})
+			},
+			save() {
+				if (!this.quyuname) {
+					this.$u.toast('请选择您的意向区域')
+					return
+				}
+				if (!this.loupanname) {
+					this.$u.toast('请选择您的意向楼盘')
+					return
+				}
+				if (!this.kehuname) {
+					this.$u.toast('请输入客户姓名')
+					return
+				}
+				if (!this.$u.test.mobile(this.kehutel)) {
+					this.$u.toast('请输入正确的客户联系方式')
+					return
+				}
+				if (!this.name) {
+					this.$u.toast('请输入带看人姓名')
+					return
+				}
+				if (!this.$u.test.mobile(this.tel)) {
+					this.$u.toast('请输入正确的带看人联系方式')
+					return
+				}
+				if (!this.shop && this.certification_type == 1) {
+					this.$u.toast('请输入中介门店')
+					return
+				}
+				if (!this.time) {
+					this.$u.toast('请选择看房日期')
+					return
+				}
+				if (this.time < this.$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd hh:MM:ss')) {
+					this.$u.toast('看房日期不得小于当前时间')
+					return
+				}
+				if (!this.xieyi) {
+					this.$u.toast("请勾选协议")
+					return
+				}
+				this.$u.post('/api/Report/submit_report', {
+					area_id: this.quyuid,
+					property_id: this.loupanid,
+					client_name: this.kehuname,
+					client_phone: this.kehutel,
+					report_name: this.name,
+					report_phone: this.tel,
+					shop: this.shop,
+					time: this.time
+				}).then(res => {
+					if (res.code == 1) {
+						this.showover = true
+						this.quyuid = ''
+						this.quyuname = ''
+						this.loupanid = ''
+						this.loupanname = ''
+						this.kehuname = ''
+						this.kehutel = ''
+						this.name = ''
+						this.tel = ''
+						this.shop = ''
+						this.time = ''
+						this.xieyi = false
+						this.$refs.biaofunDatetimePicker.clearTime()
+					} else {
+						this.$u.toast(res.msg)
+					}
+				})
+			},
+			changetime(e) {
+				this.time = `${e.f1} ${e.f8}:00`
+			},
+			changeloupan(e) {
+				this.loupanid = e[0].value
+				this.loupanname = e[0].label
+			},
+			changequyu(e) {
+				this.quyuid = e[0].value
+				this.quyuname = e[0].label
+				this.$u.post('/api/Report/area_property_list', {
+					area_id: this.quyuid
+				}).then(res => {
+					this.loupanlist = res.data
+				})
+			},
+			getquyu() {
+				this.$u.post('/api/Data/area_list', {
+					level: 3,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.quyulist = res.data
+				})
+			},
+			toshenqing(type) {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "/pages/index/broker?type=" + type
+				})
+			},
+			getuser() {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.certification_type = res.data.certification_type
+					if (res.data.certification_type == 0) {
+						this.show = true
+					} else {
+						this.show = false
+					}
+				})
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.baobei {
+		.over-popup {
+			width: 650rpx;
+			height: 564rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+
+			.over-text {
+				margin-top: 32rpx;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+			}
+		}
+
+		.baobei-down {
+			position: fixed;
+			bottom: 150rpx;
+			left: 0;
+			width: 750rpx;
+
+			.tijiao {
+				margin: 30rpx auto;
+				width: 702rpx;
+				line-height: 82rpx;
+				background: #1F7EFF;
+				border-radius: 8rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			.xieyi {
+				.text {
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+
+					text {
+						color: #1F7EFF;
+					}
+				}
+			}
+		}
+
+		.broker-row {
+			height: 82rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.input-right {
+				flex: 1;
+				font-size: 24rpx;
+			}
+
+			.broker-row-left {
+				width: 252rpx;
+
+				text:first-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				text:nth-child(2) {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #F83838;
+				}
+			}
+		}
+
+		.broker-title {
+			padding: 24rpx 0;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+		}
+
+		.baobei-popup {
+			width: 650rpx;
+			height: 806rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			padding-top: 126rpx;
+
+			.baobei-btn {
+				width: 100%;
+				padding: 0 44rpx;
+
+				text:first-child {
+					width: 262rpx;
+					line-height: 100rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 262rpx;
+					line-height: 100rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.baobei-tips {
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #C5C5C5;
+				margin-bottom: 98rpx;
+			}
+
+			.image {
+				width: 214rpx;
+				height: 242rpx;
+				margin-bottom: 72rpx;
+			}
+		}
+
+		.nav-left {
+			padding: 0 20rpx;
+
+			.text {
+				font-size: 32rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #FFFFFF;
+				margin-left: 5rpx;
+			}
+		}
+	}
+</style>

+ 162 - 0
pages/index/broker.vue

@@ -0,0 +1,162 @@
+<template>
+	<view class="broker">
+		<view class="broker-title">
+			基本信息
+		</view>
+		<view class="broker-row u-flex">
+			<view class="broker-row-left u-flex">
+				<text>姓名</text>
+				<text>*</text>
+			</view>
+			<input type="text" placeholder="请输入" v-model="name" class="input-right">
+		</view>
+		<!-- <view class="broker-row u-flex">
+			<view class="broker-row-left u-flex">
+				<text>身份证号</text>
+				<text>*</text>
+			</view>
+			<input type="idcard" placeholder="请输入" v-model="card" class="input-right">
+		</view> -->
+		<view class="broker-row u-flex">
+			<view class="broker-row-left u-flex">
+				<text>手机号</text>
+				<text>*</text>
+			</view>
+			<input type="number" placeholder="请输入" v-model="tel" class="input-right">
+		</view>
+		<view class="broker-btn" @click="save">
+			确认
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				type: 1,
+				name: '',
+				card: '',
+				tel: '',
+				title:''
+			}
+		},
+		onLoad(option) {
+			this.type = option.type
+			this.title = option.title
+			this.getuser()
+		},
+		onShow() {
+			if (this.type == 1) {
+				uni.setNavigationBarTitle({
+					title: "中介经纪人"
+				})
+			} else {
+				uni.setNavigationBarTitle({
+					title: "全民经纪人"
+				})
+			}
+		},
+		methods: {
+			getuser(){
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.name = res.data.broker_name
+					this.card = res.data.broker_id_card
+					this.tel = res.data.broker_phone
+				})
+			},
+			save() {
+				if(!this.name){
+					this.$u.toast("请输入姓名")
+					return
+				}
+				// if(!this.$u.test.idCard(this.card)){
+				// 	this.$u.toast("请输入正确的身份证")
+				// 	return
+				// }
+				if(!this.$u.test.mobile(this.tel)){
+					this.$u.toast("请输入正确的手机号")
+					return
+				}
+				uni.showLoading({
+					mask:true,
+					title:"请稍后"
+				})
+				this.$u.post('/api/Member/submit_broker',{
+					type:this.type,
+					name:this.name,
+					id_card:this.card,
+					phone:this.tel
+				}).then(res => {
+					this.$u.toast('提交成功,请等待后台审核')
+					if(res.code == 1){
+						setTimeout(() => {
+							uni.switchTab({
+								url: "/pages/index/index" 
+							})
+						},800)
+					}
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.broker {
+		padding: 0 24rpx;
+
+		.broker-btn {
+			width: 702rpx;
+			line-height: 82rpx;
+			background: #1F7EFF;
+			border-radius: 8rpx;
+			text-align: center;
+			font-size: 28rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #FFFFFF;
+			position: fixed;
+			bottom: 226rpx;
+			left: 24rpx;
+		}
+
+		.broker-row {
+			height: 82rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.input-right {
+				flex: 1;
+				font-size: 24rpx;
+			}
+
+			.broker-row-left {
+				width: 252rpx;
+
+				text:first-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				text:nth-child(2) {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #F83838;
+				}
+			}
+		}
+
+		.broker-title {
+			padding: 24rpx 0;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+		}
+	}
+
+</style>

+ 199 - 0
pages/index/change-city.vue

@@ -0,0 +1,199 @@
+<template>
+	<view class="change-city">
+		<view class="change-header">
+			<view class="header-top u-flex u-row-between">
+				<view class="top-left u-flex">
+					<u-icon name="search" color="#B0B0B0"></u-icon>
+					<input type="text" placeholder="请输入地址" v-model="keyword" confirm-type="search" @confirm="tosearch">
+				</view>
+				<text class="quxiao" @click="quxiao">取消</text>
+			</view>
+			<view class="header-down u-flex">
+				<view class="down-item u-flex-col u-col-center u-row-center" :class="{'down-item1' : current == 0}" @click="changeshengfen">
+					<text>省楼盘</text>
+					<text></text>
+				</view>
+				<view class="down-item u-flex-col u-col-center u-row-center" :class="{'down-item1' : current == 1}">
+					<text>市楼盘</text>
+					<text></text>
+				</view>
+			</view>
+		</view>
+		<view class="city-item" v-for="(item,index) in list" :key="index" @click="changitem(item)">
+			{{item.name}}
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				current: 0,
+				sheng: [],
+				shengdata: {},
+				shi: [],
+				list: [],
+				keyword: ''
+			}
+		},
+		onLoad() {
+			this.getsheng()
+		},
+		methods: {
+			quxiao() {
+				this.keyword = ''
+				if (this.current == 0) {
+					this.list = JSON.parse(JSON.stringify(this.sheng))
+				} else {
+					this.list = JSON.parse(JSON.stringify(this.shi))
+				}
+			},
+			tosearch() {
+				if (this.current == 0) {
+					if (this.keyword) {
+						this.list = []
+						this.sheng.forEach(val => {
+							if (val.name.indexOf(this.keyword) > -1) {
+								this.list.push(val)
+							}
+						})
+					} else {
+						this.list = JSON.parse(JSON.stringify(this.sheng))
+					}
+				} else {
+					if (this.keyword) {
+						this.list = []
+						this.shi.forEach(val => {
+							if (val.name.indexOf(this.keyword) > -1) {
+								this.list.push(val)
+							}
+						})
+					} else {
+						this.list = JSON.parse(JSON.stringify(this.shi))
+					}
+				}
+			},
+			getsheng() {
+				this.$u.post('/api/Data/area_list', {
+					level: 1
+				}).then(res => {
+					this.sheng = res.data
+					this.list = res.data
+				})
+			},
+			changitem(item) {
+				if (this.current == 0) {
+					this.shengdata = item
+					uni.showLoading({
+						mask: true,
+						title: "请稍后"
+					})
+					this.$u.post('/api/Data/area_list', {
+						level: 2,
+						province_id: item.id
+					}).then(res => {
+						this.list = res.data
+						this.shi = res.data
+						this.keyword = ''
+						this.current = 1
+					})
+				} else {
+					const eventChannel = this.getOpenerEventChannel();
+					eventChannel.emit('changecity', { sheng: this.shengdata, shi: item });
+					uni.navigateBack()
+				}
+			},
+			changeshengfen() {
+				this.current = 0
+				this.list = JSON.parse(JSON.stringify(this.sheng))
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.change-city {
+		.city-item {
+			line-height: 88rpx;
+			padding: 0 24rpx;
+			font-size: 28rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #666666;
+			border-bottom: 2rpx solid #F5F5F5;
+		}
+
+		.change-header {
+			position: sticky;
+			top: 0;
+			left: 0;
+			z-index: 10;
+			width: 750rpx;
+			height: 188rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx;
+			border-bottom: 12rpx solid #F5F5F5;
+
+			.header-down {
+				.down-item {
+					margin-right: 60rpx;
+
+					text:first-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+					}
+
+					text:last-child {
+						width: 84rpx;
+						height: 8rpx;
+						border-radius: 6rpx;
+						margin-top: -12rpx;
+						position: relative;
+						z-index: -1;
+					}
+				}
+
+				.down-item1 {
+					text:first-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+
+					text:last-child {
+						background: #1677FF;
+					}
+				}
+			}
+
+			.header-top {
+				padding: 20rpx 0;
+
+				.quxiao {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+
+				.top-left {
+					width: 612rpx;
+					height: 72rpx;
+					background: #FFFFFF;
+					border-radius: 20rpx;
+					border: 2rpx solid #F2F2F2;
+					padding: 0 22rpx;
+
+					input {
+						flex: 1;
+						margin-left: 16rpx;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 251 - 0
pages/index/chat.vue

@@ -0,0 +1,251 @@
+<template>
+	<view class="chat">
+		<view class="chat-list">
+			<view class="more-btn" @click="tomore">
+				{{showmore ? '点击查看更多' : '没有更多了'}}
+			</view>
+			<view class="chat-item u-flex u-col-top u-row-between" v-for="(item,index) in list" :key="index">
+				<image :src="item.headimg" :style="{opacity:item.type == 2 ? 1 : 0}" class="user-head" mode=""></image>
+				<view class="item-box u-flex-1 u-flex-col" :style="{alignItems: item.type == 2 ? 'flex-start' : 'flex-end'}">
+					<text>{{item.name}}</text>
+					<text :class="item.type == 2 ? 'text1' : 'text2'">{{item.content}}</text>
+				</view>
+				<image :src="item.headimg" :style="{opacity:item.type == 2 ? 0 : 1}" class="user-head" mode=""></image>
+			</view>
+			<view class="chat-item u-flex u-col-top u-row-between" v-for="(item,index) in chatlist" :key="index">
+				<image :src="item.headimg" :style="{opacity:item.type == 2 ? 1 : 0}" class="user-head" mode=""></image>
+				<view class="item-box u-flex-1 u-flex-col" :style="{alignItems: item.type == 2 ? 'flex-start' : 'flex-end'}">
+					<text>{{item.name}}</text>
+					<text :class="item.type == 2 ? 'text1' : 'text2'">{{item.content}}</text>
+				</view>
+				<image :src="item.headimg" :style="{opacity:item.type == 2 ? 0 : 1}" class="user-head" mode=""></image>
+			</view>
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="chat-btn u-flex u-row-between">
+			<input type="text" placeholder="请输入" v-model="text">
+			<text @click="send(text)">发送</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				text: '',
+				hx_username: '',
+				worker_id:'',
+				page: 1,
+				list: [],
+				chatlist:[],
+				myname:'',
+				myheadimg:'',
+				workername:'',
+				workerheadimg:'',
+			}
+		},
+		onLoad(option) {
+			this.hx_username = option.hx_username
+			this.worker_id = option.worker_id
+			this.myname = uni.getStorageSync("name")
+			this.myheadimg = uni.getStorageSync("headimg")
+			this.getlist()
+			this.getworker()
+			this.getmsg()
+		},
+		computed:{
+			showmore(){
+				if(this.list.length % 20 == 0 && this.list.length > 0){
+					return true
+				}else{
+					return false
+				}
+			}
+		},
+		methods: {
+			tomore(){
+				if(this.showmore){
+					this.page++
+					this.getlist()
+				}
+			},
+			getmsg(){
+				this.$WebIM.conn.addEventHandler('getmsg', {
+					// 当前用户收到文本消息。
+					onTextMessage: (message) => {
+						console.log(message);
+						this.chatlist.push({
+							content: message.msg,
+							create_at: this.$u.timeFormat(message.time, 'yyyy-mm-dd hh:MM:ss'),
+							headimg: message.from == uni.getStorageSync("hx_username") ? this.myheadimg : this.workerheadimg,
+							name: message.from == uni.getStorageSync("hx_username") ? this.myname : this.workername,
+							type: message.from == uni.getStorageSync("hx_username") ? 1 : 2,
+						})
+						this.$nextTick(() => {
+							uni.pageScrollTo({
+								scrollTop:99999
+							})
+						})
+					},
+				})
+			},
+			getworker(){
+				this.$u.post('/api/News/get_worker_info',{
+					worker_id: this.worker_id
+				}).then(res => {
+					this.workername = res.data.name
+					this.workerheadimg = res.data.headimg
+				})
+			},
+			getlist() {
+				uni.showLoading({
+					mask:true,
+					title:"请稍后"
+				})
+				this.$u.post('/api/News/news_list', {
+					worker_id: this.worker_id,
+					page_num: 20,
+					page: this.page
+				}).then(res => {
+					var list = res.data
+					list.forEach(val => {
+						this.list.unshift(val)
+					})
+					if(this.page == 1){
+						this.$nextTick(() => {
+							uni.pageScrollTo({
+								scrollTop:99999
+							})
+						})
+					}
+					
+				})
+			},
+			send(text) {
+				if (!text) {
+					this.$u.toast("请输入内容")
+					return
+				}
+				this.text = ''
+				let option = {
+					// 消息类型。
+					type: "txt",
+					// 消息内容。
+					msg: text,
+					// 消息发送方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。
+					from: uni.getStorageSync("hx_username"),
+					// 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。
+					to: this.hx_username,
+					// 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`,默认为单聊。
+					chatType: "singleChat",
+				};
+				// 创建文本消息。
+				let msg = this.$WebIM.message.create(option);
+				// console.log(msg);
+				this.$WebIM.conn.send(msg).then(res => {
+					this.$u.post('/api/News/send_news', {
+						worker_id: this.worker_id,
+						content: text
+					}).then(res => {
+						this.chatlist.push({
+							content: msg.msg,
+							create_at: this.$u.timeFormat(msg.time, 'yyyy-mm-dd hh:MM:ss'),
+							headimg: this.myheadimg,
+							name: this.myname,
+							type: 1,
+						})
+						this.$nextTick(() => {
+							uni.pageScrollTo({
+								scrollTop:99999
+							})
+						})
+						
+						// console.log(this.chatlist);
+					})
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F2F2F2;
+	}
+
+	.chat {
+		.chat-list {
+			padding: 24rpx;
+			.more-btn{
+				padding: 10rpx 0;
+				text-align: center;
+			}
+			.chat-item {
+				margin-bottom: 44rpx;
+
+				.item-box {
+					text:first-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #666666;
+						padding: 8rpx 24rpx;
+					}
+
+					text:last-child {
+						padding: 20rpx;
+						border-radius: 20rpx;
+					}
+
+					.text1 {
+						background-color: #fff;
+					}
+
+					.text2 {
+						background-color: #1F7EFF;
+						color: #fff;
+					}
+				}
+
+				.user-head {
+					width: 80rpx;
+					height: 80rpx;
+					border-radius: 100rpx;
+				}
+			}
+		}
+
+		.chat-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			z-index: 10;
+			padding: 0 24rpx 60rpx 24rpx;
+
+			input {
+				width: 574rpx;
+				height: 58rpx;
+				background: #F2F2F2;
+				border-radius: 30rpx;
+				padding: 0 28rpx;
+				box-sizing: border-box;
+			}
+
+			text {
+				width: 102rpx;
+				line-height: 58rpx;
+				background: #1F7EFF;
+				border-radius: 30rpx;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+	}
+</style>

+ 216 - 0
pages/index/fuli-info.vue

@@ -0,0 +1,216 @@
+<template>
+	<view class="fuli-info">
+		<u-parse :html="content"></u-parse>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="houses-btn u-flex u-row-between">
+			<text @click="opentel">隐私电话</text>
+			<text @click="tochat">在线咨询</text>
+		</view>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">您是否进行呼叫?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="totel">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+		<gf-tel ref="tellist" @over="getuser"></gf-tel>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				id: '',
+				content: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: '',
+				showtocall: false,
+				showlogin: false,
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		methods: {
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			opentel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = true
+				} else {
+					this.showlogin = true
+				}
+
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			totel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = false
+					if (this.worker_id == 0) {
+						this.$refs.tellist.open(this.id, 2)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 1
+						})
+						uni.makePhoneCall({
+							phoneNumber: this.worker_phone
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id, 2)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "./chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			getdata() {
+				this.$u.post("/api/welfare/welfare_detail", {
+					id: this.id
+				}).then(res => {
+					const regex = new RegExp('<img', 'gi')
+					this.content = res.data.content.replace(regex, `<img style="max-width: 100%; height: auto"`)
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.fuli-info {
+		padding: 24rpx;
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.houses-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 1;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+	}
+</style>

+ 96 - 0
pages/index/fuli.vue

@@ -0,0 +1,96 @@
+<template>
+	<view class="fuli">
+		<view class="swiper-box">
+			<u-swiper :list="swiperlisi" name="logo" height="320" @click="tobanner" border-radius="20"></u-swiper>
+		</view>
+		<view class="u-flex u-row-between u-flex-wrap list-box">
+			<image :src="item.logo" v-for="(item,index) in list" :key="index" @click="toinfo(item)" mode="aspectFill"></image>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		data() {
+			return {
+				swiperlisi: [],
+				list: [],
+				page: 1,
+				title: ''
+			}
+		},
+		onLoad(option) {
+			this.title = option.title
+			this.getbanner()
+			this.getlist()
+		},
+		onShow() {
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		computed: {
+			...mapState(['defaultcity'])
+		},
+		methods: {
+			tobanner(e) {
+				if (this.swiperlisi[e].url) {
+					uni.navigateTo({
+						url: this.swiperlisi[e].url
+					})
+				}
+			},
+			getlist() {
+				this.$u.post('/api/welfare/welfare_list', {
+					page: this.page,
+					page_num: 20,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			},
+			getbanner() {
+				this.$u.post('/api/Index/banner', {
+					location: 3
+				}).then(res => {
+					this.swiperlisi = res.data
+				})
+			},
+			toinfo(item) {
+				uni.navigateTo({
+					url: "./fuli-info?id=" + item.id
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.fuli {
+
+
+		.swiper-box {
+			margin: 24rpx;
+		}
+
+		.list-box {
+			padding: 0 24rpx;
+
+			image {
+				width: 340rpx;
+				height: 110rpx;
+				border-radius: 10rpx;
+				margin-bottom: 20rpx;
+			}
+		}
+	}
+</style>

+ 55 - 0
pages/index/home.vue

@@ -0,0 +1,55 @@
+<template>
+	<view class="home-page">
+		<gf-yinsi @handleAgree="handleAgree"></gf-yinsi>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			handleAgree(e) {
+				uni.switchTab({
+					url: "/pages/index/index"
+				})
+				if (uni.getStorageSync("city") && uni.getStorageSync("city").city_id) {
+					this.$store.commit('setdefaultcity', uni.getStorageSync("city"))
+				} else {
+					this.$amapPlugin.getRegeo({
+						success: (res) => {
+							//成功回调
+							// console.log(res[0]);
+							this.$store.commit('setcity', {
+								city: res[0].regeocodeData.addressComponent.city,
+								userLocation: `${res[0].longitude},${res[0].latitude}`,
+								city_id: '',
+								province_id: '',
+							})
+						},
+						fail: (info) => {
+							//失败回调
+							// console.log(info)
+							this.$store.commit('setcity', {
+								city: '温州市',
+								userLocation: '120.699279,27.993849',
+								city_id: 2,
+								province_id: 1
+							})
+						}
+					})
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.home-page {}
+</style>

+ 1030 - 0
pages/index/houses-info.vue

@@ -0,0 +1,1030 @@
+<template>
+	<view class="houses-info">
+		<view class="index-bg"></view>
+		<view class="swiper-box">
+			<u-swiper :list="swiperlisi" height="367" border-radius="20"></u-swiper>
+		</view>
+		<view class="houses-tabs u-flex u-row-between">
+			<view class="tabs-item u-flex-col u-col-center" @click="opendijia">
+				<image src="../../static/images/tabs1.png" mode=""></image>
+				<text>底价详情</text>
+			</view>
+			<view class="tabs-item u-flex-col u-col-center" @click="torizhao">
+				<image src="../../static/images/tabs2.png" mode=""></image>
+				<text>日照测评</text>
+			</view>
+			<view class="tabs-item u-flex-col u-col-center" @click="toyifang">
+				<image src="../../static/images/tabs3.png" mode=""></image>
+				<text>一房一价</text>
+			</view>
+			<view class="tabs-item u-flex-col u-col-center" @click="tovideo">
+				<image src="../../static/images/tabs4.png" mode=""></image>
+				<text>抖音视频</text>
+			</view>
+		</view>
+		<view class="houses-box">
+			<view class="box-header u-flex u-row-between">
+				<text>{{detail.name}}</text>
+				<text @click="toinfo()">详情>></text>
+			</view>
+			<view class="box-tips">
+				备案名:{{detail.record_name}}
+			</view>
+			<view class="u-flex price">
+				<text>参考均价</text>
+				<text>{{detail.avg_price}}元/㎡</text>
+			</view>
+			<view class="houses-data u-flex u-flex-wrap u-row-between">
+				<view class="data-item u-flex-col u-col-center">
+					<text>{{detail.floor_area}}</text>
+					<text>占地面积</text>
+				</view>
+				<view class="data-item u-flex-col u-col-center">
+					<text>{{detail.covered_area}}</text>
+					<text>总建筑面积</text>
+				</view>
+				<view class="data-item u-flex-col u-col-center">
+					<text>{{detail.house_min_area}}㎡-{{detail.house_max_area}}㎡</text>
+					<text>户型面积</text>
+				</view>
+				<view class="data-item u-flex-col u-col-center">
+					<text>{{detail.greening_rate}}</text>
+					<text>绿化率</text>
+				</view>
+				<view class="data-item u-flex-col u-col-center">
+					<text>{{detail.plot_ratio}}</text>
+					<text>容积率</text>
+				</view>
+			</view>
+			<view class="houses-label u-flex u-flex-wrap">
+				<text v-for="(item,index) in detail.trait" :key="index"
+					:style="{color:color[index % 5],border:`2rpx solid ${color[index % 4]}`}">{{item}}</text>
+			</view>
+			<view class="kaifa-box">
+				<view style="margin-bottom: 24rpx;">开盘日期: {{detail.sale_time}}</view>
+				<view>开发商: {{detail.developers}}</view>
+			</view>
+		</view>
+		<view class="address-box u-flex">
+			<u-icon name="map-fill" color="#131415"></u-icon>
+			<text class="text">{{detail.project_address}}</text>
+		</view>
+		<view class="fangchan-wenda" v-if="detail.comment_switch == 1">
+			<view class="wenda-title u-flex u-row-between">
+				<text>房产问答</text>
+				<text @click="tomore" v-if="pinglundata.id">更多问答>></text>
+			</view>
+			<view v-if="pinglundata.id" @click="topingluninfo">
+				<view class="wenda-box">
+					<view class="box-top u-flex u-row-between">
+						<text class="text1">问</text>
+						<image class="img" :src="pinglundata.user_headimg" mode=""></image>
+						<text class="text2 u-flex-1">{{pinglundata.user_name}}</text>
+						<text class="text3">{{pinglundata.create_time}}</text>
+					</view>
+					<view class="table-header u-flex u-row-center" v-if="pinglundata.quiz_type == 2">
+						<input type="text" placeholder="请输入" class="u-flex-1"
+							:value="JSON.parse(pinglundata.content).title" :disabled="true">
+					</view>
+					<scroll-view v-if="pinglundata.quiz_type == 2" scroll-y="true" scroll-x="true" class="wenda-table">
+						<view class="table-row" v-for="(a,b) in JSON.parse(pinglundata.content).list" :key="b">
+							<view class="table-col u-line-1" v-for="(c,d) in a" :key="d">{{c.value}}</view>
+						</view>
+					</scroll-view>
+					<view v-if="pinglundata.quiz_type == 1" class="wenda-text">
+						{{pinglundata.content}}
+					</view>
+				</view>
+				<view class="wenda-box" v-if="pinglundata.apply_info">
+					<view class="box-top u-flex u-row-between">
+						<text class="text1" style="background-color: #04B578;">答</text>
+						<image class="img" :src="pinglundata.apply_info.user_headimg" mode=""></image>
+						<text class="text2 u-flex-1">{{pinglundata.apply_info.user_name}}</text>
+						<text class="text3">{{pinglundata.apply_info.create_time}}</text>
+					</view>
+					<view class="wenda-text">
+						{{pinglundata.apply_info.content}}
+					</view>
+				</view>
+				<view class="wenda-more">
+					{{pinglundata.apply_num}}人参与回复
+				</view>
+			</view>
+			<view v-else class="not-wenda u-flex-col u-col-center u-row-center">
+				<image class="img" src="../../static/images/not-wenda.png" mode=""></image>
+				<text class="text1">当前楼房还没有问答?</text>
+				<text class="text2" @click="tomore">前往发布提问 >></text>
+			</view>
+		</view>
+		<view class="map-box" v-if="detail.latitude && detail.longitude">
+			<view class="map-title">
+				区域地图
+			</view>
+			<map @click="tomap" style="width: 100%;height: 376rpx;" :latitude="latitude" :longitude="longitude"
+				:markers="[{id:1,latitude:latitude,longitude:longitude,width:20,height:30}]"></map>
+		</view>
+		<view class="huxing-box" v-if="detail.house_type.length > 0">
+			<view class="huixng-title">
+				在售户型
+			</view>
+			<view class="scroll-box1" style="position: relative;">
+				<u-icon name="arrow-left" style="position: absolute;top: 100rpx;left: -20rpx;z-index: 1;"></u-icon>
+				<scroll-view scroll-x="true" class="huxing-list">
+					<view class="huxing-item" v-for="(item,index) in detail.house_type" :key="index">
+						<image :src="item.logo" @click="openimg(item)" class="huxing-img" mode=""></image>
+						<view class="name">
+							{{item.house_type_name}}
+						</view>
+						<view class="jianyi">
+							建面:约{{item.area}}㎡
+						</view>
+					</view>
+				</scroll-view>
+				<u-icon name="arrow-right" style="position: absolute;top: 100rpx;right: -20rpx;z-index: 1;"></u-icon>
+			</view>
+
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="houses-btn u-flex u-row-between">
+			<text @click="opentel" :style="{'width':(preempt_switch != 1 ? '328rpx':'218rpx')}">隐私电话</text>
+			<text @click="baobei" v-if="preempt_switch == 1">客户报备</text>
+			<text @click="tochat" :style="{'width':(preempt_switch != 1 ? '328rpx':'218rpx')}">在线咨询</text>
+		</view>
+		<u-popup v-model="showdijia" mode="center" background="rgba(0,0,0,0)">
+			<view class="dijia-box u-flex-col u-col-center">
+				<image class="dijia-img" src="../../static/images/dijia-bg.png" mode=""></image>
+				<view class="u-flex-col u-col-center dijia-text">
+					<text>{{detail.discounts_policy}}</text>
+				</view>
+				<u-icon name="close-circle-fill" color="#fff" size="100" @click="showdijia = false"></u-icon>
+			</view>
+		</u-popup>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">您是否进行呼叫?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="totel">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="shownotkaifang" mode="center" background="rgba(0,0,0,0)" :closeable="true" closeTop="80rpx"
+			closeIconColor="#fff">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text" style="margin-top: 50rpx;">
+					<text>此板块暂未开放</text>
+					<text>敬请期待</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+		<gf-tel ref="tellist" @over="getuser"></gf-tel>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from "vuex"
+	export default {
+		//分享
+		onShareAppMessage(res) {
+			this.$u.get('/api/Member/transmit').then(res => {
+
+			})
+			return {
+				title: this.detail.name,
+				path: "pages/index/houses-info?id="+this.id ,
+				imageUrl: this.swiperlisi[0],
+			}
+		},
+		//分享朋友圈
+		onShareTimeline(res) {
+			this.$u.get('/api/Member/transmit').then(res => {
+
+			})
+			return {
+				title: this.detail.name,
+				path: "pages/index/houses-info?id="+this.id,
+				imageUrl: this.swiperlisi[0],
+			}
+		},
+		data() {
+			return {
+				swiperlisi: [],
+				showdijia: false,
+				showtocall: false,
+				id: '',
+				detail: {
+					house_type: []
+				},
+				showlogin: false,
+				pinglundata: {},
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: '',
+				sunshine_info: 0,
+				build_info: 0,
+				video_list: 0,
+				configs: {},
+				shownotkaifang: false,
+				detailName: "",
+				preempt_switch:0
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.detailName = option.name
+			this.getdata()
+			this.getpinglun()
+			this.configs = uni.getStorageSync("config")
+		},
+		onReady() {
+
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		computed: {
+			...mapState(['config', 'defaultcity']),
+			latitude() {
+				return Number(this.detail.latitude) > Number(this.detail.longitude) ? this.detail.longitude : this.detail
+					.latitude
+			},
+			longitude() {
+				return Number(this.detail.latitude) > Number(this.detail.longitude) ? this.detail.latitude : this.detail
+					.longitude
+			},
+			color() {
+				return this.$color
+			},
+
+		},
+		methods: {
+			opendijia() {
+				if (!this.detail.discounts_policy) {
+					// this.$u.toast("此板块暂未开放,敬请期待")
+					this.shownotkaifang = true
+					return
+				}
+				if (!uni.getStorageSync("token")) {
+					if (this.configs.floor_price_switch == 1) {
+						if (this.configs.floor_price_num > 0) {
+							this.configs.floor_price_num = this.configs.floor_price_num - 1
+							this.showdijia = true
+							uni.setStorageSync("config", this.configs)
+							this.$u.post('/api/Property/click_discounts_policy', {
+								id: this.id
+							})
+						} else {
+							this.showlogin = true
+						}
+					} else {
+						this.showlogin = true
+					}
+					return
+				}
+				this.$u.post('/api/Property/click_discounts_policy', {
+					id: this.id
+				})
+				this.showdijia = true
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			topingluninfo() {
+				uni.navigateTo({
+					url: "/pagesA/index/wenda-info?id=" + this.pinglundata.id + "&louid=" + this.id
+				})
+			},
+			getpinglun() {
+				this.$u.post('/api/Comment/consult_comment_list', {
+					id: this.id
+				}).then(res => {
+					if (res.code == 1) {
+						this.pinglundata = res.data[0] || {}
+					}
+				})
+			},
+			tomore() {
+				uni.navigateTo({
+					url: "/pagesA/index/wenda-list?id=" + this.id
+				})
+			},
+			tomap() {
+				uni.openLocation({
+					latitude: Number(this.latitude),
+					longitude: Number(this.longitude)
+				})
+			},
+			openimg(item) {
+				uni.previewImage({
+					urls: [item.logo]
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			opentel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getdata() {
+				this.$u.post('/api/Property/property_detail', {
+					id: this.id
+				}).then(res => {
+					this.swiperlisi = res.data.banner
+					this.detail = res.data
+					this.detailName = res.data.name
+					this.preempt_switch = res.data.preempt_switch
+				})
+
+				this.$u.get('/api/Property/sunshine_info', {
+					id: this.id
+				}).then(res => {
+					this.sunshine_info = res.data.build_info.length
+				})
+
+				this.$u.post('/api/Property/build_info', {
+					id: this.id
+				}).then(res => {
+					this.build_info = res.data.length
+				})
+
+				this.$u.post('/api/Property/video_list', {
+					id: this.id,
+					page: 1,
+					page_num: 20
+				}).then(res => {
+					this.video_list = res.data.length
+				})
+			},
+			tovideo() {
+				if (this.video_list == 0) {
+					// this.$u.toast("此板块暂未开放,敬请期待")
+					this.shownotkaifang = true
+					return
+				}
+				uni.navigateTo({
+					url: "./video?id=" + this.id
+				})
+			},
+			toinfo() {
+				uni.navigateTo({
+					url: "./info?id=" + this.id
+				})
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this
+								.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			baobei() {
+				uni.setStorageSync('detailName', this.detail.name);
+				if (uni.getStorageSync("token")) {
+					uni.navigateTo({
+						url: "/pages/index/report?id=" + this.id
+					})
+				} else {
+					this.showlogin = true
+				}
+			},
+			toyifang() {
+
+				if (this.build_info == 0) {
+					// this.$u.toast("此板块暂未开放,敬请期待")
+					this.shownotkaifang = true
+					return
+				}
+				if (!uni.getStorageSync("token")) {
+					if (this.configs.room_price_switch == 1) {
+						if (this.configs.room_price_num > 0) {
+							this.configs.room_price_num = this.configs.room_price_num - 1
+							uni.navigateTo({
+								url: "/pagesA/index/yifang?id=" + this.id
+							})
+							uni.setStorageSync("config", this.configs)
+						} else {
+							this.showlogin = true
+						}
+					} else {
+						this.showlogin = true
+					}
+					return
+				}
+				uni.navigateTo({
+					url: "/pagesA/index/yifang?id=" + this.id
+				})
+			},
+			torizhao() {
+				if (this.sunshine_info == 0) {
+					// this.$u.toast("此板块暂未开放,敬请期待")
+					this.shownotkaifang = true
+					return
+				}
+				if (!uni.getStorageSync("token")) {
+					if (this.configs.sunlight_appraisal_switch == 1) {
+						if (this.configs.sunlight_appraisal_num > 0) {
+							this.configs.sunlight_appraisal_num = this.configs.sunlight_appraisal_num - 1
+							uni.navigateTo({
+								url: "/pagesA/index/rizhao?id=" + this.id
+							})
+							uni.setStorageSync("config", this.configs)
+						} else {
+							this.showlogin = true
+						}
+					} else {
+						this.showlogin = true
+					}
+					return
+				}
+				uni.navigateTo({
+					url: "/pagesA/index/rizhao?id=" + this.id
+				})
+			},
+			totel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = false
+					if (this.worker_id == 0) {
+						this.$refs.tellist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 1
+						})
+						uni.makePhoneCall({
+							phoneNumber: this.worker_phone
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.houses-info {
+		position: relative;
+		padding: 1rpx 0;
+
+		.fangchan-wenda {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 24rpx 20rpx 24rpx;
+
+			.wenda-more {
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #666666;
+				padding: 0 20rpx;
+			}
+
+			.not-wenda {
+				height: 280rpx;
+
+				.img {
+					width: 142rpx;
+					height: 142rpx;
+				}
+
+				.text1 {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #CCCCCC;
+					margin-bottom: 8rpx;
+				}
+
+				.text2 {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #1677FF;
+				}
+			}
+
+			.wenda-box {
+				padding: 0 20rpx;
+
+				.table-header {
+					width: 620rpx;
+					height: 94rpx;
+					border: 2rpx solid #F0F0F0;
+
+					input {
+						text-align: center;
+						color: red;
+					}
+				}
+
+				.wenda-table {
+					width: 620rpx;
+					max-height: 378rpx;
+					border-radius: 16rpx;
+					margin-bottom: 20rpx;
+
+					.table-row {
+						white-space: nowrap;
+						height: 94rpx;
+
+						.table-col {
+							width: 155rpx;
+							line-height: 94rpx;
+							height: 94rpx;
+							border-bottom: 2rpx solid #F0F0F0;
+							border-left: 2rpx solid #F0F0F0;
+							padding: 0 16rpx;
+							display: inline-block;
+							font-size: 24rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: rgba(102, 102, 102, 0.88);
+						}
+
+						.table-col:last-child {
+							border-right: 2rpx solid #F0F0F0;
+
+						}
+					}
+
+					.table-row:last-child {
+						.table-col {
+							border-bottom: 2rpx solid #F0F0F0;
+						}
+					}
+				}
+
+				.wenda-text {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					margin-bottom: 20rpx;
+				}
+
+				.box-top {
+					margin-bottom: 20rpx;
+
+					.text2 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+						margin-right: 20rpx;
+					}
+
+					.text3 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					.img {
+						width: 36rpx;
+						height: 36rpx;
+						border-radius: 100rpx;
+						margin: 0 20rpx;
+					}
+
+					.text1 {
+						width: 36rpx;
+						line-height: 36rpx;
+						background: #1677FF;
+						border-radius: 8rpx;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Semibold, PingFang SC;
+						font-weight: 600;
+						color: #FFFFFF;
+					}
+				}
+			}
+
+			.wenda-title {
+				padding: 20rpx 0 30rpx 0;
+
+				text:first-child {
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #131415;
+				}
+
+				text:last-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #1677FF;
+				}
+			}
+		}
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.dijia-box {
+			position: relative;
+
+			.dijia-text {
+				position: absolute;
+				z-index: 10;
+				top: 120rpx;
+				left: 0;
+				width: 100%;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #EC9234;
+				padding: 0 150rpx;
+			}
+
+			.dijia-img {
+				width: 650rpx;
+				height: 520rpx;
+				margin-bottom: 52rpx;
+			}
+		}
+
+		.houses-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 1;
+
+			text:first-child {
+				width: 218rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+			
+			text:nth-child(2) {
+				width: 218rpx;
+				line-height: 84rpx;
+				background: #5BC22A;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			text:last-child {
+				width: 218rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.huxing-box {
+			width: 702rpx;
+			// height: 450rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx 30rpx 20rpx;
+
+			.huxing-list {
+				white-space: nowrap;
+
+				.huxing-item {
+					margin-right: 20rpx;
+					display: inline-block;
+
+					.jianyi {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					.name {
+						margin: 24rpx 0 10rpx 0;
+						font-size: 24rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+
+					.huxing-img {
+						width: 206rpx;
+						height: 206rpx;
+					}
+				}
+			}
+
+			.huixng-title {
+				padding: 24rpx 0;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #131415;
+			}
+		}
+
+		.map-box {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx 24rpx 20rpx;
+
+			.map-title {
+				padding: 24rpx 0;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #131415;
+			}
+		}
+
+		.address-box {
+			width: 702rpx;
+			height: 82rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 22rpx;
+
+			.text {
+				flex: 1;
+				margin-left: 10rpx;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #131415;
+			}
+		}
+
+		.houses-box {
+			width: 702rpx;
+			height: 594rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx;
+
+			.kaifa-box {
+				padding: 24rpx 20rpx;
+				background: #F5F5F5;
+				border-radius: 20rpx;
+
+				view {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+			}
+
+			.houses-label {
+				padding: 24rpx 0 14rpx 0;
+
+				text {
+					line-height: 40rpx;
+					background: #fff;
+					border-radius: 8rpx;
+					padding: 0 10rpx;
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					margin-right: 10rpx;
+					margin-bottom: 10rpx;
+				}
+			}
+
+			.houses-data {
+				padding: 20rpx 0;
+				// height: 126rpx;
+				border-bottom: 2rpx solid #F5F5F5;
+
+				.data-item {
+					// width: 134rpx;
+					// flex: 1;
+					// margin-right: 22rpx;
+
+					// margin-right: 10rpx;
+					text:first-child {
+						font-size: 30rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #131415;
+						margin-bottom: 8rpx;
+						white-space: nowrap;
+					}
+
+					text:last-child {
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+				}
+
+				.data-item:last-child {
+					margin-right: 0;
+				}
+			}
+
+			.price {
+				padding-bottom: 24rpx;
+				border-bottom: 2rpx solid #F5F5F5;
+
+				text:first-child {
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					margin-right: 8rpx;
+				}
+
+				text:last-child {
+					font-size: 32rpx;
+					font-family: DINAlternate-Bold, DINAlternate;
+					font-weight: bold;
+					color: #FF3B30;
+				}
+			}
+
+			.box-tips {
+				font-size: 24rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #666666;
+				margin-bottom: 20rpx;
+			}
+
+			.box-header {
+				padding: 24rpx 0 12rpx 0;
+
+				text:first-child {
+					font-size: 36rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #131415;
+				}
+
+				text:last-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #1F7EFF;
+				}
+			}
+		}
+
+		.houses-tabs {
+			width: 702rpx;
+			height: 218rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+
+			.tabs-item {
+				flex: 1;
+
+				image {
+					width: 84rpx;
+					height: 84rpx;
+					margin-bottom: 20rpx;
+				}
+
+				text {
+					// margin-top: -34rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #131415;
+				}
+			}
+		}
+
+		.swiper-box {
+			width: 702rpx;
+			margin: 20rpx auto;
+		}
+
+		.index-bg {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 750rpx;
+			height: 556rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			z-index: -1;
+		}
+	}
+</style>

+ 735 - 0
pages/index/index.vue

@@ -0,0 +1,735 @@
+<template>
+	<view class="index-index">
+		<view class="index-bg"></view>
+		<u-navbar :title="config.store_title" title-color="#fff" :isFixed="false" :background="{background:'rgba(0,0,0,0)'}" :border-bottom="false" :isBack="false">
+			<view class="u-flex nav-left" slot="left" @click="tochangecity">
+				<u-icon name="map-fill" size="34" color="#fff"></u-icon>
+				<text class="text">{{defaultcity.city || '定位中'}}</text>
+			</view>
+		</u-navbar>
+		<view class="renqi-box u-flex">
+			<u-icon name="heart-fill" color="#fff" size="26"></u-icon>
+			<text class="text">累计人气值 {{popularity}}</text>
+		</view>
+		<view class="search-box u-flex u-row-between" @click="tosearch">
+			<u-icon name="search" color="#CCCCCC" size="36"></u-icon>
+			<input type="text" placeholder="搜索楼盘" class="input" :disabled="true">
+			<text class="text">搜索</text>
+		</view>
+		<view class="swiper-box">
+			<u-swiper :list="swiperlisi" name="logo" height="280" border-radius="20" @click="tobanner"></u-swiper>
+		</view>
+		<view class="tabs-list" v-if="tabslist.length > 0">
+			<gf-scroll :list="tabslist" :userinfo="userinfo" @click="tourl"></gf-scroll>
+		</view>
+		<view class="list-box" v-if="dijialist.length > 0">
+			<view class="list-title u-flex u-row-between">
+				<view class="u-flex title-left">
+					<text>底价人气热盘</text>
+					<image src="../../static/images/hot.png" mode=""></image>
+				</view>
+				<view class="more" @click="toall(1)">
+					查看更多
+				</view>
+			</view>
+			<view class="u-flex u-row-between u-flex-wrap">
+				<view class="list-item" v-for="(item,index) in dijialist" :key="index" @click="toinfo(item)">
+					<view class="item-img">
+						<image :src="item.logo" class="logo" mode="aspectFill"></image>
+						<view class="logo-look u-flex">
+							<u-icon name="eye-fill" size="28" color="#fff"></u-icon>
+							<text class="text">{{getview(item.page_view)}}</text>
+						</view>
+					</view>
+					<view class="item-name u-line-1">
+						{{item.name}}
+					</view>
+					<view class="u-flex price">
+						<text>参考均价</text>
+						<text v-if="Number(item.avg_price)">{{item.avg_price}}元/㎡</text>
+						<text v-else>{{item.avg_price}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="list-box" v-if="tuijianlist.length > 0">
+			<view class="list-title u-flex u-row-between">
+				<view class="u-flex title-left">
+					<text>推荐楼盘</text>
+				</view>
+				<view class="more" @click="toall(5)">
+					查看更多
+				</view>
+			</view>
+			<view class="u-flex u-row-between u-flex-wrap">
+				<view class="list-item" v-for="(item,index) in tuijianlist" :key="index" @click="toinfo(item)">
+					<view class="item-img">
+						<image :src="item.logo" class="logo" mode="aspectFill"></image>
+						<view class="logo-look u-flex">
+							<u-icon name="eye-fill" size="28" color="#fff"></u-icon>
+							<text class="text">{{getview(item.page_view)}}</text>
+						</view>
+					</view>
+					<view class="item-name u-line-1">
+						{{item.name}}
+					</view>
+					<view class="u-flex price">
+						<text>参考均价</text>
+						<text v-if="Number(item.avg_price)">{{item.avg_price}}元/㎡</text>
+						<text v-else>{{item.avg_price}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<u-popup v-model="showguanggao" mode="center" border-radius="20" background="rgba(0,0,0,0)">
+			<view class="guanggao-box">
+				<u-swiper :list="guanggaolist" bgColor="rgba(0,0,0,0)" name="logo" height="974" border-radius="20" :autoplay="false"></u-swiper>
+				<view class="close-box u-flex">
+					<text style="border-right: 1rpx solid #fff;">{{s}}s</text>
+					<text @click="closeguanggao">关闭</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showgzh" mode="center" border-radius="20">
+			<view style="font-size: 0;">
+				<image style="width: 650rpx;height: 650rpx;" :src="config.service_code" mode=""></image>
+			</view>
+		</u-popup>
+		<u-popup v-model="showcity" mode="center" border-radius="20" :maskCloseAble="false">
+			<view class="changecity-popup u-flex-col u-col-center u-row-center">
+				<view class="city-bg"></view>
+				<image src="../../static/images/index-img2.png" class="city-img" mode=""></image>
+				<view class="city-tips u-flex-col u-col-center">
+					<text>您当前所在定位城市为:</text>
+					<text>【{{citydata.city}}】</text>
+					<text>是否切换至当前定位城市?</text>
+				</view>
+				<view class="city-btn u-flex u-row-between">
+					<text @click="notchangecity">否</text>
+					<text @click="changecity">是</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showcitynot" mode="center" border-radius="20" :maskCloseAble="false" :closeable="true">
+			<view class="changecity-popup u-flex-col u-col-center u-row-center">
+				<view class="city-bg"></view>
+				<image src="../../static/images/index-img2.png" class="city-img" mode=""></image>
+				<view class="city-tips u-flex-col u-col-center" style="width: 352rpx;">
+					<text>此城市末开放数据</text>
+					<text>己为你自动切换</text>
+					<text>【{{notcityname}}】</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-tabbar></gf-tabbar>
+	</view>
+</template>
+
+<script>
+	import {
+		mapGetters,
+		mapState
+	} from 'vuex'
+	export default {
+		data() {
+			return {
+				swiperlisi: [],
+				tabslist: [],
+				showguanggao: false,
+				guanggaolist: [],
+				s: 5,
+				time: null,
+				showgzh: false,
+				popularity: 0,
+				dijialist: [],
+				tuijianlist: [],
+				showcity: false,
+				showcitynot: false,
+				notcityname: '',
+				userinfo: {
+					certification_type: 0
+				}
+			}
+		},
+		onLoad() {
+			this.getbanner()
+			this.getguanggao()
+			if (this.defaultcity.city_id) {
+				this.getlist()
+			}
+		},
+		onShow() {
+			this.getpopularity()
+			if ([0, 1, '0', '1'].includes(this.config.intermediary_show)) {
+				if (uni.getStorageSync("token")) {
+					this.getuser()
+				} else {
+					this.userinfo = {
+						certification_type: 0
+					}
+					this.gettabs()
+				}
+			}
+		},
+		computed: {
+			...mapGetters(['config']),
+			...mapState(['defaultcity', 'citydata'])
+		},
+		watch: {
+			citydata: {
+				deep: true,
+				handler(val) {
+					if (uni.getStorageSync("city") && uni.getStorageSync("city").city_id) {
+
+					} else {
+						if (val.city != this.defaultcity.city) {
+							this.showcity = true
+						}
+					}
+				}
+			},
+			defaultcity: {
+				deep: true,
+				handler(val) {
+					if (val.city_id) {
+						this.getlist()
+					}
+				}
+			},
+			config: {
+				deep: true,
+				handler(val) {
+					if (uni.getStorageSync("token")) {
+						this.getuser()
+					} else {
+						this.userinfo = {
+							certification_type: 0
+						}
+						this.gettabs()
+					}
+				}
+			}
+		},
+		methods: {
+			getview(count) {
+				if (count > 10000) {
+					return Number((count / 10000).toFixed(2)) + 'w'
+				}
+				if (count > 1000) {
+					return Number((count / 1000).toFixed(2)) + 'k'
+				}
+				return count
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.userinfo = res.data
+					this.gettabs()
+				})
+			},
+			tochangecity() {
+				uni.navigateTo({
+					url: "/pages/index/change-city",
+					events: {
+						changecity: (res) => {
+							this.$store.commit('setdefaultcity', {
+								city: res.shi.name,
+								userLocation: `${res.shi.lng},${res.shi.lat}`,
+								city_id: res.shi.id,
+								province_id: res.sheng.id
+							})
+							this.setcity()
+						}
+					}
+				})
+			},
+			notchangecity() {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Index/location', {
+					longitude: '120.699279',
+					latitude: '27.993849',
+					city_name: '温州市'
+				}).then(res => {
+					if (res.code == 1) {
+						this.showcity = false
+						this.$store.commit('setdefaultcity', {
+							city: '温州市',
+							userLocation: '120.699279,27.993849',
+							city_id: res.data.city_id,
+							province_id: res.data.province_id
+						})
+					} else {
+						this.showcity = false
+						this.showcitynot = true
+						this.notcityname = res.data.city_name
+						this.$store.commit('setdefaultcity', {
+							city: res.data.city_name,
+							userLocation: `${res.data.longitude},${res.data.latitude}`,
+							city_id: res.data.city_id,
+							province_id: res.data.province_id
+						})
+						this.setcity()
+					}
+				})
+			},
+			changecity() {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Index/location', {
+					longitude: this.citydata.userLocation.split(',')[0],
+					latitude: this.citydata.userLocation.split(',')[1],
+					city_name: this.citydata.city
+				}).then(res => {
+					if (res.code == 1) {
+						this.showcity = false
+						this.$store.commit('setdefaultcity', {
+							city: this.citydata.city,
+							userLocation: this.citydata.userLocation,
+							city_id: res.data.city_id,
+							province_id: res.data.province_id
+						})
+					} else {
+						this.showcity = false
+						this.showcitynot = true
+						this.notcityname = res.data.city_name
+						this.$store.commit('setdefaultcity', {
+							city: res.data.city_name,
+							userLocation: `${res.data.longitude},${res.data.latitude}`,
+							city_id: res.data.city_id,
+							province_id: res.data.province_id
+						})
+						this.setcity()
+					}
+				})
+			},
+			setcity() {
+				this.$u.post('/api/Index/location', {
+					longitude: this.defaultcity.userLocation.split(',')[0],
+					latitude: this.defaultcity.userLocation.split(',')[1],
+					city_name: this.defaultcity.city
+				})
+			},
+			getlist() {
+				this.$u.get('/api/Index/property_list', {
+					page: 1,
+					page_num: 10,
+					type: 1,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.dijialist = res.data
+				})
+				this.$u.get('/api/Index/property_list', {
+					page: 1,
+					page_num: 10,
+					type: 5,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.tuijianlist = res.data
+				})
+			},
+			daojishi() {
+				this.s = 5
+				this.time = setInterval(() => {
+					if (this.s == 0) {
+						this.showguanggao = false
+						clearInterval(this.time)
+					} else {
+						this.s--
+					}
+				}, 1000)
+			},
+			getguanggao() {
+				this.$u.post('/api/Index/adv_list').then(res => {
+					if(res.data.length > 0){
+						this.guanggaolist = res.data
+						this.showguanggao = true
+						this.daojishi()
+					}
+				})
+			},
+			gettabs() {
+				this.$u.post("/api/Index/diamond_list").then(res => {
+					this.tabslist = []
+					res.data.forEach(val => {
+						if (val.id == 11 && this.config.intermediary_show == 1 && (this.userinfo.certification_type == 1 || this.userinfo.certification_type == 0)) {
+							this.tabslist.push(val)
+						} else if (val.id == 12 && this.config.people_show == 1 && (this.userinfo.certification_type == 2 || this.userinfo.certification_type == 0)) {
+							this.tabslist.push(val)
+						} else if (val.id != 11 && val.id != 12) {
+							this.tabslist.push(val)
+						}
+					})
+					console.log(this.tabslist);
+					// console.log(this.userinfo.certification_type);
+					// console.log(JSON.parse(JSON.stringify(this.tabslist)));
+				})
+			},
+			tobanner(e) {
+				if (this.swiperlisi[e].url) {
+					uni.navigateTo({
+						url: this.swiperlisi[e].url
+					})
+				}
+			},
+			getbanner() {
+				this.$u.post('/api/Index/banner').then(res => {
+					this.swiperlisi = res.data
+				})
+			},
+			getpopularity() {
+				this.$u.post('/api/Index/add_popularity').then(res => {
+					this.$store.commit('setpopularity', res.data)
+					this.popularity = res.data
+				})
+			},
+			tosearch() {
+				uni.navigateTo({
+					url: "./search"
+				})
+			},
+			toinfo(item) {
+				uni.navigateTo({
+					url: "./houses-info?id=" + item.id+ '&name=' + item.name
+				})
+			},
+			tourl(item) {
+				if (item.id == 1) {
+					uni.navigateTo({
+						url: "/pagesA/index/newHouses?title=" + item.title
+					})
+				}
+				if (item.id == 2) {
+					uni.navigateTo({
+						url: "/pagesA/index/allHouses?type=3&title=" + item.title
+					})
+				}
+				if (item.id == 3) {
+					uni.navigateTo({
+						url: "/pagesA/index/allHouses?type=4&title=" + item.title
+					})
+				}
+				if (item.id == 4) {
+					uni.navigateTo({
+						url: "/pagesA/index/dataCenter?title=" + item.title
+					})
+				}
+				if (item.id == 5) {
+					this.showgzh = true
+				}
+				if (item.id == 6) {
+					uni.navigateTo({
+						url: "./fuli?title=" + item.title
+					})
+				}
+				if (item.id == 7) {
+					uni.navigateTo({
+						url: "./news?title=" + item.title
+					})
+				}
+				if (item.id == 8) {
+					uni.navigateTo({
+						url: "/pagesA/index/counter?title=" + item.title
+					})
+				}
+				if (item.id == 9) {
+					uni.navigateTo({
+						url: "/pagesA/index/allHouses?title=" + item.title
+					})
+				}
+				if (item.id == 10) {
+					uni.navigateTo({
+						url: "./pk-list?title=" + item.title
+					})
+				}
+				if (item.id == 11) {
+					if (this.$islogin()) return
+					uni.navigateTo({
+						url: "./broker?type=1&title=" + item.title
+					})
+				}
+				if (item.id == 12) {
+					if (this.$islogin()) return
+					uni.navigateTo({
+						url: "./broker?type=2&title=" + item.title
+					})
+				}
+			},
+			toall(type) {
+				uni.navigateTo({
+					url: "/pagesA/index/allHouses?type=" + type
+				})
+			},
+			closeguanggao() {
+				this.showguanggao = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.index-index {
+		position: relative;
+		z-index: 1;
+
+		.changecity-popup {
+			width: 602rpx;
+			height: 590rpx;
+			position: relative;
+
+			.city-btn {
+				width: 100%;
+				padding: 0 40rpx;
+
+				text:first-child {
+					width: 250rpx;
+					line-height: 88rpx;
+					background: #CCCCCC;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 250rpx;
+					line-height: 88rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.city-tips {
+				width: 480rpx;
+				font-size: 32rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #666666;
+				margin-bottom: 56rpx;
+				text-align: center;
+			}
+
+			.city-img {
+				width: 198rpx;
+				height: 198rpx;
+				margin-bottom: 26rpx;
+			}
+
+			.city-bg {
+				width: 602rpx;
+				height: 442rpx;
+				background: linear-gradient(180deg, #1EFF7B 0%, rgba(255, 255, 255, 0) 100%);
+				opacity: 0.2;
+				position: absolute;
+				top: 0;
+				left: 0;
+			}
+		}
+
+		.guanggao-box {
+			width: 650rpx;
+			height: 974rpx;
+			position: relative;
+
+			.close-box {
+				position: absolute;
+				top: 24rpx;
+				right: 24rpx;
+				z-index: 1;
+				width: 150rpx;
+				height: 50rpx;
+				background: rgba(0, 0, 0, 0.5);
+				border-radius: 8rpx;
+				border: 2rpx solid #FFFFFF;
+
+				text {
+					flex: 1;
+					line-height: 30rpx;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+		}
+
+		.list-box {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx;
+
+			.list-item {
+				width: 320rpx;
+				margin-bottom: 24rpx;
+
+				.price {
+					text:first-child {
+						font-size: 20rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						margin-right: 10rpx;
+					}
+
+					text:last-child {
+						font-size: 32rpx;
+						font-family: DINAlternate-Bold, DINAlternate;
+						font-weight: bold;
+						color: #FF3B30;
+					}
+				}
+
+				.item-name {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #131415;
+					margin: 10rpx 0;
+				}
+
+				.item-img {
+					width: 320rpx;
+					height: 240rpx;
+					border-radius: 20rpx;
+					position: relative;
+					overflow: hidden;
+					.logo-look {
+						position: absolute;
+						bottom: 0;
+						left: 0;
+						width: 320rpx;
+						height: 52rpx;
+						background: rgba(0, 0, 0, 0.3);
+						padding: 0 20rpx;
+
+						.text {
+							font-size: 20rpx;
+							font-family: SourceHanSansSC-Heavy, SourceHanSansSC;
+							font-weight: 800;
+							color: rgba(256, 256, 256, 0.7);
+							margin-left: 12rpx;
+						}
+					}
+					.logo {
+						width: 320rpx;
+						height: 240rpx;
+					}
+				}
+			}
+
+			.list-title {
+				padding: 24rpx 0;
+
+				.more {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+
+				.title-left {
+					text {
+						font-size: 34rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #131415;
+						margin-right: 14rpx;
+					}
+
+					image {
+						width: 26rpx;
+						height: 32rpx;
+					}
+				}
+			}
+		}
+
+		.tabs-list {
+			padding: 0 24rpx;
+			margin-bottom: 20rpx;
+		}
+
+		.swiper-box {
+			padding: 0 24rpx;
+			margin-bottom: 20rpx;
+		}
+
+		.search-box {
+			width: 702rpx;
+			height: 72rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 0 auto 20rpx auto;
+			padding-left: 24rpx;
+
+			.input {
+				flex: 1;
+				margin: 0 10rpx;
+			}
+
+			.text {
+				padding: 0 24rpx;
+				border-left: 1rpx solid #E5E7ED;
+				line-height: 36rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #1E7DFF;
+			}
+		}
+
+		.renqi-box {
+			width: 750rpx;
+			height: 56rpx;
+			background: rgba(256, 256, 256, 0.1);
+			padding: 0 24rpx;
+			margin-bottom: 24rpx;
+
+			.text {
+				font-size: 24rpx;
+				font-family: Helvetica;
+				color: #FFFFFF;
+				margin-left: 10rpx;
+			}
+		}
+
+		.nav-left {
+			padding: 0 20rpx;
+
+			.text {
+				font-size: 32rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #FFFFFF;
+				margin-left: 5rpx;
+			}
+		}
+
+		.index-bg {
+			width: 750rpx;
+			height: 732rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			position: absolute;
+			top: 1;
+			left: 0;
+			z-index: -1;
+		}
+	}
+</style>

+ 401 - 0
pages/index/info.vue

@@ -0,0 +1,401 @@
+<template>
+	<view class="info1">
+		<view class="info1-title">
+			基本情况
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">备案名称</text>
+			<text class="u-flex-1">{{detail.record_name}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">销售状态</text>
+			<text class="u-flex-1">{{detail.sale_state}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">售楼位置</text>
+			<view class="u-flex u-col-top">
+				<u-icon name="map-fill" color="#1F7EFF" size="30" style="margin-top: 2rpx;margin-right: 10rpx;"></u-icon>
+				<text class="u-flex-1">{{detail.sales_office}}</text>
+			</view>
+		</view>
+		<!-- <view class="u-flex info1-row">
+			<text class="text">楼盘位置</text>
+			<view class="u-flex u-col-top">
+				<u-icon name="map-fill" color="#1F7EFF" size="30" style="margin-top: 2rpx;margin-right: 10rpx;"></u-icon>
+				<text class="u-flex-1">上城区三关塘路与华家竹园路交汇处向西200米</text>
+			</view>
+		</view> -->
+		<view class="u-flex info1-row">
+			<text class="text">装修状况</text>
+			<text class="u-flex-1">{{detail.fitment_state}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">交房时间</text>
+			<text class="u-flex-1">{{detail.delivery_time}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">建筑层高</text>
+			<text class="u-flex-1">{{detail.floor_height}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">户型面积</text>
+			<text class="u-flex-1">{{detail.house_min_area}}㎡-{{detail.house_max_area}}㎡</text>
+		</view>
+		<view class="u-flex info1-row" v-if="detail.trait">
+			<text class="text">楼盘类型</text>
+			<text class="u-flex-1" v-if="detail.trait.length > 0">{{detail.trait.join(' ')}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">物业费用</text>
+			<text class="u-flex-1">{{detail.property_cost}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">物业公司</text>
+			<text class="u-flex-1">{{detail.property_company}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">物业类别</text>
+			<text class="u-flex-1">{{detail.property_class}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">产权年限</text>
+			<text class="u-flex-1">{{detail.property_deadline}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">楼层状况</text>
+			<text class="u-flex-1">{{detail.floor_case}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">人车分流</text>
+			<text class="u-flex-1">{{detail.car_shunt}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">开盘时间</text>
+			<text class="u-flex-1">{{detail.sale_time}}</text>
+		</view>
+		<view class="xian"></view>
+		<view class="info1-title">
+			总体情况
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">项目名称</text>
+			<text class="u-flex-1">{{detail.name}}</text>
+		</view>
+		<!-- <view class="u-flex info1-row">
+			<text class="text">项目简介</text>
+			<text class="u-flex-1">上城区三关塘路与华家竹园路交汇处向西200米</text>
+		</view> -->
+		<view class="u-flex info1-row">
+			<text class="text">项目地址</text>
+			<view class="u-flex u-col-top" @click="tomap">
+				<u-icon name="map-fill" color="#1F7EFF" size="30" style="margin-top: 2rpx;margin-right: 10rpx;"></u-icon>
+				<text class="u-flex-1">{{detail.project_address}}</text>
+			</view>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">总户数量</text>
+			<text class="u-flex-1">{{detail.resident_num}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">车位配比</text>
+			<text class="u-flex-1">{{detail.stall_ratio}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">总栋数</text>
+			<text class="u-flex-1">{{detail.tower_num}}栋</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">绿化率</text>
+			<text class="u-flex-1">{{detail.greening_rate}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">容积率</text>
+			<text class="u-flex-1">{{detail.plot_ratio}}%</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">占地面积</text>
+			<text class="u-flex-1">{{detail.floor_area}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">总建面积</text>
+			<text class="u-flex-1">{{detail.covered_area}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">总车位数</text>
+			<text class="u-flex-1">{{detail.stall_num}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">学校</text>
+			<text class="u-flex-1">{{detail.school}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">小区内配套</text>
+			<text class="u-flex-1">{{detail.plot_mating}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">外立面</text>
+			<text class="u-flex-1">{{detail.external_wall}}</text>
+		</view>
+		<view class="u-flex info1-row">
+			<text class="text">预售许可证</text>
+			<text class="u-flex-1">{{detail.permit_presale}}</text>
+		</view>
+		<view class="xian"></view>
+		<view class="info1-title">
+			楼盘简介
+		</view>
+		<view class="jianjie">
+			{{detail.project_synopsis}}
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="houses-btn u-flex u-row-between">
+			<text @click="opentel">隐私电话</text>
+			<text @click="tochat">在线咨询</text>
+		</view>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">您是否进行呼叫?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="totel">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+		<gf-tel ref="tellist" @over="getuser"></gf-tel>
+	</view>
+</template>
+
+<script>
+	export default {
+
+		data() {
+			return {
+				showtocall: false,
+				id: '',
+				detail: {},
+				showlogin: false,
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		methods: {
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			tomap() {
+				uni.openLocation({
+					latitude: Number(this.detail.latitude),
+					longitude: Number(this.detail.longitude)
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			opentel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getdata() {
+				this.$u.get('/api/Property/property_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+				})
+			},
+			totel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = false
+					if (this.worker_id == 0) {
+						this.$refs.tellist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 1
+						})
+						uni.makePhoneCall({
+							phoneNumber: this.worker_phone
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.info1 {
+		padding: 16rpx 24rpx;
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.houses-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 1;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.xian {
+			width: 702rpx;
+			height: 2rpx;
+			background: #CCCCCC;
+			margin: 16rpx auto;
+		}
+
+		.info1-row {
+			margin-bottom: 24rpx;
+			font-size: 24rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #666666;
+
+			.text {
+				width: 140rpx;
+			}
+		}
+
+		.jianjie {
+			font-size: 24rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #666666;
+		}
+
+		.info1-title {
+			padding: 24rpx 0;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+		}
+	}
+</style>

+ 75 - 0
pages/index/news-info.vue

@@ -0,0 +1,75 @@
+<template>
+	<view class="news-info">
+		<web-view v-if="detail.url" :src="detail.url"></web-view>
+		<view v-if="!detail.url">
+			<view  class="news-title">
+				{{detail.title}}
+			</view>
+			<view class="u-flex news-header">
+				<image :src="detail.head_image" class="head" mode=""></image>
+				<text class="name">{{detail.source}} {{detail.create_at}} 发表于{{detail.publish}}</text>
+			</view>
+			<u-parse :html="detail.content" :show-with-animation="true" :lazy-load="true"></u-parse>
+			<!-- <view class="" v-html="detail.content"></view> -->
+		</view>
+
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				id: '',
+				detail: {}
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+		},
+		methods: {
+			getdata() {
+				this.$u.post('/api/Headline/headline_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+					const regex = new RegExp('<img', 'gi')
+					this.detail.content = res.data.content.replace(regex, `<img style="max-width: 100%; height: auto"`)
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.news-info {
+		padding: 24rpx;
+
+		.news-header {
+			margin-bottom: 40rpx;
+
+			.head {
+				width: 36rpx;
+				height: 36rpx;
+				border-radius: 100rpx;
+				margin-right: 10rpx;
+			}
+
+			.name {
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+			}
+		}
+
+		.news-title {
+			font-size: 36rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+			margin-bottom: 24rpx;
+		}
+	}
+</style>

+ 181 - 0
pages/index/news.vue

@@ -0,0 +1,181 @@
+<template>
+	<view class="news">
+		<view class="first-box u-flex u-row-between u-col-top">
+			<view class="first-item" v-for="(item,index) in list" v-if="index < 2" :key="index" @click="toinfo(item)">
+				<image :src="item.logo" class="image" mode=""></image>
+				<view class="name u-line-2">
+					{{item.title}}
+				</view>
+				<view class="user u-flex">
+					<image :src="item.head_image" class="head" mode=""></image>
+					<text class="user-name">{{item.source}}</text>
+				</view>
+			</view>
+		</view>
+		<view class="news-item u-flex u-row-between" v-for="(item,index) in list" v-if="index >= 2" :key="index" @click="toinfo(item)">
+			<image :src="item.logo" class="image" mode=""></image>
+			<view class="item-right">
+				<view class="name u-line-2">
+					{{item.title}}
+				</view>
+				<view class="u-flex u-row-between">
+					<view class="time u-flex">
+						<u-icon name="eye-fill" color="#CCCCCC" size="26"></u-icon>
+						<text class="look">{{item.page_view}}人浏览</text>
+						<text class="time-text">{{item.create_at}}</text>
+					</view>
+					<view class="user u-flex">
+						<image :src="item.head_image" class="head" mode=""></image>
+						<text class="user-name">{{item.source}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		data() {
+			return {
+				page: 1,
+				list: [],
+				title: ''
+			}
+		},
+		computed: {
+			...mapState(['defaultcity'])
+		},
+		onLoad(option) {
+			this.title = option.title
+			this.getlist()
+		},
+		onShow() {
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			getlist() {
+				this.$u.post('/api/Headline/headline_list', {
+					page: this.page,
+					page_num: 20,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.list = this.list.concat(res.data || [])
+				})
+			},
+			toinfo(item) {
+				uni.navigateTo({
+					url: "./news-info?id=" + item.id
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.news {
+		padding: 0 44rpx;
+
+		.news-item {
+			padding: 32rpx 0;
+			border-bottom: 2rpx solid #CCCCCC;
+
+			.image {
+				width: 140rpx;
+				height: 110rpx;
+				border-radius: 10rpx;
+			}
+
+			.item-right {
+				flex: 1;
+				margin-left: 14rpx;
+
+				.name {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+					margin-bottom: 16rpx;
+				}
+
+				.user {
+					.user-name {
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					.head {
+						width: 24rpx;
+						height: 24rpx;
+						border-radius: 100rpx;
+						margin-right: 10rpx;
+					}
+				}
+
+				.time {
+					font-size: 18rpx;
+					font-weight: 400;
+					color: #999999;
+
+					.look {
+						margin: 0 10rpx;
+					}
+				}
+			}
+		}
+
+		.first-box {
+			padding: 24rpx 0;
+			border-bottom: 2rpx solid #CCCCCC;
+
+			.first-item {
+				width: 320rpx;
+
+				.user {
+					margin-top: 10rpx;
+
+					.user-name {
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					.head {
+						width: 24rpx;
+						height: 24rpx;
+						border-radius: 100rpx;
+						margin-right: 10rpx;
+					}
+				}
+
+				.image {
+					width: 320rpx;
+					height: 220rpx;
+					border-radius: 10rpx;
+				}
+
+				.name {
+					margin-top: 14rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+				}
+			}
+		}
+	}
+</style>

+ 392 - 0
pages/index/pk-info.vue

@@ -0,0 +1,392 @@
+<template>
+	<view class="pk-info">
+		<scroll-view scroll-y="true" scroll-x="true" class="pk-scroll-w">
+			<view class="pk-scroll-w-box">
+				<view class="pk-header u-flex-col u-col-center">
+					<view class="pk-left-w">
+						<view class="pk-left">
+							<image src="../../static/images/pk.png" mode="aspectFit"></image>
+						</view>
+					</view>
+					<view class="pk-item" v-for="(item,index) in list" :key="index">
+						<image :src="item.logo" class="pk-item-img" mode=""></image>
+						<view class="pk-item-box">
+							<view class="item-name u-line-2">
+								{{item.name}}
+							</view>
+							<view class="label-box u-flex">
+								<text v-for="(a,b) in item.trait" :key="b" v-if="b < 2">{{a}}</text>
+							</view>
+							<view class="price-box u-flex">
+								<text>参考均价</text>
+								<text>{{item.avg_price}}/㎡</text>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="pk-title u-flex">
+					<text>基本情况</text>
+				</view>
+				<view class="pk-table">
+					<view class="pk-table-row u-flex" v-for="(item,index) in jibenlist" :key="index">
+						<view class="row-left u-flex">
+							<text>{{item.title}}</text>
+						</view>
+						<text class="row-text" v-for="(a,b) in list" :key="b" :style="{width:b == 0 ? '276rpx' : '264rpx'}">{{list[b][item.value]}}</text>
+					</view>
+				</view>
+				<view class="pk-title u-flex">
+					<text>总体情况</text>
+				</view>
+				<view class="pk-table">
+					<view class="pk-table-row u-flex" v-for="(item,index) in zongtilist" :key="index">
+						<view class="row-left u-flex">
+							<text>{{item.title}}</text>
+						</view>
+						<text class="row-text" v-for="(a,b) in list" :key="b" :style="{width:b == 0 ? '276rpx' : '264rpx'}">{{list[b][item.value]}}</text>
+					</view>
+				</view>
+				<view class="pk-title u-flex">
+					<text>项目介绍</text>
+				</view>
+				<view class="pk-table">
+					<view class="pk-table-row u-flex">
+						<view class="row-left u-flex">
+							<text>项目简介</text>
+						</view>
+						<text class="row-text" v-for="(a,b) in list" :key="b" :style="{width:b == 0 ? '276rpx' : '264rpx'}">{{a.project_synopsis}}</text>
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				list: [],
+				jibenlist: [{
+						title: '备案名',
+						value: 'record_name'
+					},
+					{
+						title: '销售状态',
+						value: 'sale_state'
+					},
+					{
+						title: '开盘时间',
+						value: 'sale_time'
+					},
+					{
+						title: '物业类别',
+						value: 'property_class'
+					},
+					{
+						title: '产权年限',
+						value: 'property_deadline'
+					},
+					{
+						title: '装修状况',
+						value: 'fitment_state'
+					},
+					{
+						title: '物业公司',
+						value: 'property_company'
+					},
+					{
+						title: '交房时间',
+						value: 'delivery_time'
+					},
+					{
+						title: '项目地址',
+						value: 'project_address'
+					}
+				],
+				zongtilist: [{
+						title: '占地面积(㎡)',
+						value: 'floor_area'
+					},
+					{
+						title: '总占地面积(㎡)',
+						value: 'covered_area'
+					},
+					{
+						title: '容积率',
+						value: 'plot_ratio'
+					},
+					{
+						title: '绿化率(%)',
+						value: 'greening_rate'
+					},
+					{
+						title: '总栋数',
+						value: 'tower_num'
+					},
+					{
+						title: '总户数',
+						value: 'resident_num'
+					},
+					{
+						title: '层高',
+						value: 'floor_height'
+					},
+					{
+						title: '户型面积',
+						value: 'house_type_area'
+					},
+					{
+						title: '总车位数',
+						value: 'stall_num'
+					},
+					{
+						title: '车位配比',
+						value: 'stall_ratio'
+					},
+					{
+						title: '人车分流',
+						value: 'car_shunt'
+					},
+					{
+						title: '物业费用',
+						value: 'property_cost'
+					},
+					{
+						title: '学校',
+						value: 'school'
+					},
+					{
+						title: '小区内配套',
+						value: 'plot_mating'
+					},
+					{
+						title: '外立面',
+						value: 'external_wall'
+					},
+					{
+						title: '楼层状况',
+						value: 'floor_case'
+					},
+					{
+						title: '预售许可证',
+						value: 'permit_presale'
+					},
+					{
+						title: '开发商',
+						value: 'developers'
+					},
+					{
+						title: '售楼中心地址',
+						value: 'sales_office'
+					}
+				],
+				ids: []
+			}
+		},
+		onLoad(option) {
+			this.ids = JSON.parse(option.ids)
+			this.getdata()
+		},
+		methods: {
+			getdata() {
+				this.$u.post('/api/Property/property_comparison',{
+					id_info:this.ids.join(",")
+				}).then(res => {
+					this.list = res.data
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pk-info {
+		.pk-scroll-w {
+			width: 750rpx;
+			height: 100vh;
+
+			.pk-scroll-w-box {
+				padding: 0 24rpx 24rpx 0;
+
+				.pk-table {
+					margin-bottom: 24rpx;
+
+					.pk-table-row {
+						align-items: stretch;
+						white-space: nowrap;
+
+						.row-text {
+							min-height: 82rpx;
+							padding: 24rpx 40rpx;
+							width: 264rpx;
+							border-left: 2rpx solid #fff;
+							border-bottom: 2rpx solid #fff;
+							background-color: #F5F5F5;
+							font-size: 24rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #333333;
+							display: inline-block;
+							flex-shrink: 0;
+							white-space: pre-wrap;
+						}
+
+						.row-left {
+							padding-left: 24rpx;
+							background-color: #fff;
+							border-bottom: 2rpx solid #fff;
+							min-height: 82rpx;
+							display: inline-flex;
+							flex-shrink: 0;
+							position: sticky;
+							left: 0;
+
+							text {
+								width: 124rpx;
+								background: #CCCCCC;
+								padding: 24rpx 14rpx;
+								height: 100%;
+								font-size: 24rpx;
+								font-family: PingFangSC-Regular, PingFang SC;
+								font-weight: 400;
+								color: #333333;
+								text-align: center;
+								white-space: pre-wrap;
+							}
+						}
+					}
+				}
+
+				.pk-title {
+					padding: 0 0 20rpx 0;
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+
+					text {
+						padding: 0 24rpx;
+						position: sticky;
+						left: 0;
+					}
+				}
+
+				.pk-header {
+					white-space: nowrap;
+					position: sticky;
+					top: 0;
+					z-index: 100;
+					background-color: #fff;
+					// padding: 24rpx 0 24rpx 24rpx;
+					writing-mode: vertical-lr;
+
+					.pk-item {
+						display: inline-block;
+						width: 240rpx;
+						height: 320rpx;
+						background: #FFFFFF;
+						box-shadow: 0px 4rpx 8rpx 0px rgba(0, 0, 0, 0.1);
+						border-radius: 8rpx;
+						margin-left: 24rpx;
+						flex-shrink: 0;
+						writing-mode: horizontal-tb;
+
+						.pk-item-img {
+							width: 240rpx;
+							height: 160rpx;
+						}
+
+						.pk-item-box {
+							padding: 0 12rpx;
+
+							.price-box {
+								margin-bottom: 8rpx;
+
+								text:first-child {
+									font-size: 18rpx;
+									font-family: PingFangSC-Regular, PingFang SC;
+									font-weight: 400;
+									color: #999999;
+									margin-right: 8rpx;
+								}
+
+								text:last-child {
+									font-size: 18rpx;
+									font-family: DINAlternate-Bold, DINAlternate;
+									font-weight: bold;
+									color: #FF3B30;
+								}
+							}
+
+							.label-box {
+								margin-bottom: 8rpx;
+
+								text {
+									line-height: 32rpx;
+									background: #F5F5F5;
+									border-radius: 8rpx;
+									padding: 0 12rpx;
+									font-size: 18rpx;
+									font-family: PingFangSC-Regular, PingFang SC;
+									font-weight: 400;
+									color: #999999;
+									margin-right: 10rpx;
+									max-width: 50%;
+									overflow: hidden;
+									text-overflow:ellipsis;
+									white-space: nowrap;
+								}
+							}
+
+							.item-name {
+								height: 68rpx;
+								font-size: 24rpx;
+								font-family: PingFangSC-Regular, PingFang SC;
+								font-weight: 400;
+								color: #131415;
+								margin-bottom: 8rpx;
+								white-space: pre-wrap;
+							}
+						}
+					}
+
+					.pk-left-w {
+						position: sticky;
+						left: 0;
+						background-color: #fff;
+						padding: 24rpx 0 24rpx 24rpx;
+						width: 124rpx;
+						box-sizing: content-box;
+
+						.pk-left {
+
+							width: 124rpx;
+							height: 320rpx;
+							background: linear-gradient(132deg, #FFDD7B 0%, #FFA120 100%);
+							box-shadow: 0px 4rpx 8rpx 0rpx rgba(0, 0, 0, 0.1);
+							border-radius: 8px;
+							display: inline-block;
+
+							image {
+								width: 124rpx;
+								height: 320rpx;
+							}
+						}
+					}
+
+				}
+
+				.u-flex-stretch {
+					align-items: stretch;
+				}
+
+				.pk-scroll-w-left {
+					width: 124rpx;
+					height: 100%;
+					background-color: red;
+				}
+			}
+		}
+	}
+</style>

+ 292 - 0
pages/index/pk-list.vue

@@ -0,0 +1,292 @@
+<template>
+	<view class="pk-list">
+		<view class="index-bg"></view>
+		<view class="search-box u-flex u-row-between" @click="tosearch">
+			<u-icon name="search" color="#CCCCCC" size="36"></u-icon>
+			<input type="text" placeholder="搜索楼盘" class="input" :disabled="true">
+			<text class="text">搜索</text>
+		</view>
+		<view class="pk-box">
+			<view class="box-title">
+				全部楼盘
+			</view>
+			<u-checkbox-group active-color="#1E7DFF" shape="circle" @change="changepk">
+				<view class="pk-item u-flex u-row-between" v-for="(item,index) in list" :key="index">
+					<image :src="item.logo" class="pk-img" mode="aspectFill"></image>
+					<view class="pk-center u-flex-1">
+						<u-icon name="trash" class="del-btn" @click="del(index)"></u-icon>
+						<view class="item-name u-line-1">
+							{{item.name}}
+						</view>
+						<view class="item-tips">
+							<text class="u-line-1" style="white-space: nowrap;" v-if="item.house_type">{{item.house_type.join('·')}}·</text>
+							<text style="white-space: nowrap;">{{item.house_min_area || 0}}-{{item.house_max_area || 0}}㎡</text>
+						</view>
+						<view class="item-tips">
+							{{item.area}}
+						</view>
+						<view class="price-box u-flex">
+							<text>参考均价</text>
+							<text>{{item.avg_price}}元/㎡</text>
+						</view>
+						<view class="u-flex label-box">
+							<text v-for="(a,b) in item.trait" :key="b" v-if="b < 2">{{a}}</text>
+						</view>
+					</view>
+					<u-checkbox :name="item.id" v-model="item.checked"></u-checkbox>
+				</view>
+			</u-checkbox-group>
+			<view style="height: 60vh;" v-if="list.length == 0">
+				<u-empty text="请点击上方搜索楼盘" mode="list"></u-empty>
+			</view>
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="pk-down-btn u-flex u-row-between">
+			<text @click="clear">重置</text>
+			<text @click="toinfo">PK</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				value: false,
+				list: [],
+				ids: [],
+				title: ''
+			}
+		},
+		onLoad(option) {
+			this.title = option.title
+		},
+		onShow() {
+			this.list = uni.getStorageSync("pklist") || []
+			this.list.forEach(val => {
+				val.checked = false
+			})
+			this.list = JSON.parse(JSON.stringify(this.list))
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		methods: {
+			del(index) {
+				uni.showModal({
+					content: "确定删除?",
+					success: (e) => {
+						if (e.confirm) {
+							this.$u.toast("删除成功")
+							this.list.splice(index, 1)
+							uni.setStorageSync("pklist", this.list)
+							this.clear()
+						}
+					}
+				})
+			},
+			clear() {
+				this.ids = []
+				this.list.forEach(val => {
+					val.checked = false
+				})
+			},
+			changepk(e) {
+				this.ids = e
+			},
+			toinfo() {
+				if (this.ids.length < 2) {
+					this.$u.toast("至少选择两项")
+					return
+				}
+				if (this.ids.length > 3) {
+					this.$u.toast("至多选择三项")
+					return
+				}
+				uni.navigateTo({
+					url: "./pk-info?ids=" + JSON.stringify(this.ids)
+				})
+			},
+			tosearch() {
+				uni.navigateTo({
+					url: "./pk-search"
+				})
+			}
+		}
+
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.pk-list {
+		position: relative;
+		z-index: 1;
+		padding: 1rpx 0;
+
+		.pk-down-btn {
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 10;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #B2B2B2;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.pk-box {
+			width: 702rpx;
+			// height: 1760rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 0 auto 20rpx auto;
+			padding: 0 20rpx;
+
+			.pk-item {
+				margin-bottom: 32rpx;
+				position: relative;
+
+				.del-btn {
+					position: absolute;
+					top: 20rpx;
+					right: 0;
+					z-index: 10;
+				}
+
+				.pk-img {
+					width: 280rpx;
+					height: 240rpx;
+					border-radius: 20rpx;
+					margin-right: 20rpx;
+				}
+
+				.pk-center {
+
+
+					.label-box {
+						text {
+							margin-right: 10rpx;
+							padding: 0 12rpx;
+							line-height: 40rpx;
+							height: 40rpx;
+							background: #F5F5F5;
+							border-radius: 8rpx;
+							font-size: 18rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #999999;
+						}
+					}
+
+					.price-box {
+						margin-bottom: 8rpx;
+
+						text:first-child {
+							font-size: 20rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #999999;
+							margin-right: 8rpx;
+						}
+
+						text:last-child {
+							font-size: 32rpx;
+							font-family: DINAlternate-Bold, DINAlternate;
+							font-weight: bold;
+							color: #FF3B30;
+						}
+					}
+
+					.item-name {
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #131415;
+						margin: 10rpx 0;
+						min-width: 1rpx;
+					}
+
+					.item-tips {
+						font-size: 18rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						margin-bottom: 12rpx;
+					}
+				}
+			}
+
+			.box-title {
+				padding: 24rpx 0;
+				font-size: 34rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #131415;
+			}
+		}
+
+		.search-box {
+			width: 702rpx;
+			height: 72rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 24rpx auto;
+			padding-left: 24rpx;
+
+			.input {
+				flex: 1;
+				margin: 0 10rpx;
+			}
+
+			.text {
+				padding: 0 24rpx;
+				border-left: 1rpx solid #E5E7ED;
+				line-height: 36rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #1E7DFF;
+			}
+		}
+
+		.index-bg {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 750rpx;
+			height: 556rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			z-index: -1;
+		}
+	}
+</style>

+ 183 - 0
pages/index/pk-search.vue

@@ -0,0 +1,183 @@
+<template>
+	<view class="pk-search">
+		<view class="search-box u-flex u-row-between">
+			<u-icon name="search" color="#CCCCCC" size="36"></u-icon>
+			<input type="text" placeholder="搜索楼盘" class="input" v-model="keyword1">
+			<text class="text" @click="tosearch">搜索</text>
+		</view>
+		<view class="lishi-box">
+			<view class="lishi-title">
+				历史搜索
+			</view>
+			<view class="u-flex u-flex-wrap">
+				<text v-for="(item,index) in lishilist" :key="index" class="lishi-item" @click="lishisearch(item)">{{item}}</text>
+			</view>
+		</view>
+		<view class="search-list">
+			<view class="search-item u-flex u-row-between" v-for="(item,index) in list" :key="index">
+				<text>{{item.name}}</text>
+				<text @click="addpk(item)">添加</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				lishilist: [],
+				keyword:'',
+				keyword1:'',
+				page:1,
+				list:[]
+			}
+		},
+		onLoad() {
+			this.lishilist = uni.getStorageSync("lishi") || []
+			this.getlist()
+		},
+		onReachBottom() {
+			if(this.list.length % 20 == 0){
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			lishisearch(item){
+				this.keyword = item
+				this.keyword1 = item
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			addpk(item){
+				var list = uni.getStorageSync("pklist") || []
+				var index = list.findIndex(value => value.id == item.id)
+				console.log(index);
+				if(index == -1){
+					list.unshift(item)
+					uni.setStorageSync("pklist",list)
+					uni.navigateBack()
+				}else{
+					uni.showModal({
+						content:"该楼盘已添加!"
+					})
+				}
+			},
+			setlishi() {
+				if (this.keyword) {
+					if (this.lishilist.indexOf(this.keyword) == -1) {
+						this.lishilist.unshift(this.keyword)
+						uni.setStorageSync("lishi", this.lishilist)
+					}
+				}
+			},
+			tosearch() {
+				this.keyword = this.$u.trim(this.keyword1)
+				this.setlishi()
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			getlist(){
+				this.$u.post('/api/Index/property_list', {
+					page: this.page,
+					page_num: 20,
+					keyword: this.keyword
+				}).then(res => {
+					if (this.page == 1) {
+						this.list = res.data
+					} else {
+						this.list = this.list.concat(res.data)
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pk-search {
+		.search-list {
+			padding: 0 24rpx;
+
+			.search-item {
+				padding: 18rpx 0;
+				border-bottom: 1rpx solid #F2F2F2;
+
+				text:first-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+
+				text:last-child {
+					width: 80rpx;
+					line-height: 46rpx;
+					background: #1F7EFF;
+					border-radius: 8rpx;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+		}
+
+		.lishi-box {
+			padding: 0 24rpx;
+
+			.lishi-item {
+				line-height: 44rpx;
+				background: #E5E5E5;
+				border-radius: 22rpx;
+				padding: 0 30rpx;
+				font-size: 18rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				margin-bottom: 20rpx;
+				margin-right: 20rpx;
+			}
+
+			.lishi-title {
+				font-size: 24rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #333333;
+				margin-bottom: 14rpx;
+			}
+		}
+
+		.search-box {
+			width: 702rpx;
+			height: 72rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 24rpx auto;
+			padding-left: 24rpx;
+			border: 2rpx solid #CCCCCC;
+			position: sticky;
+			top: 0;
+			left: 0;
+
+			.input {
+				flex: 1;
+				margin: 0 10rpx;
+			}
+
+			.text {
+				padding: 0 24rpx;
+				border-left: 1rpx solid #E5E7ED;
+				line-height: 36rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #1E7DFF;
+			}
+		}
+	}
+</style>

+ 439 - 0
pages/index/report.vue

@@ -0,0 +1,439 @@
+<template>
+	<view class="baobei">
+		<!-- 		<u-navbar :title="config.store_title" title-color="#fff" :background="{background:'#1F7EFF'}" :border-bottom="false" :isBack="false">
+			<view class="u-flex nav-left" slot="left">
+				<u-icon name="map-fill" size="34" color="#fff"></u-icon>
+				<text class="text">{{defaultcity.city || '定位中'}}</text>
+			</view>
+		</u-navbar> -->
+		<view class="" style="padding: 0 24rpx;">
+			<view class="broker-title">
+				基本信息
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>意向项目</text>
+				</view>
+				<text class="input-right">{{loupanname}}</text>
+				<!-- <input type="text" placeholder="请输入您意向楼盘" class="input-right" :disabled="true" v-model="loupanname"> -->
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>客户姓名</text>
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="kehuname">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="kehutel">
+			</view>
+		</view>
+		<u-gap bg-color="#F5F5F5" height="20"></u-gap>
+		<view class="" style="padding: 0 24rpx;">
+			<view class="broker-title">
+				其他信息
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>带看人姓名</text>
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="name">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="tel">
+			</view>
+			<view class="broker-row u-flex" v-if="certification_type == 1">
+				<view class="broker-row-left u-flex">
+					<text>中介门店</text>
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="shop">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>预约看房日期</text>
+				</view>
+				<biaofunDatetimePicker ref="biaofunDatetimePicker" placeholder="请选择看房日期" class="input-right"
+					:start="$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd hh:MM')" @change="changetime">
+				</biaofunDatetimePicker>
+				<!-- <input type="text" placeholder="请选择看房日期" class="input-right" :disabled="true" v-model="time"> -->
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+		</view>
+		<view class="baobei-down u-flex-col u-col-center ">
+			<view class="xieyi u-flex u-row-center">
+				<u-checkbox v-model="xieyi" active-color="#1F7EFF" size="26"></u-checkbox>
+				<view class="text" @click="xieyi = !xieyi">
+					勾选并同意<text @click.stop="totext(3)">《报备活动规则》</text>
+				</view>
+			</view>
+			<view class="tijiao" @click="save">
+				确认
+			</view>
+		</view>
+		<u-popup v-model="show" :maskCloseAble="false" mode="center" border-radius="20">
+			<view @click="clear" class="" style="font-weight: 400;text-align: right;padding: 30rpx 30rpx 0 0;box-sizing: border-box;">
+				X
+			</view>
+			<view class="baobei-popup u-flex-col u-col-center">
+				<image src="../../static/images/baobei-img.png" class="image" mode=""></image>
+				<view class="baobei-tips u-flex-col u-col-center">
+					<text>您还未进行信息认证</text>
+					<text>请您前去认证</text>
+				</view>
+				<view class="baobei-btn u-flex u-row-between">
+					<text @click="toshenqing(2)">全民经纪人</text>
+					<text @click="toshenqing(1)">中介经纪人</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showover" :closeable="true" mode="center" border-radius="20">
+			<view class="over-popup u-flex-col u-col-center u-row-center">
+				<u-icon name="checkmark-circle-fill" color="#14CB30" size="168"></u-icon>
+				<view class="over-text u-flex-col u-col-center">
+					<text>已提交客户资料,开发商审核中</text>
+					<text>防截客锁定中,请耐心等待</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-select v-model="quyushow" :list="quyulist" label-name="name" value-name="id" @confirm="changequyu">
+		</u-select>
+		<u-select v-model="loupanshow" :list="loupanlist" label-name="name" value-name="id" @confirm="changeloupan">
+		</u-select>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from "vuex"
+	import biaofunDatetimePicker from "../../components/biaofun-datetime-picker/biaofun-datetime-picker.vue"
+	export default {
+		data() {
+			return {
+				show: false,
+				xieyi: false,
+				showover: false,
+
+				quyulist: [],
+				quyushow: false,
+				quyuname: '',
+				quyuid: '',
+
+				loupanlist: [],
+				loupanshow: false,
+				loupanname: '',
+				loupanid: '',
+
+				kehuname: '',
+				kehutel: '',
+				name: '',
+				tel: '',
+				shop: '',
+				time: '',
+				certification_type: '',
+				quyuIpt: true,
+			}
+		},
+		onLoad(option) {
+			this.loupanid = option.id
+			this.loupanname = uni.getStorageSync("detailName")
+			this.getquyu()
+		},
+		onShow() {
+			uni.setNavigationBarTitle({
+				title: this.config.store_title
+			})
+			if (this.$islogin()) {
+				this.show = true
+			} else {
+				this.getuser()
+			}
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		components: {
+			biaofunDatetimePicker
+		},
+		methods: {
+			totext(type) {
+				uni.navigateTo({
+					url: "/pages/mine/xieyi?type=" + type
+				})
+			},
+			clear() {
+				uni.switchTab({
+					url: "/pages/index/index"
+				})
+			},
+			save() {
+				if (!this.kehuname) {
+					this.$u.toast('请输入客户姓名')
+					return
+				}
+				if (!this.$u.test.mobile(this.kehutel)) {
+					this.$u.toast('请输入正确的客户联系方式')
+					return
+				}
+				if (!this.name) {
+					this.$u.toast('请输入带看人姓名')
+					return
+				}
+				if (!this.$u.test.mobile(this.tel)) {
+					this.$u.toast('请输入正确的带看人联系方式')
+					return
+				}
+				if (!this.shop && this.certification_type == 1) {
+					this.$u.toast('请输入中介门店')
+					return
+				}
+				if (!this.time) {
+					this.$u.toast('请选择看房日期')
+					return
+				}
+				if (this.time < this.$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd hh:MM:ss')) {
+					this.$u.toast('看房日期不得小于当前时间')
+					return
+				}
+				if (!this.xieyi) {
+					this.$u.toast("请勾选协议")
+					return
+				}
+				this.$u.post('/api/Report/submit_report', {
+					// area_id: this.quyuid,
+					property_id: this.loupanid,
+					client_name: this.kehuname,
+					client_phone: this.kehutel,
+					report_name: this.name,
+					report_phone: this.tel,
+					shop: this.shop,
+					time: this.time
+				}).then(res => {
+					if (res.code == 1) {
+						// this.showover = true
+						this.quyuid = ''
+						this.quyuname = ''
+						this.loupanid = ''
+						this.loupanname = ''
+						this.kehuname = ''
+						this.kehutel = ''
+						this.name = ''
+						this.tel = ''
+						this.shop = ''
+						this.time = ''
+						this.xieyi = false
+						this.$refs.biaofunDatetimePicker.clearTime()
+						this.$u.toast("已提交客户资料,开发商审核中")
+						setTimeout(() => {
+							uni.switchTab({
+								url: "/pages/index/index"
+							})
+						}, 2000)
+					} else {
+						this.$u.toast(res.msg)
+					}
+				})
+			},
+			changetime(e) {
+				this.time = `${e.f1} ${e.f8}:00`
+			},
+			changeloupan(e) {
+				this.loupanid = e[0].value
+				this.loupanname = e[0].label
+			},
+			changequyu(e) {
+				this.quyuid = e[0].value
+				this.quyuname = e[0].label
+				this.$u.post('/api/Report/area_property_list', {
+					area_id: this.quyuid
+				}).then(res => {
+					this.loupanlist = res.data
+				})
+			},
+			getquyu() {
+				this.$u.post('/api/Data/area_list', {
+					level: 3,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					this.quyulist = res.data
+				})
+			},
+			toshenqing(type) {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "/pages/index/broker?type=" + type
+				})
+			},
+			getuser() {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.certification_type = res.data.certification_type
+					if (res.data.certification_type == 0) {
+						this.show = true
+					} else {
+						this.show = false
+					}
+				})
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.baobei {
+		.over-popup {
+			width: 650rpx;
+			height: 564rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+
+			.over-text {
+				margin-top: 32rpx;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+			}
+		}
+
+		.baobei-down {
+			position: fixed;
+			bottom: 120rpx;
+			left: 0;
+			width: 750rpx;
+
+			.tijiao {
+				margin: 30rpx auto;
+				width: 702rpx;
+				line-height: 82rpx;
+				background: #1F7EFF;
+				border-radius: 8rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			.xieyi {
+				.text {
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+
+					text {
+						color: #1F7EFF;
+					}
+				}
+			}
+		}
+
+		.broker-row {
+			height: 82rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.input-right {
+				flex: 1;
+				font-size: 24rpx;
+			}
+
+			.broker-row-left {
+				width: 252rpx;
+
+				text:first-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				text:nth-child(2) {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #F83838;
+				}
+			}
+		}
+
+		.broker-title {
+			padding: 24rpx 0;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+		}
+
+		.baobei-popup {
+			width: 650rpx;
+			height: 806rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			padding-top: 126rpx;
+
+			.baobei-btn {
+				width: 100%;
+				padding: 0 44rpx;
+
+				text:first-child {
+					width: 262rpx;
+					line-height: 100rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 262rpx;
+					line-height: 100rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.baobei-tips {
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #C5C5C5;
+				margin-bottom: 98rpx;
+			}
+
+			.image {
+				width: 214rpx;
+				height: 242rpx;
+				margin-bottom: 72rpx;
+			}
+		}
+
+		.nav-left {
+			padding: 0 20rpx;
+
+			.text {
+				font-size: 32rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #FFFFFF;
+				margin-left: 5rpx;
+			}
+		}
+	}
+</style>

+ 213 - 0
pages/index/search.vue

@@ -0,0 +1,213 @@
+<template>
+	<view class="search1">
+		<view class="search-box u-flex u-row-between">
+			<u-icon name="search" color="#CCCCCC" size="36"></u-icon>
+			<input type="text" placeholder="搜索楼盘" class="input" v-model="keyword1">
+			<text class="text" @click="tosearch">搜索</text>
+		</view>
+		<view class="lishi-box" v-if="list.length == 0">
+			<view class="lishi-title">
+				历史搜索
+			</view>
+			<view class="u-flex u-flex-wrap">
+				<text v-for="(item,index) in lishilist" :key="index" class="lishi-item" @click="lishisearch(item)">{{item}}</text>
+			</view>
+			<!-- <view class="news-item u-flex u-row-between" v-for="(item,index) in 2" :key="index" @click="toinfo">
+				<image src="https://dummyimage.com/140x110" class="image" mode=""></image>
+				<view class="item-right">
+					<view class="name u-line-2">
+						已取证!差价1.5W+/㎡!戏水池、会所、嵌入式冰箱,冠军推荐!
+					</view>
+					<view class="u-flex u-row-between">
+						<view class="time u-flex">
+							<u-icon name="eye-fill" color="#CCCCCC" size="26"></u-icon>
+							<text class="look">12345人浏览</text>
+							<text class="time-text">2023-03-25</text>
+						</view>
+						<view class="user u-flex">
+							<image src="https://dummyimage.com/24x24" class="head" mode=""></image>
+							<text class="user-name">温州购房通</text>
+						</view>
+					</view>
+				</view>
+			</view> -->
+		</view>
+		<view class="list-box" style="padding: 0 24rpx;">
+			<view class="list-item" v-for="(item,index) in list" :key="index">
+				<gf-goods :data="item" type="1"></gf-goods>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		data() {
+			return {
+				lishilist: [],
+				keyword1: '',
+				keyword: '',
+				page: 1,
+				list: []
+			}
+		},
+		onLoad() {
+			this.lishilist = uni.getStorageSync("lishi") || []
+		},
+		onShow() {
+			uni.setNavigationBarTitle({
+				title: this.config.store_title
+			})
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			lishisearch(item) {
+				this.keyword = item
+				this.keyword1 = item
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			tosearch() {
+				this.keyword = this.$u.trim(this.keyword1)
+				this.setlishi()
+				this.getlist()
+			},
+			setlishi() {
+				if (this.keyword) {
+					if (this.lishilist.indexOf(this.keyword) == -1) {
+						this.lishilist.unshift(this.keyword)
+						uni.setStorageSync("lishi", this.lishilist)
+					}
+				}
+			},
+			getlist() {
+				this.$u.post('/api/Index/property_list', {
+					page: this.page,
+					page_num: 20,
+					keyword: this.keyword,
+					city_id: this.defaultcity.city_id
+				}).then(res => {
+					if (this.page == 1) {
+						this.list = res.data
+					} else {
+						this.list = this.list.concat(res.data)
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.search1 {
+		.lishi-box {
+			padding: 0 24rpx;
+
+			.news-item {
+				padding: 32rpx 0;
+				border-bottom: 2rpx solid #CCCCCC;
+
+				.image {
+					width: 140rpx;
+					height: 110rpx;
+					border-radius: 10rpx;
+				}
+
+				.item-right {
+					flex: 1;
+					margin-left: 14rpx;
+
+					.name {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+						margin-bottom: 16rpx;
+					}
+
+					.user {
+						.user-name {
+							font-size: 18rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #999999;
+						}
+
+						.head {
+							width: 24rpx;
+							height: 24rpx;
+							border-radius: 100rpx;
+							margin-right: 10rpx;
+						}
+					}
+
+					.time {
+						font-size: 18rpx;
+						font-weight: 400;
+						color: #999999;
+
+						.look {
+							margin: 0 10rpx;
+						}
+					}
+				}
+			}
+
+			.lishi-item {
+				line-height: 44rpx;
+				background: #E5E5E5;
+				border-radius: 22rpx;
+				padding: 0 30rpx;
+				font-size: 18rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				margin-bottom: 20rpx;
+				margin-right: 20rpx;
+			}
+
+			.lishi-title {
+				font-size: 24rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #333333;
+				margin-bottom: 14rpx;
+			}
+		}
+
+		.search-box {
+			width: 702rpx;
+			height: 72rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 24rpx auto;
+			padding-left: 24rpx;
+			border: 2rpx solid #CCCCCC;
+
+			.input {
+				flex: 1;
+				margin: 0 10rpx;
+			}
+
+			.text {
+				padding: 0 24rpx;
+				border-left: 1rpx solid #E5E7ED;
+				line-height: 36rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #1E7DFF;
+			}
+		}
+	}
+</style>

+ 117 - 0
pages/index/video.vue

@@ -0,0 +1,117 @@
+<template>
+	<view class="video1 u-flex u-row-between u-flex-wrap">
+		<view class="video-item" v-for="(item,index) in list" :key="index" @click="playmp4(item)">
+			<view class="image-box">
+				<image :src="item.logo" class="image" mode="aspectFill"></image>
+				<image src="../../static/images/video.png" class="play" mode=""></image>
+				<!-- <text class="text">03.25</text> -->
+			</view>
+			<view class="video-name u-line-1">
+				{{item.title}}
+			</view>
+			<view class="time">
+				{{item.create_at}}
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		data() {
+			return {
+				id: '',
+				page: 1,
+				list: []
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getdata()
+			}
+		},
+		methods: {
+			playmp4(item) {
+				uni.navigateTo({
+					url: "/pages/video/info?mp4=" + encodeURIComponent(item.video)
+				})
+			},
+			getdata() {
+				this.$u.post('/api/Property/video_list', {
+					id: this.id,
+					page: this.page,
+					page_num: 20,
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.video1 {
+		padding: 24rpx;
+
+		.video-item {
+			width: 340rpx;
+			margin-bottom: 18rpx;
+
+			.video-name {
+				font-size: 20rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+				margin: 14rpx 0;
+			}
+
+			.time {
+				font-size: 20rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+			}
+
+			.image-box {
+				width: 340rpx;
+				height: 272rpx;
+				position: relative;
+
+				.play {
+					width: 64rpx;
+					height: 64rpx;
+					position: absolute;
+					top: 50%;
+					left: 50%;
+					transform: translate(-50%, -50%);
+				}
+
+				.image {
+					width: 340rpx;
+					height: 272rpx;
+					border-radius: 10rpx;
+				}
+
+				.text {
+					position: absolute;
+					z-index: 10;
+					right: 10rpx;
+					bottom: 10rpx;
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+		}
+	}
+</style>

+ 298 - 0
pages/mine/baobei-info.vue

@@ -0,0 +1,298 @@
+<template>
+	<view class="baobei-info">
+		<view class="info-header u-flex-col u-col-center u-row-center">
+			<view class="image-box u-flex u-row-between">
+				<view class="image u-flex u-row-center" v-for="(item,index) in tabs" :key="index">
+					<image src="../../static/images/jindu1.png" v-if="index < status" mode=""></image>
+					<image src="../../static/images/jindu.png" v-else mode=""></image>
+				</view>
+			</view>
+			<view class="jindu-box u-flex u-row-between">
+				<view class="item-bg" :style="{width:130 * status + 'rpx'}"></view>
+				<view class="item" v-for="(item,index) in tabs" :key="index">
+					<text :class="index < status ? 'text' : ''">{{item}}</text>
+				</view>
+			</view>
+		</view>
+		<u-gap bg-color="#F5F5F5" height="20"></u-gap>
+		<view class="" style="padding: 0 24rpx;width: 702rpx;margin: 0 auto;border-radius: 20rpx;background-color: #fff;">
+			<view class="broker-title">
+				基本信息
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>意向区域</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请选择您的意向区域" v-model="detail.area_name" class="input-right" :disabled="true">
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>意向项目</text>
+				</view>
+				<input type="text" placeholder="请选择您的意向楼盘" v-model="detail.property_name" class="input-right" :disabled="true">
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>客户姓名</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="detail.client_name" :disabled="true">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="detail.client_phone" :disabled="true">
+			</view>
+		</view>
+		<u-gap bg-color="#F5F5F5" height="20"></u-gap>
+		<view class="" style="padding: 0 24rpx;width: 702rpx;margin: 0 auto;border-radius: 20rpx;background-color: #fff;">
+			<view class="broker-title">
+				其他信息
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>带看人姓名</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="detail.report_name" :disabled="true">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>联系方式</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="number" placeholder="请输入" class="input-right" v-model="detail.report_phone" :disabled="true">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>中介门店</text>
+					<!-- <text>*</text> -->
+				</view>
+				<input type="text" placeholder="请输入" class="input-right" v-model="detail.shop" :disabled="true">
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>预约看房日期</text>
+				</view>
+				<input type="text" placeholder="请选择看房日期" class="input-right" v-model="detail.time" :disabled="true">
+				<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+			</view>
+			<view class="broker-row u-flex">
+				<view class="broker-row-left u-flex">
+					<text>审核状态</text>
+				</view>
+				<view class="input-right">
+					<text style="color: rgba(240, 127, 48, 1);" v-if="detail.status == 1">审核中</text>
+					<text style="color: rgba(68, 220, 37, 1);" v-if="detail.status == 2">已通过</text>
+					<text style="color: rgba(220, 75, 37, 1);" v-if="detail.status == 3">审核失败</text>
+					<text style="color: rgba(204, 204, 204, 1)" v-if="detail.status == 4">已失效</text>
+				</view>
+			</view>
+		</view>
+		<u-gap bg-color="#F5F5F5" height="20"></u-gap>
+		<view class="" style="padding: 0 24rpx;width: 702rpx;margin: 0 auto;border-radius: 20rpx;background-color: #fff;">
+			<view class="broker-title">
+				报备流程
+			</view>
+			<view class="u-flex" style="padding-bottom: 40rpx;">
+				<text style="width: 22rpx;height: 22rpx;background: #F07F30;border-radius: 100rpx;margin-right: 24rpx;"></text>
+				<view class="u-flex-col u-col-top" style="width: 348rpx;background: #F2F2F2;border-radius: 10rpx;padding: 24rpx;">
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(240, 127, 48, 1);" v-if="detail.status == 1">审核中</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(68, 220, 37, 1);" v-if="detail.status == 2 && detail.flow_status == 1">报备</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(68, 220, 37, 1);" v-if="detail.status == 2 && detail.flow_status == 2">到访</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(68, 220, 37, 1);" v-if="detail.status == 2 && detail.flow_status == 3">认购</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(68, 220, 37, 1);" v-if="detail.status == 2 && detail.flow_status == 4">签约</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(68, 220, 37, 1);" v-if="detail.status == 2 && detail.flow_status == 5">结佣</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(220, 75, 37, 1);" v-if="detail.status == 3">审核失败</text>
+					<text style="margin-bottom: 6rpx;font-size: 24rpx;color: rgba(204, 204, 204, 1)" v-if="detail.status == 4">已失效</text>
+					<text style="font-size: 20rpx;color: #999999;">{{detail.explain}}</text>
+				</view>
+			</view>
+		</view>
+		<view style="height: 200rpx;"></view>
+		<view class="baobei-info-btn" @click="show = true" v-if="detail.status == 2">
+			二维码展示
+		</view>
+		<u-popup v-model="show" mode="center" background="rgba(0,0,0,0)">
+			<view class="code-popup u-flex-col u-col-center">
+				<image src="../../static/images/code.png" class="code" mode=""></image>
+				<u-icon name="close-circle-fill" size="72" color="#fff" @click="show = false"></u-icon>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	import { mapState } from 'vuex'
+	export default {
+		data() {
+			return {
+				show: false,
+				id: '',
+				detail: {},
+				tabs: ['报备', '到访', '认购', '签约', '结佣'],
+				status: 0
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+		},
+		onShow() {
+			uni.setNavigationBarTitle({
+				title: this.config.store_title
+			})
+		},
+		computed:{
+			...mapState(['config'])
+		},
+		methods: {
+			getdata() {
+				this.$u.post('/api/Report/report_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+					if(this.detail.status == 2){
+						this.status = res.data.flow_status
+					}
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	page{
+		background-color: rgba(245, 245, 245, 1);
+	}
+	.code-popup {
+		.code {
+			width: 564rpx;
+			height: 564rpx;
+			border-radius: 20rpx;
+			margin-bottom: 60rpx;
+		}
+	}
+
+	.baobei-info {
+		.info-header {
+			width: 702rpx;
+			height: 180rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+		
+			.jindu-box {
+				border-radius: 20rpx;
+				overflow: hidden;
+				position: relative;
+				z-index: 1;
+				background-color: rgba(229, 229, 229, 1);
+		
+				.item-bg {
+					background-color: rgba(31, 126, 255, 1);
+					border-radius: 20rpx;
+					height: 54rpx;
+					position: absolute;
+					top: 0;
+					left: 0;
+					z-index: -1;
+				}
+		
+				.item {
+					width: 130rpx;
+		
+					// position: relative;
+					// z-index: 1;
+					// border-radius: 20rpx;
+					// overflow: hidden;
+					text {
+						display: inline-block;
+						width: 130rpx;
+						line-height: 54rpx;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						text-align: center;
+					}
+		
+					.text {
+						color: #fff;
+					}
+				}
+			}
+		
+			.image-box {
+				margin-bottom: 6rpx;
+		
+				.image {
+					width: 130rpx;
+		
+					image {
+						width: 67rpx;
+						height: 64rpx;
+					}
+				}
+			}
+		}
+		.baobei-info-btn {
+			width: 702rpx;
+			line-height: 82rpx;
+			background: #1F7EFF;
+			border-radius: 8rpx;
+			position: fixed;
+			bottom: 50rpx;
+			left: 24rpx;
+			text-align: center;
+			font-size: 28rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #FFFFFF;
+			z-index: 100;
+		}
+
+		.broker-row {
+			height: 82rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.input-right {
+				flex: 1;
+				font-size: 24rpx;
+			}
+
+			.broker-row-left {
+				width: 252rpx;
+
+				text:first-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				text:nth-child(2) {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #F83838;
+				}
+			}
+		}
+
+		.broker-title {
+			padding: 24rpx 0;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+		}
+	}
+
+</style>

+ 88 - 0
pages/mine/baobei-list.vue

@@ -0,0 +1,88 @@
+<template>
+	<view  class="baobei-list">
+		<view  class="baobei-item u-flex u-row-between" v-for="(item,index) in list" :key="index" @click="toinfo(item)">
+			<view  class="left u-flex-col u-flex-1">
+				<text>意向项目:{{item.property_name}}</text>
+				<text>意向区域:{{item.area_name}}</text>
+				<text>预约看房时间:{{item.time}}</text>
+				<text>报备时间:{{item.create_at}}</text>
+			</view>
+			<view class="right" style="background-color: rgba(240, 127, 48, 1);" v-if="item.status == 1">审核中</view>
+			<view class="right" style="background-color: rgba(68, 220, 37, 1);" v-if="item.status == 2">已通过</view>
+			<view class="right" style="background-color: rgba(220, 75, 37, 1);" v-if="item.status == 3">审核失败</view>
+			<view class="right" style="background-color: rgba(204, 204, 204, 1);" v-if="item.status == 4">已失效</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				list: [],
+				page: 1
+			}
+		},
+		onLoad() {
+			this.getdata()
+		},
+		methods: {
+			getdata() {
+				this.$u.post('/api/Report/report_list', {
+					page: this.page,
+					page_num: 20
+				}).then(res => {
+					if(res.code!=0){
+						this.list = this.list.concat(res.data)
+						console.log(this.list);
+					}
+				})
+			},
+			toinfo(item) {
+				uni.navigateTo({
+					url: "./baobei-info?id=" + item.id
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	page {
+		background-color: rgba(245, 245, 245, 1);
+	}
+
+	.baobei-list {
+
+		.baobei-item {
+			padding: 20rpx 20rpx 10rpx 20rpx;
+			background-color: #fff;
+			width: 702rpx;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+
+			.right {
+				width: 160rpx;
+				line-height: 60rpx;
+				border-radius: 10rpx;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			.left {
+				text {
+					margin-bottom: 10rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+			}
+		}
+	}
+
+</style>

+ 109 - 0
pages/mine/jifen.vue

@@ -0,0 +1,109 @@
+<template>
+	<view class="yongjin">
+		<view class="yongjin-item u-flex" v-for="(item,index) in list" :key="index">
+			<view class="left">
+				¥
+			</view>
+			<view class="right u-flex-1">
+				<view class="u-flex u-row-between right1">
+					<text>{{item.explain}}</text>
+					<text>{{item.type == 1 ? '+' : '-'}}{{item.change_amount}}</text>
+				</view>
+				<view class="u-flex u-row-between right2">
+					<text>{{item.create_at}}</text>
+					<text>我的积分 {{item.amount}}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				page: 1,
+				list: []
+			}
+		},
+		onLoad() {
+			this.getlist()
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			getlist() {
+				this.$u.get('/api/Member/integral_list', {
+					page: this.page,
+					page_num: 20
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.yongjin {
+		.yongjin-item {
+			height: 164rpx;
+			border-bottom: 2rpx solid rgba(245, 245, 245, 1);
+			padding: 0 24rpx;
+
+			.right {
+				.right2 {
+					text:first-child {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					text:last-child {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+				}
+
+				.right1 {
+					margin-bottom: 4rpx;
+
+					text:first-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+
+					text:last-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+				}
+			}
+
+			.left {
+				text-align: center;
+				width: 100rpx;
+				line-height: 100rpx;
+				border-radius: 100rpx;
+				font-size: 60rpx;
+				color: #fff;
+				font-weight: bold;
+				background-color: rgba(247, 164, 107, 1);
+				margin-right: 32rpx;
+			}
+		}
+	}
+
+</style>

+ 181 - 0
pages/mine/login.vue

@@ -0,0 +1,181 @@
+<template>
+
+	<view class="login u-flex-col u-col-center">
+		<image src="../../static/logo..png" class="logo" mode=""></image>
+		<text class="text">房屋底价超市</text>
+		<!-- #ifdef  MP-WEIXIN-->
+		<button open-type="getPhoneNumber" class="login-btn" @getphonenumber="tologin">
+			微信授权登录
+		</button>
+		<!-- #endif -->
+		<!-- #ifdef  MP-TOUTIAO -->
+		<button open-type="getPhoneNumber" class="login-btn" @getphonenumber="tologin1">
+			抖音授权登录
+		</button>
+		<!-- #endif -->
+	</view>
+
+</template>
+
+
+
+<script>
+	import {
+		mapState
+	} from "vuex"
+	export default {
+		data() {
+			return {
+				phone: '',
+				pwd: ''
+			}
+		},
+		onLoad() {
+
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		methods: {
+			setcity() {
+				this.$u.post('/api/Index/location', {
+					longitude: this.defaultcity.userLocation.split(',')[0],
+					latitude: this.defaultcity.userLocation.split(',')[1],
+					city_name: this.defaultcity.city
+				})
+			},
+			tologin(e) {
+				if (e.detail.code) {
+					var phoneCode = e.detail.code
+					uni.login({
+						success: (code) => {
+							this.$u.post('/api/Login/login', {
+								code: code.code,
+								program_num:2
+							}).then(res => {
+								if (res.code == 1) {
+									uni.setStorageSync("token", res.data.token)
+									if (!res.data.phone || 1) {
+										this.$u.post('/api/Member/bind_Phone', {
+											code: phoneCode,
+											program_num:2
+										}).then(res => {
+											if (res.code == 1) {
+												this.$u.toast("登录成功")
+												this.$u.post('/api/Member/member_info').then(
+													res => {
+														uni.setStorageSync("hx_username",
+															res.data.hx_username)
+														this.$WebIM.conn.open({
+															user: res.data.hx_username,
+															pwd: "999999",
+														}).then(() => {
+															console.log(
+																"login success"
+															);
+														}).catch((reason) => {
+															console.log(
+																"login fail",
+																reason);
+														});
+													})
+												this.setcity()
+												setTimeout(() => {
+													uni.navigateBack()
+												}, 800)
+											} else {
+												this.$u.toast(res.msg)
+												uni.removeStorageSync('token')
+											}
+										})
+									} else {
+										this.$u.toast("登录成功")
+										this.setcity()
+										setTimeout(() => {
+											uni.navigateBack()
+										}, 800)
+									}
+								} else {
+									this.$u.toast(res.msg)
+								}
+							})
+						}
+					})
+				}
+			},
+			tologin1() {
+				tt.login({
+					success: (code) => {
+						this.$u.post('/api/Login/tou_login', {
+							code: code.code
+						}).then(res => {
+							if (res.code == 1) {
+								uni.setStorageSync("token", res.data.token)
+								this.$u.toast("登录成功")
+								this.$u.post('/api/Member/member_info').then(
+									res => {
+										uni.setStorageSync("hx_username", res.data.hx_username)
+										this.$WebIM.conn.open({
+											user: res.data.hx_username,
+											pwd: "999999",
+										}).then(() => {
+											console.log(
+												"login success");
+										}).catch((reason) => {
+											console.log("login fail",
+												reason);
+										});
+									})
+								this.setcity()
+								setTimeout(() => {
+									uni.navigateBack()
+								}, 800)
+								// }
+							} else {
+								this.$u.toast(res.msg)
+							}
+						})
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.login {
+		.login-btn {
+			width: 470rpx;
+			line-height: 88rpx;
+			background: #1F7EFF;
+			border-radius: 20rpx;
+			text-align: center;
+			font-size: 28rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #FFFFFF;
+			margin: 0 0 20rpx 0;
+			padding: 0;
+		}
+
+		.logo {
+			width: 200rpx;
+			height: 200rpx;
+			border-radius: 100rpx;
+			margin-top: 280rpx;
+			margin-bottom: 54rpx;
+		}
+
+		.text {
+			color: #1F7EFF;
+			font-size: 60rpx;
+			letter-spacing: 10rpx;
+			font-weight: 500;
+			margin-bottom: 184rpx;
+		}
+
+		.login-btn::after {
+			border: none;
+		}
+	}
+</style>

+ 583 - 0
pages/mine/mine.vue

@@ -0,0 +1,583 @@
+<template>
+	<view class="mine">
+		<view class="index-bg"></view>
+		<view class="mine-tips" v-if="userinfo.certification_type != 0">
+			<u-notice-bar mode="horizontal" bg-color="rgba(0,0,0,0)"
+				:list="[`${userinfo.certification_type == 1 ? config.intermediary_explain : config.people_explain}`]"
+				padding="0" :volume-icon="false" color="#fff" font-size="22"></u-notice-bar>
+		</view>
+		<view class="user-box u-flex">
+			<image v-if="userinfo.headimg" :src="userinfo.headimg" class="user-head" mode=""></image>
+			<image v-else src="../../static/images/head.png" class="user-head" mode=""></image>
+			<view class="user-center u-flex-1 u-flex-col u-col-top">
+				<text class="text1" v-if="userinfo.name">{{userinfo.name}}</text>
+				<button class="text1" @getphonenumber="login" v-else @click="tologin">点击进行登录</button>
+				<text class="text2" v-if="userinfo.certification_type == 0">未认证</text>
+				<text class="text2" v-if="userinfo.certification_type == 1">中介经纪人</text>
+				<text class="text2" v-if="userinfo.certification_type == 2">全民经纪人</text>
+			</view>
+			<u-icon name="edit-pen-fill" color="#fff" @click="toinfo" size="36"></u-icon>
+		</view>
+
+		<!-- 		<view class="yongjin-box">
+			<view class="price u-flex u-row-center">
+				<image src="../../static/images/qianbao.png" class="img" mode=""></image>
+				<view class="text u-flex-col">
+					<text>{{userinfo.balance || '0.00'}}</text>
+					<text>积分总额(元)</text>
+				</view>
+			</view>
+			<view class="mingxi u-flex u-row-between">
+				<text class="u-flex-1" style="border-right: 2rpx solid #F5F5F5;" @click="toyongjin">积分明细</text>
+				<text class="u-flex-1" @click="toxieyi">积分说明</text>
+			</view>
+		</view> -->
+
+		<view class="yongjin-box">
+			<view class="price">
+				<view class="" style="display:flex;justify-content: space-between;">
+					<view class="" style="display:flex;">
+						<image style="width: 36rpx;height:36rpx;" src="../../static/images/jifen.png" mode=""></image>
+						<view class="">
+							<text class="yongjin-box">我的积分</text>
+						</view>
+						<image style="width: 36rpx;height:36rpx;" src="../../static/images/explain.png" mode=""></image>
+					</view>
+					<view class="">
+						<text class="jffont" @click="tojifen">积分明细</text>
+						<image style="width: 24rpx;height: 24rpx;margin-right: 10rpx;"
+							src="../../static/images/nextto.png" mode=""></image>
+					</view>
+				</view>
+				<view class="" style="margin-top: 40rpx;display: flex;justify-content: space-around;">
+					<view class="">
+						<text style="font-size: 48rpx;font-weight: 800;">{{userinfo.integral || '0.00'}}</text>
+						<view class="font">
+							<text>积分总额</text>
+						</view>
+					</view>
+					<view class="" style="margin-left: 200rpx;">
+						<text style="font-size: 48rpx;font-weight: 800;">{{userinfo.now_month_integral|| '0.00'}}</text>
+						<view class="font">
+							<text>本月积分</text>
+						</view>
+					</view>
+
+				</view>
+				
+				<view v-if="userinfo.is_integral_hint==1" class="forward"
+					style="margin-top: 20rpx;border-top: 2rpx solid #F6F6F6;padding: 24rpx 20rpx 0;">
+					<view class="u-flex">
+						<image style="width: 32rpx;height: 32rpx;margin-right: 12rpx;"
+							src="../../static/images/index-img2.png" mode=""></image>
+						<!-- <view class="" style="width: 500rpx;height: 34rpx;margin-top: -50rpx;"> -->
+						<uni-notice-bar background-color="#fff" font-size="12" color="#000" style="width: 500rpx;"
+							scrollable single text="您当月积分0,若本月无积分入账,历史积分将全部清零"></uni-notice-bar>
+						<!-- </view> -->
+						<button class="btn" open-type="share">
+							转发赚积分
+						</button>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- 佣金总额 -->
+		<view class="yongjin-box" style="margin-top: 20rpx;">
+			<view class="price">
+				<view class="" style="display:flex;justify-content: space-between;">
+					<view class="" style="display:flex;">
+						<image style="width: 36rpx;height:36rpx;" src="../../static/images/qianbao.png" mode=""></image>
+						<view class="">
+							<text class="yongjin-box">佣金总额(元)</text>
+						</view>
+						<image @click='toxieyi' style="width: 36rpx;height:36rpx;" src="../../static/images/explain.png"
+							mode=""></image>
+					</view>
+					<view class="">
+						<text class="jffont" @click='toyongjin'>佣金明细</text>
+						<image style="width: 24rpx;height: 24rpx;margin-right: 10rpx;"
+							src="../../static/images/nextto.png" mode=""></image>
+					</view>
+				</view>
+				<view class="" style="margin-top: 40rpx;margin-left: 50rpx;">
+					<view class="">
+						<text style="font-size: 30rpx;font-weight: 800;">¥</text>
+						<text style="font-size: 48rpx;font-weight: 800;">{{userinfo.balance || '0.00'}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 		<view class="yongjin-box " style="display: flex;">
+			<view class="" style="width: 350rpx; border-right: 2px solid #F5F5F5;">
+				<view class="" style="display:flex;">
+					<image style="width: 36rpx;height:36rpx;"  src="../../static/images/jifen.png"  mode=""></image>
+					<view class="">
+						<text class="yongjin-box font">积分总额(元)</text>
+					</view>
+					<image   style="width: 36rpx;height:36rpx;" src="../../static/images/explain.png" mode=""></image>
+				</view>
+				<view class="" style="margin-top: 40rpx;display: flex;justify-content: space-between;">
+					<view class="">
+						<text style="font-size: 48rpx;font-weight: 800;">{{userinfo.balance || '0.00'}}</text>
+					</view>
+					<view class="" style="margin-top: 20rpx;">
+						<text class="jffont" >积分明细</text>
+						<image style="width: 24rpx;height: 24rpx;margin-right: 10rpx;" src="../../static/images/nextto.png" mode=""></image>
+					</view>
+				</view>
+			</view>
+			<view class="" style="width: 350rpx;margin-left: 30rpx;">
+				<view class="" style="display:flex;">
+					<image style="width: 36rpx;height:36rpx;"  src="../../static/images/qianbao.png"  mode=""></image>
+					<view class="">
+						<text class="yongjin-box font">佣金总额(元)</text>
+					</view>
+					<image @click="toxieyi" style="width: 36rpx;height:36rpx;" src="../../static/images/explain.png" mode=""></image>
+				</view>
+				<view class="" style="margin-top: 40rpx;display: flex;justify-content: space-between;">
+					<view class="">
+						<text style="font-size: 48rpx;font-weight: 800;">{{userinfo.balance || '0.00'}}</text>
+					</view>
+					<view class="" style="margin-top: 20rpx;">
+						<text class="jffont" @click="toyongjin" >佣金明细</text>
+						<image style="width: 24rpx;height: 24rpx;margin-right: 10rpx;" src="../../static/images/nextto.png" mode=""></image>
+					</view>
+				</view>
+			</view>
+		</view> -->
+		<view class="tabs-box u-flex">
+			<view class="tabs-item u-flex-col u-col-center" @click="tourl(1)"
+				v-if="(userinfo.certification_type == 1 || userinfo.certification_type == 0) ">
+				<image src="../../static/images/mine-tabs1.png" mode=""></image>
+				<text>中介经纪人</text>
+			</view>
+			<view class="tabs-item u-flex-col u-col-center" @click="tourl(2)"
+				v-if="(userinfo.certification_type == 2 || userinfo.certification_type == 0) ">
+				<image src="../../static/images/mine-tabs2.png" mode=""></image>
+				<text>全民经纪人</text>
+			</view>
+			<view class="tabs-item u-flex-col u-col-center" @click="tobaobei" v-if="config.report_switch == 1">
+				<image src="../../static/images/mine-tabs3.png" mode=""></image>
+				<text>我的报备</text>
+			</view>
+			<!-- 			<navigator target="miniProgram" app-id="wx43a84d2ad51cf509" class="tabs-item u-flex-col u-col-center">
+				<image src="../../static/images/yewu.png" mode=""></image>
+				<text>业务端</text>
+			</navigator> -->
+
+			<view @click="openmin" class="tabs-item u-flex-col u-col-center">
+				<image src="../../static/images/yewu.png" mode=""></image>
+				<text>业务端</text>
+			</view>
+		</view>
+		<view class="setting-box u-flex u-row-between" @click="tosetting">
+			<text>系统设置</text>
+			<u-icon name="arrow-right"></u-icon>
+		</view>
+		<gf-tabbar></gf-tabbar>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from "vuex"
+	export default {
+		//分享
+		onShareAppMessage(res) {
+			this.$u.get('/api/Member/transmit').then(res => {
+				this.getuser()
+			})
+			return {
+				title: '晨照选房',//分享时标题名字
+				path: 'pages/index/index', // 全局分享的路径,比如 首页
+				imageUrl: '../../static/logo.jpg', 
+			}
+		},
+		//分享朋友圈
+		onShareTimeline(res) {
+			this.$u.get('/api/Member/transmit').then(res => {
+				this.getuser()
+			})
+			return {
+				title: '晨照选房',//分享时标题名字
+				path: 'pages/index/index', // 全局分享的路径,比如 首页
+				imageUrl: '../../static/logo.jpg', 
+			}
+		},
+
+		data() {
+			return {
+				userinfo: {
+					certification_type: 0
+				}
+			}
+		},
+		onLoad() {
+			
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		onShow() {
+			console.log(this.config);
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			} else {
+				this.userinfo = {
+					certification_type: 0,
+				}
+			}
+		},
+		methods: {
+			openmin() {
+				//#ifdef  MP-WEIXIN
+				uni.navigateToMiniProgram({
+					appId: 'wx43a84d2ad51cf509', //跳转的小程序的aooId
+					path: '', //如果这里不填,默认是跳转到对方小程序的主页面
+					extraData: { //需要传给对方小程序的数据
+						'data1': 'test'
+					},
+					success(res) {
+						console.log(111);
+					}
+				})
+				// #endif
+
+
+				//#ifdef  MP-TOUTIAO 
+				tt.navigateToMiniProgram({
+					appId: "wx43a84d2ad51cf509",
+					success: function() {
+						
+					},
+					fail: function(e) {
+						console.log(e);
+					},
+				});
+
+				//#endif
+			},
+			tologin() {
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			toxieyi() {
+				uni.navigateTo({
+					url: "./xieyi?type=4"
+				})
+			},
+			tourl(type) {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "/pages/index/broker?type=" + type
+				})
+			},
+			login(e) {
+				if (e.detail.code) {
+					var phoneCode = e.detail.code
+					uni.login({
+						success: (code) => {
+							this.$u.post('/api/Login/login', {
+								code: code.code
+							}).then(res => {
+								if (res.code == 1) {
+									uni.setStorageSync("token", res.data.token)
+									if (!res.data.phone || 1) {
+										this.$u.post('/api/Member/bind_Phone', {
+											code: phoneCode
+										}).then(res => {
+											if (res.code == 1) {
+												this.$u.toast("登录成功")
+												this.$u.post('/api/Member/member_info').then(
+													res => {
+														uni.setStorageSync("hx_username",
+															res.data.hx_username)
+														this.$WebIM.conn.open({
+															user: res.data.hx_username,
+															pwd: "999999",
+														}).then(() => {
+															console.log(
+																"login success"
+															);
+														}).catch((reason) => {
+															console.log(
+																"login fail",
+																reason);
+														});
+													})
+												this.setcity()
+												this.getuser()
+											} else {
+												this.$u.toast(res.msg)
+												uni.removeStorageSync('token')
+											}
+										})
+									} else {
+										this.$u.toast("登录成功")
+										this.getuser()
+									}
+								} else {
+									this.$u.toast(res.msg)
+								}
+							})
+						}
+					})
+				}
+			},
+			setcity() {
+				this.$u.post('/api/Index/location', {
+					longitude: this.defaultcity.userLocation.split(',')[0],
+					latitude: this.defaultcity.userLocation.split(',')[1],
+					city_name: this.defaultcity.city
+				})
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					uni.setStorageSync("name", res.data.name)
+					uni.setStorageSync("headimg", res.data.headimg)
+					this.userinfo = res.data
+				})
+			},
+			tosetting() {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "./setting"
+				})
+			},
+			tobaobei() {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "./baobei-list"
+				})
+			},
+			toyongjin() {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "./yongjin"
+				})
+			},
+			tojifen() {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "./jifen"
+				})
+			},
+			toinfo() {
+				if (this.$islogin()) return
+				uni.navigateTo({
+					url: "./userinfo"
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.mine {
+		position: relative;
+		z-index: 1;
+
+		.setting-box {
+			width: 702rpx;
+			height: 82rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 0 auto;
+			padding: 0 24rpx;
+			font-size: 24rpx;
+			font-weight: 400;
+			color: #333333;
+		}
+
+		.tabs-box {
+			width: 702rpx;
+			height: 218rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+
+			.tabs-item {
+				width: 25%;
+
+				image {
+					width: 84rpx;
+					height: 84rpx;
+					margin-bottom: 20rpx;
+					border-radius: 20rpx;
+				}
+
+				text {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #131415;
+				}
+			}
+		}
+
+
+		.yongjin-box {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 0 auto;
+			// padding: 0 50rpx;
+
+			.btn {
+				width: 132rpx;
+				height: 52rpx;
+				background: #1F7EFF;
+				border-radius: 10rpx;
+				color: #fff;
+				line-height: 52rpx;
+				padding: 0;
+				font-size: 22rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+			}
+
+			.mingxi {
+				height: 82rpx;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+
+				text {
+					text-align: center;
+					line-height: 82rpx;
+				}
+			}
+			.price {
+				min-height: 226rpx;
+				border-bottom: 2rpx solid rgba(245, 245, 245, 1);
+				padding: 34rpx 20rpx;
+
+				.forward {
+					::v-deep .uni-noticebar {
+						padding-top: 0 !important;
+						padding-bottom: 0 !important;
+						margin: 0 !important;
+					}
+				}
+
+				.font {
+					width: 96rpx;
+					height: 34rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #888888;
+					line-height: 34rpx;
+				}
+
+				.jffont {
+					width: 112rpx;
+					height: 40rpx;
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					line-height: 40rpx;
+				}
+
+				.img {
+					width: 94rpx;
+					height: 94rpx;
+					margin-right: 34rpx;
+				}
+
+				.text {
+					text:first-child {
+						font-size: 48rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+
+					text:last-child {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+				}
+			}
+		}
+
+		.user-box {
+			padding: 48rpx 24rpx 82rpx 24rpx;
+
+			.user-center {
+				margin: 0 32rpx;
+
+				.text1 {
+					font-size: 32rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					margin: 0 0 20rpx 0;
+					padding: 0;
+					border: none;
+					background-color: rgba(0, 0, 0, 0);
+					line-height: 1.5;
+					text-align: left;
+				}
+
+				.text1::after {
+					margin: 0;
+					padding: 0;
+					border: none;
+				}
+
+				.text2 {
+					padding: 0 20rpx;
+					min-width: 102rpx;
+					line-height: 40rpx;
+					border-radius: 24rpx;
+					border: 2rpx solid #FFFFFF;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+
+			.user-head {
+				width: 120rpx;
+				height: 120rpx;
+				border-radius: 100rpx;
+			}
+		}
+
+		.mine-tips {
+			width: 750rpx;
+			line-height: 56rpx;
+			background: rgba(255, 255, 255, 0.1);
+			padding: 0 24rpx;
+			font-size: 22rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #FFFFFF;
+		}
+
+		.index-bg {
+			width: 750rpx;
+			height: 556rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			position: absolute;
+			top: 1;
+			left: 0;
+			z-index: -1;
+		}
+	}
+</style>

+ 124 - 0
pages/mine/setting.vue

@@ -0,0 +1,124 @@
+<template>
+	<view class="setting">
+		<view class="item u-flex u-row-between" @click="totext(1)">
+			<text class="text">用户协议</text>
+			<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+		</view>
+		<view class="item u-flex u-row-between" @click="totext(2)">
+			<text class="text">隐私政策</text>
+			<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+		</view>
+		<view class="item u-flex u-row-between" @click="showtocall = true">
+			<text class="text">退出登录</text>
+			<u-icon name="arrow-right" color="#CCCCCC"></u-icon>
+		</view>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">确定退出登录?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="logout">确定</text>
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return{
+				showtocall:false
+			}
+		},
+		onLoad() {
+			
+		},
+		methods:{
+			logout(){
+				uni.removeStorageSync("token")
+				this.$WebIM.conn.close()
+				this.$u.toast("退出成功")
+				setTimeout(() => {
+					uni.navigateBack()
+				},800)
+			},
+			totext(type){
+				uni.navigateTo({
+					url:"./xieyi?type=" + type
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.setting{
+		padding: 24rpx;
+		.tocall-box {
+			position: relative;
+		
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+		
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+		
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: rgba(31, 126, 255, 1);
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+		
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: rgba(204, 204, 204, 1);
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					text-decoration: none;
+				}
+			}
+		
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+		.item{
+			padding: 24rpx 0;
+			border-bottom: 2rpx solid rgba(245, 245, 245, 1);
+			.text{
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+			}
+		}
+	}
+</style>

+ 141 - 0
pages/mine/userinfo.vue

@@ -0,0 +1,141 @@
+<template>
+	<view class="userinfo u-flex-col u-col-center">
+		<view class="user-head" @click="changehead">
+			<image v-if="userinfo.headimg" :src="userinfo.headimg" class="head" mode=""></image>
+			<image v-else src="../../static/images/head.png" class="head" mode=""></image>
+			<image src="../../static/images/xiangji.png" class="change" mode=""></image>
+		</view>
+		<input type="text" placeholder="请输入昵称" class="input" v-model="userinfo.name">
+		<view class="user-btn" @click="save">
+			确认
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				userinfo: {
+					headimg:'',
+					name:''
+				},
+				ossdata:{}
+			}
+		},
+		onLoad() {
+			this.getuser()
+			this.getoss()
+		},
+		methods: {
+			getoss(){
+				this.$u.post('/api/Upload/getSignedUrl').then(res => {
+					this.ossdata = res.data
+				})
+			},
+			changehead(){
+				uni.chooseImage({
+					count: 1,
+					success: (img) => {
+						var key = this.ossdata.key + new Date().getTime() + Math.floor(Math.random() * 150) + '.png'
+						uni.uploadFile({
+							url: this.ossdata.host, //输入你的bucketname.endpoint
+							filePath: img.tempFilePaths[0],
+							name: 'file',
+							formData: {
+								key: key,
+								policy: this.ossdata.policy, // 输入你获取的的policy
+								OSSAccessKeyId: this.ossdata.OSSAccessKeyId, // 输入你的AccessKeyId
+								success_action_status: '200', // 让服务端返回200,不然,默认会返回204
+								signature: this.ossdata.Signature, // 输入你获取的的signature
+							},
+							success: (res) => {
+								if (res.statusCode == 200) {
+									this.userinfo.headimg = this.ossdata.host + '/' + key
+									this.$u.post('/api/Member/edit_member_info',{
+										type:1,
+										headimg:this.userinfo.headimg
+									}).then(res => {
+										this.$u.toast(res.msg)
+									})
+								}
+							},
+							fail: (err) => {
+								console.log(err);
+							}
+						})
+					}
+				})
+			},
+			save(){
+				if(!this.userinfo.name){
+					this.$u.toast("请输入昵称")
+					return
+				}
+				this.$u.post('/api/Member/edit_member_info',{
+					type:2,
+					name:this.userinfo.name
+				}).then(res => {
+					this.$u.toast(res.msg)
+				})
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.userinfo = res.data
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.userinfo {
+		.user-btn {
+			position: fixed;
+			bottom: 200rpx;
+			left: 24rpx;
+			width: 702rpx;
+			line-height: 82rpx;
+			background: #1F7EFF;
+			border-radius: 8rpx;
+			text-align: center;
+			font-size: 28rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #FFFFFF;
+		}
+
+		.input {
+			width: 400rpx;
+			height: 100rpx;
+			text-align: center;
+			border-bottom: 2rpx solid rgba(216, 216, 216, 1);
+		}
+
+		.user-head {
+			width: 256rpx;
+			height: 256rpx;
+			border-radius: 100%;
+			position: relative;
+			margin: 102rpx 0 30rpx 0;
+
+			.head {
+				width: 256rpx;
+				height: 256rpx;
+				border-radius: 100%;
+			}
+
+			.change {
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+				width: 78rpx;
+				height: 78rpx;
+				z-index: 10;
+			}
+		}
+	}
+
+</style>

+ 74 - 0
pages/mine/xieyi.vue

@@ -0,0 +1,74 @@
+<template>
+	<view style="padding: 24rpx;" v-html="content">
+		
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return{
+				type:1,
+				content:''
+			}
+		},
+		onLoad(option) {
+			this.type = option.type
+			this.getdata()
+		},
+		onShow() {
+			if(this.type == 1){
+				uni.setNavigationBarTitle({
+					title:'用户协议'
+				})
+			}
+			if(this.type == 2){
+				uni.setNavigationBarTitle({
+					title:'	隐私政策'
+				})
+			}
+			if(this.type == 3){
+				uni.setNavigationBarTitle({
+					title:'	报备活动规则'
+				})
+			}
+			if(this.type == 4){
+				uni.setNavigationBarTitle({
+					title:'	佣金说明'
+				})
+			}
+		},
+		methods:{
+			getdata(){
+				if(this.type == 1){
+					this.$u.post('/api/Index/platform_config').then(res => {
+						const regex = new RegExp('<img', 'gi')
+						this.content = res.data.agreement.replace(regex, `<img style="max-width: 100%; height: auto"`)
+					})
+				}
+				if(this.type == 2){
+					this.$u.post('/api/Index/platform_config').then(res => {
+						const regex = new RegExp('<img', 'gi')
+						this.content = res.data.privacy_policy.replace(regex, `<img style="max-width: 100%; height: auto"`)
+					})
+				}
+				if(this.type == 3){
+					this.$u.post('/api/Index/platform_config').then(res => {
+						const regex = new RegExp('<img', 'gi')
+						this.content = res.data.report_rule.replace(regex, `<img style="max-width: 100%; height: auto"`)
+					})
+				}
+				if(this.type == 4){
+					this.$u.post('/api/Index/platform_config').then(res => {
+						const regex = new RegExp('<img', 'gi')
+						this.content = res.data.brokerage_explain.replace(regex, `<img style="max-width: 100%; height: auto"`)
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	
+</style>

+ 109 - 0
pages/mine/yongjin.vue

@@ -0,0 +1,109 @@
+<template>
+	<view class="yongjin">
+		<view class="yongjin-item u-flex" v-for="(item,index) in list" :key="index">
+			<view class="left">
+				¥
+			</view>
+			<view class="right u-flex-1">
+				<view class="u-flex u-row-between right1">
+					<text>{{item.explain}}</text>
+					<text>{{item.type == 1 ? '+' : '-'}}{{item.change_amount}}</text>
+				</view>
+				<view class="u-flex u-row-between right2">
+					<text>{{item.create_at}}</text>
+					<text>我的佣金 {{item.amount}}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				page: 1,
+				list: []
+			}
+		},
+		onLoad() {
+			this.getlist()
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			getlist() {
+				this.$u.get('/api/Member/balance_list', {
+					page: this.page,
+					page_num: 20
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.yongjin {
+		.yongjin-item {
+			height: 164rpx;
+			border-bottom: 2rpx solid rgba(245, 245, 245, 1);
+			padding: 0 24rpx;
+
+			.right {
+				.right2 {
+					text:first-child {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					text:last-child {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+				}
+
+				.right1 {
+					margin-bottom: 4rpx;
+
+					text:first-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+
+					text:last-child {
+						font-size: 28rpx;
+						font-family: PingFangSC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+					}
+				}
+			}
+
+			.left {
+				text-align: center;
+				width: 100rpx;
+				line-height: 100rpx;
+				border-radius: 100rpx;
+				font-size: 60rpx;
+				color: #fff;
+				font-weight: bold;
+				background-color: rgba(247, 164, 107, 1);
+				margin-right: 32rpx;
+			}
+		}
+	}
+
+</style>

+ 25 - 0
pages/video/info.vue

@@ -0,0 +1,25 @@
+<template>
+	<view style="font-size: 0;width: 750rpx;height: 100vh;">
+		<video :src="mp4" style="width: 750rpx;height: 100vh;" controls="true"></video>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return{
+				mp4:''
+			}
+		},
+		onLoad(option) {
+			this.mp4 = decodeURIComponent(option.mp4)
+		},
+		methods:{
+			
+		}
+	}
+</script>
+
+<style lang="scss">
+	
+</style>

+ 151 - 0
pages/video/video.vue

@@ -0,0 +1,151 @@
+<template>
+	<view class="video-list">
+		<u-navbar :title="config.store_title" title-color="#fff" :background="{background:'#1F7EFF'}" :border-bottom="false" :isBack="false">
+			<view class="u-flex nav-left" slot="left">
+				<u-icon name="map-fill" size="34" color="#fff"></u-icon>
+				<text class="text">{{defaultcity.city || '定位中'}}</text>
+			</view>
+		</u-navbar>
+		<view class="video1 u-flex u-row-between u-flex-wrap">
+			<view class="video-item" v-for="(item,index) in list" :key="index" @click="toinfo(item)">
+				<view class="image-box">
+					<image :src="item.logo" class="image" mode="aspectFill"></image>
+					<image src="../../static/images/video.png" class="play" mode=""></image>
+					<!-- <text class="text">03.25</text> -->
+				</view>
+				<view class="video-name u-line-1">
+					{{item.title}}
+				</view>
+				<view class="time">
+					{{item.create_at}}
+				</view>
+			</view>
+		</view>
+		<gf-tabbar></gf-tabbar>
+	</view>
+
+</template>
+
+<script>
+	import { mapState } from "vuex"
+	export default {
+		data() {
+			return {
+				page:1,
+				list:[]
+			}
+		},
+		onLoad() {
+			
+		},
+		onShow() {
+			uni.setNavigationBarTitle({
+				title: this.config.store_title
+			})
+			this.page = 1
+			this.list = []
+			this.getlist()
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		computed: {
+			...mapState(['config', 'defaultcity'])
+		},
+		methods: {
+			toinfo(item){
+				uni.navigateTo({
+					url:"./info?mp4=" + encodeURIComponent(item.video)
+				})
+			},
+			getlist(){
+				this.$u.post('/api/Index/video_list',{
+					page:this.page,
+					page_num:20,
+					city_id:this.defaultcity.city_id
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.video-list {
+		.nav-left {
+			padding: 0 20rpx;
+
+			.text {
+				font-size: 32rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #FFFFFF;
+				margin-left: 5rpx;
+			}
+		}
+
+		.video1 {
+			padding: 24rpx;
+
+			.video-item {
+				width: 340rpx;
+				margin-bottom: 18rpx;
+
+				.video-name {
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+					margin: 14rpx 0;
+					// height: 56rpx;
+				}
+
+				.time {
+					font-size: 20rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+
+				.image-box {
+					width: 340rpx;
+					height: 272rpx;
+					position: relative;
+
+					.play {
+						width: 64rpx;
+						height: 64rpx;
+						position: absolute;
+						top: 50%;
+						left: 50%;
+						transform: translate(-50%, -50%);
+					}
+
+					.image {
+						width: 340rpx;
+						height: 272rpx;
+						background-color: rgba(0,0,0,0.1);
+						border-radius: 10rpx;
+					}
+
+					.text {
+						position: absolute;
+						z-index: 10;
+						right: 10rpx;
+						bottom: 10rpx;
+						font-size: 20rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FFFFFF;
+					}
+				}
+			}
+		}
+	}
+
+</style>

+ 242 - 0
pagesA/components/echarts-uniapp/echarts-uniapp.vue

@@ -0,0 +1,242 @@
+<template>
+	<!-- #ifdef MP-WEIXIN || MP-TOUTIAO -->
+	<canvas type="2d" class="echarts" :canvas-id="canvasId" :id="canvasId" @touchstart="touchStart"
+		@touchmove="touchMove" @touchend="touchEnd" />
+	<!-- #endif -->
+	<!-- #ifndef MP-WEIXIN || MP-TOUTIAO -->
+	<canvas class="echarts" :canvas-id="canvasId" :id="canvasId" @touchstart="touchStart" @touchmove="touchMove"
+		@touchend="touchEnd" />
+	<!-- #endif -->
+
+</template>
+<script>
+	
+	/**
+	 * echartsForUniApp echart兼容uni-app
+	 * @description echart兼容uni-app
+	 * @property {Object} option 图表数据
+	 * @property {String} canvasId 画布id
+	 * @example <echarts ref="echarts" :option="option" canvasId="echarts"></echarts>
+	 */
+	import WxCanvas from './wx-canvas.js';
+	import * as echarts from './echarts.min.js';	
+	
+	var chartList = {}
+	export default {
+		props: {
+			canvasId: {
+				type: String,
+				default: 'echarts'
+			},
+			option: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			},
+		},
+		watch: {
+			option(newValue, oldValue) {
+				if(newValue.series){
+					this.initChart(newValue)
+				}
+			}
+		},
+		data() {
+			return {
+				ctx:null
+			}
+		},
+		
+		mounted() {
+			// Disable prograssive because drawImage doesn't support DOM as parameter
+			// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
+			echarts.registerPreprocessor(option => {
+				if (option && option.series) {
+					if (option.series.length > 0) {
+						option.series.forEach(series => {
+							series.progressive = 0;
+						});
+					} else if (typeof option.series === 'object') {
+						option.series.progressive = 0;
+					}
+				}
+			});
+
+		},
+
+		methods: {
+			getCanvasAttr2d() {
+				return new Promise((resolve, reject) => {
+					const query = uni.createSelectorQuery().in(this)
+					query
+						.select('#' + this.canvasId)
+						.fields({
+							node: true,
+							size: true
+						})
+						.exec(res => {
+							const canvasNode = res[0].node
+							this.canvasNode = canvasNode
+							const canvasDpr = uni.getSystemInfoSync().pixelRatio
+							const canvasWidth = res[0].width
+							const canvasHeight = res[0].height
+							this.ctx = canvasNode.getContext('2d')
+			
+							const canvas = new WxCanvas(this.ctx, this.canvasId, true, canvasNode)
+							echarts.setCanvasCreator(() => {
+								return canvas
+							})
+							resolve({
+								canvas,
+								canvasWidth,
+								canvasHeight,
+								canvasDpr
+							})
+						})
+				});
+			},
+			getCanvasAttr() {
+				return new Promise((resolve, reject) => {
+					this.ctx = uni.createCanvasContext(this.canvasId, this);
+					var canvas = new WxCanvas(this.ctx, this.canvasId, false);
+					echarts.setCanvasCreator(() => {
+						return canvas;
+					});
+					const canvasDpr = 1
+					var query = uni.createSelectorQuery()
+						// #ifndef MP-ALIPAY
+						.in(this)
+					// #endif
+					query.select('#' + this.canvasId).boundingClientRect(res => {
+						const canvasWidth = res.width
+						const canvasHeight = res.height
+						resolve({
+							canvas,
+							canvasWidth,
+							canvasHeight,
+							canvasDpr
+						})
+					}).exec();
+				});
+			},
+			// #ifdef H5
+			//H5绘制图表
+			initChart(option) {
+				this.ctx = uni.createCanvasContext(this.canvasId, this);
+				chartList[this.canvasId] = echarts.init(document.getElementById(this.canvasId));
+				chartList[this.canvasId].setOption(option?option:this.option);
+			},
+			//H5生成图片
+			canvasToTempFilePath(opt) {
+				const base64 = chartList[this.canvasId].getDataURL()
+				opt.success && opt.success({tempFilePath:base64})
+			},
+			// #endif
+			// #ifndef H5
+			//绘制图表
+			async initChart(option) {
+				// #ifdef MP-WEIXIN || MP-TOUTIAO 
+				const canvasAttr = await this.getCanvasAttr2d();
+				// #endif
+				// #ifndef MP-WEIXIN || MP-TOUTIAO
+				const canvasAttr = await this.getCanvasAttr();
+				// #endif
+				const {
+					canvas,
+					canvasWidth,
+					canvasHeight,
+					canvasDpr
+				} = canvasAttr
+				chartList[this.canvasId] = echarts.init(canvas, null, {
+					width: canvasWidth,
+					height: canvasHeight,
+					devicePixelRatio: canvasDpr // new
+				});
+				canvas.setChart(chartList[this.canvasId]);
+				chartList[this.canvasId].setOption(option?option:this.option);
+			},
+			//生成图片
+			canvasToTempFilePath(opt) {
+				// #ifdef MP-WEIXIN || MP-TOUTIAO
+				var query = uni.createSelectorQuery()
+				// #ifndef MP-ALIPAY
+					.in(this)
+				// #endif
+				query.select('#' + this.canvasId).fields({ node: true, size: true }).exec(res => {
+					const canvasNode = res[0].node
+					opt.canvas = canvasNode
+					uni.canvasToTempFilePath(opt, this)
+				})
+				// #endif
+				// #ifndef MP-WEIXIN || MP-TOUTIAO
+				if (!opt.canvasId) {
+					opt.canvasId = this.canvasId;
+				}
+				this.ctx.draw(true, () => {
+					uni.canvasToTempFilePath(opt, this);
+				});
+				// #endif
+			},
+			// #endif
+			
+			touchStart(e) {
+				if (chartList[this.canvasId] && e.touches.length > 0) {
+					var touch = e.touches[0];
+					var handler = chartList[this.canvasId].getZr().handler;
+					handler.dispatch('mousedown', {
+						zrX: touch.x,
+						zrY: touch.y
+					});
+					handler.dispatch('mousemove', {
+						zrX: touch.x,
+						zrY: touch.y
+					});
+					handler.processGesture(wrapTouch(e), 'start');
+				}
+			},
+			touchMove(e) {
+				if (chartList[this.canvasId] && e.touches.length > 0) {
+					var touch = e.touches[0];
+					var handler = chartList[this.canvasId].getZr().handler;
+					handler.dispatch('mousemove', {
+						zrX: touch.x,
+						zrY: touch.y
+					});
+					handler.processGesture(wrapTouch(e), 'change');
+				}
+			},
+
+			touchEnd(e) {
+				if (chartList[this.canvasId]) {
+					const touch = e.changedTouches ? e.changedTouches[0] : {};
+					var handler = chartList[this.canvasId].getZr().handler;
+					handler.dispatch('mouseup', {
+						zrX: touch.x,
+						zrY: touch.y
+					});
+					handler.dispatch('click', {
+						zrX: touch.x,
+						zrY: touch.y
+					});
+					handler.processGesture(wrapTouch(e), 'end');
+				}
+			}
+		}
+	}
+
+	function wrapTouch(event) {
+		for (let i = 0; i < event.touches.length; ++i) {
+			const touch = event.touches[i];
+			touch.offsetX = touch.x;
+			touch.offsetY = touch.y;
+		}
+		return event;
+	}
+</script>
+<style lang="scss" scoped>
+	.echarts {
+		width: 100%;
+		height: 100%;
+	}
+</style>

File diff suppressed because it is too large
+ 0 - 0
pagesA/components/echarts-uniapp/echarts.min.js


+ 105 - 0
pagesA/components/echarts-uniapp/wx-canvas.js

@@ -0,0 +1,105 @@
+export default class WxCanvas {
+  constructor(ctx, canvasId, isNew, canvasNode) {
+    this.ctx = ctx;
+    this.canvasId = canvasId;
+    this.chart = null;
+    this.isNew = isNew
+    if (isNew) {
+      this.canvasNode = canvasNode;
+    }
+    else {
+      this._initStyle(ctx);
+    }
+
+    // this._initCanvas(zrender, ctx);
+
+    this._initEvent();
+  }
+
+  getContext(contextType) {
+    if (contextType === '2d') {
+      return this.ctx;
+    }
+  }
+
+  // canvasToTempFilePath(opt) {
+  //   if (!opt.canvasId) {
+  //     opt.canvasId = this.canvasId;
+  //   }
+  //   return wx.canvasToTempFilePath(opt, this);
+  // }
+
+  setChart(chart) {
+    this.chart = chart;
+  }
+
+  attachEvent() {
+    // noop
+  }
+
+  detachEvent() {
+    // noop
+  }
+
+  _initCanvas(zrender, ctx) {
+    zrender.util.getContext = function () {
+      return ctx;
+    };
+
+    zrender.util.$override('measureText', function (text, font) {
+      ctx.font = font || '12px sans-serif';
+      return ctx.measureText(text);
+    });
+  }
+
+  _initStyle(ctx) {
+    ctx.createRadialGradient = () => {
+      return ctx.createCircularGradient(arguments);
+    };
+  }
+
+  _initEvent() {
+    this.event = {};
+    const eventNames = [{
+      wxName: 'touchStart',
+      ecName: 'mousedown'
+    }, {
+      wxName: 'touchMove',
+      ecName: 'mousemove'
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'mouseup'
+    }, {
+      wxName: 'touchEnd',
+      ecName: 'click'
+    }];
+
+    eventNames.forEach(name => {
+      this.event[name.wxName] = e => {
+        const touch = e.touches[0];
+        this.chart.getZr().handler.dispatch(name.ecName, {
+          zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
+          zrY: name.wxName === 'tap' ? touch.clientY : touch.y
+        });
+      };
+    });
+  }
+
+  set width(w) {
+    if (this.canvasNode) this.canvasNode.width = w
+  }
+  set height(h) {
+    if (this.canvasNode) this.canvasNode.height = h
+  }
+
+  get width() {
+    if (this.canvasNode)
+      return this.canvasNode.width
+    return 0
+  }
+  get height() {
+    if (this.canvasNode)
+      return this.canvasNode.height
+    return 0
+  }
+}

+ 172 - 0
pagesA/index/allHouses.vue

@@ -0,0 +1,172 @@
+<template>
+	<view class="allHouses">
+		<view class="index-bg"></view>
+		<view class="search-box u-flex u-row-between">
+			<u-icon name="search" color="#CCCCCC" size="36"></u-icon>
+			<input type="text" placeholder="搜索楼盘" class="input" v-model="keyword1">
+			<text class="text" @click="tosearch">搜索</text>
+		</view>
+		<view class="newHouses-list">
+			<view class="newHouses-title u-flex u-row-between">
+				<text>全部楼盘</text>
+				<view class="u-flex" @click="opensearch">
+					<image src="../../static/images/shaixuan.png" mode=""></image>
+					<text style="font-size: 26rpx;font-weight: 500;color: #1677FF;margin-left: 10rpx;">区域搜索</text>
+				</view>
+			</view>
+			<view :class="buju == 1 ? '' : 'u-flex u-row-between u-flex-wrap'">
+				<view v-for="(item,index) in list" :key="index">
+					<gf-goods :type="buju" :data="item"></gf-goods>
+				</view>
+			</view>
+		</view>
+		<gf-search ref="search" @shaixuan="shaixuan"></gf-search>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from "vuex"
+	export default {
+		data() {
+			return {
+				keyword1: '',
+				keyword: '',
+				type: 1,
+				buju: 2,
+				page: 1,
+				list: [],
+				params: {},
+				title: ''
+			}
+		},
+		computed: {
+			...mapState(['defaultcity'])
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		onLoad(option) {
+			this.type = option.type
+			this.title = option.title
+			if (this.type == 2) {
+				this.buju = 1
+			} else {
+				this.buju = 2
+			}
+			this.getlist()
+		},
+		onShow() {
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		methods: {
+			shaixuan(e) {
+				this.params = e
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			tosearch() {
+				this.keyword = this.$u.trim(this.keyword1)
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			getlist() {
+				this.$u.post('/api/Index/property_list', {
+					page: this.page,
+					page_num: 20,
+					type: this.type,
+					keyword: this.keyword,
+					...this.params,
+					city_id: this.params.area_id ? '' : this.defaultcity.city_id
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			},
+			opensearch() {
+				this.$refs.search.show = true
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.allHouses {
+		position: relative;
+		z-index: 1;
+
+		// width: 750rpx;
+		// overflow-x: hidden;
+		.newHouses-list {
+			width: 702rpx;
+			background: linear-gradient(180deg, #FFFFFF 0%, #FFFFFF 38%, rgba(255, 255, 255, 0) 100%);
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx;
+
+
+			.newHouses-title {
+				padding: 20rpx 0;
+
+				text {
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #131415;
+				}
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.search-box {
+			width: 702rpx;
+			height: 72rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 0 auto 20rpx auto;
+			padding-left: 24rpx;
+
+			.input {
+				flex: 1;
+				margin: 0 10rpx;
+			}
+
+			.text {
+				padding: 0 24rpx;
+				border-left: 1rpx solid #E5E7ED;
+				line-height: 36rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #1E7DFF;
+			}
+		}
+
+		.index-bg {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 750rpx;
+			height: 556rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			z-index: -1;
+		}
+	}
+</style>

+ 221 - 0
pagesA/index/counter-info.vue

@@ -0,0 +1,221 @@
+<template>
+	<view class="counter-info" v-if="show">
+		<view class="info-box" v-if="type == 3">
+			<view class="">
+				<view class="box-title">
+					贷款总计
+				</view>
+				<view class="box-list u-flex u-row-between u-flex-wrap">
+					<text class="text" style="width: 55%;">首月月供:¥{{detail.general_info.first_monthly_payment.toFixed(2)}}元</text>
+					<text class="text u-flex-1">贷款年限:{{detail.general_info.age_limit}}年</text>
+					<text class="text" style="width: 55%;">贷款总额:¥{{detail.general_info.calculate_amount_all.toFixed(2)}}元</text>
+					<text class="text u-flex-1">累计利息:¥{{detail.general_info.interest_total.toFixed(2)}}元</text>
+					<text class="text" style="width: 55%;">累计还款总额:¥{{detail.general_info.repayment_amount_all.toFixed(2)}}元</text>
+				</view>
+			</view>
+			<view class="">
+				<view class="box-title">
+					公积金贷款
+				</view>
+				<view class="box-list u-flex u-row-between u-flex-wrap">
+					<text class="text" style="width: 55%;">首月月供:¥{{detail.accumulation_info.first_monthly_payment.toFixed(2)}}元</text>
+					<text class="text u-flex-1">贷款年限:{{detail.general_info.age_limit}}年</text>
+					<text class="text" style="width: 55%;">贷款总额:¥{{detail.accumulation_info.calculate_amount_all.toFixed(2)}}元</text>
+					<text class="text u-flex-1">累计利息:¥{{detail.accumulation_info.interest_total.toFixed(2)}}元</text>
+					<text class="text" style="width: 55%;">累计还款总额:¥{{detail.accumulation_info.repayment_amount_all.toFixed(2)}}元</text>
+				</view>
+			</view>
+			<view class="">
+				<view class="box-title">
+					商业贷款
+				</view>
+				<view class="box-list u-flex u-row-between u-flex-wrap">
+					<text class="text" style="width: 55%;">首月月供:¥{{detail.business_info.first_monthly_payment.toFixed(2)}}元</text>
+					<text class="text u-flex-1">贷款年限:{{detail.general_info.age_limit}}年</text>
+					<text class="text" style="width: 55%;">贷款总额:¥{{detail.business_info.calculate_amount_all.toFixed(2)}}元</text>
+					<text class="text u-flex-1">累计利息:¥{{detail.business_info.interest_total.toFixed(2)}}元</text>
+					<text class="text" style="width: 55%;">累计还款总额:¥{{detail.business_info.repayment_amount_all.toFixed(2)}}元</text>
+				</view>
+			</view>
+			
+			<view class="box-btn" @click="toback">
+				重新计算
+			</view>
+		</view>
+		<view class="info-box" v-else>
+			<view class="box-title">
+				贷款总计
+			</view>
+			<view class="box-list u-flex u-row-between u-flex-wrap">
+				<text class="text" style="width: 55%;">首月月供:¥{{Number(detail.first_monthly_payment).toFixed(2)}}元</text>
+				<text class="text u-flex-1">贷款年限:{{detail.age_limit}}年</text>
+				<text class="text" style="width: 55%;">贷款总额:¥{{detail.calculate_amount.toFixed(2)}}元</text>
+				<text class="text u-flex-1">累计利息:¥{{detail.interest_total.toFixed(2)}}元</text>
+				<text class="text" style="width: 55%;">累计还款总额:¥{{detail.repayment_amount_all.toFixed(2)}}元</text>
+			</view>
+			<view class="box-btn" @click="toback">
+				重新计算
+			</view>
+		</view>
+		<view class="info-list">
+			<view class="list-header u-flex u-row-between">
+				<text>期数</text>
+				<text>月供(元)</text>
+				<text>本金(元)</text>
+				<text>利息(元)</text>
+			</view>
+			<view class="list-item u-flex u-row-between" v-for="(item,index) in detail.repayment_info" :key="index">
+				<text>第{{item.periods}}期</text>
+				<text>{{item.monthly_payment}}</text>
+				<text>{{item.principal}}</text>
+				<text>{{item.interest}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				params: {},
+				type: 1,
+				detail: {
+					general_info:{},
+					accumulation_info:{},
+					business_info:{},
+					repayment_info:[]
+				},
+				show:false
+			}
+		},
+		onLoad(option) {
+			this.params = JSON.parse(decodeURIComponent(option.params))
+			this.type = option.type
+			this.getdata()
+		},
+		methods: {
+			toback() {
+				uni.navigateBack()
+			},
+			getdata() {
+				uni.showLoading({
+					mask:true,
+					title:"请稍后"
+				})
+				if (this.type == 1 || this.type == 2) {
+					this.$u.post('/api/Calculator/not_group_loans', this.params).then(res => {
+						if (res.code == 1) {
+							this.detail = res.data
+						} else {
+							this.$u.toast(res.msg)
+						}
+						this.show = true
+					})
+				} else {
+					this.$u.post('/api/Calculator/group_loans', this.params).then(res => {
+						if (res.code == 1) {
+							this.detail = res.data
+						} else {
+							this.$u.toast(res.msg)
+						}
+						this.show = true
+					})
+				}
+
+			}
+		}
+	}
+
+</script>
+
+<style lang="scss">
+	.counter-info {
+		position: relative;
+		z-index: 1;
+		padding: 1rpx 0;
+		background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 284rpx, #F6F6F6 100%);
+		min-height: 100vh;
+
+		.info-list {
+			width: 722rpx;
+			// height: 650rpx;
+			background: #FFFFFF;
+			border-radius: 10rpx;
+			margin: 20rpx auto;
+			padding: 20rpx 10rpx 1rpx 10rpx;
+
+			.list-item {
+				margin-bottom: 20rpx;
+
+				text {
+					flex: 1;
+					text-align: center;
+					line-height: 66rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+			}
+
+			.list-header {
+				height: 66rpx;
+				background: #C6DDFD;
+				border-radius: 10rpx;
+				margin-bottom: 20rpx;
+
+				text {
+					flex: 1;
+					text-align: center;
+					line-height: 66rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+			}
+		}
+
+		.info-box {
+			width: 702rpx;
+			// height: 390rpx;
+			background: #FFFFFF;
+			border-radius: 10rpx;
+			margin: 108rpx auto 20rpx auto;
+			padding: 0 24rpx 1rpx 24rpx;
+
+			.box-btn {
+				width: 100%;
+				line-height: 80rpx;
+				background: linear-gradient(143deg, #8DBDFF 0%, #1F7EFF 100%);
+				border-radius: 40rpx;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+				margin: 40rpx auto;
+			}
+
+			.box-list {
+				.text {
+					margin-bottom: 20rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+				}
+			}
+
+			.box-title {
+				padding: 24rpx 0;
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #333333;
+			}
+		}
+	}
+
+</style>

+ 704 - 0
pagesA/index/counter.vue

@@ -0,0 +1,704 @@
+<template>
+	<view class="counter">
+		<view class="dataCenter-header u-flex u-row-between">
+			<view class="header-item u-flex-col u-col-center" v-for="(item,index) in tabs" :key="index" @click="change(index)">
+				<text :class="current == index ? 'active1' : 'active'">{{item}}</text>
+				<image :style="{opacity:current == index ? 1 : 0}" src="../../static/images/dataCenter1-1.png" mode=""></image>
+			</view>
+		</view>
+		<view class="" v-if="current == 0">
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">还款方式:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<u-radio-group v-model="denge" class="u-flex-1" size="24">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">等额本息</u-radio>
+						<u-radio :name="2" label-size="24">等额本金</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">计算方式:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<u-radio-group v-model="jisuan" class="u-flex-1" size="24">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">贷款总额</u-radio>
+						<u-radio :name="2" label-size="24">单价面积</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款总额:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 1">
+					<input type="digit" placeholder="请输入" class="input" v-model="shangyeprice">
+					<text class="text">万元</text>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 2">
+					<input type="digit" placeholder="请输入" class="input" v-model="shangyeprice">
+					<text class="text" style="margin-right: 10rpx;">元/㎡</text>
+					x
+					<input type="digit" placeholder="请输入" class="input" v-model="shangyemianji">
+					<text class="text">㎡</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex" v-if="jisuan == 2" @click="shoufushow = true">
+				<view class="u-flex row-left">
+					<text class="text">首付成数:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="text" placeholder="请选择" class="input" v-model="shoufuname" :disabled="true">
+					<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款利率:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="digit" placeholder="请输入" class="input" v-model="shangyelilv">
+					<text class="text">%</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex" @click="qixianshow = true">
+				<view class="u-flex row-left">
+					<text class="text">贷款期限:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="text" placeholder="请选择" class="input" v-model="qixianname" :disabled="true">
+					<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+				</view>
+			</view>
+		</view>
+		<view class="" v-if="current == 1">
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">还款方式:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<u-radio-group v-model="denge" class="u-flex-1" size="24">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">等额本息</u-radio>
+						<u-radio :name="2" label-size="24">等额本金</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">计算方式:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<u-radio-group v-model="jisuan" class="u-flex-1" size="24">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">贷款总额</u-radio>
+						<u-radio :name="2" label-size="24">单价面积</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款总额:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 1">
+					<input type="digit" placeholder="请输入" class="input" v-model="gongjijinprice">
+					<text class="text">万元</text>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 2">
+					<input type="digit" placeholder="请输入" class="input" v-model="gongjijinprice">
+					<text class="text" style="margin-right: 10rpx;">元/㎡</text>
+					x
+					<input type="digit" placeholder="请输入" class="input" v-model="gongjijinmianji">
+					<text class="text">㎡</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex" v-if="jisuan == 2" @click="shoufushow = true">
+				<view class="u-flex row-left">
+					<text class="text">首付成数:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="text" placeholder="请选择" class="input" v-model="shoufuname" :disabled="true">
+					<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款利率:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="digit" placeholder="请输入" class="input" v-model="gongjijinlilv">
+					<text class="text">%</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex" @click="qixianshow = true">
+				<view class="u-flex row-left">
+					<text class="text">贷款期限:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="text" placeholder="请选择" class="input" v-model="qixianname" :disabled="true">
+					<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+				</view>
+			</view>
+		</view>
+		<view class="" v-if="current == 2">
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">还款方式:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<u-radio-group v-model="denge" class="u-flex-1" size="24">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">等额本息</u-radio>
+						<u-radio :name="2" label-size="24">等额本金</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">计算方式:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<u-radio-group v-model="jisuan" class="u-flex-1" size="24" @change="changejisuan">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">房屋总价</u-radio>
+						<u-radio :name="2" label-size="24">单价面积</u-radio>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">房屋总价:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 1">
+					<input type="digit" placeholder="请输入" class="input" v-model="zuheprice" @input="changezuhe">
+					<text class="text">万元</text>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1" v-if="jisuan == 2">
+					<input type="digit" placeholder="请输入" class="input" v-model="zuheprice" @input="changezuhe">
+					<text class="text" style="margin-right: 10rpx;">元/㎡</text>
+					x
+					<input type="digit" placeholder="请输入" class="input" v-model="zuhemianji" @input="changezuhe">
+					<text class="text">㎡</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">首付成数:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<u-radio-group v-model="shoufu" class="u-flex-1" size="24" @change="changechengshu">
+					<view class="row-right u-flex u-row-between">
+						<u-radio :name="1" label-size="24">首套</u-radio>
+						<u-radio :name="2" label-size="24">二套</u-radio>
+						<view class="row-right u-flex u-row-between" style="width: 30%;" @click="shoufushow = true">
+							<input type="text" placeholder="请选择" class="input" v-model="shoufuname" :disabled="true">
+							<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+						</view>
+					</view>
+				</u-radio-group>
+			</view>
+			<view class="jisuan-row u-flex" @click="qixianshow = true">
+				<view class="u-flex row-left">
+					<text class="text">贷款期限:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="text" placeholder="请选择" class="input" v-model="qixianname" :disabled="true">
+					<u-icon name="arrow-right" color="#ccc" size="24"></u-icon>
+				</view>
+			</view>
+			<u-gap height="20" bg-color="#F6F6F6"></u-gap>
+			<view class="tabs-title">
+				公积金贷款信息
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款总额:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="number" placeholder="请输入" class="input" v-model="gongjijinprice" @input="changezuhe2">
+					<text class="text">万元</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款利率:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="number" placeholder="请输入" class="input" v-model="gongjijinlilv">
+					<text class="text">%</text>
+				</view>
+			</view>
+			<u-gap height="20" bg-color="#F6F6F6"></u-gap>
+			<view class="tabs-title">
+				商业贷款信息
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款总额:</text>
+					<!-- <u-icon name="question-circle-fill" color="#CCCCCC"></u-icon> -->
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="number" placeholder="请输入" class="input" v-model="shangyeprice" @input="changezuhe1">
+					<text class="text">万元</text>
+				</view>
+			</view>
+			<view class="jisuan-row u-flex">
+				<view class="u-flex row-left">
+					<text class="text">贷款利率:</text>
+					<u-icon name="question-circle-fill" color="#CCCCCC"></u-icon>
+				</view>
+				<view class="row-right u-flex u-row-between u-flex-1">
+					<input type="number" placeholder="请输入" class="input" v-model="shangyelilv">
+					<text class="text">%</text>
+				</view>
+			</view>
+		</view>
+		<view class="down-btn u-flex u-row-between">
+			<text @click="chongzhi">重置</text>
+			<text @click="toinfo">计算</text>
+		</view>
+		<u-select v-model="qixianshow" :list="qixianlist" label-name="name" value-name="value" @confirm="changeqixian"></u-select>
+		<u-select v-model="shoufushow" :list="shoufulist" label-name="name" value-name="value" @confirm="changeshoufu"></u-select>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				tabs: ['商业贷款', '公积金贷款', '组合贷款'],
+				current: 0,
+				denge: 1,
+				jisuan: 1,
+				shoufu: 1,
+
+
+				shangyeprice: '',
+				shangyemianji: '',
+				shangyelilv: '',
+
+				gongjijinprice: '',
+				gongjijinmianji: '',
+				gongjijinlilv: '',
+
+				zuheprice: '',
+				zuhemianji: '',
+
+				qixianname: '30年(360期)',
+				qixianvalue: '360',
+				qixianlist: [],
+				qixianshow: false,
+
+				shoufuname: '',
+				shoufuvalue: '',
+				shoufulist: [],
+				shoufushow: false,
+
+				config: {},
+				title: ''
+			}
+		},
+		onLoad(option) {
+			this.title = option.title
+			this.getdata()
+		},
+		onShow() {
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		computed: {
+
+		},
+		methods: {
+			chongzhi() {
+				this.shangyeprice = ''
+				this.shangyemianji = ''
+				this.shangyelilv = this.config.business_interest_rate
+
+				this.gongjijinprice = ''
+				this.gongjijinmianji = ''
+				this.gongjijinlilv = this.config.accumulation_interest_rate
+
+				this.zuheprice = ''
+				this.zuhemianji = ''
+
+				this.qixianname = '30年(360期)'
+				this.qixianvalue = 360
+
+				this.shoufuname = `${this.config.first_home_divide}成`
+				this.shoufuvalue = this.config.first_home_divide
+
+				this.denge = 1
+				this.jisuan = 1
+				this.shoufu = 1
+			},
+			changejisuan() {
+				this.changezuhe()
+			},
+			changechengshu(e) {
+				if (e == 1) {
+					this.shoufuname = `${this.config.first_home_divide}成`
+					this.shoufuvalue = this.config.first_home_divide
+				} else {
+					this.shoufuname = `${this.config.second_home_divide}成`
+					this.shoufuvalue = this.config.second_home_divide
+				}
+				this.changezuhe()
+			},
+			changezuhe() {
+				if (this.zuheprice > 0) {
+					if (this.jisuan == 1) {
+						this.shangyeprice = (this.zuheprice * (1 - this.shoufuvalue / 10)).toFixed(2)
+					} else {
+						this.shangyeprice = ((this.zuheprice * this.zuhemianji) / 10000 * (1 - this.shoufuvalue / 10)).toFixed(2)
+					}
+					this.gongjijinprice = ''
+				} else {
+					this.gongjijinprice = ''
+					this.shangyeprice = ''
+				}
+			},
+			changezuhe1(e) {
+				if (this.zuheprice > 0) {
+					if (this.jisuan == 1) {
+						var zuheprice = (this.zuheprice * (1 - this.shoufuvalue / 10)).toFixed(2)
+					} else {
+						var zuheprice = ((this.zuheprice * this.zuhemianji) / 10000 * (1 - this.shoufuvalue / 10)).toFixed(2)
+					}
+					if (this.shangyeprice > zuheprice) {
+						this.$u.toast(`商业贷款必须小于${zuheprice}万元`)
+						this.gongjijinprice = ''
+						return
+					}
+					this.gongjijinprice = (zuheprice - this.shangyeprice).toFixed(2)
+				}
+			},
+			changezuhe2(e) {
+				if (this.zuheprice > 0) {
+					if (this.jisuan == 1) {
+						var zuheprice = (this.zuheprice * (1 - this.shoufuvalue / 10)).toFixed(2)
+					} else {
+						var zuheprice = ((this.zuheprice * this.zuhemianji) / 10000 * (1 - this.shoufuvalue / 10)).toFixed(2)
+					}
+					if (this.gongjijinprice > zuheprice) {
+						this.$u.toast(`公积金贷款必须小于${zuheprice}万元`)
+						this.shangyeprice = ''
+						return
+					}
+					this.shangyeprice = (zuheprice - this.gongjijinprice).toFixed(2)
+				}
+			},
+			changeshoufu(e) {
+				this.shoufuname = e[0].label
+				this.shoufuvalue = e[0].value
+				if (this.current == 2) {
+					this.changezuhe()
+				}
+			},
+			changeqixian(e) {
+				this.qixianname = e[0].label
+				this.qixianvalue = e[0].value
+			},
+			getdata() {
+				this.$u.post('/api/Calculator/divide_list').then(res => {
+					res.data.forEach(val => {
+						this.shoufulist.push({
+							name: `${val.name}成`,
+							value: val.name
+						})
+					})
+				})
+				for (let i = 1; i <= 30; i++) {
+					this.qixianlist.push({
+						name: `${i}年(${i * 12}期)`,
+						value: i * 12
+					})
+				}
+				this.$u.post('/api/Index/platform_config').then(res => {
+					if (res.code == 1) {
+						this.config = res.data
+						this.shangyelilv = this.config.business_interest_rate
+						this.gongjijinlilv = this.config.accumulation_interest_rate
+						this.shoufuname = `${this.config.first_home_divide}成`
+						this.shoufuvalue = this.config.first_home_divide
+					}
+				})
+			},
+			change(index) {
+				this.current = index
+				this.shangyelilv = this.config.business_interest_rate
+				this.gongjijinlilv = this.config.accumulation_interest_rate
+				this.shoufu = 1
+				this.shoufuname = `${this.config.first_home_divide}成`
+				this.shoufuvalue = this.config.first_home_divide
+			},
+			toinfo() {
+				if (this.current == 0) {
+					if (this.jisuan == 1) {
+						if (!this.shangyeprice) {
+							this.$u.toast("请输入贷款总额")
+							return
+						}
+					}
+					if (this.jisuan == 2) {
+						if (!this.shangyeprice || !this.shangyemianji) {
+							this.$u.toast("请输入单价面积")
+							return
+						}
+						if (!this.shoufuname) {
+							this.$u.toast("请选择首付成数")
+							return
+						}
+					}
+					if (!this.shangyelilv) {
+						this.$u.toast("请输入贷款利率")
+						return
+					}
+					var params = {
+						repay_type: this.denge,
+						calculate_amount: this.jisuan == 1 ? (this.shangyeprice * 10000) : (this.shangyeprice * this.shangyemianji * (1 - this.shoufuvalue / 10)),
+						interest_rate: this.shangyelilv,
+						time_limit: this.qixianvalue
+					}
+					this.$u.post('/api/Calculator/not_group_loans', params).then(res => {
+						if (res.code == 1) {
+							uni.navigateTo({
+								url: "./counter-info?params=" + encodeURIComponent(JSON.stringify(params)) + "&type=1"
+							})
+						} else {
+							this.$u.toast(res.msg)
+						}
+					})
+				}
+				if (this.current == 1) {
+					if (this.jisuan == 1) {
+						if (!this.gongjijinprice) {
+							this.$u.toast("请输入贷款总额")
+							return
+						}
+					}
+					if (this.jisuan == 2) {
+						if (!this.gongjijinprice || !this.gongjijinmianji) {
+							this.$u.toast("请输入单价面积")
+							return
+						}
+						if (!this.shoufuname) {
+							this.$u.toast("请选择首付成数")
+							return
+						}
+					}
+					if (!this.gongjijinlilv) {
+						this.$u.toast("请输入贷款利率")
+						return
+					}
+					var params = {
+						repay_type: this.denge,
+						calculate_amount: this.jisuan == 1 ? (this.gongjijinprice * 10000) : (this.gongjijinprice * this.gongjijinmianji * (1 - this.shoufuvalue / 10)),
+						interest_rate: this.gongjijinlilv,
+						time_limit: this.qixianvalue
+					}
+					this.$u.post('/api/Calculator/not_group_loans', params).then(res => {
+						if (res.code == 1) {
+							uni.navigateTo({
+								url: "./counter-info?params=" + encodeURIComponent(JSON.stringify(params)) + "&type=2"
+							})
+						} else {
+							this.$u.toast(res.msg)
+						}
+					})
+				}
+				if (this.current == 2) {
+					if (this.jisuan == 1) {
+						if (!this.zuheprice) {
+							this.$u.toast("请输入房屋总价")
+							return
+						}
+					}
+					if (this.jisuan == 2) {
+						if (!this.zuheprice || !this.zuhemianji) {
+							this.$u.toast("请输入单价面积")
+							return
+						}
+						if (!this.shoufuname) {
+							this.$u.toast("请选择首付成数")
+							return
+						}
+					}
+					if (!this.shangyelilv) {
+						this.$u.toast("请输入商业贷款利率")
+						return
+					}
+					if (!this.gongjijinlilv) {
+						this.$u.toast("请输入公积金贷款利率")
+						return
+					}
+					var all = Number(this.gongjijinprice) + Number(this.shangyeprice)
+					if (this.jisuan == 1) {
+						var zuheprice = (this.zuheprice * (1 - this.shoufuvalue / 10)).toFixed(2)
+					} else {
+						var zuheprice = ((this.zuheprice * this.zuhemianji) / 10000 * (1 - this.shoufuvalue / 10)).toFixed(2)
+					}
+					if (all > zuheprice) {
+						this.$u.toast(`贷款金额不得大于${zuheprice}万元`)
+						return
+					}
+					var params = {
+						repay_type: this.denge,
+						business_calculate_amount: this.jisuan == 1 ? (this.shangyeprice * 10000) : (this.shangyeprice * this.shangyemianji * (1 - this.shoufuvalue / 10)),
+						business_interest_rate: this.shangyelilv,
+						accumulation_calculate_amount: this.jisuan == 1 ? (this.gongjijinprice * 10000) : (this.gongjijinprice * this.gongjijinmianji * (1 - this.shoufuvalue / 10)),
+						accumulation_interest_rate: this.gongjijinlilv,
+						time_limit: this.qixianvalue
+					}
+					uni.showLoading({
+						mask: true,
+						title: "请稍后"
+					})
+					this.$u.post('/api/Calculator/group_loans', params).then(res => {
+						if (res.code == 1) {
+							uni.navigateTo({
+								url: "./counter-info?params=" + encodeURIComponent(JSON.stringify(params)) + "&type=3"
+							})
+						} else {
+							this.$u.toast(res.msg)
+						}
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.counter {
+		.tabs-title {
+			padding: 24rpx 240rpx 0 24rpx;
+			font-size: 24rpx;
+			font-family: PingFangSC-Medium, PingFang SC;
+			font-weight: 500;
+			color: #333333;
+			background-color: #fff;
+		}
+
+		.jisuan-row {
+			height: 82rpx;
+			border-bottom: 2rpx solid #F6F6F6;
+			padding: 0 24rpx;
+			background-color: #fff;
+
+			.row-left {
+				width: 294rpx;
+				font-size: 24rpx;
+				font-weight: 400;
+				color: #999999;
+			}
+
+			.row-right {
+				.input {
+					font-size: 24rpx;
+					flex: 1;
+					margin-right: 10rpx;
+				}
+
+				.text {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #CCCCCC;
+
+				}
+			}
+		}
+
+		.down-btn {
+			position: fixed;
+			z-index: 10;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			bottom: 0;
+			left: 0;
+			padding: 0 24rpx 54rpx 24rpx;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.dataCenter-header {
+			padding: 0 70rpx;
+			height: 120rpx;
+			background-color: #fff;
+			position: sticky;
+			top: 0;
+			left: 0;
+			z-index: 10;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.header-item {
+				.active {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+
+				.active1 {
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+				}
+
+				image {
+					width: 50rpx;
+					height: 20rpx;
+					// margin-top: 10rpx;
+				}
+			}
+		}
+	}
+</style>

+ 734 - 0
pagesA/index/dataCenter.vue

@@ -0,0 +1,734 @@
+<template>
+	<view class="dataCenter">
+		<view class="dataCenter-header">
+			<view class="u-flex u-row-between" style="padding: 20rpx 0 4rpx 0;border-bottom: 2rpx solid #F5F5F5;height: 100rpx;">
+				<view class="header-item u-flex-col u-col-center" v-for="(item,index) in tabs" :key="index" @click="change(index)">
+					<text :class="current == index ? 'active1' : 'active'">{{item}}</text>
+					<image :style="{opacity:current == index ? 1 : 0}" src="../../static/images/dataCenter1-1.png" mode=""></image>
+				</view>
+			</view>
+			<view class="header-box u-flex u-row-between">
+				<view class="name u-flex" @click="showcity = !showcity" v-if="cityleft.length > 0">
+					<text>{{cityleft[cityleftindex].name}}</text>
+					<text>{{cityright[cityrightindex].name}}</text>
+				</view>
+				<view class="u-flex" v-show="current == 0">
+					<view class="time" v-if="defaulttime">
+						<biaofunDatetimePicker placeholder="" :end="defaulttime" fields="day" :defaultValue="defaulttime" @change="changeday"></biaofunDatetimePicker>
+					</view>
+					<u-icon name="arrow-down" color="#979797" size="28"></u-icon>
+				</view>
+				<view class="u-flex" v-show="current == 1">
+					<view class="time" v-if="defaulttime">
+						<biaofunDatetimePicker placeholder="" :end="defaulttime" fields="month" :defaultValue="defaulttime" @change="changemonth"></biaofunDatetimePicker>
+					</view>
+					<u-icon name="arrow-down" color="#979797" size="28"></u-icon>
+				</view>
+			</view>
+		</view>
+		<view v-if="current == 0 || current == 1">
+			<view class="data-item" v-for="(item,index) in list" :key="index">
+				<view class="item-left">
+					{{item.name}}每{{current == 0 ? '日' : '月'}}成交
+				</view>
+				<view class="item-center u-flex u-row-between">
+					<view class="item-item u-flex-col">
+						<view class="item-item1">
+							总成交量
+						</view>
+						<view class="item-item2 u-flex u-col-bottom">
+							<text>{{item.cover_all}}</text>
+							<text>套</text>
+						</view>
+						<view class="item-item3">
+							{{item.area_all}}㎡
+						</view>
+						<view class="item-item4 u-flex-col u-row-center">
+							<view class="u-flex" style="margin-bottom: 12rpx;">
+								<text class="item-text1">环比:</text>
+								<text class="item-text2">{{item.hb_all}}%</text>
+							</view>
+							<view class="u-flex">
+								<text class="item-text1">同比:</text>
+								<text class="item-text2">{{item.tb_all}}%</text>
+							</view>
+						</view>
+					</view>
+					<text class="xian"></text>
+					<view class="item-item u-flex-col">
+						<view class="item-item1">
+							其中住宅
+						</view>
+						<view class="item-item2 u-flex u-col-bottom">
+							<text>{{item.cover_residence}}</text>
+							<text>套</text>
+						</view>
+						<view class="item-item3">
+							{{item.area_residence}}㎡
+						</view>
+						<view class="item-item4 u-flex-col u-row-center">
+							<view class="u-flex" style="margin-bottom: 12rpx;">
+								<text class="item-text1">环比:</text>
+								<text class="item-text2">{{item.hb_residence}}%</text>
+							</view>
+							<view class="u-flex">
+								<text class="item-text1">同比:</text>
+								<text class="item-text2">{{item.tb_residence}}%</text>
+							</view>
+						</view>
+					</view>
+					<text class="xian"></text>
+					<view class="item-item u-flex-col">
+						<view class="item-item1">
+							其中非住宅
+						</view>
+						<view class="item-item2 u-flex u-col-bottom">
+							<text>{{item.cover_general}}</text>
+							<text>套</text>
+						</view>
+						<view class="item-item3">
+							{{item.area_general}}㎡
+						</view>
+						<view class="item-item4 u-flex-col u-row-center">
+							<view class="u-flex" style="margin-bottom: 12rpx;">
+								<text class="item-text1">环比:</text>
+								<text class="item-text2">{{item.hb_general}}%</text>
+							</view>
+							<view class="u-flex">
+								<text class="item-text1">同比:</text>
+								<text class="item-text2">{{item.tb_general}}%</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view v-if="current == 2">
+			<view class="tabs2-box u-flex">
+				<text :style="{color:tabs21 == 1 ? '#1F7EFF' : '#666666'}" @click="changetabs1(1)">近半年</text>
+				<text :style="{color:tabs21 == 2 ? '#1F7EFF' : '#666666'}" @click="changetabs1(2)">近一年</text>
+			</view>
+			<view class="" style="height: 378rpx;width: 100%;">
+				<echarts-box canvas-id="tabs21" ref="echarts" :option="option21"></echarts-box>
+			</view>
+			<scroll-view class="tabs21-type" scroll-x="true">
+				<text :class="tabs21type == -1 ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity1(-1)">全市</text>
+				<text v-for="(a,b) in qulist" :key="b" :class="tabs21type == b ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity1(b)">{{a.name}}</text>
+			</scroll-view>
+			<view class="tabs-tips" v-html="config.trend_remark_cover"></view>
+			<view class="tabs2-box u-flex">
+				<text :style="{color:tabs22 == 1 ? '#1F7EFF' : '#666666'}" @click="changetabs2(1)">近半年</text>
+				<text :style="{color:tabs22 == 2 ? '#1F7EFF' : '#666666'}" @click="changetabs2(2)">近一年</text>
+			</view>
+			<view class="" style="height: 378rpx;width: 100%;">
+				<echarts-box canvas-id="tabs22" ref="echarts" :option="option22"></echarts-box>
+			</view>
+			<scroll-view class="tabs21-type" scroll-x="true">
+				<text :class="tabs22type == -1 ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity2(-1)">全市</text>
+				<text v-for="(a,b) in qulist" :key="b" :class="tabs22type == b ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity2(b)">{{a.name}}</text>
+			</scroll-view>
+			<view class="tabs-tips" v-html="config.trend_remark_area"></view>
+		</view>
+		<view v-if="current == 3">
+			<view class="tabs2-box u-flex">
+				<text :style="{color:tabs31 == 1 ? '#1F7EFF' : '#666666'}" @click="changetabs3(1)">近半年</text>
+				<text :style="{color:tabs31 == 2 ? '#1F7EFF' : '#666666'}" @click="changetabs3(2)">近一年</text>
+			</view>
+			<view class="" style="height: 378rpx;width: 100%;">
+				<echarts-box canvas-id="tabs31" ref="echarts" :option="option31"></echarts-box>
+			</view>
+			<scroll-view class="tabs21-type" scroll-x="true">
+				<text :class="tabs31type == -1 ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity3(-1)">全市</text>
+				<text v-for="(a,b) in qulist" :key="b" :class="tabs31type == b ? 'tabs21-text tabs21-text1' : 'tabs21-text'" @click="changecity3(b)">{{a.name}}</text>
+			</scroll-view>
+			<view class="tabs-tips" v-html="config.trend_remark_price"></view>
+		</view>
+		<view class="changecity u-flex u-col-top" v-if="showcity" @click="showcity = false">
+			<view class="city-box u-flex-col" @click.stop>
+				<view class="scroll-box u-flex">
+					<scroll-view class="scroll-left" scroll-y="true">
+						<view :class="index == cityleftindex ? 'city-item city-item-active' : 'city-item'" v-for="(item,index) in cityleft" :key="index" @click="changecityleft(index)">
+							{{item.name}}
+						</view>
+					</scroll-view>
+					<scroll-view class="scroll-right" scroll-y="true">
+						<u-radio-group v-model="cityrightindex1">
+							<view class="right-item u-flex u-row-between" v-for="(item,index) in cityright" :key="index">
+								<text :class="index == cityrightindex1 ? 'text-active' : 'text'" @click="cityrightindex1 = index">{{item.name}}</text>
+								<u-radio :name="index"></u-radio>
+							</view>
+						</u-radio-group>
+					</scroll-view>
+				</view>
+				<view class="city-btn u-flex u-row-between">
+					<text @click="showcity = false">取消</text>
+					<text @click="tosearch">确定</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import echartsBox from "../components/echarts-uniapp/echarts-uniapp.vue"
+	import * as echarts from '../components/echarts-uniapp/echarts.min.js';
+	import biaofunDatetimePicker from "../../components/biaofun-datetime-picker/biaofun-datetime-picker.vue"
+	import getDataCenter from "../../common/echartDate.js"
+	import {
+		mapState
+	} from "vuex"
+	export default {
+		data() {
+			return {
+				config: {},
+
+				option21: {},
+				option22: {},
+				option31: {},
+
+				tabs: ['每日成交', '每月成交', '成交趋势', '价格趋势'],
+				current: 0,
+
+				showcity: false,
+				cityleft: [],
+				cityleftindex: 0,
+				cityright: [],
+				cityrightindex: 0,
+				cityrightindex1: 0,
+				daytime: '',
+				monthtime: '',
+				defaulttime: '',
+				list: [],
+				qulist: [],
+				tabs21: 1,
+				tabs22: 1,
+				tabs21type: -1,
+				tabs22type: -1,
+
+				tabs31: 1,
+				tabs31type: -1,
+				title: ''
+			}
+		},
+		onLoad(option) {
+			this.title = option.title
+			this.defaulttime = this.$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd hh:MM')
+			this.daytime = this.$u.timeFormat(new Date().getTime(), 'yyyy-mm-dd')
+			this.monthtime = this.$u.timeFormat(new Date().getTime(), 'yyyy-mm')
+			this.getsheng()
+			this.getconfig()
+		},
+		onShow() {
+			if (this.title) {
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		components: {
+			echartsBox,
+			biaofunDatetimePicker
+		},
+		computed: {
+			...mapState(['defaultcity'])
+		},
+		methods: {
+			changetabs3(index) {
+				this.tabs31 = index
+				this.getdata()
+			},
+			changecity3(index) {
+				this.tabs31type = index
+				this.getdata()
+			},
+			getconfig() {
+				this.$u.post('/api/Index/platform_config').then(res => {
+					this.config = res.data
+				})
+			},
+			changecity2(index) {
+				this.tabs22type = index
+				this.getchengjiao(2)
+			},
+			changecity1(index) {
+				this.tabs21type = index
+				this.getchengjiao(1)
+			},
+			tosearch() {
+				this.cityrightindex = this.cityrightindex1
+				this.showcity = false
+				this.tabs21 = 1
+				this.tabs22 = 1
+				this.tabs21type = -1
+				this.tabs22type = -1
+
+				this.tabs31 = 1
+				this.tabs31type = -1
+				this.getqu()
+				this.getdata()
+			},
+			changecityleft(index) {
+				this.cityleftindex = index
+				this.cityrightindex1 = 0
+				this.cityrightindex = 0
+				this.getshi()
+			},
+			getsheng() {
+				this.$u.post('/api/Data/area_list', {
+					level: 1
+				}).then(res => {
+					this.cityleft = res.data
+					this.cityleft.forEach((val, key) => {
+						if (val.id == this.defaultcity.province_id) {
+							this.cityleftindex = key
+						}
+					})
+					this.getshi()
+				})
+			},
+			getshi() {
+				this.$u.post('/api/Data/area_list', {
+					level: 2,
+					province_id: this.cityleft[this.cityleftindex].id
+				}).then(res => {
+					this.cityright = res.data
+					this.cityright.forEach((val, key) => {
+						if (val.id == this.defaultcity.city_id) {
+							this.cityrightindex1 = key
+							this.cityrightindex = key
+						}
+					})
+					this.getqu()
+					this.getdata()
+				})
+			},
+			getqu() {
+				this.$u.post('/api/Data/area_list', {
+					level: 3,
+					city_id: this.cityright[this.cityrightindex].id
+				}).then(res => {
+					this.qulist = res.data
+				})
+			},
+			changetabs1(index) {
+				this.tabs21 = index
+				this.getchengjiao(1)
+			},
+			changetabs2(index) {
+				this.tabs22 = index
+				this.getchengjiao(2)
+			},
+			getdata() {
+				if (this.current == 0 || this.current == 1) {
+					this.$u.post('/api/Data/turnover_info', {
+						type: this.current == 0 ? 1 : 2,
+						time: this.current == 0 ? this.daytime : this.monthtime,
+						city_id: this.cityright[this.cityrightindex].id,
+						default_time: 0
+					}).then(res => {
+						this.list = res.data
+					})
+				}
+				if (this.current == 2) {
+					this.getchengjiao(1)
+					this.getchengjiao(2)
+				}
+				if (this.current == 3) {
+					this.$u.post('/api/Data/trend_info_price', {
+						type: this.tabs31,
+						area_id: this.tabs31type == -1 ? this.cityright[this.cityrightindex].id : this.qulist[this.tabs31type].id,
+					}).then(res => {
+						var xAxis = []
+						var yAxis = []
+						res.data.forEach(val => {
+							xAxis.unshift(`${val.month}月`)
+							yAxis.unshift(val.price_all)
+						})
+						this.setechart(getDataCenter.getDataCenter(xAxis, yAxis, '价格'), 3)
+					})
+				}
+			},
+			getchengjiao(type) {
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				if (type == 1) {
+					this.$u.post('/api/Data/trend_info_cover', {
+						type: this.tabs21,
+						area_id: this.tabs21type == -1 ? this.cityright[this.cityrightindex].id : this.qulist[this.tabs21type].id,
+					}).then(res => {
+						var xAxis = []
+						var yAxis = []
+						res.data.forEach(val => {
+							xAxis.unshift(`${val.month}月`)
+							yAxis.unshift(val.cover_all)
+						})
+						uni.showLoading({
+							mask: true,
+							title: "请稍后"
+						})
+						this.setechart(getDataCenter.getDataCenter(xAxis, yAxis, '总套数'), 1)
+					})
+				} else {
+					this.$u.post('/api/Data/trend_info_area', {
+						type: this.tabs22,
+						area_id: this.tabs22type == -1 ? this.cityright[this.cityrightindex].id : this.qulist[this.tabs22type].id,
+					}).then(res => {
+						var xAxis = []
+						var yAxis = []
+						res.data.forEach(val => {
+							xAxis.unshift(`${val.month}月`)
+							yAxis.unshift(val.area_all)
+						})
+						uni.showLoading({
+							mask: true,
+							title: "请稍后"
+						})
+						this.setechart(getDataCenter.getDataCenter(xAxis, yAxis, '总面积'), 2)
+					})
+				}
+			},
+			changemonth(e) {
+				this.monthtime = e.f6
+				this.getdata()
+			},
+			changeday(e) {
+				this.daytime = e.f1
+				this.getdata()
+			},
+			setechart(data, type) {
+				// console.log(data);
+				// uni.showLoading({
+				// 	mask:true,
+				// 	title:"请稍后"
+				// })
+				setTimeout(() => {
+					uni.hideLoading()
+					if (type == 1) {
+						this.option21 = data
+					}
+					if (type == 2) {
+						this.option22 = data
+					}
+					if (type == 3) {
+						this.option31 = data
+					}
+				}, 200)
+				// this.option21 = data
+			},
+			change(index) {
+				this.showcity = false
+				this.current = index
+				this.option21 = {}
+				this.option22 = {}
+				this.option31 = {}
+				this.getdata()
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.dataCenter {
+		.changecity {
+			position: fixed;
+			z-index: 99;
+			width: 750rpx;
+			height: calc(100vh - 220rpx);
+			background-color: rgba(0, 0, 0, 0.4);
+			left: 0;
+			bottom: 0;
+
+			.city-box {
+				width: 750rpx;
+				height: 70vh;
+				background: #FFFFFF;
+
+				.scroll-box {
+					flex: 1;
+					min-height: 1rpx;
+					width: 750rpx;
+
+					.scroll-right {
+						flex: 1;
+						height: 100%;
+
+						.right-item {
+							height: 100rpx;
+							padding: 0 52rpx;
+
+							.text {
+								font-size: 28rpx;
+								font-family: PingFangSC-Regular, PingFang SC;
+								font-weight: 400;
+								color: #333333;
+							}
+
+							.text-active {
+								font-size: 28rpx;
+								font-family: PingFangSC-Regular, PingFang SC;
+								font-weight: 400;
+								color: #1F7EFF;
+							}
+						}
+					}
+
+					.scroll-left {
+						width: 258rpx;
+						height: 100%;
+						background: #F7F7F7;
+
+						.city-item {
+							width: 258rpx;
+							line-height: 100rpx;
+							// background: #FFFFFF;
+							text-align: center;
+							padding: 0 20rpx;
+							font-size: 28rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #333333;
+						}
+
+						.city-item-active {
+							background-color: rgba(255, 255, 255, 1);
+							color: rgba(31, 126, 255, 1);
+						}
+					}
+				}
+
+				.city-btn {
+					width: 750rpx;
+					height: 166rpx;
+					background: #FFFFFF;
+					padding: 0 48rpx;
+
+					text:first-child {
+						width: 200rpx;
+						line-height: 84rpx;
+						background: #CCCCCC;
+						border-radius: 20rpx;
+						text-align: center;
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FFFFFF;
+					}
+
+					text:last-child {
+						width: 414rpx;
+						line-height: 84rpx;
+						background: #1F7EFF;
+						border-radius: 20rpx;
+						text-align: center;
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FFFFFF;
+					}
+				}
+			}
+		}
+
+		.tabs-tips {
+			font-size: 18rpx;
+			font-family: PingFangSC-Regular, PingFang SC;
+			font-weight: 400;
+			color: #CCCCCC;
+			padding: 24rpx 30rpx 24rpx 30rpx;
+			border-bottom: 1rpx solid #F5F5F5;
+		}
+
+		.tabs21-type {
+			white-space: nowrap;
+			margin: 0 20rpx;
+
+			.tabs21-text {
+				font-size: 30rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #666666;
+				display: inline-block;
+				padding: 10rpx 14rpx;
+			}
+
+			.tabs21-text1 {
+				color: #1F7EFF;
+			}
+		}
+
+		.tabs2-box {
+			padding: 24rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			text {
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #666666;
+				margin-right: 36rpx;
+			}
+		}
+
+		.data-item {
+			width: 702rpx;
+			background: rgba(31, 126, 255, 0.1);
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding-bottom: 14rpx;
+
+			.item-center {
+				width: 662rpx;
+				height: 320rpx;
+				background: #FFFFFF;
+				border-radius: 20rpx;
+				margin: 16rpx auto;
+
+				.xian {
+					width: 2rpx;
+					height: 180rpx;
+					background: #F5F5F5;
+					border-radius: 20rpx;
+				}
+
+				.item-item {
+					flex: 1;
+					padding: 26rpx 20rpx 42rpx 20rpx;
+
+					.item-item1 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+					}
+
+					.item-item2 {
+						text:first-child {
+							font-size: 48rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #333333;
+						}
+
+						text:last-child {
+							font-size: 24rpx;
+							color: #999999;
+							margin-bottom: 10rpx;
+						}
+					}
+
+					.item-item3 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						margin-bottom: 20rpx;
+					}
+
+					.item-item4 {
+						// width: 168rpx;
+						height: 98rpx;
+						background: #F5F5F5;
+						border-radius: 8rpx;
+						padding: 0 10rpx;
+
+						.item-text1 {
+							font-size: 20rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #333333;
+						}
+
+						.item-text2 {
+							font-size: 20rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: #FF2600;
+						}
+					}
+				}
+			}
+
+			.item-left {
+				width: 242rpx;
+				line-height: 80rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx 0px 20rpx 0px;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+				margin-bottom: 8rpx;
+			}
+		}
+
+		.header-box {
+			width: 702rpx;
+			height: 80rpx;
+			background: #E8F2FF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx;
+
+			.name {
+				text:first-child {
+					font-size: 28rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+					margin-right: 20rpx;
+				}
+
+				text:last-child {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+			}
+
+			.time {
+				font-size: 28rpx;
+				font-family: PingFangSC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #333333;
+				margin-right: 10rpx;
+			}
+		}
+
+		.dataCenter-header {
+			padding: 0 24rpx 1rpx 24rpx;
+			// height: 120rpx;
+			background-color: #fff;
+			position: sticky;
+			top: 0;
+			left: 0;
+			z-index: 10;
+
+
+			.header-item {
+				.active {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+
+				.active1 {
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #333333;
+				}
+
+				image {
+					width: 50rpx;
+					height: 20rpx;
+					// margin-top: 10rpx;
+				}
+			}
+		}
+	}
+</style>

+ 113 - 0
pagesA/index/kefu.vue

@@ -0,0 +1,113 @@
+<template>
+	<view class="kefu-page">
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)" @close="toback">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser" @close="toback" type="2"></gf-chat>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				showlogin: false,
+				id:''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			if (uni.getStorageSync("token")) {
+				this.$nextTick(() => {
+					this.$refs.chatlist.open(this.id)
+				})
+			} else {
+				this.showlogin = true
+			}
+		},
+		methods: {
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			toback() {
+				uni.navigateBack()
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.kefu-page {
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					text-decoration: none;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+	}
+</style>

+ 169 - 0
pagesA/index/newHouses.vue

@@ -0,0 +1,169 @@
+<template>
+	<view class="newHouses">
+		<view class="newHouses-bg"></view>
+		<view class="renqi-box u-flex">
+			<u-icon name="heart-fill" color="#fff" size="26"></u-icon>
+			<text class="text">累计人气值 {{popularity}}</text>
+		</view>
+		<view class="swiper-box">
+			<u-swiper :list="swiperlisi" height="376" name="logo" @click="tobanner" border-radius="20"></u-swiper>
+		</view>
+		<view class="newHouses-list">
+			<view class="newHouses-title u-flex u-row-between">
+				<text>全部楼盘</text>
+				<view class="u-flex" @click="opensearch">
+					<image src="../../static/images/shaixuan.png" mode=""></image>
+					<text style="font-size: 26rpx;font-weight: 500;color: #1677FF;margin-left: 10rpx;">区域搜索</text>
+				</view>
+			</view>
+			<view class="u-flex u-row-between u-flex-wrap">
+				<view v-for="(item,index) in list" :key="index">
+					<gf-goods :data="item"></gf-goods>
+				</view>
+			</view>
+		</view>
+		<gf-search ref="search" @shaixuan="shaixuan"></gf-search>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState,
+		mapActions,
+		mapMutations,
+		mapGetters
+	} from 'vuex'
+	export default {
+		data() {
+			return {
+				swiperlisi: [],
+				page: 1,
+				list: [],
+				params: {},
+				title: ''
+			}
+		},
+		onLoad(option) {
+			this.title = option.title
+			this.getlist()
+			this.getbanner()
+		},
+		onShow() {
+			if(this.title){
+				uni.setNavigationBarTitle({
+					title: this.title
+				})
+			}
+		},
+		computed: {
+			...mapState(["popularity", 'defaultcity']),
+		},
+		onReachBottom() {
+			if (this.list.length % 20 == 0) {
+				this.page++
+				this.getlist()
+			}
+		},
+		methods: {
+			shaixuan(e) {
+				this.params = e
+				this.page = 1
+				this.list = []
+				this.getlist()
+			},
+			tobanner(e) {
+				if (this.swiperlisi[e].url) {
+					uni.navigateTo({
+						url: this.swiperlisi[e].url
+					})
+				}
+			},
+			getbanner() {
+				this.$u.post('/api/Index/banner', {
+					location: 2
+				}).then(res => {
+					this.swiperlisi = res.data
+				})
+			},
+			getlist() {
+				this.$u.post('/api/Index/property_list', {
+					page: this.page,
+					page_num: 20,
+					type: 2,
+					...this.params,
+					city_id: this.params.area_id ? '' : this.defaultcity.city_id
+				}).then(res => {
+					this.list = this.list.concat(res.data)
+				})
+			},
+			opensearch() {
+				this.$refs.search.show = true
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F6F6F6;
+	}
+
+	.newHouses {
+		position: relative;
+		z-index: 1;
+
+		.newHouses-list {
+			width: 702rpx;
+			background: linear-gradient(180deg, #FFFFFF 0%, #FFFFFF 38%, rgba(255, 255, 255, 0) 100%);
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 0 20rpx;
+
+			.newHouses-title {
+				padding: 20rpx 0;
+
+				text {
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #131415;
+				}
+
+				image {
+					width: 32rpx;
+					height: 32rpx;
+				}
+			}
+		}
+
+		.swiper-box {
+			padding: 0 24rpx;
+			margin-bottom: 20rpx;
+		}
+
+		.renqi-box {
+			width: 750rpx;
+			height: 56rpx;
+			background: rgba(256, 256, 256, 0.1);
+			padding: 0 24rpx;
+			margin-bottom: 24rpx;
+
+			.text {
+				font-size: 24rpx;
+				font-family: Helvetica;
+				color: #FFFFFF;
+				margin-left: 10rpx;
+			}
+		}
+
+		.newHouses-bg {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 750rpx;
+			height: 556rpx;
+			background: linear-gradient(180deg, #1E7DFF 0%, #F6F6F6 100%);
+			z-index: -1;
+		}
+	}
+</style>

+ 751 - 0
pagesA/index/rizhao.vue

@@ -0,0 +1,751 @@
+<template>
+	<view class="rizhao">
+		<u-navbar :title="title" back-icon-color="#fff" title-color="#fff" :background="{background:'rgba(0,0,0,0)'}" :border-bottom="false" :immersive="true"></u-navbar>
+		<view class="header-3d" id="objContaier" @click="to3D">
+			<image v-if="detail.sunlight_image" :src="detail.sunlight_image" class="bg-3d" mode="aspectFill"></image>
+			<image v-else src="../static/3d-bg.png" class="bg-3d" mode="aspectFill"></image>
+			<view class="btn-3d u-flex u-row-center">
+				<image src="../static/3d-btn.png" mode=""></image>
+			</view>
+		</view>
+		<view class="time-box u-flex u-flex-wrap u-row-center">
+			<view class="u-flex time-item u-row-center" v-for="(a,b) in timelist" :key="b">
+				<text :style="{background:a.color}"></text>
+				<text>{{a.name}}</text>
+			</view>
+		</view>
+		<view class="louceng-fangxiang u-flex u-row-between u-flex-wrap">
+			<text :class="{text:fangxiang == index}" v-for="(item,index) in fangxianglist" :key="index" @click="changefangxiang(index)">{{item.orientation}}</text>
+		</view>
+		<view class="louceng-jieqi">
+			<view class="jieqi-box u-flex u-row-between u-flex-wrap">
+				<text v-for="(a,b) in jieqilist" :class="b == jieqi ? 'text' : ''" :key="b" @click="changejieqi(b)">{{a.solar_terms}}</text>
+			</view>
+		</view>
+		<view class="rizhao-louhao u-flex u-flex-wrap">
+			<view class="u-flex u-col-center u-row-center louhao-active" :style="{borderColor:louhao == index ? '#1F7EFF' : '#999999'}" v-for="(item,index) in louhaoList" :key="index" @click="changelou(index)">
+				<text class="text1" :style="{color:louhao == index ? '#1F7EFF' : '#999999'}">{{item.build_num}}#</text>
+				<text class="text2" v-if="louhao == index">✓</text>
+			</view>
+		</view>
+		<scroll-view class="louceng-time-table" scroll-x="true" v-if="list.length > 0">
+			<view class="u-flex-col" :style="{width:getwidth() + 'rpx'}">
+				<view class="table-header">
+					{{louhaoList[louhao].build_num}}#{{fangxianglist[fangxiang] ? fangxianglist[fangxiang].orientation : ''}}{{jieqilist[jieqi] ? jieqilist[jieqi].solar_terms : ''}}
+				</view>
+				<view class="body-header u-flex">
+					<view class="header-title u-flex-col u-row-between">
+						<text class="text1">单元</text>
+						<text class="text2">楼层</text>
+						<image src="../../static/images/xiegang.png" mode=""></image>
+					</view>
+					<view class="danyuan-header" v-for="(a,b) in list[0].unit_info" :key="b">
+						<view class="danyuan-title">
+							第{{a.unit}}单元
+						</view>
+						<view class="u-flex">
+							<view class="house-title" v-for="(c,d) in a.house_info" :key="d">
+								{{a.house_info.length - d}}室
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="body-item" v-for="(item,index) in list" :key="index">
+					<view class="item-title">
+						<text>{{item.floor}}F</text>
+					</view>
+					<view class="danyuan-item" v-for="(a,b) in item.unit_info" :key="b">
+						<view class="house-item" v-for="(c,d) in a.house_info" :key="d" :style="{background:getcolor(c)}">
+							<view class="house-room u-flex">
+								<text>{{c.room_num}}</text>
+								<text>室</text>
+							</view>
+							<view class="house-allprice">
+								<text>{{c.sunlight_duration}}</text>
+								<text></text>
+							</view>
+							<view class="house-price">
+								<text></text>
+								<text>{{c.sunlight_time}}</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+		<view class="" style="padding: 24rpx;">
+			<view v-html="sunshine"></view>
+		</view>
+		<view class="u-flex-col" style="font-size: 28rpx;color: #9DA3AB;padding: 0 24rpx;">
+			<view class="u-flex" style="margin-bottom: 10rpx;" @click="showmianze2 = true">
+				<text style="margin-right: 10rpx;">免责声明</text>
+				<u-icon name="info-circle-fill"></u-icon>
+			</view>
+		</view>
+		<view class="" style="height:170rpx"></view>
+		<view class="rizhao-btn u-flex u-row-between">
+			<text @click="opentel">隐私电话</text>
+			<text @click="tochat">在线咨询</text>
+		</view>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">您是否进行呼叫?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="tocell">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<!-- <u-popup v-model="showmianze1" mode="bottom" height="900rpx">
+			<view class="" style="padding: 24rpx;">
+				<view v-html="sunshine"></view>
+			</view>
+		</u-popup> -->
+		<u-popup v-model="showmianze2" mode="bottom" height="900rpx">
+			<view class="" style="padding: 24rpx;">
+				<view v-html="disclaimer"></view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+		<gf-tel ref="tellist" @over="getuser"></gf-tel>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				showmianze2: false,
+				showtocall: false,
+				showlogin: false,
+				id: '',
+				louhaoList: [],
+				louhao: 0,
+				jieqilist: [],
+				jieqi: 0,
+				fangxianglist: [],
+				fangxiang: 0,
+				detail: {},
+				list: [],
+				timelist: [{
+					name: '8h=日照',
+					color: '#61C86A',
+					value: ['08:00']
+				}, {
+					name: '8h>日照>=6h',
+					color: '#9BD56D',
+					value: ['08:00', '06:00']
+				}, {
+					name: '6h>日照>=4h',
+					color: '#E7E2A6',
+					value: ['06:00', '04:00']
+				}, {
+					name: '4h>日照>=2h',
+					color: '#F4CE9E',
+					value: ['04:00', '02:00']
+				}, {
+					name: '2h>日照>=0h',
+					color: '#F5BBB1',
+					value: ['02:00', '00:00']
+				}],
+				sunshine: '',
+				disclaimer: '',
+				title: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+			this.getlist()
+			this.getconfig()
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		mounted() {
+
+		},
+		methods: {
+			to3D() {
+				if (this.detail.abbr_url) {
+					uni.navigateTo({
+						url: '/pagesA/index/webview?url=' + this.detail.abbr_url + "&id=" + this.id + "&type=1"
+					})
+				} else {
+					this.$u.toast("暂无数据")
+				}
+			},
+			opentel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			getconfig() {
+				this.$u.post('/api/Index/platform_config').then(res => {
+					const regex = new RegExp('<img', 'gi')
+					this.sunshine = res.data.sunshine.replace(regex, `<img style="max-width: 100%; height: auto"`)
+					this.disclaimer = res.data.disclaimer.replace(regex, `<img style="max-width: 100%; height: auto"`)
+				})
+			},
+			changejieqi(index) {
+				this.jieqi = index
+				this.getdetail()
+			},
+			changefangxiang(index) {
+				this.fangxiang = index
+				this.getdetail()
+			},
+			getcolor(item) {
+				for (let i = 0; i < this.timelist.length; i++) {
+					var sunlight_duration = item.sunlight_duration.length == 4 ? ('0' + item.sunlight_duration) : item.sunlight_duration
+					if (this.timelist[i].value[0] == sunlight_duration) {
+						return this.timelist[i].color
+					}
+					if (this.timelist[i].value[1]) {
+						if (this.timelist[i].value[0] > sunlight_duration && this.timelist[i].value[1] <= sunlight_duration) {
+							return this.timelist[i].color
+						}
+					}
+				}
+			},
+			getwidth() {
+				var width = 0
+				this.list.forEach((item, index) => {
+					if (index == 0) {
+						width = width + 104
+						item.unit_info.forEach(val => {
+							width = width + val.house_info.length * 160
+						})
+					}
+				})
+				return width
+			},
+			getlist() {
+				this.$u.get('/api/Property/sunshine_info', {
+					id: this.id
+				}).then(res => {
+					this.louhaoList = res.data.build_info
+					this.jieqilist = res.data.solar_terms_info
+					this.fangxianglist = res.data.orientation_info
+					this.getdetail()
+				})
+			},
+			getdetail() {
+				this.$u.get('/api/Property/sunshine_detail', {
+					id: this.id,
+					build_num: this.louhaoList[this.louhao] ? this.louhaoList[this.louhao].build_num : '',
+					orientation: this.fangxianglist[this.fangxiang] ? this.fangxianglist[this.fangxiang].orientation : '',
+					solar_terms: this.jieqilist[this.jieqi] ? this.jieqilist[this.jieqi].solar_terms : ''
+				}).then(res => {
+					this.list = res.data.sort((a, b) => b.floor - a.floor)
+					this.list.forEach(item => {
+						item.unit_info = item.unit_info.sort((a, b) => b.unit - a.unit)
+						item.unit_info.forEach(val => {
+							val.house_info = val.house_info.sort((a, b) => b.room_num - a.room_num)
+						})
+					})
+				})
+			},
+			getdata() {
+				this.$u.post('/api/Property/property_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+					this.title = res.data.name
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			tocell() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = false
+					if (this.worker_id == 0) {
+						this.$refs.tellist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 1
+						})
+						uni.makePhoneCall({
+							phoneNumber: this.worker_phone
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			changelou(index) {
+				this.louhao = index
+				this.getdetail()
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F5F5F5;
+	}
+
+	.rizhao {
+		.header-3d {
+			height: 648rpx;
+			width: 750rpx;
+			position: relative;
+
+			.bg-3d {
+				height: 648rpx;
+				width: 750rpx;
+			}
+
+			.btn-3d {
+				width: 128rpx;
+				height: 128rpx;
+				background: rgba(0, 0, 0, 0.5);
+				border: 4rpx solid rgba(255, 255, 255, 0.5);
+				border-radius: 100%;
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+
+				image {
+					width: 50rpx;
+					height: 70rpx;
+				}
+			}
+		}
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					text-decoration: none;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.rizhao-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 10;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+				text-decoration: none;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.louceng-time-table {
+			width: 702rpx;
+			margin: 20rpx auto;
+			background-color: #fff;
+
+			.body-header {
+				height: 124rpx;
+				white-space: nowrap;
+				border-bottom: 1rpx solid #CCCCCC;
+
+				.danyuan-header {
+
+					.danyuan-title {
+						height: 58rpx;
+						line-height: 58rpx;
+						text-align: center;
+						border-bottom: 1rpx solid #CCCCCC;
+						border-right: 1rpx solid #CCCCCC;
+					}
+
+					.house-title {
+						width: 160rpx;
+						height: 64rpx;
+						line-height: 64rpx;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+						text-align: center;
+						border-right: 1rpx solid #CCCCCC;
+					}
+				}
+
+				.header-title {
+					width: 104rpx;
+					height: 124rpx;
+					border-right: 1rpx solid #CCCCCC;
+					padding: 8rpx 12rpx;
+					position: relative;
+
+					image {
+						position: absolute;
+						top: 0;
+						left: 0;
+						width: 100%;
+						height: 100%;
+					}
+
+					text {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+					}
+
+					.text1 {
+						width: 100%;
+						text-align: right;
+					}
+
+					.text2 {
+						width: 100%;
+					}
+				}
+			}
+
+			.body-item {
+				// height: 160rpx;
+				display: inline-flex;
+				align-items: stretch;
+				white-space: nowrap;
+				border-bottom: 1rpx solid #CCCCCC;
+
+				.danyuan-item {
+					display: inline-flex;
+					align-items: stretch;
+					white-space: nowrap;
+					vertical-align: top;
+
+					.house-item {
+						display: inline-flex;
+						flex-direction: column;
+						justify-content: flex-start;
+						width: 160rpx;
+						padding-left: 16rpx;
+						border-right: 1rpx solid #CCCCCC;
+						min-height: 160rpx;
+
+						.house-mianji {
+							text:first-child {
+								font-size: 24rpx;
+								color: #333333;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-price {
+							text:first-child {
+								font-size: 24rpx;
+								color: #1F7EFF;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-allprice {
+							text:first-child {
+								font-size: 28rpx;
+								color: #333333;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-room {
+							padding-top: 10rpx;
+
+							text:first-child {
+								font-size: 24rpx;
+								color: #333333;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+					}
+				}
+
+				.item-title {
+					display: inline-flex;
+					align-items: center;
+					justify-content: center;
+					vertical-align: top;
+					width: 104rpx;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+					border-right: 1rpx solid #CCCCCC;
+					min-width: 1rpx;
+				}
+			}
+
+
+			.table-header {
+				width: 100%;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+				line-height: 110rpx;
+				border-bottom: 1rpx solid #CCCCCC;
+
+			}
+		}
+
+		.time-box {
+			width: 750rpx;
+			height: 138rpx;
+			background: #FFFFFF;
+			margin: 0 auto;
+			padding: 24rpx 24rpx 4rpx 24rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.time-item {
+				width: 33%;
+				margin-bottom: 20rpx;
+
+				text:first-child {
+					width: 32rpx;
+					height: 32rpx;
+					background: #61C86A;
+					border-radius: 8rpx;
+					margin-right: 20rpx;
+				}
+
+				text:last-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					// margin-right: 40rpx;
+				}
+			}
+		}
+
+		.louceng-jieqi {
+			background-color: #fff;
+			padding-bottom: 24rpx;
+
+			.jieqi-box {
+				width: 662rpx;
+				// height: 164rpx;
+				background: #F5F5F5;
+				border-radius: 20rpx;
+				margin: 0 auto;
+				padding: 24rpx 20rpx 4rpx 20rpx;
+
+				text {
+					margin-bottom: 20rpx;
+					width: 194rpx;
+					line-height: 48rpx;
+					background: #FFFFFF;
+					border-radius: 8rpx;
+					border: 2rpx solid #999999;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				.text {
+					color: #1F7EFF;
+					border-color: #1F7EFF;
+				}
+			}
+		}
+
+		.louceng-fangxiang {
+			padding: 24rpx 44rpx;
+			background-color: #FFFFFF;
+
+			text {
+				flex: 1;
+				min-width: 318rpx;
+				line-height: 84rpx;
+				background: #FFFFFF;
+				border-radius: 20rpx;
+				border: 2rpx solid #999999;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+			}
+
+			.text {
+				color: #1F7EFF;
+				border-color: #1F7EFF;
+			}
+		}
+
+		.rizhao-louhao {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			padding: 0 0 24rpx 0;
+			margin: 20rpx auto;
+
+			.louhao-active {
+				margin: 0 20rpx;
+				width: 92rpx;
+				height: 40rpx;
+				background: #FFFFFF;
+				border-radius: 8rpx;
+				border: 1rpx solid #999999;
+				position: relative;
+				margin-top: 24rpx;
+
+				.text1 {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				.text2 {
+					width: 20rpx;
+					line-height: 20rpx;
+					background: #1F7EFF;
+					border-radius: 8rpx 0px 8rpx 0px;
+					text-align: center;
+					position: absolute;
+					bottom: 0;
+					right: 0;
+					z-index: 1;
+					color: #fff;
+					font-size: 18rpx;
+				}
+			}
+		}
+	}
+</style>

+ 116 - 0
pagesA/index/webview.vue

@@ -0,0 +1,116 @@
+<template>
+	<view class="webview-page">
+		<web-view :src="url  + '/html/index.html?url=' + src" v-if="src"></web-view>
+		<cover-view class="cover-box">
+			<button class="share-btn" @click="tokefu">
+				<cover-image class="img-btn" src="../static/kefu.png" mode=""></cover-image>
+			</button>
+			<button class="share-btn" open-type="share">
+				<cover-image class="img-btn" src="../static/share.png" mode=""></cover-image>
+			</button>
+		</cover-view>
+	</view>
+</template>
+
+<script>
+	import url from "../../common/url.js"
+	export default {
+		data() {
+			return {
+				src: '',
+				url: url,
+				id: '',
+				type: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			// console.log(option)
+			this.src = encodeURIComponent(option.url)
+			this.id = option.id
+			this.type = option.type
+		},
+		onShow() {
+			this.getuser()
+		},
+		onShareAppMessage() {
+			if (this.type == 1) {
+				return {
+					path: '/pagesA/index/rizhao?id=' + this.id
+				}
+			} else {
+				return {
+					path: '/pagesA/index/yifang?id=' + this.id
+				}
+			}
+		},
+		methods: {
+			tokefu() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						uni.navigateTo({
+							url: "/pagesA/index/kefu?id=" + this.id
+						})
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					uni.navigateTo({
+						url: "/pagesA/index/kefu?id=" + this.id
+					})
+				}
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.webview-page {
+		height: 100vh;
+
+		.cover-box {
+			position: fixed;
+			top: 240px;
+			right: 10px;
+			background-color: rgba(0, 0, 0, 0);
+			z-index: 10;
+			padding: 1px 5px;
+			border-radius: 100px;
+		}
+
+		.share-btn {
+			margin: 0;
+			padding: 0;
+			background-color: rgba(0, 0, 0, 0);
+			border: none;
+			line-height: 1;
+			margin: 15px 0;
+			width: 30px;
+			height: 30px;
+
+			.img-btn {
+				width: 30px;
+				height: 30px;
+				opacity: 0;
+			}
+		}
+
+		.share-btn::after {
+			border: none;
+		}
+	}
+</style>

+ 482 - 0
pagesA/index/wenda-info.vue

@@ -0,0 +1,482 @@
+<template>
+	<view class="wenda-info">
+		<view class="fangchan-wenda">
+			<view class="wenda-box">
+				<view class="box-top u-flex u-row-between">
+					<text class="text1">问</text>
+					<image class="img" :src="pinglundetail.user_headimg" mode=""></image>
+					<text class="text2">{{pinglundetail.user_name || ''}}</text>
+					<!-- <text class="admin">管理员</text>
+					<text class="yewu">业务人员</text> -->
+					<text class="text3 u-flex-1">{{pinglundetail.create_time ? pinglundetail.create_time : ''}}</text>
+				</view>
+				<view class="tiwen-zhiding u-flex" v-if="is_allow == 1 && user_id == pinglundetail.u_id && pinglundetail.quiz_type == 2">
+					<text class="text">置顶</text>
+					<u-switch v-model="checked"></u-switch>
+				</view>
+				<view class="table-header u-flex u-row-center" v-if="pinglundetail.quiz_type == 2">
+					<input type="text" placeholder="请输入" class="u-flex-1" :value="JSON.parse(pinglundetail.content).title" :disabled="true">
+				</view>
+				<scroll-view v-if="pinglundetail.quiz_type == 2" scroll-y="true" scroll-x="true" class="wenda-table">
+					<view class="table-row" v-for="(a,b) in JSON.parse(pinglundetail.content).list" :key="b">
+						<view class="table-col u-line-1" v-for="(c,d) in a" :key="d" @click.stop="$u.toast(c.value)">{{c.value}}</view>
+					</view>
+				</scroll-view>
+				<view class="wenda-text" v-if="pinglundetail.quiz_type == 1">
+					{{pinglundetail.content || ''}}
+				</view>
+			</view>
+			<view class="wenda-box" v-for="(item,index) in pinglunlist" :key="index">
+				<view class="box-top u-flex u-row-between">
+					<text class="text1" style="background-color: #04B578;">答</text>
+					<image class="img" :src="item.user_headimg" mode=""></image>
+					<text class="text2">{{item.user_name}}</text>
+					<text class="admin" v-if="item.reply_type == 2">管理员</text>
+					<text class="yewu" v-if="item.reply_type == 3">业务人员</text>
+					<text class="text3 u-flex-1">{{item.create_time}}</text>
+				</view>
+				<view class="wenda-text">
+					{{item.content}}
+				</view>
+			</view>
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="houses-btn u-flex u-row-between">
+			<view class="btn-left u-flex u-row-center" @click="openhuifu">
+				<image src="../../static/images/huifu.png" mode=""></image>
+				<text>立即回复</text>
+			</view>
+			<view class="btn-right" @click="tochat">在线咨询</view>
+		</view>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showhuifu" mode="center" border-radius="20">
+			<view class="huifu-popup">
+				<view class="textarea">
+					<textarea placeholder="请输入回复内容" v-model="huifu"></textarea>
+				</view>
+				<view class="huifu-btn u-flex u-row-center" @click="tohuifu">
+					<image src="../../static/images/huifu.png" mode=""></image>
+					<text>回复</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				checked: false,
+				showlogin: false,
+				showhuifu: false,
+				id: '',
+				louid: '',
+				detail: {},
+				pinglundetail: {},
+				pinglunlist: [],
+				page: 1,
+				is_allow: 0,
+				user_id: '',
+				huifu: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.louid = option.louid
+			this.getlou()
+			this.getdata()
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		onReachBottom() {
+			if (this.pinglunlist.length % 10 == 0) {
+				this.page++
+				this.getdata()
+			}
+		},
+		methods: {
+			tohuifu() {
+				if (!this.huifu) {
+					this.$u.toast("请输入回复内容")
+					return
+				}
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Comment/reply_comment', {
+					comment_id: this.id,
+					content: this.huifu
+				}).then(res => {
+					this.$u.toast(res.msg)
+					if (res.code == 1) {
+						this.showhuifu = false
+						this.huifu = ''
+						setTimeout(() => {
+							this.page = 1
+							this.pinglunlist = []
+							this.getdata()
+						}, 800)
+					}
+				})
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.is_allow = res.data.is_allow
+					this.user_id = res.data.id
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			getdata() {
+				this.$u.post('/api/Comment/consult_reply_comment_list', {
+					id: this.id,
+					page: this.page
+				}).then(res => {
+					if (this.page == 1) {
+						this.pinglundetail = res.data.comment
+					}
+					this.pinglunlist = this.pinglunlist.concat(res.data.list)
+				})
+			},
+			openhuifu() {
+				if (uni.getStorageSync("token")) {
+					this.showhuifu = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getlou() {
+				this.$u.post('/api/Property/property_detail', {
+					id: this.louid
+				}).then(res => {
+					this.detail = res.data
+				})
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.louid)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.wenda-info {
+		.huifu-popup {
+			width: 650rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			padding: 24rpx;
+
+			.huifu-btn {
+				width: 602rpx;
+				height: 88rpx;
+				background: #04B578;
+				border-radius: 20rpx;
+
+				image {
+					width: 40rpx;
+					height: 40rpx;
+					margin-right: 20rpx;
+				}
+
+				text {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+
+			.textarea {
+				width: 602rpx;
+				height: 326rpx;
+				background: #FFFFFF;
+				border-radius: 20rpx;
+				border: 2rpx solid #CCCCCC;
+				padding: 20rpx;
+				margin-bottom: 24rpx;
+
+				textarea {
+					width: 100%;
+					height: 100%;
+				}
+			}
+
+		}
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.houses-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 1;
+
+			.btn-left {
+				width: 338rpx;
+				height: 84rpx;
+				background: #04B578;
+				border-radius: 20rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+
+				image {
+					width: 40rpx;
+					height: 40rpx;
+					margin-right: 20rpx;
+				}
+			}
+
+			.btn-right {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.fangchan-wenda {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 24rpx 24rpx 20rpx 24rpx;
+
+			.wenda-box {
+				padding: 0 20rpx;
+
+				.tiwen-zhiding {
+					margin-bottom: 20rpx;
+
+					.text {
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+						margin-right: 16rpx;
+					}
+				}
+
+				.table-header {
+					width: 620rpx;
+					height: 94rpx;
+					border: 2rpx solid #F0F0F0;
+				
+					input {
+						text-align: center;
+						color: red;
+					}
+				}
+
+				.wenda-table {
+					width: 620rpx;
+					max-height: 378rpx;
+					border-radius: 16rpx;
+					margin-bottom: 20rpx;
+
+					.table-row {
+						white-space: nowrap;
+						height: 94rpx;
+
+						.table-col {
+							width: 155rpx;
+							line-height: 94rpx;
+							height: 94rpx;
+							border-bottom: 2rpx solid #F0F0F0;
+							border-left: 2rpx solid #F0F0F0;
+							padding: 0 16rpx;
+							display: inline-block;
+							font-size: 24rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: rgba(102, 102, 102, 0.88);
+						}
+
+						.table-col:last-child {
+							border-right: 2rpx solid #F0F0F0;
+
+						}
+					}
+
+					.table-row:last-child {
+						.table-col {
+							border-bottom: 2rpx solid #F0F0F0;
+						}
+					}
+				}
+
+				.wenda-text {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					margin-bottom: 20rpx;
+				}
+
+				.box-top {
+					margin-bottom: 20rpx;
+
+					.yewu {
+						width: 118rpx;
+						line-height: 36rpx;
+						border-radius: 8rpx;
+						border: 2rpx solid #1677FF;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #1677FF;
+					}
+
+					.admin {
+						width: 118rpx;
+						line-height: 36rpx;
+						border-radius: 8rpx;
+						border: 2rpx solid #FF9F18;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FF9F18;
+					}
+
+					.text2 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+						margin-right: 20rpx;
+					}
+
+					.text3 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						text-align: right;
+					}
+
+					.img {
+						width: 36rpx;
+						height: 36rpx;
+						border-radius: 100rpx;
+						margin: 0 20rpx;
+					}
+
+					.text1 {
+						width: 36rpx;
+						line-height: 36rpx;
+						background: #1677FF;
+						border-radius: 8rpx;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Semibold, PingFang SC;
+						font-weight: 600;
+						color: #FFFFFF;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 757 - 0
pagesA/index/wenda-list.vue

@@ -0,0 +1,757 @@
+<template>
+	<view class="wenda-list">
+		<view class="fangchan-wenda" v-for="(item,index) in list" :key="index" @click="toinfo(item)">
+			<view class="wenda-box">
+				<view class="box-top u-flex u-row-between">
+					<text class="text1">问</text>
+					<image class="img" :src="item.user_headimg" mode=""></image>
+					<text class="text2">{{item.user_name}}</text>
+					<!-- <text class="admin">管理员</text>
+					<text class="yewu">业务人员</text> -->
+					<text class="text3 u-flex-1">{{item.create_time}}</text>
+				</view>
+				<view class="table-header u-flex u-row-center" v-if="item.quiz_type == 2">
+					<input type="text" placeholder="请输入" class="u-flex-1" :value="JSON.parse(item.content).title" :disabled="true">
+				</view>
+				<scroll-view v-if="item.quiz_type == 2" scroll-y="true" enable-flex scroll-x="true" class="wenda-table">
+					<view class="table-row" v-for="(a,b) in JSON.parse(item.content).list" :key="b">
+						<view class="table-col u-line-1" v-for="(c,d) in a" :key="d">{{c.value}}</view>
+					</view>
+				</scroll-view>
+				<view class="wenda-text" v-if="item.quiz_type == 1">
+					{{item.content}}
+				</view>
+			</view>
+			<view class="wenda-box" v-if="item.apply_info">
+				<view class="box-top u-flex u-row-between">
+					<text class="text1" style="background-color: #04B578;">答</text>
+					<image class="img" :src="item.apply_info.user_headimg" mode=""></image>
+					<text class="text2">{{item.apply_info.user_name}}</text>
+					<text class="admin" v-if="item.apply_info.reply_type == 2">管理员</text>
+					<text class="yewu" v-if="item.apply_info.reply_type == 3">业务人员</text>
+					<text class="text3 u-flex-1">{{item.apply_info.create_time}}</text>
+				</view>
+				<view class="wenda-text">
+					{{item.apply_info.content}}
+				</view>
+			</view>
+			<view class="wenda-more">
+				{{item.apply_num}}人参与回复
+			</view>
+		</view>
+		<view class="not-wenda u-flex-col u-col-center u-row-center" v-if="list.length == 0">
+			<image class="img" src="../../static/images/not-wenda.png" mode=""></image>
+			<text class="text1">当前楼房还没有问答?</text>
+			<text class="text2">请您提出的您的问题</text>
+		</view>
+		<view class="" style="height: 170rpx;"></view>
+		<view class="houses-btn u-flex u-row-between">
+			<view class="btn-left u-flex u-row-center" @click="opentiwen">
+				<image src="../../static/images/tiwen.png" mode=""></image>
+				<text>立即提问</text>
+			</view>
+			<view class="btn-right" @click="tochat">在线咨询</view>
+		</view>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showtiwen" mode="center" border-radius="20">
+			<view class="tiwen-popup">
+				<view class="tiwen-zhiding u-flex" v-if="quiz_type == 2 && is_allow == 1">
+					<text class="text">置顶</text>
+					<u-switch v-model="checked"></u-switch>
+				</view>
+				<view class="table-header u-flex u-row-center" v-if="quiz_type == 2">
+					<input type="text" placeholder="请输入" class="u-flex-1" v-model="tabletitle">
+				</view>
+				<scroll-view v-if="quiz_type == 2" scroll-x="true" scroll-y="true" :enhanced="false" class="wenda-table1">
+					<view class="table-row" v-for="(a,b) in table" :key="b">
+						<input type="text" placeholder="请输入" class="table-col" v-for="(c,d) in a" :key="d" v-model="c.value">
+					</view>
+				</scroll-view>
+				<view v-if="quiz_type == 1" class="textarea">
+					<textarea placeholder="请输入提问内容" v-model="content"></textarea>
+				</view>
+				<view class="tiwen-btn u-flex u-row-between">
+					<view v-if="is_allow == 1" class="u-flex u-row-center tiwen-btn-item u-flex-1" style="background: #1677FF;" @click="showtable = true">
+						<image src="../../static/images/table.png" mode=""></image>
+						<text>添加表格</text>
+					</view>
+					<view class="u-flex u-row-center tiwen-btn-item u-flex-1" style="background: #FFA120;" @click="totiwen">
+						<image src="../../static/images/tiwen.png" mode=""></image>
+						<text>提问</text>
+					</view>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showtable" mode="center" border-radius="20">
+			<view class="table-popup">
+				<view class="table-header">
+					表格属性
+				</view>
+				<view class="table-row-col u-flex u-row-between">
+					<view class="row-col-item u-flex-col">
+						<text>行数</text>
+						<input type="number" placeholder="请输入" v-model="row">
+					</view>
+					<view class="row-col-item u-flex-col">
+						<text>列数</text>
+						<input type="number" placeholder="请输入" v-model="col">
+					</view>
+				</view>
+				<!-- <view class="table-title u-flex-col">
+					<text>标题</text>
+					<input type="text" placeholder="请输入">
+				</view>
+				<view class="table-title u-flex-col">
+					<text>摘要</text>
+					<input type="text" placeholder="请输入">
+				</view> -->
+				<view class="add-table-btn u-flex u-row-between">
+					<text @click="showtable = false">取消</text>
+					<text @click="createtable">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				showtiwen: false,
+				showlogin: false,
+				showtable: false,
+				checked: false,
+				page: 1,
+				list: [],
+				detail: {},
+				quiz_type: 1,
+				content: '',
+				table: [],
+				tabletitle: '',
+				is_allow: 0,
+				row: '',
+				col: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getlist()
+			this.getlou()
+		},
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		methods: {
+			totiwen() {
+				if (this.quiz_type == 1) {
+					if (!this.content) {
+						this.$u.toast("请输入问答内容")
+						return
+					}
+				} else {
+					if (!this.tabletitle) {
+						this.$u.toast("请输入表格标题")
+						return
+					}
+					for (let i = 0; i < this.table.length; i++) {
+						for (let j = 0; j < this.table[i].length; j++) {
+							if (!this.table[i][j].value) {
+								this.$u.toast("请完善表格")
+								return
+							}
+						}
+					}
+				}
+				uni.showLoading({
+					mask: true,
+					title: "请稍后"
+				})
+				this.$u.post('/api/Comment/submit_comment', {
+					id: this.id,
+					type: this.quiz_type,
+					is_top: this.value ? 1 : 0,
+					content: this.quiz_type == 1 ? this.content : JSON.stringify({ list: this.table, title: this.tabletitle })
+				}).then(res => {
+					this.$u.toast(res.msg)
+					if (res.code == 1) {
+						this.row = ''
+						this.col = ''
+						this.content = ''
+						this.table = []
+						this.tabletitle = ''
+						this.showtiwen = false
+						setTimeout(() => {
+							this.page = 1
+							this.list = []
+							this.getlist()
+						}, 800)
+					}
+				})
+			},
+			createtable() {
+				if (!this.row || this.row == 0) {
+					this.$u.toast("请输入行数")
+					return
+				}
+				if (!this.col || this.col == 0) {
+					this.$u.toast("请输入列数")
+					return
+				}
+				this.quiz_type = 2
+				this.showtable = false
+				this.table = []
+				for (let i = 0; i < this.row; i++) {
+					var arr = []
+					for (let j = 0; j < this.col; j++) {
+						arr.push({
+							value: ''
+						})
+					}
+					this.table.push(arr)
+				}
+			},
+			opentiwen() {
+				if (uni.getStorageSync("token")) {
+					this.quiz_type = 1
+					this.showtiwen = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.is_allow = res.data.is_allow
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			getlist() {
+				this.$u.post('/api/Comment/consult_comment_list', {
+					id: this.id,
+					page: this.page
+				}).then(res => {
+					if (res.code == 1) {
+						this.list = this.list.concat(res.data)
+					}
+				})
+			},
+			getlou() {
+				this.$u.post('/api/Property/property_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+				})
+			},
+			toinfo(item) {
+				uni.navigateTo({
+					url: "/pagesA/index/wenda-info?id=" + item.id + "&louid=" + this.id
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F5F5F5;
+	}
+
+	.wenda-list {
+		.not-wenda {
+			height: 80vh;
+
+			.img {
+				width: 178rpx;
+				height: 178rpx;
+				margin-bottom: 20rpx;
+			}
+
+			.text1 {
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #CCCCCC;
+				margin-bottom: 10rpx;
+			}
+
+			.text2 {
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #CCCCCC;
+			}
+		}
+
+		.table-popup {
+			width: 650rpx;
+
+			.add-table-btn {
+				padding: 40rpx 24rpx;
+
+				text:first-child {
+					width: 284rpx;
+					line-height: 88rpx;
+					background: #CCCCCC;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 284rpx;
+					line-height: 88rpx;
+					background: #1677FF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #FFFFFF;
+				}
+			}
+
+			.table-title {
+				margin-bottom: 20rpx;
+				padding: 0 24rpx;
+
+				text {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					margin-bottom: 20rpx;
+				}
+
+				input {
+					width: 100%;
+					height: 88rpx;
+					background: #FFFFFF;
+					border-radius: 20rpx;
+					border: 2rpx solid #E5E5E5;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+			}
+
+			.table-row-col {
+				padding: 0 24rpx;
+				margin-bottom: 20rpx;
+
+				.row-col-item {
+					text {
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+						margin-bottom: 20rpx;
+					}
+
+					input {
+						width: 284rpx;
+						height: 88rpx;
+						background: #FFFFFF;
+						border-radius: 20rpx;
+						border: 2rpx solid #E5E5E5;
+						padding: 0 24rpx;
+						box-sizing: border-box;
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+					}
+				}
+			}
+
+			.table-header {
+				margin-bottom: 40rpx;
+				line-height: 88rpx;
+				border-bottom: 2rpx solid #E5E5E5;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+				padding: 0 24rpx;
+			}
+		}
+
+		.tiwen-popup {
+			width: 650rpx;
+			padding: 24rpx;
+
+			.tiwen-zhiding {
+				margin-bottom: 20rpx;
+
+				.text {
+					font-size: 28rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					margin-right: 16rpx;
+				}
+			}
+
+			.table-header {
+				width: 600rpx;
+				height: 94rpx;
+				border: 2rpx solid #F0F0F0;
+
+				input {
+					text-align: center;
+					color: red;
+				}
+			}
+
+			.wenda-table1 {
+				width: 600rpx;
+				max-height: 378rpx;
+				border-radius: 16rpx;
+				margin-bottom: 20rpx;
+
+				.table-row {
+					white-space: nowrap;
+					height: 94rpx;
+
+					.table-col {
+						width: 150rpx;
+						height: 94rpx;
+						border-bottom: 2rpx solid #F0F0F0;
+						border-left: 2rpx solid #F0F0F0;
+						padding: 0 16rpx;
+						display: inline-block;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: rgba(102, 102, 102, 0.88);
+						box-sizing: border-box;
+					}
+
+					.table-col:last-child {
+						border-right: 2rpx solid #F0F0F0;
+
+					}
+				}
+
+				.table-row:last-child {
+					.table-col {
+						// border-bottom: 2rpx solid #F0F0F0;
+					}
+				}
+			}
+
+			.tiwen-btn {
+				.tiwen-btn-item {
+
+					height: 88rpx;
+					border-radius: 20rpx;
+					margin: 0 10rpx;
+
+					image {
+						width: 40rpx;
+						height: 40rpx;
+						margin-right: 20rpx;
+					}
+
+					text {
+						font-size: 28rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FFFFFF;
+					}
+				}
+			}
+
+			.textarea {
+				height: 326rpx;
+				background: #FFFFFF;
+				border-radius: 20rpx;
+				border: 2rpx solid #CCCCCC;
+				padding: 20rpx;
+				margin-bottom: 24rpx;
+
+				textarea {
+					width: 100%;
+					height: 100%;
+				}
+			}
+		}
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.houses-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+			z-index: 1;
+
+			.btn-left {
+				width: 338rpx;
+				height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+
+				image {
+					width: 40rpx;
+					height: 40rpx;
+					margin-right: 20rpx;
+				}
+			}
+
+			.btn-right {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.fangchan-wenda {
+			width: 702rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 24rpx 24rpx 20rpx 24rpx;
+
+			.wenda-more {
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #666666;
+				padding: 0 20rpx;
+			}
+
+			.wenda-box {
+				padding: 0 20rpx;
+
+				.table-header {
+					width: 620rpx;
+					height: 94rpx;
+					border: 2rpx solid #F0F0F0;
+
+					input {
+						text-align: center;
+						color: red;
+					}
+				}
+
+				.wenda-table {
+					width: 620rpx;
+					max-height: 378rpx;
+					border-radius: 16rpx;
+					margin-bottom: 20rpx;
+
+					.table-row {
+						white-space: nowrap;
+						height: 94rpx;
+
+						.table-col {
+							width: 155rpx;
+							line-height: 94rpx;
+							height: 94rpx;
+							border-bottom: 2rpx solid #F0F0F0;
+							border-left: 2rpx solid #F0F0F0;
+							padding: 0 16rpx;
+							display: inline-block;
+							font-size: 24rpx;
+							font-family: PingFangSC-Regular, PingFang SC;
+							font-weight: 400;
+							color: rgba(102, 102, 102, 0.88);
+						}
+
+						.table-col:last-child {
+							border-right: 2rpx solid #F0F0F0;
+
+						}
+					}
+
+					.table-row:last-child {
+						.table-col {
+							// border-bottom: 2rpx solid #F0F0F0;
+						}
+					}
+				}
+
+				.wenda-text {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+					margin-bottom: 20rpx;
+				}
+
+				.box-top {
+					margin-bottom: 20rpx;
+
+					.yewu {
+						width: 118rpx;
+						line-height: 36rpx;
+						border-radius: 8rpx;
+						border: 2rpx solid #1677FF;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #1677FF;
+					}
+
+					.admin {
+						width: 118rpx;
+						line-height: 36rpx;
+						border-radius: 8rpx;
+						border: 2rpx solid #FF9F18;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #FF9F18;
+					}
+
+					.text2 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #666666;
+						margin-right: 20rpx;
+					}
+
+					.text3 {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #999999;
+						text-align: right;
+					}
+
+					.img {
+						width: 36rpx;
+						height: 36rpx;
+						border-radius: 100rpx;
+						margin: 0 20rpx;
+					}
+
+					.text1 {
+						width: 36rpx;
+						line-height: 36rpx;
+						background: #1677FF;
+						border-radius: 8rpx;
+						text-align: center;
+						font-size: 24rpx;
+						font-family: PingFangSC-Semibold, PingFang SC;
+						font-weight: 600;
+						color: #FFFFFF;
+					}
+				}
+			}
+		}
+	}
+</style>

+ 659 - 0
pagesA/index/yifang.vue

@@ -0,0 +1,659 @@
+<template>
+	<view class="rizhao">
+		<u-navbar :title="title" back-icon-color="#fff" title-color="#fff" :background="{background:'rgba(0,0,0,0)'}" :border-bottom="false" :immersive="true"></u-navbar>
+		<view class="header-3d" id="objContaier" @click="to3D">
+			<image v-if="detail.sunlight_image" :src="detail.sunlight_image" class="bg-3d" mode="aspectFill"></image>
+			<image v-else src="../static/3d-bg.png" class="bg-3d" mode="aspectFill"></image>
+			<view class="btn-3d u-flex u-row-center">
+				<image src="../static/3d-btn.png" mode=""></image>
+			</view>
+		</view>
+		<view class="rizhao-louhao u-flex u-flex-wrap">
+			<view class="u-flex u-col-center u-row-center louhao-active" :style="{borderColor:louhao == index ? '#1F7EFF' : '#999999'}" v-for="(item,index) in louhaoList" :key="index" @click="changelou(index)">
+				<text class="text1" :style="{color:louhao == index ? '#1F7EFF' : '#999999'}">{{item.build_num}}#</text>
+				<text class="text2" v-if="louhao == index">✓</text>
+			</view>
+		</view>
+		<scroll-view class="louceng-time-table" scroll-x="true" v-if="list.length > 0">
+			<view class="u-flex-col" :style="{width:getwidth() + 'rpx'}">
+				<view class="table-header">
+					{{louhaoList[louhao].build_num}}#
+				</view>
+				<view class="body-header u-flex">
+					<view class="header-title u-flex-col u-row-between">
+						<text class="text1">单元</text>
+						<text class="text2">楼层</text>
+						<image src="../../static/images/xiegang.png" mode=""></image>
+					</view>
+					<view class="danyuan-header" v-for="(a,b) in list[0].unit_info" :key="b">
+						<view class="danyuan-title">
+							第{{a.unit}}单元
+						</view>
+						<view class="u-flex">
+							<view class="house-title" v-for="(c,d) in a.house_info" :key="d">
+								{{a.house_info.length - d}}室
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="body-item" v-for="(item,index) in list" :key="index">
+					<view class="item-title">{{item.floor}}F</view>
+					<view class="danyuan-item" v-for="(a,b) in item.unit_info" :key="b">
+						<view class="house-item" style="background-color: #dafddc;" v-for="(c,d) in a.house_info" :key="d">
+							<view class="house-room u-flex">
+								<text>{{c.room_num}}</text>
+								<text>室</text>
+							</view>
+							<view class="house-allprice">
+								<text>{{(c.record_total_price/10000).toFixed(2)}}</text>
+								<text>万元</text>
+							</view>
+							<view class="house-price">
+								<text>{{c.record_unit_price}}</text>
+								<text>元/㎡</text>
+							</view>
+							<view class="house-mianji">
+								<text>{{c.covered_area}}</text>
+								<text>㎡</text>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</scroll-view>
+		<!-- <view class="" v-html="disclaimer"></view> -->
+		<view class="" style="height: 170rpx;"></view>
+		<view class="rizhao-btn u-flex u-row-between">
+			<text @click="opentel">隐私电话</text>
+			<text @click="tochat">在线咨询</text>
+		</view>
+		<u-popup v-model="showtocall" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">您是否进行呼叫?</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showtocall = false">取消</text>
+					<text @click="tocell">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<u-popup v-model="showlogin" mode="center" background="rgba(0,0,0,0)">
+			<view class="tocall-box u-flex-col u-col-center">
+				<image class="tocall-img" src="../../static/images/popup1-1.png" mode=""></image>
+				<view class="u-flex-col u-col-center tocall-text">你目前处于未登录状态请前往登录</view>
+				<view class="u-flex u-row-between tocall-btn">
+					<text @click="showlogin = false">取消</text>
+					<text @click="tologin">确定</text>
+				</view>
+			</view>
+		</u-popup>
+		<gf-chat ref="chatlist" @over="getuser"></gf-chat>
+		<gf-tel ref="tellist" @over="getuser"></gf-tel>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				showtocall: false,
+
+				id: '',
+				louhaoList: [],
+				louhao: 0,
+				list: [],
+				detail: {},
+				showlogin: false,
+				disclaimer: '',
+				title: '',
+				worker_id: 0,
+				worker_phone: '',
+				worker_hx_username: ''
+			}
+		},
+		onLoad(option) {
+			this.id = option.id
+			this.getdata()
+			this.getconfig()
+		},
+
+		onShow() {
+			if (uni.getStorageSync("token")) {
+				this.getuser()
+			}
+		},
+		methods: {
+			to3D() {
+				if (this.detail.abbr_url) {
+					uni.navigateTo({
+						url: '/pagesA/index/webview?url=' + this.detail.abbr_url + "&id=" + this.id + "&type=2"
+					})
+				} else {
+					this.$u.toast("暂无数据")
+				}
+			},
+			getuser() {
+				this.$u.post('/api/Member/member_info').then(res => {
+					this.worker_id = res.data.worker_id
+					this.worker_phone = res.data.worker_phone
+					this.worker_hx_username = res.data.worker_hx_username
+				})
+			},
+			opentel() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = true
+				} else {
+					this.showlogin = true
+				}
+			},
+			getconfig() {
+				this.$u.post('/api/Index/platform_config').then(res => {
+					const regex = new RegExp('<img', 'gi')
+					this.disclaimer = res.data.disclaimer.replace(regex, `<img style="max-width: 100%; height: auto"`)
+				})
+			},
+			getwidth() {
+				var width = 0
+				this.list.forEach((item, index) => {
+					if (index == 0) {
+						width = width + 104
+						item.unit_info.forEach(val => {
+							width = width + val.house_info.length * 160
+						})
+					}
+				})
+				return width
+			},
+			getlist() {
+				this.$u.post('/api/Property/house_detail', {
+					id: this.id,
+					build_num: this.louhaoList[this.louhao].build_num
+				}).then(res => {
+					this.list = res.data.sort((a, b) => b.floor - a.floor)
+					this.list.forEach(item => {
+						item.unit_info = item.unit_info.sort((a, b) => b.unit - a.unit)
+						item.unit_info.forEach(val => {
+							val.house_info = val.house_info.sort((a, b) => b.room_num - a.room_num)
+						})
+					})
+				})
+			},
+			getdata() {
+				this.$u.post('/api/Property/property_detail', {
+					id: this.id
+				}).then(res => {
+					this.detail = res.data
+					this.title = res.data.name
+				})
+				this.$u.post('/api/Property/build_info', {
+					id: this.id
+				}).then(res => {
+					this.louhaoList = res.data
+					if (this.louhaoList.length > 0) {
+						this.getlist()
+					}
+				})
+			},
+			tologin() {
+				this.showlogin = false
+				uni.navigateTo({
+					url: "/pages/mine/login"
+				})
+			},
+			tochat() {
+				if (uni.getStorageSync("token")) {
+					if (this.worker_id == 0) {
+						this.$refs.chatlist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 2
+						})
+						uni.navigateTo({
+							url: "/pages/index/chat?hx_username=" + this.worker_hx_username + "&worker_id=" + this.worker_id
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			tocell() {
+				if (uni.getStorageSync("token")) {
+					this.showtocall = false
+					if (this.worker_id == 0) {
+						this.$refs.tellist.open(this.id)
+					} else {
+						this.$u.post('/api/Member/consult_record', {
+							type: 1
+						})
+						uni.makePhoneCall({
+							phoneNumber: this.worker_phone
+						})
+					}
+				} else {
+					this.showlogin = true
+				}
+			},
+			changelou(index) {
+				this.louhao = index
+				this.getlist()
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #F5F5F5;
+	}
+
+	.rizhao {
+		.header-3d {
+			height: 648rpx;
+			width: 750rpx;
+			position: relative;
+
+			.bg-3d {
+				height: 648rpx;
+				width: 750rpx;
+			}
+
+			.btn-3d {
+				width: 128rpx;
+				height: 128rpx;
+				background: rgba(0, 0, 0, 0.5);
+				border: 4rpx solid rgba(255, 255, 255, 0.5);
+				border-radius: 100%;
+				position: absolute;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+
+				image {
+					width: 50rpx;
+					height: 70rpx;
+				}
+			}
+		}
+
+		.tocall-box {
+			position: relative;
+
+			.tocall-img {
+				width: 650rpx;
+				height: 476rpx;
+			}
+
+			.tocall-btn {
+				position: absolute;
+				bottom: 70rpx;
+				left: 0;
+				width: 100%;
+				padding: 0 48rpx;
+
+				text:first-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #FFA120;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+				}
+
+				text:last-child {
+					width: 254rpx;
+					line-height: 80rpx;
+					background: #1F7EFF;
+					border-radius: 20rpx;
+					text-align: center;
+					font-size: 34rpx;
+					font-family: PingFangSC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #FFFFFF;
+					text-decoration: none;
+				}
+			}
+
+			.tocall-text {
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+				position: absolute;
+				top: 244rpx;
+				left: 0;
+				z-index: 10;
+				width: 100%;
+			}
+		}
+
+		.rizhao-btn {
+			position: fixed;
+			bottom: 0;
+			left: 0;
+			z-index: 10;
+			width: 750rpx;
+			height: 166rpx;
+			background: #FFFFFF;
+			padding: 0 24rpx 54rpx 24rpx;
+
+			text:first-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #FFA120;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+				text-decoration: none;
+			}
+
+			text:last-child {
+				width: 338rpx;
+				line-height: 84rpx;
+				background: #1F7EFF;
+				border-radius: 20rpx;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #FFFFFF;
+			}
+		}
+
+		.louceng-time-table {
+			width: 702rpx;
+			margin: 20rpx auto;
+			background-color: #fff;
+
+			.body-header {
+				height: 124rpx;
+				white-space: nowrap;
+				border-bottom: 1rpx solid #CCCCCC;
+
+				.danyuan-header {
+
+					.danyuan-title {
+						height: 58rpx;
+						line-height: 58rpx;
+						text-align: center;
+						border-bottom: 1rpx solid #CCCCCC;
+						border-right: 1rpx solid #CCCCCC;
+					}
+
+					.house-title {
+						width: 160rpx;
+						height: 64rpx;
+						line-height: 64rpx;
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+						text-align: center;
+						border-right: 1rpx solid #CCCCCC;
+					}
+				}
+
+				.header-title {
+					width: 104rpx;
+					height: 124rpx;
+					border-right: 1rpx solid #CCCCCC;
+					padding: 8rpx 12rpx;
+					position: relative;
+
+					image {
+						position: absolute;
+						top: 0;
+						left: 0;
+						width: 100%;
+						height: 100%;
+					}
+
+					text {
+						font-size: 24rpx;
+						font-family: PingFangSC-Regular, PingFang SC;
+						font-weight: 400;
+						color: #333333;
+					}
+
+					.text1 {
+						width: 100%;
+						text-align: right;
+					}
+
+					.text2 {
+						width: 100%;
+					}
+				}
+			}
+
+			.body-item {
+				white-space: nowrap;
+				border-bottom: 1rpx solid #CCCCCC;
+				display: inline-flex;
+				align-items: stretch;
+
+				.danyuan-item {
+					display: inline-flex;
+					align-items: stretch;
+					white-space: nowrap;
+
+					.house-item {
+						display: inline-flex;
+						flex-direction: column;
+						justify-content: center;
+						width: 160rpx;
+						padding-left: 16rpx;
+						border-right: 1rpx solid #CCCCCC;
+						min-height: 160rpx;
+
+						.house-mianji {
+							text:first-child {
+								font-size: 24rpx;
+								color: #333333;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-price {
+							text:first-child {
+								font-size: 24rpx;
+								color: #1F7EFF;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-allprice {
+							text:first-child {
+								font-size: 28rpx;
+								color: #FFA120;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+
+						.house-room {
+							text:first-child {
+								font-size: 24rpx;
+								color: #333333;
+							}
+
+							text:last-child {
+								font-size: 18rpx;
+								color: #999999;
+							}
+						}
+					}
+				}
+
+				.item-title {
+					vertical-align: top;
+					width: 104rpx;
+					text-align: center;
+					line-height: 160rpx;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #333333;
+					border-right: 1rpx solid #CCCCCC;
+					display: inline-block;
+					min-width: 1rpx;
+				}
+			}
+
+
+			.table-header {
+				width: 100%;
+				text-align: center;
+				font-size: 24rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #333333;
+				line-height: 110rpx;
+				border-bottom: 1rpx solid #CCCCCC;
+
+			}
+		}
+
+		.time-box {
+			width: 702rpx;
+			height: 138rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			margin: 20rpx auto;
+			padding: 24rpx 20rpx 4rpx 20rpx;
+
+			.time-item {
+				margin-bottom: 20rpx;
+
+				text:first-child {
+					width: 32rpx;
+					height: 32rpx;
+					background: #61C86A;
+					border-radius: 8rpx;
+					margin-right: 20rpx;
+				}
+
+				text:last-child {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+					margin-right: 40rpx;
+				}
+			}
+		}
+
+		.louceng-jieqi {
+			background-color: #fff;
+			padding-bottom: 24rpx;
+
+			.jieqi-box {
+				width: 662rpx;
+				height: 164rpx;
+				background: #F5F5F5;
+				border-radius: 20rpx;
+				margin: 0 auto;
+				padding: 24rpx 20rpx 4rpx 20rpx;
+
+				text {
+					margin-bottom: 20rpx;
+					width: 194rpx;
+					line-height: 48rpx;
+					background: #FFFFFF;
+					border-radius: 8rpx;
+					border: 2rpx solid #999999;
+					text-align: center;
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				.text {
+					color: #1F7EFF;
+					border-color: #1F7EFF;
+				}
+			}
+		}
+
+		.louceng-fangxiang {
+			padding: 24rpx 44rpx;
+			background-color: #FFFFFF;
+
+			text {
+				width: 318rpx;
+				line-height: 84rpx;
+				background: #FFFFFF;
+				border-radius: 20rpx;
+				border: 2rpx solid #999999;
+				text-align: center;
+				font-size: 28rpx;
+				font-family: PingFangSC-Regular, PingFang SC;
+				font-weight: 400;
+				color: #999999;
+			}
+
+			.text {
+				color: #1F7EFF;
+				border-color: #1F7EFF;
+			}
+		}
+
+		.rizhao-louhao {
+			width: 750rpx;
+			background: #FFFFFF;
+			border-radius: 20rpx;
+			padding: 0 18rpx 24rpx 18rpx;
+			border-bottom: 2rpx solid #F5F5F5;
+
+			.louhao-active {
+				margin: 0 25rpx;
+				width: 92rpx;
+				height: 40rpx;
+				background: #FFFFFF;
+				border-radius: 8rpx;
+				border: 1rpx solid #999999;
+				position: relative;
+				margin-top: 24rpx;
+
+				.text1 {
+					font-size: 24rpx;
+					font-family: PingFangSC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #999999;
+				}
+
+				.text2 {
+					width: 20rpx;
+					line-height: 20rpx;
+					background: #1F7EFF;
+					border-radius: 8rpx 0px 8rpx 0px;
+					text-align: center;
+					position: absolute;
+					bottom: 0;
+					right: 0;
+					z-index: 1;
+					color: #fff;
+					font-size: 18rpx;
+				}
+			}
+		}
+	}
+</style>

BIN
pagesA/static/3d-bg.png


BIN
pagesA/static/3d-btn.png


BIN
pagesA/static/chongzhi.png


BIN
pagesA/static/kefu.png


BIN
pagesA/static/rizhao.png


BIN
pagesA/static/share.png


+ 1295 - 0
platforms/h5/common/OrbitControls.js

@@ -0,0 +1,1295 @@
+import {
+	EventDispatcher,
+	MOUSE,
+	Quaternion,
+	Spherical,
+	TOUCH,
+	Vector2,
+	Vector3
+} from './three.js';
+
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+//
+//    Orbit - left mouse / touch: one-finger move
+//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
+//    Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move
+
+const _changeEvent = { type: 'change' };
+const _startEvent = { type: 'start' };
+const _endEvent = { type: 'end' };
+
+class OrbitControls extends EventDispatcher {
+
+	constructor( object, domElement ) {
+
+		super();
+
+		this.object = object;
+		this.domElement = domElement;
+		this.domElement.style.touchAction = 'none'; // disable touch scroll
+
+		// Set to false to disable this control
+		this.enabled = true;
+
+		// "target" sets the location of focus, where the object orbits around
+		this.target = new Vector3();
+
+		// How far you can dolly in and out ( PerspectiveCamera only )
+		this.minDistance = 0;
+		this.maxDistance = Infinity;
+
+		// How far you can zoom in and out ( OrthographicCamera only )
+		this.minZoom = 0;
+		this.maxZoom = Infinity;
+
+		// How far you can orbit vertically, upper and lower limits.
+		// Range is 0 to Math.PI radians.
+		this.minPolarAngle = 0; // radians
+		this.maxPolarAngle = Math.PI; // radians
+
+		// How far you can orbit horizontally, upper and lower limits.
+		// If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ], with ( max - min < 2 PI )
+		this.minAzimuthAngle = - Infinity; // radians
+		this.maxAzimuthAngle = Infinity; // radians
+
+		// Set to true to enable damping (inertia)
+		// If damping is enabled, you must call controls.update() in your animation loop
+		this.enableDamping = false;
+		this.dampingFactor = 0.05;
+
+		// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
+		// Set to false to disable zooming
+		this.enableZoom = true;
+		this.zoomSpeed = 1.0;
+
+		// Set to false to disable rotating
+		this.enableRotate = true;
+		this.rotateSpeed = 1.0;
+
+		// Set to false to disable panning
+		this.enablePan = true;
+		this.panSpeed = 1.0;
+		this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up
+		this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
+
+		// Set to true to automatically rotate around the target
+		// If auto-rotate is enabled, you must call controls.update() in your animation loop
+		this.autoRotate = false;
+		this.autoRotateSpeed = 2.0; // 30 seconds per orbit when fps is 60
+
+		// The four arrow keys
+		this.keys = { LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' };
+
+		// Mouse buttons
+		this.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };
+
+		// Touch fingers
+		this.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };
+
+		// for reset
+		this.target0 = this.target.clone();
+		this.position0 = this.object.position.clone();
+		this.zoom0 = this.object.zoom;
+
+		// the target DOM element for key events
+		this._domElementKeyEvents = null;
+
+		//
+		// public methods
+		//
+
+		this.getPolarAngle = function () {
+
+			return spherical.phi;
+
+		};
+
+		this.getAzimuthalAngle = function () {
+
+			return spherical.theta;
+
+		};
+
+		this.getDistance = function () {
+
+			return this.object.position.distanceTo( this.target );
+
+		};
+
+		this.listenToKeyEvents = function ( domElement ) {
+
+			domElement.addEventListener( 'keydown', onKeyDown );
+			this._domElementKeyEvents = domElement;
+
+		};
+
+		this.stopListenToKeyEvents = function () {
+
+			this._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
+			this._domElementKeyEvents = null;
+
+		};
+
+		this.saveState = function () {
+
+			scope.target0.copy( scope.target );
+			scope.position0.copy( scope.object.position );
+			scope.zoom0 = scope.object.zoom;
+
+		};
+
+		this.reset = function () {
+
+			scope.target.copy( scope.target0 );
+			scope.object.position.copy( scope.position0 );
+			scope.object.zoom = scope.zoom0;
+
+			scope.object.updateProjectionMatrix();
+			scope.dispatchEvent( _changeEvent );
+
+			scope.update();
+
+			state = STATE.NONE;
+
+		};
+
+		// this method is exposed, but perhaps it would be better if we can make it private...
+		this.update = function () {
+
+			const offset = new Vector3();
+
+			// so camera.up is the orbit axis
+			const quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );
+			const quatInverse = quat.clone().invert();
+
+			const lastPosition = new Vector3();
+			const lastQuaternion = new Quaternion();
+
+			const twoPI = 2 * Math.PI;
+
+			return function update() {
+
+				const position = scope.object.position;
+
+				offset.copy( position ).sub( scope.target );
+
+				// rotate offset to "y-axis-is-up" space
+				offset.applyQuaternion( quat );
+
+				// angle from z-axis around y-axis
+				spherical.setFromVector3( offset );
+
+				if ( scope.autoRotate && state === STATE.NONE ) {
+
+					rotateLeft( getAutoRotationAngle() );
+
+				}
+
+				if ( scope.enableDamping ) {
+
+					spherical.theta += sphericalDelta.theta * scope.dampingFactor;
+					spherical.phi += sphericalDelta.phi * scope.dampingFactor;
+
+				} else {
+
+					spherical.theta += sphericalDelta.theta;
+					spherical.phi += sphericalDelta.phi;
+
+				}
+
+				// restrict theta to be between desired limits
+
+				let min = scope.minAzimuthAngle;
+				let max = scope.maxAzimuthAngle;
+
+				if ( isFinite( min ) && isFinite( max ) ) {
+
+					if ( min < - Math.PI ) min += twoPI; else if ( min > Math.PI ) min -= twoPI;
+
+					if ( max < - Math.PI ) max += twoPI; else if ( max > Math.PI ) max -= twoPI;
+
+					if ( min <= max ) {
+
+						spherical.theta = Math.max( min, Math.min( max, spherical.theta ) );
+
+					} else {
+
+						spherical.theta = ( spherical.theta > ( min + max ) / 2 ) ?
+							Math.max( min, spherical.theta ) :
+							Math.min( max, spherical.theta );
+
+					}
+
+				}
+
+				// restrict phi to be between desired limits
+				spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
+
+				spherical.makeSafe();
+
+
+				spherical.radius *= scale;
+
+				// restrict radius to be between desired limits
+				spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
+
+				// move target to panned location
+
+				if ( scope.enableDamping === true ) {
+
+					scope.target.addScaledVector( panOffset, scope.dampingFactor );
+
+				} else {
+
+					scope.target.add( panOffset );
+
+				}
+
+				offset.setFromSpherical( spherical );
+
+				// rotate offset back to "camera-up-vector-is-up" space
+				offset.applyQuaternion( quatInverse );
+
+				position.copy( scope.target ).add( offset );
+
+				scope.object.lookAt( scope.target );
+
+				if ( scope.enableDamping === true ) {
+
+					sphericalDelta.theta *= ( 1 - scope.dampingFactor );
+					sphericalDelta.phi *= ( 1 - scope.dampingFactor );
+
+					panOffset.multiplyScalar( 1 - scope.dampingFactor );
+
+				} else {
+
+					sphericalDelta.set( 0, 0, 0 );
+
+					panOffset.set( 0, 0, 0 );
+
+				}
+
+				scale = 1;
+
+				// update condition is:
+				// min(camera displacement, camera rotation in radians)^2 > EPS
+				// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+				if ( zoomChanged ||
+					lastPosition.distanceToSquared( scope.object.position ) > EPS ||
+					8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
+
+					scope.dispatchEvent( _changeEvent );
+
+					lastPosition.copy( scope.object.position );
+					lastQuaternion.copy( scope.object.quaternion );
+					zoomChanged = false;
+
+					return true;
+
+				}
+
+				return false;
+
+			};
+
+		}();
+
+		this.dispose = function () {
+
+			scope.domElement.removeEventListener( 'contextmenu', onContextMenu );
+
+			scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
+			scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
+			scope.domElement.removeEventListener( 'wheel', onMouseWheel );
+
+			scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+			scope.domElement.removeEventListener( 'pointerup', onPointerUp );
+
+
+			if ( scope._domElementKeyEvents !== null ) {
+
+				scope._domElementKeyEvents.removeEventListener( 'keydown', onKeyDown );
+				scope._domElementKeyEvents = null;
+
+			}
+
+			//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+
+		};
+
+		//
+		// internals
+		//
+
+		const scope = this;
+
+		const STATE = {
+			NONE: - 1,
+			ROTATE: 0,
+			DOLLY: 1,
+			PAN: 2,
+			TOUCH_ROTATE: 3,
+			TOUCH_PAN: 4,
+			TOUCH_DOLLY_PAN: 5,
+			TOUCH_DOLLY_ROTATE: 6
+		};
+
+		let state = STATE.NONE;
+
+		const EPS = 0.000001;
+
+		// current position in spherical coordinates
+		const spherical = new Spherical();
+		const sphericalDelta = new Spherical();
+
+		let scale = 1;
+		const panOffset = new Vector3();
+		let zoomChanged = false;
+
+		const rotateStart = new Vector2();
+		const rotateEnd = new Vector2();
+		const rotateDelta = new Vector2();
+
+		const panStart = new Vector2();
+		const panEnd = new Vector2();
+		const panDelta = new Vector2();
+
+		const dollyStart = new Vector2();
+		const dollyEnd = new Vector2();
+		const dollyDelta = new Vector2();
+
+		const pointers = [];
+		const pointerPositions = {};
+
+		function getAutoRotationAngle() {
+
+			return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+		}
+
+		function getZoomScale() {
+
+			return Math.pow( 0.95, scope.zoomSpeed );
+
+		}
+
+		function rotateLeft( angle ) {
+
+			sphericalDelta.theta -= angle;
+
+		}
+
+		function rotateUp( angle ) {
+
+			sphericalDelta.phi -= angle;
+
+		}
+
+		const panLeft = function () {
+
+			const v = new Vector3();
+
+			return function panLeft( distance, objectMatrix ) {
+
+				v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
+				v.multiplyScalar( - distance );
+
+				panOffset.add( v );
+
+			};
+
+		}();
+
+		const panUp = function () {
+
+			const v = new Vector3();
+
+			return function panUp( distance, objectMatrix ) {
+
+				if ( scope.screenSpacePanning === true ) {
+
+					v.setFromMatrixColumn( objectMatrix, 1 );
+
+				} else {
+
+					v.setFromMatrixColumn( objectMatrix, 0 );
+					v.crossVectors( scope.object.up, v );
+
+				}
+
+				v.multiplyScalar( distance );
+
+				panOffset.add( v );
+
+			};
+
+		}();
+
+		// deltaX and deltaY are in pixels; right and down are positive
+		const pan = function () {
+
+			const offset = new Vector3();
+
+			return function pan( deltaX, deltaY ) {
+
+				const element = scope.domElement;
+
+				if ( scope.object.isPerspectiveCamera ) {
+
+					// perspective
+					const position = scope.object.position;
+					offset.copy( position ).sub( scope.target );
+					let targetDistance = offset.length();
+
+					// half of the fov is center to top of screen
+					targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
+
+					// we use only clientHeight here so aspect ratio does not distort speed
+					panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
+					panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
+
+				} else if ( scope.object.isOrthographicCamera ) {
+
+					// orthographic
+					panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
+					panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
+
+				} else {
+
+					// camera neither orthographic nor perspective
+					console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+					scope.enablePan = false;
+
+				}
+
+			};
+
+		}();
+
+		function dollyOut( dollyScale ) {
+
+			if ( scope.object.isPerspectiveCamera ) {
+
+				scale /= dollyScale;
+
+			} else if ( scope.object.isOrthographicCamera ) {
+
+				scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
+				scope.object.updateProjectionMatrix();
+				zoomChanged = true;
+
+			} else {
+
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+				scope.enableZoom = false;
+
+			}
+
+		}
+
+		function dollyIn( dollyScale ) {
+
+			if ( scope.object.isPerspectiveCamera ) {
+
+				scale *= dollyScale;
+
+			} else if ( scope.object.isOrthographicCamera ) {
+
+				scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
+				scope.object.updateProjectionMatrix();
+				zoomChanged = true;
+
+			} else {
+
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+				scope.enableZoom = false;
+
+			}
+
+		}
+
+		//
+		// event callbacks - update the object state
+		//
+
+		function handleMouseDownRotate( event ) {
+
+			rotateStart.set( event.clientX, event.clientY );
+
+		}
+
+		function handleMouseDownDolly( event ) {
+
+			dollyStart.set( event.clientX, event.clientY );
+
+		}
+
+		function handleMouseDownPan( event ) {
+
+			panStart.set( event.clientX, event.clientY );
+
+		}
+
+		function handleMouseMoveRotate( event ) {
+
+			rotateEnd.set( event.clientX, event.clientY );
+
+			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
+
+			const element = scope.domElement;
+
+			rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
+
+			rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
+
+			rotateStart.copy( rotateEnd );
+
+			scope.update();
+
+		}
+
+		function handleMouseMoveDolly( event ) {
+
+			dollyEnd.set( event.clientX, event.clientY );
+
+			dollyDelta.subVectors( dollyEnd, dollyStart );
+
+			if ( dollyDelta.y > 0 ) {
+
+				dollyOut( getZoomScale() );
+
+			} else if ( dollyDelta.y < 0 ) {
+
+				dollyIn( getZoomScale() );
+
+			}
+
+			dollyStart.copy( dollyEnd );
+
+			scope.update();
+
+		}
+
+		function handleMouseMovePan( event ) {
+
+			panEnd.set( event.clientX, event.clientY );
+
+			panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
+
+			pan( panDelta.x, panDelta.y );
+
+			panStart.copy( panEnd );
+
+			scope.update();
+
+		}
+
+		function handleMouseWheel( event ) {
+
+			if ( event.deltaY < 0 ) {
+
+				dollyIn( getZoomScale() );
+
+			} else if ( event.deltaY > 0 ) {
+
+				dollyOut( getZoomScale() );
+
+			}
+
+			scope.update();
+
+		}
+
+		function handleKeyDown( event ) {
+
+			let needsUpdate = false;
+
+			switch ( event.code ) {
+
+				case scope.keys.UP:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+					} else {
+
+						pan( 0, scope.keyPanSpeed );
+
+					}
+
+					needsUpdate = true;
+					break;
+
+				case scope.keys.BOTTOM:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+					} else {
+
+						pan( 0, - scope.keyPanSpeed );
+
+					}
+
+					needsUpdate = true;
+					break;
+
+				case scope.keys.LEFT:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+					} else {
+
+						pan( scope.keyPanSpeed, 0 );
+
+					}
+
+					needsUpdate = true;
+					break;
+
+				case scope.keys.RIGHT:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+					} else {
+
+						pan( - scope.keyPanSpeed, 0 );
+
+					}
+
+					needsUpdate = true;
+					break;
+
+			}
+
+			if ( needsUpdate ) {
+
+				// prevent the browser from scrolling on cursor keys
+				event.preventDefault();
+
+				scope.update();
+
+			}
+
+
+		}
+
+		function handleTouchStartRotate() {
+
+			if ( pointers.length === 1 ) {
+
+				rotateStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
+
+			} else {
+
+				const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
+				const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
+
+				rotateStart.set( x, y );
+
+			}
+
+		}
+
+		function handleTouchStartPan() {
+
+			if ( pointers.length === 1 ) {
+
+				panStart.set( pointers[ 0 ].pageX, pointers[ 0 ].pageY );
+
+			} else {
+
+				const x = 0.5 * ( pointers[ 0 ].pageX + pointers[ 1 ].pageX );
+				const y = 0.5 * ( pointers[ 0 ].pageY + pointers[ 1 ].pageY );
+
+				panStart.set( x, y );
+
+			}
+
+		}
+
+		function handleTouchStartDolly() {
+
+			const dx = pointers[ 0 ].pageX - pointers[ 1 ].pageX;
+			const dy = pointers[ 0 ].pageY - pointers[ 1 ].pageY;
+
+			const distance = Math.sqrt( dx * dx + dy * dy );
+
+			dollyStart.set( 0, distance );
+
+		}
+
+		function handleTouchStartDollyPan() {
+
+			if ( scope.enableZoom ) handleTouchStartDolly();
+
+			if ( scope.enablePan ) handleTouchStartPan();
+
+		}
+
+		function handleTouchStartDollyRotate() {
+
+			if ( scope.enableZoom ) handleTouchStartDolly();
+
+			if ( scope.enableRotate ) handleTouchStartRotate();
+
+		}
+
+		function handleTouchMoveRotate( event ) {
+
+			if ( pointers.length == 1 ) {
+
+				rotateEnd.set( event.pageX, event.pageY );
+
+			} else {
+
+				const position = getSecondPointerPosition( event );
+
+				const x = 0.5 * ( event.pageX + position.x );
+				const y = 0.5 * ( event.pageY + position.y );
+
+				rotateEnd.set( x, y );
+
+			}
+
+			rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );
+
+			const element = scope.domElement;
+
+			rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height
+
+			rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );
+
+			rotateStart.copy( rotateEnd );
+
+		}
+
+		function handleTouchMovePan( event ) {
+
+			if ( pointers.length === 1 ) {
+
+				panEnd.set( event.pageX, event.pageY );
+
+			} else {
+
+				const position = getSecondPointerPosition( event );
+
+				const x = 0.5 * ( event.pageX + position.x );
+				const y = 0.5 * ( event.pageY + position.y );
+
+				panEnd.set( x, y );
+
+			}
+
+			panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );
+
+			pan( panDelta.x, panDelta.y );
+
+			panStart.copy( panEnd );
+
+		}
+
+		function handleTouchMoveDolly( event ) {
+
+			const position = getSecondPointerPosition( event );
+
+			const dx = event.pageX - position.x;
+			const dy = event.pageY - position.y;
+
+			const distance = Math.sqrt( dx * dx + dy * dy );
+
+			dollyEnd.set( 0, distance );
+
+			dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );
+
+			dollyOut( dollyDelta.y );
+
+			dollyStart.copy( dollyEnd );
+
+		}
+
+		function handleTouchMoveDollyPan( event ) {
+
+			if ( scope.enableZoom ) handleTouchMoveDolly( event );
+
+			if ( scope.enablePan ) handleTouchMovePan( event );
+
+		}
+
+		function handleTouchMoveDollyRotate( event ) {
+
+			if ( scope.enableZoom ) handleTouchMoveDolly( event );
+
+			if ( scope.enableRotate ) handleTouchMoveRotate( event );
+
+		}
+
+		//
+		// event handlers - FSM: listen for events and reset state
+		//
+
+		function onPointerDown( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			if ( pointers.length === 0 ) {
+
+				scope.domElement.setPointerCapture( event.pointerId );
+
+				scope.domElement.addEventListener( 'pointermove', onPointerMove );
+				scope.domElement.addEventListener( 'pointerup', onPointerUp );
+
+			}
+
+			//
+
+			addPointer( event );
+
+			if ( event.pointerType === 'touch' ) {
+
+				onTouchStart( event );
+
+			} else {
+
+				onMouseDown( event );
+
+			}
+
+		}
+
+		function onPointerMove( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			if ( event.pointerType === 'touch' ) {
+
+				onTouchMove( event );
+
+			} else {
+
+				onMouseMove( event );
+
+			}
+
+		}
+
+		function onPointerUp( event ) {
+
+		    removePointer( event );
+
+		    if ( pointers.length === 0 ) {
+
+		        scope.domElement.releasePointerCapture( event.pointerId );
+
+		        scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+		        scope.domElement.removeEventListener( 'pointerup', onPointerUp );
+
+		    }
+
+		    scope.dispatchEvent( _endEvent );
+
+		    state = STATE.NONE;
+
+		}
+
+		function onPointerCancel( event ) {
+
+			removePointer( event );
+
+		}
+
+		function onMouseDown( event ) {
+
+			let mouseAction;
+
+			switch ( event.button ) {
+
+				case 0:
+
+					mouseAction = scope.mouseButtons.LEFT;
+					break;
+
+				case 1:
+
+					mouseAction = scope.mouseButtons.MIDDLE;
+					break;
+
+				case 2:
+
+					mouseAction = scope.mouseButtons.RIGHT;
+					break;
+
+				default:
+
+					mouseAction = - 1;
+
+			}
+
+			switch ( mouseAction ) {
+
+				case MOUSE.DOLLY:
+
+					if ( scope.enableZoom === false ) return;
+
+					handleMouseDownDolly( event );
+
+					state = STATE.DOLLY;
+
+					break;
+
+				case MOUSE.ROTATE:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						if ( scope.enablePan === false ) return;
+
+						handleMouseDownPan( event );
+
+						state = STATE.PAN;
+
+					} else {
+
+						if ( scope.enableRotate === false ) return;
+
+						handleMouseDownRotate( event );
+
+						state = STATE.ROTATE;
+
+					}
+
+					break;
+
+				case MOUSE.PAN:
+
+					if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+						if ( scope.enableRotate === false ) return;
+
+						handleMouseDownRotate( event );
+
+						state = STATE.ROTATE;
+
+					} else {
+
+						if ( scope.enablePan === false ) return;
+
+						handleMouseDownPan( event );
+
+						state = STATE.PAN;
+
+					}
+
+					break;
+
+				default:
+
+					state = STATE.NONE;
+
+			}
+
+			if ( state !== STATE.NONE ) {
+
+				scope.dispatchEvent( _startEvent );
+
+			}
+
+		}
+
+		function onMouseMove( event ) {
+
+			switch ( state ) {
+
+				case STATE.ROTATE:
+
+					if ( scope.enableRotate === false ) return;
+
+					handleMouseMoveRotate( event );
+
+					break;
+
+				case STATE.DOLLY:
+
+					if ( scope.enableZoom === false ) return;
+
+					handleMouseMoveDolly( event );
+
+					break;
+
+				case STATE.PAN:
+
+					if ( scope.enablePan === false ) return;
+
+					handleMouseMovePan( event );
+
+					break;
+
+			}
+
+		}
+
+		function onMouseWheel( event ) {
+
+			if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;
+
+			event.preventDefault();
+
+			scope.dispatchEvent( _startEvent );
+
+			handleMouseWheel( event );
+
+			scope.dispatchEvent( _endEvent );
+
+		}
+
+		function onKeyDown( event ) {
+
+			if ( scope.enabled === false || scope.enablePan === false ) return;
+
+			handleKeyDown( event );
+
+		}
+
+		function onTouchStart( event ) {
+
+			trackPointer( event );
+
+			switch ( pointers.length ) {
+
+				case 1:
+
+					switch ( scope.touches.ONE ) {
+
+						case TOUCH.ROTATE:
+
+							if ( scope.enableRotate === false ) return;
+
+							handleTouchStartRotate();
+
+							state = STATE.TOUCH_ROTATE;
+
+							break;
+
+						case TOUCH.PAN:
+
+							if ( scope.enablePan === false ) return;
+
+							handleTouchStartPan();
+
+							state = STATE.TOUCH_PAN;
+
+							break;
+
+						default:
+
+							state = STATE.NONE;
+
+					}
+
+					break;
+
+				case 2:
+
+					switch ( scope.touches.TWO ) {
+
+						case TOUCH.DOLLY_PAN:
+
+							if ( scope.enableZoom === false && scope.enablePan === false ) return;
+
+							handleTouchStartDollyPan();
+
+							state = STATE.TOUCH_DOLLY_PAN;
+
+							break;
+
+						case TOUCH.DOLLY_ROTATE:
+
+							if ( scope.enableZoom === false && scope.enableRotate === false ) return;
+
+							handleTouchStartDollyRotate();
+
+							state = STATE.TOUCH_DOLLY_ROTATE;
+
+							break;
+
+						default:
+
+							state = STATE.NONE;
+
+					}
+
+					break;
+
+				default:
+
+					state = STATE.NONE;
+
+			}
+
+			if ( state !== STATE.NONE ) {
+
+				scope.dispatchEvent( _startEvent );
+
+			}
+
+		}
+
+		function onTouchMove( event ) {
+
+			trackPointer( event );
+
+			switch ( state ) {
+
+				case STATE.TOUCH_ROTATE:
+
+					if ( scope.enableRotate === false ) return;
+
+					handleTouchMoveRotate( event );
+
+					scope.update();
+
+					break;
+
+				case STATE.TOUCH_PAN:
+
+					if ( scope.enablePan === false ) return;
+
+					handleTouchMovePan( event );
+
+					scope.update();
+
+					break;
+
+				case STATE.TOUCH_DOLLY_PAN:
+
+					if ( scope.enableZoom === false && scope.enablePan === false ) return;
+
+					handleTouchMoveDollyPan( event );
+
+					scope.update();
+
+					break;
+
+				case STATE.TOUCH_DOLLY_ROTATE:
+
+					if ( scope.enableZoom === false && scope.enableRotate === false ) return;
+
+					handleTouchMoveDollyRotate( event );
+
+					scope.update();
+
+					break;
+
+				default:
+
+					state = STATE.NONE;
+
+			}
+
+		}
+
+		function onContextMenu( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			event.preventDefault();
+
+		}
+
+		function addPointer( event ) {
+
+			pointers.push( event );
+
+		}
+
+		function removePointer( event ) {
+
+			delete pointerPositions[ event.pointerId ];
+
+			for ( let i = 0; i < pointers.length; i ++ ) {
+
+				if ( pointers[ i ].pointerId == event.pointerId ) {
+
+					pointers.splice( i, 1 );
+					return;
+
+				}
+
+			}
+
+		}
+
+		function trackPointer( event ) {
+
+			let position = pointerPositions[ event.pointerId ];
+
+			if ( position === undefined ) {
+
+				position = new Vector2();
+				pointerPositions[ event.pointerId ] = position;
+
+			}
+
+			position.set( event.pageX, event.pageY );
+
+		}
+
+		function getSecondPointerPosition( event ) {
+
+			const pointer = ( event.pointerId === pointers[ 0 ].pointerId ) ? pointers[ 1 ] : pointers[ 0 ];
+
+			return pointerPositions[ pointer.pointerId ];
+
+		}
+
+		//
+
+		scope.domElement.addEventListener( 'contextmenu', onContextMenu );
+
+		scope.domElement.addEventListener( 'pointerdown', onPointerDown );
+		scope.domElement.addEventListener( 'pointercancel', onPointerCancel );
+		scope.domElement.addEventListener( 'wheel', onMouseWheel, { passive: false } );
+
+		// force an update at start
+
+		this.update();
+
+	}
+
+}
+
+
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+// This is very similar to OrbitControls, another set of touch behavior
+//
+//    Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate
+//    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
+//    Pan - left mouse, or arrow keys / touch: one-finger move
+
+class MapControls extends OrbitControls {
+
+	constructor( object, domElement ) {
+
+		super( object, domElement );
+
+		this.screenSpacePanning = false; // pan orthogonal to world-space direction camera.up
+
+		this.mouseButtons.LEFT = MOUSE.PAN;
+		this.mouseButtons.RIGHT = MOUSE.ROTATE;
+
+		this.touches.ONE = TOUCH.PAN;
+		this.touches.TWO = TOUCH.DOLLY_ROTATE;
+
+	}
+
+}
+
+export { OrbitControls, MapControls };

+ 568 - 0
platforms/h5/common/obj/MTLLoader.js

@@ -0,0 +1,568 @@
+import {
+	Color,
+	DefaultLoadingManager,
+	FileLoader,
+	FrontSide,
+	Loader,
+	LoaderUtils,
+	MeshPhongMaterial,
+	RepeatWrapping,
+	TextureLoader,
+	Vector2,
+	sRGBEncoding
+} from '../three.js';
+
+/**
+ * Loads a Wavefront .mtl file specifying materials
+ */
+
+class MTLLoader extends Loader {
+
+	constructor(manager) {
+
+		super(manager);
+
+	}
+
+	/**
+	 * Loads and parses a MTL asset from a URL.
+	 *
+	 * @param {String} url - URL to the MTL file.
+	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
+	 * @param {Function} [onProgress] - Callback for download progress.
+	 * @param {Function} [onError] - Callback for download errors.
+	 *
+	 * @see setPath setResourcePath
+	 *
+	 * @note In order for relative texture references to resolve correctly
+	 * you must call setResourcePath() explicitly prior to load.
+	 */
+	load(url, onLoad, onProgress, onError) {
+
+		const scope = this;
+
+		const path = (this.path === '') ? LoaderUtils.extractUrlBase(url) : this.path;
+
+		const loader = new FileLoader(this.manager);
+		loader.setPath(this.path);
+		loader.setRequestHeader(this.requestHeader);
+		loader.setWithCredentials(this.withCredentials);
+		loader.load(url, function(text) {
+
+			try {
+
+				onLoad(scope.parse(text, path));
+
+			} catch (e) {
+
+				if (onError) {
+
+					onError(e);
+
+				} else {
+
+					console.error(e);
+
+				}
+
+				scope.manager.itemError(url);
+
+			}
+
+		}, onProgress, onError);
+
+	}
+
+	setMaterialOptions(value) {
+
+		this.materialOptions = value;
+		return this;
+
+	}
+
+	/**
+	 * Parses a MTL file.
+	 *
+	 * @param {String} text - Content of MTL file
+	 * @return {MaterialCreator}
+	 *
+	 * @see setPath setResourcePath
+	 *
+	 * @note In order for relative texture references to resolve correctly
+	 * you must call setResourcePath() explicitly prior to parse.
+	 */
+	parse(text, path) {
+
+		const lines = text.split('\n');
+		let info = {};
+		const delimiter_pattern = /\s+/;
+		const materialsInfo = {};
+
+		for (let i = 0; i < lines.length; i++) {
+
+			let line = lines[i];
+			line = line.trim();
+
+			if (line.length === 0 || line.charAt(0) === '#') {
+
+				// Blank line or comment ignore
+				continue;
+
+			}
+
+			const pos = line.indexOf(' ');
+
+			let key = (pos >= 0) ? line.substring(0, pos) : line;
+			key = key.toLowerCase();
+
+			let value = (pos >= 0) ? line.substring(pos + 1) : '';
+			value = value.trim();
+
+			if (key === 'newmtl') {
+
+				// New material
+
+				info = { name: value };
+				materialsInfo[value] = info;
+
+			} else {
+
+				if (key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke') {
+
+					const ss = value.split(delimiter_pattern, 3);
+					info[key] = [parseFloat(ss[0]), parseFloat(ss[1]), parseFloat(ss[2])];
+
+				} else {
+
+					info[key] = value;
+
+				}
+
+			}
+
+		}
+
+		const materialCreator = new MaterialCreator(this.resourcePath || path, this.materialOptions);
+		materialCreator.setCrossOrigin(this.crossOrigin);
+		materialCreator.setManager(this.manager);
+		materialCreator.setMaterials(materialsInfo);
+		return materialCreator;
+
+	}
+
+}
+
+/**
+ * Create a new MTLLoader.MaterialCreator
+ * @param baseUrl - Url relative to which textures are loaded
+ * @param options - Set of options on how to construct the materials
+ *                  side: Which side to apply the material
+ *                        FrontSide (default), THREE.BackSide, THREE.DoubleSide
+ *                  wrap: What type of wrapping to apply for textures
+ *                        RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
+ *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
+ *                                Default: false, assumed to be already normalized
+ *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
+ *                                  Default: false
+ * @constructor
+ */
+
+class MaterialCreator {
+
+	constructor(baseUrl = '', options = {}) {
+
+		this.baseUrl = baseUrl;
+		this.options = options;
+		this.materialsInfo = {};
+		this.materials = {};
+		this.materialsArray = [];
+		this.nameLookup = {};
+
+		this.crossOrigin = 'anonymous';
+
+		this.side = (this.options.side !== undefined) ? this.options.side : FrontSide;
+		this.wrap = (this.options.wrap !== undefined) ? this.options.wrap : RepeatWrapping;
+
+	}
+
+	setCrossOrigin(value) {
+
+		this.crossOrigin = value;
+		return this;
+
+	}
+
+	setManager(value) {
+
+		this.manager = value;
+
+	}
+
+	setMaterials(materialsInfo) {
+
+		this.materialsInfo = this.convert(materialsInfo);
+		this.materials = {};
+		this.materialsArray = [];
+		this.nameLookup = {};
+
+	}
+
+	convert(materialsInfo) {
+
+		if (!this.options) return materialsInfo;
+
+		const converted = {};
+
+		for (const mn in materialsInfo) {
+
+			// Convert materials info into normalized form based on options
+
+			const mat = materialsInfo[mn];
+
+			const covmat = {};
+
+			converted[mn] = covmat;
+
+			for (const prop in mat) {
+
+				let save = true;
+				let value = mat[prop];
+				const lprop = prop.toLowerCase();
+
+				switch (lprop) {
+
+					case 'kd':
+					case 'ka':
+					case 'ks':
+
+						// Diffuse color (color under white light) using RGB values
+
+						if (this.options && this.options.normalizeRGB) {
+
+							value = [value[0] / 255, value[1] / 255, value[2] / 255];
+
+						}
+
+						if (this.options && this.options.ignoreZeroRGBs) {
+
+							if (value[0] === 0 && value[1] === 0 && value[2] === 0) {
+
+								// ignore
+
+								save = false;
+
+							}
+
+						}
+
+						break;
+
+					default:
+
+						break;
+
+				}
+
+				if (save) {
+
+					covmat[lprop] = value;
+
+				}
+
+			}
+
+		}
+
+		return converted;
+
+	}
+
+	preload() {
+
+		for (const mn in this.materialsInfo) {
+
+			this.create(mn);
+
+		}
+
+	}
+
+	getIndex(materialName) {
+
+		return this.nameLookup[materialName];
+
+	}
+
+	getAsArray() {
+
+		let index = 0;
+
+		for (const mn in this.materialsInfo) {
+
+			this.materialsArray[index] = this.create(mn);
+			this.nameLookup[mn] = index;
+			index++;
+
+		}
+
+		return this.materialsArray;
+
+	}
+
+	create(materialName) {
+
+		if (this.materials[materialName] === undefined) {
+
+			this.createMaterial_(materialName);
+
+		}
+
+		return this.materials[materialName];
+
+	}
+
+	createMaterial_(materialName) {
+
+		// Create material
+
+		const scope = this;
+		const mat = this.materialsInfo[materialName];
+		const params = {
+
+			name: materialName,
+			side: this.side
+
+		};
+
+		function resolveURL(baseUrl, url) {
+
+			if (typeof url !== 'string' || url === '')
+				return '';
+
+			// Absolute URL
+			if (/^https?:\/\//i.test(url)) return url;
+
+			return baseUrl + url;
+
+		}
+
+		function setMapForType(mapType, value) {
+
+			if (params[mapType]) return; // Keep the first encountered texture
+
+			const texParams = scope.getTextureParams(value, params);
+			const map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
+
+			map.repeat.copy(texParams.scale);
+			map.offset.copy(texParams.offset);
+
+			map.wrapS = scope.wrap;
+			map.wrapT = scope.wrap;
+
+			if (mapType === 'map' || mapType === 'emissiveMap') {
+
+				map.encoding = sRGBEncoding;
+
+			}
+
+			params[mapType] = map;
+
+		}
+
+		for (const prop in mat) {
+
+			const value = mat[prop];
+			let n;
+
+			if (value === '') continue;
+
+			switch (prop.toLowerCase()) {
+
+				// Ns is material specular exponent
+
+				case 'kd':
+
+					// Diffuse color (color under white light) using RGB values
+
+					params.color = new Color().fromArray(value).convertSRGBToLinear();
+
+					break;
+
+				case 'ks':
+
+					// Specular color (color when light is reflected from shiny surface) using RGB values
+					params.specular = new Color().fromArray(value).convertSRGBToLinear();
+
+					break;
+
+				case 'ke':
+
+					// Emissive using RGB values
+					params.emissive = new Color().fromArray(value).convertSRGBToLinear();
+
+					break;
+
+				case 'map_kd':
+
+					// Diffuse texture map
+
+					setMapForType('map', value);
+
+					break;
+
+				case 'map_ks':
+
+					// Specular map
+
+					setMapForType('specularMap', value);
+
+					break;
+
+				case 'map_ke':
+
+					// Emissive map
+
+					setMapForType('emissiveMap', value);
+
+					break;
+
+				case 'norm':
+
+					setMapForType('normalMap', value);
+
+					break;
+
+				case 'map_bump':
+				case 'bump':
+
+					// Bump texture map
+
+					setMapForType('bumpMap', value);
+
+					break;
+
+				case 'map_d':
+
+					// Alpha map
+
+					setMapForType('alphaMap', value);
+					params.transparent = true;
+
+					break;
+
+				case 'ns':
+
+					// The specular exponent (defines the focus of the specular highlight)
+					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
+
+					params.shininess = parseFloat(value);
+
+					break;
+
+				case 'd':
+					n = parseFloat(value);
+
+					if (n < 1) {
+
+						params.opacity = n;
+						params.transparent = true;
+
+					}
+
+					break;
+
+				case 'tr':
+					n = parseFloat(value);
+
+					if (this.options && this.options.invertTrProperty) n = 1 - n;
+
+					if (n > 0) {
+
+						params.opacity = 1 - n;
+						params.transparent = true;
+
+					}
+
+					break;
+
+				default:
+					break;
+
+			}
+
+		}
+
+		this.materials[materialName] = new MeshPhongMaterial(params);
+		return this.materials[materialName];
+
+	}
+
+	getTextureParams(value, matParams) {
+
+		const texParams = {
+
+			scale: new Vector2(1, 1),
+			offset: new Vector2(0, 0)
+
+		};
+
+		const items = value.split(/\s+/);
+		let pos;
+
+		pos = items.indexOf('-bm');
+
+		if (pos >= 0) {
+
+			matParams.bumpScale = parseFloat(items[pos + 1]);
+			items.splice(pos, 2);
+
+		}
+
+		pos = items.indexOf('-s');
+
+		if (pos >= 0) {
+
+			texParams.scale.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
+			items.splice(pos, 4); // we expect 3 parameters here!
+
+		}
+
+		pos = items.indexOf('-o');
+
+		if (pos >= 0) {
+
+			texParams.offset.set(parseFloat(items[pos + 1]), parseFloat(items[pos + 2]));
+			items.splice(pos, 4); // we expect 3 parameters here!
+
+		}
+
+		texParams.url = items.join(' ').trim();
+		return texParams;
+
+	}
+
+	loadTexture(url, mapping, onLoad, onProgress, onError) {
+
+		const manager = (this.manager !== undefined) ? this.manager : DefaultLoadingManager;
+		let loader = manager.getHandler(url);
+
+		if (loader === null) {
+
+			loader = new TextureLoader(manager);
+
+		}
+
+		if (loader.setCrossOrigin) loader.setCrossOrigin(this.crossOrigin);
+
+		const texture = loader.load(url, onLoad, onProgress, onError);
+
+		if (mapping !== undefined) texture.mapping = mapping;
+
+		return texture;
+
+	}
+
+}
+
+export { MTLLoader };
+

+ 905 - 0
platforms/h5/common/obj/OBJLoader.js

@@ -0,0 +1,905 @@
+import {
+	BufferGeometry,
+	FileLoader,
+	Float32BufferAttribute,
+	Group,
+	LineBasicMaterial,
+	LineSegments,
+	Loader,
+	Material,
+	Mesh,
+	MeshPhongMaterial,
+	Points,
+	PointsMaterial,
+	Vector3,
+	Color
+} from '../three.js';
+
+// o object_name | g group_name
+const _object_pattern = /^[og]\s*(.+)?/;
+// mtllib file_reference
+const _material_library_pattern = /^mtllib /;
+// usemtl material_name
+const _material_use_pattern = /^usemtl /;
+// usemap map_name
+const _map_use_pattern = /^usemap /;
+const _face_vertex_data_separator_pattern = /\s+/;
+
+const _vA = new Vector3();
+const _vB = new Vector3();
+const _vC = new Vector3();
+
+const _ab = new Vector3();
+const _cb = new Vector3();
+
+const _color = new Color();
+
+function ParserState() {
+
+	const state = {
+		objects: [],
+		object: {},
+
+		vertices: [],
+		normals: [],
+		colors: [],
+		uvs: [],
+
+		materials: {},
+		materialLibraries: [],
+
+		startObject: function ( name, fromDeclaration ) {
+
+			// If the current object (initial from reset) is not from a g/o declaration in the parsed
+			// file. We need to use it for the first parsed g/o to keep things in sync.
+			if ( this.object && this.object.fromDeclaration === false ) {
+
+				this.object.name = name;
+				this.object.fromDeclaration = ( fromDeclaration !== false );
+				return;
+
+			}
+
+			const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
+
+			if ( this.object && typeof this.object._finalize === 'function' ) {
+
+				this.object._finalize( true );
+
+			}
+
+			this.object = {
+				name: name || '',
+				fromDeclaration: ( fromDeclaration !== false ),
+
+				geometry: {
+					vertices: [],
+					normals: [],
+					colors: [],
+					uvs: [],
+					hasUVIndices: false
+				},
+				materials: [],
+				smooth: true,
+
+				startMaterial: function ( name, libraries ) {
+
+					const previous = this._finalize( false );
+
+					// New usemtl declaration overwrites an inherited material, except if faces were declared
+					// after the material, then it must be preserved for proper MultiMaterial continuation.
+					if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
+
+						this.materials.splice( previous.index, 1 );
+
+					}
+
+					const material = {
+						index: this.materials.length,
+						name: name || '',
+						mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
+						smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
+						groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
+						groupEnd: - 1,
+						groupCount: - 1,
+						inherited: false,
+
+						clone: function ( index ) {
+
+							const cloned = {
+								index: ( typeof index === 'number' ? index : this.index ),
+								name: this.name,
+								mtllib: this.mtllib,
+								smooth: this.smooth,
+								groupStart: 0,
+								groupEnd: - 1,
+								groupCount: - 1,
+								inherited: false
+							};
+							cloned.clone = this.clone.bind( cloned );
+							return cloned;
+
+						}
+					};
+
+					this.materials.push( material );
+
+					return material;
+
+				},
+
+				currentMaterial: function () {
+
+					if ( this.materials.length > 0 ) {
+
+						return this.materials[ this.materials.length - 1 ];
+
+					}
+
+					return undefined;
+
+				},
+
+				_finalize: function ( end ) {
+
+					const lastMultiMaterial = this.currentMaterial();
+					if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
+
+						lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
+						lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
+						lastMultiMaterial.inherited = false;
+
+					}
+
+					// Ignore objects tail materials if no face declarations followed them before a new o/g started.
+					if ( end && this.materials.length > 1 ) {
+
+						for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {
+
+							if ( this.materials[ mi ].groupCount <= 0 ) {
+
+								this.materials.splice( mi, 1 );
+
+							}
+
+						}
+
+					}
+
+					// Guarantee at least one empty material, this makes the creation later more straight forward.
+					if ( end && this.materials.length === 0 ) {
+
+						this.materials.push( {
+							name: '',
+							smooth: this.smooth
+						} );
+
+					}
+
+					return lastMultiMaterial;
+
+				}
+			};
+
+			// Inherit previous objects material.
+			// Spec tells us that a declared material must be set to all objects until a new material is declared.
+			// If a usemtl declaration is encountered while this new object is being parsed, it will
+			// overwrite the inherited material. Exception being that there was already face declarations
+			// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
+
+			if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
+
+				const declared = previousMaterial.clone( 0 );
+				declared.inherited = true;
+				this.object.materials.push( declared );
+
+			}
+
+			this.objects.push( this.object );
+
+		},
+
+		finalize: function () {
+
+			if ( this.object && typeof this.object._finalize === 'function' ) {
+
+				this.object._finalize( true );
+
+			}
+
+		},
+
+		parseVertexIndex: function ( value, len ) {
+
+			const index = parseInt( value, 10 );
+			return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
+
+		},
+
+		parseNormalIndex: function ( value, len ) {
+
+			const index = parseInt( value, 10 );
+			return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
+
+		},
+
+		parseUVIndex: function ( value, len ) {
+
+			const index = parseInt( value, 10 );
+			return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
+
+		},
+
+		addVertex: function ( a, b, c ) {
+
+			const src = this.vertices;
+			const dst = this.object.geometry.vertices;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+			dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+			dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+
+		},
+
+		addVertexPoint: function ( a ) {
+
+			const src = this.vertices;
+			const dst = this.object.geometry.vertices;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+
+		},
+
+		addVertexLine: function ( a ) {
+
+			const src = this.vertices;
+			const dst = this.object.geometry.vertices;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+
+		},
+
+		addNormal: function ( a, b, c ) {
+
+			const src = this.normals;
+			const dst = this.object.geometry.normals;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+			dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+			dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+
+		},
+
+		addFaceNormal: function ( a, b, c ) {
+
+			const src = this.vertices;
+			const dst = this.object.geometry.normals;
+
+			_vA.fromArray( src, a );
+			_vB.fromArray( src, b );
+			_vC.fromArray( src, c );
+
+			_cb.subVectors( _vC, _vB );
+			_ab.subVectors( _vA, _vB );
+			_cb.cross( _ab );
+
+			_cb.normalize();
+
+			dst.push( _cb.x, _cb.y, _cb.z );
+			dst.push( _cb.x, _cb.y, _cb.z );
+			dst.push( _cb.x, _cb.y, _cb.z );
+
+		},
+
+		addColor: function ( a, b, c ) {
+
+			const src = this.colors;
+			const dst = this.object.geometry.colors;
+
+			if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+			if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+			if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+
+		},
+
+		addUV: function ( a, b, c ) {
+
+			const src = this.uvs;
+			const dst = this.object.geometry.uvs;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ] );
+			dst.push( src[ b + 0 ], src[ b + 1 ] );
+			dst.push( src[ c + 0 ], src[ c + 1 ] );
+
+		},
+
+		addDefaultUV: function () {
+
+			const dst = this.object.geometry.uvs;
+
+			dst.push( 0, 0 );
+			dst.push( 0, 0 );
+			dst.push( 0, 0 );
+
+		},
+
+		addUVLine: function ( a ) {
+
+			const src = this.uvs;
+			const dst = this.object.geometry.uvs;
+
+			dst.push( src[ a + 0 ], src[ a + 1 ] );
+
+		},
+
+		addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
+
+			const vLen = this.vertices.length;
+
+			let ia = this.parseVertexIndex( a, vLen );
+			let ib = this.parseVertexIndex( b, vLen );
+			let ic = this.parseVertexIndex( c, vLen );
+
+			this.addVertex( ia, ib, ic );
+			this.addColor( ia, ib, ic );
+
+			// normals
+
+			if ( na !== undefined && na !== '' ) {
+
+				const nLen = this.normals.length;
+
+				ia = this.parseNormalIndex( na, nLen );
+				ib = this.parseNormalIndex( nb, nLen );
+				ic = this.parseNormalIndex( nc, nLen );
+
+				this.addNormal( ia, ib, ic );
+
+			} else {
+
+				this.addFaceNormal( ia, ib, ic );
+
+			}
+
+			// uvs
+
+			if ( ua !== undefined && ua !== '' ) {
+
+				const uvLen = this.uvs.length;
+
+				ia = this.parseUVIndex( ua, uvLen );
+				ib = this.parseUVIndex( ub, uvLen );
+				ic = this.parseUVIndex( uc, uvLen );
+
+				this.addUV( ia, ib, ic );
+
+				this.object.geometry.hasUVIndices = true;
+
+			} else {
+
+				// add placeholder values (for inconsistent face definitions)
+
+				this.addDefaultUV();
+
+			}
+
+		},
+
+		addPointGeometry: function ( vertices ) {
+
+			this.object.geometry.type = 'Points';
+
+			const vLen = this.vertices.length;
+
+			for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
+
+				const index = this.parseVertexIndex( vertices[ vi ], vLen );
+
+				this.addVertexPoint( index );
+				this.addColor( index );
+
+			}
+
+		},
+
+		addLineGeometry: function ( vertices, uvs ) {
+
+			this.object.geometry.type = 'Line';
+
+			const vLen = this.vertices.length;
+			const uvLen = this.uvs.length;
+
+			for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
+
+				this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
+
+			}
+
+			for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
+
+				this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
+
+			}
+
+		}
+
+	};
+
+	state.startObject( '', false );
+
+	return state;
+
+}
+
+//
+
+class OBJLoader extends Loader {
+
+	constructor( manager ) {
+
+		super( manager );
+
+		this.materials = null;
+
+	}
+
+	load( url, onLoad, onProgress, onError ) {
+
+		const scope = this;
+
+		const loader = new FileLoader( this.manager );
+		loader.setPath( this.path );
+		loader.setRequestHeader( this.requestHeader );
+		loader.setWithCredentials( this.withCredentials );
+		loader.load( url, function ( text ) {
+
+			try {
+
+				onLoad( scope.parse( text ) );
+
+			} catch ( e ) {
+
+				if ( onError ) {
+
+					onError( e );
+
+				} else {
+
+					console.error( e );
+
+				}
+
+				scope.manager.itemError( url );
+
+			}
+
+		}, onProgress, onError );
+
+	}
+
+	setMaterials( materials ) {
+
+		this.materials = materials;
+
+		return this;
+
+	}
+
+	parse( text ) {
+
+		const state = new ParserState();
+
+		if ( text.indexOf( '\r\n' ) !== - 1 ) {
+
+			// This is faster than String.split with regex that splits on both
+			text = text.replace( /\r\n/g, '\n' );
+
+		}
+
+		if ( text.indexOf( '\\\n' ) !== - 1 ) {
+
+			// join lines separated by a line continuation character (\)
+			text = text.replace( /\\\n/g, '' );
+
+		}
+
+		const lines = text.split( '\n' );
+		let result = [];
+
+		for ( let i = 0, l = lines.length; i < l; i ++ ) {
+
+			const line = lines[ i ].trimStart();
+
+			if ( line.length === 0 ) continue;
+
+			const lineFirstChar = line.charAt( 0 );
+
+			// @todo invoke passed in handler if any
+			if ( lineFirstChar === '#' ) continue;
+
+			if ( lineFirstChar === 'v' ) {
+
+				const data = line.split( _face_vertex_data_separator_pattern );
+
+				switch ( data[ 0 ] ) {
+
+					case 'v':
+						state.vertices.push(
+							parseFloat( data[ 1 ] ),
+							parseFloat( data[ 2 ] ),
+							parseFloat( data[ 3 ] )
+						);
+						if ( data.length >= 7 ) {
+
+							_color.setRGB(
+								parseFloat( data[ 4 ] ),
+								parseFloat( data[ 5 ] ),
+								parseFloat( data[ 6 ] )
+							).convertSRGBToLinear();
+
+							state.colors.push( _color.r, _color.g, _color.b );
+
+						} else {
+
+							// if no colors are defined, add placeholders so color and vertex indices match
+
+							state.colors.push( undefined, undefined, undefined );
+
+						}
+
+						break;
+					case 'vn':
+						state.normals.push(
+							parseFloat( data[ 1 ] ),
+							parseFloat( data[ 2 ] ),
+							parseFloat( data[ 3 ] )
+						);
+						break;
+					case 'vt':
+						state.uvs.push(
+							parseFloat( data[ 1 ] ),
+							parseFloat( data[ 2 ] )
+						);
+						break;
+
+				}
+
+			} else if ( lineFirstChar === 'f' ) {
+
+				const lineData = line.slice( 1 ).trim();
+				const vertexData = lineData.split( _face_vertex_data_separator_pattern );
+				const faceVertices = [];
+
+				// Parse the face vertex data into an easy to work with format
+
+				for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {
+
+					const vertex = vertexData[ j ];
+
+					if ( vertex.length > 0 ) {
+
+						const vertexParts = vertex.split( '/' );
+						faceVertices.push( vertexParts );
+
+					}
+
+				}
+
+				// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
+
+				const v1 = faceVertices[ 0 ];
+
+				for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
+
+					const v2 = faceVertices[ j ];
+					const v3 = faceVertices[ j + 1 ];
+
+					state.addFace(
+						v1[ 0 ], v2[ 0 ], v3[ 0 ],
+						v1[ 1 ], v2[ 1 ], v3[ 1 ],
+						v1[ 2 ], v2[ 2 ], v3[ 2 ]
+					);
+
+				}
+
+			} else if ( lineFirstChar === 'l' ) {
+
+				const lineParts = line.substring( 1 ).trim().split( ' ' );
+				let lineVertices = [];
+				const lineUVs = [];
+
+				if ( line.indexOf( '/' ) === - 1 ) {
+
+					lineVertices = lineParts;
+
+				} else {
+
+					for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {
+
+						const parts = lineParts[ li ].split( '/' );
+
+						if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
+						if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
+
+					}
+
+				}
+
+				state.addLineGeometry( lineVertices, lineUVs );
+
+			} else if ( lineFirstChar === 'p' ) {
+
+				const lineData = line.slice( 1 ).trim();
+				const pointData = lineData.split( ' ' );
+
+				state.addPointGeometry( pointData );
+
+			} else if ( ( result = _object_pattern.exec( line ) ) !== null ) {
+
+				// o object_name
+				// or
+				// g group_name
+
+				// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
+				// let name = result[ 0 ].slice( 1 ).trim();
+				const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 );
+
+				state.startObject( name );
+
+			} else if ( _material_use_pattern.test( line ) ) {
+
+				// material
+
+				state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
+
+			} else if ( _material_library_pattern.test( line ) ) {
+
+				// mtl file
+
+				state.materialLibraries.push( line.substring( 7 ).trim() );
+
+			} else if ( _map_use_pattern.test( line ) ) {
+
+				// the line is parsed but ignored since the loader assumes textures are defined MTL files
+				// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
+
+				console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
+
+			} else if ( lineFirstChar === 's' ) {
+
+				result = line.split( ' ' );
+
+				// smooth shading
+
+				// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
+				// but does not define a usemtl for each face set.
+				// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
+				// This requires some care to not create extra material on each smooth value for "normal" obj files.
+				// where explicit usemtl defines geometry groups.
+				// Example asset: examples/models/obj/cerberus/Cerberus.obj
+
+				/*
+					 * http://paulbourke.net/dataformats/obj/
+					 *
+					 * From chapter "Grouping" Syntax explanation "s group_number":
+					 * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
+					 * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
+					 * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
+					 * than 0."
+					 */
+				if ( result.length > 1 ) {
+
+					const value = result[ 1 ].trim().toLowerCase();
+					state.object.smooth = ( value !== '0' && value !== 'off' );
+
+				} else {
+
+					// ZBrush can produce "s" lines #11707
+					state.object.smooth = true;
+
+				}
+
+				const material = state.object.currentMaterial();
+				if ( material ) material.smooth = state.object.smooth;
+
+			} else {
+
+				// Handle null terminated files without exception
+				if ( line === '\0' ) continue;
+
+				console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
+
+			}
+
+		}
+
+		state.finalize();
+
+		const container = new Group();
+		container.materialLibraries = [].concat( state.materialLibraries );
+
+		const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
+
+		if ( hasPrimitives === true ) {
+
+			for ( let i = 0, l = state.objects.length; i < l; i ++ ) {
+
+				const object = state.objects[ i ];
+				const geometry = object.geometry;
+				const materials = object.materials;
+				const isLine = ( geometry.type === 'Line' );
+				const isPoints = ( geometry.type === 'Points' );
+				let hasVertexColors = false;
+
+				// Skip o/g line declarations that did not follow with any faces
+				if ( geometry.vertices.length === 0 ) continue;
+
+				const buffergeometry = new BufferGeometry();
+
+				buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) );
+
+				if ( geometry.normals.length > 0 ) {
+
+					buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) );
+
+				}
+
+				if ( geometry.colors.length > 0 ) {
+
+					hasVertexColors = true;
+					buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) );
+
+				}
+
+				if ( geometry.hasUVIndices === true ) {
+
+					buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) );
+
+				}
+
+				// Create materials
+
+				const createdMaterials = [];
+
+				for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
+
+					const sourceMaterial = materials[ mi ];
+					const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
+					let material = state.materials[ materialHash ];
+
+					if ( this.materials !== null ) {
+
+						material = this.materials.create( sourceMaterial.name );
+
+						// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
+						if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) {
+
+							const materialLine = new LineBasicMaterial();
+							Material.prototype.copy.call( materialLine, material );
+							materialLine.color.copy( material.color );
+							material = materialLine;
+
+						} else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) {
+
+							const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } );
+							Material.prototype.copy.call( materialPoints, material );
+							materialPoints.color.copy( material.color );
+							materialPoints.map = material.map;
+							material = materialPoints;
+
+						}
+
+					}
+
+					if ( material === undefined ) {
+
+						if ( isLine ) {
+
+							material = new LineBasicMaterial();
+
+						} else if ( isPoints ) {
+
+							material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
+
+						} else {
+
+							material = new MeshPhongMaterial();
+
+						}
+
+						material.name = sourceMaterial.name;
+						material.flatShading = sourceMaterial.smooth ? false : true;
+						material.vertexColors = hasVertexColors;
+
+						state.materials[ materialHash ] = material;
+
+					}
+
+					createdMaterials.push( material );
+
+				}
+
+				// Create mesh
+
+				let mesh;
+
+				if ( createdMaterials.length > 1 ) {
+
+					for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
+
+						const sourceMaterial = materials[ mi ];
+						buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
+
+					}
+
+					if ( isLine ) {
+
+						mesh = new LineSegments( buffergeometry, createdMaterials );
+
+					} else if ( isPoints ) {
+
+						mesh = new Points( buffergeometry, createdMaterials );
+
+					} else {
+
+						mesh = new Mesh( buffergeometry, createdMaterials );
+
+					}
+
+				} else {
+
+					if ( isLine ) {
+
+						mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] );
+
+					} else if ( isPoints ) {
+
+						mesh = new Points( buffergeometry, createdMaterials[ 0 ] );
+
+					} else {
+
+						mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] );
+
+					}
+
+				}
+
+				mesh.name = object.name;
+
+				container.add( mesh );
+
+			}
+
+		} else {
+
+			// if there is only the default parser state object with no geometry data, interpret data as point cloud
+
+			if ( state.vertices.length > 0 ) {
+
+				const material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
+
+				const buffergeometry = new BufferGeometry();
+
+				buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) );
+
+				if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
+
+					buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) );
+					material.vertexColors = true;
+
+				}
+
+				const points = new Points( buffergeometry, material );
+				container.add( points );
+
+			}
+
+		}
+
+		return container;
+
+	}
+
+}
+
+export { OBJLoader };

File diff suppressed because it is too large
+ 13013 - 0
platforms/h5/common/three.js


BIN
static/.DS_Store


BIN
static/images/.DS_Store


BIN
static/images/baobei-img.png


BIN
static/images/baobei.png


BIN
static/images/baobei1.png


BIN
static/images/code.png


BIN
static/images/dataCenter1-1.png


BIN
static/images/dijia-bg.png


BIN
static/images/explain.png


BIN
static/images/head.png


BIN
static/images/hot.png


BIN
static/images/huifu.png


BIN
static/images/index-img1.png


BIN
static/images/index-img2.png


BIN
static/images/index.png


BIN
static/images/index1.png


BIN
static/images/jifen.png


BIN
static/images/jindu.png


BIN
static/images/jindu1.png


BIN
static/images/mine-tabs1.png


BIN
static/images/mine-tabs2.png


BIN
static/images/mine-tabs3.png


Some files were not shown because too many files changed in this diff