Tang 3 年 前
コミット
2ff0f50eef
21 ファイル変更2581 行追加212 行削除
  1. 10 0
      src/components/tableList.vue
  2. 16 0
      src/newApi/appuser.js
  3. 16 0
      src/newApi/colleges.js
  4. 24 0
      src/newApi/course.js
  5. 16 0
      src/newApi/festival.js
  6. 8 0
      src/newApi/studentList.js
  7. 2 2
      src/utils/request.js
  8. 432 0
      src/views/Marketing/goods/commodityManageMent/edit/courseContent/index copy.vue
  9. 155 17
      src/views/Marketing/goods/commodityManageMent/edit/courseContent/index.vue
  10. 163 0
      src/views/Marketing/goods/commodityManageMent/edit/courseContent/share.vue
  11. 21 0
      src/views/education/classManageMent/studentMenu/index.vue
  12. 238 0
      src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimension.vue
  13. 206 0
      src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimensionData/index.vue
  14. 219 0
      src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimensionData/infoBox.vue
  15. 14 192
      src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/index.vue
  16. 211 0
      src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/studentDimension.vue
  17. 187 1
      src/views/education/studentManageMent/studentList/index.vue
  18. 239 0
      src/views/education/studentManageMent/studentStatistics/index.vue
  19. 188 0
      src/views/education/studentManageMent/studentXQ/accesslog.vue
  20. 10 0
      src/views/education/studentManageMent/studentXQ/index.vue
  21. 206 0
      src/views/education/studentManageMent/studentXQ/studylog.vue

+ 10 - 0
src/components/tableList.vue

@@ -985,6 +985,16 @@
               (实收¥{{ scope.row[item.prop2] }})</span
             >
           </div>
+          <ul style="margin:0;" v-else-if="item.scope === 'chance'">
+            <li>总共:{{scope.row[item.prop1]}}</li>
+            <li>消耗:{{scope.row[item.prop2]}}</li>
+            <li>剩余:{{scope.row[item.prop1]-scope.row[item.prop2]}}</li>
+          </ul>
+          <ul style="margin:0;" v-else-if="item.scope === 'studyCount'">
+            <li>总共:{{scope.row[item.prop1]+scope.row[item.prop2]}}</li>
+            <li>消耗:{{scope.row[item.prop1]}}</li>
+            <li>剩余:{{scope.row[item.prop2]}}</li>
+          </ul>
           <span
             v-else-if="item.scope === 'statusPeriod'"
             :style="scope.row[item.prop] === 2 ? 'color:red' : ''"

+ 16 - 0
src/newApi/appuser.js

@@ -63,4 +63,20 @@ export default {
             method: 'get',
         })
     },
+    //统计查询客户端用户列表
+    inquirestudystats_list(data) {
+        return request({
+            url: '/app/user/stats_list',
+            method: 'get',
+            params: data
+        })
+    },
+    //导出统计查询客户端用户列表
+    exportstudystats_list(data) {
+        return request({
+            url: '/app/user/stats_list_export',
+            method: 'get',
+            params: data
+        })
+    },
 }

+ 16 - 0
src/newApi/colleges.js

@@ -31,4 +31,20 @@ export default {
             method: 'get',
         })
     },
+    //查询用户视频学习日志列表
+    inquireUserStudyloglist(data) {
+        return request({
+            url: '/user/study/log/list',
+            method: 'get',
+            params: data
+        })
+    },
+    //查询用户访问日志列表
+    inquireUserVisitloglist(data) {
+        return request({
+            url: '/user/visit/log/list',
+            method: 'get',
+            params: data
+        })
+    },
 }

+ 24 - 0
src/newApi/course.js

@@ -46,4 +46,28 @@ export default {
             method: 'get',
         })
     },
+    //课程统计报表
+    inquireCoursestatement(data) {
+        return request({
+            url: '/course/statement',
+            method: 'get',
+            params: data
+        })
+    },
+    //课程详情统计
+    inquireCoursedetailstatistics(data) {
+        return request({
+            url: '/course/detail/statistics',
+            method: 'get',
+            params: data
+        })
+    },
+    //学员观看记录
+    inquireCourseuserwatch(data) {
+        return request({
+            url: '/course/user/watch',
+            method: 'get',
+            params: data
+        })
+    },
 }

+ 16 - 0
src/newApi/festival.js

@@ -63,4 +63,20 @@ export default {
             data
         })
     },
+    //保存课程小节观看权限
+    coursesectionaddwatchper(data) {
+        return request({
+            url: '/course/section/add/watch/per',
+            method: 'post',
+            data
+        })
+    },
+    //获取课程小节观看权限
+    coursesectionwatchper(data) {
+        return request({
+            url: '/course/section/watch/per',
+            method: 'get',
+            params: data
+        })
+    },
 }

+ 8 - 0
src/newApi/studentList.js

@@ -88,6 +88,14 @@ export default {
             params: data
         })
     },
+    // 导出學員用户列表
+    inquiregradestudentlistStudentExport(data) {
+        return request({
+            url: '/grade/student/listStudentExport',
+            method: 'get',
+            params: data
+        })
+    },
     
 
 }

+ 2 - 2
src/utils/request.js

@@ -7,8 +7,8 @@ import methods from '@/utils/methodsTool';
 
 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
 // 创建axios实例
