diff --git a/src/api/login/index.ts b/src/api/login/index.ts
index ef86563b1..d1b064057 100644
--- a/src/api/login/index.ts
+++ b/src/api/login/index.ts
@@ -12,11 +12,26 @@ export interface SmsLoginVO {
code: string
}
+export interface ImpersonateReqVO {
+ tenantId?: number
+ userId?: number
+}
+
// 登录
export const login = (data: UserLoginVO) => {
return request.post({ url: '/system/auth/login', data })
}
+// 模拟身份登录
+export const loginImpersonate = (data: ImpersonateReqVO) => {
+ return request.post({ url: '/system/auth/login/impersonate', data})
+}
+
+// 退出身份模拟
+export const stopImpersonation = () => {
+ return request.post({ url: '/system/auth/stop-impersonation'})
+}
+
// 刷新访问令牌
export const refreshToken = () => {
return request.post({ url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken() })
diff --git a/src/layout/components/UserInfo/src/UserInfo.vue b/src/layout/components/UserInfo/src/UserInfo.vue
index 5c5e37322..ee4d0189c 100644
--- a/src/layout/components/UserInfo/src/UserInfo.vue
+++ b/src/layout/components/UserInfo/src/UserInfo.vue
@@ -8,6 +8,8 @@ import { useUserStore } from '@/store/modules/user'
import LockDialog from './components/LockDialog.vue'
import LockPage from './components/LockPage.vue'
import { useLockStore } from '@/store/modules/lock'
+import * as LoginApi from '@/api/login'
+import * as authUtil from "@/utils/auth"
defineOptions({ name: 'UserInfo' })
@@ -34,6 +36,18 @@ const lockScreen = () => {
dialogVisible.value = true
}
+const stopImpersonation = async () => {
+ const res = await LoginApi.stopImpersonation()
+ if(!res){
+ return
+ }
+ await userStore.loginOut()
+ tagsViewStore.delAllViews()
+ authUtil.setToken(res)
+ authUtil.setTenantId(res.tenantId)
+ push({ path: authUtil.getImpersonateRefererPath() || '' })
+}
+
const loginOut = async () => {
try {
await ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
@@ -76,6 +90,10 @@ const toDocument = () => {
{{ t('lock.lockScreen') }}
+
+
+ {{ t('common.stopImpersonation') }}
+
{{ t('common.loginOut') }}
diff --git a/src/locales/en.ts b/src/locales/en.ts
index 6562c9b75..03ade0eff 100644
--- a/src/locales/en.ts
+++ b/src/locales/en.ts
@@ -7,6 +7,7 @@ export default {
login: 'Login',
required: 'This is required',
loginOut: 'Login out',
+ stopImpersonation: 'Stop impersonation',
document: 'Document',
profile: 'User Center',
reminder: 'Reminder',
diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts
index 0721651d8..c377fca2c 100644
--- a/src/locales/zh-CN.ts
+++ b/src/locales/zh-CN.ts
@@ -7,6 +7,7 @@ export default {
login: '登录',
required: '该项为必填项',
loginOut: '退出系统',
+ stopImpersonation: '退出身份模拟',
document: '项目文档',
profile: '个人中心',
reminder: '温馨提示',
diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts
index b38618096..b54847e71 100644
--- a/src/store/modules/user.ts
+++ b/src/store/modules/user.ts
@@ -11,6 +11,7 @@ interface UserVO {
avatar: string
nickname: string
deptId: number
+ impersonated: boolean
}
interface UserInfoVO {
diff --git a/src/utils/auth.ts b/src/utils/auth.ts
index c68a67a9b..7d64351c3 100644
--- a/src/utils/auth.ts
+++ b/src/utils/auth.ts
@@ -6,6 +6,7 @@ const { wsCache } = useCache()
const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN'
+const ImpersonateRefererKey = 'IMPERSONATED_REFERER'
// 获取token
export const getAccessToken = () => {
@@ -24,6 +25,16 @@ export const setToken = (token: TokenType) => {
wsCache.set(AccessTokenKey, token.accessToken)
}
+// 设置退出模拟身份登录后的跳转路径
+export const setImpersonateRefererPath = (path: string) => {
+ wsCache.set(ImpersonateRefererKey, path)
+}
+
+// 获取退出模拟身份登录后的跳转路径
+export const getImpersonateRefererPath = () => {
+ return wsCache.get(ImpersonateRefererKey)
+}
+
// 删除token
export const removeToken = () => {
wsCache.delete(AccessTokenKey)
diff --git a/src/views/system/tenant/index.vue b/src/views/system/tenant/index.vue
index ae9a2b790..8cb7e6abd 100644
--- a/src/views/system/tenant/index.vue
+++ b/src/views/system/tenant/index.vue
@@ -140,6 +140,16 @@
/>
+
+ 模拟身份
+
{
loading.value = true
@@ -243,6 +259,23 @@ const handleDelete = async (id: number) => {
} catch {}
}
+/** 模拟身份登录 */
+const handleImpersonate = async (row) => {
+ try {
+ const res = await LoginApi.loginImpersonate({tenantId: row.id, userId: row.contactUserId})
+ if (!res) {
+ return
+ }
+ await userStore.loginOut()
+ authUtil.setToken(res)
+ authUtil.setTenantId(row.id)
+ authUtil.setImpersonateRefererPath(currentRoute.value.path)
+ tagsViewStore.delAllViews()
+ push({ path: '/' })
+ } finally {
+ }
+}
+
/** 导出按钮操作 */
const handleExport = async () => {
try {