classes.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. <template>
  2. <div id="plan">
  3. <!-- 根据计划,获取所有期数及期数下批次,然后提供选择期数;查询出该期数下学校上报的学生,选择学生手动分班 :filter="filterFields"-->
  4. <list-frame :title="pageTitle" @query="stuSearch" :total="total" :needAdd="false" :needFilter="false" returns="./index">
  5. <el-card style="padding:10px">
  6. <el-row>
  7. <el-form :inline="true" size="mini">
  8. <el-form-item>
  9. <el-button type="primary" @click="toAutoSetClass">一键分班</el-button>
  10. </el-form-item>
  11. </el-form>
  12. <el-form :inline="true" size="mini">
  13. <el-form-item label="批次">
  14. <el-select v-model="selectInfo.batchid" placeholder="请先选择期数" @change="getClasses">
  15. <el-option v-for="(i, index) in batchList" :key="index" :label="i.batch" :value="i._id"></el-option>
  16. </el-select>
  17. </el-form-item>
  18. <el-form-item label="班级">
  19. <el-select v-model="selectInfo.classid" placeholder="请先选择批次" @change="getLimit">
  20. <el-option v-for="(i, index) in classList" :key="index" :label="i.name" :value="i._id"></el-option>
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item>
  24. <el-button type="primary" @click="toSetClass">确认分班</el-button>
  25. </el-form-item>
  26. </el-form>
  27. </el-row>
  28. <el-row type="flex" justify="space-around" :gutter="10" align="middle" style="padding:10px 0;">
  29. <el-col :span="7">班级需求:{{ selectInfo.personReq }}人</el-col>
  30. <el-col :span="7">已选择学生:{{ selected.length }}人</el-col>
  31. <el-col :span="7">男性:{{ selectInfo.male }}人</el-col>
  32. <el-col :span="7">女性:{{ selectInfo.female }}人</el-col>
  33. </el-row>
  34. <data-table
  35. ref="table"
  36. :fields="fields"
  37. :data="list"
  38. :opera="opera"
  39. :select="true"
  40. :selected="selected"
  41. @edit="toEdit"
  42. @delete="toDelete"
  43. @handleSelect="toSelect"
  44. ></data-table>
  45. </el-card>
  46. </list-frame>
  47. </div>
  48. </template>
  49. <script>
  50. import listFrame from '@frame/layout/admin/list-frame';
  51. import dataTable from '@frame/components/data-table';
  52. import _ from 'lodash';
  53. import { mapState, createNamespacedHelpers } from 'vuex';
  54. const { mapActions: trainPlan } = createNamespacedHelpers('trainplan');
  55. const { mapActions: schPlan } = createNamespacedHelpers('schPlan');
  56. const { mapActions: student } = createNamespacedHelpers('student');
  57. const { mapActions: classes } = createNamespacedHelpers('classes');
  58. const { mapActions: director } = createNamespacedHelpers('director');
  59. const { mapActions: dept } = createNamespacedHelpers('dept');
  60. export default {
  61. metaInfo: { title: '安排班级' },
  62. name: 'plan',
  63. props: {},
  64. components: { listFrame, dataTable },
  65. data: () => ({
  66. opera: [],
  67. fields: [
  68. { label: '学生姓名', prop: 'name' },
  69. { label: '学校', prop: 'school_name' },
  70. { label: '性别', prop: 'gender' },
  71. ],
  72. filterFields: [], //{ label: '期数', model: 'termid', type: 'select' }
  73. list: [],
  74. selected: [],
  75. selectedTest: [],
  76. total: 0,
  77. selectInfo: {
  78. male: 0,
  79. female: 0,
  80. personReq: 0,
  81. },
  82. termList: [],
  83. batchList: [],
  84. classList: [],
  85. directorList: [],
  86. deptList: [],
  87. options: undefined,
  88. classtype: '0',
  89. }),
  90. created() {},
  91. methods: {
  92. ...trainPlan(['fetch']),
  93. ...schPlan({ schQuery: 'query' }),
  94. ...student({ getStudentList: 'noClass' }), //noClass
  95. ...classes({ getClassesList: 'query', createClass: 'divide', addStudent: 'addStudent' }),
  96. ...director({ getDirectorList: 'query' }),
  97. ...dept({ getDeptList: 'query' }),
  98. async search({ skip = 0, limit = 10, ...info } = {}) {
  99. const res = await this.fetch(this.id);
  100. if (this.$checkRes(res)) {
  101. let { termnum } = res.data;
  102. this.$set(this, `termList`, termnum);
  103. let termid = _.get(this.options, `termid`);
  104. if (termid) {
  105. this.getBatch(termid);
  106. // this.stuSearch();
  107. }
  108. }
  109. },
  110. //查询选择期上报的学生,提供批次选择
  111. async stuSearch({ skip = 0, limit = 10, ...info } = {}) {
  112. const res = await this.getStudentList({ termid: this.options.termid, skip, limit, type: this.classtype });
  113. if (this.$checkRes(res)) {
  114. this.$set(this, `list`, res.data);
  115. this.$set(this, `total`, res.total);
  116. }
  117. if (skip !== 0) return;
  118. },
  119. getBatch() {
  120. let termid = _.get(this.options, 'termid');
  121. if (!termid) return;
  122. let batchs = this.termList.find(f => f._id === termid);
  123. if (batchs) {
  124. let { batchnum } = batchs;
  125. this.$set(this, `batchList`, batchnum);
  126. }
  127. },
  128. //根据批次id,查询下面的班级
  129. async getClasses(data) {
  130. let res = [];
  131. for (const term of this.termList) {
  132. let { batchnum } = term;
  133. let r = batchnum.find(f => f._id == data);
  134. if (r) res = r.class;
  135. }
  136. this.$set(this, `classList`, res);
  137. },
  138. toEdit({ data }) {
  139. this.$router.push({ path: '/dept/detail', query: { id: data.id } });
  140. },
  141. async toDelete({ data }) {
  142. const res = await this.delete(data.id);
  143. this.$checkRes(res, '删除成功', '删除失败');
  144. this.search();
  145. },
  146. toSelect(selecteds) {
  147. this.$set(this, `selected`, selecteds);
  148. let male = 0,
  149. female = 0;
  150. for (const i of selecteds) {
  151. if (i.gender === '1' || i.gender === '男') male++;
  152. else female++;
  153. }
  154. this.$set(this.selectInfo, `male`, male);
  155. this.$set(this.selectInfo, `female`, female);
  156. },
  157. async toAutoSetClass() {
  158. // 整理数据生成班级;将学生列表重新查询=>为了将已经有班级的学生剔除,以便继续分班(重新查询)
  159. let info = {};
  160. info.termid = _.get(this.defaultOption, `termid`);
  161. info.planid = this.id;
  162. //手动添加学生使用这部分,接口换了,之后转移到新加的手动
  163. // let stuList = JSON.parse(JSON.stringify(this.selected));
  164. // // if (this.isOutRange(stuList)) return;
  165. // info.students = stuList;
  166. let res = await this.createClass(info);
  167. if (this.$checkRes(res, '分班成功', '分班失败')) this.resetData();
  168. //重置信息
  169. // this.selectInfo = {
  170. // male: 0,
  171. // female: 0,
  172. // };
  173. // this.selected = [];
  174. // this.$refs.table.selectReset();
  175. },
  176. async toSetClass() {
  177. let data = {};
  178. data.id = _.pick(this.selectInfo, ['classid']).classid;
  179. let stuList = JSON.parse(JSON.stringify(this.selected));
  180. data.ids = stuList.map(i => i._id);
  181. let res = await this.addStudent(data);
  182. if (this.$checkRes(res, '分配成功', res.errmsg || '分配失败')) {
  183. this.resetData();
  184. this.search();
  185. }
  186. },
  187. isOutRange(selected) {
  188. let res = true;
  189. if (selected.length <= 0) this.$message.warning('请选择学生');
  190. else if (_.inRange(selected.length, 1, this.selectInfo.personReq * 1)) this.$message.error('选择人数不足');
  191. else if (selected.length > this.selectInfo.personReq * 1) this.$message('超出班级规定人数');
  192. else res = false;
  193. return res;
  194. },
  195. getLimit(selected) {
  196. let res = this.classList.find(f => f._id == selected);
  197. if (res) {
  198. this.$set(this.selectInfo, `personReq`, res.number);
  199. this.$set(this, `classtype`, res.type);
  200. this.stuSearch();
  201. }
  202. },
  203. resetData() {
  204. this.list = [];
  205. this.selected = [];
  206. this.batchList = [];
  207. this.classList = [];
  208. this.selectInfo = {
  209. male: 0,
  210. female: 0,
  211. personReq: 0,
  212. };
  213. },
  214. },
  215. watch: {
  216. defaultOption: {
  217. immediate: true,
  218. deep: true,
  219. handler(val) {
  220. if (!_.get(this, 'options')) {
  221. this.$set(this, `options`, _.cloneDeep(val));
  222. this.search();
  223. } else {
  224. let nplanid = _.get(val, 'planid');
  225. let oplanid = _.get(this.options, 'planid');
  226. if (nplanid && !_.isEqual(nplanid, oplanid)) {
  227. this.termList = [];
  228. this.resetData();
  229. this.search();
  230. }
  231. let ntermid = _.get(val, 'termid');
  232. let otermid = _.get(this.options, 'termid');
  233. if (ntermid && !_.isEqual(ntermid, otermid)) {
  234. this.$set(this, `options`, _.cloneDeep(val));
  235. this.resetData();
  236. this.getBatch();
  237. this.stuSearch();
  238. }
  239. }
  240. },
  241. },
  242. },
  243. computed: {
  244. ...mapState(['user', 'defaultOption']),
  245. pageTitle() {
  246. return `${this.$route.meta.title}`;
  247. },
  248. id() {
  249. return this.defaultOption.planid;
  250. },
  251. },
  252. };
  253. </script>
  254. <style lang="less" scoped></style>