Forráskód Böngészése

Merge branch 'master' of http://www.sysuimars.cn:3000/wss/feiniao-site-node

wangsisi 12 órája
szülő
commit
5cab29774a

+ 3 - 3
config/config.json

@@ -1,9 +1,9 @@
 {
   "development": {
-    "username": "feiniao_site_node_development",
-    "password": "NXrdGDHTjZENL7XA",
+    "username": "root",
+    "password": "wss123",
     "database": "feiniao_site_node_development",
-    "host": "8.210.65.64",
+    "host": "localhost",
     "dialect": "mysql",
     "timezone":"+08:00",
     "logQueryParameters":true

BIN
data/mysgl/#ib_16384_0.dblwr


BIN
data/mysgl/#innodb_redo/#ib_redo10


BIN
data/mysgl/#innodb_temp/temp_1.ibt


BIN
data/mysgl/#innodb_temp/temp_10.ibt


BIN
data/mysgl/#innodb_temp/temp_2.ibt


BIN
data/mysgl/#innodb_temp/temp_3.ibt


BIN
data/mysgl/#innodb_temp/temp_4.ibt


BIN
data/mysgl/#innodb_temp/temp_5.ibt


BIN
data/mysgl/#innodb_temp/temp_6.ibt


BIN
data/mysgl/#innodb_temp/temp_7.ibt


BIN
data/mysgl/#innodb_temp/temp_8.ibt


BIN
data/mysgl/#innodb_temp/temp_9.ibt


BIN
data/mysgl/binlog.000007


+ 1 - 0
data/mysgl/binlog.index

@@ -1,3 +1,4 @@
 ./binlog.000004
 ./binlog.000005
 ./binlog.000006
+./binlog.000007

BIN
data/mysgl/feiniao_site_node_development/articles.ibd


BIN
data/mysgl/feiniao_site_node_development/categories.ibd


BIN
data/mysgl/feiniao_site_node_development/contacts.ibd


BIN
data/mysgl/feiniao_site_node_development/news.ibd


BIN
data/mysgl/feiniao_site_node_development/sequelizemeta.ibd


BIN
data/mysgl/ibtmp1


BIN
data/mysgl/mysql.ibd


BIN
data/mysgl/undo_001


BIN
data/mysgl/undo_002


+ 321 - 0
docs/FRONTEND_API_GUIDE.md

@@ -0,0 +1,321 @@
+# 联系我们 API 接口文档
+
+## 基本信息
+
+- **开发环境**: `http://localhost:3000`
+- **生产环境**: `https://api.feiniao.com` (待配置)
+- **Content-Type**: `application/json`
+
+## 1. 提交联系表单
+
+### 接口信息
+- **URL**: `/contact/submit`
+- **方法**: `POST`
+- **描述**: 用户提交联系我们表单,系统会保存到数据库并自动发送邮件通知
+
+### 请求参数
+
+```json
+{
+  "name": "张三",           // 必填:联系人姓名
+  "email": "user@example.com", // 必填:联系人邮箱
+  "phone": "13800138000",    // 可选:联系电话
+  "company": "某某科技公司",   // 可选:公司名称
+  "subject": "产品咨询",      // 必填:留言主题
+  "message": "我想了解产品详情" // 必填:留言内容
+}
+```
+
+### 成功响应 (201)
+
+```json
+{
+  "success": true,
+  "message": {
+    "id": 1,
+    "message": "感谢您的留言,我们已收到并会在24小时内回复"
+  },
+  "data": "留言提交成功,我们会尽快回复您"
+}
+```
+
+### 错误响应 (400)
+
+```json
+{
+  "success": false,
+  "message": "参数验证失败",
+  "error": [
+    "联系人姓名不能为空",
+    "邮箱格式不正确"
+  ]
+}
+```
+
+## 2. 获取联系记录列表 (管理员用)
+
+### 接口信息
+- **URL**: `/contact/list`
+- **方法**: `GET`
+- **描述**: 获取联系我们留言列表,支持分页和状态筛选
+
+### 请求参数 (Query)
+
+```
+GET /contact/list?page=1&limit=10&status=0
+```
+
+- `page`: 页码 (默认: 1)
+- `limit`: 每页数量 (默认: 10)
+- `status`: 处理状态 (0-未处理, 1-已处理)
+
+### 成功响应 (200)
+
+```json
+{
+  "success": true,
+  "message": {
+    "contacts": [
+      {
+        "id": 1,
+        "name": "张三",
+        "email": "user@example.com",
+        "phone": "13800138000",
+        "company": "某某科技公司",
+        "subject": "产品咨询",
+        "message": "我想了解产品详情",
+        "status": 0,
+        "isEmailSent": true,
+        "createdAt": "2025-09-19T09:27:05.000Z",
+        "updatedAt": "2025-09-19T09:27:06.000Z"
+      }
+    ],
+    "pagination": {
+      "total": 25,
+      "page": 1,
+      "limit": 10,
+      "totalPages": 3
+    }
+  },
+  "data": "获取成功"
+}
+```
+
+## 3. 获取联系详情
+
+### 接口信息
+- **URL**: `/contact/detail/:id`
+- **方法**: `GET`
+- **描述**: 根据ID获取具体的联系记录详情
+
+### 请求示例
+
+```
+GET /contact/detail/1
+```
+
+### 成功响应 (200)
+
+```json
+{
+  "success": true,
+  "message": "获取成功",
+  "data": {
+    "id": 1,
+    "name": "张三",
+    "email": "user@example.com",
+    "phone": "13800138000",
+    "company": "某某科技公司",
+    "subject": "产品咨询",
+    "message": "我想了解产品详情",
+    "status": 0,
+    "isEmailSent": true,
+    "createdAt": "2025-09-19T09:27:05.000Z",
+    "updatedAt": "2025-09-19T09:27:06.000Z"
+  }
+}
+```
+
+## 4. 更新处理状态
+
+### 接口信息
+- **URL**: `/contact/update/:id/status`
+- **方法**: `PUT`
+- **描述**: 更新联系记录的处理状态
+
+### 请求示例
+
+```json
+PUT /contact/update/1/status
+{
+  "status": 1  // 0-未处理, 1-已处理
+}
+```
+
+### 成功响应 (200)
+
+```json
+{
+  "success": true,
+  "message": "状态更新成功",
+  "data": {
+    "id": 1,
+    "status": 1,
+    // ... 其他字段
+  }
+}
+```
+
+## 5. 删除联系记录
+
+### 接口信息
+- **URL**: `/contact/delete/:id`
+- **方法**: `DELETE`
+- **描述**: 根据ID删除联系记录
+
+### 请求示例
+
+```
+DELETE /contact/delete/1
+```
+
+### 成功响应 (200)
+
+```json
+{
+  "success": true,
+  "message": "删除成功",
+  "data": null
+}
+```
+
+## 前端集成示例
+
+### JavaScript/Fetch 示例
+
+```javascript
+// 提交联系表单
+async function submitContact(formData) {
+  try {
+    const response = await fetch('http://localhost:3000/contact/submit', {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: JSON.stringify(formData)
+    });
+    
+    const result = await response.json();
+    
+    if (result.success) {
+      console.log('提交成功:', result.message);
+      // 显示成功消息给用户
+    } else {
+      console.error('提交失败:', result.error);
+      // 显示错误消息给用户
+    }
+  } catch (error) {
+    console.error('网络错误:', error);
+  }
+}
+
+// 使用示例
+const contactData = {
+  name: '张三',
+  email: 'zhangsan@example.com',
+  phone: '13800138000',
+  company: '某某科技公司',
+  subject: '产品咨询',
+  message: '我想了解一下你们的产品价格和功能特点。'
+};
+
+submitContact(contactData);
+```
+
+### React 示例
+
+```jsx
+import { useState } from 'react';
+
+function ContactForm() {
+  const [formData, setFormData] = useState({
+    name: '',
+    email: '',
+    phone: '',
+    company: '',
+    subject: '',
+    message: ''
+  });
+  const [loading, setLoading] = useState(false);
+  const [message, setMessage] = useState('');
+
+  const handleSubmit = async (e) => {
+    e.preventDefault();
+    setLoading(true);
+    
+    try {
+      const response = await fetch('http://localhost:3000/contact/submit', {
+        method: 'POST',
+        headers: {
+          'Content-Type': 'application/json',
+        },
+        body: JSON.stringify(formData)
+      });
+      
+      const result = await response.json();
+      
+      if (result.success) {
+        setMessage('留言提交成功,我们会尽快回复您!');
+        setFormData({ name: '', email: '', phone: '', company: '', subject: '', message: '' });
+      } else {
+        setMessage('提交失败:' + (result.error?.join(', ') || result.message));
+      }
+    } catch (error) {
+      setMessage('网络错误,请稍后重试');
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  return (
+    <form onSubmit={handleSubmit}>
+      {/* 表单字段 */}
+      <input
+        type="text"
+        placeholder="姓名 *"
+        value={formData.name}
+        onChange={(e) => setFormData({...formData, name: e.target.value})}
+        required
+      />
+      <input
+        type="email"
+        placeholder="邮箱 *"
+        value={formData.email}
+        onChange={(e) => setFormData({...formData, email: e.target.value})}
+        required
+      />
+      {/* 其他字段... */}
+      
+      <button type="submit" disabled={loading}>
+        {loading ? '提交中...' : '提交留言'}
+      </button>
+      
+      {message && <p>{message}</p>}
+    </form>
+  );
+}
+```
+
+## 注意事项
+
+1. **必填字段**: `name`, `email`, `subject`, `message`
+2. **邮箱格式**: 必须是有效的邮箱格式
+3. **自动邮件**: 提交成功后会自动发送通知邮件给管理员和自动回复给用户
+4. **状态码**: 成功201,客户端错误400,服务器错误500
+5. **CORS**: 如果前后端不同域,需要配置CORS
+
+## 错误处理
+
+- **400**: 参数验证失败,检查必填字段和格式
+- **404**: 记录不存在(查询/更新/删除时)
+- **500**: 服务器内部错误,联系后端开发人员

+ 68 - 0
test-docker-connection.js

@@ -0,0 +1,68 @@
+const { Sequelize } = require('sequelize');
+const config = require('./config/config.json').development;
+
+console.log('Docker数据库配置:', {
+  host: config.host,
+  database: config.database,
+  username: config.username,
+  dialect: config.dialect
+});
+
+const sequelize = new Sequelize(config.database, config.username, config.password, {
+  host: config.host,
+  dialect: config.dialect,
+  logging: console.log,
+  pool: {
+    max: 5,
+    min: 0,
+    acquire: 30000,
+    idle: 10000
+  },
+  dialectOptions: {
+    ssl: false,
+    connectTimeout: 60000
+  }
+});
+
+async function testDockerConnection() {
+  try {
+    console.log('\n正在测试Docker数据库连接...');
+    await sequelize.authenticate();
+    console.log('✅ Docker数据库连接成功!');
+    
+    // 测试查询
+    console.log('\n正在测试查询...');
+    const [results] = await sequelize.query('SELECT 1 as test, NOW() as current_time');
+    console.log('✅ 查询测试成功:', results);
+    
+    // 检查数据库版本
+    const [version] = await sequelize.query('SELECT VERSION() as version');
+    console.log('MySQL版本:', version[0].version);
+    
+    // 测试连接池状态
+    console.log('\n连接池状态:');
+    console.log('- 总连接数:', sequelize.connectionManager.pool.size);
+    console.log('- 可用连接数:', sequelize.connectionManager.pool.available);
+    console.log('- 使用中连接数:', sequelize.connectionManager.pool.using);
+    console.log('- 等待连接数:', sequelize.connectionManager.pool.waiting);
+    
+  } catch (error) {
+    console.error('❌ Docker数据库连接失败:');
+    console.error('错误类型:', error.name);
+    console.error('错误代码:', error.code || error.original?.code);
+    console.error('错误消息:', error.message);
+    
+    if (error.code === 'ECONNREFUSED') {
+      console.error('\n🔍 连接被拒绝分析:');
+      console.error('- Docker MySQL容器可能未启动');
+      console.error('- 端口3306可能被占用');
+      console.error('- 建议检查: docker ps | grep mysql');
+    }
+    
+  } finally {
+    await sequelize.close();
+    console.log('\n数据库连接已关闭');
+  }
+}
+
+testDockerConnection();

+ 23 - 7
utils/emailService.js

@@ -1,25 +1,41 @@
 const nodemailer = require('nodemailer');
 
 // 邮件配置 - 使用环境变量或默认配置
+// 根据QQ邮箱官方文档配置SMTP服务器
 const emailConfig = {
-  service: process.env.EMAIL_SERVICE || 'qq',
+  host: process.env.EMAIL_HOST || 'smtp.qq.com',
+  port: process.env.EMAIL_PORT || 587, // 使用STARTTLS的端口
+  secure: false, // 587端口使用STARTTLS
   auth: {
-    user: process.env.EMAIL_USER || 'your-email@qq.com',
-    pass: process.env.EMAIL_PASS || 'your-app-password'
+    user: process.env.EMAIL_USER || '739239437@qq.com', // QQ邮箱完整地址
+    pass: process.env.EMAIL_PASS || 'zyggcylcanbgbddc' // QQ邮箱授权码(不是QQ密码)
+  },
+  tls: {
+    rejectUnauthorized: false
   }
 };
 
 // 接收邮箱配置
-const receiverEmail = process.env.ADMIN_EMAIL || 'admin@yourcompany.com';
+const receiverEmail = process.env.ADMIN_EMAIL || '1661073856@qq.com';
 
 // 检查邮件配置是否有效
-const isEmailConfigured = emailConfig.auth.user !== 'your-email@qq.com' && 
-                         emailConfig.auth.pass !== 'your-app-password' &&
-                         receiverEmail !== 'admin@yourcompany.com';
+// 只要有邮箱用户名和密码/授权码就认为配置有效
+const isEmailConfigured = emailConfig.auth.user && 
+                         emailConfig.auth.pass && 
+                         emailConfig.auth.user.trim() !== '' &&
+                         emailConfig.auth.pass.trim() !== '';
 
 // 创建邮件传输器(仅在配置有效时)
 const transporter = isEmailConfigured ? nodemailer.createTransport(emailConfig) : null;
 
+console.log('邮件服务配置状态:', {
+  configured: isEmailConfigured,
+  host: emailConfig.host,
+  port: emailConfig.port,
+  user: emailConfig.auth.user,
+  hasPassword: !!emailConfig.auth.pass
+});
+
 /**
  * 发送联系我们留言通知邮件
  * @param {Object} contactData 联系信息