Your Name 3 年之前
父節點
當前提交
b7f0c64fd1

+ 46
- 0
src/components/Picker/index.jsx 查看文件

@@ -0,0 +1,46 @@
1
+import { useEffect, useState } from 'react'
2
+import { Picker, View } from '@tarojs/components'
3
+import './style.scss'
4
+
5
+export default (props) => {
6
+  const { kv, value, onChange, dicts, placeholder, ...leftProps } = props
7
+  const [rangeKey, rangeVal] = kv || ['label', 'value']
8
+
9
+  const [inx, setInx] = useState()
10
+  const [text, setText] = useState()
11
+
12
+  const handleChange = (e) => {
13
+    const index = e.detail.value - 0
14
+    const item = dicts[index]
15
+    if (onChange) {
16
+      onChange(item[rangeVal], item)
17
+    }
18
+  }
19
+
20
+  useEffect(() => {
21
+    if (dicts && dicts.length > 0) {
22
+      if (value !== undefined && value !== null) {
23
+        for(let i = 0; i < dicts.length; i += 1) {
24
+          if (dicts[i][rangeVal] === value) {
25
+            setInx(i)
26
+            setText(dicts[i][rangeKey])
27
+            break;
28
+          }
29
+        }
30
+      }
31
+    }
32
+  }, [dicts, rangeKey, rangeVal, value])
33
+
34
+  return (
35
+    <Picker
36
+      className='g-picker'
37
+      rangeKey={rangeKey}
38
+      onChange={handleChange}
39
+      value={inx}
40
+      range={dicts}
41
+      {...leftProps}
42
+    >
43
+      <View>{text || placeholder || '请选择'}</View>
44
+    </Picker>
45
+  )
46
+}

+ 0
- 0
src/components/Picker/style.scss 查看文件


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

@@ -125,6 +125,7 @@ export const API_GOODS_BELONGS = resolvePath('goodsToBuilding')
125 125
 
126 126
 // client
127 127
 export const API_CLIENT_LIST = resolvePath('customer/recommend/mine')
128
+export const API_CHANNEL_CLIENT_LIST = resolvePath('channelCustomer/recommend/mine')
128 129
 export const API_RECOMENT_CLIENT = resolvePath('customer/new')
129 130
 export const API_CLIENT_PROGRESS = resolvePath('customer')
130 131
 export const API_TYPE_DATA = resolvePath('awesome/dict/recommendcustomer')

+ 10
- 0
src/constants/user.js 查看文件

@@ -17,3 +17,13 @@ export const ROLE_CODE = {
17 17
   CUSTOMER: 'customer', // 客户
18 18
   MARKETING: 'marketing', // 驻场
19 19
 }
20
+
21
+// 客户流转状态
22
+// 数组索引代表对应的 key
23
+export const BIZ_STATUS = {
24
+  '1': '报备',
25
+  '2': '到访',
26
+  '3': '认筹',
27
+  '4': '签约',
28
+  '5': '结佣',
29
+}

+ 18
- 0
src/pages/mine/addCustomer/components/BuildingPicker.jsx 查看文件

@@ -0,0 +1,18 @@
1
+import React, { useEffect, useState } from 'react'
2
+import Picker from '@/components/Picker'
3
+import { fetch } from '@/utils/request'
4
+import { API_GET_AGENT_BUILDINGS } from '@/constants/api'
5
+
6
+export default (props) => {
7
+  const [dicts, setDicts] = useState([])
8
+
9
+  useEffect(() => {
10
+    fetch({ url: API_GET_AGENT_BUILDINGS }).then((res) => {
11
+      setDicts(res || [])
12
+    })
13
+  }, [])
14
+
15
+  return (
16
+    <Picker kv={['buildingName', 'buildingId']} dicts={dicts} {...props} />
17
+  )
18
+}

+ 29
- 0
src/pages/mine/addCustomer/components/ConsultantPicker.jsx 查看文件

