优化小程序登录工作空间与法律协议

This commit is contained in:
hero920103 committed 2026-10-30 21:01:41 +08:00
1 parent 2e2b837a20
commit 1eace4c082
6 files changed
+1084 -673

No files matched your search

+223 -13
View File
@@ -3,10 +3,35 @@
<!-- 顶部信息:融入页面背景,不再单独做彩色抬头 -->
<view class="head" :style="headPad">
<view class="head-row">
<text class="head-title">选择子系统</text>
<text class="head-count">{{ enabledCount }}/{{ cards.length }} 已开通</text>
<view>
<text class="head-title">工作空间</text>
<text class="head-caption">选择一个应用,开始今天的工作</text>
</view>
</view>
<view class="tenant-switcher" :class="{ selectable: tenants.length > 1 }" @tap="openTenantPicker">
<view class="tenant-mark"><FaIcon name="building" color="#3689d6" :size="17" /></view>
<view class="tenant-current">
<text class="tenant-label">当前公司</text>
<text class="head-sub">{{ user.tenant || '云泽平台' }}</text>
</view>
<text v-if="user.account" class="tenant-account">{{ user.account }}</text>
<FaIcon v-if="tenants.length > 1" name="chevron-right" color="#83a2be" :size="13" />
</view>
</view>
<view v-if="tenantPickerVisible" class="tenant-mask" @tap="closeTenantPicker">
<view class="tenant-sheet" @tap.stop>
<view class="sheet-head">
<text class="sheet-title">切换公司</text>
<text class="sheet-close" @tap="closeTenantPicker">完成</text>
</view>
<text class="sheet-sub">选择后将切换当前工作空间</text>
<view v-for="item in tenants" :key="item.tid" class="tenant-option" :class="{ current: Number(item.tid) === currentTid, disabled: switchingTenant }" @tap="changeTenant(item)">
<view class="tenant-option-icon"><FaIcon name="building" color="#398fe7" :size="16" /></view>
<view class="tenant-option-info"><text class="tenant-option-name">{{ item.tenant_name || `企业${item.tid}` }}</text><text class="tenant-option-meta">{{ Number(item.tid) === currentTid ? '当前工作空间' : '切换到此公司' }}</text></view>
<FaIcon v-if="Number(item.tid) === currentTid" name="circle-check" color="#398fe7" :size="18" />
</view>
</view>
<text class="head-sub">{{ user.tenant || '云泽平台' }}<text v-if="user.account"> · {{ user.account }}</text></text>
</view>
<view class="body">
@@ -53,7 +78,8 @@ import { mpHeadPad } from '@/utils/mpHead.js'
const headPad = mpHeadPad()
import { onShow } from '@dcloudio/uni-app'
import { isLoggedIn } from '@/utils/auth.js'
import { isLoggedIn, getTenants, getTid, setAuthTokens, setTid, setTenantName } from '@/utils/auth.js'
import { switchTenant } from '@/api/auth.js'
import { fetchHome } from '@/api/workspace.js'
import { openMenu } from '@/utils/nav.js'
import { getSubsystemByModule, goSubsystem } from '@/config/subsystems.js'
@@ -80,6 +106,10 @@ const loadError = ref('')
const user = ref({})
const modules = ref([])
const menus = ref([])
const tenants = ref([])
const currentTid = ref(0)
const tenantPickerVisible = ref(false)
const switchingTenant = ref(false)
/** 叶子菜单(可直接跳转的功能页),已锁定的过滤掉 */
const leafMenus = computed(() => menus.value.filter((m) => m.leaf !== false && !m.locked))
@@ -125,6 +155,8 @@ async function load(force = false) {
try {
const data = await fetchHome(force)
user.value = data.user || {}
tenants.value = getTenants()
currentTid.value = getTid()
modules.value = Array.isArray(data.modules) ? data.modules : []
menus.value = Array.isArray(data.menus) ? data.menus : []
loadError.value = ''
@@ -159,6 +191,43 @@ function enter(card) {
uni.showToast({ title: card.name + '暂未开放', icon: 'none' })
}
function openTenantPicker() {
if (tenants.value.length < 2) return
tenantPickerVisible.value = true
}
function closeTenantPicker() {
if (!switchingTenant.value) tenantPickerVisible.value = false
}
async function changeTenant(item) {
const tid = Number(item && item.tid)
if (!tid || tid === currentTid.value || switchingTenant.value) {
tenantPickerVisible.value = false
return
}
switchingTenant.value = true
uni.showLoading({ title: '正在切换...', mask: true })
try {
const result = await switchTenant({ tid })
if (!result || !result.tokens) throw new Error((result && result.msg) || '切换公司失败')
setAuthTokens(result.tokens)
setTid(tid)
const tenantName = item.tenant_name || `企业${tid}`
setTenantName(tenantName)
user.value = Object.assign({}, user.value, { tenant: tenantName, tid })
currentTid.value = tid
tenantPickerVisible.value = false
await load(true)
uni.showToast({ title: '已切换公司', icon: 'success' })
} catch (err) {
uni.showToast({ title: (err && err.message) || '切换公司失败', icon: 'none' })
} finally {
uni.hideLoading()
switchingTenant.value = false
}
}
/* ==================== 生命周期 ==================== */
onMounted(() => {
@@ -200,23 +269,70 @@ onShow(() => {
}
.head-title {
font-size: 42rpx;
font-weight: 600;
color: $color-text;
font-size: 46rpx;
font-weight: 700;
color: #193d61;
letter-spacing: 1rpx;
}
.head-count {
font-size: 23rpx;
color: $color-text-muted;
.head-caption {
display: block;
margin-top: 10rpx;
font-size: 24rpx;
color: #8aa2b8;
}
.tenant-switcher {
margin-top: 28rpx;
padding: 20rpx 22rpx;
display: flex;
align-items: center;
gap: 16rpx;
border: 1rpx solid rgba(255, 255, 255, 0.92);
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.78);
box-shadow: 0 12rpx 32rpx rgba(81, 133, 176, 0.08);
&.selectable:active { background: #f4faff; }
}
.tenant-mark {
width: 68rpx;
height: 68rpx;
flex-shrink: 0;
border-radius: 20rpx;
background: #eaf5ff;
display: flex;
align-items: center;
justify-content: center;
}
.tenant-current {
flex: 1;
min-width: 0;
}
.tenant-label {
display: block;
margin-bottom: 5rpx;
font-size: 20rpx;
color: #94aabe;
}
.head-sub {
display: block;
margin-top: 8rpx;
font-size: 23rpx;
color: $color-text-muted;
font-size: 28rpx;
font-weight: 600;
color: #294a68;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tenant-account {
max-width: 180rpx;
font-size: 21rpx;
color: #8da3b7;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -231,6 +347,100 @@ onShow(() => {
padding: 8rpx $page-padding-x 0;
}
.tenant-mask {
position: fixed;
z-index: 99;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(18, 42, 68, 0.32);
display: flex;
align-items: flex-end;
}
.tenant-sheet {
width: 100%;
max-height: 72vh;
overflow-y: auto;
padding: 38rpx 32rpx calc(env(safe-area-inset-bottom, 0px) + 40rpx);
box-sizing: border-box;
border-radius: 36rpx 36rpx 0 0;
background: linear-gradient(180deg, #f5faff 0%, #ffffff 24%);
}
.sheet-head {
display: flex;
align-items: center;
justify-content: space-between;
}
.sheet-title {
font-size: 32rpx;
font-weight: 600;
color: #203b56;
}
.sheet-close {
font-size: 25rpx;
color: #398fe7;
padding: 10rpx;
}
.sheet-sub {
display: block;
margin: 8rpx 0 20rpx;
font-size: 23rpx;
color: #8aa0b4;
}
.tenant-option {
display: flex;
align-items: center;
gap: 18rpx;
padding: 20rpx 16rpx;
border-radius: 18rpx;
border: 1rpx solid #edf3f8;
margin-top: 12rpx;
&.current {
background: #f2f8ff;
border-color: #cfe5fa;
}
&.disabled { opacity: 0.6; }
}
.tenant-option-icon {
width: 64rpx;
height: 64rpx;
border-radius: 18rpx;
background: #eaf5ff;
display: flex;
align-items: center;
justify-content: center;
}
.tenant-option-info {
flex: 1;
min-width: 0;
}
.tenant-option-name,
.tenant-option-meta { display: block; }
.tenant-option-name {
font-size: 27rpx;
font-weight: 500;
color: #294763;
}
.tenant-option-meta {
margin-top: 5rpx;
font-size: 22rpx;
color: #91a5b8;
}
/* ============ 失败提示 ============ */
.err-box {
display: flex;