lrf402788946 5 years ago
parent
commit
4308e7c556
6 changed files with 323 additions and 16 deletions
  1. 25 12
      src/plugins/dateM.js
  2. 6 0
      src/router/index.js
  3. 1 0
      src/views/duty/index.vue
  4. 278 0
      src/views/new-plan/arrange.vue
  5. 12 3
      src/views/new-plan/index.vue
  6. 1 1
      vue.config.js

+ 25 - 12
src/plugins/dateM.js

@@ -1,22 +1,35 @@
 import Vue from 'vue';
 import _ from 'lodash';
-const vm = new Vue({});
+var moment = require('moment');
 const Plugin = {
   install(Vue, options) {
-    Vue.prototype.$fullDateString = (date, type) => {
-      let res;
-      let dStr = date.toLocaleDateString();
-      let arr = dStr.split('/');
-      let year = parseInt(arr[0]);
-      let month = parseInt(arr[1]) >= 10 ? parseInt(arr[1]) : `0${parseInt(arr[1])}`;
-      let day = parseInt(arr[2]) >= 10 ? parseInt(arr[2]) : `0${parseInt(arr[2])}`;
-      res = `${year}-${month}-${day}`;
-      if (type === 'datetime') {
-        let tStr = date.toLocaleTimeString();
-        res = `${res} ${tStr}`;
+    Vue.prototype.$checkDate = ({ startStr, endStr, vacation = [] }) => {
+      let res = true;
+      let cbt = (time, vs, ve) => {
+        let r = moment(time).isBetween(vs, ve, null, '[]');
+        if (r) res = false;
+        return r;
+      };
+      for (const vac of vacation) {
+        if (moment(startStr).isBefore(vac.start)) {
+          if (cbt(endStr, vac.start, vac.end)) {
+            res = vac;
+            break;
+          }
+        } else {
+          if (cbt(startStr, vac.start, vac.end)) {
+            res = vac;
+            break;
+          }
+        }
       }
       return res;
     };
+    Vue.prototype.$plusDay = (date, day = 1) => {
+      return moment(date)
+        .add(day, 'days')
+        .format('YYYY-MM-DD');
+    };
   },
 };
 Vue.use(Plugin);

+ 6 - 0
src/router/index.js

@@ -18,6 +18,12 @@ const newPlan = [
     meta: { title: '计划模板' },
     component: () => import('@/views/new-plan/template.vue'),
   },
+  {
+    path: '/newPlan/arrange',
+    name: 'newPlan_arrange',
+    meta: { title: '计划安排' },
+    component: () => import('@/views/new-plan/arrange.vue'),
+  },
 ];
 
 const routes = [

+ 1 - 0
src/views/duty/index.vue

@@ -1,6 +1,7 @@
 <template>
   <div id="detail">
     <detail-frame :title="mainTitle" returns="/dept/index" v-loading="loading">
+      <p v-html="info.bzduty"></p>
       <data-form v-if="!loading" :data="info" :fields="fields" :rules="rules" @save="handleSave" :isNew="isNew"> </data-form>
     </detail-frame>
   </div>

+ 278 - 0
src/views/new-plan/arrange.vue

@@ -0,0 +1,278 @@
+<template>
+  <div id="arrange">
+    <detail-frame :title="pageTitle" returns="./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>
+                {{ info.title }}
+              </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" :vacation="vacation" :events="events"></calendar>
+          </el-card>
+        </el-col>
+      </el-row>
+    </detail-frame>
+    <el-dialog :visible.sync="dialog" title="模板计划" width="30%" :close-on-click-modal="false">
+      <el-form>
+        <el-form-item label="请输入您要生成的期数">
+          <el-input v-model="input.term"></el-input>
+        </el-form-item>
+        <el-form-item label="请选择开始日期">
+          <el-date-picker v-model="input.start" type="date" placeholder="请选择开始日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd"> </el-date-picker>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-row :gutter="20" type="flex" justify="center" align="middle">
+          <el-col :span="4">
+            <el-button @click="dialog = false">取消</el-button>
+          </el-col>
+          <el-col :span="4">
+            <el-button type="primary" @click="setDefaultPlan">确定</el-button>
+          </el-col>
+        </el-row>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import _ from 'lodash';
+var moment = require('moment');
+import detailFrame from '@frame/layout/admin/detail-frame';
+import calendar from '@frame/components/calendar';
+import dataTable from '@frame/components/data-table';
+import { mapState, createNamespacedHelpers } from 'vuex';
+const { mapActions } = createNamespacedHelpers('trainplan');
+const { mapActions: trainTemplate } = createNamespacedHelpers('trainTemplate');
+export default {
+  name: 'arrange',
+  props: {},
+  components: { detailFrame, calendar, dataTable },
+  data: function() {
+    var that = this;
+    return {
+      template: {},
+      info: {},
+      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: '请选择班级类型' }],
+      },
+      dialog: false,
+      selfBtn: {
+        term: {
+          text: '生成模板计划',
+          //设置假期
+          click: () => (that.dialog = true),
+          position: 'left',
+        },
+      },
+      input: {
+        term: 50,
+        start: '2020-01-01',
+      },
+      heights: 250,
+      collapse: '',
+    };
+  },
+  created() {
+    this.search();
+    this.searchTemplate();
+  },
+  methods: {
+    ...mapActions(['fetch', 'update']),
+    ...trainTemplate({ trainTemplate: 'query' }),
+    async search() {
+      const res = await this.fetch(this.id);
+      if (this.$checkRes(res)) {
+        let fest = _.get(res.data, 'festivals', []);
+        let vac = fest.map(i => {
+          let object = {};
+          object.id = i._id;
+          object.start = i.begindate;
+          object.end = i.finishdate;
+          object.title = i.name;
+          object.rendering = 'background';
+          object.color = 'red';
+          object.editable = false;
+          return object;
+        });
+        this.$set(this, `vacation`, vac);
+        this.$set(this, `info`, res.data);
+      }
+    },
+    setDefaultPlan() {
+      this.dialog = false;
+      let { term, start } = this.input;
+      let { day, batchnum, classnum } = this.template;
+      let event = []; //处理成功事件的存储
+      let qb = 0; //剩余没有满足之前的批数
+      let qt = 0; //剩余没有满足之前的期数
+      //第一次正常安排
+      let arrange = (t, v) => {
+        let arr = [];
+        for (let it = 1; it <= t; it++) {
+          for (let ib = 1; ib <= v; ib++) {
+            let end = this.$plusDay(start, day - 1);
+            let object = { startStr: start, endStr: end, vacation: this.vacation };
+            let res = this.$checkDate(object);
+            if (res == true) {
+              let batch = {
+                term: it - qt,
+                batch: ib,
+                class: classnum,
+                start,
+                end,
+                type: '0',
+                title: `第${it - qt}期第${ib}批次`,
+                color: this.getColor(it, ib),
+              };
+              start = this.$plusDay(start);
+              arr.push(batch);
+            } else {
+              if (ib == 1) qt += 1;
+              else qb += batchnum - ib + 1;
+              start = this.$plusDay(res.end);
+              break;
+            }
+          }
+        }
+        return arr;
+      };
+      event = arrange(term, batchnum);
+      while (qb > 0) {
+        qt = qt + Math.ceil(qb / batchnum);
+        let sb = qb % batchnum;
+        let lessArr = arrange(qt, batchnum);
+        let last = _.last(event);
+        let lessNArr = _.chunk(lessArr, 3).map((i, index) => {
+          i.map(ii => {
+            ii.term = last.term + index + 1;
+            ii.title = `第${ii.term}期第${ii.batch}批次`;
+            return ii;
+          });
+          return i;
+        });
+        lessArr = _.flatten(lessNArr);
+        //TODO需要判断是否还有剩余的批次,有的话还需要处理
+      }
+
+      //最后赋值回去
+      this.$set(this, `events`, event);
+      this.$set(this, `selectList`, event);
+    },
+    setHeight() {
+      let heights = this.$refs.card.$el.clientHeight * 0.63;
+      this.$set(this, `heights`, heights);
+    },
+    //列表编辑事件
+    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);
+    },
+    //计划保存
+    savePlan() {},
+    //
+    selectDate() {},
+    //
+    eventClick() {},
+    //
+    async searchTemplate() {
+      let res = await this.trainTemplate();
+      if (this.$checkRes(res)) {
+        if (res.data.length > 0) {
+          this.$set(this, `template`, res.data[0]);
+        }
+      }
+    },
+    getColor(it, ib) {
+      let { color, batchnum } = this.template;
+      if (color.length > 0) {
+        let num = ((it - 1) * batchnum + ib) % color.length;
+        return color[num];
+      } else return '#004499';
+    },
+  },
+  computed: {
+    ...mapState(['user']),
+    id() {
+      return this.$route.query.id;
+    },
+    isNew() {
+      return this.$route.query.id ? false : true; //false : true;
+    },
+    pageTitle() {
+      return `${this.$route.meta.title}`;
+    },
+    widths() {
+      let width = (document.body.clientWidth - 200) * 0.5;
+      return width > 400 ? width : 400;
+    },
+  },
+  metaInfo() {
+    return { title: this.$route.meta.title };
+  },
+};
+</script>
+
+<style lang="less" scoped></style>