@@ -0,0 +1,29 @@
1
+import React, { useEffect, useState } from 'react'
2
+import { getCardList } from '@/services/card'
3
+import Picker from '@/components/Picker'
4
+
5
+export default (props) => {
6
+  const { buildingId } = props
7
+
8
+  const [dicts, setDicts] = useState([])
9
+
10
+  useEffect(() => {
11
+    if (buildingId) {
12
+      const params = {
13
+        pageNumber: 1,
14
+        pageSize: 50,
15
+        buildingId,
16
+      }
17
+      getCardList(params).then((res) => {
18
+        const { records } = res
19
+        setDicts(records || [])
20
+      })
21
+    } else {
22
+      setDicts([])
23
+    }
24
+  }, [buildingId])
25
+
26
+  return (
27
+    <Picker kv={['name', 'id']} dicts={dicts} {...props} />
28
+  )
29
+}

+ 26
- 0
src/pages/mine/addCustomer/getSubmitor.jsx 查看文件

@@ -0,0 +1,26 @@
1
+
2
+import { ROLE_CODE } from '@/constants/user'
3
+import { fetch } from '@/utils/request'
4
+import { API_REPORT_CUETOMER, API_USER_ADD_CUSTOMER, API_CHANNEL_REPORT } from '@/constants/api'
5
+
6
+export default function getSubmitor(person) {
7
+  const { personType } = person
8
+
9
+  const builder = (url) => (payload) => fetch({ url, method: 'post', payload })
10
+  let fn = () => undefined
11
+  switch (personType) {
12
+    case ROLE_CODE.CONSULTANT:
13
+      fn = builder(API_REPORT_CUETOMER)
14
+      break
15
+    case ROLE_CODE.CHANNEL_AGENT:
16
+      fn = builder(API_CHANNEL_REPORT)
17
+      break
18
+    case ROLE_CODE.CUSTOMER:
19
+      fn = builder(API_USER_ADD_CUSTOMER)
20
+      break
21
+    default:
22
+      break
23
+  }
24
+  
25
+  return fn;
26
+}

+ 63
- 123
src/pages/mine/addCustomer/index.jsx 查看文件

@@ -1,33 +1,32 @@
1 1
 import { useState, useEffect } from 'react'
2 2
 import withLayout from '@/layout'
3
-import { ScrollView, Input, Image, Picker, Block } from '@tarojs/components'
3
+import { ScrollView, Input, Image, Block } from '@tarojs/components'
4 4
 import '@/assets/css/iconfont.css'
5
-import { useSelector } from 'react-redux'
6 5
 import { fetch } from '@/utils/request'
7
-import { API_GET_AGENT_BUILDINGS, API_CARDS_LIST, API_REPORT_CUETOMER, API_USER_ADD_CUSTOMER, API_CHANNEL_REPORT } from '@/constants/api'
6
+import { API_REPORT_CUETOMER, API_USER_ADD_CUSTOMER, API_CHANNEL_REPORT } from '@/constants/api'
7
+import { ROLE_CODE } from '@/constants/user'
8 8
 import Taro from '@tarojs/taro'
9
+import Picker from '@/components/Picker'
10
+import BuildingPicker from './components/BuildingPicker'
11
+import ConsultantPicker from './components/ConsultantPicker'
12
+import getSubmitor from './getSubmitor'
9 13
 import './index.scss'
10 14
 
11 15
 const defaultSpecialImage = 'https://yz-websit.oss-cn-hangzhou.aliyuncs.com/xlk/index-icon19.jpg'
12 16
 
