ソースを参照

完善选科报名表、实现拖拽功能

shilipojs 3 年 前
コミット
c03fea05f1

+ 27 - 1
mock/modules/elective-subject.js

@@ -72,7 +72,7 @@ module.exports = [
             rankInGrade: 64, // 选科全校排名
             allowSelect: true, // 是否可以报名
             disabledReason: '不知道', // 不可报名时的原因
-            selected:  true, // 报名状态
+            selected:  false, // 报名状态
             selectedRank:  1, // 多志愿时的排序
           },
           {
@@ -88,6 +88,32 @@ module.exports = [
             selected:  false, // 报名状态
             selectedRank:  2, // 多志愿时的排序
           },
+          {
+            groupId: 3, // 组合
+            groupName: '历化政', // 名称
+            classCount: 3,  // 班级数
+            personCount: 180,  // 限制人数
+            personInTime: 60,  // 实时人数
+            rankInGroup: 32, // 选科实时排名
+            rankInGrade: 67, // 选科全校排名
+            allowSelect: true, // 是否可以报名
+            disabledReason: '不知道', // 不可报名时的原因
+            selected:  false, // 报名状态
+            selectedRank:  2, // 多志愿时的排序
+          },
+          {
+            groupId: 4, // 组合
+            groupName: '历化地', // 名称
+            classCount: 4,  // 班级数
+            personCount: 180,  // 限制人数
+            personInTime: 60,  // 实时人数
+            rankInGroup: 32, // 选科实时排名
+            rankInGrade: 67, // 选科全校排名
+            allowSelect: true, // 是否可以报名
+            disabledReason: '不知道', // 不可报名时的原因
+            selected:  false, // 报名状态
+            selectedRank:  2, // 多志愿时的排序
+          },
         ]
       }
     }

+ 217 - 200
src/assets/styles/index.scss