-export const baseURL = process.env.VUE_APP_BASE_API
-// export const baseURL = 'http://192.168.1.24:5030/'
+// export const baseURL = process.env.VUE_APP_BASE_API
+export const baseURL = 'http://192.168.1.24:5030/'
 export const BASE_IMG_URL = process.env.VUE_APP_IMG_API
 const service = axios.create({
   // axios中请求配置有baseURL选项,表示请求URL公共部分

+ 432 - 0
src/views/Marketing/goods/commodityManageMent/edit/courseContent/index copy.vue

@@ -0,0 +1,432 @@
+<template>
+  <div id="courseContent">
+    <div style="margin-bottom: 20px">
+      <el-button
+        v-if="!submitStatusInfo"
+        @click="addCourse"
+        size="small"
+        :disabled="tableData.length > 0 && tableData[0].type > 0"
+        >添加课程</el-button
+      >
+      <el-button
+        v-if="!submitStatusInfo"
+        @click="addMoreList"
+        size="small"
+        :disabled="
+          tableData.length > 0 && tableData[0].courseName ? true : false
+        "
+        >添加模块/章/节</el-button
+      >
+      <el-button
+        @click="openAudition"
+        type="success"
+        size="small"
+        v-if="tableData.length > 0"
+        >试听设置</el-button
+      >
+      <el-button type="primary" @click="openPlayPhotoSet" size="small"
+        >播放和拍照设置</el-button
+      >
+      <el-button type="primary" @click="openStyleNumSet" size="small"
+        >每天学习限制</el-button
+      >
+      <el-button type="primary" @click="openHandoutSet" size="small"
+        >关联讲义</el-button
+      >
+    </div>
+    <el-table
+      :data="tableData"
+      border
+      :header-cell-style="{
+        'background-color': '#eee',
+        padding: '8px',
+        color: '#333',
+      }"
+      :default-sort="{ prop: 'sort', order: 'ascending' }"
+    >
+      <el-table-column
+        v-for="(item, index) in compayTypes(tableSetVideo)"
+        :width="item.width"
+        :key="index"
+        :label="item.label"
+        align="center"
+        :show-overflow-tooltip="true"
+        header-align="center"
+        :sortable="item.prop === 'sort'"
+        sort-by="sort"
+        :prop="item.prop"
+      >
+        <template slot-scope="scope">
+          <span v-if="item.scope === 'types'">{{
+            scope.row[item.prop] === 1
+              ? "录播"
+              : scope.row[item.prop] === 2
+              ? "直播"
+              : scope.row[item.prop] === 3
+              ? "回放"
+              : "未知"
+          }}</span>
+          <span v-else-if="item.scope === 'type'">{{
+            scope.row[item.prop] === 1
+              ? "模块"
+              : scope.row[item.prop] === 2
+              ? "章"
+              : scope.row[item.prop] === 3
+              ? "节"
+              : "未知"
+          }}</span>
+          <span v-else-if="item.scope === 'busin'">
+            {{ scope.row[item.prop1] + " - " + scope.row[item.prop2] }}
+          </span>
+          <span v-else-if="item.scope === 'Status'">
+            {{
+              scope.row[item.prop] === 1
+                ? "发布"
+                : scope.row[item.prop] === 0
+                ? "未发布"
+                : "未知"
+            }}
+          </span>
+          <div v-else-if="item.scope === 'inputs'">
+            <el-input-number
+              style="width: 50px"
+              size="small"
+              :controls="false"
+              v-model="scope.row[item.prop]"
+              controls-position="right"
+              :min="0"
+            ></el-input-number>
+          </div>
+          <span v-else>{{ scope.row[item.prop] }}</span></template
+        >
+      </el-table-column>
+      <el-table-column
+        label="操作"
+        align="center"
+        fixed="right"
+        width="100px"
+        v-if="!submitStatusInfo"
+      >
+        <template slot-scope="scope">
+          <el-button type="text" @click="delCourse(scope.row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <popple-set
+      :key="Math.random()"
+      ref="poppleSet"
+      @uploadArrays="uploadArrays"
+    />
+    <course-check ref="courseCheck" @backData="backVideoData" />
+    <more-list-check
+      ref="moreListCheck"
+      @backData="backMoreListData"
+      :bfCourseId="bfCourseId"
+    />
+    <play-photo ref="playPhoto" @backData="backPlayPhotoData" />
+    <every-day-study-num ref="everyDayStudyNum" @backData="backEveryDaySet" />
+    <handout-view ref="handoutView" @backData="backHandoutView" />
+  </div>
+</template>
+
+<script>
+import poppleSet from "../../poppleSet.vue";
+import courseCheck from "./courseCheck.vue";
+import moreListCheck from "./moreListCheck.vue";
+import playPhoto from "./playPhoto.vue";
+import everyDayStudyNum from "./everyDayStudyNum.vue";
+import handoutView from "./handoutView.vue";
+
+export default {
+  components: {
+    poppleSet,
+    courseCheck,
+    moreListCheck,
+    playPhoto,
+    everyDayStudyNum,
+    handoutView,
+  },
+  props: ["listData", "submitStatusInfo"],
+  data() {
+    return {
+      tableSetVideo: [
+        { label: "排序", prop: "sort", scope: "inputs", width: "100" },
+        { label: "编码", prop: "code", width: "140" },
+        { label: "课程名称", prop: "courseName", width: "300", type: 1 },
+        { label: "类型", prop: "type", width: "190", type: 2, scope: "type" },
+        { label: "名称", prop: "menuName", width: "300", type: 2 },
+        { label: "科目", prop: "subjectName", width: "150", type: 1 },
+        { label: "专业", prop: "categoryName", type: 1 },
+        { label: "院校", prop: "schoolName", width: "150", type: 1 },
+        // {
+        //   label: "业务层次",
+        //   prop1: "projectName",
+        //   prop2: "businessName",
+        //   scope: "busin",
+        //   width: "350px",
+        //   type: 1,
+        // },
+        // { label: "教育类型", prop: "educationName", width: "160", type: 1 },
+        {
+          label: "发布状态",
+          prop: "publishStatus",
+          scope: "Status",
+        },
+      ],
+      tableData: [],
+      auditionList: [], //试听数据
+      bfCourseId: 0,
+    };
+  },
+  watch: {
+    tableData(val) {
+      if (val.length === 0) {
+        this.auditionList = [];
+      }
+    },
+  },
+  computed: {
+    compayTypes: function () {
+      return function (array) {
+        let ary = [];
+        ary = array.filter((item) => {
+          if (this.tableData.length > 0) {
+            if (this.tableData[0].type) {
+              return item.type !== 1;
+            } else {
+              return item.type !== 2;
+            }
+          } else {
+            return item;
+          }
+        });
+        return ary;
+      };
+    },
+  },
+  mounted() {
+    this.$bus.$on("sendBybus", () => {
+      this.tableData = [];
+    });
+  },
+  methods: {
+    /**
+     * 获取初始课程列表
+     */
+    getBybusCoursetableData(id) {
+      this.$api.obtainCourseSgoodsId(id).then((res) => {
+        if (res.rows.length === 1 && res.rows[0].courseShow === 0) {
+          this.bfCourseId = res.rows[0].courseId;
+          this.getMoreList(res.rows[0].courseId);
+          this.auditionList.forEach((item) => {
+            item.courseId = res.rows[0].courseId;
+          });
+          return;
+        }
+        this.tableData = res.rows;
+      });
+    },
+    /**
+     * 获取商品模块/章/节列表
+     */
+    getMoreList(id) {
+      this.$api.inquireCoursemenuListS({ courseId: id }).then((res) => {
+        res.rows.forEach((item) => {
+          item.auditionMinute = this.$methodsTools.secondToDate(
+            item.durationTime,
+            false
+          );
+          item.name = item.menuName;
+        });
+        this.tableData = res.rows;
+      });
+    },
+    /**
+     * 获取初始课程试听列表
+     */
+    getBybusCourseAudition(audition) {
+      this.auditionList = audition;
+      console.log(audition);
+    },
+    /**
+     * 点击添加函数
+     */
+    addCourse() {
+      //搜索条件
+      var data = {
+        businessId: this.listData.businessId,
+        subjectIds: this.listData.subjectIds.toString(),
+        status: 1,
+        pageSize: 10,
+        pageNum: 1,
+        publishStatus: 1,
+      };
+      //已选课程
+      var aList = this.tableData.map((item) => {
+        return item.courseId;
+      });
+      //打开选择课程组件
+      this.$refs.courseCheck.openBox(
+        data,
+        aList,
+        this.listData.educationTypeId
+      );
+    },
+    /**
+     * 选择课程回调数据
+     */
+    backVideoData(array) {
+      let copyData = JSON.parse(JSON.stringify(array));
+      if (this.tableData.length) {
+        let maxIndex = 0;
+        this.tableData.forEach((item) => {
+          if (item.sort > maxIndex) {
+            maxIndex = item.sort;
+          }
+        });
+        copyData.forEach((item, index) => {
+          item.sort = maxIndex + index + 1;
+        });
+      } else {
+        copyData.forEach((item, index) => {
+          item.sort = index + 1;
+        });
+      }
+      this.tableData = this.tableData.concat(copyData);
+    },
+    /**
+     * 删除课程
+     */
+    delCourse(item) {
+      if (this.tableData[0].type) {
+        const FINDINDEX = this.tableData.findIndex((items) => {
+          return items.type === item.type && item.menuId === item.menuId;
+        });
+        this.tableData.splice(FINDINDEX, 1);
+        this.auditionList = this.auditionList.filter((items) => {
+          return items.TypeId !== item.TypeId;
+        });
+        this.$message.success("删除成功");
+      } else {
+        const FINDINDEX = this.tableData.findIndex((items) => {
+          return items.courseId === item.courseId;
+        });
+        this.tableData.splice(FINDINDEX, 1);
+        this.auditionList = this.auditionList.filter((items) => {
+          return items.courseId !== item.courseId;
+        });
+        this.$message.success("删除成功");
+      }
+    },
+    /**
+     * 点击添加函数
+     */
+    addMoreList() {
+      //搜索条件
+      var data = {
+        businessId: this.listData.businessId,
+        subjectIds: this.listData.subjectIds.toString(),
+        status: 1,
+        pageSize: 10,
+        pageNum: 1,
+        publishStatus: 1,
+      };
+      //已选模块/章/节
+      var aList = this.tableData.map((item) => {
+        return `${item.type}-${item.menuId}`;
+      });
+      //打开选择模块/章/节组件
+      this.$refs.moreListCheck.openBox(
+        data,
+        aList,
+        this.listData.educationTypeId
+      );
+    },
+    /**
+     * 选择模块/章/节回调数据
+     */
+    backMoreListData(array) {
+      let copyData = JSON.parse(JSON.stringify(array));
+      if (this.tableData.length) {
+        let maxIndex = 0;
+        this.tableData.forEach((item) => {
+          if (item.sort > maxIndex) {
+            maxIndex = item.sort;
+          }
+        });
+        copyData.forEach((item, index) => {
+          item.sort = maxIndex + index + 1;
+        });
+      } else {
+        copyData.forEach((item, index) => {
+          item.sort = index + 1;
+        });
+      }
+      this.tableData = this.tableData.concat(copyData);
+    },
+    /**
+     * 点击试听函数
+     */
+    openAudition() {
+      console.log(this.tableData, this.auditionList);
+      this.$refs.poppleSet.openExpand(this.tableData, this.auditionList);
+    },
+    /**
+     * 试听回调数据
+     */
+    uploadArrays(arrays) {
+      this.auditionList = arrays;
+    },
+    /**
+     * 点击播放和拍照设置函数
+     */
+    openPlayPhotoSet() {
+      this.$refs.playPhoto.openBox(this.listData);
+    },
+    /**
+     * 播放和拍照设置回调数据
+     */
+    backPlayPhotoData(obj) {
+      this.$set(this.listData, "playConfig", obj.playConfig);
+      this.$set(this.listData, "photographConfig", obj.photographConfig);
+      this.$set(
+        this.listData,
+        "goodsPhotographExamConfig",
+        obj.goodsPhotographExamConfig
+      );
+    },
+    /**
+     * 点击学习限制函数
+     */
+    openStyleNumSet() {
+      this.$refs.everyDayStudyNum.openBox(this.listData.sectionMaxNum);
+    },
+    /**
+     * 学习限制回调数据
+     */
+    backEveryDaySet(num) {
+      this.$set(this.listData, "sectionMaxNum", num);
+    },
+    /**
+     * 点击选择讲义函数
+     */
+    openHandoutSet() {
+      if (!this.listData.businessId) {
+        this.$message.warning("请选择业务层次");
+        return;
+      }
+      console.log(this.listData);
+      this.$refs.handoutView.openBox(this.listData.handoutsId);
+    },
+    /**
+     * 讲义回调数据
+     */
+    backHandoutView(id) {
+      this.$set(this.listData, "handoutsId", id);
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 155 - 17
src/views/Marketing/goods/commodityManageMent/edit/courseContent/index.vue

@@ -43,13 +43,17 @@
         color: '#333',
       }"
       :default-sort="{ prop: 'sort', order: 'ascending' }"
+      lazy
+      :load="load"
+      row-key="keyId"
+      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
     >
       <el-table-column
         v-for="(item, index) in compayTypes(tableSetVideo)"
         :width="item.width"
         :key="index"
         :label="item.label"
-        align="center"
+        :align="item.scope === 'typeNames' ? 'left' : 'center'"
         :show-overflow-tooltip="true"
         header-align="center"
         :sortable="item.prop === 'sort'"
@@ -73,6 +77,8 @@
               ? "章"
               : scope.row[item.prop] === 3
               ? "节"
+              : scope.row[item.prop] === 0
+              ? "课程"
               : "未知"
           }}</span>
           <span v-else-if="item.scope === 'busin'">
@@ -87,16 +93,35 @@
                 : "未知"
             }}
           </span>
-          <div v-else-if="item.scope === 'inputs'">
-            <el-input-number
-              style="width: 50px"
-              size="small"
-              :controls="false"
-              v-model="scope.row[item.prop]"
-              controls-position="right"
-              :min="0"
-            ></el-input-number>
-          </div>
+          <span v-else-if="item.scope === 'typeNames'">
+            <span
+              v-if="scope.row['sectionType']"
+              style="color: green; margin-right: 10px"
+              >{{
+                scope.row["sectionType"] === 1
+                  ? "[录播]"
+                  : scope.row["sectionType"] === 2
+                  ? "[直播]"
+                  : scope.row["sectionType"] === 3
+                  ? "[回放]"
+                  : ""
+              }}</span
+            >
+
+            {{ scope.row[item.prop] }}
+          </span>
+          <span v-else-if="item.scope === 'inputs'">
+            <span v-if="item.scope === 'inputs' && scope.row['index']">
+              <el-input-number
+                style="width: 50px"
+                size="small"
+                :controls="false"
+                v-model="scope.row[item.prop]"
+                controls-position="right"
+                :min="0"
+              ></el-input-number>
+            </span>
+          </span>
           <span v-else>{{ scope.row[item.prop] }}</span></template
         >
       </el-table-column>
