|
@@ -0,0 +1,550 @@
|
|
|
+<template>
|
|
|
+ <div class="m-container">
|
|
|
+ <!-- 搜索标题 -->
|
|
|
+ <saveform
|
|
|
+ :inline="true"
|
|
|
+ ref="searchForm"
|
|
|
+ class="searchForm"
|
|
|
+ saveKey="exerciseDuration"
|
|
|
+ :model.sync="searchForm"
|
|
|
+ >
|
|
|
+ <el-form-item prop="dates">
|
|
|
+ <!-- @change="changeWeek" -->
|
|
|
+ <el-date-picker
|
|
|
+ :clearable="false"
|
|
|
+ v-model="searchForm.dates"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ :picker-options="{ firstDayOfWeek: 1 }"
|
|
|
+ type="daterange"
|
|
|
+ style="width: 405px"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ >
|
|
|
+ </el-date-picker>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item>
|
|
|
+ <el-button @click="search" type="danger">搜索</el-button>
|
|
|
+ <el-button @click="onReSet" type="primary">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </saveform>
|
|
|
+ <!-- 分组添加柱状图 -->
|
|
|
+ <ve-histogram
|
|
|
+ style="width: 100%"
|
|
|
+ height="350px"
|
|
|
+ :data="chartData"
|
|
|
+ :data-empty="dataEmpty"
|
|
|
+ :extend="chartExtend"
|
|
|
+ :legend="legend"
|
|
|
+ :data-zoom="dataZoom"
|
|
|
+ ></ve-histogram>
|
|
|
+
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="exportQuestion"
|
|
|
+ style="margin: 16px 0"
|
|
|
+ v-permission="'studentCoursewarePlayRecord/exportStatList'"
|
|
|
+ >导出</el-button
|
|
|
+ >
|
|
|
+ <div class="tableWrap">
|
|
|
+ <el-table
|
|
|
+ :data="tableList"
|
|
|
+ :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
|
|
|
+ @sort-change="onSortChange"
|
|
|
+ >
|
|
|
+ <el-table-column width="120px" align="center" prop="id" label="排名">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>
|
|
|
+ {{ scope.$index + 1 }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="organizationName"
|
|
|
+ label="分部名称"
|
|
|
+ ></el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="memberNum"
|
|
|
+ sortable="custom"
|
|
|
+ label="会员人数"
|
|
|
+ width="100px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.memberNum }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="noPlayNum"
|
|
|
+ sortable="custom"
|
|
|
+ label="无练习人数"
|
|
|
+ width="120px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.noPlayNum }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="playTimeLess10"
|
|
|
+ sortable="custom"
|
|
|
+ label="0-10分钟"
|
|
|
+ width="120px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.playTimeLess10 }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="playTimeLess60"
|
|
|
+ sortable="custom"
|
|
|
+ label="10-60分钟"
|
|
|
+ width="120px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.playTimeLess60 }}人</div>
|
|
|
+ </template></el-table-column
|
|
|
+ >
|
|
|
+
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="playTimeLess120"
|
|
|
+ sortable="custom"
|
|
|
+ label="60-120分钟"
|
|
|
+ width="120px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.playTimeLess120 }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="playTimeLess240"
|
|
|
+ sortable="custom"
|
|
|
+ label="120-240分钟"
|
|
|
+ width="130px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.playTimeLess240 }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="playTimeRather240"
|
|
|
+ sortable="custom"
|
|
|
+ label=">240分钟"
|
|
|
+ width="120px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.playTimeRather240 }}人</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ align="center"
|
|
|
+ prop="avgPlayTime"
|
|
|
+ sortable="custom"
|
|
|
+ label="平均时长"
|
|
|
+ width="100px"
|
|
|
+ >
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>{{ scope.row.avgPlayTime || 0 }}分钟</div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+
|
|
|
+ <el-table-column align="center" label="操作" fixed="right">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button
|
|
|
+ v-permission="'/coursewareDurationDetail'"
|
|
|
+ @click="onDetail(scope.row)"
|
|
|
+ type="text"
|
|
|
+ >详情</el-button
|
|
|
+ >
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import { Export } from "@/utils/downLoadFile";
|
|
|
+import saveform from "@/components/save-form";
|
|
|
+import dayjs from "dayjs";
|
|
|
+import histogram from "v-charts/lib/histogram.common";
|
|
|
+import { getNowDateAndMonday, getNowDateAndSunday } from "@/utils/utils";
|
|
|
+import { api_studentCoursewarePlayRecordList } from "../api";
|
|
|
+import { getTimeFormat } from "@/utils";
|
|
|
+let nowTime = dayjs()
|
|
|
+ .subtract(1, "day")
|
|
|
+ .format("YYYY-MM-DD");
|
|
|
+// export const getTimeFormat = (times, keys = []) => {
|
|
|
+// if (times && times.length) {
|
|
|
+// return {
|
|
|
+// [keys[0] || "start"]: dayjs(times[0]).format("YYYY-MM-DD"),
|
|
|
+// [keys[1] || "start"]: dayjs(times[1]).format("YYYY-MM-DD")
|
|
|
+// };
|
|
|
+// }
|
|
|
+// return {};
|
|
|
+// };
|
|
|
+export const getCurrentMonth = () => {
|
|
|
+ return [
|
|
|
+ dayjs()
|
|
|
+ .startOf("month")
|
|
|
+ .format("YYYY-MM-DD"),
|
|
|
+ dayjs()
|
|
|
+ .endOf("month")
|
|
|
+ .format("YYYY-MM-DD")
|
|
|
+ ];
|
|
|
+};
|
|
|
+export default {
|
|
|
+ components: { saveform, "ve-histogram": histogram },
|
|
|
+ name: "helpCategory",
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ searchForm: {
|
|
|
+ dates: getCurrentMonth(),
|
|
|
+ sort: null,
|
|
|
+ asc: null
|
|
|
+ },
|
|
|
+ tableList: []
|
|
|
+ };
|
|
|
+ },
|
|
|
+ async mounted() {
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ onSortChange(val) {
|
|
|
+ const template = {
|
|
|
+ memberNum: 1,
|
|
|
+ noPlayNum: 2,
|
|
|
+ playTimeLess10: 3,
|
|
|
+ playTimeLess60: 4,
|
|
|
+ playTimeLess120: 5,
|
|
|
+ playTimeLess240: 6,
|
|
|
+ playTimeRather240: 7,
|
|
|
+ avgPlayTime: 8
|
|
|
+ };
|
|
|
+ this.searchForm.sort = template[val.prop];
|
|
|
+ if (val.order === "ascending") {
|
|
|
+ this.searchForm.asc = true;
|
|
|
+ } else if (val.order === "descending") {
|
|
|
+ this.searchForm.asc = false;
|
|
|
+ } else {
|
|
|
+ this.searchForm.asc = null;
|
|
|
+ this.searchForm.sort = null;
|
|
|
+ }
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ exportQuestion() {
|
|
|
+ const { dates } = this.searchForm;
|
|
|
+ Export(
|
|
|
+ this,
|
|
|
+ {
|
|
|
+ url: "/api-web/studentCoursewarePlayRecord/exportStatList",
|
|
|
+ fileName: "云课堂观看统计.xls",
|
|
|
+ method: "post",
|
|
|
+ params: {
|
|
|
+ ...getTimeFormat(dates, ["startTime", "endTime"])
|
|
|
+ // exportEnum: "VIDEO_PLAY_STAT",
|
|
|
+ // queryInfo: {
|
|
|
+ // ...getTimeFormat(dates, ["startTime", "endTime"])
|
|
|
+ // }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "您确定导出云课堂观看统计?"
|
|
|
+ );
|
|
|
+ },
|
|
|
+ onDetail(row) {
|
|
|
+ this.$router.push({
|
|
|
+ path: "/coursewareDurationDetail",
|
|
|
+ query: {
|
|
|
+ organId: row.organizationId,
|
|
|
+ dates: JSON.stringify(this.searchForm.dates)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ search() {
|
|
|
+ this.$refs.searchForm.validate(valid => {
|
|
|
+ this.pageInfo = {
|
|
|
+ ...this.pageInfo,
|
|
|
+ page: 1
|
|
|
+ };
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ onReSet() {
|
|
|
+ this.pageInfo = {
|
|
|
+ ...this.pageInfo,
|
|
|
+ page: 1
|
|
|
+ };
|
|
|
+ this.$refs.searchForm.resetFields();
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ getDefaultTime() {
|
|
|
+ const dayjs = this.$helpers.dayjs;
|
|
|
+ let nowDate = dayjs(new Date()).format("YYYY-MM-DD");
|
|
|
+ let lastWeek = dayjs(nowDate)
|
|
|
+ .subtract(1, "week")
|
|
|
+ .format("YYYY-MM-DD");
|
|
|
+
|
|
|
+ console.log(lastWeek, nowDate, "121212");
|
|
|
+ this.searchForm.dates = [
|
|
|
+ getNowDateAndMonday(lastWeek),
|
|
|
+ getNowDateAndSunday(nowDate)
|
|
|
+ ];
|
|
|
+
|
|
|
+ console.log(this.searchForm.dates, "this.searchForm.dates");
|
|
|
+ },
|
|
|
+ changeWeek(val) {
|
|
|
+ if (val) {
|
|
|
+ // this.searchForm.dates = [
|
|
|
+ // getNowDateAndMonday(val[0]),
|
|
|
+ // getNowDateAndSunday(val[1])
|
|
|
+ // ];
|
|
|
+ } else {
|
|
|
+ this.getDefaultTime();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async getList() {
|
|
|
+ try {
|
|
|
+ const { dates, sort, asc } = this.searchForm;
|
|
|
+ let params = {
|
|
|
+ sort,
|
|
|
+ asc,
|
|
|
+ ...getTimeFormat(dates, ["startTime", "endTime"])
|
|
|
+ };
|
|
|
+ const res = await api_studentCoursewarePlayRecordList({
|
|
|
+ page: 1,
|
|
|
+ rows: 10,
|
|
|
+ ...params
|
|
|
+ });
|
|
|
+ this.tableList = [];
|
|
|
+ this.tableList = res.data;
|
|
|
+ } catch {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ // items() {
|
|
|
+ // let obj = {};
|
|
|
+ // let arr = [
|
|
|
+ // "normalNum",
|
|
|
+ // "train1",
|
|
|
+ // "train2",
|
|
|
+ // "train3",
|
|
|
+ // "train4",
|
|
|
+ // "buyRate",
|
|
|
+ // "avgTrainTime"
|
|
|
+ // ];
|
|
|
+ // arr.forEach(str => {
|
|
|
+ // if (this.dataList[str] + "") {
|
|
|
+ // obj[str] = {
|
|
|
+ // title: titles[str],
|
|
|
+ // percent: this.dataList[str],
|
|
|
+ // desc: descs[str]
|
|
|
+ // };
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+
|
|
|
+ // return obj;
|
|
|
+ // },
|
|
|
+ // scaleItems() {
|
|
|
+ // let obj = {};
|
|
|
+ // let arr = ["trainRate", "trainStandRate"];
|
|
|
+ // arr.forEach(str => {
|
|
|
+ // if (this.dataList[str] + "") {
|
|
|
+ // obj[str] = {
|
|
|
+ // title: titles[str],
|
|
|
+ // percent: this.dataList[str],
|
|
|
+ // desc: descs[str]
|
|
|
+ // };
|
|
|
+ // }
|
|
|
+ // });
|
|
|
+
|
|
|
+ // return obj;
|
|
|
+ // },
|
|
|
+ legend() {
|
|
|
+ return {
|
|
|
+ left: "10px"
|
|
|
+ };
|
|
|
+ },
|
|
|
+ chartData() {
|
|
|
+ const temp = {
|
|
|
+ noPlayNum: "无练习人数",
|
|
|
+ playTimeLess10: "0-10分钟",
|
|
|
+ playTimeLess60: "10-60分钟",
|
|
|
+ playTimeLess120: "60-120分钟",
|
|
|
+ playTimeLess240: "120-240分钟",
|
|
|
+ playTimeRather240: ">240分钟",
|
|
|
+ avgPlayTime: "平均时长"
|
|
|
+ };
|
|
|
+ const values = this.tableList;
|
|
|
+
|
|
|
+ const months = {};
|
|
|
+ for (const key in temp) {
|
|
|
+ for (const item of values) {
|
|
|
+ if (!months[item.organizationName]) {
|
|
|
+ months[item.organizationName] = {
|
|
|
+ 分部: item.organizationName
|
|
|
+ };
|
|
|
+ }
|
|
|
+ months[item.organizationName][temp[key]] = item[key] || 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ console.log(months, "months");
|
|
|
+ return {
|
|
|
+ columns: [
|
|
|
+ "分部",
|
|
|
+ "无练习人数",
|
|
|
+ "0-10分钟",
|
|
|
+ "10~60分钟",
|
|
|
+ "60-120分钟",
|
|
|
+ "120-240分钟",
|
|
|
+ ">240分钟",
|
|
|
+ "平均时长"
|
|
|
+ ],
|
|
|
+ rows: Object.values(months)
|
|
|
+ };
|
|
|
+ },
|
|
|
+ chartExtend() {
|
|
|
+ return {
|
|
|
+ yAxis: {
|
|
|
+ //纵轴标尺固定
|
|
|
+ minInterval: 1,
|
|
|
+ type: "value",
|
|
|
+ scale: true,
|
|
|
+ min: 0,
|
|
|
+ axisLabel: {
|
|
|
+ formatter: "{value}"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: {
|
|
|
+ type: "bar",
|
|
|
+ smooth: false
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ axisPointer: {
|
|
|
+ type: "shadow",
|
|
|
+ shadowStyle: {
|
|
|
+ color: "rgba(150,150,150,0.2)"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ formatter: item => {
|
|
|
+ // let arr = [
|
|
|
+ // { name: "会员人数", dot: "元" },
|
|
|
+ // { name: "<60分钟", dot: "%" },
|
|
|
+ // { name: "60-120分钟", dot: "元" },
|
|
|
+ // { name: "120-240分钟", dot: "元" },
|
|
|
+ // { name: ">240分钟", dot: "元" },
|
|
|
+ // { name: "平均时长", dot: "元" }
|
|
|
+ // ];
|
|
|
+ // console.log(item, "-121212--------------");
|
|
|
+ return [
|
|
|
+ item[0].axisValueLabel,
|
|
|
+ ...item.map(d => {
|
|
|
+ return `<br/>${d.marker}${d.seriesName}: ${d.value}${
|
|
|
+ d.seriesName == "平均时长" ? "分钟" : "人"
|
|
|
+ }`;
|
|
|
+ })
|
|
|
+ ].join("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
+ scalChartExtend() {
|
|
|
+ return {
|
|
|
+ yAxis: {
|
|
|
+ //纵轴标尺固定
|
|
|
+ minInterval: 1,
|
|
|
+ type: "value",
|
|
|
+ scale: true,
|
|
|
+ min: 0,
|
|
|
+ axisLabel: {
|
|
|
+ formatter: "{value}%"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ series: {
|
|
|
+ type: "bar",
|
|
|
+ smooth: false
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ axisPointer: {
|
|
|
+ type: "shadow",
|
|
|
+ shadowStyle: {
|
|
|
+ color: "rgba(150,150,150,0.2)"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ formatter: item => {
|
|
|
+ return [
|
|
|
+ item[0].axisValueLabel,
|
|
|
+ ...item.map(d => {
|
|
|
+ return `<br/>${d.marker}${d.seriesName}: ${d.value}%`;
|
|
|
+ })
|
|
|
+ ].join("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+ },
|
|
|
+ dataZoom() {
|
|
|
+ return [
|
|
|
+ {
|
|
|
+ show: true,
|
|
|
+ type: "slider",
|
|
|
+ start: 0,
|
|
|
+ end: 30,
|
|
|
+ filterMode: "empty",
|
|
|
+ zoomLock: true,
|
|
|
+ handleSize: 0
|
|
|
+ }
|
|
|
+ ];
|
|
|
+ },
|
|
|
+ dataEmpty() {
|
|
|
+ return !this.chartData.rows.length;
|
|
|
+ },
|
|
|
+ exporyun() {
|
|
|
+ return {
|
|
|
+ organId: this.organId
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+::v-deep .el-date-editor.el-input {
|
|
|
+ width: 100% !important;
|
|
|
+}
|
|
|
+::v-deep .el-select {
|
|
|
+ width: 100% !important;
|
|
|
+}
|
|
|
+::v-deep .el-table .cell {
|
|
|
+ display: -webkit-box;
|
|
|
+ overflow: hidden;
|
|
|
+ max-height: 45px;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ -webkit-line-clamp: 3;
|
|
|
+ -webkit-box-orient: vertical;
|
|
|
+}
|
|
|
+::v-deep .el-dialog__body {
|
|
|
+ padding: 10px 20px;
|
|
|
+}
|
|
|
+.newBand {
|
|
|
+ display: inline-block;
|
|
|
+}
|
|
|
+
|
|
|
+::v-deep .el-tabs__active-bar {
|
|
|
+ background-color: transparent !important;
|
|
|
+}
|
|
|
+::v-deep.el-tabs__nav-wrap {
|
|
|
+ &:after {
|
|
|
+ background-color: transparent !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+/*去掉切换时el-tab-pane底部的蓝色下划线*/
|
|
|
+::v-deep .el-tabs__nav-wrap::after {
|
|
|
+ background-color: transparent !important;
|
|
|
+}
|
|
|
+
|
|
|
+/*去掉tabs底部的下划线*/
|
|
|
+</style>
|