fix: align client integration contracts
This commit is contained in:
@@ -2,8 +2,10 @@ import { computed, ref } from 'vue'
|
||||
import { defineStore } from 'pinia'
|
||||
import {
|
||||
changeMerchantMemberStatus,
|
||||
changeMerchantRoleStatus,
|
||||
createMerchantMember,
|
||||
createMerchantRole,
|
||||
deleteMerchantRole,
|
||||
getMerchantMembers,
|
||||
getMerchantPermissionResources,
|
||||
getMerchantRoles,
|
||||
@@ -12,6 +14,7 @@ import {
|
||||
resetMerchantMemberPassword,
|
||||
replaceMerchantRolePermissions,
|
||||
updateMerchantMember,
|
||||
updateMerchantRole,
|
||||
updateTenantProfile,
|
||||
type MerchantRole,
|
||||
type MerchantMember,
|
||||
@@ -67,6 +70,7 @@ export interface TenantRole {
|
||||
description: string
|
||||
status: TenantRecordStatus
|
||||
builtin: boolean
|
||||
permissionIds: string[]
|
||||
permissionCodes: string[]
|
||||
}
|
||||
|
||||
@@ -136,7 +140,7 @@ export const TENANT_PERMISSION_GROUPS: readonly TenantPermissionGroup[] = [
|
||||
|
||||
const allPermissionCodes = TENANT_PERMISSION_GROUPS.flatMap((group) => group.items.map((item) => item.code))
|
||||
|
||||
const frontendToBackendPermissionCodes: Readonly<Record<string, readonly string[]>> = {
|
||||
export const FRONTEND_TO_MERCHANT_PERMISSION_CODES: Readonly<Record<string, readonly string[]>> = {
|
||||
'order:first-leg:list': ['merchant:order:list', 'merchant:order:view'],
|
||||
'order:first-leg:create': ['merchant:order:create'],
|
||||
'order:first-leg:edit': ['merchant:order:edit'],
|
||||
@@ -154,10 +158,12 @@ const frontendToBackendPermissionCodes: Readonly<Record<string, readonly string[
|
||||
'company:permission:assign': ['merchant:role:grant'],
|
||||
}
|
||||
|
||||
const mappedMerchantPermissionCodes = new Set(Object.values(FRONTEND_TO_MERCHANT_PERMISSION_CODES).flat())
|
||||
|
||||
const initialRoles: TenantRole[] = [
|
||||
{ id: 'ROLE-ADMIN', name: '企业管理员', code: 'TENANT_ADMIN', description: '企业内置管理员,拥有全部客户端权限', status: 'ACTIVE', builtin: true, permissionCodes: [...allPermissionCodes] },
|
||||
{ id: 'ROLE-ORDER', name: '订单专员', code: 'ORDER_OPERATOR', description: '负责头程订单创建、提交和跟进', status: 'ACTIVE', builtin: false, permissionCodes: ['account:profile:view', 'dashboard:view', 'order:first-leg:list', 'order:first-leg:create', 'order:first-leg:edit', 'order:first-leg:submit', 'order:first-leg:cancel', 'company:profile:view'] },
|
||||
{ id: 'ROLE-VIEWER', name: '业务查看员', code: 'BUSINESS_VIEWER', description: '只读查看企业资料和业务订单', status: 'ACTIVE', builtin: false, permissionCodes: ['account:profile:view', 'dashboard:view', 'order:first-leg:list', 'company:profile:view'] },
|
||||
{ id: 'ROLE-ADMIN', name: '企业管理员', code: 'TENANT_ADMIN', description: '企业内置管理员,拥有全部客户端权限', status: 'ACTIVE', builtin: true, permissionIds: [], permissionCodes: [...allPermissionCodes] },
|
||||
{ id: 'ROLE-ORDER', name: '订单专员', code: 'ORDER_OPERATOR', description: '负责头程订单创建、提交和跟进', status: 'ACTIVE', builtin: false, permissionIds: [], permissionCodes: ['account:profile:view', 'dashboard:view', 'order:first-leg:list', 'order:first-leg:create', 'order:first-leg:edit', 'order:first-leg:submit', 'order:first-leg:cancel', 'company:profile:view'] },
|
||||
{ id: 'ROLE-VIEWER', name: '业务查看员', code: 'BUSINESS_VIEWER', description: '只读查看企业资料和业务订单', status: 'ACTIVE', builtin: false, permissionIds: [], permissionCodes: ['account:profile:view', 'dashboard:view', 'order:first-leg:list', 'company:profile:view'] },
|
||||
]
|
||||
|
||||
const initialMembers: TenantMember[] = [
|
||||
@@ -228,7 +234,7 @@ export const useTenantAdministrationStore = defineStore('tenant-administration',
|
||||
const grantedBackendCodes = new Set(permissionResources.value
|
||||
.filter((resource) => grantedIds.includes(String(resource.id)))
|
||||
.map((resource) => resource.permissionCode))
|
||||
const permissionCodes = Object.entries(frontendToBackendPermissionCodes)
|
||||
const permissionCodes = Object.entries(FRONTEND_TO_MERCHANT_PERMISSION_CODES)
|
||||
.filter(([, backendCodes]) => backendCodes.some((code) => grantedBackendCodes.has(code)))
|
||||
.map(([frontendCode]) => frontendCode)
|
||||
return {
|
||||
@@ -238,6 +244,7 @@ export const useTenantAdministrationStore = defineStore('tenant-administration',
|
||||
description: role.description ?? '暂无角色说明',
|
||||
status: role.status === 'ACTIVE' ? 'ACTIVE' : 'INACTIVE',
|
||||
builtin: role.roleType === 'SYSTEM',
|
||||
permissionIds: grantedIds,
|
||||
permissionCodes: role.roleType === 'SYSTEM' && role.roleCode === 'MERCHANT_OWNER' ? [...allPermissionCodes] : permissionCodes,
|
||||
}
|
||||
}
|
||||
@@ -352,24 +359,28 @@ export const useTenantAdministrationStore = defineStore('tenant-administration',
|
||||
roles.value.push(mapMerchantRole(created))
|
||||
}
|
||||
|
||||
function updateRole(id: string, payload: Pick<TenantRole, 'name' | 'description'>) {
|
||||
async function updateRole(id: string, payload: Pick<TenantRole, 'name' | 'description'>) {
|
||||
const role = roles.value.find((item) => item.id === id)
|
||||
if (!role) throw new Error('角色不存在')
|
||||
Object.assign(role, payload)
|
||||
if (role.builtin) throw new Error('内置角色不能编辑')
|
||||
const updated = await updateMerchantRole(id, { roleName: payload.name.trim(), description: payload.description.trim() })
|
||||
Object.assign(role, mapMerchantRole(updated))
|
||||
}
|
||||
|
||||
function toggleRoleStatus(id: string) {
|
||||
async function toggleRoleStatus(id: string) {
|
||||
const role = roles.value.find((item) => item.id === id)
|
||||
if (!role) throw new Error('角色不存在')
|
||||
if (role.builtin) throw new Error('内置角色不能停用')
|
||||
role.status = role.status === 'ACTIVE' ? 'INACTIVE' : 'ACTIVE'
|
||||
const updated = await changeMerchantRoleStatus(id, role.status === 'ACTIVE' ? 'DISABLED' : 'ACTIVE')
|
||||
Object.assign(role, mapMerchantRole(updated))
|
||||
}
|
||||
|
||||
function deleteRole(id: string) {
|
||||
async function deleteRole(id: string) {
|
||||
const role = roles.value.find((item) => item.id === id)
|
||||
if (!role) throw new Error('角色不存在')
|
||||
if (role.builtin) throw new Error('内置角色不能删除')
|
||||
if (members.value.some((member) => member.roleIds.includes(id))) throw new Error('该角色仍有成员使用,不能删除')
|
||||
await deleteMerchantRole(id)
|
||||
roles.value = roles.value.filter((item) => item.id !== id)
|
||||
}
|
||||
|
||||
@@ -377,11 +388,18 @@ export const useTenantAdministrationStore = defineStore('tenant-administration',
|
||||
const role = roles.value.find((item) => item.id === id)
|
||||
if (!role) throw new Error('角色不存在')
|
||||
if (role.builtin) throw new Error('内置管理员权限不能修改')
|
||||
const backendCodes = new Set(permissionCodes.flatMap((code) => frontendToBackendPermissionCodes[code] ?? []))
|
||||
const permissionIds = permissionResources.value
|
||||
const backendCodes = new Set(permissionCodes.flatMap((code) => FRONTEND_TO_MERCHANT_PERMISSION_CODES[code] ?? []))
|
||||
const selectedPermissionIds = permissionResources.value
|
||||
.filter((resource) => backendCodes.has(resource.permissionCode))
|
||||
.map((resource) => resource.id)
|
||||
await replaceMerchantRolePermissions(id, permissionIds)
|
||||
const mappedResourceIds = new Set(permissionResources.value
|
||||
.filter((resource) => mappedMerchantPermissionCodes.has(resource.permissionCode))
|
||||
.map((resource) => String(resource.id)))
|
||||
// The endpoint replaces every ID, including MENU nodes this screen does not render.
|
||||
const preservedPermissionIds = role.permissionIds.filter((permissionId) => !mappedResourceIds.has(permissionId))
|
||||
const nextPermissionIds = [...new Set([...preservedPermissionIds, ...selectedPermissionIds])]
|
||||
await replaceMerchantRolePermissions(id, nextPermissionIds)
|
||||
role.permissionIds = nextPermissionIds.map(String)
|
||||
role.permissionCodes = [...new Set(permissionCodes)]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user