浏览代码

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

1002884655 3 年前
父节点
当前提交
f287d58e78
共有 39 个文件被更改,包括 628 次插入365 次删除
  1. 1
    1
      config/dev.js
  2. 1
    0
      config/index.js
  3. 8
    1
      src/app.jsx
  4. 1
    1
      src/assets/css/iconfont.json
  5. 7
    2
      src/components/Auth/AuthPhone.jsx
  6. 15
    4
      src/components/Auth/useAuth.js
  7. 5
    3
      src/components/Poster/index.jsx
  8. 8
    2
      src/components/Poster/style.scss
  9. 3
    3
      src/constants/api.js
  10. 35
    5
      src/layout/index.js
  11. 5
    9
      src/layout/useAuth.js
  12. 66
    0
      src/native/PageContainer/index.js
  13. 3
    0
      src/native/PageContainer/index.json
  14. 19
    0
      src/native/PageContainer/index.wxml
  15. 0
    0
      src/native/PageContainer/index.wxss
  16. 112
    171
      src/pages/index/activityDetail/index.jsx
  17. 3
    3
      src/pages/index/buildingDetail/components/Banner/index.jsx
  18. 3
    3
      src/pages/index/buildingDetail/components/BasicInfo/index.jsx
  19. 61
    27
      src/pages/index/buildingDetail/components/BuildingDetailBanner/index.jsx
  20. 6
    6
      src/pages/index/buildingDetail/components/DetailBottom/index.jsx
  21. 15
    4
      src/pages/index/buildingDetail/components/LivingActivity/index.jsx
  22. 34
    6
      src/pages/index/buildingDetail/components/News/index.jsx
  23. 9
    2
      src/pages/index/buildingDetail/components/ProjectDynamic/index.jsx
  24. 0
    23
      src/pages/index/buildingDetail/hooks/useBuildingPoster.js
  25. 0
    32
      src/pages/index/buildingDetail/hooks/useBuildingShare.js
  26. 3
    0
      src/pages/index/buildingDetail/index.config.js
  27. 31
    20
      src/pages/index/buildingDetail/index.jsx
  28. 1
    1
      src/pages/index/index.config.js
  29. 3
    0
      src/pages/index/webview/index.config.js
  30. 19
    0
      src/pages/index/webview/index.jsx
  31. 6
    0
      src/routes.js
  32. 16
    17
      src/utils/hooks/useFavor.js
  33. 9
    5
      src/utils/hooks/useParams.js
  34. 25
    0
      src/utils/hooks/usePoster.js
  35. 22
    13
      src/utils/hooks/useShare.js
  36. 1
    1
      src/utils/tracking/addNum.js
  37. 19
    0
      src/utils/tracking/share.js
  38. 24
    0
      src/utils/tracking/track.js
  39. 29
    0
      src/utils/tracking/userSource.js

+ 1
- 1
config/dev.js 查看文件

@@ -4,7 +4,7 @@ module.exports = {
4 4
   },
