index.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <?php
  2. /**
  3. * @link:http://www.goodmall.com/
  4. * @copyright: Copyright (c) 2020
  5. * 文件描述
  6. * Author: xuyaoxiang
  7. * Date: 2021/1/28
  8. * Time: 9:57
  9. */
  10. ?>
  11. <style>
  12. .card{
  13. /* width: 800px; */
  14. margin-bottom: 20px;
  15. /* margin-right: 20px; */
  16. min-width: 400px;
  17. }
  18. .cardHead{
  19. display: flex;
  20. align-items: center;
  21. justify-content: space-between;
  22. flex-wrap: wrap;
  23. }
  24. .cardContent{
  25. margin-top: 20px;
  26. display: flex;
  27. flex-wrap: wrap;
  28. }
  29. .cardContent .item{
  30. display: flex;
  31. align-items: center;
  32. margin: 15px;
  33. padding-left: 4%;
  34. }
  35. .cardHeadLeft{
  36. margin-bottom: 10px;
  37. }
  38. .el-date-editor .el-range-separator{/* 设置选择日期框的中间的 ‘至’ 的宽度 */
  39. width: 8%;
  40. }
  41. .myTable{
  42. min-height: 500px;
  43. }
  44. </style>
  45. <div id="app" v-cloak>
  46. <el-card shadow="never" style="border:0;min-width: 1000px;" body-style="background-color: #f3f3f3;padding: 10px 0 0;">
  47. <div slot="header" style="display: flex;align-items: center;">
  48. <!-- <div>PK概况</div> -->
  49. <div id="nowtime" style="font-weight: bold;"></div>
  50. </div>
  51. <el-row :gutter="20">
  52. <el-col>
  53. <el-card class="card box-card" v-loading="personalPkStatistics.loading">
  54. <div class="cardHead">
  55. <div class="cardHeadLeft" style="font-size: 17px;font-weight: bold;flex-shrink: 0;">个人PK概况</div>
  56. <el-date-picker
  57. size="small"
  58. v-model="personalPkStatistics.timeRange"
  59. @change="timeChange('personalPkStatistics')"
  60. type="daterange"
  61. range-separator="至"
  62. start-placeholder="开始日期"
  63. end-placeholder="结束日期"
  64. value-format="timestamp"
  65. align="center"><!-- yyyy-MM-dd HH:mm:ss -->
  66. </el-date-picker>
  67. </div>
  68. <div class="cardContent" v-if="personalPkStatistics.list">
  69. <div class="item" v-for="(item, index) in personalPkStatistics.list">
  70. <img style="display: block;width: 60px;height: 60px;margin-right: 15px;" :src="item.icon" />
  71. <div style="font-weight: bold;">
  72. <div>{{ item.name }}</div>
  73. <div style="font-size: 20px;">{{ item.number }}</div>
  74. </div>
  75. </div>
  76. </div>
  77. </el-card>
  78. </el-col>
  79. <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
  80. <el-card class="card box-card" v-loading="personalPkDayUserStatistics.loading">
  81. <div class="cardHead">
  82. <div class="cardHeadLeft" style="font-size: 17px;font-weight: bold;flex-shrink: 0;">拉新PK <span style="font-size: 16px;font-weight: normal;color: #999;">(单位:人)</span></div>
  83. <el-date-picker
  84. size="small"
  85. v-model="personalPkDayUserStatistics.timeRange"
  86. @change="timeChange('personalPkDayUserStatistics')"
  87. type="daterange"
  88. range-separator="至"
  89. start-placeholder="开始日期"
  90. end-placeholder="结束日期"
  91. value-format="timestamp"
  92. align="center">
  93. </el-date-picker>
  94. </div>
  95. <div class="dataBox" id="echartsPersonalPkDayUser" style="width: 7.5rem;height: 4rem;margin-bottom: 20px;">
  96. </div>
  97. </el-card>
  98. </el-col>
  99. <el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
  100. <el-card class="card box-card" v-loading="personalPkDayMoneyStatistics.loading">
  101. <div class="cardHead">
  102. <div class="cardHeadLeft" style="font-size: 17px;font-weight: bold;flex-shrink: 0;">业绩PK<span style="font-size: 16px;font-weight: normal;color: #999;">(单位:元)</span></div>
  103. <el-date-picker
  104. size="small"
  105. v-model="personalPkDayMoneyStatistics.timeRange"
  106. @change="timeChange('personalPkDayMoneyStatistics')"
  107. type="daterange"
  108. range-separator="至"
  109. start-placeholder="开始日期"
  110. end-placeholder="结束日期"
  111. value-format="timestamp"
  112. align="center">
  113. </el-date-picker>
  114. </div>
  115. <div class="dataBox" id="echartsPersonalPkDayMoney" style="width: 7.5rem;height: 4rem;margin-bottom: 20px;margin-top: 0px;">
  116. </div>
  117. </el-card>
  118. </el-col>
  119. <el-col >
  120. <el-card class="card box-card" v-if="rankData.list" v-loading="rankData.loading">
  121. <div class="cardHead" style="padding-bottom: 10px;border-bottom: 1px solid #E8EAF5;">
  122. <div style="font-size: 17px;font-weight: bold;flex-shrink: 0;">个人排行TOP10</div>
  123. <div style="display: flex;align-items: center;">
  124. <div>PK活动名称:</div>
  125. <el-select v-model="rankData.id" size="small" placeholder="请选择" @change="getAllRankingList">
  126. <el-option
  127. v-for="item in activityList"
  128. :key="item.id"
  129. :label="item.name"
  130. :value="item.id">
  131. </el-option>
  132. </el-select>
  133. </div>
  134. </div>
  135. <el-table
  136. class="myTable"
  137. stripe
  138. size="small"
  139. :data="rankData.list"
  140. :show-header="false"
  141. style="width: 100%;margin-top: 30px;">
  142. <el-table-column
  143. label="日期"
  144. min-width="80"
  145. align="center">
  146. <template slot-scope="scope">
  147. <img :src="diy_img_prefix + '/static/addons/Pk/fir.png'" alt="" v-if="scope.$index+1 === 1">
  148. <img :src="diy_img_prefix + `/static/addons/Pk/sec.png`" alt="" v-else-if="scope.$index+1 === 2">
  149. <img :src="diy_img_prefix + `/static/addons/Pk/thir.png`" alt="" v-else-if="scope.$index+1 === 3">
  150. <span v-else>{{scope.$index+1}}</span>
  151. </template>
  152. </el-table-column>
  153. <el-table-column
  154. prop="name"
  155. label="姓名"
  156. min-width="150"
  157. >
  158. <template slot-scope="scope">
  159. <div style="display: flex;align-items: center;">
  160. <el-image fit="cover" :src="scope.row.user.avatar_url ? scope.row.user.avatar_url:'resources/img/common/default-avatar.png'" style="width: 50px;height:50px;border-radius: 50%;flex-shrink: 0;margin-right: 5px;"></el-image>
  161. <div v-if="scope.row.nickname">{{scope.row.user.nickname}}</div>
  162. <div v-else>{{scope.row.user.username}}</div>
  163. </div>
  164. </template>
  165. </el-table-column>
  166. <el-table-column
  167. prop="num"
  168. label="rankData.performance_type == 1 ? '拉新' : `业绩`"
  169. min-width="100"
  170. align="center"
  171. >
  172. <template slot-scope="scope">
  173. <div v-if="rankData.performance_type == 1"><span style="font-size: 20px;font-weight: bold;color: #EA5353;">{{scope.row.new_user_num}}</span>人</div>
  174. <div v-if="rankData.performance_type == 2"><span style="font-size: 20px;font-weight: bold;color: #EA5353;">{{scope.row.order_money_num}}</span>元</div>
  175. </template>
  176. </el-table-column>
  177. </el-table>
  178. </el-card>
  179. </el-col>
  180. </el-row>
  181. </el-card>
  182. </div>
  183. <script>
  184. const app = new Vue({
  185. el: '#app',
  186. data: {
  187. diy_img_prefix: '<?= Yii::getAlias('@attachurl') ?>',
  188. // 个人PK概况
  189. personalPkStatistics: {
  190. loading: false,
  191. timeRange: [],
  192. list: [],
  193. },
  194. //个人拉新PK按天统计
  195. personalPkDayUserStatistics: {
  196. loading: false,
  197. timeRange: [],
  198. list: [],
  199. echarts: null,
  200. },
  201. //个人业绩PK按天统计
  202. personalPkDayMoneyStatistics: {
  203. loading: false,
  204. timeRange: [],
  205. list: [],
  206. echarts: null,
  207. },
  208. // 活动列表
  209. activityList: [],
  210. // 排行榜
  211. rankData: {
  212. loading: false,
  213. topn: 10,
  214. list: [],
  215. id: 0,
  216. performance_type: 0
  217. }
  218. },
  219. created() {
  220. var size = (window.innerWidth || document.documentElement.clientWidth) / 1920 * 100;
  221. document.documentElement.style.fontSize = size + "px";
  222. document.body.style.fontSize = "14px";
  223. setInterval(()=>{
  224. this.NowTime()
  225. },1000)
  226. },
  227. mounted() {
  228. // 初始化
  229. this.iniData();
  230. // 加载数据
  231. this.loadData();
  232. },
  233. watch:{
  234. 'rankData.id': {
  235. handler(newId, oldId) {
  236. let that = this;
  237. that.activityList.map(function (item) {
  238. if (item.id == newId) {
  239. that.rankData.performance_type = item.performance_type;
  240. return false;
  241. }
  242. });
  243. },
  244. }
  245. },
  246. methods: {
  247. formatTime(timeStamp) {
  248. var date = new Date();
  249. date.setTime(timeStamp * 1000);
  250. var y = date.getFullYear();
  251. var m = date.getMonth() + 1;
  252. m = m < 10 ? ('0' + m) : m;
  253. var d = date.getDate();
  254. d = d < 10 ? ('0' + d) : d;
  255. var h = date.getHours();
  256. h = h < 10 ? ('0' + h) : h;
  257. var minute = date.getMinutes();
  258. var second = date.getSeconds();
  259. minute = minute < 10 ? ('0' + minute) : minute;
  260. second = second < 10 ? ('0' + second) : second;
  261. return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
  262. },
  263. timeChange(tag){
  264. // 个人PK概况
  265. if (tag == 'personalPkStatistics') {
  266. this.getPersonalPkStatistics();
  267. }
  268. //个人PK按天统计
  269. if (tag == 'personalPkDayUserStatistics') {
  270. this.getPersonalPkDayStatistics(tag, 'new_user_num');
  271. }
  272. //个人业绩PK按天统计
  273. if (tag == 'personalPkDayMoneyStatistics') {
  274. this.getPersonalPkDayStatistics(tag, 'order_money_num');
  275. }
  276. },
  277. loadData() {
  278. // 个人PK概况
  279. this.getPersonalPkStatistics();
  280. //个人PK按天统计
  281. this.getPersonalPkDayStatistics('personalPkDayUserStatistics', 'new_user_num');
  282. //个人业绩PK按天统计
  283. this.getPersonalPkDayStatistics('personalPkDayMoneyStatistics', 'order_money_num');
  284. // 获取活动列表
  285. this.getActivityList();
  286. },
  287. // 初始化数据
  288. iniData() {
  289. // 个人PK概况 时间范围
  290. this.personalPkStatistics.timeRange = [
  291. this.getTimestamps(30),
  292. this.getTimestamps()
  293. ];
  294. // 个人PK按天统计 时间范围
  295. this.personalPkDayUserStatistics.timeRange = [
  296. this.getTimestamps(30),
  297. this.getTimestamps()
  298. ];
  299. // 个人业绩PK按天统计 时间范围
  300. this.personalPkDayMoneyStatistics.timeRange = [
  301. this.getTimestamps(30),
  302. this.getTimestamps()
  303. ];
  304. // 个人PK按天统计 echart 初始化
  305. this.personalPkDayUserStatistics.echarts = echarts.init(document.querySelector("#echartsPersonalPkDayUser"));
  306. //个人业绩PK按天统计 echart 初始化
  307. this.personalPkDayMoneyStatistics.echarts = echarts.init(document.querySelector("#echartsPersonalPkDayMoney"));
  308. },
  309. // 获取时间戳
  310. getTimestamps(deduct_days = 0) {
  311. return new Date(new Date(new Date().toLocaleDateString()).getTime() - deduct_days * 24 * 3600 * 1000).getTime();
  312. },
  313. // 个人PK概况
  314. getPersonalPkStatistics()
  315. {
  316. if (this.personalPkStatistics.loading) {
  317. return false;
  318. }
  319. this.personalPkStatistics.loading = true;
  320. let params = {
  321. r: 'pk/default/personal-pk-statistics',
  322. start_time: this.personalPkStatistics.timeRange[0] / 1000,
  323. end_time: this.personalPkStatistics.timeRange[1] / 1000,
  324. };
  325. let that = this;
  326. request({
  327. params: params,
  328. method: 'get',
  329. }).then(e => {
  330. that.personalPkStatistics.loading = false;
  331. if (e.data.code == 0) {
  332. that.personalPkStatistics.list = e.data.data.list;
  333. } else {
  334. that.$message.error(e.data.msg);
  335. }
  336. }).catch(e => {
  337. that.personalPkStatistics.loading = false;
  338. });
  339. },
  340. // 按天统计数据
  341. // tag 数据标签
  342. // count_field 统计的字段
  343. getPersonalPkDayStatistics(tag, count_field)
  344. {
  345. let obj = this[tag];
  346. if (obj.loading) {
  347. return false;
  348. }
  349. obj.loading = true;
  350. let params = {
  351. r: 'pk/default/personal-pk-day-statistics',
  352. start_time: obj.timeRange[0] / 1000,
  353. end_time: obj.timeRange[1] / 1000,
  354. count_field: count_field
  355. };
  356. let that = this;
  357. request({
  358. params: params,
  359. method: 'get',
  360. }).then(e => {
  361. obj.loading = false;
  362. if (e.data.code == 0) {
  363. obj.list = e.data.data;
  364. // 个人拉新PK 按天统计
  365. if (tag == 'personalPkDayUserStatistics') {
  366. that.personalPkDayUserStatisticsRender();
  367. }
  368. if (tag == 'personalPkDayMoneyStatistics') {
  369. that.personalPkDayMoneyStatisticsRender();
  370. }
  371. } else {
  372. that.$message.error(e.data.msg);
  373. }
  374. }).catch(e => {
  375. obj.loading = false;
  376. });
  377. },
  378. // top 10
  379. getAllRankingList(){
  380. let that = this;
  381. if (that.rankData.loading) {
  382. return false;
  383. }
  384. let params = {
  385. r: 'pk/default/personal-pk-ranking',
  386. activity_id: that.rankData.id,//个人活动ID
  387. topn: this.rankData.topn
  388. };
  389. that.rankData.loading = true;
  390. request({
  391. params: params,
  392. method: 'get',
  393. }).then(e => {
  394. that.rankData.loading = false;
  395. if (e.data.code == 0) {
  396. that.rankData.list = e.data.data;
  397. } else {
  398. this.$message.error(e.data.msg);
  399. }
  400. }).catch(e => {
  401. that.rankData.loading = false;
  402. });
  403. },
  404. // 获取活动列表
  405. getActivityList()
  406. {
  407. let params = {
  408. r: 'pk/default/activity-list',
  409. };
  410. let that = this;
  411. request({
  412. params: params,
  413. method: 'get',
  414. }).then(e => {
  415. if (e.data.code == 0) {
  416. that.activityList = e.data.data.list;
  417. this.getCurrentActivity();
  418. } else {
  419. this.$message.error(e.data.msg);
  420. }
  421. }).catch(e => {
  422. });
  423. },
  424. // 获取当前活动
  425. getCurrentActivity()
  426. {
  427. let params = {
  428. r: 'pk/default/current-pk-activity',
  429. };
  430. let that = this;
  431. request({
  432. params: params,
  433. method: 'get',
  434. }).then(e => {
  435. if (e.data.code == 0) {
  436. that.rankData.id = e.data.data.activity.id;
  437. that.getAllRankingList();
  438. } else {
  439. this.$message.error(e.data.msg);
  440. }
  441. }).catch(e => {
  442. });
  443. },
  444. // 个人PK 按天统计 echart 显示
  445. personalPkDayUserStatisticsRender(){
  446. option = {
  447. color: ["#5F93F9", "#58D3A2"],
  448. tooltip: {
  449. trigger: "axis",
  450. axisPointer: {
  451. lineStyle: {
  452. color: "#dddc6b"
  453. }
  454. }
  455. },
  456. legend: {
  457. bottom: "0%",
  458. left:"4%",
  459. itemGap : 60,
  460. // data: ['个人PK', '战队PK']
  461. data: ['拉新']
  462. },
  463. grid: {
  464. left: '2%',
  465. right: '4%',
  466. bottom: '8%',
  467. containLabel: true
  468. },
  469. xAxis: [
  470. {
  471. type: 'category',
  472. boundaryGap: false,
  473. //data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  474. data: this.personalPkDayUserStatistics.list.keys
  475. },
  476. /* {
  477. axisPointer: { show: false },
  478. axisLine: { show: false },
  479. position: "bottom",
  480. offset: 20
  481. } */
  482. ],
  483. yAxis: [
  484. {
  485. type: 'value',
  486. axisTick: { show: false },
  487. }
  488. ],
  489. series: [
  490. {
  491. name: '拉新',
  492. type: 'line',
  493. smooth: true,
  494. symbolSize: 10,
  495. areaStyle: {
  496. normal: {
  497. color: new echarts.graphic.LinearGradient(
  498. 0,
  499. 0,
  500. 0,
  501. 1,
  502. [
  503. {
  504. offset: 0,
  505. color: "#5F93F9"
  506. },
  507. {
  508. offset: 1,
  509. color: "#ffffff"
  510. }
  511. ],
  512. false
  513. ),
  514. shadowColor: "rgba(0, 0, 0, 0.1)"
  515. }
  516. },
  517. //data: [120, 800, 101, 134, 90, 230, 510]
  518. data: this.personalPkDayUserStatistics.list.values
  519. },
  520. ]
  521. };
  522. // 使用刚指定的配置项和数据显示图表。
  523. let myChart = this.personalPkDayUserStatistics.echarts;
  524. myChart.clear();
  525. myChart.setOption(option);
  526. window.addEventListener("resize", function() {
  527. var size = (window.innerWidth || document.documentElement.clientWidth) / 1920 * 100;
  528. document.documentElement.style.fontSize = size + "px";
  529. document.body.style.fontSize = "14px";
  530. myChart.resize();
  531. });
  532. },
  533. personalPkDayMoneyStatisticsRender(){
  534. option = {
  535. color: ["#5F93F9", "#58D3A2"],
  536. tooltip: {
  537. trigger: "axis",
  538. axisPointer: {
  539. lineStyle: {
  540. color: "#dddc6b"
  541. }
  542. }
  543. },
  544. legend: {
  545. bottom: "0%",
  546. left:"4%",
  547. itemGap : 60,
  548. // data: ['个人PK', '战队PK']
  549. data: ['业绩']
  550. },
  551. grid: {
  552. left: '2%',
  553. right: '4%',
  554. bottom: '8%',
  555. containLabel: true
  556. },
  557. xAxis: [
  558. {
  559. type: 'category',
  560. boundaryGap: false,
  561. //data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
  562. data: this.personalPkDayMoneyStatistics.list.keys
  563. },
  564. /* {
  565. axisPointer: { show: false },
  566. axisLine: { show: false },
  567. position: "bottom",
  568. offset: 20
  569. } */
  570. ],
  571. yAxis: [
  572. {
  573. type: 'value',
  574. axisTick: { show: false },
  575. }
  576. ],
  577. series: [
  578. {
  579. name: '业绩',
  580. type: 'line',
  581. smooth: true,
  582. symbolSize: 10,
  583. areaStyle: {
  584. normal: {
  585. color: new echarts.graphic.LinearGradient(
  586. 0,
  587. 0,
  588. 0,
  589. 1,
  590. [
  591. {
  592. offset: 0,
  593. color: "#5F93F9"
  594. },
  595. {
  596. offset: 1,
  597. color: "#ffffff"
  598. }
  599. ],
  600. false
  601. ),
  602. shadowColor: "rgba(0, 0, 0, 0.1)"
  603. }
  604. },
  605. //data: [120, 800, 101, 134, 90, 230, 510]
  606. data: this.personalPkDayMoneyStatistics.list.values
  607. },
  608. ]
  609. };
  610. // 使用刚指定的配置项和数据显示图表。
  611. let myChart = this.personalPkDayMoneyStatistics.echarts;
  612. myChart.clear();
  613. myChart.setOption(option);
  614. window.addEventListener("resize", function() {
  615. var size = (window.innerWidth || document.documentElement.clientWidth) / 1920 * 100;
  616. document.documentElement.style.fontSize = size + "px";
  617. document.body.style.fontSize = "14px";
  618. myChart.resize();
  619. });
  620. },
  621. NowTime(){
  622. //获取年月日
  623. var time=new Date();
  624. var year=time.getFullYear();
  625. var month=time.getMonth()+1;
  626. var day=time.getDate();
  627. //获取时分秒
  628. var h=time.getHours();
  629. var m=time.getMinutes();
  630. var s=time.getSeconds();
  631. //检查是否小于10
  632. h=this.check(h);
  633. m=this.check(m);
  634. s=this.check(s);
  635. document.getElementById("nowtime").innerHTML="当前时间:"+year+"年"+month+"月"+day+"日 "+h+":"+m+":"+s;
  636. },
  637. //时间数字小于10,则在之前加个“0”补位。
  638. check(i){
  639. //方法一,用三元运算符
  640. var num;
  641. i<10?num="0"+i:num=i;
  642. return num;
  643. },
  644. }
  645. });
  646. </script>