init:代码初始化
This commit is contained in:
299
docs/IMPORT_API.md
Normal file
299
docs/IMPORT_API.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# 数据导入 API 文档
|
||||
|
||||
## POST /api/prices/import
|
||||
|
||||
批量导入钢材价格数据到数据库。
|
||||
|
||||
### 请求格式
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"prices": [
|
||||
{
|
||||
"price_id": "2008067775216672769",
|
||||
"goods_material": "HPB300",
|
||||
"goods_spec": "Φ8",
|
||||
"partsname_name": "螺纹钢",
|
||||
"productarea_name": "昆钢",
|
||||
"price_source": "我的钢铁",
|
||||
"price_region": "昆明",
|
||||
"pntree_name": "钢筋",
|
||||
"price_date": "2026-01-05T10:30:00.000Z",
|
||||
"make_price": 3800,
|
||||
"hang_price": 3850,
|
||||
"last_make_price": 3750,
|
||||
"last_hang_price": 3800,
|
||||
"make_price_updw": "↑50",
|
||||
"hang_price_updw": "↑50",
|
||||
"operator_code": "OP001",
|
||||
"operator_name": "张三"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 字段说明
|
||||
|
||||
#### 必填字段
|
||||
|
||||
| 字段名 | 类型 | 说明 | 示例 |
|
||||
|--------|------|------|------|
|
||||
| `goods_material` | string | 材质牌号 | `"HPB300"` |
|
||||
| `goods_spec` | string | 规格型号 | `"Φ8"` |
|
||||
| `partsname_name` | string | 品名 | `"螺纹钢"` |
|
||||
| `productarea_name` | string | 产地/钢厂 | `"昆钢"` |
|
||||
| `price_source` | string | 价格来源 | `"我的钢铁"` |
|
||||
| `price_region` | string | 价格地区 | `"昆明"` |
|
||||
| `price_date` | string | 价格日期(ISO 8601) | `"2026-01-05T10:30:00.000Z"` |
|
||||
| `hang_price` | number | 挂牌价(元/吨) | `3850` |
|
||||
|
||||
#### 可选字段
|
||||
|
||||
| 字段名 | 类型 | 说明 | 默认值 | 示例 |
|
||||
|--------|------|------|--------|------|
|
||||
| `price_id` | string | 价格唯一ID(为空时自动生成) | `null` | `"2008067775216672769"` |
|
||||
| `pntree_name` | string | 分类名称 | `"钢筋"` | `"钢筋"` |
|
||||
| `make_price` | number | 钢厂价(元/吨) | `null` | `3800` |
|
||||
| `last_make_price` | number | 上次钢厂价 | `null` | `3750` |
|
||||
| `last_hang_price` | number | 上次挂牌价 | `null` | `3800` |
|
||||
| `make_price_updw` | string | 钢厂价涨跌 | `null` | `"↑50"` |
|
||||
| `hang_price_updw` | string | 挂牌价涨跌 | `null` | `"↑50"` |
|
||||
| `operator_code` | string | 操作员代码 | `null` | `"OP001"` |
|
||||
| `operator_name` | string | 操作员名称 | `null` | `"张三"` |
|
||||
|
||||
#### 自动生成字段
|
||||
|
||||
以下字段由系统自动生成,无需传入:
|
||||
|
||||
- `id` - 自增主键
|
||||
- `created_at` - 创建时间
|
||||
- `updated_at` - 更新时间
|
||||
|
||||
### price_id 自动生成规则
|
||||
|
||||
如果传入的数据中 `price_id` 为空或不存在,系统会基于以下字段生成 MD5 哈希值:
|
||||
|
||||
```
|
||||
{goods_material}-{goods_spec}-{price_region}-{price_source}-{price_date}
|
||||
```
|
||||
|
||||
**示例:**
|
||||
```
|
||||
HPB300-Φ8-昆明-我的钢铁-2026-01-05T10:30:00.000Z
|
||||
↓ MD5 哈希
|
||||
a1b2c3d4e5f6...(32 位十六进制字符串)
|
||||
```
|
||||
|
||||
这样可以确保相同业务数据不会重复插入。
|
||||
|
||||
### 响应格式
|
||||
|
||||
#### 成功响应
|
||||
|
||||
**HTTP Status:** `200 OK`
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "成功导入 100 条数据",
|
||||
"data": {
|
||||
"imported": 100,
|
||||
"total": 105,
|
||||
"validCount": 100,
|
||||
"errorCount": 5,
|
||||
"errors": [
|
||||
{
|
||||
"index": 3,
|
||||
"data": { ... },
|
||||
"reasons": {
|
||||
"missing": ["hang_price"],
|
||||
"invalid": [
|
||||
{ "field": "price_date", "expected": "valid Date", "received": "invalid-date" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 失败响应
|
||||
|
||||
**HTTP Status:** `200 OK` (业务失败)
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "没有有效的数据可以导入",
|
||||
"data": {
|
||||
"total": 10,
|
||||
"imported": 0,
|
||||
"errors": [
|
||||
{
|
||||
"index": 0,
|
||||
"data": { ... },
|
||||
"reasons": {
|
||||
"missing": ["goods_material", "hang_price"],
|
||||
"invalid": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 服务器错误
|
||||
|
||||
**HTTP Status:** `500 Internal Server Error`
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "数据库连接失败"
|
||||
}
|
||||
```
|
||||
|
||||
### 数据验证规则
|
||||
|
||||
#### 必填字段验证
|
||||
|
||||
- 所有必填字段不能为空、null 或 undefined
|
||||
- 字符串字段长度不能为 0
|
||||
|
||||
#### 数据类型验证
|
||||
|
||||
| 字段 | 允许的类型 | 验证规则 |
|
||||
|------|-----------|----------|
|
||||
| `hang_price` | `number` | 必须是有效数字,不能为 NaN |
|
||||
| `make_price` | `number` \| `null` | 如果存在,必须是有效数字 |
|
||||
| `last_make_price` | `number` \| `null` | 如果存在,必须是有效数字 |
|
||||
| `last_hang_price` | `number` \| `null` | 如果存在,必须是有效数字 |
|
||||
| `price_date` | `string` \| `Date` | 必须是有效的日期格式 |
|
||||
|
||||
### 错误处理
|
||||
|
||||
#### 数据格式错误
|
||||
|
||||
如果传入的数据不符合格式要求:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"message": "无效的数据格式",
|
||||
"error": "数据必须是数组格式"
|
||||
}
|
||||
```
|
||||
|
||||
#### 缺少必填字段
|
||||
|
||||
如果某条记录缺少必填字段,该记录会被跳过,错误信息会返回在响应中:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "成功导入 95 条数据,5 条数据因格式错误被跳过",
|
||||
"data": {
|
||||
"imported": 95,
|
||||
"total": 100,
|
||||
"validCount": 95,
|
||||
"errorCount": 5,
|
||||
"errors": [
|
||||
{
|
||||
"index": 10,
|
||||
"data": { "goods_material": "HPB300" },
|
||||
"reasons": {
|
||||
"missing": ["goods_spec", "hang_price", "price_date"],
|
||||
"invalid": []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 使用示例
|
||||
|
||||
#### JavaScript (Fetch API)
|
||||
|
||||
```javascript
|
||||
const response = await fetch('http://localhost:3000/api/prices/import', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
prices: [
|
||||
{
|
||||
goods_material: 'HPB300',
|
||||
goods_spec: 'Φ8',
|
||||
partsname_name: '螺纹钢',
|
||||
productarea_name: '昆钢',
|
||||
price_source: '我的钢铁',
|
||||
price_region: '昆明',
|
||||
price_date: '2026-01-05T10:30:00.000Z',
|
||||
hang_price: 3850
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
console.log(result);
|
||||
```
|
||||
|
||||
#### cURL
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/prices/import \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"prices": [
|
||||
{
|
||||
"goods_material": "HPB300",
|
||||
"goods_spec": "Φ8",
|
||||
"partsname_name": "螺纹钢",
|
||||
"productarea_name": "昆钢",
|
||||
"price_source": "我的钢铁",
|
||||
"price_region": "昆明",
|
||||
"price_date": "2026-01-05T10:30:00.000Z",
|
||||
"hang_price": 3850
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **批量限制**:建议单次导入不超过 1000 条记录
|
||||
2. **重复数据处理**:使用 `ON DUPLICATE KEY UPDATE` 机制自动更新已存在的记录
|
||||
3. **事务处理**:每次批量插入是一个事务,失败会回滚
|
||||
4. **错误详情**:响应中最多返回前 10 个错误详情
|
||||
5. **price_id 唯一性**:系统会自动确保 price_id 的唯一性,无需手动处理
|
||||
|
||||
### 完整字段对照表
|
||||
|
||||
| 数据库字段 | JSON 字段 | 必填 | 类型 | 说明 |
|
||||
|-----------|-----------|------|------|------|
|
||||
| `price_id` | `price_id` | ❌ | string | 价格唯一ID |
|
||||
| `goods_material` | `goods_material` | ✅ | string | 材质牌号 |
|
||||
| `goods_spec` | `goods_spec` | ✅ | string | 规格型号 |
|
||||
| `partsname_name` | `partsname_name` | ✅ | string | 品名 |
|
||||
| `productarea_name` | `productarea_name` | ✅ | string | 产地/钢厂 |
|
||||
| `price_source` | `price_source` | ✅ | string | 价格来源 |
|
||||
| `price_region` | `price_region` | ✅ | string | 价格地区 |
|
||||
| `pntree_name` | `pntree_name` | ❌ | string | 分类名称 |
|
||||
| `price_date` | `price_date` | ✅ | string | 价格日期 |
|
||||
| `make_price` | `make_price` | ❌ | number | 钢厂价 |
|
||||
| `hang_price` | `hang_price` | ✅ | number | 挂牌价 |
|
||||
| `last_make_price` | `last_make_price` | ❌ | number | 上次钢厂价 |
|
||||
| `last_hang_price` | `last_hang_price` | ❌ | number | 上次挂牌价 |
|
||||
| `make_price_updw` | `make_price_updw` | ❌ | string | 钢厂价涨跌 |
|
||||
| `hang_price_updw` | `hang_price_updw` | ❌ | string | 挂牌价涨跌 |
|
||||
| `operator_code` | `operator_code` | ❌ | string | 操作员代码 |
|
||||
| `operator_name` | `operator_name` | ❌ | string | 操作员名称 |
|
||||
| `created_at` | - | - | - | 自动生成 |
|
||||
| `updated_at` | - | - | - | 自动生成 |
|
||||
Reference in New Issue
Block a user