@@ -108,7 +133,18 @@
         v-if="!submitStatusInfo"
       >
         <template slot-scope="scope">
-          <el-button type="text" @click="delCourse(scope.row)">删除</el-button>
+          <el-button
+            type="text"
+            @click="delCourse(scope.row)"
+            v-if="scope.row.index"
+            >删除</el-button
+          >
+          <el-button
+            type="text"
+            v-if="scope.row.type === 3 && scope.row.sectionType !== 1"
+            @click="openShare(scope.row)"
+            >分享</el-button
+          >
         </template>
       </el-table-column>
     </el-table>
@@ -124,6 +160,7 @@
       :bfCourseId="bfCourseId"
     />
     <play-photo ref="playPhoto" @backData="backPlayPhotoData" />
+    <share ref="share" />
     <every-day-study-num ref="everyDayStudyNum" @backData="backEveryDaySet" />
     <handout-view ref="handoutView" @backData="backHandoutView" />
   </div>
@@ -134,6 +171,7 @@ import poppleSet from "../../poppleSet.vue";
 import courseCheck from "./courseCheck.vue";
 import moreListCheck from "./moreListCheck.vue";
 import playPhoto from "./playPhoto.vue";
+import share from "./share.vue";
 import everyDayStudyNum from "./everyDayStudyNum.vue";
 import handoutView from "./handoutView.vue";
 
@@ -143,6 +181,7 @@ export default {
     courseCheck,
     moreListCheck,
     playPhoto,
+    share,
     everyDayStudyNum,
     handoutView,
   },
@@ -152,9 +191,15 @@ export default {
       tableSetVideo: [
         { label: "排序", prop: "sort", scope: "inputs", width: "100" },
         { label: "编码", prop: "code", width: "140" },
-        { label: "课程名称", prop: "courseName", width: "300", type: 1 },
-        { label: "类型", prop: "type", width: "190", type: 2, scope: "type" },
-        { label: "名称", prop: "menuName", width: "300", type: 2 },
+        // { label: "课程名称", prop: "courseName", width: "300", type: 1 },
+        {
+          label: "名称",
+          prop: "menuName",
+          width: "300",
+          scope: "typeNames",
+        },
+        { label: "类型", prop: "type", width: "190", scope: "type" },
+        // { label: "名称", prop: "menuName", width: "300", type: 2 },
         { label: "科目", prop: "subjectName", width: "150", type: 1 },
         { label: "专业", prop: "categoryName", type: 1 },
         { label: "院校", prop: "schoolName", width: "150", type: 1 },
@@ -176,6 +221,7 @@ export default {
       tableData: [],
       auditionList: [], //试听数据
       bfCourseId: 0,
+      dialogVisible: false, //分享窗口
     };
   },
   watch: {
@@ -210,6 +256,62 @@ export default {
     });
   },
   methods: {
+    /**
+     * 打开分享窗口
+     */
+    openShare(rows) {
+      let goodsId = this.$route.query.id
+      this.$refs.share.openBox(rows,goodsId);
+      // this.$api.coursesectionwatchper().then((res) => {});
+    },
+    /**
+     * 异步加载table数据
+     */
+    load(tree, treeNode, resolve) {
+      if (tree.type === 0) {
+        this.$api
+          .inquireCoursemenuListS({ courseId: tree.courseId })
+          .then((res) => {
+            res.rows.forEach((item) => {
+              if (item.type === 2) {
+                item.chapterId = item.menuId;
+              }
+              item.keyId = `${tree.courseId}-${item.menuId}`;
+              item.children = [];
+              item.courseId = tree.courseId;
+              item.hasChildren = item.type === 3 ? false : true;
+            });
+            return resolve(res.rows);
+          });
+      } else if (tree.type === 1) {
+        this.$api.inquireCourseListmodulechapter(tree.menuId).then((res) => {
+          res.data.forEach((item) => {
+            item.keyId = `${tree.courseId}-${tree.menuId}-${item.chapterId}`;
+            item.children = [];
+            item.type = 2;
+            item.menuName = item.name;
+            item.courseId = tree.courseId;
+            item.hasChildren = item.type === 3 ? false : true;
+          });
+          return resolve(res.data);
+        });
+      } else if (tree.type === 2) {
+        this.$api
+          .inquireCoursechaptersectionlist(tree.chapterId)
+          .then((res) => {
+            res.data.forEach((item) => {
+              item.keyId = `${tree.courseId}-${tree.moduleId}-${tree.chapterId}-${item.sectionId}`;
+              item.children = [];
+              item.type = 3;
+              item.menuName = item.name;
+              item.hasChildren = false;
+            });
+            return resolve(res.data);
+          });
+      } else {
+        return resolve([]);
+      }
+    },
     /**
      * 获取初始课程列表
      */
@@ -223,6 +325,14 @@ export default {
           });
           return;
         }
+        res.rows.forEach((item, index) => {
+          item.keyId = item.courseId + "";
+          item.children = [];
+          item.hasChildren = true;
+          item.type = 0;
+          item.menuName = item.courseName;
+          item.index = true;
+        });
         this.tableData = res.rows;
       });
     },
@@ -236,7 +346,16 @@ export default {
             item.durationTime,
             false
           );
+          item.children = [];
+          item.hasChildren = item.type === 1 || item.type === 2 ? true : false;
           item.name = item.menuName;
+          item.index = true;
+          item.keyId = `${id}-${item.type === 1 ? item.menuId : 0}-${
+            item.type === 2 ? item.menuId : 0
+          }-${item.type === 3 ? item.menuId : 0}`;
+          item.moduleId = item.type === 1 ? item.menuId : 0;
+          item.chapterId = item.type === 2 ? item.menuId : 0;
+          item.sectionId = item.type === 3 ? item.menuId : 0;
         });
         this.tableData = res.rows;
       });