@@ -1,200 +1,217 @@
-@import './variables.scss';
-@import './mixin.scss';
-@import './transition.scss';
-@import './element-ui.scss';
-@import './sidebar.scss';
-@import './btn.scss';
-
-body {
-  height: 100%;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  text-rendering: optimizeLegibility;
-  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
-}
-
-label {
-  font-weight: 700;
-}
-
-html {
-  height: 100%;
-  box-sizing: border-box;
-}
-
-#app {
-  height: 100%;
-}
-
-*,
-*:before,
-*:after {
-  box-sizing: inherit;
-}
-.no-padding {
-  padding: 0px !important;
-}
-
-.padding-content {
-  padding: 4px 0;
-}
-
-a:focus,
-a:active {
-  outline: none;
-}
-
-a,
-a:focus,
-a:hover {
-  cursor: pointer;
-  color: inherit;
-  text-decoration: none;
-}
-
-div:focus {
-  outline: none;
-}
-
-.fr {
-  float: right;
-}
-
-.fl {
-  float: left;
-}
-
-.pr-5 {
-  padding-right: 5px;
-}
-
-.pl-5 {
-  padding-left: 5px;
-}
-
-.block {
-  display: block;
-}
-
-.pointer {
-  cursor: pointer;
-}
-
-.inlineBlock {
-  display: block;
-}
-
-.clearfix {
-  &:after {
-    visibility: hidden;
-    display: block;
-    font-size: 0;
-    content: " ";
-    clear: both;
-    height: 0;
-  }
-}
-
-aside {
-  background: #eef1f6;
-  padding: 8px 24px;
-  margin-bottom: 20px;
-  border-radius: 2px;
-  display: block;
-  line-height: 32px;
-  font-size: 16px;
-  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-  color: #2c3e50;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-
-  a {
-    color: #337ab7;
-    cursor: pointer;
-
-    &:hover {
-      color: rgb(32, 160, 255);
-    }
-  }
-}
-
-//main-container全局样式
-.app-container {
-  padding: 20px;
-}
-
-.components-container {
-  margin: 30px 50px;
-  position: relative;
-}
-
-.pagination-container {
-  margin-top: 30px;
-}
-
-.text-center {
-  text-align: center
-}
-
-.sub-navbar {
-  height: 50px;
-  line-height: 50px;
-  position: relative;
-  width: 100%;
-  text-align: right;
-  padding-right: 20px;
-  transition: 600ms ease position;
-  background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
-
-  .subtitle {
-    font-size: 20px;
-    color: #fff;
-  }
-
-  &.draft {
-    background: #d0d0d0;
-  }
-
-  &.deleted {
-    background: #d0d0d0;
-  }
-}
-
-.link-type,
-.link-type:focus {
-  color: #337ab7;
-  cursor: pointer;
-
-  &:hover {
-    color: rgb(32, 160, 255);
-  }
-}
-
-.filter-container {
-  padding-bottom: 10px;
-
-  .filter-item {
-    display: inline-block;
-    vertical-align: middle;
-    margin-bottom: 10px;
-  }
-}
-
-//refine vue-multiselect plugin
-.multiselect {
-  line-height: 16px;
-}
-
-.multiselect--active {
-  z-index: 1000 !important;
-}
-
-.evaluation-card-wrapper {
-  padding-left: 6px;
-  padding-right: 6px;
-  margin-bottom: 10px;
-}
-
-tr.highlight-row {
-  color: red; 
-}
+@import './variables.scss';
+@import './mixin.scss';
+@import './transition.scss';
+@import './element-ui.scss';
+@import './sidebar.scss';
+@import './btn.scss';
+
+body {
+  height: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+  text-rendering: optimizeLegibility;
+  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+}
+
+label {
+  font-weight: 700;
+}
+
+html {
+  height: 100%;
+  box-sizing: border-box;
+}
+
+#app {
+  height: 100%;
+}
+
+*,
+*:before,
+*:after {
+  box-sizing: inherit;
+}
+.no-padding {
+  padding: 0px !important;
+}
+
+.padding-content {
+  padding: 4px 0;
+}
+
+a:focus,
+a:active {
+  outline: none;
+}
+
+a,
+a:focus,
+a:hover {
+  cursor: pointer;
+  color: inherit;
+  text-decoration: none;
+}
+
+div:focus {
+  outline: none;
+}
+
+.fr {
+  float: right;
+}
+
+.fl {
+  float: left;
+}
+
+.pr-5 {
+  padding-right: 5px;
+}
+
+.pl-5 {
+  padding-left: 5px;
+}
+
+.block {
+  display: block;
+}
+
+.pointer {
+  cursor: pointer;
+}
+
+.inlineBlock {
+  display: block;
+}
+
+.clearfix {
+  &:after {
+    visibility: hidden;
+    display: block;
+    font-size: 0;
+    content: " ";
+    clear: both;
+    height: 0;
+  }
+}
+
+aside {
+  background: #eef1f6;
+  padding: 8px 24px;
+  margin-bottom: 20px;
+  border-radius: 2px;
+  display: block;
+  line-height: 32px;
+  font-size: 16px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
+  color: #2c3e50;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+
+  a {
+    color: #337ab7;
+    cursor: pointer;
+
+    &:hover {
+      color: rgb(32, 160, 255);
+    }
+  }
+}
+
+//main-container全局样式
+.app-container {
+  padding: 20px;
+}
+
+.components-container {
+  margin: 30px 50px;
+  position: relative;
+}
+
+.pagination-container {
+  margin-top: 30px;
+}
+
+.text-center {
+  text-align: center
+}
+.btn-blue{
+  color: deepskyblue;
+  padding: 0 5px;
+  border-bottom: 1px solid deepskyblue;
+  cursor: pointer;
+}
+.btn-red{
+  color: orangered;
+  padding: 0 5px;
+  border-bottom: 1px solid orangered;
+  cursor: pointer;
+}
+.btn-green{
+  color: #1ab394;
+  padding: 0 5px;
+  border-bottom: 1px solid #1ab394;
+  cursor: pointer;
+}
+.sub-navbar {
+  height: 50px;
+  line-height: 50px;
+  position: relative;
+  width: 100%;
+  text-align: right;
+  padding-right: 20px;
+  transition: 600ms ease position;
+  background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
+
+  .subtitle {
+    font-size: 20px;
+    color: #fff;
+  }
+
+  &.draft {
+    background: #d0d0d0;
+  }
+
+  &.deleted {
+    background: #d0d0d0;
+  }
+}
+
+.link-type,
+.link-type:focus {
+  color: #337ab7;
+  cursor: pointer;
+
+  &:hover {
+    color: rgb(32, 160, 255);
+  }
+}
+
+.filter-container {
+  padding-bottom: 10px;
+
+  .filter-item {
+    display: inline-block;
+    vertical-align: middle;
+    margin-bottom: 10px;
+  }
+}
+
+//refine vue-multiselect plugin
+.multiselect {
+  line-height: 16px;
+}
+
+.multiselect--active {
+  z-index: 1000 !important;
+}
+
+.evaluation-card-wrapper {
+  padding-left: 6px;
+  padding-right: 6px;
+  margin-bottom: 10px;
+}
+
+tr.highlight-row {
+  color: red;
+}

