Files
steel_prices_service/docs/DATA_SOURCE_IDENTIFICATION.md
2026-01-06 18:00:43 +08:00

354 lines
11 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.

# 数据源标识系统说明
## 概述
为了清晰区分来自三个不同接口的数据,我们为每个数据源添加了明确的标识字段。这样可以:
1. **清晰区分数据来源** - 知道数据来自哪个接口
2. **便于数据筛选** - 按数据源查询和统计
3. **数据溯源** - 追踪数据的采集方式(本地文件或 API
4. **避免数据混淆** - 即使数据相似也能区分来源
## 数据源配置
### 三个接口的标识
| 接口端点 | 数据来源 | 标识码 | 颜色标签 | 描述 |
|---------|---------|--------|---------|------|
| `DEFAULT` | 云南钢协 | `YUNNAN_STEEL_ASSOC` | 🔴 #FF6B6B | 云南钢协指导价API |
| `BACKUP` | 我的钢铁 | `MY_STEEL` | 🔵 #4ECDC4 | 我的钢铁网价格API |
| `EXTENDED` | 德钢指导价 | `DE_STEEL_FACTORY` | 🟢 #95E1D3 | 德钢钢厂指导价API |
### 本地文件映射
| 文件名 | 数据来源 | 标识码 | 颜色标签 | 描述 |
|-------|---------|--------|---------|------|
| `刚协指导价.json` | 云南钢协 | `YUNNAN_STEEL_ASSOC` | 🔴 #FF6B6B | 云南钢协指导价 |
| `钢材网架.json` | 我的钢铁 | `MY_STEEL` | 🔵 #4ECDC4 | 我的钢铁网价格 |
| `钢厂指导价.json` | 德钢指导价 | `DE_STEEL_FACTORY` | 🟢 #95E1D3 | 德钢钢厂指导价 |
## 数据库字段说明
### 新增字段
```sql
-- 数据源代码(唯一标识)
price_source_code VARCHAR(32) NOT NULL
-- 可能的值: 'YUNNAN_STEEL_ASSOC', 'MY_STEEL', 'DE_STEEL_FACTORY'
-- 数据源描述
price_source_desc VARCHAR(64) NOT NULL
-- 例如: '云南钢协指导价API', '我的钢铁网价格API'
-- 数据来源标识
data_origin VARCHAR(32) NOT NULL
-- 格式:
-- - 'LOCAL_FILE' - 从本地文件导入
-- - 'API:DEFAULT' - 从 DEFAULT 接口导入
-- - 'API:BACKUP' - 从 BACKUP 接口导入
-- - 'API:EXTENDED' - 从 EXTENDED 接口导入
```
### 完整表结构
```sql
CREATE TABLE prices (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
price_id VARCHAR(64) UNIQUE NOT NULL,
goods_material VARCHAR(32) NOT NULL,
goods_spec VARCHAR(16) NOT NULL,
partsname_name VARCHAR(32) NOT NULL,
productarea_name VARCHAR(64) NOT NULL,
-- 数据源标识字段
price_source VARCHAR(32) NOT NULL, -- 原有字段:价格来源名称
price_source_code VARCHAR(32) NOT NULL, -- 新增:数据源代码
price_source_desc VARCHAR(64) NOT NULL, -- 新增:数据源描述
data_origin VARCHAR(32) NOT NULL, -- 新增:数据来源标识
price_region VARCHAR(32) NOT NULL,
pntree_name VARCHAR(32) NOT NULL,
price_date DATETIME NOT NULL,
make_price INT DEFAULT NULL,
hang_price INT NOT NULL,
last_make_price INT DEFAULT NULL,
last_hang_price INT DEFAULT NULL,
make_price_updw VARCHAR(8) DEFAULT NULL,
hang_price_updw VARCHAR(8) DEFAULT NULL,
operator_code VARCHAR(16) DEFAULT NULL,
operator_name VARCHAR(32) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- 索引
INDEX idx_price_date (price_date),
INDEX idx_region_material (price_region, goods_material),
INDEX idx_source_date (price_source, price_date),
INDEX idx_source_code (price_source_code), -- 新增:按数据源代码查询
INDEX idx_data_origin (data_origin), -- 新增:按数据来源查询
INDEX idx_goods_spec (goods_spec)
);
```
## 使用示例
### 1. 数据库迁移(为现有表添加新字段)
```bash
npm run db:migrate
```
**输出示例:**
```
🔄 开始数据库迁移:添加数据源标识字段
✅ 数据源字段迁移成功
============================================================
✅ 数据库迁移完成!
============================================================
📊 新增字段说明:
- price_source_code: 数据源代码YUNNAN_STEEL_ASSOC / MY_STEEL / DE_STEEL_FACTORY
- price_source_desc: 数据源描述
- data_origin: 数据来源标识LOCAL_FILE 或 API:ENDPOINT
🎨 数据源标识:
🔴 YUNNAN_STEEL_ASSOC - 云南钢协指导价DEFAULT 接口)
🔵 MY_STEEL - 我的钢铁网价格BACKUP 接口)
🟢 DE_STEEL_FACTORY - 德钢钢厂指导价EXTENDED 接口)
```
### 2. 从 API 接口导入数据(带标识)
```bash
# 导入云南钢协数据DEFAULT 接口)
node scripts/import-data.js single-api DEFAULT
# 导入我的钢铁数据BACKUP 接口)
node scripts/import-data.js single-api BACKUP
# 导入德钢指导价数据EXTENDED 接口)
node scripts/import-data.js single-api EXTENDED
# 从所有 API 接口导入
npm run db:import:api
```
**导入过程示例:**
```
🌐 正在从 API 接口获取数据: DEFAULT
📊 数据源: 云南钢协指导价API
🏷️ 标识码: YUNNAN_STEEL_ASSOC
🎨 标签: #FF6B6B
📅 查询参数: {
"startDate": "2025-01-06",
"endDate": "2026-01-06",
"page": 1,
"pageSize": 100000
}
🔐 正在获取 Token...
✅ Token 获取成功
🔄 切换到接口: 默认钢材价格查询
Page ID: PG-D615-D8E2-2FD84B8D
Menu ID: MK-A8B8-109E-13D34116
✅ 解析到 1250 条有效数据
进度: 1000/1250 条
进度: 1250/1250 条
✅ 成功导入 1250 条数据
```
### 3. 从本地文件导入数据(带标识)
```bash
# 从本地文件导入
npm run db:import:local
```
**导入过程示例:**
```
📄 正在读取本地文件: 刚协指导价.json
📊 数据源: 云南钢协指导价
🏷️ 标识码: YUNNAN_STEEL_ASSOC
🎨 标签: #FF6B6B
✅ 解析到 900 条有效数据
进度: 900/900 条
✅ 成功导入 900 条数据
```
## 数据查询示例
### SQL 查询
#### 1. 查询所有数据源统计
```sql
SELECT
price_source_code AS '数据源代码',
price_source_desc AS '数据源描述',
data_origin AS '数据来源',
COUNT(*) AS '记录数',
AVG(hang_price) AS '平均价格',
MIN(hang_price) AS '最低价格',
MAX(hang_price) AS '最高价格'
FROM prices
GROUP BY price_source_code, price_source_desc, data_origin
ORDER BY price_source_code;
```
**结果示例:**
```
+---------------------+----------------------+----------------+----------+----------+----------+----------+
| 数据源代码 | 数据源描述 | 数据来源 | 记录数 | 平均价格 | 最低价格 | 最高价格 |
+---------------------+----------------------+----------------+----------+----------+----------+----------+
| YUNNAN_STEEL_ASSOC | 云南钢协指导价API | API:DEFAULT | 1250 | 4500.50 | 3800 | 5200 |
| YUNNAN_STEEL_ASSOC | 云南钢协指导价 | LOCAL_FILE | 900 | 4480.30 | 3850 | 5180 |
| MY_STEEL | 我的钢铁网价格API | API:BACKUP | 850 | 4420.80 | 3700 | 5150 |
| MY_STEEL | 我的钢铁网价格 | LOCAL_FILE | 211 | 4400.60 | 3750 | 5120 |
| DE_STEEL_FACTORY | 德钢钢厂指导价API| API:EXTENDED | 15000 | 4550.20 | 3900 | 5300 |
| DE_STEEL_FACTORY | 德钢钢厂指导价 | LOCAL_FILE | 29987 | 4530.90 | 3880 | 5280 |
+---------------------+----------------------+----------------+----------+----------+----------+----------+
```
#### 2. 按数据源筛选
```sql
-- 查询云南钢协的数据
SELECT * FROM prices
WHERE price_source_code = 'YUNNAN_STEEL_ASSOC'
ORDER BY price_date DESC;
-- 查询从 API 导入的数据
SELECT * FROM prices
WHERE data_origin LIKE 'API:%'
ORDER BY price_date DESC;
-- 查询特定接口的数据
SELECT * FROM prices
WHERE data_origin = 'API:DEFAULT'
ORDER BY price_date DESC;
```
#### 3. 对比不同数据源的价格
```sql
SELECT
DATE(price_date) AS '日期',
price_source_code AS '数据源',
AVG(hang_price) AS '平均价格'
FROM prices
WHERE DATE(price_date) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY DATE(price_date), price_source_code
ORDER BY DATE(price_date), price_source_code;
```
### Node.js 查询
```javascript
// 查询特定数据源的数据
const yunnanSteelPrices = await Price.search({
material: 'HRB400E',
startDate: '2025-01-01',
endDate: '2025-01-31'
});
// 过滤云南钢协数据
const filtered = yunnanSteelPrices.filter(item =>
item.price_source_code === 'YUNNAN_STEEL_ASSOC'
);
// 按数据源分组统计
const statsBySource = await Price.getStats({
/* 可以扩展 getStats 方法支持按数据源统计 */
});
```
## API 接口返回数据格式
导入数据时,每条记录将包含以下标识字段:
```json
{
"price_id": "abc123...",
"goods_material": "HRB400E",
"goods_spec": "Φ18",
"partsname_name": "螺纹钢",
"productarea_name": "云南德胜",
"price_source": "云南钢协",
"price_source_code": "YUNNAN_STEEL_ASSOC", // 数据源代码
"price_source_desc": "云南钢协指导价API", // 数据源描述
"data_origin": "API:DEFAULT", // 数据来源标识
"price_region": "昆明",
"pntree_name": "钢筋",
"price_date": "2025-01-06 00:00:00",
"make_price": 4450,
"hang_price": 4500,
"last_make_price": 4400,
"last_hang_price": 4450,
"make_price_updw": "+50",
"hang_price_updw": "+50"
}
```
## 颜色标签使用建议
这些颜色标签可以在前端界面中使用,帮助用户直观区分数据来源:
```javascript
const SOURCE_COLORS = {
YUNNAN_STEEL_ASSOC: '#FF6B6B', // 红色 - 云南钢协
MY_STEEL: '#4ECDC4', // 蓝绿色 - 我的钢铁
DE_STEEL_FACTORY: '#95E1D3' // 绿色 - 德钢指导价
};
// 在 React/Vue 等前端框架中使用
<div style={{ color: SOURCE_COLORS[item.price_source_code] }}>
{item.price_source_desc}
</div>
```
## 注意事项
1. **唯一性**: `price_source_code` 是数据源的唯一标识,建议在业务逻辑中使用
2. **兼容性**: 原有的 `price_source` 字段保留,用于显示中文名称
3. **索引优化**: 已为 `price_source_code``data_origin` 添加索引,查询性能更好
4. **数据迁移**: 如果已有数据,运行迁移脚本会自动添加新字段并设置默认值
## 故障排查
### 问题 1: 迁移后新字段为空
**原因**: 旧数据没有标识字段信息
**解决方案**:
```sql
-- 更新旧数据的标识字段
UPDATE prices SET
price_source_code = CASE
WHEN price_source = '云南钢协' THEN 'YUNNAN_STEEL_ASSOC'
WHEN price_source = '我的钢铁' THEN 'MY_STEEL'
WHEN price_source = '德钢指导价' THEN 'DE_STEEL_FACTORY'
ELSE 'UNKNOWN'
END,
price_source_desc = price_source,
data_origin = 'LOCAL_FILE'
WHERE data_origin = '' OR data_origin IS NULL;
```
### 问题 2: 导入数据时字段未填充
**原因**: 导入脚本版本过旧
**解决方案**:
```bash
# 确保使用最新的 import-data.js
git pull origin main
npm run db:import:api
```
## 相关文档
- [导入脚本使用说明](../scripts/README-IMPORT.md)
- [API 接口文档](../docs/IMPORT_API.md)
- [数据库设计文档](../docs/DATABASE_SCHEMA.md)