user.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="20">
  4. <el-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4">
  5. <div class="head-container">
  6. <el-input
  7. v-model="filterText"
  8. placeholder="输入部门名称搜索"
  9. prefix-icon="el-icon-search"
  10. class="filter-item"
  11. style="margin-bottom: 20px"
  12. size="small"
  13. />
  14. </div>
  15. <el-tree
  16. :data="deptData"
  17. :props="deptTreeProps"
  18. :expand-on-click-node="false"
  19. default-expand-all
  20. @node-click="handleNodeClick"
  21. />
  22. </el-col>
  23. <el-col :xs="24" :sm="24" :md="20" :lg="20" :xl="20">
  24. <!-- 查询和其他操作 -->
  25. <div class="filter-container">
  26. <el-input
  27. v-model="query.userName"
  28. clearable
  29. size="small"
  30. class="filter-item"
  31. style="width: 200px;"
  32. placeholder="请输入用户名"
  33. @keyup.enter.native="handleFind"
  34. />
  35. <el-button class="filter-item" type="primary" icon="el-icon-search" size="small" @click="handleFind">搜索
  36. </el-button>
  37. <el-button class="filter-item" type="primary" icon="el-icon-refresh" size="small" @click="handleReset">重置
  38. </el-button>
  39. <el-button class="filter-item" type="primary" size="small" icon="el-icon-plus" @click="handleAdd">添加
  40. </el-button>
  41. </div>
  42. <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  43. <el-table-column label="序号" width="60" align="center">
  44. <template slot-scope="scope">
  45. <span>{{ scope.$index + 1 }}</span>
  46. </template>
  47. </el-table-column>
  48. <el-table-column label="用户名" align="center">
  49. <template slot-scope="scope">
  50. <span>{{ scope.row.username }}</span>
  51. </template>
  52. </el-table-column>
  53. <el-table-column label="手机号" align="center">
  54. <template slot-scope="scope">
  55. <span>{{ scope.row.phone }}</span>
  56. </template>
  57. </el-table-column>
  58. <el-table-column label="邮箱" width="180" align="center">
  59. <template slot-scope="scope">
  60. <span>{{ scope.row.email }}</span>
  61. </template>
  62. </el-table-column>
  63. <el-table-column label="部门" align="center">
  64. <template slot-scope="scope">
  65. <div>{{ scope.row.deptName }}</div>
  66. </template>
  67. </el-table-column>
  68. <el-table-column label="状态" align="center">
  69. <template slot-scope="scope">
  70. <div v-for="item in dicts" :key="item.id">
  71. <el-tag v-if="scope.row.lockFlag.toString() == item.itemValue" :type="scope.row.lockFlag ? '' : 'info'">{{
  72. item.itemText }}
  73. </el-tag>
  74. </div>
  75. </template>
  76. </el-table-column>
  77. <el-table-column label="操作" fixed="right" min-width="150" align="center">
  78. <template slot-scope="scope">
  79. <!--<el-button @click="handRest(scope.row)" type="warning" size="small">重置密码</el-button>-->
  80. <el-button size="small" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
  81. <el-button size="small" icon="el-icon-delete" type="danger" @click="handleDelete(scope.row)">删除
  82. </el-button>
  83. </template>
  84. </el-table-column>
  85. </el-table>
  86. <!--分页-->
  87. <div class="pagination">
  88. <el-pagination
  89. :current-page.sync="currentPage"
  90. :page-size="pageSize"
  91. layout="total, prev, pager, next, jumper"
  92. :total="total"
  93. background
  94. @current-change="handleCurrentChange"
  95. />
  96. </div>
  97. <!-- 添加或修改对话框 -->
  98. <el-dialog :title="operation?'新增用户':'编辑用户'" :visible.sync="dialogFormVisible" center>
  99. <el-form :model="dataForm" :rules="rules2" label-width="80px" size="small" label-position="right">
  100. <el-form-item label="用户名" :label-width="formLabelWidth" prop="username" required>
  101. <el-input v-model="dataForm.username" auto-complete="off" placeholder="请输入用户名" />
  102. </el-form-item>
  103. <el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
  104. <el-input v-model="dataForm.email" auto-complete="off" placeholder="请输入邮箱" />
  105. </el-form-item>
  106. <el-form-item label="手机" :label-width="formLabelWidth" prop="phone">
  107. <el-input v-model="dataForm.phone" auto-complete="off" placeholder="请输入手机" />
  108. </el-form-item>
  109. <el-form-item label="部门" :label-width="formLabelWidth">
  110. <popup-tree-input
  111. :data="deptData"
  112. :props="deptTreeProps"
  113. :prop="dataForm.deptName"
  114. :node-key="dataForm.deptId"
  115. :current-change-handle="deptTreeCurrentChangeHandle"
  116. />
  117. </el-form-item>
  118. <el-form-item label="角色" prop="userRoles" label-width="120px">
  119. <el-select v-model="dataForm.roleList" multiple placeholder="请选择" style="width: 100%;">
  120. <el-option
  121. v-for="item in roles"
  122. :key="item.id"
  123. :label="item.roleName"
  124. :value="item.roleId"
  125. />
  126. </el-select>
  127. </el-form-item>
  128. <el-form-item label="状态" prop="lockFlag" label-width="120px">
  129. <el-switch
  130. v-model="dataForm.lockFlag"
  131. active-color="#13ce66"
  132. inactive-color="#ff4949"
  133. active-text="正常"
  134. active-value="0"
  135. inactive-text="锁定"
  136. inactive-value="9"
  137. />
  138. </el-form-item>
  139. </el-form>
  140. <div slot="footer" class="dialog-footer">
  141. <el-button @click="dialogFormVisible = false">取 消</el-button>
  142. <el-button type="primary" @click="submitForm">确 定</el-button>
  143. </div>
  144. </el-dialog>
  145. </el-col>
  146. </el-row>
  147. </div>
  148. </template>
  149. <script>
  150. import { addUser, getUserList, editUser, deleteUser, restPass, registerUser } from '@/api/user'
  151. import { getRoleList } from '@/api/roles'
  152. import { getDept } from '@/api/dept'
  153. import PopupTreeInput from '@/components/PopupTreeInput'
  154. import initDict from '@/mixins/initDict'
  155. export default {
  156. components: {
  157. PopupTreeInput
  158. },
  159. mixins: [initDict],
  160. data() {
  161. // 验证手机号是否合法
  162. const checkTel = (rule, value, callback) => {
  163. if (value === '') {
  164. callback(new Error('请输入手机号码'))
  165. } else if (!this.checkMobile(value)) {
  166. callback(new Error('手机号码不合法'))
  167. } else {
  168. callback()
  169. }
  170. }
  171. return {
  172. // 用户列表
  173. tableData: [],
  174. roles: [], // 角色列表
  175. jobs: [], // 岗位列表
  176. operation: false, // true:新增, false:编辑
  177. currentPage: 1,
  178. pageSize: 10,
  179. total: 0, // 总数量
  180. deptId: '',
  181. dialogFormVisible: false, // 控制弹出框
  182. formLabelWidth: '120px',
  183. query: {
  184. userName: ''
  185. },
  186. dataForm: {
  187. username: '',
  188. avatar: '',
  189. deptId: '',
  190. deptName: '',
  191. email: 'lihaodongmail@163.com',
  192. phone: '17521296869',
  193. lockFlag: '' + 0,
  194. roleList: []
  195. },
  196. deptData: [],
  197. deptTreeProps: {
  198. label: 'name',
  199. children: 'children'
  200. },
  201. value5: '100',
  202. filterText: '',
  203. loading: false,
  204. jobName: '',
  205. rules2: {
  206. username: [{ required: true, message: '请输入用户名', trigger: 'blur' }, {
  207. pattern: /^[a-zA-Z0-9_]{4,8}$/,
  208. message: '以字母开头,长度在4-8之间, 只能包含字符、数字和下划线'
  209. }],
  210. phone: [{ required: true, message: '请输入手机号', trigger: 'blur' }, { validator: checkTel, trigger: 'change' }],
  211. email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }, {
  212. pattern: /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/, message: '输入邮箱不合法'
  213. }]
  214. }
  215. }
  216. },
  217. created() {
  218. this.adminList()
  219. this.findUserRoles()
  220. this.findDeptTree()
  221. // 加载数据字典
  222. this.getDict('用户状态')
  223. },
  224. methods: {
  225. // 加载用户角色信息
  226. findUserRoles: function() {
  227. const params = new URLSearchParams()
  228. params.append('roleName', '')
  229. getRoleList(params).then((res) => {
  230. this.roles = res.data.data
  231. })
  232. },
  233. // 加载部门列表
  234. findDeptTree: function() {
  235. getDept().then((res) => {
  236. this.deptData = res.data.data
  237. })
  238. },
  239. // 部门菜单树选中
  240. deptTreeCurrentChangeHandle(data) {
  241. this.dataForm.deptId = data.deptId
  242. this.dataForm.deptName = data.name
  243. },
  244. // 加载用户列表
  245. adminList: function() {
  246. this.loading = true
  247. const params = new URLSearchParams()
  248. params.append('current', this.currentPage)
  249. params.append('size', this.pageSize)
  250. params.append('deptId', this.deptId)
  251. params.append('username', this.query.userName)
  252. getUserList(params).then(response => {
  253. this.loading = false
  254. this.tableData = response.data.data.records
  255. this.total = response.data.data.total
  256. })
  257. },
  258. handleFind: function() {
  259. this.adminList()
  260. },
  261. handleReset: function() {
  262. this.query = {
  263. userName: ''
  264. }
  265. this.adminList()
  266. },
  267. // 添加
  268. handleAdd: function() {
  269. this.dialogFormVisible = true
  270. this.operation = true
  271. this.dataForm = {
  272. username: '',
  273. deptId: '',
  274. deptName: '',
  275. jobId: '',
  276. email: 'lihaodongmail@163.com',
  277. phone: '17521296869',
  278. lockFlag: '' + 0,
  279. roleList: []
  280. }
  281. },
  282. // 编辑
  283. handleEdit: function(row) {
  284. this.dialogFormVisible = true
  285. this.operation = false
  286. // this.dataForm = row
  287. this.dataForm = Object.assign({}, row)
  288. this.dataForm.jobId = row.jobId
  289. // this.getJobs(this.dataForm.jobId)
  290. // this.getJobs(row.jobId)
  291. // 设置选择的角色列表
  292. const userRoles = []
  293. for (let i = 0, len = row.roleList.length; i < len; i++) {
  294. userRoles.push(row.roleList[i].roleId)
  295. }
  296. this.dataForm.roleList = userRoles
  297. },
  298. // 密码重置 todo
  299. handRest: function(row) {
  300. const that = this
  301. this.$confirm('此操作将会将该用户密码重置, 是否继续?', '提示', {
  302. confirmButtonText: '确定',
  303. cancelButtonText: '取消',
  304. type: 'warning'
  305. })
  306. .then(() => {
  307. restPass(row.userId).then(response => {
  308. if (response.status === 200) {
  309. that.$message({
  310. type: 'success',
  311. message: '重置密码成功'
  312. })
  313. } else {
  314. that.$message({
  315. type: 'error',
  316. message: response.data.msg
  317. })
  318. }
  319. })
  320. })
  321. .catch(() => {
  322. this.$message({
  323. type: 'info',
  324. message: '已取消删除'
  325. })
  326. })
  327. },
  328. // 删除用户
  329. handleDelete: function(row) {
  330. const that = this
  331. this.$confirm('此操作将该管理员删除, 是否继续?', '提示', {
  332. confirmButtonText: '确定',
  333. cancelButtonText: '取消',
  334. type: 'warning'
  335. })
  336. .then(() => {
  337. deleteUser(row.userId).then(response => {
  338. if (response.status === 200) {
  339. this.$message({
  340. type: 'success',
  341. message: '操作成功'
  342. })
  343. that.adminList()
  344. } else {
  345. this.$message({
  346. type: 'error',
  347. message: response.data.msg
  348. })
  349. }
  350. })
  351. })
  352. .catch(() => {
  353. this.$message({
  354. type: 'info',
  355. message: '已取消删除'
  356. })
  357. })
  358. },
  359. handleCurrentChange: function(val) {
  360. this.currentPage = val
  361. this.adminList()
  362. },
  363. handleNodeClick(data) {
  364. this.deptId = data.deptId === '' ? '' : data.deptId
  365. this.adminList()
  366. },
  367. submitForm: function() {
  368. const userRoles = []
  369. for (let i = 0, len = this.dataForm.roleList.length; i < len; i++) {
  370. userRoles.push(this.dataForm.roleList[i])
  371. }
  372. this.dataForm.roleList = userRoles
  373. console.log(this.dataForm)
  374. debugger
  375. if (!this.operation) {
  376. // 编辑用户
  377. editUser(this.dataForm).then(response => {
  378. if (response.status === 200) {
  379. this.$message({
  380. type: 'success',
  381. message: '操作成功'
  382. })
  383. this.dialogFormVisible = false
  384. this.adminList()
  385. } else {
  386. this.$message({
  387. type: 'error',
  388. message: response.data.msg
  389. })
  390. }
  391. })
  392. } else {
  393. // 添加用户
  394. addUser(this.dataForm).then(response => {
  395. if (response.status === 200) {
  396. this.$message({
  397. type: 'success',
  398. message: '操作成功'
  399. })
  400. this.dialogFormVisible = false
  401. this.adminList()
  402. } else {
  403. this.$message({
  404. type: 'error',
  405. message: response.data.msg
  406. })
  407. }
  408. })
  409. }
  410. },
  411. // 验证手机号
  412. checkMobile(str) {
  413. const reg = /^1[3456789]\d{9}$/
  414. return reg.test(str)
  415. }
  416. }
  417. }
  418. </script>
  419. <style>
  420. </style>