AI销管
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Groupcontrast.vue 18 KiB

2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
2年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. <template>
  2. <view class="pages">
  3. <view class="boxtittab">
  4. <view class="tabbox">
  5. <view :class="{ activecllasscet: activeTotal == 4 }" @click="tabtimetap(4)">近七天</view>
  6. </view>
  7. <view class="tabbox">
  8. <view :class="{ activecllasscet: activeTotal == 5 }" @click="tabtimetap(5)">近15天</view>
  9. </view>
  10. <view class="tabbox">
  11. <view :class="{ activecllasscet: activeTotal == 6 }" @click="tabtimetap(6)">近30天</view>
  12. </view>
  13. <view class="tabbox">
  14. <view :class="{ activecllasscet: activeTotal == 3 }" @click="tabtimetap(3)">自定义</view>
  15. </view>
  16. </view>
  17. <view class="container">
  18. <scroll-view style="height: calc(100vh - 92rpx - 32rpx);" class="lside" scroll-y="true">
  19. <view class="lside-scrollbox">
  20. <block v-for="(data, index) in lsideList">
  21. <view class="lside-scrollbox-items" @tap="chooseLside(data, index)"
  22. :class="{active: index === lsideListIndex}" :key="index">
  23. {{ data.title }}
  24. </view>
  25. </block>
  26. </view>
  27. </scroll-view>
  28. <scroll-view style="height: calc(100vh - 92rpx - 32rpx);" class="rside" scroll-y="true">
  29. <view class="rside-scrollbox">
  30. <!-- 接待量 -->
  31. <template v-if="lsideListIndex === 0">
  32. <view class="single">
  33. <view class="title">
  34. <view class="title1">接待量(TOP10)</view>
  35. </view>
  36. <view class="hejisan">
  37. <view class="sanbox1">
  38. <view class="text1-2">{{newTeam1||0}}</view>
  39. <view class="text1-1">项目</view>
  40. </view>
  41. <view class="sanbox1">
  42. <view class="text1-2">{{newAvg1||0}}</view>
  43. <view class="text1-1">均值</view>
  44. </view>
  45. </view>
  46. <block v-for="(item,index) in newlisttabinfo1">
  47. <view class="box">
  48. <view class="box-lside">
  49. <template v-if="index < 2">
  50. <image class="img"
  51. :src="'../../../static/images/ranking/ranking'+ (index+1) +'.png'"
  52. mode=""></image>
  53. </template>
  54. <template v-else>
  55. <view class="ranking">{{ index + 1 }}</view>
  56. </template>
  57. </view>
  58. <view class="box-rside">
  59. <view class="box-top">
  60. <view class="percent-name">{{item.name}}</view>
  61. <view class="percent-zxl">{{ !item.zxl ? 0 : item.zxl}}</view>
  62. </view>
  63. <view class="percent-box">
  64. <view class="percent" :style="'width:'+ getPercent(item.zxl,1) + '%'">
  65. </view>
  66. </view>
  67. </view>
  68. </view>
  69. </block>
  70. </view>
  71. </template>
  72. <!-- 接待时长 -->
  73. <template v-if="lsideListIndex === 1">
  74. <view class="single">
  75. <view class="title">
  76. <view class="title1">接待时长(TOP10)</view>
  77. </view>
  78. <view class="hejisan">
  79. <view class="sanbox1">
  80. <view class="text1-2">{{newTeam2||0}}</view>
  81. <view class="text1-1">项目</view>
  82. </view>
  83. <view class="sanbox1">
  84. <view class="text1-2">{{newAvg2||0}}</view>
  85. <view class="text1-1">均值</view>
  86. </view>
  87. </view>
  88. <block v-for="(item,index) in newlisttabinfo2">
  89. <view class="box">
  90. <view class="box-lside">
  91. <template v-if="index < 2">
  92. <image class="img"
  93. :src="'../../../static/images/ranking/ranking'+ (index+1) +'.png'"
  94. mode=""></image>
  95. </template>
  96. <template v-else>
  97. <view class="ranking">{{ index + 1 }}</view>
  98. </template>
  99. </view>
  100. <view class="box-rside">
  101. <view class="box-top">
  102. <view class="percent-name">{{item.name}}</view>
  103. <view class="percent-zxl">{{ !item.zxl ? 0 : item.zxl}}</view>
  104. </view>
  105. <view class="percent-box">
  106. <view class="percent" :style="'width:'+ getPercent(item.zxl,2) + '%'">
  107. </view>
  108. </view>
  109. </view>
  110. </view>
  111. </block>
  112. </view>
  113. </template>
  114. <!-- 销讲执行排名 -->
  115. <template v-if="lsideListIndex === 2">
  116. <view class="single">
  117. <view class="title">
  118. <view class="title1" style="flex: 1;">销讲执行排名(TOP10)</view>
  119. </view>
  120. <view class="hejisan">
  121. <view class="sanbox1">
  122. <view class="text1-2">{{newTeam3||0}}</view>
  123. <view class="text1-1">项目</view>
  124. </view>
  125. <view class="sanbox1">
  126. <view class="text1-2">{{newAvg3||0}}%</view>
  127. <view class="text1-1">均值</view>
  128. </view>
  129. </view>
  130. <block v-for="(item,index) in newlisttabinfo3">
  131. <view class="box">
  132. <view class="box-lside">
  133. <template v-if="index < 2">
  134. <image class="img"
  135. :src="'../../../static/images/ranking/ranking'+ (index+1) +'.png'"
  136. mode=""></image>
  137. </template>
  138. <template v-else>
  139. <view class="ranking">{{ index + 1 }}</view>
  140. </template>
  141. </view>
  142. <view class="box-rside">
  143. <view class="box-top">
  144. <view class="percent-name">{{item.name}}</view>
  145. <view class="percent-zxl">{{ !item.zxl ? 0 : item.zxl}}</view>
  146. </view>
  147. <view class="percent-box">
  148. <view class="percent" :style="'width:'+ getPercent1(item.zxl) + '%'">
  149. </view>
  150. </view>
  151. </view>
  152. </view>
  153. </block>
  154. </view>
  155. </template>
  156. <!-- 顾问执行排名 -->
  157. <template v-if="lsideListIndex === 3">
  158. <view class="single">
  159. <view class="title">
  160. <view class="title1" style="flex: 1;">顾问执行排名(TOP10)</view>
  161. </view>
  162. <block v-for="(item,index) in newlisttabinfo4">
  163. <view class="box">
  164. <view class="box-lside">
  165. <template v-if="index < 2">
  166. <image class="img"
  167. :src="'../../../static/images/ranking/ranking'+ (index+1) +'.png'"
  168. mode=""></image>
  169. </template>
  170. <template v-else>
  171. <view class="ranking">{{ index + 1 }}</view>
  172. </template>
  173. </view>
  174. <view class="box-rside">
  175. <view class="box-top">
  176. <view class="percent-name">{{item.name}}</view>
  177. <view class="percent-zxl">{{ !item.zxl ? 0 : item.zxl}}</view>
  178. </view>
  179. <view class="percent-box">
  180. <view class="percent" :style="'width:'+ getPercent1(item.zxl) + '%'">
  181. </view>
  182. </view>
  183. </view>
  184. </view>
  185. </block>
  186. </view>
  187. </template>
  188. <template v-if="lsideListIndex === 4">
  189. <view class="single">
  190. <view class="title" style="padding-right: 30rpx;">
  191. <view class="title1" style="flex: 1;">销讲能力</view>
  192. <view class="title2" style="flex: 1;justify-content: flex-end;" @click="staffShow=true">
  193. <view class="title2-che" style="width: auto;">{{staff.label}}
  194. <image class="righttochoose" src="@/static/images/down.png" mode="">
  195. </image>
  196. </view>
  197. </view>
  198. </view>
  199. <view class="uchaserbox">
  200. <view v-if="!emptyCharData" class="uchaserbox" style="display: flex;
  201. align-items: center;justify-content: center;">
  202. <u-empty style="margin: 09 0 0 0;" mode="data"></u-empty>
  203. </view>
  204. <qiun-data-charts v-else class="qiudatacharts" type="radar" :chartData="chartData"
  205. :canvas2d="true" canvasId="wangxiaohuaerlingeryilingwuyib88" background="none"
  206. :loadingType="0" :opts="opts" />
  207. </view>
  208. </view>
  209. </template>
  210. </view>
  211. </scroll-view>
  212. </view>
  213. <!-- 日期选择器 -->
  214. <u-calendar v-model="totalTimeShow" mode="range" @change="totalTimeChange"></u-calendar>
  215. <!-- 选择项目 -->
  216. <u-select v-model="staffShow" :list="staffList" @confirm="staffSelectCallback" :default-value='selindex'>
  217. </u-select>
  218. <!-- 加载组件 -->
  219. <u-loadings v-model="LOADING"></u-loadings>
  220. </view>
  221. </template>
  222. <script>
  223. var app = getApp();
  224. var util = require("../../../utils/util.js");
  225. var config = require("../../../config");
  226. export default {
  227. data() {
  228. return {
  229. activeTotal: 4, // 时间选择下标
  230. // 日期选择器
  231. totalTimeShow: false, // 日期选择器
  232. lastStartDate: '', // 开始时间
  233. lastEndDate: '', // 结束时间
  234. // 项目选择器
  235. staffShow: false, // 展示项目选择器
  236. staffList: [], // 可选项目列表
  237. staff: {
  238. value: '',
  239. label: '',
  240. }, // 选择的项目数据
  241. houseId: '', // 项目id
  242. lsideList: [{
  243. title: '接待量',
  244. method: 'receptionCountList',
  245. methodParams: "1,groupComparisonReception",
  246. },
  247. {
  248. title: '接待时长',
  249. method: 'receptionCountList',
  250. methodParams: "2,groupComparisonReceptionTime"
  251. },
  252. {
  253. title: '销讲排名',
  254. method: 'receptionCountList',
  255. methodParams: "3,groupComparisonTalkRank"
  256. },
  257. {
  258. title: '顾问排名',
  259. method: 'receptionCountList',
  260. methodParams: "4,groupComparisonTalkRankByConsultant"
  261. },
  262. {
  263. title: '销讲能力',
  264. method: 'getPowerList',
  265. methodParams: ''
  266. },
  267. ],
  268. lsideListIndex: 0, // 默认选中下标
  269. // 右侧存放数据变量
  270. newlisttabinfo1: [{
  271. name: '接待量',
  272. zxl: '0'
  273. },
  274. {
  275. name: '平均执行率',
  276. zxl: '0'
  277. },
  278. {
  279. name: '接待客户',
  280. zxl: '0'
  281. },
  282. ], // 接待量
  283. // 接待量
  284. newTeam1: '',
  285. newAvg1: '',
  286. newlisttabinfo2: [{
  287. name: '接待量',
  288. zxl: '0'
  289. },
  290. {
  291. name: '平均执行率',
  292. zxl: '0'
  293. },
  294. {
  295. name: '接待客户',
  296. zxl: '0'
  297. },
  298. ], // 接待时长
  299. // 接待时长
  300. newTeam2: '',
  301. newAvg2: '',
  302. newlisttabinfo3: [{
  303. name: '接待量',
  304. zxl: '0'
  305. },
  306. {
  307. name: '平均执行率',
  308. zxl: '0'
  309. },
  310. {
  311. name: '接待客户',
  312. zxl: '0'
  313. },
  314. ], // 销讲排名
  315. // 销讲排名
  316. newTeam3: '',
  317. newAvg3: '',
  318. newlisttabinfo4: [{
  319. name: '接待量',
  320. zxl: '0'
  321. },
  322. {
  323. name: '平均执行率',
  324. zxl: '0'
  325. },
  326. {
  327. name: '接待客户',
  328. zxl: '0'
  329. },
  330. ], // 顾问排名
  331. // 顾问排名
  332. newTeam4: '',
  333. newAvg4: '',
  334. chartData: {
  335. categories: [],
  336. series: []
  337. }, // 销讲能力
  338. opts: {
  339. type: "radar",
  340. width: 300,
  341. fontSize: 10,
  342. extra: {
  343. radar: {
  344. max: 100
  345. }
  346. }
  347. },
  348. emptyCharData: false,
  349. };
  350. },
  351. onLoad() {
  352. this.LOADING = true
  353. uni.$on('updateGroup', (data) => {
  354. this.houseId = data.arr.join(',')
  355. // 获取销奖能力
  356. this.getPowerList()
  357. })
  358. this.getSectionList()
  359. },
  360. onPullDownRefresh() {},
  361. methods: {
  362. // 获取部门列表
  363. getSectionList() {
  364. this.$u.post('/user/getHouseByToken', )
  365. .then(res => {
  366. // console.log(res)
  367. this.staffList = []
  368. res.map((item, index) => {
  369. let obj = {}
  370. obj.value = item.id
  371. obj.label = item.propertyName
  372. this.staffList.push(obj)
  373. })
  374. this.houseId = this.staffList[0].value
  375. this.staff = this.staffList[0]
  376. this.getdata()
  377. })
  378. },
  379. // 获取数据
  380. getdata() {
  381. let params = this.lsideList[this.lsideListIndex].methodParams.split(',')
  382. this[this.lsideList[this.lsideListIndex].method](params[0], params[1])
  383. },
  384. // 转换百分比
  385. getPercent(num, type) {
  386. if (this.newlisttabinfo1 && this.newlisttabinfo1.length && type == 1) {
  387. let index0 = this.newlisttabinfo1[0]
  388. let percent = num / (index0.zxl) * 100
  389. return percent.toFixed(2)
  390. } else if (this.newlisttabinfo2 && this.newlisttabinfo2.length && type == 2) {
  391. let index0 = this.newlisttabinfo2[0]
  392. let percent = num / (index0.zxl) * 100
  393. return percent.toFixed(2)
  394. } else if (this.newlisttabinfo3 && this.newlisttabinfo3.length && type == 3) {
  395. let index0 = this.newlisttabinfo3[0]
  396. let percent = num / (index0.zxl) * 100
  397. return percent.toFixed(2)
  398. } else {
  399. return 0
  400. }
  401. },
  402. // 取数值
  403. getPercent1(num) {
  404. console.log(num)
  405. return num || 0
  406. },
  407. // 接待时长
  408. receptionCountList(index, url) {
  409. this.$u.post(`/cusLvStatistics/${url}`, {
  410. timeType: this.lastEndDate ? null : this.activeTotal + '',
  411. lastEndDate: this.lastEndDate,
  412. lastStartDate: this.lastStartDate
  413. })
  414. .then(res => {
  415. this.LOADING = false
  416. // console.log(res)
  417. let result = res.result
  418. this['newTeam' + index] = res.avg[0]
  419. this['newAvg' + index] = res.avg[1]
  420. this['newlisttabinfo' + index] = []
  421. // 当选择全部时
  422. let arr = []
  423. // 当两个都选择的时候
  424. result.map(item => {
  425. let obj = {}
  426. obj.name = item.houseName
  427. obj.zxl = item.data
  428. arr.push(obj)
  429. })
  430. arr = this.dealData(arr)
  431. this['newlisttabinfo' + index] = arr
  432. }).catch(() => {
  433. this.LOADING = false
  434. })
  435. },
  436. // 获取销奖能力
  437. getPowerList() {
  438. this.chartData = {
  439. categories: [],
  440. series: []
  441. }
  442. this.$u.post('/cusLvStatistics/groupComparisonMarketingAbility', {
  443. houseIds: this.houseId,
  444. timeType: this.lastEndDate ? null : this.activeTotal + '',
  445. lastEndDate: this.lastEndDate,
  446. lastStartDate: this.lastStartDate
  447. })
  448. .then(res => {
  449. this.LOADING = false
  450. let allobj = {
  451. categories: [],
  452. series: []
  453. }
  454. if (res.result.length > 0) {
  455. console.log(res, 'asdjkasl')
  456. res.result.map((item, index) => {
  457. let obj = {
  458. name: item.length > 0 ? item[0].houseName : '',
  459. data: []
  460. }
  461. item.map(item1 => {
  462. if (index == 0) {
  463. allobj.categories.push(item1.name)
  464. }
  465. obj.data.push(item1.avgExecutionRate)
  466. })
  467. allobj.series.push(obj)
  468. })
  469. this.chartData = allobj
  470. this.emptyCharData = true;
  471. } else {
  472. this.emptyCharData = false;
  473. }
  474. console.log(this.emptyCharData)
  475. this.$forceUpdate()
  476. }).catch(e => {
  477. this.LOADING = false
  478. })
  479. },
  480. //时间切换
  481. tabtimetap(index) {
  482. this.activeTotal = index;
  483. if (index == 3) {
  484. this.totalTimeShow = true;
  485. } else {
  486. this.lastEndDate = ''
  487. this.lastStartDate = ''
  488. this.getdata()
  489. }
  490. },
  491. //自定义时间
  492. totalTimeChange(e) {
  493. console.log(e.startDate, e.endDate)
  494. this.activeTotal = 3;
  495. this.lastEndDate = e.endDate
  496. this.lastStartDate = e.startDate
  497. this.getdata()
  498. },
  499. // 定义一个公共方法对数据进行处理
  500. dealData(arr) {
  501. // 获取最大值
  502. let num = Math.max.apply(Math, arr.map(function(o) {
  503. return o.zxl
  504. })) //结果:3
  505. if (num > 100) {
  506. // 获取最大值的下标
  507. arr.map(item => {
  508. item.zxl1 = Math.floor(item.zxl / num * 100)
  509. })
  510. return arr
  511. } else {
  512. arr.map(item => {
  513. item.zxl1 = item.zxl
  514. })
  515. return arr
  516. }
  517. },
  518. // 选择项目后更新数据
  519. staffSelectCallback(e) {
  520. this.staff = e[0]
  521. this.houseId = e[0].value
  522. this.getPowerList()
  523. },
  524. // 左侧菜单选中
  525. chooseLside(data, index) {
  526. this.lsideListIndex = index
  527. console.log(index)
  528. this.getdata()
  529. },
  530. },
  531. };
  532. </script>
  533. <style lang="scss" scoped>
  534. .pages {
  535. width: 100%;
  536. height: 100vh;
  537. display: flex;
  538. flex-direction: column;
  539. background: #F8F8F8;
  540. .boxtittab {}
  541. .container {
  542. padding: 16rpx 0;
  543. width: 100%;
  544. height: calc(100% - 92rpx - var(--window-top));
  545. display: grid;
  546. grid-template-columns: 160rpx calc(100vw - 160rpx);
  547. .lside {
  548. width: 100%;
  549. background: #F6F7FB;
  550. .lside-scrollbox {
  551. width: 100%;
  552. display: flex;
  553. flex-direction: column;
  554. .lside-scrollbox-items {
  555. width: 100%;
  556. height: 72rpx;
  557. display: flex;
  558. justify-content: center;
  559. align-items: center;
  560. font-size: 24rpx;
  561. font-family: PingFangSC-Regular, PingFang SC;
  562. font-weight: 400;
  563. color: #666666;
  564. overflow: hidden;
  565. text-overflow: ellipsis;
  566. white-space: nowrap;
  567. &.active {
  568. font-weight: 600;
  569. color: #2671E2;
  570. background: #FFFFFF;
  571. }
  572. }
  573. }
  574. }
  575. }
  576. .rside {
  577. width: 100%;
  578. .rside-scrollbox {
  579. width: 100%;
  580. background: #fff;
  581. display: flex;
  582. flex-direction: column;
  583. .single {
  584. width: 100%;
  585. display: flex;
  586. flex-direction: column;
  587. .hejisan {
  588. margin: 0 auto 28rpx;
  589. width: 542rpx;
  590. height: 120rpx;
  591. display: flex;
  592. background: #F6F7FB;
  593. border-radius: 8rpx;
  594. .sanbox1 {
  595. position: relative;
  596. flex-grow: 1;
  597. display: flex;
  598. flex-direction: column;
  599. justify-content: center;
  600. align-items: center;
  601. &:last-child::after {
  602. content: '';
  603. position: absolute;
  604. left: 0;
  605. top: 50%;
  606. transform: translateY(-50%);
  607. width: 1rpx;
  608. height: 80rpx;
  609. background: #E0E0E0;
  610. }
  611. }
  612. .text1-1 {
  613. font-size: 24rpx;
  614. font-family: PingFangSC-Regular, PingFang SC;
  615. font-weight: 400;
  616. color: #333333;
  617. line-height: 32rpx;
  618. }
  619. .text1-2 {
  620. color: #333333;
  621. font-size: 40rpx;
  622. line-height: 46rpx;
  623. font-family: PingFangSC-Regular, PingFang SC;
  624. margin-bottom: 10rpx;
  625. }
  626. }
  627. .uchaserbox {
  628. width: 100%;
  629. height: 470rpx;
  630. display: flex;
  631. flex-direction: column;
  632. #wangxiaohuaerlingeryilingwuyib88 {
  633. flex-grow: 1;
  634. }
  635. .qiudatacharts {
  636. flex-grow: 1;
  637. }
  638. }
  639. .box {
  640. margin: 0 0 28rpx;
  641. padding: 0 24rpx;
  642. width: 100%;
  643. display: flex;
  644. .box-lside {
  645. margin: 0 24rpx 0 0;
  646. flex-shrink: 0;
  647. display: flex;
  648. justify-content: center;
  649. align-items: center;
  650. .img {
  651. width: 42rpx;
  652. height: 44rpx;
  653. }
  654. .ranking {
  655. width: 42rpx;
  656. height: 44rpx;
  657. font-size: 24rpx;
  658. font-family: SFPro-SemiboldItalic, SFPro;
  659. font-weight: normal;
  660. color: #8A8D9F;
  661. }
  662. }
  663. .box-rside {
  664. flex-grow: 1;
  665. .box-top {
  666. margin-bottom: 14rpx;
  667. width: 470rpx;
  668. display: flex;
  669. .percent-name {
  670. flex-grow: 1;
  671. width: calc(100% - 42rpx);
  672. overflow: hidden;
  673. white-space: nowrap;
  674. text-overflow: ellipsis;
  675. }
  676. .percent-zxl {
  677. flex-shrink: 0;
  678. }
  679. }
  680. .percent-box {
  681. width: 100%;
  682. height: 30rpx;
  683. .percent {
  684. height: 100%;
  685. background: #F1F3FF;
  686. border-radius: 15px;
  687. }
  688. }
  689. }
  690. }
  691. }
  692. }
  693. }
  694. }
  695. </style>