index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. <template>
  2. <div class="app-container">
  3. <el-row>
  4. <el-col :span="24">
  5. <div class="cell">
  6. <div class="cell-title">
  7. <div class="title">用户管理</div>
  8. <div class="title-right">
  9. <el-button type="primary" @click="handler_download_excel">导出表单</el-button>
  10. <el-button type="warning" @click="add_user">新增用户</el-button>
  11. </div>
  12. </div>
  13. <div class="cell-body">
  14. <el-form :inline="true" :model="formInline" class="demo-form-inline">
  15. <el-form-item label="关键字:">
  16. <el-input v-model="formInline.user" placeholder="请输入姓名或身份证"></el-input>
  17. </el-form-item>
  18. <el-form-item>
  19. <el-button type="warning" @click="btn_search">查询</el-button>
  20. </el-form-item>
  21. <el-form-item label="">
  22. <el-select v-model="formInline.category" placeholder="类别" @change="btn_search"
  23. clearable>
  24. <el-option label="学生" value="学生"></el-option>
  25. <el-option label="教工" value="教工"></el-option>
  26. <el-option label="员工" value="员工"></el-option>
  27. </el-select>
  28. </el-form-item>
  29. </el-form>
  30. <el-table :data="tableData" height="510" style="width: 100%" :cell-style="cell_style"
  31. :header-cell-style="header_cell_style">
  32. <el-table-column label="序号" align="center" width="100">
  33. <template slot-scope="scope">
  34. <span>{{(pagination.currentPage - 1) * pagination.pageSize + scope.$index + 1}}</span>
  35. </template>
  36. </el-table-column>
  37. <el-table-column label="姓名" align="center" width="100">
  38. <template slot-scope="scope">
  39. <span>{{ scope.row.user_name }}</span>
  40. </template>
  41. </el-table-column>
  42. <el-table-column label="手机" align="center" width="180">
  43. <template slot-scope="scope">
  44. <span>{{ scope.row.phone }}</span>
  45. </template>
  46. </el-table-column>
  47. <el-table-column label="身份证" align="center">
  48. <template slot-scope="scope">
  49. <span>{{ scope.row.sfzh }}</span>
  50. </template>
  51. </el-table-column>
  52. <el-table-column label="类别" align="center" width="100">
  53. <template slot-scope="scope">
  54. <span>{{ scope.row.classfy }}</span>
  55. </template>
  56. </el-table-column>
  57. <el-table-column label="年级" align="center" width="100">
  58. <template slot-scope="scope">
  59. <span>{{ scope.row.bj }}</span>
  60. </template>
  61. </el-table-column>
  62. <el-table-column label="账户余额(元)" align="center" width="180">
  63. <template slot-scope="scope">
  64. <span>{{ scope.row.balance }}</span>
  65. </template>
  66. </el-table-column>
  67. <el-table-column label="备注" align="center">
  68. <template slot-scope="scope">
  69. <span>{{ scope.row.remark }}</span>
  70. </template>
  71. </el-table-column>
  72. <el-table-column label="操作" align="center">
  73. <template slot-scope="scope">
  74. <el-button size="mini" class="btn-table" @click="recharge(scope.$index, scope.row)">
  75. 充值</el-button>
  76. </template>
  77. </el-table-column>
  78. </el-table>
  79. <div class="pagination-table">
  80. <el-pagination @current-change="currentPageChange"
  81. :current-page.sync="pagination.currentPage" :page-size="pagination.pageSize"
  82. layout="prev, pager, next, jumper" :total="pagination.total">
  83. </el-pagination>
  84. </div>
  85. </div>
  86. </div>
  87. </el-col>
  88. </el-row>
  89. <!-- 新增用户对话框 -->
  90. <el-dialog title="新增用户" custom-class="add-user-dialog" :visible.sync="dialogAddUserVisible"
  91. :close-on-click-modal="false" :close-on-press-escape="false" @close="add_user_dialog_close">
  92. <el-form :model="addForm" ref="addUserForm" :rules="addFormRules">
  93. <el-form-item label="姓  名:" :label-width="formLabelWidth" :required="true" prop="user_name">
  94. <el-input v-model="addForm.user_name" autocomplete="off" maxlength="10" ref="username_focus">
  95. </el-input>
  96. </el-form-item>
  97. <el-form-item label="手  机:" :label-width="formLabelWidth" :required="true" prop="phone">
  98. <el-input v-model="addForm.phone" autocomplete="off" maxlength="11"></el-input>
  99. </el-form-item>
  100. <el-form-item label="身份证号:" :label-width="formLabelWidth" :required="true" prop="sfzh">
  101. <el-input v-model="addForm.sfzh" autocomplete="off" maxlength="18"></el-input>
  102. </el-form-item>
  103. <el-form-item label="类  别:" :label-width="formLabelWidth" :required="true" prop="classfy">
  104. <el-select v-model="addForm.classfy" placeholder="类别">
  105. <el-option label="学生" value="学生"></el-option>
  106. <el-option label="教工" value="教工"></el-option>
  107. <el-option label="员工" value="员工"></el-option>
  108. </el-select>
  109. </el-form-item>
  110. <el-form-item label="年  级:" :label-width="formLabelWidth" :required="true" prop="bj">
  111. <el-select v-model="addForm.bj" placeholder="年级">
  112. <el-option label="大一" value="大一"></el-option>
  113. <el-option label="大二" value="大二"></el-option>
  114. <el-option label="大三" value="大三"></el-option>
  115. <el-option label="大四" value="大四"></el-option>
  116. <el-option label="非学生" value="非学生"></el-option>
  117. </el-select>
  118. </el-form-item>
  119. <el-form-item label="备  注:" :label-width="formLabelWidth">
  120. <el-input type="textarea" resize="none" :rows="4" placeholder="请输入内容" v-model="addForm.remark"
  121. maxlength="100" show-word-limit></el-input>
  122. </el-form-item>
  123. </el-form>
  124. <div slot="footer" class="dialog-footer">
  125. <el-button @click="dialogAddUserVisible = false">取 消</el-button>
  126. <el-button type="primary" @click="handler_add_user">新 增</el-button>
  127. </div>
  128. </el-dialog>
  129. <!-- 充值对话框 -->
  130. <el-dialog title="充值" custom-class="chongzhi-dialog" :visible.sync="dialogChongzhiVisible"
  131. :close-on-click-modal="false" :close-on-press-escape="false" @close="dialog_close">
  132. <el-form :model="form" ref="chongzhiForm" :rules="chongzhiRules">
  133. <el-form-item label="充值账号:" :label-width="formLabelWidth">
  134. <div>{{form.sfzh}}</div>
  135. </el-form-item>
  136. <el-form-item label="姓  名:" :label-width="formLabelWidth">
  137. <div>{{form.user_name}}</div>
  138. </el-form-item>
  139. <el-form-item label="充值金额:" :label-width="formLabelWidth" :required="true" prop="amount">
  140. <el-input v-model="form.amount" autocomplete="off" maxlength="3" ref="amount_focus"></el-input>
  141. </el-form-item>
  142. <el-form-item label="备  注:" :label-width="formLabelWidth">
  143. <el-input type="textarea" resize="none" :rows="4" placeholder="请输入内容" v-model="form.desc"
  144. maxlength="100" show-word-limit></el-input>
  145. </el-form-item>
  146. </el-form>
  147. <div slot="footer" class="dialog-footer">
  148. <el-button @click="dialogChongzhiVisible = false">取 消</el-button>
  149. <el-button type="primary" @click="handler_chongzhi">确 定</el-button>
  150. </div>
  151. </el-dialog>
  152. </div>
  153. </template>
  154. <script>
  155. import {
  156. getUserList,
  157. addUser,
  158. chongzhi,
  159. downloadExcel
  160. } from '@/api/userMgr';
  161. export default {
  162. data() {
  163. var checkUserName = (rule, value, callback) => {
  164. if (!value) {
  165. return callback(new Error('请输入姓名'));
  166. }
  167. setTimeout(() => {
  168. var reg = /^[\u4E00-\u9FA5]{2,10}$/
  169. if (!reg.test(value)) {
  170. callback(new Error('必须为2-10个汉字!'));
  171. } else {
  172. callback();
  173. }
  174. }, 100);
  175. }
  176. var checkPhone = (rule, value, callback) => {
  177. if (!value) {
  178. return callback(new Error('请输入手机号'));
  179. }
  180. setTimeout(() => {
  181. var reg = /^1[3456789]\d{9}$/
  182. if (!reg.test(value)) {
  183. callback(new Error('手机号格式不对'));
  184. } else {
  185. callback();
  186. }
  187. }, 100);
  188. }
  189. var checkIdCard = (rule, value, callback) => {
  190. if (!value) {
  191. return callback(new Error('请输入身份证'));
  192. }
  193. setTimeout(() => {
  194. var reg =
  195. /^[1-9]\d{5}(18|19|([2]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
  196. if (!reg.test(value)) {
  197. callback(new Error('身份证不符合要求'));
  198. } else {
  199. callback();
  200. }
  201. }, 100);
  202. }
  203. var checkClassfy = (rule, value, callback) => {
  204. if (!value) {
  205. return callback(new Error('请选择类别'));
  206. }
  207. if (this.addForm.classfy == '学生' && this.addForm.bj == '非学生') {
  208. return callback(new Error('类型与年级不一致'));
  209. }
  210. if ((this.addForm.classfy == '教工' || this.addForm.classfy == '员工') && (this.addForm.bj == '大一' || this
  211. .addForm.bj == '大二' || this.addForm.bj == '大三' || this.addForm.bj == '大四')) {
  212. return callback(new Error('类型与年级不一致'));
  213. }
  214. callback();
  215. }
  216. var checkBj = (rule, value, callback) => {
  217. if (!value) {
  218. return callback(new Error('请选择年级'));
  219. }
  220. if (this.addForm.classfy == '学生' && this.addForm.bj == '非学生') {
  221. return callback(new Error('类型与年级不一致'));
  222. }
  223. if ((this.addForm.classfy == '教工' || this.addForm.classfy == '员工') && (this.addForm.bj == '大一' || this
  224. .addForm.bj == '大二' || this.addForm.bj == '大三' || this.addForm.bj == '大四')) {
  225. return callback(new Error('类型与年级不一致'));
  226. }
  227. callback();
  228. }
  229. var checkMoney = (rule, value, callback) => {
  230. if (!value) {
  231. return callback(new Error('金额不能为空'));
  232. }
  233. setTimeout(() => {
  234. var reg = /^([1-9]{1}\d*)$/
  235. if (!reg.test(value)) {
  236. callback(new Error('请输入正整数'));
  237. } else if (value < 1 || value > 200) {
  238. callback(new Error('范围在1-200'));
  239. } else {
  240. callback();
  241. }
  242. }, 100);
  243. }
  244. return {
  245. // 弹出对话框数据
  246. dialogChongzhiVisible: false,
  247. form: {
  248. id: '',
  249. sfzh: '',
  250. user_name: '',
  251. amount: '',
  252. remark: ''
  253. },
  254. chongzhiRules: {
  255. amount: [{
  256. validator: checkMoney
  257. }]
  258. },
  259. // 添加用户对话框数据
  260. dialogAddUserVisible: false,
  261. addForm: {
  262. user_name: '',
  263. phone: '',
  264. sfzh: '',
  265. classfy: '',
  266. bj: '',
  267. remark: ''
  268. },
  269. addFormRules: {
  270. user_name: [{
  271. validator: checkUserName
  272. }],
  273. phone: [{
  274. validator: checkPhone
  275. }],
  276. sfzh: [{
  277. validator: checkIdCard
  278. }],
  279. classfy: [{
  280. validator: checkClassfy
  281. }],
  282. bj: [{
  283. validator: checkBj
  284. }]
  285. },
  286. // 查询表单数据
  287. formInline: {
  288. user: '',
  289. category: ''
  290. },
  291. tableData: [],
  292. // 分页参数
  293. pagination: {
  294. currentPage: 1,
  295. pageSize: 8,
  296. total: 0
  297. },
  298. formLabelWidth: '120px',
  299. // 表格单元格样式
  300. cell_style: {
  301. color: '#1A202B',
  302. 'font-size': '16px',
  303. 'font-family': 'Microsoft YaHei-3970(82674968)'
  304. },
  305. // 表格头部样式
  306. header_cell_style: {
  307. background: '#E6ECFE',
  308. color: '#1A202B',
  309. 'font-size': '18px',
  310. 'font-family': 'Microsoft YaHei-3970(82674968)'
  311. }
  312. }
  313. },
  314. mounted() {
  315. document.getElementsByClassName("el-pagination__jump")[0].childNodes[0].nodeValue = "跳至";
  316. // 获取用户列表数据
  317. this.get_user_list('list')
  318. },
  319. methods: {
  320. /**
  321. * 下载Excel表格
  322. */
  323. handler_download_excel() {
  324. // 开始发送请求,获取配置数据
  325. downloadExcel().then((res) => {
  326. console.log(res);
  327. if (typeof res.code == 'undefined' || res.code == '') {
  328. this.$message.error('返回数据格式问题,code未获取到!')
  329. return
  330. }
  331. if (res.code == 200) {
  332. this.$message.success('下载成功!')
  333. let xls = 'http://demo.xwsyjjy.com' + res.downurl
  334. window.open(xls)
  335. } else {
  336. this.$message.error('未知异常!')
  337. }
  338. }).catch((err) => {
  339. // console.log(err);
  340. this.$message.error(err.message)
  341. })
  342. },
  343. /**
  344. * 充值
  345. */
  346. handler_chongzhi() {
  347. this.$refs["chongzhiForm"].validate(validate => {
  348. if (validate) {
  349. let params = {
  350. id: this.form.id,
  351. balance: this.form.amount
  352. }
  353. // 开始发送请求,获取配置数据
  354. chongzhi(params).then((res) => {
  355. // console.log(res);
  356. if (typeof res.code == 'undefined' || res.code == '') {
  357. this.$message.error('返回数据格式问题,code未获取到!')
  358. return
  359. }
  360. if (res.code == 200) {
  361. this.dialogChongzhiVisible = false
  362. this.$message.success('充值成功!')
  363. this.get_user_list('list')
  364. } else {
  365. this.$message.error('未知异常!')
  366. }
  367. }).catch((err) => {
  368. // console.log(err);
  369. this.$message.error(err.message)
  370. })
  371. } else {
  372. this.$message.error('验证不通过')
  373. return false
  374. }
  375. })
  376. },
  377. /**
  378. * 打开新增用户对话框
  379. */
  380. add_user() {
  381. this.dialogAddUserVisible = true
  382. setTimeout(() => {
  383. this.$nextTick(() => {
  384. this.$refs.username_focus.focus()
  385. })
  386. }, 100)
  387. },
  388. /**
  389. * 新增用户操作
  390. */
  391. handler_add_user() {
  392. this.$refs["addUserForm"].validate(validate => {
  393. console.log(typeof validate);
  394. console.log(validate);
  395. if (validate) {
  396. let params = {
  397. user_name: this.addForm.user_name,
  398. phone: this.addForm.phone,
  399. sfzh: this.addForm.sfzh,
  400. classfy: this.addForm.classfy,
  401. bj: this.addForm.bj,
  402. remark: this.addForm.remark
  403. }
  404. // 开始发送请求,获取配置数据
  405. addUser(params).then((res) => {
  406. console.log(res);
  407. if (typeof res.code == 'undefined' || res.code == '') {
  408. this.$message.error('返回数据格式问题,code未获取到!')
  409. return
  410. }
  411. if (res.code == 200) {
  412. this.dialogAddUserVisible = false
  413. this.$message.success('新增用户成功!')
  414. this.get_user_list('list')
  415. } else {
  416. this.$message.error('未知异常!')
  417. }
  418. }).catch((err) => {
  419. // console.log(err);
  420. this.$message.error(err.message)
  421. })
  422. } else {
  423. this.$message.error('验证不通过')
  424. return false
  425. }
  426. })
  427. },
  428. /**
  429. * 获取用户列表数据
  430. */
  431. get_user_list(param) {
  432. let params = {
  433. page: this.pagination.currentPage,
  434. rows: this.pagination.pageSize
  435. }
  436. if (param == 'search') {
  437. params.page = 1
  438. if (this.formInline.user !== '') {
  439. params.name_card = this.formInline.user
  440. }
  441. if (this.formInline.category !== '') {
  442. params.classfy = this.formInline.category
  443. }
  444. }
  445. // 开始发送请求,获取配置数据
  446. getUserList(params).then((res) => {
  447. // console.log(res.rows);
  448. if (typeof res.rows !== 'undefined' && res.rows !== '') {
  449. this.pagination.total = res.total
  450. this.tableData = []
  451. for (var i = 0; i < res.rows.length; i++) {
  452. this.tableData.push(res.rows[i])
  453. }
  454. } else {
  455. this.$message.warning('没有符合条件的数据!')
  456. }
  457. }).catch((err) => {
  458. // console.log(err);
  459. this.$message.error(err.message)
  460. })
  461. },
  462. /**
  463. * 查询
  464. */
  465. btn_search() {
  466. this.get_user_list('search')
  467. },
  468. /**
  469. * 充值对话框初始化
  470. * @param {Object} index
  471. * @param {Object} row
  472. */
  473. recharge(index, row) {
  474. // console.log(index, row);
  475. this.dialogChongzhiVisible = true
  476. this.form.id = row.id
  477. this.form.sfzh = row.sfzh
  478. this.form.user_name = row.user_name
  479. // 使金额输入框input_amount获得焦点
  480. setTimeout(() => {
  481. this.$nextTick(() => {
  482. this.$refs.amount_focus.focus()
  483. })
  484. }, 100)
  485. },
  486. /**
  487. * currentPage 改变时会触发
  488. * @param {Object} val
  489. */
  490. currentPageChange(val) {
  491. this.pagination.currentPage = val
  492. this.get_user_list('pages')
  493. },
  494. /**
  495. * 对话框关闭时清理数据
  496. */
  497. add_user_dialog_close() {
  498. this.addForm = {}
  499. },
  500. /**
  501. * 对话框关闭时清理数据
  502. */
  503. dialog_close() {
  504. this.form = {}
  505. }
  506. }
  507. }
  508. </script>
  509. <style lang="scss" scoped>
  510. .app-container {
  511. background-color: #EFF2F7;
  512. padding: 10px;
  513. .el-row {
  514. .el-col {
  515. padding: 10px;
  516. .cell {
  517. padding: 30px;
  518. border-radius: 10px;
  519. background-color: #FFFFFF;
  520. // box-shadow: 5px 5px 15px #979797;
  521. box-shadow: 0px 3px 21px 0px rgba(60, 108, 254, 0.16);
  522. .cell-title {
  523. display: flex;
  524. justify-content: space-between;
  525. align-items: center;
  526. margin-bottom: 30px;
  527. padding-bottom: 30px;
  528. border-bottom: 1px solid #CCCCCC;
  529. .title {
  530. font-size: 22px;
  531. font-family: Microsoft YaHei-3970(82674968);
  532. font-weight: bold;
  533. color: #1A202B;
  534. }
  535. .title-right {
  536. display: flex;
  537. justify-content: space-between;
  538. align-items: center;
  539. .el-button {
  540. width: 110px;
  541. height: 46px;
  542. background: #2B4CFE;
  543. font-size: 18px;
  544. color: #FFFFFF;
  545. font-family: Microsoft YaHei-3970(82674968);
  546. border-radius: 5px;
  547. }
  548. .el-button--warning {
  549. background: #F88A64;
  550. }
  551. }
  552. }
  553. .cell-body {
  554. .el-button--warning {
  555. background: #F88A64;
  556. }
  557. .btn-table {
  558. border-radius: 15px !important;
  559. border-color: #5488FE;
  560. color: #5488FE;
  561. }
  562. .pagination-table {
  563. display: flex;
  564. justify-content: flex-end;
  565. align-items: center;
  566. height: 30px;
  567. margin-top: 20px;
  568. padding-right: 100px;
  569. ::v-deep .el-pagination {
  570. display: flex;
  571. justify-content: flex-end;
  572. align-items: center;
  573. }
  574. ::v-deep .el-pagination ul {
  575. display: flex;
  576. }
  577. ::v-deep .el-pagination button,
  578. ::v-deep .el-pagination li {
  579. display: flex;
  580. justify-content: center;
  581. align-items: center;
  582. width: 50px;
  583. height: 36px;
  584. border: 1px solid #626262;
  585. border-radius: 3px;
  586. font-size: 14px;
  587. margin: 0 5px;
  588. }
  589. ::v-deep .el-pagination span {
  590. margin-left: 10px;
  591. }
  592. ::v-deep .el-pagination .el-pagination__jump {
  593. font-size: 16px;
  594. }
  595. ::v-deep .el-pagination .el-pagination__editor {
  596. width: 50px;
  597. height: 36px;
  598. margin: 0 5px;
  599. }
  600. ::v-deep .el-pagination .el-input__inner {
  601. width: 50px;
  602. height: 36px;
  603. border: 1px solid #626262;
  604. margin: -4px 0 0 0;
  605. }
  606. }
  607. }
  608. }
  609. }
  610. }
  611. ::v-deep .el-dialog {
  612. margin: 0 !important;
  613. width: 600px;
  614. height: 500px;
  615. background: #FFFFFF;
  616. box-shadow: 0px 0px 13px 0px rgba(0, 0, 0, 0.29);
  617. border-radius: 10px;
  618. position: absolute;
  619. top: 50%;
  620. left: 50%;
  621. transform: translate(-50%, -50%);
  622. .el-dialog__header {
  623. display: flex;
  624. align-items: center;
  625. width: 100%;
  626. height: 58px;
  627. padding: 30px;
  628. background: #E6EBFE;
  629. border-radius: 10px 10px 0px 0px;
  630. font-weight: bold;
  631. }
  632. .el-dialog__body {
  633. padding-bottom: 0;
  634. .el-form-item__label,
  635. .el-form-item__content {
  636. font-size: 16px;
  637. font-family: Microsoft YaHei-3970(82674968);
  638. color: #53575A;
  639. }
  640. .el-input__inner {
  641. width: 180px;
  642. }
  643. }
  644. .el-dialog__footer {
  645. padding-bottom: 0 !important;
  646. text-align: center;
  647. .el-button.el-button--default {
  648. width: 75px;
  649. height: 40px;
  650. border: 1px solid #2B4CFE;
  651. border-radius: 6px;
  652. font-size: 16px;
  653. font-family: Microsoft YaHei-3970(82674968);
  654. color: #2B4CFE;
  655. }
  656. .el-button.el-button--primary {
  657. width: 75px;
  658. height: 40px;
  659. background: #2B4CFE;
  660. border-radius: 6px;
  661. font-size: 16px;
  662. font-family: Microsoft YaHei-3970(82674968);
  663. color: #FFFFFF;
  664. margin-left: 60px;
  665. }
  666. }
  667. }
  668. }
  669. </style>
  670. <style>
  671. .add-user-dialog {
  672. height: 600px !important;
  673. }
  674. .chongzhi-dialog {
  675. height: 500px !important;
  676. }
  677. </style>