Kaynağa Gözat

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

zlisen 3 yıl önce
ebeveyn
işleme
9d87d3d33c

+ 2
- 2
config/dev.js Dosyayı Görüntüle

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

+ 27
- 0
src/components/FirstScreen/index.jsx Dosyayı Görüntüle

@@ -0,0 +1,27 @@
1
+import { useState, useEffect } from 'react'
2
+import { Image } from '@tarojs/components'
3
+import { getImgURL } from '@/utils/image'
4
+import './style.scss'
5
+
6
+export default (props) => {
7
+  const { info, visible = false, onClose } = props
8
+
9
+  const ImgClick = () => {
10
+
11
+  }
12
+
13
+  console.log('---------info------>', info, visible)
14
+
15
+  return (
16
+    <view className='components Adv' style={{display: visible ? 'block' : 'none'}}>
17
+      <view className='centerLabel'>
18
+        <view>
19
+          <view className='Img' onClick={ImgClick}>
20
+            <Image mode='scaleToFill' src={getImgURL(info?.image)}></Image>
21
+          </view>
22
+          <text className='iconfont icon-guanbi' onClick={onClose}></text>
23
+        </view>
24
+      </view>
25
+    </view>
26
+  )
27
+}

+ 36
- 0
src/components/FirstScreen/style.scss Dosyayı Görüntüle

@@ -0,0 +1,36 @@
1
+.components.Adv {
2
+  width: 100%;
3
+  position: fixed;
4
+  top: 0;
5
+  left: 0;
6
+  bottom: 0;
7
+  z-index: 1000;
8
+  background: rgba(0, 0, 0, 0.6);
9
+  >view {
10
+    width: 100%;
11
+    >view {
12
+      padding: 0 134px;
13
+      position: relative;
14
+      overflow: hidden;
15
+      text-align: center;
16
+      >.Img {
17
+        width: 100%;
18
+        position: relative;
19
+        overflow: hidden;
20
+        padding-bottom: 150%;
21
+        background: #eee;
22
+        border-radius: 24px;
23
+        >image {
24
+          width: 100%;
25
+          height: 100%;
26
+        }
27
+      }
28
+      >text {
29
+        display: inline-block;
30
+        font-size: 60px;
31
+        color: #fff;
32
+        margin-top: 30px;
33
+      }
34
+    }
35
+  }
36
+}

+ 7
- 0
src/constants/api.js Dosyayı Görüntüle

@@ -121,7 +121,14 @@ export const API_TYPE_DATA = resolvePath('awesome/dict/recommendcustomer')
121 121
 // channel
122 122
 export const API_CHANNEL_REPORT = resolvePath('channel/report')
123 123
 
124
+// 驻场
125
+export const API_MANAGE_CUSTOMER_LIST = resolvePath('marking/customers')
126
+export const API_TOBE_MANAGER = resolvePath('marketing')
127
+export const API_MY_BUILDINGIDS = resolvePath('building/mine')
128
+
129
+
124 130
 // report
131
+export const API_REPORT_CUETOMER = resolvePath('customer/manualReport ')
125 132
 export const API_REPORT_LIST = resolvePath('myReport')
126 133
 export const API_REPORT_CLIENT = resolvePath('customer/report')
127 134
 export const API_RECOMMEND_GET = resolvePath('customer/recommend/get')

+ 7
- 0
src/layout/index.js Dosyayı Görüntüle

@@ -8,15 +8,18 @@ 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 FirstScreen from '@/components/FirstScreen'
11 12
 import { report as reportCustomer } from '@/utils/customer'
12 13
 import { ROLE_CODE } from '@/constants/user'
13 14
 import useAuth from './useAuth'
15
+import useScreen from './useScreen'
14 16
 import { routes } from '../routes'
15 17
 
16 18
 import './style.scss'
17 19
 
