feat(组织架构): 完成员工与组织节点管理

This commit is contained in:
xy
2026-09-24 16:22:21 +08:00
parent 9a6ac93e21
commit 9145b57e6f
14 changed files with 1908 additions and 501 deletions
+27 -17
View File
@@ -20,26 +20,35 @@ function getRecords(data: BackendCollection<OrganizationResponseDto>) {
return Array.isArray(data) ? data : (data.records ?? data.items ?? data.content ?? [])
}
export function getCampuses(): Promise<CampusRecord[]> {
export async function getCampuses(): Promise<CampusRecord[]> {
if (useMockData) {
return Promise.resolve([])
return []
}
return request
.get<ApiResponse<BackendCollection<OrganizationResponseDto>>>('/v1/campuses', {
params: { page: 1, size: 200 },
})
.then(unwrapApiResponse)
.then((data) =>
getRecords(data).map((item) => ({
id: item.id,
code: item.code ?? item.id,
name: item.name ?? item.campusName ?? item.id,
address: item.address ?? undefined,
status: item.status ?? 'ENABLED',
sortNo: item.sortNo ?? 0,
})),
)
const firstPage = await getCampusPage(1, 200)
const pageCount = Math.ceil(firstPage.total / firstPage.pageSize)
if (pageCount <= 1) return firstPage.records
const remainingPages = await Promise.all(
Array.from({ length: pageCount - 1 }, (_, index) =>
getCampusPage(index + 2, firstPage.pageSize),
),
)
return [firstPage, ...remainingPages].flatMap((page) => page.records)
}
async function getCampusPage(page: number, pageSize: number) {
const response = await request.get<ApiResponse<BackendCollection<OrganizationResponseDto>>>(
'/v1/campuses',
{ params: { page, size: pageSize } },
)
const data = unwrapApiResponse(response)
const records = getRecords(data).map(mapCampus)
return {
records,
total: Array.isArray(data) ? records.length : (data.total ?? records.length),
pageSize: Array.isArray(data) ? pageSize : (data.size ?? pageSize),
}
}
export function getDepartments(campusId?: string): Promise<DepartmentRecord[]> {
@@ -102,6 +111,7 @@ function mapCampus(data: OrganizationResponseDto): CampusRecord {
id: data.id,
code: data.code ?? data.id,
name: data.name ?? data.campusName ?? data.id,
institutionName: data.institutionName?.trim() || '新华院区',
address: data.address ?? undefined,
status: data.status ?? 'ENABLED',
sortNo: data.sortNo ?? 0,
+18
View File
@@ -234,6 +234,7 @@ export interface CampusRecord {
id: string
code: string
name: string
institutionName: string
address?: string
status: OrganizationStatus
sortNo: number
@@ -254,6 +255,7 @@ export type OrganizationStatus = 'ENABLED' | 'DISABLED' | string
export interface CreateCampusRequest {
code: string
name: string
institutionName?: string
address?: string
status?: OrganizationStatus
sortNo?: number
@@ -276,6 +278,7 @@ export interface OrganizationResponseDto {
id: string
code?: string | null
name?: string | null
institutionName?: string | null
address?: string | null
status?: OrganizationStatus | null
sortNo?: number | null
@@ -422,12 +425,14 @@ export type UserStatus = 'enabled' | 'disabled' | 'locked'
export interface UserQuery extends PageQuery {
keyword?: string
department?: string
departmentId?: string
status?: UserStatus | 'all'
campusId?: string
}
export interface UserRecord {
id: string
employeeId?: number | null
name: string
account: string
department: string
@@ -435,6 +440,8 @@ export interface UserRecord {
status: UserStatus
lastLoginAt: string
employeeNo?: string | null
position?: string | null
professionalTitle?: string | null
phone?: string | null
email?: string | null
campusId?: string | null
@@ -443,6 +450,7 @@ export interface UserRecord {
departmentName?: string
roleNames?: string[]
roleIds?: string[]
roleDataScopes?: RoleDataScopeType[]
version?: number
passwordChangeRequired?: boolean
}
@@ -451,9 +459,12 @@ export type UserListResponse = PageResult<UserRecord>
export interface UserResponseDto {
id: string
employeeId?: number | null
username: string
displayName: string
employeeNo?: string | null
position?: string | null
professionalTitle?: string | null
phone?: string | null
email?: string | null
campusId?: string | null
@@ -474,6 +485,7 @@ export interface UserRoleSummaryDto {
code: string
name: string
status?: RoleStatus | null
dataScope?: RoleDataScopeType | null
}
export interface CreateUserRequest {
@@ -481,11 +493,14 @@ export interface CreateUserRequest {
password: string
displayName: string
employeeNo?: string
position?: string
professionalTitle?: string
phone?: string
email?: string
campusId: string
departmentId?: string | null
status?: BackendUserStatus
passwordChangeRequired?: boolean
}
export type BackendUserStatus = 'ENABLED' | 'DISABLED' | 'LOCKED'
@@ -493,6 +508,8 @@ export type BackendUserStatus = 'ENABLED' | 'DISABLED' | 'LOCKED'
export interface UpdateUserRequest {
displayName: string
employeeNo?: string
position?: string
professionalTitle?: string
phone?: string
email?: string
campusId: string
@@ -622,6 +639,7 @@ export interface UpdateDepartmentPermissionPolicyRequest {
export interface PasswordResetRequest {
newPassword: string
forceChangeOnNextLogin?: boolean
reason: string
}
export type UserImportRowStatus = 'VALID' | 'INVALID'
+12 -1
View File
@@ -90,6 +90,7 @@ function mapUser(dto: UserResponseDto): UserRecord {
return {
id: dto.id,
employeeId: dto.employeeId,
name: dto.displayName,
account: dto.username,
department: dto.departmentName ?? (dto.departmentId ? '未知科室' : '未指定科室'),
@@ -97,6 +98,8 @@ function mapUser(dto: UserResponseDto): UserRecord {
status: normalizeStatus(dto.status),
lastLoginAt: formatDateTime(dto.lastLoginAt),
employeeNo: dto.employeeNo,
position: dto.position,
professionalTitle: dto.professionalTitle,
phone: dto.phone,
email: dto.email,
campusId: dto.campusId,
@@ -105,6 +108,7 @@ function mapUser(dto: UserResponseDto): UserRecord {
departmentName: dto.departmentName ?? undefined,
roleNames,
roleIds: roles.map((role) => role.id),
roleDataScopes: roles.map((role) => role.dataScope ?? 'SELF'),
version: dto.version ?? undefined,
passwordChangeRequired: dto.passwordChangeRequired,
}
@@ -139,6 +143,10 @@ function toBackendQuery(query: UserQuery) {
params.campusId = query.campusId
}
if (query.departmentId) {
params.departmentId = query.departmentId
}
return params
}
@@ -163,10 +171,13 @@ export function getUsers(query: UserQuery): Promise<UserListResponse> {
const matchesKeyword =
!keyword || [record.name, record.account].join(' ').toLowerCase().includes(keyword)
const matchesDepartment = !query.department || record.department === query.department
const matchesDepartmentId = !query.departmentId || record.departmentId === query.departmentId
const matchesStatus = !query.status || query.status === 'all' || record.status === query.status
const matchesCampus = !query.campusId || record.campusId === query.campusId
return matchesKeyword && matchesDepartment && matchesStatus && matchesCampus
return (
matchesKeyword && matchesDepartment && matchesDepartmentId && matchesStatus && matchesCampus
)
})
const page = Math.max(query.page, 1)
const pageSize = Math.max(query.pageSize, 1)