+ 12 - 3
src/views/new-plan/index.vue

@@ -1,9 +1,9 @@
 <template>
   <div id="index">
     <list-frame :title="pageTitle" @query="search" :total="total" :needFilter="false" @add="toAdd">
-      <data-table :fields="fields" :data="list" :opera="opera" @edit="toEdit" @delete="toDelete"></data-table>
+      <data-table :fields="fields" :data="list" :opera="opera" @edit="toEdit" @delete="toDelete" @date="date"></data-table>
     </list-frame>
-    <el-dialog title="年度信息" width="30%" :visible.sync="dialog" center :destroy-on-close="true" @close="handleClose">
+    <el-dialog title="年度信息" width="30%" :visible.sync="dialog" center :destroy-on-close="true" @close="handleClose" :reset="false">
       <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'">
@@ -47,6 +47,11 @@ export default {
           icon: 'el-icon-edit',
           method: 'edit',
         },
+        {
+          label: '计划安排',
+          icon: 'el-icon-date',
+          method: 'date',
+        },
         {
           label: '删除',
           icon: 'el-icon-delete',
@@ -56,7 +61,7 @@ export default {
       fields: [
         { label: '年度', prop: 'year' },
         { label: '标题', prop: 'title' },
-        { label: '状态', prop: 'status', format: i => (i === '0' ? '筹备中' : i === '1' ? '已发布' : '已结束') },
+        { label: '状态', prop: 'status', format: i => (i === '0' ? '筹备中' : i === '1' ? '进行中' : '已结束') },
       ],
       festFields: [
         { label: '节假日', prop: 'name', model: 'name', options: { readonly: true } },
@@ -117,6 +122,7 @@ export default {
         msg = '修改成功';
       }
       if (this.$checkRes(res, msg, res.errmsg || '操作失败')) {
+        this.search();
         this.handleClose();
       }
     },
@@ -161,6 +167,9 @@ export default {
         sessionStorage.setItem('holiday', JSON.stringify(res.holiday_list));
       } else this.$set(this, 'holiday', JSON.parse(holiday));
     },
+    date({ data }) {
+      this.$router.push({ path: './arrange', query: { id: data.id } });
+    },
   },
   computed: {
     ...mapState(['user']),

+ 1 - 1
vue.config.js

@@ -43,7 +43,7 @@ module.exports = {
         changeOrigin: true,
         ws: true,
       },
-      '/jh': {
+      '/jh': { //聚合科技API
         target: 'http://v.juhe.cn',
         changeOrigin: true,
         ws: true,