Przeglądaj źródła

试卷列表调整,新增回收站

zhangjie 2 lat temu
rodzic
commit
308952fd9d

+ 18 - 0
src/modules/question/api.js

@@ -108,3 +108,21 @@ export function moveClassifyApi(movedClassifyId, targetClassifyId) {
     }
   );
 }
+
+// question-recycle
+export function questionRecycleListApi(data) {
+  return $httpWithMsg.post(
+    `${QUESTION_API}/question/recycle/list`,
+    {},
+    { params: data }
+  );
+}
+export function recoverQuestionApi(ids) {
+  return $httpWithMsg.post(`${QUESTION_API}/question/recycle/recover`, { ids });
+}
+export function thoroughDeleteQuestionApi(ids) {
+  return $httpWithMsg.post(`${QUESTION_API}/question/recycle/delete`, { ids });
+}
+export function clearQuestionRecycleApi() {
+  return $httpWithMsg.post(`${QUESTION_API}/question/recycle/clear`, {});
+}

+ 337 - 15
src/modules/question/components/FolderQuestionManageDialog.vue

@@ -1,32 +1,239 @@
 <template>
-  <el-dialog
-    :visible.sync="modalIsShow"
-    title="文件夹管理"
-    :modal="false"
-    :close-on-click-modal="false"
-    :close-on-press-escape="false"
-    append-to-body
-    fullscreen
-  >
-    <div class="folder-question">
-      <div class="folder-list">
-        <question-folder ref="QuestionFolder" is-edit></question-folder>
+  <div>
+    <el-dialog
+      :visible.sync="modalIsShow"
+      title="文件夹管理"
+      :modal="false"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      append-to-body
+      fullscreen
+    >
+      <div class="folder-question">
+        <div class="folder-list">
+          <question-folder
+            ref="QuestionFolder"
+            is-edit
+            @selected="folderFilterSelected"
+          ></question-folder>
+        </div>
+        <div class="question-list part-box">
+          <el-form class="part-filter-form" :inline="true" :model="filter">
+            <el-form-item label="课程名称">
+              <course-select v-model="filter.courseId" @change="courseChange">
+              </course-select>
+            </el-form-item>
+            <el-form-item label="题型">
+              <question-type-select v-model="filter.quesStructType">
+              </question-type-select>
+            </el-form-item>
+            <el-form-item label="属性名">
+              <property-select
+                v-model="filter.coursePropertyId"
+                :course-id="filter.courseId"
+              ></property-select>
+            </el-form-item>
+            <el-form-item label="一级属性">
+              <property-sub-select
+                v-model="filter.firstPropertyId"
+                :parent-id="filter.coursePropertyId"
+                data-type="first"
+              ></property-sub-select>
+            </el-form-item>
+            <el-form-item label="二级属性">
+              <property-sub-select
+                v-model="filter.secondPropertyId"
+                :parent-id="filter.firstPropertyId"
+                data-type="second"
+              ></property-sub-select>
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="danger" @click="toPage(1)">查询</el-button>
+            </el-form-item>
+          </el-form>
+
+          <div class="part-box-action">
+            <div>
+              <el-button type="primary" plain @click="toBatchMove"
+                >移动</el-button
+              >
+              <el-button type="danger" plain @click="toBatchCopy"
+                >复制</el-button
+              >
+              <el-button type="danger" plain @click="toBatchDelete"
+                >删除</el-button
+              >
+            </div>
+            <div></div>
+          </div>
+
+          <el-table
+            v-loading="loading"
+            element-loading-text="加载中"
+            :data="questionList"
+            @selection-change="tableSelectChange"
+          >
+            <el-table-column
+              type="selection"
+              width="50"
+              align="center"
+            ></el-table-column>
+            <el-table-column label="题干">
+              <template slot-scope="scope">
+                <rich-text
+                  class="row-question-body"
+                  title="点击查看试题"
+                  :text-json="scope.row.quesBody"
+                  @click="toViewQuestion(scope.row)"
+                ></rich-text>
+              </template>
+            </el-table-column>
+            <el-table-column label="课程" width="120">
+              <template slot-scope="scope">
+                <span>{{ scope.row.course.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="题型" width="100">
+              <template slot-scope="scope">
+                <span>{{ scope.row.questionType | questionType }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="难度" width="80"> </el-table-column>
+            <el-table-column label="使用量" width="80"> </el-table-column>
+            <el-table-column label="创建人" width="120">
+              <template slot-scope="scope">
+                <span>{{ scope.row.creator }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="创建时间" width="170" prop="creationTime">
+            </el-table-column>
+            <el-table-column label="操作" width="180" fixed="right">
+              <template slot-scope="scope">
+                <div class="operate_left">
+                  <el-button
+                    size="mini"
+                    type="primary"
+                    plain
+                    @click="toEditQuestion(scope.row)"
+                    >编辑</el-button
+                  >
+                  <el-dropdown>
+                    <el-button type="primary" size="mini" plain>
+                      更多 <i class="el-icon-more el-icon--right"></i>
+                    </el-button>
+                    <el-dropdown-menu slot="dropdown" class="action-dropdown">
+                      <el-dropdown-item>
+                        <el-button
+                          size="mini"
+                          type="primary"
+                          plain
+                          @click="toMoveQuestion(scope.row)"
+                          >移动</el-button
+                        >
+                      </el-dropdown-item>
+                      <el-dropdown-item>
+                        <el-button
+                          size="mini"
+                          type="primary"
+                          plain
+                          @click="toCopyQuestion(scope.row)"
+                          >复制</el-button
+                        >
+                      </el-dropdown-item>
+                      <el-dropdown-item>
+                        <el-button
+                          size="mini"
+                          type="danger"
+                          plain
+                          @click="toDeleteQuestion(scope.row)"
+                          >删除</el-button
+                        >
+                      </el-dropdown-item>
+                      <el-dropdown-item>
+                        <el-button
+                          size="mini"
+                          type="primary"
+                          plain
+                          @click="toLinkQuestion(scope.row)"
+                          >关联属性</el-button
+                        >
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </el-dropdown>
+                </div>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div class="part-page">
+            <el-pagination
+              :current-page="currentPage"
+              :page-size="pageSize"
+              :page-sizes="[10, 20, 50, 100, 200, 300]"
+              layout="total, sizes, prev, pager, next, jumper"
+              :total="total"
+              @current-change="toPage"
+              @size-change="handleSizeChange"
+            >
+            </el-pagination>
+          </div>
+        </div>
       </div>
-      <div class="question-list"></div>
-    </div>
-  </el-dialog>
+    </el-dialog>
+
+    <!-- QuestionEditDialog -->
+    <question-edit-dialog
+      ref="QuestionEditDialog"
+      :question="curQuestion"
+    ></question-edit-dialog>
+    <!-- QuestionFolderDialog -->
+    <question-folder-dialog
+      ref="QuestionFolderDialog"
+      :is-edit="false"
+      @selected="moveQuestion"
+    ></question-folder-dialog>
+  </div>
 </template>
 
 <script>
+import {
+  questionPageListApi,
+  deleteQuestionApi,
+  moveQuestionApi,
+  copyQuestionApi,
+} from "../api";
 import QuestionFolder from "./QuestionFolder.vue";
+import QuestionEditDialog from "./QuestionEditDialog.vue";
+import QuestionFolderDialog from "./QuestionFolderDialog.vue";
+
 export default {
   name: "FolderQuestionManageDialog",
   components: {
     QuestionFolder,
+    QuestionEditDialog,
+    QuestionFolderDialog,
   },
   data() {
     return {
       modalIsShow: false,
+      filter: {
+        classifyId: null,
+        courseId: "",
+        quesStructType: "",
+        coursePropertyId: "",
+        firstPropertyId: "",
+        secondPropertyId: "",
+      },
+      questionList: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 0,
+      loading: false,
+      curQuestion: {},
+      curMoveQids: [],
+      curFolder: {},
+      curMoveType: "",
+      selectedQuestionIds: [],
     };
   },
   methods: {
@@ -36,6 +243,121 @@ export default {
     open() {
       this.modalIsShow = true;
     },
+    toPage(page) {
+      this.currentPage = page;
+      this.getList();
+    },
+    async getList() {
+      this.selectedQuestionIds = [];
+      this.loading = true;
+      const res = await questionPageListApi({
+        ...this.filter,
+        curPage: this.currentPage,
+        pageSize: this.pageSize,
+      }).catch(() => {});
+      this.loading = false;
+      if (!res) return;
+      this.questionList = res.data.content;
+      this.total = res.data.totalElements;
+    },
+    handleSizeChange(val) {
+      this.pageSize = val;
+      this.toPage(1);
+    },
+    tableSelectChange(selections) {
+      this.selectedQuestionIds = selections.map((item) => item.id);
+    },
+    folderFilterSelected(folder) {
+      this.filter.classifyId = folder && folder.id;
+      this.toPage(1);
+    },
+    toViewQuestion(row) {
+      console.log(row);
+    },
+    toEditQuestion(row) {
+      console.log(row);
+      // todo:编辑试题
+      this.curQuestion = row;
+      this.$refs.QuestionEditDialog.open();
+    },
+    toMoveQuestion(row) {
+      this.curQuestion = row;
+      this.curMoveQids = [row.id];
+      this.$refs.QuestionFolderDialog.open();
+    },
+    async moveQuestion(folder) {
+      let res = null;
+      res = await moveQuestionApi(this.curMoveQids, folder.id).catch(() => {});
+
+      if (!res) return;
+      this.$message.success("操作成功!");
+      this.getList();
+    },
+    async toCopyQuestion(ids) {
+      const res = await copyQuestionApi(ids).catch(() => {});
+      if (!res) return;
+      this.$message.success("操作成功!");
+      this.getList();
+    },
+    async toDeleteQuestion(row) {
+      const confirm = await this.$confirm("确认删除试题吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.deleteQuestion([row.id]);
+    },
+    async deleteQuestion(ids) {
+      this.loading = true;
+      const res = await deleteQuestionApi(ids).catch((error) => {
+        this.$notify({
+          message: error.response.data.desc,
+          type: "error",
+        });
+      });
+
+      if (!res) return;
+
+      this.$notify({
+        message: "删除成功",
+        type: "success",
+      });
+      this.getList();
+    },
+    toBatchMove() {
+      if (!this.selectedQuestionIds.length) {
+        this.$message.error("请选择试题!");
+        return;
+      }
+      this.curMoveQids = [...this.selectedQuestionIds];
+    },
+    toBatchCopy() {
+      if (!this.selectedQuestionIds.length) {
+        this.$message.error("请选择试题!");
+        return;
+      }
+      this.toCopyQuestion(this.selectedQuestionIds);
+    },
+    async toBatchDelete() {
+      if (!this.selectedQuestionIds.length) {
+        this.$message.error("请选择试题!");
+        return;
+      }
+
+      const confirm = await this.$confirm("确认删除选中试题吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.deleteQuestion(this.selectedQuestionIds);
+    },
+    toLinkQuestion(row) {
+      console.log(row);
+    },
+    toAddFolder() {
+      this.curFolder = { parentId: this.filter.classifyId };
+      this.$refs.ModifyFolder.open();
+    },
   },
 };
 </script>

+ 6 - 0
src/modules/question/router.js

@@ -1,4 +1,5 @@
 import QuestionManage from "./views/QuestionManage";
+import QuestionRecycle from "./views/QuestionRecycle";
 
 export default [
   {
@@ -6,4 +7,9 @@ export default [
     name: "QuestionManage",
     component: QuestionManage,
   },
+  {
+    path: "/question-recycle",
+    name: "QuestionRecycle",
+    component: QuestionRecycle,
+  },
 ];

+ 7 - 0
src/modules/question/views/QuestionManage.vue

@@ -193,6 +193,8 @@
         >
         </el-pagination>
       </div>
+
+      <el-button type="danger" @click="toRecycle">回收站</el-button>
     </div>
 
     <!-- QuestionEditDialog -->
@@ -433,6 +435,11 @@ export default {
     folderModified() {
       this.getFolderList();
     },
+    toRecycle() {
+      this.$router.push({
+        name: "QuestionRecycle",
+      });
+    },
   },
 };
 </script>

+ 260 - 0
src/modules/question/views/QuestionRecycle.vue

@@ -0,0 +1,260 @@
+<template>
+  <div class="content question-recycle">
+    <div class="part-box">
+      <div class="part-box-header">
+        <h2 class="part-box-title">回收站</h2>
+
+        <el-button type="danger" plain @click="goback">返回</el-button>
+      </div>
+
+      <div class="part-box-action">
+        <div>
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-data-analysis"
+            @click="toBatchRecover"
+            >恢复</el-button
+          >
+          <el-button
+            type="danger"
+            plain
+            icon="el-icon-lock"
+            @click="toBatchDelete"
+            >删除</el-button
+          >
+        </div>
+        <div>
+          <el-button
+            type="primary"
+            plain
+            icon="el-icon-folder-opened"
+            @click="toClear"
+            >清空回收站</el-button
+          >
+        </div>
+      </div>
+    </div>
+
+    <div class="part-box">
+      <el-table
+        v-loading="loading"
+        element-loading-text="加载中"
+        :data="dataList"
+        @selection-change="tableSelectChange"
+      >
+        <el-table-column
+          type="selection"
+          width="50"
+          align="center"
+        ></el-table-column>
+        <el-table-column label="文件夹/试题">
+          <template slot-scope="scope">
+            <rich-text
+              class="row-question-body"
+              title="点击查看试题"
+              :text-json="scope.row.quesBody"
+              @click="toViewQuestion(scope.row)"
+            ></rich-text>
+          </template>
+        </el-table-column>
+        <el-table-column label="课程" width="120">
+          <template slot-scope="scope">
+            <span>{{ scope.row.course.name }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="题型" width="100">
+          <template slot-scope="scope">
+            <span>{{ scope.row.questionType | questionType }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作人" width="120">
+          <template slot-scope="scope">
+            <span>{{ scope.row.creator }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="删除时间" width="170" prop="creationTime">
+        </el-table-column>
+        <el-table-column label="操作" width="180" fixed="right">
+          <template slot-scope="scope">
+            <div class="operate_left">
+              <el-button
+                size="mini"
+                type="primary"
+                plain
+                @click="toRecover(scope.row)"
+                >恢复</el-button
+              >
+              <el-button
+                size="mini"
+                type="danger"
+                plain
+                @click="toDelete(scope.row)"
+                >删除</el-button
+              >
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="part-page">
+        <el-pagination
+          :current-page="currentPage"
+          :page-size="pageSize"
+          :page-sizes="[10, 20, 50, 100, 200, 300]"
+          layout="total, sizes, prev, pager, next, jumper"
+          :total="total"
+          @current-change="toPage"
+          @size-change="handleSizeChange"
+        >
+        </el-pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  questionRecycleListApi,
+  recoverQuestionApi,
+  thoroughDeleteQuestionApi,
+  clearQuestionRecycleApi,
+} from "../api";
+
+export default {
+  name: "QuestionRecycle",
+  data() {
+    return {
+      dataList: [],
+      currentPage: 1,
+      pageSize: 10,
+      total: 0,
+      selectedIds: [],
+    };
+  },
+  mounted() {
+    // this.toPage(1);
+  },
+  methods: {
+    toPage(page) {
+      this.currentPage = page;
+      this.getList();
+    },
+    async getList() {
+      this.selectedIds = [];
+      this.loading = true;
+      const res = await questionRecycleListApi({
+        curPage: this.currentPage,
+        pageSize: this.pageSize,
+      }).catch(() => {});
+      this.loading = false;
+      if (!res) return;
+      this.dataList = res.data.content;
+      this.total = res.data.totalElements;
+    },
+    tableSelectChange(selections) {
+      this.selectedIds = selections.map((item) => item.id);
+    },
+    async toClear() {
+      const confirm = await this.$confirm("确认要清空回收站吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.loading = true;
+      const res = await clearQuestionRecycleApi().catch((error) => {
+        this.$notify({
+          message: error.response.data.desc,
+          type: "error",
+        });
+      });
+
+      if (!res) return;
+
+      this.$notify({
+        message: "操作成功",
+        type: "success",
+      });
+      this.toPage(1);
+    },
+    async toDelete(row) {
+      const confirm = await this.$confirm("确认彻底删除数据吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.deleteData([row.id]);
+    },
+    async deleteData(ids) {
+      this.loading = true;
+      const res = await thoroughDeleteQuestionApi(ids).catch((error) => {
+        this.$notify({
+          message: error.response.data.desc,
+          type: "error",
+        });
+      });
+
+      if (!res) return;
+
+      this.$notify({
+        message: "删除成功",
+        type: "success",
+      });
+      this.getList();
+    },
+    async toBatchDelete() {
+      if (!this.selectedIds.length) {
+        this.$message.error("请选择数据!");
+        return;
+      }
+
+      const confirm = await this.$confirm("确认彻底删除选中数据吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.deleteData(this.selectedIds);
+    },
+    async toRecover(row) {
+      const confirm = await this.$confirm("确认恢复数据吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.recoverData([row.id]);
+    },
+    async recoverData(ids) {
+      this.loading = true;
+      const res = await recoverQuestionApi(ids).catch((error) => {
+        this.$notify({
+          message: error.response.data.desc,
+          type: "error",
+        });
+      });
+
+      if (!res) return;
+
+      this.$notify({
+        message: "操作成功",
+        type: "success",
+      });
+      this.getList();
+    },
+    async toBatchRecover() {
+      if (!this.selectedIds.length) {
+        this.$message.error("请选择数据!");
+        return;
+      }
+
+      const confirm = await this.$confirm("确认恢复选中数据吗?", "提示", {
+        type: "warning",
+      }).catch(() => {});
+      if (confirm !== "confirm") return;
+
+      this.recoverData(this.selectedIds);
+    },
+    toViewQuestion(row) {
+      console.log(row);
+    },
+  },
+};
+</script>