backlogList.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <template>
  2. <view class="backlog-list">
  3. <view class="list-container">
  4. <view
  5. v-for="(item, index) in typeMap"
  6. :key="index"
  7. class="list-item"
  8. @click="handleTo(item.type)">
  9. <view class="list-item-body">
  10. <image :src="item.icon" class="label-icon" alt="" />
  11. <view class="main-info">
  12. <view class="box">
  13. <view class="left title">
  14. {{ item.label }}
  15. </view>
  16. <view
  17. v-if="item.firstData"
  18. class="time">
  19. {{ item.firstData | formatTime }}
  20. </view>
  21. </view>
  22. <view class="box desc">
  23. <view class="left text">
  24. {{ formatMsg(item) || '&nbsp;' }}
  25. </view>
  26. <view v-if="item.num && item.num > 0" class="num">
  27. {{ item.num > 99 ? '99+' : item.num }}
  28. </view>
  29. </view>
  30. </view>
  31. </view>
  32. </view>
  33. </view>
  34. </view>
  35. </template>
  36. <script>
  37. import * as API from 'API/crm/message'
  38. import { MessageNum } from 'API/crm/message'
  39. import { WaitingQueryOaExamineList } from 'API/oa/examine.js'
  40. import { mapGetters } from 'vuex'
  41. import moment from 'moment'
  42. export default {
  43. name: 'BacklogList',
  44. filters: {
  45. formatTime(firstData) {
  46. if (!firstData.updateTime) return '--'
  47. return moment(firstData.updateTime).format('MM月DD日')
  48. }
  49. },
  50. data() {
  51. return {
  52. detailComponent: '',
  53. height: 0,
  54. loading: false,
  55. backlogDetail: {},
  56. examineList: [],
  57. activate: true,
  58. typeMap: [
  59. {
  60. label: '今日需联系线索',
  61. type: 11,
  62. component: 'DetailLeadsItem',
  63. fn: API.TodayLeads,
  64. icon: this.$static('images/backlog/today_leads.png'),
  65. firstData: null,
  66. field: 'todayLeads'
  67. },
  68. {
  69. label: '今日需联系客户',
  70. type: 1,
  71. component: 'DetailCustomerItem',
  72. fn: API.TodayCustomer,
  73. icon: this.$static('images/backlog/today_customer.png'),
  74. firstData: null,
  75. field: 'todayCustomer'
  76. },
  77. {
  78. label: '今日需联系商机',
  79. type: 12,
  80. component: 'DetailBusinessItem',
  81. fn: API.TodayBusiness,
  82. icon: this.$static('images/backlog/today_business.png'),
  83. firstData: null,
  84. field: 'todayBusiness'
  85. },
  86. {
  87. label: '分配给我的线索',
  88. type: 2,
  89. component: 'DetailLeadsItem',
  90. fn: API.FollowLeads,
  91. icon: this.$static('images/backlog/leads.png'),
  92. firstData: null,
  93. field: 'followLeads'
  94. },
  95. {
  96. label: '分配给我的客户',
  97. type: 3,
  98. component: 'DetailCustomerItem',
  99. fn: API.FollowCustomer,
  100. icon: this.$static('images/backlog/my_customer.png'),
  101. firstData: null,
  102. field: 'followCustomer'
  103. },
  104. {
  105. label: '待进入公海的客户',
  106. type: 4,
  107. component: 'DetailCustomerItem',
  108. fn: API.PutInPoolRemind,
  109. icon: this.$static('images/backlog/seas.png'),
  110. firstData: null,
  111. field: 'putInPoolRemind'
  112. },
  113. {
  114. label: '待审核的合同',
  115. type: 5,
  116. component: 'DetailContractItem',
  117. fn: API.CheckContract,
  118. icon: this.$static('images/backlog/wait_contract.png'),
  119. firstData: null,
  120. field: 'checkContract'
  121. },
  122. {
  123. label: '待审核的回款',
  124. type: 6,
  125. component: 'DetailReceivablesItem',
  126. fn: API.CheckReceivables,
  127. icon: this.$static('images/backlog/wait_refound.png'),
  128. firstData: null,
  129. field: 'checkReceivables'
  130. },
  131. {
  132. label: '待回款提醒',
  133. type: 7,
  134. component: 'DetailAwaitReceivablesItem',
  135. fn: API.RemindReceivablesPlan,
  136. icon: this.$static('images/backlog/remind-refound.png'),
  137. firstData: null,
  138. field: 'remindReceivablesPlan'
  139. },
  140. {
  141. label: '即将到期的合同',
  142. type: 8,
  143. component: 'DetailContractItem',
  144. fn: API.EndContract,
  145. icon: this.$static('images/backlog/over_contract.png'),
  146. firstData: null,
  147. field: 'endContract'
  148. },
  149. {
  150. label: '待审核的办公',
  151. type: 100,
  152. component: 'DetailExaminationItem',
  153. fn: WaitingQueryOaExamineList,
  154. icon: this.$static('images/backlog/oa.png'),
  155. firstData: null,
  156. field: 'examineNum'
  157. }
  158. ]
  159. }
  160. },
  161. computed: {
  162. ...mapGetters({
  163. authData: 'user/authData'
  164. })
  165. },
  166. mounted() {
  167. this.getMessageNum()
  168. },
  169. wkActivated() {
  170. this.getMessageNum()
  171. },
  172. methods: {
  173. getMessageNum() {
  174. if (this.loading) return
  175. this.loading = true
  176. Promise.all([
  177. MessageNum(),
  178. WaitingQueryOaExamineList({
  179. limit: 1,
  180. page: 1,
  181. status: 1
  182. })
  183. ]).then(resArr => {
  184. this.loading = false
  185. const res = {
  186. ...resArr[0],
  187. examineNum: resArr[1].totalRow
  188. }
  189. this.examineList = resArr[1].list || []
  190. const keys = [
  191. 'todayCustomer',
  192. 'followLeads',
  193. 'followCustomer',
  194. 'putInPoolRemind',
  195. 'endContract',
  196. 'checkContract',
  197. 'checkReceivables',
  198. 'remindReceivablesPlan',
  199. 'todayLeads',
  200. 'todayBusiness',
  201. 'examineNum'
  202. ]
  203. const data = {}
  204. keys.forEach(key => {
  205. this.backlogDetail[key] = Number(res[key]) || 0
  206. data[key] = Number(res[key]) || 0
  207. })
  208. this.typeMap = this.typeMap.filter(o => res.hasOwnProperty(o.field))
  209. this.setNumber()
  210. }).catch(() => {
  211. this.loading = false
  212. this.backlogDetail = {}
  213. this.setNumber()
  214. })
  215. },
  216. /**
  217. * 设置待办事项数量
  218. */
  219. setNumber() {
  220. let data = this.backlogDetail
  221. this.typeMap.forEach((item, index) => {
  222. if (data.hasOwnProperty(item.field)) {
  223. item.num = data[item.field] || 0
  224. } else {
  225. item.num = 0
  226. }
  227. this.$set(this.typeMap, index, item)
  228. })
  229. this.getFirstData()
  230. },
  231. /**
  232. * 获取每一项的第一条待办
  233. */
  234. getFirstData() {
  235. this.typeMap.forEach((typeObj, index) => {
  236. if (typeObj.num > 0) {
  237. let params = {
  238. page: 1,
  239. limit: 1
  240. }
  241. if (typeObj.type === 9) {
  242. params.status = 1
  243. } else {
  244. params = Object.assign(params, {type: 1, isSub: 1})
  245. }
  246. if (typeObj.type !== 10) {
  247. typeObj.fn(params).then(res => {
  248. console.log(typeObj.label, res.list)
  249. typeObj.firstData = res.list[0] || null
  250. this.$set(this.typeMap, index, typeObj)
  251. }).catch(() => {})
  252. } else if (typeObj.type === 9) {
  253. typeObj.firstData = this.examineList[0] || null
  254. this.$set(this.typeMap, index, typeObj)
  255. } else {
  256. typeObj.fn({
  257. page: 1,
  258. limit: 1,
  259. by: 1
  260. }).then(res => {
  261. console.log(typeObj.label, res.list)
  262. typeObj.firstData = res.list[0] || null
  263. this.$set(this.typeMap, index, typeObj)
  264. }).catch()
  265. }
  266. }
  267. })
  268. },
  269. formatMsg(data) {
  270. // 1今日需联系客户 2分配给我的线索 3分配给我的客户 4待进入公海的客户 5待审核合同
  271. // 6待审核回款 7待回款提醒 8即将到期的合同 9待回访合同 10待审核发票
  272. let num = data.num
  273. if (num === 0) return `暂无${data.label}`
  274. let str = ''
  275. let obj = data.firstData
  276. if (!obj) return `暂无${data.label}`
  277. if (num > 1) {
  278. switch (data.type) {
  279. case 1:
  280. str = `${obj.customerName}等${num}个客户需要您今日联系`
  281. break;
  282. case 2:
  283. str = `${obj.leadsName}等${num}个线索需要您今日跟进`
  284. break;
  285. case 3:
  286. str = `${obj.customerName}等${num}个客户需要您今日跟进`
  287. break;
  288. case 4:
  289. str = `${obj.customerName}等${num}个客户即将进入公海`
  290. break;
  291. case 5:
  292. str = `您有${num}个新的合同正在等待审批`
  293. break;
  294. case 6:
  295. str = `您有${num}个回款申请正在等待审批`
  296. break;
  297. case 7:
  298. str = `您有${num}个回款计划即将到期`
  299. break;
  300. case 8:
  301. str = `${obj.name}等${num}个合同即将到期`
  302. break;
  303. case 9:
  304. // 待回访合同
  305. break;
  306. case 10:
  307. // 待审核发票
  308. break;
  309. case 11:
  310. str = `${obj.leadsName}等${num}个线索需要您今日联系`
  311. break;
  312. case 12:
  313. str = `${obj.businessName}等${num}个商机需要您今日联系`
  314. break;
  315. case 100:
  316. str = `${obj.createUser.realname}等${num}人发起了申请,正在等待您的审批`
  317. break;
  318. }
  319. } else {
  320. switch (data.type) {
  321. case 1:
  322. str = `${obj.customerName}需要您今日联系`
  323. break;
  324. case 2:
  325. str = `${obj.leadsName}需要您今日跟进`
  326. break;
  327. case 3:
  328. str = `${obj.customerName}需要您今日跟进`
  329. break;
  330. case 4:
  331. str = `${obj.customerName}还有${obj.poolDay}天即将进入公海`
  332. break;
  333. case 5:
  334. str = `${obj.ownerUserName}提交了新的合同,正在等待您的审批`
  335. break;
  336. case 6:
  337. str = `${obj.ownerUserName}提交了回款申请,正在等待您的审批`
  338. break;
  339. case 7:
  340. str = `${obj.customerName}的第${obj.num}期回款即将到期`
  341. break;
  342. case 8:
  343. str = `${obj.name}即将到期`
  344. break;
  345. case 9:
  346. // 待回访合同
  347. break;
  348. case 10:
  349. // 待审核发票
  350. break;
  351. case 11:
  352. str = `${obj.leadsName}需要您今日联系`
  353. break;
  354. case 12:
  355. str = `${obj.businessName}需要您今日联系`
  356. break;
  357. case 100:
  358. str = `${obj.createUser.realname}发起了${obj.categoryTitle},正在等待您的审批`
  359. break;
  360. }
  361. }
  362. return str || ''
  363. },
  364. handleTo(type) {
  365. let path = type !== 1 ? '/pages_message/backlogDetailTab' : '/pages_message/backlogDetailFilter'
  366. // if (type === 10) path = 'oa/journal'
  367. this.$Router.navigateTo({
  368. url: path,
  369. query: {
  370. type: type === 10 ? 2 : type
  371. }
  372. })
  373. },
  374. }
  375. }
  376. </script>
  377. <style scoped lang="scss">
  378. .backlog-list {
  379. width: 100%;
  380. height: 100%;
  381. overflow: auto;
  382. .list-container {
  383. flex: 1;
  384. padding: 15rpx 0;
  385. overflow: auto;
  386. .list-item {
  387. width: 100%;
  388. background-color: white;
  389. padding: 0 32rpx;
  390. &:last-child {
  391. border-bottom: 0 none;
  392. }
  393. .list-item-body {
  394. text-align: left;
  395. border-bottom: 1rpx solid $border-color;
  396. padding: 18rpx 0;
  397. @include left;
  398. .label-icon {
  399. width: 80rpx;
  400. height: 80rpx;
  401. border-radius: 50%;
  402. margin-right: 20rpx;
  403. }
  404. .main-info {
  405. flex: 1;
  406. font-size: 30rpx;
  407. overflow: hidden;
  408. .box {
  409. @include left;
  410. &.desc {
  411. margin-top: 10rpx;
  412. }
  413. .left {
  414. flex: 1;
  415. margin-right: 20rpx;
  416. @include ellipsis;
  417. }
  418. .title {
  419. font-weight: 500;
  420. }
  421. .time {
  422. color: #999;
  423. font-size: 26rpx;
  424. }
  425. .text {
  426. font-size: 28rpx;
  427. color: $gray;
  428. }
  429. .num {
  430. min-width: 36rpx;
  431. height: 36rpx;
  432. line-height: 36rpx;
  433. font-size: 24rpx;
  434. padding: 0 5rpx;
  435. color: white;
  436. border-radius: 36rpx;
  437. background-color: $error;
  438. @include center;
  439. }
  440. }
  441. }
  442. }
  443. }
  444. }
  445. }
  446. </style>