修改文件结构,统一文档格式
This commit is contained in:
@@ -1,122 +0,0 @@
|
||||
# 经纬度数据同步问题修复报告
|
||||
|
||||
## 问题描述
|
||||
|
||||
用户反馈经纬度输入框的值与数据库存储的值不一致,存在数据不同步的问题。
|
||||
|
||||
## 问题分析
|
||||
|
||||
通过深入调查,发现问题的根本原因是:
|
||||
|
||||
### 1. 数据库存储格式问题
|
||||
- **问题**: 数据库中的 `location` 字段被存储为 JSON 字符串而不是 JSON 对象
|
||||
- **表现**: `location` 字段值为 `"{\"lat\":38.47,\"lng\":106.28}"` (字符串格式)
|
||||
- **期望**: `location` 字段值应为 `{"lat":38.47,"lng":106.28}` (对象格式)
|
||||
|
||||
### 2. 前端解析问题
|
||||
- 当 `location` 字段为字符串时,前端无法正确解析 `lng` 和 `lat` 属性
|
||||
- 导致编辑表单中经纬度输入框显示为空
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 1. 数据库格式修复
|
||||
|
||||
创建并运行了 `fix-location-data.js` 脚本:
|
||||
|
||||
```javascript
|
||||
// 将JSON字符串转换为JSON对象
|
||||
if (typeof farm.location === 'string') {
|
||||
newLocation = JSON.parse(farm.location);
|
||||
await farm.update({ location: newLocation });
|
||||
}
|
||||
```
|
||||
|
||||
**修复结果**:
|
||||
- 总记录数: 12
|
||||
- 修复成功: 11
|
||||
- 修复失败: 0
|
||||
- 无需修复: 1
|
||||
|
||||
### 2. 代码验证
|
||||
|
||||
#### 后端代码检查
|
||||
- ✅ `Farm` 模型定义正确 (`DataTypes.JSON`)
|
||||
- ✅ `createFarm` 函数正确处理经纬度数据
|
||||
- ✅ `updateFarm` 函数正确构建 location 对象
|
||||
|
||||
#### 前端代码检查
|
||||
- ✅ `editFarm` 函数正确解析 `record.location?.lng` 和 `record.location?.lat`
|
||||
- ✅ 表单验证规则完整
|
||||
- ✅ `handleSubmit` 函数正确提交数据
|
||||
|
||||
## 测试验证
|
||||
|
||||
### 1. 数据格式验证
|
||||
|
||||
修复前:
|
||||
```
|
||||
Location对象: "{\"lat\":38.4872,\"lng\":106.2309}"
|
||||
❌ Location字段为空或格式错误
|
||||
```
|
||||
|
||||
修复后:
|
||||
```
|
||||
Location对象: {"lat":38.4872,"lng":106.2309}
|
||||
经度 (lng): 106.2309 (类型: number)
|
||||
纬度 (lat): 38.4872 (类型: number)
|
||||
✅ 有经纬度数据
|
||||
```
|
||||
|
||||
### 2. 数据同步测试
|
||||
|
||||
运行 `test-data-sync.js` 验证完整流程:
|
||||
|
||||
```
|
||||
=== 测试结果 ===
|
||||
✅ 创建记录成功
|
||||
✅ 查询验证通过
|
||||
✅ API响应格式正确
|
||||
✅ 前端数据解析正确
|
||||
✅ 更新操作成功
|
||||
✅ 数据一致性检查通过
|
||||
结果: 数据同步正常
|
||||
```
|
||||
|
||||
## 修复效果
|
||||
|
||||
### 修复前
|
||||
- 数据库中 location 字段为 JSON 字符串
|
||||
- 前端无法正确解析经纬度数据
|
||||
- 编辑表单中经纬度输入框显示为空
|
||||
- 用户输入的值与数据库存储值不一致
|
||||
|
||||
### 修复后
|
||||
- 数据库中 location 字段为 JSON 对象
|
||||
- 前端正确解析并显示经纬度数据
|
||||
- 编辑表单正确回显经纬度值
|
||||
- 用户输入值与数据库存储值完全一致
|
||||
|
||||
## 预防措施
|
||||
|
||||
### 1. 数据验证
|
||||
- 在 `createFarm` 和 `updateFarm` 函数中确保 location 对象格式正确
|
||||
- 添加数据类型检查,确保经纬度为数值类型
|
||||
|
||||
### 2. 前端处理
|
||||
- 在 `editFarm` 函数中添加容错处理
|
||||
- 确保 location 对象解析的健壮性
|
||||
|
||||
### 3. 测试覆盖
|
||||
- 定期运行数据一致性检查
|
||||
- 在部署前验证经纬度数据的完整流程
|
||||
|
||||
## 总结
|
||||
|
||||
经纬度数据同步问题已完全解决:
|
||||
|
||||
1. **根本原因**: 数据库中 location 字段存储格式错误(JSON字符串 vs JSON对象)
|
||||
2. **解决方案**: 运行数据修复脚本,将所有记录的 location 字段转换为正确的 JSON 对象格式
|
||||
3. **验证结果**: 所有测试通过,数据同步正常
|
||||
4. **预防措施**: 建立了完整的测试和验证机制
|
||||
|
||||
现在用户在前端编辑养殖场时,经纬度输入框会正确显示数据库中存储的值,实现了完全的数据同步。
|
||||
@@ -1,116 +0,0 @@
|
||||
# Farms静态数据导入总结
|
||||
|
||||
## 概述
|
||||
成功将后端API中的farms静态数据导入到数据库的farms表中。
|
||||
|
||||
## 数据来源
|
||||
|
||||
### 1. API静态数据
|
||||
来源:`routes/farms.js` 中的 `/public` 路由
|
||||
- 宁夏农场1 (银川市)
|
||||
- 宁夏农场2 (石嘴山市)
|
||||
- 宁夏农场3 (吴忠市)
|
||||
|
||||
### 2. 种子数据
|
||||
来源:`seeds/20230102000000_farm_data.js` 和 `seeds/20230103000000_extended_data.js`
|
||||
- 阳光农场 (养猪场)
|
||||
- 绿野牧场 (养牛场)
|
||||
- 山谷羊场 (养羊场)
|
||||
- 蓝天养鸡场 (养鸡场)
|
||||
- 金山养鸭场 (养鸭场)
|
||||
- 银河渔场 (渔场)
|
||||
- 星空牧场 (综合养殖场)
|
||||
- 彩虹农庄 (有机农场)
|
||||
|
||||
## 导入过程
|
||||
|
||||
### 1. 创建导入脚本
|
||||
文件:`import-farms-static-data.js`
|
||||
- 合并API静态数据和种子数据
|
||||
- 使用事务确保数据一致性
|
||||
- 清空现有数据并重置自增ID
|
||||
- 批量插入新数据
|
||||
|
||||
### 2. 执行导入
|
||||
```bash
|
||||
node import-farms-static-data.js
|
||||
```
|
||||
|
||||
### 3. 验证导入结果
|
||||
文件:`verify-farms-import.js`
|
||||
- 数据完整性检查
|
||||
- ID序列连续性验证
|
||||
- 地理位置数据验证
|
||||
- 农场类型统计
|
||||
|
||||
## 导入结果
|
||||
|
||||
### 数据统计
|
||||
- **总计**:11个农场
|
||||
- **ID范围**:1-11(连续)
|
||||
- **数据完整性**:✅ 所有字段完整
|
||||
- **地理位置**:✅ 所有位置数据有效
|
||||
|
||||
### 农场类型分布
|
||||
| 类型 | 数量 |
|
||||
|------|------|
|
||||
| 综合农场 | 3个 |
|
||||
| 养猪场 | 1个 |
|
||||
| 养牛场 | 1个 |
|
||||
| 养羊场 | 1个 |
|
||||
| 养鸡场 | 1个 |
|
||||
| 养鸭场 | 1个 |
|
||||
| 渔场 | 1个 |
|
||||
| 综合养殖场 | 1个 |
|
||||
| 有机农场 | 1个 |
|
||||
|
||||
### API验证
|
||||
- `/api/farms/public` ✅ 返回正确的静态数据
|
||||
- `/api/farms` ✅ 返回完整的数据库数据
|
||||
|
||||
## 数据结构
|
||||
|
||||
每个农场记录包含以下字段:
|
||||
- `id`: 主键,自增
|
||||
- `name`: 农场名称
|
||||
- `type`: 农场类型
|
||||
- `location`: 地理位置(JSON格式,包含lat和lng)
|
||||
- `address`: 详细地址
|
||||
- `contact`: 联系人
|
||||
- `phone`: 联系电话
|
||||
- `status`: 状态(active/inactive/maintenance)
|
||||
- `created_at`: 创建时间
|
||||
- `updated_at`: 更新时间
|
||||
|
||||
## 相关文件
|
||||
|
||||
### 创建的文件
|
||||
- `import-farms-static-data.js` - 数据导入脚本
|
||||
- `verify-farms-import.js` - 数据验证脚本
|
||||
- `farms-data-import-summary.md` - 本总结文档
|
||||
|
||||
### 涉及的现有文件
|
||||
- `routes/farms.js` - API路由定义
|
||||
- `models/Farm.js` - 数据模型定义
|
||||
- `controllers/farmController.js` - 控制器逻辑
|
||||
- `seeds/20230102000000_farm_data.js` - 种子数据
|
||||
- `seeds/20230103000000_extended_data.js` - 扩展种子数据
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据库连接警告**:执行过程中出现循环依赖警告,但不影响功能
|
||||
2. **事务安全**:使用数据库事务确保数据导入的原子性
|
||||
3. **ID重置**:导入前重置了自增ID,确保从1开始
|
||||
4. **数据覆盖**:导入过程会清空现有farms数据
|
||||
|
||||
## 后续建议
|
||||
|
||||
1. 定期备份farms数据
|
||||
2. 考虑添加数据迁移脚本
|
||||
3. 优化循环依赖问题
|
||||
4. 添加更多数据验证规则
|
||||
|
||||
---
|
||||
|
||||
**导入完成时间**:2025-08-21
|
||||
**状态**:✅ 成功完成
|
||||
@@ -1,256 +0,0 @@
|
||||
# 经纬度数据传递验证报告
|
||||
|
||||
## 概述
|
||||
|
||||
本报告详细验证了经纬度输入值从前端表单到数据库操作层的完整传递流程,确保location字段的更新逻辑被正确执行,并验证查询绑定的值与数据库中的实际值一致。
|
||||
|
||||
## 验证范围
|
||||
|
||||
### 1. 前端数据处理
|
||||
- ✅ 经纬度输入框配置正确
|
||||
- ✅ 表单验证规则完善
|
||||
- ✅ 数据提交格式正确
|
||||
|
||||
### 2. 后端API处理
|
||||
- ✅ 创建养殖场时经纬度处理
|
||||
- ✅ 更新养殖场时经纬度处理(已修复)
|
||||
- ✅ 空值和边界值处理
|
||||
|
||||
### 3. 数据库存储
|
||||
- ✅ JSON字段存储格式正确
|
||||
- ✅ 数据类型保持一致
|
||||
- ✅ 精度保持完整
|
||||
|
||||
## 详细验证结果
|
||||
|
||||
### 前端组件配置
|
||||
|
||||
**经度输入框配置:**
|
||||
```vue
|
||||
<a-input-number
|
||||
v-model:value="formData.longitude"
|
||||
:min="-180"
|
||||
:max="180"
|
||||
:precision="6"
|
||||
:step="0.000001"
|
||||
:string-mode="false"
|
||||
:controls="false"
|
||||
placeholder="请输入经度 (-180 ~ 180)"
|
||||
:parser="(value) => {
|
||||
if (typeof value === 'string') {
|
||||
const num = parseFloat(value.replace(/[^\d.-]/g, ''));
|
||||
return isNaN(num) ? undefined : num;
|
||||
}
|
||||
return value;
|
||||
}"
|
||||
:formatter="(value) => value ? value.toString() : ''"
|
||||
/>
|
||||
```
|
||||
|
||||
**纬度输入框配置:**
|
||||
```vue
|
||||
<a-input-number
|
||||
v-model:value="formData.latitude"
|
||||
:min="-90"
|
||||
:max="90"
|
||||
:precision="6"
|
||||
:step="0.000001"
|
||||
:string-mode="false"
|
||||
:controls="false"
|
||||
placeholder="请输入纬度 (-90 ~ 90)"
|
||||
:parser="(value) => {
|
||||
if (typeof value === 'string') {
|
||||
const num = parseFloat(value.replace(/[^\d.-]/g, ''));
|
||||
return isNaN(num) ? undefined : num;
|
||||
}
|
||||
return value;
|
||||
}"
|
||||
:formatter="(value) => value ? value.toString() : ''"
|
||||
/>
|
||||
```
|
||||
|
||||
### 表单验证规则
|
||||
|
||||
**经度验证:**
|
||||
- ✅ 允许为空值
|
||||
- ✅ 数值有效性检查
|
||||
- ✅ 范围验证(-180 到 180)
|
||||
- ✅ 精度限制(最多6位小数)
|
||||
|
||||
**纬度验证:**
|
||||
- ✅ 允许为空值
|
||||
- ✅ 数值有效性检查
|
||||
- ✅ 范围验证(-90 到 90)
|
||||
- ✅ 精度限制(最多6位小数)
|
||||
|
||||
### 后端API处理
|
||||
|
||||
**创建养殖场(createFarm):**
|
||||
```javascript
|
||||
// 构建location对象
|
||||
const location = {};
|
||||
if (longitude !== undefined && longitude !== null) {
|
||||
location.lng = parseFloat(longitude);
|
||||
}
|
||||
if (latitude !== undefined && latitude !== null) {
|
||||
location.lat = parseFloat(latitude);
|
||||
}
|
||||
|
||||
const farm = await Farm.create({
|
||||
name,
|
||||
type: 'farm',
|
||||
location,
|
||||
address,
|
||||
contact: owner,
|
||||
phone,
|
||||
status: status || 'active'
|
||||
});
|
||||
```
|
||||
|
||||
**更新养殖场(updateFarm):**
|
||||
```javascript
|
||||
// 构建location对象 - 创建新对象以确保Sequelize检测到变化
|
||||
const location = { ...(farm.location || {}) };
|
||||
if (longitude !== undefined && longitude !== null) {
|
||||
location.lng = parseFloat(longitude);
|
||||
}
|
||||
if (latitude !== undefined && latitude !== null) {
|
||||
location.lat = parseFloat(latitude);
|
||||
}
|
||||
|
||||
await farm.update({
|
||||
name,
|
||||
type: farm.type || 'farm',
|
||||
location,
|
||||
address,
|
||||
contact: owner,
|
||||
phone,
|
||||
status: status || 'active'
|
||||
});
|
||||
```
|
||||
|
||||
### 数据库模型定义
|
||||
|
||||
```javascript
|
||||
location: {
|
||||
type: DataTypes.JSON,
|
||||
allowNull: false,
|
||||
defaultValue: {}
|
||||
}
|
||||
```
|
||||
|
||||
## 测试结果
|
||||
|
||||
### 基础功能测试
|
||||
|
||||
| 测试项目 | 输入值 | 期望结果 | 实际结果 | 状态 |
|
||||
|---------|--------|----------|----------|------|
|
||||
| 创建记录 | lng: 106.123456, lat: 38.654321 | 正确存储 | ✅ 正确存储 | 通过 |
|
||||
| 更新记录 | lng: 107.987654, lat: 39.123456 | 正确更新 | ✅ 正确更新 | 通过 |
|
||||
| 部分更新 | 仅更新经度 | 经度更新,纬度保持 | ✅ 符合期望 | 通过 |
|
||||
| 清空坐标 | 空对象 | location为空对象 | ✅ 符合期望 | 通过 |
|
||||
|
||||
### 边界值测试
|
||||
|
||||
| 测试项目 | 输入值 | 存储值 | 精度保持 | 状态 |
|
||||
|---------|--------|--------|----------|------|
|
||||
| 最小边界值 | lng: -180, lat: -90 | lng: -180, lat: -90 | ✅ | 通过 |
|
||||
| 最大边界值 | lng: 180, lat: 90 | lng: 180, lat: 90 | ✅ | 通过 |
|
||||
| 零值 | lng: 0, lat: 0 | lng: 0, lat: 0 | ✅ | 通过 |
|
||||
| 高精度值 | lng: 106.123456789, lat: 38.987654321 | lng: 106.123456789, lat: 38.987654321 | ✅ | 通过 |
|
||||
|
||||
### 空值处理测试
|
||||
|
||||
| 测试项目 | 输入值 | 处理结果 | 状态 |
|
||||
|---------|--------|----------|------|
|
||||
| undefined值 | longitude: undefined, latitude: undefined | location: {} | ✅ 通过 |
|
||||
| null值 | longitude: null, latitude: null | location: {} | ✅ 通过 |
|
||||
| 空字符串 | longitude: '', latitude: '' | location: {} | ✅ 通过 |
|
||||
| 仅经度有值 | longitude: 106.123, latitude: undefined | location: {lng: 106.123} | ✅ 通过 |
|
||||
| 仅纬度有值 | longitude: undefined, latitude: 38.456 | location: {lat: 38.456} | ✅ 通过 |
|
||||
|
||||
### API流程测试
|
||||
|
||||
| 操作 | 输入经纬度 | 存储结果 | 状态 |
|
||||
|------|------------|----------|------|
|
||||
| 创建 | lng: 106.789123, lat: 38.456789 | ✅ 正确存储 | 通过 |
|
||||
| 更新 | lng: 107.111222, lat: 39.333444 | ✅ 正确更新 | 通过 |
|
||||
|
||||
## 发现的问题及修复
|
||||
|
||||
### 问题1:更新操作中经纬度值未正确保存
|
||||
|
||||
**问题描述:**
|
||||
在更新养殖场时,新的经纬度值没有被正确保存到数据库中。
|
||||
|
||||
**原因分析:**
|
||||
原代码直接修改了原有的location对象引用:
|
||||
```javascript
|
||||
const location = farm.location || {};
|
||||
```
|
||||
Sequelize可能没有检测到这个对象的变化,因为它是同一个引用。
|
||||
|
||||
**修复方案:**
|
||||
创建一个新的location对象来确保Sequelize检测到变化:
|
||||
```javascript
|
||||
const location = { ...(farm.location || {}) };
|
||||
```
|
||||
|
||||
**修复验证:**
|
||||
- ✅ 更新操作现在能正确保存新的经纬度值
|
||||
- ✅ 部分更新功能正常工作
|
||||
- ✅ 不影响其他字段的更新
|
||||
|
||||
## 数据流验证
|
||||
|
||||
### 完整数据流路径
|
||||
|
||||
1. **前端输入** → 用户在经纬度输入框中输入数值
|
||||
2. **前端验证** → 表单验证规则检查数值有效性和范围
|
||||
3. **前端提交** → 通过API发送JSON数据到后端
|
||||
4. **后端接收** → 控制器从req.body中提取longitude和latitude
|
||||
5. **后端处理** → 使用parseFloat转换并构建location对象
|
||||
6. **数据库存储** → Sequelize将location对象存储为JSON格式
|
||||
7. **数据库查询** → 查询时返回完整的location对象
|
||||
8. **前端显示** → 编辑时正确解析location.lng和location.lat
|
||||
|
||||
### 数据类型转换验证
|
||||
|
||||
| 阶段 | 数据类型 | 示例值 |
|
||||
|------|----------|--------|
|
||||
| 前端输入 | number | 106.123456 |
|
||||
| API传输 | number | 106.123456 |
|
||||
| 后端处理 | number (parseFloat) | 106.123456 |
|
||||
| 数据库存储 | JSON | {"lng":106.123456,"lat":38.654321} |
|
||||
| 数据库查询 | number | 106.123456 |
|
||||
| 前端显示 | number | 106.123456 |
|
||||
|
||||
## 结论
|
||||
|
||||
### 验证结果总结
|
||||
|
||||
✅ **经纬度数据传递流程完全正确**
|
||||
- 前端输入框配置合理,支持高精度数值输入
|
||||
- 表单验证规则完善,确保数据有效性
|
||||
- 后端API正确处理经纬度数据的创建和更新
|
||||
- 数据库存储格式正确,支持JSON格式的location字段
|
||||
- 数据类型在整个流程中保持一致
|
||||
|
||||
✅ **修复的问题**
|
||||
- 更新操作中的对象引用问题已解决
|
||||
- 经纬度值现在能正确保存和更新
|
||||
|
||||
✅ **边界情况处理**
|
||||
- 空值处理正确
|
||||
- 边界值验证通过
|
||||
- 高精度数值保持完整
|
||||
|
||||
### 建议
|
||||
|
||||
1. **监控建议**:建议在生产环境中添加日志记录,监控经纬度数据的更新操作
|
||||
2. **性能建议**:对于大量的位置更新操作,可以考虑批量更新优化
|
||||
3. **扩展建议**:未来可以考虑添加地理位置验证(如检查坐标是否在合理的地理范围内)
|
||||
|
||||
### 最终确认
|
||||
|
||||
经过全面测试验证,经纬度输入值能够正确传递到数据库操作层,location字段的更新逻辑被正确执行,查询绑定的值与数据库中的实际值完全一致。系统现在能够可靠地处理经纬度数据的存储和更新操作。
|
||||
81
backend/tools/README.md
Normal file
81
backend/tools/README.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# 后端工具目录
|
||||
|
||||
本目录包含用于开发、测试、数据管理和系统维护的各种工具脚本。
|
||||
|
||||
## 📂 目录结构
|
||||
|
||||
```
|
||||
tools/
|
||||
├── data-management/ # 数据管理和维护脚本
|
||||
├── testing/ # 测试相关脚本
|
||||
├── verification/ # 数据验证和检查脚本
|
||||
└── README.md # 本文档
|
||||
```
|
||||
|
||||
## 🔧 数据管理脚本 (`data-management/`)
|
||||
|
||||
包含用于数据库操作、数据导入导出、数据修复等的脚本:
|
||||
|
||||
- **创建和生成**: `create-*.js`, `generate-*.js`
|
||||
- **导入和插入**: `import-*.js`, `insert-*.js`
|
||||
- **修复和更新**: `fix-*.js`, `update-*.js`, `reset_*.js`
|
||||
- **重新排序**: `reorder-*.js`, `simple-*.js`
|
||||
- **数据恢复**: `restore-*.js`
|
||||
- **清理操作**: `cleanup-*.js`
|
||||
|
||||
## 🧪 测试脚本 (`testing/`)
|
||||
|
||||
包含各种功能测试、API测试、集成测试脚本:
|
||||
|
||||
- **API测试**: `test-*-api.js`
|
||||
- **数据库测试**: `test-db-*.js`, `test-simple-db.js`
|
||||
- **功能测试**: `test-*-flow.js`, `test-*-binding.js`
|
||||
- **工具测试**: `test_*.js`
|
||||
|
||||
## ✅ 验证脚本 (`verification/`)
|
||||
|
||||
包含数据验证、系统检查、分析工具:
|
||||
|
||||
- **数据检查**: `check-*.js`, `check_*.js`
|
||||
- **数据验证**: `verify-*.js`
|
||||
- **系统分析**: `analyze-*.js`
|
||||
- **统计计数**: `count-*.js`
|
||||
|
||||
## 📝 使用说明
|
||||
|
||||
### 运行脚本
|
||||
```bash
|
||||
# 从backend目录运行
|
||||
cd backend
|
||||
|
||||
# 运行数据管理脚本
|
||||
node tools/data-management/import-farms-static-data.js
|
||||
|
||||
# 运行测试脚本
|
||||
node tools/testing/test-db-connection.js
|
||||
|
||||
# 运行验证脚本
|
||||
node tools/verification/check-current-data.js
|
||||
```
|
||||
|
||||
### 环境要求
|
||||
- Node.js 18.0+
|
||||
- 正确配置的 .env 文件
|
||||
- MySQL 数据库连接
|
||||
|
||||
### ⚠️ 注意事项
|
||||
|
||||
1. **生产环境谨慎**: 数据管理脚本可能会修改数据库,在生产环境使用前请务必备份
|
||||
2. **依赖检查**: 运行前确保所有依赖已安装 (`npm install`)
|
||||
3. **权限要求**: 某些脚本需要数据库管理员权限
|
||||
4. **日志记录**: 重要操作会生成日志,请注意查看
|
||||
|
||||
### 🔗 相关文档
|
||||
|
||||
- [开发指南](../../DEVELOPMENT.md)
|
||||
- [故障排除](../../TROUBLESHOOTING.md)
|
||||
- [API文档](../../API.md)
|
||||
|
||||
---
|
||||
|
||||
*最后更新: 2025年1月*
|
||||
@@ -1,23 +1,23 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const migrationFile = path.join(__dirname, 'migrations/20230101000000_initial_schema.js');
|
||||
|
||||
// 读取迁移文件
|
||||
let content = fs.readFileSync(migrationFile, 'utf8');
|
||||
|
||||
// 替换所有的 Sequelize. 为 DataTypes.
|
||||
content = content.replace(/Sequelize\.STRING/g, 'DataTypes.STRING');
|
||||
content = content.replace(/Sequelize\.INTEGER/g, 'DataTypes.INTEGER');
|
||||
content = content.replace(/Sequelize\.TEXT/g, 'DataTypes.TEXT');
|
||||
content = content.replace(/Sequelize\.DECIMAL/g, 'DataTypes.DECIMAL');
|
||||
content = content.replace(/Sequelize\.ENUM/g, 'DataTypes.ENUM');
|
||||
content = content.replace(/Sequelize\.DATE/g, 'DataTypes.DATE');
|
||||
|
||||
// 修复literal函数
|
||||
content = content.replace(/DataTypes\.literal/g, 'literal');
|
||||
|
||||
// 写入修复后的文件
|
||||
fs.writeFileSync(migrationFile, content, 'utf8');
|
||||
|
||||
console.log('✅ 迁移文件数据类型已修复');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const migrationFile = path.join(__dirname, 'migrations/20230101000000_initial_schema.js');
|
||||
|
||||
// 读取迁移文件
|
||||
let content = fs.readFileSync(migrationFile, 'utf8');
|
||||
|
||||
// 替换所有的 Sequelize. 为 DataTypes.
|
||||
content = content.replace(/Sequelize\.STRING/g, 'DataTypes.STRING');
|
||||
content = content.replace(/Sequelize\.INTEGER/g, 'DataTypes.INTEGER');
|
||||
content = content.replace(/Sequelize\.TEXT/g, 'DataTypes.TEXT');
|
||||
content = content.replace(/Sequelize\.DECIMAL/g, 'DataTypes.DECIMAL');
|
||||
content = content.replace(/Sequelize\.ENUM/g, 'DataTypes.ENUM');
|
||||
content = content.replace(/Sequelize\.DATE/g, 'DataTypes.DATE');
|
||||
|
||||
// 修复literal函数
|
||||
content = content.replace(/DataTypes\.literal/g, 'literal');
|
||||
|
||||
// 写入修复后的文件
|
||||
fs.writeFileSync(migrationFile, content, 'utf8');
|
||||
|
||||
console.log('✅ 迁移文件数据类型已修复');
|
||||
@@ -1,63 +1,63 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
require('dotenv').config();
|
||||
|
||||
async function testConnection() {
|
||||
const config = {
|
||||
host: process.env.DB_HOST || '129.211.213.226',
|
||||
port: process.env.DB_PORT || 3306,
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'Aiotagro@741',
|
||||
database: process.env.DB_NAME || 'nxTest',
|
||||
connectTimeout: 10000,
|
||||
acquireTimeout: 10000,
|
||||
timeout: 10000
|
||||
};
|
||||
|
||||
console.log('尝试连接数据库...');
|
||||
console.log('配置:', {
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
database: config.database
|
||||
});
|
||||
|
||||
try {
|
||||
const connection = await mysql.createConnection(config);
|
||||
console.log('✅ 数据库连接成功!');
|
||||
|
||||
// 测试查询
|
||||
const [rows] = await connection.execute('SELECT 1 as test');
|
||||
console.log('✅ 查询测试成功:', rows);
|
||||
|
||||
// 获取数据库信息
|
||||
const [dbInfo] = await connection.execute('SELECT DATABASE() as current_db, VERSION() as version');
|
||||
console.log('✅ 数据库信息:', dbInfo);
|
||||
|
||||
await connection.end();
|
||||
console.log('✅ 连接已关闭');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库连接失败:');
|
||||
console.error('错误代码:', error.code);
|
||||
console.error('错误消息:', error.message);
|
||||
console.error('完整错误:', error);
|
||||
|
||||
// 提供一些常见错误的解决方案
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查MySQL服务是否正在运行');
|
||||
console.log('2. 检查端口3306是否开放');
|
||||
console.log('3. 检查防火墙设置');
|
||||
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查用户名和密码是否正确');
|
||||
console.log('2. 检查用户是否有远程访问权限');
|
||||
} else if (error.code === 'ER_BAD_DB_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查数据库名称是否正确');
|
||||
console.log('2. 检查数据库是否存在');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testConnection();
|
||||
const mysql = require('mysql2/promise');
|
||||
require('dotenv').config();
|
||||
|
||||
async function testConnection() {
|
||||
const config = {
|
||||
host: process.env.DB_HOST || '129.211.213.226',
|
||||
port: process.env.DB_PORT || 3306,
|
||||
user: process.env.DB_USER || 'root',
|
||||
password: process.env.DB_PASSWORD || 'Aiotagro@741',
|
||||
database: process.env.DB_NAME || 'nxTest',
|
||||
connectTimeout: 10000,
|
||||
acquireTimeout: 10000,
|
||||
timeout: 10000
|
||||
};
|
||||
|
||||
console.log('尝试连接数据库...');
|
||||
console.log('配置:', {
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
database: config.database
|
||||
});
|
||||
|
||||
try {
|
||||
const connection = await mysql.createConnection(config);
|
||||
console.log('✅ 数据库连接成功!');
|
||||
|
||||
// 测试查询
|
||||
const [rows] = await connection.execute('SELECT 1 as test');
|
||||
console.log('✅ 查询测试成功:', rows);
|
||||
|
||||
// 获取数据库信息
|
||||
const [dbInfo] = await connection.execute('SELECT DATABASE() as current_db, VERSION() as version');
|
||||
console.log('✅ 数据库信息:', dbInfo);
|
||||
|
||||
await connection.end();
|
||||
console.log('✅ 连接已关闭');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库连接失败:');
|
||||
console.error('错误代码:', error.code);
|
||||
console.error('错误消息:', error.message);
|
||||
console.error('完整错误:', error);
|
||||
|
||||
// 提供一些常见错误的解决方案
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查MySQL服务是否正在运行');
|
||||
console.log('2. 检查端口3306是否开放');
|
||||
console.log('3. 检查防火墙设置');
|
||||
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查用户名和密码是否正确');
|
||||
console.log('2. 检查用户是否有远程访问权限');
|
||||
} else if (error.code === 'ER_BAD_DB_ERROR') {
|
||||
console.log('\n💡 可能的解决方案:');
|
||||
console.log('1. 检查数据库名称是否正确');
|
||||
console.log('2. 检查数据库是否存在');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testConnection();
|
||||
@@ -1,13 +1,13 @@
|
||||
const { testConnection } = require('./config/database-simple');
|
||||
|
||||
async function test() {
|
||||
console.log('测试数据库连接...');
|
||||
const result = await testConnection();
|
||||
if (result) {
|
||||
console.log('✅ 数据库连接测试成功');
|
||||
} else {
|
||||
console.log('❌ 数据库连接测试失败');
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
const { testConnection } = require('./config/database-simple');
|
||||
|
||||
async function test() {
|
||||
console.log('测试数据库连接...');
|
||||
const result = await testConnection();
|
||||
if (result) {
|
||||
console.log('✅ 数据库连接测试成功');
|
||||
} else {
|
||||
console.log('❌ 数据库连接测试失败');
|
||||
}
|
||||
}
|
||||
|
||||
test();
|
||||
@@ -1,48 +1,48 @@
|
||||
const db = require('./config/database');
|
||||
const SensorData = require('./models/SensorData');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// 检查传感器数据总数
|
||||
const count = await SensorData.count();
|
||||
console.log('传感器数据总数:', count);
|
||||
|
||||
// 检查最近的温度数据
|
||||
const temperatureData = await SensorData.findAll({
|
||||
where: { sensor_type: 'temperature' },
|
||||
limit: 10,
|
||||
order: [['recorded_at', 'DESC']]
|
||||
});
|
||||
console.log('\n最近10条温度数据:');
|
||||
temperatureData.forEach(r => {
|
||||
console.log(`${r.sensor_type}: ${r.value}${r.unit} at ${r.recorded_at}`);
|
||||
});
|
||||
|
||||
// 检查最近的湿度数据
|
||||
const humidityData = await SensorData.findAll({
|
||||
where: { sensor_type: 'humidity' },
|
||||
limit: 10,
|
||||
order: [['recorded_at', 'DESC']]
|
||||
});
|
||||
console.log('\n最近10条湿度数据:');
|
||||
humidityData.forEach(r => {
|
||||
console.log(`${r.sensor_type}: ${r.value}${r.unit} at ${r.recorded_at}`);
|
||||
});
|
||||
|
||||
// 检查24小时内的数据
|
||||
const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
const recentCount = await SensorData.count({
|
||||
where: {
|
||||
recorded_at: {
|
||||
[require('sequelize').Op.gte]: twentyFourHoursAgo
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log('\n24小时内的传感器数据总数:', recentCount);
|
||||
|
||||
} catch (error) {
|
||||
console.error('检查数据时出错:', error);
|
||||
} finally {
|
||||
process.exit();
|
||||
}
|
||||
const db = require('./config/database');
|
||||
const SensorData = require('./models/SensorData');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
// 检查传感器数据总数
|
||||
const count = await SensorData.count();
|
||||
console.log('传感器数据总数:', count);
|
||||
|
||||
// 检查最近的温度数据
|
||||
const temperatureData = await SensorData.findAll({
|
||||
where: { sensor_type: 'temperature' },
|
||||
limit: 10,
|
||||
order: [['recorded_at', 'DESC']]
|
||||
});
|
||||
console.log('\n最近10条温度数据:');
|
||||
temperatureData.forEach(r => {
|
||||
console.log(`${r.sensor_type}: ${r.value}${r.unit} at ${r.recorded_at}`);
|
||||
});
|
||||
|
||||
// 检查最近的湿度数据
|
||||
const humidityData = await SensorData.findAll({
|
||||
where: { sensor_type: 'humidity' },
|
||||
limit: 10,
|
||||
order: [['recorded_at', 'DESC']]
|
||||
});
|
||||
console.log('\n最近10条湿度数据:');
|
||||
humidityData.forEach(r => {
|
||||
console.log(`${r.sensor_type}: ${r.value}${r.unit} at ${r.recorded_at}`);
|
||||
});
|
||||
|
||||
// 检查24小时内的数据
|
||||
const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
const recentCount = await SensorData.count({
|
||||
where: {
|
||||
recorded_at: {
|
||||
[require('sequelize').Op.gte]: twentyFourHoursAgo
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log('\n24小时内的传感器数据总数:', recentCount);
|
||||
|
||||
} catch (error) {
|
||||
console.error('检查数据时出错:', error);
|
||||
} finally {
|
||||
process.exit();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user