feat(import): 用 Excel 格式替换 CSV 导入
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m33s

- 删除 CSV 解析代码,新增 Excel 解析器 (excelize)

- 更新 IoT 卡和设备导入任务处理器

- 更新 API 路由文档和前端接入指南

- 归档变更到 openspec/changes/archive/

- 同步 delta specs 到 main specs
This commit is contained in:
2026-01-31 14:13:02 +08:00
parent 62708892ec
commit d309951493
24 changed files with 2279 additions and 589 deletions

View File

@@ -3,7 +3,9 @@ package task
import (
"context"
"errors"
"os"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/bytedance/sonic"
@@ -96,9 +98,9 @@ func (h *IotCardImportHandler) HandleIotCardImport(ctx context.Context, task *as
zap.String("storage_key", importTask.StorageKey),
)
cards, totalCount, err := h.downloadAndParseCSV(ctx, importTask)
cards, totalCount, err := h.downloadAndParse(ctx, importTask)
if err != nil {
h.logger.Error("下载或解析 CSV 失败",
h.logger.Error("下载或解析 Excel 失败",
zap.Uint("task_id", importTask.ID),
zap.Error(err),
)
@@ -130,7 +132,7 @@ func (h *IotCardImportHandler) HandleIotCardImport(ctx context.Context, task *as
return nil
}
func (h *IotCardImportHandler) downloadAndParseCSV(ctx context.Context, task *model.IotCardImportTask) (model.CardListJSON, int, error) {
func (h *IotCardImportHandler) downloadAndParse(ctx context.Context, task *model.IotCardImportTask) (model.CardListJSON, int, error) {
if h.storageService == nil {
return nil, 0, ErrStorageNotConfigured
}
@@ -145,13 +147,12 @@ func (h *IotCardImportHandler) downloadAndParseCSV(ctx context.Context, task *mo
}
defer cleanup()
f, err := os.Open(localPath)
if err != nil {
return nil, 0, err
if !strings.HasSuffix(strings.ToLower(task.FileName), ".xlsx") {
ext := filepath.Ext(task.FileName)
return nil, 0, fmt.Errorf("不支持的文件格式 %s,请上传Excel文件(.xlsx)", ext)
}
defer f.Close()
parseResult, err := utils.ParseCardCSV(f)
parseResult, err := utils.ParseCardExcel(localPath)
if err != nil {
return nil, 0, err
}