Răsfoiți Sursa

专业目标页面

zhangjie 1 an în urmă
părinte
comite
365e6bddb0

+ 82 - 0
src/modules/course/api.js

@@ -134,3 +134,85 @@ export const documentSave = (datas) => {
 export const documentDelete = (id) => {
   return $postParam("/api/admin/mark/archive/document/delete", { id });
 };
+
+// 专业管理 ------------------->
+// 专业管理-列表查询
+export const professionalListPage = (datas) => {
+  return $postParam("/api/admin/professional/certification/page", datas);
+};
+// 专业管理-新增编辑
+export const professionalSave = (datas) => {
+  return $post("/api/admin/professional/certification/save", datas);
+};
+
+// 专业管理-课程管理
+// 专业管理-课程管理-列表查询
+export const professionalCourseListPage = (datas) => {
+  return $postParam("/api/admin/professional/certification/course/list", datas);
+};
+// 专业管理-课程管理-课程选择
+export const professionalCourseQueryList = (datas) => {
+  return $postParam(
+    "/api/admin/professional/certification/course/query_list",
+    datas
+  );
+};
+// 专业管理-课程管理-保存
+export const professionalCourseSave = (datas) => {
+  return $post("/api/admin/professional/certification/course/save", datas);
+};
+// 专业管理-课程管理-排序
+export const professionalCourseSort = (datas) => {
+  return $post("/api/admin/professional/certification/course/sort", datas);
+};
+// 专业管理-课程管理-删除
+export const professionalCourseRemove = (id) => {
+  return $postParam("/api/admin/professional/certification/course/remove", {
+    id,
+  });
+};
+
+// 专业管理-毕业要求管理
+// 专业管理-毕业要求管理-列表查询
+export const professionalRequirementListPage = (datas) => {
+  return $postParam(
+    "/api/admin/professional/certification/requirement/list",
+    datas
+  );
+};
+// 专业管理-毕业要求管理-保存
+export const professionalRequirementSave = (datas) => {
+  return $post("/api/admin/professional/certification/requirement/save", datas);
+};
+// 专业管理-毕业要求管理-排序
+export const professionalRequirementSort = (datas) => {
+  return $post("/api/admin/professional/certification/requirement/sort", datas);
+};
+// 专业管理-毕业要求管理-删除
+export const professionalRequirementRemove = (id) => {
+  return $post("/api/admin/professional/certification/requirement/remove", {
+    id,
+  });
+};
+
+// 专业管理-毕业支撑矩阵
+// 专业管理-毕业支撑矩阵-列表查询
+export const professionalMatrixDetail = (datas) => {
+  return $postParam("/api/admin/professional/certification/matrix/get", datas);
+};
+// 专业管理-毕业支撑矩阵-保存
+export const professionalMatrixSave = (datas) => {
+  return $post("/api/admin/professional/certification/matrix/save", datas, {
+    silence: true,
+  });
+};
+// 专业管理-毕业支撑矩阵-下载
+export const professionalMatrixDownload = (professionalId) => {
+  return $postParam(
+    "/api/admin/professional/certification/matrix/download",
+    { professionalId },
+    {
+      responseType: "blob",
+    }
+  );
+};

+ 120 - 0
src/modules/course/components/profession/AddProfessionalCourse.vue

@@ -0,0 +1,120 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    title="选择课程"
+    top="10vh"
+    width="500px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @opened="visibleChange"
+  >
+    <el-table
+      ref="TableList"
+      :data="dataList"
+      border
+      max-height="500px"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column
+        type="selection"
+        fixed="left"
+        width="55"
+        align="center"
+      ></el-table-column>
+      <el-table-column
+        type="index"
+        label="序号"
+        width="70"
+        :index="indexMethod"
+      ></el-table-column>
+      <el-table-column prop="name" label="姓名"></el-table-column>
+      <el-table-column prop="code" label="学号"></el-table-column>
+    </el-table>
+
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { professionalCourseQueryList, professionalCourseSave } from "../../api";
+
+export default {
+  name: "professional-course-add",
+  props: {
+    rowData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      dataList: [],
+      multipleSelection: [],
+      cacheOrgId: "",
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    visibleChange() {
+      this.getList();
+      this.$nextTick(() => {
+        this.$refs.TableList?.clearSelection();
+      });
+    },
+    async getList() {
+      if (this.cacheOrgId === this.rowData.orgId && this.dataList.length)
+        return;
+
+      this.dataList = [];
+      const data = await professionalCourseQueryList({
+        orgId: this.rowData.orgId,
+      });
+      this.dataList = data || [];
+      this.cacheOrgId = this.rowData.orgId;
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val;
+    },
+    async submit() {
+      if (!this.multipleSelection.length) {
+        this.$message.error("请选择课程!");
+        return;
+      }
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const data = await professionalCourseSave({
+        professionalId: this.rowData.id,
+        courses: this.multipleSelection.map((item) => {
+          return {
+            courseCode: item.courseCode,
+            courseName: item.courseName,
+          };
+        }),
+      }).catch(() => {});
+      this.isSubmit = false;
+
+      if (!data) return;
+      this.multipleSelection = [];
+      this.$message.success("选择成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+  },
+};
+</script>

+ 115 - 0
src/modules/course/components/profession/ModifyProfessional.vue

@@ -0,0 +1,115 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    :title="title"
+    top="10vh"
+    width="500px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <el-form
+      ref="modalFormComp"
+      :model="modalForm"
+      :key="modalForm.id"
+      label-width="100px"
+    >
+      <el-form-item prop="professionalName" label="专业名称:">
+        <el-input
+          v-model.trim="modalForm.professionalName"
+          placeholder="专业名称"
+          clearable
+        ></el-input>
+      </el-form-item>
+      <el-form-item prop="orgId" label="所属学院:">
+        <org-select
+          v-model="modalForm.orgId"
+          placeholder="所属学院"
+        ></org-select>
+      </el-form-item>
+    </el-form>
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { professionalSave } from "../../api";
+
+const initModalForm = {
+  id: null,
+  orgId: "",
+  professionalName: "",
+};
+
+export default {
+  name: "ModifyProfessional",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      modalForm: { ...initModalForm },
+      rules: {
+        professionalName: [
+          { required: true, message: "请输入专业名称", trigger: "change" },
+          {
+            message: "专业名称不能超过30个字",
+            max: 30,
+            trigger: "change",
+          },
+        ],
+        orgId: [
+          { required: true, message: "请选择所属学院", trigger: "change" },
+        ],
+      },
+    };
+  },
+  computed: {
+    isEdit() {
+      return !!this.instance.id;
+    },
+    title() {
+      return (this.isEdit ? "编辑" : "新增") + "专业";
+    },
+  },
+  methods: {
+    visibleChange() {
+      this.modalForm = this.$objAssign(initModalForm, this.instance);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      const data = await professionalSave(this.modalForm).catch(() => {});
+      this.isSubmit = false;
+
+      if (!data) return;
+
+      this.$message.success("修改成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+  },
+};
+</script>

+ 114 - 0
src/modules/course/components/profession/ModifyRequirement.vue

@@ -0,0 +1,114 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    :title="title"
+    top="10vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <el-form
+      ref="modalFormComp"
+      :model="modalForm"
+      :rules="rules"
+      label-width="100px"
+    >
+      <el-form-item prop="requirementName" label="毕业要求:">
+        <el-input
+          v-model.trim="modalForm.requirementName"
+          placeholder="请输入毕业要求"
+          clearable
+        ></el-input>
+      </el-form-item>
+    </el-form>
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { professionalRequirementSave } from "../../api";
+
+const initModalForm = {
+  id: null,
+  professionalId: "",
+  requirementName: "",
+};
+
+export default {
+  name: "modify-requirement",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  computed: {
+    isEdit() {
+      return !!this.instance.id;
+    },
+    title() {
+      return (this.isEdit ? "编辑" : "新增") + "毕业要求";
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      modalForm: { ...initModalForm },
+      rules: {
+        requirementName: [
+          {
+            required: true,
+            message: "请输入毕业要求",
+            trigger: "change",
+          },
+          {
+            message: "毕业要求不能超过50个字",
+            max: 50,
+            trigger: "change",
+          },
+        ],
+      },
+    };
+  },
+  methods: {
+    initData(val) {
+      this.modalForm = this.$objAssign(initModalForm, val);
+    },
+    visibleChange() {
+      this.initData(this.instance);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      const valid = await this.$refs.modalFormComp.validate().catch(() => {});
+      if (!valid) return;
+
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let datas = { ...this.modalForm };
+      const data = await professionalRequirementSave(datas).catch(() => {});
+      this.isSubmit = false;
+
+      if (!data) return;
+
+      this.$message.success(this.title + "成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+  },
+};
+</script>

+ 96 - 0
src/modules/course/components/profession/ModifyRequirementNode.vue

@@ -0,0 +1,96 @@
+<template>
+  <el-dialog
+    :visible.sync="modalIsShow"
+    :title="title"
+    top="10vh"
+    width="600px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    append-to-body
+    @open="visibleChange"
+  >
+    <el-form ref="modalFormComp" :model="modalForm" label-width="100px">
+      <el-form-item label="子节点数:">
+        <el-input-number
+          v-model="modalForm.nodeCount"
+          :min="0"
+          :max="10"
+          :step="1"
+          step-strictly
+          :controls="false"
+        ></el-input-number>
+      </el-form-item>
+    </el-form>
+    <div slot="footer">
+      <el-button type="primary" :disabled="isSubmit" @click="submit"
+        >确认</el-button
+      >
+      <el-button @click="cancel">取消</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { professionalRequirementSave } from "../../api";
+
+const initModalForm = {
+  id: null,
+  professionalId: "",
+  requirementName: "",
+  nodeCount: 0,
+};
+
+export default {
+  name: "modify-requirement-node",
+  props: {
+    instance: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  computed: {
+    isEdit() {
+      return !!this.instance.nodeCount;
+    },
+    title() {
+      return (this.isEdit ? "编辑" : "新增") + "子节点";
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      isSubmit: false,
+      modalForm: { ...initModalForm },
+    };
+  },
+  methods: {
+    initData(val) {
+      this.modalForm = this.$objAssign(initModalForm, val);
+    },
+    visibleChange() {
+      this.initData(this.instance);
+    },
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    async submit() {
+      if (this.isSubmit) return;
+      this.isSubmit = true;
+      let datas = { ...this.modalForm };
+      const data = await professionalRequirementSave(datas).catch(() => {});
+      this.isSubmit = false;
+
+      if (!data) return;
+
+      this.$message.success("操作成功!");
+      this.$emit("modified");
+      this.cancel();
+    },
+  },
+};
+</script>

+ 93 - 0
src/modules/course/components/profession/ProfessionalCourse.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="professional-course">
+    <div class="box-justify part-box part-box-pad">
+      <div>
+        <p class="tips-info">请根据开设专业选择课程</p>
+      </div>
+      <div>
+        <el-button type="primary" @click="toAdd">选择课程</el-button>
+      </div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table :data="dataList" border>
+        <el-table-column type="index" width="50"> </el-table-column>
+        <el-table-column label="课程(代码)">
+          <template slot-scope="scope">
+            {{ scope.row.courseName }}({{ scope.row.courseCode }})
+          </template>
+        </el-table-column>
+        <el-table-column class-name="action-column" label="操作" width="120px">
+          <template slot-scope="scope">
+            <el-button
+              class="btn-danger"
+              type="text"
+              @click="toDelete(scope.row)"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- AddProfessionalCourse -->
+    <add-professional-course
+      ref="AddProfessionalCourse"
+      :row-data="rowData"
+      @modified="getList"
+    ></add-professional-course>
+  </div>
+</template>
+
+<script>
+import {
+  professionalCourseListPage,
+  professionalCourseRemove,
+} from "../../api";
+
+import AddProfessionalCourse from "./AddProfessionalCourse.vue";
+
+export default {
+  name: "professional-course",
+  components: {
+    AddProfessionalCourse,
+  },
+  props: {
+    rowData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      dataList: [],
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const data = await professionalCourseListPage({
+        professionalId: this.rowData.id,
+      });
+      this.dataList = data || [];
+    },
+    toAdd() {
+      this.$refs.AddProfessionalCourse.open();
+    },
+    toDelete(row) {
+      this.$confirm(`确定要删除课程【${row.courseName}】吗?`, "提示", {
+        type: "warning",
+      })
+        .then(async () => {
+          await professionalCourseRemove(row.id);
+          this.$message.success("删除成功!");
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>

+ 84 - 0
src/modules/course/components/profession/ProfessionalDetail.vue

@@ -0,0 +1,84 @@
+<template>
+  <div class="professional-detail">
+    <el-dialog
+      class="page-dialog"
+      :visible.sync="modalIsShow"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      append-to-body
+      fullscreen
+    >
+      <div slot="title">{{ rowData.professionalName }}</div>
+      <div class="mb-4 tab-btns">
+        <el-button
+          v-for="tab in tabs"
+          :key="tab.val"
+          size="medium"
+          :type="curTab == tab.val ? 'primary' : 'default'"
+          @click="selectMenu(tab.val)"
+          >{{ tab.name }}
+        </el-button>
+      </div>
+
+      <div v-if="modalIsShow">
+        <component :is="curTab" :row-data="rowData"></component>
+      </div>
+
+      <div slot="footer"></div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import ProfessionalCourse from "./ProfessionalCourse.vue";
+import ProfessionalRequirement from "./ProfessionalRequirement.vue";
+import ProfessionalMatrix from "./ProfessionalMatrix.vue";
+
+export default {
+  name: "professional-detail",
+  components: {
+    ProfessionalCourse,
+    ProfessionalRequirement,
+    ProfessionalMatrix,
+  },
+  props: {
+    rowData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      modalIsShow: false,
+      curTab: "ProfessionalCourse",
+      tabs: [
+        {
+          name: "课程管理",
+          val: "ProfessionalCourse",
+        },
+        {
+          name: "毕业要求管理",
+          val: "ProfessionalRequirement",
+        },
+        {
+          name: "毕业支撑矩阵",
+          val: "ProfessionalMatrix",
+        },
+      ],
+    };
+  },
+  methods: {
+    cancel() {
+      this.modalIsShow = false;
+    },
+    open() {
+      this.modalIsShow = true;
+    },
+    selectMenu(tab) {
+      this.curTab = tab;
+    },
+  },
+};
+</script>

+ 177 - 0
src/modules/course/components/profession/ProfessionalMatrix.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="professional-matrix">
+    <div class="box-justify part-box part-box-pad">
+      <div>
+        <p class="tips-info">
+          {{ rowData.professionalName }}毕业要求支撑矩阵管理
+        </p>
+      </div>
+      <div>
+        <el-button type="success" :loading="loading" @click="toDownload"
+          >下载</el-button
+        >
+      </div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table :data="dataList" border>
+        <el-table-column label="课程名称">
+          <template slot-scope="scope">
+            {{ scope.row.courseName }}
+          </template>
+        </el-table-column>
+        <el-table-column label="毕业要求">
+          <el-table-column
+            v-for="(column, cindex) in columns"
+            :key="cindex"
+            :label="column.name"
+          >
+            <template v-if="hasSubRequirements">
+              <el-table-column
+                v-for="subr in column.subRequirements"
+                :key="subr"
+                :label="subr"
+              >
+                <template slot-scope="scope">
+                  <el-input-number
+                    v-model="scope.row[`${column.name}_${subr.name}`].value"
+                    class="width-50"
+                    :min="0"
+                    :max="1"
+                    :step="0.01"
+                    step-strictly
+                    :controls="false"
+                    @change="
+                      (val) =>
+                        unitChange(
+                          scope.row[`${column.name}_${subr.name}`].id,
+                          val
+                        )
+                    "
+                  ></el-input-number>
+                </template>
+              </el-table-column>
+            </template>
+            <template v-else>
+              <el-input-number
+                v-model="scope.row[`${column.name}_null`].value"
+                class="width-50"
+                :min="0"
+                :max="1"
+                :step="0.01"
+                step-strictly
+                :controls="false"
+                @change="
+                  (val) => unitChange(scope.row[`${column.name}_null`].id, val)
+                "
+              ></el-input-number>
+            </template>
+          </el-table-column>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- ProfessionalCourseAdd -->
+    <professional-course-add
+      ref="ProfessionalCourseAdd"
+      :row-data="rowData"
+      @modified="getList"
+    ></professional-course-add>
+  </div>
+</template>
+
+<script>
+import {
+  professionalMatrixDetail,
+  professionalMatrixSave,
+  professionalMatrixDownload,
+} from "../../api";
+import { downloadByApi } from "@/plugins/download";
+
+export default {
+  name: "professional-matrix",
+  props: {
+    rowData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      dataList: [],
+      columns: [],
+      hasSubRequirements: false,
+      loading: false,
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const res = await professionalMatrixDetail({
+        professionalId: this.rowData.id,
+      });
+      const tableData = res || [];
+      this.dataList = tableData.map((item, index) => {
+        if (!index) this.parseColumns(item.requirements);
+
+        const nitem = {
+          courseCode: item.courseCode,
+          courseName: item.courseName,
+        };
+        item.requirements.forEach((requirement) => {
+          requirement.subRequirements((subr) => {
+            nitem[`${requirement.name}_${subr.name + ""}`] = {
+              id: subr.id,
+              value: subr.content,
+            };
+          });
+        });
+
+        return nitem;
+      });
+    },
+    parseColumns(requirements) {
+      this.hasSubRequirements = requirements.some(
+        (item) => item.subRequirements[0].name !== null
+      );
+      if (!this.hasSubRequirements) {
+        this.columns = requirements.map((item) => {
+          return { name: item.name };
+        });
+        return;
+      }
+
+      this.columns = requirements.map((item) => {
+        return {
+          name: item.name,
+          subRequirements: item.subRequirements.map((subr) => subr.name),
+        };
+      });
+    },
+    async unitChange(id, val) {
+      await professionalMatrixSave({
+        id,
+        name: val,
+      });
+    },
+    async toDownload(row) {
+      if (this.loading) return;
+      this.loading = true;
+
+      const res = await downloadByApi(() => {
+        return professionalMatrixDownload(this.rowData.id);
+      }, "").catch((e) => {
+        this.$message.error(e || "下载失败,请重新尝试!");
+      });
+      this.loading = false;
+
+      if (!res) return;
+      this.$message.success("下载成功!");
+    },
+  },
+};
+</script>

+ 123 - 0
src/modules/course/components/profession/ProfessionalRequirement.vue

@@ -0,0 +1,123 @@
+<template>
+  <div class="professional-requirement">
+    <div class="box-justify part-box part-box-pad">
+      <div>
+        <p class="tips-info">
+          如果采用线下阅卷,请先导入试卷结构后再按模版导入期末成绩
+        </p>
+      </div>
+      <div>
+        <el-button type="primary" @click="toAdd">新增毕业要求</el-button>
+      </div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table :data="dataList" border>
+        <el-table-column type="index" width="50"> </el-table-column>
+        <el-table-column prop="requirementName" label="毕业要求">
+        </el-table-column>
+        <el-table-column prop="nodeCount" label="子节点"> </el-table-column>
+        <el-table-column class-name="action-column" label="操作" width="160px">
+          <template slot-scope="scope">
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toEditNode(scope.row)"
+              >子节点</el-button
+            >
+            <el-button
+              class="btn-primary"
+              type="text"
+              @click="toEdit(scope.row)"
+              >编辑</el-button
+            >
+            <el-button
+              class="btn-danger"
+              type="text"
+              @click="toDelete(scope.row)"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <!-- ModifyRequirement -->
+    <modify-requirement
+      ref="ModifyRequirement"
+      :instance="curRow"
+      @modified="getList"
+    ></modify-requirement>
+    <!-- ModifyRequirementNode -->
+    <modify-requirement-node
+      ref="ModifyRequirementNode"
+      :instance="curRow"
+      @modified="getList"
+    ></modify-requirement-node>
+  </div>
+</template>
+
+<script>
+import {
+  professionalRequirementListPage,
+  professionalRequirementRemove,
+} from "../../api";
+
+import ModifyRequirement from "./ModifyRequirement.vue";
+import ModifyRequirementNode from "./ModifyRequirementNode.vue";
+
+export default {
+  name: "professional-requirement",
+  components: {
+    ModifyRequirement,
+    ModifyRequirementNode,
+  },
+  props: {
+    rowData: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  data() {
+    return {
+      dataList: [],
+      curRow: {},
+    };
+  },
+  mounted() {
+    this.getList();
+  },
+  methods: {
+    async getList() {
+      const data = await professionalRequirementListPage({
+        professionalId: this.rowData.id,
+      });
+      this.dataList = data || [];
+    },
+    toAdd() {
+      this.curRow = { professionalId: this.rowData.id };
+      this.$refs.ModifyRequirement.open();
+    },
+    toEdit(row) {
+      this.curRow = { ...row, professionalId: this.rowData.id };
+      this.$refs.ModifyRequirement.open();
+    },
+    toEditNode(row) {
+      this.curRow = { ...row, professionalId: this.rowData.id };
+      this.$refs.ModifyRequirementNode.open();
+    },
+    toDelete(row) {
+      this.$confirm(`确定要删除毕业要求【${row.requirementName}】吗?`, "提示", {
+        type: "warning",
+      })
+        .then(async () => {
+          await professionalRequirementRemove(row.id);
+          this.$message.success("删除成功!");
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>

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

@@ -1,6 +1,7 @@
 import TargetScoreManage from "./views/TargetScoreManage.vue";
 import TargetReportManage from "./views/TargetReportManage.vue";
 import CourseDocumentManage from "./views/CourseDocumentManage.vue";
+import ProfessionalCertification from "./views/ProfessionalCertification.vue";
 
 export default [
   {
@@ -18,4 +19,9 @@ export default [
     name: "CourseDocumentManage",
     component: CourseDocumentManage,
   },
+  {
+    path: "/course/professional-certification",
+    name: "ProfessionalCertification",
+    component: ProfessionalCertification,
+  },
 ];

+ 162 - 0
src/modules/course/views/ProfessionalCertification.vue

@@ -0,0 +1,162 @@
+<template>
+  <div class="target-score-manage">
+    <div class="part-box part-box-filter part-box-flex">
+      <el-form ref="FilterForm" label-position="left" label-width="85px" inline>
+        <template v-if="checkPriv('condition', 'condition')">
+          <el-form-item label="所属学院:">
+            <org-select
+              v-model="filter.orgId"
+              placeholder="所属学院"
+            ></org-select>
+          </el-form-item>
+          <el-form-item label="关键词:" label-width="75px">
+            <el-input
+              v-model.trim="filter.professionalName"
+              placeholder="专业名称"
+              clearable
+            ></el-input>
+          </el-form-item>
+        </template>
+        <el-form-item label-width="0px">
+          <el-button
+            v-if="checkPrivilege('button', 'select')"
+            type="primary"
+            @click="search"
+            >查询</el-button
+          >
+        </el-form-item>
+      </el-form>
+      <div class="part-box-action">
+        <el-button
+          v-if="checkPrivilege('button', 'add')"
+          type="primary"
+          icon="el-icon-add"
+          @click="toAdd"
+          >新增</el-button
+        >
+      </div>
+    </div>
+
+    <div class="part-box part-box-pad">
+      <el-table ref="TableList" :data="dataList">
+        <el-table-column
+          type="index"
+          label="序号"
+          width="70"
+          :index="indexMethod"
+        ></el-table-column>
+        <el-table-column prop="professionalName" label="专业">
+        </el-table-column>
+        <el-table-column prop="orgName" label="所属学院"> </el-table-column>
+        <el-table-column prop="createName" label="创建人">
+          <span slot-scope="scope">
+            {{ scope.row.userName }}({{ scope.row.userLoginName }})
+          </span>
+        </el-table-column>
+        <!-- <el-table-column prop="createTime" label="创建时间">
+          <span slot-scope="scope">
+            {{ scope.row.createTime | timestampFilter }}
+          </span>
+        </el-table-column> -->
+        <el-table-column
+          class-name="action-column"
+          label="操作"
+          width="100"
+          fixed="right"
+        >
+          <template slot-scope="scope">
+            <el-button
+              v-if="checkPrivilege('link', 'CertificationManage')"
+              class="btn-primary"
+              type="text"
+              @click="toDetail(scope.row)"
+              >管理</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="part-page">
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :pager-count="5"
+          :current-page="current"
+          :total="total"
+          :page-size="size"
+          @current-change="toPage"
+          @size-change="pageSizeChange"
+        >
+        </el-pagination>
+      </div>
+    </div>
+    <!-- ProfessionalDetail -->
+    <professional-detail
+      v-if="checkPrivilege('link', 'CertificationManage')"
+      ref="ProfessionalDetail"
+      :row-data="curRow"
+    ></professional-detail>
+    <!-- ModifyProfessional -->
+    <modify-professional
+      v-if="checkPrivilege('button', 'add')"
+      ref="ModifyProfessional"
+      :instance="curRow"
+      @modified="getList"
+    ></modify-professional>
+  </div>
+</template>
+
+<script>
+import { professionalListPage } from "../api";
+import ProfessionalDetail from "../components/profession/ProfessionalDetail.vue";
+import ModifyProfessional from "../components/profession/ModifyProfessional.vue";
+
+export default {
+  name: "professional-manage",
+  components: { ProfessionalDetail, ModifyProfessional },
+  data() {
+    return {
+      filter: {
+        semesterId: "",
+        examId: "",
+        courseCode: "",
+      },
+      current: 1,
+      size: this.GLOBAL.pageSize,
+      total: 0,
+      dataList: [],
+      curRow: {},
+    };
+  },
+  methods: {
+    async getList() {
+      if (!this.checkPrivilege("list", "list")) return;
+
+      const datas = {
+        ...this.filter,
+        pageNumber: this.current,
+        pageSize: this.size,
+      };
+      const data = await professionalListPage(datas);
+      this.dataList = data.records;
+      this.total = data.total;
+    },
+    toPage(page) {
+      this.current = page;
+      this.getList();
+    },
+    search() {
+      this.toPage(1);
+    },
+    toAdd() {
+      this.curRow = {
+        orgId: this.$ls.get("orgId", ""),
+      };
+      this.$refs.ModifyProfessional.open();
+    },
+    toDetail(row) {
+      this.curRow = row;
+      this.$refs.ProfessionalDetail.open();
+    },
+  },
+};
+</script>

+ 1 - 1
src/plugins/axios.js

@@ -20,7 +20,7 @@ axios.defaults.timeout = GLOBAL.timeout;
 axios.interceptors.request.use(
   (config) => {
     // 显示loading提示
-    if (!queue.length) {
+    if (!queue.length && !config.silence) {
       load = Message({
         customClass: "el-message-loading",
         iconClass: "el-message__icon el-icon-loading",