322 lines
6.8 KiB
Vue
322 lines
6.8 KiB
Vue
<template>
|
|
<view class="page">
|
|
<!-- 当前生效身份 -->
|
|
<view v-if="currentIdentity" class="current-banner">
|
|
<view class="banner-label">当前生效身份</view>
|
|
<view class="banner-name">{{ getIdentityTitle(currentIdentity) }}</view>
|
|
<view class="banner-sub">{{ getIdentitySubtitle(currentIdentity) }}</view>
|
|
</view>
|
|
|
|
<!-- 加载中 -->
|
|
<view v-if="loading" class="state-box">
|
|
<u-loading-icon mode="circle" color="#007aff"></u-loading-icon>
|
|
<text class="state-text">加载中...</text>
|
|
</view>
|
|
|
|
<!-- 空状态 -->
|
|
<view v-else-if="!identityList.length" class="state-box">
|
|
<text class="state-text">暂无可用身份</text>
|
|
</view>
|
|
|
|
<!-- 身份列表 -->
|
|
<view v-else class="identity-list">
|
|
<view
|
|
v-for="item in identityList"
|
|
:key="item.identityId"
|
|
class="identity-card"
|
|
:class="{
|
|
'is-current': isCurrentIdentity(item),
|
|
'is-default': item.isDefault
|
|
}"
|
|
>
|
|
<view class="card-header">
|
|
<view class="card-title">{{ getIdentityTitle(item) }}</view>
|
|
<view class="card-tags">
|
|
<view v-if="isCurrentIdentity(item)" class="tag tag-current">当前使用</view>
|
|
<view v-if="item.isDefault" class="tag tag-default">默认</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="info-list">
|
|
<view class="info-row">
|
|
<text class="info-label">所属部门</text>
|
|
<text class="info-value">{{ item.deptName || '-' }}</text>
|
|
</view>
|
|
<view class="info-row">
|
|
<text class="info-label">所属角色</text>
|
|
<text class="info-value">{{ item.roleName || '-' }}</text>
|
|
</view>
|
|
<view class="info-row">
|
|
<text class="info-label">角色标识</text>
|
|
<text class="info-value">{{ item.roleKey || '-' }}</text>
|
|
</view>
|
|
<view v-if="item.postName" class="info-row">
|
|
<text class="info-label">所属岗位</text>
|
|
<text class="info-value">{{ item.postName }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<button
|
|
class="switch-btn"
|
|
:class="{ 'switch-btn--disabled': isCurrentIdentity(item) }"
|
|
:loading="switchingId === item.identityId"
|
|
:disabled="isCurrentIdentity(item) || !!switchingId"
|
|
@click="handleSwitch(item)"
|
|
>
|
|
{{ isCurrentIdentity(item) ? '当前使用中' : '切换到此身份' }}
|
|
</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
import { onShow } from '@dcloudio/uni-app';
|
|
import { getMyIdentity } from '@/request/identity.js';
|
|
import { performIdentitySwitch, reLaunchAfterSwitch } from '@/utils/identitySwitch.js';
|
|
|
|
const loading = ref(false);
|
|
const switchingId = ref(null);
|
|
const identityList = ref([]);
|
|
const currentIdentity = ref(null);
|
|
|
|
function unwrapIdentityData(res) {
|
|
if (!res) return { identities: [], currentIdentity: null };
|
|
const data = res.data && typeof res.data === 'object' ? res.data : res;
|
|
return {
|
|
identities: data.identities || [],
|
|
currentIdentity: data.currentIdentity || null
|
|
};
|
|
}
|
|
|
|
function getIdentityTitle(item) {
|
|
return item.identityName || item.roleName || '未命名身份';
|
|
}
|
|
|
|
function getIdentitySubtitle(item) {
|
|
const parts = [];
|
|
if (item.deptName) parts.push(item.deptName);
|
|
if (item.roleName && item.roleName !== item.identityName) parts.push(item.roleName);
|
|
return parts.join(' · ') || '-';
|
|
}
|
|
|
|
function isCurrentIdentity(item) {
|
|
if (item.current) return true;
|
|
return currentIdentity.value && currentIdentity.value.identityId === item.identityId;
|
|
}
|
|
|
|
async function fetchIdentityList() {
|
|
loading.value = true;
|
|
try {
|
|
const res = await getMyIdentity();
|
|
if (res.code === 0 || res.code === 200) {
|
|
const { identities, currentIdentity: current } = unwrapIdentityData(res);
|
|
identityList.value = identities;
|
|
currentIdentity.value = current;
|
|
} else {
|
|
identityList.value = [];
|
|
currentIdentity.value = null;
|
|
uni.showToast({ title: res.msg || '获取身份列表失败', icon: 'none' });
|
|
}
|
|
} catch (e) {
|
|
console.error('获取身份列表失败:', e);
|
|
identityList.value = [];
|
|
currentIdentity.value = null;
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
async function handleSwitch(item) {
|
|
if (isCurrentIdentity(item) || switchingId.value) return;
|
|
|
|
const identityName = getIdentityTitle(item);
|
|
const confirmMsg = `确认切换到「${identityName}」吗?切换后数据将按新身份刷新。`;
|
|
|
|
uni.showModal({
|
|
title: '切换身份',
|
|
content: confirmMsg,
|
|
confirmText: '确认切换',
|
|
success: async (modalRes) => {
|
|
if (!modalRes.confirm) return;
|
|
|
|
switchingId.value = item.identityId;
|
|
try {
|
|
await performIdentitySwitch(item.identityId);
|
|
reLaunchAfterSwitch();
|
|
} catch (e) {
|
|
console.error('身份切换失败:', e);
|
|
} finally {
|
|
switchingId.value = null;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
onShow(() => {
|
|
fetchIdentityList();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.page {
|
|
min-height: 100vh;
|
|
background: #f4f7fb;
|
|
padding: 24rpx;
|
|
padding-bottom: 48rpx;
|
|
}
|
|
|
|
.current-banner {
|
|
background: linear-gradient(135deg, #3e95f1 0%, #4269f5 100%);
|
|
border-radius: 20rpx;
|
|
padding: 32rpx;
|
|
margin-bottom: 24rpx;
|
|
color: #fff;
|
|
|
|
.banner-label {
|
|
font-size: 24rpx;
|
|
opacity: 0.85;
|
|
}
|
|
|
|
.banner-name {
|
|
font-size: 34rpx;
|
|
font-weight: bold;
|
|
margin-top: 12rpx;
|
|
}
|
|
|
|
.banner-sub {
|
|
font-size: 26rpx;
|
|
opacity: 0.9;
|
|
margin-top: 8rpx;
|
|
}
|
|
}
|
|
|
|
.state-box {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 120rpx 0;
|
|
|
|
.state-text {
|
|
margin-top: 24rpx;
|
|
font-size: 28rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.identity-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24rpx;
|
|
}
|
|
|
|
.identity-card {
|
|
background: #fff;
|
|
border-radius: 20rpx;
|
|
padding: 32rpx;
|
|
border: 2rpx solid transparent;
|
|
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
|
|
|
&.is-current {
|
|
border-color: #67c23a;
|
|
}
|
|
|
|
&.is-default {
|
|
border-color: #e6a23c;
|
|
}
|
|
|
|
&.is-current.is-default {
|
|
border-color: #67c23a;
|
|
}
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 16rpx;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
.card-title {
|
|
flex: 1;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.card-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8rpx;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.tag {
|
|
font-size: 22rpx;
|
|
padding: 4rpx 12rpx;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.tag-current {
|
|
background: #e8f8ef;
|
|
color: #67c23a;
|
|
}
|
|
|
|
.tag-default {
|
|
background: #fdf6ec;
|
|
color: #e6a23c;
|
|
}
|
|
|
|
.info-list {
|
|
margin-bottom: 28rpx;
|
|
}
|
|
|
|
.info-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
padding: 16rpx 0;
|
|
border-bottom: 1rpx dashed #eee;
|
|
font-size: 28rpx;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
}
|
|
|
|
.info-label {
|
|
color: #999;
|
|
flex-shrink: 0;
|
|
margin-right: 24rpx;
|
|
}
|
|
|
|
.info-value {
|
|
color: #333;
|
|
text-align: right;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.switch-btn {
|
|
width: 100%;
|
|
height: 80rpx;
|
|
line-height: 80rpx;
|
|
background: linear-gradient(90deg, #3e95f1 0%, #4269f5 100%);
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
border-radius: 40rpx;
|
|
border: none;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&--disabled {
|
|
background: #e8e8e8;
|
|
color: #999;
|
|
}
|
|
}
|
|
</style>
|