Browse Source

chore: cas sso model business change

master
wangxiang 2 years ago
parent
commit
fc677618bd
No known key found for this signature in database
GPG Key ID: 1BA7946AB6B232E4
  1. 10
      src/api/common/base/entity/index.ts
  2. 5
      src/api/platform/core/controller/user.ts
  3. 44
      src/api/platform/core/entity/user.ts
  4. 4
      src/api/platform/system/controller/ssoUser.ts
  5. 19
      src/api/platform/system/controller/user.ts
  6. 12
      src/api/platform/system/entity/ssoUser.ts
  7. 29
      src/api/platform/system/entity/user.ts
  8. 13
      src/hooks/web/useTenant.ts
  9. 4
      src/layouts/default/header/components/user-dropdown/index.vue
  10. 13
      src/locales/lang/en/routes/demo.ts
  11. 13
      src/locales/lang/zh-CN/routes/demo.ts
  12. 2
      src/router/guard/permissionGuard.ts
  13. 35
      src/router/routes/demo/permission.ts
  14. 2
      src/router/routes/modules/demoFeat.ts
  15. 19
      src/store/modules/user.ts
  16. 4
      src/utils/cache/persistent.ts
  17. 4
      src/views/core/lock/LockPage.vue
  18. 95
      src/views/demo/permission/Btn.vue
  19. 61
      src/views/demo/permission/index.vue
  20. 96
      src/views/system/user/ResetPwdModal.vue
  21. 9
      src/views/system/user/account/setting/UserInfo.vue
  22. 6
      src/views/system/user/account/setting/data.ts
  23. 19
      src/views/system/user/index.vue
  24. 4
      src/views/system/user/sso/sso.data.ts

10
src/api/common/base/entity/index.ts

