diff --git a/danger-manage-web/src/views/educationPlanExam/lessonsProgram/index.vue b/danger-manage-web/src/views/educationPlanExam/lessonsProgram/index.vue
index ceb7f0f8489ea393f5b44f8220a600b8eaf8b45b..10569ff3ee507a879d265f2800a015b9165d0274 100644
--- a/danger-manage-web/src/views/educationPlanExam/lessonsProgram/index.vue
+++ b/danger-manage-web/src/views/educationPlanExam/lessonsProgram/index.vue
@@ -74,7 +74,9 @@
         <template v-slot="scope">
           <div>
             {{
-              courseOptions.filter(
+              scope.row.courseType && courseOptions.filter(
+                (item) => item.planId == scope.row.courseType
+              )[0] && courseOptions.filter(
                 (item) => item.planId == scope.row.courseType
               )[0].planName
             }}
@@ -88,7 +90,7 @@
       </el-table-column>
       <el-table-column label="附件" align="center" prop="enclosure">
         <template v-slot="{ row: { enclosure } }">
-          <a v-if="enclosure.indexOf('.txt')>=0" @click="downloadText(enclosure)" class="down-load">下载附件</a>
+          <a v-if="enclosure && enclosure.indexOf('.txt')>=0" @click="downloadText(enclosure)" class="down-load">下载附件</a>
           <a v-else :href="enclosure" class="down-load">下载附件</a>
         </template>
       </el-table-column>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/components/AddQuestion.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/components/AddQuestion.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1cbe4e90166b486e6ef4840c382dbd8db783b21d
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/components/AddQuestion.vue
@@ -0,0 +1,333 @@
+<template>
+  <div ref="myBody" class="add-question flex">
+    <div class="text flex">
+      <div class="left">
+        目前录入题目是第<span>{{ questionNextNum }}</span
+        >道题
+      </div>
+      <div class="right">{{ courseName }}</div>
+    </div>
+
+    <el-form class="form flex" ref="form" :model="form" label-width="auto">
+      <!-- <div class="top flex"> -->
+      <div>
+        <el-form-item
+          label="题目内容"
+          prop="topicTitle"
+          :rules="{
+            required: true,
+            message: '必须输入题目内容',
+            trigger: 'blur',
+          }"
+        >
+          <el-input
+            type="textarea"
+            placeholder="多行输入"
+            resize="none"
+            rows="4"
+            v-model="form.topicTitle"
+          >
+          </el-input>
+        </el-form-item>
+      </div>
+
+      <div class="bottom">
+        <!-- <el-form-item label="选项1" prop="title">
+          <el-input v-model="form.title" placeholder="请输入"></el-input>
+        </el-form-item> -->
+        <el-form-item
+          v-for="(question, index) in form.questions"
+          :label="'选项' + (index + 1)"
+          :key="question.key"
+          :prop="'questions.' + index + '.value'"
+          :rules="
+            index === 0
+              ? {
+                  required: true,
+                  message: '第一项不能为空不能为空',
+                  trigger: 'blur',
+                }
+              : {}
+          "
+        >
+          <div class="add-select flex">
+            <el-input
+              type="textarea"
+              placeholder="多行输入"
+              style="flex: 1; margin-right: 10px"
+              rows="2"
+              v-model="question.value"
+            ></el-input>
+            <div class="flex algin-items">
+              <div
+                @click="rightAnswerClick(index)"
+                class="right"
+                :class="{ active: answerNum === index }"
+              >
+                设为正确答案
+              </div>
+              <el-button
+                size="mini"
+                type="danger"
+                v-if="index > 0"
+                @click.prevent="removeDomain(question)"
+                >删除</el-button
+              >
+            </div>
+          </div>
+        </el-form-item>
+
+        <el-form-item
+          class="noAttr"
+          :label="`选项${form.questions.length + 1}`"
+          prop=""
+        >
+          <div class="add-select flex">
+            <el-input
+              type="textarea"
+              placeholder="多行输入"
+              resize="none"
+              rows="2"
+              v-model="addValue"
+              style="flex: 1; margin-right: 10px"
+            >
+            </el-input>
+            <div class="flex algin-items">
+              <div
+                @click="rightAnswerClick(form.questions.length)"
+                class="right"
+                :class="{ active: answerNum === form.questions.length }"
+              >
+                设为正确答案
+              </div>
+
+              <el-button
+                size="mini"
+                type="primary"
+                @click.prevent="add(addValue)"
+                >新增</el-button
+              >
+            </div>
+          </div>
+        </el-form-item>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import {
+  addQuestion,
+  checkQuestion,
+  changeQuestion,
+  getQuestion,
+  getLessonById,
+} from "@/api/educationPlanExam/lessonsProgram.js";
+
+export default {
+  name: "AnswerLesson",
+  props: {
+    // visible: {
+    //   type: Boolean,
+    //   default: false,
+    // },
+    courseId: {
+      type: Number,
+    },
+    topicId: {
+      type: Number,
+    },
+  },
+  components: {},
+  data() {
+    return {
+      form: {
+        topicTitle: "",
+        questions: [{ value: "" }, { value: "" }, { value: "" }],
+      },
+      answerNum: null,
+      addValue: "",
+      // 录入的是第几道题
+      questionNextNum: 1,
+      courseName: "",
+    };
+  },
+
+  created() {
+    // 如果存在就是修改
+    if (this.topicId) {
+      checkQuestion(this.topicId).then((res) => {
+        console.log(res.data);
+        const data = res.data;
+        this.form = {
+          topicTitle: data.topicTitle,
+          questions: JSON.parse(data.topicOption),
+        };
+        this.answerNum = data.answer;
+      });
+    }
+
+    // 查询是第几道题
+    this.getQuestion();
+    // 获取课程标题
+    this.getLessonById(this.courseId);
+  },
+  methods: {
+    getQuestion() {
+      getQuestion({ courseId: this.courseId }).then((res) => {
+        this.questionNextNum = res.total + 1;
+      });
+    },
+    getLessonById(courseId) {
+      getLessonById(courseId).then((res) => {
+        console.log(res);
+        this.courseName = res.data.courseName;
+      });
+    },
+    addQuestion(data) {
+      // 如果是修改,就用修改的方法,如果是新增,就用新增的方法
+      if (this.topicId) {
+        return changeQuestion({ topicId: this.topicId, ...data });
+      } else {
+        return addQuestion({ courseId: this.courseId, ...data });
+      }
+    },
+    rightAnswerClick(index) {
+      this.answerNum = index;
+      console.log(index);
+    },
+    // 删除选项
+    removeDomain(question) {
+      const index = this.form.questions.indexOf(question);
+      // 如果是正确答案,就让正确答案清空
+      if (this.answerNum === index) {
+        this.answerNum = null;
+      }
+      if (index >= 0) {
+        this.form.questions.splice(index, 1);
+      }
+    },
+    // 新增选项
+    add(addValue) {
+      this.form.questions.push({ value: addValue });
+      console.log();
+    },
+    save(num = 2) {
+      return new Promise((resove) => {
+        if (!this.answerNum && this.answerNum !== 0) {
+          this.$message({
+            message: "警告,请设置一个正确答案",
+            type: "warning",
+          });
+          return resove(false);
+        }
+        this.$refs.form.validate((valid) => {
+          if (valid) {
+            const data = {};
+            data.topicTitle = this.form.topicTitle;
+            data.topicOption = JSON.stringify(this.form.questions);
+            data.answer = this.answerNum;
+            this.addQuestion(data).then((res) => {
+              if (res.code == 200) {
+                // 把修改的这个归位,变成正常添加
+                this.$emit("update:topicId", null);
+                this.$message({
+                  message: "添加题目成功",
+                  type: "success",
+                });
+                this.$parent.$parent.componentsNumChange(num);
+                this.$parent.$parent.$parent.getList();
+                resove(true);
+              }
+            });
+          }
+        });
+      });
+    },
+
+    saveAndNext() {
+      this.save(3).then((res) => {
+        if (res) {
+          this.reset();
+          this.questionNextNum++;
+        }
+      });
+    },
+    reset() {
+      this.form = {
+        topicTitle: "",
+        questions: [{ value: "" }, { value: "" }, { value: "" }],
+      };
+      this.answerNum = null;
+      this.addValue = "";
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.add-question {
+  width: 100%;
+  height: 550px;
+  // overflow: hidden;
+  flex-direction: column;
+  padding-bottom: 7px;
+  margin-bottom: 20px;
+  border-bottom: 1px solid #bbbbbb;
+  .form {
+    flex: 1;
+    flex-direction: column;
+    height: 100%;
+    .bottom {
+      overflow-y: auto;
+      height: 330px;
+      box-sizing: border-box;
+
+      .algin-items {
+        align-items: center;
+        width: 200px;
+      }
+      .right {
+        display: inline-block;
+        width: 133px;
+        margin-right: 10px;
+        line-height: initial;
+        padding: 4px 0;
+        border: 1px solid #bbbbbb;
+        color: #101010;
+        font-size: 12px;
+        text-align: center;
+        border-radius: 4px;
+        box-sizing: border-box;
+        cursor: pointer;
+        &.active {
+          background-color: #0bab0c;
+          color: #ffffff;
+        }
+        &:hover {
+          background-color: rgba(11, 171, 12, 0.5);
+          color: #ffffff;
+        }
+      }
+    }
+  }
+  .text {
+    margin-top: 13px;
+    margin-bottom: 34px;
+    justify-content: space-between;
+    height: 28px;
+    .left {
+      line-height: 28px;
+      color: #101010;
+      font-size: 14px;
+    }
+    .right {
+      width: 411px;
+      line-height: 28px;
+      background: #1d84ff;
+      padding-right: 5px;
+      color: #fff;
+      text-align: right;
+    }
+  }
+}
+</style>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/components/Dia.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Dia.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c0b88372aaf59a5d347701b130a195e6b3b4561c
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Dia.vue
@@ -0,0 +1,173 @@
+<!--
+ * @Author: 纪泽龙 jizelong@qq.com
+ * @Date: 2022-09-22 10:38:49
+ * @LastEditors: 纪泽龙 jizelong@qq.com
+ * @LastEditTime: 2022-09-28 17:48:07
+ * @FilePath: /danger-manage-web/src/views/lessonsProgram/components/addLesson.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <el-dialog
+    class="add-lession"
+    :title="title"
+    :visible.sync="visible"
+    width="1000px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    :before-close="dialogCancel"
+    @closed="closeFinished"
+    destroy-on-close
+  >
+    <div v-if="visible" ref="myBody" class="body">
+      <transition name="fade" mode="out-in">
+        <component
+          :is="currentComponent"
+          :courseId.sync="courseId"
+          :topicId.sync="topicId"
+          ref="current"
+        ></component>
+      </transition>
+      <!-- <Lesson ref='lesson'/> -->
+      <!-- <AddQuestion />
+      <QuestionList/> -->
+    </div>
+
+    <div slot="footer" class="dialog-footer">
+      <el-button
+        type="primary"
+        v-if="this.componentsNum == 1 || this.componentsNum == 3"
+        @click="save"
+        >保存</el-button
+      >
+
+      <el-button type="primary" @click="saveAndNext">{{
+        saveNextText
+      }}</el-button>
+      <el-button
+        v-if="this.componentsNum == 2"
+        type="primary"
+        @click="dialogCancel"
+        >{{ "确认" }}</el-button
+      >
+      <el-button @click="dialogCancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import Lesson from "./Lesson";
+import AddQuestion from "./AddQuestion";
+import QuestionList from "./QuestionList";
+
+export default {
+  name: "AnswerLesson",
+  props: {
+    visible: {
+      type: Boolean,
+      default: false,
+    },
+    componentsNum: {
+      type: Number,
+      default: 1,
+    },
+    courseId: {
+      type: Number,
+    },
+  },
+  // components: {
+  //   Lesson,
+  //   AddQuestion,
+  //   QuestionList,
+  // },
+
+  data() {
+    return {
+      title: "录入课程",
+      currentComponent: Lesson,
+      // 当前题目查看
+      topicId: null,
+    };
+  },
+  watch: {
+    componentsNum: {
+      handler(num) {
+        if (num === 1) {
+          this.currentComponent = Lesson;
+          if (this.courseId) {
+            this.title = "修改课程";
+          } else {
+            this.title = "新增课程";
+          }
+        } else if (num === 2) {
+          this.currentComponent = QuestionList;
+
+          this.title = "题目列表";
+        } else {
+          this.currentComponent = AddQuestion;
+          if (this.topicId) {
+            this.title = "修改题目";
+          } else {
+            this.title = "新增题目";
+          }
+        }
+      },
+      deep: true,
+    },
+  },
+  computed: {
+    saveNextText() {
+      let text;
+      if (this.componentsNum == 1) {
+        text = "保存并录入题目";
+      } else if (this.componentsNum == 2) {
+        text = "录入考题";
+      } else {
+        text = "保存并录入下一题";
+      }
+      return text;
+    },
+  },
+  methods: {
+    saveBody() {
+      this.startHeight = this.$refs.myBody.offsetHeight - 55 + "px";
+    },
+
+    closeFinished() {},
+    // 关闭之后
+    // 只保存
+    save() {
+      // this.answerClear();
+      this.$refs.current.save();
+    },
+    // 保存并录入
+    saveAndNext() {
+      this.$refs.current.saveAndNext();
+    },
+    // 隐藏与显示dialog
+    dialogCancel() {
+      this.$emit("update:visible", false);
+    },
+    // 把ID改变了
+    changeCourseId(courseId) {
+      this.$emit("update:courseId", courseId);
+    },
+    // 改变当前组件
+    componentsNumChange(num) {
+      this.$emit("update:componentsNum", num);
+    },
+
+    answerClear() {
+      this.answerArr = [];
+      this.changeCourseId(null);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.body {
+  width: 100%;
+  height: 100%;
+  padding-right: 40px;
+  padding-left: 36px;
+}
+</style>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/components/Editor.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Editor.vue
new file mode 100644
index 0000000000000000000000000000000000000000..10d09938d510894924327afe0d2cc9291093c961
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Editor.vue
@@ -0,0 +1,262 @@
+<template>
+  <div>
+    <el-upload
+      :action="uploadUrl"
+      :on-success="handleUploadSuccess"
+      :on-error="handleUploadError"
+      name="file"
+      :show-file-list="false"
+      :headers="headers"
+      style="display: none"
+      ref="upload"
+      v-if="this.uploadUrl"
+    >
+    </el-upload>
+    <div class="editor" ref="editor" :style="styles"></div>
+  </div>
+</template>
+
+<script>
+import Quill from "quill";
+import "quill/dist/quill.core.css";
+import "quill/dist/quill.snow.css";
+import "quill/dist/quill.bubble.css";
+import { getToken } from "@/utils/auth";
+
+export default {
+  name: "Editor",
+  props: {
+    /* 编辑器的内容 */
+    value: {
+      type: String,
+      default: "",
+    },
+    /* 高度 */
+    height: {
+      type: Number,
+      default: null,
+    },
+    /* 最小高度 */
+    minHeight: {
+      type: Number,
+      default: null,
+    },
+    /* 只读 */
+    readOnly: {
+      type: Boolean,
+      default: false,
+    },
+    /* 上传地址 */
+    uploadUrl: {
+      type: String,
+      default: "",
+    }
+  },
+  data() {
+    return {
+      headers: {
+        Authorization: "Bearer " + getToken()
+      },
+      Quill: null,
+      currentValue: "",
+      options: {
+        theme: "snow",
+        bounds: document.body,
+        debug: "warn",
+        modules: {
+          // 工具栏配置
+          toolbar: [
+            ["bold", "italic", "underline", "strike"],       // 加粗 斜体 下划线 删除线
+            ["blockquote", "code-block"],                    // 引用  代码块
+            [{ list: "ordered" }, { list: "bullet" }],       // 有序、无序列表
+            [{ indent: "-1" }, { indent: "+1" }],            // 缩进
+            [{ size: ["small", false, "large", "huge"] }],   // 字体大小
+            [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题
+            [{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色
+            [{ align: [] }],                                 // 对齐方式
+            ["clean"],                                       // 清除文本格式
+            ["link", "image"]                       // 链接、图片、视频"video"
+          ],
+        },
+        placeholder: "请输入内容",
+        readOnly: this.readOnly,
+      },
+    };
+  },
+  computed: {
+    styles() {
+      let style = {};
+      if (this.minHeight) {
+        style.minHeight = `${this.minHeight}px`;
+      }
+      if (this.height) {
+        style.height = `${this.height}px`;
+      }
+      return style;
+    },
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val !== this.currentValue) {
+          this.currentValue = val === null ? "" : val;
+          if (this.Quill) {
+            this.Quill.pasteHTML(this.currentValue);
+          }
+        }
+      
+      },
+      immediate: true,
+    },
+  },
+  mounted() {
+    this.init();
+  },
+  beforeDestroy() {
+    this.Quill = null;
+  },
+  methods: {
+    init() {
+      const editor = this.$refs.editor;
+      this.Quill = new Quill(editor, this.options);
+      // 如果设置了上传地址则自定义图片上传事件
+      if (this.uploadUrl) {
+        let toolbar = this.Quill.getModule("toolbar");
+        toolbar.addHandler("image", (value) => {
+          this.uploadType = "image";
+          if (value) {
+            this.$refs.upload.$children[0].$refs.input.click();
+          } else {
+            this.quill.format("image", false);
+          }
+        });
+        toolbar.addHandler("video", (value) => {
+          this.uploadType = "video";
+          if (value) {
+            this.$refs.upload.$children[0].$refs.input.click();
+          } else {
+            this.quill.format("video", false);
+          }
+        });
+      }
+      this.Quill.pasteHTML(this.currentValue);
+      this.Quill.on("text-change", (delta, oldDelta, source) => {
+        const html = this.$refs.editor.children[0].innerHTML;
+        const text = this.Quill.getText();
+        const quill = this.Quill;
+        this.currentValue = html;
+        this.$emit("input", html);
+        this.$emit("on-change", { html, text, quill });
+      });
+      this.Quill.on("text-change", (delta, oldDelta, source) => {
+        this.$emit("on-text-change", delta, oldDelta, source);
+      });
+      this.Quill.on("selection-change", (range, oldRange, source) => {
+        this.$emit("on-selection-change", range, oldRange, source);
+      });
+      this.Quill.on("editor-change", (eventName, ...args) => {
+        this.$emit("on-editor-change", eventName, ...args);
+      });
+    },
+    handleUploadSuccess(res, file) {
+      // 获取富文本组件实例
+      let quill = this.Quill;
+      // 如果上传成功
+      if (res.code == 200) {
+        // 获取光标所在位置
+        let length = quill.getSelection().index;
+        // 插入图片  res.url为服务器返回的图片地址
+        quill.insertEmbed(length, "image", res.url);
+        // 调整光标到最后
+        quill.setSelection(length + 1);
+      } else {
+        this.$message.error("图片插入失败");
+      }
+    },
+    handleUploadError() {
+      this.$message.error("图片插入失败");
+    },
+  },
+};
+</script>
+
+<style>
+.editor, .ql-toolbar {
+  white-space: pre-wrap !important;
+  line-height: normal !important;
+}
+.quill-img {
+  display: none;
+}
+.ql-snow .ql-tooltip[data-mode="link"]::before {
+  content: "请输入链接地址:";
+}
+.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
+  border-right: 0px;
+  content: "保存";
+  padding-right: 0px;
+}
+
+.ql-snow .ql-tooltip[data-mode="video"]::before {
+  content: "请输入视频地址:";
+}
+
+.ql-snow .ql-picker.ql-size .ql-picker-label::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item::before {
+  content: "14px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
+  content: "10px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
+  content: "18px";
+}
+.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
+.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
+  content: "32px";
+}
+
+.ql-snow .ql-picker.ql-header .ql-picker-label::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item::before {
+  content: "文本";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
+  content: "标题1";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
+  content: "标题2";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
+  content: "标题3";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
+  content: "标题4";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
+  content: "标题5";
+}
+.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
+.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
+  content: "标题6";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item::before {
+  content: "标准字体";
+}
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
+  content: "衬线字体";
+}
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
+  content: "等宽字体";
+}
+</style>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/components/Lesson.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Lesson.vue
new file mode 100644
index 0000000000000000000000000000000000000000..fb3d5b8073f6db00826c8e82c4d1c25d11b683b0
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/components/Lesson.vue
@@ -0,0 +1,264 @@
+<!--
+ * @Author: 纪泽龙 jizelong@qq.com
+ * @Date: 2022-09-22 10:59:44
+ * @LastEditors: 纪泽龙 jizelong@qq.com
+ * @LastEditTime: 2022-09-28 17:52:32
+ * @FilePath: /danger-manage-web/src/views/lessonsProgram/components/Lession.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div class="form-wrapper">
+    <el-form
+      class="form"
+      ref="form"
+      :model="form"
+      label-width="auto"
+      :rules="rules"
+    >
+      <div class="top flex">
+        <el-form-item label="课程标题" prop="courseName">
+          <el-input style="width: 500px" v-model="form.courseName"></el-input>
+        </el-form-item>
+
+        <el-form-item label="课程类型" prop="courseType">
+          <el-select
+            v-model="form.courseType"
+            placeholder="请选择隐患等级"
+            clearable
+            size="small"
+          >
+            <el-option
+              v-for="course in courseOptions"
+              :key="course.planId"
+              :label="course.planName"
+              :value="course.planId"
+            />
+          </el-select>
+        </el-form-item>
+      </div>
+
+      <!-- </div> -->
+      <el-form-item label="课程内容" prop="courseConent">
+        <Editor v-model="form.courseConent" :min-height="192" />
+        <el-input
+          v-show="false"
+          disabled
+          v-model="form.courseConent"
+        ></el-input>
+      </el-form-item>
+
+      <div class="flex">
+        <el-form-item label="视频上传" v-if="!readOnly" prop="video">
+          <FileUpload
+            listType="picture"
+            @resFun="getFileInfoVideo"
+            @remove="listRemoveVideo"
+            :fileArr="fileListVideo"
+            :fileSize="500"
+            :fileType="['mp4']"
+          />
+          <el-input v-show="false" disabled v-model="form.video"></el-input>
+        </el-form-item>
+        <el-form-item label="附件上传" v-if="!readOnly" prop="enclosure">
+          <FileUpload
+            listType="picture"
+            @resFun="getFileInfoFile"
+            @remove="listRemoveFile"
+            :fileArr="fileListFile"
+          />
+          <el-input v-show="false" disabled v-model="form.enclosure"></el-input>
+        </el-form-item>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import Editor from "./Editor";
+import FileUpload from "@/components/FileUpload";
+import uploadfile from "@/assets/uploadfile.png";
+import { mapGetters } from "vuex";
+import {
+  addLessons,
+  getLessonById,
+  changeLesson,
+} from "@/api/educationPlanExam/lessonsProgram";
+
+export default {
+  name: "",
+  props: {
+    courseId: {
+      type: Number,
+    },
+  },
+  components: {
+    Editor,
+    FileUpload,
+  },
+  data() {
+    return {
+      form: {
+        courseName: "",
+        courseType: "",
+        courseConent: "",
+        video: "",
+        enclosure: "",
+      },
+      fileListVideo: [],
+      fileListFile: [],
+      readOnly: false,
+      rules: {
+        courseName: [
+          { required: true, trigger: "blur", message: "课程名称不能为空" },
+        ],
+        courseType: [
+          { required: true, trigger: "change", message: "课程类型不能为空" },
+        ],
+        courseConent: [
+          { required: true, trigger: "blur", message: "课程内容不能为空" },
+        ],
+        video: [{ required: true, trigger: "blue", message: "视频不能为空" }],
+        enclosure: [
+          { required: true, trigger: "blur", message: "附件不能为空" },
+        ],
+      },
+    };
+  },
+  computed: {
+    // 获取课程类型
+    ...mapGetters(["courseOptions"]),
+  },
+  created() {
+    if (this.courseId) {
+      this.getLessonById();
+    }
+  },
+  mounted() {},
+  methods: {
+    // 添加课程
+    addLessons(data) {
+      console.log("this.courseId", this.courseId);
+      if (!this.courseId) {
+        console.log("添加");
+        return addLessons(data);
+      } else {
+        console.log("修改");
+        return changeLesson({ courseId: this.courseId, ...data });
+      }
+    },
+    // 复现
+    getLessonById() {
+      getLessonById(this.courseId).then((res) => {
+        if (res.code == 200) {
+          const data = res.data;
+          const { courseName, courseType, courseConent, video, enclosure } =
+            data;
+          this.form = {
+            courseName,
+            courseType,
+            courseConent,
+            video,
+            enclosure,
+          };
+          this.fileListVideo = [
+            {
+              name: courseName + "视频",
+              url: uploadfile,
+            },
+          ];
+          this.fileListFile = [
+            {
+              name: courseName + "附件",
+              url: uploadfile,
+            },
+          ];
+        }
+      });
+    },
+    getFileInfoVideo(res) {
+      this.form.video = res.url;
+      // this.form.videoName = res.fileName;
+      this.fileListVideo = [
+        {
+          name: res.fileName,
+          url: uploadfile,
+        },
+      ];
+    },
+    listRemoveVideo(e) {
+      this.fileListVideo = [];
+      this.form.video = "";
+      // this.form.videoName = null;
+    },
+    getFileInfoFile(res) {
+      this.form.enclosure = res.url;
+      // this.form.enclosureName = res.fileName;
+      this.fileListFile = [
+        {
+          name: res.fileName,
+          url: uploadfile,
+        },
+      ];
+    },
+    listRemoveFile(e) {
+      this.fileListFild = [];
+      this.form.enclosure = "";
+      // this.form.fileName = null;
+    },
+    save(num = 2) {
+      // 因为富文本编辑器会残留<p><br></p>,所以要清空
+      if (this.form.courseConent === "<p><br></p>") {
+        this.form.courseConent = "";
+      }
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          // console.log(this.form);
+          this.addLessons({ ...this.form }).then((res) => {
+            // 如果添加会传回来,就用传回来的,如果是修改本身就有,就用本身的
+            const courseId = res.data || this.courseId;
+            if (res.code == 200) {
+              // 这样调比较纯函数一点
+              if (num == 2) {
+                this.$message({
+                  message: "保存课程成功",
+                  type: "success",
+                });
+              } else if (num == 3) {
+                this.$message({
+                  message: "保存课程成功,请开始录入题目",
+                  type: "success",
+                });
+              }
+              this.$parent.$parent.componentsNumChange(num);
+              this.$parent.$parent.changeCourseId(courseId);
+              this.$parent.$parent.$parent.getList();
+
+              return true;
+            }
+          });
+        }
+      });
+    },
+    // 保存并进入题目
+    saveAndNext() {
+      this.save(3);
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.form-wrapper {
+  padding-top: 22px;
+  width: 100%;
+  height: 550px;
+  overflow: hidden;
+  // padding-bottom: 10px;
+  margin-bottom: 20px;
+
+  border-bottom: 1px solid #bbbbbb;
+  .top {
+    width: 100%;
+    justify-content: space-between;
+  }
+}
+</style>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/components/QuestionList.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/components/QuestionList.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1402105ce0945177002fb0bf3c4281e54a84ebac
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/components/QuestionList.vue
@@ -0,0 +1,327 @@
+<!--
+ * @Author: 纪泽龙 jizelong@qq.com
+ * @Date: 2022-09-22 17:56:05
+ * @LastEditors: 纪泽龙 jizelong@qq.com
+ * @LastEditTime: 2022-09-28 17:54:16
+ * @FilePath: /danger-manage-web/src/views/lessonsProgram/components/QuestionList.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<template>
+  <div ref="myBody" class="add-question flex">
+    <div class="text flex">
+      <div class="left">
+        目前有<span>{{ questionNum }}</span
+        >道题
+        <span class="warn">温馨提示:发布课程前需要进行考试设置</span>
+      </div>
+      <div class="right">{{courseName}}</div>
+    </div>
+    <div class="table flex" v-loading="loading">
+      <div class="th flex">
+        <div class="left">序号</div>
+        <div class="middle">题目名称</div>
+        <div class="right">操作</div>
+      </div>
+      <div class="td-wrapper">
+        <div
+          v-for="(item, index) in questionList"
+          :key="item.topicId"
+          class="td flex"
+        >
+          <div class="left">{{ index + 1 }}</div>
+          <div class="middle zzz">
+            {{ item.topicTitle }}
+          </div>
+          <div class="right">
+            <div>
+              <el-button
+                @click="edit(item.topicId)"
+                icon="el-icon-edit"
+                type="text"
+                >修改</el-button
+              >
+              <el-button
+                @click="deleteLesson(item.topicId)"
+                icon="el-icon-delete"
+                type="text"
+                >删除</el-button
+              >
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="rightNum flex">
+      <div class="left">考试设置</div>
+      <div class="middle flex">
+        <div class="left-text">答对题目大于</div>
+        <div>
+          <el-input
+            v-model="rightNum"
+            style="width: 60px"
+            size="mini"
+          ></el-input>
+        </div>
+        <div>为合格</div>
+      </div>
+      <div class="right">
+        <el-button
+          @click="saveRightNum"
+          icon="el-icon-check"
+          size="mini"
+          type="success"
+          >保存</el-button
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  getQuestion,
+  deleteQuestion,
+  changeLesson,
+  getLessonById,
+} from "@/api/educationPlanExam/lessonsProgram";
+export default {
+  name: "AnswerLesson",
+  props: {
+    courseId: {
+      type: Number,
+    },
+  },
+  components: {},
+  data() {
+    return {
+      // 当前课程的第几题,调一遍接口
+      questionNum: null,
+      // 答对几道题
+      rightNum: 0,
+      questionList: [],
+      loading: false,
+      courseName:'',
+    };
+  },
+  // watch: {
+  //   visible(newValue) {
+  //     if (newValue) {
+  //       this.$nextTick(() => {
+  //         this.saveBody();
+  //       });
+  //     }
+  //   },
+  // },
+
+  created() {
+    console.log("this.courseId", this.courseId);
+    if (this.courseId) {
+      this.getQuestion({ courseId: this.courseId });
+      // 获取只题目正确几题算过关
+      this.getLessonById(this.courseId);
+    }
+  },
+  methods: {
+    save() {
+      console.log("QuestionList");
+    },
+    saveAndNext() {
+      this.$parent.$parent.componentsNumChange(3);
+    },
+    getQuestion(courseId) {
+      return getQuestion(courseId).then((res) => {
+        console.log(res);
+
+        this.questionList = res.rows.map((item) => {
+          return {
+            topicId: item.topicId,
+            topicTitle: item.topicTitle,
+          };
+        });
+        this.questionNum = res.total;
+        return true;
+      });
+    },
+    getLessonById(courseId) {
+      getLessonById(courseId).then((res) => {
+        console.log(res);
+        this.rightNum = res.data.qualifiedNum;
+        this.courseName = res.data.courseName;
+      });
+    },
+    edit(topicId) {
+      this.$emit("update:topicId", topicId);
+      this.$parent.$parent.componentsNumChange(3);
+    },
+    deleteLesson(topicId) {
+      this.$confirm("请确定删除该题", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.loading = true;
+          return deleteQuestion(topicId);
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            this.$message({
+              message: "删除成功",
+              type: "success",
+            });
+          }
+          return this.getQuestion({ courseId: this.courseId });
+        })
+        .finally(() => {
+          this.loading = false;
+          // 课程列表重置一下
+          this.$parent.$parent.$parent.getList();
+        });
+    },
+    saveRightNum() {
+      if (this.rightNum > this.questionList.length) {
+        this.$message({
+          message: "答对题目数应小于等于考试题目总数",
+          type: "warning",
+        });
+        return;
+      }
+      changeLesson({ courseId: this.courseId, qualifiedNum: this.rightNum }).then(
+        (res) => {
+          if (res.code == 200) {
+            this.$message({
+              message: "答题合格数修改成功",
+              type: "success",
+            });
+          }
+        }
+      );
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.add-question {
+  width: 100%;
+  height: 550px;
+  // overflow: hidden;
+  flex-direction: column;
+  padding-bottom: 7px;
+  margin-bottom: 20px;
+  border-bottom: 1px solid #bbbbbb00;
+
+  .text {
+    margin-top: 13px;
+    margin-bottom: 32px;
+    justify-content: space-between;
+    height: 28px;
+    .left {
+      line-height: 28px;
+      color: #101010;
+      font-size: 14px;
+      .warn {
+        display: inline-flex;
+        font-size: 12px;
+        color: red;
+        margin-left: 10px;
+      }
+    }
+
+    .right {
+      width: 411px;
+      line-height: 28px;
+      background: #1d84ff;
+      padding-right: 5px;
+      color: #fff;
+      text-align: right;
+    }
+  }
+  .table {
+    flex: 1;
+    height: 0;
+
+    flex-direction: column;
+    .th {
+      width: 100%;
+      height: 70px;
+      line-height: 70px;
+      background: #f5f5f5;
+      color: #606266;
+
+      > div {
+        height: 100%;
+      }
+      .left {
+        width: 15%;
+        text-align: center;
+      }
+      .middle {
+        width: 60%;
+        padding-left: 100px;
+      }
+      .right {
+        width: 25%;
+        text-align: center;
+      }
+    }
+    .td-wrapper {
+      flex: 1;
+      overflow-y: auto;
+      // 这样子元素才能有滚动条
+      .td {
+        height: 68px;
+        line-height: 68px;
+        box-sizing: border-box;
+        border-bottom: 1px solid #bbbbbb;
+        &:last-child {
+          border-bottom: none;
+        }
+        > div {
+          height: 100%;
+        }
+        .left {
+          width: 15%;
+          text-align: center;
+        }
+        .middle {
+          width: 60%;
+          padding-left: 10px;
+        }
+        .right {
+          width: 25%;
+          text-align: center;
+        }
+      }
+    }
+  }
+  .rightNum {
+    margin-top: 5px;
+    height: 55px;
+    box-sizing: border-box;
+    border: 1px solid #bbbbbb;
+    line-height: 55px;
+    > .left {
+      width: 140px;
+      background: #0bab0c;
+      font-size: 14px;
+      color: #fff;
+      text-align: center;
+    }
+    > .middle {
+      > div {
+        margin-right: 5px;
+      }
+      .left-text {
+        margin-left: 10px;
+      }
+      .middle {
+        margin-right: 20px;
+      }
+    }
+    .right {
+      margin-left: 20px;
+    }
+    // background: black;
+  }
+}
+</style>
diff --git a/danger-manage-web/src/views/educationPlanExam/questionBank/index.vue b/danger-manage-web/src/views/educationPlanExam/questionBank/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..43b9c72f68caf58fa731b2be4f38505628158b30
--- /dev/null
+++ b/danger-manage-web/src/views/educationPlanExam/questionBank/index.vue
@@ -0,0 +1,449 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="课件类别" prop="courseType">
+        <el-select
+          v-model="queryParams.courseType"
+          placeholder="请选择课程类型"
+          clearable
+          size="small"
+        >
+          <el-option
+            v-for="course in courseOptions"
+            :key="course.planId"
+            :label="course.planName"
+            :value="course.planId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="名称" prop="courseName">
+        <el-input
+          v-model="queryParams.courseName"
+          placeholder="请输入课程名称"
+          clearable
+          size="small"
+        />
+      </el-form-item>
+      <el-form-item label="发布时间" prop="releaseTime">
+        <el-date-picker
+          v-model="queryParams.releaseTime"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          type="datetime"
+          placeholder="选择日期时间"
+          default-time="12:00:00"
+        >
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="search"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetClick"
+          >重置</el-button
+        >
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['system:book:add']"
+          >新增</el-button
+        >
+      </el-col>
+    </el-row>
+
+    <el-table v-loading="loading" :data="lessonsList">
+      <el-table-column label="课程标题" align="center" prop="courseName" />
+      <el-table-column label="课程类别" align="center" prop="courseType">
+        <template v-slot="scope">
+          <div>
+            {{
+              scope.row.courseType && courseOptions.filter(
+                (item) => item.planId == scope.row.courseType
+              )[0] && courseOptions.filter(
+                (item) => item.planId == scope.row.courseType
+              )[0].planName
+            }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="课程状态" align="center" prop="status">
+        <template v-slot="scope">
+          <div>{{ ["未发布", "已发布"][scope.row.status] }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="附件" align="center" prop="enclosure">
+        <template v-slot="{ row: { enclosure } }">
+          <a v-if="enclosure && enclosure.indexOf('.txt')>=0" @click="downloadText(enclosure)" class="down-load">下载附件</a>
+          <a v-else :href="enclosure" class="down-load">下载附件</a>
+        </template>
+      </el-table-column>
+      <el-table-column label="视频" align="center" prop="video">
+        <template v-slot="{ row: { courseName, video } }">
+          <a @click="downLoadVideo(video, courseName)" class="down-load"
+            >下载视频</a
+          >
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="发布时间"
+        align="center"
+        prop="releaseTime"
+        :formatter="formatter"
+      />
+      <el-table-column
+        label="考试题"
+        align="center"
+        prop="topicNum"
+        width="180"
+      >
+        <template v-slot="{ row: { topicNum, courseId } }">
+          <div @click="checkQuestion(courseId)" class="timuNum">
+            <div v-if="topicNum > 0">{{ `已录入${topicNum}题` }}</div>
+            <div v-else>未录入</div>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
+        <template v-slot="{ row: { status, courseId } }">
+          <!-- <div>{{status}}</div> -->
+          <el-button
+            v-if="status == 0"
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="changeLesson(courseId)"
+            >修改</el-button
+          >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="deletLesson(courseId)"
+            >删除</el-button
+          >
+          <el-button
+            v-if="status == 0"
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="issueLesson(courseId)"
+            >发布</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+    <Dia
+      ref="Dia"
+      :componentsNum.sync="componentsNum"
+      :courseId.sync="courseId"
+      :visible.sync="dilogFlag"
+    />
+  </div>
+</template>
+
+<script>
+import {
+  getLessons,
+  getLessonById,
+  issue,
+  deleteLesson,
+} from "@/api/educationPlanExam/lessonsProgram.js";
+// 获取课程类型
+import { getPlanList } from "@/api/educationPlanExam/trainingProgram";
+import { mapGetters, mapMutations } from "vuex";
+
+import Dia from "./components/Dia";
+
+export default {
+  name: "",
+  components: {
+    Dia,
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: false,
+      // 总条数
+      total: 0,
+      // courseOptions: [],
+      lessonsList: [],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        courseType: null,
+        courseName: null,
+        releaseTime: "",
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+
+      dilogFlag: false,
+      componentsNum: 1,
+      // 点击的id,如果是新增为空
+      courseId: null,
+    };
+  },
+  computed: {
+    ...mapGetters(["courseOptions"]),
+  },
+  created() {
+    this.getPlanList();
+    this.getList();
+  },
+
+  methods: {
+    ...mapMutations({ setOptions: "SET_COURSE_OPTIONS" }),
+    // 获取课程类别,也就是计划名称
+    getPlanList() {
+      getPlanList().then((res) => {
+        const courseOptions = res.data.map((item) => {
+          return {
+            planId: item.planId,
+            planName: item.planName,
+          };
+        });
+        // this.$store.commit("SET_COURSE_OPTIONS");
+        this.setOptions(courseOptions);
+      });
+    },
+
+    /** 查询课程列表 */
+    getList() {
+      this.loading = true;
+      getLessons(this.queryParams)
+        .then((res) => {
+          // console.log(res);
+          this.lessonsList = res.rows;
+          this.total = res.total;
+        })
+        .finally(() => {
+          this.loading = false;
+        });
+    },
+    search() {
+      // console.log(this.queryParams);
+      this.getList();
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.$refs.Dia.title = "新增课程";
+      this.componentsNum = 1;
+      this.courseId = null;
+      this.dilogFlag = true;
+    },
+    changeLesson(courseId) {
+      this.$refs.Dia.title = "修改课程";
+      this.componentsNum = 1;
+      this.courseId = courseId;
+      this.dilogFlag = true;
+    },
+
+    // 直接查看考题
+    checkQuestion(courseId) {
+      // 要查看考题的id
+      this.courseId = courseId;
+      console.log(this.courseId);
+      // 2代表列表组件
+      this.componentsNum = 2;
+      this.dilogFlag = true;
+    },
+    // 重置
+    resetClick() {
+      this.reset();
+      this.getList();
+    },
+    // 复位
+    reset() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        courseType: null,
+        courseName: null,
+        releaseTime: "",
+      };
+    },
+    deletLesson(courseId) {
+      this.$confirm("请确定删除", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          return deleteLesson(courseId);
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            this.$message({
+              message: "删除成功",
+              type: "success",
+            });
+          }
+          this.getList();
+        })
+        .catch(() => {});
+    },
+    // 发布
+    issueLesson(courseId) {
+      this.$confirm("请确定发布", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          // 判断是否录入答题合格数
+          return getLessonById(courseId);
+        })
+        .then((res) => {
+          if (res.data.qualifiedNum > 0) {
+            return true;
+          }
+        })
+        .then((res) => {
+          if (res) {
+            // 成功就发布
+            return issue({ courseId });
+          } else {
+            this.$message({
+              message: "请先录入答题合格数",
+              type: "warning",
+            });
+          }
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            this.$message({
+              message: "发布成功",
+              type: "success",
+            });
+            this.getList();
+          }
+        })
+        .catch(() => {});
+    },
+    formatter(row, column, cellValue, index) {
+      // console.log(row, column, cellValue, index);
+      if (!cellValue) return "-";
+      else return cellValue;
+    },
+    downloadText(url) {
+      // url = url.replace(/\\/g, "/");
+      const xhr = new XMLHttpRequest();
+      xhr.open("GET", url, true);
+      xhr.responseType = "blob";
+      //xhr.setRequestHeader('Authorization', 'Basic a2VybWl0Omtlcm1pdA==');
+      xhr.onload = function () {
+        if (xhr.readyState === 4 && xhr.status === 200) {
+          let blob = this.response;
+          console.log(blob);
+          // 转换一个blob链接
+          // 注: URL.createObjectURL() 静态方法会创建一个 DOMString(DOMString 是一个UTF-16字符串),
+          // 其中包含一个表示参数中给出的对象的URL。这个URL的生命周期和创建它的窗口中的document绑定
+          let downLoadUrl = window.URL.createObjectURL(
+            new Blob([blob], {
+              type: "txt",
+            })
+          );
+          // 视频的type是video/mp4,图片是image/jpeg
+          // 01.创建a标签
+          let a = document.createElement("a");
+          // 02.给a标签的属性download设定名称
+          a.download = name;
+          // 03.设置下载的文件名
+          a.href = downLoadUrl;
+          // 04.对a标签做一个隐藏处理
+          a.style.display = "none";
+          // 05.向文档中添加a标签
+          document.body.appendChild(a);
+          // 06.启动点击事件
+          a.click();
+          // 07.下载完毕删除此标签
+          a.remove();
+        }
+      };
+
+      xhr.send();
+    },
+    downLoadVideo(url, name) {
+      var xhr = new XMLHttpRequest();
+      xhr.open("GET", url, true);
+      xhr.responseType = "arraybuffer"; // 返回类型blob
+      xhr.onload = function () {
+        if (xhr.readyState === 4 && xhr.status === 200) {
+          let blob = this.response;
+          console.log(blob);
+          // 转换一个blob链接
+          // 注: URL.createObjectURL() 静态方法会创建一个 DOMString(DOMString 是一个UTF-16字符串),
+          // 其中包含一个表示参数中给出的对象的URL。这个URL的生命周期和创建它的窗口中的document绑定
+          let downLoadUrl = window.URL.createObjectURL(
+            new Blob([blob], {
+              type: "video/mp4",
+            })
+          );
+          // 视频的type是video/mp4,图片是image/jpeg
+          // 01.创建a标签
+          let a = document.createElement("a");
+          // 02.给a标签的属性download设定名称
+          a.download = name;
+          // 03.设置下载的文件名
+          a.href = downLoadUrl;
+          // 04.对a标签做一个隐藏处理
+          a.style.display = "none";
+          // 05.向文档中添加a标签
+          document.body.appendChild(a);
+          // 06.启动点击事件
+          a.click();
+          // 07.下载完毕删除此标签
+          a.remove();
+        }
+      };
+      xhr.send();
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.down-load {
+  color: #0bab0c;
+}
+.timuNum {
+  color: #1d84ff;
+  cursor: pointer;
+}
+::v-deep .el-select {
+  width: 100%;
+}
+::v-deep .el-dialog {
+  margin-top: 15vh !important;
+}
+</style>