123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- <template>
- <div id="arrange">
- <!-- <detail-frame :title="pageTitle" :returns="returns"> -->
- <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
- :year="`${info.year || '2020'}`"
- :selfBtn="selfBtn"
- @draft="selectDate"
- @eventClick="eventClick"
- :vacation="vacation"
- :events="events"
- ></calendar>
- </el-card>
- </el-col>
- </el-row>
- <el-drawer :visible.sync="drawer" direction="rtl" title="安排计划" @close="toClose">
- <event
- :data="form"
- :year="info.year"
- :vacation="vacation"
- :isNew="formIsNew"
- :predefineColors="template.color"
- @save="setEvent"
- @delete="toDelete"
- ></event>
- </el-drawer>
- <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-tooltip content="第X期 此处为填写X" placement="right">
- <el-input-number v-model="input.termnum"></el-input-number>
- </el-tooltip>
- </el-form-item>
- <el-form-item label="请选择开始日期">
- <el-date-picker
- :picker-options="pickerOptions"
- 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 event from '../parts/event';
- import { mapState, createNamespacedHelpers } from 'vuex';
- const { mapActions } = createNamespacedHelpers('trainplan');
- const { mapActions: trainTemplate } = createNamespacedHelpers('trainTemplate');
- const { mapActions: schPlan } = createNamespacedHelpers('schPlan');
- const { mapActions: util } = createNamespacedHelpers('util');
- export default {
- name: 'arrange',
- props: {},
- components: {
- // detailFrame,
- calendar,
- // dataTable,
- event,
- },
- data: function() {
- var that = this;
- return {
- view: 'plan',
- template: {},
- info: {
- year: '2020',
- },
- 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: '请选择班级类型' }],
- },
- dialog: false,
- selfBtn: {
- term: {
- text: '生成模板计划',
- click: () => (that.dialog = true),
- position: 'left',
- },
- plan: {
- text: '保存培训计划',
- click: () => that.savePlan(),
- position: 'right',
- },
- },
- input: {
- term: 0,
- },
- pickerOptions: {
- disabledDate: time => that.checkDate(time),
- },
- heights: 250,
- collapse: '',
- drawer: false,
- formIsNew: true,
- };
- },
- created() {
- this.search();
- },
- methods: {
- ...mapActions(['fetch', 'update']),
- ...trainTemplate({ trainTemplate: 'query' }),
- ...schPlan({ setSchPlan: 'schArrange' }),
- ...util({ modelFetch: 'fetch' }),
- async search() {
- let planid = _.get(this.defaultOption, 'planid');
- if (!planid) return;
- const res = await this.fetch(planid);
- 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);
- let midArr = JSON.parse(JSON.stringify(res.data));
- let events = [];
- events = _.flatten(
- midArr.termnum.map(item => {
- item.batchnum.map((i, index) => {
- i.termid = item._id;
- 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.map((i, index) => {
- i.index = index;
- return i;
- });
- this.$set(this, `events`, events);
- this.$set(this, `selectList`, events);
- }
- this.searchTemplate();
- },
- //模板事件开始
- //生成默认模板
- setDefaultPlan() {
- this.$set(this, `events`, []);
- this.$set(this, `selectList`, []);
- this.dialog = false;
- let { term, start, termnum } = this.input;
- let { day, batchnum, classnum } = this.template;
- let event = []; //处理成功事件的存储
- //第一次正常安排
- //qb:剩余没有满足之前的批数 qt:剩余没有满足之前的期数
- let { list, qb, start: rstart } = this.arrange(term, start);
- event = list;
- start = rstart;
- event = this.otherArrange(qb, start, event);
- //最后赋值回去
- event.map((i, index) => {
- i.index = index;
- return i;
- });
- //整理期数为输入的期数,将班级
- event = this.nameTerm(event, termnum);
- this.$set(this, `events`, event);
- this.$set(this, `selectList`, event);
- },
- //默认安排事件
- arrange(t, start, part) {
- let qt = 0;
- let qb = 0;
- let { day, batchnum, classnum, stunum } = this.template;
- if (!part) part = batchnum;
- let list = [];
- for (let it = 1; it <= t; it++) {
- for (let ib = 1; ib <= part; ib++) {
- let end = this.$plusDay(start, day - 1);
- let res = this.$checkDate(start, end, this.vacation);
- if (res == true) {
- let batch = {
- term: it - qt,
- batch: ib,
- class: classnum,
- start,
- end,
- type: '0',
- number: stunum,
- title: `第${it - qt}期第${ib}批次`,
- color: this.getColor(it, ib),
- };
- start = this.$plusDay(start);
- list.push(batch);
- } else {
- if (ib == 1) qt += 1;
- qb += batchnum - ib + 1;
- start = this.$plusDay(res.end);
- break;
- }
- }
- }
- return { list, qb, start };
- },
- //默认处理未安排的事件
- otherArrange(qb, start, event) {
- let { day, batchnum, classnum } = this.template;
- //将剩余的批数转换成局部变量,然后赋0重置qb,为了在arrange中重新计算是否有接触假期
- let tta = Math.ceil(qb / batchnum);
- let part = qb % batchnum;
- qb = 0;
- let { list, qb: rqb, start: rstart } = this.arrange(tta, start, part);
- start = rstart;
- let last = _.last(event);
- let arr = [];
- if (last) arr = this.sortOtherData(last, list);
- else arr = list;
- event = event.concat(arr);
- //判断是否还有剩余的批次,期;有的话还需要处理
- if (rqb > 0) {
- return this.otherArrange(rqb, start, event);
- } else {
- return event;
- }
- },
- //默认事件排序
- sortOtherData(last, data) {
- let arr = _.chunk(data, 3).map((i, index) => {
- i.map(ii => {
- ii.term = last.term + index + 1;
- ii.title = `第${ii.term}期第${ii.batch}批次`;
- return ii;
- });
- return i;
- });
- return _.flatten(arr);
- },
- //模板事件结束
- //将期数改为手动输入的
- nameTerm(events, start) {
- let duplicate = _.cloneDeep(events);
- duplicate = duplicate.map(i => {
- i.term = start * 1 + i.term - 1;
- i.title = `第${i.term}期第${i.batch}批次`;
- return i;
- });
- return duplicate;
- },
- //手动操作事件开始
- setEvent({ data, isNew }) {
- data = JSON.parse(JSON.stringify(data));
- if (data.type == 0) {
- data.title = `第${data.term}期第${data.batch}批次`;
- } else {
- let { name } = data;
- data = { ...data, title: name };
- }
- this.$set(this.events, data.index, data);
- this.$set(this.selectList, data.index, data);
- this.toClose();
- },
- //列表编辑事件
- 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.index !== data.index)
- );
- this.selectList.splice(index, 1);
- this.toClose();
- },
- //计划保存
- savePlan() {
- let data = JSON.parse(JSON.stringify(this.info));
- let plan = JSON.parse(JSON.stringify(this.selectList));
- let termnum = [];
- termnum = _.uniqBy(
- plan.map(item => {
- let obj = { term: item.term };
- if (item.termid) obj._id = item.termid;
- return obj;
- }),
- 'term'
- ).map(i => {
- let object = _.cloneDeep(i);
- object.batchnum = plan
- .filter(fil => fil.term === i.term)
- .map(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;
- let res;
- let msg;
- res = this.update(data);
- msg = `计划保存成功`;
- this.$checkRes(res, msg);
- },
- //选择时间的事件
- 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);
- this.$set(this.form, `index`, this.events.length);
- this.drawer = true;
- this.formIsNew = true;
- },
- //
- eventClick({ event }) {
- let obj = _.get(event, `extendedProps`);
- if (!obj) {
- console.warn(`无对应事件`);
- return;
- }
- let e = this.events.find(f => f.index == obj.index);
- if (e) this.$set(this, `form`, e);
- this.drawer = true;
- this.formIsNew = false;
- },
- //
- async searchTemplate() {
- let planid = _.get(this.defaultOption, 'planid');
- let planyearid = _.get(this.defaultOption, 'planyearid');
- let res = await this.modelFetch({ model: 'trainmodel', planyearid, planid });
- if (this.$checkRes(res)) {
- if (res.data !== null) {
- this.$set(this, `template`, res.data);
- }
- }
- },
- //其他事件(无关紧要)
- //关闭抽屉函数
- toClose() {
- this.drawer = false;
- this.formIsNew = true;
- this.setHeight();
- },
- setHeight() {
- let heights = this.$refs.card.$el.clientHeight * 0.63;
- this.$set(this, `heights`, heights);
- },
- //设置事件颜色
- getColor(it, ib) {
- let { color, batchnum } = this.template;
- if (color.length > 0) {
- // let num = ((it - 1) * batchnum + ib) % color.length;
- let num = (it - 1) % color.length;
- return color[num];
- } else return '#004499';
- },
- checkDate(date) {
- let year = JSON.parse(JSON.stringify(this.info.year));
- let res = moment(date).isBetween(`${year}-01-01`, `${year}-12-31`, null, '[]');
- return !res;
- },
- // returns() {
- // if (this.view == 'plan') this.$router.push({ path: './index' });
- // else if (this.view == 'school') this.view = 'plan';
- // else this.view = 'school';
- // },
- // changeView() {
- // this.savePlan();
- // this.view = 'school';
- // },
- async toSave(schPlan) {
- const res = await this.setSchPlan(schPlan);
- if (this.$checkRes(res)) {
- this.savePlan();
- }
- },
- toDirector() {
- this.view = 'director';
- },
- },
- watch: {
- defaultOption: {
- handler(val) {
- this.search();
- },
- deep: true,
- },
- },
- computed: {
- ...mapState(['user', 'defaultOption']),
- 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.65;
- return width > 400 ? width : 400;
- },
- },
- metaInfo() {
- return { title: this.$route.meta.title };
- },
- };
- </script>
- <style lang="less" scoped>
- /deep/.el-card__body {
- overflow: auto;
- padding: 10px;
- }
- </style>
|