RoleManagement.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. <template>
  2. <div class="role-management">
  3. <!-- 页面标题 -->
  4. <div class="page-header">
  5. <h2>角色管理</h2>
  6. <div class="header-actions">
  7. <button class="btn btn-primary" @click="addRole">添加角色</button>
  8. <button class="btn btn-secondary" @click="refreshRoles">刷新</button>
  9. </div>
  10. </div>
  11. <!-- 角色列表 -->
  12. <div class="role-list">
  13. <el-table
  14. :data="roles"
  15. style="width: 100%"
  16. border
  17. stripe
  18. >
  19. <el-table-column
  20. prop="id"
  21. label="ID"
  22. width="80"
  23. align="center"
  24. />
  25. <el-table-column
  26. prop="name"
  27. label="角色名称"
  28. min-width="150"
  29. />
  30. <el-table-column
  31. prop="description"
  32. label="角色描述"
  33. min-width="300"
  34. />
  35. <el-table-column
  36. prop="createTime"
  37. label="创建时间"
  38. width="180"
  39. align="center"
  40. />
  41. <el-table-column
  42. prop="userCount"
  43. label="用户数量"
  44. width="100"
  45. align="center"
  46. />
  47. <el-table-column
  48. label="操作"
  49. width="200"
  50. align="center"
  51. >
  52. <template #default="scope">
  53. <el-button
  54. type="primary"
  55. size="small"
  56. @click="editRole(scope.row)"
  57. style="margin-right: 8px"
  58. >
  59. 编辑
  60. </el-button>
  61. <el-button
  62. type="warning"
  63. size="small"
  64. @click="managePermissions(scope.row)"
  65. style="margin-right: 8px"
  66. >
  67. 权限
  68. </el-button>
  69. <el-button
  70. type="danger"
  71. size="small"
  72. @click="deleteRole(scope.row.id)"
  73. :disabled="scope.row.name === '管理员'"
  74. >
  75. 删除
  76. </el-button>
  77. </template>
  78. </el-table-column>
  79. </el-table>
  80. </div>
  81. <!-- 分页 -->
  82. <div v-if="roles.length > 0" class="pagination">
  83. <el-pagination
  84. v-model:current-page="currentPage"
  85. v-model:page-size="pageSize"
  86. :page-sizes="[10, 20, 50, 100]"
  87. layout="total, sizes, prev, pager, next, jumper"
  88. :total="roles.length"
  89. @size-change="handleSizeChange"
  90. @current-change="handleCurrentChange"
  91. />
  92. </div>
  93. <!-- 角色表单对话框 -->
  94. <el-dialog
  95. v-model="dialogVisible"
  96. :title="isEditing ? '编辑角色' : '添加角色'"
  97. width="500px"
  98. >
  99. <el-form
  100. :model="roleForm"
  101. :rules="rules"
  102. ref="roleFormRef"
  103. label-width="100px"
  104. >
  105. <el-form-item label="角色名称" prop="name">
  106. <el-input v-model="roleForm.name" placeholder="请输入角色名称" />
  107. </el-form-item>
  108. <el-form-item label="角色描述" prop="description">
  109. <el-input
  110. v-model="roleForm.description"
  111. type="textarea"
  112. rows="3"
  113. placeholder="请输入角色描述"
  114. />
  115. </el-form-item>
  116. </el-form>
  117. <template #footer>
  118. <span class="dialog-footer">
  119. <el-button @click="dialogVisible = false">取消</el-button>
  120. <el-button type="primary" @click="submitForm">保存</el-button>
  121. </span>
  122. </template>
  123. </el-dialog>
  124. <!-- 权限管理对话框 -->
  125. <el-dialog
  126. v-model="permissionDialogVisible"
  127. title="权限管理"
  128. width="600px"
  129. >
  130. <div class="permission-management">
  131. <h3>{{ selectedRole.name }} - 权限设置</h3>
  132. <el-tree
  133. :data="permissionTree"
  134. show-checkbox
  135. node-key="id"
  136. default-expand-all
  137. v-model:checkedKeys="checkedPermissions"
  138. @check="handlePermissionCheck"
  139. >
  140. <template #default="{ node }">
  141. <span class="permission-node">
  142. {{ node.label }}
  143. </span>
  144. </template>
  145. </el-tree>
  146. </div>
  147. <template #footer>
  148. <span class="dialog-footer">
  149. <el-button @click="permissionDialogVisible = false">取消</el-button>
  150. <el-button type="primary" @click="savePermissions">保存权限</el-button>
  151. </span>
  152. </template>
  153. </el-dialog>
  154. </div>
  155. </template>
  156. <script>
  157. export default {
  158. name: 'RoleManagement',
  159. data() {
  160. return {
  161. // 角色列表
  162. roles: [
  163. {
  164. id: 1,
  165. name: '管理员',
  166. description: '系统管理员,拥有所有权限',
  167. createTime: '2024-01-01 00:00:00',
  168. userCount: 2
  169. },
  170. {
  171. id: 2,
  172. name: '操作员',
  173. description: '普通操作员,拥有基本操作权限',
  174. createTime: '2024-01-01 00:00:00',
  175. userCount: 15
  176. },
  177. {
  178. id: 3,
  179. name: '查看员',
  180. description: '只读权限,只能查看数据',
  181. createTime: '2024-01-01 00:00:00',
  182. userCount: 8
  183. }
  184. ],
  185. // 分页信息
  186. currentPage: 1,
  187. pageSize: 10,
  188. // 对话框可见性
  189. dialogVisible: false,
  190. permissionDialogVisible: false,
  191. // 是否为编辑模式
  192. isEditing: false,
  193. // 角色表单
  194. roleForm: {
  195. id: '',
  196. name: '',
  197. description: ''
  198. },
  199. // 选中的角色
  200. selectedRole: {},
  201. // 表单验证规则
  202. rules: {
  203. name: [
  204. { required: true, message: '请输入角色名称', trigger: 'blur' },
  205. { min: 2, max: 50, message: '角色名称长度应在2-50个字符之间', trigger: 'blur' }
  206. ],
  207. description: [
  208. { required: true, message: '请输入角色描述', trigger: 'blur' },
  209. { min: 5, message: '角色描述长度至少为5个字符', trigger: 'blur' }
  210. ]
  211. },
  212. // 权限树
  213. permissionTree: [
  214. {
  215. id: 1,
  216. label: '系统管理',
  217. children: [
  218. {
  219. id: 11,
  220. label: '用户管理'
  221. },
  222. {
  223. id: 12,
  224. label: '角色管理'
  225. },
  226. {
  227. id: 13,
  228. label: '权限管理'
  229. },
  230. {
  231. id: 14,
  232. label: '系统设置'
  233. }
  234. ]
  235. },
  236. {
  237. id: 2,
  238. label: '拖轮管理',
  239. children: [
  240. {
  241. id: 21,
  242. label: '拖轮列表'
  243. },
  244. {
  245. id: 22,
  246. label: '拖轮详情'
  247. },
  248. {
  249. id: 23,
  250. label: '拖轮状态'
  251. },
  252. {
  253. id: 24,
  254. label: '拖轮维护'
  255. }
  256. ]
  257. },
  258. {
  259. id: 3,
  260. label: '任务管理',
  261. children: [
  262. {
  263. id: 31,
  264. label: '任务列表'
  265. },
  266. {
  267. id: 32,
  268. label: '任务分配'
  269. },
  270. {
  271. id: 33,
  272. label: '任务执行'
  273. },
  274. {
  275. id: 34,
  276. label: '任务统计'
  277. }
  278. ]
  279. },
  280. {
  281. id: 4,
  282. label: '报警管理',
  283. children: [
  284. {
  285. id: 41,
  286. label: '报警列表'
  287. },
  288. {
  289. id: 42,
  290. label: '报警处理'
  291. },
  292. {
  293. id: 43,
  294. label: '报警统计'
  295. }
  296. ]
  297. },
  298. {
  299. id: 5,
  300. label: '报表管理',
  301. children: [
  302. {
  303. id: 51,
  304. label: '运行报表'
  305. },
  306. {
  307. id: 52,
  308. label: '任务报表'
  309. },
  310. {
  311. id: 53,
  312. label: '报警报表'
  313. }
  314. ]
  315. }
  316. ],
  317. // 选中的权限
  318. checkedPermissions: []
  319. }
  320. },
  321. mounted() {
  322. // 初始化加载角色
  323. this.loadRoles()
  324. },
  325. methods: {
  326. // 加载角色
  327. loadRoles() {
  328. // 实际项目中,这里应该调用后端API获取角色列表
  329. // 模拟API调用
  330. setTimeout(() => {
  331. console.log('Roles loaded successfully')
  332. }, 500)
  333. },
  334. // 刷新角色
  335. refreshRoles() {
  336. this.loadRoles()
  337. this.$message.success('角色列表已刷新')
  338. },
  339. // 添加角色
  340. addRole() {
  341. this.roleForm = {
  342. id: '',
  343. name: '',
  344. description: ''
  345. }
  346. this.isEditing = false
  347. this.dialogVisible = true
  348. },
  349. // 编辑角色
  350. editRole(role) {
  351. this.roleForm = { ...role }
  352. this.isEditing = true
  353. this.dialogVisible = true
  354. },
  355. // 删除角色
  356. deleteRole(id) {
  357. this.$confirm('确定要删除此角色吗?', '警告', {
  358. confirmButtonText: '确定',
  359. cancelButtonText: '取消',
  360. type: 'warning'
  361. }).then(() => {
  362. const index = this.roles.findIndex(role => role.id === id)
  363. if (index !== -1) {
  364. this.roles.splice(index, 1)
  365. this.$message.success('角色已删除')
  366. }
  367. }).catch(() => {
  368. // 取消删除
  369. })
  370. },
  371. // 提交表单
  372. submitForm() {
  373. this.$refs.roleFormRef.validate((valid) => {
  374. if (valid) {
  375. if (this.isEditing) {
  376. // 编辑角色
  377. const index = this.roles.findIndex(role => role.id === this.roleForm.id)
  378. if (index !== -1) {
  379. this.roles[index] = { ...this.roleForm }
  380. this.$message.success('角色已更新')
  381. }
  382. } else {
  383. // 添加角色
  384. const newRole = {
  385. ...this.roleForm,
  386. id: this.roles.length + 1,
  387. createTime: new Date().toLocaleString('zh-CN'),
  388. userCount: 0
  389. }
  390. this.roles.push(newRole)
  391. this.$message.success('角色已添加')
  392. }
  393. this.dialogVisible = false
  394. } else {
  395. return false
  396. }
  397. })
  398. },
  399. // 管理权限
  400. managePermissions(role) {
  401. this.selectedRole = { ...role }
  402. // 模拟加载角色权限
  403. this.checkedPermissions = this.getRolePermissions(role.id)
  404. this.permissionDialogVisible = true
  405. },
  406. // 获取角色权限
  407. getRolePermissions(roleId) {
  408. // 实际项目中,这里应该调用后端API获取角色权限
  409. // 模拟数据
  410. if (roleId === 1) {
  411. // 管理员拥有所有权限
  412. return [1, 11, 12, 13, 14, 2, 21, 22, 23, 24, 3, 31, 32, 33, 34, 4, 41, 42, 43, 5, 51, 52, 53]
  413. } else if (roleId === 2) {
  414. // 操作员拥有部分权限
  415. return [2, 21, 22, 23, 3, 31, 32, 33, 4, 41, 42]
  416. } else {
  417. // 查看员只拥有查看权限
  418. return [21, 22, 23, 31, 41, 51, 52, 53]
  419. }
  420. },
  421. // 处理权限选择
  422. handlePermissionCheck() {
  423. // 权限选择逻辑
  424. },
  425. // 保存权限
  426. savePermissions() {
  427. // 实际项目中,这里应该调用后端API保存角色权限
  428. // 模拟保存
  429. setTimeout(() => {
  430. this.$message.success('权限已保存')
  431. this.permissionDialogVisible = false
  432. }, 500)
  433. },
  434. // 分页处理
  435. handleSizeChange(size) {
  436. this.pageSize = size
  437. },
  438. handleCurrentChange(current) {
  439. this.currentPage = current
  440. }
  441. }
  442. }
  443. </script>
  444. <style scoped>
  445. .role-management {
  446. padding: 20px 0;
  447. }
  448. /* 页面标题 */
  449. .page-header {
  450. display: flex;
  451. justify-content: space-between;
  452. align-items: center;
  453. margin-bottom: 24px;
  454. padding-bottom: 16px;
  455. border-bottom: 1px solid #e2e8f0;
  456. }
  457. .page-header h2 {
  458. margin: 0;
  459. color: #1e293b;
  460. font-size: 24px;
  461. font-weight: 600;
  462. }
  463. .header-actions {
  464. display: flex;
  465. gap: 12px;
  466. }
  467. /* 角色列表 */
  468. .role-list {
  469. margin-bottom: 24px;
  470. }
  471. /* 分页 */
  472. .pagination {
  473. display: flex;
  474. justify-content: flex-end;
  475. margin-top: 30px;
  476. }
  477. /* 权限管理 */
  478. .permission-management {
  479. margin-bottom: 20px;
  480. }
  481. .permission-management h3 {
  482. margin: 0 0 20px 0;
  483. color: #1e293b;
  484. font-size: 18px;
  485. font-weight: 600;
  486. }
  487. .permission-node {
  488. font-size: 14px;
  489. }
  490. /* 响应式设计 */
  491. @media (max-width: 768px) {
  492. .page-header {
  493. flex-direction: column;
  494. align-items: flex-start;
  495. gap: 12px;
  496. }
  497. .header-actions {
  498. width: 100%;
  499. justify-content: flex-start;
  500. }
  501. .pagination {
  502. justify-content: center;
  503. }
  504. }
  505. </style>