detail.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <template>
  2. <div id="detail">
  3. <detail-frame :title="mainTitle" returns="/plan/index">
  4. <el-row :gutter="10" type="flex">
  5. <el-col :span="12">
  6. <el-card header="全年计划信息">
  7. <el-form :model="info" :rules="rules" label-width="60px" size="small" @submit.native.prevent>
  8. <el-form-item label="年份">
  9. {{ info.year }}
  10. </el-form-item>
  11. <el-form-item label="标题" prop="title" required>
  12. <el-input v-model="info.title"></el-input>
  13. </el-form-item>
  14. <el-collapse v-model="collapse" accordion>
  15. <el-collapse-item title="计划简表" name="1">
  16. <data-table :fields="fields" :data="events" :opera="opera" @edit="toEdit" @delete="toDelete" :height="heights"></data-table>
  17. </el-collapse-item>
  18. </el-collapse>
  19. <el-form-item>
  20. <el-row type="flex" align="middle" justify="space-around" style="margin-top:20px">
  21. <el-col :span="6">
  22. <el-button type="primary" @click="savePlan">保存全年计划</el-button>
  23. </el-col>
  24. </el-row>
  25. </el-form-item>
  26. </el-form>
  27. </el-card>
  28. </el-col>
  29. <el-col :span="16" :style="`width:${widths}px`">
  30. <el-card ref="card">
  31. <calendar @draft="selectDate" @eventClick="eventClick" :events="events"></calendar>
  32. </el-card>
  33. </el-col>
  34. </el-row>
  35. </detail-frame>
  36. <el-drawer :visible.sync="drawer" direction="rtl" title="安排计划" @close="toClose">
  37. <el-form :model="form" ref="form" :rules="formRules" label-width="80px" size="small" @submit.native.prevent style="padding: 15px;">
  38. <el-form-item label="开始时间" prop="start" required>
  39. <el-date-picker v-model="form.start" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd"> </el-date-picker>
  40. </el-form-item>
  41. <el-form-item label="结束时间" prop="end" required>
  42. <el-date-picker v-model="form.end" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd"> </el-date-picker>
  43. </el-form-item>
  44. <el-form-item label="期数" prop="term" required> <el-input v-model="form.term"></el-input> </el-form-item>
  45. <el-form-item label="班级类型" prop="type" required>
  46. <el-radio-group v-model="form.type">
  47. <el-radio label="0">正常班级</el-radio>
  48. <el-radio label="1">特殊班级</el-radio>
  49. </el-radio-group>
  50. </el-form-item>
  51. <el-form-item label="批次" prop="batch" v-if="form.type === '0'"> <el-input v-model="form.batch"></el-input> </el-form-item>
  52. <el-form-item label="班级数量" prop="class" v-if="form.type === '0'"> <el-input v-model="form.class"></el-input> </el-form-item>
  53. <el-form-item label="每班人数" prop="number" required> <el-input v-model="form.number"></el-input> </el-form-item>
  54. <el-form-item label="班级名称" prop="name" v-if="form.type === '1'"> <el-input v-model="form.name"></el-input> </el-form-item>
  55. <el-form-item label="颜色" prop="color">
  56. <el-color-picker v-model="form.color" :predefine="predefineColors" size="mini"></el-color-picker>
  57. </el-form-item>
  58. <el-form-item>
  59. <el-row type="flex" align="middle" justify="space-around">
  60. <el-col :span="6">
  61. <el-button type="primary" @click="saveForm">保存</el-button>
  62. </el-col>
  63. <el-col :span="6">
  64. <el-button @click="resetForm">重置</el-button>
  65. </el-col>
  66. </el-row>
  67. </el-form-item>
  68. </el-form>
  69. </el-drawer>
  70. </div>
  71. </template>
  72. <script>
  73. import detailFrame from '@frame/layout/admin/detail-frame';
  74. import calendar from '@frame/components/calendar';
  75. import dataTable from '@frame/components/data-table';
  76. import _ from 'lodash';
  77. import { mapActions, mapState, createNamespacedHelpers } from 'vuex';
  78. export default {
  79. metaInfo: { title: '计划详情' },
  80. name: 'detail',
  81. props: {},
  82. components: { detailFrame, calendar, dataTable },
  83. data: () => ({
  84. info: {
  85. year: '',
  86. termnum: {
  87. batchnum: [],
  88. },
  89. },
  90. form: { color: '#409EFF' },
  91. rules: {
  92. title: [{ required: true, message: '请输入标题' }],
  93. },
  94. formRules: {
  95. start: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
  96. end: [{ required: true, message: '请选择结束时间', trigger: 'change' }],
  97. term: [{ required: true, message: '请输入期数' }],
  98. number: [{ required: true, message: '请输入每班人数' }],
  99. type: [{ required: true, message: '请选择班级类型' }],
  100. },
  101. drawer: false,
  102. events: [],
  103. predefineColors: ['#409EFF'],
  104. collapse: '',
  105. fields: [
  106. { label: '开始时间', prop: 'start' },
  107. { label: '结束时间', prop: 'end' },
  108. { label: '期数', prop: 'term' },
  109. { label: '班级类型', prop: 'type', format: item => (item === '0' ? '正常班级' : '特殊班级') },
  110. ],
  111. opera: [
  112. {
  113. label: '编辑',
  114. icon: 'el-icon-edit',
  115. method: 'edit',
  116. },
  117. {
  118. label: '删除',
  119. icon: 'el-icon-delete',
  120. method: 'delete',
  121. confirm: true,
  122. },
  123. ],
  124. heights: 250,
  125. axiosData: {
  126. termnum: [
  127. {
  128. term: '1',
  129. batchnum: [
  130. {
  131. start: '2020-01-01',
  132. end: '2020-01-09',
  133. type: '0',
  134. number: '56',
  135. color: '#0BEB95',
  136. batch: '1',
  137. class: '1',
  138. title: '第1期第1批次',
  139. id: 'p1580869239498',
  140. },
  141. {
  142. start: '2020-01-01',
  143. end: '2020-01-09',
  144. type: '1',
  145. number: '56',
  146. color: '#409EFF',
  147. name: '第一期特殊1班',
  148. title: '第一期特殊1班',
  149. id: 'p1580869422724',
  150. },
  151. ],
  152. classnum: 2,
  153. },
  154. {
  155. term: '2',
  156. batchnum: [
  157. {
  158. start: '2020-01-01',
  159. end: '2020-01-09',
  160. type: '0',
  161. number: '56',
  162. color: '#0BEB95',
  163. batch: '1',
  164. class: '1',
  165. title: '第2期第1批次',
  166. id: 'p1580869239490',
  167. },
  168. {
  169. start: '2020-01-01',
  170. end: '2020-01-09',
  171. type: '1',
  172. number: '56',
  173. color: '#409EFF',
  174. name: '第二期特殊1班',
  175. title: '第二期特殊1班',
  176. id: 'p1580869422726',
  177. },
  178. {
  179. start: '2020-01-01',
  180. end: '2020-01-09',
  181. type: '1',
  182. number: '56',
  183. color: '#409EFF',
  184. name: '第二期特殊2班',
  185. title: '第二期特殊2班',
  186. id: 'p1580869422725',
  187. },
  188. ],
  189. classnum: 3,
  190. },
  191. {
  192. term: '3',
  193. batchnum: [
  194. {
  195. start: '2020-01-01',
  196. end: '2020-01-09',
  197. type: '0',
  198. number: '56',
  199. color: '#ff4444',
  200. batch: '1',
  201. class: '1',
  202. title: '第3期第1批次',
  203. id: 'p1580869239499',
  204. },
  205. ],
  206. classnum: 1,
  207. },
  208. ],
  209. title: 'test',
  210. year: 2020,
  211. },
  212. }),
  213. created() {
  214. if (this.isNew) this.$set(this.info, `year`, new Date().getFullYear());
  215. },
  216. mounted() {},
  217. methods: {
  218. // ...mapClass(['fetch', 'create', 'update']),
  219. //查询计划
  220. async search() {
  221. // const res = await this.fetch(this.id);
  222. // if (this.$checkRes(res)) this.$set(this, `info`, res.data);
  223. // this.loading = false;
  224. let events = [];
  225. events = _.flatten(
  226. this.axiosData.termnum.map(item => {
  227. item.batchnum.map(i => {
  228. i.term = item.term;
  229. return i;
  230. });
  231. return item.batchnum;
  232. })
  233. );
  234. let { termnum, year, title } = this.axiosData;
  235. this.$set(this, `events`, events);
  236. this.$set(this, `info`, { title, year });
  237. },
  238. //拖拽选择事件
  239. selectDate(object) {
  240. this.$set(this.form, `start`, JSON.parse(JSON.stringify(object.startStr)));
  241. this.$set(this.form, `end`, JSON.parse(JSON.stringify(object.endStr)));
  242. this.drawer = true;
  243. },
  244. //日历事件点击事件
  245. eventClick({ event }) {
  246. let arr = this.events.filter(fil => fil.id == event.id);
  247. if (arr.length > 0) this.form = arr[0];
  248. else {
  249. console.warn(`无对应id事件`);
  250. return;
  251. }
  252. this.drawer = true;
  253. },
  254. //列表编辑事件
  255. toEdit({ data, index }) {
  256. this.$set(this, `form`, JSON.parse(JSON.stringify(data)));
  257. this.drawer = true;
  258. },
  259. //列表删除事件
  260. toDelete({ data, index }) {
  261. this.events.splice(index, 1);
  262. },
  263. //保存计划事件
  264. savePlan() {
  265. //全年计划内容
  266. let data = JSON.parse(JSON.stringify(this.info));
  267. data.year = this.year;
  268. let termnum = [];
  269. //1,获取所有期数
  270. //2,按期数将events内数据分组
  271. termnum = _.uniq(this.events.map(item => item.term)).map(i => {
  272. let object = { term: i };
  273. object.batchnum = this.events.filter(fil => fil.term === i).map(b => _.pickBy(b, (val, key) => key !== 'term'));
  274. object.classnum = object.batchnum.reduce((pre, cur) => {
  275. if (cur.type === '0') return pre + parseInt(cur.class);
  276. else return pre + 1;
  277. }, 0);
  278. return object;
  279. });
  280. data.termnum = termnum;
  281. //TODO 连接接口
  282. },
  283. //保存表单函数
  284. saveForm() {
  285. this.$refs['form'].validate(valid => {
  286. if (valid) {
  287. this.setEvent();
  288. this.resetForm();
  289. } else {
  290. console.warn('form validate error!!!');
  291. }
  292. });
  293. },
  294. //重置表单函数
  295. resetForm() {
  296. this.$refs.form.resetFields();
  297. this.setHeight();
  298. },
  299. //添加/修改函数
  300. setEvent() {
  301. //TODO 需要根据班级类型把数据分开
  302. let data = JSON.parse(JSON.stringify(this.form));
  303. let { start, end, term, type, number, color, id } = data;
  304. let object = {};
  305. if (data.type === '0') {
  306. // 正常班级
  307. let { batch, class: classes } = data;
  308. object = { start, end, term, type, number, color, batch, class: classes };
  309. object.title = `第${JSON.parse(JSON.stringify(term))}期第${JSON.parse(JSON.stringify(batch))}批次`;
  310. } else {
  311. let { name } = data;
  312. object = { start, end, term, type, number, color, name, title: name };
  313. }
  314. if (!id) {
  315. object.id = `p${new Date().getTime()}`;
  316. this.events.push(object);
  317. } else {
  318. object.id = id;
  319. this.$set(
  320. this.events,
  321. _.findIndex(this.events, item => item.id == object.id),
  322. object
  323. );
  324. this.drawer = false;
  325. }
  326. if (_.findIndex(this.predefineColors, item => item == data.color) < 0) this.predefineColors.push(data.color);
  327. },
  328. //关闭抽屉函数
  329. toClose() {
  330. this.drawer = false;
  331. this.resetForm();
  332. },
  333. setHeight() {
  334. let heights = this.$refs.card.$el.clientHeight * 0.63;
  335. this.$set(this, `heights`, heights);
  336. },
  337. },
  338. watch: {
  339. isNew: {
  340. immediate: true,
  341. handler(val) {
  342. if (val) this.loading = false;
  343. else this.search();
  344. },
  345. },
  346. },
  347. computed: {
  348. widths() {
  349. let width = (document.body.clientWidth - 200) * 0.5;
  350. return width > 400 ? width : 400;
  351. },
  352. id() {
  353. return this.$route.query.id;
  354. },
  355. isNew() {
  356. return this.$route.query.id ? true : false; //false : true;
  357. },
  358. mainTitle() {
  359. let meta = this.$route.meta;
  360. let main = meta.title || '';
  361. let sub = meta.sub || '';
  362. return `${main}${sub}`;
  363. },
  364. keyWord() {
  365. let meta = this.$route.meta;
  366. let main = meta.title || '';
  367. return main;
  368. },
  369. },
  370. };
  371. </script>
  372. <style lang="less" scoped>
  373. /deep/.el-divider--horizontal {
  374. margin: 5px 0;
  375. }
  376. </style>