index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <template xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
  2. <div class="app-container">
  3. <div>
  4. <el-card>
  5. <div slot="header" class="clearfix">
  6. <b><span>用户管理</span></b>
  7. </div>
  8. <div class="filter-container">
  9. <el-button type="primary" size="small" style="round-clip: 10px" @click="insertEvent"
  10. :loading="loadButton">添加
  11. </el-button>
  12. </div>
  13. <div style="padding-top: 10px">
  14. <vxe-table
  15. ref="xTable"
  16. border
  17. export-config
  18. keep-source
  19. auto-resize
  20. resizable
  21. :edit-rules="rules"
  22. :loading="loading"
  23. :data="tableData"
  24. v-show="showTable"
  25. show-overflow
  26. highlight-current-row
  27. align="center"
  28. >
  29. <!--:edit-config="{trigger: 'manual', mode: 'row',autoClear:false,showStatus: true,icon:'none'}"-->
  30. <vxe-table-column title="用户基本信息" align="center">
  31. <vxe-table-column
  32. field="username"
  33. title="用户名"
  34. width="7%"
  35. align="center"
  36. />
  37. <!--:edit-render="{name: '$input', attrs: {type: 'text'}}"-->
  38. <!-- <vxe-table-column-->
  39. <!-- field="password"-->
  40. <!-- title="密码"-->
  41. <!-- width="12%"-->
  42. <!-- align="center"-->
  43. <!-- />-->
  44. <vxe-table-column
  45. field="mailbox"
  46. title="邮箱"
  47. width="12%"
  48. align="center"
  49. />
  50. <!--:edit-render="{name: '$input', attrs: {type: 'text'}}"-->
  51. <vxe-table-column
  52. field="name"
  53. title="姓名"
  54. width="7%"
  55. align="center"
  56. />
  57. <!--:edit-render="{name: '$input', attrs: {type: 'text'}}"-->
  58. <vxe-table-column
  59. field="status"
  60. title="状态"
  61. width="8%"
  62. align="center"
  63. :formatter="formatStatus"
  64. />
  65. <!--:edit-render="{name: '$select', options: userStatus }"-->
  66. <vxe-table-column title="操作" width="15%" align="center">
  67. <template v-slot="{ row }">
  68. <!--<template v-if="$refs.xTable.isActiveByRow(row)">-->
  69. <!--<el-button-->
  70. <!--type="success"-->
  71. <!--style="padding: 3px 4px 3px 4px;margin: 2px;"-->
  72. <!--size="mini"-->
  73. <!--icon="el-icon-edit"-->
  74. <!--@click="editSave(row)"-->
  75. <!--&gt;保存-->
  76. <!--</el-button>-->
  77. <!--<el-button-->
  78. <!--class="cancel-btn"-->
  79. <!--icon="el-icon-refresh"-->
  80. <!--type="warning"-->
  81. <!--style="padding: 3px 4px 3px 4px;margin: 2px;"-->
  82. <!--size="mini"-->
  83. <!--@click="cancelRowEvent(row)"-->
  84. <!--&gt;取消-->
  85. <!--</el-button>-->
  86. <!--</template>-->
  87. <!--<template v-else>-->
  88. <el-button
  89. :loading="loadButton"
  90. type="primary"
  91. style="padding: 3px 4px 3px 4px;margin: 2px;"
  92. size="mini "
  93. icon="el-icon-edit"
  94. @click="editRowEvent(row)"
  95. >编辑
  96. </el-button>
  97. <el-button
  98. :loading="loadButton"
  99. type="danger"
  100. style="padding: 3px 4px 3px 4px;margin: 2px;"
  101. size="mini "
  102. icon="el-icon-delete"
  103. @click="deleteRowEvent(row)"
  104. >删除
  105. </el-button>
  106. <!--</template>-->
  107. </template>
  108. </vxe-table-column>
  109. </vxe-table-column>
  110. </vxe-table>
  111. <vxe-modal
  112. ref="xModal"
  113. v-model="showEdit"
  114. :title="selectRow ? '编辑&保存' : '新增&保存'"
  115. width="800"
  116. resize
  117. destroy-on-close
  118. >
  119. <el-form
  120. :model="formData"
  121. :rules="rules"
  122. ref="ruleForm"
  123. label-width="100px"
  124. title-align="center"
  125. title-width="100"
  126. >
  127. <el-form-item label="用户名" prop="username" class="formItem" >
  128. <el-input v-model="formData.username" placeholder="填写用户名" clearable></el-input>
  129. </el-form-item>
  130. <el-form-item label="密码" prop="password" class="formItem" >
  131. <el-input type="password" v-model="formData.password" placeholder="填写密码" clearable></el-input>
  132. </el-form-item>
  133. <el-form-item label="姓名" prop="name" class="formItem" >
  134. <el-input v-model="formData.name" placeholder="填写姓名" clearable></el-input>
  135. </el-form-item>
  136. <el-form-item label="状态" prop="status" class="formItem" >
  137. <el-select v-model="formData.status" placeholder="请选择状态" size="medium">
  138. <el-option
  139. v-for="item in userStatus"
  140. :key="item.value"
  141. :value="item.value"
  142. :label="item.label"
  143. ></el-option>
  144. </el-select>
  145. </el-form-item>
  146. <el-form-item label="配置菜单" prop="menu" class="formItem" >
  147. <el-cascader
  148. v-model="formData.menu"
  149. :options="options"
  150. :props="props"
  151. collapse-tags
  152. />
  153. </el-form-item>
  154. <el-form-item align="center" span="24">
  155. <el-button status="primary" @click="editSave">保存</el-button>
  156. <el-button @click="cancelRowEvent">取消</el-button>
  157. </el-form-item>
  158. </el-form>
  159. </vxe-modal>
  160. </div>
  161. </el-card>
  162. </div>
  163. <!-- 删除提示框 -->
  164. <el-dialog :visible.sync="delVisible" title="提示" width="300px" center>
  165. <div class="del-dialog-cnt">删除不可恢复,是否确定删除?</div>
  166. <span slot="footer" class="dialog-footer">
  167. <el-button type="primary" @click="deleteCancel()">取 消</el-button>
  168. <el-button type="primary" @click="deleteInfo()">确 定</el-button>
  169. </span>
  170. </el-dialog>
  171. </div>
  172. </template>
  173. <script>
  174. export default {
  175. data() {
  176. let strTopShiftReg = /(\~(?=\!)|\!(?=\@)|\@(?=\#)|\#(?=\$)|\$(?=\%)|\%(?=\^)|\^(?=\&)|\&(?=\*)|\*(?=\()|\((?=\))|\)(?=\_)|\_(?=\+)|\+(?=\~)){3}/
  177. let strTopResverShiftReg = /(\+(?=\_)|\_(?=\))|\)(?=\()|\((?=\*)|\*(?=\&)|\&(?=\^)|\^(?=\%)|\%(?=\$)|\$(?=\#)|\#(?=\@)|\@(?=\!)|\!(?=\~)|\~(?=\+)){3}/
  178. //字母连续规则
  179. let strReg = /(a(?=b)|b(?=c)|c(?=d)|d(?=e)|e(?=f)|f(?=g)|g(?=h)|h(?=i)|i(?=j)|j(?=k)|k(?=l)|l(?=m)|m(?=n)|n(?=o)|o(?=p)|p(?=q)|q(?=r)|r(?=s)|s(?=t)|t(?=u)|u(?=v)|v(?=w)|w(?=x)|x(?=y)|y(?=z)|z(?=a)){3}[a-z]/i
  180. let strResverReg = /(a(?=z)|z(?=y)|y(?=x)|x(?=w)|w(?=v)|v(?=u)|u(?=t)|t(?=s)|s(?=r)|r(?=q)|q(?=p)|p(?=o)|o(?=n)|n(?=m)|m(?=l)|l(?=k)|k(?=j)|j(?=i)|i(?=h)|h(?=g)|g(?=f)|f(?=e)|e(?=d)|d(?=c)|c(?=b)|b(?=a)){3}[a-z]/i
  181. //数字连续规则
  182. let numReg = /(\`(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)|0(?=\-)|\-(?=\=)|\=(?=\`)){3}/
  183. let numResverReg = /(\=(?=\-)|\-(?=0)|0(?=9)|9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=\`)|\`(?=\=)){3}/
  184. //键盘字母横向连续规则
  185. let keyboardHorizontalReg = /(q(?=w)|w(?=e)|e(?=r)|r(?=t)|t(?=y)|y(?=u)|u(?=i)|i(?=o)|o(?=p)|p(?=q)|a(?=s)|s(?=d)|d(?=f)|f(?=g)|g(?=h)|h(?=j)|j(?=k)|k(?=l)|l(?=a)|z(?=x)|x(?=c)|c(?=v)|v(?=b)|b(?=n)|n(?=m)|m(?=z)){3}[a-z]/i
  186. let keyboardHorizontalResverReg = /(p(?=o)|o(?=i)|i(?=u)|u(?=y)|y(?=t)|t(?=r)|r(?=e)|e(?=w)|w(?=q)|q(?=p)|l(?=k)|k(?=j)|j(?=h)|h(?=g)|g(?=f)|f(?=d)|d(?=s)|s(?=a)|a(?=l)|m(?=n)|n(?=b)|b(?=v)|v(?=c)|c(?=x)|x(?=z)|z(?=m)){3}[a-z]/i
  187. //多个相同字母、数字规则
  188. let sameReg = /([0-9a-zA-Z])\1{3}/
  189. let keyboardSlopeArr = ["1qaz", "2wsx", "3edc", "4rfv", "5tgb", "6yhn", "7ujm", "8ik,", "9ol.", "0p;/", "/;p0", ".lo9", ",ki8", "mju7", "nhy6", "bgt5", "vfr4", "cde3", "xsw2", "zaq1", "4esz", "5rdx", "6tfc", "7ygv", "8uhb", "9ijn", "0okm", "-pl,", "=[;.", ".;[=", ",lp-", "mko0", "nji9", "bhu8", "vgy7", "cft6", "xdr5", "zse4"]
  190. let keyboardSlopeShiftArr = ["!qaz", "@wsx", "#edc","$rfv", "%tgb", "^yhn", "&ujm", "*ik<", "(ol>", ")p:?", "?:p)", ">lo(", "<ki*", "mju&", "nhy^", "bgt%", "vfr$", "cde#", "xsw@", "zaq!", "$esz", "%rdx", "^tfc", "&ygv", "*uhb", "(ijn", ")okm", "_pl<", "+{:>", ">:{+", "<lp_", "mko)", "nji(", "bhu*", "vgy&", "cft^", "xdr%", "zse$"]
  191. const checkName = ({rule, value, callback}) => {
  192. var username = this.formData.username
  193. var s6 = this.tableDatas
  194. if (username == null || username === '') {
  195. return Promise.reject(new Error('请填写用户名'))
  196. }
  197. for (let i = 0; i < s6.length; i++) {
  198. if (this.id == '' || this.id == undefined) {
  199. // 新增
  200. if ((username == s6[i].username)) {
  201. return Promise.reject(new Error('用户名不能重复'))
  202. }
  203. } else {
  204. // 修改
  205. if (this.id != s6[i].id) {
  206. if ((username == s6[i].username)) {
  207. return Promise.reject(new Error('用户名不能重复'))
  208. }
  209. }
  210. }
  211. }
  212. return Promise.resolve()
  213. }
  214. const checkpassword = (rule, value, callback) => {
  215. var password = this.formData.password
  216. if (this.fileUploadNodeShowSysValue==0){
  217. if (sameReg.test(password)) {
  218. return Promise.reject(new Error('密码不能含有连续4位相同的数字或字母'))
  219. } else if (strResverReg.test(password)) {
  220. return Promise.reject(new Error('密码不能含有4位连续的字母'))
  221. } else if (strReg.test(password)) {
  222. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字符'))
  223. } else if (numReg.test(password)) {
  224. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字符'))
  225. } else if (numResverReg.test(password)) {
  226. return Promise.reject(new Error('密码不能含有4位连续的数字'))
  227. } else if (keyboardHorizontalReg.test(password)) {
  228. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字母'))
  229. } else if (keyboardHorizontalResverReg.test(password)) {
  230. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字母'))
  231. } else if (keyboardSlopeArr.some(v => password.toLowerCase().indexOf(v) > -1)) {
  232. return Promise.reject(new Error('密码不能含有4位键盘斜向方向连续的字符'))
  233. }else if (keyboardSlopeShiftArr.some(v => password.toLowerCase().indexOf(v) > -1)) {
  234. return Promise.reject(new Error('密码不能含有4位键盘斜向方向连续的字符'))
  235. }else if (strTopShiftReg.test(password)) {
  236. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字符'))
  237. }else if (strTopResverShiftReg.test(password)) {
  238. return Promise.reject(new Error('密码不能含有4位键盘横向方向连续的字符'))
  239. }
  240. }
  241. return Promise.resolve()
  242. }
  243. return {
  244. fileUploadNodeShowSysValue: '1',
  245. id: '',
  246. tableDatas: [],
  247. elStations: [],
  248. elStation: '',
  249. total: 0,
  250. pageSize: 5,
  251. currentPage: 1,
  252. loadButton: false,
  253. rowId: '',
  254. showTable: true,
  255. tableData: [],
  256. delVisible: false,
  257. loading: false,
  258. // 是否为编辑
  259. isEdit: false,
  260. pvRotationMode: [],
  261. userStatus: [{value: "0", label: "正常"}, {value: "2", label: "禁用"}],
  262. // 表单验证规则
  263. rules: {
  264. username: [
  265. {required: true, validator: checkName},
  266. {message: '输入过长', max: 15}
  267. ],
  268. password: [
  269. {required: true, message: '请填写密码', validator: checkpassword},
  270. {
  271. pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{7,10}/,
  272. message: '由8位数字、字母大小写及特殊符号组成'
  273. }
  274. ],
  275. name:[{required: true, message: '请填写姓名', trigger: 'blur'}],
  276. status:[{required: true, message: '请选择状态', trigger: 'change'}]
  277. },
  278. formData:{},
  279. showEdit:false,
  280. selectRow:false,
  281. props: { multiple: true },
  282. options:[],
  283. childrenOption:[]
  284. }
  285. },
  286. created() {
  287. // this.getParameterBySysKey()
  288. this.getAll()
  289. // this.getAllMenu()
  290. },
  291. methods: {
  292. // getParameterBySysKey(){
  293. // this.$axios.get('/sysParameter/sysParameterKey/FILE_UPLOAD_NODE_SHOW').then(res => {
  294. // this.fileUploadNodeShowSysValue = res.data.sysValue
  295. // })
  296. // },
  297. getAll() {
  298. this.loading = true
  299. this.$axios.get('/sysUserController/getAll').then((res) => {
  300. this.tableData = res.data
  301. if (res.data == null) {
  302. this.showTable = false
  303. } else {
  304. this.showTable = true
  305. }
  306. this.loading = false
  307. }).catch((error) => {
  308. this.$message.error('获取用户信息出错' + error)
  309. })
  310. },
  311. // getAllMenu(){
  312. // this.$axios.get('/sysMenu').then(res => {
  313. // // console.log(res.data)
  314. // var data = res.data
  315. // var option = [{value:9001,label:'后台管理', disabled: true}]
  316. // var option9000=[{value:9000,label:'统计查询', disabled: true}]
  317. // for(var i=0;i<data.length;i++){
  318. // var children = []
  319. // if(data[i].children.length>0){
  320. // for (var j =0;j<data[i].children.length;j++) {
  321. // if(data[i].children[j].id ==1){
  322. // children.push({
  323. // id: data[i].children[j].id,
  324. // fId:58,
  325. // value:data[i].children[j].id,
  326. // label: data[i].children[j].title,
  327. // path: data[i].children[j].path,
  328. // itemPath: data[i].children[j].itemPath,
  329. // url: data[i].children[j].url
  330. // })
  331. // this.childrenOption.push({
  332. // id: data[i].children[j].id,
  333. // fId:58,
  334. // value:data[i].children[j].id,
  335. // label: data[i].children[j].title,
  336. // path: data[i].children[j].path,
  337. // itemPath: data[i].children[j].itemPath,
  338. // url: data[i].children[j].url
  339. // })
  340. // }else{
  341. // children.push({
  342. // id: data[i].children[j].id,
  343. // fId:data[i].id,
  344. // value:data[i].children[j].id,
  345. // label: data[i].children[j].title,
  346. // path: data[i].children[j].path,
  347. // itemPath: data[i].children[j].itemPath,
  348. // url: data[i].children[j].url
  349. // })
  350. // this.childrenOption.push({
  351. // id: data[i].children[j].id,
  352. // fId:data[i].id,
  353. // value:data[i].children[j].id,
  354. // label: data[i].children[j].title,
  355. // path: data[i].children[j].path,
  356. // itemPath: data[i].children[j].itemPath,
  357. // url: data[i].children[j].url
  358. // })
  359. // }
  360. //
  361. // }
  362. // }
  363. // if(data[i].url == '9000'){
  364. // option9000.push({
  365. // id: data[i].id,
  366. // value:data[i].id,
  367. // label: data[i].title,
  368. // itemPath: data[i].itemPath,
  369. // url: data[i].url,
  370. // children:children
  371. // })
  372. // }else{
  373. // option.push({
  374. // id: data[i].id,
  375. // value:data[i].id,
  376. // label: data[i].title,
  377. // itemPath: data[i].itemPath,
  378. // url: data[i].url,
  379. // children:children
  380. // })
  381. // }
  382. // }
  383. // this.options = option.concat(option9000)
  384. // // console.log(this.childrenOption)
  385. // })
  386. // },
  387. insertEvent(row) {
  388. this.id = ''
  389. this.showTable = true
  390. this.isEdit = false
  391. // this.loadButton = true
  392. this.showEdit = true
  393. this.selectRow = false
  394. this.formData={}
  395. // this.$refs.xTable.insert().then(({row}) => this.$refs.xTable.setActiveRow(row))
  396. },
  397. editRowEvent(row) {
  398. this.id = row.id
  399. this.isEdit = true
  400. // this.loadButton = true
  401. this.showEdit = true
  402. this.selectRow = true
  403. this.formData = row
  404. this.formData.menu = this.formatMenu(this.formData.menu)
  405. // this.$refs.xTable.setActiveRow(row)
  406. },
  407. editSave() {
  408. this.$refs["ruleForm"].validate(valid => {
  409. if (valid) {
  410. var menu = []
  411. if(this.formData.menu != null){
  412. for(var i=0;i<this.formData.menu.length;i++){
  413. if(menu.find(value=>value == this.formData.menu[i][0])){
  414. menu.push(this.formData.menu[i][1])
  415. }else{
  416. menu.push(this.formData.menu[i][0])
  417. menu.push(this.formData.menu[i][1])
  418. }
  419. }
  420. // console.log(this.formData.menu)
  421. this.formData.menu = menu.toString()
  422. }else{
  423. this.formData.menu = ''
  424. }
  425. if (this.isEdit) {
  426. // 编辑保存
  427. this.$axios.put('/sysUser/', this.formData).then(res => {
  428. this.$message({
  429. message: '修改成功',
  430. type: 'success'
  431. })
  432. this.loadButton = false
  433. this.getAll()
  434. }).catch((error) => {
  435. // this.$refs.xTable.setActiveRow(row)
  436. this.$message.error('修改用户出错' + error)
  437. })
  438. } else {
  439. // 新增保存
  440. this.formData.stationCode = this.elStation
  441. console.log(this.formData)
  442. this.$axios.post('/sysUser/', this.formData).then(res => {
  443. this.$message({
  444. message: '保存成功',
  445. type: 'success'
  446. })
  447. this.loadButton = false
  448. this.getAll()
  449. }).catch((error) => {
  450. this.$message.error('修改用户出错' + error)
  451. })
  452. }
  453. this.showEdit = false
  454. this.selectRow = false
  455. }
  456. })
  457. },
  458. cancelRowEvent(row) {
  459. // const xTable = this.$refs.xTable
  460. this.$refs.xModal.close()
  461. this.loadButton = false
  462. // xTable.clearActived().then(() => {
  463. // // 还原行数据
  464. // if (this.isEdit) {
  465. // // 编辑
  466. // xTable.revertData(row)
  467. // } else {
  468. // // 新增
  469. // xTable.remove(row)
  470. // }
  471. // this.loadButton = false
  472. // })
  473. },
  474. // 删除场站信息
  475. deleteRowEvent(row) {
  476. this.rowId = row.id
  477. this.delVisible = true
  478. },
  479. deleteCancel() {
  480. this.delVisible = false
  481. },
  482. deleteInfo() {
  483. this.$axios.delete('/sysUser/' + this.rowId).then(res => {
  484. this.$message({
  485. message: '删除成功',
  486. type: 'success'
  487. })
  488. this.delVisible = false
  489. this.getAll()
  490. }).catch((error) => {
  491. this.$message.error('删除用户出错' + error)
  492. })
  493. },
  494. formatStatus({ cellValue }){
  495. const item = this.userStatus.find(item => item.value === cellValue)
  496. return item ? item.label : ''
  497. },
  498. formatMenu(menu){
  499. if(menu === null){
  500. return null
  501. }else{
  502. var data = menu.split(",")
  503. var menuArr = []
  504. for (var i=0;i<data.length;i++){
  505. for(var j=0;j<this.childrenOption.length;j++){
  506. if(this.childrenOption[j].id == data[i]){
  507. menuArr.push([this.childrenOption[j].fId,this.childrenOption[j].id])
  508. }
  509. }
  510. }
  511. return menuArr
  512. }
  513. }
  514. }
  515. }
  516. </script>
  517. <style scoped>
  518. .my_table_insert .vxe-body--row.is--new {
  519. background-color: #f1fdf1;
  520. }
  521. .formItem{
  522. width: 45%;
  523. display: inline-block;
  524. }
  525. /*/deep/*/
  526. /*.vxe-input--inner{*/
  527. /* width: auto;*/
  528. /*}*/
  529. </style>