@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
* @create: 2022/4/8
*/
/** 扩展安全框架用户信息 */
export interface KiccUser {
/** CAS统一认证用户模型 */
export interface CasUser {
username: string;
password: string;
enabled: boolean;
@ -30,8 +30,14 @@ export interface KiccUser { @@ -30,8 +30,14 @@ export interface KiccUser {
updateByName: string;
updateTime: string;
remarks: string;
roleId: string;
tenantId: string;
exPrincipals: { [key: string]: string };
[key: string]: any;
}
/** SSO扩展用户模型 */
export interface KiccUser extends CasUser {
deptId: string;
userType: string;
exPermissions: string[];

5
src/api/platform/core/controller/user.ts

@ -4,8 +4,7 @@ @@ -4,8 +4,7 @@
* author wangxiang4
*/
import type { Captcha, User, LoginParams, TokenEnhancer } from '../entity/user';
import type { RequestOptions } from '/#/axios';
import type { Captcha, LoginParams, TokenEnhancer, UserVo } from '../entity/user';
import { encryptionLogin } from '/@/utils/cipher';
import { defHttp } from '/@/utils/http/axios';
import qs from 'qs';
@ -46,7 +45,7 @@ export const login = (params: LoginParams) => { @@ -46,7 +45,7 @@ export const login = (params: LoginParams) => {
};
/** 获取当前用户信息 */
export const getUserInfo = () => defHttp.get<User>({ url: Api.getUserInfo });
export const getUserInfo = () => defHttp.get<UserVo>({ url: Api.getUserInfo });
/** 登出 */
export const logout = () => defHttp.delete({ url: Api.logout }, { errorMessageMode: 'none'});

44
src/api/platform/core/entity/user.ts

@ -5,9 +5,9 @@ @@ -5,9 +5,9 @@
* @author: wangxiang4
* @create: 2022/4/8
*/
import type { CommonEntity } from '/@/api/common/data/entity';
import type { KiccUser } from '/@/api/common/base/entity';
import type { CasUser } from '/@/api/common/base/entity';
import type { RequestOptions } from '/#/axios';
import { SsoUser } from '/@/api/platform/system/entity/ssoUser';
/** 登录参数对象 */
export interface LoginParams {
@ -29,55 +29,35 @@ export interface TokenEnhancer { @@ -29,55 +29,35 @@ export interface TokenEnhancer {
refresh_token: string;
scope: string;
token_type: string;
user_info: KiccUser;
user_info: CasUser;
}
/** 用户对象 */
export interface User extends CommonEntity {
// 用户id
/** 用户VO对象 */
export interface UserVo extends SsoUser {
// 系统用户id
id: string;
// 用户名
userName: string;
// 昵称
nickName: string;
// CAS用户ID
casUserId: string;
// 用户类型
userType: string;
// 头像
avatar: string;
// 所属部门ID
deptId: string;
// 所属部门名称
deptName: string;
// 邮箱
email: string;
// 菜单按钮权限
permissions: string[];
// 角色ID权限
roleIds: string[];
// 手机号
phone: string;
// 用户密码
password: string;
// 用户性别
sex: string;
// 最后登陆IP
loginIp: string;
// 最后登陆时间
loginTime: string;
// 地图标记点位置图片旋转值
mapOrientation: number;
// 地图设计器默认中心点位置
mapCenter: string;
// 用户状态
status: string;
// 备注信息
remarks: string;
// 多租户ID
tenantId: string;
// 指定登录后首页跳转
homePath?: string;
// 前端项目配置多租户选择集合
tenantIds: string[];
// 角色ID权限
roleIds: string[];
// 菜单按钮权限
permissions: string[];
[key: string]: any;
}

4
src/api/platform/system/controller/ssoUser.ts

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
*/
import type { SsoUserParams, SsoUser ,SsoUserResult } from '/@/api/platform/system/entity/ssoUser';
import { defHttp } from '/@/utils/http/axios';
import { UserVo } from '/@/api/platform/core/entity/user';
enum Api {
list = '/system_proxy/system/ssoUser/list',
@ -15,6 +16,7 @@ enum Api { @@ -15,6 +16,7 @@ enum Api {
del = '/system_proxy/system/ssoUser/remove',
updatePwd = '/system_proxy/system/ssoUser/updatePwd',
resetPwd='/system_proxy/system/ssoUser/resetPwd',
updateSsoUserAndExUser = '/system_proxy/system/ssoUser/updateSsoUserAndExUser'
}
export const listSsoUser = (params?: Partial<SsoUserParams>) => defHttp.get<SsoUserResult>({ url: Api.list, params }, { isReturnResultResponse: true });
@ -32,3 +34,5 @@ export const delSsoUser = (ids: string) => defHttp.delete({ url: `${Api.del}/${i @@ -32,3 +34,5 @@ export const delSsoUser = (ids: string) => defHttp.delete({ url: `${Api.del}/${i
export const updatePwd = (params: Partial<SsoUser>) => defHttp.put({ url: Api.updatePwd, params });
export const resetPwd = (params: Partial<SsoUser>) => defHttp.put({ url: Api.resetPwd, data: params });
export const updateSsoUserAndExUser = (params: Partial<UserVo>) => defHttp.put({ url: Api.updateSsoUserAndExUser, data: params });

19
src/api/platform/system/controller/user.ts

@ -3,11 +3,10 @@ @@ -3,11 +3,10 @@
* Copyright © 2023-2023 <a href="https://godolphinx.org"></a> All rights reserved.
* author wangxiang4
*/
import type { UserParams, UserResult } from '/@/api/platform/system/entity/user';
import type { User } from '/@/api/platform/core/entity/user';
import type { UserParams, User, UserResult } from '/@/api/platform/system/entity/user';
import type { UserVo } from '/@/api/platform/core/entity/user';
import type { ResultVo } from '/@/api/common/base/entity';
import { defHttp } from '/@/utils/http/axios';
import { KiccUser } from '/@/api/common/base/entity';
enum Api {
list = '/system_proxy/system/user/list',
@ -15,12 +14,9 @@ enum Api { @@ -15,12 +14,9 @@ enum Api {
get = '/system_proxy/system/user',
edit = '/system_proxy/system/user/update',
del = '/system_proxy/system/user/remove',
updatePwd = '/system_proxy/system/user/updatePwd',
resetPwd='/system_proxy/system/user/resetPwd',
changeStatus='/system_proxy/system/user/changeStatus',
changeTenant='/system_proxy/system/user/changeTenant',
resetTenant='/system_proxy/system/user/resetTenant',
synchronousAuthenticationUser = '/system_proxy/system/user/synchronousAuthenticationUser',
getCourierUserList= '/system_proxy/system/user/getCourierUserList',
getUserTypeList= '/system_proxy/system/user/getUserTypeList',
}
@ -40,12 +36,6 @@ export const getUser = (id: string) => defHttp.get<ResultVo>({ url: `${Api.get}/ @@ -40,12 +36,6 @@ export const getUser = (id: string) => defHttp.get<ResultVo>({ url: `${Api.get}/
/** 删除用户 */
export const delUser = (ids: string) => defHttp.delete({ url: `${Api.del}/${ids}` });
/** 更新密码 */
export const updatePwd = (params: Partial<User>) => defHttp.put({ url: Api.updatePwd, params });
/** 重置密码 */
export const resetPwd = (params: Partial<User>) => defHttp.put({ url: Api.resetPwd, data: params });
/** 修改用户状态 */
export const changeStatus = (id: string, status: string) => defHttp.put({ url: Api.changeStatus, data: { id: id, status: status } });
@ -55,11 +45,8 @@ export const changeTenant = (tenantIds: string[]) => defHttp.get({ url: `${Api.c @@ -55,11 +45,8 @@ export const changeTenant = (tenantIds: string[]) => defHttp.get({ url: `${Api.c
/** 还原用户多租户 */
export const resetTenant = () => defHttp.get({ url: Api.resetTenant });
/** 同步身份验证用户 */
export const synchronousAuthenticationUser = () => defHttp.get<KiccUser>({ url: Api.synchronousAuthenticationUser });
/** 获取全部快递员集合 */
export const getCourierUserList = () => defHttp.get<User[]>({ url: Api.getCourierUserList });
export const getCourierUserList = () => defHttp.get<UserVo[]>({ url: Api.getCourierUserList });
/** 获取用户类型集合 */
export const getUserTypeList = () => defHttp.get({ url: Api.getUserTypeList });

12
src/api/platform/system/entity/ssoUser.ts

@ -8,8 +8,11 @@ @@ -8,8 +8,11 @@
import type { R } from '/#/axios';
import type { Page } from '/@/api/common/data/entity';
import { CommonEntity } from '/@/api/common/data/entity';
/** SSO用户查询参数 */
export type SsoUserParams = Page & SsoUser;
/** SSO用户对象 */
export interface SsoUser extends CommonEntity {
// 用户id
id: string;
@ -17,16 +20,16 @@ export interface SsoUser extends CommonEntity { @@ -17,16 +20,16 @@ export interface SsoUser extends CommonEntity {
userName: string;
// 昵称
nickName: string;
// 头像
avatar: string;
// 用户密码
password: string;
// 邮箱
email: string;
// 手机号
phone: string;
// 用户密码
password: string;
// 用户性别
sex: string;
// 头像
avatar: string;
// 最后登陆IP
loginIp: string;
// 最后登陆时间
@ -34,4 +37,5 @@ export interface SsoUser extends CommonEntity { @@ -34,4 +37,5 @@ export interface SsoUser extends CommonEntity {
[key: string]: any;
}
/** SSO用户对象 */
export type SsoUserResult = R<SsoUser[]>;

29
src/api/platform/system/entity/user.ts

@ -6,11 +6,34 @@ @@ -6,11 +6,34 @@
* @create: 2022/4/8
*/
import type { R } from '/#/axios';
import type { Page } from '/@/api/common/data/entity';
import type { User } from '/@/api/platform/core/entity/user';
import type { CommonEntity, Page } from '/@/api/common/data/entity';
import { UserVo } from '/@/api/platform/core/entity/user';
/** 用户查询参数 */
export type UserParams = Page & User;
/** 用户对象 */
export interface User extends CommonEntity {
// 系统用户id
id: string;
// CAS用户ID
casUserId: string;
// 用户类型
userType: string;
// 所属部门ID
deptId: string;
// 所属部门名称
deptName: string;
// 地图标记点位置图片旋转值
mapOrientation: number;
// 地图设计器默认中心点位置
mapCenter: string;
// 用户状态
status: string;
// 指定登录后首页跳转
homePath?: string;
[key: string]: any;
}
/** 用户响应对象 */
export type UserResult = R<User[]>;
export type UserResult = R<UserVo[]>;

13
src/hooks/web/useTenant.ts

@ -11,25 +11,20 @@ export function useTenant() { @@ -11,25 +11,20 @@ export function useTenant() {
const userStore = useUserStore();
// 切换多租户会改变当前系统中的数据环境
async function changeTenantEnv(tenantIds: string[], reload = true) {
async function changeTenantEnv(tenantIds: string[]) {
// 更改当前后端系统中的全局多租户数据
await changeTenant(tenantIds);
// 更改当前前端系统中的全局多租户数据
const userInfo = userStore.getUserInfo;
userInfo.tenantIds = tenantIds;
userInfo.tenantId = tenantIds.join(',');
userStore.setUserInfo(userInfo);
reload && location.reload();
document.location.reload();
return tenantIds;
}
// 重置多租户信息
async function resetTenantEnv(reload = true) {
async function resetTenantEnv() {
// 更改当前后端系统中的全局多租户数据
await resetTenant();
// 更改当前前端系统中的全局多租户数据
await userStore.getUserInfoAction();
reload && location.reload();
document.location.reload();
}
return {

4
src/layouts/default/header/components/user-dropdown/index.vue

@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { useRouter } from 'vue-router';
type MenuEvent = 'logout' | 'doc' | 'lock' | 'accountSettings' | 'userCenter';
import type { User } from '/@/api/platform/core/entity/user';
import type { UserVo } from '/@/api/platform/core/entity/user';
import DropMenuItem from './DropMenuItem.vue';
export default defineComponent({
@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
const { getUseLockPage } = useHeaderSetting();
const userStore = useUserStore();
const getUserInfo = computed((): User => userStore.getUserInfo || {});
const getUserInfo = computed((): UserVo => userStore.getUserInfo || {});
const { push } = useRouter();
const [register, { openModal }] = useModal();

13
src/locales/lang/en/routes/demo.ts

@ -150,6 +150,19 @@ export default { @@ -150,6 +150,19 @@ export default {
listBasic: 'Basic list',
listSearch: 'Search list',
},
permission: {
permission: 'Permission',
front: 'front-end',
frontPage: 'Page',
frontBtn: 'Button',
frontTestA: 'Test page A',
frontTestB: 'Test page B',
back: 'background',
backPage: 'Page',
backBtn: 'Button',
},
setup: {
page: 'Intro page',
},

13
src/locales/lang/zh-CN/routes/demo.ts

@ -145,6 +145,19 @@ export default { @@ -145,6 +145,19 @@ export default {
listBasic: '标准列表',
listSearch: '搜索列表',
},
permission: {
permission: '权限管理',
front: '基于前端权限',
frontPage: '页面权限',
frontBtn: '按钮权限',
frontTestA: '权限测试页A',
frontTestB: '权限测试页B',
back: '基于后台权限',
backPage: '页面权限',
backBtn: '按钮权限',
},
setup: {
page: '引导页',
},

2
src/router/guard/permissionGuard.ts

@ -91,7 +91,7 @@ export function createPermissionGuard(router: Router) { @@ -91,7 +91,7 @@ export function createPermissionGuard(router: Router) {
next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
return;
}
// 页面刷新重新拉取用户信息数据
// 页面刷新重新拉取用户信息数据(修改redis内多租户或切换用户角色会改变当前用户数据)
if (userStore.getLastUpdateTime === 0) {
try {
await userStore.getUserInfoAction();

35
src/router/routes/demo/permission.ts

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
import type { AppRouteModule } from '/@/router/types';
import { getParentLayout, LAYOUT } from '/@/router/constant';
import { t } from '/@/hooks/web/useI18n';
const permission: AppRouteModule = {
path: '/permission',
name: 'Permission',
component: LAYOUT,
redirect: '/permission/front/page',
meta: {
icon: 'ion:key-outline',
title: t('routes.demo.permission.permission'),
},
children: [
{
path: 'page',
name: 'BackAuthPage',
component: () => import('/@/views/demo/permission/index.vue'),
meta: {
title: t('routes.demo.permission.backPage'),
},
},
{
path: 'btn',
name: 'BackAuthBtn',
component: () => import('/@/views/demo/permission/Btn.vue'),
meta: {
title: t('routes.demo.permission.backBtn'),
},
},
],
};
export default permission;

2
src/router/routes/modules/demoFeat.ts

@ -6,6 +6,7 @@ import feat from '../demo/feat'; @@ -6,6 +6,7 @@ import feat from '../demo/feat';
import iframe from '../demo/iframe';
import level from '../demo/level';
import page from '../demo/page';
import permission from '../demo/permission';
import setup from '../demo/setup';
import { isProdMode } from '/@/utils/env';
@ -27,6 +28,7 @@ const demoFeat: AppRouteModule = { @@ -27,6 +28,7 @@ const demoFeat: AppRouteModule = {
iframe,
level,
page,
permission,
],
};

19
src/store/modules/user.ts

@ -10,7 +10,7 @@ import { store } from '/@/store'; @@ -10,7 +10,7 @@ import { store } from '/@/store';
import { PageEnum } from '/@/enums/pageEnum';
import { ACCESS_TOKEN_KEY, PERMISSIONS_KEY, REFRESH_TOKEN_KEY, ROLE_IDS_KEY, USER_INFO_KEY } from '/@/enums/cacheEnum';
import { getAuthCache, setAuthCache } from '/@/utils/auth';
import { User, LoginParams } from '/@/api/platform/core/entity/user';
import { UserVo, LoginParams } from '/@/api/platform/core/entity/user';
import { logout, getUserInfo, login } from '/@/api/platform/core/controller/user';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
@ -27,7 +27,7 @@ import { merge } from 'lodash-es'; @@ -27,7 +27,7 @@ import { merge } from 'lodash-es';
import { RequestOptions } from '/#/axios';
interface UserState {
userInfo: Nullable<User>;
userInfo: Nullable<UserVo>;
sessionTimeout?: boolean;
lastUpdateTime: number;
roleIds: string[];
@ -40,10 +40,10 @@ export const useUserStore = defineStore({ @@ -40,10 +40,10 @@ export const useUserStore = defineStore({
id: 'app-user',
state: (): UserState => ({
// 用户信息
userInfo: getAuthCache<User>(USER_INFO_KEY),
userInfo: getAuthCache<UserVo>(USER_INFO_KEY),
// 登录是否过期记录(确保下次登陆不刷新路由直接还原)
sessionTimeout: false,
// 最后一次性更新用户信息时间
// 最后一次性更新用户信息时间(用于页面刷新更新用户数据)
lastUpdateTime: 0,
// 角色ID用于权限校验
roleIds: getAuthCache<string[]>(ROLE_IDS_KEY),
@ -55,7 +55,7 @@ export const useUserStore = defineStore({ @@ -55,7 +55,7 @@ export const useUserStore = defineStore({
refresh_token: getAuthCache<string>(REFRESH_TOKEN_KEY),
}),
getters: {
getUserInfo(): User {
getUserInfo(): UserVo {
return this.userInfo || {};
},
getAccessToken(): string {
@ -94,7 +94,7 @@ export const useUserStore = defineStore({ @@ -94,7 +94,7 @@ export const useUserStore = defineStore({
this.refresh_token = refreshToken;
setAuthCache(REFRESH_TOKEN_KEY, refreshToken);
},
setUserInfo(userInfo: Nullable<User>) {
setUserInfo(userInfo: Nullable<UserVo>) {
this.userInfo = userInfo;
this.lastUpdateTime = new Date().getTime();
setAuthCache(USER_INFO_KEY, userInfo);
@ -111,7 +111,7 @@ export const useUserStore = defineStore({ @@ -111,7 +111,7 @@ export const useUserStore = defineStore({
this.setPermissions([]);
},
/** 登录 */
async login(params: LoginParams): Promise<User | null> {
async login(params: LoginParams): Promise<UserVo | null> {
try {
const { goHome = true, clientId = '', ...loginParams } = params;
// 处理自定义授权客户端
@ -134,7 +134,7 @@ export const useUserStore = defineStore({ @@ -134,7 +134,7 @@ export const useUserStore = defineStore({
}
},
/** 登录成功后动作 */
async afterLoginAction(goHome?: boolean): Promise<User | null> {
async afterLoginAction(goHome?: boolean): Promise<UserVo | null> {
if (!this.getAccessToken) return null;
// 获取用户信息
const userInfo = await this.getUserInfoAction();
@ -157,7 +157,7 @@ export const useUserStore = defineStore({ @@ -157,7 +157,7 @@ export const useUserStore = defineStore({
return userInfo;
},
/** 获取用户信息 */
async getUserInfoAction(): Promise<User> {
async getUserInfoAction(): Promise<UserVo> {
const { apiUrl } = useGlobSetting();
const { t } = useI18n();
try {
@ -167,7 +167,6 @@ export const useUserStore = defineStore({ @@ -167,7 +167,6 @@ export const useUserStore = defineStore({
? userInfo.avatar
: apiUrl + userInfo.avatar
: await urlToBase64(defaultAvatar);
userInfo.tenantIds = String(userInfo.tenantId).split(',');
// 存储用户扩展信息,便于鉴权
this.setUserInfo(userInfo);
this.setRoleIds(userInfo.roleIds);

4
src/utils/cache/persistent.ts vendored

@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
*/
import type { LockInfo } from '/#/store';
import type { User } from '/@/api/platform/core/entity/user';
import type { UserVo } from '/@/api/platform/core/entity/user';
import type { ProjectConfig } from '/#/config';
import type { RouteLocationNormalized } from 'vue-router';
import { createLocalStorage, createSessionStorage } from '/@/utils/cache';
@ -34,7 +34,7 @@ interface BasicStore { @@ -34,7 +34,7 @@ interface BasicStore {
[REFRESH_TOKEN_KEY]: string | number | null | undefined;
[ROLE_IDS_KEY]: string[];
[PERMISSIONS_KEY]: string[];
[USER_INFO_KEY]: User;
[USER_INFO_KEY]: UserVo;
[LOCK_INFO_KEY]: LockInfo;
[PROJ_CFG_KEY]: ProjectConfig;
[MULTIPLE_TABS_KEY]: RouteLocationNormalized[];

4
src/views/core/lock/LockPage.vue

@ -88,7 +88,7 @@ @@ -88,7 +88,7 @@
import { useNow } from './useNow';
import { useDesign } from '/@/hooks/web/useDesign';
import { LockOutlined } from '@ant-design/icons-vue';
import { User } from '/@/api/platform/core/entity/user';
import { UserVo } from '/@/api/platform/core/entity/user';
import defaultAvatar from '/@/assets/images/defaultAvatar.svg';
const InputPassword = Input.Password;
@ -101,7 +101,7 @@ @@ -101,7 +101,7 @@
const userStore = useUserStore();
const { hour, month, minute, meridiem, year, day, week } = useNow(true);
const { t } = useI18n();
const userInfo = computed<User>(() => {
const userInfo = computed<UserVo>(() => {
return userStore.getUserInfo || {};
});

95
src/views/demo/permission/Btn.vue

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
<template>
<PageWrapper contentBackground title="按钮权限控制" contentClass="p-4">
<p>
当前拥有的code列表: <a> {{ userStore.getPermissions }} </a>
</p>
<Divider/>
<Alert
class="mt-4"
type="info"
message="点击后请查看按钮变化(必须处于后台权限模式才可测试此页面所展示的功能)"
show-icon
/>
<Divider/>
<a-button type="primary" class="mr-2" @click="switchToken(2)">
点击切换按钮权限(用户id为2)
</a-button>
<a-button type="primary" @click="switchToken(1)">
点击切换按钮权限(用户id为1,默认)
</a-button>
<template>
<Divider>组件方式判断权限</Divider>
<Authority :value="'1000'">
<a-button type="primary" class="mx-4"> 拥有code ['1000']权限可见 </a-button>
</Authority>
<Authority :value="'2000'">
<a-button color="success" class="mx-4"> 拥有code ['2000']权限可见 </a-button>
</Authority>
<Authority :value="['1000', '2000']">
<a-button color="error" class="mx-4"> 拥有code ['1000','2000']角色权限可见 </a-button>
</Authority>
<Divider>函数方式方式判断权限</Divider>
<a-button v-if="hasPermission('1000')" type="primary" class="mx-4">
拥有code ['1000']权限可见
</a-button>
<a-button v-if="hasPermission('2000')" color="success" class="mx-4">
拥有code ['2000']权限可见
</a-button>
<a-button v-if="hasPermission(['1000', '2000'])" color="error" class="mx-4">
拥有code ['1000','2000']角色权限可见
</a-button>
<Divider>指令方式方式判断权限(该方式不能动态修改权限.)</Divider>
<a-button v-auth="'1000'" type="primary" class="mx-4"> 拥有code ['1000']权限可见 </a-button>
<a-button v-auth="'2000'" color="success" class="mx-4"> 拥有code ['2000']权限可见 </a-button>
<a-button v-auth="['1000', '2000']" color="error" class="mx-4">
拥有code ['1000','2000']角色权限可见
</a-button>
</template>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Alert, Divider } from 'ant-design-vue';
import { usePermission } from '/@/hooks/web/usePermission';
import { Authority } from '/@/components/Authority';
import { PageWrapper } from '/@/components/Page';
import { useUserStore } from '/@/store/modules/user';
export default defineComponent({
components: { Alert, PageWrapper, Divider, Authority },
setup() {
const { hasPermission } = usePermission();
const userStore = useUserStore();
async function switchToken(userId: number) {
// Token(demo)
// com.cloud.kicc.common.data.entity.CasUser roleId
const token = '46cdd008-4129-4d88-b845-a52d78b163db';
userStore.setAccessToken(token);
//
userStore.getUserInfoAction();
}
return {
hasPermission,
userStore,
switchToken,
};
},
});
</script>
<style lang="less" scoped>
.demo {
background-color: @component-background;
}
</style>

61
src/views/demo/permission/index.vue

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
<template>
<PageWrapper
title="后台权限示例 用户角色切换"
contentBackground
contentClass="p-4"
content="目前mock了两组数据, id为1 和 2 具体返回的菜单可以在mock/sys/menu.ts内查看"
>
<Alert class="mt-4"
type="info"
message="点击后请查看左侧菜单变化"
show-icon
/>
<div class="mt-4">
权限切换(请先切换权限模式为后台权限模式):
<Space>
<a-button @click="switchToken(1)">
获取用户id为1的菜单
</a-button>
<a-button @click="switchToken(2)">
获取用户id为2的菜单
</a-button>
</Space>
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { usePermission } from '/@/hooks/web/usePermission';
import { useUserStore } from '/@/store/modules/user';
import { PageWrapper } from '/@/components/Page';
import { Alert, Space } from 'ant-design-vue';
export default defineComponent({
components: { Space, Alert, PageWrapper },
setup() {
const { refreshMenu } = usePermission();
const userStore = useUserStore();
async function switchToken(userId: number) {
// Token (demo)
// com.cloud.kicc.common.data.entity.CasUser roleId
const token = '46cdd008-4129-4d88-b845-a52d78b163db';
userStore.setAccessToken(token);
//
userStore.getUserInfoAction();
refreshMenu();
}
return {
refreshMenu,
switchToken,
};
},
});
</script>
<style lang="less" scoped>
.demo {
background-color: @component-background;
}
</style>

96
src/views/system/user/ResetPwdModal.vue

@ -1,96 +0,0 @@ @@ -1,96 +0,0 @@
<template>
<BasicModal
v-bind="$attrs"
centered
title="重置密码"
minHeight="100px"
@ok="handleSubmit"
@register="registerModal"
>
<Form :model="modelRef" :rules="rulesRef">
<FormItem name="newPassword" v-bind="validateInfos.newPassword">
<StrengthMeter v-model:value="modelRef.newPassword" placeholder="请输入重置密码"/>
</FormItem>
</Form>
</BasicModal>
</template>
<script lang="ts" setup>
/**
* 提供模板规范代码参考,请尽量保证编写代码风格跟模板规范代码一致
* 采用ant-design-vue原生组件编写表单,采用 setup 写法
* Copyright © 2023-2023 <a href="https://godolphinx.org">海豚生态开源社区</a> All rights reserved.
* author wangxiang4
*/
import { reactive } from 'vue';
import { BasicModal, ModalProps, useModalInner } from '/@/components/Modal';
import { StrengthMeter } from '/@/components/StrengthMeter';
import { Form } from 'ant-design-vue';
import { resetPwd } from '/@/api/platform/system/controller/user';
import { useMessage } from '/@/hooks/web/useMessage';
/** 类型规范统一声明定义区域 */
interface WindowState {
id: string;
newPassword: string;
}
/** 通用变量统一声明区域 */
const { createMessage } = useMessage();
/** https://v3.cn.vuejs.org/api/options-data.html#emits */
const emit = defineEmits(['success', 'register']);
const FormItem = Form.Item;
const useForm = Form.useForm;
const modelRef = reactive<WindowState>({
id: '',
newPassword: ''
});
const rulesRef = reactive<Recordable>({
newPassword: [
{
required: true,
whitespace: true,
message: '请输入密码!',
},
{
pattern: new RegExp('[^\\u4e00-\\u9fa5]+'),
type: 'string',
message: '密码不能输入汉字!',
},
{
min: 6,
max: 32,
message: '长度必需在6-32之间!',
}
]
});
const { resetFields, clearValidate, validate, validateInfos } = useForm(modelRef, rulesRef);
const [registerModal, { setModalProps, closeModal }] = useModalInner( (data: BoxPayload) => {
//
resetFields();
clearValidate();
//
modelRef.id = data.record?.id;
const props: Partial<ModalProps> = { confirmLoading: false };
// :
setModalProps(props);
});
/** 处理模态框提交 */
async function handleSubmit() {
try {
//
await validate();
//
setModalProps({ confirmLoading: true });
if (!modelRef.id) return createMessage.error('用户编号ID不存在,请检查!');
await resetPwd(modelRef);
//
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>

9
src/views/system/user/account/setting/UserInfo.vue

@ -29,17 +29,18 @@ @@ -29,17 +29,18 @@
import { BasicForm, useForm } from '/@/components/Form/index';
import { CropperAvatar } from '/@/components/Cropper';
import { useMessage } from '/@/hooks/web/useMessage';
import { editUser, getUser } from '/@/api/platform/system/controller/user';
import { getUser } from '/@/api/platform/system/controller/user';
import { updateSsoUserAndExUser } from '/@/api/platform/system/controller/ssoUser';
import { userFormSchema } from './data';
import { useUserStore } from '/@/store/modules/user';
import { commonUpload } from '/@/api/platform/core/controller/upload';
import { useContentHeight } from '/@/hooks/web/useContentHeight';
import { User } from '/@/api/platform/core/entity/user';
import { UserVo } from '/@/api/platform/core/entity/user';
import { isBase64image } from '/@/utils/is';
interface State {
baseInfoBtnLoading: boolean;
userInfo: User | any;
userInfo: UserVo | any;
}
export default defineComponent({
components: {
@ -96,7 +97,7 @@ @@ -96,7 +97,7 @@
!isBase64image(state.userInfo.avatar) &&
(formData.avatar = state.userInfo.avatar);
state.baseInfoBtnLoading = true;
await editUser(formData);
await updateSsoUserAndExUser(formData);
createMessage.success('保存成功!');
await userStore.getUserInfoAction();
} finally {

6
src/views/system/user/account/setting/data.ts

@ -34,6 +34,12 @@ export const userFormSchema: FormSchema[] = [ @@ -34,6 +34,12 @@ export const userFormSchema: FormSchema[] = [
component: 'Input',
show: false
},
{
field: 'casUserId',
label: 'cas用户ID',
component: 'Input',
show: false
},
{
field: 'nickName',
label: '用户昵称',

19
src/views/system/user/index.vue

@ -47,20 +47,12 @@ @@ -47,20 +47,12 @@
auth: ['user_del'],
onClick: handleDel.bind(null, record)
}]"
:dropDownActions="[
{
label: '重置密码',
icon: 'fa6-brands:battle-net',
auth: ['user_reset'],
onClick: handleResetPassword.bind(null, record),
}]"
/>
</template>
</template>
</BasicTable>
<!--弹出窗体区域-->
<UserModal @register="registerModal" @success="handleRefreshTable"/>
<ResetPwdModal @register="registerResetPwdModal" @success="handleRefreshTable"/>
</PageWrapper>
</template>
@ -74,7 +66,6 @@ @@ -74,7 +66,6 @@
import { defineComponent, reactive, toRaw } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { listUser, delUser } from '/@/api/platform/system/controller/user';
import ResetPwdModal from './ResetPwdModal.vue';
import { PageWrapper } from '/@/components/Page';
import DeptTree from './DeptTree.vue';
import { useModal } from '/@/components/Modal';
@ -98,7 +89,6 @@ @@ -98,7 +89,6 @@
DeptTree,
TableAction,
UserModal,
ResetPwdModal,
},
setup() {
@ -115,7 +105,6 @@ @@ -115,7 +105,6 @@
});
const { createConfirm, createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerResetPwdModal, { openModal: openResetPwdModal }] = useModal();
const [registerTable, { reload, clearSelectedRowKeys }] = useTable({
title: '用户列表',
api: listUser,
@ -166,12 +155,6 @@ @@ -166,12 +155,6 @@
openModal(true, { _tag: 'edit', record });
}
/** 处理重置用户密码 */
function handleResetPassword(record: Recordable) {
record = record || { id: toRaw(state.ids) };
openResetPwdModal(true, { record });
}
/** 删除按钮操作,行内删除 */
async function handleDel(record?: Recordable) {
const ids = record?.id || toRaw(state.ids);
@ -203,14 +186,12 @@ @@ -203,14 +186,12 @@
state,
registerTable,
registerModal,
registerResetPwdModal,
handleAdd,
handleEdit,
handleDel,
handleSelectionChange,
handleRefreshTable,
handleSelect,
handleResetPassword,
};
}
});

4
src/views/system/user/sso/sso.data.ts

@ -160,10 +160,6 @@ export const userFormSchema: FormSchema[] = [ @@ -160,10 +160,6 @@ export const userFormSchema: FormSchema[] = [
label: '邮箱',
component: 'Input',
rules: [
{
required: true,
message: '请输入邮箱!',
},
{
type: 'email',
message: '请输入正确的邮箱地址!',

Loading…
Cancel
Save