zhangjie hace 1 año
padre
commit
235d114dea

+ 17 - 0
src/assets/styles/common-comp.scss

@@ -450,3 +450,20 @@ $--cc-labels-pre: cc-labels;
     }
   }
 }
+
+// drag-table
+.drag-table {
+  .after-drop {
+    td {
+      border-bottom: 2px solid $--color-primary;
+    }
+  }
+  .before-drop {
+    td {
+      border-top: 2px solid $--color-primary;
+    }
+  }
+  .drag-handle {
+    cursor: move;
+  }
+}

+ 1 - 1
src/assets/styles/element-ui-costom.scss

@@ -311,7 +311,7 @@
   }
   td,
   th {
-    border-color: $--color-border !important;
+    border-color: $--color-border-bold !important;
     padding: 14px 0;
     font-weight: 500;
   }

+ 1 - 0
src/assets/styles/home.scss

@@ -102,6 +102,7 @@
       display: block;
       max-width: 160px;
       max-height: 40px;
+      margin: 0 auto;
     }
   }
 

+ 9 - 0
src/assets/styles/pages.scss

@@ -1555,3 +1555,12 @@
     }
   }
 }
+
+// professional-matrix
+.professional-matrix {
+  .el-input-number .el-input__inner {
+    padding-left: 5px;
+    padding-right: 5px;
+    border-radius: 4px;
+  }
+}

+ 189 - 0
src/components/DragTable.vue

@@ -0,0 +1,189 @@
+<template>
+  <table class="table table-tiny drag-table">
+    <colgroup>
+      <col width="20" />
+      <col v-for="column in columns" :key="column.prop" :width="column.width" />
+    </colgroup>
+    <thead>
+      <tr>
+        <th></th>
+        <th v-for="column in columns" :key="column.prop">
+          {{ column.label }}
+        </th>
+      </tr>
+    </thead>
+    <tbody
+      class="drag-table-tbody"
+      @drop.prevent="dropInnerElement"
+      @dragover.prevent="dragOver($event)"
+      @dragleave.prevent
+    >
+      <tr
+        v-for="row in tableData"
+        :key="row.$key"
+        :id="row.$key"
+        :class="[
+          'drag-table-row',
+          {
+            'after-drop': row.$key === curDropRow.$key && isDragDown,
+            'before-drop': row.$key === curDropRow.$key && !isDragDown,
+          },
+        ]"
+        draggable="false"
+        @dragstart="($event) => dragStart($event, row)"
+        @dragend.prevent="dragEnd"
+      >
+        <td
+          class="drag-handle"
+          @mousedown.stop="dragHandleMousedown"
+          @mouseup.stop="dragHandleMouseup"
+        >
+          <div class="drag-handle">1</div>
+        </td>
+        <td v-for="column in columns" :key="column.prop">
+          <slot :name="column.prop" v-bind:row="row">
+            {{ row[column.prop] }}
+          </slot>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+</template>
+
+<script>
+import { randomCode } from "@/plugins/utils";
+
+export default {
+  name: "drag-table",
+  props: {
+    data: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    columns: {
+      type: Array,
+      default() {
+        // {label,prop,width?}[]
+        return [];
+      },
+    },
+    sortField: {
+      type: String,
+      default: "sortNum",
+    },
+  },
+  data() {
+    return {
+      tableData: [],
+      curDragRow: {},
+      curDropRow: {},
+      dragStartPageY: null,
+      isDragDown: false,
+    };
+  },
+  methods: {
+    buildData(val) {
+      if (!val) {
+        this.tableData = [];
+        return;
+      }
+
+      this.tableData = val.map((item) => {
+        return {
+          ...item,
+          $key: randomCode(),
+        };
+      });
+    },
+    getRelateElement(dom) {
+      let element = null;
+      let parentNode = dom;
+      while (!element && !parentNode.className.includes("drag-table-tbody")) {
+        if (!element && parentNode["id"]) {
+          element = parentNode;
+        } else {
+          parentNode = parentNode.parentNode;
+        }
+      }
+
+      return element;
+    },
+    getSiblingRow(targetKey, offset) {
+      const pos = this.tableData.findIndex((row) => row.$key === targetKey);
+      return this.tableData[pos + offset] || null;
+    },
+    dragStart(e, row) {
+      this.dragStartPageY = e.pageY;
+      this.curDragRow = row;
+    },
+    dragOver(e) {
+      // console.log(e.target);
+      this.isDragDown = e.pageY > this.dragStartPageY;
+      if (e.target.className.includes("drag-table-tbody")) {
+        this.curDropRow = this.isDragDown
+          ? this.tableData.slice(-1)[0]
+          : this.tableData[0];
+        return;
+      }
+
+      const elementDom = this.getRelateElement(e.target);
+      if (!elementDom) return;
+
+      const targetKey = elementDom.id;
+      this.curDropRow = this.getSiblingRow(targetKey, 0);
+    },
+    dropInnerElement() {
+      // console.log(this.curDragRow.id, this.curDropRowId);
+      if (this.curDragRow.id === this.curDropRow.id || !this.curDropRow) return;
+
+      // 往下:target上一个位置
+      // 往上:target下一个位置
+      this.moveElementToElement({
+        curRow: this.curDragRow,
+        toRow: this.curDropRow,
+        isDragDown: this.isDragDown,
+      });
+    },
+    dragEnd(e) {
+      e.target.setAttribute("draggable", false);
+      this.curDragRow = {};
+      this.curDropRow = {};
+      this.dragStartPageY = null;
+      this.isDragDown = false;
+    },
+    moveElementToElement({ curRow, toRow, isDragDown }) {
+      const curPos = this.tableData.findIndex(
+        (row) => row.$key === curRow.$key
+      );
+      this.tableData.splice(curPos, 1);
+
+      const toPos = this.tableData.findIndex((row) => row.$key === toRow.$key);
+      const offset = isDragDown ? 1 : 0;
+      this.tableData.splice(toPos + offset, 0, curRow);
+
+      this.tableData.forEach((row, index) => {
+        row[this.sortField] = index + 1;
+      });
+      this.$emit("sort-change", this.tableData);
+    },
+    dragHandleMousedown(e) {
+      const elementDom = this.getRelateElement(e.target);
+      elementDom.setAttribute("draggable", true);
+    },
+    dragHandleMouseup(e) {
+      const elementDom = this.getRelateElement(e.target);
+      elementDom.setAttribute("draggable", false);
+    },
+  },
+  watch: {
+    data: {
+      handler(val) {
+        this.buildData(val);
+      },
+      immediate: true,
+    },
+  },
+};
+</script>

