refactor: 重构代码结构和类型定义,优化类型安全性和代码可维护性
- 添加类型定义文件和类型引用 - 删除废弃的页面模块和导出文件 - 新增聚合管理模块和插件系统 - 修复类型错误和潜在运行时问题 - 更新API基础URL和配置 - 优化组件类型定义和事件处理 - 重构数据源接口和实现 - 完善文档和开发进度记录
This commit is contained in:
@@ -296,6 +296,7 @@ class MockAfterSalesDataSource implements IAfterSalesDataSource {
|
||||
return [
|
||||
{
|
||||
id: 'TICKET-001',
|
||||
ticketId: 'TKT-2026-001',
|
||||
orderId: 'order-001',
|
||||
customerId: 'C001',
|
||||
customerName: 'John Doe',
|
||||
|
||||
@@ -2,7 +2,7 @@ import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from
|
||||
|
||||
const API_BASE_URL = process.env.NODE_ENV === 'production'
|
||||
? '/api'
|
||||
: 'http://localhost:3000/api';
|
||||
: 'http://localhost:3001/api';
|
||||
|
||||
const apiClient: AxiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
|
||||
@@ -52,6 +52,18 @@ export interface Customer {
|
||||
email?: string;
|
||||
}
|
||||
|
||||
export interface Product {
|
||||
id: string;
|
||||
sku: string;
|
||||
name: string;
|
||||
price: number;
|
||||
stock: number;
|
||||
category?: string;
|
||||
moq?: number;
|
||||
costPrice?: number;
|
||||
suggestedPrice?: number;
|
||||
}
|
||||
|
||||
export interface BatchOrderQueryParams {
|
||||
customerId?: string;
|
||||
status?: string;
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
* @created 2026-03-19
|
||||
*/
|
||||
|
||||
import { Certificate, CertificateQueryParams } from '@/types/certificate';
|
||||
import { Certificate, CertificateQueryParams, CertificateStatus, CertificateType } from '@/types/certificate';
|
||||
import { IDataSource } from '@/types/datasource';
|
||||
import { BaseDataSource, BaseMockDataSource, DataSourceFactory } from './dataSourceFactory';
|
||||
|
||||
export type { Certificate } from '@/types/certificate';
|
||||
export { CertificateStatus, CertificateType };
|
||||
|
||||
// ============================================
|
||||
// 真实API实现
|
||||
// ============================================
|
||||
@@ -72,8 +75,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '1',
|
||||
name: 'CE认证证书',
|
||||
type: 'PRODUCT_CERT',
|
||||
status: 'APPROVED',
|
||||
type: CertificateType.PRODUCT_CERT,
|
||||
status: CertificateStatus.APPROVED,
|
||||
fileUrl: '/files/ce-cert.pdf',
|
||||
fileName: 'CE-Certificate-2026.pdf',
|
||||
uploadDate: '2026-03-15',
|
||||
@@ -87,8 +90,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '2',
|
||||
name: '营业执照',
|
||||
type: 'BUSINESS_LICENSE',
|
||||
status: 'APPROVED',
|
||||
type: CertificateType.BUSINESS_LICENSE,
|
||||
status: CertificateStatus.APPROVED,
|
||||
fileUrl: '/files/business-license.pdf',
|
||||
fileName: 'Business-License-2026.pdf',
|
||||
uploadDate: '2026-01-10',
|
||||
@@ -100,8 +103,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '3',
|
||||
name: 'FCC认证',
|
||||
type: 'SAFETY_CERT',
|
||||
status: 'PENDING',
|
||||
type: CertificateType.SAFETY_CERT,
|
||||
status: CertificateStatus.PENDING,
|
||||
fileUrl: '/files/fcc-cert.pdf',
|
||||
fileName: 'FCC-Certificate.pdf',
|
||||
uploadDate: '2026-03-18',
|
||||
@@ -113,8 +116,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '4',
|
||||
name: 'ISO9001',
|
||||
type: 'QUALITY_CERT',
|
||||
status: 'EXPIRED',
|
||||
type: CertificateType.QUALITY_CERT,
|
||||
status: CertificateStatus.EXPIRED,
|
||||
fileUrl: '/files/iso9001.pdf',
|
||||
fileName: 'ISO9001-2025.pdf',
|
||||
uploadDate: '2025-01-01',
|
||||
@@ -126,8 +129,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '5',
|
||||
name: 'RoHS认证',
|
||||
type: 'PRODUCT_CERT',
|
||||
status: 'APPROVED',
|
||||
type: CertificateType.PRODUCT_CERT,
|
||||
status: CertificateStatus.APPROVED,
|
||||
fileUrl: '/files/rohs-cert.pdf',
|
||||
fileName: 'RoHS-Certificate.pdf',
|
||||
uploadDate: '2026-02-20',
|
||||
@@ -141,8 +144,8 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
{
|
||||
id: '6',
|
||||
name: 'UL认证',
|
||||
type: 'SAFETY_CERT',
|
||||
status: 'PENDING',
|
||||
type: CertificateType.SAFETY_CERT,
|
||||
status: CertificateStatus.PENDING,
|
||||
fileUrl: '/files/ul-cert.pdf',
|
||||
fileName: 'UL-Certificate.pdf',
|
||||
uploadDate: '2026-03-19',
|
||||
@@ -168,7 +171,7 @@ class MockCertificateDataSource extends BaseMockDataSource<Certificate, Certific
|
||||
}
|
||||
|
||||
const updates: Partial<Certificate> = {
|
||||
status: status as 'APPROVED' | 'PENDING' | 'REJECTED' | 'EXPIRED',
|
||||
status: status as CertificateStatus,
|
||||
};
|
||||
|
||||
if (status === 'APPROVED') {
|
||||
|
||||
@@ -59,9 +59,17 @@ export class BaseDataSource<T, P = any> implements IDataSource<T, P> {
|
||||
* 基础Mock数据源类
|
||||
* 提供通用的Mock数据实现
|
||||
*/
|
||||
export class BaseMockDataSource<T, P = any> implements IMockDataSource<T, P> {
|
||||
export class BaseMockDataSource<T, P = any> implements IMockDataSource<T> {
|
||||
protected mockData: T[] = [];
|
||||
|
||||
reset(): void {
|
||||
this.mockData = [];
|
||||
}
|
||||
|
||||
getMockData(): T[] {
|
||||
return this.mockData;
|
||||
}
|
||||
|
||||
async list(): Promise<T[]> {
|
||||
return this.mockData;
|
||||
}
|
||||
@@ -103,15 +111,6 @@ export class BaseMockDataSource<T, P = any> implements IMockDataSource<T, P> {
|
||||
this.mockData.splice(index, 1);
|
||||
}
|
||||
|
||||
// Mock特定方法
|
||||
reset(): void {
|
||||
this.mockData = [];
|
||||
}
|
||||
|
||||
getMockData(): T[] {
|
||||
return this.mockData;
|
||||
}
|
||||
|
||||
// 延迟方法,用于模拟网络延迟
|
||||
protected async delay(ms: number): Promise<void> {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
@@ -2,7 +2,7 @@ import axios from 'axios';
|
||||
|
||||
// 创建axios实例
|
||||
const http = axios.create({
|
||||
baseURL: 'http://localhost:3000', // 后端API基础URL
|
||||
baseURL: 'http://localhost:3001', // 后端API基础URL
|
||||
timeout: 10000, // 请求超时时间
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@@ -58,6 +58,83 @@ export interface SiteQueryParams {
|
||||
status?: string;
|
||||
}
|
||||
|
||||
export interface SiteAnalytics {
|
||||
id: string;
|
||||
siteId: string;
|
||||
dateRange: {
|
||||
start: string;
|
||||
end: string;
|
||||
};
|
||||
metrics: {
|
||||
visitors: number;
|
||||
pageViews: number;
|
||||
bounceRate: number;
|
||||
avgSessionDuration: number;
|
||||
};
|
||||
sales: {
|
||||
totalRevenue: number;
|
||||
totalOrders: number;
|
||||
avgOrderValue: number;
|
||||
conversionRate: number;
|
||||
};
|
||||
topProducts: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
sales: number;
|
||||
quantity: number;
|
||||
}>;
|
||||
trafficSources: Array<{
|
||||
source: string;
|
||||
visitors: number;
|
||||
percentage: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export type SiteConfig = IndependentSite;
|
||||
|
||||
export interface SiteOrder {
|
||||
id: string;
|
||||
siteId: string;
|
||||
orderNumber: string;
|
||||
customerName: string;
|
||||
customerEmail: string;
|
||||
total: number;
|
||||
currency: string;
|
||||
status: 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';
|
||||
paymentMethod: string;
|
||||
paymentStatus: 'pending' | 'paid' | 'failed' | 'refunded';
|
||||
shippingAddress: {
|
||||
name: string;
|
||||
address: string;
|
||||
city: string;
|
||||
country: string;
|
||||
zipCode: string;
|
||||
};
|
||||
items: Array<{
|
||||
productId: string;
|
||||
productName: string;
|
||||
quantity: number;
|
||||
price: number;
|
||||
}>;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SiteProduct {
|
||||
id: string;
|
||||
siteId: string;
|
||||
name: string;
|
||||
sku: string;
|
||||
price: number;
|
||||
stock: number;
|
||||
status: 'published' | 'draft' | 'unpublished';
|
||||
description?: string;
|
||||
images?: string[];
|
||||
category?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// IndependentSite专用接口
|
||||
// ============================================
|
||||
@@ -129,7 +206,7 @@ class ApiIndependentSiteDataSource implements IIndependentSiteDataSource {
|
||||
* AI注意: 这是Mock实现,不是真实业务逻辑
|
||||
* 仅在REACT_APP_USE_MOCK=true时启用
|
||||
*/
|
||||
class MockIndependentSiteDataSource implements IIndependentSiteDataSource, IMockDataSource<IndependentSite, SiteQueryParams> {
|
||||
class MockIndependentSiteDataSource implements IIndependentSiteDataSource, IMockDataSource<IndependentSite> {
|
||||
readonly __MOCK__ = true as const;
|
||||
readonly __MOCK_NAME__ = 'MockIndependentSiteDataSource';
|
||||
|
||||
|
||||
@@ -4,32 +4,55 @@
|
||||
* 仅在USE_MOCK=true时启用
|
||||
*/
|
||||
|
||||
import { Inventory } from '../types/inventory';
|
||||
import { Inventory, InventoryStatus } from '../types/inventory';
|
||||
|
||||
export interface Warehouse {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
address: string;
|
||||
city: string;
|
||||
country: string;
|
||||
capacity: number;
|
||||
currentUsage: number;
|
||||
status: 'active' | 'inactive' | 'maintenance';
|
||||
manager: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface InventoryForecast {
|
||||
id: string;
|
||||
productId: string;
|
||||
productName: string;
|
||||
sku: string;
|
||||
currentStock: number;
|
||||
forecastedDemand: number;
|
||||
recommendedOrder: number;
|
||||
leadTime: number;
|
||||
riskLevel: 'low' | 'medium' | 'high';
|
||||
date: string;
|
||||
}
|
||||
|
||||
export interface InventoryQueryParams {
|
||||
productId?: string;
|
||||
status?: InventoryStatus;
|
||||
warehouseId?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 库存数据接口
|
||||
export interface InventoryDataSource {
|
||||
list(params?: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
productId?: string;
|
||||
status?: string;
|
||||
warehouseId?: string;
|
||||
}): Promise<{ data: Inventory[]; total: number }>;
|
||||
|
||||
list(params?: InventoryQueryParams): Promise<{ data: Inventory[]; total: number }>;
|
||||
get(id: string): Promise<Inventory | null>;
|
||||
|
||||
create(inventory: Omit<Inventory, 'id' | 'createdAt' | 'updatedAt'>): Promise<Inventory>;
|
||||
|
||||
update(id: string, inventory: Partial<Inventory>): Promise<Inventory | null>;
|
||||
|
||||
updateStock(id: string, quantity: number): Promise<Inventory | null>;
|
||||
|
||||
getByProductId(productId: string): Promise<Inventory[]>;
|
||||
|
||||
getByWarehouseId(warehouseId: string): Promise<Inventory[]>;
|
||||
|
||||
getLowStockAlerts(threshold: number): Promise<Inventory[]>;
|
||||
|
||||
getInventoryStatistics(): Promise<{
|
||||
totalItems: number;
|
||||
totalStock: number;
|
||||
@@ -37,19 +60,12 @@ export interface InventoryDataSource {
|
||||
outOfStockItems: number;
|
||||
warehouseDistribution: Record<string, number>;
|
||||
}>;
|
||||
fetchWarehouses(): Promise<Warehouse[]>;
|
||||
getInventoryForecasts(): Promise<InventoryForecast[]>;
|
||||
}
|
||||
|
||||
// 库存DataSource实现
|
||||
export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
async list(params?: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
productId?: string;
|
||||
status?: string;
|
||||
warehouseId?: string;
|
||||
}): Promise<{ data: Inventory[]; total: number }> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
async list(params?: InventoryQueryParams): Promise<{ data: Inventory[]; total: number }> {
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -57,7 +73,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -70,7 +86,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '无线耳机',
|
||||
quantity: 200,
|
||||
threshold: 30,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-11'),
|
||||
@@ -83,7 +99,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '运动鞋',
|
||||
quantity: 150,
|
||||
threshold: 25,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-12'),
|
||||
@@ -96,7 +112,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手机',
|
||||
quantity: 5,
|
||||
threshold: 10,
|
||||
status: 'low_stock',
|
||||
status: InventoryStatus.LOW_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-09'),
|
||||
@@ -109,7 +125,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '平板电脑',
|
||||
quantity: 0,
|
||||
threshold: 15,
|
||||
status: 'out_of_stock',
|
||||
status: InventoryStatus.OUT_OF_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-08'),
|
||||
@@ -145,8 +161,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async get(id: string): Promise<Inventory | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -154,7 +168,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -167,7 +181,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '无线耳机',
|
||||
quantity: 200,
|
||||
threshold: 30,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-11'),
|
||||
@@ -181,8 +195,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async create(inventory: Omit<Inventory, 'id' | 'createdAt' | 'updatedAt'>): Promise<Inventory> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const newInventory: Inventory = {
|
||||
...inventory,
|
||||
id: `inv_${Date.now()}`,
|
||||
@@ -194,8 +206,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async update(id: string, inventory: Partial<Inventory>): Promise<Inventory | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const existingInventory = await this.get(id);
|
||||
if (!existingInventory) {
|
||||
return null;
|
||||
@@ -211,22 +221,20 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async updateStock(id: string, quantity: number): Promise<Inventory | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const existingInventory = await this.get(id);
|
||||
if (!existingInventory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const newQuantity = existingInventory.quantity + quantity;
|
||||
let status: 'in_stock' | 'low_stock' | 'out_of_stock';
|
||||
let status: InventoryStatus;
|
||||
|
||||
if (newQuantity <= 0) {
|
||||
status = 'out_of_stock';
|
||||
status = InventoryStatus.OUT_OF_STOCK;
|
||||
} else if (newQuantity < existingInventory.threshold) {
|
||||
status = 'low_stock';
|
||||
status = InventoryStatus.LOW_STOCK;
|
||||
} else {
|
||||
status = 'in_stock';
|
||||
status = InventoryStatus.IN_STOCK;
|
||||
}
|
||||
|
||||
const updatedInventory: Inventory = {
|
||||
@@ -241,8 +249,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async getByProductId(productId: string): Promise<Inventory[]> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -250,7 +256,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -263,7 +269,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '无线耳机',
|
||||
quantity: 200,
|
||||
threshold: 30,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-11'),
|
||||
@@ -276,8 +282,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async getByWarehouseId(warehouseId: string): Promise<Inventory[]> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -285,7 +289,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -298,7 +302,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '无线耳机',
|
||||
quantity: 200,
|
||||
threshold: 30,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-11'),
|
||||
@@ -311,7 +315,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '运动鞋',
|
||||
quantity: 150,
|
||||
threshold: 25,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-12'),
|
||||
@@ -324,8 +328,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
}
|
||||
|
||||
async getLowStockAlerts(threshold: number): Promise<Inventory[]> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -333,7 +335,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -346,7 +348,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手机',
|
||||
quantity: 5,
|
||||
threshold: 10,
|
||||
status: 'low_stock',
|
||||
status: InventoryStatus.LOW_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-09'),
|
||||
@@ -359,7 +361,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '平板电脑',
|
||||
quantity: 0,
|
||||
threshold: 15,
|
||||
status: 'out_of_stock',
|
||||
status: InventoryStatus.OUT_OF_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-08'),
|
||||
@@ -378,8 +380,6 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
outOfStockItems: number;
|
||||
warehouseDistribution: Record<string, number>;
|
||||
}> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockInventory: Inventory[] = [
|
||||
{
|
||||
id: 'inv_1',
|
||||
@@ -387,7 +387,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手表',
|
||||
quantity: 100,
|
||||
threshold: 20,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-10'),
|
||||
@@ -400,7 +400,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '无线耳机',
|
||||
quantity: 200,
|
||||
threshold: 30,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-11'),
|
||||
@@ -413,7 +413,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '运动鞋',
|
||||
quantity: 150,
|
||||
threshold: 25,
|
||||
status: 'in_stock',
|
||||
status: InventoryStatus.IN_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-12'),
|
||||
@@ -426,7 +426,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '智能手机',
|
||||
quantity: 5,
|
||||
threshold: 10,
|
||||
status: 'low_stock',
|
||||
status: InventoryStatus.LOW_STOCK,
|
||||
warehouseId: 'warehouse_1',
|
||||
warehouseName: '北京仓库',
|
||||
lastStockUpdate: new Date('2026-03-09'),
|
||||
@@ -439,7 +439,7 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
productName: '平板电脑',
|
||||
quantity: 0,
|
||||
threshold: 15,
|
||||
status: 'out_of_stock',
|
||||
status: InventoryStatus.OUT_OF_STOCK,
|
||||
warehouseId: 'warehouse_2',
|
||||
warehouseName: '上海仓库',
|
||||
lastStockUpdate: new Date('2026-03-08'),
|
||||
@@ -450,12 +450,14 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
|
||||
const totalItems = mockInventory.length;
|
||||
const totalStock = mockInventory.reduce((sum, item) => sum + item.quantity, 0);
|
||||
const lowStockItems = mockInventory.filter(i => i.status === 'low_stock').length;
|
||||
const outOfStockItems = mockInventory.filter(i => i.status === 'out_of_stock').length;
|
||||
const lowStockItems = mockInventory.filter(i => i.status === InventoryStatus.LOW_STOCK).length;
|
||||
const outOfStockItems = mockInventory.filter(i => i.status === InventoryStatus.OUT_OF_STOCK).length;
|
||||
|
||||
const warehouseDistribution: Record<string, number> = {};
|
||||
mockInventory.forEach(item => {
|
||||
warehouseDistribution[item.warehouseName] = (warehouseDistribution[item.warehouseName] || 0) + item.quantity;
|
||||
if (item.warehouseName) {
|
||||
warehouseDistribution[item.warehouseName] = (warehouseDistribution[item.warehouseName] || 0) + item.quantity;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -466,7 +468,84 @@ export class InventoryDataSourceImpl implements InventoryDataSource {
|
||||
warehouseDistribution,
|
||||
};
|
||||
}
|
||||
|
||||
async fetchWarehouses(): Promise<Warehouse[]> {
|
||||
return [
|
||||
{
|
||||
id: 'warehouse_1',
|
||||
name: '北京仓库',
|
||||
code: 'BJ-WH-001',
|
||||
address: '北京市朝阳区建国路88号',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
capacity: 10000,
|
||||
currentUsage: 7500,
|
||||
status: 'active',
|
||||
manager: '张三',
|
||||
phone: '010-12345678',
|
||||
email: 'zhangsan@example.com',
|
||||
createdAt: '2026-01-01',
|
||||
updatedAt: '2026-03-15',
|
||||
},
|
||||
{
|
||||
id: 'warehouse_2',
|
||||
name: '上海仓库',
|
||||
code: 'SH-WH-001',
|
||||
address: '上海市浦东新区张江路100号',
|
||||
city: '上海',
|
||||
country: '中国',
|
||||
capacity: 15000,
|
||||
currentUsage: 12000,
|
||||
status: 'active',
|
||||
manager: '李四',
|
||||
phone: '021-87654321',
|
||||
email: 'lisi@example.com',
|
||||
createdAt: '2026-01-15',
|
||||
updatedAt: '2026-03-16',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
async getInventoryForecasts(): Promise<InventoryForecast[]> {
|
||||
return [
|
||||
{
|
||||
id: 'forecast_1',
|
||||
productId: '1',
|
||||
productName: '智能手表',
|
||||
sku: 'WATCH-001',
|
||||
currentStock: 100,
|
||||
forecastedDemand: 150,
|
||||
recommendedOrder: 50,
|
||||
leadTime: 7,
|
||||
riskLevel: 'low',
|
||||
date: '2026-03-21',
|
||||
},
|
||||
{
|
||||
id: 'forecast_2',
|
||||
productId: '2',
|
||||
productName: '无线耳机',
|
||||
sku: 'EARPHONE-001',
|
||||
currentStock: 200,
|
||||
forecastedDemand: 180,
|
||||
recommendedOrder: 0,
|
||||
leadTime: 5,
|
||||
riskLevel: 'low',
|
||||
date: '2026-03-21',
|
||||
},
|
||||
{
|
||||
id: 'forecast_3',
|
||||
productId: '4',
|
||||
productName: '智能手机',
|
||||
sku: 'PHONE-001',
|
||||
currentStock: 5,
|
||||
forecastedDemand: 50,
|
||||
recommendedOrder: 45,
|
||||
leadTime: 10,
|
||||
riskLevel: 'high',
|
||||
date: '2026-03-21',
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 导出DataSource实例
|
||||
export const inventoryDataSource = new InventoryDataSourceImpl();
|
||||
|
||||
@@ -37,6 +37,23 @@ export interface TrackingEvent {
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface FreightQuote {
|
||||
id: string;
|
||||
channel: string;
|
||||
carrier: string;
|
||||
name: string;
|
||||
basePrice: number;
|
||||
pricePerKg: number;
|
||||
pricePerVol: number;
|
||||
estimatedDays: number;
|
||||
totalPrice: number;
|
||||
fuelSurcharge: number;
|
||||
remoteAreaSurcharge: number;
|
||||
customsDuty: number;
|
||||
insurance: number;
|
||||
totalWithDuty: number;
|
||||
}
|
||||
|
||||
export interface ILogisticsDataSource {
|
||||
fetchProviders(): Promise<LogisticsProvider[]>;
|
||||
createProvider(data: Partial<LogisticsProvider>): Promise<LogisticsProvider>;
|
||||
|
||||
@@ -31,6 +31,8 @@ export interface Competitor {
|
||||
lastUpdated: string;
|
||||
trackedProducts: string[];
|
||||
marketShare?: number;
|
||||
website?: string;
|
||||
socialFollowers?: number;
|
||||
}
|
||||
|
||||
export interface IMarketingDataSource {
|
||||
|
||||
@@ -32,7 +32,9 @@ export interface MerchantShop {
|
||||
export interface MerchantOrder {
|
||||
id: string;
|
||||
merchantId: string;
|
||||
merchantName: string;
|
||||
orderId: string;
|
||||
platform: string;
|
||||
totalAmount: number;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
@@ -123,7 +125,9 @@ class MockMerchantDataSource implements IMerchantDataSource {
|
||||
{
|
||||
id: '1',
|
||||
merchantId: '1',
|
||||
merchantName: 'Test Company A',
|
||||
orderId: 'ORD-2026-001',
|
||||
platform: 'Amazon',
|
||||
totalAmount: 1500.00,
|
||||
status: 'COMPLETED',
|
||||
createdAt: '2026-03-15',
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import { Order } from '../types/order';
|
||||
|
||||
// 订单数据接口
|
||||
export interface OrderDataSource {
|
||||
list(params?: {
|
||||
page?: number;
|
||||
@@ -40,7 +39,6 @@ export interface OrderDataSource {
|
||||
}>;
|
||||
}
|
||||
|
||||
// 订单DataSource实现
|
||||
export class OrderDataSourceImpl implements OrderDataSource {
|
||||
async list(params?: {
|
||||
page?: number;
|
||||
@@ -50,8 +48,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}): Promise<{ data: Order[]; total: number }> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockOrders: Order[] = [
|
||||
{
|
||||
id: '1',
|
||||
@@ -62,17 +58,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '1',
|
||||
productName: '智能手表',
|
||||
quantity: 1,
|
||||
price: 199.99
|
||||
unitPrice: 199.99,
|
||||
totalPrice: 199.99
|
||||
}
|
||||
],
|
||||
totalAmount: 199.99,
|
||||
status: 'completed',
|
||||
status: 'delivered',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-10'),
|
||||
updatedAt: new Date('2026-03-10'),
|
||||
@@ -86,17 +84,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '2',
|
||||
productName: '无线耳机',
|
||||
quantity: 2,
|
||||
price: 129.99
|
||||
unitPrice: 129.99,
|
||||
totalPrice: 259.98
|
||||
}
|
||||
],
|
||||
totalAmount: 259.98,
|
||||
status: 'processing',
|
||||
paymentMethod: 'paypal',
|
||||
shippingAddress: {
|
||||
street: '上海市浦东新区',
|
||||
name: '李四',
|
||||
address: '上海市浦东新区',
|
||||
city: '上海',
|
||||
country: '中国',
|
||||
zipCode: '200000'
|
||||
zip: '200000'
|
||||
},
|
||||
createdAt: new Date('2026-03-11'),
|
||||
updatedAt: new Date('2026-03-11'),
|
||||
@@ -110,17 +110,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '3',
|
||||
productName: '运动鞋',
|
||||
quantity: 1,
|
||||
price: 89.99
|
||||
unitPrice: 89.99,
|
||||
totalPrice: 89.99
|
||||
}
|
||||
],
|
||||
totalAmount: 89.99,
|
||||
status: 'pending',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-12'),
|
||||
updatedAt: new Date('2026-03-12'),
|
||||
@@ -150,8 +152,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
|
||||
async get(id: string): Promise<Order | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockOrders: Order[] = [
|
||||
{
|
||||
id: '1',
|
||||
@@ -162,17 +162,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '1',
|
||||
productName: '智能手表',
|
||||
quantity: 1,
|
||||
price: 199.99
|
||||
unitPrice: 199.99,
|
||||
totalPrice: 199.99
|
||||
}
|
||||
],
|
||||
totalAmount: 199.99,
|
||||
status: 'completed',
|
||||
status: 'delivered',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-10'),
|
||||
updatedAt: new Date('2026-03-10'),
|
||||
@@ -186,17 +188,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '2',
|
||||
productName: '无线耳机',
|
||||
quantity: 2,
|
||||
price: 129.99
|
||||
unitPrice: 129.99,
|
||||
totalPrice: 259.98
|
||||
}
|
||||
],
|
||||
totalAmount: 259.98,
|
||||
status: 'processing',
|
||||
paymentMethod: 'paypal',
|
||||
shippingAddress: {
|
||||
street: '上海市浦东新区',
|
||||
name: '李四',
|
||||
address: '上海市浦东新区',
|
||||
city: '上海',
|
||||
country: '中国',
|
||||
zipCode: '200000'
|
||||
zip: '200000'
|
||||
},
|
||||
createdAt: new Date('2026-03-11'),
|
||||
updatedAt: new Date('2026-03-11'),
|
||||
@@ -208,8 +212,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
|
||||
async create(order: Omit<Order, 'id' | 'createdAt' | 'updatedAt'>): Promise<Order> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const newOrder: Order = {
|
||||
...order,
|
||||
id: `order_${Date.now()}`,
|
||||
@@ -221,8 +223,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
|
||||
async update(id: string, order: Partial<Order>): Promise<Order | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const existingOrder = await this.get(id);
|
||||
if (!existingOrder) {
|
||||
return null;
|
||||
@@ -238,8 +238,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
|
||||
async updateStatus(id: string, status: string): Promise<Order | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const existingOrder = await this.get(id);
|
||||
if (!existingOrder) {
|
||||
return null;
|
||||
@@ -247,7 +245,7 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
|
||||
const updatedOrder: Order = {
|
||||
...existingOrder,
|
||||
status: status as 'pending' | 'processing' | 'shipped' | 'completed' | 'cancelled',
|
||||
status: status as Order['status'],
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
@@ -255,14 +253,21 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
|
||||
async cancel(id: string): Promise<Order | null> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
return this.updateStatus(id, 'cancelled');
|
||||
const existingOrder = await this.get(id);
|
||||
if (!existingOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const updatedOrder: Order = {
|
||||
...existingOrder,
|
||||
status: 'cancelled',
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
|
||||
return updatedOrder;
|
||||
}
|
||||
|
||||
async getByCustomerId(customerId: string): Promise<Order[]> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockOrders: Order[] = [
|
||||
{
|
||||
id: '1',
|
||||
@@ -273,17 +278,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '1',
|
||||
productName: '智能手表',
|
||||
quantity: 1,
|
||||
price: 199.99
|
||||
unitPrice: 199.99,
|
||||
totalPrice: 199.99
|
||||
}
|
||||
],
|
||||
totalAmount: 199.99,
|
||||
status: 'completed',
|
||||
status: 'delivered',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-10'),
|
||||
updatedAt: new Date('2026-03-10'),
|
||||
@@ -297,17 +304,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '3',
|
||||
productName: '运动鞋',
|
||||
quantity: 1,
|
||||
price: 89.99
|
||||
unitPrice: 89.99,
|
||||
totalPrice: 89.99
|
||||
}
|
||||
],
|
||||
totalAmount: 89.99,
|
||||
status: 'pending',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-12'),
|
||||
updatedAt: new Date('2026-03-12'),
|
||||
@@ -326,8 +335,6 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
averageOrderValue: number;
|
||||
statusDistribution: Record<string, number>;
|
||||
}> {
|
||||
// 这里应该调用实际的API
|
||||
// 暂时返回Mock数据
|
||||
const mockOrders: Order[] = [
|
||||
{
|
||||
id: '1',
|
||||
@@ -338,17 +345,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '1',
|
||||
productName: '智能手表',
|
||||
quantity: 1,
|
||||
price: 199.99
|
||||
unitPrice: 199.99,
|
||||
totalPrice: 199.99
|
||||
}
|
||||
],
|
||||
totalAmount: 199.99,
|
||||
status: 'completed',
|
||||
status: 'delivered',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-10'),
|
||||
updatedAt: new Date('2026-03-10'),
|
||||
@@ -362,17 +371,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '2',
|
||||
productName: '无线耳机',
|
||||
quantity: 2,
|
||||
price: 129.99
|
||||
unitPrice: 129.99,
|
||||
totalPrice: 259.98
|
||||
}
|
||||
],
|
||||
totalAmount: 259.98,
|
||||
status: 'processing',
|
||||
paymentMethod: 'paypal',
|
||||
shippingAddress: {
|
||||
street: '上海市浦东新区',
|
||||
name: '李四',
|
||||
address: '上海市浦东新区',
|
||||
city: '上海',
|
||||
country: '中国',
|
||||
zipCode: '200000'
|
||||
zip: '200000'
|
||||
},
|
||||
createdAt: new Date('2026-03-11'),
|
||||
updatedAt: new Date('2026-03-11'),
|
||||
@@ -386,17 +397,19 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
productId: '3',
|
||||
productName: '运动鞋',
|
||||
quantity: 1,
|
||||
price: 89.99
|
||||
unitPrice: 89.99,
|
||||
totalPrice: 89.99
|
||||
}
|
||||
],
|
||||
totalAmount: 89.99,
|
||||
status: 'pending',
|
||||
paymentMethod: 'credit_card',
|
||||
shippingAddress: {
|
||||
street: '北京市朝阳区',
|
||||
name: '张三',
|
||||
address: '北京市朝阳区',
|
||||
city: '北京',
|
||||
country: '中国',
|
||||
zipCode: '100000'
|
||||
zip: '100000'
|
||||
},
|
||||
createdAt: new Date('2026-03-12'),
|
||||
updatedAt: new Date('2026-03-12'),
|
||||
@@ -421,5 +434,4 @@ export class OrderDataSourceImpl implements OrderDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
// 导出DataSource实例
|
||||
export const orderDataSource = new OrderDataSourceImpl();
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
// 产品数据源
|
||||
import { Product } from '@/types/product';
|
||||
/**
|
||||
* [MOCK-007] 产品模块DataSource
|
||||
* AI注意: 这是Mock实现,不是真实业务逻辑
|
||||
* 仅在USE_MOCK=true时启用
|
||||
*/
|
||||
|
||||
import { Product, ProductStatus } from '@/types/product';
|
||||
import { IDataSource, IMockDataSource } from '@/types/datasource';
|
||||
|
||||
export interface ProfitMonitor {
|
||||
@@ -30,54 +35,45 @@ export interface ROIAnalysis {
|
||||
status: 'ACTIVE' | 'COMPLETED' | 'PAUSED';
|
||||
}
|
||||
|
||||
// API实现
|
||||
export class ProductApiDataSource implements IDataSource<Product> {
|
||||
async list(): Promise<Product[]> {
|
||||
// 这里应该调用实际的API
|
||||
return [];
|
||||
}
|
||||
|
||||
async detail(id: string): Promise<Product> {
|
||||
// 这里应该调用实际的API
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async create(data: Partial<Product>): Promise<Product> {
|
||||
// 这里应该调用实际的API
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async update(id: string, data: Partial<Product>): Promise<Product> {
|
||||
// 这里应该调用实际的API
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
// 这里应该调用实际的API
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
// 额外的方法
|
||||
async getByCategory(category: string): Promise<Product[]> {
|
||||
// 这里应该调用实际的API
|
||||
return [];
|
||||
}
|
||||
|
||||
async updateStatus(id: string, status: 'active' | 'inactive' | 'discontinued'): Promise<Product | null> {
|
||||
// 这里应该调用实际的API
|
||||
async updateStatus(id: string, status: ProductStatus): Promise<Product | null> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
// Mock实现
|
||||
export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
private mockProducts: Product[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: '智能手机',
|
||||
sku: 'PHONE-001',
|
||||
description: '最新款智能手机',
|
||||
price: 5999.99,
|
||||
category: '电子产品',
|
||||
categories: ['电子产品'],
|
||||
status: 'active',
|
||||
stock: 100,
|
||||
images: ['https://example.com/phone1.jpg', 'https://example.com/phone2.jpg'],
|
||||
@@ -87,9 +83,10 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
{
|
||||
id: '2',
|
||||
name: '笔记本电脑',
|
||||
sku: 'LAPTOP-001',
|
||||
description: '高性能笔记本电脑',
|
||||
price: 8999.99,
|
||||
category: '电子产品',
|
||||
categories: ['电子产品'],
|
||||
status: 'active',
|
||||
stock: 50,
|
||||
images: ['https://example.com/laptop1.jpg', 'https://example.com/laptop2.jpg'],
|
||||
@@ -99,9 +96,10 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
{
|
||||
id: '3',
|
||||
name: '运动鞋',
|
||||
sku: 'SHOE-001',
|
||||
description: '轻便透气运动鞋',
|
||||
price: 89.99,
|
||||
category: '服装',
|
||||
categories: ['服装'],
|
||||
status: 'active',
|
||||
stock: 150,
|
||||
images: ['https://example.com/shoe1.jpg', 'https://example.com/shoe2.jpg'],
|
||||
@@ -126,9 +124,10 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
const newProduct: Product = {
|
||||
id: `${this.mockProducts.length + 1}`,
|
||||
name: data.name || '',
|
||||
sku: data.sku || `SKU-${Date.now()}`,
|
||||
description: data.description || '',
|
||||
price: data.price || 0,
|
||||
category: data.category || '',
|
||||
categories: data.categories || [],
|
||||
status: data.status || 'active',
|
||||
stock: data.stock || 0,
|
||||
images: data.images || [],
|
||||
@@ -160,12 +159,11 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
this.mockProducts.splice(index, 1);
|
||||
}
|
||||
|
||||
// 额外的方法
|
||||
async getByCategory(category: string): Promise<Product[]> {
|
||||
return this.mockProducts.filter(p => p.category === category);
|
||||
return this.mockProducts.filter(p => p.categories?.includes(category));
|
||||
}
|
||||
|
||||
async updateStatus(id: string, status: 'active' | 'inactive' | 'discontinued'): Promise<Product | null> {
|
||||
async updateStatus(id: string, status: ProductStatus): Promise<Product | null> {
|
||||
const existingProduct = this.mockProducts.find(p => p.id === id);
|
||||
if (!existingProduct) {
|
||||
return null;
|
||||
@@ -185,15 +183,15 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
return updatedProduct;
|
||||
}
|
||||
|
||||
// Mock特定方法
|
||||
reset(): void {
|
||||
this.mockProducts = [
|
||||
{
|
||||
id: '1',
|
||||
name: '智能手机',
|
||||
sku: 'PHONE-001',
|
||||
description: '最新款智能手机',
|
||||
price: 5999.99,
|
||||
category: '电子产品',
|
||||
categories: ['电子产品'],
|
||||
status: 'active',
|
||||
stock: 100,
|
||||
images: ['https://example.com/phone1.jpg', 'https://example.com/phone2.jpg'],
|
||||
@@ -203,9 +201,10 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
{
|
||||
id: '2',
|
||||
name: '笔记本电脑',
|
||||
sku: 'LAPTOP-001',
|
||||
description: '高性能笔记本电脑',
|
||||
price: 8999.99,
|
||||
category: '电子产品',
|
||||
categories: ['电子产品'],
|
||||
status: 'active',
|
||||
stock: 50,
|
||||
images: ['https://example.com/laptop1.jpg', 'https://example.com/laptop2.jpg'],
|
||||
@@ -215,9 +214,10 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
{
|
||||
id: '3',
|
||||
name: '运动鞋',
|
||||
sku: 'SHOE-001',
|
||||
description: '轻便透气运动鞋',
|
||||
price: 89.99,
|
||||
category: '服装',
|
||||
categories: ['服装'],
|
||||
status: 'active',
|
||||
stock: 150,
|
||||
images: ['https://example.com/shoe1.jpg', 'https://example.com/shoe2.jpg'],
|
||||
@@ -232,8 +232,4 @@ export class ProductMockDataSource implements IMockDataSource<Product> {
|
||||
}
|
||||
}
|
||||
|
||||
// 数据源导出
|
||||
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||||
export const productDataSource = useMock
|
||||
? new ProductMockDataSource()
|
||||
: new ProductApiDataSource();
|
||||
export const productDataSource = new ProductMockDataSource();
|
||||
|
||||
@@ -236,7 +236,7 @@ export class UserDataSourceImpl implements UserDataSource {
|
||||
return mockUsers.filter(u =>
|
||||
u.name.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
u.email.toLowerCase().includes(keyword.toLowerCase()) ||
|
||||
u.phone.includes(keyword)
|
||||
(u.phone && u.phone.includes(keyword))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user