18 20
 export default (ChildComponent) => (props) => {
19 21
   const consultant = useSelector(s => s.system.consultant)
22
+  const city = useSelector(s => s.city.curCity)
20 23
   const { spinning, userInfo } = useSelector(s => s.user)
21 24
   const { person, ...extInfo } = userInfo || {}
22 25
   const router = useRouter()
@@ -31,6 +34,8 @@ export default (ChildComponent) => (props) => {
31 34
   const [shareContent, setShareContent] = useState({})
32 35
   // 页面埋点
33 36
   const [trackData, setTrackData] = useState({})
37
+  // 开屏广告
38
+  const [screenInfo, screenVisible, toggleShowScreen] = useScreen(city.id, person)
34 39
 
35 40
   // 报备客户
36 41
   useEffect(() => {
@@ -90,6 +95,7 @@ export default (ChildComponent) => (props) => {
90 95
             router={router}
91 96
             consultant={consultant}
92 97
             page={page}
98
+            city={city}
93 99
             shareContent={shareContent}
94 100
             trackData={trackData}
95 101
             {...props}
@@ -100,6 +106,7 @@ export default (ChildComponent) => (props) => {
100 106
       {
101 107
         !!showConsultant && (<FixedConsultant consultant={consultant} />)
102 108
       }
109
+      <FirstScreen info={screenInfo} visible={screenVisible} onClose={toggleShowScreen} />
103 110
     </>
104 111
   )
105 112
 }

+ 37
- 0
src/layout/useScreen.js Dosyayı Görüntüle

@@ -0,0 +1,37 @@
1
+/**
2
+ * 获取开屏广告
3
+ * @param {*} cityId 
4
+ */
5
+import { useEffect, useState, useCallback } from 'react'
6
+import { useDispatch, useSelector } from 'react-redux'
7
+import { queryExtContents } from '@/services/common'
8
+
9
+export default function useScreen(cityId, person) {
10
+  const dispatch = useDispatch()
11
+
12
+  const [firstScreen, setFirstScreen] = useState()
13
+  const canShow = useSelector(s => !s.system.firstScreen.filter(x => x === cityId)[0])
14
+  const toggle = useCallback(
15
+    () => dispatch({ type: 'TOGGLE_FIRSTSCREEN', payload: { cityId } }),
16
+    [cityId, dispatch],
17
+  )
18
+
19
+  useEffect(() => {
20
+    if (cityId && person?.personId) {
21
+      queryExtContents({cityId}).then((res) => {
22
+        const screen = (res || []).filter(x => x.showType === 'screen' && x.showPosition === 'index')[0] || {}
23
+        setFirstScreen(screen)
24
+  
25
+        if (screen) {
26
+          toggle()
27
+        }
28
+      })
29
+    }
30
+  }, [cityId, toggle, person?.personId])
31
+
32
+  const show = canShow && firstScreen
33
+
34
+  console.log('------showshow--------->', show)
35
+
36
+  return [firstScreen, show, toggle]
37
+}

+ 39
- 21
src/pages/index/brandDetail/index.jsx Dosyayı Görüntüle

@@ -4,8 +4,9 @@ import Taro from '@tarojs/taro'
4 4
 import { ScrollView, Image } from '@tarojs/components'
5 5
 import ProjectListItem from '@/components/ProjectListItem/index'
6 6
 import { queryBrandInfo } from '@/services/common';
7
-import { getItemList } from '@/services/item';
8 7
 import { getImgURL } from '@/utils/image'
8
+import { fetch } from '@/utils/request'
9
+import { API_ITEMS_LIST } from '@/constants/api'
9 10
 import '@/assets/css/iconfont.css'
10 11
 import ColumnTitle from '../components/ColumnTitle/index'
11 12
 import './index.scss'
@@ -13,40 +14,57 @@ import './index.scss'
13 14
 export default withLayout((props) => {
14 15
   const { router } = props
15 16
   const { id } = router.params
16
-
17
-  const [ProjectList, setProjectList] = useState([{}, {}])
17
+  
18
+  const [PageList, setPageList] = useState([])
19
+  const [IsPull, setPull] = useState(false)
20
+  const [pageNumber, setPageNumber] = useState(1)
21
+  const [HasNextPage, setHasNextPage] = useState(true)
18 22
   const [brandInfo, setBrandInfo] = useState({})
19 23
 
20
-  const getList = (params) => {
21
-    Taro.showLoading()
22
-    getItemList({
23
-      brandId: id,
24
-      ...(params || {}),
25
-    }).then((res) => {
26
-      const { records } = res
27
-      setProjectList(records || {})
28
-      Taro.hideLoading()
29
-    }).catch((err) => {
30
-      console.error(err)
31
-      Taro.hideLoading()
24
+  useEffect(() => {
25
+    GetPageList()
26
+  }, [pageNumber])
27
+
28
+  const PageRefresh = () => { // 页面下拉刷新回调
29
+    setPull(true)
30
+  }
31
+
32
+  const GetPageList = () => {
33
+    setHasNextPage(false)
34
+    fetch({ url: API_ITEMS_LIST, method: 'get', payload: { pageNumber, pageSize: 10 } }).then((res) => {
35
+      setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
36
+      setHasNextPage(res.current < res.pages)
37
+      setPull(false)
32 38
     })
33 39
   }
34 40
 
41
+  const PageLoadMore = () => { // 页面上拉加载更多
42
+    if(HasNextPage) {
43
+      setPageNumber(pageNumber + 1)
44
+    }
45
+  }
46
+
47
+  useEffect(() => { // 下拉刷新触发
48
+    if (IsPull) {
49
+      if(pageNumber === 1) {
50
+        GetPageList()
51
+      } else {
52
+        setPageNumber(1)
53
+      }
54
+    }
55
+  }, [IsPull])
56
+
35 57
   useEffect(() => {
36 58
     if (id) {
37 59
       queryBrandInfo(id).then((res) => {
38 60
         setBrandInfo(res || {})
39
-      }).catch((err) => {
40
-        console.error(err)
41 61
       })
42
-
43
-      getList({ pageNumber: 1 })
44 62
     }
45 63
   }, [id])
46 64
 
47 65
   return (
48 66
     <view className='brandDetail'>
49
-      <ScrollView scroll-y>
67
+      <ScrollView scroll-y refresher-enabled refresher-triggered={IsPull} onrefresherrefresh={PageRefresh} onscrolltolower={PageLoadMore} refresher-background='#fff'>
50 68
         <view className='Content'>
51 69
 
52 70
           {/* 主图 */}
@@ -69,7 +87,7 @@ export default withLayout((props) => {
69 87
             <ColumnTitle Name='在售项目' Icon='icon-aixin' ShowMore ToMore={() => { Taro.navigateTo({ url: `/pages/index/buildingList/index` }) }}></ColumnTitle>
70 88
             <view className='ProjectList'>
71 89
               {
72
-                ProjectList.map((item, index) => (
90
+                PageList.map((item, index) => (
73 91
                   <ProjectListItem Data={item} key={`ProjectListItem-${index}`}></ProjectListItem>
74 92
                 ))
75 93
               }

+ 4
- 2
src/pages/index/buildingList/index.jsx Dosyayı Görüntüle

@@ -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)

+ 0
- 1
src/pages/index/index.jsx Dosyayı Görüntüle

@@ -53,7 +53,6 @@ export default withLayout(() => {
53 53
 
54 54
   return (
55 55
     <view className='Page Index'>
56
-
57 56
       <ScrollView scroll-y>
58 57
         <view className='PageContent'>
59 58
 

+ 45
- 34
src/pages/mine/addCustomer/index.jsx Dosyayı Görüntüle

@@ -1,10 +1,10 @@
1 1
 import { useState, useEffect } from 'react'
2 2
 import withLayout from '@/layout'
3
-import { ScrollView, Input, Image, Picker } from '@tarojs/components'
3
+import { ScrollView, Input, Image, Picker, Block } from '@tarojs/components'
4 4
 import '@/assets/css/iconfont.css'
5 5
 import { useSelector } from 'react-redux'
6 6
 import { fetch } from '@/utils/request'
7
-import { API_ITEMS_LIST, API_CARDS_LIST, API_REPORT_CLIENT, API_RECOMENT_CLIENT, API_CHANNEL_REPORT } from '@/constants/api'
7
+import { API_ITEMS_LIST, API_CARDS_LIST, API_REPORT_CUETOMER, API_RECOMENT_CLIENT, API_CHANNEL_REPORT } from '@/constants/api'
8 8
 import Taro from '@tarojs/taro'
9 9
 import './index.scss'
10 10
 
@@ -12,7 +12,8 @@ const defaultSpecialImage = 'https://yz-websit.oss-cn-hangzhou.aliyuncs.com/xlk/
12 12
 
13 13
 export default withLayout((props) => {
14 14
 
15
-  const { type } = props
15
+  const { router } = props
16
+  const { type } = router.params
16 17
   const user = useSelector(state => state.user)
17 18
   const [PersonId, setPersonId] = useState(null)
18 19
   const [BuildingName, setBuildingName] = useState(null)
@@ -47,14 +48,19 @@ export default withLayout((props) => {
47 48
   useEffect(() => {
48 49
     if (CanSubmit) {
49 50
       let url = null
50
-      if(type === 'consultant') { // 置业顾问
51
-        url = API_REPORT_CLIENT
52
-      } else if(type === 'customer') { // 普通客户
51
+      if (type === 'consultant') { // 置业顾问
52
+        url = API_REPORT_CUETOMER
53
+      } else if (type === 'customer') { // 普通客户
53 54
         url = API_RECOMENT_CLIENT
54 55
       } else { // 经纪人
55 56
         url = API_CHANNEL_REPORT
56 57
       }
57
-      const params = { ...FormData, sex: SexId, intention: BuildingId, realtyConsultant: CardId }
58
+      let params = {}
59
+      if(type === 'consultant') {
60
+        params = { name: FormData.name, phone: FormData.phone, sex: SexId }
61
+      } else {
62
+        params = { ...FormData, sex: SexId, intention: BuildingId, realtyConsultant: CardId }
63
+      }
58 64
       fetch({ url, method: 'post', payload: params }).then(() => {
59 65
         Taro.showToast({ title: '添加成功', icon: 'none' })
60 66
         Taro.navigateBack({ delta: 1 })
@@ -129,7 +135,7 @@ export default withLayout((props) => {
129 135
       Taro.showToast({ title: '请填写正确的客户电话', icon: 'none' })
130 136
       return false
131 137
     }
132
-    if (BuildingId === null) {
138
+    if (BuildingId === null && type !== 'consultant') {
133 139
       Taro.showToast({ title: '请选择客户的意向楼盘', icon: 'none' })
134 140
       return false
135 141
     }
@@ -168,32 +174,37 @@ export default withLayout((props) => {
168 174
             <text className='iconfont icon-jiantoudown'></text>
169 175
           </view>
170 176
 
171
-          <text>意向楼盘</text>
172
-          <view className='FormLine flex-h'>
173
-            <view className='flex-item'>
174
-              <Picker range-key='name' onChange={PickerChange} value={0} range={BuildingList}>
175
-                <text>{BuildingName || '请选择'}</text>
176
-              </Picker>
177
-            </view>
178
-          </view>
179
-
180
-          <text>内场接待(选填)</text>
181
-          <view className='FormLine flex-h'>
182
-            <view className='flex-item'>
183
-              <Picker range-key='name' onChange={CardPickerChange} value={0} range={CardList}>
184
-                <text>{CardName || '请选择'}</text>
185
-              </Picker>
186
-            </view>
187
-            <Image mode='heightFix' src={defaultSpecialImage}></Image>
188
-            <text>选择</text>
189
-          </view>
190
-
191
-          <text>备注</text>
192
-          <view className='FormLine flex-h'>
193
-            <view className='flex-item'>
194
-              <Input placeholder='补充说明(选填)' data-type='describe' onInput={FormInput.bind(this)}></Input>
195
-            </view>
196
-          </view>
177
+          {
178
+            type !== 'consultant' &&
179
+            <Block>
180
+              <text>意向楼盘</text>
181
+              <view className='FormLine flex-h'>
182
+                <view className='flex-item'>
183
+                  <Picker range-key='name' onChange={PickerChange} value={0} range={BuildingList}>
184
+                    <text>{BuildingName || '请选择'}</text>
185
+                  </Picker>
186
+                </view>
187
+              </view>
188
+
189
+              <text>内场接待(选填)</text>
190
+              <view className='FormLine flex-h'>
191
+                <view className='flex-item'>
192
+                  <Picker range-key='name' onChange={CardPickerChange} value={0} range={CardList}>
193
+                    <text>{CardName || '请选择'}</text>
194
+                  </Picker>
195
+                </view>
196
+                <Image mode='heightFix' src={defaultSpecialImage}></Image>
197
+                <text>选择</text>
198
+              </view>
199
+
200
+              <text>备注</text>
201
+              <view className='FormLine flex-h'>
202
+                <view className='flex-item'>
203
+                  <Input placeholder='补充说明(选填)' data-type='describe' onInput={FormInput.bind(this)}></Input>
204
+                </view>
205
+              </view>
206
+            </Block>
207
+          }
197 208
 
198 209
           <view className='Btn'>
199 210
             <text onClick={ToSubmit}>提交</text>

+ 9
- 11
src/pages/mine/components/MyCustomerListItem/index.jsx Dosyayı Görüntüle

@@ -1,25 +1,23 @@
1
-import React, { useState, useEffect } from 'react'
2
-import './index.scss'
1
+
2
+import { Image } from '@tarojs/components'
3 3
 import Taro from '@tarojs/taro'
4
+import './index.scss'
4 5
 
5 6
 export default function MyCustomerListItem (props) {
6
-  const { Data = {} } = props
7
+  const { data = {} } = props
7 8
   return (
8
-    <view className='components MyCustomerListItem flex-h' onClick={() => { Taro.navigateTo({ url: `/pages/mine/myCustomerDetail/index?id=${Data.id}` }) }}>
9
+    <view className='components MyCustomerListItem flex-h' onClick={() => { Taro.navigateTo({ url: `/pages/mine/myCustomerDetail/index?id=${data.customerId}` }) }}>
9 10
       <view className='Img'>
10
-        {
11
-          Data.img &&
12
-          <Image mode='aspectFill' className='centerLabel' src={Data.img || null} />
13
-        }
11
+        <Image mode='scaleToFill' src={data.avatarurl}></Image>
14 12
       </view>
15 13
       <view className='flex-item'>
16 14
         <view className='Name flex-h'>
17
-          <text className='flex-item'>徐慧慧</text>
15
+          <text className='flex-item'>{data.name}</text>
18 16
           <text>11/11 15:12:58收回</text>
19 17
         </view>
20 18
         <view className='Time flex-h'>
21
-          <text className='flex-item'>136 **** 9434</text>
22
-          <text>跟进状态</text>
19
+          <text className='flex-item'>{data.phone}</text>
20
+          <text>{data.status === 0 ? '' : data.status === 1 ? '报备' : data.status === 2 ? '到访' : data.status === 3 ? '认筹' : '签约'}</text>
23 21
         </view>
24 22
       </view>
25 23
     </view>

+ 5
- 5
src/pages/mine/components/ResidentListItem/index.jsx Dosyayı Görüntüle

@@ -1,10 +1,10 @@
1 1
 import React, { useState, useEffect } from 'react'
2
-import './index.scss'
3 2
 import Taro from '@tarojs/taro'
4 3
 import { Image } from '@tarojs/components'
4
+import './index.scss'
5 5
 
6 6
 export default function ResidentListItem (props) {
7
-  const { Data = {} } = props
7
+  const { data = {} } = props
8 8
   return (
9 9
     <view className='components ResidentListItem'>
10 10
       <view className='flex-h'>
@@ -17,15 +17,15 @@ export default function ResidentListItem (props) {
17 17
       <view className='flex-h'>
18 18
         <text>客户姓名:</text>
19 19
         <view className='flex-item'>
20
-          <text></text>
20
+          <text>{data.name}</text>
21 21
         </view>
22 22
       </view>
23 23
       <view className='flex-h'>
24 24
         <text>手机号码:</text>
25 25
         <view className='flex-item'>
26
-          <text>136****9434</text>
26
+          <text>{data.phone}</text>
27 27
         </view>
28
-        <Image mode='heightFix' src={require('../../../../assets/mine-icon27.png')}></Image>
28
+        <Image mode='heightFix' src={require('@/assets/mine-icon27.png')}></Image>
29 29
         <text className='Type'>结佣</text>
30 30
       </view>
31 31
       <view className='flex-h'>

+ 46
- 13
src/pages/mine/myCustomer/index.jsx Dosyayı Görüntüle

@@ -1,27 +1,60 @@
1
-import React, { useState, useEffect } from 'react'
1
+import { useState, useEffect } from 'react'
2 2
 import withLayout from '@/layout'
3
-import './index.scss'
4 3
 import { ScrollView } from '@tarojs/components'
5 4
 import '@/assets/css/iconfont.css'
5
+import { useSelector } from 'react-redux'
6
+import { fetch } from '@/utils/request'
7
+import { API_CLIENT_LIST } from '@/constants/api'
8
+import './index.scss'
6 9
 import MyCustomerListItem from '../components/MyCustomerListItem/index'
7 10
 
8
-export default withLayout((props) => {
9
-
10
-  // const [PageProps] = useState(props)
11
-  const [PageList, setPageList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', ''])
11
+export default withLayout(() => {
12
+  
13
+  const user = useSelector(state => state.user)
14
+  const [PageList, setPageList] = useState([])
12 15
   const [IsPull, setPull] = useState(false)
13
-  const [PullTimer, setPullTimer] = useState(null)
16
+  const [PersonId, setPersonId] = useState(null)
17
+  const [pageNumber, setPageNumber] = useState(1)
18
+  const [HasNextPage, setHasNextPage] = useState(true)
19
+
20
+  useEffect(() => {
21
+    if(user?.userInfo?.person?.personId) {
22
+      setPersonId(user.userInfo.person.personId)
23
+    }
24
+  }, [user])
25
+
26
+  useEffect(() => {
27
+    if(PersonId) {
28
+      GetPageList()
29
+    }
30
+  }, [pageNumber, PersonId])
14 31
 
15 32
   const PageRefresh = () => { // 页面下拉刷新回调
16 33
     setPull(true)
17 34
   }
18 35
 
36
+  const GetPageList = () => {
37
+    setHasNextPage(false)
38
+    fetch({ url: API_CLIENT_LIST, method: 'get', payload: { customerId: PersonId, pageNumber, pageSize: 10 } }).then((res) => {
39
+      setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
40
+      setHasNextPage(res.current < res.pages)
41
+      setPull(false)
42
+    })
43
+  }
44
+
45
+  const PageLoadMore = () => { // 页面上拉加载更多
46
+    if(HasNextPage) {
47
+      setPageNumber(pageNumber + 1)
48
+    }
49
+  }
50
+
19 51
   useEffect(() => { // 下拉刷新触发
20 52
     if (IsPull) {
21
-      clearTimeout(PullTimer)
22
-      setPullTimer(setTimeout(() => {
23
-        setPull(false)
24
-      }, 2000))
53
+      if(pageNumber === 1) {
54
+        GetPageList()
55
+      } else {
56
+        setPageNumber(1)
57
+      }
25 58
     }
26 59
   }, [IsPull])
27 60
 
@@ -46,13 +79,13 @@ export default withLayout((props) => {
46 79
       <view className='flex-item'>
47 80
         <view>
48 81
 
49
-          <ScrollView scroll-y={true} refresher-enabled={true} refresher-triggered={IsPull} onrefresherrefresh={PageRefresh} refresher-background='#fff'>
82
+          <ScrollView scroll-y refresher-enabled refresher-triggered={IsPull} onrefresherrefresh={PageRefresh} onscrolltolower={PageLoadMore} refresher-background='#fff'>
50 83
             <view className='PageContent'>
51 84
               <view className='List'>
52 85
                 {
53 86
                   PageList.map((item, index) => (
54 87
                     <view>
55
-                      <MyCustomerListItem Data={item} key={`MyCustomerListItem-${index}`}></MyCustomerListItem>
88
+                      <MyCustomerListItem data={item} key={`MyCustomerListItem-${index}`}></MyCustomerListItem>
56 89
                     </view>
57 90
                   ))
58 91
                 }

+ 120
- 26
src/pages/mine/residentManager/index.jsx Dosyayı Görüntüle

@@ -1,53 +1,147 @@
1 1
 import { useState, useEffect } from 'react'
2 2
 import withLayout from '@/layout'
3
-import { ScrollView, Image } from '@tarojs/components'
3
+import { ScrollView, Input } from '@tarojs/components'
4 4
 import '@/assets/css/iconfont.css'
5
+import { useSelector } from 'react-redux'
6
+import { fetch } from '@/utils/request'
7
+import { API_MANAGE_CUSTOMER_LIST, API_MY_BUILDINGIDS } from '@/constants/api'
5 8
 import './index.scss'
6 9
 import ResidentListItem from '../components/ResidentListItem/index'
7 10
 
8 11
 export default withLayout(() => {
12
+  // const [FilterMenu] = useState([
13
+  //   { name: '报备', id: 1 },
14
+  //   { name: '到访', id: 2 },
15
+  //   { name: '认筹', id: 3 },
16
+  //   { name: '认购', id: 4 },
17
+  //   { name: '签约', id: 5 },
18
+  //   { name: '报备无效', id: 6 },
19
+  //   { name: '报备过期', id: 7 }
20
+  // ])
21
+  // const [CurrentFilterMenuId, setCurrentFilterMenuId] = useState(null)
9 22
 
10
-  const [PageList, setPageList] = useState(['', '', '', '', '', '', '', '', '', '', '', '', ''])
23
+  // const CutFilter = (item) => {
24
+  //   return () => {
25
+  //     setCurrentFilterMenuId(item.id === CurrentFilterMenuId ? null : item.id)
26
+  //   }
27
+  // }
28
+
29
+  const user = useSelector(state => state.user)
30
+  const [BuildingIds, setBuildingIds] = useState([])
31
+  const [PageList, setPageList] = useState([])
11 32
   const [IsPull, setPull] = useState(false)
12
-  const [PullTimer, setPullTimer] = useState(null)
13
-  const [FilterMenu] = useState([
14
-    { name: '报备', id: 1 },
15
-    { name: '到访', id: 2 },
16
-    { name: '认筹', id: 3 },
17
-    { name: '认购', id: 4 },
18
-    { name: '签约', id: 5 },
19
-    { name: '报备无效', id: 6 },
20
-    { name: '报备过期', id: 7 }
21
-  ])
22
-  const [CurrentFilterMenuId, setCurrentFilterMenuId] = useState(null)
33
+  const [PersonId, setPersonId] = useState(null)
34
+  const [pageNumber, setPageNumber] = useState(1)
35
+  const [HasNextPage, setHasNextPage] = useState(true)
36
+  const [CurrentBuildingId, setCurrentBuildingId] = useState(null)
37
+  const [CurrentBuildingName, setCurrentBuildingName] = useState(null)
38
+  const [FilterData, setFilterData] = useState({})
39
+
40
+  useEffect(() => {
41
+    if (user?.userInfo?.person?.personId) {
42
+      setPersonId(user.userInfo.person.personId)
43
+    }
44
+  }, [user])
45
+
46
+  useEffect(() => {
47
+    if (PersonId) {
48
+      GetMyBuildingIds()
49
+    }
50
+  }, [PersonId])
51
+
52
+  useEffect(() => {
53
+    if (FilterData.keywords) {
54
+      if (pageNumber === 1) {
55
+        GetPageList()
56
+      } else {
57
+        setPageNumber(1)
58
+      }
59
+    }
60
+  }, [FilterData])
61
+
62
+  useEffect(() => {
63
+    if (BuildingIds.length) {
64
+      setCurrentBuildingId(BuildingIds[0].buildingId)
65
+      setCurrentBuildingName(BuildingIds[0].name)
66
+    }
67
+  }, [BuildingIds])
68
+
69
+  useEffect(() => {
70
+    if (CurrentBuildingId) {
71
+      if (pageNumber === 1) {
72
+        GetPageList()
73
+      } else {
74
+        setPageNumber(1)
75
+      }
76
+    }
77
+  }, [CurrentBuildingId])
78
+
79
+  const GetMyBuildingIds = () => {
80
+    fetch({ url: API_MY_BUILDINGIDS, method: 'get' }).then((res) => {
81
+      setBuildingIds(res || [])
82
+    })
83
+  }
84
+
85
+  // useEffect(() => {
86
+  //   if(CurrentFilterMenuId) {
87
+  //     if(pageNumber === 1) {
88
+  //       GetPageList()
89
+  //     } else {
90
+  //       setPageNumber(1)
91
+  //     }
92
+  //   }
93
+  // }, [CurrentFilterMenuId])
23 94
 
24 95
   const PageRefresh = () => { // 页面下拉刷新回调
25 96
     setPull(true)
26 97
   }
27 98
 
28
-  const CutFilter = (item) => {
29
-    return () => {
30
-      setCurrentFilterMenuId(item.id === CurrentFilterMenuId ? null : item.id)
99
+  const GetPageList = () => {
100
+    setHasNextPage(false)
101
+    fetch({ url: API_MANAGE_CUSTOMER_LIST, method: 'get', payload: { pageNumber, pageSize: 10, ...FilterData, buildingId: CurrentBuildingId } }).then((res) => {
102
+      setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
103
+      setHasNextPage(res.current < res.pages)
104
+      setPull(false)
105
+    })
106
+  }
107
+
108
+  const PageLoadMore = () => { // 页面上拉加载更多
109
+    if (HasNextPage) {
110
+      setPageNumber(pageNumber + 1)
31 111
     }
32 112
   }
33 113
 
34 114
   useEffect(() => { // 下拉刷新触发
35 115
     if (IsPull) {
36
-      clearTimeout(PullTimer)
37
-      setPullTimer(setTimeout(() => {
38
-        setPull(false)
39
-      }, 2000))
116
+      if (pageNumber === 1) {
117
+        GetPageList()
118
+      } else {
119
+        setPageNumber(1)
120
+      }
40 121
     }
41 122
   }, [IsPull])
42 123
 
124
+  const PickerChange = (e) => {
125
+    setCurrentBuildingId(BuildingIds[e.detail.value - 0].buildingId)
126
+    setCurrentBuildingName(BuildingIds[e.detail.value - 0].name)
127
+  }
128
+
129
+  const SearchConfirm = (e) => {
130
+    setFilterData({ ...FilterData, keywords: e.detail.value })
131
+  }
132
+
43 133
   return (
44 134
     <view className='Page residentManager flex-v'>
45 135
 
46
-      <view className='Search'>
47
-        <view>
136
+      <view className='Search flex-h'>
137
+        <view className='flex-item'>
48 138
           <text className='iconfont icon-sousuo'></text>
49
-          <text>请输入关键字搜索</text>
139
+          <Input confirm-type='search' placeholder='请输入关键字搜索' onConfirm={SearchConfirm} onscrolltolower={PageLoadMore}></Input>
50 140
         </view>
141
+        <text>{CurrentBuildingName}</text>
142
+        <picker value={0} range-key='name' onChange={PickerChange} range={BuildingIds}>
143
+          <view class='picker'>更换</view>
144
+        </picker>
51 145
       </view>
52 146
 
53 147
       <view className='flex-item'>
@@ -55,7 +149,7 @@ export default withLayout(() => {
55 149
           <ScrollView scroll-y refresher-enabled refresher-triggered={IsPull} onrefresherrefresh={PageRefresh} refresher-background='#fff'>
56 150
             <view className='PageContent'>
57 151
 
58
-              <view className='Filter'>
152
+              {/* <view className='Filter'>
59 153
                 <text>筛选条件</text>
60 154
                 <view>
61 155
                   {
@@ -70,12 +164,12 @@ export default withLayout(() => {
70 164
                     ))
71 165
                   }
72 166
                 </view>
73
-              </view>
167
+              </view> */}
74 168
 
75 169
               <view className='List'>
76 170
                 {
77 171
                   PageList.map((item, index) => (
78
-                    <ResidentListItem Data={item} key={`ResidentListItem-${index}`}></ResidentListItem>
172
+                    <ResidentListItem data={item} key={`ResidentListItem-${index}`}></ResidentListItem>
79 173
                   ))
80 174
                 }
81 175
               </view>

+ 29
- 9
src/pages/mine/residentManager/index.scss Dosyayı Görüntüle

@@ -3,31 +3,51 @@
3 3
   position: relative;
4 4
   overflow: hidden;
5 5
   >.Search {
6
-    padding: 0 50px 20px;
6
+    padding: 0 30px 20px;
7 7
     position: relative;
8 8
     overflow: hidden;
9 9
     margin-top: 20px;
10
+    align-items: center;
10 11
     >view {
11 12
       position: relative;
12 13
       overflow: hidden;
13 14
       background: #f8f8f8;
14
-      border-radius: 44px;
15
+      border-radius: 80px;
15 16
       text-align: center;
16 17
       font-size: 0;
17 18
       white-space: nowrap;
18 19
       >text {
19 20
         display: inline-block;
20 21
         vertical-align: middle;
22
+        font-size: 24px;
23
+        color: #666;
24
+        line-height: 80px;
25
+      }
26
+      >input {
27
+        display: inline-block;
28
+        vertical-align: middle;
29
+        width: 200px;
21 30
         font-size: 20px;
22
-        color: #999;
23
-        margin-left: 8px;
24
-        line-height: 44px;
25
-        &:first-child {
26
-          margin-left: 0;
27
-          font-size: 28px;
28
-        }
31
+        margin-left: 10px;
32
+        height: 80px;
33
+        text-align: left;
29 34
       }
30 35
     }
36
+    >text {
37
+      font-size: 28px;
38
+      line-height: 40px;
39
+      max-width: 160px;
40
+      white-space: nowrap;
41
+      overflow: hidden;
42
+      text-overflow: ellipsis;
43
+      margin-left: 20px;
44
+      margin-right: 10px;
45
+    }
46
+    .picker {
47
+      font-size: 28px;
48
+      line-height: 40px;
49
+      color: #193C83;
50
+    }
31 51
   }
32 52
   > .flex-item {
33 53
     position: relative;

+ 4
- 2
src/pages/mine/tabData.js Dosyayı Görüntüle

@@ -1,7 +1,7 @@
1 1
 const MineMenuList = {
2 2
   User: [ // 普通用户
3 3
     [
4
-      { name: '推荐客户', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/addCustomer/index?type=customer' }
4
+      { name: '推荐客户', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/addCustomer/index?type=customer' },
5 5
     ],
6 6
     [
7 7
       { name: '我的分享', icon: require('../../assets/mine-icon9.png'), router: '/pages/mine/myShare/index' },
@@ -14,6 +14,7 @@ const MineMenuList = {
14 14
       { name: '意见反馈', icon: require('../../assets/mine-icon16.png'), router: '/pages/mine/feedBack/index' }
15 15
     ],
16 16
     [
17
+      { name: '成为驻场管理', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/toBeManager/index' },
17 18
       { name: '成为置业顾问', icon: require('../../assets/mine-icon4.png'), router: 'propertyConsultant' },
18 19
       { name: '成为专业经纪人', icon: require('../../assets/mine-icon2.png'), router: null }
19 20
     ]
@@ -39,6 +40,7 @@ const MineMenuList = {
39 40
   Adviser: [ // 置业顾问
40 41
     [
41 42
       { name: '添加客户', icon: require('../../assets/mine-icon7.png'), router: '/pages/mine/addCustomer/index?type=consultant' },
43
+      { name: '成为驻场管理', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/toBeManager/index' },
42 44
       { name: '我的主页', icon: require('../../assets/mine-icon15.png'), router: '/pages/mine/myHomepage/index' },
43 45
       { name: '我的推广码', icon: require('../../assets/mine-icon14.png'), router: '' },
44 46
       { name: '客户分析', icon: require('../../assets/mine-icon5.png'), router: '/pages/mine/customerAnalyse/index' },
@@ -58,7 +60,7 @@ const MineMenuList = {
58 60
   ],
59 61
   Resident: [ // 驻场管理
60 62
     [
61
-      // { name: '推荐客户', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/addCustomer/index?type=manager' },
63
+      { name: '绑定楼盘码', icon: require('../../assets/mine-icon8.png'), router: '/pages/mine/toBeManager/index' },
62 64
       { name: '驻场管理', icon: require('../../assets/mine-icon17.png'), router: '/pages/mine/residentManager/index' }
63 65
     ],
64 66
     [

+ 3
- 0
src/pages/mine/toBeManager/index.config.js Dosyayı Görüntüle

@@ -0,0 +1,3 @@
1
+export default {
2
+  navigationBarTitleText: '成为驻场管理'
3
+}

+ 52
- 0
src/pages/mine/toBeManager/index.jsx Dosyayı Görüntüle

@@ -0,0 +1,52 @@
1
+import { useState } from 'react'
2
+import Taro from '@tarojs/taro'
3
+import withLayout from '@/layout'
4
+import { ScrollView, Input } from '@tarojs/components'
5
+import { fetch } from '@/utils/request'
6
+import { API_TOBE_MANAGER } from '@/constants/api'
7
+import './index.scss'
8
+
9
+export default withLayout(() => {
10
+
11
+  const [Code, setCode] = useState('')
12
+
13
+  const ToSubmit = () => {
14
+    if (Code !== '') {
15
+      fetch({ url: API_TOBE_MANAGER, method: 'post', payload: { marketingCode: Code } }).then((res) => {
16
+        Taro.showToast({
17
+          title: '绑定成功',
18
+          icon: 'none'
19
+        })
20
+      })
21
+    } else {
22
+      Taro.showToast({
23
+        title: '请输入楼盘码',
24
+        icon: 'none'
25
+      })
26
+    }
27
+  }
28
+
29
+  const CodeChange = (e) => {
30
+    setCode(e.detail.value)
31
+  }
32
+
33
+  return (
34
+    <view className='Page toBeManager'>
35
+
36
+      <ScrollView scroll-y>
37
+        <view className='PageContent'>
38
+
39
+          <view className='Input'>
40
+            <Input placeholder='请输入楼盘码' onInput={CodeChange}></Input>
41
+          </view>
42
+
43
+          <view className='Btn'>
44
+            <text onClick={ToSubmit}>提交</text>
45
+          </view>
46
+
47
+        </view>
48
+      </ScrollView>
49
+
50
+    </view>
51
+  )
52
+})

+ 44
- 0
src/pages/mine/toBeManager/index.scss Dosyayı Görüntüle

@@ -0,0 +1,44 @@
1
+.Page.toBeManager {
2
+  background: #fff;
3
+  height: 100vh;
4
+  width: 100%;
5
+  > scroll-view {
6
+    width: 100%;
7
+    height: 100%;
8
+    .PageContent {
9
+      position: relative;
10
+      overflow: hidden;
11
+      min-height: 100vh;
12
+      >.Input {
13
+        padding: 0 30px;
14
+        position: relative;
15
+        overflow: hidden;
16
+        margin-top: 30px;
17
+        >input {
18
+          display: block;
19
+          font-size: 28px;
20
+          line-height: 80px;
21
+          height: 80px;
22
+          text-indent: 20px;
23
+          border: 2px solid rgba(0, 0, 0, 0.08);
24
+          border-radius: 8px;
25
+        }
26
+      }
27
+      >.Btn {
28
+        padding: 40px;
29
+        position: relative;
30
+        overflow: hidden;
31
+        > text {
32
+          display: block;
33
+          text-align: center;
34
+          font-size: 32px;
35
+          line-height: 92px;
36
+          background: #193c83;
37
+          color: #fff;
38
+          font-weight: bold;
39
+          border-radius: 92px;
40
+        }
41
+      }
42
+    }
43
+  }
44
+}

+ 15
- 0
src/reducers/system.js Dosyayı Görüntüle

@@ -13,6 +13,8 @@ const INITIAL_STATE = {
13 13
   recommender: {},
14 14
   // 当前推荐置业顾问信息
15 15
   consultant: {},
16
+  // 开屏广告 - 如果当前城市已展示过, 那么会把 cityId 放入数组
17
+  firstScreen: [],
16 18
 };
17 19
 
18 20
 export default function(state = INITIAL_STATE, action) {
@@ -41,6 +43,19 @@ export default function(state = INITIAL_STATE, action) {
41 43
         consultant: action.payload
42 44
       };
43 45
     }
46
+    case 'TOGGLE_FIRSTSCREEN': {
47
+      const { cityId } = action.payload
48
+      const showed = state.firstScreen.filter(x => x === cityId)[0]
49
+
50
+      if (!showed) {
51
+        return {
52
+          ...state,
53
+          firstScreen: state.firstScreen.concat(cityId)
54
+        };
55
+      }
56
+
57
+      return state;
58
+    }
44 59
 
45 60
     default:
46 61
       return state;

+ 6
- 0
src/routes.js Dosyayı Görüntüle

@@ -259,6 +259,12 @@ const routes = [
259 259
     pkg: 'main',
260 260
     type: 'mine',
261 261
   },
262
+  {
263
+    name: '成为驻场管理',
264
+    page: 'pages/mine/toBeManager/index',
265
+    pkg: 'main',
266
+    type: 'mine',
267
+  },
262 268
   {
263 269
     name: '推荐客户',
264 270
     page: 'pages/mine/recommendUser/index',

+ 1
- 1
src/utils/login.js Dosyayı Görüntüle

@@ -40,7 +40,7 @@ export default (payload) => {
40 40
 
41 41
           // 获取人员详细信息
42 42
           // eslint-disable-next-line no-unused-vars
43
-          queryUserInfo(person.personId).then(info => {
43
+          queryUserInfo().then(info => {
44 44
             // const { unReadNum } = info
45 45
 
46 46
             // 默认红点开始就有

+ 16
- 1
src/utils/request.js Dosyayı Görüntüle

@@ -89,12 +89,27 @@ 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 = typeof payload === 'Object'
95
+    ? Object.keys(payload).reduce((acc, key) => {
96
+        const val = payload[key]
97
+        if (val === null || val === undefined) {
98
+          return acc;
99
+        }
100
+
101
+        return {
102
+          ...acc,
103
+          [key]: val,
104
+        }
105
+      }, {})
106
+    : payload
92 107
   
93 108
   return [
94 109
     {
95 110
       url,
96 111
       method,
97
-      data: payload,
112
+      data,
98 113
       header: {
99 114
         'content-type': 'application/json',
100 115
         'authorization': `Bearer ${Taro.getStorageSync('token')}`,