roleList.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. <template>
  2. <div class="mainBox">
  3. <!--搜索功能 start------------------------------------------------------------>
  4. <div class="layerBoxNoBg">
  5. <div>
  6. <el-button type="primary" @click="openWindow()">添加角色</el-button>
  7. </div>
  8. </div>
  9. <!--搜索功能 end------------------------------------------------------------>
  10. <!--表格内容 start------------------------------------------------------------>
  11. <div class="layerBox">
  12. <tableTitle :name="tableDivTitle"/>
  13. <el-row>
  14. <template>
  15. <el-table :data="tableData" style="width: 100%">
  16. <el-table-column fixed prop="id" label="编号" width="50"></el-table-column>
  17. <el-table-column prop="role_name" label="角色名称"></el-table-column>
  18. <el-table-column prop="remark" label="职能描述"></el-table-column>
  19. <el-table-column prop="users_count" label="成员数量"></el-table-column>
  20. <el-table-column prop="sort" label="排序"></el-table-column>
  21. <el-table-column prop="created_at" label="添加时间"></el-table-column>
  22. <el-table-column fixed="right" label="操作" width="200" header-align="center">
  23. <template slot-scope="scope">
  24. <div class="listBtnBox">
  25. <div v-if="scope.row.id !== 1" class="listDeleteBtn" @click="deleteRow(scope.row.id)"><i class="el-icon-edit-outline"></i>删除</div>
  26. <div class="listEditBtn" @click="editRow(scope.row.id)"><i class="el-icon-edit-outline"></i>编辑</div>
  27. </div>
  28. </template>
  29. </el-table-column>
  30. </el-table>
  31. </template>
  32. </el-row>
  33. </div>
  34. <!--分页 start------------------------------------------------------------>
  35. <div class="alignBox">
  36. <el-row>
  37. <el-col :span="24">
  38. <el-pagination :current-page="getApiData.page" @size-change="handleSizeChange" @current-change="handleCurrentChange" :page-size="10" layout="total, prev, pager, next, jumper" :total="allCount"></el-pagination>
  39. </el-col>
  40. </el-row>
  41. </div>
  42. <!--分页 end------------------------------------------------------------>
  43. <!--表格内容 end------------------------------------------------------------>
  44. <!--弹出框 start------------------------------------------------------------>
  45. <el-dialog :title="editId ? '编辑角色' : '添加角色'" :visible.sync="windowStatus" :close-on-click-modal="false">
  46. <el-form :model="form" ref="form" :rules="formRules" autocomplete="off" label-position="left">
  47. <div class="formDiv">
  48. <el-form-item label="角色名称:" :label-width="formLabelWidth" prop="role_name" class="custom-align-right">
  49. <el-input v-model="form.role_name" autocomplete="off" placeholder="请输入角色名称"></el-input>
  50. </el-form-item>
  51. <el-form-item label="职能描述:" :label-width="formLabelWidth" prop="remark" class="custom-align-right">
  52. <el-input type="textarea" v-model="form.remark" class="custom-textarea" placeholder="请输入职能描述"></el-input>
  53. </el-form-item>
  54. <el-form-item label="排序:" :label-width="formLabelWidth" prop="" class="custom-align-right">
  55. <el-input v-model="form.sort" autocomplete="off" placeholder="请输入排序"></el-input>
  56. </el-form-item>
  57. <el-form-item label="权限:" :label-width="formLabelWidth" prop="rule" class="custom-align-right">
  58. <div class="treeBox" v-loading="loading">
  59. <el-tree
  60. ref="tree"
  61. :data="roleData"
  62. show-checkbox
  63. node-key="id"
  64. :default-expanded-keys="expandedKeys"
  65. :default-checked-keys="checkedKeys"
  66. :props="defaultProps">
  67. </el-tree>
  68. <!--没有被选中的父级在halfCheckedNodes,halfCheckedKeys属性中-->
  69. </div>
  70. </el-form-item>
  71. <input type="hidden" v-model="form.rule" />
  72. </div>
  73. </el-form>
  74. <div slot="footer" class="dialog-footer">
  75. <div>
  76. <el-button @click="closeWindow">取 消</el-button>
  77. <el-button type="primary" @click="addData" v-if="editId==0">提交</el-button>
  78. <el-button type="primary" @click="editData" v-else>修改</el-button>
  79. </div>
  80. </div>
  81. </el-dialog>
  82. <!--弹出框 end------------------------------------------------------------>
  83. </div>
  84. </template>
  85. <script>
  86. //引入公用样式
  87. import '@/styles/global.less';
  88. //表格标题
  89. import tableTitle from './components/tableTitle';
  90. export default {
  91. components: {
  92. tableTitle,//表格标题
  93. },
  94. data() {
  95. //0.全局操作 start ------------------------------------------------------------>
  96. //表单验证
  97. const validateEmpty = (rule,value,callback) => {
  98. if (value.length == 0) {
  99. callback(new Error('该项不能为空!'))
  100. } else {
  101. callback()
  102. }
  103. }
  104. //数组不能为空
  105. const validateArray = (rule,value,callback) => {
  106. if (value.length == 0) {
  107. callback(new Error('该项不能为空!'))
  108. } else {
  109. callback()
  110. }
  111. }
  112. //0.全局操作 end ------------------------------------------------------------>
  113. return {
  114. //1.列表和分页相关 start ------------------------------------------------------------>
  115. tableDivTitle:"角色管理",
  116. tableData: [],//列表
  117. allCount:0,//总条数
  118. editId:0,//要修改的网站id
  119. getApiData:{
  120. page:1,//当前是第几页
  121. pageSize:10,//一共多少条
  122. },
  123. //分页相关 end ------------------------------------------------------------>
  124. //2.弹出框设置 start ------------------------------------------------------------>
  125. //是否显示弹出窗口
  126. windowStatus:false,
  127. formLabelWidth: '120px',
  128. isShowTable:1,//是否显示表格
  129. //弹出框设置 end ------------------------------------------------------------>
  130. //3.搜索相关 start ------------------------------------------------------------>
  131. //搜索相关 end ------------------------------------------------------------>
  132. //3.弹出框中的表单设置 start ------------------------------------------------------------>
  133. //3.1 表单收集的数据
  134. form: {
  135. role_name:"",//角色名称
  136. rule:[],//权限
  137. remark:"",//职能描述
  138. sort:0//排序
  139. },
  140. expandedKeys:[],//展开的节点
  141. checkedKeys:[],//选中的节点
  142. roleData:[],//菜单树
  143. loading:true,//加载中
  144. defaultProps: {
  145. children: 'children',
  146. label: 'label'
  147. },
  148. //3.2表单验证规则
  149. formRules: {
  150. //角色名称不能为空
  151. role_name:[{required:true,trigger:'blur',validator:validateEmpty}],
  152. //职能描述不能为空
  153. remark:[{required:true,trigger:'blur',validator:validateEmpty}],
  154. //排序不能为空
  155. //sort:[{required:true,trigger:'blur',validator:validateEmpty}],
  156. //权限不能为空
  157. rule:[{required:true,trigger:'blur',validator:validateArray}],
  158. },
  159. //弹出框中的表单设置 end ------------------------------------------------------------>
  160. }
  161. },
  162. methods: {
  163. //1.列表和分页相关 start ------------------------------------------------------------>
  164. //1.1 获取内容
  165. getData(){
  166. this.$store.dispatch('userRole/roleList',this.getApiData).then(res=> {
  167. this.allCount = res.data.count;
  168. this.tableData = res.data.rows;
  169. })
  170. },
  171. //1.2 列表内容分页
  172. //直接跳转
  173. handleSizeChange(val) {
  174. this.getApiData.page = val;
  175. this.getData();
  176. },
  177. //1.3 点击分页
  178. handleCurrentChange(val) {
  179. this.getApiData.page = val;
  180. this.getData();
  181. },
  182. //1.4 获取菜单树
  183. getAllMenuList(){
  184. this.$store.dispatch('userRole/getAllMenuList').then(res=> {
  185. console.log(res)
  186. this.roleData = res.data;
  187. })
  188. },
  189. //1.5 删除角色
  190. deleteRow(id){
  191. this.$confirm('此操作将永久删除该条数据, 是否继续?', '提示', {
  192. confirmButtonText: '确定',
  193. cancelButtonText: '取消',
  194. type: 'warning'
  195. }).then(() => {
  196. console.log("当前删除:" + id)
  197. this.$store.dispatch('userRole/delRole',{id:id}).then(res=> {
  198. this.getData();
  199. this.$message({
  200. type: 'success',
  201. message: '删除成功!'
  202. });
  203. }).catch(() => {
  204. this.$message({
  205. type: 'warning',
  206. message: '网络错误,请重试!'
  207. });
  208. })
  209. }).catch(() => {
  210. this.$message({
  211. type: 'warning',
  212. message: '已取消删除'
  213. });
  214. });
  215. },
  216. //列表和分页相关 end ------------------------------------------------------------>
  217. //2.弹出框设置 start ------------------------------------------------------------>
  218. //2.1 打开弹出框
  219. openWindow() {
  220. this.form.role_name = "";
  221. this.form.remark = "";
  222. this.form.sort = "";
  223. this.loading = false;
  224. //清空弹出框
  225. // this.$nextTick(() => {
  226. // //请空选中的节点
  227. // this.$refs.tree.setCheckedKeys([]);
  228. // //还原搜索的状态
  229. // this.$refs.tree.root.childNodes.forEach((e) => {
  230. // e.expanded = false;
  231. // });
  232. // // 收回树中所有展开的节点
  233. // this.collapseAllNodes(this.$refs.tree.root.childNodes);
  234. this.getAllMenuList();
  235. //this.clearToServe();
  236. this.windowStatus = true;
  237. //this.$refs.form.clearValidate();
  238. },
  239. //2.2 关闭弹出框
  240. closeWindow(){
  241. this.windowStatus = false;
  242. this.clearToServe();
  243. this.$refs.form.clearValidate();
  244. },
  245. //2.3 清空提交窗口
  246. clearToServe(){
  247. //重置窗口
  248. this.editId = "";
  249. this.expandedKeys = [];
  250. //this.checkedKeys = [];
  251. this.$nextTick(() => {
  252. //请空选中的节点
  253. this.$refs.tree.setCheckedKeys([]);
  254. //还原搜索的状态
  255. this.$refs.tree.root.childNodes.forEach((e) => {
  256. e.expanded = false;
  257. });
  258. });
  259. this.form.role_name = "";
  260. this.form.remark = "";
  261. this.form.sort = "";
  262. },
  263. //弹出框设置 end ------------------------------------------------------------>
  264. //4.添加 start ------------------------------------------------------------>
  265. addData(){
  266. this.form.id = this.editId;
  267. //如果排序不填,默认排序传递数字
  268. if(this.form.sort == ""){
  269. this.form.sort = 0;
  270. }
  271. //半选的节点
  272. let supplement = [];
  273. let allKeys = this.$refs.tree.getHalfCheckedNodes();
  274. if(allKeys.length > 0){
  275. for(let i = 0; i < allKeys.length; i++){
  276. supplement.push(allKeys[i].id);
  277. }
  278. }
  279. console.log(supplement)
  280. //选中的节点
  281. let checkedArr = this.$refs.tree.getCheckedKeys();
  282. this.form.rule = checkedArr;
  283. console.log(checkedArr)
  284. //合并节点
  285. this.form.rule = [...new Set([...supplement, ...checkedArr])];
  286. console.log(this.form.rule)
  287. //提交数据
  288. this.$refs.form.validate(valid => {
  289. if (valid) {
  290. this.$store.dispatch('userRole/addRole',this.form).then(res=> {
  291. this.$message({
  292. type: 'success',
  293. message: '已成功添加角色!'
  294. });
  295. console.log(res)
  296. this.closeWindow();
  297. this.getData();
  298. }).catch(() => {
  299. this.$message({
  300. type: 'info',
  301. message: '网络错误,请重试!'
  302. });
  303. })
  304. }
  305. })
  306. },
  307. //添加 end ------------------------------------------------------------>
  308. //4.编辑 start ------------------------------------------------------------>
  309. //回显数据
  310. editRow(id){
  311. this.openWindow();
  312. this.loading = true;
  313. //设置要编辑的id
  314. this.editId = id;
  315. this.$store.dispatch('userRole/roleInfo',{id:id}).then(res=> {
  316. console.log(res)
  317. // this.$nextTick(() => {
  318. // //请空选中的节点
  319. // this.$refs.tree.setCheckedKeys([]);
  320. // //还原搜索的状态
  321. // this.$refs.tree.root.childNodes.forEach((e) => {
  322. // e.expanded = false;
  323. // });
  324. // });
  325. //回显用户权限
  326. // this.expandedKeys = res.data.rule;
  327. // this.checkedKeys = res.data.rule;
  328. // this.isCheck = false;
  329. // this.$nextTick(() => {
  330. // this.isCheck = false;
  331. // })
  332. //加1秒延迟等待dom加载
  333. let that = this;
  334. setTimeout(() => {
  335. res.data.rule.forEach((i,n) => {
  336. var node = that.$refs.tree.getNode(i);
  337. //console.log(node)
  338. if(node){
  339. if(node.isLeaf){
  340. that.$refs.tree.setChecked(node,true);
  341. }
  342. }
  343. });
  344. that.loading = false;
  345. },1000)
  346. //回显用户名称
  347. this.form.role_name = res.data.role_name;
  348. //回显职能描述
  349. this.form.remark = res.data.remark;
  350. //回显排序
  351. this.form.sort = res.data.sort;
  352. }).catch(() => {
  353. this.$message.error('网络错误,请重试!');
  354. })
  355. },
  356. //提交编辑
  357. editData(){
  358. this.form.id = this.editId;
  359. //如果排序不填,默认排序传递数字
  360. if(this.form.sort == ""){
  361. this.form.sort = 0;
  362. }
  363. //半选的节点
  364. let supplement = [];
  365. let allKeys = this.$refs.tree.getHalfCheckedNodes();
  366. if(allKeys.length > 0){
  367. for(let i = 0; i < allKeys.length; i++){
  368. supplement.push(allKeys[i].id);
  369. }
  370. }
  371. console.log(supplement)
  372. //选中的节点
  373. let checkedArr = this.$refs.tree.getCheckedKeys();
  374. this.form.rule = checkedArr;
  375. console.log(checkedArr)
  376. //合并节点
  377. this.form.rule = [...new Set([...supplement, ...checkedArr])];
  378. console.log(this.form.rule)
  379. //提交数据
  380. this.$refs.form.validate(valid => {
  381. if (valid) {
  382. this.$store.dispatch('userRole/updateRole',this.form).then(res=> {
  383. console.log(res)
  384. this.closeWindow();
  385. this.$message({
  386. type: 'success',
  387. message: '修改成功!'
  388. });
  389. this.getData();
  390. }).catch(() => {
  391. this.$message({
  392. type: 'warning',
  393. message: '网络错误,请重试!'
  394. });
  395. })
  396. }
  397. })
  398. },
  399. //编辑 end ------------------------------------------------------------>
  400. //5.tree start ------------------------------------------------------------>
  401. checkChange(data) {
  402. const node = this.$refs.tree.getNode(data.id);
  403. this.setNode(node);
  404. },
  405. setNode(node) {
  406. console.log(node, "node");
  407. if (node.checked) {
  408. //如果当前是选中checkbox,则递归设置父节点和父父节点++选中
  409. this.setParentNode(node);
  410. } else {
  411. //当前是取消选中,将所有子节点都取消选中
  412. this.setChildenNode(node);
  413. }
  414. },
  415. setParentNode(node) {
  416. if (node.parent) {
  417. for (const key in node) {
  418. if (key === "parent") {
  419. node[key].checked = true;
  420. this.setParentNode(node[key]);
  421. }
  422. }
  423. }
  424. },
  425. setChildenNode(node) {
  426. let len = node.childNodes.length;
  427. for (let i = 0; i < len; i++) {
  428. node.childNodes[i].checked = false;
  429. this.setChildenNode(node.childNodes[i]);
  430. }
  431. },
  432. //5.tree end ------------------------------------------------------------>
  433. },
  434. mounted(){
  435. //获取页面列表
  436. this.getData();
  437. //获取菜单树
  438. this.getAllMenuList();
  439. }
  440. }
  441. </script>
  442. <style scoped lang="less">
  443. .layerBoxNoBg {
  444. padding: 30px 0 0 0;
  445. }
  446. //表单微调 start------------------------------------------------------------>*/
  447. ::v-deep .custom-form-item > .el-form-item__label {
  448. line-height: 140px !important;
  449. }
  450. ::v-deep .custom-textarea .el-textarea__inner {
  451. resize: none; /* 禁止用拖拽调整大小 */
  452. }
  453. ::v-deep .custom-align-right .el-form-item__label {
  454. text-align: right; /* 设置标签文字右对齐 */
  455. }
  456. ::v-deep .el-select-group__title {
  457. color: #909399;
  458. }
  459. ::v-deep .el-select {
  460. width: 100% !important;
  461. }
  462. </style>