qq 3 年 前
コミット
e4ec8f0d09

+ 27 - 3
src/assets/icon-font/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2502459 */
-  src: url('iconfont.woff2?t=1624428802718') format('woff2'),
-       url('iconfont.woff?t=1624428802718') format('woff'),
-       url('iconfont.ttf?t=1624428802718') format('truetype');
+  src: url('iconfont.woff2?t=1637225920088') format('woff2'),
+       url('iconfont.woff?t=1637225920088') format('woff'),
+       url('iconfont.ttf?t=1637225920088') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,30 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icondengpao1:before {
+  content: "\e62d";
+}
+
+.iconcuotiku:before {
+  content: "\e61a";
+}
+
+.iconcuotiben:before {
+  content: "\e60f";
+}
+
+.icontuisong:before {
+  content: "\e61d";
+}
+
+.iconkinds:before {
+  content: "\e60d";
+}
+
+.iconguanbi:before {
+  content: "\e607";
+}
+
 .iconquanping:before {
   content: "\e637";
 }

ファイルの差分が大きいため隠しています
+ 1 - 1
src/assets/icon-font/iconfont.js


+ 42 - 0
src/assets/icon-font/iconfont.json

@@ -6,6 +6,48 @@
   "description": "",
   "glyphs": [
     {
+      "icon_id": "1666825",
+      "name": "灯泡",
+      "font_class": "dengpao1",
+      "unicode": "e62d",
+      "unicode_decimal": 58925
+    },
+    {
+      "icon_id": "1025411",
+      "name": "错题库",
+      "font_class": "cuotiku",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "10048757",
+      "name": "错题本",
+      "font_class": "cuotiben",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "12295434",
+      "name": "推送",
+      "font_class": "tuisong",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "1127375",
+      "name": "分类",
+      "font_class": "kinds",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "18260369",
+      "name": "关闭",
+      "font_class": "guanbi",
+      "unicode": "e607",
+      "unicode_decimal": 58887
+    },
+    {
       "icon_id": "11229054",
       "name": "全屏",
       "font_class": "quanping",

BIN
src/assets/icon-font/iconfont.ttf


BIN
src/assets/icon-font/iconfont.woff


BIN
src/assets/icon-font/iconfont.woff2


+ 3 - 1
src/components/assembly/head.vue

@@ -59,11 +59,13 @@ export default {
     };
   },
   created() {
-    if(JSON.parse(localStorage.getItem('user_info'))){
+    if(localStorage.getItem("is_user") != 1){
         this.info = JSON.parse(localStorage.getItem('user_info')) 
+        console.log(this.info)
     }else{
       account().then(res =>{
        if(res.errcode==0){
+         localStorage.setItem('is_user',2)
          localStorage.setItem('user_info', JSON.stringify(res.data)) 
           this.info = JSON.parse(localStorage.getItem('user_info')) 
        }

+ 0 - 1
src/components/customer/capital.vue

@@ -186,7 +186,6 @@
       </div>
     </div>
     <!-- <foot></foot> -->
-    
   </div>
 </template>
 <script>

+ 7 - 5
src/components/customer/myClass.vue

@@ -96,7 +96,7 @@ export default {
       params: {
         page: 1,
         size: 10,
-        cid:1,
+        cid:'',
       },
       tableData: [],
       classL: [],
@@ -105,16 +105,18 @@ export default {
     };
   },
   created() {
-    var thta = this;
+    var that = this;
     this.navKey = localStorage.getItem('navKey');
     //班级
     classes().then((res) => {
-      console.log(res)
+      console.log(res.data[0])
       if (res.errcode == 0) {
-        thta.classL = res.data;
+        that.classL = res.data;
+        that.params.cid = res.total>0?res.data[0].id:'';
+        that.getList();
       }
     });
-    this.getList();
+
   },
   methods: {
       navKeys(i){

+ 470 - 0
src/components/customer/per_err.vue

@@ -0,0 +1,470 @@
+<template>
+  <div class="page scroll-x">
+    <topHead></topHead>
+    <topNav></topNav>
+    <div class="container d-f">
+      <div class="leftMenu">
+        <li @click="jump('/topic')">
+          <i class="iconfont iconcuotiku"></i>
+          <span>班级错题</span>
+          <i class="iconfont iconcuotiku"></i>
+           <span></span>
+        </li>
+        <li  class="active" @click="jump('/student_err')">
+          <i class="iconfont iconcuotiben"></i> <span>学生错题</span>
+        </li>
+        <li @click="jump('/push_err')">
+          <i class="iconfont icontuisong"></i><span>错题推送</span>
+        </li>
+      </div>
+      <div class="rightContent">
+        <div class="recordTitle">
+          <span>错题中心> </span>
+          <span>学生错题></span>
+          <span>{{name}}</span>
+        </div>
+        <div class="d-f screen screen1">
+          <span>来源:</span>
+          <el-select
+            clearable
+            placeholder="请选择"
+            v-model="source"
+            @change="sourceList"
+          >
+            <el-option value="exam" label="考试"></el-option>
+            <el-option value="work" label="作业"></el-option>
+          </el-select>
+          <el-select
+            v-model="params.tid"
+            clearable
+            placeholder="请选择"
+            style="width: 150px; margin-left: 5px"
+          >
+            <el-option v-for="item,i in sour_list" :key="i+'j'" :label='item.name' :value="item.id"></el-option>
+          </el-select>
+          <el-button @click="search">搜索</el-button>
+        </div>
+        <div class="error_coll">
+          <li class="d-f j-s" v-for="item,i in tableData" :key="i+'a'">
+            <div>
+              <div class="t_img">
+                <div class="stem">
+                  {{item.qid}}. {{item.stem}}
+                </div>
+                <div class="d-f j-s">
+                  <span>来源:{{item.task_type=='work'?'作业':'考试'}}-{{item.task_name}}</span>
+                  <span>答案: <span class="bold">{{item.answer}}</span> </span>
+                  <span @click="is_answer = true">
+                    <i class="iconfont icondengpao1"></i> 答案解析</span
+                  >
+                </div>
+              </div>
+              <div class="d-f j-s probability">
+                <div>错误率:{{item.error_ratio}}</div>
+                <div class="d-f j-s">
+                  <span>总人数:{{item.student_count}}</span>
+                  <span>错误/正确人数:{{item.error_count}}/{{item.right_count}}</span>
+                </div>
+              </div>
+            </div>
+            <div
+              class="roseChart"
+              :style="{
+                width: '240px',
+                height: '180px',
+              }"
+            ></div>
+          </li>
+        </div>
+        <div class="none" v-if="tableData.length == 0">
+          <div>
+            <img src="../../assets/none.png" alt="" />
+          </div>
+          <div>暂无数据</div>
+        </div>
+        <div class="d-f j-s pagePagin" v-if="total > 0">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="total"
+            :page-size="params.size"
+            :current-page="params.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 答案解析 -->
+    <div class="fit" v-if="is_answer">
+      <div>
+        <div class="titl">答案解析</div>
+        <div class="del el-icon-close" @click="is_answer = false"></div>
+        <div>
+          <div class="analysis">{{tableData[index].analysis}}</div>
+        </div>
+      </div>
+    </div>
+    <!-- <foot></foot> -->
+  </div>
+</template>
+<script>
+import topNav from "@/components/assembly/topnav";
+import topHead from "@/components/assembly/head";
+import foot from "@/components/assembly/foot";
+import { tasks,stuErrPer} from "@/util/api";
+export default {
+  data() {
+    return {
+      params: {
+        page: 1,
+        size: 10,
+        cid:'',
+        sid:'',
+        tid:'',
+      },
+      index:0,
+      tableData: [],
+      total: 0,
+      is_show: false,
+      is_answer: false,
+       source: "", //来源
+      sour_list: [],
+      name:"",
+    };
+  },
+  created() {
+    this.name = this.$route.query.name;
+    this.params.cid = this.$route.query.cid;
+    this.params.sid = this.$route.query.sid;
+    this.getList();
+  },
+  mounted() {
+    var that = this;
+    this.$nextTick(function () {
+      //这里写方法
+      that.drawRose();
+    });
+  },
+  watch: {
+    tableData: function () {
+      //tableData为需要监听的data
+      var that = this;
+      this.$nextTick(function () {
+        //这里写方法
+        that.drawRose();
+      });
+    },
+  },
+  methods: {
+    //来源
+    sourceList(val) {
+      var that = this,
+        obj = {};
+      this.params.tid='';
+      obj.mtype = val;
+      tasks(obj).then((res) => {
+        if (res.errcode == 0) {
+          that.sour_list = res.data;
+        }
+      });
+    },
+    drawRose() {
+      var roseCharts = document.getElementsByClassName("roseChart");
+      console.log(roseCharts);
+      var index = 0;
+      for (var i = 0; i < this.tableData.length; i++) {
+        index = i;
+        var xdata = [];
+        var ydata = [];
+      var maxNum = '';
+      if(this.tableData[i].dist.length<0){
+        return
+      }
+      for (var j = 0; j < this.tableData[i].dist.length; j++) {
+        xdata.push(this.tableData[i].dist[j].key);
+        ydata.push(this.tableData[i].dist[j].val);
+      }
+      maxNum = Math.max(...ydata);
+      for (var q = 0; q < ydata.length; q++) {
+        ydata[q] = {
+          value: ydata[q],
+          itemStyle: {
+            color: ydata[q] >= 75 ? "#39D095" : "#508CEE",
+          },
+        };
+      }
+      var itemChart = this.$echarts.init(roseCharts[index]);
+      var itemChart = this.$echarts.init(roseCharts[0]);
+      // console.log(itemChart);
+      console.log(itemChart);
+      // 绘制图表
+      itemChart.setOption({
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            // 坐标轴指示器,坐标轴触发有效
+            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
+          },
+        },
+        grid: {
+          left: "0%",
+          right: "0%",
+          bottom: "0%",
+          containLabel: true,
+          height: 170,
+        },
+        xAxis: [
+          {
+            type: "category",
+            data: ["A", "B", "C", "D"],
+            axisTick: {
+              alignWithLabel: true,
+            },
+            axisLine: {
+              lineStyle: {
+                color: "#D9D9D9",
+              },
+            },
+            axisLabel: {
+              //x轴文字的配置
+              show: true,
+              textStyle: {
+                color: "#999",
+                fontSize: 13,
+                // align: "right",
+              },
+            },
+            axisTick: {
+              show: false,
+            },
+          },
+        ],
+        yAxis: [
+          {
+            type: "value",
+            axisLabel: {
+              formatter: "{value}",
+              textStyle: {
+                color: "#999",
+              },
+            },
+            max: maxNum,
+            min: 0,
+            interval: 25,
+            splitLine: {
+              show: true,
+              lineStyle: {
+                type: "dashed",
+                color: "#D9D9D9",
+              },
+            },
+            axisTick: {
+              //y轴刻度线
+              show: false,
+            },
+            axisLine: {
+              //y轴
+              show: false,
+            },
+            axisLabel: {
+              //x轴文字的配置
+              show: true,
+              margin: 40,
+              textStyle: {
+                color: "#999",
+                fontSize: 13,
+                align: "left",
+              },
+            },
+          },
+        ],
+        series: [
+          {
+            name: "学生人数",
+            type: "bar",
+            barWidth: "20",
+            itemStyle: {
+              normal: {
+                color: function (params) {
+                  //注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
+                  var colorList = [];
+                  if (params.value < 26) {
+                    colorList.push("#508CEE");
+                  } else if (25 < params.value && params.value < 51) {
+                    colorList.push("#1FDA9A");
+                  } else {
+                    colorList.push("#FA0A2F");
+                  }
+                  return colorList;
+                },
+              },
+            },
+            data: [20, 50, 70, 40],
+          },
+        ],
+      });
+      }
+    },
+    //搜索
+    search() {
+      this.params.page = 1;
+      this.getList();
+    },
+    //分页
+    handleCurrentChange(val) {
+      this.params.page = val;
+      this.getList();
+    },
+    //获取列表
+    getList() {
+      const load = this.$loading({
+        lock: true,
+        text: "Loading",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      var that = this;
+      var par = '/'+this.params.cid+'/'+this.params.sid+'?page='+this.params.page+'&size='+this.params.size;
+      if(this.params.tid){
+         par = par+'&tid='+this.params.tid;
+      }
+      
+      stuErrPer(par).then((res) => {
+        if (res.errcode == 0) {
+          that.tableData = res.data?res.data:[];
+          console.log(that.tableData)
+          that.total = res.total;
+          //关闭loading
+            load.close();
+        }
+      });
+    },
+    jump(url) {
+        this.$router.push(url);
+    },
+  },
+  components: { topHead, topNav, foot },
+};
+</script>
+<style scoped>
+.container {
+  background: #f4f4f4;
+  margin-top: 30px;
+}
+.error_coll li {
+  background: #ffff;
+  margin: 10px 0;
+  height: 222px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+.error_coll li > div {
+  width: 635px;
+}
+.error_coll .probability {
+  font-size: 13px;
+  color: #999999;
+}
+.error_coll .probability > div:first-child {
+  color: #fa0a2f;
+}
+.error_coll .probability > div:last-child {
+  width: 35%;
+}
+.error_coll .t_img {
+  border-bottom: 1px solid #ededed;
+  padding-bottom: 10px;
+  margin-bottom: 10px;
+  color: #999999;
+  font-size: 13px;
+}
+.error_coll .t_img > div > span:last-child {
+  color: #52c4ff;
+  cursor: pointer;
+}
+.error_coll .t_img .bold {
+  font-weight: bold;
+}
+.error_coll .t_img img {
+  width: 100%;
+  height: 122px;
+}
+.error_coll .t_img .stem{
+  font-size: 14px;
+  color: #333;
+  height: 130px;
+}
+.recordTitle {
+  font-size: 13px;
+  color: #cccccc;
+  margin: 0 0 15px 0;
+}
+.recordTitle span:last-child {
+  color: #666;
+}
+.screen {
+  margin-top: 0;
+  background: #fff;
+  padding: 15px 5px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  position: relative;
+}
+.screen span {
+  margin-left: 10px;
+}
+.leftMenu {
+  width: 230px;
+  padding: 10px 0;
+  background-color: #fff;
+  height: 176px;
+}
+.leftMenu i {
+  /* width: 14px;
+  height: 14px;*/
+  /* vertical-align: middle;  */
+  display: inline-block;
+  margin-left: 24px;
+  margin-right: 16px;
+}
+.leftMenu li {
+  height: 44px;
+  line-height: 44px;
+  width: 100%;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+  border-left: 2px solid #fff;
+  box-sizing: border-box;
+}
+.leftMenu li.active {
+  background: #ffe8ec;
+  border-left: 2px solid #fa0a2f;
+  color: #fa0a2f;
+}
+.pagePagin .el-pagination {
+  margin-left: auto;
+}
+</style>
+<style>
+.screen1 .el-select {
+  width: 120px;
+}
+.cap_table .el-progress-bar {
+  padding-right: 0;
+}
+.cap_table .el-progress__text {
+  display: none;
+}
+.none {
+  color: #999;
+  text-align: center;
+  margin: 0 0 60px 0;
+}
+.none div:nth-child(1) {
+  width: 416px;
+  height: 276px;
+  margin: 0 auto 40px auto;
+}
+</style>

+ 514 - 0
src/components/customer/push_err.vue

@@ -0,0 +1,514 @@
+<template>
+  <div class="page scroll-x">
+    <topHead></topHead>
+    <topNav></topNav>
+    <div class="container d-f">
+      <div class="leftMenu">
+        <li @click="jump('/topic')">
+          <i class="iconfont iconbanji"></i>
+          <span>班级错题</span>
+        </li>
+        <li @click="jump('student_err')">
+          <i class="iconfont iconyuejuan"></i> <span>学生错题</span>
+        </li>
+        <li class="active">
+          <i class="iconfont iconzuoye1"></i><span>错题推送</span>
+        </li>
+      </div>
+      <div class="rightContent">
+        <div class="recordTitle">
+          <span>错题中心 > </span>
+          <span>错题推送</span>
+        </div>
+        <div class="d-f screen screen1">
+          <span>班级:</span>
+          <el-select
+            @change="classC"
+            v-model="params.cid"
+            clearable
+            placeholder="请选择"
+          >
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in classL"
+              :key="item.name"
+            ></el-option>
+          </el-select>
+          <span>来源:</span>
+          <el-select
+            clearable
+            placeholder="请选择"
+            v-model="source"
+            @change="sourceList"
+          >
+            <el-option value="exam" label="考试"></el-option>
+            <el-option value="work" label="作业"></el-option>
+          </el-select>
+          <el-select
+            v-model="params.tid"
+            clearable
+            placeholder="请选择"
+            style="width: 150px; margin-left: 5px"
+          >
+            <el-option v-for="item,i in sour_list" :key="i+'j'" :label='item.name' :value="item.id"></el-option>
+          </el-select>
+          <el-button @click="search">搜索</el-button>
+          <div class="promotion" @click="is_show=true">
+            <span class="el-icon-s-promotion"></span> 推送错题
+          </div>
+        </div>
+        <div class="d-f j-s table_head">
+          <li>姓名</li>
+          <li>推送人数</li>
+          <li>错题来源</li>
+          <li>考试错题</li>
+          <li>是否打印</li>
+          <li>推送时间</li>
+          <li>操作</li>
+        </div>
+        <div class="none" v-if="tableData.length == 0">
+          <div>
+            <img src="../../assets/none.png" alt="" />
+          </div>
+          <div>暂无数据</div>
+        </div>
+        <div
+          v-else
+          class="cap_table"
+          :style="{ minHeight: Common.clientHeight - 400 + 'px' }"
+        >
+          <li v-for="(item, i) in 3" :key="i" class="d-f j-s">
+            <div>高一一班</div>
+            <div>100/50</div>
+            <div>90</div>
+            <div>20</div>
+            <div>已打印</div>
+            <div>2020-10-23 12:25:36</div>
+            <div>
+              <span @click="jump('/see_pusherr')">查看</span>
+              <span>编辑</span>
+              <span>删除</span>
+            </div>
+          </li>
+        </div>
+        <div class="d-f j-s pagePagin" v-if="total > 0">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="total"
+            :page-size="params.size"
+            :current-page="params.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 推送错题 -->
+    <div class="fit" v-show="is_show">
+       <div>
+          <div class="tit">错题推送</div>
+           <div class="form_box">
+          <div>
+            <span>班级</span>
+            <el-select
+              @change="classC"
+              v-model="params.cid"
+              clearable
+              placeholder="请选择"
+              style="width: 325px"
+            >
+              <el-option
+                :label="item.name"
+                :value="item.id"
+                v-for="item in classL"
+                :key="item.name"
+              ></el-option>
+            </el-select>
+          </div>
+          <div>
+            <span>来源</span>
+            <el-select
+              clearable
+              placeholder="请选择"
+              v-model="source"
+              style="width: 100px"
+              @change="sourceList"
+            >
+                       <el-option value="exam" label="考试"></el-option>
+            <el-option value="work" label="作业"></el-option>
+            </el-select>
+            <el-select
+              v-model="params.ly2"
+              clearable
+              placeholder="请选择"
+              style="width: 220px; margin-left: 5px"
+            >
+              <el-option v-for="item,i in sour_list" :key="i+'j'" :label='item.name' :value="item.id"></el-option>
+            </el-select>
+          </div>
+          <div>
+            <span>学生</span>
+            <div class="transfer_box">
+               <el-transfer
+    filterable
+    :filter-method="filterMethod"
+    filter-placeholder="请输入"
+    v-model="value"
+    :data="data">
+  </el-transfer>
+            </div>
+          </div>
+          <div>
+            <span>备注</span>
+            <el-input
+              style="width: 325px"
+              v-model="params.l"
+              placeholder="请输入"
+            ></el-input>
+          </div>
+        </div>
+         <div class="btn">
+          <el-button @click="is_show = false">取消</el-button>
+          <el-button type="primary" @click="is_show = false">确认</el-button>
+        </div>
+       </div>
+    </div>
+    <!-- <foot></foot> -->
+  </div>
+</template>
+<script>
+import topNav from "@/components/assembly/topnav";
+import topHead from "@/components/assembly/head";
+import foot from "@/components/assembly/foot";
+import { searchClass, classes ,tasks} from "@/util/api";
+export default {
+  data() {
+    return {
+      params: {
+        page: 1,
+        size: 10,
+        cid: "",
+        tid:'',
+      },
+        source: "", //来源
+      sour_list: [],
+      is_show:false,
+      tableData: [],
+      classL: [],
+      total: 0,
+      value:'',
+      filterMethod(query, item) {
+          return item.pinyin.indexOf(query) > -1;
+        },
+      data:[],
+    };
+  },
+  created() {
+    var that = this;
+    //班级
+    classes().then((res) => {
+      if (res.errcode == 0) {
+        that.classL = res.data;
+        that.params.cid = res.total > 0 ? res.data[0].id : "";
+        that.getList();
+        searchClass({cid:that.params.cid}).then(res=>{
+          if(res.errcode==0){
+            var l = [];
+            res.data.forEach(item => {
+              var obj = {};
+              obj.key = item.id;
+              obj.label = item.name;
+              l.push(obj)
+            });
+            that.data = l;
+            console.log(that.data)
+          }
+        })
+      }
+    });
+  },
+  methods: {
+    //来源
+    sourceList(val) {
+      var that = this,
+        obj = {};
+      this.params.tid='';
+      obj.mtype = val;
+      tasks(obj).then((res) => {
+        if (res.errcode == 0) {
+          that.sour_list = res.data;
+        }
+      });
+    },
+    classC(i) {
+      console.log(i);
+      this.params.page = 1;
+      this.params.cid = i;
+      this.getList();
+    },
+    //重置
+    reset() {
+      this.params.page = 1;
+      this.params.cid = "";
+      this.getList();
+    },
+    //搜索
+    search() {
+      this.params.page = 1;
+      this.getList();
+    },
+    //分页
+    handleCurrentChange(val) {
+      this.params.page = val;
+      this.getList();
+    },
+    //查看
+    // jump_da(title, id) {
+    //   this.$router.push({ path: "/tk_dt_fx", query: { title, id } });
+    // },
+    //获取列表
+    getList() {
+      // const load = this.$loading({
+      //   lock: true,
+      //   text: "Loading",
+      //   spinner: "el-icon-loading",
+      //   background: "rgba(0, 0, 0, 0.7)",
+      // });
+      // var that = this;
+      // var obj = JSON.parse(JSON.stringify(this.params));
+      // searchClass(obj).then((res) => {
+        // if (res.errcode == 0) {
+        //   that.tableData = res.data;
+        //   that.total = res.total;
+        //   //关闭loading
+        //   load.close();
+        // }
+      // });
+    },
+    jump(url) {
+      this.$router.push(url);
+    },
+    tk_py(title, id, tid) {
+      // console.log(title)
+      this.$router.push({ path: "/tk_yp", query: { title, id, tid } });
+    },
+  },
+  components: { topHead, topNav, foot },
+};
+</script>
+<style scoped>
+.fit .form_box > div {
+  display: flex;
+  margin: 10px 0;
+}
+.fit .form_box > div span {
+  width: 75px;
+  font-size: 14px;
+  color: #666666;
+  line-height: 35px;
+}
+.fit .btn .el-button {
+  padding: 10px 20px;
+}
+.fit .btn {
+  margin: 25px 0 5px 0;
+  text-align: right;
+}
+.fit {
+  position: fixed;
+  z-index: 99;
+  background: rgba(0, 0, 0, 0.4);
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+.fit > div {
+  width: 400px;
+  padding: 20px;
+  box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 10px;
+  background: #ffffff;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+.fit .tit {
+  font-size: 16px;
+  color: #000000;
+  margin-bottom: 20px;
+}
+.cap_table {
+  background-color: #fff;
+}
+.cap_table .el-progress.el-progress--line {
+  width: 88px;
+}
+.cap_table .operation span {
+  color: #0a9dff;
+  margin-right: 20px;
+  cursor: pointer;
+}
+.promotion {
+  position: absolute;
+  font-size: 13px;
+  color: #1fb3ff;
+  right: 20px;
+  cursor: pointer;
+}
+.promotion > span {
+  margin-right: 5px;
+}
+.container {
+  background: #f4f4f4;
+  /* margin-bottom: 40px; */
+  margin-top: 30px;
+}
+.table_head {
+  border-bottom: 1px solid #f4f4f4;
+}
+.table_head,
+.cap_table li {
+  background-color: #fff;
+  line-height: 44px;
+  padding: 0 15px;
+  box-sizing: border-box;
+  color: #999;
+  font-size: 13px;
+}
+.table_head > li:last-child {
+  text-align: right;
+}
+.cap_table li > div:last-child {
+  text-align: right;
+  color: #0a9dff;
+}
+.cap_table li > div span {
+  margin-left: 10px;
+  cursor: pointer;
+}
+.cap_table li > div span:first-child {
+  margin: 0;
+}
+.cap_table .contrasts {
+  margin-left: 10px;
+}
+.cap_table li:nth-child(even) {
+  background-color: #f5f9fb;
+}
+.cap_table li div {
+  line-height: 44px;
+  font-size: 14px;
+  color: #333;
+}
+.table_head li,
+.cap_table li > div {
+  width: 17%;
+}
+.table_head li:nth-child(6),
+.cap_table li > div:nth-child(6) {
+  width: 25%;
+}
+
+.recordTitle {
+  font-size: 13px;
+  color: #cccccc;
+  margin: 0 0 15px 0;
+}
+.recordTitle span:last-child {
+  color: #666;
+}
+.screen {
+  margin-top: 0;
+  background: #fff;
+  padding: 15px 5px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  position: relative;
+}
+.screen span {
+  margin-left: 10px;
+}
+.leftMenu {
+  width: 230px;
+  padding: 10px 0;
+  background-color: #fff;
+  height: 176px;
+}
+.leftMenu i {
+  /* width: 14px;
+  height: 14px;*/
+  /* vertical-align: middle;  */
+  display: inline-block;
+  margin-left: 24px;
+  margin-right: 16px;
+}
+.leftMenu li {
+  height: 44px;
+  line-height: 44px;
+  width: 100%;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+  border-left: 2px solid #fff;
+  box-sizing: border-box;
+}
+.leftMenu li.active {
+  background: #ffe8ec;
+  border-left: 2px solid #fa0a2f;
+  color: #fa0a2f;
+}
+.pagePagin .el-pagination {
+  margin-left: auto;
+}
+</style>
+<style>
+.screen1 .el-select {
+  width: 120px;
+}
+.cap_table .el-progress-bar {
+  padding-right: 0;
+}
+.cap_table .el-progress__text {
+  display: none;
+}
+.none {
+  color: #999;
+  text-align: center;
+  margin: 0 0 60px 0;
+}
+.none div:nth-child(1) {
+  width: 416px;
+  height: 276px;
+  margin: 0 auto 40px auto;
+}
+.transfer_box .el-transfer{
+  display: flex;
+  justify-content: space-between;
+  width: 325px;
+}
+.transfer_box .el-input__prefix{
+  left: 2px;
+}
+.transfer_box .el-transfer-panel__filter{
+  margin: 10px;
+}
+.transfer_box .el-input--prefix .el-input__inner{
+  padding-left: 30px;
+}
+.transfer_box .el-transfer-panel__filter .el-input__inner{
+  height: 30px;
+}
+.transfer_box .el-transfer-panel{
+  width: 155px;
+}
+.transfer_box .el-transfer__buttons{
+  position: absolute;
+}
+.transfer_box .el-transfer__buttons{
+  display: none;
+}
+</style>

+ 280 - 0
src/components/customer/see_pusherr.vue

@@ -0,0 +1,280 @@
+<template>
+  <div class="page scroll-x">
+    <topHead></topHead>
+    <topNav></topNav>
+    <div class="container d-f">
+      <div class="leftMenu">
+         <li  @click="jump('/topic')">
+          <i class="iconfont iconbanji"></i>
+          <span>班级错题</span>
+        </li>
+        <li @click="jump('student_err')">
+          <i class="iconfont iconyuejuan"></i> <span>学生错题</span>
+        </li>
+        <li class="active" @click="jump('push_err')">
+          <i class="iconfont iconzuoye1"></i><span>错题推送</span>
+        </li>
+      </div>
+      <div class="rightContent">
+        <div class="recordTitle">
+          <span>错题中心 > </span>
+          <span>错题推送</span>
+        </div>
+        <div class="d-f j-s table_head">
+         
+          <li>姓名</li>
+           <li>学号</li>
+          <li>错题数</li>
+          <li>是否打印</li>
+          <li>推送时间</li>
+          <li>操作</li>
+        </div>
+          <div class="none" v-if="tableData.length == 0">
+            <div>
+              <img src="../../assets/none.png" alt="" />
+            </div>
+            <div>暂无数据</div>
+          </div>
+        <div
+        v-else
+          class="cap_table"
+          :style="{ minHeight: Common.clientHeight - 400 + 'px' }"
+        >
+          <li v-for="(item, i) in 3" :key="i" class="d-f j-s">
+            <div>小明</div>
+            <div>0122</div>
+            <div>90</div>
+            <div>已打印</div>
+            <div>2021-12-30 12:25:36</div>
+            <div>查看错题本</div>
+          </li>
+        </div>
+        <div class="d-f j-s pagePagin" v-if="total > 0">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="total"
+            :page-size="params.size"
+            :current-page="params.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+    <!-- <foot></foot> -->
+  </div>
+</template>
+<script>
+import topNav from "@/components/assembly/topnav";
+import topHead from "@/components/assembly/head";
+import foot from "@/components/assembly/foot";
+import { searchClass,  classes } from "@/util/api";
+export default {
+  data() {
+    return {
+      params: {
+        page: 1,
+        size: 10,
+        cid:'',
+      },
+      tableData: [],
+      classL: [],
+      total: 0,
+    };
+  },
+  created() {
+    var that = this;
+    //班级
+    classes().then((res) => {
+      console.log(res.data[0])
+      if (res.errcode == 0) {
+        that.classL = res.data;
+        that.params.cid = res.total>0?res.data[0].id:'';
+        that.getList();
+      }
+    });
+
+  },
+  methods: {
+      classC(i){
+          console.log(i)
+          this.params.page = 1
+          this.params.cid = i
+        this.getList();
+      },
+    //重置
+    reset(){
+      this.params.page=1;
+      this.params.cid='';
+      this.getList();
+    },
+    //搜索
+    search(){
+      this.params.page = 1;
+      this.getList();
+    },
+    //分页
+    handleCurrentChange(val) {
+      this.params.page = val;
+      this.getList();
+    },
+    //查看
+    // jump_da(title, id) {
+    //   this.$router.push({ path: "/tk_dt_fx", query: { title, id } });
+    // },
+    //获取列表
+    getList() {
+      const load = this.$loading({
+        lock: true,
+        text: "Loading",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      var that = this;
+      var obj = JSON.parse(JSON.stringify(this.params));
+      searchClass(obj).then((res) => {
+        if (res.errcode == 0) {
+          that.tableData = res.data;
+          that.total = res.total;
+          //关闭loading
+            load.close();
+        }
+      });
+    },
+    jump(url) {
+        this.$router.push(url);
+    },
+    tk_py(title, id,tid) {
+      // console.log(title)
+      this.$router.push({ path: "/tk_yp", query: { title, id,tid } });
+    },
+  },
+  components: { topHead, topNav, foot },
+};
+</script>
+<style scoped>
+.cap_table {
+  background-color: #fff;
+}
+.cap_table .el-progress.el-progress--line {
+  width: 88px;
+}
+.cap_table .operation span {
+  color: #0a9dff;
+  margin-right: 20px;
+  cursor: pointer;
+}
+.container {
+  background: #f4f4f4;
+  /* margin-bottom: 40px; */
+  margin-top: 30px;
+}
+.table_head {
+  border-bottom: 1px solid #f4f4f4;
+}
+.table_head,
+.cap_table li {
+  background-color: #fff;
+  line-height: 44px;
+  padding: 0 15px;
+  box-sizing: border-box;
+  color: #999;
+  font-size: 13px;
+}
+.table_head>li:last-child{
+    text-align: right;
+}
+.cap_table li>div:last-child{
+    text-align: right;
+    color: #0A9DFF;
+    cursor: pointer;
+}
+.cap_table .contrasts {
+  margin-left: 10px;
+}
+.cap_table li:nth-child(even) {
+  background-color: #f5f9fb;
+}
+.cap_table li div {
+  line-height: 44px;
+  font-size: 14px;
+  color: #333;
+}
+.table_head li,
+.cap_table li > div{
+  width: 20%;
+}
+
+.recordTitle {
+  font-size: 13px;
+  color: #cccccc;
+  margin: 0 0 15px 0;
+}
+.recordTitle span:last-child {
+  color: #666;
+}
+.screen {
+  margin-top: 0;
+  background: #fff;
+  padding: 15px 5px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+}
+.screen span {
+  margin-left: 10px;
+}
+.leftMenu {
+  width: 230px;
+  padding: 10px 0;
+  background-color: #fff;
+  height: 176px;
+}
+.leftMenu i {
+  /* width: 14px;
+  height: 14px;*/
+  /* vertical-align: middle;  */
+  display: inline-block;
+  margin-left: 24px;
+  margin-right: 16px;
+}
+.leftMenu li {
+  height: 44px;
+  line-height: 44px;
+  width: 100%;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+  border-left: 2px solid #fff;
+  box-sizing: border-box;
+}
+.leftMenu li.active {
+  background: #ffe8ec;
+  border-left: 2px solid #fa0a2f;
+  color: #fa0a2f;
+}
+.pagePagin .el-pagination {
+  margin-left: auto;
+}
+</style>
+<style>
+.screen1 .el-select {
+  width: 120px;
+}
+.cap_table .el-progress-bar {
+  padding-right: 0;
+}
+.cap_table .el-progress__text {
+  display: none;
+}
+.none {
+  color: #999;
+  text-align: center;
+  margin: 0 0 60px 0;
+}
+.none div:nth-child(1) {
+  width: 416px;
+  height: 276px;
+  margin: 0 auto 40px auto;
+}
+</style>

+ 292 - 0
src/components/customer/student_err.vue

@@ -0,0 +1,292 @@
+<template>
+  <div class="page scroll-x">
+    <topHead></topHead>
+    <topNav></topNav>
+    <div class="container d-f">
+      <div class="leftMenu">
+         <li  @click="jump('/topic')">
+          <i class="iconfont iconbanji"></i>
+          <span>班级错题</span>
+        </li>
+        <li class="active">
+          <i class="iconfont iconyuejuan"></i> <span>学生错题</span>
+        </li>
+        <li @click="jump('/push_err')">
+          <i class="iconfont iconzuoye1"></i><span>错题推送</span>
+        </li>
+      </div>
+      <div class="rightContent">
+        <div class="recordTitle">
+          <span>错题中心> </span>
+          <span>学生错题</span>
+        </div>
+        <div class="d-f screen screen1">
+          <span>班级:</span>
+          <el-select @change="classC" v-model="params.cid" clearable placeholder="请选择">
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in classL"
+              :key="item.name"
+            ></el-option>
+          </el-select>
+          <div class="search_box">
+            <i class="el-icon-search"></i>
+            <el-input
+              v-model="params.kw"
+              placeholder="请输入关键字搜索"
+            ></el-input>
+          </div>
+          <el-button @click="search">搜索</el-button>
+        </div>
+        <div class="d-f j-s table_head">
+         
+          <li>姓名</li>
+           <li>学号</li>
+          <li>错题数</li>
+          <li>作业错题</li>
+          <li>考试错题</li>
+          <li>综合出错率</li>
+          <li>操作</li>
+        </div>
+          <div class="none" v-if="tableData.length == 0">
+            <div>
+              <img src="../../assets/none.png" alt="" />
+            </div>
+            <div>暂无数据</div>
+          </div>
+        <div
+        v-else
+          class="cap_table"
+          :style="{ minHeight: Common.clientHeight - 400 + 'px' }"
+        >
+          <li v-for="(item, i) in tableData" :key="i" class="d-f j-s">
+            <div>{{item.student_name}}</div>
+            <div>{{item.student_sno}}</div>
+            <div>{{item.total_errors}}</div>
+            <div>{{item.work_error_count}}</div>
+            <div>{{item.exam_error_count}}</div>
+            <div>{{item.error_ratio}}%</div>
+            <div @click="jump('/per_err?sid='+item.student_id+'&cid='+params.cid+'&name='+item.student_name)">查看</div>
+          </li>
+        </div>
+        <div class="d-f j-s pagePagin" v-if="total > 0">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="total"
+            :page-size="params.size"
+            :current-page="params.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+    <!-- <foot></foot> -->
+  </div>
+</template>
+<script>
+import topNav from "@/components/assembly/topnav";
+import topHead from "@/components/assembly/head";
+import foot from "@/components/assembly/foot";
+import { stuErr,  classes } from "@/util/api";
+export default {
+  data() {
+    return {
+      params: {
+        page: 1,
+        size: 10,
+        cid:'',
+      },
+      tableData: [],
+      classL: [],
+      total: 0,
+    };
+  },
+  created() {
+    var that = this;
+    //班级
+    classes().then((res) => {
+      if (res.errcode == 0) {
+        that.classL = res.data;
+        that.params.cid = res.total>0?res.data[0].id:'';
+        that.getList();
+      }
+    });
+
+  },
+  methods: {
+      classC(i){
+          console.log(i)
+          this.params.page = 1
+          this.params.cid = i
+        this.getList();
+      },
+    //搜索
+    search(){
+      this.params.page = 1;
+      this.getList();
+    },
+    //分页
+    handleCurrentChange(val) {
+      this.params.page = val;
+      this.getList();
+    },
+    //查看
+    //获取列表
+    getList() {
+      const load = this.$loading({
+        lock: true,
+        text: "Loading",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      var that = this;
+      var obj = JSON.parse(JSON.stringify(this.params));
+      stuErr(obj).then((res) => {
+        if (res.errcode == 0) {
+          that.tableData = res.data;
+          that.total = res.total;
+          //关闭loading
+            load.close();
+        }
+      });
+    },
+    jump(url) {
+        this.$router.push(url);
+    },
+  },
+  components: { topHead, topNav, foot },
+};
+</script>
+<style scoped>
+.cap_table {
+  background-color: #fff;
+}
+.cap_table .el-progress.el-progress--line {
+  width: 88px;
+}
+.cap_table .operation span {
+  color: #0a9dff;
+  margin-right: 20px;
+  cursor: pointer;
+}
+.container {
+  background: #f4f4f4;
+  /* margin-bottom: 40px; */
+  margin-top: 30px;
+}
+.table_head {
+  border-bottom: 1px solid #f4f4f4;
+}
+.table_head,
+.cap_table li {
+  background-color: #fff;
+  line-height: 44px;
+  padding: 0 15px;
+  box-sizing: border-box;
+  color: #999;
+  font-size: 13px;
+}
+.table_head>li:last-child{
+    text-align: right;
+}
+.cap_table li>div:last-child{
+    text-align: right;
+    color: #0A9DFF;
+        cursor: pointer;
+}
+.cap_table li>div:nth-child(6){
+    color: #FA0A2F;
+    font-weight: bold;
+    font-size: 14px;
+}
+.cap_table .contrasts {
+  margin-left: 10px;
+}
+.cap_table li:nth-child(even) {
+  background-color: #f5f9fb;
+}
+.cap_table li div {
+  line-height: 44px;
+  font-size: 14px;
+  color: #333;
+}
+.table_head li,
+.cap_table li > div{
+  width: 20%;
+}
+
+.recordTitle {
+  font-size: 13px;
+  color: #cccccc;
+  margin: 0 0 15px 0;
+}
+.recordTitle span:last-child {
+  color: #666;
+}
+.screen {
+  margin-top: 0;
+  background: #fff;
+  padding: 15px 5px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+}
+.screen span {
+  margin-left: 10px;
+}
+.leftMenu {
+  width: 230px;
+  padding: 10px 0;
+  background-color: #fff;
+  height: 176px;
+}
+.leftMenu i {
+  /* width: 14px;
+  height: 14px;*/
+  /* vertical-align: middle;  */
+  display: inline-block;
+  margin-left: 24px;
+  margin-right: 16px;
+}
+.leftMenu li {
+  height: 44px;
+  line-height: 44px;
+  width: 100%;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+  border-left: 2px solid #fff;
+  box-sizing: border-box;
+}
+.leftMenu li.active {
+  background: #ffe8ec;
+  border-left: 2px solid #fa0a2f;
+  color: #fa0a2f;
+}
+.pagePagin .el-pagination {
+  margin-left: auto;
+}
+</style>
+<style>
+.screen1 .el-select {
+  width: 120px;
+}
+.cap_table .el-progress-bar {
+  padding-right: 0;
+}
+.cap_table .el-progress__text {
+  display: none;
+}
+.none {
+  color: #999;
+  text-align: center;
+  margin: 0 0 60px 0;
+}
+.none div:nth-child(1) {
+  width: 416px;
+  height: 276px;
+  margin: 0 auto 40px auto;
+}
+</style>

+ 605 - 151
src/components/customer/topic.vue

@@ -1,197 +1,651 @@
 <template>
-  <div class="page">
+  <div class="page scroll-x">
     <topHead></topHead>
     <topNav></topNav>
-    <div class="container">
-      <div class="screen">
-        <div class="push_box">
-          <span>错题推送</span>
-          <span>推送记录</span>
+    <div class="container d-f">
+      <div class="leftMenu">
+        <li class="active">
+          <i class="iconfont iconcuotiku"></i>
+          <span>班级错题</span>
+        </li>
+        <li @click="jump('/student_err')">
+          <i class="iconfont iconcuotiben"></i> <span>学生错题</span>
+        </li>
+        <li @click="jump('/push_err')">
+          <i class="iconfont icontuisong"></i><span>错题推送</span>
+        </li>
+      </div>
+      <div class="rightContent">
+        <div class="recordTitle">
+          <span>错题中心> </span>
+          <span>班级错题</span>
+        </div>
+        <div class="d-f screen screen1">
+          <span>班级:</span>
+          <el-select
+            @change="classC"
+            v-model="params.cid"
+            clearable
+            placeholder="请选择"
+          >
+            <el-option
+              :label="item.name"
+              :value="item.id"
+              v-for="item in classL"
+              :key="item.name"
+            ></el-option>
+          </el-select>
+          <span>来源:</span>
+          <el-select
+            clearable
+            placeholder="请选择"
+            v-model="source"
+            @change="sourceList"
+          >
+            <el-option value="exam" label="考试"></el-option>
+            <el-option value="work" label="作业"></el-option>
+          </el-select>
+          <el-select
+            v-model="tid"
+            clearable
+            placeholder="请选择"
+            style="width: 150px; margin-left: 5px"
+          >
+            <el-option v-for="item,i in sour_list" :key="i+'j'" :label='item.name' :value="item.id"></el-option>
+          </el-select>
+          <div class="search_box">
+            <i class="el-icon-search"></i>
+            <el-input
+              v-model="params.kw"
+              placeholder="请输入关键字搜索"
+            ></el-input>
+          </div>
+          <el-button @click="search">搜索</el-button>
+          <div class="reset" @click="is_show = true">
+            <span class="el-icon-setting"></span> 设置错误率
+          </div>
         </div>
-        <li class="d-f">
-          <div>类别:</div>
+        <div class="error">错误率:{{ratio}}%</div>
+        <div class="error_coll">
+          <li class="d-f j-s" v-for="item,i in tableData" :key="i+'a'">
+            <div>
+              <div class="t_img">
+                <div class="stem">
+                  {{item.qid}}. {{item.stem}}
+                </div>
+                <div class="d-f j-s">
+                  <span>来源:{{item.task_type=='work'?'作业':'考试'}}-{{item.task_name}}</span>
+                  <span>答案: <span class="bold">{{item.answer}}</span> </span>
+                  <span @click="is_answer = true">
+                    <i class="iconfont icondengpao1"></i> 答案解析</span
+                  >
+                </div>
+              </div>
+              <div class="d-f j-s probability">
+                <div>错误率:{{item.error_ratio}}</div>
+                <div class="d-f j-s">
+                  <span>总人数:{{item.student_count}}</span>
+                  <span>错误/正确人数:{{item.error_count}}/{{item.right_count}}</span>
+                </div>
+              </div>
+            </div>
+            <div
+              class="roseChart"
+              :style="{
+                width: '240px',
+                height: '180px',
+              }"
+            ></div>
+          </li>
+        </div>
+        <div class="none" v-if="tableData.length == 0">
+          <div>
+            <img src="../../assets/none.png" alt="" />
+          </div>
+          <div>暂无数据</div>
+        </div>
+        <div class="d-f j-s pagePagin" v-if="total > 0">
+          <el-pagination
+            background
+            layout="prev, pager, next"
+            :total="total"
+            :page-size="params.size"
+            :current-page="params.page"
+            @current-change="handleCurrentChange"
+          >
+          </el-pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 设置错题率 -->
+    <div class="fit" v-show="is_show">
+      <div>
+        <div class="tit">设置错题率</div>
+        <div class="form_box">
           <div>
-            <span
-              v-for="(item, i) in type"
-              :key="item"
-              :class="typeIndex == i ? 'active' : ''"
-              @click="typeIndex = i"
-              >{{ item }}</span
+            <span>班级</span>
+            <el-select
+              @change="classC"
+              v-model="params.cid"
+              clearable
+              placeholder="请选择"
+              style="width: 325px"
             >
+              <el-option
+                :label="item.name"
+                :value="item.id"
+                v-for="item in classL"
+                :key="item.name"
+              ></el-option>
+            </el-select>
           </div>
-        </li>
-        <li class="d-f">
-          <div>年级:</div>
           <div>
-            <span
-              v-for="(item, i) in grad"
-              :key="item"
-              :class="gradIndex == i ? 'active' : ''"
-              @click="gradIndex = i"
-              >{{ item }}</span
+            <span>来源</span>
+            <el-select
+              clearable
+              placeholder="请选择"
+              v-model="source"
+              style="width: 100px"
+              @change="sourceList"
             >
+                 <el-option value="exam" label="考试"></el-option>
+            <el-option value="work" label="作业"></el-option>
+            </el-select>
+            <el-select
+              v-model="tid"
+              clearable
+              placeholder="请选择"
+              style="width: 220px; margin-left: 5px"
+            >
+               <el-option v-for="item,i in sour_list" :key="i+'j'" :label='item.name' :value="item.id"></el-option>
+            </el-select>
           </div>
-        </li>
+          <div>
+            <span>错题率</span>
+            <el-input
+              style="width: 325px"
+              v-model="ratio"
+              placeholder="请输入"
+            ></el-input>
+          </div>
+        </div>
+        <div class="btn">
+          <el-button @click="is_show = false">取消</el-button>
+          <el-button type="primary" @click="sure_ratio">确认</el-button>
+        </div>
       </div>
-      <el-table
-        :data="tableData"
-        stripe
-        style="width: 100%;margin-top:30px"
-         :height="this.tabp"
-        :header-cell-style="{ background: '#F5F5F5', color: '#999',}"
-      >
-        <el-table-column prop="" label="序号">
-          <template slot-scope="scope">{{ scope.$index +1}} </template>
-        </el-table-column>
-        <el-table-column prop="date" label="时间"> </el-table-column>
-        <el-table-column prop="name" label="学科"></el-table-column>
-        <el-table-column prop="score" label="推送数量(份)"> 
-          <template slot-scope="scope">
-              <span style="font-weight: bold">{{ scope.row.score }}</span>
-            </template>
-        </el-table-column>
-        <el-table-column prop="pscore" label="页码数"> 
-          <template slot-scope="scope">
-              <span style="font-weight: bold">{{ scope.row.pscore }}</span>
-            </template>
-        </el-table-column>
-        <el-table-column label="操作" width="80">
-          <template slot-scope="scope">
-            <el-button
-              @click.native.prevent="deleteRow(scope.$index, tableData)"
-              type="text"
-              size="small"
-            >
-              查看
-            </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-      <div class="d-f j-s pagePagin">
-        <div style="font-size:13px">点击“查看”,可以查看本次推送的班级列表</div>
-        <el-pagination background layout="prev, pager, next" :total="100">
-        </el-pagination>
+    </div>
+    <!-- 答案解析 -->
+    <div class="fit" v-if="is_answer">
+      <div>
+        <div class="titl">答案解析</div>
+        <div class="del el-icon-close" @click="is_answer = false"></div>
+        <div>
+          <div class="analysis">{{tableData[index].analysis}}</div>
+        </div>
       </div>
     </div>
+    <!-- <foot></foot> -->
   </div>
 </template>
 <script>
 import topNav from "@/components/assembly/topnav";
 import topHead from "@/components/assembly/head";
+import foot from "@/components/assembly/foot";
+import { classes, clsErr, tasks } from "@/util/api";
 export default {
   data() {
     return {
-      type: ["按班级", "按日期"],
-      grad: ["高一", "高二", "高三"],
-      typeIndex: 0,
-      gradIndex: 0,
-      params: {},
-      tableData: [
-        {
-          date: "2016-05-02",
-          name: "数学",
-          score: 100,
-          gscore: 98,
-          pscore: 78,
-          jg: 70,
-        },
-        {
-          date: "2016-05-02",
-          name: "数学",
-          score: 100,
-          gscore: 98,
-          pscore: 78,
-          jg: 70,
-        },
-        {
-          date: "2016-05-02",
-          name: "数学",
-          score: 100,
-          gscore: 98,
-          pscore: 78,
-          jg: 70,
-        },
-        {
-          date: "2016-05-02",
-          name: "数学",
-          score: 100,
-          gscore: 98,
-          pscore: 78,
-          jg: 70,
+      params: {
+        page: 1,
+        size: 10,
+        cid: "0",
+      },
+      tid:'',
+      ratio:0,
+      index:0,
+      tableData: [],
+      classL: [],
+      total: 0,
+      is_show: false,
+      is_answer: false,
+       source: "", //来源
+      sour_list: [],
+    };
+  },
+  created() {
+    var that = this;
+    //班级
+    classes().then((res) => {
+      if (res.errcode == 0) {
+        that.params.cid = res.total > 0 ? res.data[0].id : "";
+        that.classL = res.data;
+      }
+    });
+    this.getList();
+  },
+  mounted() {
+    var that = this;
+    this.$nextTick(function () {
+      //这里写方法
+      that.drawRose();
+    });
+  },
+  watch: {
+    tableData: function () {
+      //tableData为需要监听的data
+      var that = this;
+      this.$nextTick(function () {
+        //这里写方法
+        that.drawRose();
+      });
+    },
+  },
+  methods: {
+    //设置错题率
+    sure_ratio(){
+      var regs= /^([1-9]{1}[0-9]{0,7})\d*$/;
+      if(!this.ratio){
+        return
+      }
+      if(regs.test(this.ratio)){
+        this.params.page = 1;
+        this.is_show = false;
+        this.getList();
+      }else{
+         this.$message.warning("请输入100内的整数");
+      }
+    },
+    //来源
+    sourceList(val) {
+      var that = this,
+        obj = {};
+      this.params.tid='';
+      obj.mtype = val;
+      tasks(obj).then((res) => {
+        if (res.errcode == 0) {
+          that.sour_list = res.data;
+        }
+      });
+    },
+    drawRose() {
+      var roseCharts = document.getElementsByClassName("roseChart");
+      console.log(roseCharts);
+      var index = 0;
+      for (var i = 0; i < this.tableData.length; i++) {
+        index = i;
+        var xdata = [];
+        var ydata = [];
+      var maxNum = '';
+      if(this.tableData[i].dist.length<0){
+        return
+      }
+      for (var j = 0; j < this.tableData[i].dist.length; j++) {
+        xdata.push(this.tableData[i].dist[j].key);
+        ydata.push(this.tableData[i].dist[j].val);
+      }
+      maxNum = Math.max(...ydata);
+      for (var q = 0; q < ydata.length; q++) {
+        ydata[q] = {
+          value: ydata[q],
+          itemStyle: {
+            color: ydata[q] >= 75 ? "#39D095" : "#508CEE",
+          },
+        };
+      }
+      var itemChart = this.$echarts.init(roseCharts[index]);
+      var itemChart = this.$echarts.init(roseCharts[0]);
+      // console.log(itemChart);
+      console.log(itemChart);
+      // 绘制图表
+      itemChart.setOption({
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            // 坐标轴指示器,坐标轴触发有效
+            type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
+          },
         },
-        {
-          date: "2016-05-02",
-          name: "数学",
-          score: 100,
-          gscore: 98,
-          pscore: 78,
-          jg: 70,
+        grid: {
+          left: "0%",
+          right: "0%",
+          bottom: "0%",
+          containLabel: true,
+          height: 170,
         },
-      ],
-    };
+        xAxis: [
+          {
+            type: "category",
+            data: ["A", "B", "C", "D"],
+            axisTick: {
+              alignWithLabel: true,
+            },
+            axisLine: {
+              lineStyle: {
+                color: "#D9D9D9",
+              },
+            },
+            axisLabel: {
+              //x轴文字的配置
+              show: true,
+              textStyle: {
+                color: "#999",
+                fontSize: 13,
+                // align: "right",
+              },
+            },
+            axisTick: {
+              show: false,
+            },
+          },
+        ],
+        yAxis: [
+          {
+            type: "value",
+            axisLabel: {
+              formatter: "{value}",
+              textStyle: {
+                color: "#999",
+              },
+            },
+            max: maxNum,
+            min: 0,
+            interval: 25,
+            splitLine: {
+              show: true,
+              lineStyle: {
+                type: "dashed",
+                color: "#D9D9D9",
+              },
+            },
+            axisTick: {
+              //y轴刻度线
+              show: false,
+            },
+            axisLine: {
+              //y轴
+              show: false,
+            },
+            axisLabel: {
+              //x轴文字的配置
+              show: true,
+              margin: 40,
+              textStyle: {
+                color: "#999",
+                fontSize: 13,
+                align: "left",
+              },
+            },
+          },
+        ],
+        series: [
+          {
+            name: "学生人数",
+            type: "bar",
+            barWidth: "20",
+            itemStyle: {
+              normal: {
+                color: function (params) {
+                  //注意,如果颜色太少的话,后面颜色不会自动循环,最好多定义几个颜色
+                  var colorList = [];
+                  if (params.value < 26) {
+                    colorList.push("#508CEE");
+                  } else if (25 < params.value && params.value < 51) {
+                    colorList.push("#1FDA9A");
+                  } else {
+                    colorList.push("#FA0A2F");
+                  }
+                  return colorList;
+                },
+              },
+            },
+            data: [20, 50, 70, 40],
+          },
+        ],
+      });
+      }
+    },
+    //班级筛选
+    classC(i) {
+      console.log(i);
+      this.params.page = 1;
+      this.params.cid = i;
+      this.getList();
+    },
+    //搜索
+    search() {
+      this.params.page = 1;
+      this.getList();
+    },
+    //分页
+    handleCurrentChange(val) {
+      this.params.page = val;
+      this.getList();
+    },
+    //获取列表
+    getList() {
+      const load = this.$loading({
+        lock: true,
+        text: "Loading",
+        spinner: "el-icon-loading",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      var that = this;
+      this.params.tid = this.tid?this.tid:0;
+      this.params.ratio = this.ratio;
+      clsErr(this.params).then((res) => {
+        if (res.errcode == 0) {
+          that.tableData = res.data?res.data:[];
+          console.log(that.tableData)
+          that.total = res.total;
+          //关闭loading
+            load.close();
+        }
+      });
+    },
+    jump(url) {
+        this.$router.push(url);
+    },
   },
-  created() {},
-  methods: {},
-  components: { topHead, topNav },
+  components: { topHead, topNav, foot },
 };
 </script>
 <style scoped>
-.page{
-  padding: 0;
+.container {
+  background: #f4f4f4;
+  margin-top: 30px;
 }
-.pagePagin{
-  margin: 20px 0;
+.fit .form_box > div {
+  display: flex;
+  margin: 10px 0;
 }
-.screen {
-  position: relative;
-  padding-left: 15px;
+.fit .analysis{
+  font-size: 13px;
+  background: #FFF8E8;
+  margin-top: 20px;
+  padding: 10px 15px;
+  line-height: 27px;
 }
-.screen li {
-  color: #333333;
+.fit .del {
+  color: #bebebe;
+  font-size: 22px;
+  cursor: pointer;
+  position: absolute;
+  top: 20px;
+  right: 20px;
+}
+.fit img {
+  width: 100%;
+  margin-top: 10px;
+}
+.fit .btn .el-button {
+  padding: 10px 20px;
+}
+.fit .btn {
+  margin: 25px 0 5px 0;
+  text-align: right;
+}
+.fit .form_box > div span {
+  width: 75px;
+  font-size: 14px;
+  color: #666666;
+  line-height: 35px;
+}
+.fit {
+  position: fixed;
+  z-index: 99;
+  background: rgba(0, 0, 0, 0.4);
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+}
+.fit > div {
+  width: 400px;
+  padding: 20px;
+  box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.1);
+  border-radius: 10px;
+  background: #ffffff;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+.fit .tit {
+  font-size: 16px;
+  color: #000000;
   margin-bottom: 20px;
 }
-.screen li > div:first-child {
+.error_coll li {
+  background: #ffff;
+  margin: 10px 0;
+  height: 222px;
+  padding: 20px;
+  box-sizing: border-box;
+}
+.error_coll li > div {
+  width: 635px;
+}
+.error_coll .probability {
+  font-size: 13px;
   color: #999999;
-  font-size: 14px;
-    line-height: 20px;
-    margin-right: 15px;
 }
-.screen > li > div > span {
-  display: inline-block;
-  width: 68px;
-  height: 24px;
-  border-radius: 4px;
-  text-align: center;
-  line-height: 23px;
+.error_coll .probability > div:first-child {
+  color: #fa0a2f;
+}
+.error_coll .probability > div:last-child {
+  width: 35%;
+}
+.error_coll .t_img {
+  border-bottom: 1px solid #ededed;
+  padding-bottom: 10px;
+  margin-bottom: 10px;
+  color: #999999;
   font-size: 13px;
-  margin-right: 20px;
+}
+.error_coll .t_img > div > span:last-child {
+  color: #52c4ff;
   cursor: pointer;
 }
-.screen > li > div > span.active {
-  background: #fa0a2f;
-  color: #fff;
+.error_coll .t_img .bold {
+  font-weight: bold;
 }
-.screen .push_box {
-  position: absolute;
-  right: 20px;
-  top: 35px;
+.error_coll .t_img img {
+  width: 100%;
+  height: 122px;
 }
-.screen .push_box span {
-  display: inline-block;
-  width: 96px;
+.error_coll .t_img .stem{
+  font-size: 14px;
+  color: #333;
+  height: 130px;
+}
+.error {
+  width: 100%;
   height: 32px;
-  background: #ffffff;
-  border: 1px solid #fa0a2f;
-  border-radius: 4px;
-  line-height: 32px;
+  background: #ffeabe;
+  border: 0px solid #030000;
+  font-size: 13px;
+  color: #f08216;
   text-align: center;
-  margin-left: 10px;
-  color: #fa0a2f;
-  font-size: 12px;
+  line-height: 32px;
+}
+.reset {
+  font-size: 13px;
+  color: #1fb3ff;
   cursor: pointer;
+  position: absolute;
+  right: 20px;
 }
-.container {
-  padding: 20px 15px 5px 15px;
+.recordTitle {
+  font-size: 13px;
+  color: #cccccc;
+  margin: 0 0 15px 0;
+}
+.recordTitle span:last-child {
+  color: #666;
+}
+.screen {
+  margin-top: 0;
+  background: #fff;
+  padding: 15px 5px;
+  box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
+  margin-bottom: 10px;
+  position: relative;
+}
+.screen span {
+  margin-left: 10px;
+}
+.leftMenu {
+  width: 230px;
+  padding: 10px 0;
+  background-color: #fff;
+  height: 176px;
+}
+.leftMenu i {
+  /* width: 14px;
+  height: 14px;*/
+  /* vertical-align: middle;  */
+  display: inline-block;
+  margin-left: 24px;
+  margin-right: 16px;
+}
+.leftMenu li {
+  height: 44px;
+  line-height: 44px;
+  width: 100%;
+  color: #666;
+  font-size: 14px;
+  cursor: pointer;
+  border-left: 2px solid #fff;
   box-sizing: border-box;
 }
+.leftMenu li.active {
+  background: #ffe8ec;
+  border-left: 2px solid #fa0a2f;
+  color: #fa0a2f;
+}
+.pagePagin .el-pagination {
+  margin-left: auto;
+}
+</style>
+<style>
+.screen1 .el-select {
+  width: 120px;
+}
+.cap_table .el-progress-bar {
+  padding-right: 0;
+}
+.cap_table .el-progress__text {
+  display: none;
+}
+.none {
+  color: #999;
+  text-align: center;
+  margin: 0 0 60px 0;
+}
+.none div:nth-child(1) {
+  width: 416px;
+  height: 276px;
+  margin: 0 auto 40px auto;
+}
 </style>

+ 8 - 6
src/components/log.vue

@@ -35,6 +35,7 @@
                 placeholder="请输入密码"
                 auto-complete="new-password"
                 show-password
+                 @keypress.native.enter="onSubmit"
               ></el-input>
             </el-form-item>
             <div class="d-f j-s cipher">
@@ -42,7 +43,7 @@
               <span>忘记密码?</span>
             </div>
             <el-form-item>
-              <el-button type="primary" @click="onSubmit">登陆</el-button>
+              <el-button type="primary"  @click="onSubmit">登陆</el-button>
             </el-form-item>
           </el-form>
         </div>
@@ -296,16 +297,17 @@ export default {
         if (res.errcode == 0) {
           if (res.data.is_first_login == true) {
             localStorage.setItem("token", res.data.access_token);
-            this.$message.warning("您是第一次登录请先重置密码");
-            this.is_login = false
+            that.$message.warning("您是第一次登录请先重置密码");
+            that.is_login = false
           } else {
             localStorage.setItem("token", res.data.access_token);
             localStorage.setItem("is_login", 1);
+            localStorage.setItem("is_user", 1);
             localStorage.setItem('username',this.params.username)
-            this.$message.success("登录成功");
+            that.$message.success("登录成功");
             setTimeout(() => {
-              this.$router.push("/");
-            }, 1000);
+              that.$router.push("/");
+            }, 500);
           }
         }
       });

+ 41 - 1
src/router/index.js

@@ -13,6 +13,10 @@ import Tk_fx from '@/components/customer/tk_fx'
 import Tk_dt_fx from '@/components/customer/tk_dt_fx'
 import Tk_xs_fx from '@/components/customer/tk_xs_fx'
 import MyClass from '@/components/customer/myClass'
+import Student_err from '@/components/customer/student_err'
+import Push_err from '@/components/customer/push_err'
+import See_pusherr from '@/components/customer/see_pusherr'
+import Per_err from '@/components/customer/per_err'
 
 
 
@@ -96,7 +100,25 @@ export default new Router({
       name: 'Topic',
       component: Topic,
       meta:{
-        title:'错题中心',
+        title:'班级错题',
+        requiresAuth: true 
+      }
+    },
+    {
+      path: '/student_err',
+      name: 'Student_err',
+      component: Student_err,
+      meta:{
+        title:'学生错题',
+        requiresAuth: true 
+      }
+    },
+    {
+      path: '/push_err',
+      name: 'Push_err',
+      component: Push_err,
+      meta:{
+        title:'错题推送',
         requiresAuth: true 
       }
     },
@@ -136,6 +158,24 @@ export default new Router({
         requiresAuth: true 
       }
     },
+    {
+      path: '/see_pusherr',
+      name: 'See_pusherr',
+      component: See_pusherr,
+      meta:{
+        title:'错题推送',
+        requiresAuth: true 
+      }
+    },
+    {
+      path: '/per_err',
+      name: 'Per_err',
+      component: Per_err,
+      meta:{
+        title:'个人错题',
+        requiresAuth: true 
+      }
+    },
     
   ]
 })

+ 3 - 0
src/util/api.js

@@ -22,3 +22,6 @@ export const questions = p => get('v1/api/papers/'+p)//作业分析-答题分析
 export const account = p => get('/v1/api/account',p)//获取用户信息
 export const searchClass = p => get('/v1/api/students',p)//学生列表
 export const collected = p => get('/v1/api/resource/collected',p)//收藏列表
+export const clsErr = p => get('/v1/api/cls-errs',p)//班级错题
+export const stuErr = p => get('/v1/api/stu-errs',p)//学生错题综合
+export const stuErrPer = p => get('/v1/api/stu-errs'+p,)//学生错题个人