5 5
   defineConstants: {
6 6
     HOST: '"https://xlk.njyz.tech"',
7
-    // HOST: '"http://127.0.0.1:8088"',
7
+    // HOST: '"http://127.0.0.1:8081"',
8 8
     WSS_HOST: '"wss://xlk.njyz.tech"',
9 9
     OSS_PATH: '"https://zhiyun-image.oss-accelerate.aliyuncs.com/"',
10 10
     OSS_FAST_PATH: '"https://zhiyun-image.oss-accelerate.aliyuncs.com/"',

+ 1
- 0
config/index.js 查看文件

@@ -28,6 +28,7 @@ const config = {
28 28
   },
29 29
   copy: {
30 30
     patterns: [
31
+      { from: 'src/native/', to: 'dist/native/' },
31 32
     ],
32 33
     options: {
33 34
     }

+ 8
- 1
src/app.jsx 查看文件

@@ -5,19 +5,26 @@ import { getLocation, getRouterParams } from '@/utils/tools'
5 5
 import login from '@/utils/login'
6 6
 import im from '@/utils/im'
7 7
 import store from './store'
8
+import trackUserSource from '@/utils/tracking/userSource'
8 9
 
9 10
 import './app.scss'
10 11
 
11 12
 class App extends Component {
13
+  // 更新埋点
14
+  updateTracking;
12 15
 
13 16
   componentDidMount () {}
14 17
 
15 18
   componentDidShow (options) {
16 19
     // 保留初始场景
17 20
     Taro.setStorage({ key: 'scene', data: options.scene })
21
+    // 埋点
22
+    trackUserSource(options).then((res) => (this.updateTracking = res))
18 23
   }
19 24
 
20
-  componentDidHide () {}
25
+  componentDidHide () {
26
+    this.updateTracking()
27
+  }
21 28
 
22 29
   componentDidCatchError () {}
23 30
 

+ 1
- 1
src/assets/css/iconfont.json 查看文件

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "id": "2603904",
3
-  "name": "新联",
3
+  "name": "新联",
4 4
   "font_family": "iconfont",
5 5
   "css_prefix_text": "icon-",
6 6
   "description": "",

+ 7
- 2
src/components/Auth/AuthPhone.jsx 查看文件

@@ -6,10 +6,15 @@ import useAuth from './useAuth'
6 6
 import './style.scss'
7 7
 
8 8
 export default (props) => {
9
-  const { onCancel = (x => x) } = props;
9
+  const {
10
+    consultant,
11
+    router,
12
+    page,
13
+    onCancel = (x => x),
14
+  } = props;
10 15
 
11 16
   const [loading, setLoading] = useState(false)
12
-  const { updatePhoneNumber } = useAuth()
17
+  const { updatePhoneNumber } = useAuth(consultant, router, page)
13 18
 
14 19
   const handlePhoneNumber = (detail) => {
15 20
     const { errMsg, ...data } = detail || {}

+ 15
- 4
src/components/Auth/useAuth.js 查看文件

@@ -5,7 +5,7 @@ import { dispatchUpdateUserInfo } from '@/actions/user'
5 5
 import { queryUserPhone } from '@/services/user'
6 6
 import { UPDATE_USER_INFO } from '@/constants/user'
7 7
 
8
-export default function useAuth() {
8
+export default function useAuth(consultant, router, page) {
9 9
   const dispatch = useDispatch()
10 10
 
11 11
   const updateUserInfo = useCallback((data) => {
@@ -24,8 +24,19 @@ export default function useAuth() {
24 24
   const updatePhoneNumber = useCallback((data) => {
25 25
     return new Promise((resolve, reject) => {
26 26
       const sessionKey = Taro.getStorageSync('sessionKey')
27
-      Object.assign(data, { sessionKey })
28
-      queryUserPhone(data).then((res) => {
27
+      const { id: targetId, recommender } = router.params
28
+      const buildingId = router.path.indexOf('pages/index/buildingInfo/index') > -1 ? targetId : undefined
29
+      const params = {
30
+        sessionKey,
31
+        sceneId: router.scene,
32
+        buildingId,
33
+        targetId,
34
+        targetType: page.type,
35
+        targetName: page.name,
36
+        promoter: recommender,
37
+        ...data,
38
+      }
39
+      queryUserPhone(params).then((res) => {
29 40
         dispatch({
30 41
           type: UPDATE_USER_INFO,
31 42
           payload: {
@@ -38,7 +49,7 @@ export default function useAuth() {
38 49
         reject(err)
39 50
       })
40 51
     })
41
-  }, [dispatch])
52
+  }, [dispatch, consultant, router, page])
42 53
 
43 54
   return { updateUserInfo, updatePhoneNumber }
44 55
 }

+ 5
- 3
src/components/Poster/index.jsx 查看文件

@@ -85,8 +85,10 @@ export default (props) => {
85 85
   }
86 86
 
87 87
   return (
88
-    <Modal title={title} visible={show} onClose={onClose}>
89
-      <View className='modal-poster'>
88
+    // <Modal title={title} visible={show} onClose={onClose}>
89
+    // eslint-disable-next-line react/jsx-no-undef
90
+    <page-container show={show} position='bottom' onClickOverlay={onClose}>
91
+      <View className='modal-poster' onClick={onClose}>
90 92
         <View className='modal-poster-img-box'>
91 93
         {
92 94
           !processing
@@ -99,6 +101,6 @@ export default (props) => {
99 101
         </Button>
100 102
       </View>
101 103
       <Poster dataSource={dataSource} onStart={() => setProcessing(true)} onEnd={handlePoster} />
102
-    </Modal>
104
+    </page-container>
103 105
   )
104 106
 }

+ 8
- 2
src/components/Poster/style.scss 查看文件

@@ -1,6 +1,7 @@
1 1
 .modal-poster {
2 2
   width: 100vw;
3
-  height: calc(100vh - 62rpx);
3
+  height: 100vh;
4
+  // height: calc(100vh - 62rpx);
4 5
   box-sizing: border-box;
5 6
   padding: 40rpx;
6 7
 
@@ -31,4 +32,9 @@
31 32
     font-weight: 600;
32 33
     line-height: 90rpx;
33 34
   }
34
-}
35
+}
36
+
37
+page-container {
38
+  position: fixed;
39
+  z-index: 1000;
40
+}

+ 3
- 3
src/constants/api.js 查看文件

@@ -10,7 +10,7 @@ export const wss_host = WSS_HOST
10 10
 
11 11
 export const pathname = '/api/wx'
12 12
 
13
-const resolvePath = api => `${host + pathname}/${api}`
13
+export const resolvePath = api => `${host + pathname}/${api}`
14 14
 
15 15
 // 特价房源
16 16
 export const API_SPECIAL_ROOM_LIST = resolvePath('buildingSpecialRoom') // 特价房源列表
@@ -145,8 +145,8 @@ export const API_INDEX_SHARE = resolvePath('main/share')
145 145
 
146 146
 export const API_ACTIVITY_FAVOR = resolvePath('activity/save')
147 147
 export const API_NEWS_FAVOR = resolvePath('news/save')
148
-export const API_CARD_FAVOR = resolvePath('card/save')
149
-export const API_PROJECT_FAVOR = resolvePath('project/save')
148
+export const API_CARD_FAVOR = resolvePath('consultant/save')
149
+export const API_PROJECT_FAVOR = resolvePath('building/save')
150 150
 
151 151
 // 埋点接口
152 152
 export const API_BURIED_POINT = resolvePath('taPersonVisitRecord')

+ 35
- 5
src/layout/index.js 查看文件

@@ -7,6 +7,7 @@ import Loading from '@/components/Loading'
7 7
 import AuthAvatar from '@/components/Auth/AuthAvatar'
8 8
 import AuthPhone from '@/components/Auth/AuthPhone'
9 9
 import Spin from '@/components/Spin/Spin2'
10
+import { ROLE_CODE } from '@/constants/user'
10 11
 import useAuth from './useAuth'
11 12
 import { routes } from '../routes'
12 13
 
@@ -17,15 +18,41 @@ export default (ChildComponent) => (props) => {
17 18
   const { spinning, userInfo } = useSelector(s => s.user)
18 19
   const { person, ...extInfo } = userInfo || {}
19 20
   const router = useRouter()
21
+  const page = routes.filter((r) => (router.path.indexOf(r.page) > -1))[0]
20 22
   const [loading, setLoading] = useState(false)
21
-  const [authPhone, authAvatar] = useAuth(person)
23
+  const [authPhone, authAvatar] = useAuth(person, page)
24
+
25
+  const { id } = router.params
26
+
27
+  // 页面分享
28
+  const [shareContent, setShareContent] = useState({})
29
+  // 页面埋点
30
+  const [trackData, setTrackData] = useState({})
31
+
32
+  // 请求埋点设置
33
+  useEffect(() => {
34
+    if (id) {
35
+      setShareContent({})
36
+    }
37
+  } ,[id, page.type])
38
+
39
+  // 埋点数据
40
+  useEffect(() => {
41
+    const consultantId = person?.personType === ROLE_CODE.CONSULTANT ? person.personId : undefined
42
+
43
+    setTrackData({
44
+      eventType: page.type,
45
+      propertyName: page.name,
46
+      consultantId,
47
+      sharePersonId: person?.personId,
48
+      targetId: id,
49
+    })
50
+  }, [person, page, id])
22 51
 
23
-  
24 52
   // 主要用于埋点
25 53
   useEffect(() => {
26
-    const page = routes.filter((r) => (router.path.indexOf(r.page) > -1))[0]
27 54
     Taro.setStorage({ key: 'page', data: page })
28
-  }, [router.path])
55
+  }, [page])
29 56
 
30 57
   useEffect(() => {
31 58
     setLoading(!person || !person.personId)
@@ -43,7 +70,7 @@ export default (ChildComponent) => (props) => {
43 70
       </Overlay>
44 71
       <Overlay visible={authPhone} aligin='bottom'>
45 72
         <View className='auth-wrapper'>
46
-          <AuthPhone />
73
+          <AuthPhone consultant={consultant} router={router} page={page} />
47 74
         </View>
48 75
       </Overlay>
49 76
       <Overlay visible={!authPhone && authAvatar} aligin='bottom'>
@@ -58,6 +85,9 @@ export default (ChildComponent) => (props) => {
58 85
             person={person}
59 86
             router={router}
60 87
             consultant={consultant}
88
+            page={page}
89
+            shareContent={shareContent}
90
+            trackData={trackData}
61 91
             {...props}
62 92
             {...extInfo}
63 93
         />

+ 5
- 9
src/layout/useAuth.js 查看文件

@@ -1,17 +1,13 @@
1 1
 import { useState, useEffect } from 'react'
2
-import { useRouter } from '@tarojs/taro'
3
-import { routes } from '../routes'
4 2
 
5
-export default function useAuth(person) {
3
+export default function useAuth(person, page) {
6 4
   const [authPhone, setAuthPhone] = useState(false)
7 5
   const [authAvatar, setAuthAvatar] = useState(false)
8
-  const { path } = useRouter()
9 6
 
10 7
   useEffect(() => {
11
-    const current = routes.filter((route) => path.indexOf(route.page) > -1)[0]
12
-    if (current && current.auth && current.auth.length) {
8
+    if (page && page.auth && page.auth.length) {
13 9
       // 如果需要授权手机
14
-      if (current.auth.indexOf('phone') > -1) {
10
+      if (page.auth.indexOf('phone') > -1) {
15 11
         if (person.inited && !person.phone) {
16 12
           setAuthPhone(true)
17 13
         } else {
@@ -20,7 +16,7 @@ export default function useAuth(person) {
20 16
       }
21 17
 
22 18
       // 如果需要授权头像
23
-      if (current.auth.indexOf('avatar') > -1) {
19
+      if (page.auth.indexOf('avatar') > -1) {
24 20
         if (person.inited && (!person.avatarurl || person.avatarurl.indexOf('default_avatar') > -1)) {
25 21
           setAuthAvatar(true)
26 22
         } else {
@@ -31,7 +27,7 @@ export default function useAuth(person) {
31 27
       setAuthPhone(false)
32 28
       setAuthAvatar(false)
33 29
     }
34
-  }, [person, path])
30
+  }, [person, page])
35 31
 
36 32
   return [authPhone, authAvatar]
37 33
 }

+ 66
- 0
src/native/PageContainer/index.js 查看文件

@@ -0,0 +1,66 @@
1
+Component({
2
+  properties: {
3
+    show: {
4
+      type: Boolean,
5
+      value: false,
6
+    },
7
+    position: {
8
+      type: String,
9
+      value: 'right',
10
+    },
11
+    duration: {
12
+      type: Number,
13
+      value: 300,
14
+    },
15
+    round: {
16
+      type: Boolean,
17
+      value: false,
18
+    },
19
+    overlay: {
20
+      type: Boolean,
21
+      value: true,
22
+    },
23
+    height: {
24
+      type: String,
25
+      value: '100%',
26
+      observer: function(val) {
27
+        const h = val || '100%'
28
+        const customStyle = 'height: '+ h +';'
29
+        this.setData({ customStyle })
30
+      }
31
+    },
32
+    overlayColor: {
33
+      type: String,
34
+      value: 'black',
35
+      observer: function(val) {
36
+        let overlayStyle = ''
37
+        switch(val) {
38
+          case 'white':
39
+            overlayStyle = 'background-color: rgba(255, 255, 255, 0.7)'
40
+            break
41
+          case 'blur':
42
+            overlayStyle = 'background-color: rgba(0, 0, 0, 0.7); filter: blur(4px);'
43
+            break
44
+          default:
45
+            overlayStyle = 'background-color: rgba(0, 0, 0, 0.7)'
46
+        }
47
+        this.setData({ overlayStyle })
48
+      }
49
+    }
50
+  },
51
+  data: {
52
+    customStyle: '',
53
+    overlayStyle: ''
54
+  },
55
+  methods: {
56
+    onBeforeEnter(e) {},
57
+    onEnter(e) {},
58
+    onAfterEnter(e) {},
59
+    onBeforeLeave(e) {},
60
+    onLeave(e) {},
61
+    onAfterLeave(e) {},
62
+    onClickOverlay(e) {
63
+      this.triggerEvent('clickOverlay', e)
64
+    }
65
+  }
66
+})

+ 3
- 0
src/native/PageContainer/index.json 查看文件

@@ -0,0 +1,3 @@
1
+{
2
+  "usingComponents": {}
3
+}

+ 19
- 0
src/native/PageContainer/index.wxml 查看文件

@@ -0,0 +1,19 @@
1
+<page-container 
2
+  show="{{show}}"
3
+  round="{{round}}"
4
+  overlay="{{overlay}}"
5
+  duration="{{duration}}"
6
+  position="{{position}}"
7
+  close-on-slide-down="{{false}}"
8
+  bindbeforeenter="onBeforeEnter"
9
+  bindenter="onEnter"
10
+  bindafterenter="onAfterEnter"
11
+  bindbeforeleave="onBeforeLeave"
12
+  bindleave="onLeave"
13
+  bindafterleave="onAfterLeave"
14
+  bindclickoverlay="onClickOverlay"
15
+  custom-style="{{customStyle}}"
16
+  overlay-style="{{overlayStyle}}"
17
+>
18
+  <slot></slot>
19
+</page-container>

+ 0
- 0
src/native/PageContainer/index.wxss 查看文件


+ 112
- 171
src/pages/index/activityDetail/index.jsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import { useState, useEffect } from "react";
2
-import Taro, { useDidShow, useReady } from "@tarojs/taro";
2
+import Taro from "@tarojs/taro";
3 3
 import withLayout from "@/layout";
4 4
 import {
5 5
   ScrollView,
@@ -11,12 +11,13 @@ import Disclaimer from '@/components/Disclaimer'
11 11
 import {
12 12
   // addActivityShareNum,
13 13
   signupActivity,
14
-  favorActivity,
15
-  cancelFavorActivity,
16 14
   queryActivityDetail,
17 15
 } from "@/services/activity";
18 16
 import { getImgURL } from "@/utils/image";
19 17
 import getDateFormat from "@/utils/chatDate";
18
+import useParams from '@/utils/hooks/useParams'
19
+import useShare from '@/utils/hooks/useShare'
20
+import useFavor from '@/utils/hooks/useFavor'
20 21
 
21 22
 import "./index.scss";
22 23
 
@@ -40,29 +41,10 @@ const activityStatusDict = {
40 41
 };
41 42
 
42 43
 export default withLayout((props) => {
43
-  const { id } = props.router.params;
44
+  const { router, shareContent, trackData, person, page } = props
45
+  const { id } = router.params;
44 46
   const [detail, setDetail] = useState();
45
-  const [canChoose, setCanChoose] = useState("none");
46
-
47
-  const [IsPull, setPull] = useState(false);
48
-  const [PullTimer, setPullTimer] = useState(null);
49
-
50
-  const PageRefresh = () => {
51
-    // 页面下拉刷新回调
52
-    setPull(true);
53
-  };
54
-
55
-  useEffect(() => {
56
-    // 下拉刷新触发
57
-    if (IsPull) {
58
-      clearTimeout(PullTimer);
59
-      setPullTimer(
60
-        setTimeout(() => {
61
-          setPull(false);
62
-        }, 2000)
63
-      );
64
-    }
65
-  }, [IsPull]);
47
+  const buildingId = detail?.buildingId
66 48
 
67 49
   const getDetail = (params) => {
68 50
     Taro.showLoading();
@@ -75,59 +57,28 @@ export default withLayout((props) => {
75 57
     });
76 58
   };
77 59
 
60
+  // 本页面分享或者海报参数
61
+  const paramsRef = useParams({id, buildingId, person, from: `${page.type}_share`})
62
+
63
+  const fullTrackData = { ...trackData, buildingId }
64
+  
65
+  const [isSaved, handleFavor] = useFavor(detail?.isSaved, { id, buildingId, ...trackData })
66
+
67
+  useShare(
68
+    {
69
+      title: shareContent.shareContentTitle || detail?.title,
70
+      path: `${router.path}?${paramsRef.current}`,
71
+      image: shareContent.shareContentImg || getImgURL(detail?.imgUrl),
72
+    },
73
+    fullTrackData,
74
+  )
75
+
78 76
   useEffect(() => {
79 77
     if (id) {
80 78
       getDetail(id);
81 79
     }
82 80
   }, [id]);
83 81
 
84
-  useReady(() => {
85
-    console.log("Taro.showLoading()");
86
-  });
87
-
88
-  useDidShow(() => {
89
-    // Taro.getCurrentPages()
90
-    console.log("Taro.showLoading()");
91
-
92
-    // console.log(Taro.getCurrentPages(),'Taro.showLoading()')
93
-    // getDetail()
94
-  });
95
-
96
-  //收藏
97
-  const handleFavo = () => {
98
-    const { dynamicId, isSaved } = detail;
99
-    if (isSaved) {
100
-      cancelFavorActivity(dynamicId).then((res) => {
101
-        Taro.showToast({
102
-          title: "已取消收藏",
103
-        });
104
-        setDetail({
105
-          ...detail,
106
-          isSaved: 0,
107
-        });
108
-      });
109
-    } else {
110
-      favorActivity(dynamicId).then((res) => {
111
-        Taro.showToast({
112
-          title: "收藏成功",
113
-        });
114
-        setDetail({
115
-          ...detail,
116
-          isSaved: 1,
117
-        });
118
-      });
119
-    }
120
-    // savePoint({
121
-    //   event: 'save',
122
-    //   eventType: 'activity',
123
-    //   targetType: 'dynamic',
124
-    //   propertyName: '活动详情收藏',
125
-    //   data: '{}'
126
-    // }).then(res => {
127
-    //   console.log('活动详情收藏')
128
-    // })
129
-  };
130
-
131 82
   const handleSignup = () => {
132 83
     const {
133 84
       detail: { buildingId, dynamicId, isSign },
@@ -152,116 +103,106 @@ export default withLayout((props) => {
152 103
   };
153 104
 
154 105
   return <>
155
-  {
156
- detail && (
157
-  <view className="Page activityDetail flex-v">
158
-    <view className="flex-item">
159
-      <view>
160
-        <ScrollView
161
-          scroll-y
162
-          refresher-enabled
163
-          refresher-triggered={IsPull}
164
-          onrefresherrefresh={PageRefresh}
165
-          refresher-background="#fff"
166
-        >
167
-          <view className="PageContent">
168
-            <view className="Top">
169
-              <Image
170
-                mode="aspectFill"
171
-                src={getImgURL(detail.bannerListImg)}
172
-                className="centerLabel"
173
-              ></Image>
174
-            </view>
106
+  { detail && (
107
+    <view className="Page activityDetail flex-v">
108
+      <view className="flex-item">
109
+        <view>
110
+          <ScrollView scroll-y>
111
+            <view className="PageContent">
112
+              <view className="Top">
113
+                <Image
114
+                  mode="aspectFill"
115
+                  src={getImgURL(detail.bannerListImg)}
116
+                  className="centerLabel"
117
+                ></Image>
118
+              </view>
175 119
 
176
-            <view className="Info">
177
-              <view>
178
-                <view className="Title flex-h">
179
-                  <view className="flex-item">
180
-                    <text>{detail.title}</text>
120
+              <view className="Info">
121
+                <view>
122
+                  <view className="Title flex-h">
123
+                    <view className="flex-item">
124
+                      <text>{detail.title}</text>
125
+                    </view>
126
+                    <text className="Tips">
127
+                      {detail.enlisted || 0}人已报名
128
+                    </text>
181 129
                   </view>
182
-                  <text className="Tips">
183
-                    {detail.enlisted || 0}人已报名
130
+                  <text className="Time">
131
+                    报名截止时间:
132
+                    {getDateFormat(
133
+                      new Date(detail.enlistEnd).valueOf(),
134
+                      true,
135
+                      "yyyy/M/d"
136
+                    )}
184 137
                   </text>
185
-                </view>
186
-                <text className="Time">
187
-                  报名截止时间:
188
-                  {getDateFormat(
189
-                    new Date(detail.enlistEnd).valueOf(),
190
-                    true,
191
-                    "yyyy/M/d"
192
-                  )}
193
-                </text>
194
-                {/* <text className="Name">“香颂 · 蔚澜半岛”</text> */}
195
-                <view className="flex-h Address">
196
-                  <text>地址:</text>
197
-                  <view className="flex-item">
198
-                    <text>{detail.address}</text>
138
+                  {/* <text className="Name">“香颂 · 蔚澜半岛”</text> */}
139
+                  <view className="flex-h Address">
140
+                    <text>地址:</text>
141
+                    <view className="flex-item">
142
+                      <text>{detail.address}</text>
143
+                    </view>
199 144
                   </view>
200
-                </view>
201
-                <view className="flex-h Date">
202
-                  <text>时间:</text>
203
-                  <view className="flex-item">
204
-                    <text>
205
-                      {getDateFormat(
206
-                        new Date(detail.startDate).valueOf(),
207
-                        true,
208
-                        "yyyy/M/d"
209
-                      )}{" "}
210
-                      -{" "}
211
-                      {getDateFormat(
212
-                        new Date(detail.endDate).valueOf(),
213
-                        true,
214
-                        "yyyy/M/d"
215
-                      )}
216
-                    </text>
145
+                  <view className="flex-h Date">
146
+                    <text>时间:</text>
147
+                    <view className="flex-item">
148
+                      <text>
149
+                        {getDateFormat(
150
+                          new Date(detail.startDate).valueOf(),
151
+                          true,
152
+                          "yyyy/M/d"
153
+                        )}{" "}
154
+                        -{" "}
155
+                        {getDateFormat(
156
+                          new Date(detail.endDate).valueOf(),
157
+                          true,
158
+                          "yyyy/M/d"
159
+                        )}
160
+                      </text>
161
+                    </view>
162
+                  </view>
163
+                  <view className="Btn">
164
+                    <text>分享好友</text>
217 165
                   </view>
218
-                </view>
219
-                <view className="Btn">
220
-                  <text>分享好友</text>
221 166
                 </view>
222 167
               </view>
223
-            </view>
224 168
 
225
-            <view className="ActivityIntro">
226
-              <view className="Title">
227
-                <text>活动介绍</text>
169
+              <view className="ActivityIntro">
170
+                <view className="Title">
171
+                  <text>活动介绍</text>
172
+                </view>
173
+                <Image
174
+                  mode="aspectFill"
175
+                  src={getImgURL(detail.imgUrl)}
176
+                  className="img"
177
+                ></Image>
178
+                <RichText nodes={detail.desc} />
179
+                {/* <richText nodes={detail.desc} ></richText> */}
228 180
               </view>
229
-              <Image
230
-                mode="aspectFill"
231
-                src={getImgURL(detail.imgUrl)}
232
-                className="img"
233
-              ></Image>
234
-              <RichText nodes={detail.desc} />
235
-              {/* <richText nodes={detail.desc} ></richText> */}
236
-            </view>
237 181
 
238
-            <Disclaimer />
239
-          </view>
240
-        </ScrollView>
241
-      </view>
242
-    </view>
243
-    <view className="PageBottom flex-h">
244
-      <view className="Share">
245
-        <text className="iconfont icon-fenxiang"></text>
246
-        <text>分享</text>
182
+              <Disclaimer />
183
+            </view>
184
+          </ScrollView>
185
+        </view>
247 186
       </view>
248
-      <view className="Collect" onClick={handleFavo}>
249
-        <text
250
-          className="iconfont icon-shoucang"
251
-          style={detail.isSaved === 1 ? { color: "red" } : undefined}
252
-        ></text>
253
-        <text>收藏</text>
187
+      <view className="PageBottom flex-h">
188
+        <view className="Share">
189
+          <text className="iconfont icon-fenxiang"></text>
190
+          <text>分享</text>
191
+        </view>
192
+        <view className="Collect" onClick={handleFavor}>
193
+          <text
194
+            className="iconfont icon-shoucang"
195
+            style={isSaved ? { color: "red" } : undefined}
196
+          ></text>
197
+          <text>收藏</text>
198
+        </view>
199
+        <view className="flex-item"></view>
200
+
201
+        <text className="Post" onClick={handleSignup}>
202
+          {activityStatusDict[detail.activityStatus]?.text}
203
+        </text>
254 204
       </view>
255
-      <view className="flex-item"></view>
256
-
257
-      <text className="Post" onClick={handleSignup}>
258
-        {activityStatusDict[detail.activityStatus]?.text}
259
-      </text>
260 205
     </view>
261
-  </view>
262
-)
263
-  }
264
-    </>
265
-   
266
-  
206
+  )}
207
+  </>
267 208
 });

+ 3
- 3
src/pages/index/buildingDetail/components/Banner/index.jsx 查看文件

@@ -4,14 +4,14 @@ import { getImgURL } from '@/utils/image'
4 4
 import './index.scss'
5 5
 
6 6
 export default function Banner (props) {
7
-  const { List = [] } = props
7
+  const { List, onClick } = props
8 8
   return (
9 9
     <view className='components Banner'>
10 10
       <Swiper autoplay interval={2000} indicator-dots>
11 11
         {
12
-          List.map((item, index) => (
12
+          (List||[]).map((item, index) => (
13 13
             <SwiperItem key={`Banner-${index}`}>
14
-              <view className='swiper-item'>
14
+              <view className='swiper-item' onClick={() => onClick(item, List)}>
15 15
                 <Image mode='aspectFill' className='centerLabel' src={getImgURL(item.image || item.coverImg || item.url || item.img)} />
16 16
               </view>
17 17
             </SwiperItem>

+ 3
- 3
src/pages/index/buildingDetail/components/BasicInfo/index.jsx 查看文件

@@ -8,10 +8,10 @@ import './index.scss'
8 8
 
9 9
 
10 10
 export default function BasicInfo (props) {
11
-  const { Info = {} } = props
11
+  const { Info = {}, trackData } = props
12 12
   const { buildingId, isSave } = Info
13 13
 
14
-  const [isSaved, handleFavor] = useFavor(isSave)
14
+  const [isSaved, handleFavor] = useFavor(isSave, { id: buildingId, buildingId, ...trackData })
15 15
 
16 16
   const goto = (url) => Taro.navigateTo({ url })
17 17
 
@@ -23,7 +23,7 @@ export default function BasicInfo (props) {
23 23
         <view className='flex-item'>
24 24
           <text>{Info.buildingName}</text>
25 25
         </view>
26
-        <view className='Collect' onClick={() => handleFavor(buildingId)}>
26
+        <view className='Collect' onClick={handleFavor}>
27 27
           <text className={classNames(['iconfont icon-shoucang'], { active: isSaved })}></text>
28 28
           <text>{isSaved ? '取消收藏' : '收藏'}</text>
29 29
         </view>

+ 61
- 27
src/pages/index/buildingDetail/components/BuildingDetailBanner/index.jsx 查看文件

@@ -1,10 +1,24 @@
1 1
 import { useState } from 'react'
2
-import { Swiper, SwiperItem, Image } from '@tarojs/components'
2
+import Taro from '@tarojs/taro'
3
+import { Video } from '@tarojs/components'
3 4
 import { getImgURL } from '@/utils/image'
5
+import Banner from '../Banner'
4 6
 import './index.scss'
5 7
 
8
+const getImage = item => getImgURL(item.image || item.coverImg || item.url || item.img)
9
+
6 10
 export default function BuildingDetailBanner (props) {
7
-  const { PictureList = [{}, {}, {}] } = props
11
+  const { Info } = props
12
+  const { buildingImg, panoramaList, videoUrl, videoImage } = Info || {}
13
+  const videoPoster = videoImage ? videoImage[0] : undefined
14
+
15
+  const showPicBtn = buildingImg && buildingImg.length > 0
16
+  const showVRBtn = panoramaList && panoramaList.length > 0
17
+  const shwoVideoBtn = !!videoUrl
18
+
19
+  // JS 中 true + true = 2
20
+  const showBtns = (showPicBtn + showVRBtn + shwoVideoBtn) > 1
21
+
8 22
   const [NavList] = useState([
9 23
     { name: 'VR', id: 1 },
10 24
     { name: '视频', id: 2 },
@@ -18,33 +32,63 @@ export default function BuildingDetailBanner (props) {
18 32
     }
19 33
   }
20 34
 
35
+  const handlePreview = (item, all) => {
36
+    const img = getImage(item)
37
+    if (!img) return
38
+
39
+    Taro.previewImage({
40
+      current: img,
41
+      urls: all.map(getImage),
42
+    })
43
+  }
44
+
45
+  const handleVR = (item) => {
46
+    const url = (item || {}).panoramaLink
47
+    if (!url) return
48
+
49
+    Taro.navigateTo({
50
+      url: `/pages/index/webview/index?url=${encodeURIComponent(url)}`
51
+    })
52
+  }
53
+
21 54
   return (
22 55
     <view className='components buildingDetailBanner'>
23 56
 
24 57
       {/* 切换 */}
25
-      <view className='CutPoint'>
26
-        <view>
27
-          {
28
-            NavList.map((item, index) => (
29
-              <text key={`NavItem-${index}`} className={CurrentNavId === item.id ? 'active' : ''} onClick={CutNavId(item.id)}>{item.name}</text>
30
-            ))
31
-          }
32
-        </view>
33
-      </view>
58
+      {
59
+        showBtns && (
60
+          <view className='CutPoint'>
61
+            <view>
62
+              {
63
+                NavList.map((item, index) => (
64
+                  <text key={`NavItem-${index}`} className={CurrentNavId === item.id ? 'active' : ''} onClick={CutNavId(item.id)}>{item.name}</text>
65
+                ))
66
+              }
67
+            </view>
68
+          </view>
69
+        )
70
+      }
34 71
 
35 72
       {/* VR */}
36 73
       {
37
-        CurrentNavId === 1 &&
38
-        <view className='Vr'>
39
-
40
-        </view>
74
+        CurrentNavId === 1 && (
75
+          <view className='Vr'>
76
+            <Banner List={panoramaList} onClick={handleVR} />
77
+          </view>
78
+        )
41 79
       }
42 80
 
43 81
       {/* 视频 */}
44 82
       {
45 83
         CurrentNavId === 2 &&
46 84
         <view className='Video'>
47
-
85
+          <Video
86
+            controls
87
+            showMuteBtn
88
+            src={videoUrl}
89
+            poster={getImgURL(videoPoster)}
90
+            style={{ height: '600rpx', width: '750rpx' }}
91
+          />
48 92
         </view>
49 93
       }
50 94
 
@@ -52,17 +96,7 @@ export default function BuildingDetailBanner (props) {
52 96
       {
53 97
         CurrentNavId === 3 &&
54 98
         <view className='Picture'>
55
-          <Swiper autoplay interval={2000} indicator-dots>
56
-            {
57
-              PictureList.map((item, index) => (
58
-                <SwiperItem key={`Banner-${index}`}>
59
-                  <view className='swiper-item'>
60
-                    <Image mode='aspectFill' className='centerLabel' src={getImgURL(item.image || item.coverImg || item.url || item.img) || null} />
61
-                  </view>
62
-                </SwiperItem>
63
-              ))
64
-            }
65
-          </Swiper>
99
+          <Banner List={buildingImg} onClick={handlePreview} />
66 100
         </view>
67 101
       }
68 102
 

+ 6
- 6
src/pages/index/buildingDetail/components/DetailBottom/index.jsx 查看文件

@@ -3,17 +3,17 @@ import Taro from '@tarojs/taro'
3 3
 import { useSelector } from 'react-redux'
4 4
 import { Image } from '@tarojs/components'
5 5
 import AuthRole from '@/components/auth/AuthRole'
6
-import Poster from '@/components/Poster'
6
+// import Poster from '@/components/Poster'
7 7
 import { queryActivityList } from '@/services/activity'
8 8
 import { ROLE_CODE } from '@/constants/user'
9 9
 import './index.scss'
10 10
 
11 11
 export default function DetailBottom (props) {
12
-  const { Info = {}, poster } = props
12
+  const { Info = {}, onPoster } = props
13 13
 
14 14
   // 当前推荐置业
15 15
   const { consultant } = useSelector(s => s.system)
16
-  const [showPoster, setShowPoster] = useState(false)
16
+  // const [showPoster, setShowPoster] = useState(false)
17 17
   const [actList, setActList] = useState([])
18 18
 
19 19
   const handleCall = () => {
@@ -71,7 +71,7 @@ export default function DetailBottom (props) {
71 71
     <view>
72 72
       <view className='components DetailBottom flex-h'>
73 73
         <view className='flex-item'>
74
-          <view className='Item' onClick={() => setShowPoster(true)}>
74
+          <view className='Item' onClick={onPoster}>
75 75
             <Image mode='heightFix' src={require('@/assets/buildingDetail-icon3.png')}></Image>
76 76
             <text>一键海报</text>
77 77
           </view>
@@ -106,12 +106,12 @@ export default function DetailBottom (props) {
106 106
         </view>
107 107
       </view>
108 108
 
109
-      <Poster
109
+      {/* <Poster
110 110
         show={showPoster}
111 111
         dataSource={poster}
112 112
         onClose={() => setShowPoster(false)}
113 113
         onSuccess={() => setShowPoster(false)}
114
-      />
114
+      /> */}
115 115
     </view>
116 116
   )
117 117
 }

+ 15
- 4
src/pages/index/buildingDetail/components/LivingActivity/index.jsx 查看文件

@@ -1,11 +1,22 @@
1
-
1
+import Taro from '@tarojs/taro'
2 2
 import { Image } from '@tarojs/components'
3 3
 import '@/assets/css/iconfont.css'
4 4
 import { getImgURL } from '@/utils/image'
5 5
 import './index.scss'
6 6
 
7 7
 export default function LivingActivity (props) {
8
-  const { List = [] } = props
8
+  const { Info = {} } = props
9
+  const List = Info?.liveActivityList || []
10
+
11
+  const gotoList = () => {
12
+    const buildingId = Info?.buildingId
13
+    Taro.switchTab({
14
+      url: `/pages/video/index?buildingId=${buildingId}`
15
+    })
16
+  }
17
+
18
+  const gotoDetail = () => {}
19
+
9 20
   return List.length > 0 ? (
10 21
     <view className='components LivingActivity'>
11 22
 
@@ -13,14 +24,14 @@ export default function LivingActivity (props) {
13 24
         <view className='flex-item'>
14 25
           <text>直播活动</text>
15 26
         </view>
16
-        <text>更多</text>
27
+        <text onClick={gotoList}>更多</text>
17 28
         <text className='iconfont icon-jiantouright'></text>
18 29
       </view>
19 30
 
20 31
       <view className='List flex-h'>
21 32
         {
22 33
           List.map((item, index) => (
23
-            <view className='flex-item' key={`ListItem-${index}`}>
34
+            <view className='flex-item' key={`ListItem-${index}`} onClick={() => gotoDetail(item)}>
24 35
               <view style={{display: item.listImg ? 'block' : 'none'}}>
25 36
                 <Image mode='aspectFill' src={getImgURL(item.listImg)} className='centerLabel'></Image>
26 37
               </view>

+ 34
- 6
src/pages/index/buildingDetail/components/News/index.jsx 查看文件

@@ -1,26 +1,54 @@
1
-
1
+import { useState, useEffect } from 'react'
2
+import Taro from '@tarojs/taro'
2 3
 import { Image } from '@tarojs/components'
3 4
 import { getImgURL } from '@/utils/image'
5
+import { fetch } from '@/utils/request'
6
+import { API_NEWS_LIST } from '@/constants/api'
4 7
 import '@/assets/css/iconfont.css'
5 8
 import './index.scss'
6 9
 
7 10
 export default function News (props) {
8
-  const { List = [] } = props
9
-  return List.length > 0 ? (
11
+  const { Info = {} } = props
12
+
13
+  const [NewsList, setNewsList] = useState([])
14
+
15
+  const gotoList = () => {
16
+    const buildingId = Info?.buildingId
17
+    Taro.navigateTo({
18
+      url: `/pages/index/newsList/index?buildingId=${buildingId}`
19
+    })
20
+  }
21
+
22
+  const gotoDetail = (item) => {
23
+    Taro.navigateTo({
24
+      url: `/pages/index/newsDetail/index?id=${item.newsId}`
25
+    })
26
+  }
27
+
28
+  useEffect(() => {
29
+    if (Info?.buildingId) {
30
+      // 获取资讯列表
31
+      fetch({ url: API_NEWS_LIST, payload: { buildingId: Info.buildingId, pageSize: 2, pageNum: 1 } }).then((res) => {
32
+        setNewsList(res.records || [])
33
+      })
34
+    }
35
+  }, [Info?.buildingId])
36
+
37
+  return NewsList.length > 0 ? (
10 38
     <view className='components News'>
11 39
 
12 40
       <view className='Title flex-h'>
13 41
         <view className='flex-item'>
14 42
           <text>新鲜资讯</text>
15 43
         </view>
16
-        <text>更多</text>
44
+        <text onClick={gotoList}>更多</text>
17 45
         <text className='iconfont icon-jiantouright'></text>
18 46
       </view>
19 47
 
20 48
       <view className='List flex-h'>
21 49
         {
22
-          List.map((item, index) => (
23
-            <view className='flex-item' key={`ListItem-${index}`}>
50
+          NewsList.map((item, index) => (
51
+            <view className='flex-item' key={`ListItem-${index}`} onClick={() => gotoDetail(item)}>
24 52
               <view className='Img' style={{display: item.newsImg || item.newsName ? 'block' : 'none'}}>
25 53
                 <Image mode='aspectFill' src={getImgURL(item.newsImg)} className='centerLabel'></Image>
26 54
               </view>

+ 9
- 2
src/pages/index/buildingDetail/components/ProjectDynamic/index.jsx 查看文件

@@ -1,4 +1,5 @@
1 1
 // import React, { useState, useEffect } from 'react'
2
+import Taro from '@tarojs/taro'
2 3
 import '@/assets/css/iconfont.css'
3 4
 import './index.scss'
4 5
 
@@ -7,6 +8,12 @@ export default function ProjectDynamic (props) {
7 8
 
8 9
   const info = List[0]
9 10
 
11
+  const handleClick = () => {
12
+    Taro.navigateTo({
13
+      url: `/pages/index/buildingDynamic/index?id=${info.buildingId}`
14
+    })
15
+  }
16
+
10 17
   return info ? (
11 18
     <view className='components ProjectDynamic'>
12 19
 
@@ -14,11 +21,11 @@ export default function ProjectDynamic (props) {
14 21
         <view className='flex-item'>
15 22
           <text>项目动态</text>
16 23
         </view>
17
-        <text>更多</text>
24
+        <text onClick={handleClick}>更多</text>
18 25
         <text className='iconfont icon-jiantouright'></text>
19 26
       </view>
20 27
 
21
-      <view className='Info'>
28
+      <view className='Info' onClick={handleClick}>
22 29
         <text className='Time'>{info.trendTime}</text>
23 30
         <text className='Title'>{info.trendTitle}</text>
24 31
         <text className='Desc'>{info.trendContent}</text>

+ 0
- 23
src/pages/index/buildingDetail/hooks/useBuildingPoster.js 查看文件

@@ -1,23 +0,0 @@
1
-import { useEffect, useState } from 'react'
2
-import { getMiniQrcode } from '@/services/common'
3
-
4
-export default function useBuildingPoster(person, router, poster, paramsRef) {
5
-  const [posterData, setPosterData] = useState()
6
-
7
-  useEffect(() => {
8
-    const page = router.path
9
-    const scene = paramsRef.current
10
-
11
-    getMiniQrcode({ page, scene }).then((miniCode) => {
12
-      setPosterData({
13
-        poster,
14
-        miniCode,
15
-        name: person.name || person.nickname,
16
-        avatar: person.avatarurl,
17
-      })
18
-    })
19
-  // eslint-disable-next-line react-hooks/exhaustive-deps
20
-  }, [router.path, poster])
21
-
22
-  return posterData
23
-}

+ 0
- 32
src/pages/index/buildingDetail/hooks/useBuildingShare.js 查看文件

@@ -1,32 +0,0 @@
1
-import { useRef, useEffect } from 'react'
2
-import useShare from '@/utils/hooks/useShare'
3
-import { ROLE_CODE } from '@/constants/user'
4
-
5
-export default function useBuildingShare(person, buildingInfo, router, paramsRef) {
6
-  const shareRef = useRef()
7
-  const trackRef = useRef()
8
-
9
-  useEffect(() => {
10
-    if (buildingInfo?.buildingId) {
11
-      const shareContents = (buildingInfo.shareContents || [])[0] || {}
12
-      shareRef.current = {
13
-        title: shareContents.shareContentTitle || buildingInfo.buildingName,
14
-        path: `${router.path}?${paramsRef.current}`,
15
-        image: shareContents.shareContentImg,
16
-      }
17
-    }
18
-
19
-    // 判断当前人员是否置业顾问
20
-    const consultant = person.personType === ROLE_CODE.CONSULTANT ? { id: person.personId } : {}
21
-
22
-    trackRef.current = {
23
-      targetId: buildingInfo?.buildingId,
24
-      consultantId: consultant.id,
25
-      sharePersonId: person.personId,
26
-      buildingId: buildingInfo?.buildingId,
27
-    }
28
-  // eslint-disable-next-line react-hooks/exhaustive-deps
29
-  }, [buildingInfo, router.path])
30
-
31
-  useShare(shareRef, trackRef)
32
-}

+ 3
- 0
src/pages/index/buildingDetail/index.config.js 查看文件

@@ -1,4 +1,7 @@
1 1
 export default {
2 2
   navigationBarTitleText: '楼盘详情',
3 3
   enableShareAppMessage: true,
4
+  usingComponents: {
5
+    'page-container': '/native/PageContainer/index'
6
+  }
4 7
 }

+ 31
- 20
src/pages/index/buildingDetail/index.jsx 查看文件

@@ -1,10 +1,13 @@
1
-import { useState, useEffect, useMemo, useRef } from 'react'
1
+import { useState, useEffect } from 'react'
2 2
 import withLayout from '@/layout'
3 3
 import { ScrollView } from '@tarojs/components'
4 4
 import Disclaimer from '@/components/Disclaimer'
5
+import Poster from '@/components/Poster'
5 6
 import { fetch } from '@/utils/request'
6
-import { API_ITEMS_DETAIL, API_NEWS_LIST } from '@/constants/api'
7
-import useConsultant from '@/utils/hooks/useConsultant'
7
+import { API_ITEMS_DETAIL } from '@/constants/api'
8
+import useParams from '@/utils/hooks/useParams'
9
+import useShare from '@/utils/hooks/useShare'
10
+import usePoster from '@/utils/hooks/usePoster'
8 11
 import DetailBottom from './components/DetailBottom/index'
9 12
 import BuildingDetailBanner from './components/BuildingDetailBanner/index'
10 13
 import BasicInfo from './components/BasicInfo/index'
@@ -17,28 +20,33 @@ import MarketingActivity from './components/MarketingActivity/index'
17 20
 import LivingActivity from './components/LivingActivity/index'
18 21
 import News from './components/News/index'
19 22
 import Pictures from './components/Pictures/index'
20
-import useParams from './hooks/useParams'
21
-import useBuildingShare from './hooks/useBuildingShare'
22
-import useBuildingPoster from './hooks/useBuildingPoster'
23 23
 
24 24
 import './index.scss'
25 25
 
26 26
 export default withLayout((props) => {
27
-  const { router, person } = props
27
+  const { router, person, shareContent, trackData, page } = props
28 28
   const { id } = router.params
29 29
 
30
+  const [showPoster, setShowPoster] = useState(false)
30 31
   const [DetailInfo, setDetailInfo] = useState({})
31 32
   const [PictureList, setPictureList] = useState([])
32
-  const [NewsList, setNewsList] = useState([])
33 33
 
34 34
   // 本页面分享或者海报参数
35
-  const paramsRef = useParams(person, DetailInfo)
35
+  const paramsRef = useParams({id, buildingId: id, person, from: `${page.type}_share`})
36
+
37
+  const fullTrackData = { ...trackData, buildingId: id }
36 38
 
37 39
   // 分享
38
-  useBuildingShare(person, DetailInfo, router, paramsRef)
40
+  useShare({
41
+      title: shareContent.shareContentTitle || DetailInfo?.buildingName,
42
+      path: `${router.path}?${paramsRef.current}`,
43
+      image: shareContent.shareContentImg,
44
+    },
45
+    fullTrackData,
46
+  )
39 47
 
40 48
   // 海报
41
-  const posterData = useBuildingPoster(person, router, DetailInfo?.poster, paramsRef)
49
+  const posterData = usePoster(person, DetailInfo?.poster, router, paramsRef)
42 50
 
43 51
   useEffect(() => {
44 52
     // 获取楼盘信息
@@ -54,10 +62,6 @@ export default withLayout((props) => {
54 62
       console.error(err)
55 63
     })
56 64
 
57
-    // 获取资讯列表
58
-    fetch({ url: API_NEWS_LIST, payload: { buildingId: id, pageSize: 2, pageNum: 1 } }).then((res) => {
59
-      setNewsList(res.records || [])
60
-    })
61 65
   }, [id, router.path])
62 66
 
63 67
   return (
@@ -71,7 +75,7 @@ export default withLayout((props) => {
71 75
               <view className='BannerContainer'>
72 76
                 <view>
73 77
                   <view>
74
-                    <BuildingDetailBanner></BuildingDetailBanner>
78
+                    <BuildingDetailBanner Info={DetailInfo}></BuildingDetailBanner>
75 79
                   </view>
76 80
                 </view>
77 81
               </view>
@@ -81,7 +85,7 @@ export default withLayout((props) => {
81 85
 
82 86
                 {/* 基本信息 */}
83 87
                 <view className='BasicInfo'>
84
-                  <BasicInfo Info={DetailInfo}></BasicInfo>
88
+                  <BasicInfo Info={DetailInfo} trackData={fullTrackData}></BasicInfo>
85 89
                 </view>
86 90
 
87 91
                 {/* 特价房源 */}
@@ -116,12 +120,12 @@ export default withLayout((props) => {
116 120
 
117 121
                 {/* 直播活动 */}
118 122
                 <view className='LivingActivity' style={{minHeight: 0}}>
119
-                  <LivingActivity List={DetailInfo?.liveActivityList}></LivingActivity>
123
+                  <LivingActivity Info={DetailInfo}></LivingActivity>
120 124
                 </view>
121 125
 
122 126
                 {/* 新鲜资讯 */}
123 127
                 <view className='News' style={{minHeight: 0}}>
124
-                  <News List={NewsList}></News>
128
+                  <News Info={DetailInfo}></News>
125 129
                 </view>
126 130
 
127 131
                 {/* 相册 */}
@@ -139,8 +143,15 @@ export default withLayout((props) => {
139 143
       </view>
140 144
 
141 145
       <view className='PageBottom'>
142
-        <DetailBottom Info={DetailInfo} poster={posterData}></DetailBottom>
146
+        <DetailBottom Info={DetailInfo} onPoster={() => setShowPoster(true)}></DetailBottom>
143 147
       </view>
148
+
149
+      <Poster
150
+        show={showPoster}
151
+        dataSource={posterData}
152
+        onClose={() => setShowPoster(false)}
153
+        onSuccess={() => setShowPoster(false)}
154
+      />
144 155
     </view>
145 156
   )
146 157
 })

+ 1
- 1
src/pages/index/index.config.js 查看文件

@@ -1,3 +1,3 @@
1 1
 export default {
2
-  navigationBarTitleText: '新联'
2
+  navigationBarTitleText: '新联'
3 3
 }

+ 3
- 0
src/pages/index/webview/index.config.js 查看文件

@@ -0,0 +1,3 @@
1
+export default {
2
+  navigationBarTitleText: '新联家全景'
3
+}

+ 19
- 0
src/pages/index/webview/index.jsx 查看文件

@@ -0,0 +1,19 @@
1
+import React, { useEffect } from 'react'
2
+import Taro from '@tarojs/taro'
3
+import withLayout from '@/layout'
4
+import { WebView } from '@tarojs/components'
5
+
6
+export default withLayout((props) => {
7
+  const { router } = props
8
+  const { url, title } = router.params
9
+
10
+  useEffect(() => {
11
+    if (title) {
12
+      Taro.setNavigationBarTitle({ title: decodeURIComponent(title) })
13
+    }
14
+  }, [title])
15
+
16
+  return (
17
+    <WebView url={decodeURIComponent(url)} />
18
+  )
19
+})

+ 6
- 0
src/routes.js 查看文件

@@ -357,6 +357,12 @@ const routes = [
357 357
     pkg: 'main',
358 358
     type: 'mine',
359 359
   },
360
+  {
361
+    name: '全景图',
362
+    page: 'pages/index/webview/index',
363
+    pkg: 'main',
364
+    type: 'other',
365
+  },
360 366
 
361 367
 ]
362 368
 

+ 16
- 17
src/utils/hooks/useFavor.js 查看文件

@@ -1,15 +1,21 @@
1 1
 import { useEffect, useState } from 'react'
2 2
 import Taro from '@tarojs/taro'
3
-import { favorProject, cancelFavorProject } from '@/services/item'
3
+import { fetch } from '@/utils/request'
4
+import { resolvePath } from '@/constants/api'
5
+import track from '@/utils/tracking/track'
4 6
 
5
-export default function(eventType, saved) {
7
+const addFavor = (type, id) => fetch({ url: resolvePath(`${type}/save/${id}`),  method: 'POST' })
8
+const cancelFavor = (type, id) => fetch({ url: resolvePath(`${type}/save/${id}`),  method: 'POST' })
9
+
10
+export default function(saved, options = {}) {
11
+  const { id, eventType } = options
6 12
   const [isSaved, setIsSaved] = useState(saved)
7 13
 
8 14
   useEffect(() => setIsSaved(saved), [saved])
9 15
 
10
-  const handleSave = (buildingId) => {
16
+  const handleSave = () => {
11 17
     if (isSaved) {
12
-      cancelFavorProject(buildingId).then(() => {
18
+      cancelFavor(eventType, id).then(() => {
13 19
         setIsSaved(false)
14 20
         Taro.showToast({
15 21
           title: '已取消收藏',
@@ -17,7 +23,7 @@ export default function(eventType, saved) {
17 23
         })
18 24
       })
19 25
     } else {
20
-      favorProject(buildingId).then(() => {
26
+      addFavor(eventType, id).then(() => {
21 27
         setIsSaved(true)
22 28
         Taro.showToast({
23 29
           title: '收藏成功',
@@ -25,18 +31,11 @@ export default function(eventType, saved) {
25 31
         })
26 32
       })
27 33
     }
28
-    // savePoint({
29
-    //   event: 'save',
30
-    //   eventType: type,
31
-    //   propertyName: '项目收藏',
32
-    //   data: '{}'
33
-    // })
34
+    track({
35
+      event: 'save',
36
+      ...options,
37
+    })
34 38
   }
35 39
 
36
-  switch (eventType) {
37
-    case 'building':
38
-      return [isSaved, handleSave];
39
-    default:
40
-      return [];
41
-  }
40
+  return [isSaved, handleSave];
42 41
 }

src/pages/index/buildingDetail/hooks/useParams.js → src/utils/hooks/useParams.js 查看文件

@@ -1,20 +1,24 @@
1
+/**
2
+ * 用来构造分享的参数, 比如分享,海报等等
3
+ */
4
+
1 5
 import { useRef, useMemo } from 'react'
2 6
 import { ROLE_CODE } from '@/constants/user'
3 7
 
4
-export default function useParams(person, buildingInfo) {  
5
-
8
+export default function useParams({id, buildingId, person, from}) {
6 9
   // 判断当前人员是否置业顾问
7 10
   const consultant = person.personType === ROLE_CODE.CONSULTANT ? { id: person.personId } : {}
8 11
 
9 12
   const paramsRef = useRef()
10 13
   paramsRef.current = useMemo(() => {
11 14
     return [
12
-      `id=${buildingInfo?.buildingId}`,
13
-      `from=building_share`,
15
+      `id=${id}`,
16
+      `from=${from}`,
14 17
       `recommender=${person.personId}`,
18
+      buildingId ? `buildingId=${buildingId}` : undefined,
15 19
       consultant.id ? `consultant=${consultant.id}` : undefined,
16 20
     ].filter(Boolean).join('&')
17
-  }, [buildingInfo?.buildingId, person.personId, consultant.id])
21
+  }, [id, buildingId, from, person.personId, consultant.id])
18 22
 
19 23
   return paramsRef
20 24
 }

+ 25
- 0
src/utils/hooks/usePoster.js 查看文件

@@ -0,0 +1,25 @@
1
+import { useEffect, useState } from 'react'
2
+import { getMiniQrcode } from '@/services/common'
3
+
4
+export default function usePoster(person, poster, router, paramsRef) {
5
+  const [posterData, setPosterData] = useState()
6
+
7
+  useEffect(() => {
8
+    if (poster) {
9
+      const page = router.path
10
+      const scene = paramsRef.current
11
+  
12
+      getMiniQrcode({ page, scene }).then((miniCode) => {
13
+        setPosterData({
14
+          poster,
15
+          miniCode,
16
+          name: person.name || person.nickname,
17
+          avatar: person.avatarurl,
18
+        })
19
+      })
20
+    }
21
+  // eslint-disable-next-line react-hooks/exhaustive-deps
22
+  }, [router.path, poster])
23
+
24
+  return posterData
25
+}

+ 22
- 13
src/utils/hooks/useShare.js 查看文件

@@ -1,27 +1,36 @@
1
-import React, { useState } from 'react'
1
+import React, { useRef } from 'react'
2 2
 import Taro, { useShareAppMessage } from '@tarojs/taro'
3
-import { shareTracking } from '@/utils/tracking'
3
+import shareTracking from '@/utils/tracking/share'
4
+
5
+export default function useShare(shareContent, trackData) {
6
+  const shareRef = useRef()
7
+  const trackRef = useRef()
8
+
9
+  shareRef.current = shareContent
10
+  trackRef.current = trackData
4 11
 
5
-export default function useShare(shareRef, trackRef) {
6 12
   useShareAppMessage((res) => {
7 13
     const {
8
-      title = '',
9
-      path = '',
10
-      image = '',
14
+      title,
15
+      path,
16
+      image,
11 17
     } = shareRef.current || {}
12 18
 
13 19
     const {
14
-      // event = 'share',
15
-      // eventType = '',
16
-      // propertyName = '',
17
-      consultantId = '',
18
-      sharePersonId = '',
19
-      targetId = '',
20
-      buildingId = '',
20
+      event = 'share',
21
+      eventType,
22
+      propertyName,
23
+      consultantId,
24
+      sharePersonId,
25
+      targetId,
26
+      buildingId,
21 27
     } = trackRef.current || {}
22 28
 
23 29
     // 分享埋点
24 30
     shareTracking({
31
+      event,
32
+      eventType,
33
+      propertyName,
25 34
       consultantId,
26 35
       sharePersonId,
27 36
       targetId,

+ 1
- 1
src/utils/tracking/addNum.js 查看文件

@@ -51,6 +51,6 @@ export default function addNum({ targetId, eventType }) {
51 51
     //     addHFiveShareNum(targetId)
52 52
     //     break;
53 53
     default:
54
-        return
54
+      return
55 55
   }
56 56
 }

+ 19
- 0
src/utils/tracking/share.js 查看文件

@@ -0,0 +1,19 @@
1
+import Taro from '@tarojs/taro'
2
+import track from './track'
3
+import addNum from './addNum'
4
+
5
+export default (options) => {
6
+  const page = Taro.getStorageSync('page')
7
+  if (!page) return;
8
+
9
+  const { name: propertyName, type: eventType } = page
10
+  addNum({ eventType, targetId: options.targetId })
11
+
12
+  track({
13
+    event: 'share',
14
+    eventType,
15
+    propertyName,
16
+    data: '{}',
17
+    ...options,
18
+  })
19
+}

+ 24
- 0
src/utils/tracking/track.js 查看文件

@@ -0,0 +1,24 @@
1
+import { savePoint } from '@/services/common'
2
+
3
+export default (options) => {
4
+  const {
5
+    event = '',
6
+    eventType = '',
7
+    propertyName = '',
8
+    consultantId = '',
9
+    sharePersonId = '',
10
+    targetId = '',
11
+    buildingId = '',
12
+  } = options
13
+
14
+  savePoint({
15
+    event,
16
+    eventType,
17
+    propertyName,
18
+    consultantId,
19
+    sharePersonId,
20
+    targetId,
21
+    buildingId,
22
+    data: '{}',
23
+  })
24
+}

+ 29
- 0
src/utils/tracking/userSource.js 查看文件

@@ -0,0 +1,29 @@
1
+import { savePoint, updatePoint } from '@/services/common'
2
+import { routes } from '../../routes'
3
+
4
+export default async (router) => {
5
+  const { path, query, scene } = router || {}
6
+  const { id, buildingId, recommender } = query || {}
7
+
8
+  const pageInfo = routes.filter(x => path.indexOf(x.page) > -1)[0] || { type: 'other', name: '其他' }
9
+
10
+  const trackPayload = {
11
+    event: 'start',
12
+    eventType: pageInfo.type,
13
+    propertyName: pageInfo.name,
14
+    data: '{}',
15
+    id,
16
+    buildingId,
17
+    realScene: scene,
18
+    sceneId: scene,
19
+    sharePersonId: recommender,
20
+  }
21
+
22
+  try {
23
+    const { recordId } = await savePoint(trackPayload)
24
+    return function () { updatePoint(recordId); }
25
+  } catch (e) {
26
+    console.error('进入小程序埋点出错:', e);
27
+    return function () { }
28
+  }
29
+}