智慧水务管理系统 - 精河县供水工程综合管理平台

crm-backend-simple.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. require('dotenv').config();
  2. const express = require('express');
  3. const cors = require('cors');
  4. const fs = require('fs');
  5. const path = require('path');
  6. const app = express();
  7. const PORT = process.env.PORT || 3002;
  8. app.use(cors());
  9. app.use(express.json());
  10. // 使用 JSON 文件存储数据
  11. const dbPath = path.join(__dirname, '..', 'data', 'crm-data.json');
  12. function loadDB() {
  13. try {
  14. if (fs.existsSync(dbPath)) {
  15. return JSON.parse(fs.readFileSync(dbPath, 'utf-8'));
  16. }
  17. } catch (e) {
  18. console.error('加载数据库失败:', e.message);
  19. }
  20. return { customers: [], followUps: [] };
  21. }
  22. function saveDB(data) {
  23. try {
  24. fs.writeFileSync(dbPath, JSON.stringify(data, null, 2), 'utf-8');
  25. } catch (e) {
  26. console.error('保存数据库失败:', e.message);
  27. }
  28. }
  29. // 初始化
  30. let db = loadDB();
  31. // 健康检查
  32. app.get('/api/health', (req, res) => {
  33. res.json({ status: 'ok', service: 'CRM API', customers: db.customers.length });
  34. });
  35. // 获取客户列表
  36. app.get('/api/customers', (req, res) => {
  37. try {
  38. const { status, keyword } = req.query;
  39. let customers = db.customers;
  40. if (status) {
  41. customers = customers.filter(c => c.status === status);
  42. }
  43. if (keyword) {
  44. const k = keyword.toLowerCase();
  45. customers = customers.filter(c =>
  46. c.name.toLowerCase().includes(k) ||
  47. (c.company && c.company.toLowerCase().includes(k)) ||
  48. (c.phone && c.phone.includes(k))
  49. );
  50. }
  51. customers.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  52. res.json({ success: true, data: customers });
  53. } catch (error) {
  54. res.status(500).json({ success: false, error: error.message });
  55. }
  56. });
  57. // 获取客户详情
  58. app.get('/api/customers/:id', (req, res) => {
  59. try {
  60. const customer = db.customers.find(c => c.id == req.params.id);
  61. if (!customer) {
  62. return res.status(404).json({ success: false, error: '客户不存在' });
  63. }
  64. const followUps = db.followUps.filter(f => f.customer_id == req.params.id)
  65. .sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
  66. res.json({ success: true, data: { ...customer, followUps } });
  67. } catch (error) {
  68. res.status(500).json({ success: false, error: error.message });
  69. }
  70. });
  71. // 创建客户
  72. app.post('/api/customers', (req, res) => {
  73. try {
  74. const { name, company, phone, email, source, notes } = req.body;
  75. if (!name) {
  76. return res.status(400).json({ success: false, error: '客户名称必填' });
  77. }
  78. const customer = {
  79. id: Date.now(),
  80. name,
  81. company: company || '',
  82. phone: phone || '',
  83. email: email || '',
  84. source: source || '',
  85. status: 'potential',
  86. notes: notes || '',
  87. created_at: new Date().toISOString(),
  88. updated_at: new Date().toISOString()
  89. };
  90. db.customers.push(customer);
  91. saveDB(db);
  92. res.json({ success: true, data: { id: customer.id }, message: '客户创建成功' });
  93. } catch (error) {
  94. res.status(500).json({ success: false, error: error.message });
  95. }
  96. });
  97. // 更新客户
  98. app.put('/api/customers/:id', (req, res) => {
  99. try {
  100. const index = db.customers.findIndex(c => c.id == req.params.id);
  101. if (index === -1) {
  102. return res.status(404).json({ success: false, error: '客户不存在' });
  103. }
  104. const { name, company, phone, email, source, status, notes } = req.body;
  105. db.customers[index] = {
  106. ...db.customers[index],
  107. name, company, phone, email, source, status, notes,
  108. updated_at: new Date().toISOString()
  109. };
  110. saveDB(db);
  111. res.json({ success: true, message: '客户更新成功' });
  112. } catch (error) {
  113. res.status(500).json({ success: false, error: error.message });
  114. }
  115. });
  116. // 删除客户
  117. app.delete('/api/customers/:id', (req, res) => {
  118. try {
  119. const index = db.customers.findIndex(c => c.id == req.params.id);
  120. if (index === -1) {
  121. return res.status(404).json({ success: false, error: '客户不存在' });
  122. }
  123. db.customers.splice(index, 1);
  124. db.followUps = db.followUps.filter(f => f.customer_id != req.params.id);
  125. saveDB(db);
  126. res.json({ success: true, message: '客户删除成功' });
  127. } catch (error) {
  128. res.status(500).json({ success: false, error: error.message });
  129. }
  130. });
  131. // 添加跟进记录
  132. app.post('/api/customers/:id/followups', (req, res) => {
  133. try {
  134. const { type, content, nextFollowup } = req.body;
  135. const followUp = {
  136. id: Date.now(),
  137. customer_id: parseInt(req.params.id),
  138. type: type || '',
  139. content: content || '',
  140. next_followup: nextFollowup || null,
  141. created_at: new Date().toISOString()
  142. };
  143. db.followUps.push(followUp);
  144. // 更新客户状态
  145. if (type === '成交') {
  146. const index = db.customers.findIndex(c => c.id == req.params.id);
  147. if (index !== -1) {
  148. db.customers[index].status = 'customer';
  149. db.customers[index].updated_at = new Date().toISOString();
  150. }
  151. }
  152. saveDB(db);
  153. res.json({ success: true, data: { id: followUp.id }, message: '跟进记录添加成功' });
  154. } catch (error) {
  155. res.status(500).json({ success: false, error: error.message });
  156. }
  157. });
  158. // 获取统计数据
  159. app.get('/api/stats', (req, res) => {
  160. try {
  161. const total = db.customers.length;
  162. const potential = db.customers.filter(c => c.status === 'potential').length;
  163. const contacting = db.customers.filter(c => c.status === 'contacting').length;
  164. const customer = db.customers.filter(c => c.status === 'customer').length;
  165. res.json({ success: true, data: { total, potential, contacting, customer } });
  166. } catch (error) {
  167. res.status(500).json({ success: false, error: error.message });
  168. }
  169. });
  170. app.listen(PORT, () => {
  171. console.log(`🚀 CRM API 服务已启动:http://localhost:${PORT}`);
  172. console.log(`📊 数据文件:${dbPath}`);
  173. console.log(`📝 当前客户数:${db.customers.length}`);
  174. });