+ 22 - 0
src/utils/index.js

@@ -15,6 +15,28 @@ export function formatDate(cellValue) {
   return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
 }
 
+/**
+ * 格式化科目缩写
+ */
+export function formatSubject(cellValue) {
+  if (cellValue == null || cellValue == '') return ''
+  switch (cellValue) {
+    case '物':
+      return '物理'
+    case '历':
+      return '历史'
+    case '化':
+      return '化学'
+    case '地':
+      return '地理'
+    case '政':
+      return '政治'
+    case '生':
+      return '生物'
+
+  }
+}
+
 /**
  * @param {number} time
  * @param {string} option

+ 8 - 0
src/views/career/subject/subjectChoice.vue

@@ -389,6 +389,14 @@
         this.curSelectLiberalArts.push(this.liberalArts[0]["name"]);
         this.curSelectLiberalArts.push(this.liberalArts[1]["name"]);
       }
+      // 回显
+      if(this.$route.query.curSelectScienceList) {
+        this.curSelectScienceList = this.$route.query.curSelectScienceList
+      }
+
+      if(this.$route.query.curSelectLiberalArts.length > 0) {
+        this.curSelectLiberalArts = this.$route.query.curSelectLiberalArts
+      }
       this.httpGetXkcxYears();
       this.httpUniversityFilters();
       this.httpGetMarjorsList();

+ 76 - 11
src/views/system/user/profile/components/report-table.vue

@@ -8,34 +8,50 @@
     </template>
     <mx-table :propDefines="propDefines" :rows="formatList">
       <template #temp="{row}">
-<!--        <el-button>选择</el-button>-->
-<!--        <el-button>查看</el-button>-->
+        <span class="btn-blue mr5" @click="toSelectSub(row)">选择</span>
+        <span class="btn-green">查看记录</span>
+        <!--        <el-button>查看</el-button>-->
       </template>
       <template #proportion="{row}">
         <span :style="{color: row.personInTime > row.personCount ? 'red' : '#42b983'}">{{row.personInTime}}</span>
         <span >/{{row.personCount}}</span>
       </template>
       <template #signUp="{row}">
-        <span>{{ row.selected ? '已报名' : '报名' }}</span>
+        <span class="btn-red" v-if="row.selected" @click="toUnSelect(row)">取消报名</span>
+        <span class="btn-green" v-else @click="toSelect(row)">报名</span>
       </template>
       <template #subjects="{row}">
-        <el-tag type="success" class="mr10 mb10" v-for="subject in row.subjects">{{ subject[0] }}</el-tag>
+        <el-row>
+          <el-col :span="8" v-for="subject in row.subjects">
+            <el-tag type="success" class="mr10 mb10" >{{ subject[0] }}</el-tag>
+          </el-col>
+        </el-row>
       </template>
       <template #colleges="{row}">
-        <div v-for="college in row.colleges">
-          <el-tag type="success" class="mb10">{{ college.major[0] }}</el-tag>:
-          <span>{{ college.college }}</span>
-        </div>
+        <el-row>
+          <el-col :span="12" v-for="college in row.colleges">
+            <el-tag type="success" class="mb10">{{ college.major[0] }}</el-tag>:
+            <span>{{ college.college }}</span>
+          </el-col>
+        </el-row>
       </template>
     </mx-table>
+    <p>您的选科志愿: <span v-for="(item,index) in selectedList" >{{item.groupName}}{{index+1 < selectedList.length ? '、' : '' }}</span></p>
+    <!-- 拖拽 -->
+    <test-drage ref="drage" :sortList="selectedList"></test-drage>
   </el-card>
 </template>
 <script>
-
+import { formatSubject } from '@/utils/index'
+import TestDrage  from './test-drage'
 export default {
+  components: {
+    TestDrage
+  },
   data() {
     return {
       list: [],
+      preferenceCount: 3,
       optionalMajors: [],
       propDefines: {
         index: {
@@ -66,6 +82,7 @@ export default {
         },
         temp: {
           label: '选择专业',
+          width: '140',
           slot: 'temp'
         },
         subjects: {
@@ -76,16 +93,22 @@ export default {
         colleges: {
           label: '院校',
           slot: 'colleges',
-          width: 200
+          width: '250'
         },
         signUp: {
           label: '操作',
-          slot: 'signUp'
+          slot: 'signUp',
+          width:'100',
+          fixed: 'right'
         }
       }
     }
   },
   computed: {
+    selectedList() {
+      if (!this.list.length) return []
+      return this.list.filter(item => item.selected)
+    },
     formatList() {
       if (!this.list.length) return []
       if (!this.optionalMajors.length) return []
@@ -108,8 +131,50 @@ export default {
 
   },
   methods: {
+    toSelect(row) {
+      const count = this.list.reduce((prev,cur) => {
+        return prev += cur.selected ? 1 : 0
+      },0)
+      console.log(count)
+      if(count >= this.preferenceCount) {
+        this.$message.warning(`最多选择${this.preferenceCount}个志愿`)
+        return
+      }
+      row.selected = true
+      this.$refs.drage.init(this.selectedList)
+    },
+    toUnSelect(row) {
+      this.$confirm(`是否解除选科组合【${row.groupName}】`, '警告', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        row.selected = false
+        this.$refs.drage.init(this.selectedList)
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '已取消'
+        });
+      });
+    },
+    toSelectSub(row)  {
+      // 首选科目
+      const groupArr = row.groupName.split('').map(item => {
+        return formatSubject(item)
+      })
+      const firstSub =  groupArr[0] // 首选科目
+      const lastSub = groupArr.splice(1, 2) // 次选科目
+      console.log(groupArr)
+      console.log(firstSub)
+      console.log(lastSub)
+      // 跳转到选科页面
+      this.$router.push({path:'/career/subject/subjectChoice',query: {curSelectScienceList: firstSub,curSelectLiberalArts: lastSub }})
+    },
     init(list) {
       console.log(list)
+
+      console.log(formatSubject('物'))
       this.list = list
     },
     initOption(optionalMajors) {

+ 4 - 1
src/views/system/user/profile/components/select-subject.vue

@@ -12,8 +12,11 @@
           placement="bottom"
           trigger="hover"
           v-for="item in optionalMajors"
+          popper-class="zero-padding-popover"
         >
-          <el-button type="primary" @click="toGroupMatch(item)">匹配组合</el-button>
+          <div class="fx-column">
+            <el-button plain type="text" @click="toGroupMatch(item)">匹配组合</el-button>
+          </div>
           <el-tag class="mr10 mb10" type="success" slot="reference">{{ item.majorCategoryName }}</el-tag>
         </el-popover>
       </div>

+ 84 - 0
src/views/system/user/profile/components/test-drage.vue

@@ -0,0 +1,84 @@
+<template>
+  <!--  拖拽demo-->
+  <transition-group name="drag"
+                    class="list"
+                    tag="ul"
+  >
+    <li
+      @dragenter="dragenter($event, index)"
+      @dragover="dragover($event, index)"
+      @dragstart="dragstart(index)"
+      draggable
+      v-for="(item, index) in sortList"
+      :key="item.groupId"
+      class="list-item"
+    >
+      <span>{{`第${index + 1}志愿`}}</span>
+      {{ item.groupName }}
+    </li>
+  </transition-group>
+</template>
+<script>
+export default {
+  // props: {
+  //   sortList: {
+  //     type: Array,
+  //     default:_ => []
+  //   }
+  // },
+  data() {
+    return {
+      dragIndex: '',
+      enterIndex: '',
+      sortList: [],
+    }
+  },
+  methods: {
+    init(data) {
+      this.sortList = data
+    },
+    dragstart(index) {
+      this.dragIndex = index
+    },
+    dragenter(e, index) {
+      e.preventDefault()
+      // 避免源对象触发自身的dragenter事件
+      if (this.dragIndex !== index) {
+        const source = this.sortList[this.dragIndex]
+        this.sortList.splice(this.dragIndex, 1)
+        this.sortList.splice(index, 0, source)
+        console.log(this.sortList)
+        // 排序变化后目标对象的索引变成源对象的索引
+        this.dragIndex = index
+      }
+    },
+    shuffle() {
+      this.sortList = this.$shuffle(this.sortList)
+    },
+    dragover(e, index) {
+      e.preventDefault()
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.list {
+  list-style: none;
+
+  .drag-move {
+    transition: transform .3s;
+  }
+
+  .list-item {
+    cursor: move;
+    width: 300px;
+    background: #EA6E59;
+    border-radius: 4px;
+    color: #FFF;
+    margin-bottom: 6px;
+    height: 50px;
+    line-height: 50px;
+    text-align: center;
+  }
+}
+</style>