Browse Source

全年计划

lrf402788946 5 years ago
parent
commit
d1cce6343f
4 changed files with 330 additions and 0 deletions
  1. 4 0
      package.json
  2. 12 0
      src/router/index.js
  3. 233 0
      src/views/plan/detail.vue
  4. 81 0
      src/views/plan/index.vue

+ 4 - 0
package.json

@@ -8,6 +8,10 @@
     "lint": "vue-cli-service lint"
     "lint": "vue-cli-service lint"
   },
   },
   "dependencies": {
   "dependencies": {
+    "@fullcalendar/core": "^4.3.1",
+    "@fullcalendar/daygrid": "^4.3.0",
+    "@fullcalendar/interaction": "^4.3.0",
+    "@fullcalendar/vue": "^4.3.1",
     "axios": "^0.19.1",
     "axios": "^0.19.1",
     "core-js": "^3.4.4",
     "core-js": "^3.4.4",
     "element-ui": "^2.13.0",
     "element-ui": "^2.13.0",

+ 12 - 0
src/router/index.js

@@ -176,6 +176,18 @@ const routes = [
         meta: { title: '学生', sub: '详情' },
         meta: { title: '学生', sub: '详情' },
         component: () => import('@/views/student/detail.vue'),
         component: () => import('@/views/student/detail.vue'),
       },
       },
+      {
+        path: '/plan/index',
+        name: 'plan_index',
+        meta: { title: '计划', sub: '管理' },
+        component: () => import('@/views/plan/index.vue'),
+      },
+      {
+        path: '/plan/detail',
+        name: 'plan_detail',
+        meta: { title: '计划', sub: '详情' },
+        component: () => import('@/views/plan/detail.vue'),
+      },
     ],
     ],
   },
   },
 ];
 ];

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

@@ -0,0 +1,233 @@
+<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" label-width="60px" size="small" @submit.native.prevent>
+              <el-form-item label="年份">
+                {{ 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="events" :opera="opera" @edit="toEdit" @delete="toDelete" :height="heights"></data-table>
+                </el-collapse-item>
+              </el-collapse>
+            </el-form>
+          </el-card>
+        </el-col>
+        <el-col :span="16" :style="`width:${widths}px`">
+          <el-card ref="card">
+            <calendar @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">
+      <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"> </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"> </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="batch" required> <el-input v-model="form.batch"></el-input> </el-form-item>
+        <el-form-item label="班级数量" prop="class" required> <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" required> <el-input v-model="form.name"></el-input> </el-form-item>
+        <el-form-item label="班级类型" prop="start" required>
+          <el-radio-group v-model="form.type" prop="type">
+            <el-radio label="0">正常班级</el-radio>
+            <el-radio label="1">特殊班级</el-radio>
+          </el-radio-group>
+        </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>
+    </el-drawer>
+  </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 _ from 'lodash';
+import { mapActions, mapState, createNamespacedHelpers } from 'vuex';
+export default {
+  metaInfo: { title: '计划详情' },
+  name: 'detail',
+  props: {},
+  components: { detailFrame, calendar, dataTable },
+  data: () => ({
+    info: {
+      termnum: {
+        batchnum: [],
+      },
+    },
+    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: '请输入期数' }],
+      batch: [{ required: true, message: '请输入批次' }],
+      class: [{ required: true, message: '请输入班级数量' }],
+      number: [{ required: true, message: '请输入每班人数' }],
+      name: [{ required: true, message: '请输入班级名称' }],
+      type: [{ required: true, message: '请选择班级类型' }],
+    },
+    drawer: false,
+    events: [],
+    predefineColors: ['#409EFF'],
+    collapse: '',
+    fields: [
+      { label: '开始时间', prop: 'start' },
+      { label: '结束时间', prop: 'end' },
+      { label: '期数', prop: 'term' },
+      { label: '批次', prop: 'batch' },
+      { label: '班级数量', prop: 'class' },
+      { label: '每班人数', prop: 'number' },
+      { label: '班级名称', prop: 'name' },
+      { 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,
+  }),
+  created() {},
+  mounted() {},
+  methods: {
+    // ...mapClass(['fetch', 'create', 'update']),
+    async search() {
+      const res = await this.fetch(this.id);
+      console.log(res);
+      if (this.$checkRes(res)) this.$set(this, `info`, res.data);
+      this.loading = false;
+    },
+    selectDate(object) {
+      this.$set(this.form, `start`, JSON.parse(JSON.stringify(object.startStr)));
+      this.$set(this.form, `end`, JSON.parse(JSON.stringify(object.endStr)));
+      this.drawer = true;
+    },
+    eventClick({ event }) {
+      console.log(event);
+    },
+    toEdit({ data, index }) {
+      this.$set(this, `form`, JSON.parse(JSON.stringify(data)));
+      this.drawer = true;
+    },
+    toDelete({ data, index }) {
+      this.events.splice(index, 1);
+    },
+    saveForm() {
+      this.$refs['form'].validate(valid => {
+        if (valid) {
+          this.setEvent();
+          this.resetForm();
+        } else {
+          console.warn('form validate error!!!');
+        }
+      });
+    },
+    resetForm() {
+      this.$refs.form.resetFields();
+      this.setHeight();
+    },
+    setEvent() {
+      let data = JSON.parse(JSON.stringify(this.form));
+      let object = { ...data, title: `第${JSON.parse(JSON.stringify(data.term))}期第${JSON.parse(JSON.stringify(data.batch))}批次` };
+      if (!object.id) {
+        object.id = `p${new Date().getTime()}`;
+        this.events.push(object);
+      } else {
+        this.$set(
+          this.events,
+          _.findIndex(this.events, item => item.id == object.id),
+          object
+        );
+      }
+      if (_.findIndex(this.predefineColors, item => item == data.color) < 0) this.predefineColors.push(data.color);
+    },
+    toClose() {
+      this.drawer = false;
+      this.resetForm();
+    },
+    setHeight() {
+      let heights = this.$refs.card.$el.clientHeight * 0.63;
+      this.$set(this, `heights`, heights);
+    },
+  },
+  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;
+    },
+    year() {
+      if (this.isNew) return new Date().getFullYear();
+      else return new Date().getFullYear();
+    },
+    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>

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

@@ -0,0 +1,81 @@
+<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"></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 } = createNamespacedHelpers('dept');
+export default {
+  metaInfo: { title: '计划管理' },
+  name: 'index',
+  props: {},
+  components: {
+    listFrame,
+    dataTable,
+  },
+  data: () => ({
+    opera: [
+      {
+        label: '编辑',
+        icon: 'el-icon-edit',
+        method: 'edit',
+      },
+      {
+        label: '删除',
+        icon: 'el-icon-delete',
+        method: 'delete',
+        confirm: true,
+      },
+    ],
+    fields: [
+      { label: '计划标题', prop: 'name' },
+      { label: '年度', prop: 'year' },
+      { label: '状态', prop: 'status' },
+    ],
+    list: [],
+    total: 0,
+  }),
+  created() {
+    // this.search();
+  },
+  methods: {
+    ...mapActions(['query', 'delete']),
+    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: '/dept/detail', query: { id: data.id } });
+    },
+    async toDelete({ data }) {
+      const res = await this.delete(data.id);
+      this.$checkRes(res, '删除成功', '删除失败');
+      this.search();
+    },
+  },
+  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>