+ 6 - 3
src/modules/course/api.js

@@ -190,9 +190,12 @@ export const professionalRequirementSort = (datas) => {
 };
 // 专业管理-毕业要求管理-删除
 export const professionalRequirementRemove = (id) => {
-  return $post("/api/admin/professional/certification/requirement/remove", {
-    id,
-  });
+  return $postParam(
+    "/api/admin/professional/certification/requirement/remove",
+    {
+      id,
+    }
+  );
 };
 
 // 专业管理-毕业支撑矩阵

+ 41 - 11
src/modules/course/components/profession/AddProfessionalCourse.vue

@@ -3,12 +3,24 @@
     :visible.sync="modalIsShow"
     title="选择课程"
     top="10vh"
-    width="500px"
+    width="800px"
     :close-on-click-modal="false"
     :close-on-press-escape="false"
     append-to-body
     @opened="visibleChange"
   >
+    <el-form ref="FilterForm" label-position="left" inline label-width="0px">
+      <el-form-item>
+        <org-select v-model="filter.orgId" placeholder="开课学院"></org-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" :disabled="!canSearch" @click="getList"
+          >查询</el-button
+        >
+      </el-form-item>
+    </el-form>
+
     <el-table
       ref="TableList"
       :data="dataList"
@@ -21,6 +33,7 @@
         fixed="left"
         width="55"
         align="center"
+        :selectable="(row) => row.canSelect"
       ></el-table-column>
       <el-table-column
         type="index"
@@ -28,8 +41,21 @@
         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-column
+        prop="courseName"
+        label="课程名称"
+        min-width="120"
+      ></el-table-column>
+      <el-table-column
+        prop="courseCode"
+        label="课程编码"
+        min-width="120"
+      ></el-table-column>
+      <el-table-column
+        prop="orgName"
+        label="开课学院"
+        min-width="120"
+      ></el-table-column>
     </el-table>
 
     <div slot="footer">
@@ -54,13 +80,21 @@ export default {
       },
     },
   },
+  computed: {
+    canSearch() {
+      return this.filter.orgId;
+    },
+  },
   data() {
     return {
       modalIsShow: false,
+      filter: {
+        professionalId: "",
+        orgId: "",
+      },
       isSubmit: false,
       dataList: [],
       multipleSelection: [],
-      cacheOrgId: "",
     };
   },
   methods: {
@@ -71,21 +105,17 @@ export default {
       this.modalIsShow = true;
     },
     visibleChange() {
+      this.filter.orgId = this.rowData.orgId;
+      this.filter.professionalId = this.rowData.id;
       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,
-      });
+      const data = await professionalCourseQueryList(this.filter);
       this.dataList = data || [];
