ソースを参照

Merge branch 'main' of http://git.ycjcjy.com/marketing/miniapp into main

1002884655 3 年 前
コミット
4474b25e4e

+ 2
- 2
config/dev.js ファイルの表示

@@ -6,8 +6,8 @@ module.exports = {
6 6
     HOST: '"https://xlk.njyz.tech"',
7 7
     // HOST: '"http://127.0.0.1:8081"',
8 8
     WSS_HOST: '"wss://xlk.njyz.tech"',
9
-    OSS_PATH: '"https://zhiyun-image.oss-accelerate.aliyuncs.com/"',
10
-    OSS_FAST_PATH: '"https://zhiyun-image.oss-accelerate.aliyuncs.com/"',
9
+    OSS_PATH: '"https://xlk-assets.oss-accelerate.aliyuncs.com/"',
10
+    OSS_FAST_PATH: '"https://xlk-assets.oss-accelerate.aliyuncs.com/"',
11 11
     ICON_FONT: '"https://yz-websit.oss-cn-hangzhou.aliyuncs.com/xlk/css/iconfont.ttf"',
12 12
     Version: '"V3.5.29-20201112"'
13 13
   },

+ 9
- 3
src/app.jsx ファイルの表示

@@ -10,6 +10,8 @@ import trackUserSource from '@/utils/tracking/userSource'
10 10
 import './app.scss'
11 11
 
12 12
 class App extends Component {
13
+  // 是否登录
14
+  logged;
13 15
   // 更新埋点
14 16
   updateTracking;
15 17
 
@@ -19,7 +21,9 @@ class App extends Component {
19 21
     // 保留初始场景
20 22
     Taro.setStorage({ key: 'scene', data: options.scene })
21 23
     // 埋点
22
-    trackUserSource(options).then((res) => (this.updateTracking = res))
24
+    if (this.logged) {
25
+      trackUserSource(options).then((res) => (this.updateTracking = res))
26
+    }
23 27
   }
24 28
 
25 29
   componentDidHide () {
@@ -72,8 +76,10 @@ class App extends Component {
72 76
           // 初始化 im
73 77
           im.init(personId)
74 78
 
75
-          // // 埋点
76
-          // trackUserSource(router.params).then(r => this.updateTrack = r)
79
+          this.logged = true
80
+
81
+          // 埋点
82
+          trackUserSource(options).then((x) => (this.updateTracking = x))
77 83
         })
78 84
       })
79 85
     })

+ 6
- 0
src/constants/api.js ファイルの表示

@@ -263,3 +263,9 @@ export const API_TEMPLATE_TYPE = resolvePath('template/of/')
263 263
 // 品牌商
264 264
 export const API_BRAND_LIST = resolvePath('brand')
265 265
 export const API_BRAND_INFO = resolvePath('brand')
266
+
267
+
268
+// 品牌商
269
+export const API_POLICYTYPE_LIST = resolvePath('taPolicyType')
270
+// export const API_BRAND_INFO = resolvePath('brand')
271
+// GET /api/{plat}/taPolicyType

+ 6
- 0
src/layout/index.js ファイルの表示

@@ -8,6 +8,7 @@ import AuthAvatar from '@/components/Auth/AuthAvatar'
8 8
 import AuthPhone from '@/components/Auth/AuthPhone'
9 9
 import Spin from '@/components/Spin/Spin2'
10 10
 import FixedConsultant from '@/components/FixedConsultant'
11
+import { report as reportCustomer } from '@/utils/customer'
11 12
 import { ROLE_CODE } from '@/constants/user'
12 13
 import useAuth from './useAuth'
13 14
 import { routes } from '../routes'
