<template>
  <div class="course-weight-manage">
    <div class="part-box part-box-pad">
      <p>说明：</p>
      <p>
        1.请在课程目标考核对应的评价方式表格中打√，并录入权重占比及目标分值；
      </p>
      <p>2.所有课程目标的总目标分值等于100分；</p>
      <p>3.各课程目标下评价方式的总权重应等于100%；</p>
      <p>4.目标整体权重应等于100%，用于计算课程整体达成度。</p>
    </div>
    <div class="part-box part-box-pad">
      <el-form class="mb-2" inline>
        <el-form-item label="整体权重设置："></el-form-item>
        <el-form-item label="平均成绩权重：">
          <el-input-number
            v-model="customRate"
            class="width-50"
            size="small"
            :min="0"
            :max="100"
            :step="1"
            step-strictly
            :controls="false"
          >
          </el-input-number>
          <span style="margin-left: 5px">%</span>
        </el-form-item>
        <el-form-item label="期末成绩权重：">
          <el-input-number
            v-model="defaultRate"
            class="width-50"
            size="small"
            :min="0"
            :max="100"
            :step="1"
            step-strictly
            :controls="false"
          >
          </el-input-number>
          <span style="margin-left: 5px">%</span>
        </el-form-item>
      </el-form>
      <el-table :data="tableSetData">
        <el-table-column
          prop="evaluationName"
          label="评价方式"
          width="140"
          fixed="left"
        ></el-table-column>
        <el-table-column v-for="(target, tindex) in dataList" :key="tindex">
          <template slot="header">
            <el-row type="flex" align="middle">
              <el-col :span="10" :offset="2">
                {{ target.courseTargetName }}
              </el-col>
              <el-col :span="12">
                <span style="margin-right: 5px">目标整体权重</span>
                <el-input-number
                  v-model="targetTotalWeight[target.courseTargetId]"
                  class="width-50"
                  size="small"
                  :min="0"
                  :max="100"
                  :step="1"
                  step-strictly
                  :controls="false"
                >
                </el-input-number>
                <span style="margin-left: 5px">%</span>
              </el-col>
            </el-row>
          </template>
          <el-table-column min-width="340">
            <template slot="header">
              <el-row>
                <el-col :span="10" :offset="2"> 权重 </el-col>
              </el-row>
            </template>
            <template slot-scope="scope">
              <el-row type="flex" align="middle">
                <el-col :span="2">
                  <el-checkbox
                    v-if="scope.$index !== endRowNo"
                    v-model="scope.row.targets[tindex].enable"
                    :disabled="scope.row.targets[tindex].disabled"
                    @change="enableChange(scope.$index, tindex)"
                  ></el-checkbox>
                </el-col>
                <el-col :span="10">
                  <span v-if="scope.$index === endRowNo">
                    {{ scope.row.targets[tindex].weight }}
                  </span>
                  <el-input-number
                    v-else
                    v-model="scope.row.targets[tindex].weight"
                    :disabled="!scope.row.targets[tindex].enable"
                    class="width-80"
                    size="small"
                    :min="0"
                    :max="100"
                    :step="1"
                    step-strictly
                    :controls="false"
                  >
                  </el-input-number>
                  <span style="margin-left: 5px">%</span>
                </el-col>
              </el-row>
            </template>
          </el-table-column>
        </el-table-column>
      </el-table>
      <div class="text-center" style="margin: 20px 0">
        <el-button type="primary" :loading="loading" @click="submit"
          >保存</el-button
        >
      </div>
      <el-table
        v-if="resultDataList.length && cwStatus.currentSettingStatus"
        :data="resultDataList"
        :header-cell-style="{ textAlign: 'center' }"
        :cell-style="{ textAlign: 'center' }"
        :span-method="spanMethod"
      >
        <el-table-column
          prop="courseTargetName"
          label="课程目标"
          width="140"
        ></el-table-column>
        <el-table-column
          prop="degreeRequirement"
          label="支撑毕业要求"
          min-width="200"
        ></el-table-column>
        <el-table-column prop="totalWeight" label="目标整体权重" width="110">
          <template slot-scope="scope">{{ scope.row.totalWeight }}%</template>
        </el-table-column>
        <el-table-column label="考核/评价环节及目标分值">
          <el-table-column
            v-for="(ename, eindex) in evaluationData"
            :key="ename"
            :label="ename"
          >
            <template slot-scope="scope">
              {{
                scope.row.evaluationList[eindex].enable
                  ? scope.row.evaluationList[eindex].targetScore
                  : ""
              }}
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column label="目标分值统计" width="120">
          <template slot-scope="scope">
            {{ getEvaluationSumScore(scope.row.evaluationList) }}
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import { courseWeightDetail, courseWeightSave } from "../../api";
import { omit, pick } from "lodash";
import { calcSum } from "@/plugins/utils";
import { mapState, mapActions } from "vuex";

