index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. <template>
  2. <div class="app-container app-containerth">
  3. <el-row style="margin-top: 18px;" class="searBoxstu" >
  4. <el-col :span="5" class="searBoxs">
  5. <el-row class="roleBoxui" >
  6. <el-col :span="24" class="roleBotyu" style="height: 100%;">
  7. <el-row :gutter="10" class="mb8" style="height: 100%;">
  8. <el-col :span="1.5">
  9. <el-button type="primary" style="background-color: #FF9639;color: #fff;border: none;" plain icon="el-icon-refresh"
  10. @click="efresh" v-hasPermi="['system:role:list']">刷新</el-button>
  11. </el-col>
  12. </el-row>
  13. </el-col>
  14. </el-row>
  15. <div class="searBox">
  16. <div class="searInput">
  17. <input type="text" placeholder="请输入角色" v-model="queryParams.roleName">
  18. </div>
  19. <div class="searBtn" @click="quregu">
  20. <img src="@/assets/images/icon_sr_ss@2x.png" alt="" class="icon">
  21. </div>
  22. </div>
  23. <div class="searList">
  24. <div class="searItem" v-for="(item,index) in roleList" :key="item.roleName" :class="[indexdw == index? 'active' : '']" @click="jieese(item.id,index)">
  25. {{item.roleName}}
  26. </div>
  27. </div>
  28. <pagination sty v-show="totale>0" :total="totale" layout="prev, pager, next" :page.sync="queryParams.pageNum"
  29. :limit.sync="queryParams.pageSize" @pagination="getList" small />
  30. </el-col>
  31. <el-col :span="19" class="roleContr">
  32. <el-row class="roleBox">
  33. <el-col :span="24" class="roleBot">
  34. <el-row :gutter="10" class="mb8">
  35. <el-col :span="1.5">
  36. <el-button type="primary" style="background-color: #2AC1CA;color: #fff;border: none;" plain icon="el-icon-plus"
  37. @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
  38. </el-col>
  39. <el-col :span="1.5">
  40. <el-button type="primary" style="background-color: #FF9639;color: #fff;border: none;" plain icon="el-icon-edit"
  41. @click="handleUpdate" :disabled="single" v-hasPermi="['system:role:list']">修改</el-button>
  42. </el-col>
  43. <el-col :span="1.5">
  44. <el-button type="primary" :disabled="multiple" style="background-color: #3C8DBC;color: #fff;border: none;" plain icon="el-icon-delete"
  45. @click="handleDelete" v-hasPermi="['system:role:edit']">删除</el-button>
  46. </el-col>
  47. </el-row>
  48. </el-col>
  49. </el-row>
  50. <div class="roleContrBox roleContrBoxthy">
  51. <el-col :span="24">
  52. <div class="searContLeft">
  53. <el-table v-loading="loading" :data="cloumns" @selection-change="handleSelectionChange" :max-height="tableHeight">
  54. <el-table-column type="selection" width="55" align="center" />
  55. <el-table-column label="序号" align="center" prop="id" />
  56. <el-table-column label="用户角色" align="center" prop="roleName" />
  57. <el-table-column label="权限表单" align="center" prop="tableName" />
  58. <el-table-column label="数据过滤" align="center" prop="dataScope">
  59. <!-- <template slot-scope="scope">
  60. {{scope.row.dataScope | relationTypeFn}}
  61. </template> -->
  62. </el-table-column>
  63. <el-table-column label="是否可用" align="center">
  64. <!-- <template slot="header" slot-scope="scope">
  65. <div><el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange"></el-checkbox>数据过滤4</div>
  66. </template> -->
  67. <template slot-scope="scope">
  68. <el-checkbox true-label="Y" false-label="N" v-model="scope.row.isUse" ></el-checkbox>
  69. </template>
  70. </el-table-column>
  71. </el-table>
  72. </div>
  73. </el-col>
  74. <pagination
  75. v-show="total>0"
  76. :total="total"
  77. :page.sync="queryParamstr.pageNum"
  78. :limit.sync="queryParamstr.pageSize"
  79. @pagination="getDeptTreeselect"
  80. class="pajie"
  81. />
  82. </div>
  83. </el-col>
  84. </el-row>
  85. <!-- 添加或修改对话框 -->
  86. <el-dialog :close-on-click-modal="false" :title="title" :visible.sync="open" width="600px" append-to-body>
  87. <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  88. <el-form-item label="权限表单:" prop="tableName">
  89. <el-input v-model="form.tableName" placeholder="请输入权限表单" />
  90. </el-form-item>
  91. <el-form-item label="权限范围:" prop="dataScope">
  92. <el-select style="width: 100%;" v-model="form.dataScope" placeholder="权限范围" clearable size="small">
  93. <el-option
  94. v-for="dict in statusOptions"
  95. :key="dict.dictValue"
  96. :label="dict.dictLabel"
  97. :value="dict.dictValue"
  98. />
  99. </el-select>
  100. </el-form-item>
  101. </el-form>
  102. <div slot="footer" class="dialog-footer">
  103. <el-button type="primary" @click="submitForm">确 定</el-button>
  104. <el-button @click="cancel">取 消</el-button>
  105. </div>
  106. </el-dialog>
  107. </div>
  108. </template>
  109. <script>
  110. import { listRole, getRole, delRole, addRole, updateRole, exportRole, dataScope, changeRoleStatus } from "@/api/system/role";
  111. import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu";
  112. import { treeselect as deptTreeselect, roleDeptTreeselect } from "@/api/system/dept";
  113. import { listPostporen, addlistPostporen, getRoler,delelistPostporen,piutRoler } from "@/api/system/permisss.js";
  114. export default {
  115. name: "Role",
  116. data() {
  117. return {
  118. searIndex: '',
  119. defaultProps: {
  120. children: 'children',
  121. label: 'label'
  122. },
  123. indexs: 3,
  124. // 遮罩层
  125. loading: true,
  126. // 选中数组
  127. ids: [],
  128. // 非单个禁用
  129. single: true,
  130. // 非多个禁用
  131. multiple: true,
  132. // 显示搜索条件
  133. showSearch: true,
  134. // 总条数
  135. total: 0,
  136. totale:0,
  137. // 角色表格数据
  138. roleList: [],
  139. // 弹出层标题
  140. title: "",
  141. // 是否显示弹出层
  142. open: false,
  143. // 是否显示弹出层(数据权限)
  144. openDataScope: false,
  145. menuExpand: false,
  146. menuNodeAll: false,
  147. deptExpand: true,
  148. deptNodeAll: false,
  149. // 日期范围
  150. dateRange: [],
  151. // 状态数据字典
  152. statusOptions: [],
  153. // 数据范围选项
  154. // 菜单列表
  155. menuOptions: [],
  156. // 部门列表
  157. deptOptions: [],
  158. // 查询参数
  159. queryParams: {
  160. roleName: undefined,
  161. roleId: undefined,
  162. status: undefined,
  163. pageNum: 1,
  164. pageSize: 10,
  165. },
  166. queryParamstr:{
  167. pageNum: 1,
  168. pageSize: 10,
  169. roleId: undefined,
  170. },
  171. // 表单参数
  172. form: {},
  173. // 表单校验
  174. rules: {
  175. roleName: [{
  176. required: true,
  177. message: "角色名称不能为空",
  178. trigger: "blur"
  179. }],
  180. roleKey: [{
  181. required: true,
  182. message: "权限字符不能为空",
  183. trigger: "blur"
  184. }],
  185. roleSort: [{
  186. required: true,
  187. message: "角色顺序不能为空",
  188. trigger: "blur"
  189. }]
  190. },
  191. cloumns:[],
  192. relationType: [],
  193. // 表格的高度
  194. tableHeight: document.documentElement.scrollHeight - 245 + "px",
  195. ijeudid:-1,
  196. indexdw:-1,
  197. isIndeterminate: true,
  198. checkAll: false,
  199. kiejfur:[]
  200. };
  201. },
  202. created() {
  203. this.getDicts("role_data").then(response => {
  204. this.statusOptions = response.data;
  205. this.relationType = response.data
  206. this.getDeptTreeselect()
  207. });
  208. this.getList();
  209. },
  210. filters: {
  211. relationTypeFn(data) {
  212. var _this = this
  213. let is = ''
  214. for (let item of that.relationType) {
  215. if (item.dictValue == data) {
  216. is = item.dictLabel
  217. }
  218. }
  219. return is
  220. },
  221. },
  222. methods: {
  223. handleNodeClick() {
  224. },
  225. /** 查询角色列表 */
  226. getList() {
  227. this.loading = true;
  228. this.roleList = []
  229. listRole(this.addDateRange(this.queryParams, this.dateRange)).then(
  230. response => {
  231. if(response.rows.length !==0){
  232. this.roleList = response.rows;
  233. this.totale = response.total;
  234. }else{
  235. this.roleList.push({roleName:'暂无数据'})
  236. }
  237. // this.total = response.total;
  238. this.loading = false;
  239. }
  240. );
  241. },
  242. /** 查询菜单树结构 */
  243. getMenuTreeselect() {
  244. menuTreeselect().then(response => {
  245. this.menuOptions = response.data;
  246. });
  247. },
  248. /** 查询列表数据*/
  249. getDeptTreeselect() {
  250. listPostporen(this.queryParamstr).then(response => {
  251. this.cloumns = response.rows;
  252. this.total = response.total
  253. // this.cloumns.
  254. this.cloumns.filter(route => {
  255. for(var item in route){
  256. if(item == 'dataScope'){
  257. console.log(route[item])
  258. console.log(this.relationType)
  259. this.relationType.filter(router =>{
  260. console.log(router)
  261. if(router.dictValue == route[item]){
  262. route[item] = router.dictLabel
  263. }
  264. })
  265. }
  266. }
  267. })
  268. });
  269. },
  270. /** 根据角色ID查询菜单树结构 */
  271. getRoleMenuTreeselect(id) {
  272. return roleMenuTreeselect(id).then(response => {
  273. this.menuOptions = response.menus;
  274. return response;
  275. });
  276. },
  277. /** 根据角色ID查询部门树结构 */
  278. getRoleDeptTreeselect(id) {
  279. return roleDeptTreeselect(id).then(response => {
  280. this.deptOptions = response.depts;
  281. return response;
  282. });
  283. },
  284. // 角色状态修改
  285. handleStatusChange(row) {
  286. let text = row.status === "0" ? "启用" : "停用";
  287. this.$confirm('确认要"' + text + '""' + row.roleName + '"角色吗?', "警告", {
  288. confirmButtonText: "确定",
  289. cancelButtonText: "取消",
  290. type: "warning"
  291. }).then(function() {
  292. return changeRoleStatus(row.id, row.status);
  293. }).then(() => {
  294. this.msgSuccess(text + "成功");
  295. }).catch(function() {
  296. row.status = row.status === "0" ? "1" : "0";
  297. });
  298. },
  299. // 取消按钮
  300. cancel() {
  301. this.open = false;
  302. this.reset();
  303. },
  304. // 取消按钮(数据权限)
  305. cancelDataScope() {
  306. this.openDataScope = false;
  307. this.reset();
  308. },
  309. // 表单重置
  310. reset() {
  311. this.form = {
  312. };
  313. this.resetForm("form");
  314. },
  315. /** 搜索按钮操作 */
  316. handleQuery() {
  317. this.queryParams.pageNum = 1;
  318. this.getList();
  319. },
  320. /** 重置按钮操作 */
  321. resetQuery() {
  322. this.dateRange = [];
  323. this.resetForm("queryForm");
  324. this.handleQuery();
  325. },
  326. // 多选框选中数据
  327. handleSelectionChange(selection) {
  328. this.ids = selection.map(item => item.id)
  329. this.single = selection.length != 1
  330. this.multiple = !selection.length
  331. },
  332. /** 新增按钮操作 */
  333. handleAdd() {
  334. this.reset();
  335. // this.getMenuTreeselect();
  336. this.open = true;
  337. this.title = "添加数据权限";
  338. },
  339. /** 修改按钮操作 */
  340. handleUpdate(row) {
  341. this.reset();
  342. const id = row.id || this.ids
  343. // const roleMenu = this.getRoleMenuTreeselect(id);
  344. getRoler(id).then(response => {
  345. this.form = response.data;
  346. this.open = true;
  347. this.$nextTick(() => {
  348. roleMenu.then(res => {
  349. let checkedKeys = res.checkedKeys
  350. checkedKeys.forEach((v) => {
  351. this.$nextTick(() => {
  352. this.$refs.menu.setChecked(v, true, false);
  353. })
  354. })
  355. });
  356. });
  357. this.title = "修改数据权限";
  358. });
  359. },
  360. /** 选择角色权限范围触发 */
  361. dataScopeSelectChange(value) {
  362. if (value !== '2') {
  363. this.$refs.dept.setCheckedKeys([]);
  364. }
  365. },
  366. /** 分配数据权限操作 */
  367. handleDataScope(row) {
  368. this.reset();
  369. const roleDeptTreeselect = this.getRoleDeptTreeselect(row.id);
  370. getRole(row.id).then(response => {
  371. this.form = response.data;
  372. this.openDataScope = true;
  373. this.$nextTick(() => {
  374. roleDeptTreeselect.then(res => {
  375. this.$refs.dept.setCheckedKeys(res.checkedKeys);
  376. });
  377. });
  378. this.title = "分配数据权限";
  379. });
  380. },
  381. /** 提交按钮 */
  382. submitForm: function() {
  383. this.$refs["form"].validate(valid => {
  384. if (valid) {
  385. if (this.form.id != undefined) {
  386. // this.form.menuIds = this.getMenuAllCheckedKeys();
  387. piutRoler(this.form).then(response => {
  388. this.msgSuccess("修改成功");
  389. this.open = false;
  390. this.getDeptTreeselect();
  391. });
  392. } else {
  393. // this.form.menuIds = this.getMenuAllCheckedKeys();
  394. this.form.roleId = this.ijeudid
  395. if(this.form.roleId !== -1){
  396. addlistPostporen(this.form).then(response => {
  397. this.msgSuccess("新增成功");
  398. this.open = false;
  399. this.getDeptTreeselect();
  400. });
  401. }else{
  402. this.msgSuccess("请先选择角色在添加");
  403. this.open = false
  404. }
  405. }
  406. }
  407. });
  408. },
  409. /** 提交按钮(数据权限) */
  410. submitDataScope: function() {
  411. if (this.form.id != undefined) {
  412. this.form.deptIds = this.getDeptAllCheckedKeys();
  413. dataScope(this.form).then(response => {
  414. this.msgSuccess("修改成功");
  415. this.openDataScope = false;
  416. // this.getDeptTreeselect();
  417. });
  418. }
  419. },
  420. /** 删除按钮操作 */
  421. handleDelete(row) {
  422. const ids = row.id || this.ids;
  423. this.$confirm('是否确认删除角色编号为"' + ids + '"的数据项?', "警告", {
  424. confirmButtonText: "确定",
  425. cancelButtonText: "取消",
  426. type: "warning"
  427. }).then(function() {
  428. return delelistPostporen(ids);
  429. }).then(() => {
  430. this.getDeptTreeselect();
  431. this.msgSuccess("删除成功");
  432. })
  433. },
  434. /** 导出按钮操作 */
  435. handleExport() {
  436. this.download('system/role/export', {
  437. ...this.queryParams
  438. }, `role_${new Date().getTime()}.xlsx`)
  439. },
  440. // 查询
  441. quregu(){
  442. this.getList()
  443. },
  444. // 刷新
  445. efresh(){
  446. this.queryParams.roleName = undefined
  447. this.getList()
  448. this.queryParamstr.roleId = undefined
  449. this.getDeptTreeselect()
  450. },
  451. // 点击角色id
  452. jieese(id,index){
  453. this.indexdw = index
  454. this.ijeudid = id
  455. this.queryParamstr.roleId = id
  456. this.getDeptTreeselect()
  457. },
  458. handleCheckAllChange(val) {
  459. if(val == true){
  460. this.cloumns.filter(router =>{
  461. router.isUse = 'Y'
  462. })
  463. }else{
  464. this.cloumns.filter(router =>{
  465. router.isUse = 'N'
  466. })
  467. }
  468. this.isIndeterminate = false;
  469. },
  470. handleCheckedCitiesChange(value) {
  471. }
  472. }
  473. };
  474. </script>
  475. <style lang="scss">
  476. .roleContrBoxthy{
  477. position: relative;
  478. .pagination-container{
  479. // position: fixed;
  480. position: absolute;
  481. bottom: 10px;
  482. right: 20px;
  483. margin-top: 87px;
  484. }
  485. }
  486. .app-containerth{
  487. .pajie{
  488. bottom: 30px;
  489. }
  490. }
  491. </style>
  492. <style lang="scss" scoped>
  493. .roleContrBox {
  494. background-color: #fff;
  495. // border-radius: 6px;
  496. overflow: hidden;
  497. padding: 23px 0;
  498. height: calc(95vh - 168px);;
  499. }
  500. .roleContr {
  501. padding-left: 17px;
  502. height: calc(100% - 168px);
  503. .searContLeft {
  504. padding:0 17px 23px 23px;
  505. // border-right: 2px solid #E5E5E5;
  506. }
  507. .searContRight {
  508. padding-left: 18px;
  509. .searTitle {
  510. display: flex;
  511. padding-left: 11px;
  512. margin-bottom: 26px;
  513. .searName {
  514. color: #343434;
  515. font-size: 12px;
  516. width: 156px;
  517. }
  518. .searItem {
  519. flex: 1;
  520. font-size: 12px;
  521. }
  522. }
  523. .searCont {
  524. display: flex;
  525. height: 23px;
  526. padding-left: 11px;
  527. align-items: center;
  528. margin-bottom: 4px;
  529. cursor: pointer;
  530. .searName {
  531. color: #343434;
  532. font-size: 12px;
  533. width: 156px;
  534. }
  535. .searItem {
  536. flex: 1;
  537. font-size: 12px;
  538. }
  539. &:hover {
  540. background-color: rgba(0, 0, 0, .1);
  541. }
  542. }
  543. .active {
  544. background-color: #CADBE4 !important;
  545. .searName {
  546. color: #fff;
  547. }
  548. }
  549. }
  550. }
  551. .searBoxstu{
  552. // height: 100vh;
  553. // height: calc(100vh - 70px);
  554. // background-color: #fff;
  555. }
  556. .searBoxs {
  557. background-color: #fff;
  558. border-radius: 6px;
  559. padding: 23px;
  560. height: calc(100vh - 140px); ;
  561. min-height: calc(100vh - 140px);
  562. .searBox {
  563. display: flex;
  564. .searInput {
  565. flex: 1;
  566. height: 32px;
  567. margin-right: 8px;
  568. box-sizing: border-box;
  569. border-radius: 4px;
  570. overflow: hidden;
  571. }
  572. input {
  573. width: 100%;
  574. height: 100%;
  575. background-color: #F7F6F6;
  576. border: none;
  577. padding: 0 7px;
  578. outline: none;
  579. &::placeholder {
  580. color: #AAAAAA;
  581. font-size: 12px;
  582. }
  583. }
  584. .searBtn {
  585. width: 30px;
  586. height: 32px;
  587. display: flex;
  588. justify-content: center;
  589. align-items: center;
  590. background-color: #3C8DBC;
  591. cursor: pointer;
  592. border-radius: 4px;
  593. overflow: hidden;
  594. .icon {
  595. width: 18px;
  596. height: 17px;
  597. }
  598. }
  599. }
  600. .searList {
  601. padding: 10px 0;
  602. height: 70%;
  603. .searItem {
  604. padding: 0 8px;
  605. line-height: 30px;
  606. font-size: 12px;
  607. color: #343434;
  608. cursor: pointer;
  609. }
  610. .active {
  611. background-color: #CADBE4;
  612. color: #3C8DBC;
  613. }
  614. }
  615. }
  616. .app-container {
  617. background-color: #EFF0FF;
  618. // min-height: calc(100vh - 70px);
  619. box-sizing: border-box;
  620. box-sizing: border-box;
  621. }
  622. .roleBox {
  623. padding: 0 23px;
  624. background: #fff;
  625. // border-radius: 6px;
  626. .roleCol {
  627. padding: 20px 0;
  628. border-bottom: 1px solid #E5E5E5;
  629. .roleH {
  630. width: 18px;
  631. height: 8px;
  632. border-radius: 4px;
  633. background-color: #3C8DBC;
  634. margin-bottom: 8px;
  635. }
  636. span {
  637. font-size: 15px;
  638. color: #3C8DBC;
  639. }
  640. }
  641. .roleBot {
  642. padding: 22px 0;
  643. padding-bottom: 0;
  644. .roleBtn {
  645. height: 32px;
  646. display: flex;
  647. border-radius: 3px;
  648. justify-content: center;
  649. align-items: center;
  650. width: 83px;
  651. margin-right: 18px;
  652. .icon {
  653. width: 14px;
  654. height: 14px;
  655. margin-right: 7px;
  656. }
  657. span {
  658. color: #fff;
  659. font-size: 12px;
  660. }
  661. }
  662. }
  663. }
  664. .roleBotyu{
  665. padding: 0;
  666. padding-bottom: 22px;
  667. padding-top: 1px;
  668. }
  669. .roleBoxui{
  670. padding-left: 0;
  671. }
  672. </style>
  673. <style>
  674. .el-icon-my-export{
  675. background: url('~@/assets/images/icon_btn_bc@2x.png') center no-repeat;
  676. background-size: 13px 13px;
  677. /* background-size: cover;*/
  678. }
  679. .el-icon-my-export:before{
  680. content: "替";
  681. font-size: 16px;
  682. visibility: hidden;
  683. }
  684. .el-icon-my-export{
  685. font-size: 16px;
  686. }
  687. .el-icon-my-export:before{
  688. content: "\e611";
  689. }
  690. </style>