@@ -31,6 +32,11 @@ export default (ChildComponent) => (props) => {
31 32
   // 页面埋点
32 33
   const [trackData, setTrackData] = useState({})
33 34
 
35
+  // 报备客户
36
+  useEffect(() => {
37
+    reportCustomer(person, consultant, false).catch(() => {})
38
+  }, [person, consultant])
39
+
34 40
   // 请求埋点设置
35 41
   useEffect(() => {
36 42
     if (id) {

+ 4
- 2
src/pages/index/buildingList/index.jsx ファイルの表示

@@ -13,7 +13,9 @@ import FilterForHouseType from './components/FilterForHouseType/index'
13 13
 import FilterForMore from './components/FilterForMore/index'
14 14
 import FilterForHouseSort from './components/FilterForHouseSort/index'
15 15
 
16
-export default withLayout(() => {
16
+export default withLayout((props) => {
17
+  const { router } = props
18
+  const { isRecentOpening } = router.params
17 19
 
18 20
   const city = useSelector(state => state.city)
19 21
   const [PageList, setPageList] = useState([])
@@ -87,7 +89,7 @@ export default withLayout(() => {
87 89
         Data[key] = FilterData[key]
88 90
       }
89 91
     }
90
-    fetch({ url: API_ITEMS_LIST, method: 'get', payload: { cityId: city.curCity.id, pageNumber, pageSize, ...Data } }).then((res) => {
92
+    fetch({ url: API_ITEMS_LIST, method: 'get', payload: { cityId: city.curCity.id, pageNumber, pageSize, isRecentOpening, ...Data } }).then((res) => {
91 93
       setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
92 94
       setHasNextPage(res.current < res.pages)
93 95
       setPull(false)

+ 51
- 34
src/pages/index/encyDetail/index.jsx ファイルの表示

@@ -1,52 +1,69 @@
1
-import React, { useState, useEffect } from 'react'
2
-import withLayout from '@/layout'
3
-import './index.scss'
4
-import { ScrollView } from '@tarojs/components'
5
-import '@/assets/css/iconfont.css'
6
-import { Image, RichText } from '@tarojs/components'
1
+import React, { useState, useEffect } from "react";
2
+import Taro from "@tarojs/taro";
3
+import withLayout from "@/layout";
4
+import "./index.scss";
5
+import { ScrollView } from "@tarojs/components";
6
+import "@/assets/css/iconfont.css";
7
+import { Image, RichText } from "@tarojs/components";
8
+import { queryPolicyDetail } from "@/services/policy";
9
+import getDateFormat from "@/utils/chatDate";
7 10
 
8 11
 export default withLayout((props) => {
12
+  const { router, shareContent, trackData, person, page } = props;
13
+  const { id } = router.params;
14
+  const [data, setData] = useState({});
9 15
 
10
-  // const [PageProps] = useState(props)
16
+  const getData = (params) => {
17
+    Taro.showLoading();
18
+    queryPolicyDetail(params).then((res) => {
19
+      setData(res);
20
+      Taro.hideLoading();
21
+    });
22
+  };
23
+  useEffect(() => {
24
+    if (id) {
25
+      getData(id);
26
+    }
27
+  }, [id]);
11 28
 
12 29
   return (
13
-    <view className='Page encyDetail flex-v'>
14
-      <view className='flex-item'>
30
+    <view className="Page encyDetail flex-v">
31
+      <view className="flex-item">
15 32
         <view>
16
-          <ScrollView scroll-y={true} refresher-enabled={false} refresher-background='#fff'>
17
-            <view className='PageContent'>
18
-
19
-              <view className='Info'>
33
+          <ScrollView
34
+            scroll-y={true}
35
+            refresher-enabled={false}
36
+            refresher-background="#fff"
37
+          >
38
+            <view className="PageContent">
39
+              <view className="Info">
20 40
                 <view>
21
-                  <text className='Title'>公积金又有新变化,附最新南京公积金贷款和提取方法。</text>
41
+                  <text className="Title">
42
+                    {data.title} {data.subtitle}
43
+                  </text>
22 44
                   <view>
23
-                    <text>阅读:28</text>
24
-                    <text>点赞15</text>
25
-                    <text>收藏22</text>
45
+                  <text>阅读:{data.pvNum}</text>
46
+                    <text className="Time">
47
+                      {getDateFormat(
48
+                        new Date(data.createDate).valueOf(),
49
+                        true,
50
+                        "yyyy-M-d"
51
+                      )}
52
+                    </text>
53
+                   
26 54
                   </view>
27
-                  <text className='Time'>时间:2019-10-20 10:00 </text>
28
-                  <text className='Share'>分享好友</text>
29 55
                 </view>
30 56
               </view>
31 57
 
32
-              <view className='Content'>
33
-                <RichText nodes={'<p>这是内容</p>'}></RichText>
58
+              <view className="Content">
59
+                <RichText nodes={data.body}></RichText>
34 60
               </view>
35
-
36 61
             </view>
37 62
           </ScrollView>
38 63
         </view>
39 64
       </view>
40
-      <view className='Bottom'>
41
-        <view>
42
-          <Image mode='heightFix' src={require('../../../assets/buildingDetail-icon3.png')}></Image>
43
-          <text>生成海报</text>
44
-        </view>
45
-        <view>
46
-          <text className='iconfont icon-shoucang'></text>
47
-          <text>收藏</text>
48
-        </view>
49
-      </view>
65
+    
66
+    
50 67
     </view>
51
-  )
52
-})
68
+  );
69
+});

+ 1
- 1
src/pages/index/encyDetail/index.scss ファイルの表示

@@ -54,7 +54,7 @@
54 54
                 display: block;
55 55
                 font-size: 28px;
56 56
                 color: #333;
57
-                margin-top: 20px;
57
+                float: right;
58 58
               }
59 59
               >.Share {
60 60
                 display: block;

+ 149
- 48
src/pages/index/encyclopediasOfBuyHouse/index.jsx ファイルの表示

@@ -1,56 +1,157 @@
1
-import React, { useState, useEffect } from 'react'
2
-import withLayout from '@/layout'
3
-import './index.scss'
4
-import { ScrollView, Image } from '@tarojs/components'
5
-import '@/assets/css/iconfont.css'
6
-import Taro from '@tarojs/taro'
1
+import React, { useState, useEffect } from "react";
2
+import withLayout from "@/layout";
3
+import "./index.scss";
4
+import { useSelector } from "react-redux";
5
+import { ScrollView, Image } from "@tarojs/components";
6
+import "@/assets/css/iconfont.css";
7
+import Taro from "@tarojs/taro";
8
+import { fetch } from "@/utils/request";
9
+import { queryPolicyTypeList, queryPolicyList } from "@/services/policy";
7 10
 
8
-export default withLayout((props) => {
11
+const EncyItem = (props) => {
12
+  const city = useSelector(state => state.city)
13
+
14
+  const { item, index } = props;
15
+  const [list, setList] = useState([]);
16
+
17
+  useEffect(() => {
18
+    if (item.policyTypeId) {
19
+      getPolicyListByType(item.policyTypeId);
20
+    }
21
+  }, [item,city]);
9 22
 
23
+  const getPolicyListByType = policyTypeId => {
24
+    queryPolicyList({ pageSize: 100,policyTypeId,cityId: city?.curCity?.id }).then((res) => {
25
+      setList(res.records);
26
+    });
27
+  };
28
+
29
+  return (
30
+    <view key={`ListItem-${index}`}>
31
+      <view className="Title">
32
+        <text>{index + 1 > 9 ? index + 1 : `0${index + 1}`}</text>
33
+        <text>/{item.policyTypeName}</text>
34
+        {/* <Image mode="heightFix" src={item.icon}></Image> */}
35
+      </view>
36
+      <view className="List">
37
+        {list.map((subItem, subIndex) => (
38
+          <view
39
+            key={`subItem-${subIndex}`}
40
+            onClick={() => {
41
+              Taro.navigateTo({
42
+                url: `/pages/index/encyDetail/index?id=${subItem.policyId}`,
43
+              });
44
+            }}
45
+          >
46
+            <text className="Name">{subItem.title}</text>
47
+            {subItem.isHot === 1 && (
48
+              <text className="Tips" style={{ background: "#FF0000" }}>
49
+                {/* {subItem.tips} */}
50
+                HOT
51
+              </text>
52
+            )}
53
+            {/* {subItem.icon !== "" && (
54
+              <Image mode="heightFix" src={subItem.icon}></Image>
55
+            )} */}
56
+          </view>
57
+        ))}
58
+      </view>
59
+    </view>
60
+  );
61
+};
62
+
63
+export default withLayout((props) => {
10 64
   // const [PageProps] = useState(props)
11
-  const [PageList] = useState([
12
-    {name: '准备买房', icon: require('@/assets/ency-icon3.png'), list: [{name: '买房资质查询', id: 1, tips: 'HOT', tipsColor: '#FF0000', icon: ''}, {name: '22个房产名词', id: 2, tips: 'NEW', tipsColor: '#30CFCF', icon: ''}]},
13
-    {name: '看房选房', icon: require('@/assets/ency-icon4.png'), list: [{name: '热门楼盘地图', id: 3, tips: '', icon: ''}, {name: '选户型攻略', id: 4, tips: '实用', tipsColor: '#62D547', icon: ''}, {name: '期房新房怎么选', id: 5, tips: '', icon: ''}]},
14
-    {name: '认筹签约', icon: require('@/assets/ency-icon5.png'), list: [{name: '买房签约流程', id: 6, tips: '哇!', tipsColor: '#FF396C', icon: require('@/assets/ency-icon2.png')}, {name: '契税征收标准', id: 7, tips: '', icon: ''}, {name: '公司名义买房', id: 8, tips: '', icon: ''}]},
15
-    {name: '贷款买房', icon: require('@/assets/ency-icon6.png'), list: [{name: '新房贷政策', id: 9, tips: '', icon: ''}, {name: '贷款查征信', id: 10, tips: '', icon: require('../../../assets/ency-icon1.png')}]}
16
-  ])
17 65
 
66
+  const [PageList, setPageList] = useState([
67
+    {
68
+      name: "准备买房",
69
+      icon: require("@/assets/ency-icon3.png"),
70
+      list: [
71
+        {
72
+          name: "买房资质查询",
73
+          id: 1,
74
+          tips: "HOT",
75
+          tipsColor: "#FF0000",
76
+          icon: "",
77
+        },
78
+        {
79
+          name: "22个房产名词",
80
+          id: 2,
81
+          tips: "NEW",
82
+          tipsColor: "#30CFCF",
83
+          icon: "",
84
+        },
85
+      ],
86
+    },
87
+    {
88
+      name: "看房选房",
89
+      icon: require("@/assets/ency-icon4.png"),
90
+      list: [
91
+        { name: "热门楼盘地图", id: 3, tips: "", icon: "" },
92
+        {
93
+          name: "选户型攻略",
94
+          id: 4,
95
+          tips: "实用",
96
+          tipsColor: "#62D547",
97
+          icon: "",
98
+        },
99
+        { name: "期房新房怎么选", id: 5, tips: "", icon: "" },
100
+      ],
101
+    },
102
+    {
103
+      name: "认筹签约",
104
+      icon: require("@/assets/ency-icon5.png"),
105
+      list: [
106
+        {
107
+          name: "买房签约流程",
108
+          id: 6,
109
+          tips: "哇!",
110
+          tipsColor: "#FF396C",
111
+          icon: require("@/assets/ency-icon2.png"),
112
+        },
113
+        { name: "契税征收标准", id: 7, tips: "", icon: "" },
114
+        { name: "公司名义买房", id: 8, tips: "", icon: "" },
115
+      ],
116
+    },
117
+    {
118
+      name: "贷款买房",
119
+      icon: require("@/assets/ency-icon6.png"),
120
+      list: [
121
+        { name: "新房贷政策", id: 9, tips: "", icon: "" },
122
+        {
123
+          name: "贷款查征信",
124
+          id: 10,
125
+          tips: "",
126
+          icon: require("../../../assets/ency-icon1.png"),
127
+        },
128
+      ],
129
+    },
130
+  ]);
131
+
132
+  const getPageList = () => {
133
+    queryPolicyTypeList({ pageSize: 100 }).then((res) => {
134
+      setPageList(res.records);
135
+    });
136
+  };
137
+  // GET /api/{plat}/taPolicyType
138
+
139
+  useEffect(() => {
140
+    getPageList();
141
+  }, []);
18 142
   return (
19
-    <view className='Page encyclopediasOfBuyHouse'>
20
-
21
-      <ScrollView scroll-y={true} refresher-enabled={false} refresher-background='#fff'>
22
-        <view className='PageContent'>
23
-          {
24
-            PageList.map((item, index) => (
25
-              <view key={`ListItem-${index}`}>
26
-                <view className='Title'>
27
-                  <text>{index + 1 > 9 ? index + 1 : `0${index + 1}`}</text>
28
-                  <text>/{item.name}</text>
29
-                  <Image mode='heightFix' src={item.icon}></Image>
30
-                </view>
31
-                <view className='List'>
32
-                  {
33
-                    item.list.map((subItem, subIndex) => (
34
-                      <view key={`subItem-${subIndex}`} onClick={() => { Taro.navigateTo({ url: `/pages/index/encyDetail/index?id=${subItem.id}` }) }}>
35
-                        <text className='Name'>{subItem.name}</text>
36
-                        {
37
-                          subItem.tips !== '' &&
38
-                          <text className='Tips' style={{background: subItem.tipsColor}}>{subItem.tips}</text>
39
-                        }
40
-                        {
41
-                          subItem.icon !== '' &&
42
-                          <Image mode='heightFix' src={subItem.icon}></Image>
43
-                        }
44
-                      </view>
45
-                    ))
46
-                  }
47
-                </view>
48
-              </view>
49
-            ))
50
-          }
143
+    <view className="Page encyclopediasOfBuyHouse">
144
+      <ScrollView
145
+        scroll-y={true}
146
+        refresher-enabled={false}
147
+        refresher-background="#fff"
148
+      >
149
+        <view className="PageContent">
150
+          {PageList.map((item, index) => (
151
+            <EncyItem item={item} key={index} index={index}></EncyItem>
152
+          ))}
51 153
         </view>
52 154
       </ScrollView>
53
-
54 155
     </view>
55
-  )
56
-})
156
+  );
157
+});

+ 1
- 0
src/pages/index/encyclopediasOfBuyHouse/index.scss ファイルの表示

@@ -63,6 +63,7 @@
63 63
               color: #333;
64 64
               position: relative;
65 65
               z-index: 1;
66
+              padding: 0 20px;
66 67
             }
67 68
             >.Tips {
68 69
               display: inline-block;

+ 3
- 0
src/routes.js ファイルの表示

@@ -44,6 +44,7 @@ const routes = [
44 44
     page: 'pages/chat/chatDetail/index',
45 45
     pkg: 'main',
46 46
     type: 'other',
47
+    auth: ['phone', 'avatar'],
47 48
   },
48 49
 
49 50
   // /********************************
@@ -131,6 +132,7 @@ const routes = [
131 132
     page: 'pages/index/buildingTakeLook/index',
132 133
     pkg: 'main',
133 134
     type: 'building',
135
+    auth: ['phone', 'avatar'],
134 136
   },
135 137
   {
136 138
     name: '项目动态',
@@ -173,6 +175,7 @@ const routes = [
173 175
     page: 'pages/index/activityDetail/index',
174 176
     pkg: 'main',
175 177
     type: 'activity',
178
+    auth: ['phone', 'avatar'],
176 179
   },
177 180
   {
178 181
     name: '特价房',

+ 7
- 0
src/services/policy.js ファイルの表示

@@ -1,8 +1,15 @@
1 1
 import { fetch } from '@/utils/request'
2 2
 import {
3 3
   API_POLICY_LIST,
4
+  API_POLICYTYPE_LIST
4 5
 } from '@/constants/api'
5 6
 
7
+/**
8
+ * 获取列表
9
+ * @param {*} payload
10
+ */
11
+ export const queryPolicyTypeList = payload => fetch({ url: API_POLICYTYPE_LIST, payload })
12
+
6 13
 
7 14
 /**
8 15
  * 获取列表

+ 42
- 0
src/utils/customer.js ファイルの表示

@@ -0,0 +1,42 @@
1
+
2
+import { reportClient } from '@/services/report'
3
+
4
+/**
5
+ * 报备客户
6
+ * @param {*} userInfo 
7
+ * @param {*} consultant 
8
+ * @param {*} showToast 
9
+ */
10
+function report(person, consultant, showToast) {
11
+  if (!person || !(person.tel || person.phone)) {
12
+    return Promise.reject('用户手机号不存在');
13
+  }
14
+
15
+  if (!consultant || !consultant.id) {
16
+    return Promise.reject('置业顾问信息不存在');
17
+  }
18
+
19
+  if (consultant.id == person.personId) {
20
+    return Promise.resolve();
21
+  }
22
+
23
+  const realPhone = person.tel || person.phone
24
+  const payload = {
25
+    realtyConsultant: consultant.id, //报备人 置业顾问
26
+    phone: realPhone,
27
+    showToast,
28
+  }
29
+
30
+  return new Promise((resolve, reject) => {
31
+    reportClient(payload).then(res => {
32
+      resolve()
33
+    }).catch(err => {
34
+      console.error(err)
35
+      reject(err.message || err)
36
+    })
37
+  })
38
+}
39
+
40
+export {
41
+  report,
42
+}

+ 2
- 0
src/utils/login.js ファイルの表示

@@ -58,6 +58,8 @@ export default (payload) => {
58 58
             })
59 59
           }
60 60
 
61
+          // 如果通过扫码进入
62
+
61 63
         }).catch(reject)
62 64
       }
63 65
     })

+ 34
- 0
src/utils/qrcode.js ファイルの表示

@@ -0,0 +1,34 @@
1
+
2
+import { getCodeScene  } from '@/services/common'
3
+import { parseQueryString } from './tools'
4
+
5
+/**
6
+ * 获取二维码参数
7
+ * 微信小程序  基础库 2.1.2 开始支持
8
+ * @param {*} scene 场景值
9
+ */
10
+export function getQrCodeParams(sceneID) {
11
+  if (!sceneID) {
12
+    console.error('未解析到二维码场景值')
13
+    return Promise.reject('未解析到二维码场景值')
14
+  }
15
+
16
+  console.log('解析到二维码场景 ID', sceneID)
17
+
18
+  return new Promise((resolve, reject) => {
19
+    getCodeScene(sceneID).then((res) => {
20
+      const data = typeof res === 'string' ? JSON.parse(res) : res
21
+      const params = parseQueryString(data.scene || '')
22
+
23
+      console.log('解析到二维码场景参数: ', params)
24
+
25
+      resolve({
26
+        ...params,
27
+        '__raw': data.scene,
28
+      })
29
+    }).catch(err => {
30
+      console.error('解析二维码场景参数失败', err)
31
+      reject('解析二维码场景参数失败')
32
+    })
33
+  })
34
+}

+ 14
- 1
src/utils/request.js ファイルの表示

@@ -89,12 +89,25 @@ export function optionBuilder(options) {
89 89
   const showMessage = Object.prototype.hasOwnProperty.call(payload, 'showToast') ? payload.showToast : showToast
90 90
   const consultant = Taro.getStorageSync('consultantId') || ''
91 91
   const recommender = Taro.getStorageSync('recommender') || ''
92
+
93
+  // 去掉 null 跟 undefined 字段
94
+  const data = Object.keys(payload).reduce((acc, key) => {
95
+    const val = payload[key]
96
+    if (val === null || val === undefined) {
97
+      return acc;
98
+    }
99
+
100
+    return {
101
+      ...acc,
102
+      [key]: val,
103
+    }
104
+  }, {})
92 105
   
93 106
   return [
94 107
     {
95 108
       url,
96 109
       method,
97
-      data: payload,
110
+      data,
98 111
       header: {
99 112
         'content-type': 'application/json',
100 113
         'authorization': `Bearer ${Taro.getStorageSync('token')}`,