Your Name vor 3 Jahren
Ursprung
Commit
197e47e1fd

+ 3
- 0
src/constants/api.js Datei anzeigen

308
 
308
 
309
 // 渠道-销售简报
309
 // 渠道-销售简报
310
 export const API_CHANNEL_STAT_REPORT = resolvePath('briefing')
310
 export const API_CHANNEL_STAT_REPORT = resolvePath('briefing')
311
+
312
+// 渠道客户基本状态
313
+export const API_CHANNEL_CUSTOMER_STATUS = resolvePath('channelCustomer/status')

+ 8
- 4
src/pages/mine/addCustomer/index.jsx Datei anzeigen

34
     sex: '', // 性别
34
     sex: '', // 性别
35
     intention: '', // 意向楼盘
35
     intention: '', // 意向楼盘
36
     realtyConsultant: '', // 置业顾问
36
     realtyConsultant: '', // 置业顾问
37
-    describe: '', // 描述
37
+    remark: '', // 描述
38
   })
38
   })
39
 
39
 
40
   const postSubmit = getSubmitor(person)
40
   const postSubmit = getSubmitor(person)
86
     postSubmit(payload).then(() => {
86
     postSubmit(payload).then(() => {
87
       setLoading(false)
87
       setLoading(false)
88
       Taro.showToast({ title: '操作成功', icon: 'none' })
88
       Taro.showToast({ title: '操作成功', icon: 'none' })
89
-      Taro.navigateBack({ delta: 1 })
89
+      
90
+      const t = setTimeout(() => {
91
+        Taro.navigateBack({ delta: 1 })
92
+        clearTimeout(t)
93
+      }, 2000)
90
     }).catch((err) => {
94
     }).catch((err) => {
91
       console.error(err)
95
       console.error(err)
92
       setLoading(false)
96
       setLoading(false)
140
               <text>内场接待(选填)</text>
144
               <text>内场接待(选填)</text>
141
               <view className='FormLine flex-h'>
145
               <view className='FormLine flex-h'>
142
                 <view className='flex-item'>
146
                 <view className='flex-item'>
143
-                  <ConsultantPicker onChange={setCardId} value={CardId} />
147
+                  <ConsultantPicker buildingId={buildingId} onChange={setCardId} value={CardId} />
144
                 </view>
148
                 </view>
145
                 <Image mode='heightFix' src={defaultSpecialImage}></Image>
149
                 <Image mode='heightFix' src={defaultSpecialImage}></Image>
146
                 <text>选择</text>
150
                 <text>选择</text>
149
               <text>备注</text>
153
               <text>备注</text>
150
               <view className='FormLine flex-h'>
154
               <view className='FormLine flex-h'>
151
                 <view className='flex-item'>
155
                 <view className='flex-item'>
152
-                  <Input placeholder='补充说明(选填)' data-type='describe' onInput={FormInput.bind(this)}></Input>
156
+                  <Input placeholder='补充说明(选填)' data-type='remark' onInput={FormInput.bind(this)}></Input>
153
                 </view>
157
                 </view>
154
               </view>
158
               </view>
155
             </Block>
159
             </Block>

+ 17
- 5
src/pages/mine/components/MyCustomerListItem/index.jsx Datei anzeigen

4
 import { BIZ_STATUS } from '@/constants/user'
4
 import { BIZ_STATUS } from '@/constants/user'
5
 import './index.scss'
5
 import './index.scss'
6
 
6
 
7
+const addDays = (dt, days) => {
8
+  const zone8 = 8 * 3600 * 100 // 中国时区, 因为 toJSON 是 ISO 时间
9
+  const ret = new Date(new Date(dt).valueOf() + (days - 1) * 24 * 3600 * 1000 + zone8)
10
+  return ret.toJSON().substring(0, 10)
11
+}
12
+
7
 export default function MyCustomerListItem (props) {
13
 export default function MyCustomerListItem (props) {
8
   const { data = {} } = props
14
   const { data = {} } = props
9
 
15
 
10
-  const { expirationDate, customerStatus } = data
11
-  const expStr = expirationDate && customerStatus === '1' ? `${expirationDate.substring(0, 10)} 回收` : ''
16
+  const { expirationDate, customerStatus, createDate } = data
17
+  const expStr = expirationDate && customerStatus === '1' ? `${addDays(createDate, expirationDate)} 回收` : ''
12
 
18
 
13
   const gotoDetail = () => {
19
   const gotoDetail = () => {
14
-    const id = data.channelCustomerId || data.customerId
15
-    const url = `/pages/mine/myCustomerDetail/index?id=${id}`
16
-    Taro.navigateTo({ url })
20
+    if (!data.customerId) {
21
+      Taro.showToast({
22
+        title: '该用户尚未到访',
23
+        icon: 'none',
24
+      })
25
+    } else {
26
+      const url = `/pages/mine/myCustomerDetail/index?id=${data.customerId}`
27
+      Taro.navigateTo({ url })
28
+    }
17
   }
29
   }
18
 
30
 
19
   return (
31
   return (

+ 1
- 1
src/pages/mine/customerDetail/index.jsx Datei anzeigen

32
   const [FollowAddCounts, setFollowAddCounts] = useState(0)
32
   const [FollowAddCounts, setFollowAddCounts] = useState(0)
33
 
33
 
34
   const UpdateCustomerInfo = () => {
34
   const UpdateCustomerInfo = () => {
35
-    fetch({ url: `${API_GET_CUSTOMER_INFO}${CustomerId}` }).then((res) => {
35
+    fetch({ url: `${API_GET_CUSTOMER_INFO}/${CustomerId}` }).then((res) => {
36
       if (res) {
36
       if (res) {
37
         setCustomerInfo(res)
37
         setCustomerInfo(res)
38
       }
38
       }

+ 20
- 5
src/pages/mine/myCustomer/index.jsx Datei anzeigen

17
   const [ShowDatePicker, setShowDatePicker] = useState(false)
17
   const [ShowDatePicker, setShowDatePicker] = useState(false)
18
   const [pageNumber, setPageNumber] = useState(1)
18
   const [pageNumber, setPageNumber] = useState(1)
19
   const [HasNextPage, setHasNextPage] = useState(true)
19
   const [HasNextPage, setHasNextPage] = useState(true)
20
+  const [dateRange, setDateRange] = useState([])
20
   const [bizType, setBizType] = useState('')
21
   const [bizType, setBizType] = useState('')
22
+  const [name, setName] = useState()
21
   const GetPageList = useRef()
23
   const GetPageList = useRef()
22
 
24
 
23
   GetPageList.current = () => {
25
   GetPageList.current = () => {
24
     setHasNextPage(false)
26
     setHasNextPage(false)
25
     const url = ROLE_CODE.CHANNEL_AGENT === person.personType ? API_CHANNEL_CLIENT_LIST : API_CLIENT_LIST
27
     const url = ROLE_CODE.CHANNEL_AGENT === person.personType ? API_CHANNEL_CLIENT_LIST : API_CLIENT_LIST
26
-    fetch({ url, payload: { pageNumber, pageSize: 10 } }).then((res) => {
28
+    const [startDate, endDate] = dateRange
29
+    const payload = {
30
+      pageNumber,
31
+      name,
32
+      status: bizType ? bizType - 0 : undefined,
33
+      pageSize: 10,
34
+      startDate: startDate ? `${startDate}T00:00:00.000Z` : undefined,
35
+      endDate: endDate ? `${endDate}T23:59:59.999Z` : undefined,
36
+    }
37
+    fetch({ url, payload }).then((res) => {
27
       setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
38
       setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
28
       setHasNextPage(res.current < res.pages)
39
       setHasNextPage(res.current < res.pages)
29
       setPull(false)
40
       setPull(false)
30
     })
41
     })
31
   }
42
   }
32
 
43
 
44
+  const handleNameConfirm = (e) => {
45
+    setName(e.detail.value)
46
+  }
47
+
33
   const PageRefresh = () => { // 页面下拉刷新回调
48
   const PageRefresh = () => { // 页面下拉刷新回调
34
     setPull(true)
49
     setPull(true)
35
   }
50
   }
42
 
57
 
43
   useEffect(() => {
58
   useEffect(() => {
44
     GetPageList.current()
59
     GetPageList.current()
45
-  }, [pageNumber])
60
+  }, [pageNumber, bizType, name, dateRange])
46
 
61
 
47
   useEffect(() => { // 下拉刷新触发
62
   useEffect(() => { // 下拉刷新触发
48
     if (IsPull) {
63
     if (IsPull) {
55
   }, [IsPull])
70
   }, [IsPull])
56
 
71
 
57
   const DateChange = (e) => {
72
   const DateChange = (e) => {
58
-    console.log(e)
73
+    setDateRange(e)
59
     setShowDatePicker(false)
74
     setShowDatePicker(false)
60
   }
75
   }
61
 
76
 
65
       <view className='Filter'>
80
       <view className='Filter'>
66
         <view className='flex-h'>
81
         <view className='flex-h'>
67
           <view className='Time' onClick={() => { setShowDatePicker(true) }}>
82
           <view className='Time' onClick={() => { setShowDatePicker(true) }}>
68
-            <text>全部时间</text>
83
+            <text>选择时间</text>
69
             <text className='iconfont icon-sanjiaoxingdown'></text>
84
             <text className='iconfont icon-sanjiaoxingdown'></text>
70
           </view>
85
           </view>
71
           <view className='Type'>
86
           <view className='Type'>
75
           <view className='flex-item'></view>
90
           <view className='flex-item'></view>
76
           <view className='Search'>
91
           <view className='Search'>
77
             <text className='iconfont icon-sousuo'></text>
92
             <text className='iconfont icon-sousuo'></text>
78
-            <Input placeholder='请输入'></Input>
93
+            <Input placeholder='请输入' onConfirm={handleNameConfirm}></Input>
79
           </view>
94
           </view>
80
         </view>
95
         </view>
81
       </view>
96
       </view>

+ 50
- 0
src/pages/mine/myCustomerDetail/hooks/useFollow.js Datei anzeigen

1
+
2
+import { useEffect, useRef, useState } from 'react'
3
+import Taro from '@tarojs/taro'
4
+import { getFollowRecord, addFollowRecord } from '@/services/person'
5
+
6
+export default function useFollow(customer) {
7
+  const [submitting, setSubmitting] = useState(false)
8
+  const [followList, setFollowList] = useState([])
9
+  const queryRef = useRef()
10
+  queryRef.current = () => {
11
+    getFollowRecord({
12
+      pageNumber: 1,
13
+      pageSize: 100,
14
+      customerId: customer.customerId,
15
+      recordType: '跟进',
16
+    }).then((res) => {
17
+      const { records } = res
18
+      setFollowList(records || [])
19
+    })
20
+  }
21
+
22
+  const addFollow = (data) => {
23
+    const payload = {
24
+      recordType: '添加跟进',
25
+      recordContent: data,
26
+      customerSex: customer.sex,
27
+      customerId: customer.customerId,
28
+    }
29
+
30
+    setSubmitting(true)
31
+
32
+    addFollowRecord(payload).then((res) => {
33
+      Taro.showToast({
34
+        title: '添加成功',
35
+        icon: 'none',
36
+      })
37
+
38
+      setFollowList([res].concat(followList))
39
+      setSubmitting(false)
40
+    }).catch(() => setSubmitting(false))
41
+  }
42
+
43
+  useEffect(() => {
44
+    if (customer.customerId) {
45
+      queryRef.current()
46
+    }
47
+  }, [customer?.customerId])
48
+
49
+  return [followList, submitting, addFollow]
50
+}

+ 4
- 1
src/pages/mine/myCustomerDetail/index.config.js Datei anzeigen

1
 export default {
1
 export default {
2
-  navigationBarTitleText: '客户详情'
2
+  navigationBarTitleText: '客户详情',
3
+  usingComponents: {
4
+    'page-modal': '@/native/PageContainer/index'
5
+  }
3
 }
6
 }

+ 68
- 24
src/pages/mine/myCustomerDetail/index.jsx Datei anzeigen

1
 import React, { useState, useEffect } from 'react'
1
 import React, { useState, useEffect } from 'react'
2
+import Taro from '@tarojs/taro'
2
 import withLayout from '@/layout'
3
 import withLayout from '@/layout'
3
-import { getChannelCustomerDetail } from '@/services/person'
4
+import { getChannelCustomerStatus, getCustomerDetail, getCustomerInfo } from '@/services/person'
4
 import { ScrollView, Image } from '@tarojs/components'
5
 import { ScrollView, Image } from '@tarojs/components'
6
+import Modal from '@/components/Modal'
7
+import { ROLE_CODE } from '@/constants/user'
8
+import { formatDate } from '@/utils/chatDate'
9
+import EditUserDetailBasicInfo from '../components/EditUserDetailBasicInfo'
10
+import useFollow from './hooks/useFollow'
5
 import '@/assets/css/iconfont.css'
11
 import '@/assets/css/iconfont.css'
6
 import './index.scss'
12
 import './index.scss'
7
-import { ROLE_CODE } from '@/constants/user'
13
+
14
+const addDays = (dt, days) => {
15
+  const zone8 = 8 * 3600 * 100 // 中国时区, 因为 toJSON 是 ISO 时间
16
+  const ret = new Date(new Date(dt).valueOf() + (days - 1) * 24 * 3600 * 1000 + zone8)
17
+  return ret.toJSON().substring(0, 10)
18
+}
8
 
19
 
9
 export default withLayout((props) => {
20
 export default withLayout((props) => {
10
   const { router, person } = props
21
   const { router, person } = props
11
   const { id } = router.params
22
   const { id } = router.params
12
 
23
 
13
   const [custBaseInfo, setCustBaseInfo] = useState({})
24
   const [custBaseInfo, setCustBaseInfo] = useState({})
25
+  const [custMoreInfo, setCustMoreInfo] = useState({})
26
+  const [statusInfo, setStatusInfo] = useState({})
27
+  const [followContent, setFollowContent] = useState()
28
+  const [showUserEditor, setShowUserEditor] = useState(false)
29
+  const [showFollowModal, setShowFollowModal] = useState(false)
30
+  const [followList, followSubmitting, addFollow] = useFollow(custBaseInfo)
31
+
32
+  const { channelCustomer, building } = statusInfo
33
+  const expirationDate = building?.expirationDate ?
34
+    addDays(channelCustomer?.createDate, building?.expirationDate) :
35
+    '暂无'
36
+
37
+  const handleAddFollow = () => {
38
+    addFollow(followContent)
39
+    const t = setTimeout(() => {
40
+      setShowFollowModal(false)
41
+      clearTimeout(t)
42
+    }, 1500)
43
+  }
14
 
44
 
15
   useEffect(() => {
45
   useEffect(() => {
16
     if (id) {
46
     if (id) {
17
-      if (person.personType === ROLE_CODE.CHANNEL_AGENT) {
18
-        getChannelCustomerDetail(id).then((res) => setCustBaseInfo(res || {}))
19
-      }
47
+      getCustomerDetail(id).then((x) => {
48
+        setCustBaseInfo(x || {})
49
+      })
50
+
51
+      getChannelCustomerStatus(id).then((x) => {
52
+        setStatusInfo(x || {})
53
+      })
54
+
55
+      getCustomerInfo(id).then((x) => {
56
+        setCustMoreInfo(x || {})
57
+      })
20
     }
58
     }
21
   }, [id, person])
59
   }, [id, person])
22
 
60
 
23
   return (
61
   return (
24
     <view className='Page myCustomerDetail'>
62
     <view className='Page myCustomerDetail'>
25
-
26
       <ScrollView scrollY>
63
       <ScrollView scrollY>
27
         <view className='PageContent'>
64
         <view className='PageContent'>
28
 
65
 
34
             <view className='Content'>
71
             <view className='Content'>
35
               <view className='UserInfo flex-h'>
72
               <view className='UserInfo flex-h'>
36
                 <view className='Icon'>
73
                 <view className='Icon'>
37
-                  <Image mode='aspectFill' src={null}></Image>
74
+                  <Image mode='aspectFill' src={custBaseInfo.avatarurl || custBaseInfo.picture}></Image>
38
                 </view>
75
                 </view>
39
                 <view className='flex-item'>
76
                 <view className='flex-item'>
40
                   <text>{custBaseInfo.name}</text>
77
                   <text>{custBaseInfo.name}</text>
41
                   <text>{custBaseInfo.phone}</text>
78
                   <text>{custBaseInfo.phone}</text>
42
                 </view>
79
                 </view>
43
-                <text className='iconfont icon-jiantouright'></text>
80
+                <text className='iconfont icon-jiantouright' onClick={() => setShowUserEditor(true)}></text>
44
               </view>
81
               </view>
45
               <view className='Status'>
82
               <view className='Status'>
46
-                <view className='flex-h'>
83
+                {/* <view className='flex-h'>
47
                   <view className='flex-item'>
84
                   <view className='flex-item'>
48
                     <text>对楼盘意向值:</text>
85
                     <text>对楼盘意向值:</text>
49
                     <text>xxxxxxxxxxx</text>
86
                     <text>xxxxxxxxxxx</text>
50
                   </view>
87
                   </view>
51
-                </view>
88
+                </view> */}
52
                 <view className='flex-h'>
89
                 <view className='flex-h'>
53
                   <view className='flex-item'>
90
                   <view className='flex-item'>
54
                     <text>跟进状态:</text>
91
                     <text>跟进状态:</text>
62
                 <view className='flex-h'>
99
                 <view className='flex-h'>
63
                   <view className='flex-item'>
100
                   <view className='flex-item'>
64
                     <text>跟进结果:</text>
101
                     <text>跟进结果:</text>
65
-                    <text>已跟进</text>
102
+                    <text>{statusInfo.followed ? '今日已跟进' : '今日未跟进'}</text>
66
                   </view>
103
                   </view>
67
                   <view className='flex-item'>
104
                   <view className='flex-item'>
68
                     <text>报备结果:</text>
105
                     <text>报备结果:</text>
69
-                    <text>已报备</text>
106
+                    <text>{custBaseInfo.status > 1 ? '已到访' : '已报备'}</text>
70
                   </view>
107
                   </view>
71
                 </view>
108
                 </view>
72
                 <view className='flex-h'>
109
                 <view className='flex-h'>
73
                   <view className='flex-item'>
110
                   <view className='flex-item'>
74
                     <text>预计收回时间:</text>
111
                     <text>预计收回时间:</text>
75
-                    <text>2020-06-12-12:00</text>
112
+                    <text>{expirationDate}</text>
76
                   </view>
113
                   </view>
77
                 </view>
114
                 </view>
78
               </view>
115
               </view>
119
           </view>
156
           </view>
120
 
157
 
121
           {/* 操作人员 */}
158
           {/* 操作人员 */}
122
-          <view className='OptUser'>
159
+          {/* <view className='OptUser'>
123
             <view className='Title flex-h'>
160
             <view className='Title flex-h'>
124
               <text>操作人员</text>
161
               <text>操作人员</text>
125
               <view className='flex-item'></view>
162
               <view className='flex-item'></view>
139
                 </view>
176
                 </view>
140
               </view>
177
               </view>
141
             </view>
178
             </view>
142
-          </view>
179
+          </view> */}
143
 
180
 
144
           {/* 跟进记录 */}
181
           {/* 跟进记录 */}
145
           <view className='Record'>
182
           <view className='Record'>
146
             <view className='Title flex-h'>
183
             <view className='Title flex-h'>
147
               <text>跟进记录</text>
184
               <text>跟进记录</text>
148
-              <view className='Edit'>
185
+              <view className='Edit' onClick={() => setShowFollowModal(true)}>
149
                 <Image mode='heightFix' src={require('../../../assets/mine-icon26.png')}></Image>
186
                 <Image mode='heightFix' src={require('../../../assets/mine-icon26.png')}></Image>
150
-                <text>修改</text>
187
+                <text>新增</text>
151
               </view>
188
               </view>
152
               <view className='flex-item'></view>
189
               <view className='flex-item'></view>
153
-              <view className='More'>
190
+              {/* <view className='More'>
154
                 <text>更多</text>
191
                 <text>更多</text>
155
                 <text className='iconfont icon-jiantouright'></text>
192
                 <text className='iconfont icon-jiantouright'></text>
156
-              </view>
193
+              </view> */}
157
             </view>
194
             </view>
158
             <view className='Content'>
195
             <view className='Content'>
159
               {
196
               {
160
-                ['', '', ''].map((item, index) => (
197
+                followList.map((item, index) => (
161
                   <view key={`Item-${index}`}>
198
                   <view key={`Item-${index}`}>
162
                     <view className='flex-h'>
199
                     <view className='flex-h'>
163
                       <text>范丞丞</text>
200
                       <text>范丞丞</text>
164
                       <view className='flex-item'></view>
201
                       <view className='flex-item'></view>
165
-                      <text>2021-05-21 12:00</text>
202
+                      <text>{formatDate(item.createDate, 'yyyy-MM-dd hh:mm')}</text>
166
                     </view>
203
                     </view>
167
                     <view className='Desc'>
204
                     <view className='Desc'>
168
-                      <text>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </text>
205
+                      <text>{item.recordContent}</text>
169
                     </view>
206
                     </view>
170
                   </view>
207
                   </view>
171
                 ))
208
                 ))
172
               }
209
               }
173
             </view>
210
             </view>
174
           </view>
211
           </view>
175
-
176
         </view>
212
         </view>
177
       </ScrollView>
213
       </ScrollView>
178
-
214
+      <Modal visible={showFollowModal} title='添加跟进' onClose={() => setShowFollowModal(false)}>
215
+        <view>
216
+          <textarea style={{border: '1px solid rgba(0,0,0, .1)', borderRadius: '4px', margin: '1em', padding: '.5em'}} value={followContent} placeholder='请填写跟进内容' onInput={(e) => setFollowContent(e.detail.value)} />
217
+          <button loading={followSubmitting} style={{ background: '#193c83', color: '#fff', borderRadius: 0 }} onClick={handleAddFollow}>确定</button>
218
+        </view>
219
+      </Modal>
220
+      <page-modal show={showUserEditor} position='bottom' onClickOverlay={() => setShowUserEditor(false)} height='90vh'>
221
+        <EditUserDetailBasicInfo Data={custMoreInfo} CustomerId={id} close={() => setShowUserEditor(false)} />
222
+      </page-modal>
179
     </view>
223
     </view>
180
   )
224
   )
181
 })
225
 })

+ 40
- 22
src/pages/mine/partnerChannel/components/LineChat.jsx Datei anzeigen

2
 import Chart from '@/components/Chart'
2
 import Chart from '@/components/Chart'
3
 
3
 
4
 export default (props) => {
4
 export default (props) => {
5
-  const { dataSource } = props
5
+  const { dataSource, xAxisDataRef } = props
6
 
6
 
7
   const [options, setOptions] = useState()
7
   const [options, setOptions] = useState()
8
 
8
 
9
   useEffect(() => {
9
   useEffect(() => {
10
-    const data = [[],[]];
11
-    (dataSource || []).forEach((it) => {
12
-      const dt = it.coordinate.length >= 10 ? it.coordinate.substring(5) : it.coordinate
10
+    if (xAxisDataRef.current) {
11
+      const data = [[],[]];
12
+      (dataSource || []).forEach((it) => {
13
+        const dt = it.coordinate.length >= 10 ? it.coordinate.substring(5) : it.coordinate
14
+  
15
+        data[0].push(dt)
16
+        data[1].push(it.customerNum)
17
+      })
18
+      setOptions({
19
+        xAxis: {
20
+          type: 'category',
21
+          axisLabel: {
22
+            rotate: 45, // 旋转 45 度
23
+          },
24
+          data: xAxisDataRef.current.map((x) => {
25
+            const parts = x.split('-')
13
 
26
 
14
-      data[0].push(dt)
15
-      data[1].push(it.customerNum)
16
-    })
17
-    setOptions({
18
-      xAxis: {
19
-        type: 'category',
20
-        data: data[0],
21
-      },
22
-      yAxis: {
23
-        type: 'value',
24
-      },
25
-      series: [{
26
-        type: 'line',
27
-        smooth: true,
28
-        data: data[1],
29
-      }],
30
-      color: ['#5470c6'],
31
-    });
27
+            if (parts.length === 3) {
28
+              // 如果是天, 2006-03-04 那么会返回 03-04
29
+              return `${parts[1]}-${parts[2]}`
30
+            } else {
31
+              // 如果是月 2006-03 那么会返回 3月
32
+              return `${parts[1] - 0}月`
33
+            }
34
+          }),
35
+        },
36
+        yAxis: {
37
+          type: 'value',
38
+        },
39
+        series: [{
40
+          type: 'line',
41
+          smooth: true,
42
+          data: xAxisDataRef.current.map((dt) => {
43
+            const it = (dataSource || []).filter(x => x.coordinate === dt)[0]
44
+            return it ? it.customerNum : 0
45
+          }),
46
+        }],
47
+        color: ['#5470c6'],
48
+      });
49
+    }
32
   }, [dataSource])
50
   }, [dataSource])
33
 
51
 
34
   return (
52
   return (

+ 9
- 4
src/pages/mine/partnerChannel/hooks/useChart.js Datei anzeigen

1
-import { useState, useEffect } from 'react'
1
+import { useState, useEffect, useRef } from 'react'
2
 import { getChannelLineChat } from '@/services/agent'
2
 import { getChannelLineChat } from '@/services/agent'
3
-import { fillTime, cutDays, cutMonths } from '../utils'
3
+import { fillTime, cutDays, cutMonths, getList } from '../utils'
4
 
4
 
5
 const now = new Date()
5
 const now = new Date()
6
 
6
 
8
   const [statType, setStatType] = useState('day')
8
   const [statType, setStatType] = useState('day')
9
   const [custType, setCustType] = useState('new')
9
   const [custType, setCustType] = useState('new')
10
   const [chartData, setChartData] = useState([])
10
   const [chartData, setChartData] = useState([])
11
+  const xAxisDataRef = useRef()
11
 
12
 
12
   useEffect(() => {
13
   useEffect(() => {
13
-    const startDate = statType === 'month' ? cutMonths(now, 6) : cutDays(now, 7)
14
+    // 按月默认统计半年的, 按天默认统计7天的
15
+    const num = statType === 'month' ? 6 : 7
16
+    const startDate = statType === 'month' ? cutMonths(now, num) : cutDays(now, num)
17
+    xAxisDataRef.current = getList(startDate, num, statType)
18
+
14
     getChannelLineChat({
19
     getChannelLineChat({
15
       type: statType,
20
       type: statType,
16
       customerType: custType,
21
       customerType: custType,
21
     })
26
     })
22
   }, [statType, custType])
27
   }, [statType, custType])
23
 
28
 
24
-  return [statType, setStatType, custType, setCustType, chartData]
29
+  return [statType, setStatType, custType, setCustType, chartData, xAxisDataRef]
25
 }
30
 }

+ 24
- 18
src/pages/mine/partnerChannel/index.jsx Datei anzeigen

2
 import withLayout from '@/layout'
2
 import withLayout from '@/layout'
3
 import Taro from '@tarojs/taro'
3
 import Taro from '@tarojs/taro'
4
 import { ScrollView, Image } from '@tarojs/components'
4
 import { ScrollView, Image } from '@tarojs/components'
5
-import { getChannelRank, getChannelStatReport } from '@/services/agent'
6
-import { fetch } from '@/utils/request'
7
-import { API_GET_AGENT_BUILDINGS } from '@/constants/api'
8
-// import {  } from '@/constants/user'
5
+import { BIZ_STATUS } from '@/constants/user'
9
 import DateRangePicker from '@/components/DateRangePicker'
6
 import DateRangePicker from '@/components/DateRangePicker'
10
 import Picker from '@/components/Picker'
7
 import Picker from '@/components/Picker'
11
 import LineChat from './components/LineChat'
8
 import LineChat from './components/LineChat'
31
   const pickerTrigger = useRef()
28
   const pickerTrigger = useRef()
32
   const [,setRankDateRange, rankList] = useRank()
29
   const [,setRankDateRange, rankList] = useRank()
33
   const [,setReportDateRange, reportInfo] = useReport()
30
   const [,setReportDateRange, reportInfo] = useReport()
34
-  const [statType, setStatType, custType, setCustType, chartData] = useChart()
31
+  const [
32
+    statType,
33
+    setStatType,
34
+    custType,
35
+    setCustType,
36
+    chartData,
37
+    xAxisDataRef,
38
+  ] = useChart()
35
 
39
 
36
   const handleMore = () => {
40
   const handleMore = () => {
37
     Taro.navigateTo({ url: '/pages/mine/myCustomer/index' })
41
     Taro.navigateTo({ url: '/pages/mine/myCustomer/index' })
57
     }
61
     }
58
   }
62
   }
59
 
63
 
64
+  const [tp1 = {}, tp2 = {}, tp3 = {}] = rankList||[]
65
+
60
   return (
66
   return (
61
     <view className='Page partnerChannel'>
67
     <view className='Page partnerChannel'>
62
       <DateRangePicker visable={showPicker} close={() => setShowPicker(false)} change={handlePickerChange} />
68
       <DateRangePicker visable={showPicker} close={() => setShowPicker(false)} change={handlePickerChange} />
75
               <view className='flex-item'>
81
               <view className='flex-item'>
76
                 <Image mode='heightFix' src={require('@/assets/mine-icon21.png')}></Image>
82
                 <Image mode='heightFix' src={require('@/assets/mine-icon21.png')}></Image>
77
                 <view className='Icon'>
83
                 <view className='Icon'>
78
-                  <Image mode='aspectFill' src={null}></Image>
84
+                  <Image mode='aspectFill' src={tp2.avatarurl}></Image>
79
                 </view>
85
                 </view>
80
                 <view className='Index'>
86
                 <view className='Index'>
81
-                  <text>范冰冰</text>
87
+                  <text>{tp2.name||'暂无'}</text>
82
                   <text>2</text>
88
                   <text>2</text>
83
                 </view>
89
                 </view>
84
                 <view className='Num'>
90
                 <view className='Num'>
85
                   <text></text>
91
                   <text></text>
86
-                  <text>到访10人</text>
92
+                  <text>{tp2.number ? `到访 ${tp2.number} 人` : '暂无'}</text>
87
                 </view>
93
                 </view>
88
               </view>
94
               </view>
89
               
95
               
91
               <view className='flex-item active'>
97
               <view className='flex-item active'>
92
                 <Image mode='heightFix' src={require('@/assets/mine-icon20.png')}></Image>
98
                 <Image mode='heightFix' src={require('@/assets/mine-icon20.png')}></Image>
93
                 <view className='Icon'>
99
                 <view className='Icon'>
94
-                  <Image mode='aspectFill' src={null}></Image>
100
+                  <Image mode='aspectFill' src={tp1.avatarurl}></Image>
95
                 </view>
101
                 </view>
96
                 <view className='Index'>
102
                 <view className='Index'>
97
-                  <text>范冰冰</text>
103
+                  <text>{tp1.name||'暂无'}</text>
98
                   <text>1</text>
104
                   <text>1</text>
99
                 </view>
105
                 </view>
100
                 <view className='Num'>
106
                 <view className='Num'>
101
                   <text></text>
107
                   <text></text>
102
-                  <text>到访10人</text>
108
+                  <text>{tp1.number ? `到访 ${tp1.number} 人` : '暂无'}</text>
103
                 </view>
109
                 </view>
104
               </view>
110
               </view>
105
               
111
               
107
               <view className='flex-item'>
113
               <view className='flex-item'>
108
                 <Image mode='heightFix' src={require('@/assets/mine-icon22.png')}></Image>
114
                 <Image mode='heightFix' src={require('@/assets/mine-icon22.png')}></Image>
109
                 <view className='Icon'>
115
                 <view className='Icon'>
110
-                  <Image mode='aspectFill' src={null}></Image>
116
+                  <Image mode='aspectFill' src={tp3.avatarurl}></Image>
111
                 </view>
117
                 </view>
112
                 <view className='Index'>
118
                 <view className='Index'>
113
-                  <text>范冰冰</text>
119
+                  <text>{tp3.name||'暂无'}</text>
114
                   <text>3</text>
120
                   <text>3</text>
115
                 </view>
121
                 </view>
116
                 <view className='Num'>
122
                 <view className='Num'>
117
                   <text></text>
123
                   <text></text>
118
-                  <text>到访10人</text>
124
+                  <text>{tp3.number ? `到访 ${tp3.number} 人` : '暂无'}</text>
119
                 </view>
125
                 </view>
120
               </view>
126
               </view>
121
               
127
               
135
               <view className='flex-h'>
141
               <view className='flex-h'>
136
                 <text className='flex-item'>新增客户</text>
142
                 <text className='flex-item'>新增客户</text>
137
                 <text>{`${reportInfo.newCustomerNum||0}人`}</text>
143
                 <text>{`${reportInfo.newCustomerNum||0}人`}</text>
138
-                <text className='iconfont icon-jiantouright'></text>
144
+                {/* <text className='iconfont icon-jiantouright'></text> */}
139
               </view>
145
               </view>
140
               <view className='flex-h'>
146
               <view className='flex-h'>
141
                 <text className='flex-item'>跟进客户</text>
147
                 <text className='flex-item'>跟进客户</text>
142
                 <text>{`${reportInfo.followCustomerNum||0}人`}</text>
148
                 <text>{`${reportInfo.followCustomerNum||0}人`}</text>
143
-                <text className='iconfont icon-jiantouright'></text>
149
+                {/* <text className='iconfont icon-jiantouright'></text> */}
144
               </view>
150
               </view>
145
               <view className='flex-h'>
151
               <view className='flex-h'>
146
                 <text className='flex-item'>成交客户</text>
152
                 <text className='flex-item'>成交客户</text>
147
                 <text>{`${reportInfo.successCustomerNum||0}人`}</text>
153
                 <text>{`${reportInfo.successCustomerNum||0}人`}</text>
148
-                <text className='iconfont icon-jiantouright'></text>
154
+                {/* <text className='iconfont icon-jiantouright'></text> */}
149
               </view>
155
               </view>
150
             </view>
156
             </view>
151
           </view>
157
           </view>
165
               </view>
171
               </view>
166
             </view>
172
             </view>
167
             <view className='LineChart'>
173
             <view className='LineChart'>
168
-              <LineChat dataSource={chartData} />
174
+              <LineChat xAxisDataRef={xAxisDataRef} dataSource={chartData} />
169
             </view>
175
             </view>
170
           </view>
176
           </view>
171
 
177
 

+ 36
- 2
src/pages/mine/partnerChannel/utils/index.js Datei anzeigen

20
  * @returns 
20
  * @returns 
21
  */
21
  */
22
 export function cutDays(dt, days) {
22
 export function cutDays(dt, days) {
23
-  const ret = new Date(new Date(dt).valueOf() - days * 24 * 3600 * 1000)
23
+  const zone8 = 8 * 3600 * 100 // 中国时区, 因为 toJSON 是 ISO 时间
24
+  const ret = new Date(new Date(dt).valueOf() - (days - 1) * 24 * 3600 * 1000 + zone8)
24
   return new Date(ret.toJSON().substring(0, 10))
25
   return new Date(ret.toJSON().substring(0, 10))
25
 }
26
 }
26
 
27
 
33
 export function cutMonths(dt, months) {
34
 export function cutMonths(dt, months) {
34
   const origin = new Date(dt)
35
   const origin = new Date(dt)
35
   const mon = origin.getMonth() + 1
36
   const mon = origin.getMonth() + 1
36
-  const startMonth = mon - months + 1
37
+  const startMonth = mon - months
37
   if (startMonth <= 0) {
38
   if (startMonth <= 0) {
38
     const startYear = origin.getFullYear() - 1
39
     const startYear = origin.getFullYear() - 1
39
     return new Date(`${startYear}-${padMonth(startMonth + 12)}-01`)
40
     return new Date(`${startYear}-${padMonth(startMonth + 12)}-01`)
41
     return new Date(`${origin.getFullYear()}-${padMonth(startMonth)}-01`)
42
     return new Date(`${origin.getFullYear()}-${padMonth(startMonth)}-01`)
42
   }
43
   }
43
 }
44
 }
45
+
46
+/**
47
+ * 获取持续的月份, 或者天数
48
+ * @param {*} dt 
49
+ * @param {*} num 
50
+ * @param {*} type 
51
+ * @returns 
52
+ */
53
+export function getList(dt, num, type) {
54
+  const arr = new Array(num).fill();
55
+  if (type === 'day') {
56
+    const increment = 24 * 3600 * 1000
57
+    const zone8 = 8 * 3600 * 100 // 中国时区, 因为 toJSON 是 ISO 时间
58
+    return arr.map((_, inx) => {
59
+      const nw = new Date(dt.valueOf() + inx * increment + zone8)
60
+      return nw.toJSON().substring(0, 10)
61
+    })
62
+  } else {
63
+    const year = dt.getFullYear()
64
+    const month = dt.getMonth() + 1
65
+
66
+    return arr.map((_, inx) => {
67
+      let y = year
68
+      let nw = month + inx
69
+      if (nw > 12) {
70
+        nw -= 12
71
+        y += 1
72
+      }
73
+
74
+      return `${y}-${padMonth(nw)}`
75
+    })
76
+  }
77
+}

+ 14
- 0
src/services/person.js Datei anzeigen

16
   API_SHARE_INFOLIST,
16
   API_SHARE_INFOLIST,
17
   API_BIND_CUSTOMER,
17
   API_BIND_CUSTOMER,
18
   API_CHANNEL_CUSTOMER_DETAIL,
18
   API_CHANNEL_CUSTOMER_DETAIL,
19
+  API_CHANNEL_CUSTOMER_STATUS,
20
+  API_GET_CUSTOMER_INFO,
19
 } from '@/constants/api'
21
 } from '@/constants/api'
20
 
22
 
21
 
23
 
114
  */
116
  */
115
 export const getChannelCustomerDetail = (id) => fetch({ url: `${API_CHANNEL_CUSTOMER_DETAIL}/${id}` })
117
 export const getChannelCustomerDetail = (id) => fetch({ url: `${API_CHANNEL_CUSTOMER_DETAIL}/${id}` })
116
 
118
 
119
+/**
120
+ * 获取客户基本基本状态
121
+ * @param {*} id 
122
+ * @returns 
123
+ */
124
+export const getChannelCustomerStatus = (id) => fetch({ url: `${API_CHANNEL_CUSTOMER_STATUS}/${id}` })
117
 
125
 
126
+/**
127
+ * 获取客户详情信息
128
+ * @param {*} id 
129
+ * @returns 
130
+ */
131
+export const getCustomerInfo = (id) => fetch({ url: `${API_GET_CUSTOMER_INFO}/${id}` })