Files
junhong_cmp_fiber/docs/excel-import-frontend-guide.md
huang 80c6f6c756
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m21s
feat: 资产标识符标准化、资产历史订单查询及导入虚拟号强制验证
主要变更:
- 新增 AssetIdentifier 模型及 Store,统一管理资产标识符(ICCID/IMEI/SN 等)
- 新增迁移:asset_identifier 表、order 表新增 asset_identifier 字段、iot_card.virtual_no NOT NULL 约束
- 资产 Handler/Service/Route 全面重构,支持标识符路由查询与解析
- 新增资产历史订单查询接口,支持跨设备/卡/钱包维度的订单聚合
- 设备与物联卡导入任务强制校验虚拟号,缺失时直接拒绝
- Excel 工具函数优化,前端导入指引文档同步更新
- 归档三个 OpenSpec 提案:asset-identifier-standardization、asset-historical-orders、import-mandatory-virtual-no
- 更新 OpenAPI 文档及相关 DTO

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-07 17:39:36 +08:00

215 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Excel导入功能 - 前端接入指南
## 变更说明
导入功能已从CSV格式升级为Excel格式(.xlsx),解决长数字(如20位ICCID)被Excel自动转为科学记数法导致数据损坏的问题。
## 关键变更
### 1. 文件格式
| 项目 | 旧版本(CSV) | 新版本(Excel) |
|-----|------------|--------------|
| 文件扩展名 | `.csv` | `.xlsx` |
| MIME类型 | `text/csv` | `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` |
| 文件选择器accept | `*``.csv` | `.xlsx` |
### 2. 上传示例代码
**ICCID导入**:
```javascript
// 1. 获取预签名URL
const response = await api.post('/api/admin/storage/upload-url', {
file_name: 'cards.xlsx', // 修改扩展名
content_type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // 修改MIME类型
purpose: 'iot_import'
});
const { upload_url, file_key } = response.data;
// 2. 上传Excel文件到对象存储
await fetch(upload_url, {
method: 'PUT',
headers: {
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' // 修改MIME类型
},
body: file // File对象来自<input type="file" accept=".xlsx">
});
// 3. 提交导入任务
await api.post('/api/admin/iot-cards/import', {
carrier_id: 1,
batch_no: 'BATCH-2025-01',
file_key: file_key
});
```
**设备导入**: 流程相同,只需调用 `/api/admin/devices/import` 接口。
### 3. 文件选择器组件
**修改前**:
```html
<input type="file" accept="*" />
<!---->
<input type="file" accept=".csv" />
```
**修改后**:
```html
<input type="file" accept=".xlsx" />
```
### 4. 文件验证
```javascript
function validateFile(file) {
// 检查扩展名
if (!file.name.toLowerCase().endsWith('.xlsx')) {
throw new Error('仅支持上传Excel文件(.xlsx格式)');
}
// 检查MIME类型(可选,部分浏览器可能不准确)
const validTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/octet-stream' // 部分浏览器可能返回此类型
];
if (!validTypes.includes(file.type)) {
console.warn('文件MIME类型不匹配,但根据扩展名判断为有效文件');
}
return true;
}
```
## Excel模板文件
### ICCID导入模板
**文件名**: `iccid_import_template.xlsx`
**格式**:
| ICCID | MSISDN | virtual_no |
|-------|--------|------------|
| 89860012345678901234 | 13800000001 | VNO-00001 |
| 89860012345678901235 | 13800000002 | VNO-00002 |
**字段说明**:
| 列名 | 是否必填 | 说明 |
|------|---------|------|
| ICCID | **是** | 卡唯一标识电信19位/其他20位 |
| MSISDN | **是** | 接入号 |
| virtual_no | **是** | 虚拟号,全局唯一;留空将导致该行导入失败 |
**要点**:
- 必须包含表头行(ICCID, MSISDN, virtual_no)
- 所有列必须设置为**文本格式**(重要!)
- Excel中设置文本格式: 选中列 → 右键 → 设置单元格格式 → 文本
- `virtual_no` 为必填列,**缺少该列将导致整批导入失败**
### 设备导入模板
**文件名**: `device_import_template.xlsx`
**格式**:
| virtual_no | device_name | device_model | device_type | max_sim_slots | manufacturer | imei | iccid_1 | iccid_2 | iccid_3 | iccid_4 |
|------------|-------------|--------------|-------------|---------------|--------------|------|---------|---------|---------|---------|
| DEV-001 | GPS追踪器A | GT06N | GPS Tracker | 4 | Concox | 123456789012345 | 89860012345678901234 | 89860012345678901235 | | |
| DEV-002 | GPS追踪器B | GT06N | GPS Tracker | 4 | Concox | 123456789012346 | 89860012345678901236 | | | |
**字段说明**:
| 列名 | 是否必填 | 说明 |
|------|---------|------|
| virtual_no | **是** | 设备虚拟号,全局唯一;**留空不再跳过,将记录为失败行** |
| device_name | 否 | 设备名称 |
| device_model | 否 | 设备型号 |
| device_type | 否 | 设备类型 |
| max_sim_slots | 否 | 最大SIM卡槽数默认4 |
| manufacturer | 否 | 制造商 |
| imei | 否 | 设备IMEI |
| iccid_1 ~ iccid_4 | 否 | 绑定的IoT卡ICCID填写时对应ICCID必须已存在于系统中 |
**要点**:
- 所有列都必须设置为**文本格式**
- `virtual_no` 为必填项,留空将记录为失败行(而非静默跳过)
- iccid_1 ~ iccid_4为可选项填写时对应的ICCID必须已存在于系统中
## 模板下载功能实现
```javascript
// 方案1: 后端提供静态文件下载
<a href="/api/admin/storage/templates/iccid_import_template.xlsx" download>
下载ICCID导入模板
</a>
// 方案2: 前端本地存放模板文件
<a href="/assets/templates/iccid_import_template.xlsx" download>
下载ICCID导入模板
</a>
```
建议使用方案2(前端本地存放),减轻后端负担。
## 错误处理
### 服务端错误示例
```json
{
"code": 1,
"msg": "不支持的文件格式 .csv,请上传Excel文件(.xlsx)",
"timestamp": "2025-01-31T13:00:00Z"
}
```
### 前端错误提示
```javascript
try {
await uploadAndImport(file);
} catch (error) {
if (error.response?.data?.msg) {
// 显示服务端返回的错误消息
showError(error.response.data.msg);
} else {
showError('上传失败,请重试');
}
}
```
## 迁移检查清单
- [ ] 修改文件选择器accept属性为 `.xlsx`
- [ ] 更新上传时的MIME类型为Excel格式
- [ ] 添加前端文件格式验证(扩展名检查)
- [ ] 准备Excel模板文件并放置到前端资源目录
- [ ] 添加"下载模板"按钮/链接
- [ ] 更新相关提示文案(CSV → Excel)
- [ ] 测试完整的上传流程
- [ ] 验证错误场景(上传CSV文件时的提示)
## 注意事项
1. **向后兼容**: 本次变更不向后兼容,旧的CSV文件无法使用,前端需同步更新
2. **用户通知**: 建议在界面上添加醒目提示,告知用户格式变更
3. **模板文件**: 模板文件中的ICCID列**必须**设置为文本格式,否则长数字会被Excel自动转为科学记数法
4. **文件大小**: Excel文件比CSV大3-5倍,但对1万行数据影响不大(约3-5MB)
## 常见问题
**Q: 为什么要从CSV改为Excel?**
A: Excel编辑CSV时会将超过15位的长数字(如20位ICCID)自动转为科学记数法,导致数据损坏。使用Excel格式并设置为文本格式可彻底解决此问题。
**Q: 用户已经准备好的CSV文件怎么办?**
A: 用户可以在Excel中打开CSV,将ICCID/MSISDN列设置为文本格式,然后另存为.xlsx格式即可。
**Q: 是否支持.xls(旧版Excel)?**
A: 不支持。仅支持.xlsx (Excel 2007+),建议在文档中明确说明。
## 联系方式
如有问题,请联系后端开发团队。