You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

768 lines
18 KiB

  1. <template>
  2. <view class="pages">
  3. <!-- 日报内容部分 -->
  4. <view class="container" ref="lists">
  5. <!-- 头部日报卡 -->
  6. <view class="c-head-card">
  7. <view class="c-title-text">
  8. {{ projectName }}数智工牌日报
  9. </view>
  10. <text class="date">{{ weekObj.createTime | fomatDate }}</text>
  11. <view class="creative-time">
  12. 生成时间:{{ weekObj.createTime || '--' }}
  13. </view>
  14. </view>
  15. <view class="nodata-box" style="background: url(../../static/images/nodata.png)no-repeat;background-size: contain;" v-if="nodata">
  16. 此项目今日还没有接待量哦~
  17. </view>
  18. <view v-if="!nodata">
  19. <!-- 循环渲染的数据 -->
  20. <view class="dateList">
  21. <view class="arrs">
  22. <view class="arrs-items index1">
  23. <view class="left">
  24. 1
  25. </view>
  26. <view class="right">
  27. <view class="r-title">
  28. <text>接待量:</text>
  29. </view>
  30. <view class="r-box">
  31. <view class="r-box-item">
  32. <text>接待量</text><text class="value">{{ weekObj.receptionCount || 0 }}</text>
  33. </view>
  34. <view class="r-box-item">
  35. <text>有效接待</text><text class="value">{{ weekObj.activeCustomer || 0 }}</text>
  36. </view>
  37. <view class="r-box-item-lang">
  38. <view>有效接待率<text class="value">{{ weekObj.validReceptionRate || 0 }}%</text></view>
  39. <view class="contrast">对比昨天<text class="value"
  40. :class="{down: weekObj.validReceptionRatePK < 0, up: weekObj.validReceptionRatePK > 0}">{{ weekObj.validReceptionRatePK > 0 ? '+' : '' }}{{ weekObj.validReceptionRatePK || 0 }}%</text>
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. <view class="arrs-items index2">
  47. <view class="left">
  48. 2
  49. </view>
  50. <view class="right">
  51. <view class="r-title">
  52. <text>平均执行率:</text>
  53. </view>
  54. <view class="r-box">
  55. <view class="r-box-item-lang">
  56. <view>平均执行率<text class="value">{{ weekObj.fraction || 0 }}%</text></view>
  57. <view class="contrast">对比昨天<text class="value"
  58. :class="{down: weekObj.fractionPK < 0, up: weekObj.fractionPK > 0}">{{ weekObj.fractionPK > 0 ? '+' : '' }}{{ weekObj.fractionPK || 0 }}%</text>
  59. </view>
  60. </view>
  61. </view>
  62. </view>
  63. </view>
  64. <view class="arrs-items index3">
  65. <view class="left">
  66. 3
  67. </view>
  68. <view class="right">
  69. <view class="r-title">
  70. <text>平均接待时长:</text>
  71. </view>
  72. <view class="r-box">
  73. <view class="r-box-item-lang">
  74. <view>平均接待时长<text class="value">{{ weekObj.avgDuration || 0 }}min</text></view>
  75. <view class="contrast">对比昨天<text class="value"
  76. :class="{down: weekObj.avgDurationPK < 0, up: weekObj.avgDurationPK > 0}">{{ weekObj.avgDurationPK > 0 ? '+' : '' }}{{ weekObj.avgDurationPK || 0 }}min</text>
  77. </view>
  78. </view>
  79. </view>
  80. </view>
  81. </view>
  82. <view class="arrs-items index4">
  83. <view class="left">
  84. 4
  85. </view>
  86. <view class="right">
  87. <view class="r-title">
  88. <text>销讲维度执行前三:</text>
  89. </view>
  90. <view class="ranking">
  91. <block v-for="(rank, rankIndex) in carryOutTop" :key="rankIndex">
  92. <view class="ranking-item">
  93. <view class="serial">
  94. {{ rankIndex+1 }}
  95. </view>
  96. <view class="lside">
  97. {{ rank.title || '--' }}
  98. </view>
  99. <view class="rside">
  100. ({{ rank.value || 0 }}%)
  101. </view>
  102. </view>
  103. </block>
  104. <template v-if="carryOutTop.length == 0">
  105. <view class="empty">
  106. 暂无数据
  107. </view>
  108. </template>
  109. </view>
  110. </view>
  111. </view>
  112. <view class="arrs-items index5">
  113. <view class="left">
  114. 5
  115. </view>
  116. <view class="right">
  117. <view class="r-title">
  118. <text>销讲维度执行弱项前三:</text>
  119. </view>
  120. <view class="ranking">
  121. <block v-for="(rank, rankIndex) in carryOutLast" :key="rankIndex">
  122. <view class="ranking-item">
  123. <view class="serial">
  124. {{ rankIndex+1 }}
  125. </view>
  126. <view class="lside">
  127. {{ rank.title || '--' }}
  128. </view>
  129. <view class="rside">
  130. ({{ rank.value || 0 }}%)
  131. </view>
  132. </view>
  133. </block>
  134. <template v-if="carryOutLast.length == 0">
  135. <view class="empty">
  136. 暂无数据
  137. </view>
  138. </template>
  139. </view>
  140. </view>
  141. </view>
  142. <view class="arrs-items index6">
  143. <view class="left">
  144. 6
  145. </view>
  146. <view class="right">
  147. <view class="r-title">
  148. <text>置业顾问平均执行率排名:</text>
  149. </view>
  150. <view class="ranking">
  151. <block v-for="(rank, rankIndex) in consultant" :key="rankIndex">
  152. <view class="ranking-item">
  153. <view class="serial">
  154. {{ rankIndex+1 }}
  155. </view>
  156. <view class="lside">
  157. {{ rank.title || '--' }}
  158. </view>
  159. <view class="rside">
  160. ({{ rank.value || 0 }}%)
  161. </view>
  162. </view>
  163. </block>
  164. <template v-if="consultant.length == 0">
  165. <view class="empty">
  166. 暂无数据
  167. </view>
  168. </template>
  169. </view>
  170. </view>
  171. </view>
  172. <view class="arrs-items index7">
  173. <view class="left">
  174. 7
  175. </view>
  176. <view class="right">
  177. <view class="r-title">
  178. <text>置业顾问平均接访时长排名:</text>
  179. </view>
  180. <view class="ranking">
  181. <block v-for="(rank, rankIndex) in recording" :key="rankIndex">
  182. <view class="ranking-item">
  183. <view class="serial">
  184. {{ rankIndex+1 }}
  185. </view>
  186. <view class="lside">
  187. {{ rank.title || '--' }}
  188. </view>
  189. <view class="rside">
  190. ({{ rank.value || 0 }}min)
  191. </view>
  192. </view>
  193. </block>
  194. <template v-if="recording.length == 0">
  195. <view class="empty">
  196. 暂无数据
  197. </view>
  198. </template>
  199. </view>
  200. </view>
  201. </view>
  202. <view class="arrs-items index8">
  203. <view class="left">
  204. 8
  205. </view>
  206. <view class="right">
  207. <view class="r-title">
  208. <text>平均执行率最低的顾问:</text>
  209. </view>
  210. <view class="ranking">
  211. <block v-for="(rank, rankIndex) in lowest" :key="rankIndex">
  212. <view class="ranking-item">
  213. <view class="lside">
  214. {{ rank.title || '--' }}
  215. </view>
  216. <view class="rside value">
  217. {{ rank.value || 0 }}%
  218. </view>
  219. </view>
  220. </block>
  221. <template v-if="lowest.length == 0">
  222. <view class="empty">
  223. 暂无数据
  224. </view>
  225. </template>
  226. </view>
  227. </view>
  228. </view>
  229. <view class="arrs-items index9">
  230. <view class="left">
  231. 9
  232. </view>
  233. <view class="right">
  234. <view class="r-title">
  235. <text>客户画像触达:</text>
  236. <text class="num value">{{ weekObj.reachSum || 0 }}次</text>
  237. </view>
  238. </view>
  239. </view>
  240. <view class="arrs-items index10">
  241. <view class="left">
  242. 10
  243. </view>
  244. <view class="right">
  245. <view class="r-title">
  246. <text>未标记接待数:</text>
  247. <text class="num value down"
  248. style="font-weight: 500;font-size: 34rpx;">{{ weekObj.unlabelledReceptionNum || 0 }}</text>
  249. <text class="down value">条</text>
  250. </view>
  251. </view>
  252. </view>
  253. <view class="arrs-items index11">
  254. <view class="left">
  255. 11
  256. </view>
  257. <view class="right">
  258. <view class="r-title">
  259. <text>设备情况:</text>
  260. </view>
  261. <view class="r-box">
  262. <view class="r-box-item-lang">
  263. <view>在线<text class="value">{{ weekObj.equipmentInfo.onlineNum || 0 }}</text></view>
  264. <view style="margin-left: 24rpx;">
  265. 离线<text class="value">{{ weekObj.equipmentInfo.offlineNum || 0 }}</text></view>
  266. </view>
  267. </view>
  268. </view>
  269. </view>
  270. </view>
  271. </view>
  272. </view>
  273. </view>
  274. <!-- 底部按钮 -->
  275. <view class="nav-footer" v-if="!nodata">
  276. <view class="footer-item" @click="toHome">
  277. 回到管理端
  278. </view>
  279. <view class="footer-item" @click="copy" style="margin-left: 24rpx;">
  280. 复制内容
  281. </view>
  282. <view class="footer-item full" style="margin-left: 24rpx;">
  283. <button open-type="share" class="fulls">
  284. 一键转发
  285. </button>
  286. </view>
  287. </view>
  288. </view>
  289. </template>
  290. <script>
  291. export default {
  292. data() {
  293. return {
  294. needList: ['XJTop', 'ZXLTop', 'avgJds'], // 需要转换数组的内容
  295. carryOutTop: [], //
  296. carryOutLast: [], //
  297. consultant: [], // 置业顾问排名
  298. recording: [], // 录音排名
  299. lowest: [], // 执行率最低的顾问
  300. building: uni.getStorageSync('buildingID'),
  301. id: '', // 消息id
  302. projectName: '', // 项目名称
  303. weekObj: {}, // 日报详情
  304. nodata: false//有无数据
  305. }
  306. },
  307. onLoad(option) {
  308. if (option.id) this.id = option.id
  309. this.getMessage()
  310. },
  311. onShareAppMessage() {
  312. return {
  313. title: `${this.projectName}数智工牌日报`,
  314. path: `/pages/reportExcel/dayReport?id=${this.id}`
  315. }
  316. },
  317. methods: {
  318. // 跳转首页
  319. toHome() {
  320. uni.navigateTo({
  321. url: '/pages/index/guide'
  322. })
  323. },
  324. // 获取日报详情
  325. getMessage() {
  326. this.$u.get('/zkMessage/findByProjectId', {
  327. id: this.id
  328. }).then(res => {
  329. let data = {}
  330. if(res.zkMessage.content){
  331. data = JSON.parse(res.zkMessage.content)
  332. this.weekObj = {
  333. ...res.zkMessage,
  334. ...data
  335. }
  336. this.nodata = false
  337. }else{
  338. this.nodata = true
  339. this.weekObj = {
  340. ...res.zkMessage
  341. }
  342. }
  343. this.projectName = res.projectName
  344. console.log(this.weekObj)
  345. this.init()
  346. }).catch(e => {
  347. console.log(e)
  348. })
  349. },
  350. copy() {
  351. let str = `
  352. ${this.projectName}数智工牌日报
  353. 生成时间:${this.weekObj.createTime || '--'}
  354. 1、接待量:${this.weekObj.receptionCount || 0 }
  355. 有效接待:${this.weekObj.activeCustomer || 0}
  356. 有效接待率:${this.weekObj.validReceptionRate || 0}%
  357. 对比昨天:${ this.weekObj.validReceptionRatePK > 0 ? '+' : '' }${ this.weekObj.validReceptionRatePK || 0 }%
  358. 2、平均执行率:${ this.weekObj.fraction || 0 }%
  359. 对比昨天:${ this.weekObj.fractionPK > 0 ? '+' : '' }${ this.weekObj.fractionPK || 0 }%
  360. 3、平均接待时长:${ this.weekObj.avgDuration || 0 }min
  361. 对比昨天:${this.weekObj.avgDurationPK > 0 ? '+' : '' }${ this.weekObj.avgDurationPK || 0 }min`
  362. if (this.carryOutTop.length > 0) {
  363. str += `
  364. 4、销讲维度执行前三:`
  365. this.carryOutTop.map((item, index) => {
  366. str += `
  367. top${index+1}.${item.title || '--'}${item.value||'0'}%`
  368. })
  369. }
  370. if (this.carryOutLast.length > 0) {
  371. str += `
  372. 5、销讲维度执行弱项前三:`
  373. this.carryOutLast.map((item, index) => {
  374. str += `
  375. top${index+1}.${item.title || '--'}${item.value||'0'}%`
  376. })
  377. }
  378. if (this.consultant.length > 0) {
  379. str += `
  380. 6、置业顾问平均执行率排名:`
  381. this.consultant.map((item, index) => {
  382. str += `
  383. top${index+1}.${item.title || '--'}${item.value||'0'}%`
  384. })
  385. }
  386. if (this.recording.length > 0) {
  387. str += `
  388. 7、置业顾问平均接访时长排名:`
  389. this.recording.map((item, index) => {
  390. str += `
  391. top${index+1}.${item.title || '--'}${item.value||'0'}min`
  392. })
  393. }
  394. if (this.lowest.length > 0) {
  395. str += `
  396. 8、平均执行率最低的顾问:`
  397. this.lowest.map((item, index) => {
  398. str += `
  399. ${item.title || '--'}${item.value||'0'}%`
  400. })
  401. }
  402. str += `
  403. 9、客户画像触达:${this.weekObj.reachSum || 0}次
  404. 10、未标记接待数:${ this.weekObj.unlabelledReceptionNum || 0 }条
  405. 11、设备情况:
  406. 在线:${this.weekObj.equipmentInfo.onlineNum || 0}
  407. 离线:${this.weekObj.equipmentInfo.offlineNum || 0}`
  408. uni.setClipboardData({
  409. data: str
  410. })
  411. },
  412. // 分割数组排名前三,倒三
  413. getTopThree() {
  414. if (this.weekObj.XJTopList && this.weekObj.XJTopList.length > 0) {
  415. let arr = this.weekObj.XJTopList.slice(0, 3)
  416. arr.forEach(item => {
  417. if (item.value != 100) {
  418. this.carryOutLast.push(item)
  419. }
  420. })
  421. this.carryOutTop = this.weekObj.XJTopList.reverse().slice(0, 3)
  422. console.log(this.weekObj.XJTopList)
  423. }
  424. if (this.weekObj.ZXLTopList && this.weekObj.ZXLTopList.length > 0) {
  425. this.consultant = this.weekObj.ZXLTopList.reverse().slice(0, 3)
  426. if (this.weekObj.ZXLTopList[this.weekObj.ZXLTopList.length - 1].value != 100) {
  427. this.lowest.push(this.weekObj.ZXLTopList[this.weekObj.ZXLTopList.length - 1])
  428. }
  429. }
  430. if (this.weekObj.avgJdsList && this.weekObj.avgJdsList.length > 0) {
  431. this.recording = this.weekObj.avgJdsList.reverse().slice(0, 3)
  432. }
  433. },
  434. init() {
  435. // 把对象转成数组并在后续的步骤方便处理
  436. this.needList.forEach(item => {
  437. if (this.weekObj[item] && Object.keys(this.weekObj[item]).length > 0) {
  438. this.weekObj[item + 'List'] = [] // 销讲执行
  439. for (let i in this.weekObj[item]) {
  440. this.weekObj[item + 'List'].push({
  441. title: i,
  442. value: this.weekObj[item][i]
  443. })
  444. }
  445. }
  446. })
  447. this.sortInitArr()
  448. },
  449. // 排序对象转换后的数组
  450. sortInitArr() {
  451. this.needList.forEach(item => {
  452. if (this.weekObj[item + 'List']) {
  453. this.bubbleSort(this.weekObj[item + 'List'])
  454. }
  455. })
  456. this.getTopThree()
  457. },
  458. // 冒泡排序
  459. bubbleSort(arr) {
  460. for (let i = 0; i < arr.length - 1; i += 1) {
  461. //通过 arr.length 次把第一位放到最后,完成排序
  462. //-i是因为最后的位置是会动态改变的,当完成一次后,最后一位会变成倒数第二位
  463. for (let j = 0; j < arr.length - 1 - i; j += 1) {
  464. if (arr[j].value > arr[j + 1].value) {
  465. const temp = arr[j];
  466. arr[j] = arr[j + 1];
  467. arr[j + 1] = temp;
  468. }
  469. }
  470. }
  471. },
  472. },
  473. filters: {
  474. fomatDate(date) {
  475. if (!date) return '--'
  476. let arr = date.split(' ')
  477. let str = arr[0]
  478. let result = str.split('-')
  479. return `${result[1]}-${result[2]}`
  480. }
  481. }
  482. }
  483. </script>
  484. <style lang="scss" scoped>
  485. .pages {
  486. width: 100vw;
  487. min-height: 100vh;
  488. display: flex;
  489. flex-direction: column;
  490. .nav-header {
  491. flex-shrink: 0;
  492. }
  493. .container {
  494. padding: 30rpx 30rpx 0;
  495. flex-grow: 1;
  496. display: flex;
  497. flex-direction: column;
  498. .c-head-card {
  499. padding: 30rpx;
  500. width: 100%;
  501. min-height: 252rpx;
  502. border: 2rpx solid #000000;
  503. border-radius: 12rpx;
  504. box-shadow: 10rpx 10rpx #2671E2;
  505. display: flex;
  506. flex-direction: column;
  507. .c-title-text {
  508. // position: relative;
  509. flex-grow: 1;
  510. font-size: 48rpx;
  511. font-weight: bold;
  512. color: #303030;
  513. }
  514. .date {
  515. // position: absolute;
  516. // right: 0;
  517. // bottom: 6rpx;
  518. font-size: 30rpx;
  519. color: #303030;
  520. }
  521. .creative-time {
  522. margin: 20rpx 0 0 0;
  523. flex-shrink: 0;
  524. }
  525. }
  526. .dateList {
  527. width: 100%;
  528. .arrs {
  529. width: 100%;
  530. .arrs-items {
  531. margin: 40rpx 0 0 0;
  532. display: flex;
  533. min-height: 100rpx;
  534. .left {
  535. flex-shrink: 0;
  536. margin-right: 12rpx;
  537. width: 48rpx;
  538. height: 44rpx;
  539. display: flex;
  540. justify-content: center;
  541. align-items: center;
  542. border-radius: 8rpx;
  543. border: 1rpx solid #999999;
  544. font-size: 32rpx;
  545. }
  546. .right {
  547. flex-grow: 1;
  548. .r-title {
  549. font-size: 32rpx;
  550. height: 44rpx;
  551. display: flex;
  552. align-items: center;
  553. .num {
  554. font-size: 34rpx;
  555. }
  556. }
  557. .r-box {
  558. padding: 21rpx 0 0 0;
  559. display: flex;
  560. flex-wrap: wrap;
  561. .r-box-item {
  562. margin-right: 24rpx;
  563. }
  564. .r-box-item-lang {
  565. margin-top: 19rpx;
  566. width: 100%;
  567. display: flex;
  568. align-items: center;
  569. .contrast {
  570. margin: 0 0 0 24rpx;
  571. display: flex;
  572. align-items: center;
  573. }
  574. .down {
  575. color: #43CD80;
  576. font-size: 34rpx;
  577. }
  578. .up {
  579. font-size: 34rpx;
  580. color: #E7483C;
  581. }
  582. }
  583. }
  584. .ranking {
  585. padding: 21rpx 0 0 0;
  586. display: flex;
  587. flex-direction: column;
  588. .ranking-item {
  589. margin-bottom: 22rpx;
  590. display: flex;
  591. align-items: center;
  592. font-size: 30rpx;
  593. .serial {
  594. flex-shrink: 0;
  595. width: 42rpx;
  596. height: 42rpx;
  597. background: #2671E2;
  598. border-radius: 50%;
  599. display: flex;
  600. justify-content: center;
  601. align-items: center;
  602. color: #fff;
  603. }
  604. .lside {
  605. margin: 0 20rpx;
  606. color: #505050;
  607. }
  608. .rside {
  609. flex-shrink: 0;
  610. font-size: 32rpx;
  611. }
  612. }
  613. }
  614. }
  615. }
  616. }
  617. }
  618. }
  619. .nav-footer {
  620. position: sticky;
  621. bottom: 0;
  622. padding: 32rpx;
  623. width: 100%;
  624. display: flex;
  625. justify-content: center;
  626. background: #fff;
  627. .footer-item {
  628. flex: 1;
  629. height: 88rpx;
  630. display: flex;
  631. justify-content: center;
  632. align-items: center;
  633. color: #2671E2;
  634. border: 2rpx solid #2671E2;
  635. border-radius: 8rpx;
  636. overflow: hidden;
  637. font-size: 32rpx;
  638. &.full {
  639. background: #2671E2;
  640. color: #fff;
  641. .fulls {
  642. box-sizing: border-box;
  643. width: 100%;
  644. height: 100%;
  645. background: transparent;
  646. color: #fff;
  647. font-size: 32rpx;
  648. font-weight: normal;
  649. line-height: 88rpx;
  650. }
  651. }
  652. }
  653. }
  654. .up {
  655. color: #43CD80 !important;
  656. }
  657. .down {
  658. color: #E6273A !important;
  659. }
  660. .empty {
  661. width: 100%;
  662. line-height: 48rpx;
  663. }
  664. .value {
  665. margin-left: 5rpx;
  666. font-size: 30rpx !important;
  667. font-weight: bold !important;
  668. }
  669. .nodata-box{
  670. width: 400rpx;
  671. height: 400rpx;
  672. font-size: 28rpx;
  673. font-family: PingFangSC-Regular, PingFang SC;
  674. font-weight: 400;
  675. color: #666666;
  676. line-height: 40rpx;
  677. padding-top: 360rpx;
  678. margin: 0 auto;
  679. text-align: center;
  680. }
  681. }
  682. </style>