index.vue 20 KB

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