export default {
  name: "course-weight-manage",
  props: {
    course: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      dataList: [],
      defaultRate: 0,
      customRate: 0,
      tableSetData: [],
      targetTotalWeight: {},
      evaluationData: [],
      resultDataList: [],
      loading: false,
    };
  },
  computed: {
    ...mapState("base", ["cwStatus"]),
    endRowNo() {
      return this.tableSetData.length - 1;
    },
  },
  mounted() {
    this.initData();
  },
  methods: {
    ...mapActions("base", ["updateCwStatus"]),
    async initData() {
      await this.updateCwStatus({
        teachCourseId: this.course.id,
      });
      await this.getList();
      if (this.cwStatus.currentSettingStatus) {
        this.updateResultDataList();
      }
    },
    async getList() {
      const res = await courseWeightDetail({
        teachCourseId: this.course.id,
      });
      this.defaultRate = res.defaultRate;
      this.customRate = res.customRate;
      this.dataList = res.submitForm || [];
      this.transformData(this.dataList);
    },
    transformData(data) {
      if (!data || !data.length) return [];

      const tableSetData = [];
      const evaluationMap = {};
      const targetTotalWeight = {};
      data[0].evaluationList.forEach((item, index) => {
        evaluationMap[item.evaluationName] = index;
      });

      this.evaluationData = data[0].evaluationList.map(
        (item) => item.evaluationName
      );

      data.forEach((target) => {
        targetTotalWeight[target.courseTargetId] = target.totalWeight;
        const targetData = {
          ...omit(target, ["evaluationList"]),
          totalWeight: target.totalWeight || 0,
        };

        target.evaluationList.forEach((item) => {
          const index = evaluationMap[item.evaluationName];
          if (!tableSetData[index]) {
            tableSetData[index] = {
              evaluationName: item.evaluationName,
              targets: [],
            };
          }
          tableSetData[index].targets.push({
            ...targetData,
            enable: item.enable,
            disabled: false,
            weight: item.weight || 0,
            targetScore: item.targetScore || 0,
          });
        });
      });

      this.targetTotalWeight = targetTotalWeight;
      this.tableSetData = tableSetData;
      this.updateSetDataDisabled();
    },
    updateSetDataDisabled() {
      this.tableSetData.forEach((item, tindex) => {
        const hasTargetWeight = item.targets.some((t) => t.weight);
        item.targets.forEach((t) => {
          if (hasTargetWeight) {
            t.disabled = !t.weight;
          } else {
            t.disabled = false;
          }
        });
      });
    },
    enableChange(rowIndex, tindex) {
      const target = this.tableSetData[rowIndex].targets[tindex];
      if (!target.enable) {
        target.weight = 0;
        target.targetScore = 0;
      }
      this.tableSetData[rowIndex].targets.forEach((item, dindex) => {
        if (dindex !== tindex) {
          item.disabled = target.enable;
        }
      });
    },
    getEvaluationSumScore(evaluationList) {
      return calcSum(
        evaluationList.map((item) => (item.enable ? item.targetScore : 0))
      );
    },
    spanMethod({ rowIndex, columnIndex }) {
      const lineCount = this.resultDataList.length - 1;
      if (rowIndex === lineCount) {
        if (columnIndex === 0) {
          return [1, 2];
        } else if (columnIndex === 1) {
          return [0, 0];
        }
      }
    },
    updateDataList() {
      const evaluationData = {};
      this.tableSetData.forEach((item) => {
        item.targets.forEach((elem) => {
          const key = `${item.evaluationName}_${elem.courseTargetId}`;
          evaluationData[key] = pick(elem, ["enable", "weight", "targetScore"]);
        });
      });

      this.dataList.forEach((target) => {
        target.totalWeight = this.targetTotalWeight[target.courseTargetId];
        target.evaluationList.forEach((item) => {
          const key = `${item.evaluationName}_${target.courseTargetId}`;
          Object.assign(item, evaluationData[key]);
        });
      });
    },
    updateResultDataList() {
      // 更新合计
      const tatolEvaluation = this.evaluationData.map(
        (evaluationName, eindex) => {
          const targetScore = calcSum(
            this.dataList.map(
              (item) => item.evaluationList[eindex].targetScore || 0
            )
          );
          return {
            evaluationName,
            enable: true,
            weight: null,
            targetScore,
          };
        }
      );
      this.resultDataList = [
        ...this.dataList,
        {
          courseTargetId: "total",
          courseTargetName: "合计",
          degreeRequirement: "",
          totalWeight: calcSum(
            this.dataList.map((item) => item.totalWeight || 0)
          ),
          evaluationList: tatolEvaluation,
        },
      ];
    },
    checkDataList() {
      if (!this.dataList.length) return;

      // 整体权重设置
      if (!this.customRate) {
        this.$message.error("请输入平均成绩权重");
        return;
      }
      if (!this.defaultRate) {
        this.$message.error("请输入期末成绩权重");
        return;
      }
      if (this.defaultRate + this.customRate !== 100) {
        this.$message.error("平均成绩权重与期末成绩权重合计不等于100%");
        return;
      }

      // 目标整体权重
      if (Object.values(this.targetTotalWeight).some((item) => !item)) {
        this.$message.error("请设置所有目标的目标整体权重");
        return;
      }
      const totalWeight = calcSum(
        Object.values(this.targetTotalWeight).map((item) => item || 0)
      );
      if (totalWeight !== 100) {
        this.$message.error("目标整体权重合计不等于100%");
        return;
      }

      // 目标权重统计
      const unvalidTargets = [];
      const tableData = this.tableSetData.slice(0, -1);
      this.dataList.forEach((target, tindex) => {
        const totalWeight = calcSum(
          tableData.map((item) => item.targets[tindex].weight || 0)
        );
        if (totalWeight !== 100) {
          unvalidTargets.push(target.courseTargetName);
        }
      });
      if (unvalidTargets.length) {
        this.$message.error(
          `${unvalidTargets.join()}评价方式权重合计不等于100%`
        );
        return;
      }

      return true;
    },
    async submit() {
      if (this.loading) return;
      this.updateDataList();

      if (!this.checkDataList()) return;

      this.loading = true;
      const res = await courseWeightSave({
        teachCourseId: this.course.id,
        defaultRate: this.defaultRate,
        customRate: this.customRate,
        submitForm: this.dataList,
      }).catch(() => {});
      this.loading = false;
      if (!res) return;

      this.initData();
      this.$message.success("保存成功！");
    },
  },
};
</script>
