activeUserNum.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <template>
  2. <div>
  3. <el-card>
  4. <headers
  5. title="活跃用户统计"
  6. @changeOrgan="changeOrgan"
  7. :special="true"
  8. />
  9. <div class="chioseBox">
  10. <el-radio-group v-model="timers" @change="changeQuick">
  11. <el-radio-button label="month">本月</el-radio-button>
  12. <el-radio-button label="year">本年度</el-radio-button>
  13. <el-radio-button label="lastYear">去年</el-radio-button>
  14. </el-radio-group>
  15. <el-date-picker
  16. v-model="mdate"
  17. type="daterange"
  18. class="datePick"
  19. style="width: 300px; padding: 0 10px"
  20. range-separator="-"
  21. start-placeholder="开始日期"
  22. end-placeholder="结束日期"
  23. value-format="yyyy-MM-dd"
  24. format="yyyy-MM-dd"
  25. @change="changeValue"
  26. :picker-options="bigin()"
  27. >
  28. </el-date-picker>
  29. <p>单位:</p>
  30. <el-radio-group v-model="timer">
  31. <el-radio-button label="day">按天</el-radio-button>
  32. <el-radio-button label="month">按月</el-radio-button>
  33. </el-radio-group>
  34. </div>
  35. <ve-line
  36. style="width: 100%"
  37. height="350px"
  38. :data="timer == 'day' ? chartData : chartDataForMoth"
  39. :data-empty="dataEmpty"
  40. :extend="chartExtend"
  41. :legend="legend"
  42. ></ve-line>
  43. </el-card>
  44. </div>
  45. </template>
  46. <script>
  47. import "v-charts/lib/style.css";
  48. import "echarts/lib/component/dataZoom";
  49. import headers from "./modals/headers.vue";
  50. import veLine from "v-charts/lib/line.common";
  51. import { getNowDateAndSunday, getNowDateAndMonday } from "@/utils/date";
  52. import { getIndex } from "../api";
  53. import { getTimes } from "@/utils";
  54. import { descs, chioseNum } from "../constant";
  55. export default {
  56. components: {
  57. headers,
  58. veLine,
  59. },
  60. data() {
  61. return {
  62. timer: "day", // 按天 按月
  63. timers: "", // 本月 本年 去年
  64. mdate: [],
  65. data: [],
  66. organId: "",
  67. };
  68. },
  69. mounted() {
  70. this.init();
  71. },
  72. computed: {
  73. legend() {
  74. return {
  75. left: "10px",
  76. };
  77. },
  78. items() {
  79. let obj = {};
  80. let arr = [
  81. "MEMBER_STUDENT_NUM",
  82. "CLOUD_STUDY_LIVELY_STUDENT_NUM",
  83. "CLOUD_STUDY_DAY_USE_STUDENT_NUM",
  84. "CLOUD_STUDY_NEW_STUDENT_NUM",
  85. ];
  86. arr.forEach((str) => {
  87. if (this.data[str]) {
  88. obj[str] = this.data[str];
  89. }
  90. });
  91. /**
  92. * {
  93. HOMEWORK_CREATE_RATE:this.data["HOMEWORK_CREATE_RATE"] || {},
  94. HOMEWORK_SUBMIT_RATE: this.data["HOMEWORK_SUBMIT_RATE"] || {},
  95. HOMEWORK_COMMENT_RATE: this.data["HOMEWORK_COMMENT_RATE"] || {},
  96. };
  97. */
  98. return obj;
  99. },
  100. chartExtend() {
  101. return {
  102. series: {
  103. type: "line",
  104. smooth: false,
  105. },
  106. yAxis: {
  107. //纵轴标尺固定
  108. minInterval: 1,
  109. type: "value",
  110. scale: true,
  111. min: 0,
  112. max: 100,
  113. axisLabel: {
  114. formatter: "{value}%",
  115. },
  116. },
  117. tooltip: {
  118. axisPointer: {
  119. type: "shadow",
  120. shadowStyle: {
  121. color: "rgba(150,150,150,0.2)",
  122. },
  123. },
  124. formatter: (item) => {
  125. return [
  126. item[0].axisValueLabel,
  127. ...item.map(
  128. (d) => `<br/>${d.marker}${d.seriesName}: ${d.value[1]} %`
  129. ),
  130. ].join("");
  131. },
  132. },
  133. };
  134. },
  135. dataZoom() {
  136. return [
  137. {
  138. grid: {
  139. left: "0%",
  140. },
  141. type: "slider",
  142. start: 40,
  143. end: 100,
  144. },
  145. ];
  146. },
  147. chartData() {
  148. const values = Object.values(this.items);
  149. const months = {};
  150. for (const item of values) {
  151. for (const row of item.indexMonthData || []) {
  152. const key = this.$helpers.dayjs(row.month).format("YYYY-MM-DD");
  153. if (!months[key]) {
  154. months[key] = {
  155. 日期: key,
  156. };
  157. }
  158. months[key][item.title] = row.percent;
  159. }
  160. }
  161. return {
  162. columns: ["日期", ...values.map((item) => item.title)],
  163. rows: Object.values(months),
  164. };
  165. },
  166. chartDataForMoth() {
  167. const values = Object.values(this.items);
  168. // console.log(values)
  169. // values['VIP_GROUP_COURSE'].forEach(item=>{
  170. // console.log(item.month)
  171. // })
  172. const months = {};
  173. for (const item of values) {
  174. for (const row of item.indexMonthData || []) {
  175. const key = this.$helpers.dayjs(row.month).format("YYYY-MM");
  176. if (!months[key]) {
  177. months[key] = {
  178. 月份: key,
  179. };
  180. months[key][item.title] = row.percent;
  181. } else {
  182. if (
  183. months[key][item.title] &&
  184. item.dataType == "CLOUD_STUDY_NEW_STUDENT_NUM"
  185. ) {
  186. months[key][item.title] += parseFloat(row.percent);
  187. } else {
  188. months[key][item.title] = row.percent;
  189. }
  190. }
  191. }
  192. }
  193. // console.log(Object.values(months));
  194. return {
  195. columns: ["月份", ...values.map((item) => item.title)],
  196. rows: Object.values(months),
  197. };
  198. },
  199. dataEmpty() {
  200. return !this.chartData.rows.length;
  201. },
  202. chartExtend() {
  203. return {
  204. series: {
  205. type: "line",
  206. smooth: false,
  207. },
  208. yAxis: {
  209. //纵轴标尺固定
  210. minInterval: 1,
  211. type: "value",
  212. scale: true,
  213. min: 0,
  214. axisLabel: {
  215. formatter: "{value}人",
  216. },
  217. },
  218. tooltip: {
  219. axisPointer: {
  220. type: "shadow",
  221. shadowStyle: {
  222. color: "rgba(150,150,150,0.2)",
  223. },
  224. },
  225. formatter: (item) => {
  226. return [
  227. item[0].axisValueLabel,
  228. ...item.map(
  229. (d) => `<br/>${d.marker}${d.seriesName}: ${d.value[1]}人`
  230. ),
  231. ].join("");
  232. },
  233. },
  234. };
  235. },
  236. },
  237. methods: {
  238. init() {
  239. let nowTiem = this.$helpers.dayjs(new Date()).format("YYYY-MM-DD");
  240. let startTime = this.$helpers
  241. .dayjs(nowTiem)
  242. .subtract(8, "day")
  243. .format("YYYY-MM-DD");
  244. let endTime = this.$helpers
  245. .dayjs(nowTiem)
  246. .subtract(1, "day")
  247. .format("YYYY-MM-DD");
  248. this.mdate = [startTime, endTime];
  249. this.FetchDetail();
  250. },
  251. changeValue(date) {
  252. // 请求更改数据
  253. this.mdate = date;
  254. this.isDayOrMoth(date);
  255. console.log("调用", date);
  256. this.FetchDetail();
  257. },
  258. async FetchDetail() {
  259. this.loading = true;
  260. let data = [];
  261. try {
  262. // const { dates, ...rest } = this.search;
  263. // ...rest,
  264. const res = await getIndex({
  265. ...getTimes(this.mdate, ["startDate", "endDate"]),
  266. organId: this.organId,
  267. dataTypes:
  268. "MEMBER_STUDENT_NUM,CLOUD_STUDY_LIVELY_STUDENT_NUM,CLOUD_STUDY_DAY_USE_STUDENT_NUM,CLOUD_STUDY_NEW_STUDENT_NUM",
  269. });
  270. for (const item of res.data) {
  271. data[item.dataType] = {
  272. ...item,
  273. desc: descs[item.dataType],
  274. };
  275. }
  276. this.data = data;
  277. // for (const item of res.data) {
  278. // // 再循环一遍
  279. // for (const key in this.items) {
  280. // if (item.dataType == key) {
  281. // data[item.dataType] = {
  282. // ...item,
  283. // desc: descs[item.dataType],
  284. // };
  285. // }
  286. // }
  287. // }
  288. } catch (error) {
  289. console.log(error);
  290. }
  291. this.loading = false;
  292. this.data = data;
  293. // this.$emit("resetDate", data);
  294. },
  295. changeQuick(val) {
  296. let startDate;
  297. let endDate;
  298. if (val == "month") {
  299. // 获取本月的第一天 获取本月的今天
  300. let nowDate = this.$helpers.dayjs(new Date()).get("date");
  301. if (nowDate == 1) {
  302. startDate = this.$helpers.dayjs()
  303. .add(-1, "month")
  304. .startOf("month")
  305. .format("YYYY-MM-DD");
  306. endDate = this.$helpers.dayjs(new Date()).subtract(1, "day").format("YYYY-MM-DD");
  307. } else {
  308. startDate = this.$helpers.dayjs(new Date()).set("date", 1).format("YYYY-MM-DD");
  309. endDate = this.$helpers.dayjs(new Date()).subtract(1, "day").format("YYYY-MM-DD");
  310. }
  311. this.mdate = [startDate, endDate];
  312. this.isDayOrMoth(this.mdate);
  313. this.FetchDetail();
  314. // this.submitDate(this.date);
  315. } else if (val == "year") {
  316. let nowDate = this.$helpers.dayjs(new Date()).get("date");
  317. let nowMonth = this.$helpers.dayjs(new Date()).get("month") + 1;
  318. if (nowDate == 1 && nowMonth == 1) {
  319. startDate = this.$helpers
  320. .dayjs(new Date())
  321. .add(-1, "year")
  322. .set("month", 0)
  323. .set("date", 1)
  324. .format("YYYY-MM-DD");
  325. endDate = this.$helpers
  326. .dayjs(new Date())
  327. .subtract(1, "day")
  328. .format("YYYY-MM-DD");
  329. } else {
  330. startDate = this.$helpers
  331. .dayjs(new Date())
  332. .set("month", 0)
  333. .set("date", 1)
  334. .format("YYYY-MM-DD");
  335. this.endDate
  336. ? (endDate = this.endDate)
  337. : (endDate = this.$helpers
  338. .dayjs(new Date())
  339. .subtract(1, "day")
  340. .format("YYYY-MM-DD"));
  341. }
  342. this.mdate = [startDate, endDate];
  343. this.isDayOrMoth(this.mdate);
  344. this.FetchDetail();
  345. // this.submitDate(this.date);
  346. } else if (val == "lastYear") {
  347. startDate = this.$helpers
  348. .dayjs(new Date())
  349. .subtract(1, "year")
  350. .set("month", 0)
  351. .set("date", 1)
  352. .format("YYYY-MM-DD");
  353. endDate = this.$helpers
  354. .dayjs()
  355. .subtract(1, "year")
  356. .endOf("year")
  357. .format("YYYY-MM-DD");
  358. this.mdate = [startDate, endDate];
  359. this.isDayOrMoth(this.mdate);
  360. this.FetchDetail();
  361. // this.submitDate(this.date);
  362. }
  363. },
  364. bigin() {
  365. let self = this;
  366. return {
  367. firstDayOfWeek: 1,
  368. disabledDate(time) {
  369. if (self.endDate) {
  370. let endTime = self.$helpers.dayjs(self.endDate).valueOf();
  371. return time.getTime() > endTime;
  372. } else {
  373. return time.getTime() >= Date.now() - 24 * 60 * 60 * 1000;
  374. }
  375. },
  376. };
  377. },
  378. isDayOrMoth(arr) {
  379. if (!arr || arr.length < 1) {
  380. this.timer = "day";
  381. } else {
  382. const count = this.$helpers
  383. .dayjs(arr[0])
  384. .diff(this.$helpers.dayjs(arr[1]), "day");
  385. Math.abs(count) > chioseNum
  386. ? (this.timer = "month")
  387. : (this.timer = "day");
  388. }
  389. },
  390. changeOrgan(val) {
  391. this.organId = val;
  392. this.FetchDetail();
  393. },
  394. },
  395. };
  396. </script>
  397. <style lang="scss" scoped>
  398. ::v-deep .el-card__body {
  399. padding-top: 0 !important;
  400. }
  401. .chioseBox {
  402. position: absolute;
  403. right: 20px;
  404. z-index: 1000;
  405. display: flex;
  406. flex-direction: row;
  407. align-items: center;
  408. p {
  409. font-size: 14px;
  410. margin: 0 5px 0 10px;
  411. }
  412. .datePick {
  413. margin-left: 10px;
  414. }
  415. }
  416. .wrap {
  417. position: relative;
  418. }
  419. </style>