AI销管
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

797 lignes
19 KiB

  1. <template>
  2. <view class="pages">
  3. <!-- 筛选框 -->
  4. <view class="boxtittabs">
  5. <view class="items" @tap="screenShow = true">{{ showTimeText }}
  6. <u-icon name="arrow-down" size="24" style="padding-left: 12rpx"></u-icon>
  7. </view>
  8. <view class="items" @tap="showSelect('companyList')">{{ showBeText }}
  9. <u-icon name="arrow-down" size="24" style="padding-left: 12rpx"></u-icon>
  10. </view>
  11. <view class="items" @tap="showSelect('houseList')">{{ showBeText1 }}
  12. <u-icon name="arrow-down" size="24" style="padding-left: 12rpx"></u-icon>
  13. </view>
  14. </view>
  15. <!-- 编辑指标 -->
  16. <view class="edit" v-if="CHECKAUTHORITY('biEditTarget')">
  17. <view class="edits" @click="toEdit">
  18. 编辑指标
  19. </view>
  20. </view>
  21. <!-- 待处理 -->
  22. <view class="grop">
  23. <view class="title">
  24. <image class="title-icon" src="https://static.quhouse.com/bc2ec951ad9a47e5bf58f2829926e143.png"
  25. mode="" />
  26. 转写消费
  27. </view>
  28. <view class="grid5">
  29. <block v-for="(item,index) in stayPendingProcessingArr">
  30. <view :key="index" class="real" v-if="item.show">
  31. <view class="realnum">{{item.data || 0}}</view>
  32. <view class="realtext">{{ item.title }}</view>
  33. </view>
  34. </block>
  35. </view>
  36. </view>
  37. <!-- 接待简报 -->
  38. <view class="grop">
  39. <view class="title">
  40. <image class="title-icon" src="https://static.quhouse.com/bc2ec951ad9a47e5bf58f2829926e143.png"
  41. mode="" />
  42. 接待简报
  43. </view>
  44. <view class="grid4">
  45. <block v-for="(item,index) in ReceptionBriefingArr">
  46. <view :key="index" class="real" v-if="item.show">
  47. <view class="realnum">{{item.data || 0}}</view>
  48. <view class="realtext">{{ item.title }}{{ item.unit }}</view>
  49. </view>
  50. </block>
  51. </view>
  52. </view>
  53. <!-- 排名柱状图 -->
  54. <block v-for="(item, index) in IndexRankingArr">
  55. <view class="grop" :key="index" v-if="item.show">
  56. <view class="titles">
  57. <view class="lside">
  58. {{item.title}}排名(top10)
  59. </view>
  60. <view class="rside">
  61. <view class="rside-item" :class="{active: item.isShowCity}" @click="checkCity(item, '按项目')">
  62. 按项目
  63. </view>
  64. <view class="rside-item" :class="{active: !item.isShowCity}" @click="checkCity(item, '按城市')">
  65. 按城市
  66. </view>
  67. </view>
  68. </view>
  69. <view class="echarts">
  70. <template v-if="item.type">
  71. <template v-if="item.isShowCity">
  72. <qiun-data-charts :type="item.type" :chartData="item.lineOptsect" :opts="item.lineOpts"
  73. background="none" :ontouch="true" :canvasId="item.canvasId" :canvas2d="true" />
  74. </template>
  75. <template v-else>
  76. <qiun-data-charts :type="item.type" :chartData="item.lineOptsect1" :opts="item.lineOpts"
  77. background="none" :ontouch="true" :canvasId="item.canvasId1" :canvas2d="true" />
  78. </template>
  79. </template>
  80. <template v-else>
  81. <view class="empty">
  82. <view
  83. style="width: 100%;height: 300rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;">
  84. <view style="width: 100%;text-align: center;">
  85. <image style="width: 220rpx;height: 200rpx;"
  86. src="https://static.quhouse.com/zhikong_xcx_img/nodatalist.png" mode="">
  87. </image>
  88. </view>
  89. <view style="text-align: center;width: 100%;margin-top: 20rpx;color: #999999;">暂无数据
  90. </view>
  91. </view>
  92. </view>
  93. </template>
  94. </view>
  95. </view>
  96. </block>
  97. <!-- 趋势折线图 -->
  98. <block v-for="(item, index) in IndicatorTrendsArr">
  99. <view class="grop" :key="index" v-if="item.show">
  100. <view class="titles">
  101. <view class="lside">
  102. {{item.title}}趋势
  103. </view>
  104. </view>
  105. <view class="echarts">
  106. <template v-if="item.lineOptsect">
  107. <qiun-data-charts :type="item.type" :chartData="item.lineOptsect" :opts="item.lineOpts"
  108. background="none" :ontouch="true" :canvasId="item.canvasId" :canvas2d="true" />
  109. </template>
  110. <template v-else>
  111. <view class="empty">
  112. <view
  113. style="width: 100%;height: 300rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;">
  114. <view style="width: 100%;text-align: center;">
  115. <image style="width: 220rpx;height: 200rpx;"
  116. src="https://static.quhouse.com/zhikong_xcx_img/nodatalist.png" mode="">
  117. </image>
  118. </view>
  119. <view style="text-align: center;width: 100%;margin-top: 20rpx;color: #999999;">暂无数据
  120. </view>
  121. </view>
  122. </view>
  123. </template>
  124. </view>
  125. </view>
  126. </block>
  127. <!-- 分布饼图 -->
  128. <block v-for="(item, index) in IndicatorDistributionArr">
  129. <view class="grop" :key="index" v-if="item.show">
  130. <view class="titles">
  131. <view class="lside">
  132. {{item.title}}分布
  133. </view>
  134. </view>
  135. <view class="echarts">
  136. <template v-if="item.type">
  137. <qiun-data-charts :type="item.type" :chartData="item.lineOptsect" :opts="item.lineOpts"
  138. background="none" :ontouch="true" :canvasId="item.canvasId" :canvas2d="true" />
  139. </template>
  140. <template v-else>
  141. <view class="empty">
  142. <view
  143. style="width: 100%;height: 300rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;">
  144. <view style="width: 100%;text-align: center;">
  145. <image style="width: 220rpx;height: 200rpx;"
  146. src="https://static.quhouse.com/zhikong_xcx_img/nodatalist.png" mode="">
  147. </image>
  148. </view>
  149. <view style="text-align: center;width: 100%;margin-top: 20rpx;color: #999999;">暂无数据
  150. </view>
  151. </view>
  152. </view>
  153. </template>
  154. </view>
  155. </view>
  156. </block>
  157. <!-- 更多筛选 -->
  158. <u-popup v-model="screenShow" mode="bottom" height="400">
  159. <view class="screen">
  160. <view class="boxtittab">
  161. <view class="tabbox">
  162. <view :class="{ activecllasscet: params.dateType == 0 }" @click="tabtimetap(0, '今天')">今天</view>
  163. </view>
  164. <view class="tabbox">
  165. <view :class="{ activecllasscet: params.dateType == 1 }" @click="tabtimetap(1, '近七天')">近七天
  166. </view>
  167. </view>
  168. <view class="tabbox">
  169. <view :class="{ activecllasscet: params.dateType == 2 }" @click="tabtimetap(2, '近30天')">近30天
  170. </view>
  171. </view>
  172. <view class="tabbox">
  173. <view :class="{ activecllasscet: params.dateType == null }" @click="tabtimetap(null, '自定义')">自定义
  174. </view>
  175. </view>
  176. </view>
  177. </view>
  178. </u-popup>
  179. <!-- 日期选择器 -->
  180. <u-calendar v-model="totalTimeShow" mode="range" @change="totalTimeChange"></u-calendar>
  181. <!-- 项目&公司 -->
  182. <u-select :mask-close-able="false" label-name="templateName" value-name="id" v-model="showTemplate"
  183. mode="single-column" :list="templateList" @cancel="templateCancel" @confirm="templateConfirm"></u-select>
  184. </view>
  185. </template>
  186. <script>
  187. const config = require("@/config");
  188. import * as allArrList from './arr.js'
  189. export default {
  190. data() {
  191. return {
  192. showTimeText: '近七天', // 展示文字
  193. showBeText: '公司', //
  194. showBeText1: '项目', //
  195. showTemplate: false,
  196. screenShow: false, // 日期选择器
  197. totalTimeShow: false, // 日期选择器
  198. templateList: [], // 销讲业务
  199. houseList: [], // 项目列表
  200. companyList: [], // 项目列表
  201. stayPendingProcessingArr: allArrList.stayPendingProcessingArr, // 待处理
  202. ReceptionBriefingArr: allArrList.ReceptionBriefingArr, // 接待简报
  203. IndexRankingArr: allArrList.IndexRankingArr, // 排名
  204. IndicatorTrendsArr: allArrList.IndicatorTrendsArr, // 排名
  205. IndicatorDistributionArr: allArrList.IndicatorDistributionArr, // 排名
  206. params: {
  207. staDate: '', //开启时间
  208. endDate: '', // 结束时间
  209. houseId: '', // 楼盘
  210. orgCode: '', // 公司code
  211. dateType: 1, // 自定义时间 今天0 近七天1 30天2
  212. },
  213. needFormatArr: ['stayPendingProcessingArr', 'ReceptionBriefingArr', 'IndexRankingArr',
  214. 'IndicatorTrendsArr', 'IndicatorDistributionArr'
  215. ], // 需要格式化的数组
  216. publicId: '', // 标识区别选择的是公司还是项目
  217. publicOpts: {
  218. color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
  219. "#ea7ccc"
  220. ],
  221. padding: [25, 25, 25, 25],
  222. enableScroll: false,
  223. legend: {},
  224. xAxis: {
  225. rotateLabel: true,
  226. rotateAngle: 90,
  227. fontSize: 10,
  228. },
  229. yAxis: {
  230. gridType: "dash",
  231. },
  232. extra: {
  233. line: {
  234. type: "straight",
  235. width: 2,
  236. activeType: "hollow"
  237. }
  238. }
  239. }
  240. };
  241. },
  242. onLoad() {
  243. this.getHouse()
  244. this.getCompany()
  245. this.initPage()
  246. },
  247. onPullDownRefresh() {
  248. this.initPage()
  249. setTimeout(() => {
  250. uni.stopPullDownRefresh()
  251. }, 2000)
  252. },
  253. methods: {
  254. // 字典
  255. biDictionary() {
  256. this.$u.get('/customer/biDict').then(res => {
  257. if (res) {
  258. this.needFormatArr.forEach((item, index) => {
  259. this[item] = this[item].map(it => {
  260. return {
  261. ...it,
  262. indexType: index
  263. }
  264. })
  265. let arr1 = res.filter(arr => arr.indexType == index)
  266. arr1.map(ie => {
  267. let objs = this[item].findIndex(obj => {
  268. return obj.title == ie.indexName && obj.indexType == ie
  269. .indexType
  270. }) || 0
  271. this[item][objs].id = ie.id || ''
  272. })
  273. })
  274. this.getFindBiByAccountId()
  275. }
  276. })
  277. },
  278. // 回显
  279. getFindBiByAccountId() {
  280. this.$u.get('/customer/findBiByAccountId').then(res => {
  281. if (res) {
  282. let arr = [...res.index1.split(','), ...res.index2.split(','), ...res.index3.split(','),
  283. ...res.index4.split(','), ...res.index5.split(',')
  284. ]
  285. this.needFormatArr.forEach(item => {
  286. this[item].forEach(items => {
  287. let obj = arr.find(obj => obj == items.id)
  288. if (obj) items.show = true
  289. else items.show = false
  290. })
  291. })
  292. }
  293. })
  294. },
  295. async initPage() {
  296. await this.biDictionary()
  297. await this.bishowIndex1()
  298. await this.bishowIndex2()
  299. this.$nextTick(() => {
  300. this.bishowIndex3()
  301. this.bishowIndex4()
  302. this.bishowIndex5()
  303. })
  304. },
  305. checkCity(item, name) {
  306. if (name == '按项目') {
  307. item.isShowCity = true
  308. } else {
  309. item.isShowCity = false
  310. }
  311. this.$forceUpdate()
  312. },
  313. bishowIndex1() {
  314. this.$u.post('/customer/bishowIndex1', this.params).then(res => {
  315. if (res) {
  316. this.stayPendingProcessingArr.forEach(item => {
  317. item.data = res[item.id] || 0
  318. })
  319. }
  320. })
  321. },
  322. bishowIndex2() {
  323. this.$u.post('/customer/bishowIndex2', this.params).then(res => {
  324. if (res) {
  325. this.ReceptionBriefingArr.forEach(item => {
  326. item.data = res[item.id] || 0
  327. })
  328. }
  329. })
  330. },
  331. bishowIndex3() {
  332. this.$u.post('/customer/bishowIndex3', this.params).then(res => {
  333. if (res) {
  334. this.IndexRankingArr.forEach(item => {
  335. if (res[item.id] && res[item.id].data.length > 0) {
  336. // 按项目
  337. item.canvasId = `IndexRankingArr${item.id}`
  338. item.lineOptsect = {
  339. categories: res[item.id].data.map(itme => {
  340. return itme.name
  341. }),
  342. series: [{
  343. name: item.title,
  344. data: JSON.parse(JSON.stringify(res[item.id].data)),
  345. }]
  346. }
  347. item.type = 'column'
  348. item.lineOpts = this.publicOpts
  349. item.lineOpts.legend = {
  350. show: false
  351. }
  352. // 按城市
  353. item.canvasId1 = `IndexRankingArrs${item.id}`
  354. item.lineOptsect1 = {
  355. categories: res[item.id].data2.map(itme => {
  356. return itme.name
  357. }),
  358. series: [{
  359. name: item.title,
  360. data: JSON.parse(JSON.stringify(res[item.id].data2))
  361. }]
  362. }
  363. this.$forceUpdate()
  364. }
  365. })
  366. }
  367. })
  368. },
  369. bishowIndex5() {
  370. this.$u.post('/customer/bishowIndex5', this.params).then(res => {
  371. if (res) {
  372. this.IndicatorDistributionArr.forEach(item => {
  373. if (res[item.id]) {
  374. console.log('进来了')
  375. item.type = 'pie'
  376. item.canvasId = `IndicatorDistributionArrs${item.id}`
  377. item.lineOptsect = {
  378. series: [{
  379. data: JSON.parse(JSON.stringify(res[item.id]))
  380. }]
  381. }
  382. item.lineOpts = {
  383. color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE",
  384. "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"
  385. ],
  386. padding: [20, 20, 20, 20],
  387. enableScroll: false,
  388. extra: {
  389. pie: {
  390. activeOpacity: 0.5,
  391. activeRadius: 10,
  392. offsetAngle: 0,
  393. labelWidth: 15,
  394. border: false,
  395. borderWidth: 3,
  396. borderColor: "#FFFFFF"
  397. },
  398. markLine: {
  399. labelOffsetX: 10,
  400. labelOffsetY: 10,
  401. }
  402. },
  403. }
  404. this.$forceUpdate()
  405. }
  406. })
  407. }
  408. })
  409. },
  410. bishowIndex4() {
  411. this.$u.post('/customer/bishowIndex4', this.params).then(res => {
  412. if (res) {
  413. this.IndicatorTrendsArr.forEach(item => {
  414. if (res[item.id]) {
  415. item.canvasId = `IndicatorTrendsArr${item.id}`
  416. item.lineOptsect = {
  417. categories: [],
  418. series: [{
  419. name: item.title,
  420. data: []
  421. }]
  422. }
  423. item.type = 'line'
  424. item.lineOpts = this.publicOpts
  425. res[item.id].forEach(itme => {
  426. item.lineOptsect.categories.push(itme.statDate.split(' ')[0])
  427. item.lineOptsect.series[0].data.push(itme[item.params] || 0)
  428. })
  429. this.$forceUpdate()
  430. }
  431. })
  432. }
  433. })
  434. },
  435. toEdit() {
  436. uni.navigateTo({
  437. url: '/pages/center/RuleEditing/RuleEditing'
  438. })
  439. },
  440. showSelect(params) {
  441. this.publicId = params
  442. this.templateList = this[params]
  443. this.showTemplate = true
  444. },
  445. // 获取项目
  446. getHouse() {
  447. uni.request({
  448. url: config.service.getUser,
  449. method: "GET",
  450. header: {
  451. 'content-type': 'application/json',
  452. 'Authorization': 'Bearer ' + uni.getStorageSync('weapp_session_login_data').token
  453. },
  454. success: (res) => {
  455. this.houseList = res.data.data.houseList.map(item => {
  456. return {
  457. id: item.id,
  458. templateName: item.propertyName,
  459. }
  460. })
  461. }
  462. })
  463. },
  464. // 获取公司
  465. getCompany() {
  466. this.$u.post('/customer/getMyOrg').then(res => {
  467. if (res) {
  468. this.companyList = res.map(item => {
  469. return {
  470. id: item.orgCode,
  471. templateName: item.name
  472. }
  473. })
  474. }
  475. })
  476. },
  477. //时间切换
  478. tabtimetap(index, text) {
  479. this.params.dateType = index;
  480. if (index == null) {
  481. this.totalTimeShow = true;
  482. this.screenShow = false
  483. } else {
  484. this.screenShow = false
  485. this.showTimeText = text
  486. this.params.endDate = ''
  487. this.params.staDate = ''
  488. this.initPage()
  489. }
  490. },
  491. //自定义时间
  492. totalTimeChange(e) {
  493. this.screenShow = false
  494. this.showTimeText = `${e.startDate}-${e.endDate}`
  495. this.params.dateType = null;
  496. this.params.endDate = e.endDate
  497. this.params.staDate = e.startDate
  498. this.initPage()
  499. },
  500. //
  501. templateCancel() {
  502. this.showTemplate = false;
  503. },
  504. //
  505. templateConfirm(e) {
  506. this.showTemplate = false;
  507. if (this.publicId == 'houseList') {
  508. this.showBeText1 = e[0].label
  509. this.params.houseId = e[0].value
  510. } else {
  511. this.showBeText = e[0].label
  512. this.params.orgCode = e[0].value
  513. }
  514. this.initPage()
  515. },
  516. },
  517. }
  518. </script>
  519. <style lang="scss" scoped>
  520. .pages {
  521. padding: 0 0 20rpx 0;
  522. width: 100vw;
  523. min-height: 100vh;
  524. background: #f2f2f2;
  525. display: flex;
  526. flex-direction: column;
  527. .boxtittabs {
  528. width: 100%;
  529. height: 92rpx;
  530. background: #FFFFFF;
  531. display: flex;
  532. align-items: center;
  533. position: sticky;
  534. top: var(--window-top);
  535. .items {
  536. padding: 0 24rpx;
  537. width: 50%;
  538. height: 100%;
  539. display: flex;
  540. align-items: center;
  541. justify-content: center;
  542. overflow: hidden;
  543. white-space: nowrap;
  544. text-overflow: ellipsis;
  545. }
  546. }
  547. .screen {
  548. //时间切换的样式
  549. .boxtittab {
  550. width: 100%;
  551. height: 100%;
  552. background: #FFFFFF;
  553. display: flex;
  554. flex-direction: column;
  555. border: none;
  556. .tabbox {
  557. flex: 1;
  558. height: 100%;
  559. text-align: center;
  560. line-height: 92rpx;
  561. color: #666666;
  562. font-size: 28rpx;
  563. font-weight: 400;
  564. display: flex;
  565. justify-content: center;
  566. .activecllasscet {
  567. width: 96rpx;
  568. color: #2671E2;
  569. font-weight: 600;
  570. border-bottom: 4rpx solid #2671E2;
  571. }
  572. }
  573. }
  574. }
  575. .edit {
  576. margin: 20rpx 0 0 0;
  577. padding: 0 20rpx;
  578. width: 100%;
  579. display: flex;
  580. align-items: center;
  581. justify-content: flex-end;
  582. .edits {
  583. padding: 10rpx 20rpx;
  584. background: #1890FF;
  585. color: #fff;
  586. border-radius: 16rpx;
  587. font-size: 32rpx;
  588. }
  589. }
  590. .grop {
  591. margin: 20rpx 0 0 0;
  592. padding: 20rpx;
  593. width: 100%;
  594. background: #fff;
  595. .title {
  596. height: 42rpx;
  597. font-size: 30rpx;
  598. font-family: PingFangSC-Semibold, PingFang SC;
  599. font-weight: 600;
  600. color: #333333;
  601. line-height: 42rpx;
  602. margin-bottom: 24rpx;
  603. display: flex;
  604. align-items: center;
  605. .title-icon {
  606. width: 12rpx;
  607. height: 20rpx;
  608. margin-right: 18rpx;
  609. }
  610. }
  611. .titles {
  612. width: 100%;
  613. display: flex;
  614. .lside {
  615. flex-grow: 1;
  616. height: 42rpx;
  617. font-size: 30rpx;
  618. font-family: PingFangSC-Semibold, PingFang SC;
  619. font-weight: 600;
  620. color: #333333;
  621. line-height: 42rpx;
  622. margin-bottom: 24rpx;
  623. display: flex;
  624. align-items: center;
  625. }
  626. .rside {
  627. flex-shrink: 0;
  628. display: flex;
  629. align-items: center;
  630. .rside-item {
  631. margin: 0 10rpx 0 0;
  632. &.active {
  633. color: #1890FF;
  634. }
  635. }
  636. }
  637. }
  638. .grid5 {
  639. padding: 20rpx 0;
  640. grid-row-gap: 20rpx;
  641. .real {
  642. width: 100%;
  643. height: 100%;
  644. .realnum {
  645. width: 100%;
  646. text-align: center;
  647. height: 50rpx;
  648. font-size: 36rpx;
  649. font-family: SourceHanSansCN-Medium, SourceHanSansCN;
  650. font-weight: bold;
  651. color: #333333;
  652. line-height: 50rpx;
  653. .qushi-icon {
  654. width: 28rpx;
  655. height: 14rpx;
  656. margin-left: 2rpx;
  657. }
  658. }
  659. .realtext {
  660. width: 100%;
  661. text-align: center;
  662. margin-top: 8rpx;
  663. height: 32rpx;
  664. font-size: 24rpx;
  665. font-family: PingFangSC-Regular, PingFang SC;
  666. font-weight: 400;
  667. color: #666666;
  668. line-height: 32rpx;
  669. }
  670. }
  671. }
  672. .grid4 {
  673. padding: 20rpx 0;
  674. grid-row-gap: 20rpx;
  675. .real {
  676. width: 100%;
  677. height: 100%;
  678. .realnum {
  679. width: 100%;
  680. text-align: center;
  681. height: 50rpx;
  682. font-size: 36rpx;
  683. font-family: SourceHanSansCN-Medium, SourceHanSansCN;
  684. font-weight: bold;
  685. color: #333333;
  686. line-height: 50rpx;
  687. .qushi-icon {
  688. width: 28rpx;
  689. height: 14rpx;
  690. margin-left: 2rpx;
  691. }
  692. }
  693. .realtext {
  694. width: 100%;
  695. text-align: center;
  696. margin-top: 8rpx;
  697. height: 32rpx;
  698. font-size: 24rpx;
  699. font-family: PingFangSC-Regular, PingFang SC;
  700. font-weight: 400;
  701. color: #666666;
  702. line-height: 32rpx;
  703. }
  704. }
  705. }
  706. }
  707. .grid5 {
  708. display: grid;
  709. grid-template-columns: repeat(5, 1fr);
  710. }
  711. .grid4 {
  712. display: grid;
  713. grid-template-columns: repeat(4, 1fr);
  714. }
  715. }
  716. </style>