- 在 handleApiError 之后追加 7 行具名 re-export 块 - 暴露 4 个公共符号:getCredentialSlot / updateCredentialSlot / CredentialSlot / CredentialSlotUpdatePayload - 路径相对 './credential-slot',与现有 export * from './card' 等风格在同文件混用合法 - 现有 export */usersApi/rolesApi/handleApiError 完全不变
205 lines
5.3 KiB
TypeScript
205 lines
5.3 KiB
TypeScript
// 导出所有API服务
|
||
import * as client from "./client"
|
||
export * from "./card"
|
||
export * from "./upload"
|
||
export * from "./food"
|
||
|
||
// 用户API
|
||
export const usersApi = {
|
||
// 获取用户列表
|
||
getUsers: async (params: any) => {
|
||
await client.simulateDelay()
|
||
|
||
let filteredUsers = [...client.mockUsers]
|
||
|
||
// 搜索过滤
|
||
if (params?.search) {
|
||
const search = params.search.toLowerCase()
|
||
filteredUsers = filteredUsers.filter(
|
||
(user) =>
|
||
user.name.toLowerCase().includes(search) ||
|
||
user.email.toLowerCase().includes(search) ||
|
||
user.role.toLowerCase().includes(search),
|
||
)
|
||
}
|
||
|
||
// 排序
|
||
if (params?.sortBy) {
|
||
filteredUsers.sort((a, b) => {
|
||
const aValue = (a as any)[params.sortBy]
|
||
const bValue = (b as any)[params.sortBy]
|
||
|
||
if (typeof aValue === "string" && typeof bValue === "string") {
|
||
return params.sortOrder === "desc" ? bValue.localeCompare(aValue) : aValue.localeCompare(bValue)
|
||
}
|
||
|
||
return params.sortOrder === "desc" ? bValue - aValue : aValue - bValue
|
||
})
|
||
}
|
||
|
||
// 分页
|
||
const page = params?.page || 1
|
||
const pageSize = params?.pageSize || 10
|
||
const startIndex = (page - 1) * pageSize
|
||
const paginatedUsers = filteredUsers.slice(startIndex, startIndex + pageSize)
|
||
|
||
return {
|
||
items: paginatedUsers,
|
||
total: filteredUsers.length,
|
||
page,
|
||
pageSize,
|
||
totalPages: Math.ceil(filteredUsers.length / pageSize),
|
||
}
|
||
},
|
||
|
||
// 获取单个用户
|
||
getUser: async (id: string) => {
|
||
await client.simulateDelay()
|
||
const user = client.mockUsers.find((user) => user.id === id)
|
||
|
||
if (!user) {
|
||
throw new Error("用户不存在")
|
||
}
|
||
|
||
return user
|
||
},
|
||
|
||
// 创建用户
|
||
createUser: async (userData: any) => {
|
||
await client.simulateDelay()
|
||
|
||
// 检查邮箱是否已存在
|
||
if (client.mockUsers.some((user) => user.email === userData.email)) {
|
||
throw new Error("该邮箱已被注册")
|
||
}
|
||
|
||
const newUser = {
|
||
id: String(client.mockUsers.length + 1),
|
||
name: userData.name || "",
|
||
email: userData.email || "",
|
||
role: userData.role || "查看者",
|
||
status: userData.status || "未激活",
|
||
registeredAt: new Date().toISOString().split("T")[0],
|
||
lastLogin: "",
|
||
phone: userData.phone,
|
||
address: userData.address,
|
||
permissions: [],
|
||
loginHistory: [],
|
||
}
|
||
|
||
client.mockUsers.push(newUser)
|
||
|
||
return newUser
|
||
},
|
||
|
||
// 更新用户
|
||
updateUser: async (id: string, userData: any) => {
|
||
await client.simulateDelay()
|
||
|
||
const userIndex = client.mockUsers.findIndex((user) => user.id === id)
|
||
|
||
if (userIndex === -1) {
|
||
throw new Error("用户不存在")
|
||
}
|
||
|
||
// 检查邮箱是否已被其他用户使用
|
||
if (userData.email && userData.email !== client.mockUsers[userIndex].email) {
|
||
const emailExists = client.mockUsers.some((user) => user.email === userData.email && user.id !== id)
|
||
if (emailExists) {
|
||
throw new Error("该邮箱已被其他用户使用")
|
||
}
|
||
}
|
||
|
||
const updatedUser = {
|
||
...client.mockUsers[userIndex],
|
||
...userData,
|
||
}
|
||
|
||
client.mockUsers[userIndex] = updatedUser
|
||
|
||
return updatedUser
|
||
},
|
||
|
||
// 删除用户
|
||
deleteUser: async (id: string) => {
|
||
await client.simulateDelay()
|
||
|
||
const userIndex = client.mockUsers.findIndex((user) => user.id === id)
|
||
|
||
if (userIndex === -1) {
|
||
throw new Error("用户不存在")
|
||
}
|
||
|
||
// 超级管理员不能删除
|
||
if (client.mockUsers[userIndex].role === "超级管理员") {
|
||
throw new Error("不能删除超级管理员")
|
||
}
|
||
|
||
client.mockUsers.splice(userIndex, 1)
|
||
|
||
return true
|
||
},
|
||
}
|
||
|
||
// 角色API
|
||
export const rolesApi = {
|
||
// 获取角色列表
|
||
getRoles: async (params: any) => {
|
||
await client.simulateDelay()
|
||
|
||
let filteredRoles = [...client.mockRoles]
|
||
|
||
// 搜索过滤
|
||
if (params?.search) {
|
||
const search = params.search.toLowerCase()
|
||
filteredRoles = filteredRoles.filter(
|
||
(role) => role.name.toLowerCase().includes(search) || role.description.toLowerCase().includes(search),
|
||
)
|
||
}
|
||
|
||
// 排序
|
||
if (params?.sortBy) {
|
||
filteredRoles.sort((a, b) => {
|
||
const aValue = (a as any)[params.sortBy]
|
||
const bValue = (b as any)[params.sortBy]
|
||
|
||
if (typeof aValue === "string" && typeof bValue === "string") {
|
||
return params.sortOrder === "desc" ? bValue.localeCompare(aValue) : aValue.localeCompare(bValue)
|
||
}
|
||
|
||
return params.sortOrder === "desc" ? bValue - aValue : aValue - bValue
|
||
})
|
||
}
|
||
|
||
// 分页
|
||
const page = params?.page || 1
|
||
const pageSize = params?.pageSize || 10
|
||
const startIndex = (page - 1) * pageSize
|
||
const paginatedRoles = filteredRoles.slice(startIndex, startIndex + pageSize)
|
||
|
||
return {
|
||
items: paginatedRoles,
|
||
total: filteredRoles.length,
|
||
page,
|
||
pageSize,
|
||
totalPages: Math.ceil(filteredRoles.length / pageSize),
|
||
}
|
||
},
|
||
}
|
||
|
||
// 导出错误处理函数
|
||
export const handleApiError = (error: any) => {
|
||
if (error instanceof Error) {
|
||
return error.message
|
||
}
|
||
return "发生未知错误,请重试"
|
||
}
|
||
|
||
// 凭据槽位(Milestone v1.0 通用凭据槽位前端集成 — Phase 1 / CRED-FE-01)
|
||
export {
|
||
getCredentialSlot,
|
||
updateCredentialSlot,
|
||
type CredentialSlot,
|
||
type CredentialSlotUpdatePayload,
|
||
} from './credential-slot'
|