userM.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. <script setup>
  2. import { Search } from '@element-plus/icons-vue'
  3. import {ElMessage,ElMessageBox} from "element-plus"
  4. import {getuserList,getDepartmentList,getRoleList,addUserApi,editUserApi,
  5. editUserStatus,resetUserPsd,deleteUserApi} from '@/api/systemMana'
  6. import { useRouter } from 'vue-router';
  7. import md5 from 'js-md5'
  8. const router=useRouter()
  9. const userStatus=[{value:1,label:'启用'},{value:0,label:'禁用'}]
  10. const submitFormEl = ref()
  11. const resetPsdFormEl = ref()
  12. const user=reactive({
  13. searchParams:{
  14. key_word:'',
  15. dept_id:'',
  16. enabled:'',
  17. page_size:10,
  18. current:1,
  19. },
  20. tableData:[],
  21. departmanentData:[],
  22. roleData:[],
  23. total:0,
  24. dialogTitle:'',//弹窗标题
  25. // 添加编辑弹窗
  26. submitForm:{
  27. admin_name:'',
  28. password:'123456a',
  29. real_name:'',
  30. position:'',
  31. dept_id:'',
  32. role_id:'',
  33. mobile:'',
  34. enabled:1,
  35. remark:''
  36. },
  37. rules:{
  38. admin_name:{required:true,message:"登录账号不能为空",trigger:"blur"},
  39. password:{required:true,message:"登录密码不能为空",trigger:"blur"},
  40. real_name:{required:true,message:"姓名不能为空",trigger:"blur"},
  41. dept_id:{required:true,message:"所属部门不能为空",trigger:"change"},
  42. role_id:{required:true,message:"角色不能为空",trigger:"change"},
  43. mobile:[
  44. {required:true,message:"手机号不能为空",trigger:"blur"},
  45. {asyncValidator: (rule, value) => {
  46. return new Promise((resolve, reject) => {
  47. if (value.length !=11) {
  48. reject('手机号码必须是11位数字');
  49. } else {
  50. resolve();
  51. }
  52. });
  53. },
  54. trigger:"blur"}
  55. ],
  56. enabled:{required:true,message:"状态不能为空",trigger:"change"}
  57. },
  58. showAddDia:false,
  59. isEdit:false,
  60. // 重置密码弹窗
  61. resetPsdForm:{
  62. admin_id:'',
  63. pwd:'',
  64. confirm_pwd:''
  65. },
  66. resetPsdRules:{
  67. pwd:{required:true,message:"新密码不能为空",trigger:"blur"},
  68. confirm_pwd:{required:true,message:"确认新密码不能为空",trigger:"blur"}
  69. },
  70. showResetDia:false,
  71. })
  72. // 获取用户列表
  73. const userList=()=>{
  74. getuserList(user.searchParams).then(res=>{
  75. if(res.code == 200){
  76. user.tableData = res.data.list || []
  77. user.total = res.data.page.total
  78. }
  79. })
  80. }
  81. // 获取部门列表
  82. const departmentList=()=>{
  83. getDepartmentList().then(res=>{
  84. user.departmanentData = res.data.list || []
  85. })
  86. }
  87. // 获取角色列表
  88. const roleList=()=>{
  89. getRoleList().then(res=>{
  90. if(res.code == 200){
  91. user.roleData = res.data.list || []
  92. }
  93. })
  94. }
  95. // 刷新列表
  96. const refreshList=()=>{
  97. user.searchParams.key_word=''
  98. user.searchParams.dept_id=''
  99. user.searchParams.enabled=''
  100. user.searchParams.current=1
  101. userList()
  102. }
  103. // 去添加部门
  104. const goAddDepartment=()=>{
  105. sessionStorage.setItem('deptOpenDialog','1')
  106. router.push('/system/department')
  107. }
  108. //切换页码
  109. const changePageNo = (pageNo)=>{
  110. user.searchParams.current = pageNo
  111. userList()
  112. }
  113. // 切换每页的数量
  114. const changePageSize=(pageSize)=>{
  115. user.searchParams.page_size = pageSize
  116. userList()
  117. }
  118. // 搜索用户
  119. const userSearch=(type)=>{
  120. if(type=='deptReset'){
  121. user.searchParams.dept_id=''
  122. }
  123. user.searchParams.current = 1
  124. userList()
  125. }
  126. //点击部门树,筛选用户
  127. const userSearchByDept=(item)=>{
  128. user.searchParams.dept_id=item.dept_id
  129. userSearch()
  130. }
  131. // 添加用户
  132. const addUser=()=>{
  133. user.dialogTitle='添加用户'
  134. user.showAddDia=true
  135. user.isEdit = false
  136. }
  137. // 编辑用户
  138. const editUser=(row)=>{
  139. user.dialogTitle='编辑用户'
  140. user.submitForm.admin_id=row.admin_id
  141. user.submitForm.admin_name=row.admin_name
  142. user.submitForm.real_name=row.real_name
  143. user.submitForm.position=row.position
  144. user.submitForm.dept_id=row.dept_id
  145. user.submitForm.role_id=row.role_id
  146. user.submitForm.mobile=row.mobile
  147. user.submitForm.enabled=row.enabled
  148. user.submitForm.remark=row.remark
  149. user.showAddDia=true
  150. user.isEdit = true
  151. }
  152. // 更改用户状态
  153. const changeUserStatus=(row)=>{
  154. let changeStatus = row.enabled==1?0:1
  155. editUserStatus({admin_id:row.admin_id,enabled:changeStatus}).then((res) => {
  156. if(res.code==200){
  157. row.enabled=changeStatus
  158. ElMessage.success(`${row.enabled==1?'启用':'禁用'}成功`)
  159. }
  160. })
  161. }
  162. // 重置密码
  163. const resetPassword=(row)=>{
  164. user.dialogTitle='重置密码'
  165. user.showResetDia=true
  166. user.resetPsdForm.admin_id=row.admin_id
  167. }
  168. // 删除用户
  169. const deleteUser=(row)=>{
  170. ElMessageBox.confirm("删除后不可恢复,确认删除该用户吗?",'提示',{
  171. cancelButtonText:'取消',
  172. confirmButtonText:'确定',
  173. type: 'warning'
  174. }).then(res=>{
  175. deleteUserApi({admin_id:row.admin_id}).then(res=>{
  176. if(res.code==200){
  177. ElMessage.success('删除用户成功')
  178. refreshList()
  179. }
  180. })
  181. }).catch(()=>{})
  182. }
  183. // 提交
  184. const submit=(type)=>{
  185. if(type=='add'){
  186. submitFormEl.value.validate((valid)=>{
  187. if(valid){
  188. if(Array.isArray(user.submitForm.dept_id)){
  189. user.submitForm.dept_id=user.submitForm.dept_id[(user.submitForm.dept_id.length-1)]
  190. }
  191. if(user.submitForm.admin_id){
  192. //编辑
  193. editUserApi(user.submitForm).then(res=>{
  194. if(res.code==200){
  195. ElMessage.success(`${user.dialogTitle}成功`)
  196. user.showAddDia=false
  197. refreshList()
  198. }
  199. })
  200. }else{
  201. // 添加
  202. let params={...user.submitForm,password:md5(user.submitForm.password)}
  203. addUserApi(params).then(res=>{
  204. if(res.code==200){
  205. ElMessage.success(`${user.dialogTitle}成功`)
  206. user.showAddDia=false
  207. refreshList()
  208. }
  209. })
  210. }
  211. }
  212. })
  213. }else{
  214. // reset
  215. resetPsdFormEl.value.validate((valid)=>{
  216. if(valid){
  217. if(user.resetPsdForm.pwd != user.resetPsdForm.confirm_pwd){
  218. ElMessage.warning('新密码两次输入不一致,请核对!')
  219. return
  220. }
  221. let newPassword = md5(user.resetPsdForm.pwd)
  222. let params={
  223. admin_id:user.resetPsdForm.admin_id,
  224. pwd:newPassword,
  225. confirm_pwd:newPassword
  226. }
  227. resetUserPsd(params).then(res=>{
  228. if(res.code==200){
  229. ElMessage.success(`${user.dialogTitle}成功`)
  230. user.showResetDia=false
  231. }
  232. })
  233. }
  234. })
  235. }
  236. }
  237. // 重置表单、清除错误信息
  238. const closeDia=(type)=>{
  239. if(type=='add'){
  240. // 添加编辑
  241. user.submitForm={
  242. admin_name:'',
  243. password:'123456a',
  244. real_name:'',
  245. position:'',
  246. dept_id:'',
  247. role_id:'',
  248. mobile:'',
  249. enabled:1,
  250. remark:''
  251. }
  252. setTimeout(()=>{
  253. // 清除错误信息
  254. submitFormEl.value.clearValidate()
  255. },0)
  256. }else{
  257. // 重设密码
  258. user.resetPsdForm={
  259. pwd:'',
  260. confirm_pwd:''
  261. }
  262. setTimeout(()=>{
  263. // 清除错误信息
  264. resetPsdFormEl.value.clearValidate()
  265. },0)
  266. }
  267. }
  268. // 自定义类名
  269. const customNodeClass =(data)=>{
  270. if(data.dept_id==user.searchParams.dept_id){
  271. return 'is-selectNode'
  272. }else{
  273. return ''
  274. }
  275. }
  276. // ---------------------created
  277. // 用户列表
  278. userList()
  279. // 角色列表
  280. roleList()
  281. // 部门列表
  282. departmentList()
  283. </script>
  284. <template>
  285. <div class="system-user-container">
  286. <div class="user-container-left">
  287. <!-- 部门列表 -->
  288. <div class="department-container">
  289. <div class="department-title" @click="userSearch('deptReset')">
  290. <img src="@/assets/img/icon/institution.png" style="margin-right: 6px;">
  291. <span :style="{'color':user.searchParams.dept_id==''?'var(--themeColor)':'#333333'}">弘则研究</span>
  292. </div>
  293. <el-scrollbar class="department-contentTree" id="department-contentTree" height="calc(100vh - 248px)">
  294. <el-tree :data="user.departmanentData" :props="{label:'dept_name',children:'Children',class: customNodeClass}"
  295. node-key="dept_id" default-expand-all :expand-on-click-node="false" @node-click="userSearchByDept">
  296. </el-tree>
  297. </el-scrollbar>
  298. <div class="user-add-department" @click="goAddDepartment" v-permission="'system:user:addDept'">
  299. <el-icon size="20px" color="var(--themeColor)" style="cursor: pointer;"><CirclePlus /></el-icon>
  300. <span>添加部门</span>
  301. </div>
  302. </div>
  303. </div>
  304. <div class="user-container-right">
  305. <div class="user-container-right-header">
  306. <!-- 顶部按钮区域 -->
  307. <div class="user-container-header-buttons">
  308. <el-button type="primary" @click="addUser" class="header-optios-buttons" v-permission="'system:user:add'">添加用户</el-button>
  309. </div>
  310. <!-- 搜索区域 -->
  311. <div class="user-container-header-search">
  312. <el-input v-model="user.searchParams.key_word" placeholder="姓名/账号/手机号" :prefix-icon="Search"
  313. style="width: 440px;margin-right: 30px;" @input="userSearch"/>
  314. <el-select v-model="user.searchParams.enabled" placeholder="用户状态"
  315. clearable @change="userSearch" style="width: 286px">
  316. <el-option :label="item.label" :value="item.value" v-for="item in userStatus"></el-option>
  317. </el-select>
  318. </div>
  319. </div>
  320. <div class="user-container-right-table">
  321. <!-- 表格 -->
  322. <el-table :data="user.tableData" border max-height="690px" style="border-radius: 8px;position: sticky;">
  323. <el-table-column label="姓名" show-overflow-tooltip prop="real_name"></el-table-column>
  324. <el-table-column label="手机号" show-overflow-tooltip prop="mobile"></el-table-column>
  325. <el-table-column label="角色" show-overflow-tooltip prop="role_name"></el-table-column>
  326. <el-table-column label="部门/子部门" show-overflow-tooltip prop="dept_full_name"></el-table-column>
  327. <el-table-column label="状态" show-overflow-tooltip prop="enabled">
  328. <template #default="scope">
  329. <span style="color: #C54322;" v-if="scope.row.enabled==0">禁用</span>
  330. <span v-else>启用</span>
  331. </template>
  332. </el-table-column>
  333. <el-table-column label="操作">
  334. <template #default="scope">
  335. <div class="table-options">
  336. <span class="table-option-buttons" @click="editUser(scope.row)" v-permission="'system:user:edit'">
  337. 编辑
  338. </span>
  339. <span class="table-option-buttons" @click="resetPassword(scope.row)" v-permission="'system:user:resetPsd'">
  340. 重置密码
  341. </span>
  342. <span class="table-option-buttons" @click="changeUserStatus(scope.row)" v-permission="'system:user:changeStatus'">
  343. {{scope.row.enabled==1?'禁用':'启用'}}
  344. </span>
  345. <span class="table-option-buttons" style="color:#C54322;" @click="deleteUser(scope.row)" v-permission="'system:user:delete'">
  346. 删除
  347. </span>
  348. </div>
  349. </template>
  350. </el-table-column>
  351. <template #empty>
  352. <div class="table-no-data">
  353. <img src="@/assets/img/icon/empty-data.png" />
  354. <span>暂无数据</span>
  355. </div>
  356. </template>
  357. </el-table>
  358. <m-page :pageSize="user.searchParams.page_size" :page_no="user.searchParams.current"
  359. style="margin-top: 20px;"
  360. :total="user.total" @handleCurrentChange="changePageNo" @handleSizeChange="changePageSize" />
  361. </div>
  362. </div>
  363. <!-- 添加/编辑弹窗 -->
  364. <el-dialog :title="user.dialogTitle"
  365. v-model="user.showAddDia"
  366. width="500px"
  367. :close-on-click-modal="false" @closed="closeDia('add')">
  368. <el-form :model="user.submitForm" label-position="right"
  369. label-width="88px" :rules="user.rules" ref="submitFormEl" style="padding-left: 45px;">
  370. <el-form-item label="登录账号" prop="admin_name">
  371. <el-input type="text" placeholder="请输入登录账号" v-model="user.submitForm.admin_name" class="inner-dia-input"/>
  372. </el-form-item>
  373. <el-form-item label="登录密码" v-if="!user.isEdit" prop="password">
  374. <el-input type="text" placeholder="请输入登录密码" v-model="user.submitForm.password" class="inner-dia-input"/>
  375. </el-form-item>
  376. <el-form-item label="姓名" prop="real_name" >
  377. <template #label="scope">
  378. <div class="label-custom-equally">
  379. {{scope.label}}
  380. </div>
  381. </template>
  382. <el-input type="text" placeholder="请输入用户姓名" v-model="user.submitForm.real_name" class="inner-dia-input"/>
  383. </el-form-item>
  384. <el-form-item label="职务" prop="position">
  385. <template #label="scope">
  386. <div class="label-custom-equally">
  387. {{scope.label}}
  388. </div>
  389. </template>
  390. <el-input type="text" placeholder="请输入职务" v-model="user.submitForm.position" class="inner-dia-input"/>
  391. </el-form-item>
  392. <el-form-item label="所属部门" prop="dept_id" >
  393. <el-cascader :options="user.departmanentData" v-model="user.submitForm.dept_id" style="width:286px"
  394. :props="{value:'dept_id',label:'dept_name',children:'Children',checkStrictly: true}"
  395. ></el-cascader>
  396. </el-form-item>
  397. <el-form-item label="角色" prop="role_id">
  398. <template #label="scope">
  399. <div class="label-custom-equally">
  400. {{scope.label}}
  401. </div>
  402. </template>
  403. <el-select v-model="user.submitForm.role_id" placeholder="请选择角色" class="inner-dia-input">
  404. <el-option :label="item.role_name" :value="item.role_id" v-for="item in user.roleData"></el-option>
  405. </el-select>
  406. </el-form-item>
  407. <el-form-item label="手机号码" prop="mobile">
  408. <el-input type="text" placeholder="请输入手机号码" v-model="user.submitForm.mobile" class="inner-dia-input"/>
  409. </el-form-item>
  410. <el-form-item label="状态" prop="enabled" >
  411. <template #label="scope">
  412. <div class="label-custom-equally">
  413. {{scope.label}}
  414. </div>
  415. </template>
  416. <el-radio-group v-model="user.submitForm.enabled">
  417. <el-radio :label="1">启用</el-radio>
  418. <el-radio :label="0">禁用</el-radio>
  419. </el-radio-group>
  420. </el-form-item>
  421. <el-form-item label="备注" prop="remark">
  422. <template #label="scope">
  423. <div class="label-custom-equally">
  424. {{scope.label}}
  425. </div>
  426. </template>
  427. <el-input type="text" placeholder="请输入备注" v-model="user.submitForm.remark" class="inner-dia-input"/>
  428. </el-form-item>
  429. </el-form>
  430. <template #footer>
  431. <el-button @click="user.showAddDia=false">取消</el-button>
  432. <el-button @click="submit('add')" type="primary">保存</el-button>
  433. </template>
  434. </el-dialog>
  435. <!-- 重置密码弹窗 -->
  436. <el-dialog :title="user.dialogTitle"
  437. v-model="user.showResetDia"
  438. width="500px" @closed="closeDia('reset')"
  439. :close-on-click-modal="false">
  440. <el-form :model="user.resetPsdForm" label-position="right"
  441. label-width="108px" :rules="user.resetPsdRules" ref="resetPsdFormEl">
  442. <el-form-item label="新密码" prop="pwd">
  443. <el-input type="password" placeholder="输入长度不超过20个字符" v-model="user.resetPsdForm.pwd"
  444. maxlength="20" show-password/>
  445. </el-form-item>
  446. <el-form-item label="确认新密码" prop="confirm_pwd">
  447. <el-input type="password" placeholder="输入长度不超过20个字符" v-model="user.resetPsdForm.confirm_pwd"
  448. maxlength="20" show-password/>
  449. </el-form-item>
  450. </el-form>
  451. <template #footer>
  452. <el-button @click="user.showResetDia=false">取消</el-button>
  453. <el-button @click="submit('resetPsd')" type="primary">保存</el-button>
  454. </template>
  455. </el-dialog>
  456. </div>
  457. </template>
  458. <style lang="scss" scoped>
  459. .system-user-container{
  460. min-height: 100%;
  461. display: flex;
  462. .user-container-left{
  463. padding:20px;
  464. min-width: 260px;
  465. background-color: white;
  466. border-radius: 8px;
  467. box-sizing: border-box;
  468. .department-container{
  469. .department-title{
  470. margin-bottom: 16px;
  471. display: flex;
  472. align-items: center;
  473. cursor: pointer;
  474. span{
  475. font-size: 14px;
  476. }
  477. }
  478. .user-add-department{
  479. display:flex;
  480. align-items:center;
  481. justify-content: center;
  482. margin-top: 30px;
  483. span{
  484. cursor:pointer;
  485. margin-left: 6px;
  486. color: $themeColor;
  487. font-size: 14px;
  488. }
  489. }
  490. }
  491. }
  492. .user-container-right{
  493. margin: 0 30px;
  494. flex-grow: 1;
  495. overflow: hidden;
  496. .user-container-right-header{
  497. display: flex;
  498. justify-content: space-between;
  499. flex-wrap: wrap;
  500. .user-container-header-search{
  501. display: flex;
  502. align-items: center;
  503. flex-wrap: wrap;
  504. }
  505. }
  506. .user-container-right-table{
  507. margin-top: 30px;
  508. }
  509. }
  510. .inner-dia-input{
  511. width: 286px;
  512. }
  513. }
  514. </style>
  515. <style lang="scss">
  516. #department-contentTree{
  517. .el-tree{
  518. .el-tree-node__expand-icon.is-leaf{
  519. background-image: none;
  520. }
  521. .is-selectNode{
  522. &>.el-tree-node__content{
  523. .el-tree-node__label{
  524. color: $themeColor;
  525. }
  526. }
  527. }
  528. }
  529. }
  530. </style>