| 
					
				 | 
			
			
				@@ -0,0 +1,234 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const express = require('express'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const router = express.Router(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const Contact = require('../models/contact'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const { sendContactNotification, sendAutoReply } = require('../utils/emailService'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const { successResponse, errorResponse } = require('../utils/responese'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @api {post} /contact 提交联系我们表单 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiName CreateContact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiGroup Contact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} name 联系人姓名(必填) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} email 联系人邮箱(必填) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} [phone] 联系电话 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} [company] 公司名称 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} subject 留言主题(必填) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {String} message 留言内容(必填) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiSuccess {Boolean} status 请求状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiSuccess {String} message 响应消息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiSuccess {Object} data 创建的联系信息 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiSuccessExample {json} Success-Response: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * HTTP/1.1 201 Created 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   "status": true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   "message": "留言提交成功,我们会尽快回复您", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   "data": { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     "id": 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *     "message": "感谢您的留言,我们已收到并会在24小时内回复" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+router.post('/', async (req, res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { name, email, phone, company, subject, message } = req.body; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 参数验证 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const errors = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!name || name.trim().length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('联系人姓名不能为空'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!email || email.trim().length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('联系人邮箱不能为空'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!subject || subject.trim().length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('留言主题不能为空'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!message || message.trim().length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('留言内容不能为空'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 邮箱格式验证 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (email && !emailRegex.test(email)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('邮箱格式不正确'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 字符长度验证 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (name && name.trim().length > 100) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('联系人姓名不能超过100个字符'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (subject && subject.trim().length > 200) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('留言主题不能超过200个字符'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (company && company.trim().length > 200) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('公司名称不能超过200个字符'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (phone && phone.trim().length > 20) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      errors.push('联系电话不能超过20个字符'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (errors.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return res.status(400).json(errorResponse('参数验证失败', errors)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 保存到数据库 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const contactData = await Contact.create({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      name: name.trim(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      email: email.trim().toLowerCase(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      phone: phone ? phone.trim() : null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      company: company ? company.trim() : null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      subject: subject.trim(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      message: message.trim() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 异步发送邮件(不阻塞响应) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    setImmediate(async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 发送通知邮件给管理员 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const notificationSent = await sendContactNotification(contactData.toJSON()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 发送自动回复给客户 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const autoReplySent = await sendAutoReply(contactData.toJSON()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 更新邮件发送状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (notificationSent || autoReplySent) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          await contactData.update({ isEmailSent: true }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        console.log(`联系表单处理完成 - ID: ${contactData.id}, 通知邮件: ${notificationSent ? '成功' : '失败'}, 自动回复: ${autoReplySent ? '成功' : '失败'}`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } catch (emailError) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        console.error('邮件发送过程出错:', emailError); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 立即返回成功响应 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(201).json(successResponse('留言提交成功,我们会尽快回复您', { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      id: contactData.id, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      message: '感谢您的留言,我们已收到并会在24小时内回复' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    })); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error('提交联系表单失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(500).json(errorResponse('服务器内部错误')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @api {get} /contact 获取联系我们列表(管理员用) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiName GetContacts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiGroup Contact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {Number} [page=1] 页码 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {Number} [limit=10] 每页数量 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {Number} [status] 处理状态筛选(0-未处理,1-已处理) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+router.get('/', async (req, res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { page = 1, limit = 10, status } = req.query; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const offset = (page - 1) * limit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const whereConditions = {}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (status !== undefined) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      whereConditions.status = parseInt(status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { count, rows } = await Contact.findAndCountAll({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      where: whereConditions, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      order: [['createdAt', 'DESC']], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      limit: parseInt(limit), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      offset: parseInt(offset) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.json(successResponse('获取成功', { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      contacts: rows, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      pagination: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        total: count, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        page: parseInt(page), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        limit: parseInt(limit), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        totalPages: Math.ceil(count / limit) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    })); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error('获取联系列表失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(500).json(errorResponse('服务器内部错误')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @api {get} /contact/:id 获取联系详情 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiName GetContactDetail 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiGroup Contact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+router.get('/:id', async (req, res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { id } = req.params; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const contact = await Contact.findByPk(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!contact) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return res.status(404).json(errorResponse('联系记录不存在')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.json(successResponse('获取成功', contact)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error('获取联系详情失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(500).json(errorResponse('服务器内部错误')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @api {put} /contact/:id/status 更新处理状态 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiName UpdateContactStatus 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiGroup Contact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ *  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiParam {Number} status 处理状态(0-未处理,1-已处理) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+router.put('/:id/status', async (req, res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { id } = req.params; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { status } = req.body; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (![0, 1].includes(parseInt(status))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return res.status(400).json(errorResponse('状态值只能是0或1')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const contact = await Contact.findByPk(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!contact) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return res.status(404).json(errorResponse('联系记录不存在')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await contact.update({ status: parseInt(status) }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.json(successResponse('状态更新成功', contact)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error('更新联系状态失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(500).json(errorResponse('服务器内部错误')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @api {delete} /contact/:id 删除联系记录 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiName DeleteContact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @apiGroup Contact 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+router.delete('/:id', async (req, res) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { id } = req.params; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const contact = await Contact.findByPk(id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!contact) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return res.status(404).json(errorResponse('联系记录不存在')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await contact.destroy(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.json(successResponse('删除成功')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    console.error('删除联系记录失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.status(500).json(errorResponse('服务器内部错误')); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+module.exports = router; 
			 |