<template>
  <el-dialog
    class="page-dialog"
    :visible.sync="modalIsShow"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :show-close="false"
    append-to-body
    fullscreen
    @opened="initData"
  >
    <div slot="title" class="box-justify">
      <div>
        报告详情<span class="color-gray ml-2"
          >{{ course.courseName }}（{{ course.courseCode }}）</span
        >
      </div>
      <div>
        <el-button type="primary" :loading="downloading" @click="toSave"
          >保存报告</el-button
        >
        <el-button type="primary" :loading="downloading" @click="toExport"
          >导出报告</el-button
        >
        <el-button type="danger" @click="cancel">退出</el-button>
      </div>
    </div>
    <div v-if="modalIsShow">
      <!-- base info -->
      <div class="page-head">
        <h2>
          <span>课程基本情况</span>
        </h2>
      </div>
      <div class="part-box part-box-pad">
        <table class="table table-tiny">
          <colgroup>
            <col width="100" />
            <col />
            <col width="100" />
            <col />
            <col width="100" />
            <col />
            <col width="100" />
            <col />
          </colgroup>
          <tr>
            <td class="td-bg">课程编码</td>
            <td>{{ commonInfo.courseCode }}</td>
            <td class="td-bg">课程名称</td>
            <td>{{ commonInfo.courseName }}</td>
            <td class="td-bg">课程类别</td>
            <td>
              <el-input
                v-model="courseBasicInfo.courseType"
                placeholder="请填写课程类别"
                size="small"
                :maxlength="30"
              ></el-input>
            </td>
            <td class="td-bg">学分</td>
            <td>
              <el-input-number
                v-model="courseBasicInfo.credit"
                placeholder="请录入学分"
                size="small"
                :min="0"
                :max="999"
                :controls="false"
                style="width: 100px"
              ></el-input-number>
            </td>
          </tr>
          <tr>
            <td class="td-bg">考核方式</td>
            <td>
              <el-input
                v-model="courseBasicInfo.evaluationMode"
                placeholder="请填写考核方式"
                size="small"
                :maxlength="30"
              ></el-input>
            </td>
            <td class="td-bg">开课时间</td>
            <td>{{ courseBasicInfo.openTime }}</td>
            <td class="td-bg">授课对象</td>
            <td>{{ courseBasicInfo.teachingObject }}</td>
            <td class="td-bg">学时</td>
            <td>
              <el-input-number
                v-model="courseBasicInfo.period"
                placeholder="请录入学时"
                :min="0"
                :max="999"
                :controls="false"
                size="small"
                style="width: 100px"
              ></el-input-number>
            </td>
          </tr>
          <tr>
            <td class="td-bg">选课人数</td>
            <td>
              <el-input-number
                v-model="courseBasicInfo.selectionCount"
                placeholder="请录入选课人数"
                :min="0"
                :max="999"
                :controls="false"
                size="small"
                style="width: 125px"
              ></el-input-number>
            </td>
            <td class="td-bg">参评人数</td>
            <td>{{ courseBasicInfo.participantCount }}</td>
            <td class="td-bg">课程目标达成度期望值</td>
            <td colspan="3">
              <el-select
                v-model="courseBasicInfo.courseDegree"
                size="small"
                style="width: 100%"
              >
                <el-option
                  v-for="item in expectancyList"
                  :key="item"
                  :value="item"
                  :label="item"
                ></el-option>
              </el-select>
            </td>
          </tr>
          <tr>
            <td class="td-bg">任课老师</td>
            <td>{{ courseBasicInfo.teacher }}</td>
            <td class="td-bg">评价负责人</td>
            <td>
              <el-input
                v-model="courseBasicInfo.director"
                placeholder="请填写评价负责人姓名"
                size="small"
                :maxlength="30"
              ></el-input>
            </td>
            <td class="td-bg">评价参与人</td>
            <td colspan="3">
              <el-input
                v-model="courseBasicInfo.participant"
                placeholder="请填写评价人姓名"
                size="small"
                :maxlength="30"
              ></el-input>
            </td>
          </tr>
        </table>
      </div>

      <div class="page-head">
        <h2>
          <span>课程目标考核分布</span>
          <el-popover
            popper-class="el-popper-dark"
            placement="right-start"
            width="500"
            trigger="hover"
          >
            <i class="el-icon-question" slot="reference"></i>
            <div>
              <p>
                课程目标分布会自动按题库系统里试卷下试题标记的属性内容进行显示
              </p>
            </div>
          </el-popover>
        </h2>
      </div>
      <div class="part-box part-box-pad">
        <el-table :data="questionInfoTable">
          <el-table-column
            label="试题号"
            prop="name"
            width="140"
            align="center"
            fixed="left"
          ></el-table-column>
          <el-table-column
            label="合计"
            prop="totalScore"
            width="100"
            align="center"
            fixed="left"
          ></el-table-column>
          <el-table-column
            v-for="struct in paperStructs"
            :key="struct.mainNumber"
            :label="struct.mainNumber"
            align="center"
          >
            <el-table-column
              v-for="subNumber in struct.subNumbers"
              :key="subNumber"
              :label="subNumber"
              :prop="`${struct.mainNumber}_${subNumber}`"
              align="center"
            >
            </el-table-column>
          </el-table-column>
        </el-table>
        <div class="chart-box" style="height: 300px; margin-top: 20px">
          <v-chart
            v-if="questionInfoChartOption"
            :option="questionInfoChartOption"
          ></v-chart>
        </div>
      </div>

      <div class="page-head">
        <h2>
          <span>课程目标达成评价结果</span>
          <el-popover
            popper-class="el-popper-dark"
            placement="right-start"
            width="500"
            trigger="hover"
          >
            <i class="el-icon-question" slot="reference"></i>
            <div>
              <p>1.评价依据：填写通过考核什么内容实现课程目标的评价；</p>
              <p>2.目标分值：对应考核环节的满分；</p>
              <p>
                3.权重：对应考核环节在对应的课程目标中的权重，目标下各项权重相加等于1；
              </p>
              <p>4.实际平均分：为参与评价的学生在该环节的平均分；</p>
              <p>5.目标达成评价值：∑（实际平均分/目标分值*权重）；</p>
              <p>6.整体课程目标达成评价值：为课程分目标达成评价值的最小值。</p>
            </div>
          </el-popover>
        </h2>
      </div>
      <div class="part-box part-box-pad">
        <h4 class="part-title">课程考核成绩评价结果</h4>

        <table class="table">
          <tr class="td-bg">
            <th>课程目标</th>
            <th>评价依据</th>
            <th>评价环节</th>
            <th>权重</th>
            <th>目标分值</th>
            <th>实际平均分</th>
            <th>目标达成评价值</th>
          </tr>

          <template v-for="item in courseTargetList">
            <tr
              v-for="(evaluation, eindex) in item.evaluationList"
              :key="`${item.targetId}-${eindex}`"
            >
              <td
                v-if="!eindex"
                :rowspan="item.evaluationList.length"
                style="width: 240px"
              >
                {{ item.targetName }}
              </td>
              <td v-if="!eindex" :rowspan="item.evaluationList.length">
                <p
                  v-for="edesc in item.graduationRequirementPoint.split('\n')"
                  :key="edesc"
                >
                  {{ edesc }}
                </p>
              </td>
              <td style="width: 140px">{{ evaluation.evaluation }}</td>

              <td
                v-if="!eindex"
                style="width: 80px"
                :rowspan="item.evaluationList.length - 1"
              >
                {{ item.normalTargetWeight }}
              </td>
              <td
                v-else-if="eindex === item.evaluationList.length - 1"
                style="width: 80px"
              >
                {{ evaluation.targetWeight }}
              </td>

              <td style="width: 100px">{{ evaluation.targetScore }}</td>
              <td style="width: 100px">{{ evaluation.targetAvgScore }}</td>
              <td
                v-if="!eindex"
                :rowspan="item.evaluationList.length"
                style="width: 140px"
              >
                {{ item.evaluationValue }}
              </td>
            </tr>
          </template>
          <tr>
            <td colspan="6">课程总目标</td>
            <td>{{ courseTargetValue }}</td>
          </tr>
        </table>

        <div class="chart-box" style="height: 400px; margin-top: 20px">
          <v-chart
            v-if="courseTargetListChartOption"
            :option="courseTargetListChartOption"
          ></v-chart>
        </div>

        <h4 class="part-title">课程考核成绩评价明细结果</h4>

        <el-table
          :data="studentScoreTable"
          :span-method="studentScoreSpanMethod"
        >
          <el-table-column
            label="姓名"
            prop="name"
            min-width="120"
            align="center"
            fixed="left"
          ></el-table-column>
          <el-table-column
            label="学号"
            prop="studentCode"
            width="100"
            align="center"
            fixed="left"
          ></el-table-column>
          <el-table-column
            v-for="(target, tindex) in courseTargets"
            :key="tindex"
            :label="target.targetName"
            align="center"
          >
            <el-table-column width="140" align="center">
              <template slot="header">
                期末考试（{{ target.finalWeight | percentFilter }}）
              </template>
              <el-table-column
                label="期末成绩"
                :prop="`${target.targetId}-final`"
                width="140"
                align="center"
              >
              </el-table-column>
            </el-table-column>
            <el-table-column min-width="120" align="center">
              <template slot="header">
                平时考试（{{ target.usualWeight | percentFilter }}）
              </template>
              <el-table-column
                v-for="work in target.usualWorks"
                :key="`${target.targetId}${work}`"
                :label="work"
                :prop="`${target.targetId}-usual-${work}`"
                min-width="100"
                align="center"
              >
              </el-table-column>
            </el-table-column>
          </el-table-column>
          <el-table-column
            label="学生成绩"
            prop="score"
            align="center"
            width="100"
          ></el-table-column>
        </el-table>
      </div>
    </div>

    <div slot="footer"></div>
  </el-dialog>