@@ -246,7 +365,6 @@ export default {
      */
     getBybusCourseAudition(audition) {
       this.auditionList = audition;
-      console.log(audition);
     },
     /**
      * 点击添加函数
@@ -277,6 +395,14 @@ export default {
      */
     backVideoData(array) {
       let copyData = JSON.parse(JSON.stringify(array));
+      copyData.forEach((item) => {
+        item.keyId = item.courseId + "";
+        item.children = [];
+        item.hasChildren = true;
+        item.type = 0;
+        item.menuName = item.courseName;
+        item.index = true;
+      });
       if (this.tableData.length) {
         let maxIndex = 0;
         this.tableData.forEach((item) => {
@@ -300,7 +426,7 @@ export default {
     delCourse(item) {
       if (this.tableData[0].type) {
         const FINDINDEX = this.tableData.findIndex((items) => {
-          return items.type === item.type && item.menuId === item.menuId;
+          return items.type === item.type && items.menuId === item.menuId;
         });
         this.tableData.splice(FINDINDEX, 1);
         this.auditionList = this.auditionList.filter((items) => {
@@ -347,6 +473,18 @@ export default {
      */
     backMoreListData(array) {
       let copyData = JSON.parse(JSON.stringify(array));
+      copyData.forEach((item) => {
+        item.keyId = `${this.bfCourseId}-${item.type === 1 ? item.menuId : 0}-${
+          item.type === 2 ? item.menuId : 0
+        }-${item.type === 3 ? item.menuId : 0}`;
+        (item.courseId = this.bfCourseId),
+          (item.moduleId = item.type === 1 ? item.menuId : 0);
+        item.chapterId = item.type === 2 ? item.menuId : 0;
+        item.sectionId = item.type === 3 ? item.menuId : 0;
+        item.children = [];
+        item.hasChildren = item.type === 3 ? false : true;
+        item.index = true;
+      });
       if (this.tableData.length) {
         let maxIndex = 0;
         this.tableData.forEach((item) => {

+ 163 - 0
src/views/Marketing/goods/commodityManageMent/edit/courseContent/share.vue

@@ -0,0 +1,163 @@
+<template>
+  <div id="share">
+    <el-dialog
+      :visible.sync="dialogVisible"
+      width="520px"
+      :show-close="false"
+      :close-on-click-modal="false"
+      destroy-on-close
+    >
+      <div slot="title" class="hearders">
+        <div class="leftTitle">分享</div>
+        <div class="rightBoxs">
+          <img
+            src="@/assets/images/Close@2x.png"
+            alt=""
+            @click="dialogVisible = false"
+          />
+        </div>
+      </div>
+      <el-form label-width="180px" :model="formLabelAlign">
+        <el-form-item label="观看权限:">
+          <el-radio-group v-model="formLabelAlign.watchPer">
+            <el-radio :label="1">已开通课程的学员</el-radio>
+            <el-radio :label="2">所有学员</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="观看链接(PC端):">
+          <span>地址</span>
+        </el-form-item>
+        <el-form-item label="观看二维码:">
+          <img
+            style="width: 100px; height: 100px"
+            :src="formLabelAlign.enCode"
+            alt=""
+          />
+          <el-button
+            type="text"
+            @click="downloadFileByBase64(formLabelAlign.enCode, '小程序二维码')"
+            >下载</el-button
+          >
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitTable">保 存</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      dialogVisible: false, //分享窗口
+      formLabelAlign: {
+        watchPer: 1,
+        enCode: "",
+      },
+      keyIdArray: [],
+      sectionType: "",
+      goodsId: "",
+    };
+  },
+  methods: {
+    //将base64转换为blob
+    dataURLtoBlob(dataurl) {
+      if(!dataurl){
+        this.$message.error("下载失败")
+        return
+      }
+      var arr = dataurl.split(","),
+        mime = arr[0].match(/:(.*?);/)[1],
+        bstr = atob(arr[1]),
+        n = bstr.length,
+        u8arr = new Uint8Array(n);
+      while (n--) {
+        u8arr[n] = bstr.charCodeAt(n);
+      }
+      return new Blob([u8arr], { type: mime });
+    },
+    //下载方法
+    downloadFile(url, name = "下载图") {
+      var a = document.createElement("a");
+      a.setAttribute("href", url);
+      a.setAttribute("download", name);
+      a.setAttribute("target", "_blank");
+      let clickEvent = document.createEvent("MouseEvents");
+      clickEvent.initEvent("click", true, true);
+      a.dispatchEvent(clickEvent);
+    },
+
+    downloadFileByBase64(base64, name) {
+      var myBlob = this.dataURLtoBlob(base64);
+      var myUrl = URL.createObjectURL(myBlob);
+      this.downloadFile(myUrl, name);
+    },
+    /**
+     * 打开分享窗口
+     */
+    openBox(rows, goodsId) {
+      this.keyIdArray = rows.keyId.split("-").map(Number);
+      this.goodsId = goodsId;
+      this.sectionType = rows.sectionType;
+      this.$api
+        .coursesectionwatchper({
+          goodsId: this.goodsId,
+          courseId: this.keyIdArray[0] || "",
+          moduleId: this.keyIdArray[1] || "",
+          chapterId: this.keyIdArray[2] || "",
+          sectionId: this.keyIdArray[3] || "",
+          sectionType: this.sectionType,
+        })
+        .then((res) => {
+          if (res.data) {
+            if (!res.data.watchPer) {
+              res.data.watchPer = 1;
+            }
+            this.formLabelAlign = res.data;
+          } else {
+            this.formLabelAlign = {
+              goodsId: this.goodsId,
+              courseId: this.keyIdArray[0] || "",
+              moduleId: this.keyIdArray[1] || "",
+              chapterId: this.keyIdArray[2] || "",
+              sectionId: this.keyIdArray[3] || "",
+              sectionType: this.sectionType,
+              watchPer: 1,
+            };
+          }
+          this.dialogVisible = true;
+        });
+    },
+    /**
+     * 保存分享
+     */
+    submitTable() {
+      this.dialogVisible = false;
+      let data;
+      if (this.formLabelAlign.id) {
+        data = this.formLabelAlign;
+      } else {
+        data = {
+          goodsId: this.goodsId,
+          courseId: this.keyIdArray[0] || "",
+          moduleId: this.keyIdArray[1] || "",
+          chapterId: this.keyIdArray[2] || "",
+          sectionId: this.keyIdArray[3] || "",
+          sectionType: this.sectionType,
+          watchPer: this.formLabelAlign.watchPer,
+        };
+      }
+      this.$api.coursesectionaddwatchper(data).then((res) => {
+        this.$message.success("保存成功");
+        this.dialogVisible = false;
+      });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 21 - 0
src/views/education/classManageMent/studentMenu/index.vue

@@ -768,6 +768,27 @@ export default {
           prop: "studyCount",
           hidden: false,
         },
+        {
+          label: "学习机会",
+          prop1: "useStudyCount",
+          prop2: "studyCount",
+          hidden: true,
+          scope:"studyCount"
+        },
+        {
+          label: "考试机会",
+          prop1: "examNumber",
+          prop2: "expendNumber",
+          hidden: true,
+          scope:"chance"
+        },
+        {
+          label: "前培机会",
+          prop1: "doNumber",
+          prop2: "expendBefore",
+          hidden: true,
+          scope:"chance"
+        },
         {
           label: "复购-学时冲突",
           prop: "rebuy",

+ 238 - 0
src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimension.vue

@@ -0,0 +1,238 @@
+<template>
+  <div id="curriculumDimension">
+    <search-box-new
+      ref="searchBox"
+      :formData="formData"
+      :formList="formList"
+      @search="search"
+      @init="init"
+      ><template slot="customize">
+        <el-button size="small" type="success" @click="moreActive"
+          >批量导出</el-button
+        >
+      </template></search-box-new
+    >
+    <table-list
+      :tableSets="tableSet"
+      :tableData="tableData"
+      :navText="navText"
+      :loading="loading"
+    >
+      <template slot="btn" slot-scope="props">
+        <el-button type="text" @click="doList(props.scope.row)">详情</el-button>
+      </template>
+    </table-list>
+    <pagination
+      :total="total"
+      :pageSize="formData.pageSize"
+      :currentPage="formData.pageNum"
+      @handleSizeChange="handleSizeChange"
+      @handleCurrentChange="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script>
+import * as baseUrls from "@/utils/request.js";
+import searchBoxNew from "@/components/searchBoxNew";
+import tableList from "@/components/tableList";
+import pagination from "@/components/pagination";
+export default {
+  components: { searchBoxNew, tableList, pagination },
+  data() {
+    return {
+      loading: false, //当前表单加载是否加载动画
+      navText: {
+        title: "课程维度列表",
+        index: 0,
+        ch: "条",
+        num: false,
+        border: true,
+        choice: true,
+        addHide: true,
+        backFatherBtn: {
+          status: false,
+          title: "未定义",
+        },
+      },
+      //搜索
+      formList: [
+        {
+          prop: "sectionName",
+          placeholder: "课程名称",
+        },
+      ],
+      formData: {
+        pageSize: 10,
+        pageNum: 1,
+      },
+      // 表单
+      tableSet: [
+        {
+          label: "课程名称",
+          prop: "sectionName",
+          hidden: true,
+        },
+        {
+          label: "课程状态",
+          prop: "watchStatus",
+          hidden: true,
+          scope: "isOptions",
+          options: [
+            {
+              label: "直播中",
+              value: "live",
+            },
+            {
+              label: "直播结束",
+              value: "end",
+            },
+            {
+              label: "回放中",
+              value: "playback",
+            },
+            {
+              label: "等待直播",
+              value: "waiting",
+            },
+          ],
+        },
+        {
+          label: "直播开始时间",
+          prop: "liveStartTime",
+          hidden: true,
+          scope: "aTimeList",
+        },
+        {
+          label: "直播结束时间",
+          prop: "liveEndTime",
+          hidden: true,
+          scope: "aTimeList",
+        },
+        {
+          label: "观看人数",
+          prop: "watchNumber",
+          hidden: true,
+        },
+        {
+          label: "开通课程人数",
+          prop: "buyCourseNumber",
+          hidden: true,
+        },
+        {
+          label: "未开通课程人数",
+          prop: "unBuyCourseNumber",
+          hidden: true,
+        },
+        {
+          label: "小程序观看人数",
+          prop: "appWatchNumber",
+          hidden: true,
+        },
+        {
+          label: "PC观看人数",
+          prop: "adminWatchNumber",
+          hidden: true,
+        },
+      ],
+      tableData: [], //表单数据
+      total: 0, //一共多少条
+      id: "",
+    };
+  },
+  mounted() {
+    this.id = this.$route.query.id;
+    this.search();
+  },
+  activated() {
+    this.search();
+  },
+  methods: {
+    moreActive() {
+      let arr = JSON.parse(JSON.stringify(this.formData));
+      arr.goodsId = this.id;
+      this.$api.inquireOrderGoodsexport_listLiveGoodsList(arr).then((res) => {
+        if (res.msg) {
+          let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
+          let link = document.createElement("a");
+          let fileName = "导出直播数据" + ".xlsx";
+          document.body.appendChild(link);
+          link.href = url;
+          link.dowmload = fileName;
+          link.click();
+          link.remove();
+          this.$message.success("导出成功");
+        } else {
+          this.$message.error("导出失败");
+        }
+      });
+    },
+    doList(row) {
+      const jump = () => {
+        this.$router.push({
+          path: "curriculumDimensionData",
+          query: {
+            goodsId: row.goodsId,
+            sectionId: row.sectionId,
+          },
+        });
+      };
+      const statusPage = this.$store.state.tagsView.visitedViews.some(
+        (item) => {
+          return item.name == "CurriculumDimensionData";
+        }
+      );
+      if (statusPage) {
+        this.$store
+          .dispatch("tagsView/delCachedView", {
+            name: "CurriculumDimensionData",
+          })
+          .then((res) => {
+            jump();
+          });
+      } else {
+        jump();
+      }
+    },
+    search(int) {
+      this.loading = true;
+      if (int === 1) {
+        this.formData.pageNum = 1;
+      }
+      if (int === 2) {
+        this.formData = {
+          pageSize: 10,
+          pageNum: 1,
+        };
+      }
+      var data = JSON.parse(JSON.stringify(this.formData));
+      data.goodsId = this.id;
+      this.$api
+        .inquireCoursestatement(data)
+        .then((res) => {
+          this.tableData = res.rows;
+          this.total = res.total;
+          this.navText.index = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    init() {
+      this.search(2);
+    },
+    handleSizeChange(v) {
+      this.formData.pageSize = v;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    handleCurrentChange(v) {
+      this.formData.pageNum = v;
+      this.search();
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 206 - 0
src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimensionData/index.vue

@@ -0,0 +1,206 @@
+<template>
+  <div id="curriculumDimensionData">
+    <search-box-new
+      ref="searchBox"
+      :formData="formData"
+      :formList="formList"
+      @search="search"
+      @init="init"
+    />
+    <table-list
+      :tableSets="tableSet"
+      :tableData="tableData"
+      :navText="navText"
+      :loading="loading"
+    >
+      <template slot="btn" slot-scope="props">
+        <el-button type="text" @click="doList(props.scope.row)">详情</el-button>
+      </template>
+    </table-list>
+    <pagination
+      :total="total"
+      :pageSize="formData.pageSize"
+      :currentPage="formData.pageNum"
+      @handleSizeChange="handleSizeChange"
+      @handleCurrentChange="handleCurrentChange"
+    />
+    <infoBox ref="infoBox" />
+  </div>
+</template>
+
+<script>
+import searchBoxNew from "@/components/searchBoxNew";
+import tableList from "@/components/tableList";
+import pagination from "@/components/pagination";
+import infoBox from "./infoBox.vue";
+export default {
+  components: { searchBoxNew, tableList, pagination, infoBox },
+  data() {
+    return {
+      loading: false, //当前表单加载是否加载动画
+      navText: {
+        title: `观看直播学员数`,
+        index: 0,
+        ch: "条",
+        num: false,
+        border: true,
+        choice: true,
+        addHide: true,
+        backFatherBtn: {
+          status: false,
+          title: "未定义",
+        },
+      },
+      //搜索
+      formList: [
+        {
+          prop: "userName",
+          placeholder: "学员姓名",
+        },
+        {
+          prop: "idCard",
+          placeholder: "学员身份证",
+        },
+        {
+          prop: "phone",
+          placeholder: "学员电话",
+        },
+        {
+          prop: "purchaseStatus",
+          placeholder: "开课状态",
+          scope: "select",
+          options: [
+            {
+              label: "已开课",
+              value: "1"
+            },
+            {
+              label: "未开课",
+              value: "0"
+            },
+          ],
+        },
+      ],
+      formData: {
+        pageSize: 10,
+        pageNum: 1,
+      },
+      // 表单
+      tableSet: [
+        {
+          label: "学员姓名",
+          prop: "userName",
+          hidden: true,
+        },
+        {
+          label: "学员身份证",
+          prop: "idCard",
+          hidden: true,
+        },
+        {
+          label: "学员电话",
+          prop: "phone",
+          hidden: true,
+        },
+        {
+          label: "开课状态",
+          prop: "purchaseStatus",
+          hidden: true,
+          scope: "isOptions",
+          options: [
+            {
+              label: "已开课",
+              value: 1,
+            },
+            {
+              label: "未开课",
+              value: 0,
+            },
+          ],
+        },
+        {
+          label: "直播累计时长",
+          prop: "liveDuration",
+          hidden: true,
+          scope: "convert",
+        },
+        {
+          label: "观看直播累计时长",
+          prop: "watchLiveDuration",
+          hidden: true,
+          scope: "convert",
+        },
+        {
+          label: "观看次数",
+          prop: "watchNumber",
+          hidden: true,
+        },
+      ],
+      tableData: [], //表单数据
+      total: 0, //一共多少条
+      goodsId: "",
+      sectionId: "",
+    };
+  },
+  mounted() {
+    this.goodsId = this.$route.query.goodsId;
+    this.sectionId = this.$route.query.sectionId;
+    this.search();
+  },
+  activated() {
+    this.search();
+  },
+  methods: {
+    /**
+     * 查看详情
+     */
+    doList(row) {
+      this.$refs.infoBox.openBox({
+        goodsId: this.goodsId,
+        sectionId: this.sectionId,
+        userId: row.userId,
+      });
+    },
+    search(int) {
+      this.loading = true;
+      if (int === 1) {
+        this.formData.pageNum = 1;
+      }
+      if (int === 2) {
+        this.formData = {
+          pageSize: 10,
+          pageNum: 1,
+        };
+      }
+      var data = JSON.parse(JSON.stringify(this.formData));
+      data.goodsId = this.goodsId;
+      data.sectionId = this.sectionId;
+      this.$api
+        .inquireCoursedetailstatistics(data)
+        .then((res) => {
+          this.tableData = res.rows;
+          this.total = res.total;
+          this.navText.index = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    init() {
+      this.search(2);
+    },
+    handleSizeChange(v) {
+      this.formData.pageSize = v;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    handleCurrentChange(v) {
+      this.formData.pageNum = v;
+      this.search();
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 219 - 0
src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/curriculumDimensionData/infoBox.vue

@@ -0,0 +1,219 @@
+<template>
+  <div id="infoBox">
+    <el-dialog
+      :visible.sync="dialogVisibleTableBoxs"
+      width="1100px"
+      :show-close="false"
+      :close-on-click-modal="false"
+    >
+      <div slot="title" class="hearders">
+        <div class="leftTitle">观看记录</div>
+        <div class="rightBoxs">
+          <img
+            src="@/assets/images/Close@2x.png"
+            alt=""
+            @click="dialogVisibleTableBoxs = false"
+          />
+        </div>
+      </div>
+      <el-table
+        ref="multipleTable"
+        :data="tableData"
+        border
+        :header-cell-style="{
+          'background-color': '#eee',
+          padding: '8px',
+          color: '#333',
+        }"
+        max-height="600"
+      >
+        <el-table-column
+          label="序号"
+          type="index"
+          width="80"
+          align="center"
+          header-align="center"
+        >
+        </el-table-column>
+        <template v-for="(item, index) in tableSet">
+          <el-table-column
+            v-if="item.scope !== 'inputs'"
+            :width="item.width"
+            :key="index"
+            :label="item.label"
+            align="center"
+            :show-overflow-tooltip="true"
+            header-align="center"
+          >
+            <template slot-scope="scope">
+              <span v-if="item.scope === 'Date'">
+                {{ $methodsTools.onlyForma(scope.row[item.prop]) }}
+              </span>
+              <span v-else-if="item.scope === 'time'">
+                {{ $methodsTools.secondToDate(scope.row[item.prop], false) }}
+              </span>
+              <span v-else-if="item.scope === 'Type'">
+                {{
+                  scope.row[item.prop] === 1
+                    ? "录播"
+                    : scope.row[item.prop] === 2
+                    ? "直播"
+                    : scope.row[item.prop] === 3
+                    ? "回放"
+                    : ""
+                }}
+              </span>
+              <span v-else-if="item.scope === 'Plat'">
+                {{
+                  scope.row[item.prop] === "1"
+                    ? "小程序"
+                    : scope.row[item.prop] === "2"
+                    ? "PC端"
+                    : ""
+                }}
+              </span>
+              <span v-else>{{ scope.row[item.prop] }}</span></template
+            >
+          </el-table-column></template
+        >
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisibleTableBoxs = false">取 消</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      size: "small",
+      dialogVisibleTableBoxs: false,
+      tableData: [],
+      tableSet: [
+        { label: "进入时间", prop: "startTime", scope: "Date" },
+        {
+          label: "离开时间",
+          prop: "endTime",
+          scope: "Date",
+        },
+        { label: "观看时长", prop: "watchLiveDuration", scope: "time" },
+        { label: "观看类型", prop: "sectionType", scope: "Type" },
+        { label: "观看终端", prop: "fromPlat", scope: "Plat" },
+      ],
+      formData: {},
+    };
+  },
+  methods: {
+    /**
+     * 初始
+     */
+    openBox(obj) {
+      this.formData = JSON.parse(JSON.stringify(obj));
+      this.getInfos();
+      this.dialogVisibleTableBoxs = true;
+    },
+    /**
+     * 搜索数据
+     */
+    getInfos(int) {
+      this.$api.inquireCourseuserwatch(this.formData).then((res) => {
+        this.tableData = res.data;
+      });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+/deep/.el-button {
+  border-radius: 8px;
+}
+/deep/.el-dialog {
+  border-radius: 8px;
+  .el-dialog__header {
+    padding: 0;
+    .hearders {
+      height: 40px;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      padding: 0px 18px 0px 20px;
+      border-bottom: 1px solid #e2e2e2;
+      .leftTitle {
+        font-size: 14px;
+        font-weight: bold;
+        color: #2f4378;
+      }
+      .rightBoxs {
+        display: flex;
+        align-items: center;
+        img {
+          width: 14px;
+          height: 14px;
+          margin-left: 13px;
+          cursor: pointer;
+        }
+      }
+    }
+  }
+  .el-dialog__footer {
+    padding: 0;
+    .dialog-footer {
+      padding: 0px 40px;
+      height: 70px;
+      border-top: 1px solid #e2e2e2;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+    }
+  }
+}
+.imgBox {
+  width: 100%;
+  // height: 210px;
+  border: 1px solid #e2e2e2;
+  border-radius: 8px;
+  padding: 8px 8px 3px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  .imgLabel {
+    flex: 1;
+    width: 100%;
+    border: 1px dotted #e2e2e2;
+    color: #999;
+    font-size: 14px;
+    cursor: pointer;
+    border-radius: 8px;
+    .msPhoto {
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      max-width: 100%;
+      max-height: 270px;
+      img {
+        max-width: 100%;
+        max-height: 270px;
+      }
+    }
+    .imgbbx {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+      width: 100%;
+      height: 100%;
+      i {
+        font-weight: bold;
+        margin: 14px 0;
+        font-size: 24px;
+      }
+    }
+  }
+  p {
+    margin: 5px 0px;
+  }
+}
+</style>

+ 14 - 192
src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/index.vue

@@ -1,207 +1,29 @@
 <template>
   <div id="liveLearningRecord">
-    <search-box-new
-      ref="searchBox"
-      :formData="formData"
-      :formList="formList"
-      @search="search"
-      @init="init"
-      ><template slot="customize">
-        <el-button size="small" type="success" @click="moreActive"
-          >批量导出</el-button
-        >
-      </template></search-box-new
-    >
-    <table-list
-      :tableSets="tableSet"
-      :tableData="tableData"
-      :navText="navText"
-      :loading="loading"
-    >
-      <template slot="btn" slot-scope="props">
-        <el-button type="text" @click="doList(props.scope.row)"
-          >学员观看直播数据</el-button
-        >
-      </template>
-    </table-list>
-    <pagination
-      :total="total"
-      :pageSize="formData.pageSize"
-      :currentPage="formData.pageNum"
-      @handleSizeChange="handleSizeChange"
-      @handleCurrentChange="handleCurrentChange"
-    />
+    <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
+      <el-tab-pane lazy label="课程维度" name="first">
+        <curriculumDimension />
+      </el-tab-pane>
+      <el-tab-pane lazy label="学员维度" name="second">
+        <studentDimension />
+      </el-tab-pane>
+    </el-tabs>
   </div>
 </template>
 
 <script>
-import * as baseUrls from "@/utils/request.js";
-import searchBoxNew from "@/components/searchBoxNew";
-import tableList from "@/components/tableList";
-import pagination from "@/components/pagination";
+import curriculumDimension from "./curriculumDimension.vue";
+import studentDimension from "./studentDimension.vue";
 export default {
-  components: { searchBoxNew, tableList, pagination },
+  components: { curriculumDimension, studentDimension },
   data() {
     return {
-      loading: false, //当前表单加载是否加载动画
-      navText: {
-        title: "学员学习列表",
-        index: 0,
-        ch: "条",
-        num: false,
-        border: true,
-        choice: true,
-        addHide: true,
-        backFatherBtn: {
-          status: false,
-          title: "未定义",
-        },
-      },
-      //搜索
-      formList: [
-        {
-          prop: "searchKey",
-          placeholder: "请输入学员姓名/学员身份证",
-        },
-      ],
-      formData: {
-        pageSize: 10,
-        pageNum: 1,
-      },
-      // 表单
-      tableSet: [
-        {
-          label: "学员姓名",
-          prop: "realname",
-          hidden: true,
-        },
-        {
-          label: "学员身份证",
-          prop: "idCard",
-          hidden: true,
-        },
-        {
-          label: "直播累计时长",
-          prop: "liveTime",
-          hidden: true,
-          scope: "convert",
-        },
-        {
-          label: "观看直播累计时长",
-          prop: "seeTime",
-          hidden: true,
-          scope: "convert",
-        },
-        {
-          label: "课程总直播次数",
-          prop: "totalLiveNum",
-          hidden: true,
-        },
-        {
-          label: "课程已直播次数",
-          prop: "overLiveNum",
-          hidden: true,
-        },
-        {
-          label: "已参加直播次数",
-          prop: "joinLiveNum",
-          hidden: true,
-        },
-      ],
-      tableData: [], //表单数据
-      total: 0, //一共多少条
-      id: "",
+      activeName: "first",
     };
   },
-  mounted() {
-    this.id = this.$route.query.id;
-    this.search();
-  },
-  activated() {
-    this.search();
-  },
   methods: {
-    moreActive() {
-      let arr = JSON.parse(JSON.stringify(this.formData));
-      arr.goodsId = this.id;
-      this.$api.inquireOrderGoodsexport_listLiveGoodsList(arr).then((res) => {
-        if (res.msg) {
-          let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
-          let link = document.createElement("a");
-          let fileName = "导出直播数据" + ".xlsx";
-          document.body.appendChild(link);
-          link.href = url;
-          link.dowmload = fileName;
-          link.click();
-          link.remove();
-          this.$message.success("导出成功");
-        } else {
-          this.$message.error("导出失败");
-        }
-      });
-    },
-    doList(row) {
-      const jump = () => {
-        this.$router.push({
-          path: "watchLiveData",
-          query: {
-            orderGoodsId: row.orderGoodsId,
-            realname: row.realname,
-          },
-        });
-      };
-      const statusPage = this.$store.state.tagsView.visitedViews.some(
-        (item) => {
-          return item.name == "WatchLiveData";
-        }
-      );
-      if (statusPage) {
-        this.$store
-          .dispatch("tagsView/delCachedView", {
-            name: "WatchLiveData",
-          })
-          .then((res) => {
-            jump();
-          });
-      } else {
-        jump();
-      }
-    },
-    search(int) {
-      this.loading = true;
-      if (int === 1) {
-        this.formData.pageNum = 1;
-      }
-      if (int === 2) {
-        this.formData = {
-          pageSize: 10,
-          pageNum: 1,
-        };
-      }
-      var data = JSON.parse(JSON.stringify(this.formData));
-      data.goodsId = this.id;
-      this.$api
-        .inquireOrderGoodsBuyLiveGoodsList(data)
-        .then((res) => {
-          this.tableData = res.rows;
-          this.total = res.total;
-          this.navText.index = res.total;
-        })
-        .finally(() => {
-          this.loading = false;
-        });
-    },
-    init() {
-      this.search(2);
-    },
-    handleSizeChange(v) {
-      this.formData.pageSize = v;
-      this.formData.pageNum = 1;
-      this.search();
-    },
-    handleCurrentChange(v) {
-      this.formData.pageNum = v;
-      this.search();
+    handleClick(tab, event) {
+      console.log(tab, event);
     },
   },
 };

+ 211 - 0
src/views/education/liveLearningManagement/liveLearningRecord/studentStyleList/studentDimension.vue

@@ -0,0 +1,211 @@
+<template>
+  <div id="studentDimension">
+    <search-box-new
+      ref="searchBox"
+      :formData="formData"
+      :formList="formList"
+      @search="search"
+      @init="init"
+      ><template slot="customize">
+        <el-button size="small" type="success" @click="moreActive"
+          >批量导出</el-button
+        >
+      </template></search-box-new
+    >
+    <table-list
+      :tableSets="tableSet"
+      :tableData="tableData"
+      :navText="navText"
+      :loading="loading"
+    >
+      <template slot="btn" slot-scope="props">
+        <el-button type="text" @click="doList(props.scope.row)"
+          >学员观看直播数据</el-button
+        >
+      </template>
+    </table-list>
+    <pagination
+      :total="total"
+      :pageSize="formData.pageSize"
+      :currentPage="formData.pageNum"
+      @handleSizeChange="handleSizeChange"
+      @handleCurrentChange="handleCurrentChange"
+    />
+  </div>
+</template>
+
+<script>
+import * as baseUrls from "@/utils/request.js";
+import searchBoxNew from "@/components/searchBoxNew";
+import tableList from "@/components/tableList";
+import pagination from "@/components/pagination";
+export default {
+    components:{ searchBoxNew, tableList, pagination },
+  data() {
+    return {
+        loading: false, //当前表单加载是否加载动画
+      navText: {
+        title: "学员维度列表",
+        index: 0,
+        ch: "条",
+        num: false,
+        border: true,
+        choice: true,
+        addHide: true,
+        backFatherBtn: {
+          status: false,
+          title: "未定义",
+        },
+      },
+      //搜索
+      formList: [
+        {
+          prop: "searchKey",
+          placeholder: "请输入学员姓名/学员身份证",
+        },
+      ],
+      formData: {
+        pageSize: 10,
+        pageNum: 1,
+      },
+      // 表单
+      tableSet: [
+        {
+          label: "学员姓名",
+          prop: "realname",
+          hidden: true,
+        },
+        {
+          label: "学员身份证",
+          prop: "idCard",
+          hidden: true,
+        },
+        {
+          label: "直播累计时长",
+          prop: "liveTime",
+          hidden: true,
+          scope: "convert",
+        },
+        {
+          label: "观看直播累计时长",
+          prop: "seeTime",
+          hidden: true,
+          scope: "convert",
+        },
+        {
+          label: "课程总直播次数",
+          prop: "totalLiveNum",
+          hidden: true,
+        },
+        {
+          label: "课程已直播次数",
+          prop: "overLiveNum",
+          hidden: true,
+        },
+        {
+          label: "已参加直播次数",
+          prop: "joinLiveNum",
+          hidden: true,
+        },
+      ],
+      tableData: [], //表单数据
+      total: 0, //一共多少条
+      id: "",
+    };
+  },
+  mounted() {
+    this.id = this.$route.query.id;
+    this.search();
+  },
+  activated() {
+    this.search();
+  },
+  methods: {
+    moreActive() {
+      let arr = JSON.parse(JSON.stringify(this.formData));
+      arr.goodsId = this.id;
+      this.$api.inquireOrderGoodsexport_listLiveGoodsList(arr).then((res) => {
+        if (res.msg) {
+          let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
+          let link = document.createElement("a");
+          let fileName = "导出直播数据" + ".xlsx";
+          document.body.appendChild(link);
+          link.href = url;
+          link.dowmload = fileName;
+          link.click();
+          link.remove();
+          this.$message.success("导出成功");
+        } else {
+          this.$message.error("导出失败");
+        }
+      });
+    },
+    doList(row) {
+      const jump = () => {
+        this.$router.push({
+          path: "watchLiveData",
+          query: {
+            orderGoodsId: row.orderGoodsId,
+            realname: row.realname,
+          },
+        });
+      };
+      const statusPage = this.$store.state.tagsView.visitedViews.some(
+        (item) => {
+          return item.name == "WatchLiveData";
+        }
+      );
+      if (statusPage) {
+        this.$store
+          .dispatch("tagsView/delCachedView", {
+            name: "WatchLiveData",
+          })
+          .then((res) => {
+            jump();
+          });
+      } else {
+        jump();
+      }
+    },
+    search(int) {
+      this.loading = true;
+      if (int === 1) {
+        this.formData.pageNum = 1;
+      }
+      if (int === 2) {
+        this.formData = {
+          pageSize: 10,
+          pageNum: 1,
+        };
+      }
+      var data = JSON.parse(JSON.stringify(this.formData));
+      data.goodsId = this.id;
+      this.$api
+        .inquireOrderGoodsBuyLiveGoodsList(data)
+        .then((res) => {
+          this.tableData = res.rows;
+          this.total = res.total;
+          this.navText.index = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    init() {
+      this.search(2);
+    },
+    handleSizeChange(v) {
+      this.formData.pageSize = v;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    handleCurrentChange(v) {
+      this.formData.pageNum = v;
+      this.search();
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+</style>

+ 187 - 1
src/views/education/studentManageMent/studentList/index.vue

@@ -6,7 +6,12 @@
       :formList="formList"
       @search="search"
       @init="init"
-    />
+      ><template slot="customize">
+        <el-button size="small" type="success" @click="exportUserList"
+          >导出</el-button
+        >
+      </template></search-box-new
+    >
     <table-list
       :tableSets="tableSet"
       :tableData="tableData"
@@ -35,6 +40,7 @@
 </template>
 
 <script>
+import * as baseUrls from "@/utils/request.js";
 import searchBoxNew from "@/components/searchBoxNew";
 import tableList from "@/components/tableList";
 import pagination from "@/components/pagination";
@@ -135,6 +141,56 @@ export default {
           prop: "realname",
           placeholder: "请输入学员名称",
         },
+        {
+          prop: "gradeName",
+          placeholder: "请输入所属班级",
+        },
+        {
+          prop: "lastVisitPlat",
+          placeholder: "最近访问终端",
+          scope: "select",
+          options: [
+            {
+              label: "小程序",
+              value: 1,
+            },
+            {
+              label: "PC网站",
+              value: 2,
+            },
+          ],
+        },
+        {
+          prop1: "visitStartTime",
+          prop2: "visitEndTime",
+          placeholder1: "访问开始时间",
+          placeholder2: "访问结束时间",
+          scope: "moreDataPicker",
+          Diszing: true,
+        },
+        {
+          prop: "lastStudyPlat",
+          placeholder: "最近学习终端",
+          scope: "select",
+          options: [
+            {
+              label: "小程序",
+              value: 1,
+            },
+            {
+              label: "PC网站",
+              value: 2,
+            },
+          ],
+        },
+        {
+          prop1: "studyStartTime",
+          prop2: "studyEndTime",
+          placeholder1: "学习开始时间",
+          placeholder2: "学习结束时间",
+          scope: "moreDataPicker",
+          Diszing: true,
+        },
       ],
       formData: {
         status: "0,1",
@@ -204,6 +260,50 @@ export default {
             },
           ],
         },
+        {
+          label: "最近访问终端",
+          prop: "visitFromPlat",
+          hidden: true,
+          scope: "isOptions",
+          options: [
+            {
+              label: "小程序",
+              value: 1,
+            },
+            {
+              label: "PC网站",
+              value: 2,
+            },
+          ],
+        },
+        {
+          label: "最近访问时间",
+          prop: "lastVisitTime",
+          hidden: true,
+          scope: "aTimeList",
+        },
+        {
+          label: "最近学习终端",
+          prop: "studyFromPlat",
+          hidden: true,
+          scope: "isOptions",
+          options: [
+            {
+              label: "小程序",
+              value: 1,
+            },
+            {
+              label: "PC网站",
+              value: 2,
+            },
+          ],
+        },
+        {
+          label: "最近学习时间",
+          prop: "lastStudyTime",
+          hidden: true,
+          scope: "aTimeList",
+        },
         {
           label: "所在公司",
           prop: "companyName",
@@ -264,12 +364,86 @@ export default {
       this.$set(this.formData, "businessId", this.$route.params.businessId);
       this.$refs.searchBox.changeBusinessLevel(this.$route.params.businessId);
     }
+    //学员统计页跳转带参初始化
+    if (this.$route.params.row) {
+      console.log(this.$route.params);
+      let data = JSON.parse(this.$route.params.row);
+      switch (this.$route.params.type) {
+        case 1:
+          //新增学员数
+          let data1 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.startTime = data1;
+          this.formData.endTime = data1 + 86399999;
+          break;
+        case 2:
+          //访问学员总数
+          let data2 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.visitStartTime = data2;
+          this.formData.visitEndTime = data2 + 86399999;
+          break;
+        case 3:
+          //访问小程序学员数
+          let data3 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.visitStartTime = data3;
+          this.formData.visitEndTime = data3 + 86399999;
+          this.formData.lastVisitPlat = 1;
+          break;
+        case 4:
+          //访问PC学员数
+          let data4 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.visitStartTime = data4;
+          this.formData.visitEndTime = data4 + 86399999;
+          this.formData.lastVisitPlat = 2;
+          break;
+        case 5:
+          //学习学员数
+          let data5 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.studyStartTime = data5;
+          this.formData.studyEndTime = data5 + 86399999;
+          break;
+        case 6:
+          //小程序学习学员数
+          let data6 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.studyStartTime = data6;
+          this.formData.studyEndTime = data6 + 86399999;
+          this.formData.lastStudyPlat = 1;
+          break;
+        case 7:
+          //PC学习学员数
+          let data7 = new Date(`${data.date} 00:00:00`).getTime();
+          this.formData.studyStartTime = data7;
+          this.formData.studyEndTime = data7 + 86399999;
+          this.formData.lastStudyPlat = 2;
+          break;
+
+        default:
+          break;
+      }
+    }
     this.search();
   },
   activated() {
     this.search();
   },
   methods: {
+    /**
+     * 导出学员列表
+     */
+    exportUserList() {
+      var data = JSON.parse(JSON.stringify(this.formData));
+      delete data.pageSize;
+      delete data.pageNum;
+      this.$api.inquiregradestudentlistStudentExport(data).then((res) => {
+        let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
+        let link = document.createElement("a");
+        let fileName = "导入模板" + ".xlsx";
+        document.body.appendChild(link);
+        link.href = url;
+        link.dowmload = fileName;
+        link.click();
+        link.remove();
+      });
+    },
     editInfo(v) {
       this.addClick(v, 2);
     },
@@ -293,6 +467,18 @@ export default {
       if (this.formData.endTime) {
         data.endTime = parseInt(data.endTime / 1000);
       }
+      if (this.formData.visitStartTime) {
+        data.visitStartTime = parseInt(data.visitStartTime / 1000);
+      }
+      if (this.formData.visitEndTime) {
+        data.visitEndTime = parseInt(data.visitEndTime / 1000);
+      }
+      if (this.formData.studyStartTime) {
+        data.studyStartTime = parseInt(data.studyStartTime / 1000);
+      }
+      if (this.formData.studyEndTime) {
+        data.studyEndTime = parseInt(data.studyEndTime / 1000);
+      }
       this.$api
         .inquiregradestudentlistStudent(data)
         .then((res) => {

+ 239 - 0
src/views/education/studentManageMent/studentStatistics/index.vue

@@ -0,0 +1,239 @@
+<template>
+  <div id="studentStatistics">
+    <el-form :model="formData" ref="ruleForm" label-width="0px" :inline="true">
+      <el-form-item label="">
+        <el-date-picker
+          v-model="formData.statsStartTime"
+          type="date"
+          value-format="timestamp"
+          :size="size"
+          placeholder="开始时间"
+        >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="">
+        <el-date-picker
+          v-model="formData.statsEndTime"
+          type="date"
+          value-format="timestamp"
+          :size="size"
+          placeholder="结束时间"
+        >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button :size="size" type="primary" @click="search">查询</el-button
+        ><el-button size="small" type="success" @click="exportUserList"
+          >导出</el-button
+        >
+      </el-form-item> </el-form
+    ><el-table
+      v-loading="loading"
+      ref="multipleTable"
+      :data="tableData"
+      border
+      :header-cell-style="{
+        'background-color': '#eee',
+        padding: '8px',
+        color: '#333',
+      }"
+    >
+      <template v-for="(item, index) in tableList">
+        <el-table-column
+          v-if="item.scope !== 'inputs'"
+          :width="item.width"
+          :key="index"
+          :label="item.label"
+          align="center"
+          :show-overflow-tooltip="true"
+          header-align="center"
+        >
+          <template slot-scope="scope">
+            <span v-if="item.scope === 'time'">{{
+              $methodsTools.onlyForma(scope.row[item.prop], false)
+            }}</span
+            ><span
+              class="click_style"
+              v-else-if="item.scope === 'click'"
+              @click="jumpPage(scope.row, item.type)"
+              >{{ scope.row[item.prop] }}</span
+            >
+            <span v-else>{{ scope.row[item.prop] }}</span></template
+          >
+        </el-table-column></template
+      >
+    </el-table>
+  </div>
+</template>
+
+<script>
+import * as baseUrls from "@/utils/request.js";
+import pagination from "@/components/pagination";
+export default {
+  name: "StudentStatistics",
+  components: {
+    pagination,
+  },
+  data() {
+    return {
+      loading: false,
+      size: "small",
+      tableData: [],
+      tableList: [
+        {
+          label: "日期",
+          prop: "date",
+          width: "180px",
+        },
+        {
+          label: "学员总数",
+          prop: "allNum",
+        },
+        {
+          label: "新增学员数",
+          prop: "addNum",
+          scope: "click",
+          type: 1,
+        },
+        {
+          label: "访问学员总数",
+          prop: "visitAllNum",
+          scope: "click",
+          type: 2,
+        },
+        {
+          label: "访问小程序学员数",
+          prop: "visitSmallNum",
+          scope: "click",
+          type: 3,
+        },
+        {
+          label: "访问PC学员数",
+          prop: "visitPcNum",
+          scope: "click",
+          type: 4,
+        },
+        {
+          label: "学习学员数",
+          prop: "studyAllNum",
+          scope: "click",
+          type: 5,
+        },
+        {
+          label: "小程序学习学员数",
+          prop: "studySmallNum",
+          scope: "click",
+          type: 6,
+        },
+        {
+          label: "PC学习学员数",
+          prop: "studyPcNum",
+          scope: "click",
+          type: 7,
+        },
+      ],
+      formData: {
+        userId: this.$route.query.id,
+      },
+    };
+  },
+  mounted() {
+    //默认7天时间范围
+    this.formData = {
+      statsStartTime:
+        new Date(new Date().toLocaleDateString()).getTime() - 604800000,
+      statsEndTime: new Date(new Date().toLocaleDateString()).getTime(),
+    };
+    this.search();
+  },
+  methods: {
+    /**
+     * 导出学员列表
+     */
+    exportUserList() {
+      if (!this.formData.statsStartTime || !this.formData.statsEndTime) {
+        this.$message.error("请选择开始时间与结束时间");
+        return;
+      }
+      var data = JSON.parse(JSON.stringify(this.formData));
+      if (this.formData.statsStartTime) {
+        data.statsStartTime = parseInt(data.statsStartTime / 1000);
+      }
+      if (this.formData.statsEndTime) {
+        data.statsEndTime = parseInt(data.statsEndTime / 1000);
+      }
+      this.$api.exportstudystats_list(data).then((res) => {
+        let url = baseUrls.baseURL + "common/download?fileName=" + res.msg;
+        let link = document.createElement("a");
+        let fileName = "导入模板" + ".xlsx";
+        document.body.appendChild(link);
+        link.href = url;
+        link.dowmload = fileName;
+        link.click();
+        link.remove();
+      });
+    },
+    /**
+     * 跳转页面
+     */
+    jumpPage(row, type) {
+      const jump = () => {
+        //学员详情
+        this.$router.push({
+          name: "StudentList",
+          params: {
+            row: JSON.stringify(row),
+            type: type,
+          },
+        });
+      };
+      const statusPage = this.$store.state.tagsView.visitedViews.some(
+        (item) => {
+          return item.name == "StudentList";
+        }
+      );
+      if (statusPage) {
+        this.$store
+          .dispatch("tagsView/delCachedView", {
+            name: "StudentList",
+          })
+          .then((res) => {
+            jump();
+          });
+      } else {
+        jump();
+      }
+    },
+    search() {
+      if (!this.formData.statsStartTime || !this.formData.statsEndTime) {
+        this.$message.error("请选择开始时间与结束时间");
+        return;
+      }
+      this.loading = true;
+      var data = JSON.parse(JSON.stringify(this.formData));
+      if (this.formData.statsStartTime) {
+        data.statsStartTime = parseInt(data.statsStartTime / 1000);
+      }
+      if (this.formData.statsEndTime) {
+        data.statsEndTime = parseInt(data.statsEndTime / 1000);
+      }
+      this.$api
+        .inquirestudystats_list(data)
+        .then((res) => {
+          this.tableData = res.data;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.click_style {
+  cursor: pointer;
+  user-select: none;
+  text-decoration: underline;
+}
+</style>

+ 188 - 0
src/views/education/studentManageMent/studentXQ/accesslog.vue

@@ -0,0 +1,188 @@
+<template>
+  <div id="accesslog">
+    <div class="studentSty">
+      <el-form
+        :model="formData"
+        ref="ruleForm"
+        label-width="0px"
+        :inline="true"
+      >
+        <el-form-item label="">
+          <el-select v-model="value" placeholder="请选择" :size="size">
+            <el-option label="访问终端" :value="1"> </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="">
+          <el-date-picker
+            v-model="formData.startTime"
+            type="datetime"
+            value-format="timestamp"
+            :size="size"
+            placeholder="最近访问时间(开始时间)"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="">
+          <el-date-picker
+            v-model="formData.endTime"
+            type="datetime"
+            value-format="timestamp"
+            :size="size"
+            placeholder="最近访问时间(结束时间)"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button :size="size" type="primary" @click="search"
+            >查询</el-button
+          >
+          <el-button :size="size" @click="clearFunc">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table
+        ref="multipleTable"
+        :data="tableData"
+        border
+        :header-cell-style="{
+          'background-color': '#eee',
+          padding: '8px',
+          color: '#333',
+        }"
+      >
+        <el-table-column type="index" width="80" label="序号" align="center">
+        </el-table-column>
+        <template v-for="(item, index) in tableList">
+          <el-table-column
+            v-if="item.scope !== 'inputs'"
+            :width="item.width"
+            :key="index"
+            :label="item.label"
+            align="center"
+            :show-overflow-tooltip="true"
+            header-align="center"
+          >
+            <template slot-scope="scope">
+              <span v-if="item.scope === 'fromPlatType'">
+                {{
+                  scope.row[item.prop] === 1
+                    ? "小程序"
+                    : scope.row[item.prop] === 2
+                    ? "PC网站"
+                    : "未知"
+                }}
+              </span>
+              <span v-else-if="item.scope === 'time'">{{
+                $methodsTools.onlyForma(scope.row[item.prop])
+              }}</span>
+              <span v-else>{{ scope.row[item.prop] }}</span></template
+            >
+          </el-table-column></template
+        >
+      </el-table>
+      <pagination
+        :total="total"
+        :pageSize="formData.pageSize"
+        :currentPage="formData.pageNum"
+        @handleSizeChange="handleSizeChange"
+        @handleCurrentChange="handleCurrentChange"
+      />
+      <div class="align_center">
+        <el-button @click="backPage">返回</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import pagination from "@/components/pagination";
+export default {
+  components: { pagination },
+  data() {
+    return {
+      value: 1,
+      size: "small",
+      tableData: [],
+      tableList: [
+        {
+          label: "访问终端",
+          prop: "fromPlat",
+          scope: "fromPlatType",
+        },
+        {
+          label: "访问时间",
+          prop: "createTime",
+          scope: "time",
+          width: "180px",
+        },
+      ],
+      total: 0,
+      formData: {
+        userId: this.$route.query.id,
+        pageSize: 10,
+        pageNum: 1,
+      },
+    };
+  },
+  mounted() {
+    this.search();
+  },
+  methods: {
+    clearFunc() {
+      this.formData.startTime = "";
+      this.formData.endTime = "";
+      this.formData.pageSize = 10;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    search() {
+      this.loading = true;
+      var data = JSON.parse(JSON.stringify(this.formData));
+      if (this.formData.startTime) {
+        data.startTime = parseInt(data.startTime / 1000);
+      }
+      if (this.formData.endTime) {
+        data.endTime = parseInt(data.endTime / 1000);
+      }
+      this.$api
+        .inquireUserVisitloglist(data)
+        .then((res) => {
+          this.tableData = res.rows;
+          this.total = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    handleSizeChange(v) {
+      this.formData.pageSize = v;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    handleCurrentChange(v) {
+      this.formData.pageNum = v;
+      this.search();
+    },
+    //返回
+    backPage() {
+      this.$store.dispatch("tagsView/delView", this.$route).then((res) => {
+        // this.$router.push({
+        //   path: "StudentList",
+        // });
+        this.$router.go(-1);
+      });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.studentSty {
+  // background-color: #eee;
+  padding: 20px 10px;
+  margin-top: 16px;
+}
+.align_center {
+  margin-top: 20px;
+  text-align: center;
+}
+</style>

+ 10 - 0
src/views/education/studentManageMent/studentXQ/index.vue

@@ -16,6 +16,12 @@
       <el-tab-pane label="直播-学习记录" name="liveRecode"
         ><live-list
       /></el-tab-pane>
+      <el-tab-pane label="访问日志" name="accesslog"
+        ><access-log
+      /></el-tab-pane>
+      <el-tab-pane label="学习日志" name="studylog"
+        ><study-log
+      /></el-tab-pane>
     </el-tabs>
   </div>
 </template>
@@ -26,6 +32,8 @@ import classRecord from "./classRecord.vue";
 import studentBaseManage from "./studentBaseManage.vue";
 import studyRecord from "./studyRecord.vue";
 import liveList from "./liveList.vue";
+import accessLog from "./accesslog.vue";
+import studyLog from "./studylog.vue";
 export default {
   name: "StudentXQ",
   components: {
@@ -34,6 +42,8 @@ export default {
     studentBaseManage,
     studyRecord,
     liveList,
+    accessLog,
+    studyLog
   },
   data() {
     return {

+ 206 - 0
src/views/education/studentManageMent/studentXQ/studylog.vue

@@ -0,0 +1,206 @@
+<template>
+  <div id="studylog">
+    <div class="studentSty">
+      <el-form
+        :model="formData"
+        ref="ruleForm"
+        label-width="0px"
+        :inline="true"
+      >
+        <el-form-item label="">
+          <el-select v-model="value" placeholder="请选择" :size="size">
+            <el-option label="学习终端" :value="1"> </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="">
+          <el-date-picker
+            v-model="formData.startTime"
+            type="datetime"
+            value-format="timestamp"
+            :size="size"
+            placeholder="最近学习时间(开始时间)"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="">
+          <el-date-picker
+            v-model="formData.endTime"
+            type="datetime"
+            value-format="timestamp"
+            :size="size"
+            placeholder="最近学习时间(结束时间)"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item>
+          <el-button :size="size" type="primary" @click="search"
+            >查询</el-button
+          >
+          <el-button :size="size" @click="clearFunc">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table
+        ref="multipleTable"
+        :data="tableData"
+        border
+        :header-cell-style="{
+          'background-color': '#eee',
+          padding: '8px',
+          color: '#333',
+        }"
+      >
+        <el-table-column type="index" width="80" label="序号" align="center">
+        </el-table-column>
+        <template v-for="(item, index) in tableList">
+          <el-table-column
+            v-if="item.scope !== 'inputs'"
+            :width="item.width"
+            :key="index"
+            :label="item.label"
+            align="center"
+            :show-overflow-tooltip="true"
+            header-align="center"
+          >
+            <template slot-scope="scope">
+              <span v-if="item.scope === 'fromPlatType'">
+                {{
+                  scope.row[item.prop] === 1
+                    ? "小程序"
+                    : scope.row[item.prop] === 2
+                    ? "PC网站"
+                    : "未知"
+                }}
+              </span>
+              <span v-else-if="item.scope === 'goodsType'">
+                <template v-for="(itemt, indext) in $methodsTools.getGoodsType">
+                  <span
+                    :key="indext"
+                    v-if="itemt.value === scope.row[item.prop]"
+                    >{{ itemt.label }}</span
+                  >
+                </template>
+              </span>
+              <span v-else-if="item.scope === 'time'">{{
+                $methodsTools.onlyForma(scope.row[item.prop])
+              }}</span>
+              <span v-else>{{ scope.row[item.prop] }}</span></template
+            >
+          </el-table-column></template
+        >
+      </el-table>
+      <pagination
+        :total="total"
+        :pageSize="formData.pageSize"
+        :currentPage="formData.pageNum"
+        @handleSizeChange="handleSizeChange"
+        @handleCurrentChange="handleCurrentChange"
+      />
+      <div class="align_center">
+        <el-button @click="backPage">返回</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import pagination from "@/components/pagination";
+export default {
+  components: { pagination },
+  data() {
+    return {
+      value: 1,
+      size: "small",
+      tableData: [],
+      tableList: [
+        {
+          label: "商品课程名称",
+          prop: "goodsName",
+        },
+        {
+          label: "商品课程类型",
+          prop: "goodsType",
+          scope: "goodsType",
+        },
+        {
+          label: "学习终端",
+          prop: "fromPlat",
+          scope: "fromPlatType",
+        },
+        {
+          label: "学习时间",
+          prop: "createTime",
+          scope: "time",
+          width: "180px",
+        },
+      ],
+      total: 0,
+      formData: {
+        userId: this.$route.query.id,
+        pageSize: 10,
+        pageNum: 1,
+      },
+    };
+  },
+  mounted() {
+    this.search();
+  },
+  methods: {
+    clearFunc() {
+      this.formData.startTime = "";
+      this.formData.endTime = "";
+      this.formData.pageSize = 10;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    search() {
+      this.loading = true;
+      var data = JSON.parse(JSON.stringify(this.formData));
+      if (this.formData.startTime) {
+        data.startTime = parseInt(data.startTime / 1000);
+      }
+      if (this.formData.endTime) {
+        data.endTime = parseInt(data.endTime / 1000);
+      }
+      this.$api
+        .inquireUserStudyloglist(data)
+        .then((res) => {
+          this.tableData = res.rows;
+          this.total = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    handleSizeChange(v) {
+      this.formData.pageSize = v;
+      this.formData.pageNum = 1;
+      this.search();
+    },
+    handleCurrentChange(v) {
+      this.formData.pageNum = v;
+      this.search();
+    },
+    //返回
+    backPage() {
+      this.$store.dispatch("tagsView/delView", this.$route).then((res) => {
+        // this.$router.push({
+        //   path: "StudentList",
+        // });
+        this.$router.go(-1);
+      });
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.studentSty {
+  // background-color: #eee;
+  padding: 20px 10px;
+  margin-top: 16px;
+}
+.align_center {
+  margin-top: 20px;
+  text-align: center;
+}
+</style>