refactor: 重构代码结构和类型定义,优化类型安全性和代码可维护性
- 添加类型定义文件和类型引用 - 删除废弃的页面模块和导出文件 - 新增聚合管理模块和插件系统 - 修复类型错误和潜在运行时问题 - 更新API基础URL和配置 - 优化组件类型定义和事件处理 - 重构数据源接口和实现 - 完善文档和开发进度记录
This commit is contained in:
230
dashboard/src/contexts/UserContext.tsx
Normal file
230
dashboard/src/contexts/UserContext.tsx
Normal file
@@ -0,0 +1,230 @@
|
||||
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
|
||||
|
||||
export type UserRole = 'ADMIN' | 'MANAGER' | 'OPERATOR' | 'FINANCE' | 'SOURCING' | 'LOGISTICS' | 'ANALYST';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
role: UserRole;
|
||||
avatar?: string;
|
||||
permissions: string[];
|
||||
subscription?: {
|
||||
plan: 'free' | 'basic' | 'pro' | 'enterprise';
|
||||
expiresAt?: string;
|
||||
features: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export const ROLE_CONFIG: Record<UserRole, { label: string; color: string; description: string }> = {
|
||||
ADMIN: { label: '管理员', color: 'red', description: '全权管理,可访问所有功能' },
|
||||
MANAGER: { label: '运营主管', color: 'orange', description: '管理运营团队,审批决策' },
|
||||
OPERATOR: { label: '运营专员', color: 'blue', description: '日常运营操作,执行任务' },
|
||||
FINANCE: { label: '财务主管', color: 'green', description: '财务管理,对账结算' },
|
||||
SOURCING: { label: '采购专家', color: 'purple', description: '供应商管理,采购决策' },
|
||||
LOGISTICS: { label: '物流专家', color: 'cyan', description: '物流管理,仓储调度' },
|
||||
ANALYST: { label: '数据分析师', color: 'geekblue', description: '数据分析,报表生成' },
|
||||
};
|
||||
|
||||
export const MOCK_USERS: User[] = [
|
||||
{
|
||||
id: 'user_admin',
|
||||
name: '张管理员',
|
||||
email: 'admin@crawlful.com',
|
||||
role: 'ADMIN',
|
||||
permissions: ['*'],
|
||||
subscription: {
|
||||
plan: 'enterprise',
|
||||
expiresAt: '2027-03-21',
|
||||
features: ['ai_operations', 'auto_pricing', 'multi_shop', 'b2b_trade', 'independent_site', 'advanced_analytics', 'api_access'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_manager',
|
||||
name: '李主管',
|
||||
email: 'manager@crawlful.com',
|
||||
role: 'MANAGER',
|
||||
permissions: ['product:*', 'order:*', 'inventory:read', 'inventory:write', 'finance:read', 'report:*'],
|
||||
subscription: {
|
||||
plan: 'pro',
|
||||
expiresAt: '2026-06-21',
|
||||
features: ['ai_operations', 'auto_pricing', 'multi_shop', 'advanced_analytics'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_operator',
|
||||
name: '王专员',
|
||||
email: 'operator@crawlful.com',
|
||||
role: 'OPERATOR',
|
||||
permissions: ['product:read', 'product:write', 'order:read', 'order:write', 'inventory:read'],
|
||||
subscription: {
|
||||
plan: 'basic',
|
||||
expiresAt: '2026-04-21',
|
||||
features: ['multi_shop'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_finance',
|
||||
name: '赵财务',
|
||||
email: 'finance@crawlful.com',
|
||||
role: 'FINANCE',
|
||||
permissions: ['finance:*', 'order:read', 'report:*'],
|
||||
subscription: {
|
||||
plan: 'pro',
|
||||
expiresAt: '2026-09-21',
|
||||
features: ['ai_operations', 'advanced_analytics'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_sourcing',
|
||||
name: '孙采购',
|
||||
email: 'sourcing@crawlful.com',
|
||||
role: 'SOURCING',
|
||||
permissions: ['supplier:*', 'product:read', 'inventory:*', 'b2b:read'],
|
||||
subscription: {
|
||||
plan: 'basic',
|
||||
expiresAt: '2026-05-21',
|
||||
features: ['b2b_trade'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_logistics',
|
||||
name: '周物流',
|
||||
email: 'logistics@crawlful.com',
|
||||
role: 'LOGISTICS',
|
||||
permissions: ['logistics:*', 'inventory:*', 'order:read'],
|
||||
subscription: {
|
||||
plan: 'basic',
|
||||
expiresAt: '2026-05-21',
|
||||
features: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_analyst',
|
||||
name: '吴分析',
|
||||
email: 'analyst@crawlful.com',
|
||||
role: 'ANALYST',
|
||||
permissions: ['report:*', 'analytics:*', 'product:read', 'order:read', 'finance:read'],
|
||||
subscription: {
|
||||
plan: 'pro',
|
||||
expiresAt: '2026-08-21',
|
||||
features: ['advanced_analytics', 'api_access'],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'user_free',
|
||||
name: '免费用户',
|
||||
email: 'free@crawlful.com',
|
||||
role: 'OPERATOR',
|
||||
permissions: ['product:read', 'order:read'],
|
||||
subscription: {
|
||||
plan: 'free',
|
||||
features: [],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
interface UserContextType {
|
||||
currentUser: User;
|
||||
setCurrentUser: (user: User) => void;
|
||||
hasPermission: (permission: string) => boolean;
|
||||
hasFeature: (feature: string) => boolean;
|
||||
isPaidUser: () => boolean;
|
||||
getPlanLabel: () => string;
|
||||
}
|
||||
|
||||
const UserContext = createContext<UserContextType | undefined>(undefined);
|
||||
|
||||
export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
|
||||
const [currentUser, setCurrentUser] = useState<User>(() => {
|
||||
return MOCK_USERS[0];
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const saved = localStorage.getItem('current_user_id');
|
||||
if (saved) {
|
||||
const user = MOCK_USERS.find(u => u.id === saved);
|
||||
if (user) {
|
||||
setCurrentUser(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('current_user_id', currentUser.id);
|
||||
}
|
||||
}, [currentUser.id]);
|
||||
|
||||
const hasPermission = (permission: string): boolean => {
|
||||
if (currentUser.permissions.includes('*')) return true;
|
||||
if (currentUser.permissions.includes(permission)) return true;
|
||||
|
||||
const [resource] = permission.split(':');
|
||||
if (currentUser.permissions.includes(`${resource}:*`)) return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
const hasFeature = (feature: string): boolean => {
|
||||
return currentUser.subscription?.features.includes(feature) ?? false;
|
||||
};
|
||||
|
||||
const isPaidUser = (): boolean => {
|
||||
return currentUser.subscription?.plan !== 'free';
|
||||
};
|
||||
|
||||
const getPlanLabel = (): string => {
|
||||
const planLabels: Record<string, string> = {
|
||||
free: '免费版',
|
||||
basic: '基础版',
|
||||
pro: '专业版',
|
||||
enterprise: '企业版',
|
||||
};
|
||||
return planLabels[currentUser.subscription?.plan || 'free'];
|
||||
};
|
||||
|
||||
return (
|
||||
<UserContext.Provider value={{ currentUser, setCurrentUser, hasPermission, hasFeature, isPaidUser, getPlanLabel }}>
|
||||
{children}
|
||||
</UserContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useUser = (): UserContextType => {
|
||||
const context = useContext(UserContext);
|
||||
if (!context) {
|
||||
throw new Error('useUser must be used within a UserProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export const PERMISSIONS = {
|
||||
PRODUCT_READ: 'product:read',
|
||||
PRODUCT_WRITE: 'product:write',
|
||||
PRODUCT_DELETE: 'product:delete',
|
||||
ORDER_READ: 'order:read',
|
||||
ORDER_WRITE: 'order:write',
|
||||
ORDER_APPROVE: 'order:approve',
|
||||
INVENTORY_READ: 'inventory:read',
|
||||
INVENTORY_WRITE: 'inventory:write',
|
||||
FINANCE_READ: 'finance:read',
|
||||
FINANCE_WRITE: 'finance:write',
|
||||
FINANCE_APPROVE: 'finance:approve',
|
||||
USER_MANAGE: 'user:manage',
|
||||
SYSTEM_CONFIG: 'system:config',
|
||||
AI_OPERATIONS: 'ai:operations',
|
||||
B2B_ACCESS: 'b2b:access',
|
||||
};
|
||||
|
||||
export const FEATURES = {
|
||||
AI_OPERATIONS: 'ai_operations',
|
||||
AUTO_PRICING: 'auto_pricing',
|
||||
MULTI_SHOP: 'multi_shop',
|
||||
B2B_TRADE: 'b2b_trade',
|
||||
INDEPENDENT_SITE: 'independent_site',
|
||||
ADVANCED_ANALYTICS: 'advanced_analytics',
|
||||
API_ACCESS: 'api_access',
|
||||
};
|
||||
Reference in New Issue
Block a user