13
-export default withLayout((props) => {
17
+const sexDicts = [
18
+  { name: '男', id: '1' },
19
+  { name: '女', id: '2' },
20
+]
14 21
 
15
-  const { router } = props
22
+export default withLayout((props) => {
23
+  const { router, person } = props
16 24
   const { type } = router.params
17
-  const user = useSelector(state => state.user)
18
-  const [PersonId, setPersonId] = useState(null)
19
-  const [BuildingName, setBuildingName] = useState(null)
20
-  const [CanSubmit, setCanSubmit] = useState(false)
21
-  const [BuildingId, setBuildingId] = useState(null)
22
-  const [CardName, setCardName] = useState(null)
25
+  const { personId, personType } = person
26
+
27
+  const [loading, setLoading] = useState(false)
28
+  const [buildingId, setBuildingId] = useState(null)
23 29
   const [CardId, setCardId] = useState(null)
24
-  const [BuildingList, setBuildingList] = useState([])
25
-  const [CardList, setCardList] = useState([])
26
-  const [SexList] = useState([
27
-    { name: '男', id: '1' },
28
-    { name: '女', id: '2' }
29
-  ])
30
-  const [SexName, setSexName] = useState(null)
31 30
   const [SexId, setSexId] = useState(null)
32 31
   const [FormData, setFormData] = useState({
33 32
     name: '', // 姓名
@@ -38,97 +37,10 @@ export default withLayout((props) => {
38 37
     describe: '', // 描述
39 38
   })
40 39
 
40
+  const postSubmit = getSubmitor(person)
41 41
 
42
-  useEffect(() => {
43
-    if (PersonId !== user.userInfo.person.personId) {
44
-      setPersonId(user.userInfo.person.personId)
45
-    }
46
-  }, [user])
47
-
48
-  useEffect(() => {
49
-    if (CanSubmit) {
50
-      let url = null
51
-      if (type === 'consultant') { // 置业顾问
52
-        url = API_REPORT_CUETOMER
53
-      } else if (type === 'customer') { // 普通客户
54
-        url = API_USER_ADD_CUSTOMER
55
-      } else { // 经纪人
56
-        url = API_CHANNEL_REPORT
57
-      }
58
-      let params = {}
59
-      if (type === 'consultant') {
60
-        params = { name: FormData.name, phone: FormData.phone, sex: SexId }
61
-      } else {
62
-        params = { ...FormData, sex: SexId, buildingId: BuildingId, realtyConsultant: CardId }
63
-      }
64
-      if (type === 'estateAgent') {
65
-        params.channelCustomerId = PersonId
66
-        params.channelId = user.userInfo.person.channelId
67
-        params.buildingId = BuildingId
68
-        params.orgId = `${user.userInfo.person.orgId}`
69
-        params.personId = PersonId
70
-      }
71
-      fetch({ url, method: 'post', payload: params }).then(() => {
72
-        Taro.showToast({ title: '添加成功', icon: 'none', duration: 2000 })
73
-        setTimeout(() => {
74
-          Taro.navigateBack({ delta: 1 })
75
-          setCanSubmit(false)
76
-        }, 2000)
77
-      }).catch(() => {
78
-        setCanSubmit(false)
79
-      })
80
-    }
81
-  }, [CanSubmit])
82
-
83
-  useEffect(() => {
84
-    if (PersonId) {
85
-      GetBuildingList()
86
-    }
87
-  }, [PersonId])
88
-
89
-  useEffect(() => {
90
-    if (BuildingId) {
91
-      GetCardList()
92
-    }
93
-  }, [BuildingId])
94
-
95
-  const GetBuildingList = () => {
96
-    fetch({ url: API_GET_AGENT_BUILDINGS, method: 'get' }).then((res) => {
97
-      setBuildingList((res.records || [].map((item) => { return { id: item.buildingId, name: item.name } })))
98
-    })
99
-  }
100
-
101
-  const GetCardList = () => {
102
-    fetch({ url: API_CARDS_LIST, method: 'get', params: { pageNumber: 1, pageSize: 1000 } }).then((res) => {
103
-      setCardList((res.records || [].map((item) => { return { id: item.buildingId, name: item.name } })))
104
-    })
105
-  }
106
-
107
-  const PickerChange = (e) => {
108
-    setBuildingId(BuildingList[e.detail.value - 0].buildingId)
109
-    setBuildingName(BuildingList[e.detail.value - 0].name)
110
-    setCardId(null)
111
-    setCardName(null)
112
-  }
113
-
114
-  const CardPickerChange = (e) => {
115
-    setCardId(CardList[e.detail.value - 0].id)
116
-    setCardName(CardList[e.detail.value - 0].name)
117
-  }
118
-
119
-  const SexPickerChange = (e) => {
120
-    setSexId(SexList[e.detail.value - 0].id)
121
-    setSexName(SexList[e.detail.value - 0].name)
122
-  }
123
-
124
-  const FormInput = (e) => {
125
-    let Data = { ...FormData }
126
-    Data[e.currentTarget.dataset.type] = e.detail.value
127
-    setFormData(Data)
128
-  }
129
-
130
-  const ToSubmit = () => {
131
-    if (FormData.name === '') {
42
+  const preSubmit = (payload) => {
43
+    if (payload.name === '') {
132 44
       Taro.showToast({ title: '请填写客户姓名', icon: 'none' })
133 45
       return false
134 46
     }
@@ -136,21 +48,55 @@ export default withLayout((props) => {
136 48
       Taro.showToast({ title: '请选择客户性别', icon: 'none' })
137 49
       return false
138 50
     }
139
-    if (FormData.phone === '') {
51
+    if (payload.phone === '') {
140 52
       Taro.showToast({ title: '请填写客户电话', icon: 'none' })
141 53
       return false
142 54
     }
143
-    if (!(/^1[3|4|5|6|7|8|9][0-9]\d{4,8}$/.test(FormData.phone)) || FormData.phone.length != 11) {
55
+    if (!(/^1[3|4|5|6|7|8|9][0-9]\d{4,8}$/.test(payload.phone)) || payload.phone.length != 11) {
144 56
       Taro.showToast({ title: '请填写正确的客户电话', icon: 'none' })
145 57
       return false
146 58
     }
147
-    if (BuildingId === null && type !== 'consultant') {
59
+    if (buildingId === null && personType !== ROLE_CODE.CONSULTANT) {
148 60
       Taro.showToast({ title: '请选择客户的意向楼盘', icon: 'none' })
149 61
       return false
150 62
     }
151
-    if (!CanSubmit) {
152
-      setCanSubmit(true)
63
+    return true
64
+  }
65
+
66
+  const onSubmit = () => {
67
+    const payload = personType === ROLE_CODE.CONSULTANT ?
68
+      {
69
+        name: FormData.name, // 姓名
70
+        phone: FormData.phone, // 电话
71
+        sex: SexId, // 性别
72
+        describe: FormData.describe, // 描述
73
+      } :
74
+      {
75
+        ...FormData,
76
+        sex: SexId,
77
+        buildingId,
78
+        realtyConsultant: CardId
79
+      };
80
+    
81
+    if (!preSubmit(payload)) {
82
+      return;
153 83
     }
84
+
85
+    setLoading(true)
86
+    postSubmit(payload).then(() => {
87
+      setLoading(false)
88
+      Taro.showToast({ title: '操作成功', icon: 'none' })
89
+      Taro.navigateBack({ delta: 1 })
90
+    }).catch((err) => {
91
+      console.error(err)
92
+      setLoading(false)
93
+    })
94
+  }
95
+
96
+  const FormInput = (e) => {
97
+    let Data = { ...FormData }
98
+    Data[e.currentTarget.dataset.type] = e.detail.value
99
+    setFormData(Data)
154 100
   }
155 101
 
156 102
   return (
@@ -176,9 +122,7 @@ export default withLayout((props) => {
176 122
           <text>性别</text>
177 123
           <view className='FormLine flex-h'>
178 124
             <view className='flex-item'>
179
-              <Picker range-key='name' onChange={SexPickerChange} value={null} range={SexList}>
180
-                <text>{SexName || '请选择'}</text>
181
-              </Picker>
125
+              <Picker kv={['name', 'id']} dicts={sexDicts} onChange={setSexId} value={SexId} />
182 126
             </view>
183 127
             <text className='iconfont icon-jiantoudown'></text>
184 128
           </view>
@@ -189,18 +133,14 @@ export default withLayout((props) => {
189 133
               <text>意向楼盘</text>
190 134
               <view className='FormLine flex-h'>
191 135
                 <view className='flex-item'>
192
-                  <Picker range-key='name' onChange={PickerChange} value={null} range={BuildingList}>
193
-                    <text>{BuildingName || '请选择'}</text>
194
-                  </Picker>
136
+                  <BuildingPicker onChange={setBuildingId} value={buildingId} />
195 137
                 </view>
196 138
               </view>
197 139
 
198 140
               <text>内场接待(选填)</text>
199 141
               <view className='FormLine flex-h'>
200 142
                 <view className='flex-item'>
201
-                  <Picker range-key='name' onChange={CardPickerChange} value={null} range={CardList}>
202
-                    <text>{CardName || '请选择'}</text>
203
-                  </Picker>
143
+                  <ConsultantPicker onChange={setCardId} value={CardId} />
204 144
                 </view>
205 145
                 <Image mode='heightFix' src={defaultSpecialImage}></Image>
206 146
                 <text>选择</text>
@@ -216,7 +156,7 @@ export default withLayout((props) => {
216 156
           }
217 157
 
218 158
           <view className='Btn'>
219
-            <text onClick={ToSubmit}>提交</text>
159
+            <button loading={loading} onClick={onSubmit}>提交</button>
220 160
           </view>
221 161
 
222 162
         </view>

+ 1
- 1
src/pages/mine/addCustomer/index.scss 查看文件

@@ -55,7 +55,7 @@
55 55
         padding: 40px;
56 56
         position: relative;
57 57
         overflow: hidden;
58
-        > text {
58
+        > button {
59 59
           display: block;
60 60
           text-align: center;
61 61
           font-size: 32px;

+ 7
- 2
src/pages/mine/components/MyCustomerListItem/index.jsx 查看文件

@@ -1,10 +1,15 @@
1 1
 
2 2
 import { Image } from '@tarojs/components'
3 3
 import Taro from '@tarojs/taro'
4
+import { BIZ_STATUS } from '@/constants/user'
4 5
 import './index.scss'
5 6
 
6 7
 export default function MyCustomerListItem (props) {
7 8
   const { data = {} } = props
9
+
10
+  const { expirationDate, customerStatus } = data
11
+  const expStr = expirationDate && customerStatus === '1' ? `${expirationDate.substring(0, 10)} 回收` : ''
12
+
8 13
   return (
9 14
     <view className='components MyCustomerListItem flex-h' onClick={() => { Taro.navigateTo({ url: `/pages/mine/myCustomerDetail/index?id=${data.customerId}` }) }}>
10 15
       <view className='Img'>
@@ -13,11 +18,11 @@ export default function MyCustomerListItem (props) {
13 18
       <view className='flex-item'>
14 19
         <view className='Name flex-h'>
15 20
           <text className='flex-item'>{data.name}</text>
16
-          <text>11/11 15:12:58收回</text>
21
+          <text>{expStr}</text>
17 22
         </view>
18 23
         <view className='Time flex-h'>
19 24
           <text className='flex-item'>{data.phone}</text>
20
-          <text>{data.status === 0 ? '' : data.status === 1 ? '报备' : data.status === 2 ? '到访' : data.status === 3 ? '认筹' : '签约'}</text>
25
+          <text>{BIZ_STATUS[customerStatus]||'报备'}</text>
21 26
         </view>
22 27
       </view>
23 28
     </view>

+ 15
- 0
src/pages/mine/myCustomer/TypePicker.jsx 查看文件

@@ -0,0 +1,15 @@
1
+import React from 'react'
2
+import Picker from '@/components/Picker'
3
+import { BIZ_STATUS } from '@/constants/user'
4
+
5
+const dicts = [{ id: '', name: '全部' }].concat(Object.keys(BIZ_STATUS).map((key) => ({ id: key, name: BIZ_STATUS[key] })))
6
+
7
+export default (props) => {
8
+  return (
9
+    <Picker
10
+      kv={['name', 'id']}
11
+      dicts={dicts}
12
+      {...props}
13
+    />
14
+  )
15
+}

+ 21
- 26
src/pages/mine/myCustomer/index.jsx 查看文件

@@ -1,57 +1,52 @@
1
-import { useState, useEffect } from 'react'
1
+import { useState, useEffect, useRef } from 'react'
2 2
 import withLayout from '@/layout'
3 3
 import { ScrollView } 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_CLIENT_LIST } from '@/constants/api'
7
+import { API_CLIENT_LIST, API_CHANNEL_CLIENT_LIST } from '@/constants/api'
8
+import { ROLE_CODE } from '@/constants/user'
8 9
 import './index.scss'
9 10
 import MyCustomerListItem from '../components/MyCustomerListItem/index'
11
+import TypePicker from './TypePicker'
10 12
 
11
-export default withLayout(() => {
12
-  
13
-  const user = useSelector(state => state.user)
13
+export default withLayout((props) => {
14
+  const { person } = props
14 15
   const [PageList, setPageList] = useState([])
15 16
   const [IsPull, setPull] = useState(false)
16
-  const [PersonId, setPersonId] = useState(null)
17 17
   const [pageNumber, setPageNumber] = useState(1)
18 18
   const [HasNextPage, setHasNextPage] = useState(true)
19
+  const [bizType, setBizType] = useState('')
20
+  const GetPageList = useRef()
19 21
 
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])
31
-
32
-  const PageRefresh = () => { // 页面下拉刷新回调
33
-    setPull(true)
34
-  }
35
-
36
-  const GetPageList = () => {
22
+  GetPageList.current = () => {
37 23
     setHasNextPage(false)
38
-    fetch({ url: API_CLIENT_LIST, method: 'get', payload: { customerId: PersonId, pageNumber, pageSize: 10 } }).then((res) => {
24
+    const url = ROLE_CODE.CHANNEL_AGENT === person.personType ? API_CHANNEL_CLIENT_LIST : API_CLIENT_LIST
25
+    fetch({ url, payload: { pageNumber, pageSize: 10 } }).then((res) => {
39 26
       setPageList(pageNumber === 1 ? res.records || [] : PageList.concat(res.records || []))
40 27
       setHasNextPage(res.current < res.pages)
41 28
       setPull(false)
42 29
     })
43 30
   }
44 31
 
32
+  const PageRefresh = () => { // 页面下拉刷新回调
33
+    setPull(true)
34
+  }
35
+
45 36
   const PageLoadMore = () => { // 页面上拉加载更多
46 37
     if(HasNextPage) {
47 38
       setPageNumber(pageNumber + 1)
48 39
     }
49 40
   }
50 41
 
42
+  useEffect(() => {
43
+    GetPageList.current()
44
+  }, [pageNumber])
45
+
51 46
   useEffect(() => { // 下拉刷新触发
52 47
     if (IsPull) {
53 48
       if(pageNumber === 1) {
54
-        GetPageList()
49
+        GetPageList.current()
55 50
       } else {
56 51
         setPageNumber(1)
57 52
       }
@@ -68,7 +63,7 @@ export default withLayout(() => {
68 63
             <text className='iconfont icon-sanjiaoxingdown'></text>
69 64
           </view>
70 65
           <view className='Type'>
71
-            <text>全部类型</text>
66
+            <TypePicker value={bizType} onChange={setBizType} />
72 67
             <text className='iconfont icon-sanjiaoxingdown'></text>
73 68
           </view>
74 69
           <view className='flex-item'></view>

+ 1
- 1
src/pages/mine/myCustomer/index.scss 查看文件

@@ -33,7 +33,7 @@
33 33
             display: none;
34 34
           }
35 35
         }
36
-        >text {
36
+        >text, picker {
37 37
           display: inline-block;
38 38
           vertical-align: middle;
39 39
           font-size: 30px;