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 0 \ No newline at end of file
src/api/user/login/index.ts
1 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 8 let res: any = await request({
7 9 url: '/login',
8 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 25 return res
16 26 }
17 27 \ No newline at end of file
... ...
src/api/user/role/index.ts
1 1 import request from '../../request'
2   -import {formDataWrapper} from '@/utils/tool'
  2 +import {formDataWrapper, deleteEmptyParam} from '@/utils/tool'
3 3  
4 4 /**
5 5 * @description 角色列表
... ... @@ -9,7 +9,64 @@ export const roleList = async ( params: any ) => {
9 9 let res: any = await request({
10 10 url: '/role/list',
11 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 38 params: params
13 39 })
14 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 73 \ No newline at end of file
... ...
src/layout/menu.vue
... ... @@ -18,10 +18,15 @@ import {
18 18 let styleData = computed(() => {
19 19 return styles;
20 20 });
  21 +let menuData = computed(() => {
  22 + let res = store.family.menuStore().menuList;
  23 + return res;
  24 +});
21 25 </script>
22 26  
23 27 <template>
24 28 <el-scrollbar wrap-class="scrollbar-wrapper">
  29 + <!-- {{menuData}} -->
25 30 <el-menu
26 31 default-active="2"
27 32 :background-color="styleData.menuBg"
... ... @@ -32,41 +37,58 @@ let styleData = computed(() =&gt; {
32 37 :collapse-transition="false"
33 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 57 <template #title>
37 58 <el-icon><location /></el-icon>
38   - <span>物业管理</span>
  59 + <span>物业管理真菜单可点</span>
39 60 </template>
40 61 <el-menu-item-group>
41 62 <el-menu-item index="/property">物业列表</el-menu-item>
42 63 </el-menu-item-group>
43 64 </el-sub-menu>
44   - <el-sub-menu index="2">
  65 + <el-sub-menu index="12">
45 66 <template #title>
46 67 <el-icon><location /></el-icon>
47   - <span>小区管理</span>
  68 + <span>小区管理真菜单可点</span>
48 69 </template>
49 70 <el-menu-item-group>
50 71 <el-menu-item index="/">小区管理</el-menu-item>
51 72 </el-menu-item-group>
52 73 </el-sub-menu>
53   - <el-sub-menu index="3">
  74 + <el-sub-menu index="13">
54 75 <template #title>
55 76 <el-icon><location /></el-icon>
56   - <span>用户管理</span>
  77 + <span>用户管理真菜单可点</span>
57 78 </template>
58 79 <el-menu-item-group>
59 80 <el-menu-item index="/user">用户列表</el-menu-item>
60 81 </el-menu-item-group>
61 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 92 </el-menu>
71 93 </el-scrollbar>
72 94 </template>
... ...
src/pinia/modules/app.ts
1   -const id = 'app'
  1 +const id: string = 'app'
2 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 16 export default {
17 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 9 token: '',
  10 + organizationId: null,
  11 + id: null,
  12 + userName: ''
4 13 })
5 14 const getters = {
6   - // getCollapseStatus () {
7   - // return this.isCollapse
8   - // }
9 15 getToken() {
10 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 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 27 export default {
24 28 namespace: true,
... ...
src/router/index.ts
1 1 import { createRouter, createWebHashHistory } from 'vue-router'
  2 +import Role from "./modules/role"
2 3 import User from "./modules/user"
3 4 import Resident from "./modules/resident"
4 5 import Property from "./modules/property"
... ... @@ -36,6 +37,7 @@ const routes: Array&lt;any&gt; = [
36 37 }]
37 38 // component: () => import(/* webpackChunkName: "About" */ '@/views/tengxi/about.vue')
38 39 },
  40 + Role,
39 41 User,
40 42 Resident,
41 43 Property,
... ... @@ -46,16 +48,16 @@ const routes: Array&lt;any&gt; = [
46 48 name: 'Login',
47 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 5 name: 'User',
6 6 children: [{
7 7 path: 'user',
8   - name: 'user',
  8 + name: 'userList',
9 9 component: () => import('@/views/user/index.vue'),
10 10 meta: { title: '用户管理' }
11 11 }, {
12 12 path: '/user/role',
13   - name: 'role',
  13 + name: 'userRole',
14 14 component: () => import('@/views/user/role.vue'),
15 15 meta: { title: '用户角色' }
16 16 }, {
17 17 path: '/user/edit',
18   - name: 'edition',
  18 + name: 'userEdit',
19 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 5 NProgress.configure({ showSpinner: false })
6 6  
7 7 router.beforeEach((to: any, from: any, next: any) => {
  8 + // if (to.matched.length == 0) { router.push(to.path); }
8 9 NProgress.start()
9 10 const hasToken = true
10 11 const whiteList = ['/login']
... ... @@ -18,12 +19,12 @@ router.beforeEach((to: any, from: any, next: any) =&gt; {
18 19 // next({ path: '/about' })
19 20 next()
20 21 NProgress.done()
21   - } else {
  22 + } else {
22 23 next()
23 24 NProgress.done()
24 25 }
25 26 } else {
26   - console.log('hasno t')
  27 + console.log('hasnot')
27 28 if (whiteList.indexOf(to.path) !== -1) {
28 29 next()
29 30 } else {
... ...
src/utils/tool.ts
... ... @@ -166,4 +166,18 @@ export function formDataWrapper (data: any) {
166 166 fd.append(i, data[i])
167 167 }
168 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 184 \ No newline at end of file
... ...
src/views/dashboard/index.vue
1 1 <script setup lang="ts">
2 2 import {ref} from 'vue'
3 3 import {propertyList } from '@/api/tengxi'
  4 +import router from '@/router'
4 5 const title = ref(import.meta.env.VITE_APP_TITLE).value
5 6 propertyList().then(res => {
6 7 console.log(res)
7 8 }).catch(error => {
8 9 console.log(error)
9 10 })
  11 +console.log(router.getRoutes())
10 12 </script>
11 13  
12 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 12 page: number;
13 13 pageSize: number;
14 14 userName?: string;
15   - cellPhone?: string;
  15 + cellphone?: string;
16 16 }
17 17 interface Params {
18 18 total: number;
... ... @@ -32,7 +32,7 @@ let data = reactive({
32 32 page: 1,
33 33 pageSize: 10,
34 34 userName: "",
35   - cellPhone: "",
  35 + cellphone: "",
36 36 },
37 37 },
38 38 });
... ... @@ -108,7 +108,7 @@ onMounted(() =&gt; {
108 108 </el-form-item>
109 109 <el-form-item label="用户名">
110 110 <el-input
111   - v-model.trim="data.params.query.cellPhone"
  111 + v-model.trim="data.params.query.cellphone"
112 112 placeholder="请填写用户手机号"
113 113 maxlength="15"
114 114 @change="handleSearch"
... ... @@ -159,7 +159,7 @@ onMounted(() =&gt; {
159 159 >初始密码</el-button
160 160 >
161 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 163 >角色</router-link
164 164 ></el-button
165 165 >
... ...
src/views/user/login.vue
1 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 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 55 </script>
13 56  
14 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 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>
... ...