Commit 90b3d43bb2d77ac0db222147bbbc68147abef4c1

Authored by 杨泽宇
1 parent 6d135206

角色管理 登录 菜单

src/api/login/index.ts deleted 100644 → 0
1 -import request from '../request'  
2 -import { AxiosRequestConfig } from 'axios';  
3 -  
4 -export const login = async ( params: any, data: any ) => {  
5 - // let res: any = await request.post( '/login', data, {userName: '123', password: 'cmnt123'} )  
6 - let res: any = await request({  
7 - url: '/login',  
8 - method: 'post',  
9 - data: {  
10 - userName: '123',  
11 - password: 'cmnt123'  
12 - }  
13 - })  
14 - // let res: any = await request( {url: '/neighborhood/getList', params:{propertyId: 1, type: 1}, method: 'post' })  
15 - return res  
16 -}  
17 \ No newline at end of file 0 \ No newline at end of file
src/api/user/login/index.ts
1 import request from '../../request' 1 import request from '../../request'
2 -import { AxiosRequestConfig } from 'axios';  
3 2
4 -export const login = async ( params: any, data: any ) => {  
5 - // let res: any = await request.post( '/login', data, {userName: '123', password: 'cmnt123'} ) 3 +/**
  4 + * @description 登录
  5 + * @function login
  6 + */
  7 +export const login = async ( data: any ) => {
6 let res: any = await request({ 8 let res: any = await request({
7 url: '/login', 9 url: '/login',
8 method: 'post', 10 method: 'post',
9 - data: {  
10 - userName: '123',  
11 - password: 'cmnt123'  
12 - } 11 + data: data
  12 + })
  13 + return res
  14 +}
  15 +
  16 +/**
  17 + * @description 权限菜单
  18 + * @function menuData
  19 + */
  20 +export const menuData = async () => {
  21 + let res: any = await request({
  22 + url: '/permission/list',
  23 + method: 'get',
13 }) 24 })
14 - // let res: any = await request( {url: '/neighborhood/getList', params:{propertyId: 1, type: 1}, method: 'post' })  
15 return res 25 return res
16 } 26 }
17 \ No newline at end of file 27 \ No newline at end of file
src/api/user/role/index.ts
1 import request from '../../request' 1 import request from '../../request'
2 -import {formDataWrapper} from '@/utils/tool' 2 +import {formDataWrapper, deleteEmptyParam} from '@/utils/tool'
3 3
4 /** 4 /**
5 * @description 角色列表 5 * @description 角色列表
@@ -9,7 +9,64 @@ export const roleList = async ( params: any ) => { @@ -9,7 +9,64 @@ export const roleList = async ( params: any ) => {
9 let res: any = await request({ 9 let res: any = await request({
10 url: '/role/list', 10 url: '/role/list',
11 method: 'get', 11 method: 'get',
  12 + params: deleteEmptyParam(params)
  13 + })
  14 + return res
  15 +}
  16 +
  17 +/**
  18 + * @description 角色权限
  19 + * @function rolePermission
  20 + */
  21 + export const rolePermission = async ( params: any ) => {
  22 + let res: any = await request({
  23 + url: '/role/user/permission',
  24 + method: 'get',
  25 + params: params
  26 + })
  27 + return res
  28 +}
  29 +
  30 +/**
  31 + * @description 角色用户列表
  32 + * @function roleUser
  33 + */
  34 + export const roleUser = async ( params: any ) => {
  35 + let res: any = await request({
  36 + url: '/role/user',
  37 + method: 'put',
12 params: params 38 params: params
13 }) 39 })
14 return res 40 return res
  41 +}
  42 +
  43 +/**
  44 + * @description 角色添加修改
  45 + * @function roleSave
  46 + */
  47 + export const roleSave = async ( params: any ) => {
  48 + let res: any = await request({
  49 + url: '/role/save',
  50 + method: 'put',
  51 + data: params
  52 + })
  53 + return res
  54 +}
  55 +
  56 +/**
  57 + * @description 修改角色状态
  58 + * @function roleStatus
  59 + */
  60 + export const roleStatus = async (data: any) => {
  61 + let res: any = await request.put( '/role/status', formDataWrapper(data) )
  62 + return res
  63 +}
  64 +
  65 +/**
  66 + * @description 角色关联权限
  67 + * @function rolePermissionSave
  68 + */
  69 + export const rolePermissionSave = async (data: any) => {
  70 + let res: any = await request.post( '/role/permission', data )
  71 + return res
15 } 72 }
16 \ No newline at end of file 73 \ No newline at end of file
src/layout/menu.vue
@@ -18,10 +18,15 @@ import { @@ -18,10 +18,15 @@ import {
18 let styleData = computed(() => { 18 let styleData = computed(() => {
19 return styles; 19 return styles;
20 }); 20 });
  21 +let menuData = computed(() => {
  22 + let res = store.family.menuStore().menuList;
  23 + return res;
  24 +});
21 </script> 25 </script>
22 26
23 <template> 27 <template>
24 <el-scrollbar wrap-class="scrollbar-wrapper"> 28 <el-scrollbar wrap-class="scrollbar-wrapper">
  29 + <!-- {{menuData}} -->
25 <el-menu 30 <el-menu
26 default-active="2" 31 default-active="2"
27 :background-color="styleData.menuBg" 32 :background-color="styleData.menuBg"
@@ -32,41 +37,58 @@ let styleData = computed(() =&gt; { @@ -32,41 +37,58 @@ let styleData = computed(() =&gt; {
32 :collapse-transition="false" 37 :collapse-transition="false"
33 :collapse="store.family.appStore().isCollapse" 38 :collapse="store.family.appStore().isCollapse"
34 > 39 >
35 - <el-sub-menu index="1"> 40 + <el-sub-menu
  41 + :index="index + ''"
  42 + v-for="(item, index) in menuData"
  43 + :key="index"
  44 + >
  45 + <template #title>
  46 + <el-icon><location /></el-icon>
  47 + <span>{{ item.name }}假菜单</span>
  48 + </template>
  49 + <el-menu-item-group v-for="(ele, i) in item.menuList" :key="i">
  50 + <el-menu-item :index="ele.path ? ele.path : '/'">{{
  51 + ele.name
  52 + }}</el-menu-item>
  53 + </el-menu-item-group>
  54 + </el-sub-menu>
  55 +
  56 + <el-sub-menu index="11">
36 <template #title> 57 <template #title>
37 <el-icon><location /></el-icon> 58 <el-icon><location /></el-icon>
38 - <span>物业管理</span> 59 + <span>物业管理真菜单可点</span>
39 </template> 60 </template>
40 <el-menu-item-group> 61 <el-menu-item-group>
41 <el-menu-item index="/property">物业列表</el-menu-item> 62 <el-menu-item index="/property">物业列表</el-menu-item>
42 </el-menu-item-group> 63 </el-menu-item-group>
43 </el-sub-menu> 64 </el-sub-menu>
44 - <el-sub-menu index="2"> 65 + <el-sub-menu index="12">
45 <template #title> 66 <template #title>
46 <el-icon><location /></el-icon> 67 <el-icon><location /></el-icon>
47 - <span>小区管理</span> 68 + <span>小区管理真菜单可点</span>
48 </template> 69 </template>
49 <el-menu-item-group> 70 <el-menu-item-group>
50 <el-menu-item index="/">小区管理</el-menu-item> 71 <el-menu-item index="/">小区管理</el-menu-item>
51 </el-menu-item-group> 72 </el-menu-item-group>
52 </el-sub-menu> 73 </el-sub-menu>
53 - <el-sub-menu index="3"> 74 + <el-sub-menu index="13">
54 <template #title> 75 <template #title>
55 <el-icon><location /></el-icon> 76 <el-icon><location /></el-icon>
56 - <span>用户管理</span> 77 + <span>用户管理真菜单可点</span>
57 </template> 78 </template>
58 <el-menu-item-group> 79 <el-menu-item-group>
59 <el-menu-item index="/user">用户列表</el-menu-item> 80 <el-menu-item index="/user">用户列表</el-menu-item>
60 </el-menu-item-group> 81 </el-menu-item-group>
61 </el-sub-menu> 82 </el-sub-menu>
62 - <!-- <el-menu-item index="3" disabled>  
63 - <el-icon><document /></el-icon>  
64 - <template #title>Navigator Three</template>  
65 - </el-menu-item> -->  
66 - <el-menu-item index="4">  
67 - <el-icon><setting /></el-icon>  
68 - <template #title>Navigator Four</template>  
69 - </el-menu-item> 83 + <el-sub-menu index="14">
  84 + <template #title>
  85 + <el-icon><location /></el-icon>
  86 + <span>角色管理真菜单可点</span>
  87 + </template>
  88 + <el-menu-item-group>
  89 + <el-menu-item index="/role">角色列表</el-menu-item>
  90 + </el-menu-item-group>
  91 + </el-sub-menu>
70 </el-menu> 92 </el-menu>
71 </el-scrollbar> 93 </el-scrollbar>
72 </template> 94 </template>
src/pinia/modules/app.ts
1 -const id = 'app' 1 +const id: string = 'app'
2 const state = () => ({ 2 const state = () => ({
3 - isCollapse: false,  
4 - })  
5 - const getters = {  
6 - getCollapseStatus () {  
7 - return this.isCollapse  
8 - }  
9 - }  
10 - const actions = {  
11 - toggleCollapse() {  
12 - this.isCollapse = !this.isCollapse  
13 - }, 3 + isCollapse: false,
  4 +})
  5 +const getters = {
  6 + getCollapseStatus () {
  7 + return this.isCollapse
14 } 8 }
  9 +}
  10 +const actions = {
  11 + toggleCollapse() {
  12 + this.isCollapse = !this.isCollapse
  13 + },
  14 +}
15 15
16 export default { 16 export default {
17 namespace: true, 17 namespace: true,
src/pinia/modules/login.ts
1 -const id = 'login'  
2 -const state = () => ({ 1 +interface LoginUser {
  2 + token: string,
  3 + organizationId: number,
  4 + id: number,
  5 + userName: string
  6 +}
  7 +const id: string = 'login'
  8 +const state: Function = () => ({
3 token: '', 9 token: '',
  10 + organizationId: null,
  11 + id: null,
  12 + userName: ''
4 }) 13 })
5 const getters = { 14 const getters = {
6 - // getCollapseStatus () {  
7 - // return this.isCollapse  
8 - // }  
9 getToken() { 15 getToken() {
10 return this.token 16 return this.token
  17 + },
  18 + getOid() {
  19 + return this.organizationId
  20 + },
  21 + getId() {
  22 + return this.id
  23 + },
  24 + getUserName() {
  25 + return this.userName
11 } 26 }
12 } 27 }
13 const actions = { 28 const actions = {
14 - setToken(tokenStr: string) {  
15 - this.token = tokenStr 29 + setUserInfo(obj: LoginUser) {
  30 + this.token = obj.token
  31 + this.organizationId = obj.organizationId
  32 + this.id = obj.id
  33 + this.userName = obj.userName
16 } 34 }
17 } 35 }
18 36
src/pinia/modules/menu.ts
1 -const id = 'menu'  
2 -const state = () => ({  
3 - data1: '10086',  
4 - desc: 'test',  
5 - })  
6 - const getters = {  
7 - doubleCount() {  
8 - return this.desc  
9 - },  
10 - doubleCountPlusOne() {  
11 - return this.data1  
12 - } 1 +interface MenuItem {
  2 + menuList: MenuItem[],
  3 + id: number,
  4 + name: string,
  5 + priority: number,
  6 + url: string | null,
  7 + selected: boolean,
  8 + parentId: number | null,
  9 + keyword: string | null,
  10 + status: number
  11 +}
  12 +const id: string = 'menu'
  13 +const state: Function = () => ({
  14 + menuList: []
  15 +})
  16 +const getters = {
  17 + getMenuList() {
  18 + return this.menuList
13 } 19 }
14 - const actions = {  
15 - reset() {  
16 - this.data1 = '10010'  
17 - },  
18 - grown() {  
19 - this.desc = 'test test'  
20 - } 20 +}
  21 +const actions = {
  22 + setMenuList (data: MenuItem[]) {
  23 + this.menuList = data
21 } 24 }
  25 +}
22 26
23 export default { 27 export default {
24 namespace: true, 28 namespace: true,
src/router/index.ts
1 import { createRouter, createWebHashHistory } from 'vue-router' 1 import { createRouter, createWebHashHistory } from 'vue-router'
  2 +import Role from "./modules/role"
2 import User from "./modules/user" 3 import User from "./modules/user"
3 import Resident from "./modules/resident" 4 import Resident from "./modules/resident"
4 import Property from "./modules/property" 5 import Property from "./modules/property"
@@ -36,6 +37,7 @@ const routes: Array&lt;any&gt; = [ @@ -36,6 +37,7 @@ const routes: Array&lt;any&gt; = [
36 }] 37 }]
37 // component: () => import(/* webpackChunkName: "About" */ '@/views/tengxi/about.vue') 38 // component: () => import(/* webpackChunkName: "About" */ '@/views/tengxi/about.vue')
38 }, 39 },
  40 + Role,
39 User, 41 User,
40 Resident, 42 Resident,
41 Property, 43 Property,
@@ -46,16 +48,16 @@ const routes: Array&lt;any&gt; = [ @@ -46,16 +48,16 @@ const routes: Array&lt;any&gt; = [
46 name: 'Login', 48 name: 'Login',
47 component: () => import(/* webpackChunkName: "About" */ '@/views/user/login.vue') 49 component: () => import(/* webpackChunkName: "About" */ '@/views/user/login.vue')
48 }, 50 },
49 - // {  
50 - // path: '/404',  
51 - // name: 'Error',  
52 - // component: () => import(/* webpackChunkName: "Error" */ '@/views/error/404.vue'),  
53 - // hidden: true  
54 - // },  
55 - // {  
56 - // path: '/:pathMatch(.*)*',  
57 - // redirect: '/404'  
58 - // }, 51 + {
  52 + path: '/404',
  53 + name: 'Error',
  54 + component: () => import(/* webpackChunkName: "Error" */ '@/views/error/404.vue'),
  55 + hidden: true
  56 + },
  57 + {
  58 + path: '/:pathMatch(.*)*',
  59 + redirect: '/404'
  60 + },
59 61
60 ] 62 ]
61 63
src/router/modules/role.ts 0 → 100644
  1 +import Layout from '@/layout/enter.vue'
  2 +const role = {
  3 + path: '/',
  4 + component: Layout,
  5 + name: 'Role',
  6 + children: [{
  7 + path: 'role',
  8 + name: 'roleList',
  9 + component: () => import('@/views/role/index.vue'),
  10 + meta: { title: '角色管理' }
  11 + }, {
  12 + path: '/role/user',
  13 + name: 'roleUser',
  14 + component: () => import('@/views/role/user.vue'),
  15 + meta: { title: '角色用户' }
  16 + }, {
  17 + path: '/role/edit',
  18 + name: 'roleEdit',
  19 + component: () => import('@/views/role/edit.vue'),
  20 + meta: { title: '角色编辑' }
  21 + }, {
  22 + path: '/role/permission',
  23 + name: 'rolePermission',
  24 + component: () => import('@/views/role/permission.vue'),
  25 + meta: { title: '角色权限' }
  26 + }]
  27 +}
  28 +
  29 +export default role
src/router/modules/user.ts
@@ -5,19 +5,19 @@ const user = { @@ -5,19 +5,19 @@ const user = {
5 name: 'User', 5 name: 'User',
6 children: [{ 6 children: [{
7 path: 'user', 7 path: 'user',
8 - name: 'user', 8 + name: 'userList',
9 component: () => import('@/views/user/index.vue'), 9 component: () => import('@/views/user/index.vue'),
10 meta: { title: '用户管理' } 10 meta: { title: '用户管理' }
11 }, { 11 }, {
12 path: '/user/role', 12 path: '/user/role',
13 - name: 'role', 13 + name: 'userRole',
14 component: () => import('@/views/user/role.vue'), 14 component: () => import('@/views/user/role.vue'),
15 meta: { title: '用户角色' } 15 meta: { title: '用户角色' }
16 }, { 16 }, {
17 path: '/user/edit', 17 path: '/user/edit',
18 - name: 'edition', 18 + name: 'userEdit',
19 component: () => import('@/views/user/edit.vue'), 19 component: () => import('@/views/user/edit.vue'),
20 - meta: { title: '用户角色' } 20 + meta: { title: '用户编辑' }
21 }] 21 }]
22 } 22 }
23 23
src/utils/progress.ts
@@ -5,6 +5,7 @@ import router from &#39;@/router/index&#39; @@ -5,6 +5,7 @@ import router from &#39;@/router/index&#39;
5 NProgress.configure({ showSpinner: false }) 5 NProgress.configure({ showSpinner: false })
6 6
7 router.beforeEach((to: any, from: any, next: any) => { 7 router.beforeEach((to: any, from: any, next: any) => {
  8 + // if (to.matched.length == 0) { router.push(to.path); }
8 NProgress.start() 9 NProgress.start()
9 const hasToken = true 10 const hasToken = true
10 const whiteList = ['/login'] 11 const whiteList = ['/login']
@@ -18,12 +19,12 @@ router.beforeEach((to: any, from: any, next: any) =&gt; { @@ -18,12 +19,12 @@ router.beforeEach((to: any, from: any, next: any) =&gt; {
18 // next({ path: '/about' }) 19 // next({ path: '/about' })
19 next() 20 next()
20 NProgress.done() 21 NProgress.done()
21 - } else { 22 + } else {
22 next() 23 next()
23 NProgress.done() 24 NProgress.done()
24 } 25 }
25 } else { 26 } else {
26 - console.log('hasno t') 27 + console.log('hasnot')
27 if (whiteList.indexOf(to.path) !== -1) { 28 if (whiteList.indexOf(to.path) !== -1) {
28 next() 29 next()
29 } else { 30 } else {
src/utils/tool.ts
@@ -166,4 +166,18 @@ export function formDataWrapper (data: any) { @@ -166,4 +166,18 @@ export function formDataWrapper (data: any) {
166 fd.append(i, data[i]) 166 fd.append(i, data[i])
167 } 167 }
168 return fd 168 return fd
  169 +}
  170 +
  171 +/**
  172 + * 请求参数删除为null的
  173 + * @param {object}} data
  174 + * @returns {FormData} fd
  175 + */
  176 + export function deleteEmptyParam (params: any) {
  177 + for (const i in params) {
  178 + if (!(params[i] + '').trim()) {
  179 + delete params[i]
  180 + }
  181 + }
  182 + return params
169 } 183 }
170 \ No newline at end of file 184 \ No newline at end of file
src/views/dashboard/index.vue
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 import {ref} from 'vue' 2 import {ref} from 'vue'
3 import {propertyList } from '@/api/tengxi' 3 import {propertyList } from '@/api/tengxi'
  4 +import router from '@/router'
4 const title = ref(import.meta.env.VITE_APP_TITLE).value 5 const title = ref(import.meta.env.VITE_APP_TITLE).value
5 propertyList().then(res => { 6 propertyList().then(res => {
6 console.log(res) 7 console.log(res)
7 }).catch(error => { 8 }).catch(error => {
8 console.log(error) 9 console.log(error)
9 }) 10 })
  11 +console.log(router.getRoutes())
10 </script> 12 </script>
11 13
12 <template> 14 <template>
src/views/role/edit.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +import { reactive, ref, getCurrentInstance, onMounted } from "vue";
  3 +import { roleSave } from "@/api/user/role";
  4 +import { useRoute } from "vue-router";
  5 +import type { ElForm } from "element-plus";
  6 +const {
  7 + appContext: {
  8 + config: { globalProperties },
  9 + },
  10 +} = getCurrentInstance();
  11 +let form = reactive({
  12 + data: {
  13 + roleName: "",
  14 + code: "",
  15 + roleDesc: "",
  16 + },
  17 + dataType: "",
  18 +});
  19 +const ruleFormRef = ref<InstanceType<typeof ElForm>>();
  20 +// 表单验证规则
  21 +const rules = reactive({
  22 + roleName: [
  23 + {
  24 + required: true,
  25 + message: "请填写角色名称",
  26 + trigger: "blur",
  27 + },
  28 + ],
  29 + code: [
  30 + {
  31 + required: true,
  32 + message: "请填写角色代码",
  33 + trigger: "blur",
  34 + },
  35 + ],
  36 +});
  37 +// 表单重置
  38 +const resetForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  39 + if (!formEl) return;
  40 + formEl.resetFields();
  41 +};
  42 +// 表单提交
  43 +const submitForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  44 + if (!formEl) return;
  45 + formEl.validate((valid) => {
  46 + if (valid) {
  47 + roleSave(form.data)
  48 + .then((res) => {
  49 + if (res) {
  50 + globalProperties.$message.success("操作成功");
  51 + history.go(-1);
  52 + }
  53 + })
  54 + .catch((error) => {
  55 + console.log(error);
  56 + });
  57 + } else {
  58 + globalProperties.$message.error("请检查表单格式");
  59 + return false;
  60 + }
  61 + });
  62 +};
  63 +onMounted(() => {
  64 + form.data = useRoute().query;
  65 + if (JSON.stringify(form.data) === "{}") {
  66 + form.dataType = "add";
  67 + } else {
  68 + form.dataType = "edit";
  69 + }
  70 +});
  71 +</script>
  72 +
  73 +<template>
  74 + <div class="page-container">
  75 + <el-card class="form_card" style="max-width: 1303px">
  76 + <h1 v-show="form.dataType === 'add'">新增角色</h1>
  77 + <h1 v-show="form.dataType === 'edit'">编辑角色</h1>
  78 + <el-form
  79 + :inline="true"
  80 + :model="form.data"
  81 + :rules="rules"
  82 + ref="ruleFormRef"
  83 + label-width="120px"
  84 + style="display: flex; flex-wrap: wrap; width: 100%"
  85 + >
  86 + <el-form-item label="角色名称" prop="roleName" style="width: 100%">
  87 + <el-input
  88 + v-model.trim="form.data.roleName"
  89 + placeholder="请填写角色名称"
  90 + maxlength="15"
  91 + />
  92 + </el-form-item>
  93 + <el-form-item label="角色描述" prop="roleDesc" style="width: 100%">
  94 + <el-input
  95 + v-model.trim="form.data.roleDesc"
  96 + placeholder="请填写角色描述"
  97 + maxlength="15"
  98 + />
  99 + </el-form-item>
  100 + <el-form-item label="角色代码" prop="code" style="width: 100%">
  101 + <el-input
  102 + v-model.trim="form.data.code"
  103 + placeholder="请填写角色代码"
  104 + maxlength="15"
  105 + />
  106 + </el-form-item>
  107 + <el-form-item style="width: 100%">
  108 + <el-button type="primary" @click="submitForm(ruleFormRef)"
  109 + >提交</el-button
  110 + >
  111 + <el-button
  112 + type="info"
  113 + @click="resetForm(ruleFormRef)"
  114 + v-show="form.dataType === 'add'"
  115 + >取消</el-button
  116 + >
  117 + </el-form-item>
  118 + </el-form>
  119 + </el-card>
  120 + </div>
  121 +</template>
src/views/role/index.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +import { reactive, ref, onMounted, getCurrentInstance } from "vue";
  3 +import { roleList, roleStatus } from "@/api/user/role";
  4 +import { parseTime } from "@/utils/tool";
  5 +import Pagination from "@/components/Pagination/index.vue";
  6 +const {
  7 + appContext: {
  8 + config: { globalProperties },
  9 + },
  10 +} = getCurrentInstance();
  11 +interface Form {
  12 + page: number;
  13 + pageSize: number;
  14 + roleName: string;
  15 +}
  16 +interface Params {
  17 + total: number;
  18 + query: Form;
  19 +}
  20 +interface Data {
  21 + loading: boolean;
  22 + list: List[] | null;
  23 + params: Params;
  24 +}
  25 +interface List {
  26 + roleName: string,
  27 + code: string,
  28 + roleDesc: string,
  29 + status: number,
  30 + createTime: string,
  31 + updateTime: string,
  32 + creator: string,
  33 + creatorId: number,
  34 + updator: string,
  35 + updatorId: number,
  36 + type: number,
  37 + oId: number
  38 +}
  39 +let data: Data = reactive({
  40 + list: [],
  41 + loading: false,
  42 + params: {
  43 + total: 0,
  44 + query: {
  45 + page: 1,
  46 + pageSize: 10,
  47 + roleName: "",
  48 + },
  49 + },
  50 +});
  51 +// 列表
  52 +const getList = async () => {
  53 + data.loading = true;
  54 + try {
  55 + const res = await roleList(data.params.query);
  56 + data.list = res.data.data.list;
  57 + data.params.total = res.data.data.total;
  58 + } catch (e) {
  59 + console.log(e);
  60 + } finally {
  61 + data.loading = false;
  62 + }
  63 +};
  64 +// 分页
  65 +const handlePageChange = (page, size) => {
  66 + data.params.query.page = page;
  67 + data.params.query.pageSize = size;
  68 + getList();
  69 +};
  70 +// 查询
  71 +const handleSearch = () => {
  72 + getList();
  73 +};
  74 +// 状态
  75 +const handleStatus = async (obj) => {
  76 + try {
  77 + const res = await roleStatus({
  78 + roleId: obj.id,
  79 + status: obj.status? 0: 1
  80 + });
  81 + if(res?.data) {
  82 + globalProperties.$message.success("操作成功");
  83 + getList()
  84 + } else {
  85 + globalProperties.$message.error("操作失败");
  86 + }
  87 + } catch (e) {
  88 + console.log(e);
  89 + }
  90 +};
  91 +// 状态值
  92 +enum statusEnum {
  93 + "禁用" = 0,
  94 + "启用",
  95 +}
  96 +onMounted(() => {
  97 + getList();
  98 +});
  99 +</script>
  100 +
  101 +<template>
  102 + <div class="page-container">
  103 + <h1>角色列表</h1>
  104 + <el-row style="padding-bottom: 20px">
  105 + <el-form :inline="true" label-width="70px">
  106 + <el-form-item label="角色名">
  107 + <el-input
  108 + v-model.trim="data.params.query.roleName"
  109 + placeholder="请填写角色名"
  110 + maxlength="15"
  111 + @change="handleSearch"
  112 + />
  113 + </el-form-item>
  114 + <el-form-item>
  115 + <el-button type="primary" @click="handleSearch">查询</el-button>
  116 + <el-button type="primary">
  117 + <router-link to="/role/edit">添加角色</router-link>
  118 + </el-button>
  119 + </el-form-item>
  120 + </el-form>
  121 + </el-row>
  122 + <el-table
  123 + :data="data.list"
  124 + style="width: 100%"
  125 + border
  126 + v-loading="data.loading"
  127 + align="center"
  128 + element-loading-text="拼命加载中"
  129 + >
  130 + <el-table-column prop="id" label="ID" align="center"> </el-table-column>
  131 + <el-table-column prop="roleName" label="角色名称" align="center">
  132 + </el-table-column>
  133 + <el-table-column prop="createTime" label="注册时间" align="center">
  134 + <template #default="scope">
  135 + {{ parseTime(new Date(scope.row.createTime).getTime()) }}
  136 + </template>
  137 + </el-table-column>
  138 + <el-table-column prop="status" label="状态" align="center">
  139 + <template #default="scope">
  140 + {{ statusEnum[scope.row.status] }}
  141 + </template>
  142 + </el-table-column>
  143 + <el-table-column label="操作" align="center">
  144 + <template #default="scope">
  145 + <el-button type="text"
  146 + ><router-link :to="{ path: '/role/edit', query: scope.row }"
  147 + >编辑</router-link
  148 + ></el-button
  149 + >
  150 + <el-button type="text" @click="handleStatus(scope.row)">{{
  151 + scope.row.status ? "禁用" : "启用"
  152 + }}</el-button>
  153 + <el-button type="text"
  154 + ><router-link :to="{ path: '/role/user', query: {id: scope.row.id} }"
  155 + >用户</router-link
  156 + ></el-button
  157 + >
  158 + <el-button type="text"
  159 + ><router-link :to="{ path: '/role/permission', query: {roleId: scope.row.id, roleName: scope.row.roleName} }"
  160 + >权限</router-link
  161 + ></el-button
  162 + >
  163 + </template>
  164 + </el-table-column>
  165 + </el-table>
  166 + <Pagination
  167 + :total="data.params.total"
  168 + :currentPage="data.params.query.page"
  169 + :pageSize="data.params.query.pageSize"
  170 + @pageChange="handlePageChange"
  171 + ></Pagination>
  172 + </div>
  173 +</template>
src/views/role/permission.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +import { reactive, ref, getCurrentInstance, onMounted } from "vue";
  3 +import { rolePermissionSave, rolePermission } from "@/api/user/role";
  4 +import { useRoute } from "vue-router";
  5 +import type Node from 'element-plus/es/components/tree/src/model/node'
  6 +import type { ElForm } from "element-plus";
  7 +import type { ElTree } from 'element-plus'
  8 +const {
  9 + appContext: {
  10 + config: { globalProperties },
  11 + },
  12 +} = getCurrentInstance();
  13 +let form = reactive({
  14 + data: {
  15 + roleId: useRoute().query.roleId,
  16 + permissionIds: [],
  17 + },
  18 + permissions: [],
  19 + defaultPermissions: [],
  20 + collections: []
  21 +});
  22 +const ruleFormRef = ref<InstanceType<typeof ElForm>>();
  23 +const addTreeTest = ref<InstanceType<typeof ElTree>>()
  24 +// 表单重置
  25 +const resetForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  26 + if (!formEl) return;
  27 + form.defaultPermissions = []
  28 + addTreeTest.value!.setCheckedNodes([])
  29 + formEl.resetFields();
  30 +};
  31 +// 表单提交
  32 +const submitForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  33 + if (!formEl) return;
  34 + formEl.validate((valid) => {
  35 + if (valid) {
  36 + rolePermissionSave(form.data)
  37 + .then((res) => {
  38 + if (res) {
  39 + globalProperties.$message.success("操作成功");
  40 + history.go(-1);
  41 + }
  42 + })
  43 + .catch((error) => {
  44 + console.log(error);
  45 + });
  46 + } else {
  47 + globalProperties.$message.error("请检查表单格式");
  48 + return false;
  49 + }
  50 + });
  51 +};
  52 +// 获取角色权限
  53 +const getPermissions = async (roleId = useRoute().query.roleId) => {
  54 + try {
  55 + let res = await rolePermission({ roleId: roleId });
  56 + form.permissions = res.data.data;
  57 + form.defaultPermissions = getCheckedPermissions(res.data.data)
  58 + } catch (e) {
  59 + console.log(e);
  60 + }
  61 +};
  62 +interface Tree {
  63 + label: string
  64 + children?: Tree[]
  65 +}
  66 +const defaultProps: Tree = {
  67 + children: "menuList",
  68 + label: "name",
  69 +};
  70 +const getCheckedPermissions = (menuArray: Tree[]) => {
  71 + if (menuArray) {
  72 + menuArray.map((item: Tree) => {
  73 + if (item.menuList) {
  74 + getCheckedPermissions(item.menuList);
  75 + }
  76 + if (item.selected) {
  77 + form.collections.push(item.id);
  78 + }
  79 + });
  80 + }
  81 + return form.collections;
  82 +};
  83 +const getCheckedRoles = (node: Node, data: Node[]) => {
  84 + form.data.permissionIds = [...data.checkedKeys, ...data.halfCheckedKeys];
  85 +};
  86 +onMounted(() => {
  87 + getPermissions();
  88 +});
  89 +</script>
  90 +
  91 +<template>
  92 + <div class="page-container">
  93 + <el-card class="form_card" style="max-width: 1303px">
  94 + <h1 v-show="form.dataType === 'edit'">角色权限</h1>
  95 + <el-form
  96 + :inline="true"
  97 + :model="form.data"
  98 + ref="ruleFormRef"
  99 + label-width="120px"
  100 + style="display: flex; flex-wrap: wrap; width: 100%"
  101 + >
  102 + <el-form-item label="角色名称" prop="roleName" style="width: 100%">
  103 + <el-input
  104 + v-model.trim="useRoute().query.roleName"
  105 + placeholder="请填写角色名称"
  106 + maxlength="15"
  107 + disabled
  108 + />
  109 + </el-form-item>
  110 + <el-form-item label="角色ID" prop="roleDesc" style="width: 100%">
  111 + <el-input
  112 + v-model.trim="useRoute().query.roleId"
  113 + placeholder="请填写角色ID"
  114 + maxlength="15"
  115 + disabled
  116 + />
  117 + </el-form-item>
  118 + <el-form-item label="角色权限" prop="permissionIds" style="width: 100%">
  119 + <el-tree
  120 + :data="form.permissions"
  121 + :props="defaultProps"
  122 + :default-checked-keys="form.defaultPermissions"
  123 + node-key="id"
  124 + ref="addTreeTest"
  125 + show-checkbox
  126 + @check="getCheckedRoles"
  127 + />
  128 + </el-form-item>
  129 + <el-form-item style="width: 100%">
  130 + <el-button type="primary" @click="submitForm(ruleFormRef)"
  131 + >提交</el-button
  132 + >
  133 + <el-button
  134 + type="info"
  135 + @click="resetForm(ruleFormRef)"
  136 + >置空</el-button
  137 + >
  138 + </el-form-item>
  139 + </el-form>
  140 + </el-card>
  141 + </div>
  142 +</template>
src/views/role/user.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +import { reactive, onMounted } from "vue";
  3 +import { useRoute } from 'vue-router';
  4 +import { roleUser } from "@/api/user/role";
  5 +import Pagination from "@/components/Pagination/index.vue";
  6 +interface Form {
  7 + page: number;
  8 + pageSize: number;
  9 + roleId: string | number;
  10 +}
  11 +interface Params {
  12 + total: number;
  13 + query: Form;
  14 +}
  15 +interface Data {
  16 + loading: boolean;
  17 + list: any[] | null;
  18 + params: Params;
  19 +}
  20 +let data: Data = reactive({
  21 + list: [],
  22 + loading: false,
  23 + params: {
  24 + total: 0,
  25 + query: {
  26 + page: 1,
  27 + pageSize: 10,
  28 + roleId: '',
  29 + },
  30 + },
  31 +});
  32 +// 状态值
  33 +enum statusEnum {
  34 + "禁用" = 0,
  35 + "启用",
  36 +}
  37 +// 列表
  38 +const getList = async () => {
  39 + data.loading = true;
  40 + try {
  41 + const res = await roleUser(data.params.query);
  42 + data.list = res.data.data.list;
  43 + data.params.total = res.data.data.total;
  44 + } catch (e) {
  45 + console.log(e);
  46 + } finally {
  47 + data.loading = false;
  48 + }
  49 +};
  50 +// 分页
  51 +const handlePageChange = (page, size) => {
  52 + data.params.query.page = page;
  53 + data.params.query.pageSize = size;
  54 + getList();
  55 +};
  56 +onMounted(() => {
  57 + data.params.query.roleId = useRoute().query.id;
  58 + getList();
  59 +});
  60 +</script>
  61 +
  62 +<template>
  63 + <div class="page-container">
  64 + <h1>角色用户</h1>
  65 + <el-table
  66 + :data="data.list"
  67 + style="width: 100%"
  68 + border
  69 + v-loading="data.loading"
  70 + align="center"
  71 + element-loading-text="拼命加载中"
  72 + >
  73 + <el-table-column prop="id" label="ID" align="center"> </el-table-column>
  74 + <el-table-column prop="userName" label="用户名称" align="center">
  75 + </el-table-column>
  76 + <el-table-column prop="cellphone" label="手机号码" align="center">
  77 + </el-table-column>
  78 + <el-table-column prop="status" label="状态" align="center">
  79 + <template #default="scope">
  80 + {{ statusEnum[scope.row.status] }}
  81 + </template>
  82 + </el-table-column>
  83 + </el-table>
  84 + <Pagination
  85 + :total="data.params.total"
  86 + :currentPage="data.params.query.page"
  87 + :pageSize="data.params.query.pageSize"
  88 + @pageChange="handlePageChange"
  89 + ></Pagination>
  90 + </div>
  91 +</template>
src/views/user/index.vue
@@ -12,7 +12,7 @@ interface Form { @@ -12,7 +12,7 @@ interface Form {
12 page: number; 12 page: number;
13 pageSize: number; 13 pageSize: number;
14 userName?: string; 14 userName?: string;
15 - cellPhone?: string; 15 + cellphone?: string;
16 } 16 }
17 interface Params { 17 interface Params {
18 total: number; 18 total: number;
@@ -32,7 +32,7 @@ let data = reactive({ @@ -32,7 +32,7 @@ let data = reactive({
32 page: 1, 32 page: 1,
33 pageSize: 10, 33 pageSize: 10,
34 userName: "", 34 userName: "",
35 - cellPhone: "", 35 + cellphone: "",
36 }, 36 },
37 }, 37 },
38 }); 38 });
@@ -108,7 +108,7 @@ onMounted(() =&gt; { @@ -108,7 +108,7 @@ onMounted(() =&gt; {
108 </el-form-item> 108 </el-form-item>
109 <el-form-item label="用户名"> 109 <el-form-item label="用户名">
110 <el-input 110 <el-input
111 - v-model.trim="data.params.query.cellPhone" 111 + v-model.trim="data.params.query.cellphone"
112 placeholder="请填写用户手机号" 112 placeholder="请填写用户手机号"
113 maxlength="15" 113 maxlength="15"
114 @change="handleSearch" 114 @change="handleSearch"
@@ -159,7 +159,7 @@ onMounted(() =&gt; { @@ -159,7 +159,7 @@ onMounted(() =&gt; {
159 >初始密码</el-button 159 >初始密码</el-button
160 > 160 >
161 <el-button type="text" 161 <el-button type="text"
162 - ><router-link :to="{ path: '/user/role', query: scope.row }" 162 + ><router-link :to="{ path: '/user/role', query: {id: scope.row.id}}"
163 >角色</router-link 163 >角色</router-link
164 ></el-button 164 ></el-button
165 > 165 >
src/views/user/login.vue
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 -import { login } from "@/api/user/login";  
3 -import * as all from "vue-router"; 2 +import { login, menuData } from "@/api/user/login";
4 import * as store from "@/pinia/index"; 3 import * as store from "@/pinia/index";
5 -login().then((res) => {  
6 - console.log(res);  
7 - console.log(store.family.loginStore().token);  
8 - if (res) {  
9 - store.family.loginStore().setToken(res.data.data.token);  
10 - } 4 +import router from "@/router/index";
  5 +import { reactive, ref, getCurrentInstance } from "vue";
  6 +import type { ElForm } from "element-plus";
  7 +import { UserFilled, Lock } from "@element-plus/icons-vue";
  8 +const {
  9 + appContext: {
  10 + config: { globalProperties },
  11 + },
  12 +} = getCurrentInstance();
  13 +interface Login {
  14 + userName: string;
  15 + password: string;
  16 +}
  17 +// 登录表单数据
  18 +const loginForm: Login = reactive({
  19 + userName: "123",
  20 + password: "cmnt123",
11 }); 21 });
  22 +// 登录框上面标题
  23 +const title = ref(import.meta.env.VITE_APP_TITLE).value;
  24 +const ruleFormRef = ref<InstanceType<typeof ElForm>>();
  25 +// 表单提交
  26 +const submitForm = (formEl: InstanceType<typeof ElForm> | undefined) => {
  27 + if (!formEl) return;
  28 + formEl.validate((valid) => {
  29 + if (valid) {
  30 + login(loginForm).then((res) => {
  31 + if (res?.data) {
  32 + globalProperties.$message.success("登录成功");
  33 + store.family.loginStore().setUserInfo(res.data.data);
  34 + getMenu().then((res) => {
  35 + setTimeout(() => {
  36 + router.push({ path: "/" });
  37 + }, 1000);
  38 + });
  39 + }
  40 + });
  41 + } else {
  42 + console.log("error");
  43 + }
  44 + });
  45 +};
  46 +// 获取权限菜单
  47 +const getMenu = async () => {
  48 + try {
  49 + let res = await menuData();
  50 + store.family.menuStore().setMenuList(res.data.data);
  51 + } catch (e) {
  52 + console.log(e);
  53 + }
  54 +};
12 </script> 55 </script>
13 56
14 <template> 57 <template>
15 - <p>Login</p>  
16 - <router-link :to="{ path: '/' }"  
17 - >回首页</router-link  
18 - > 58 + <div class="login-container">
  59 + <el-form
  60 + :inline="true"
  61 + :model="loginForm"
  62 + ref="ruleFormRef"
  63 + auto-complete="on"
  64 + label-position="left"
  65 + label-width="120px"
  66 + class="login-form"
  67 + >
  68 + <div class="title-container">
  69 + <h3 class="title">{{ title }}</h3>
  70 + </div>
  71 +
  72 + <el-row>
  73 + <el-form-item prop="userName" style="width: 100%">
  74 + <el-input
  75 + v-model.trim="loginForm.userName"
  76 + placeholder="请填写用户名"
  77 + maxlength="15"
  78 + :validate-event="false"
  79 + tabindex="1"
  80 + type="text"
  81 + auto-complete="off"
  82 + clearable
  83 + :prefix-icon="UserFilled"
  84 + />
  85 + </el-form-item>
  86 + </el-row>
  87 + <el-form-item prop="password" style="width: 100%">
  88 + <el-input
  89 + v-model.trim="loginForm.password"
  90 + placeholder="请填写密码"
  91 + :validate-event="false"
  92 + maxlength="15"
  93 + tabindex="2"
  94 + :show-password="true"
  95 + clearable
  96 + type="password"
  97 + auto-complete="off"
  98 + :prefix-icon="Lock"
  99 + @keyup.enter.native="submitForm(ruleFormRef)"
  100 + >
  101 + </el-input>
  102 + </el-form-item>
  103 + <el-form-item style="width: 100%">
  104 + <el-button
  105 + type="primary"
  106 + @click="submitForm(ruleFormRef)"
  107 + style="width: 100%"
  108 + >登录</el-button
  109 + >
  110 + </el-form-item>
  111 + </el-form>
  112 + </div>
19 </template> 113 </template>
20 114
21 -<style lang="scss" scoped></style> 115 +<style lang="scss">
  116 +$bg: #283443;
  117 +$dark_gray: #889aa4;
  118 +$light_gray: #fff;
  119 +$cursor: #fff;
  120 +@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  121 + .login-container .el-input input {
  122 + color: $cursor;
  123 + }
  124 +}
  125 +.login {
  126 + &-container {
  127 + min-height: 100%;
  128 + text-align: center;
  129 + background-color: $bg;
  130 + .el-input {
  131 + input {
  132 + background: transparent;
  133 + border: 0px;
  134 + -webkit-appearance: none;
  135 + border-radius: 0px;
  136 + color: $light_gray;
  137 + height: 47px;
  138 + caret-color: $cursor;
  139 + &:-webkit-autofill {
  140 + box-shadow: 0 0 0px 1000px $bg inset !important;
  141 + -webkit-text-fill-color: $cursor !important;
  142 + }
  143 + }
  144 + }
  145 + .el-form-item {
  146 + border: 1px solid rgba(255, 255, 255, 0.1);
  147 + background: rgba(0, 0, 0, 0.1);
  148 + border-radius: 5px;
  149 + color: #454545;
  150 + }
  151 + }
  152 + &-form {
  153 + position: relative;
  154 + width: 520px;
  155 + max-width: 100%;
  156 + padding: 160px 35px 0;
  157 + margin: 0 auto;
  158 + overflow: hidden;
  159 + }
  160 +}
  161 +.title-container {
  162 + position: relative;
  163 + .title {
  164 + font-size: 26px;
  165 + color: $light_gray;
  166 + margin: 0px auto 40px auto;
  167 + text-align: center;
  168 + font-weight: bold;
  169 + }
  170 +}
  171 +</style>