Pre Merge pull request !458 from janeywong/master

pull/458/MERGE
janeywong 2024-09-28 12:33:52 +00:00 committed by Gitee
commit d864793b6d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 81 additions and 1 deletions

View File

@ -12,11 +12,26 @@ export interface SmsLoginVO {
code: string code: string
} }
export interface ImpersonateReqVO {
tenantId?: number
userId?: number
}
// 登录 // 登录
export const login = (data: UserLoginVO) => { export const login = (data: UserLoginVO) => {
return request.post({ url: '/system/auth/login', data }) 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 = () => { export const refreshToken = () => {
return request.post({ url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken() }) return request.post({ url: '/system/auth/refresh-token?refreshToken=' + getRefreshToken() })

View File

@ -8,6 +8,8 @@ import { useUserStore } from '@/store/modules/user'
import LockDialog from './components/LockDialog.vue' import LockDialog from './components/LockDialog.vue'
import LockPage from './components/LockPage.vue' import LockPage from './components/LockPage.vue'
import { useLockStore } from '@/store/modules/lock' import { useLockStore } from '@/store/modules/lock'
import * as LoginApi from '@/api/login'
import * as authUtil from "@/utils/auth"
defineOptions({ name: 'UserInfo' }) defineOptions({ name: 'UserInfo' })
@ -34,6 +36,18 @@ const lockScreen = () => {
dialogVisible.value = true 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 () => { const loginOut = async () => {
try { try {
await ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), { await ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
@ -76,6 +90,10 @@ const toDocument = () => {
<Icon icon="ep:lock" /> <Icon icon="ep:lock" />
<div @click="lockScreen">{{ t('lock.lockScreen') }}</div> <div @click="lockScreen">{{ t('lock.lockScreen') }}</div>
</ElDropdownItem> </ElDropdownItem>
<ElDropdownItem divided v-if="userStore.getUser.impersonated">
<Icon icon="humbleicons:incognito" />
<div @click="stopImpersonation">{{ t('common.stopImpersonation') }}</div>
</ElDropdownItem>
<ElDropdownItem divided @click="loginOut"> <ElDropdownItem divided @click="loginOut">
<Icon icon="ep:switch-button" /> <Icon icon="ep:switch-button" />
<div>{{ t('common.loginOut') }}</div> <div>{{ t('common.loginOut') }}</div>

View File

@ -7,6 +7,7 @@ export default {
login: 'Login', login: 'Login',
required: 'This is required', required: 'This is required',
loginOut: 'Login out', loginOut: 'Login out',
stopImpersonation: 'Stop impersonation',
document: 'Document', document: 'Document',
profile: 'User Center', profile: 'User Center',
reminder: 'Reminder', reminder: 'Reminder',

View File

@ -7,6 +7,7 @@ export default {
login: '登录', login: '登录',
required: '该项为必填项', required: '该项为必填项',
loginOut: '退出系统', loginOut: '退出系统',
stopImpersonation: '退出身份模拟',
document: '项目文档', document: '项目文档',
profile: '个人中心', profile: '个人中心',
reminder: '温馨提示', reminder: '温馨提示',

View File

@ -11,6 +11,7 @@ interface UserVO {
avatar: string avatar: string
nickname: string nickname: string
deptId: number deptId: number
impersonated: boolean
} }
interface UserInfoVO { interface UserInfoVO {

View File

@ -6,6 +6,7 @@ const { wsCache } = useCache()
const AccessTokenKey = 'ACCESS_TOKEN' const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN' const RefreshTokenKey = 'REFRESH_TOKEN'
const ImpersonateRefererKey = 'IMPERSONATED_REFERER'
// 获取token // 获取token
export const getAccessToken = () => { export const getAccessToken = () => {
@ -24,6 +25,16 @@ export const setToken = (token: TokenType) => {
wsCache.set(AccessTokenKey, token.accessToken) wsCache.set(AccessTokenKey, token.accessToken)
} }
// 设置退出模拟身份登录后的跳转路径
export const setImpersonateRefererPath = (path: string) => {
wsCache.set(ImpersonateRefererKey, path)
}
// 获取退出模拟身份登录后的跳转路径
export const getImpersonateRefererPath = () => {
return wsCache.get(ImpersonateRefererKey)
}
// 删除token // 删除token
export const removeToken = () => { export const removeToken = () => {
wsCache.delete(AccessTokenKey) wsCache.delete(AccessTokenKey)

View File

@ -140,6 +140,16 @@
/> />
<el-table-column label="操作" align="center" min-width="110" fixed="right"> <el-table-column label="操作" align="center" min-width="110" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button
link
type="primary"
@click="handleImpersonate(scope.row)"
v-if="authUtil.getTenantId() !== scope.row.id"
v-hasPermi="['system:login:impersonate']"
v-hasRole="['super_admin']"
>
模拟身份
</el-button>
<el-button <el-button
link link
type="primary" type="primary"
@ -176,14 +186,20 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime' import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download' import download from '@/utils/download'
import * as TenantApi from '@/api/system/tenant' import * as TenantApi from '@/api/system/tenant'
import * as LoginApi from '@/api/login'
import * as authUtil from '@/utils/auth'
const { currentRoute, push } = useRouter()
import { useUserStore } from '@/store/modules/user'
import * as TenantPackageApi from '@/api/system/tenantPackage' import * as TenantPackageApi from '@/api/system/tenantPackage'
import TenantForm from './TenantForm.vue' import TenantForm from './TenantForm.vue'
import { useTagsViewStore } from '@/store/modules/tagsView'
defineOptions({ name: 'SystemTenant' }) defineOptions({ name: 'SystemTenant' })
const message = useMessage() // const message = useMessage() //
const { t } = useI18n() // const { t } = useI18n() //
const userStore = useUserStore()
const loading = ref(true) // const loading = ref(true) //
const total = ref(0) // const total = ref(0) //
const list = ref([]) // const list = ref([]) //
@ -199,7 +215,7 @@ const queryParams = reactive({
const queryFormRef = ref() // const queryFormRef = ref() //
const exportLoading = ref(false) // const exportLoading = ref(false) //
const packageList = ref([] as TenantPackageApi.TenantPackageVO[]) // const packageList = ref([] as TenantPackageApi.TenantPackageVO[]) //
const tagsViewStore = useTagsViewStore()
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
@ -243,6 +259,23 @@ const handleDelete = async (id: number) => {
} catch {} } 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 () => { const handleExport = async () => {
try { try {