</template>

<script>
// import { reportData } from "./data";
import {
  targetReportDetail,
  exportTargetReport,
  targetReportSave,
  targetReportChangeCheck,
} from "../api";
import { downloadByApi } from "@/plugins/download";
import { calcSum } from "@/plugins/utils";

export default {
  name: "target-report-detail",
  props: {
    course: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  filters: {
    percentFilter(val) {
      const num = val || 0;
      const perc = num % 10 ? 2 : 1;
      return ((num || 0) / 100).toFixed(perc);
    },
  },
  data() {
    return {
      modalIsShow: false,
      expectancyList: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
      commonInfo: {},
      courseBasicInfo: {},
      paperStructs: [],
      questionInfoTable: [],
      courseTargetList: [],
      courseTargetValue: 0.67,
      questionInfoChartOption: null,
      courseTargetListChartOption: null,

      courseTargets: [],
      targetColumnCounts: [],
      studentScoreTable: [],
      downloading: false,
    };
  },
  methods: {
    cancel() {
      this.modalIsShow = false;
    },
    open() {
      this.modalIsShow = true;
    },
    resetData() {
      this.commonInfo = {};
      this.courseBasicInfo = {};
      this.paperStructs = [];
      this.questionInfoTable = [];
      this.courseTargetList = [];
      this.courseTargetValue = 0.67;
      this.questionInfoChartOption = null;
      this.courseTargetListChartOption = null;
      this.courseTargets = [];
      this.targetColumnCounts = [];
      this.studentScoreTable = [];
      this.downloading = false;
    },
    buildData(data) {
      this.commonInfo = data.commonInfo;
      this.courseBasicInfo = data.courseBasicInfo;

      this.courseTargetValue =
        data.courseEvaluationResultInfo.targetEvaluationSumValue;
      this.courseTargetList = data.courseEvaluationResultInfo.targetList.map(
        (target) => {
          target.normalTargetWeight = calcSum(
            target.evaluationList.slice(0, -1).map((elem) => elem.targetWeight)
          );
          return target;
        }
      );

      const {
        courseEvaluationSpreadInfo: { questionInfo, scoreList },
      } = data;
      this.parsePaperStructs(questionInfo);
      this.parseQuestionInfoTable(questionInfo);
      this.questionInfoChartOption = this.getQuestionInfoChartOption(scoreList);
      this.courseTargetListChartOption = this.getCourseTargetListChartOption();

      let examStudentList =
        data.courseEvaluationResultDetailInfo.examStudentList;
      examStudentList.pop();
      examStudentList.splice(examStudentList.length - 2, 1);

      this.parseCourseTargets(examStudentList);
      this.parseStudentScoreTable(examStudentList);
    },
    async initData() {
      this.resetData();

      await this.checkChange();
      const data = await targetReportDetail({
        examId: this.course.examId,
        courseCode: this.course.courseCode,
        teachCourseId: this.course.teachCourseId,
      });
      this.buildData(data);
    },
    async checkChange() {
      const res = await targetReportChangeCheck({
        examId: this.course.examId,
        courseCode: this.course.courseCode,
        teachCourseId: this.course.teachCourseId,
        report: true,
      });

      if (res.courseTargetChange) {
        this.$notify.warning("课程目标与已保存不一致，请重新设置权重！");
      }
      if (res.evaluationChange) {
        this.$notify.warning(
          "评价方式与已保存不一致，请重新设置权重及导入新的平时成绩！"
        );
      }
      if (res.targetScoreChange) {
        this.$notify.warning(res.targetScoreChangeStr);
      }
    },
    parsePaperStructs(questionInfo) {
      if (!questionInfo || !questionInfo.length) return;

      const structMap = {};
      questionInfo.forEach((item) => {
        if (!structMap[item.mainNumber]) {
          structMap[item.mainNumber] = [];
        }
        structMap[item.mainNumber].push(item.subNumber + "");
      });
      this.paperStructs = Object.keys(structMap).map((mainNumber) => {
        return {
          mainNumber,
          subNumbers: structMap[mainNumber],
        };
      });
    },
    parseQuestionInfoTable(questionInfo) {
      const targetMap = {};
      const tData = {
        name: "目标分值",
        totalScore: calcSum(questionInfo.map((item) => item.score || 0)),
      };
      questionInfo.forEach((question) => {
        const qno = `${question.mainNumber}_${question.subNumber}`;
        tData[qno] = question.score;

        question.targetList.forEach((target) => {
          if (!targetMap[target.targetId]) {
            targetMap[target.targetId] = {
              name: target.targetName,
              totalScore: 0,
            };
          }

          if (target.dimensionList.length) {
            targetMap[target.targetId][qno] = question.score;
            targetMap[target.targetId].totalScore += question.score;
          } else {
            targetMap[target.targetId][qno] = "";
          }
        });
      });

      this.questionInfoTable = [tData, ...Object.values(targetMap)];
    },
    getQuestionInfoChartOption(scoreList) {
      const scoreRange = scoreList.scoreRange.map((item) => {
        return {
          name: `${item.minScore}~${item.maxScore}`,
          value: item.rate,
        };
      });
      scoreRange.unshift({
        name: "不及格",
        value: scoreList.failRate,
      });

      let options = {
        color: ["#556dff", "#3A5AE5"],
        title: {
          text: "成绩分布图",
          left: "center",
        },
        grid: {
          left: 40,
          top: 60,
          right: 80,
          bottom: 40,
          containLabel: true,
        },
        xAxis: {
          type: "category",
          name: "成绩(分)",
          nameTextStyle: {
            color: "#363D59",
          },
          data: scoreRange.map((item) => item.name),
          axisLabel: {
            color: "#6F7482",
            interval: 0,
            fontSize: 12,
            margin: 12,
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: "#EFF0F5",
            },
          },
          splitLine: {
            show: false,
          },
          axisTick: {
            show: false,
          },
          axisPointer: {
            type: "shadow",
          },
        },
        yAxis: {
          type: "value",
          name: "百分比（%）",
          nameTextStyle: {
            color: "#363D59",
          },
          axisLabel: {
            color: "#6F7482",
          },
          axisLine: {
            lineStyle: {
              color: "#EFF0F5",
            },
          },
          splitLine: {
            lineStyle: {
              color: "#EFF0F5",
            },
          },
        },
        series: [
          {
            name: "占比",
            type: "bar",
            barWidth: 60,
            data: scoreRange.map((item) => item.value),
            label: {
              show: true,
              formatter: "{c}%",
              position: "top",
            },
          },
        ],
      };
      return options;
    },
    getCourseTargetListChartOption() {
      let options = {
        color: ["#556dff", "#f59a23"],
        title: {
          text: "课程目标达成评价值",
          left: "center",
        },
        grid: {
          left: 40,
          top: 40,
          right: 80,
          bottom: 30,
          containLabel: true,
        },
        legend: {
          top: 0,
          data: ["期望值", "达成值"],
          itemWidth: 12,
          itemHeight: 4,
          itemGap: 22,
          right: 40,
        },
        xAxis: {
          type: "category",
          name: "课程目标",
          nameTextStyle: {
            color: "#363D59",
          },
          data: this.courseTargetList.map((item) => item.targetName),
          axisLabel: {
            color: "#6F7482",
            interval: 0,
            fontSize: 12,
            margin: 12,
          },
          axisLine: {
            show: true,
            lineStyle: {
              color: "#EFF0F5",
            },
          },
          splitLine: {
            show: false,
          },
          axisTick: {
            show: false,
          },
          axisPointer: {
            type: "shadow",
          },
        },
        yAxis: {
          type: "value",
          name: "期望值",
          min: 0,
          max: 1,
          interval: 0.1,
          nameTextStyle: {
            color: "#363D59",
          },
          axisLabel: {
            color: "#6F7482",
          },
          axisLine: {
            lineStyle: {
              color: "#EFF0F5",
            },
          },
          splitLine: {
            lineStyle: {
              color: "#EFF0F5",
            },
          },
        },
        series: [
          {
            name: "达成值",
            type: "bar",
            barWidth: 60,
            data: this.courseTargetList.map((item) => item.evaluationValue),
            label: {
              show: true,
              position: "top",
            },
          },
          {
            name: "期望值",
            type: "line",
            symbol: "none",
            data: this.courseTargetList.map(
              (item) => this.courseBasicInfo.courseDegree || 0
            ),
          },
        ],
      };
      return options;
    },
    parseCourseTargets(examStudentList) {
      if (!examStudentList || !examStudentList.length) return;

      const targetList = examStudentList[0].targetList;
      const targetVals = {};
      this.courseTargetList.forEach((target) => {
        targetVals[target.targetId] = target.evaluationValue;
      });

      let tColumnCounts = [];
      this.courseTargets = targetList.map((target) => {
        const ntarget = {
          targetId: target.targetId,
          targetName: target.targetName,
          finalWeight: target.finalScore.targetWeight,
          usualWeight: target.usualScore.targetWeight,
          evaluationValue: targetVals[target.targetId],
        };
        ntarget.finalDimensions = ["期末成绩"];
        ntarget.usualWorks = target.usualScore.scoreList.map(
          (item) => item.evaluation
        );
        tColumnCounts.push(
          ntarget.finalDimensions.length + ntarget.usualWorks.length
        );
        return ntarget;
      });

      let tCount = 0;
      this.targetColumnCounts = tColumnCounts.map((item) => {
        tCount += item;
        return tCount;
      });
    },
    parseStudentScoreTable(examStudentList) {
      const lastIndex = examStudentList.length - 1;
      const studentScoreTable = examStudentList.map((student, sindex) => {
        const nitem = {
          name: student.name,
          studentCode: student.studentCode,
          score: student.score,
        };

        const finalScoreKey =
          lastIndex === sindex ? "matrixAvgScore" : "targetScoreSum";
        const workScoreKey = lastIndex === sindex ? "matrixAvgScore" : "score";

        student.targetList.forEach((target, index) => {
          nitem[`${target.targetId}-final`] = target.finalScore[finalScoreKey];

          target.usualScore.scoreList.forEach((work) => {
            nitem[`${target.targetId}-usual-${work.evaluation}`] =
              work[workScoreKey];
          });
        });
        return nitem;
      });

      const targetData = {
        name: "课程目标达成度",
        score: "",
      };
      this.courseTargets.forEach((target) => {
        targetData[`${target.targetId}-final`] = target.evaluationValue;
      });
      studentScoreTable.push(targetData);

      const fTarget = this.courseTargets[0];
      studentScoreTable.push({
        name: "课程达成度",
        [`${fTarget.targetId}-final`]: this.courseTargetValue,
      });
      this.studentScoreTable = studentScoreTable;
    },
    studentScoreSpanMethod({ row, column, rowIndex, columnIndex }) {
      const lineCount = this.studentScoreTable.length - 1;
      const maxTargetColumnCount = this.targetColumnCounts.slice(-1)[0];
      if (rowIndex === lineCount) {
        if (columnIndex === 0) {
          return [1, 2];
        } else if (columnIndex === 2) {
          return [1, maxTargetColumnCount + 1];
        } else {
          return [0, 0];
        }
      }
      if (rowIndex === lineCount - 1) {
        const colsMap = {};
        const targetColumns = [0, ...this.targetColumnCounts.slice(0, -1)];
        targetColumns.map((item, index) => {
          colsMap[item] = this.targetColumnCounts[index] - item;
        });
        if (columnIndex === 0) {
          return [1, 2];
        } else {
          if (targetColumns.includes(columnIndex - 2)) {
            return [1, colsMap[columnIndex - 2]];
          } else if (columnIndex < maxTargetColumnCount + 2) {
            return [0, 0];
          } else {
            return [1, 1];
          }
        }
      }
      if (rowIndex === lineCount - 2) {
        if (columnIndex === 0) {
          return [1, 2];
        } else if (columnIndex === 1) {
          return [0, 0];
        } else {
          return [1, 1];
        }
      }
    },
    async toSave() {
      if (this.downloading) return;
      this.downloading = true;

      const res = await targetReportSave({
        examId: this.course.examId,
        courseName: this.course.courseName,
        courseCode: this.course.courseCode,
        teachCourseId: this.course.teachCourseId,
        ...this.courseBasicInfo,
      }).catch(() => {});
      this.downloading = false;

      if (!res) return;
      this.$message.success("保存成功！");
      this.initData();
    },
    async toExport() {
      if (this.downloading) return;
      this.downloading = true;

      const res = await downloadByApi(() => {
        const datas = {
          examId: this.course.examId,
          courseCode: this.course.courseCode,
          teachCourseId: this.course.teachCourseId,
        };
        return exportTargetReport(datas);
      }).catch((e) => {
        this.$message.error(e || "下载失败，请重新尝试！");
      });
      this.downloading = false;

      if (!res) return;
      this.$message.success("下载成功！");
    },
  },
};
</script>

<style scoped>
.td-bg {
  color: #8b8fa1;
  font-weight: 500;
}
</style>
