lrf402788946 5 سال پیش
والد
کامیت
84c4c0cc4b

+ 6 - 0
src/router/index.js

@@ -71,6 +71,12 @@ const system = [
     meta: { title: '学校信息', sub: '' },
     component: () => import('@/views/school/detail.vue'),
   },
+  {
+    path: '/class/type',
+    name: 'class_type',
+    meta: { title: '班级类型管理' },
+    component: () => import('@/views/classes/type.vue'),
+  },
   {
     path: '/location/index',
     name: 'location_index',

+ 2 - 0
src/store/index.js

@@ -33,6 +33,7 @@ import termquest from '@frame/store/termquest';
 import dirPlan from '@frame/store/dir-plan';
 import login from '@frame/store/login';
 import notice from '@frame/store/notice';
+import classtype from '@frame/store/classtype';
 import * as ustate from '@frame/store/user/state';
 import * as umutations from '@frame/store/user/mutations';
 import * as dostate from '@frame/store/setting/state';
@@ -78,6 +79,7 @@ export default new Vuex.Store({
     group,
     uploadtask,
     notice,
+    classtype,
   },
   state: { ...ustate, ...dostate },
   mutations: { ...umutations, ...domutations },

+ 133 - 0
src/views/classes/type.vue

@@ -0,0 +1,133 @@
+<template>
+  <div id="clatype">
+    <detail-frame :title="pageTitle">
+      <el-row type="flex" align="middle" justify="end">
+        <el-col :span="2" style="padding:10px"> <el-button type="primary" icon="el-icon-plus" size="mini" @click="toAdd">添加类型</el-button> </el-col>
+      </el-row>
+      <data-table :fields="fields" :data="list" :total="total" :opera="opera" @edit="toEdit" @delete="toDelete"></data-table>
+    </detail-frame>
+    <el-drawer :visible.sync="drawer" @close="toClose" direction="rtl" :with-header="false">
+      <el-tabs style="padding:10px;">
+        <el-tab-pane label="班级类型">
+          <data-form :styles="{ padding: 0 }" :data="form" :fields="formFields" :rules="{}" @save="handleSave" :isNew="isNew">
+            <template #radios="{item}">
+              <template v-if="item.model == 'bedroom'">
+                <el-radio label="0">自动分配</el-radio>
+                <el-radio label="1">人工填写</el-radio>
+              </template>
+              <template v-if="item.model == 'sign'">
+                <el-radio label="0">学生签到</el-radio>
+                <el-radio label="1">教师代签</el-radio>
+              </template>
+            </template>
+          </data-form>
+        </el-tab-pane>
+      </el-tabs>
+    </el-drawer>
+  </div>
+</template>
+
+<script>
+import detailFrame from '@frame/layout/admin/detail-frame';
+import dataTable from '@frame/components/filter-page-table';
+import dataForm from '@frame/components/form';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions: classtype } = createNamespacedHelpers('classtype');
+export default {
+  name: 'clatype',
+  props: {},
+  components: { detailFrame, dataTable, dataForm },
+  data: function() {
+    return {
+      drawer: false,
+      isNew: true,
+      form: {},
+      opera: [
+        {
+          label: '编辑',
+          icon: 'el-icon-edit',
+          method: 'edit',
+        },
+        {
+          label: '删除',
+          icon: 'el-icon-delete',
+          method: 'delete',
+          confirm: true,
+        },
+      ],
+      fields: [
+        { label: '班级类型', prop: 'name' },
+        { label: '类型代码', prop: 'code' },
+        { label: '分寝方式', prop: 'bedroom', format: i => (i == '0' ? '自动分配' : '人工填写') },
+        { label: '签到类型', prop: 'sign', format: i => (i == '0' ? '学生签到' : '教师代签') },
+      ],
+      formFields: [
+        { label: '班级类型', model: 'name' },
+        { label: '类型代码', model: 'code' },
+        { label: '分寝方式', model: 'bedroom', type: 'radio' },
+        { label: '签到类型', model: 'sign', type: 'radio' },
+      ],
+      list: [],
+      total: 0,
+    };
+  },
+  created() {
+    this.toSearch();
+  },
+  methods: {
+    ...classtype(['create', 'query', 'update', 'delete']),
+    async toSearch({ skip = 0, limit = 10, ...info } = {}) {
+      const res = await this.query({ skip, limit, ...info });
+      if (this.$checkRes(res)) {
+        this.$set(this, 'list', res.data);
+        this.$set(this, 'total', res.total);
+      }
+    },
+    toAdd() {
+      this.drawer = true;
+    },
+    toEdit({ data }) {
+      this.isNew = false;
+      this.$set(this, `form`, data);
+      this.drawer = true;
+    },
+    async handleSave({ isNew, data }) {
+      let res;
+      let msg;
+      if (isNew) {
+        res = await this.create(data);
+        msg = '添加';
+      } else {
+        res = await this.update(data);
+        msg = '修改';
+      }
+      if (this.$checkRes(res, `${msg}成功`, res.errmsg)) {
+        this.toClose();
+        this.toSearch();
+      }
+    },
+    async toDelete({ data }) {
+      const res = await this.delete(data.id);
+      if (this.$checkRes(res, '删除成功', '删除失败')) {
+        this.toSearch();
+      }
+    },
+    toClose() {
+      this.drawer = false;
+      this.isNew = true;
+      this.form = {};
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 7 - 33
src/views/new-plan/arrange/arrange.vue

@@ -4,14 +4,15 @@
     <el-row type="flex" justify="center" v-if="view == 'plan'">
       <el-col :span="24" :style="`overflow:auto`">
         <el-card ref="card" v-if="info.year" height="800px">
-          <calendar
+          <!-- <calendar
             :year="`${info.year || '2020'}`"
             :selfBtn="selfBtn"
             @draft="selectDate"
             @eventClick="eventClick"
             :vacation="vacation"
             :events="events"
-          ></calendar>
+          ></calendar> -->
+          <table-cal :vacation="vacation"></table-cal>
         </el-card>
       </el-col>
     </el-row>
@@ -69,6 +70,7 @@ import detailFrame from '@frame/layout/admin/detail-frame';
 import calendar from '@frame/components/calendar';
 import dataTable from '@frame/components/data-table';
 import event from '../parts/event';
+import tableCal from './arrange/table';
 import { mapState, createNamespacedHelpers } from 'vuex';
 const { mapActions } = createNamespacedHelpers('trainplan');
 const { mapActions: trainTemplate } = createNamespacedHelpers('trainTemplate');
@@ -79,9 +81,10 @@ export default {
   props: {},
   components: {
     // detailFrame,
-    calendar,
+    // calendar,
     // dataTable,
     event,
+    tableCal,
   },
   data: function() {
     var that = this;
@@ -94,36 +97,7 @@ export default {
       form: {},
       selectList: [],
       events: [],
-      vacation: [],
-      fields: [
-        { label: '开始时间', prop: 'start' },
-        { label: '结束时间', prop: 'end' },
-        { label: '期数', prop: 'term' },
-        { label: '班级类型', prop: 'type', format: item => (item === '0' ? '正常班级' : '特殊班级') },
-      ],
-      opera: [
-        {
-          label: '编辑',
-          icon: 'el-icon-edit',
-          method: 'edit',
-        },
-        {
-          label: '删除',
-          icon: 'el-icon-delete',
-          method: 'delete',
-          confirm: true,
-        },
-      ],
-      rules: {
-        title: [{ required: true, message: '请输入标题' }],
-      },
-      formRules: {
-        start: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
-        end: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
-        term: [{ required: true, message: '请输入期数' }],
-        number: [{ required: true, message: '请输入每班人数' }],
-        type: [{ required: true, message: '请选择班级类型' }],
-      },
+      vacation: undefined,
       dialog: false,
       selfBtn: {
         term: {

+ 321 - 0
src/views/new-plan/arrange/arrange/table.vue

@@ -0,0 +1,321 @@
+<template>
+  <div id="tableCal">
+    <template v-if="already">
+      <table border="1" class="table" style="zoom:0.8" v-for="month in 12" :key="month">
+        <template>
+          <tr>
+            <th :rowspan="list[`${month}`].length + 1" class="mouthTitle" style="width:58px;">{{ getWord(month) }}月</th>
+            <th class="th" v-for="(item, index) in makeCalendar(month)" :key="index">
+              <p>{{ item }}</p>
+              <p>{{ getWeekDay(item) }}</p>
+            </th>
+            <th class="th"><p>备注</p></th>
+            <th class="th"><p>备注</p></th>
+          </tr>
+          <tr v-for="(d, di) in list[`${month}`]" :key="di">
+            <td
+              v-for="(date, ci) in makeCalendar(month)"
+              :key="ci"
+              @click="cellClick(date, month, di, ci)"
+              :style="setVS(date, month, di, ci)"
+              :rowspan="toRowspan(date, month, di, ci)"
+              :colspan="toColspan(date, month, di, ci)"
+            >
+              {{ getContent(date, month, di, ci) || '' }}
+            </td>
+            <template v-if="di == 0">
+              <td :rowspan="list[`${month}`].length + 1" :style="{ height: (list[`${month}`].length + 1) * 15 }"></td>
+              <td :rowspan="list[`${month}`].length + 1"></td>
+            </template>
+          </tr>
+        </template>
+      </table>
+    </template>
+    <div
+      style="height:800px"
+      v-else
+      v-loading="!already"
+      element-loading-text="加载中请稍后..."
+      element-loading-spinner="el-icon-loading"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
+    ></div>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+var moment = require('moment');
+import { mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  name: 'tableCal',
+  props: {
+    year: { type: Number, default: new Date().getFullYear() },
+    vacation: { type: Array },
+  },
+  components: {},
+  data: function() {
+    return {
+      value: '2020-07-20',
+      list: {},
+      has_it: false,
+      it: {},
+      already: true,
+    };
+  },
+  created() {
+    this.init();
+  },
+  methods: {
+    makeCalendar(month = 1) {
+      if (month * 1 < 10) month = `0${month}`;
+      let days = moment(`${this.year}-${month}`).daysInMonth();
+      let dlist = this.getDayList(month, days);
+      while (dlist.length < 31) {
+        dlist.push('');
+      }
+      return dlist;
+    },
+    getDayList(month, days) {
+      let dlist = [];
+      for (let index = 0; index < days; index++) {
+        dlist.push(
+          moment(`${this.year}-${month}-01`)
+            .add(index, 'days')
+            .format('M.D')
+        );
+      }
+      return dlist;
+    },
+    getWeekDay(datestr) {
+      let weekday = moment(datestr).weekday();
+      if (weekday || weekday == 0) {
+        let arr = ['一', '二', '三', '四', '五', '六', '日'];
+        return `星期${arr[weekday]}`;
+      }
+      return '';
+    },
+    cellClick(date, month, di, ci) {
+      console.log(date, month, di, ci);
+    },
+    getWord(month) {
+      let arr = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'];
+      return arr[month - 1];
+    },
+    init() {
+      let list = {};
+      let arr = [{}, {}, {}, {}, {}, {}, {}, {}];
+      for (let index = 1; index <= 12; index++) {
+        list[index] = arr;
+      }
+      this.$set(this, `list`, list);
+    },
+    setVS(date, month, di, ci) {
+      let style = { cursor: 'default' };
+      if (this.toRowspan(date, month, di, ci) == 0 || this.toColspan(date, month, di, ci) == 0) {
+        style['display'] = 'none';
+        style['pointer-events'] = 'none';
+        return style;
+      }
+      let res = this.checkVacation(date);
+      if (res) {
+        style = { cursor: 'not-allowed' };
+        style['pointer-events'] = 'none';
+        if (date != '') style['background'] = 'red';
+      }
+      return style;
+    },
+    toRowspan(date, month, di, ci) {
+      let res = this.checkVacation(date);
+      let rs = 1;
+      if (res) {
+        rs = this.list[month].length;
+        if (di != 0) rs = 0;
+      }
+      return rs;
+    },
+    toColspan(date, month, di, ci) {
+      let result = 1;
+      if (date == '') return result;
+      date = this.pointToCross(date);
+      let ir = this.intersection(date);
+      //不在假期中的直接返回1就行,不处理
+      if (!ir) return result;
+      if (ir.length < 2) {
+        //仅有1个假期,假期没有重合
+        let r = this.pure(date, ir);
+        result = r;
+      } else {
+        this.crossPro(date, ir);
+      }
+      return result;
+    },
+    //单纯处理1个假期
+    pure(date, ranges) {
+      let result = 1;
+      let vac = _.head(ranges);
+      let { start, end } = vac;
+      //先判断是否跨月
+      let omr = this.outMonth(start, end);
+      if (omr) {
+        //跨月了
+        result = this.outLotsMonth(date, start, end, omr);
+      } else {
+        //没跨越
+        result = this.notOutMonthPro(date, start, end);
+      }
+      return result;
+    },
+    //查询假期是否有交集,返回有交集的假期
+    intersection(date) {
+      let io = {};
+      if (!this.has_it) {
+        let duplicate = _.cloneDeep(this.vacation);
+        for (const i of duplicate) {
+          let ia = [];
+          for (const k of duplicate) {
+            if (_.isEqual(i, k)) continue;
+            let { start: is, end: ie } = i;
+            let { start: ks, end: ke } = k;
+            let sj = moment(is).isBetween(ks, ke, null, '[]');
+            let ej = moment(ie).isBetween(ks, ke, null, '[]');
+            let rsj = moment(ks).isBetween(is, ie, null, '[]');
+            let rej = moment(ie).isBetween(ks, ke, null, '[]');
+            if (sj || ej || rsj || rej) ia.push(k);
+          }
+          ia.push(i);
+          if (ia.length > 0) io[`${i.start}/${i.end}`] = ia;
+        }
+        this.$set(this, `it`, io);
+        this.$set(this, `has_it`, true);
+      } else {
+        io = _.cloneDeep(this.it);
+      }
+      let keys = Object.keys(io);
+      let r = keys.find(f => {
+        let arr = f.split('/');
+        return moment(date).isBetween(arr[0], arr[1], null, '[]');
+      });
+      if (r) return io[r];
+    },
+    // '.' 日期转换 '-' 日期
+    pointToCross(date) {
+      let d = date.split('.');
+      return moment(`${this.year}-${d[0]}-${d[1]}`).format('YYYY-MM-DD');
+    },
+    //跨月判断
+    outMonth(start, end) {
+      let s = moment(start).month();
+      let e = moment(end).month();
+      return e - s;
+    },
+    //跨月处理
+    outLotsMonth(date, start, end, omr) {
+      let result = 0;
+      let dm = moment(date).month() + 1;
+      let sm = moment(start).month() + 1;
+      let em = moment(end).month() + 1;
+      let marr = [];
+      //整理出月份列表
+      for (let i = 0; i <= omr; i++) {
+        marr.push(sm + i);
+      }
+      if (date == start && dm == sm) {
+        //该天的月份在开始时间的月份中
+        let sub = moment(start)
+          .endOf('month')
+          .diff(moment(start), 'days');
+        result = sub + 1;
+      } else if (dm == em) {
+        //该天在结束时间的月份中: 结束时间-这个月开始日期, 只有在这个月开始那天合并,其他的全合并
+        let esd = moment(end).startOf('month');
+        if (date == esd.format('YYYY-MM-DD')) {
+          result = moment(end).diff(esd, 'days') + 1;
+        }
+      } else {
+        let ms = moment(date).startOf('month');
+        if (date == ms.format('YYYY-MM-DD')) {
+          let me = moment(date).endOf('month');
+          result = me.diff(ms, 'days') + 1;
+        }
+      }
+      return result;
+    },
+    //无跨月处理
+    notOutMonthPro(date, start, end) {
+      let result = 0;
+      if (date == start) {
+        let sub = moment(end).diff(moment(start), 'days');
+        result = sub + 1;
+      }
+      return result;
+    },
+    crossPro(date, ir) {
+      console.log(date);
+      console.log(ir);
+    },
+    checkVacation(date) {
+      let res = false;
+      if (!this.vacation) return res;
+      let style = { cursor: 'default' };
+      for (const vac of this.vacation) {
+        let start = vac.start;
+        let end = _.get(vac, `end`, moment(start).format('YYYY-MM-DD'));
+        let r = moment(moment(`${this.year}-${date}`).format('YYYY-MM-DD')).isBetween(start, end, null, '[]');
+        if (r) {
+          res = r;
+          break;
+        }
+      }
+      return res;
+    },
+    getContent(date, month, di, ci) {
+      let res = this.vacation.filter(f => {
+        let start = f.start;
+        let end = _.get(f, `end`, moment(start).format('YYYY-MM-DD'));
+        return moment(moment(`${this.year}-${date}`).format('YYYY-MM-DD')).isBetween(start, end, null, '[]');
+      });
+      if (res.length > 0 && date != '') {
+        let r = res.map(i => i.title);
+        return r.join('/');
+      }
+      return '';
+    },
+    toDisplay(month) {
+      return _.inRange(month, 0, 4);
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+  },
+  watch: {
+    year: {
+      handler(val) {
+        if (val) this.makeCalendar();
+      },
+      immediate: true,
+    },
+    vacation: {
+      handler(val) {
+        if (val && this.year) this.already = true;
+      },
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.th p {
+  width: 55px;
+  font-size: 14px;
+}
+td {
+  text-align: center;
+  height: 15px;
+}
+</style>

+ 15 - 4
src/views/new-plan/index.vue

@@ -7,6 +7,11 @@
       <data-form :data="info" :fields="Ffields" :rules="rules" @save="handleSave" :isNew="!info.id" :styles="{ padding: 0 }" labelWidth="60px">
         <template #custom="{item,form}">
           <template v-if="item.model == 'festivals'">
+            <el-row>
+              <el-col :span="4" style="padding-bottom:10px">
+                <el-button type="primary" plain size="mini" icon="el-icon-plus" @click="addFest()">添加节假日</el-button>
+              </el-col>
+            </el-row>
             <data-table :fields="festFields" :data="form[item.model]" :opera="formOpera" @edit="toFestEdit" @delete="toFestDelete"></data-table>
           </template>
         </template>
@@ -17,7 +22,7 @@
         </template>
       </data-form>
     </el-dialog>
-    <el-drawer :title="form.name" :visible.sync="drawer" direction="rtl" @close="handleFestClose">
+    <el-drawer :title="form.name || '添加'" :visible.sync="drawer" direction="rtl" @close="handleFestClose">
       <data-form :data="form" :fields="festFields" :rules="{}" @save="handleFestSave" :isNew="!info.id" :styles="{ padding: 0 }"> </data-form>
     </el-drawer>
   </div>
@@ -85,7 +90,7 @@ export default {
         { label: '状态', prop: 'status', format: i => (i === '0' ? '筹备中' : i === '1' ? '进行中' : '已结束') },
       ],
       festFields: [
-        { label: '节假日', prop: 'name', model: 'name', options: { readonly: true } },
+        { label: '节假日', prop: 'name', model: 'name' },
         { label: '开始时间', prop: 'begindate', model: 'begindate', type: 'date' },
         { label: '结束时间', prop: 'finishdate', model: 'finishdate', type: 'date' },
       ],
@@ -163,13 +168,19 @@ export default {
       this.$set(this, 'form', nd);
       this.drawer = true;
     },
+    addFest() {
+      this.drawer = true;
+    },
     toFestDelete({ data, index }) {
       this.info.festivals.splice(index, 1);
     },
     handleFestSave({ data }) {
       let index = data.index;
-      let obj = _.omit(data, ['index']);
-      this.$set(this.info.festivals, index, obj);
+      if (index || index == 0) {
+        let obj = _.omit(data, ['index']);
+        this.$set(this.info.festivals, index, obj);
+      } else this.info.festivals.push(data);
+
       this.drawer = false;
     },
     async getOtherList() {

+ 128 - 25
src/views/new-plan/template.vue

@@ -1,18 +1,77 @@
 <template>
   <div id="templates">
     <detail-frame :title="pageTitle">
-      <data-form :data="info" :fields="fields" :rules="rules" @save="handleSave" :isNew="isNew" labelWidth="165px" :reset="false">
-        <template #custom="{item}">
-          <template v-if="item.model == 'color'">
-            <el-row type="flex" align="middle">
-              <el-col :span="1">
-                <el-color-picker v-model="color" :predefine="info.color" @change="toChange" color-format="hex"></el-color-picker>
-                <!-- <el-button type="primary" @click="toClear" size="mini">重置默认颜色</el-button> -->
-              </el-col>
-            </el-row>
+      <el-card>
+        <el-form :model="info" size="mini" label-position="right" label-suffix=":" label-width="180px">
+          <template v-for="(i, index) in fields">
+            <template v-if="!i.custom">
+              <el-form-item :key="index" :label="i.label" :required="i.required">
+                <template v-if="i.type != 'text'">
+                  <el-input :type="i.type" v-model="info[i.model]" size="mini" style="width:300px"></el-input>
+                </template>
+                <template v-else>
+                  {{ info[i.model] || 0 }}
+                </template>
+              </el-form-item>
+            </template>
+            <template else>
+              <template v-if="i.model == 'batchnum'">
+                <el-form-item :key="index" :label="i.label" :required="i.required">
+                  <el-row style="padding: 5px 0">
+                    <el-col :span="2">
+                      <el-button icon="el-icon-plus" size="mini" type="primary" @click="addBatch">添加批次</el-button>
+                    </el-col>
+                  </el-row>
+                  <el-row :gutter="5">
+                    <el-col :span="6" v-for="(bat, bindex) in info.batchnum" :key="bindex">
+                      <el-card>
+                        <el-form-item label="批次" label-width="50">
+                          <el-row type="flex" align="middle" justify="space-around">
+                            <el-col :span="2">
+                              {{ bat.batch }}
+                            </el-col>
+                            <el-col :span="2">
+                              <el-button type="danger" plain icon="el-icon-delete" @click="deleteBatch(bindex)"></el-button>
+                            </el-col>
+                          </el-row>
+                          <el-row>
+                            <el-col :span="24">
+                              <el-button type="primary" icon="el-icon-plus" @click="addClass(bindex)">添加班级</el-button>
+                            </el-col>
+                            <el-col :span="24">
+                              <el-table size="mini" :data="bat.classnum">
+                                <el-table-column align="center" label="班级" prop="class"></el-table-column>
+                                <el-table-column align="center" label="人数">
+                                  <template v-slot="{ row }">
+                                    <el-input v-model="row.number" type="number"></el-input>
+                                  </template>
+                                </el-table-column>
+                                <el-table-column align="center" label="操作">
+                                  <template v-slot="{ row, $index }">
+                                    <el-button type="text" icon="el-icon-delete" @click="toDelete(bindex, $index)"></el-button>
+                                  </template>
+                                </el-table-column>
+                              </el-table>
+                            </el-col>
+                          </el-row>
+                        </el-form-item>
+                      </el-card>
+                    </el-col>
+                  </el-row>
+                </el-form-item>
+              </template>
+              <template v-if="i.model == 'color'">
+                <el-form-item :key="index" :label="i.label" :required="i.required">
+                  <el-color-picker v-model="color" :predefine="info.color" @change="toChange" color-format="hex"></el-color-picker>
+                </el-form-item>
+              </template>
+            </template>
           </template>
-        </template>
-      </data-form>
+          <el-form-item label="">
+            <el-button type="primary" @click="handleSave">保存</el-button>
+          </el-form-item>
+        </el-form>
+      </el-card>
     </detail-frame>
   </div>
 </template>
@@ -20,34 +79,32 @@
 <script>
 import _ from 'lodash';
 import detailFrame from '@frame/layout/admin/detail-frame';
-import dataForm from '@frame/components/form';
 import { mapState, createNamespacedHelpers } from 'vuex';
 const { mapActions: trainTemplate } = createNamespacedHelpers('trainTemplate');
 const { mapActions: util } = createNamespacedHelpers('util');
 export default {
   name: 'templates',
   props: {},
-  components: { detailFrame, dataForm },
+  components: { detailFrame },
   data: () => {
     return {
-      info: { color: [] },
+      info: {
+        color: ['#E60000', '#FF7300', '#996B1F', '#FFD700', '#AFA4E0', '#74868A', '#09A343', '#E9F1F4'],
+        carpnum: 53,
+        batchnum: [],
+      },
       color: '',
       isNew: true,
       fields: [
         { label: '总人数', required: true, model: 'total', type: 'number' },
-        { label: '每批所需天数', required: true, model: 'day', type: 'number' },
-        { label: '默认每期中的批次数', required: true, model: 'batchnum', type: 'number' },
-        { label: '默认每批次中的班级数', required: true, model: 'classnum', type: 'number' },
-        { label: '默认每班中的人数', required: true, model: 'stunum', type: 'number' },
         { label: '默认每车人数', required: true, model: 'carpnum', type: 'number' },
+        { label: '每批所需天数', required: true, model: 'day', type: 'number' },
+        { label: '默认每期中的批次设置', custom: true, model: 'batchnum', type: 'number' },
         { label: '默认颜色', model: 'color', custom: true },
       ],
       rules: {
         total: [{ required: true, message: '请输入总人数' }],
         day: [{ required: true, message: '请输入每批所需天数' }],
-        batchnum: [{ required: true, message: '请输入默认每期中的批次数' }],
-        classnum: [{ required: true, message: '请输入默认每批次中的班级数' }],
-        stunum: [{ required: true, message: '请输入默认每班中的人数' }],
         carpnum: [{ required: true, message: '请输入默认每车人数' }],
       },
     };
@@ -62,19 +119,20 @@ export default {
       let planyearid = _.get(this.defaultOption, 'planyearid');
       let planid = _.get(this.defaultOption, 'planid');
       let res = await this.modelFetch({ model: 'trainmodel', planyearid, planid });
-      // let res = await this.query();
       if (this.$checkRes(res)) {
-        this.$set(this, `info`, res.data ? res.data : {});
+        res.data ? this.$set(this, `info`, res.data) : '';
         this.$set(this, `isNew`, res.data == null);
       }
     },
-    async handleSave({ isNew, data }) {
+    async handleSave() {
+      let data = _.cloneDeep(this.info);
       let res;
-      if (isNew) {
+      if (this.isNew) {
         let planyearid = _.get(this.defaultOption, 'planyearid');
         let planid = _.get(this.defaultOption, 'planid');
         res = await this.create({ ...data, planyearid, planid });
       } else {
+        delete data.stunum;
         res = await this.update(data);
       }
       this.$checkRes(res, '保存成功', res.errmsg || '保存失败');
@@ -100,6 +158,43 @@ export default {
     toClear() {
       this.info.color = [];
     },
+    addClass(bindex) {
+      let len = _.get(this.info.batchnum[bindex].classnum, 'length', 0);
+      this.info.batchnum[bindex].classnum.push({ class: len + 1, number: 56 });
+      this.$forceUpdate();
+    },
+    toDelete(bindex, index) {
+      let duplicate = _.cloneDeep(this.info.batchnum[bindex]);
+      //删除指定行
+      duplicate.classnum.splice(index, 1);
+      //重新排列班级序号
+      duplicate.classnum = duplicate.classnum.map((i, index) => {
+        i.class = index + 1;
+        return i;
+      });
+      this.$set(this.info.batchnum, bindex, duplicate);
+    },
+    init() {
+      this.info.color = ['#E60000', '#FF7300', '#996B1F', '#FFD700', '#AFA4E0', '#74868A', '#09A343', '#E9F1F4'];
+      this.info.stunum = [];
+      this.info.batchnum = [];
+    },
+    addBatch() {
+      let len = this.info.batchnum.length;
+      let arr = _.cloneDeep(this.info.batchnum);
+      arr.push({ batch: len + 1, classnum: [] });
+      this.$set(this.info, 'batchnum', arr);
+      this.$forceUpdate();
+    },
+    deleteBatch(index) {
+      let duplicate = _.cloneDeep(this.info.batchnum);
+      duplicate.splice(index, 1);
+      duplicate = duplicate.map((i, index) => {
+        i.batch = index + 1;
+        return i;
+      });
+      this.$set(this.info, `batchnum`, duplicate);
+    },
   },
   computed: {
     ...mapState(['user', 'defaultOption']),
@@ -107,6 +202,14 @@ export default {
       return `${this.$route.meta.title}`;
     },
   },
+  watch: {
+    // 'info.stunum': {
+    //   handler(val) {
+    //     let len = _.get(this.info.stunum, 'length', 0);
+    //     this.$set(this.info, `classnum`, len);
+    //   },
+    // },
+  },
   metaInfo() {
     return { title: this.$route.meta.title };
   },

+ 0 - 212
src/views/plan/classes.vue

@@ -1,212 +0,0 @@
-<template>
-  <div id="plan">
-    <!-- 根据计划,获取所有期数及期数下批次,然后提供选择期数;查询出该期数下学校上报的学生,选择学生手动分班 -->
-    <list-frame :title="mainTitle" @query="stuSearch" :total="total" :filter="filterFields" :needAdd="false" returns="/plan/index">
-      <template #options="{item}">
-        <template v-if="item.model === 'termid'">
-          <el-option v-for="(i, index) in termList" :key="index" :label="`第${i.term}期`" :value="i._id"></el-option>
-        </template>
-      </template>
-      <el-card>
-        <el-row type="flex" justify="space-around" :gutter="10" align="middle" style="padding:10px 0;">
-          <el-col :span="7">班级需求:{{ selectInfo.personReq }}人</el-col>
-          <el-col :span="7">已选择学生:{{ selected.length }}人</el-col>
-          <el-col :span="7">男性:{{ selectInfo.male }}人</el-col>
-          <el-col :span="7">女性:{{ selectInfo.female }}人</el-col>
-        </el-row>
-        <el-row>
-          <el-form :inline="true" size="mini">
-            <el-form-item label="批次">
-              <el-select v-model="selectInfo.batchid" placeholder="请先选择期数" @change="getClasses">
-                <el-option v-for="(i, index) in batchList" :key="index" :label="i.name" :value="i._id"></el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="班级">
-              <el-select v-model="selectInfo.classname" placeholder="请先选择批次">
-                <el-option v-for="(i, index) in classList" :key="index" :label="i.name" :value="i.name"></el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="toSetClass">确认分班</el-button>
-            </el-form-item>
-          </el-form>
-        </el-row>
-      </el-card>
-      <data-table
-        ref="table"
-        :fields="fields"
-        :data="list"
-        :opera="opera"
-        :select="true"
-        :selected="selected"
-        @edit="toEdit"
-        @delete="toDelete"
-        @handleSelect="toSelect"
-      ></data-table>
-    </list-frame>
-  </div>
-</template>
-
-<script>
-import listFrame from '@frame/layout/admin/list-frame';
-import dataTable from '@frame/components/data-table';
-import _ from 'lodash';
-import { mapStatem, createNamespacedHelpers } from 'vuex';
-const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
-const { mapActions: schPlan } = createNamespacedHelpers('schPlan');
-const { mapActions: student } = createNamespacedHelpers('student');
-const { mapActions: classes } = createNamespacedHelpers('classes');
-const { mapActions: director } = createNamespacedHelpers('director');
-const { mapActions: dept } = createNamespacedHelpers('dept');
-export default {
-  metaInfo: { title: '安排班级' },
-  name: 'plan',
-  props: {},
-  components: { listFrame, dataTable },
-  data: () => ({
-    opera: [],
-    fields: [
-      { label: '学生姓名', prop: 'name' },
-      { label: '学校', prop: 'school_name' },
-      { label: '性别', prop: 'gender' },
-    ],
-    filterFields: [{ label: '期数', model: 'termid', type: 'select' }],
-    list: [],
-    selected: [],
-    selectedTest: [],
-    total: 0,
-    selectInfo: {
-      male: 0,
-      female: 0,
-      personReq: 0,
-    },
-    termList: [],
-    batchList: [],
-    classList: [],
-    directorList: [],
-    deptList: [],
-  }),
-  created() {
-    this.search();
-  },
-  methods: {
-    ...trainPlan(['fetch']),
-    ...schPlan({ schQuery: 'query' }),
-    ...student({ getStudentList: 'noClass' }), //noClass
-    ...classes({ getClassesList: 'query', createClass: 'divide' }),
-    ...director({ getDirectorList: 'query' }),
-    ...dept({ getDeptList: 'query' }),
-    async search({ skip = 0, limit = 10, ...info } = {}) {
-      const res = await this.fetch(this.id);
-      if (this.$checkRes(res)) {
-        let { termnum } = res.data;
-        this.$set(this, `termList`, termnum);
-      }
-    },
-    //查询选择期上报的学生,提供批次选择
-    async stuSearch({ skip = 0, limit = 10, ...info } = {}) {
-      let { termid } = info;
-      this.selectInfo.termid = termid;
-      const res = await this.getStudentList({ termid: termid, skip, limit });
-      if (this.$checkRes(res)) {
-        this.$set(this, `list`, res.data);
-        this.$set(this, `total`, res.total);
-      }
-      if (skip !== 0) return;
-      this.getBatch(termid);
-    },
-    getBatch(termid) {
-      let batchs = this.termList.filter(f => f._id === termid);
-      if (batchs.length > 0) {
-        let { batchnum } = batchs[0];
-        this.$set(this, `batchList`, batchnum);
-      }
-    },
-    //根据批次id,查询下面的班级
-    async getClasses(data) {
-      //查询班级
-      if (!data) return;
-      const res = await this.getClassesList({ batchid: data });
-      // gc1 因为已经限制了分班人数,所以不允许出现班级人数不够的情况,查出来的班级就不应该生成,可以使用name过滤掉选项
-      let classList = [];
-      if (this.$checkRes(res)) {
-        if (res.data.length > 0) classList = res.data;
-      }
-      //整理班级数据,根据批次中的class数量,人数,创建班级
-      let batch = this.batchList.find(f => f._id === data);
-      let { name, class: classnum = 1, type, number } = batch;
-      this.selectInfo.type = type;
-      this.$set(this.selectInfo, `personReq`, number);
-      let arr = [];
-      for (let i = 1; i <= classnum; i++) {
-        let object = { name: `${name}${type === '0' ? `${i}班` : ''}` };
-        arr.push(object);
-      }
-      // gc1 过滤掉
-      arr = arr.filter(f => !classList.find(c => c.name == f.name));
-      this.$set(this, `classList`, arr);
-    },
-    toEdit({ data }) {
-      this.$router.push({ path: '/dept/detail', query: { id: data.id } });
-    },
-    async toDelete({ data }) {
-      const res = await this.delete(data.id);
-      this.$checkRes(res, '删除成功', '删除失败');
-      this.search();
-    },
-    toSelect(selecteds) {
-      this.$set(this, `selected`, selecteds);
-      let male = 0,
-        female = 0;
-      for (const i of selecteds) {
-        if (i.gender === '1' || i.gender === '男') male++;
-        else female++;
-      }
-      this.$set(this.selectInfo, `male`, male);
-      this.$set(this.selectInfo, `female`, female);
-    },
-    async toSetClass() {
-      // 整理数据生成班级;将学生列表重新查询=>为了将已经有班级的学生剔除,以便继续分班(重新查询)
-      let info = JSON.parse(JSON.stringify(_.omit(this.selectInfo, ['male', 'female', 'personReq'])));
-      let stuList = JSON.parse(JSON.stringify(this.selected));
-      if (this.isOutRange(stuList)) return;
-      info.students = stuList;
-      let res = await this.createClass(info);
-      if (this.$checkRes(res, '分班成功', '分班失败')) this.$router.push({ path: '/plan/index' });
-      //重置信息
-      // this.selectInfo = {
-      //   male: 0,
-      //   female: 0,
-      // };
-      // this.selected = [];
-      // this.$refs.table.selectReset();
-    },
-    isOutRange(selected) {
-      let res = true;
-      if (selected.length <= 0) this.$message.warning('请选择学生');
-      else if (_.inRange(selected.length, 1, this.selectInfo.personReq * 1)) this.$message.error('选择人数不足');
-      else if (selected.length > this.selectInfo.personReq * 1) this.$message('超出班级规定人数');
-      else res = false;
-      return res;
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-    id() {
-      return this.$route.query.id;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 395
src/views/plan/detail.vue

@@ -1,395 +0,0 @@
-<template>
-  <div id="detail">
-    <detail-frame :title="mainTitle" returns="/plan/index">
-      <el-row :gutter="10" type="flex">
-        <el-col :span="12">
-          <el-card header="全年计划信息">
-            <el-form :model="info" :rules="rules" :isNew="isNew" label-width="60px" size="small" @submit.native.prevent>
-              <el-form-item label="年份" required>
-                {{ info.year }}
-              </el-form-item>
-              <el-form-item label="标题" prop="title" required>
-                <el-input v-model="info.title"></el-input>
-              </el-form-item>
-
-              <el-collapse v-model="collapse" accordion>
-                <el-collapse-item title="计划简表" name="1">
-                  <data-table :fields="fields" :data="selectList" :opera="opera" @edit="toEdit" @delete="toDelete" :height="heights"></data-table>
-                </el-collapse-item>
-              </el-collapse>
-              <el-form-item>
-                <el-row type="flex" align="middle" justify="space-around" style="margin-top:20px">
-                  <el-col :span="6">
-                    <el-button type="primary" @click="savePlan">保存全年计划</el-button>
-                  </el-col>
-                </el-row>
-              </el-form-item>
-            </el-form>
-          </el-card>
-        </el-col>
-        <el-col :span="16" :style="`width:${widths}px`">
-          <el-card ref="card" v-if="info.year">
-            <calendar :year="`${info.year}`" :selfBtn="selfBtn" @draft="selectDate" @eventClick="eventClick" :events="events"></calendar>
-          </el-card>
-        </el-col>
-      </el-row>
-    </detail-frame>
-    <el-drawer :visible.sync="drawer" direction="rtl" title="安排计划" @close="toClose">
-      <event :data="form" :year="info.year" :vacation="vacation" :isNew="formIsNew" :predefineColors="predefineColors" @save="setEvent"></event>
-    </el-drawer>
-    <el-dialog title="设置假期" :visible.sync="dialog">
-      <vacation-form :list="vacation" @update="setVacation"></vacation-form>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import detailFrame from '@frame/layout/admin/detail-frame';
-import calendar from '@frame/components/calendar';
-import dataTable from '@frame/components/data-table';
-import vacationForm from './parts/vacation';
-import event from './parts/event';
-import _ from 'lodash';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions } = createNamespacedHelpers('trainplan');
-export default {
-  metaInfo: { title: '计划详情' },
-  name: 'detail',
-  props: {},
-  components: { detailFrame, calendar, dataTable, event, vacationForm },
-  data() {
-    return {
-      info: {},
-      form: { color: '#409EFF' },
-      rules: {
-        title: [{ required: true, message: '请输入标题' }],
-      },
-      formRules: {
-        start: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
-        end: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
-        term: [{ required: true, message: '请输入期数' }],
-        number: [{ required: true, message: '请输入每班人数' }],
-        type: [{ required: true, message: '请选择班级类型' }],
-      },
-      drawer: false,
-      dialog: false,
-      formIsNew: true,
-      events: [],
-      predefineColors: ['#409EFF'],
-      collapse: '',
-      fields: [
-        { label: '开始时间', prop: 'start' },
-        { label: '结束时间', prop: 'end' },
-        { label: '期数', prop: 'term' },
-        { label: '班级类型', prop: 'type', format: item => (item === '0' ? '正常班级' : '特殊班级') },
-      ],
-      opera: [
-        {
-          label: '编辑',
-          icon: 'el-icon-edit',
-          method: 'edit',
-        },
-        {
-          label: '删除',
-          icon: 'el-icon-delete',
-          method: 'delete',
-          confirm: true,
-        },
-      ],
-      heights: 250,
-      selfBtn: {
-        vacation: {
-          text: '设置假期',
-          //设置假期
-          click: () => (this.dialog = true),
-          position: 'left',
-        },
-      },
-      selectList: [],
-      vacation: [],
-    };
-  },
-  created() {
-    if (this.isNew) this.$set(this.info, `year`, new Date().getFullYear());
-  },
-  mounted() {},
-  methods: {
-    ...mapActions(['fetch', 'create', 'update']),
-    //查询计划
-    async search() {
-      const res = await this.fetch(this.id);
-      if (this.$checkRes(res)) this.$set(this, `info`, res.data);
-      let midArr = JSON.parse(JSON.stringify(res.data));
-      let events = [];
-      events = _.flatten(
-        midArr.termnum.map(item => {
-          item.batchnum.map(i => {
-            i.term = item.term;
-            i.id = i._id;
-            i.start = JSON.parse(JSON.stringify(i.startdate));
-            i.end = JSON.parse(JSON.stringify(i.enddate));
-            i.title = JSON.parse(JSON.stringify(i.name));
-            delete i.startdate, delete i.enddate;
-            return i;
-          });
-          return item.batchnum;
-        })
-      );
-      //这个events不完整,真正的events还需要将假期的数据整合至一起
-      //计划+假期=所有事件 当前events=selectList 计划事件
-      let vac = midArr.festivals.map(i => {
-        let object = {};
-        object.start = i.begindate;
-        object.end = i.finishdate;
-        object.rendering = 'background';
-        object.color = 'red';
-        object.editable = false;
-        return object;
-      });
-      this.$set(this, `vacation`, vac);
-      this.$set(this, `selectList`, JSON.parse(JSON.stringify(events)));
-      this.$set(this, `events`, events.concat(vac));
-    },
-    //拖拽选择事件
-    selectDate(object) {
-      let start = JSON.parse(JSON.stringify(object.startStr));
-      let end = JSON.parse(JSON.stringify(object.endStr));
-      this.$set(this.form, `start`, start);
-      this.$set(this.form, `end`, end);
-      let res = this.inVacation(start, end);
-      if (!res) {
-        this.$message.warning(`不能将计划安排在假期中!`);
-        return;
-      }
-      this.drawer = true;
-      this.formIsNew = true;
-    },
-    //日历事件点击事件
-    eventClick({ event }) {
-      let arr = this.events.filter(fil => fil.id == event.id);
-      if (arr.length > 0) this.form = arr[0];
-      else {
-        console.warn(`无对应id事件`);
-        return;
-      }
-      this.drawer = true;
-      this.formIsNew = false;
-    },
-    //列表编辑事件
-    toEdit({ data, index }) {
-      this.$set(this, `form`, JSON.parse(JSON.stringify(data)));
-      this.formIsNew = false;
-      this.drawer = true;
-    },
-    //列表删除事件
-    toDelete({ data, index }) {
-      this.$set(
-        this,
-        `events`,
-        this.events.filter(f => f.id !== data.id)
-      );
-      // this.events.splice(index, 1);
-      this.selectList.splice(index, 1);
-    },
-    //全年计划保存验证
-    toSavePlan() {
-      this.$refs['planForm'].validate(valid => {
-        if (valid) {
-          this.savePlan();
-        } else {
-          console.warn('form validate error!!!');
-        }
-      });
-    },
-    //保存计划事件
-    savePlan() {
-      let data = JSON.parse(JSON.stringify(this.info));
-      data.year = this.info.year;
-      let termnum = [];
-      //1,获取所有期数
-      //2,按期数将selectList内数据分组
-      termnum = _.uniq(this.selectList.map(item => item.term)).map(i => {
-        let object = { term: i };
-        object.batchnum = this.selectList
-          .filter(fil => fil.term === i)
-          .map(b => {
-            console.log(b);
-            b = _.pickBy(b, (val, key) => key !== 'term');
-            b.startdate = JSON.parse(JSON.stringify(b.start));
-            b.enddate = JSON.parse(JSON.stringify(b.end));
-            b.name ? b.name : (b.name = JSON.parse(JSON.stringify(b.title)));
-            delete b.start, delete b.end;
-            if (_.startsWith(b.id, 'eve') || _.startsWith(b.id, 'vac')) delete b.id;
-            return b;
-          });
-        object.classnum = object.batchnum.reduce((pre, cur) => {
-          if (cur.type === '0') return pre + parseInt(cur.class);
-          else return pre + 1;
-        }, 0);
-        return object;
-      });
-      data.termnum = termnum;
-      //3 设置假期
-      let vacation = JSON.parse(JSON.stringify(this.vacation));
-      vacation = vacation.map(i => {
-        let object = { begindate: i.start, finishdate: i.end, name: i.title };
-        return object;
-      });
-      data.festivals = vacation;
-      console.log(data);
-      let res;
-      let msg;
-      if (this.isNew) {
-        res = this.create(data);
-        msg = `${this.keyWord}添加成功`;
-      } else {
-        res = this.update(data);
-        msg = `${this.keyWord}修改成功`;
-      }
-      if (this.$checkRes(res, msg)) this.$router.push({ path: '/plan/index' });
-    },
-    //重置表单函数
-    resetForm() {
-      this.$refs.form.resetFields();
-      this.setHeight();
-    },
-    //添加/修改函数
-    setEvent({ data: form, isNew }) {
-      // 需要根据班级类型把数据分开
-      let data = JSON.parse(JSON.stringify(form));
-      let { start, end, term, type, number, color, id } = data;
-      let object = {};
-      if (data.type === '0') {
-        // 正常班级
-        let { batch, class: classes } = data;
-        object = { start, end, term, type, number, color, batch, class: classes };
-        object.title = `第${JSON.parse(JSON.stringify(term))}期第${JSON.parse(JSON.stringify(batch))}批次`;
-        object.name = JSON.parse(JSON.stringify(object.title));
-      } else {
-        let { name } = data;
-        object = { ...data, title: name };
-      }
-      if (isNew) {
-        object.id = `eve${new Date().getTime()}`;
-        this.events.push(object);
-        this.selectList.push(object);
-      } else {
-        object.id = id;
-        this.$set(
-          this.events,
-          _.findIndex(this.events, item => item.id == object.id),
-          object
-        );
-        this.$set(
-          this.selectList,
-          _.findIndex(this.selectList, item => item.id == object.id),
-          object
-        );
-      }
-      if (_.findIndex(this.predefineColors, item => item == data.color) < 0) this.predefineColors.push(data.color);
-      this.toClose();
-    },
-    //关闭抽屉函数
-    toClose() {
-      this.drawer = false;
-      this.form = { color: '#409EFF' };
-      this.formIsNew = true;
-      this.setHeight();
-    },
-    setHeight() {
-      let heights = this.$refs.card.$el.clientHeight * 0.63;
-      this.$set(this, `heights`, heights);
-    },
-    //更新假期列表
-    setVacation({ data, type }) {
-      this.$set(this, `vacation`, data);
-      let arr = [];
-      if (type === 'add') {
-        arr = data.map(i => {
-          i.color = `red`;
-          i.editable = false;
-          i.id ? '' : (i.id = `vac${new Date().getTime()}`);
-          i.rendering = 'background';
-          return i;
-        });
-        this.$set(this, `events`, this.selectList.concat(arr));
-      } else if (type === 'edit') {
-        for (const i of data) {
-          this.$set(
-            this.events,
-            _.findIndex(this.events, item => item.id == i.id),
-            i
-          );
-        }
-      } else if (type === 'delete') {
-        this.$set(this, `events`, this.selectList.concat(data));
-      }
-    },
-    //判断是否在假期中
-    inVacation(start, end) {
-      let startTime = new Date(start).getTime();
-      let endTime = new Date(end).getTime();
-      let res = true;
-      for (const vac of this.vacation) {
-        let vacS = new Date(vac.start).getTime();
-        let vacE = new Date(vac.end).getTime();
-        //case1 事件开始时间<假期开始时间 => 事件结束时间 > 假期开始时间 ? 事件碰到假期了.不行了 : 事件没碰到假期,没事
-        //case2 事件开始时间>=假期开始时间 => 事件开始时间 < 假期结束时间 ? GG return false: return true;
-        if (startTime >= vacS) {
-          if (startTime < vacE) {
-            res = false;
-            console.warn(`case2`);
-            break;
-          }
-        } else {
-          if (endTime > vacS) {
-            res = false;
-            console.warn(`case1`);
-            break;
-          }
-        }
-      }
-      //比较选择的时间在不在假期中,然后返回结果
-      return res;
-    },
-  },
-  watch: {
-    isNew: {
-      immediate: true,
-      handler(val) {
-        if (val) this.loading = false;
-        else this.search();
-      },
-    },
-  },
-  computed: {
-    widths() {
-      let width = (document.body.clientWidth - 200) * 0.5;
-      return width > 400 ? width : 400;
-    },
-    id() {
-      return this.$route.query.id;
-    },
-    isNew() {
-      return this.$route.query.id ? false : true; //false : true;
-    },
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped>
-/deep/.el-divider--horizontal {
-  margin: 5px 0;
-}
-</style>

+ 0 - 140
src/views/plan/index.vue

@@ -1,140 +0,0 @@
-<template>
-  <div id="index">
-    <list-frame :title="mainTitle" @query="search" :total="total" :needFilter="false" @add="$router.push({ path: '/plan/detail' })">
-      <data-table
-        :fields="fields"
-        :data="list"
-        :opera="opera"
-        @edit="toEdit"
-        @delete="toDelete"
-        @publish="toPublish"
-        @classes="toClasses"
-        @lesson="toLesson"
-        @ques="toQues"
-      ></data-table>
-    </list-frame>
-  </div>
-</template>
-
-<script>
-import listFrame from '@frame/layout/admin/list-frame';
-import dataTable from '@frame/components/data-table';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
-
-export default {
-  metaInfo: { title: '计划管理' },
-  name: 'index',
-  props: {},
-  components: {
-    listFrame,
-    dataTable,
-  },
-  data: () => ({
-    opera: [
-      {
-        label: '编辑',
-        icon: 'el-icon-edit',
-        // display: i => i.status === '0',
-        method: 'edit',
-      },
-      {
-        label: '删除',
-        icon: 'el-icon-delete',
-        display: i => i.status === '0',
-        method: 'delete',
-        confirm: true,
-      },
-      {
-        label: '发布',
-        icon: 'el-icon-view',
-        method: 'publish',
-        methodZh: i => `您确认发布计划: ${i.title}`,
-        display: i => i.status === '0',
-        confirm: true,
-      },
-      {
-        label: '安排班级',
-        icon: 'el-icon-school',
-        display: i => i.status === '1',
-        method: 'classes',
-      },
-      {
-        label: '安排课程',
-        icon: 'el-icon-date',
-        display: i => i.status === '1',
-        method: 'lesson',
-      },
-      {
-        label: '添加调查问卷',
-        icon: 'el-icon-edit-outline',
-        display: i => i.status === '1',
-        method: 'ques',
-      },
-    ],
-    fields: [
-      { label: '计划标题', prop: 'title' },
-      { label: '年度', prop: 'year' },
-      {
-        label: '状态',
-        prop: 'status',
-        format: i => {
-          return i === '0' ? '筹备中' : i === '1' ? '发布中' : '已结束';
-        },
-      },
-    ],
-    list: [],
-    total: 0,
-  }),
-  created() {
-    this.search();
-  },
-  methods: {
-    ...trainPlan(['query', 'delete', 'update']),
-    async search({ skip = 0, limit = 10, ...info } = {}) {
-      const res = await this.query({ skip, limit, ...info });
-      if (this.$checkRes(res)) {
-        this.$set(this, `list`, res.data);
-        this.$set(this, `total`, res.total);
-      }
-    },
-    toEdit({ data }) {
-      this.$router.push({ path: '/plan/detail', query: { id: data.id } });
-    },
-    async toDelete({ data }) {
-      const res = await this.delete(data.id);
-      this.$checkRes(res, '删除成功', '删除失败');
-      this.search();
-    },
-    async toPublish({ data }) {
-      let { id } = data;
-      let res = await this.update({ id, status: '1' });
-      this.$checkRes(res, '发布成功', '发布失败');
-    },
-    toLesson({ data }) {
-      this.$router.push({ path: '/plan/lesson', query: { id: data.id } });
-    },
-    toClasses({ data }) {
-      this.$router.push({ path: '/plan/classes', query: { id: data.id } });
-    },
-    toQues({ data }) {
-      this.$router.push({ path: '/plan/question', query: { id: data.id } });
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 434
src/views/plan/lesson-plan.vue

@@ -1,434 +0,0 @@
-<template>
-  <div id="lesson-plan">
-    <el-collapse v-model="activeName" accordion v-if="views === 'setting'">
-      <template v-if="classList.length > 0">
-        <el-collapse-item v-for="(item, index) in classList" :key="`coli${index}`" :name="`${index}`">
-          <template slot="title">
-            <span style="font-size:24px">{{ item.name }}</span>
-          </template>
-          <data-table style="padding:10px" ref="table" :fields="fields" :data="item.lessons" :opera="opera" @edit="toEdit"></data-table>
-          <el-form :inline="true" size="mini" label-width="120px" @submit.native.prevent>
-            <el-form-item label="班主任">
-              <el-select v-model="item.headteacherid" placeholder="请选择班主任">
-                <el-option-group v-for="group in directorList" :key="group.label" :label="group.label">
-                  <el-option v-for="item in group.options" :key="item._id" :label="`${item.name}${item.status === '0' ? '(已上报)' : ''}`" :value="item._id">
-                  </el-option>
-                </el-option-group>
-              </el-select>
-            </el-form-item>
-
-            <el-form-item label="礼仪课教师">
-              <el-select v-model="item.lyteacherid" placeholder="请选择礼仪课教师">
-                <el-option v-for="(tea, index) in lyTeacherList" :key="`lytea${index}`" :label="tea.name" :value="tea.id"></el-option>
-              </el-select>
-            </el-form-item>
-
-            <el-form-item label="教室地点">
-              <el-select v-model="item.jslocationid" placeholder="请选择教室地点">
-                <el-option v-for="(place, index) in locationList" :key="`lytea${index}`" :label="place.name" :value="place.id"></el-option>
-              </el-select>
-            </el-form-item>
-
-            <el-form-item label="开班地点">
-              <el-select v-model="item.kbyslocationid" placeholder="请选择开班地点">
-                <el-option v-for="(place, index) in locationList" :key="`lytea${index}`" :label="place.name" :value="place.id"></el-option>
-              </el-select>
-            </el-form-item>
-
-            <el-form-item label="拓展训练地点">
-              <el-select v-model="item.kzjhlocationid" placeholder="请选择拓展训练地点">
-                <el-option v-for="(place, index) in locationList" :key="`lytea${index}`" :label="place.name" :value="place.id"></el-option>
-              </el-select>
-            </el-form-item>
-
-            <el-form-item label="用餐地点">
-              <el-select v-model="item.yclocationid" placeholder="请选择用餐地点">
-                <el-option v-for="(place, index) in locationList" :key="`lytea${index}`" :label="place.name" :value="place.id"></el-option>
-              </el-select>
-            </el-form-item>
-            <el-row type="flex" justify="center" align="middle">
-              <el-col :span="5">
-                <el-button type="primary" @click="saveLessson(item.classid)" size="mini">保存班级课程</el-button>
-              </el-col>
-              <el-col :span="5">
-                <el-button type="primary" @click="toPreview(item.classid)" plain size="mini">课表预览</el-button>
-              </el-col>
-            </el-row>
-          </el-form>
-        </el-collapse-item>
-      </template>
-      <template v-else>
-        <el-collapse-item title="该批次未分班,无法继续排课!" name="none"></el-collapse-item>
-      </template>
-    </el-collapse>
-    <cards title="课表预览" :returns="toReturns" v-else>
-      <time-table :data="previews"></time-table>
-    </cards>
-    <el-drawer :with-header="false" :visible.sync="drawer" direction="rtl" @close="drawerClose">
-      <el-tabs>
-        <el-tab-pane style="padding:10px">
-          <template #label>
-            <span style="zoom:1.3">{{ form.name }}</span>
-          </template>
-          <el-form ref="form" :model="form" label-width="120px" size="mini" :rules="rules" @submit.native.prevent>
-            <el-form-item label="时间" prop="date">
-              {{ form.date }}
-            </el-form-item>
-            <el-form-item label="星期" prop="week">
-              {{ form.week }}
-            </el-form-item>
-            <el-form-item label="所授科目" prop="subid">
-              <el-select v-model="form.subid">
-                <el-option v-for="(item, index) in subjectList" :key="`subject${index}`" :label="item.name" :value="item.id"></el-option>
-              </el-select>
-            </el-form-item>
-            <el-form-item label="任课教师" prop="teaid">
-              <el-input v-model="form.teaname" :readonly="true" placeholder="点击选择教师" @click.native="toChooseTeacher"></el-input>
-            </el-form-item>
-            <el-form-item label="时长" prop="day" required>
-              <el-radio-group v-model="form.day" @change="$forceUpdate()">
-                <el-radio v-for="(i, index) in dayList" :key="`day${index}`" :label="i.label"></el-radio>
-              </el-radio-group>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="toSaveDrawer">保存</el-button>
-              <el-button @click="resetDrawer">重置</el-button>
-            </el-form-item>
-          </el-form>
-        </el-tab-pane>
-      </el-tabs>
-    </el-drawer>
-    <el-dialog :visible.sync="dialog" title="选择教师" center @close="toClose">
-      <el-tabs v-model="teaTab">
-        <el-tab-pane style="padding:10px" label="申请授课教师" name="apply">
-          <el-form :model="applyTeacherListPag" :inline="true">
-            <el-form-item label="姓名">
-              <el-input v-model="applyTeacherListPag.name" size="mini" placeholder="请输入要查询的教师姓名"></el-input>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" size="mini" @click="changePage(null, 'apply')">查询</el-button>
-            </el-form-item>
-          </el-form>
-          <data-table style="padding:10px" :fields="teaFields" :data="applyTeacherList" :opera="teaOpera" @seletTea="setTea" :height="300"></data-table>
-        </el-tab-pane>
-        <el-tab-pane style="padding:10px" label="可授课教师" name="list">
-          <el-form :model="teacherListPag" :inline="true">
-            <el-form-item label="姓名">
-              <el-input v-model="teacherListPag.name" size="mini" placeholder="请输入要查询的教师姓名"></el-input>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" size="mini" @click="changePage(null, 'teacher')">查询</el-button>
-            </el-form-item>
-          </el-form>
-          <data-table style="padding:10px" :fields="teaFields" :data="teacherList" :opera="teaOpera" @seletTea="setTea" :height="300"></data-table>
-          <el-row type="flex" align="middle" justify="end">
-            <el-col :span="24" style="text-align:right;">
-              <el-pagination
-                background
-                layout="total, prev, pager, next"
-                :total="teacherListPag.total"
-                :page-size="5"
-                :current-page.sync="teacherListPag.currentPage"
-                @current-change="cur => changePage(cur, 'teacher')"
-              >
-              </el-pagination>
-            </el-col>
-          </el-row>
-        </el-tab-pane>
-      </el-tabs>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import _ from 'lodash';
-import timeTable from '@frame/parts/time-table';
-import cards from '@frame/parts/cards';
-import dataTable from '@frame/components/data-table';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions: location } = createNamespacedHelpers('location'); //地点
-const { mapActions: subject } = createNamespacedHelpers('subject'); //科目
-const { mapActions: teacher } = createNamespacedHelpers('teacher'); //教师
-const { mapActions: teaPlan } = createNamespacedHelpers('teaPlan'); //教师申请
-const { mapActions: dept } = createNamespacedHelpers('dept'); //配合教师表使用的部门表
-const { mapActions: dirPlan } = createNamespacedHelpers('dirPlan'); //班主任不能上课的列表
-
-export default {
-  name: 'lesson-plan',
-  props: {
-    startDate: { type: String, required: true },
-    endDate: { type: String, required: true },
-    classes: { type: Array, default: () => [] },
-    trainplanid: { type: String },
-    batchid: { type: String },
-  },
-  components: { dataTable, timeTable, cards },
-  data: () => ({
-    start: '',
-    end: '',
-    views: 'setting',
-    activeName: '0',
-    drawer: false,
-    dialog: false,
-    teaTab: 'apply',
-    dateList: [],
-    classList: [],
-    fields: [
-      { label: '日期', prop: 'date' },
-      { label: '星期', prop: 'week' },
-      { label: '课程', prop: 'subname' },
-      { label: '任课教师', prop: 'teaname' },
-    ],
-    opera: [
-      {
-        label: '安排课程及教师',
-        icon: 'el-icon-edit',
-        method: 'edit',
-      },
-    ],
-    teaOpera: [
-      {
-        label: '选择教师',
-        icon: 'el-icon-check',
-        method: 'seletTea',
-      },
-    ],
-    teaFields: [
-      { label: '姓名', prop: 'name' },
-      { label: '学校', prop: 'schname' },
-      { label: '资料评分', prop: 'zlscore' },
-      { label: '面试评分', prop: 'msscore' },
-    ],
-    dayList: [{ label: '一天' }, { label: '半天' }],
-    rules: {
-      day: [{ required: true, message: '请选择时长' }],
-    },
-    form: {},
-    locationList: [],
-    subjectList: [],
-    lyTeacherList: [],
-    teacherList: [],
-    applyTeacherList: [],
-    directorList: [],
-    deptList: [],
-    teacherListPag: {
-      total: 0,
-      cur: 1,
-    },
-    applyTeacherListPag: {},
-    previews: {},
-  }),
-  created() {
-    this.setDateList();
-    this.setClasses();
-    this.getOtherList();
-  },
-  methods: {
-    ...dirPlan({ dirQuery: 'getDirTeacher' }),
-    ...location({ getLocationList: 'query' }),
-    ...subject({ getSubjectList: 'query' }),
-    ...teacher({ getTeacherList: 'query' }),
-    ...teaPlan({ getApplyTeacherList: 'applyQuery' }),
-    ...dept({ getDeptList: 'query' }),
-    setDateList() {
-      let start = new Date(this.startDate);
-      let end = new Date(this.endDate);
-      this.$set(this, `start`, this.$fullDateString(new Date(start)));
-      let day = (end.getTime() - start.getTime()) / (1 * 24 * 60 * 60 * 1000);
-      let endDate = this.$fullDateString(new Date(new Date(start).setDate(new Date(start).getDate() + day - 1)));
-      this.$set(this, `end`, endDate);
-      let arr = [];
-      for (let index = 0; index < day; index++) {
-        let s = new Date(JSON.parse(JSON.stringify(start)));
-        let i = s.setDate(s.getDate() + index);
-        i = this.$fullDateString(new Date(i));
-        let object = {
-          date: i,
-          week: new Date(i).getDay() === 0 ? 7 : new Date(i).getDay(),
-        };
-        arr.push(object);
-      }
-      this.$set(this, `dateList`, arr);
-    },
-    setClasses() {
-      let classes = JSON.parse(JSON.stringify(this.classes));
-      classes.map(i => {
-        i.lessons
-          ? i.lessons.map(i => {
-              i.week = new Date(i.date).getDay() === 0 ? 7 : new Date(i.date).getDay();
-            })
-          : (i.lessons = JSON.parse(JSON.stringify(this.dateList)));
-        return i;
-      });
-      this.$set(this, `classList`, classes);
-    },
-    toEdit({ data }) {
-      //班级信息
-      let sClass = JSON.parse(JSON.stringify(this.classes[this.activeName]));
-      //点击的日期,星期
-      let arrange = data;
-      //让用户选择课程=>根据选择的课程查询可以教课的老师,根据老师的评分排序(不一定谁做)
-      // 1先查询课程列表
-      // 2先查询arr中,是否有选择的课程,有则查询教师列表
-      this.$set(this, `form`, { ...sClass, ...arrange });
-      this.form.day ? '' : (this.form.day = '一天');
-      this.drawer = true;
-    },
-    resetDrawer() {
-      this.$set(this.form, `subid`);
-      this.$set(this.form, `subname`);
-      this.$set(this.form, `teaid`);
-      this.$set(this.form, `teaname`);
-      delete this.form.teaid, this.form.teaname, this.form.subid, this.form.subname;
-    },
-    toChooseTeacher() {
-      if (this.form.subid) {
-        this.dialog = true;
-        this.toGetTeacherList({});
-      } else this.$message.warning('请选择所授科目');
-    },
-    setTea({ data }) {
-      let { id, name } = data;
-      this.$set(this.form, `teaid`, id);
-      this.$set(this.form, `teaname`, name);
-      this.toClose();
-    },
-    toClose() {
-      this.dialog = false;
-    },
-    drawerClose() {
-      this.drawer = false;
-      this.form = {};
-      this.$refs.form.resetFields();
-    },
-    toSaveDrawer() {
-      this.$refs['form'].validate(valid => {
-        if (valid) {
-          if (this.subjectList.find(f => f._id === this.form.subid)) {
-            this.form.subname = this.subjectList.find(f => f._id === this.form.subid).name;
-          }
-          let form = JSON.parse(JSON.stringify(this.form));
-          let lesson = _.pick(form, ['day', 'subname', 'teaname', 'subid', 'teaid', 'date', 'week']);
-          // 整理列表所需要的数据
-          let res = this.classList.find(f => f.classid === form.classid);
-          let classIndex = this.classList.findIndex(f => f.classid === form.classid);
-          let index = res.lessons.findIndex(f => f.date === form.date);
-          this.$set(this.classList[classIndex].lessons, index, lesson);
-          this.drawerClose();
-        } else {
-          console.warn('form validate error!!!');
-          return false;
-        }
-      });
-    },
-    //选项列表请求
-    async getOtherList() {
-      let res;
-      res = await this.getLocationList();
-      if (this.$checkRes(res)) this.$set(this, `locationList`, res.data);
-      res = await this.getSubjectList();
-      if (this.$checkRes(res)) this.$set(this, `subjectList`, res.data);
-      //TODO 班主任表中的人员也可以成为礼仪老师,现在应该没有
-      // TODO派生:涉及之后回显问题,是要将这个人在教师/班主任表中都查然后获得到
-      res = await this.getTeacherList({ islyteacher: '1' });
-      if (this.$checkRes(res)) this.$set(this, `lyTeacherList`, res.data);
-      res = await this.getDeptList();
-      if (this.$checkRes(res)) this.$set(this, `deptList`, res.data);
-      res = await this.dirQuery({ batchid: this.batchid });
-      if (this.$checkRes(res)) {
-        let arr = res.data;
-        arr = arr.map(i => {
-          let dept = this.deptList.find(f => f._id === i.department);
-          if (res) i.dept_name = dept.name;
-          else i.dept_name = '无所属部门';
-          return i;
-        });
-        let last = this.deptList.map(i => {
-          let options = arr.filter(f => f.department === i._id);
-          let label = i.name;
-          return { options, label };
-        });
-        this.$set(this, `directorList`, last);
-      }
-    },
-    //教师列表请求
-    async toGetTeacherList({ query = {}, type } = {}) {
-      query.subid = this.form.subid;
-      query.termid = this.form.termid;
-      query.status = '4';
-      let setTeacher = async query => {
-        let res = await this.getTeacherList(query);
-        if (this.$checkRes(res)) {
-          this.$set(this, `teacherList`, res.data);
-          this.$set(this.teacherListPag, `total`, res.total);
-        }
-      };
-      let setApply = async query => {
-        let res = await this.getApplyTeacherList(query);
-        if (this.$checkRes(res)) {
-          this.$set(this, `applyTeacherList`, res.data ? res.data : []);
-        }
-      };
-      if (!type) {
-        //都查
-        setTeacher(query);
-        setApply(query);
-      } else if (type === 'teacher') {
-        //查教师
-        setTeacher(query);
-      } else if (type === 'apply') {
-        //查申请授课
-        setApply(query);
-      }
-    },
-    changePage(page = 1, type) {
-      let query = { skip: (page - 1) * 5 < 0 ? 0 : (page - 1) * 5, limit: 5 };
-      if (type === 'teacher') {
-        this.teacherListPag.name && this.teacherListPag.name !== '' ? (query.name = this.teacherListPag.name) : '';
-      } else {
-        this.applyTeacherListPag.name && this.applyTeacherListPag.name !== '' ? (query.name = this.applyTeacherListPag.name) : '';
-      }
-      this.toGetTeacherList({ query, type });
-    },
-    saveLessson(id) {
-      let tcc = this.classList.find(f => f.classid === id);
-      // // 礼仪课,开班地点,教师地点,拓展训练地点修改班级表
-      this.$emit(`save`, tcc);
-    },
-    toPreview(id) {
-      let tcc = this.classList.find(f => f.classid === id);
-      let numArr = tcc.name.match(/\d+/g);
-      let term = numArr[0];
-      let classes = numArr[2];
-      let headteacher = {};
-      this.directorList.map(f => (headteacher = f.options.find(ff => ff.id === tcc.headteacherid)));
-      let lyTeacher = this.lyTeacherList.find(f => f.id === tcc.lyteacherid);
-      let js = this.locationList.find(f => f.id === tcc.jslocationid);
-      let kbys = this.locationList.find(f => f.id === tcc.kbyslocationid);
-      let tzxl = this.locationList.find(f => f.id === tcc.kzjhlocationid);
-      let yc = this.locationList.find(f => f.id === tcc.yclocationid);
-      let object = { term, class: classes, start: this.start, end: this.end, lessons: tcc.lessons, headteacher, lyTeacher, js, kbys, tzxl, yc };
-      this.$set(this, `previews`, object);
-      this.views = 'table';
-    },
-    toReturns() {
-      this.views = 'setting';
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 209
src/views/plan/lesson.vue

@@ -1,209 +0,0 @@
-<template>
-  <div id="lesson">
-    <transition name="el-zoom-in-center">
-      <list-frame
-        v-if="view === 'list'"
-        returns="/plan/index"
-        :title="mainTitle"
-        @query="batchSearch"
-        :total="total"
-        :filter="filterFields"
-        :needAdd="false"
-        :needPag="false"
-      >
-        <template #options="{item}">
-          <template v-if="item.model === 'term'">
-            <el-option v-for="(i, index) in termList" :key="index" :label="`第${i.term}期`" :value="i._id"></el-option>
-          </template>
-        </template>
-        <data-table ref="table" :fields="fields" :data="list" :opera="opera" @date="toDate" @msg="toMsg" @bedroom="toBedroom"></data-table>
-      </list-frame>
-      <detail-frame v-else title="返回批次列表" :returns="returnList">
-        <lesson-plan
-          :startDate="batch.startdate"
-          :endDate="batch.enddate"
-          :classes="classes"
-          :trainplanid="id"
-          :batchid="batchid"
-          @save="handleSave"
-        ></lesson-plan>
-      </detail-frame>
-    </transition>
-  </div>
-</template>
-
-<script>
-import lessonPlan from './lesson-plan';
-import listFrame from '@frame/layout/admin/list-frame';
-import detailFrame from '@frame/layout/admin/detail-frame';
-import dataTable from '@frame/components/data-table';
-import _ from 'lodash';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
-const { mapActions: mapClasses } = createNamespacedHelpers('classes');
-const { mapActions: lesson } = createNamespacedHelpers('lesson'); //教师申请
-const { mapActions: bedroom } = createNamespacedHelpers('bedroom'); //分寝
-
-//教师表,地点表,课程表
-export default {
-  metaInfo: { title: '安排课程' },
-  name: 'lesson',
-  props: {},
-  components: { listFrame, dataTable, detailFrame, lessonPlan },
-  data: () => ({
-    view: 'list',
-    term: '',
-    termList: [],
-    opera: [
-      {
-        label: '排课',
-        icon: 'el-icon-date',
-        method: 'date',
-      },
-      {
-        label: '一键分寝',
-        icon: 'el-icon-s-home',
-        method: 'bedroom',
-      },
-      {
-        label: '发送确认通知',
-        icon: 'el-icon-message-solid',
-        method: 'msg',
-      },
-    ],
-    fields: [
-      { label: '', prop: 'name' },
-      { label: '批数', prop: 'batch' },
-    ],
-    filterFields: [{ label: '期数', model: 'term', type: 'select' }],
-    list: [],
-    batch: {},
-    total: 0,
-    classes: [],
-    batchid: [],
-  }),
-  created() {
-    this.search();
-  },
-  methods: {
-    ...trainPlan({ getTrainPlan: 'fetch', sendNotice: 'notice' }),
-    ...mapClasses({ getClass: 'query', updateClass: 'update' }),
-    ...lesson({ getLessonList: 'query', lessonCreate: 'create', lessonUpdate: 'update' }),
-    ...bedroom({ bedroomApart: 'apart' }),
-    async search({ skip = 0, limit = 10, ...info } = {}) {
-      let res = await this.getTrainPlan(this.id);
-      if (this.$checkRes(res)) {
-        this.$set(this, `termList`, res.data.termnum);
-      }
-    },
-    batchSearch({ skip, limit, ...info }) {
-      let { term } = info;
-      this.$set(this, `term`, term);
-      let res = this.termList.find(f => f._id === term);
-      this.$set(this, `list`, _.sortBy(res.batchnum, ['batch']));
-    },
-    async toDate({ data }) {
-      let res = await this.getClass({ batchid: data._id });
-      this.$set(this, 'batchid', data._id);
-      // this.view = 'lesson';
-      let { startdate, enddate } = data;
-      this.$set(this.batch, `startdate`, startdate);
-      this.$set(this.batch, `enddate`, enddate);
-      //查询到了班级,再查询班级是否有课表
-      if (this.$checkRes(res)) {
-        let cArr = [];
-        for (const tClass of res.data) {
-          let lesson = await this.getLessonList({ classid: tClass.id });
-          console.log(lesson);
-          if (this.$checkRes(lesson)) {
-            //根据classid查出的课表一定是唯一的,但是需要用query方法查出,所以如果有值只取出第一条,之后修改这条数据
-            let { name, lyteacherid, yclocationid, kzjhlocationid, kbyslocationid, headteacherid, jslocationid } = tClass;
-            if (lesson.data.length > 0) {
-              //说明这个班已经排过课了,整理数据
-              let ldata = JSON.parse(JSON.stringify(lesson.data[0]));
-              ldata = { ...ldata, name, lyteacherid, yclocationid, kzjhlocationid, kbyslocationid, headteacherid, jslocationid };
-              cArr.push(ldata);
-            } else {
-              //没排课,需要动手干下,整理好数据
-              let object = { name, lyteacherid, yclocationid, kzjhlocationid, kbyslocationid, headteacherid, jslocationid };
-              object.classid = tClass.id;
-              object.batchid = tClass.batchid;
-              object.termid = tClass.termid;
-              cArr.push(object);
-            }
-          }
-        }
-        this.$set(this, `classes`, cArr);
-      }
-      this.view = 'lesson';
-    },
-    returnList() {
-      this.view = 'list';
-    },
-    async handleSave(data) {
-      //此处需要3个接口:1,课表添加;2,课表修改;3,班级修改
-      //根据data中是否有id,判断是课表的添加还是修改
-      //解构出data中class字段,是班级id,将各种地点,礼仪课老师,班主任修改好
-      let classid = data.classid;
-      let { lessons, termid, batchid, headteacherid, jslocationid, yclocationid, kzjhlocationid, kbyslocationid, lyteacherid } = data;
-      let newLessons = { lessons, termid, batchid, classid };
-      let newClass = { id: classid, headteacherid, jslocationid, yclocationid, kzjhlocationid, kbyslocationid, lyteacherid };
-      let lid = _.get(data, `id`);
-      let res;
-      if (!lid) {
-        res = await this.lessonCreate(newLessons);
-      } else {
-        newLessons.id = lid;
-        res = await this.lessonUpdate(newLessons);
-      }
-      let check = (res, sucMsg, errMsg) => {
-        if (res.errcode === 0) {
-          _.isString(sucMsg) ? this.$message.success(sucMsg) : '';
-          return true;
-        } else {
-          this.$message.error(errMsg || '处理失败');
-          return false;
-        }
-      };
-      if (check(res, null, `课表${lid ? '修改' : '添加'}失败`)) {
-        newClass.lessonid = res.data._id;
-        res = await this.updateClass(newClass);
-        check(res, '班级信息修改成功', '班级信息修改失败');
-      }
-    },
-    async toMsg({ data }) {
-      let res = await this.getClass({ batchid: data._id });
-      if (this.$checkRes(res)) {
-        let arr = res.data.map(i => i.id);
-        if (arr.length > 0) {
-          const resNotice = await this.sendNotice({ classids: arr });
-          this.$checkRes(resNotice, '发送成功', '发送失败');
-        } else this.$message.warning(`该批次下未分班`);
-      }
-    },
-    async toBedroom({ data }) {
-      let object = { termid: this.term, trainplanid: this.id, batchid: data._id };
-      let res = await this.bedroomApart(object);
-      this.$checkRes(res, '分寝成功', res.errmsg);
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-    id() {
-      return this.$route.query.id;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 85
src/views/plan/msg.vue

@@ -1,85 +0,0 @@
-<template>
-  <div id="msg">
-    <list-frame v-if="view === 'list'" :title="mainTitle" @query="search" :needFilter="false" :needAdd="false" :needPag="false" returns="/plan/index">
-      <data-table ref="table" :fields="fields" :data="list" :opera="opera" @msg="toMsg"></data-table>
-    </list-frame>
-  </div>
-</template>
-
-<script>
-import listFrame from '@frame/layout/admin/list-frame';
-import dataTable from '@frame/components/data-table';
-import _ from 'lodash';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
-
-//教师表,地点表,课程表
-export default {
-  metaInfo: { title: '发送通知' },
-  name: 'msg',
-  props: {},
-  components: { listFrame, dataTable },
-  data: () => ({
-    view: 'list',
-    opera: [
-      {
-        label: '发送通知',
-        icon: 'el-icon-message',
-        method: 'msg',
-      },
-    ],
-    fields: [{ label: '期数', prop: 'term' }],
-    list: [],
-    total: 0,
-  }),
-  created() {
-    this.search();
-  },
-  methods: {
-    ...trainPlan({ getTrainPlan: 'fetch' }),
-    async search({ skip = 0, limit = 10, ...info } = {}) {
-      let res = await this.getTrainPlan(this.id);
-      if (this.$checkRes(res)) {
-        this.$set(this, `list`, res.data.termnum);
-      }
-    },
-    async toMsg({ data }) {
-      let notify = this.$notify({
-        title: '发送中',
-        message: '正在发送通知,请稍后',
-        duration: 0,
-        showClose: false,
-      });
-      notify.close();
-      this.$notify({
-        title: '发送成功',
-        duration: 2000,
-        type: 'success',
-      });
-      this.$notify({
-        title: '发送失败',
-        duration: 2000,
-        type: 'error',
-      });
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-    id() {
-      return this.$route.query.id;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 122
src/views/plan/parts/event.vue

@@ -1,122 +0,0 @@
-<template>
-  <div id="event">
-    <el-form :model="form" ref="form" :rules="formRules" label-width="80px" size="small" @submit.native.prevent style="padding: 15px;">
-      <el-form-item label="开始时间" prop="start" required>
-        <el-date-picker v-model="form.start" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" :picker-options="pickerOptions"> </el-date-picker>
-      </el-form-item>
-      <el-form-item label="结束时间" prop="end" required>
-        <el-date-picker v-model="form.end" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" :picker-options="pickerOptions"> </el-date-picker>
-      </el-form-item>
-      <el-form-item label="期数" prop="term" required> <el-input v-model="form.term"></el-input> </el-form-item>
-      <el-form-item label="班级类型" prop="type" required>
-        <el-radio-group v-model="form.type">
-          <el-radio label="0">正常班级</el-radio>
-          <el-radio label="1">特殊班级</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="批次" prop="batch" v-if="form.type === '0'"> <el-input v-model="form.batch"></el-input> </el-form-item>
-      <el-form-item label="班级数量" prop="class" v-if="form.type === '0'"> <el-input v-model="form.class"></el-input> </el-form-item>
-      <el-form-item label="每班人数" prop="number" required> <el-input v-model="form.number"></el-input> </el-form-item>
-      <el-form-item label="班级名称" prop="name" v-if="form.type === '1'"> <el-input v-model="form.name"></el-input> </el-form-item>
-      <el-form-item label="颜色" prop="color">
-        <el-color-picker v-model="form.color" :predefine="predefineColors" size="mini"></el-color-picker>
-      </el-form-item>
-      <el-form-item>
-        <el-row type="flex" align="middle" justify="space-around">
-          <el-col :span="6">
-            <el-button type="primary" @click="saveForm">保存</el-button>
-          </el-col>
-          <el-col :span="6">
-            <el-button @click="resetForm">重置</el-button>
-          </el-col>
-        </el-row>
-      </el-form-item>
-    </el-form>
-  </div>
-</template>
-
-<script>
-import _ from 'lodash';
-export default {
-  name: 'event',
-  props: {
-    data: { type: Object, default: () => {} }, //数据
-    isNew: { type: Boolean, default: true }, //是不是修改
-    predefineColors: { type: Array, default: () => [] }, //颜色列表
-    year: { type: null, default: new Date().getFullYear() },
-    vacation: { type: Array, default: () => [] },
-  },
-  components: {},
-  data() {
-    return {
-      form: { color: '#409EFF' },
-      formRules: {
-        start: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
-        end: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
-        term: [{ required: true, message: '请输入期数' }],
-        number: [{ required: true, message: '请输入每班人数' }],
-        type: [{ required: true, message: '请选择班级类型' }],
-      },
-      pickerOptions: {
-        disabledDate: time => this.setDisabledDate(time),
-      },
-    };
-  },
-  created() {},
-  methods: {
-    //保存表单函数
-    saveForm() {
-      this.$refs['form'].validate(valid => {
-        if (valid) {
-          let data = JSON.parse(JSON.stringify(this.form));
-          this.resetForm();
-          this.$emit('save', { isNew: this.isNew, data });
-        } else {
-          console.warn('form validate error!!!');
-        }
-      });
-    },
-    //重置表单函数
-    resetForm() {
-      this.$refs.form.resetFields();
-    },
-    //禁用时间
-    setDisabledDate(time) {
-      let thisTime = time.getTime();
-      let start = new Date(`${this.year}-01-01`).getTime();
-      let end = new Date(`${this.year}-12-31`).getTime();
-      if (thisTime < start) return true;
-      else if (thisTime > end) return true;
-      else {
-        //循环假期列表,判断这个时间是不是在假期时间外:
-        // 此刻=假期开始时间||此刻=假期结束时间 return true(不能选)
-        // 此刻<假期开始时间 => return false(继续判断下个假期)
-        // 此刻>假期开始时间 => 此刻<假期结束时间 ? 在假期中,return true(不允许选择): return false(继续判断下个假期)
-        let res = false;
-        for (const vac of this.vacation) {
-          let vacS = new Date(vac.start).setDate(new Date(vac.start).getDate() - 1); //减一天匹配日历
-          let vacE = new Date(vac.end).setDate(new Date(vac.end).getDate() - 1);
-          if (thisTime > vacS) {
-            if (thisTime < vacE) {
-              res = true;
-              break;
-            }
-          }
-        }
-        return res;
-      }
-    },
-  },
-  watch: {
-    data: {
-      immediate: true,
-      deep: true,
-      handler(val) {
-        if (val) this.$set(this, `form`, _.cloneDeep(this.data));
-      },
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 94
src/views/plan/parts/vacation.vue

@@ -1,94 +0,0 @@
-<template>
-  <div id="vacation">
-    <el-row>
-      <el-col :span="24">
-        <data-form :data="form" :fields="formFields" :rules="rules" @save="handleSave" :isNew="isNew"> </data-form>
-      </el-col>
-      <el-col :span="24">
-        <data-table :fields="fields" :data="data" :opera="opera" @edit="toEdit" @delete="toDelete" :height="300"></data-table>
-      </el-col>
-    </el-row>
-  </div>
-</template>
-
-<script>
-import dataTable from '@frame/components/data-table';
-import dataForm from '@frame/components/form';
-import _ from 'lodash';
-export default {
-  name: 'vacation',
-  props: {
-    list: { type: Array, default: () => [] },
-  },
-  components: { dataTable, dataForm },
-  data: () => ({
-    data: [],
-    form: {},
-    isNew: true,
-    formFields: [
-      { label: '标题', required: true, model: 'title' },
-      { label: '开始时间', required: true, model: 'start', type: 'date' },
-      { label: '结束时间', required: true, model: 'end', type: 'date' },
-    ],
-    rules: {
-      title: [{ required: true, message: '请输入标题' }],
-      start: [{ required: true, message: '请选择开始时间' }],
-      end: [{ required: true, message: '请选择结束时间' }],
-    },
-    fields: [
-      { label: '标题', prop: 'title' },
-      { label: '开始时间', prop: 'start' },
-      { label: '结束时间', prop: 'end' },
-    ],
-    opera: [
-      {
-        label: '编辑',
-        icon: 'el-icon-edit',
-        method: 'edit',
-      },
-      {
-        label: '删除',
-        icon: 'el-icon-delete',
-        method: 'delete',
-        confirm: true,
-      },
-    ],
-  }),
-  created() {},
-  methods: {
-    toEdit({ data, index }) {
-      this.form = JSON.parse(JSON.stringify(data));
-      this.form.index = index;
-      this.isNew = false;
-    },
-    toDelete({ data, index }) {
-      let arr = JSON.parse(JSON.stringify(this.data));
-      arr.splice(index, 1);
-      this.$emit(`update`, { data: arr, type: 'delete' });
-    },
-    handleSave({ data, isNew }) {
-      //添加,删除,修改,都只是操作本组件的数组,然后将本组件的数组=>传回父组件=>父组件更新=>子组件更新
-      let arr = JSON.parse(JSON.stringify(this.data));
-      if (isNew) {
-        arr.push(data);
-      } else {
-        let { index, ...info } = data;
-        arr[index] = info;
-      }
-      this.$emit(`update`, { data: arr, type: isNew ? 'add' : 'edit' });
-      this.isNew = true;
-    },
-  },
-  watch: {
-    list: {
-      immediate: true,
-      handler(val) {
-        let mid = _.cloneDeep(val);
-        this.$set(this, `data`, mid);
-      },
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>

+ 0 - 126
src/views/plan/question.vue

@@ -1,126 +0,0 @@
-<template>
-  <div id="question">
-    <list-frame v-if="view === 'list'" :title="mainTitle" @query="search" :needFilter="false" :needAdd="false" :needPag="false" returns="/plan/index">
-      <data-table ref="table" :fields="fields" :data="list" :opera="opera" @edit="toEdit"></data-table>
-    </list-frame>
-    <el-dialog :visible.sync="dialog" title="选择问卷" center @close="toClose">
-      <data-table :fields="quesFields" :data="questionList" :select="true" :selected="selected" @handleSelect="toSelect"></data-table>
-      <el-row type="flex" justify="center" :gutter="10">
-        <el-col :span="2" style="padding-top:20px">
-          <el-button type="primary" plain size="mini" @click="toSave">保&nbsp;&nbsp;&nbsp;&nbsp;存</el-button>
-        </el-col>
-        <el-col :span="2" style="padding-top:20px">
-          <el-button plain size="mini" @click="dialog = false">关&nbsp;&nbsp;&nbsp;&nbsp;闭</el-button>
-        </el-col>
-      </el-row>
-    </el-dialog>
-  </div>
-</template>
-
-<script>
-import listFrame from '@frame/layout/admin/list-frame';
-import dataTable from '@frame/components/data-table';
-import _ from 'lodash';
-import { createNamespacedHelpers } from 'vuex';
-const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
-const { mapActions: questionnaire } = createNamespacedHelpers('questionnaire');
-const { mapActions: termquest } = createNamespacedHelpers('termquest');
-
-export default {
-  metaInfo: { title: '问卷分配' },
-  name: 'question',
-  props: {},
-  components: { listFrame, dataTable },
-  data: () => ({
-    view: 'list',
-    dialog: false,
-    opera: [
-      {
-        label: '分配问卷',
-        icon: 'el-icon-document-add',
-        method: 'edit',
-      },
-    ],
-    fields: [{ label: '期数', prop: 'term' }],
-    quesFields: [
-      { label: '问卷序号', prop: 'num' },
-      { label: '问卷标题', prop: 'name' },
-    ],
-    questionList: [],
-    list: [],
-    form: {},
-    selected: [],
-    total: 0,
-  }),
-  created() {
-    this.search();
-    this.getQuesList();
-  },
-  methods: {
-    ...trainPlan({ getTrainPlan: 'fetch' }),
-    ...questionnaire({ getQuestionnaireList: 'query' }),
-    ...termquest({ getTermQuestList: 'query', termQuestCreate: 'create', termQuestUpdate: 'update' }),
-    async search({ skip = 0, limit = 10, ...info } = {}) {
-      let res = await this.getTrainPlan(this.id);
-      if (this.$checkRes(res)) {
-        this.$set(this, `list`, res.data.termnum);
-      }
-    },
-    async getQuesList() {
-      let ques = await this.getQuestionnaireList();
-      if (this.$checkRes(ques)) this.$set(this, `questionList`, ques.data);
-    },
-    async toEdit({ data }) {
-      this.dialog = true;
-      let res = await this.getTermQuestList({ termid: data._id });
-      if (this.$checkRes(res)) {
-        if (res.data.length > 0) {
-          let { questionnaireid, ...othrers } = res.data[0];
-          this.$set(this, `form`, othrers);
-          let newArr = this.questionList.filter(q => (_.find(questionnaireid, sq => sq === q.id) ? q : ''));
-          this.$set(this, `selected`, newArr);
-        } else {
-          this.$set(this, `form`, { termid: data._id });
-        }
-      }
-    },
-    toSelect(sels) {
-      this.$set(this, `selected`, sels);
-    },
-    async toSave() {
-      let res;
-      let questionnaireid = this.selected.map(p => p.id);
-      let data = { termid: this.form.termid, questionnaireid };
-      if (!this.form.id) {
-        res = await this.termQuestCreate(data);
-      } else {
-        data.id = this.form.id;
-        res = await this.termQuestUpdate(data);
-      }
-      this.$checkRes(res, this.form.id ? '修改成功' : '保存成功', this.form.id ? '修改失败' : '添加失败');
-    },
-    toClose() {
-      this.dialog = false;
-      this.form = {};
-    },
-  },
-  computed: {
-    mainTitle() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      let sub = meta.sub || '';
-      return `${main}${sub}`;
-    },
-    keyWord() {
-      let meta = this.$route.meta;
-      let main = meta.title || '';
-      return main;
-    },
-    id() {
-      return this.$route.query.id;
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped></style>