forked from yoone/API
feat(订单): 添加CSV文件导入产品功能
在订单控制器和服务中添加导入产品功能,支持通过CSV文件批量导入产品数据 文件解析使用xlsx库自动识别文件类型并处理UTF-8编码
This commit is contained in:
parent
3968fd8965
commit
ff5d7e81a1
|
|
@ -2,6 +2,7 @@ import {
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
Del,
|
Del,
|
||||||
|
Files,
|
||||||
Get,
|
Get,
|
||||||
Inject,
|
Inject,
|
||||||
Param,
|
Param,
|
||||||
|
|
@ -27,7 +28,6 @@ import {
|
||||||
} from '../dto/order.dto';
|
} from '../dto/order.dto';
|
||||||
import { User } from '../decorator/user.decorator';
|
import { User } from '../decorator/user.decorator';
|
||||||
import { ErpOrderStatus } from '../enums/base.enum';
|
import { ErpOrderStatus } from '../enums/base.enum';
|
||||||
|
|
||||||
@Controller('/order')
|
@Controller('/order')
|
||||||
export class OrderController {
|
export class OrderController {
|
||||||
@Inject()
|
@Inject()
|
||||||
|
|
@ -264,4 +264,21 @@ export class OrderController {
|
||||||
return errorResponse(error?.message || '导出失败');
|
return errorResponse(error?.message || '导出失败');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 导入产品(CSV 文件)
|
||||||
|
@ApiOkResponse()
|
||||||
|
@Post('/import')
|
||||||
|
async importWintopay(@Files() files: any) {
|
||||||
|
try {
|
||||||
|
// 条件判断:确保存在文件
|
||||||
|
const file = files?.[0];
|
||||||
|
if (!file) return errorResponse('未接收到上传文件');
|
||||||
|
|
||||||
|
const result = await this.orderService.importWintopayTable(file);
|
||||||
|
return successResponse(result);
|
||||||
|
} catch (error) {
|
||||||
|
return errorResponse(error?.message || error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Inject, Logger, Provide } from '@midwayjs/core';
|
import { Inject, Logger, Provide } from '@midwayjs/core';
|
||||||
import { WPService } from './wp.service';
|
import { WPService } from './wp.service';
|
||||||
|
import * as xlsx from 'xlsx';
|
||||||
import { Order } from '../entity/order.entity';
|
import { Order } from '../entity/order.entity';
|
||||||
import { In, Like, Repository } from 'typeorm';
|
import { In, Like, Repository } from 'typeorm';
|
||||||
import { InjectEntityModel, TypeORMDataSourceManager } from '@midwayjs/typeorm';
|
import { InjectEntityModel, TypeORMDataSourceManager } from '@midwayjs/typeorm';
|
||||||
|
|
@ -32,7 +33,7 @@ import { UpdateStockDTO } from '../dto/stock.dto';
|
||||||
import { StockService } from './stock.service';
|
import { StockService } from './stock.service';
|
||||||
import { OrderItemOriginal } from '../entity/order_item_original.entity';
|
import { OrderItemOriginal } from '../entity/order_item_original.entity';
|
||||||
import { SiteApiService } from './site-api.service';
|
import { SiteApiService } from './site-api.service';
|
||||||
import { SyncOperationResult } from '../dto/api.dto';
|
import { BatchErrorItem, SyncOperationResult,BatchOperationResult } from '../dto/api.dto';
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
@ -2728,4 +2729,58 @@ export class OrderService {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 从 CSV 导入产品;存在则更新,不存在则创建
|
||||||
|
async importWintopayTable(file: any): Promise<BatchOperationResult> {
|
||||||
|
let created = 0;
|
||||||
|
let updated = 0;
|
||||||
|
const errors: BatchErrorItem[] = [];
|
||||||
|
const records = await this.getRecordsFromTable(file);
|
||||||
|
created++
|
||||||
|
updated++
|
||||||
|
|
||||||
|
return { total: records.length, processed: records.length - errors.length, created: 0, updated: 0, errors };
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRecordsFromTable(file: any) {
|
||||||
|
// 解析文件(使用 xlsx 包自动识别文件类型并解析)
|
||||||
|
try {
|
||||||
|
let buffer: Buffer;
|
||||||
|
|
||||||
|
// 处理文件输入,获取 buffer
|
||||||
|
if (Buffer.isBuffer(file)) {
|
||||||
|
buffer = file;
|
||||||
|
}
|
||||||
|
else if (file?.data) {
|
||||||
|
if (typeof file.data === 'string') {
|
||||||
|
buffer = fs.readFileSync(file.data);
|
||||||
|
} else {
|
||||||
|
buffer = file.data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('无效的文件输入');
|
||||||
|
}
|
||||||
|
|
||||||
|
let records: any[] = []
|
||||||
|
// xlsx 包会自动根据文件内容识别文件类型(CSV 或 XLSX)
|
||||||
|
// 添加codepage: 65001以确保正确处理UTF-8编码的中文
|
||||||
|
const workbook = xlsx.read(buffer, { type: 'buffer', codepage: 65001 });
|
||||||
|
// 获取第一个工作表
|
||||||
|
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
|
||||||
|
// 将工作表转换为 JSON 数组
|
||||||
|
records = xlsx.utils.sheet_to_json(worksheet);
|
||||||
|
|
||||||
|
console.log('Parsed records count:', records.length);
|
||||||
|
if (records.length > 0) {
|
||||||
|
console.log('First record keys:', Object.keys(records[0]));
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(`文件解析失败:${e?.message || e}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue