index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <template>
  2. <div id="index">
  3. <list-frame title="教师列表页" @query="search" :total="total" :filter="filFields" :needAdd="true" @add="add()">
  4. <template #options="{item}">
  5. <template v-if="item.model == 'gender'">
  6. <el-option v-for="(item, index) in gender" :key="index" :value="item.label"></el-option>
  7. </template>
  8. <template v-if="item.model == 'status'">
  9. <el-option v-for="(item, index) in lists" :key="index" :label="item.label" :value="item.value"></el-option>
  10. </template>
  11. </template>
  12. <el-row type="flex" align="middle" justify="end" class="btn_bar">
  13. <!-- <el-col :span="3" style="text-align:right;padding:0 10px;">
  14. <el-button type="primary" size="mini" @click="printView()">打印预览</el-button>
  15. </el-col> -->
  16. <el-col :span="2">
  17. <el-button type="primary" size="mini" @click="eDialog = true">导出excel</el-button>
  18. </el-col>
  19. <el-col :span="3">
  20. <el-button size="mini" type="primary" @click="downloadTemplate">下载上传教师评分模板</el-button>
  21. </el-col>
  22. <el-col :span="2">
  23. <el-button size="mini" type="primary" @click="selectDisplay">选择显示</el-button>
  24. </el-col>
  25. <el-col :span="3">
  26. <el-upload action="/files/train/score/upload" :show-file-list="false" :on-success="handleSuccess" :on-error="handleError" multiple>
  27. <el-button size="mini" type="primary">点击上传教师评分</el-button>
  28. </el-upload>
  29. </el-col>
  30. <el-col :span="2">
  31. <el-button type="primary" size="mini" @click="toIntegral"></el-button>
  32. </el-col>
  33. </el-row>
  34. <data-table :fields="fields" :data="list" :opera="opera" @share="share" @edit="toEdit" @delete="toDelete" @select="toSelect" @star="toStar">
  35. <template #custom="{item,row}">
  36. <template v-if="item.prop === 'is_bind'">
  37. <span :style="{ color: `${row[item.prop] ? '#67C23A' : '#F56C6C'}` }">{{ row[item.prop] ? '已激活' : '未激活' }}</span>
  38. </template>
  39. </template>
  40. </data-table>
  41. </list-frame>
  42. <el-dialog :visible.sync="dialog" title="添加教师" @close="toClose" width="50%">
  43. <data-form :data="form" :fields="tearcherForm" :rules="rules" @save="turnSave"> </data-form>
  44. </el-dialog>
  45. <el-dialog :visible.sync="columnDialog" title="显示列" @close="toClose" width="50%">
  46. <el-row>
  47. <el-checkbox-group v-model="columnSelect">
  48. <el-col :span="4" v-for="(i, index) in columns" :key="index">
  49. <el-checkbox :label="i.prop">{{ i.label }}</el-checkbox>
  50. </el-col>
  51. </el-checkbox-group>
  52. <el-col :span="24">
  53. <el-button type="primary" @click="changeColumns">确定</el-button>
  54. </el-col>
  55. </el-row>
  56. </el-dialog>
  57. <el-dialog title="导出" center :visible.sync="eDialog">
  58. <el-card>
  59. <template #header>
  60. <el-row>
  61. <el-col :span="24">选择导出的字段-教师表(点击字段可以更换顺序)</el-col>
  62. <el-col :span="24">
  63. <span v-for="(i, index) in selectModel" :key="`select-${index}`" style="padding-right:15px;zoom:1.1">
  64. <el-link type="primary" v-if="index === selectIndex && index !== 0" icon="el-icon-back" @click="toChangePos(i, -1)"></el-link>
  65. <el-link @click="toDisplayPos(index)">{{ i }}</el-link>
  66. <el-link type="primary" v-if="index === selectIndex && index !== selectModel.length - 1" icon="el-icon-right" @click="toChangePos(i, 1)"></el-link>
  67. </span>
  68. </el-col>
  69. </el-row>
  70. </template>
  71. <el-checkbox-group v-model="selectModel">
  72. <el-row>
  73. <el-col :span="6" v-for="(i, index) in models.student" :key="`model-${index}`">
  74. <el-checkbox :label="i.zh" style="word-wrap: break-word">{{ i.zh }}</el-checkbox>
  75. </el-col>
  76. </el-row>
  77. </el-checkbox-group>
  78. </el-card>
  79. <template #footer>
  80. <el-row type="flex" justify="space-around" :gutter="10" align="middle">
  81. <el-col :span="4">
  82. <el-button type="primary" size="small" @click="toExportExcel">导出</el-button>
  83. </el-col>
  84. <el-col :span="4">
  85. <el-button size="small" @click="eDialog = false">取消</el-button>
  86. </el-col>
  87. </el-row>
  88. </template>
  89. </el-dialog>
  90. <el-dialog title="往期评分" center :visible.sync="StarDialog">
  91. <el-table :data="StarList" border stripe style="width: 100%">
  92. <el-table-column align="center" prop="name" label="教师名称"> </el-table-column>
  93. <el-table-column align="center" prop="create_time" label="归档时间"> </el-table-column>
  94. <el-table-column align="center" prop="xsscore" label="学生评分"> </el-table-column>
  95. </el-table>
  96. <el-pagination
  97. style="text-align: right; margin: 10px 0 0 0;"
  98. background
  99. layout="sizes,total, prev, pager, next"
  100. :page-sizes="[10, 50, 100, 150, 200]"
  101. :total="StarTotal"
  102. :page-size="limit"
  103. :current-page.sync="currentPage"
  104. @current-change="changePage"
  105. @size-change="sizeChange"
  106. >
  107. </el-pagination>
  108. </el-dialog>
  109. </div>
  110. </template>
  111. <script>
  112. import _ from 'lodash';
  113. import listFrame from '@frame/layout/admin/list-frame';
  114. import dataTable from '@frame/components/data-table';
  115. import dataForm from '@frame/components/form';
  116. import { createNamespacedHelpers } from 'vuex';
  117. const { mapActions } = createNamespacedHelpers('teacher');
  118. const { mapActions: util } = createNamespacedHelpers('util');
  119. const { mapActions: document } = createNamespacedHelpers('document');
  120. export default {
  121. name: 'index',
  122. props: {},
  123. components: {
  124. listFrame,
  125. dataTable,
  126. dataForm,
  127. },
  128. data: () => ({
  129. gender: [
  130. { label: '男', value: '男' },
  131. { label: '女', value: '女' },
  132. ],
  133. lists: [
  134. { label: '注册', value: '0' },
  135. { label: '确认身份', value: '1' },
  136. { label: '资料评分', value: '2' },
  137. { label: '面试评分', value: '3' },
  138. { label: '确认入库', value: '4' },
  139. ],
  140. opera: [
  141. {
  142. label: '确认身份',
  143. icon: 'el-icon-check',
  144. method: 'share',
  145. display: item => {
  146. return item.schid == null && item.status == '0';
  147. },
  148. },
  149. {
  150. label: '编辑',
  151. icon: 'el-icon-edit',
  152. method: 'edit',
  153. },
  154. {
  155. label: '审核',
  156. icon: 'el-icon-s-order',
  157. method: 'select',
  158. display: item => {
  159. return item.status === '1' || item.status === '2' || item.status === '3';
  160. },
  161. },
  162. {
  163. label: '往期评分',
  164. icon: 'el-icon-star-on',
  165. method: 'star',
  166. },
  167. ],
  168. fields: [],
  169. list: [],
  170. filFields: [
  171. { label: '教师名称', model: 'name' },
  172. { label: '年龄', model: 'age' },
  173. {
  174. label: '状态',
  175. model: 'status',
  176. type: 'select',
  177. },
  178. {
  179. label: '性别',
  180. model: 'gender',
  181. type: 'select',
  182. },
  183. ],
  184. total: 0,
  185. // 添加教师
  186. dialog: false,
  187. form: {},
  188. tearcherForm: [
  189. { label: '教师姓名', required: true, model: 'name' },
  190. { label: '手机号', required: true, model: 'phone', options: { maxLength: 11, minLength: 11 } },
  191. ],
  192. rules: {
  193. name: [{ required: true, message: '请输入教师姓名' }],
  194. phone: [
  195. { required: true, message: '请输入手机号' },
  196. { min: 11, max: 11, message: '请输入11位手机号 ', trigger: 'blur' },
  197. ],
  198. },
  199. columnSelect: [],
  200. columnDialog: false,
  201. columns: [
  202. { label: '姓名', prop: 'name' },
  203. { label: '性别', prop: 'gender', options: { width: `80px` } },
  204. { label: '手机号', prop: 'phone' },
  205. { label: '账户密码', prop: 'secret' },
  206. { label: '学校名称', prop: 'schname' },
  207. { label: '邮箱', prop: 'email' },
  208. { label: '年龄', prop: 'age', options: { width: `80px` } },
  209. { label: '专业', prop: 'major' },
  210. {
  211. label: '是/否是礼仪老师',
  212. prop: 'islyteacher',
  213. format: item => {
  214. return item === '0' ? '否' : item === '1' ? '是' : '其他';
  215. },
  216. },
  217. { label: '学生评分', prop: 'xsscore', options: { width: `100px` } },
  218. { label: '资料评分', prop: 'zlscore', options: { width: `100px` } },
  219. { label: '面试评分', prop: 'msscore', options: { width: `100px` } },
  220. { label: '是否激活', prop: 'is_bind', custom: true },
  221. {
  222. label: '状态',
  223. prop: 'status',
  224. format: item => {
  225. return item === '0'
  226. ? '注册'
  227. : item === '1'
  228. ? '已确定身份'
  229. : item === '2'
  230. ? '已上传资料'
  231. : item === '3'
  232. ? '已选择面试'
  233. : item === '4'
  234. ? '确认入库'
  235. : '其他';
  236. },
  237. },
  238. ],
  239. eDialog: false,
  240. models: {},
  241. selectModel: [],
  242. selectIndex: '',
  243. // 往期评分
  244. skip: 0,
  245. limit: 10,
  246. StarList: [],
  247. StarTotal: 0,
  248. StarDialog: false,
  249. currentPage: 1,
  250. }),
  251. created() {
  252. this.$set(this, `fields`, this.columns);
  253. this.$set(
  254. this,
  255. 'columnSelect',
  256. this.columns.map(i => i.prop)
  257. );
  258. this.search();
  259. this.toFindModel();
  260. },
  261. computed: {},
  262. methods: {
  263. ...util(['findModel']),
  264. ...mapActions(['query', 'delete', 'scoreImport', 'status', 'create', 'toExport']),
  265. ...document({ dCreate: 'create', dQuery: 'queryTeacher' }),
  266. async search({ skip = 0, limit = 10, ...info } = {}) {
  267. const res = await this.query({ skip, limit, ...info });
  268. if (this.$checkRes(res)) {
  269. this.$set(this, `list`, res.data);
  270. this.$set(this, `total`, res.total);
  271. }
  272. },
  273. // 确定按钮
  274. async share({ data }) {
  275. let res = await this.status({ status: '1', teachersid: [data._id] });
  276. if (this.$checkRes(res, `确认身份成功`, res.errmsg || '确认身份失败')) this.search();
  277. },
  278. toEdit({ data }) {
  279. this.$router.push({ path: '/teacher/detail', query: { id: data.id } });
  280. },
  281. toSelect({ data }) {
  282. this.$router.push({ path: '/teacher/verify', query: { id: data.id } });
  283. },
  284. async toDelete(data) {
  285. const res = await this.delete(data.id);
  286. this.$checkRes(res, '删除成功', '删除失败');
  287. this.search();
  288. },
  289. //上传成功
  290. async handleSuccess(res, file) {
  291. if (this.$checkRes(res)) {
  292. let r = await this.scoreImport(res.uri);
  293. if (this.$checkRes(r, '上传成功', r.errmsg || '上传失败')) this.search();
  294. }
  295. },
  296. //上传失败
  297. handleError(err, file) {
  298. console.log(err, file);
  299. this.$message.error('请重新上传或联系开发人员');
  300. },
  301. downloadTemplate() {
  302. window.open('/files/teacherScoreTemplate.xlsx');
  303. },
  304. // 打印教师
  305. printView() {
  306. this.$router.push({ path: '/teacher/printTea', query: {} });
  307. },
  308. // 添加教师
  309. add() {
  310. this.dialog = true;
  311. },
  312. // 提交
  313. async turnSave({ data }) {
  314. data.status = '0';
  315. const res = await this.create(data);
  316. if (this.$checkRes(res, `创建成功`, res.errmsg || '创建失败')) this.search();
  317. },
  318. // 取消
  319. toClose() {
  320. this.from = {};
  321. this.dialog = false;
  322. },
  323. // 列显示选择
  324. selectDisplay() {
  325. this.columnDialog = true;
  326. },
  327. //改变显示列
  328. changeColumns() {
  329. const r = this.columns.filter(f => this.columnSelect.find(fc => fc == f.prop));
  330. this.$set(this, `fields`, r);
  331. this.columnDialog = false;
  332. },
  333. // 导出部分
  334. async toFindModel() {
  335. const res = await this.findModel('teacher');
  336. if (this.$checkRes(res)) {
  337. const { data } = res;
  338. if (!(data && _.isObject(data))) return;
  339. const keys = Object.keys(data);
  340. let obj = {};
  341. const arr = [];
  342. for (const key of keys) {
  343. const o = data[key];
  344. const { zh } = o;
  345. if (zh) {
  346. const ao = { zh };
  347. ao['model'] = key;
  348. arr.push(ao);
  349. }
  350. }
  351. obj['student'] = arr;
  352. this.$set(this, `models`, obj);
  353. }
  354. },
  355. // 显示已经选择的字段的移动位置按钮
  356. toDisplayPos(index) {
  357. this.selectIndex = index;
  358. },
  359. // 移动位置,
  360. toChangePos(data, num) {
  361. const dup = _.cloneDeep(this.selectModel);
  362. // 当前元素位置
  363. const di = dup.findIndex(f => f == data);
  364. // 要交换的元素位置及数据
  365. const ci = di + num;
  366. const c = dup[ci];
  367. // 交换
  368. dup[ci] = data;
  369. dup[di] = c;
  370. this.$set(this, `selectModel`, dup);
  371. // 将目标也跟随过去
  372. this.toDisplayPos(ci);
  373. },
  374. async toExportExcel() {
  375. let model = this.selectModel.map(i => {
  376. const om = this.models.student.find(f => f.zh == i);
  377. if (om) return om;
  378. });
  379. model = _.compact(model);
  380. const msg = this.$message({ duration: 0, message: '正在导出,请稍后...' });
  381. const res = await this.toExport({ model });
  382. msg.close();
  383. this.$checkRes(res, '任务已执行,请在 "菜单 - 待办事项" 中查看执行进度');
  384. },
  385. // 往期评分
  386. async toStar({ data }) {
  387. const res = await this.dQuery({ skip: this.skip, limit: this.limit, teacher: data.id || data._id });
  388. if (this.$checkRes(res)) {
  389. this.$set(this, `StarList`, res.data);
  390. this.$set(this, `StarTotal`, res.total);
  391. this.$set(this, `StarDialog`, true);
  392. }
  393. },
  394. // 分页
  395. changePage(page = this.currentPage) {
  396. this.toStar({ skip: (page - 1) * this.limit, limit: this.limit });
  397. },
  398. sizeChange(limit) {
  399. this.limit = limit;
  400. this.currentPage = 1;
  401. this.toStar({ skip: 0, limit: this.limit });
  402. },
  403. // 教师积分归档
  404. toIntegral() {
  405. this.$confirm('此操作将教师积分清零并且积分归档, 是否继续?', '提示', {
  406. confirmButtonText: '确定',
  407. cancelButtonText: '取消',
  408. type: 'warning',
  409. })
  410. .then(async () => {
  411. const res = await this.dCreate({});
  412. this.$checkRes(res, `积分归档成功`, res.errmsg || '积分归档失败');
  413. })
  414. .catch(() => {
  415. this.$message({
  416. type: 'info',
  417. message: '已取消',
  418. });
  419. });
  420. },
  421. },
  422. };
  423. </script>
  424. <style lang="less" scoped></style>