初始版本

This commit is contained in:
2026-04-23 16:30:57 +08:00
commit 0d0683a6e6
538 changed files with 113042 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
/**
* 资源中心协作权限 composable
*
* 权限级别:
* 0 - 无权限
* 1 - 基础查看:名称/IP/端口/状态(所有团队成员)
* 2 - 连接查看用户名、Host、连接方式技术负责人及以上
* 3 - 完全权限:密码、私钥、编辑/删除(仅资源 Owner
*/
import type { AppResource } from '@/api/app/appResource/model'
export type ResourceAccessLevel = 0 | 1 | 2 | 3
/**
* 判断当前用户是否是资源所有者
* 后端在返回时会带 ownerUserId 字段,前端基于 localStorage UserId 判断
*/
export function isResourceOwner(resource: AppResource): boolean {
if (!import.meta.client) return false
const currentUserId = localStorage.getItem('UserId')
if (!currentUserId) return false
return Number(currentUserId) === Number(resource.ownerUserId)
|| Number(currentUserId) === Number(resource.userId)
}
/**
* 获取当前用户对某资源的访问级别
* - 后端若已计算 accessLevel直接使用
* - 否则前端保底逻辑Owner=3其余=1
*/
export function getResourceAccessLevel(resource: AppResource): ResourceAccessLevel {
// 后端已计算的权限级别,优先使用
if (resource.accessLevel !== undefined) {
return resource.accessLevel
}
// 降级:判断是否是 owner
return isResourceOwner(resource) ? 3 : 1
}
/** 是否有基础查看权限(所有人) */
export function canViewBasic(resource: AppResource): boolean {
return getResourceAccessLevel(resource) >= 1
}
/** 是否有连接信息查看权限用户名、Host 等) */
export function canViewConnection(resource: AppResource): boolean {
return getResourceAccessLevel(resource) >= 2
}
/** 是否有完整权限(编辑、删除、查看密码/私钥) */
export function canViewSensitive(resource: AppResource): boolean {
return getResourceAccessLevel(resource) >= 3
}
/** 是否能编辑/删除该资源 */
export function canManageResource(resource: AppResource): boolean {
return getResourceAccessLevel(resource) >= 3
}
/** 脱敏占位符:判断某字段是否已被后端脱敏 */
export function isMaskedValue(value: string | null | undefined): boolean {
if (!value) return false
return value === '******' || value === '***' || /^\*{3,}$/.test(value)
}
/**
* 资源权限 composablereactive接受 computed/ref 的资源对象)
*/
export function useResourceAccess(resource: AppResource | (() => AppResource | null | undefined)) {
const getResource = (): AppResource | null | undefined =>
typeof resource === 'function' ? resource() : resource
const accessLevel = computed<ResourceAccessLevel>(() => {
const r = getResource()
if (!r) return 0
return getResourceAccessLevel(r)
})
const isOwner = computed(() => {
const r = getResource()
if (!r) return false
return isResourceOwner(r)
})
const canBasic = computed(() => accessLevel.value >= 1)
const canConnection = computed(() => accessLevel.value >= 2)
const canSensitive = computed(() => accessLevel.value >= 3)
const canManage = computed(() => accessLevel.value >= 3)
/** 权限级别对应的文字说明 */
const accessLevelText = computed(() => {
switch (accessLevel.value) {
case 3: return '完全权限'
case 2: return '连接权限'
case 1: return '查看权限'
default: return '无权限'
}
})
/** 权限不足时的提示文字 */
const noPermissionTip = computed(() =>
isOwner.value ? '' : '如需查看完整信息,请联系资源创建者',
)
return {
accessLevel,
isOwner,
canBasic,
canConnection,
canSensitive,
canManage,
accessLevelText,
noPermissionTip,
}
}
/**
* 批量处理资源列表,为每个资源附加 isOwner 字段
* 调用时机:后端未返回 accessLevel 时的前端降级处理
*/
export function enrichResourcesWithPermission<T extends AppResource>(resources: T[]): T[] {
if (!import.meta.client) return resources
const currentUserId = localStorage.getItem('UserId')
if (!currentUserId) return resources
return resources.map(r => ({
...r,
isOwner: Number(currentUserId) === Number(r.ownerUserId) || Number(currentUserId) === Number(r.userId),
accessLevel: r.accessLevel ?? (
(Number(currentUserId) === Number(r.ownerUserId) || Number(currentUserId) === Number(r.userId))
? 3
: 1
),
}))
}