-      this.cacheOrgId = this.rowData.orgId;
     },
     handleSelectionChange(val) {
       this.multipleSelection = val;

+ 4 - 4
src/modules/course/components/profession/ModifyProfessional.vue

@@ -15,9 +15,9 @@
       :key="modalForm.id"
       label-width="100px"
     >
-      <el-form-item prop="professionalName" label="专业名称:">
+      <el-form-item prop="name" label="专业名称:">
         <el-input
-          v-model.trim="modalForm.professionalName"
+          v-model.trim="modalForm.name"
           placeholder="专业名称"
           clearable
         ></el-input>
@@ -44,7 +44,7 @@ import { professionalSave } from "../../api";
 const initModalForm = {
   id: null,
   orgId: "",
-  professionalName: "",
+  name: "",
 };
 
 export default {
@@ -63,7 +63,7 @@ export default {
       isSubmit: false,
       modalForm: { ...initModalForm },
       rules: {
-        professionalName: [
+        name: [
           { required: true, message: "请输入专业名称", trigger: "change" },
           {
             message: "专业名称不能超过30个字",

+ 8 - 7
src/modules/course/components/profession/ModifyRequirement.vue

@@ -13,11 +13,11 @@
       ref="modalFormComp"
       :model="modalForm"
       :rules="rules"
-      label-width="100px"
+      label-width="90px"
     >
-      <el-form-item prop="requirementName" label="毕业要求:">
+      <el-form-item prop="name" label="毕业要求:">
         <el-input
-          v-model.trim="modalForm.requirementName"
+          v-model.trim="modalForm.name"
           placeholder="请输入毕业要求"
           clearable
         ></el-input>
@@ -38,7 +38,8 @@ import { professionalRequirementSave } from "../../api";
 const initModalForm = {
   id: null,
   professionalId: "",
-  requirementName: "",
+  name: "",
+  sortNum: "",
 };
 
 export default {
@@ -65,15 +66,15 @@ export default {
       isSubmit: false,
       modalForm: { ...initModalForm },
       rules: {
-        requirementName: [
+        name: [
           {
             required: true,
             message: "请输入毕业要求",
             trigger: "change",
           },
           {
-            message: "毕业要求不能超过50个字",
-            max: 50,
+            message: "毕业要求不能超过30个字",
+            max: 30,
             trigger: "change",
           },
         ],

+ 4 - 3
src/modules/course/components/profession/ModifyRequirementNode.vue

@@ -3,13 +3,13 @@
     :visible.sync="modalIsShow"
     :title="title"
     top="10vh"
-    width="600px"
+    width="400px"
     :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 ref="modalFormComp" :model="modalForm" label-width="80px">
       <el-form-item label="子节点数:">
         <el-input-number
           v-model="modalForm.nodeCount"
@@ -36,7 +36,8 @@ import { professionalRequirementSave } from "../../api";
 const initModalForm = {
   id: null,
   professionalId: "",
-  requirementName: "",
+  name: "",
+  sortNum: "",
   nodeCount: 0,
 };
 

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

@@ -85,6 +85,7 @@ export default {
         .then(async () => {
           await professionalCourseRemove(row.id);
           this.$message.success("删除成功!");
+          this.getList();
         })
         .catch(() => {});
     },

+ 1 - 1
src/modules/course/components/profession/ProfessionalDetail.vue

@@ -8,7 +8,7 @@
       append-to-body
       fullscreen
     >
-      <div slot="title">{{ rowData.professionalName }}</div>
+      <div slot="title">{{ rowData.name }}</div>
       <div class="mb-4 tab-btns">
         <el-button
           v-for="tab in tabs"

+ 27 - 34
src/modules/course/components/profession/ProfessionalMatrix.vue

@@ -2,9 +2,7 @@
   <div class="professional-matrix">
     <div class="box-justify part-box part-box-pad">
       <div>
-        <p class="tips-info">
-          {{ rowData.professionalName }}毕业要求支撑矩阵管理
-        </p>
+        <p class="tips-info">{{ rowData.name }}毕业要求支撑矩阵管理</p>
       </div>
       <div>
         <el-button type="success" :loading="loading" @click="toDownload"
@@ -15,26 +13,28 @@
 
     <div class="part-box part-box-pad">
       <el-table :data="dataList" border>
-        <el-table-column label="课程名称">
+        <el-table-column label="课程名称" min-width="200" fixed="left">
           <template slot-scope="scope">
             {{ scope.row.courseName }}
           </template>
         </el-table-column>
-        <el-table-column label="毕业要求">
+        <el-table-column label="毕业要求" align="center">
           <el-table-column
             v-for="(column, cindex) in columns"
             :key="cindex"
             :label="column.name"
+            align="center"
           >
             <template v-if="hasSubRequirements">
               <el-table-column
                 v-for="subr in column.subRequirements"
                 :key="subr"
-                :label="subr"
+                :label="subr === 'null' ? '' : subr"
+                align="center"
               >
                 <template slot-scope="scope">
                   <el-input-number
-                    v-model="scope.row[`${column.name}_${subr.name}`].value"
+                    v-model="scope.row[`${column.name}_${subr}`].value"
                     class="width-50"
                     :min="0"
                     :max="1"
@@ -43,40 +43,33 @@
                     :controls="false"
                     @change="
                       (val) =>
-                        unitChange(
-                          scope.row[`${column.name}_${subr.name}`].id,
-                          val
-                        )
+                        unitChange(scope.row[`${column.name}_${subr}`].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 slot-scope="scope">
+                <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>
             </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>
 
@@ -123,10 +116,10 @@ export default {
           courseName: item.courseName,
         };
         item.requirements.forEach((requirement) => {
-          requirement.subRequirements((subr) => {
+          requirement.subRequirements.forEach((subr) => {
             nitem[`${requirement.name}_${subr.name + ""}`] = {
               id: subr.id,
-              value: subr.content,
+              value: subr.content || undefined,
             };
           });
         });
@@ -148,14 +141,14 @@ export default {
       this.columns = requirements.map((item) => {
         return {
           name: item.name,
-          subRequirements: item.subRequirements.map((subr) => subr.name),
+          subRequirements: item.subRequirements.map((subr) => subr.name + ""),
         };
       });
     },
     async unitChange(id, val) {
       await professionalMatrixSave({
         id,
-        name: val,
+        content: val,
       });
     },
     async toDownload(row) {

+ 6 - 3
src/modules/course/components/profession/ProfessionalRequirement.vue

@@ -13,9 +13,9 @@
 
     <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 type="index" width="50" align="center">
         </el-table-column>
+        <el-table-column prop="name" 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">
@@ -32,6 +32,7 @@
               >编辑</el-button
             >
             <el-button
+              :disabled="!!scope.row.code"
               class="btn-danger"
               type="text"
               @click="toDelete(scope.row)"
@@ -109,12 +110,14 @@ export default {
       this.$refs.ModifyRequirementNode.open();
     },
     toDelete(row) {
-      this.$confirm(`确定要删除毕业要求【${row.requirementName}】吗?`, "提示", {
+      if (row.code) return;
+      this.$confirm(`确定要删除毕业要求【${row.name}】吗?`, "提示", {
         type: "warning",
       })
         .then(async () => {
           await professionalRequirementRemove(row.id);
           this.$message.success("删除成功!");
+          this.getList();
         })
         .catch(() => {});
     },

+ 15 - 14
src/modules/course/views/ProfessionalCertification.vue

@@ -2,20 +2,20 @@
   <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')">
+        <template v-if="checkPrivilege('condition', 'condition')">
+          <el-form-item label="专业名称:">
+            <el-input
+              v-model.trim="filter.name"
+              placeholder="专业名称"
+              clearable
+            ></el-input>
+          </el-form-item>
           <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
@@ -45,12 +45,11 @@
           width="70"
           :index="indexMethod"
         ></el-table-column>
-        <el-table-column prop="professionalName" label="专业">
-        </el-table-column>
+        <el-table-column prop="name" 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 }})
+            {{ scope.row.userName }}({{ scope.row.loginName }})
           </span>
         </el-table-column>
         <!-- <el-table-column prop="createTime" label="创建时间">
@@ -116,9 +115,8 @@ export default {
   data() {
     return {
       filter: {
-        semesterId: "",
-        examId: "",
-        courseCode: "",
+        orgId: "",
+        name: "",
       },
       current: 1,
       size: this.GLOBAL.pageSize,
@@ -127,6 +125,9 @@ export default {
       curRow: {},
     };
   },
+  mounted() {
+    this.toPage(1);
+  },
   methods: {
     async getList() {
       if (!this.checkPrivilege("list", "list")) return;