星火管控前端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

userManage.vue 31KB

10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
10 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
10 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
9 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
10 个月前
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  1. <template>
  2. <div class="main_root">
  3. <div class="schoolInfo">
  4. <div
  5. class="schoolname"
  6. :class="[
  7. curClass.id === schoolInfo.id && curClass.type === schoolInfo.type
  8. ? 'active'
  9. : ''
  10. ]"
  11. @click="selectClass(schoolInfo)"
  12. >
  13. {{ schoolInfo.name }}
  14. </div>
  15. <div class="class_list">
  16. <div v-for="item in schoolInfo.children" :key="item.id">
  17. <div
  18. :class="[
  19. 'class_item',
  20. curClass.id === item.id && curClass.type === item.type
  21. ? 'active'
  22. : ''
  23. ]"
  24. :title="item.name"
  25. @click="selectClass(item)"
  26. >
  27. {{ item.name }}
  28. </div>
  29. <span
  30. @click="toOpenMenu(item, $event)"
  31. class="ivu-icon iconfont icon-sandian"
  32. ></span>
  33. </div>
  34. </div>
  35. </div>
  36. <div class="user_list">
  37. <div class="search_header">
  38. <div class="search_left">
  39. <Select
  40. :transfer="true"
  41. v-model="searchForm.care"
  42. style="width: 140px"
  43. @on-change="searchList()"
  44. >
  45. <Option v-for="item in care_list" :value="item.id" :key="item.id">{{
  46. item.title
  47. }}</Option>
  48. </Select>
  49. <Select
  50. :transfer="true"
  51. v-model="searchForm.enabled"
  52. style="width: 140px; margin: 0 10px"
  53. @on-change="searchList()"
  54. >
  55. <Option
  56. v-for="item in enabled_list"
  57. :value="item.id"
  58. :key="item.id"
  59. >{{ item.title }}</Option
  60. >
  61. </Select>
  62. <Select
  63. :transfer="true"
  64. v-model="searchForm.control"
  65. style="width: 140px; margin-right: 10px"
  66. @on-change="searchList()"
  67. >
  68. <Option
  69. v-for="item in control_list"
  70. :value="item.id"
  71. :key="item.id"
  72. >{{ item.title }}</Option
  73. >
  74. </Select>
  75. <Input
  76. v-model="searchForm.username"
  77. placeholder="请输入姓名"
  78. search
  79. @on-search="searchList()"
  80. style="width: 150px"
  81. />
  82. </div>
  83. <div>
  84. <Button type="primary" class="primary_btn" @click="userImport()"
  85. >用户导入</Button
  86. >
  87. <Button
  88. style="margin: 0 10px"
  89. type="primary"
  90. class="primary_btn"
  91. @click="userExport()"
  92. >用户导出</Button
  93. >
  94. <Button type="primary" class="primary_btn" @click="toAdd()"
  95. >新建</Button
  96. >
  97. </div>
  98. </div>
  99. <div class="table_wrap">
  100. <Table :columns="columns" :data="searchForm.list">
  101. <template slot-scope="{ row }" slot="loginname">
  102. <span
  103. v-if="row.care === 1"
  104. style="color: #fcc138"
  105. class="ivu-icon iconfont icon-guanzhu-yiguanzhu"
  106. ></span>
  107. {{ row.loginname }}
  108. </template>
  109. <template slot-scope="{ row }" slot="enabled">
  110. <i-switch
  111. size="large"
  112. v-model="row.enabled"
  113. :true-value="1"
  114. :false-value="2"
  115. @on-change="enabledChange(row)"
  116. >
  117. <span slot="open">启用</span>
  118. <span slot="close">禁用</span>
  119. </i-switch>
  120. </template>
  121. <template slot-scope="{ row }" slot="actionSlot">
  122. <div class="action_list">
  123. <div class="action_del" @click="toDel(row)">删除</div>
  124. <div class="action_success" @click="toCare(row)">
  125. <span v-if="row.care === 2">重点关注</span>
  126. <span v-else>取消关注</span>
  127. </div>
  128. </div>
  129. </template>
  130. </Table>
  131. </div>
  132. <div class="page_wrap">
  133. <Page
  134. :transfer="true"
  135. :total="searchForm.total"
  136. :current="searchForm.page"
  137. :page-size="searchForm.size"
  138. :page-size-opts="[10, 20, 40, 60]"
  139. @on-change="pageChange"
  140. @on-page-size-change="pageSizeChange"
  141. show-total
  142. show-sizer
  143. ></Page>
  144. </div>
  145. </div>
  146. <!-- 更多菜单弹窗 -->
  147. <div
  148. class="more_menu"
  149. ref="moreMenuRef"
  150. @mousedown.stop
  151. @contextmenu.stop.prevent
  152. @mousewheel.stop
  153. >
  154. <div @click="toSelectMenuItem(1)" class="menu_group">编辑</div>
  155. <div @click="toSelectMenuItem(2)" class="menu_group">删除</div>
  156. </div>
  157. <!-- 编辑班级 -->
  158. <Modal
  159. v-model="classInfo.show"
  160. :mask-closable="false"
  161. class="modal_tip"
  162. title="编辑"
  163. >
  164. <Form
  165. v-if="classInfo.show"
  166. ref="classInfo"
  167. :model="classInfo"
  168. :rules="rules"
  169. :label-width="110"
  170. >
  171. <FormItem label="班级名称" prop="classname">
  172. <Input
  173. v-model.trim="classInfo.classname"
  174. placeholder="请输入班级名称"
  175. ></Input>
  176. </FormItem>
  177. </Form>
  178. <div slot="footer" style="text-align: right">
  179. <Button @click="exitInfo.show = false">取消</Button>
  180. <Button @click="saveclassInfo()" type="primary" class="primary_btn"
  181. >保存</Button
  182. >
  183. </div>
  184. </Modal>
  185. <!-- 已存在列表 -->
  186. <Modal
  187. v-model="exitInfo.show"
  188. :mask-closable="false"
  189. class="exit_modal modal1"
  190. title="提示"
  191. >
  192. <div class="exit">
  193. <div>
  194. <div v-if="exitInfo.studentsExisted.length > 0">
  195. 以下学生信息已存在
  196. <Table border :columns="columns2" :data="exitInfo.studentsExisted">
  197. <template slot-scope="{ row }" slot="usersex">
  198. <span>
  199. {{
  200. row.usersex == 1 ? "男" : row.usersex == 2 ? "女" : "未知"
  201. }}
  202. </span>
  203. </template>
  204. </Table>
  205. </div>
  206. <div v-if="exitInfo.usersExisted.length > 0">
  207. 已存在非本校账号列表
  208. <Table border :columns="columns2" :data="exitInfo.usersExisted">
  209. <template slot-scope="{ row }" slot="usersex">
  210. <span>
  211. {{
  212. row.usersex == 1 ? "男" : row.usersex == 2 ? "女" : "未知"
  213. }}
  214. </span>
  215. </template>
  216. </Table>
  217. </div>
  218. </div>
  219. </div>
  220. </Modal>
  221. <!-- 导入 -->
  222. <Modal
  223. :mask-closable="false"
  224. v-model="importInfo.show"
  225. class="modal_tip"
  226. title="导入"
  227. >
  228. <Upload
  229. v-if="importInfo.show"
  230. type="drag"
  231. action
  232. accept=".xls,.xlsx"
  233. :before-upload="handleUpload"
  234. >
  235. <div style="padding: 30px 0; background: #f8f8f9">
  236. <Button type="primary" class="primary_btn" style="font-size: 16px">
  237. <Icon type="ios-cloud-upload-outline" size="18"></Icon>上传excel
  238. </Button>
  239. <div style="margin-top: 10px; color: #999">支持上传xlsx/xls文件</div>
  240. </div>
  241. </Upload>
  242. <div v-if="importInfo.file" class="files_list">
  243. {{ importInfo.file.name }}
  244. </div>
  245. <div class="import_tip">
  246. 导入数据需按照模板填写信息,
  247. <span class="theme_color" @click="download()">下载表格模板</span>
  248. </div>
  249. <div slot="footer">
  250. <Button @click="importInfo.show = false">取消</Button>
  251. <Button
  252. @click="ok_import"
  253. class="primary_btn"
  254. :loading="wait_flag"
  255. type="primary"
  256. >保存</Button
  257. >
  258. </div>
  259. </Modal>
  260. <!-- 新建 -->
  261. <Modal
  262. class="modal1"
  263. :mask-closable="false"
  264. v-model="addInfo.show"
  265. title="新建"
  266. >
  267. <Form
  268. v-if="addInfo.show"
  269. ref="addForm"
  270. :model="addInfo"
  271. :rules="rules"
  272. :label-width="110"
  273. inline
  274. >
  275. <FormItem label="姓名" prop="username" style="width: calc(50% - 10px)">
  276. <Input v-model="addInfo.username" placeholder="请输入姓名"></Input>
  277. </FormItem>
  278. <FormItem label="性别" style="width: calc(50% - 10px)">
  279. <RadioGroup v-model="addInfo.usersex">
  280. <Radio :label="1">男</Radio>
  281. <Radio :label="2">女</Radio>
  282. <Radio :label="0">未知</Radio>
  283. </RadioGroup>
  284. </FormItem>
  285. <FormItem label="密码" prop="loginpwd" style="width: calc(50% - 10px)">
  286. <Input v-model="addInfo.loginpwd" placeholder="请输入密码"></Input>
  287. </FormItem>
  288. <FormItem
  289. label="确认密码"
  290. prop="loginpwd1"
  291. style="width: calc(50% - 10px)"
  292. >
  293. <Input
  294. v-model="addInfo.loginpwd1"
  295. placeholder="请输入确认密码"
  296. ></Input>
  297. </FormItem>
  298. <FormItem label="登录名" prop="loginname" style="width: 100%">
  299. <Input v-model="addInfo.loginname" placeholder="请输入登录名"></Input>
  300. </FormItem>
  301. <FormItem label="班级" class="require" style="width: 100%">
  302. <Select
  303. v-model="addInfo.classid"
  304. placeholder="请选择班级"
  305. style="width: 300px"
  306. @on-change="classChange()"
  307. >
  308. <template v-if="schoolInfo.children.length > 0">
  309. <Option
  310. v-for="item in schoolInfo.children"
  311. :value="item.id"
  312. :key="item.id"
  313. >{{ item.name }}</Option
  314. >
  315. </template>
  316. </Select>
  317. </FormItem>
  318. <FormItem label="状态" style="width: 100%">
  319. <RadioGroup v-model="addInfo.enabled">
  320. <Radio :label="1">启用</Radio>
  321. <Radio :label="2">禁用</Radio>
  322. </RadioGroup>
  323. </FormItem>
  324. <FormItem label="学号" style="width: 100%">
  325. <Input v-model="addInfo.studentno" placeholder="请输入学号"></Input>
  326. </FormItem>
  327. <FormItem label="手机号码" style="width: 100%">
  328. <Input
  329. v-model="addInfo.userphone"
  330. placeholder="请输入手机号码"
  331. ></Input>
  332. </FormItem>
  333. <FormItem label="身份证号码" style="width: 100%">
  334. <Input
  335. v-model="addInfo.cardid"
  336. placeholder="请输入身份证号码"
  337. ></Input>
  338. </FormItem>
  339. </Form>
  340. <div
  341. slot="footer"
  342. style="
  343. display: flex;
  344. justify-content: space-between;
  345. align-items: center;
  346. "
  347. >
  348. <div style="color: #b50000">
  349. 注:密码必须是6-16位的大小写英文字母、数字组合。
  350. </div>
  351. <div>
  352. <Button @click="addInfo.show = false">取消</Button>
  353. <Button @click="saveAddInfo()" type="primary" class="primary_btn"
  354. >保存</Button
  355. >
  356. </div>
  357. </div>
  358. </Modal>
  359. <Spin fix v-if="showLoading" style="background-color: transparent">
  360. <Icon type="ios-loading" size="18" class="demo-spin-icon-load"></Icon>
  361. <div>加载中</div>
  362. </Spin>
  363. </div>
  364. </template>
  365. <script>
  366. import {
  367. class_delete,
  368. class_edit,
  369. class_list,
  370. user_care,
  371. user_delete,
  372. user_disabled,
  373. user_enable,
  374. user_export,
  375. user_import,
  376. user_list,
  377. user_un_care
  378. } from "@/api/school";
  379. import { user_add, user_edit } from "@/api/school";
  380. import { exportToExcel } from "@/utils/exportToExcel";
  381. import { generateRandomString, pwdCheck, reg } from "@/utils";
  382. export default {
  383. data() {
  384. const classnameCheck = async (rule, value, callback) => {
  385. if (value) {
  386. let flag = this.schoolInfo.children.some((v) => {
  387. return (
  388. v.name === this.classInfo.classname &&
  389. v.id != this.classInfo.classid
  390. );
  391. });
  392. if (flag) {
  393. return callback(new Error("班级名称已存在!"));
  394. } else {
  395. callback();
  396. }
  397. } else {
  398. return callback(new Error("班级名称不能为空!"));
  399. }
  400. };
  401. // 重复密码验证
  402. const pwdAgainCheck = async (rule, value, callback) => {
  403. if (!reg.test(value)) {
  404. return callback(new Error("密码格式不正确!"));
  405. }
  406. if (this.addInfo.loginpwd != value) {
  407. return callback(new Error("两次输入密码不一致!"));
  408. }
  409. callback();
  410. };
  411. return {
  412. userInfo: {},
  413. importInfo: {
  414. show: false,
  415. file: null
  416. },
  417. exitInfo: {
  418. show: false,
  419. studentsExisted: [],
  420. usersExisted: []
  421. },
  422. columns2: [
  423. {
  424. title: "姓名",
  425. key: "username",
  426. minWidth: 140,
  427. align: "center"
  428. },
  429. {
  430. title: "登录名",
  431. key: "loginname",
  432. minWidth: 140,
  433. align: "center"
  434. },
  435. {
  436. title: "性别",
  437. key: "usersex",
  438. align: "center",
  439. slot: "usersex"
  440. }
  441. ],
  442. form_data: null,
  443. wait_flag: false,
  444. showLoading: false,
  445. care_list: [
  446. { id: 0, title: "请选择关注状态" },
  447. { id: 1, title: "重点关注" },
  448. { id: 2, title: "不关注" }
  449. ],
  450. enabled_list: [
  451. { id: 0, title: "请选择启动状态" },
  452. { id: 1, title: "启用" },
  453. { id: 2, title: "禁用" }
  454. ],
  455. control_list: [
  456. { id: 0, title: "请选择管控状态" },
  457. { id: 1, title: "管控中" },
  458. { id: 2, title: "解除管控" }
  459. ],
  460. curClass: {
  461. id: 0,
  462. type: 1,
  463. name: ""
  464. },
  465. addInfo: {
  466. show: false,
  467. userid: null,
  468. username: "",
  469. loginname: "",
  470. loginpwd: "",
  471. loginpwd1: "",
  472. classid: "",
  473. classname: "",
  474. schoolid: null,
  475. regionid: null,
  476. enabled: 1,
  477. studentno: "",
  478. userphone: "",
  479. cardid: ""
  480. },
  481. rules: {
  482. classname: [
  483. {
  484. required: true,
  485. validator: classnameCheck,
  486. trigger: "blur"
  487. }
  488. ],
  489. username: [
  490. {
  491. required: true,
  492. message: "请输入姓名",
  493. trigger: "blur"
  494. }
  495. ],
  496. loginname: [
  497. {
  498. required: true,
  499. message: "请输入请输入登录名",
  500. trigger: "blur"
  501. }
  502. ],
  503. loginpwd: [
  504. {
  505. required: true,
  506. validator: pwdCheck,
  507. trigger: "blur"
  508. }
  509. ],
  510. loginpwd1: [
  511. {
  512. required: true,
  513. validator: pwdAgainCheck,
  514. trigger: "blur"
  515. }
  516. ]
  517. },
  518. searchForm: {
  519. page: 1,
  520. size: 10,
  521. schoolid: 1,
  522. classid: 0,
  523. care: 0,
  524. enabled: 0,
  525. control: 0,
  526. username: "",
  527. list: [],
  528. tital: 0
  529. },
  530. columns: [
  531. {
  532. title: "序号",
  533. align: "center",
  534. width: 70,
  535. render: (h, params) => {
  536. return h(
  537. "span",
  538. params.index +
  539. (this.searchForm.page - 1) * this.searchForm.size +
  540. 1
  541. );
  542. }
  543. },
  544. {
  545. title: "登录名",
  546. slot: "loginname",
  547. align: "center"
  548. },
  549. {
  550. title: "姓名",
  551. key: "username",
  552. align: "center",
  553. width: 140
  554. },
  555. {
  556. title: "班级",
  557. key: "classname",
  558. align: "center",
  559. width: 140
  560. },
  561. {
  562. title: "状态",
  563. slot: "enabled",
  564. width: 100,
  565. align: "center"
  566. },
  567. {
  568. title: "最后登录时间",
  569. key: "lasttime",
  570. align: "center",
  571. width: 180
  572. },
  573. {
  574. title: "操作",
  575. slot: "actionSlot",
  576. width: 240,
  577. align: "center"
  578. }
  579. ],
  580. classInfo: {},
  581. selectedModel: {},
  582. schoolInfo: {
  583. children: [],
  584. name: ""
  585. }
  586. };
  587. },
  588. computed: {
  589. powerParams() {
  590. return this.$store.getters.powerParams;
  591. }
  592. },
  593. created() {
  594. this.userInfo = JSON.parse(
  595. localStorage.getItem("xh_control_userInfo")
  596. ).content;
  597. this.init();
  598. this.searchList();
  599. },
  600. methods: {
  601. saveclassInfo() {
  602. this.$refs.classInfo.validate((valid) => {
  603. if (valid) {
  604. this.showLoading = true;
  605. class_edit({
  606. classid: this.classInfo.classid,
  607. classname: this.classInfo.classname,
  608. rversion: this.classInfo.rversion
  609. }).then((res) => {
  610. this.showLoading = false;
  611. if (res.code === 0) {
  612. if (this.classInfo.classid === this.curClass.id) {
  613. this.curClass.name = this.classInfo.classname;
  614. }
  615. this.classInfo.show = false;
  616. this.init();
  617. this.$Message.success(res.msg);
  618. } else {
  619. this.$Message.error(res.msg);
  620. }
  621. });
  622. }
  623. });
  624. },
  625. toSelectMenuItem(type) {
  626. this.removeMoreMenu();
  627. //type 1编辑 2删除
  628. if (type === 1) {
  629. this.classInfo = {
  630. show: true,
  631. classid: this.selectedModel.id,
  632. rversion: this.selectedModel.rversion,
  633. classname: this.selectedModel.name
  634. };
  635. } else {
  636. this.$Modal.confirm({
  637. title: "提示",
  638. content: "您确定删除【" + this.selectedModel.name + "】吗?",
  639. onOk: () => {
  640. class_delete({
  641. classid: this.selectedModel.id,
  642. rversion: this.selectedModel.rversion
  643. }).then((res) => {
  644. if (res.code === 0) {
  645. this.init();
  646. this.$Message.success(res.msg);
  647. } else {
  648. this.$Message.error(res.msg);
  649. }
  650. });
  651. },
  652. onCancel: () => {}
  653. });
  654. }
  655. },
  656. // 打开弹窗菜单
  657. toOpenMenu(Item, event) {
  658. this.selectClass(Item);
  659. if (!this.$refs.moreMenuRef) {
  660. return;
  661. }
  662. this.selectedModel = Item;
  663. let _clientX = event.clientX;
  664. let _clientY = event.clientY;
  665. this.$refs.moreMenuRef.style.display = `block`;
  666. this.$nextTick(() => {
  667. let _bodyHeight = document.body.clientHeight;
  668. let _domHeight = this.$refs.moreMenuRef.getBoundingClientRect().height;
  669. this.$refs.moreMenuRef.style.left = `${_clientX - 105}px`;
  670. if (_clientY + _domHeight > _bodyHeight) {
  671. this.$refs.moreMenuRef.style.top = `${_bodyHeight - _domHeight}px`;
  672. } else {
  673. this.$refs.moreMenuRef.style.top = `${_clientY}px`;
  674. }
  675. });
  676. },
  677. // 隐藏弹窗菜单
  678. removeMoreMenu() {
  679. if (!this.$refs.moreMenuRef) {
  680. return;
  681. }
  682. this.$refs.moreMenuRef.style.display = `none`;
  683. this.$refs.moreMenuRef.style.left = `-9999px`;
  684. this.$refs.moreMenuRef.style.top = `-9999px`;
  685. },
  686. classChange() {
  687. if (this.schoolInfo.children.length === 0) {
  688. return;
  689. }
  690. let classInfo = this.schoolInfo.children.filter(
  691. (v) => v.id === this.addInfo.classid
  692. )[0];
  693. this.addInfo.classname = classInfo.name;
  694. },
  695. download() {
  696. //下载模版
  697. let url = "../../../../doc/student.xls";
  698. const a = document.createElement("a"); // 创建a标签
  699. a.setAttribute("download", "学生信息模版"); // download属性
  700. a.setAttribute("href", url); // href链接
  701. a.click(); // 自执行点击事件
  702. },
  703. //确定导入
  704. ok_import() {
  705. if (!this.importInfo.file) {
  706. this.$Message.error("请选择上传文件");
  707. return;
  708. }
  709. this.wait_flag = true; //showLoading
  710. let that = this;
  711. user_import(this.form_data)
  712. .then((res) => {
  713. this.wait_flag = false;
  714. if (res.code == 0) {
  715. this.importInfo = {
  716. show: false,
  717. file: null
  718. };
  719. if (res.obj.code == 0) {
  720. this.$Message.success("导入成功");
  721. this.init();
  722. this.searchList();
  723. } else {
  724. this.exitInfo = {
  725. show: true,
  726. studentsExisted: res.obj.studentsExisted,
  727. usersExisted: res.obj.usersExisted
  728. };
  729. }
  730. } else {
  731. this.$Message.error(res.msg);
  732. }
  733. this.form_data = null;
  734. })
  735. .catch(() => {
  736. that.wait_flag = false;
  737. });
  738. },
  739. //导入
  740. userImport() {
  741. this.importInfo = {
  742. show: true,
  743. file: null
  744. };
  745. },
  746. // 上传文件
  747. handleUpload(file) {
  748. let str = file.name.split(".");
  749. let suffix = str[str.length - 1];
  750. suffix = suffix.toLowerCase();
  751. if (suffix === "xls" || suffix === "xlsx") {
  752. this.importInfo.file = file;
  753. this.import_img = true;
  754. this.form_data = new FormData();
  755. this.form_data.append("file", file);
  756. this.form_data.append("schoolid", this.powerParams.objectid);
  757. this.form_data.append("regionid", this.powerParams.objectid);
  758. } else {
  759. this.importInfo.file = null;
  760. this.$Message.error("请上传excel文件");
  761. }
  762. return false;
  763. },
  764. //导出
  765. userExport() {
  766. this.showLoading = true;
  767. user_export({
  768. rtype: this.powerParams.rtype,
  769. objectid: this.powerParams.objectid,
  770. schoolid: this.powerParams.objectid
  771. }).then((res) => {
  772. this.showLoading = false;
  773. if (res.code === 0) {
  774. exportToExcel(
  775. [
  776. {
  777. list: res.obj.map((item) => {
  778. return {
  779. 登录名: item.loginname,
  780. 姓名: item.username,
  781. 班级: item.classname,
  782. 状态: item.enabled === 1 ? "启用" : "禁用",
  783. 最后登录时间: item.lasttime || ""
  784. };
  785. }),
  786. name: this.curClass.name
  787. }
  788. ],
  789. this.curClass.name
  790. );
  791. } else {
  792. this.$Message.error(res.msg);
  793. }
  794. });
  795. },
  796. toAdd() {
  797. this.addInfo = {
  798. show: true,
  799. userid: null,
  800. usersex: 1,
  801. username: "",
  802. loginname: "",
  803. loginpwd: generateRandomString(),
  804. loginpwd1: "",
  805. classid: "",
  806. classname: "",
  807. schoolid: null,
  808. regionid: null,
  809. enabled: 1,
  810. studentno: "",
  811. userphone: "",
  812. cardid: ""
  813. };
  814. },
  815. saveAddInfo() {
  816. this.$refs.addForm.validate((valid) => {
  817. if (valid) {
  818. if (this.addInfo.userphone) {
  819. var filter = /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
  820. if (!filter.test(this.addInfo.userphone)) {
  821. this.$Message.error("手机号码格式不正确!");
  822. return;
  823. }
  824. }
  825. if (!this.addInfo.classid) {
  826. this.$Message.error("请选择班级!");
  827. return;
  828. }
  829. let form = {
  830. username: this.addInfo.username,
  831. loginname: this.addInfo.loginname,
  832. usersex: this.addInfo.usersex,
  833. loginpwd: this.addInfo.loginpwd,
  834. classid: this.addInfo.classid,
  835. classname: this.addInfo.classname,
  836. rtype: this.powerParams.rtype,
  837. objectid: this.powerParams.objectid,
  838. regionid: this.powerParams.objectid,
  839. schoolid: this.addInfo.schoolid || 1,
  840. enabled: this.addInfo.enabled,
  841. studentno: this.addInfo.studentno,
  842. userphone: this.addInfo.userphone,
  843. cardid: this.addInfo.cardid
  844. };
  845. let api = this.addInfo.userid ? user_edit : user_add;
  846. this.showLoading = true;
  847. api(form).then((res) => {
  848. this.showLoading = false;
  849. if (res.code === 0) {
  850. this.addInfo.show = false;
  851. this.$Message.success(res.msg);
  852. this.searchList();
  853. } else {
  854. this.$Message.error(res.msg);
  855. }
  856. });
  857. }
  858. });
  859. },
  860. toCare(row) {
  861. let api = row.care === 1 ? user_un_care : user_care;
  862. api({
  863. rtype: this.powerParams.rtype,
  864. objectid: this.powerParams.objectid,
  865. userid: row.userid,
  866. rversion: row.rversion
  867. }).then((res) => {
  868. if (res.code === 0) {
  869. this.searchList();
  870. this.$Message.success(res.msg);
  871. } else {
  872. this.$Message.error(res.msg);
  873. }
  874. });
  875. },
  876. toDel(row) {
  877. this.$Modal.confirm({
  878. title: "提示",
  879. content: "您确定删除【" + row.username + "】吗?",
  880. onOk: () => {
  881. user_delete({
  882. rtype: this.powerParams.rtype,
  883. objectid: this.powerParams.objectid,
  884. userid: row.userid,
  885. rversion: row.rversion
  886. }).then((res) => {
  887. if (res.code === 0) {
  888. this.searchList();
  889. this.$Message.success(res.msg);
  890. } else {
  891. this.$Message.error(res.msg);
  892. }
  893. });
  894. },
  895. onCancel: () => {}
  896. });
  897. },
  898. enabledChange(row) {
  899. let api = row.enabled === 1 ? user_enable : user_disabled;
  900. api({
  901. rtype: this.powerParams.rtype,
  902. objectid: this.powerParams.objectid,
  903. userid: row.userid,
  904. rversion: row.rversion
  905. }).then((data) => {
  906. this.searchList();
  907. if (data.code === 0) {
  908. this.$Message.success(data.msg);
  909. } else {
  910. this.$Message.error(data.msg);
  911. }
  912. });
  913. },
  914. selectClass(item) {
  915. this.curClass = item;
  916. this.searchList();
  917. },
  918. init() {
  919. this.showLoading = true;
  920. class_list({
  921. schoolid: this.powerParams.objectid
  922. }).then((res) => {
  923. this.showLoading = false;
  924. if (res.code === 0) {
  925. this.schoolInfo = res.obj;
  926. if (!this.curClass.id) {
  927. this.curClass = res.obj;
  928. }
  929. } else {
  930. this.$Message.error(res.msg);
  931. }
  932. });
  933. },
  934. // 搜索
  935. searchList() {
  936. this.searchForm.page = 1;
  937. this.getList();
  938. },
  939. // 页码改变
  940. pageChange(page) {
  941. this.searchForm.page = page;
  942. this.getList();
  943. },
  944. // 每页显示数量改变
  945. pageSizeChange(size) {
  946. this.searchForm.size = size;
  947. this.searchForm.page = 1;
  948. this.getList();
  949. },
  950. // 获取列表
  951. getList() {
  952. this.showLoading = true;
  953. user_list({
  954. rtype: this.powerParams.rtype,
  955. objectid: this.powerParams.objectid,
  956. schoolid: this.powerParams.objectid,
  957. page: this.searchForm.page,
  958. size: this.searchForm.size,
  959. classid: this.curClass.type === 2 ? this.curClass.id : null,
  960. care: this.searchForm.care,
  961. enabled: this.searchForm.enabled,
  962. control: this.searchForm.control,
  963. username: this.searchForm.username
  964. }).then((res) => {
  965. this.showLoading = false;
  966. if (res.code === 0) {
  967. this.searchForm.list = res.obj.data;
  968. this.searchForm.total = res.obj.total;
  969. } else {
  970. this.$Message.error(res.msg);
  971. }
  972. });
  973. }
  974. }
  975. };
  976. </script>
  977. <style lang="less" scoped>
  978. .main_root {
  979. width: calc(100% - 32px);
  980. height: calc(100% - 60px);
  981. background-color: transparent;
  982. border: none;
  983. display: flex;
  984. .schoolInfo {
  985. width: 200px;
  986. flex: none;
  987. border-radius: 15px;
  988. margin-right: 16px;
  989. height: 100%;
  990. overflow-y: auto;
  991. padding: 10px;
  992. background-color: white;
  993. .schoolname {
  994. font-size: 16px;
  995. line-height: 40px;
  996. font-weight: bold;
  997. text-align: center;
  998. cursor: pointer;
  999. }
  1000. .class_list {
  1001. div {
  1002. line-height: 30px;
  1003. height: 30px;
  1004. text-align: center;
  1005. cursor: pointer;
  1006. position: relative;
  1007. .icon-sandian {
  1008. display: none;
  1009. }
  1010. &:hover {
  1011. .icon-sandian {
  1012. display: block;
  1013. position: absolute;
  1014. top: 4px;
  1015. right: 6px;
  1016. font-size: 24px;
  1017. }
  1018. }
  1019. }
  1020. }
  1021. .active {
  1022. border-radius: 6px;
  1023. background: #dbeeff;
  1024. }
  1025. }
  1026. .user_list {
  1027. width: calc(100% - 216px);
  1028. height: 100%;
  1029. overflow-y: auto;
  1030. border-radius: 15px;
  1031. background-color: white;
  1032. }
  1033. }
  1034. .search_header {
  1035. display: flex;
  1036. justify-content: space-between;
  1037. align-items: center;
  1038. margin: 16px 16px;
  1039. .search_left {
  1040. display: flex;
  1041. justify-content: flex-start;
  1042. align-items: center;
  1043. .search_drop {
  1044. margin-right: 10px;
  1045. width: 150px;
  1046. }
  1047. }
  1048. }
  1049. .table_wrap {
  1050. .appName {
  1051. display: flex;
  1052. margin: 16px 0;
  1053. .app_logo {
  1054. flex: none;
  1055. width: 56px;
  1056. height: 56px;
  1057. border-radius: 20px;
  1058. border: 1px solid #e5e5e5;
  1059. background: #ffffff;
  1060. padding: 10px;
  1061. img {
  1062. width: 38px;
  1063. height: 38px;
  1064. object-fit: cover;
  1065. }
  1066. }
  1067. .app_comm {
  1068. flex: none;
  1069. width: 120px;
  1070. margin-left: 10px;
  1071. text-align: left;
  1072. div {
  1073. color: #339dff;
  1074. }
  1075. }
  1076. }
  1077. }
  1078. .modal_tip {
  1079. .files_list {
  1080. height: 30px;
  1081. line-height: 30px;
  1082. }
  1083. .import_tip {
  1084. height: 30px;
  1085. line-height: 30px;
  1086. text-align: center;
  1087. .theme_color {
  1088. color: #339dff;
  1089. cursor: pointer;
  1090. }
  1091. }
  1092. }
  1093. // 存在信息
  1094. .exit_modal {
  1095. /deep/ .ivu-modal {
  1096. .ivu-modal-content {
  1097. .exit {
  1098. div {
  1099. // margin-bottom: 10px;
  1100. font-size: 18px;
  1101. line-height: 40px;
  1102. }
  1103. }
  1104. .ivu-table {
  1105. -moz-user-select: none;
  1106. -khtml-user-select: none;
  1107. user-select: none;
  1108. }
  1109. div .ivu-table-header thead tr > th {
  1110. height: 40px;
  1111. }
  1112. .ivu-modal-footer {
  1113. display: none;
  1114. }
  1115. }
  1116. }
  1117. }
  1118. .more_menu {
  1119. width: 100px;
  1120. text-align: center;
  1121. background: #ffffff;
  1122. box-shadow: 0 8px 30px 0 #bcc9e380;
  1123. border-radius: 10px;
  1124. border: none;
  1125. .menu_group {
  1126. height: 35px;
  1127. line-height: 35px;
  1128. cursor: pointer;
  1129. &:hover {
  1130. background-color: #dbeeffcc;
  1131. }
  1132. }
  1133. }
  1134. </style>