feat(tenant): 推送配置说明与IM多端互踢配置
推送服务配置页新增字段说明提示(通道业务键含义、Channel ID 规则、 厂商凭据来源);IM 服务配置页新增"多端登录与互踢"卡片,支持三种 模式选择;app.ts 类型增加 multiDeviceLoginMode 字段。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
8521e35660
当前提交
4df6bd0e79
@ -39,6 +39,7 @@ export interface ImServiceConfig {
|
|||||||
historyRetentionDays: number
|
historyRetentionDays: number
|
||||||
conversationPullLimit: number
|
conversationPullLimit: number
|
||||||
multiClientConversationDeleteSync: boolean
|
multiClientConversationDeleteSync: boolean
|
||||||
|
multiDeviceLoginMode?: 'MULTI_DEVICE_FREE' | 'SAME_PLATFORM_ONE' | 'SINGLE_DEVICE'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateServiceConfig {
|
export interface UpdateServiceConfig {
|
||||||
|
|||||||
@ -108,6 +108,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
<el-card style="margin-bottom:16px">
|
||||||
|
<template #header>多端登录与互踢</template>
|
||||||
|
<div class="service-config-list">
|
||||||
|
<div class="service-config-row service-config-row--column">
|
||||||
|
<div>
|
||||||
|
<div class="service-config-title">多端登录方式</div>
|
||||||
|
<div class="service-config-desc">控制同一账号在多个设备上的登录行为。</div>
|
||||||
|
</div>
|
||||||
|
<el-radio-group
|
||||||
|
:model-value="imConfig.multiDeviceLoginMode"
|
||||||
|
class="login-mode-group"
|
||||||
|
@change="(val: ImServiceConfig['multiDeviceLoginMode']) => onToggleImConfig({ multiDeviceLoginMode: val })"
|
||||||
|
>
|
||||||
|
<el-radio value="MULTI_DEVICE_FREE">
|
||||||
|
全平台随意登录,不互踢
|
||||||
|
<div class="radio-desc">多台设备可同时在线,不限数量</div>
|
||||||
|
</el-radio>
|
||||||
|
<el-radio value="SAME_PLATFORM_ONE">
|
||||||
|
相同平台踢旧设备
|
||||||
|
<div class="radio-desc">同一平台(Android/iOS/鸿蒙)只保留最新登录设备,不同平台可同时在线</div>
|
||||||
|
</el-radio>
|
||||||
|
<el-radio value="SINGLE_DEVICE">
|
||||||
|
全平台只保留一台设备
|
||||||
|
<div class="radio-desc">任意设备登录后,其他所有设备均被踢下线</div>
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header>好友与关系链</template>
|
<template #header>好友与关系链</template>
|
||||||
<div class="service-config-list">
|
<div class="service-config-list">
|
||||||
@ -169,6 +199,7 @@ const imConfig = computed<ImServiceConfig>(() => {
|
|||||||
historyRetentionDays: parsed.historyRetentionDays ?? 7,
|
historyRetentionDays: parsed.historyRetentionDays ?? 7,
|
||||||
conversationPullLimit: parsed.conversationPullLimit ?? 100,
|
conversationPullLimit: parsed.conversationPullLimit ?? 100,
|
||||||
multiClientConversationDeleteSync: parsed.multiClientConversationDeleteSync ?? false,
|
multiClientConversationDeleteSync: parsed.multiClientConversationDeleteSync ?? false,
|
||||||
|
multiDeviceLoginMode: normalizeLoginMode(parsed.multiDeviceLoginMode),
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return defaultImConfig()
|
return defaultImConfig()
|
||||||
@ -186,9 +217,20 @@ function defaultImConfig(): ImServiceConfig {
|
|||||||
historyRetentionDays: 7,
|
historyRetentionDays: 7,
|
||||||
conversationPullLimit: 100,
|
conversationPullLimit: 100,
|
||||||
multiClientConversationDeleteSync: false,
|
multiClientConversationDeleteSync: false,
|
||||||
|
multiDeviceLoginMode: 'MULTI_DEVICE_FREE',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeLoginMode(
|
||||||
|
mode: ImServiceConfig['multiDeviceLoginMode'] | string | undefined,
|
||||||
|
): ImServiceConfig['multiDeviceLoginMode'] {
|
||||||
|
const normalized = (mode ?? '').toString().trim().toUpperCase()
|
||||||
|
if (normalized === 'SAME_PLATFORM_ONE' || normalized === 'SINGLE_DEVICE' || normalized === 'MULTI_DEVICE_FREE') {
|
||||||
|
return normalized as ImServiceConfig['multiDeviceLoginMode']
|
||||||
|
}
|
||||||
|
return 'MULTI_DEVICE_FREE'
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeFriendRequestMode(
|
function normalizeFriendRequestMode(
|
||||||
mode: ImServiceConfig['friendRequestMode'] | string | undefined,
|
mode: ImServiceConfig['friendRequestMode'] | string | undefined,
|
||||||
allowFriendRequest: boolean | undefined,
|
allowFriendRequest: boolean | undefined,
|
||||||
@ -252,6 +294,11 @@ onMounted(loadData)
|
|||||||
.service-name { font-size: 15px; }
|
.service-name { font-size: 15px; }
|
||||||
.service-config-list { display: flex; flex-direction: column; gap: 12px; }
|
.service-config-list { display: flex; flex-direction: column; gap: 12px; }
|
||||||
.service-config-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; font-size: 13px; color: #666; }
|
.service-config-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; font-size: 13px; color: #666; }
|
||||||
|
.service-config-row--column { flex-direction: column; align-items: flex-start; }
|
||||||
.service-config-title { font-size: 13px; font-weight: 500; color: #303133; line-height: 1.4; }
|
.service-config-title { font-size: 13px; font-weight: 500; color: #303133; line-height: 1.4; }
|
||||||
.service-config-desc { margin-top: 4px; font-size: 12px; color: #909399; line-height: 1.4; }
|
.service-config-desc { margin-top: 4px; font-size: 12px; color: #909399; line-height: 1.4; }
|
||||||
|
.login-mode-group { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
|
||||||
|
.login-mode-group :deep(.el-radio) { height: auto; align-items: flex-start; margin-right: 0; }
|
||||||
|
.login-mode-group :deep(.el-radio__label) { white-space: normal; font-size: 13px; font-weight: 500; color: #303133; }
|
||||||
|
.radio-desc { font-size: 12px; color: #909399; font-weight: 400; line-height: 1.5; margin-top: 2px; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -34,6 +34,13 @@
|
|||||||
<el-card>
|
<el-card>
|
||||||
<template #header>厂商配置</template>
|
<template #header>厂商配置</template>
|
||||||
<el-divider content-position="left">通知通道</el-divider>
|
<el-divider content-position="left">通知通道</el-divider>
|
||||||
|
<el-alert
|
||||||
|
description="通知通道定义 Android 通知渠道,以及 iOS/鸿蒙 对应的分类配置。业务键(Key)为业务层自定义的唯一标识,代码内部用于引用此通道,例如 im_message;Channel ID 需与 App manifest 中声明的 NotificationChannel ID 完全一致;版本号在渠道参数变更时自增,客户端将以新版本号重新注册渠道。"
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
:show-icon="false"
|
||||||
|
style="margin-bottom:12px"
|
||||||
|
/>
|
||||||
<el-table :data="pushConfig.channels" border style="margin-bottom:16px">
|
<el-table :data="pushConfig.channels" border style="margin-bottom:16px">
|
||||||
<el-table-column label="业务键" min-width="130">
|
<el-table-column label="业务键" min-width="130">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
@ -80,6 +87,13 @@
|
|||||||
<el-button style="margin-bottom:20px" @click="addChannel">新增通道</el-button>
|
<el-button style="margin-bottom:20px" @click="addChannel">新增通道</el-button>
|
||||||
|
|
||||||
<el-divider content-position="left">业务分类路由</el-divider>
|
<el-divider content-position="left">业务分类路由</el-divider>
|
||||||
|
<el-alert
|
||||||
|
description="业务分类路由将系统内置的推送类型(如 IM 消息、好友请求、系统通知)映射到对应通道和优先级,决定推送到达时的展示行为。"
|
||||||
|
type="info"
|
||||||
|
:closable="false"
|
||||||
|
:show-icon="false"
|
||||||
|
style="margin-bottom:12px"
|
||||||
|
/>
|
||||||
<el-table :data="routeRows" border style="margin-bottom:20px">
|
<el-table :data="routeRows" border style="margin-bottom:20px">
|
||||||
<el-table-column label="业务分类" width="160">
|
<el-table-column label="业务分类" width="160">
|
||||||
<template #default="{ row }">{{ row.type }}</template>
|
<template #default="{ row }">{{ row.type }}</template>
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户