Browse Source

vue课程设计后台服务器

master
张稚琦 2 years ago
commit
3de028cc81
100 changed files with 3113 additions and 0 deletions
  1. +27
    -0
      README.md
  2. +303
    -0
      analogDataSql.sql
  3. +50
    -0
      app.js
  4. +131
    -0
      app/controllers/collectController.js
  5. +126
    -0
      app/controllers/orderController.js
  6. +164
    -0
      app/controllers/productController.js
  7. +21
    -0
      app/controllers/resourcesController.js
  8. +234
    -0
      app/controllers/shoppingCartController.js
  9. +217
    -0
      app/controllers/userController.js
  10. +13
    -0
      app/middleware/RewriteUrl.js
  11. +25
    -0
      app/middleware/checkLogin.js
  12. +74
    -0
      app/middleware/checkUserInfo.js
  13. +18
    -0
      app/middleware/error.js
  14. +19
    -0
      app/middleware/isLogin.js
  15. +25
    -0
      app/middleware/koaBodyConfig.js
  16. +33
    -0
      app/middleware/session.js
  17. +31
    -0
      app/models/dao/collectDao.js
  18. +40
    -0
      app/models/dao/db.js
  19. +30
    -0
      app/models/dao/orderDao.js
  20. +68
    -0
      app/models/dao/productDao.js
  21. +16
    -0
      app/models/dao/resourcesDao.js
  22. +36
    -0
      app/models/dao/shoppingCartDao.js
  23. +26
    -0
      app/models/dao/userDao.js
  24. +26
    -0
      app/routers/index.js
  25. +18
    -0
      app/routers/router/collectRouter.js
  26. +17
    -0
      app/routers/router/orderRouter.js
  27. +23
    -0
      app/routers/router/productRouter.js
  28. +16
    -0
      app/routers/router/resourcesRouter.js
  29. +19
    -0
      app/routers/router/shoppingCartRouter.js
  30. +19
    -0
      app/routers/router/userRouter.js
  31. +23
    -0
      config.js
  32. +104
    -0
      docs/API.md
  33. +982
    -0
      package-lock.json
  34. +21
    -0
      package.json
  35. +118
    -0
      public/docs/README.md
  36. BIN
      public/imgs/accessory/accessory-promo1.png
  37. BIN
      public/imgs/accessory/accessory-promo2.png
  38. BIN
      public/imgs/accessory/charger-10000mAh.png
  39. BIN
      public/imgs/accessory/charger-18w.png
  40. BIN
      public/imgs/accessory/charger-30w.png
  41. BIN
      public/imgs/accessory/charger-36w.png
  42. BIN
      public/imgs/accessory/charger-60w.png
  43. BIN
      public/imgs/accessory/charger-car-37w.png
  44. BIN
      public/imgs/accessory/charger-car.png
  45. BIN
      public/imgs/accessory/charger-tio.png
  46. BIN
      public/imgs/accessory/protectingMen-Mi-CC9.png
  47. BIN
      public/imgs/accessory/protectingMen-Mi-CC9e.png
  48. BIN
      public/imgs/accessory/protectingShell-Mi-9-red.png
  49. BIN
      public/imgs/accessory/protectingShell-Mi-9.png
  50. BIN
      public/imgs/accessory/protectingShell-Mi-9SE.png
  51. BIN
      public/imgs/accessory/protectingShell-Mi-CC9Pro.png
  52. BIN
      public/imgs/accessory/protectingShell-Mix-3.png
  53. BIN
      public/imgs/accessory/protectingShell-RedMi-K20&pro.png
  54. BIN
      public/imgs/accessory/protectingShell-RedMi-K20.png
  55. BIN
      public/imgs/appliance/AirCondition-F3W1.png
  56. BIN
      public/imgs/appliance/AirCondition-V1C1.png
  57. BIN
      public/imgs/appliance/MiTv-4A-32.png
  58. BIN
      public/imgs/appliance/MiTv-4A-65.png
  59. BIN
      public/imgs/appliance/MiTv-4C-55.png
  60. BIN
      public/imgs/appliance/MiTv-4X-43.png
  61. BIN
      public/imgs/appliance/MiTv-ArtTv-65.png
  62. BIN
      public/imgs/appliance/MiTv-E55A.png
  63. BIN
      public/imgs/appliance/MiTv-E65A.png
  64. BIN
      public/imgs/appliance/Washer-Pro-10.png
  65. BIN
      public/imgs/appliance/appliance-promo1.png
  66. BIN
      public/imgs/appliance/appliance-promo2.png
  67. BIN
      public/imgs/cms_1.jpg
  68. BIN
      public/imgs/cms_2.jpg
  69. BIN
      public/imgs/cms_3.jpg
  70. BIN
      public/imgs/cms_4.jpg
  71. BIN
      public/imgs/phone/Mi-CC9.png
  72. BIN
      public/imgs/phone/Redmi-7A.png
  73. BIN
      public/imgs/phone/Redmi-8.png
  74. BIN
      public/imgs/phone/Redmi-8A.png
  75. BIN
      public/imgs/phone/Redmi-Note8-pro.png
  76. BIN
      public/imgs/phone/Redmi-Note8.png
  77. BIN
      public/imgs/phone/Redmi-k30-5G.png
  78. BIN
      public/imgs/phone/Redmi-k30.png
  79. BIN
      public/imgs/phone/phone.png
  80. BIN
      public/imgs/phone/picture/AirCondition-F3W1-1.jpg
  81. BIN
      public/imgs/phone/picture/AirCondition-V1C1-1.jpg
  82. BIN
      9
  83. BIN
      9
  84. BIN
      9
  85. BIN
      9
  86. BIN
      9
  87. BIN
      9
  88. BIN
      -1.jpg
  89. BIN
      public/imgs/phone/picture/MiTv-4A-32-1.jpg
  90. BIN
      public/imgs/phone/picture/MiTv-4A-32-2.jpg
  91. BIN
      public/imgs/phone/picture/MiTv-4A-32-3.jpg
  92. BIN
      public/imgs/phone/picture/MiTv-4A-32-4.jpg
  93. BIN
      -1.jpg
  94. BIN
      -2.jpg
  95. BIN
      -3.jpg
  96. BIN
      -1.jpg
  97. BIN
      -2.jpg
  98. BIN
      -3.jpg
  99. BIN
      public/imgs/phone/picture/MiTv-ArtTv-65-1.jpg
  100. BIN
      public/imgs/phone/picture/MiTv-E55A-1.jpg

+ 27
- 0
README.md View File

@@ -0,0 +1,27 @@
# store-server

## 前言

2020年寒假尤其特殊,因为新型冠状病毒肺炎疫情,学校至今没有开学。想起上学期利用课余时间学习了`vue`、`node.js`,一直想做个完整的项目实战一下,但之前在学校并没有那么多的时间。现在恰好有时间,就想着做一个项目巩固之前学到的东西。

本项目前后端分离,这是项目的后端,前端请移步[vue-store](https://github.com/hai-27/vue-store)。

## 接口文档

[接口文档](https://github.com/hai-27/store-server/blob/master/docs/API.md)

## 运行项目
```
1. Clone project

git clone https://github.com/hai-27/store-server.git

2. Project setup

cd store-server
npm install

3. Run project

node app.js
```

+ 303
- 0
analogDataSql.sql View File

@@ -0,0 +1,303 @@
/*
* @Description: 插入模拟的数据库信息语句
* @Author: hai-27
* @Date: 2020-02-09 14:40:32
* @LastEditors: hai-27
* @LastEditTime: 2020-02-25 22:39:16
*/
insert into category
values(null, "手机");

insert into category
values(null, "电视机");
insert into category
values(null, "空调");
insert into category
values(null, "洗衣机");

insert into category
values(null, "保护套");
insert into category
values(null, "保护膜");
insert into category
values(null, "充电器");
insert into category
values(null, "充电宝");


insert into product
values
(null, 'Redmi K30', 1, '120Hz流速屏,全速热爱', '120Hz高帧率流速屏/ 索尼6400万前后六摄 / 6.67''小孔径全面屏 / 最高可选8GB+256GB大存储 / 高通骁龙730G处理器 / 3D四曲面玻璃机身 / 4500mAh+27W快充 / 多功能NFC', 'public/imgs/phone/Redmi-k30.png', 2000.00, 1599.00, 10, 0),
(null, 'Redmi K30 5G', 1, '双模5G,120Hz流速屏', '双模5G / 三路并发 / 高通骁龙765G / 7nm 5G低功耗处理器 / 120Hz高帧率流速屏 / 6.67''小孔径全面屏 / 索尼6400万前后六摄 / 最高可选8GB+256GB大存储 / 4500mAh+30W快充 / 3D四曲面玻璃机身 / 多功能NFC', 'public/imgs/phone/Redmi-k30-5G.png', 2599.00, 2599.00, 10, 0),
(null, '小米CC9 Pro', 1, '1亿像素,五摄四闪', '1亿像素主摄 / 全场景五摄像头 / 四闪光灯 / 3200万自拍 / 10 倍混合光学变焦,50倍数字变焦 / 5260mAh ⼤电量 / 标配 30W疾速快充 / ⼩米⾸款超薄屏下指纹 / 德国莱茵低蓝光认证 / 多功能NFC / 红外万能遥控 / 1216超线性扬声器', 'public/imgs/phone/Mi-CC9.png', 2799.00, 2599.00, 20, 0),
(null, 'Redmi 8', 1, '5000mAh超长续航', '5000mAh超长续航 / 高通骁龙439八核处理器 / 4GB+64GB', 'public/imgs/phone/Redmi-8.png', 799.00, 699.00, 20, 0),
(null, 'Redmi 8A', 1, '5000mAh超长续航', '5000mAh超长续航 / 高通骁龙439八核处理器 / 4GB+64GB / 1200万AI后置相机', 'public/imgs/phone/Redmi-8A.png', 599.00, 699.00, 20, 0),
(null, 'Redmi Note8 Pro', 1, '6400万全场景四摄', '6400万四摄小金刚拍照新旗舰超强解析力,超震撼', 'public/imgs/phone/Redmi-Note8-pro.png', 1399.00, 1199.00, 20, 0),
(null, 'Redmi Note8', 1, '千元4800万四摄', '千元4800万四摄 | 高通骁龙665 | 小金刚品质保证', 'public/imgs/phone/Redmi-Note8.png', 999.00, 999.00, 20, 0),
(null, 'Redmi 7A', 1, '小巧大电量 持久流畅', '小巧大电量,持久又流畅骁龙8核高性能处理器 | 4000mAh超长续航 | AI人脸解锁 | 整机防泼溅', 'public/imgs/phone/Redmi-7A.png', 599.00, 539.00, 20, 0);

insert into product
values
(null, '小米电视4A 32英寸', 2, '人工智能系统,高清液晶屏', '小米电视4A 32英寸 | 64位四核处理器 | 1GB+4GB大内存 | 人工智能系统', 'public/imgs/appliance/MiTv-4A-32.png', 799.00, 799.00, 10, 0),
(null, '小米全面屏电视E55A', 2, '全面屏设计,人工智能语音', '全面屏设计 | 内置小爱同学 | 4K + HDR | 杜比DTS | PatchWall | 海量内容 | 2GB + 8GB大存储 | 64位四核处理器', 'public/imgs/appliance/MiTv-E55A.png', 2099.00, 1899.00, 10, 0),
(null, '小米全面屏电视E65A', 2, '全面屏设计,人工智能语音', '人工智能语音系统 | 海量影视内容 | 4K 超高清屏 | 杜比音效 | 64位四核处理器 | 2GB + 8GB大存储', 'public/imgs/appliance/MiTv-E65A.png', 3999.00, 2799.00, 10, 0),
(null, '小米电视4X 43英寸', 2, 'FHD全高清屏,人工智能语音', '人工智能语音系统 | FHD全高清屏 | 64位四核处理器 | 海量片源 | 1GB+8GB大内存 | 钢琴烤漆', 'public/imgs/appliance/MiTv-4X-43.png', 1499.00, 1299.00, 10, 0),
(null, '小米电视4C 55英寸', 2, '4K HDR,人工智能系统', '人工智能 | 大内存 | 杜比音效 | 超窄边 | 4K HDR | 海量片源 | 纤薄机身| 钢琴烤漆', 'public/imgs/appliance/MiTv-4C-55.png', 1999.00, 1799.00, 10, 0),
(null, '小米电视4A 65英寸', 2, '4K HDR,人工智能系统', '人工智能 | 大内存 | 杜比音效 | 超窄边 | 4K HDR | 海量片源 | 纤薄机身| 钢琴烤漆', 'public/imgs/appliance/MiTv-4A-65.png', 2999.00, 2799.00, 10, 0),
(null, '小米壁画电视 65英寸', 2, '壁画外观,全面屏,远场语音', '纯平背板 | 通体13.9mm | 远场语音 | 4K+HDR | 杜比+DTS | 画框模式 | 内置小爱同学 | PatchWall | SoundBar+低音炮 | 四核处理器+大存储', 'public/imgs/appliance/MiTv-ArtTv-65.png', 6999.00, 6999.00, 10, 0);

insert into product
values
(null, '米家互联网空调C1(一级能效)', 3, '变频节能省电,自清洁', '一级能效 | 1.5匹 | 全直流变频 | 高效制冷/热 | 静音设计 | 自清洁 | 全屋互联', 'public/imgs/appliance/AirCondition-V1C1.png', 2699.00, 2599.00, 20, 10),
(null, '米家空调', 3, '出众静音,快速制冷热', '大1匹 | 三级能效 | 静音 | 快速制冷热 | 广角送风 | 除湿功能 | 高密度过滤网 | 典雅外观', 'public/imgs/appliance/AirCondition-F3W1.png', 1799.00, 1699.00, 20, 8);

insert into product
values
(null, '米家互联网洗烘一体机 Pro 10kg', 4, '智能洗烘,省心省力', '国标双A+级洗烘能力 / 22种洗烘模式 / 智能投放洗涤剂 / 支持小爱同学语音遥控 / 支持OTA在线智能升级 / 智能空气洗 / 除菌率达99.9%+', 'public/imgs/appliance/Washer-Pro-10.png', 2999.00, 2999.00, 20, 7);

insert into product
values
(null, 'Redmi K20/ K20 Pro 怪力魔王保护壳', 5, '怪力魔王专属定制', '优选PC材料,强韧张力,经久耐用 / 精选开孔,全面贴合机身 / 手感轻薄细腻,舒适无负担 / 三款颜色可选,彰显个性,与众不同', 'public/imgs/accessory/protectingShell-RedMi-K20&pro.png', 39.00, 39.00, 20, 10),
(null, '小米9 ARE U OK保护壳', 5, '一个与众不同的保护壳', '彰显独特个性 / 轻薄无负担 / 优选PC材料 / 贴合机身 / 潮流五色', 'public/imgs/accessory/protectingShell-Mi-9.png', 49.00, 39.00, 20, 10);

insert into product
values
(null, '小米CC9&小米CC9美图定制版 标准高透贴膜', 6, '高清透亮,耐磨性强', '耐磨性强,防护更出众 / 疏油疏水,有效抗水抗脏污 / 高清透亮,保留了原生屏幕的亮丽颜色和清晰度 / 操作灵敏,智能吸附 / 进口高端PET材质,裸机般手感', 'public/imgs/accessory/protectingMen-Mi-CC9.png', 19.00, 19.00, 20, 9),
(null, '小米CC9e 标准高透贴膜', 6, '高清透亮,耐磨性强', '耐磨性强,防护更出众 / 疏油疏水,有效抗水抗脏污 / 高清透亮,保留了原生屏幕的亮丽颜色和清晰度 / 操作灵敏,智能吸附 / 进口高端PET材质,裸机般手感', 'public/imgs/accessory/protectingMen-Mi-CC9e.png', 19.00, 19.00, 20, 9);

insert into product
values
(null, '小米USB充电器30W快充版(1A1C)', 7, '多一种接口,多一种选择', '双口输出 / 30W 输出 / 可折叠插脚 / 小巧便携', 'public/imgs/accessory/charger-30w.png', 59.00, 59.00, 20, 8),
(null, '小米USB充电器快充版(18W)', 7, '安卓、苹果设备均可使用', '支持QC3.0设备充电 / 支持iOS设备充电/ 美观耐用', 'public/imgs/accessory/charger-18w.png', 29.00, 29.00, 20, 8),
(null, '小米USB充电器60W快充版(6口)', 7, '6口输出,USB-C输出接口', '6口输出 / USB-C输出接口 / 支持QC3.0快充协议 / 总输出功率60W', 'public/imgs/accessory/charger-60w.png', 129.00, 129.00, 20, 0),
(null, '小米USB充电器36W快充版(2口)', 7, '6多重安全保护,小巧便携', '双USB输出接口 / 支持QC3.0快充协议 / 多重安全保护 / 小巧便携', 'public/imgs/accessory/charger-36w.png', 59.00, 59.00, 20, 0),
(null, '小米车载充电器快充版', 7, '让爱车成为移动充电站', 'QC3.0 双口输出 / 智能温度控制 / 5重安全保护 / 兼容iOS&Android设备', 'public/imgs/accessory/charger-car.png', 69.00, 69.00, 20, 0),
(null, '小米车载充电器快充版(37W)', 7, '双口快充,车载充电更安全', '单口27W 快充 / 双口输出 / 多重安全保护', 'public/imgs/accessory/charger-car-37w.png', 49.00, 49.00, 20, 0),
(null, '小米二合一移动电源(充电器)', 7, '一个设备多种用途', '5000mAh充沛电量 / 多协议快充 / USB 口输出', 'public/imgs/accessory/charger-tio.png', 99.00, 99.00, 20, 0);

insert into product
values
(null, '小米无线充电宝青春版10000mAh', 8, '能量满满,无线有线都能充', '10000mAh大容量 / 支持边充边放 / 有线无线都能充 / 双向快充', 'public/imgs/accessory/charger-10000mAh.png', 129.00, 129.00, 20, 8);

insert into product
values
(null, '小米CC9 Pro/尊享版 撞色飘带保护壳', 5, '全面贴合,无感更舒适', '优选环保PC材质,强韧张力,全面贴合,无感更舒适', 'public/imgs/accessory/protectingShell-Mi-CC9Pro.png', 69.00, 69.00, 20, 0),
(null, 'Redmi K20系列 幻境之心保护壳', 5, '柔软坚韧,全面贴合', '优质环保材质,柔软坚韧 / 全面贴合,有效抵抗灰尘 / 鲜亮三种颜色可选,为爱机随时换装', 'public/imgs/accessory/protectingShell-RedMi-K20.png', 39.00, 39.00, 20, 0),
(null, '小米9 SE 街头风保护壳黑色', 5, '个性时尚,细节出众', '个性时尚 / 细节出众 / 纤薄轻巧 / 多彩时尚', 'public/imgs/accessory/protectingShell-Mi-9SE.png', 49.00, 49.00, 20, 0),
(null, '小米9 街头风保护壳 红色', 5, '个性时尚,细节出众', '时尚多彩 / 细节出众 / 纤薄轻巧 / 是腕带也是支架', 'public/imgs/accessory/protectingShell-Mi-9-red.png', 49.00, 49.00, 20, 0),
(null, '小米MIX 3 极简保护壳蓝色', 5, '时尚简约设计,手感细腻顺滑', '时尚简约设计,手感细腻顺滑 / 优质环保PC原材料,强韧张力,经久耐用 / 超薄 0.8MM厚度', 'public/imgs/accessory/protectingShell-Mix-3.png', 49.00, 12.90, 20, 0);

insert into product_picture
values
(null, 1, "public/imgs/phone/picture/Redmi-k30-1.png", null),
(null, 1, "public/imgs/phone/picture/Redmi-k30-2.png", null),
(null, 1, "public/imgs/phone/picture/Redmi-k30-3.png", null),
(null, 1, "public/imgs/phone/picture/Redmi-k30-4.png", null),
(null, 1, "public/imgs/phone/picture/Redmi-k30-5.png", null);

insert into product_picture
values
(null, 2, "public/imgs/phone/picture/Redmi K30 5G-1.jpg", null),
(null, 2, "public/imgs/phone/picture/Redmi K30 5G-2.jpg", null),
(null, 2, "public/imgs/phone/picture/Redmi K30 5G-3.jpg", null),
(null, 2, "public/imgs/phone/picture/Redmi K30 5G-4.jpg", null),
(null, 2, "public/imgs/phone/picture/Redmi K30 5G-5.jpg", null);

insert into product_picture
values
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-1.jpg", null),
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-2.jpg", null),
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-3.jpg", null),
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-4.jpg", null),
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-5.jpg", null),
(null, 3, "public/imgs/phone/picture/MI CC9 Pro-6.jpg", null);

insert into product_picture
values
(null, 4, "public/imgs/phone/picture/Redmi 8-1.jpg", null),
(null, 4, "public/imgs/phone/picture/Redmi 8-2.jpg", null),
(null, 4, "public/imgs/phone/picture/Redmi 8-3.jpg", null),
(null, 4, "public/imgs/phone/picture/Redmi 8-4.jpg", null),
(null, 4, "public/imgs/phone/picture/Redmi 8-5.jpg", null);

insert into product_picture
values
(null, 5, "public/imgs/phone/picture/Redmi 8A-1.jpg", null);

insert into product_picture
values
(null, 6, "public/imgs/phone/picture/Redmi Note8 Pro-1.png", null),
(null, 6, "public/imgs/phone/picture/Redmi Note8 Pro-2.png", null),
(null, 6, "public/imgs/phone/picture/Redmi Note8 Pro-3.png", null),
(null, 6, "public/imgs/phone/picture/Redmi Note8 Pro-4.png", null),
(null, 6, "public/imgs/phone/picture/Redmi Note8 Pro-5.png", null);

insert into product_picture
values
(null, 7, "public/imgs/phone/picture/Redmi Note8-1.jpg", null),
(null, 7, "public/imgs/phone/picture/Redmi Note8-2.jpg", null),
(null, 7, "public/imgs/phone/picture/Redmi Note8-3.jpg", null),
(null, 7, "public/imgs/phone/picture/Redmi Note8-4.jpg", null),
(null, 7, "public/imgs/phone/picture/Redmi Note8-5.jpg", null);

insert into product_picture
values
(null, 8, "public/imgs/phone/picture/Redmi 7A-1.jpg", null),
(null, 8, "public/imgs/phone/picture/Redmi 7A-2.jpg", null),
(null, 8, "public/imgs/phone/picture/Redmi 7A-3.jpg", null),
(null, 8, "public/imgs/phone/picture/Redmi 7A-4.jpg", null),
(null, 8, "public/imgs/phone/picture/Redmi 7A-5.jpg", null);

insert into product_picture
values
(null, 9, "public/imgs/phone/picture/MiTv-4A-32-1.jpg", null),
(null, 9, "public/imgs/phone/picture/MiTv-4A-32-2.jpg", null),
(null, 9, "public/imgs/phone/picture/MiTv-4A-32-3.jpg", null),
(null, 9, "public/imgs/phone/picture/MiTv-4A-32-4.jpg", null);

insert into product_picture
values
(null, 10, "public/imgs/phone/picture/MiTv-E55A-1.jpg", null),
(null, 10, "public/imgs/phone/picture/MiTv-E55A-2.jpg", null),
(null, 10, "public/imgs/phone/picture/MiTv-E55A-3.jpg", null),
(null, 10, "public/imgs/phone/picture/MiTv-E55A-4.jpg", null);

insert into product_picture
values
(null, 11, "public/imgs/phone/picture/MiTv-E65A-1.jpg", null),
(null, 11, "public/imgs/phone/picture/MiTv-E65A-2.jpg", null),
(null, 11, "public/imgs/phone/picture/MiTv-E65A-3.jpg", null),
(null, 11, "public/imgs/phone/picture/MiTv-E65A-4.jpg", null);

insert into product_picture
values
(null, 12, "public/imgs/phone/picture/MiTv-4X 43-1.jpg", null),
(null, 12, "public/imgs/phone/picture/MiTv-4X 43-2.jpg", null),
(null, 12, "public/imgs/phone/picture/MiTv-4X 43-3.jpg", null);

insert into product_picture
values
(null, 13, "public/imgs/phone/picture/MiTv-4C 55-1.jpg", null),
(null, 13, "public/imgs/phone/picture/MiTv-4C 55-2.jpg", null),
(null, 13, "public/imgs/phone/picture/MiTv-4C 55-3.jpg", null);

insert into product_picture
values
(null, 14, "public/imgs/phone/picture/MiTv-4A 65-1.jpg", null);

insert into product_picture
values
(null, 15, "public/imgs/phone/picture/MiTv-ArtTv-65-1.jpg", null);

insert into product_picture
values
(null, 16, "public/imgs/phone/picture/AirCondition-V1C1-1.jpg", null);

insert into product_picture
values
(null, 17, "public/imgs/phone/picture/AirCondition-F3W1-1.jpg", null);

insert into product_picture
values
(null, 18, "public/imgs/phone/picture/Washer-Pro-10-1.jpg", null),
(null, 18, "public/imgs/phone/picture/Washer-Pro-10-2.jpg", null),
(null, 18, "public/imgs/phone/picture/Washer-Pro-10-3.jpg", null),
(null, 18, "public/imgs/phone/picture/Washer-Pro-10-4.jpg", null);

insert into product_picture
values
(null, 19, "public/imgs/phone/picture/protectingShell-RedMi-K20&pro-1.jpg", null);

insert into product_picture
values
(null, 20, "public/imgs/phone/picture/protectingShell-Mi-9-1.jpg", null),
(null, 20, "public/imgs/phone/picture/protectingShell-Mi-9-2.jpg", null);

insert into product_picture
values
(null, 21, "public/imgs/phone/picture/protectingMen-Mi-CC9-1.jpg", null);

insert into product_picture
values
(null, 22, "public/imgs/phone/picture/protectingMen-Mi-CC9e-1.jpg", null);

insert into product_picture
values
(null, 23, "public/imgs/phone/picture/charger-30w-1.jpg", null),
(null, 23, "public/imgs/phone/picture/charger-30w-2.jpg", null),
(null, 23, "public/imgs/phone/picture/charger-30w-3.jpg", null),
(null, 23, "public/imgs/phone/picture/charger-30w-4.jpg", null);

insert into product_picture
values
(null, 24, "public/imgs/phone/picture/charger-18w-1.jpg", null),
(null, 24, "public/imgs/phone/picture/charger-18w-2.jpg", null),
(null, 24, "public/imgs/phone/picture/charger-18w-3.jpg", null);

insert into product_picture
values
(null, 25, "public/imgs/phone/picture/charger-60w-1.jpg", null),
(null, 25, "public/imgs/phone/picture/charger-60w-2.jpg", null),
(null, 25, "public/imgs/phone/picture/charger-60w-3.jpg", null),
(null, 25, "public/imgs/phone/picture/charger-60w-4.jpg", null);

insert into product_picture
values
(null, 26, "public/imgs/phone/picture/charger-36w-1.jpg", null),
(null, 26, "public/imgs/phone/picture/charger-36w-2.jpg", null),
(null, 26, "public/imgs/phone/picture/charger-36w-3.jpg", null),
(null, 26, "public/imgs/phone/picture/charger-36w-4.jpg", null),
(null, 26, "public/imgs/phone/picture/charger-36w-5.jpg", null);

insert into product_picture
values
(null, 27, "public/imgs/phone/picture/charger-car-1.jpg", null),
(null, 27, "public/imgs/phone/picture/charger-car-2.jpg", null),
(null, 27, "public/imgs/phone/picture/charger-car-3.jpg", null),
(null, 27, "public/imgs/phone/picture/charger-car-4.jpg", null),
(null, 27, "public/imgs/phone/picture/charger-car-5.jpg", null),
(null, 27, "public/imgs/phone/picture/charger-car-6.jpg", null);

insert into product_picture
values
(null, 28, "public/imgs/phone/picture/charger-car-37w-1.jpg", null),
(null, 28, "public/imgs/phone/picture/charger-car-37w-2.jpg", null),
(null, 28, "public/imgs/phone/picture/charger-car-37w-3.jpg", null),
(null, 28, "public/imgs/phone/picture/charger-car-37w-4.jpg", null),
(null, 28, "public/imgs/phone/picture/charger-car-37w-5.jpg", null);

insert into product_picture
values
(null, 29, "public/imgs/phone/picture/charger-tio-1.jpg", null),
(null, 29, "public/imgs/phone/picture/charger-tio-2.jpg", null),
(null, 29, "public/imgs/phone/picture/charger-tio-3.jpg", null),
(null, 29, "public/imgs/phone/picture/charger-tio-4.jpg", null),
(null, 29, "public/imgs/phone/picture/charger-tio-5.jpg", null);

insert into product_picture
values
(null, 30, "public/imgs/phone/picture/charger-10000mAh-1.jpg", null),
(null, 30, "public/imgs/phone/picture/charger-10000mAh-2.jpg", null),
(null, 30, "public/imgs/phone/picture/charger-10000mAh-3.jpg", null),
(null, 30, "public/imgs/phone/picture/charger-10000mAh-4.jpg", null),
(null, 30, "public/imgs/phone/picture/charger-10000mAh-5.jpg", null);

insert into product_picture
values
(null, 31, "public/imgs/phone/picture/protectingShell-Mi-CC9Pro-1.jpg", null);

insert into product_picture
values
(null, 32, "public/imgs/phone/picture/protectingShell-RedMi-K20-1.jpg", null);

insert into product_picture
values
(null, 33, "public/imgs/phone/picture/protectingShell-Mi-9SE-1.jpg", null);

insert into product_picture
values
(null, 34, "public/imgs/phone/picture/protectingShell-Mi-9-red-1.jpg", null);

insert into product_picture
values
(null, 35, "public/imgs/phone/picture/protectingShell-Mix-3-1.jpg", null);

+ 50
- 0
app.js View File

@@ -0,0 +1,50 @@
/*
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 23:40:51
*/
const Koa = require('koa');
const KoaStatic = require('koa-static');
const KoaBody = require('koa-body');
const Session = require('koa-session');

let { Port, staticDir } = require('./config');

let app = new Koa();

// 处理异常
const error = require('./app/middleware/error');
app.use(error);

// 为静态资源请求重写url
const rewriteUrl = require('./app/middleware/rewriteUrl');
app.use(rewriteUrl);
// 使用koa-static处理静态资源
app.use(KoaStatic(staticDir));

// session
const CONFIG = require('./app/middleware/session');
app.keys = ['session app keys'];
app.use(Session(CONFIG, app));

// 判断是否登录
const isLogin = require('./app/middleware/isLogin');
app.use(isLogin);

app.use(async (ctx, next) => {
ctx.state.user = ctx.session.user;
await next();
});

// 处理请求体数据
const koaBodyConfig = require('./app/middleware/koaBodyConfig');
app.use(KoaBody(koaBodyConfig));

// 使用路由中间件
const Routers = require('./app/routers');
app.use(Routers.routes()).use(Routers.allowedMethods());

app.listen(Port, () => {
console.log(`服务器启动在${ Port }端口`);
});

+ 131
- 0
app/controllers/collectController.js View File

@@ -0,0 +1,131 @@
/*
* @Description: 我的收藏模块控制器
* @Author: hai-27
* @Date: 2020-03-04 22:30:31
* @LastEditors: hai-27
* @LastEditTime: 2020-03-04 23:32:23
*/
const collectDao = require('../models/dao/collectDao');
const productDao = require('../models/dao/productDao');
const checkLogin = require('../middleware/checkLogin');

module.exports = {
/**
* 添加收藏
* @param {Object} ctx
*/
AddCollect: async ctx => {
let { user_id, product_id } = ctx.request.body;

// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}

// 判断该用户的收藏列表是否存在该商品
let tempCollect = await collectDao.FindCollect(user_id, product_id);

if (tempCollect.length > 0) {
ctx.body = {
code: '003',
msg: '该商品已经添加收藏,请到我的收藏查看'
}
return;
}

// 获取当前时间戳
const timeTemp = new Date().getTime();
try {
// 把收藏商品信息插入数据库
const result = await collectDao.AddCollect(user_id, product_id, timeTemp);
// 插入成功
if (result.affectedRows === 1) {
ctx.body = {
code: '001',
msg: '添加收藏成功'
}
return;
}
} catch (error) {
reject(error);
}

ctx.body = {
code: '002',
msg: '添加收藏失败'
}
},
/**
* 获取用户的所有收藏商品信息
* @param {Object} ctx
*/
GetCollect: async ctx => {
let { user_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}
// 获取所有收藏信息
const collect = await collectDao.GetCollect(user_id);

// 该用户没有收藏的商品,直接返回信息
if (collect.length == 0) {
ctx.body = {
code: '002',
msg: '该用户没有收藏的商品'
}
return;
}

let collectList = [];
// 生成收藏商品的详细信息列表
for (let i = 0; i < collect.length; i++) {
const temp = collect[i];
// 获取每个商品详细信息
const product = await productDao.GetProductById(temp.product_id);
collectList.push(product[0]);
}

ctx.body = {
code: '001',
collectList: collectList
}
},
/**
* 删除用户的收藏商品信息
* @param {Object} ctx
*/
DeleteCollect: async ctx => {
let { user_id, product_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}

// 判断该用户的收藏列表是否存在该商品
let tempCollect = await collectDao.FindCollect(user_id, product_id);

if (tempCollect.length > 0) {
// 如果存在则删除
try {
const result = await collectDao.DeleteCollect(user_id, product_id);
// 判断是否删除成功
if (result.affectedRows === 1) {
ctx.body = {
code: '001',
msg: '删除收藏成功'
}
return;
}
} catch (error) {
reject(error);
}
} else {
// 不存在则返回信息
ctx.body = {
code: '002',
msg: '该商品不在收藏列表'
}
}
}
}

+ 126
- 0
app/controllers/orderController.js View File

@@ -0,0 +1,126 @@
/*
* @Description: 订单模块控制器
* @Author: hai-27
* @Date: 2020-02-24 16:35:22
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 14:32:16
*/
const orderDao = require('../models/dao/orderDao');
const shoppingCartDao = require('../models/dao/shoppingCartDao');
const productDao = require('../models/dao/productDao');
const checkLogin = require('../middleware/checkLogin');

module.exports = {
/**
* 获取用户的所有订单信息
* @param {Object} ctx
*/
GetOrder: async ctx => {
let { user_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}
// 获取所有的订单id
const ordersGroup = await orderDao.GetOrderGroup(user_id);

// 该用户没有订单,直接返回信息
if (ordersGroup.length == 0) {
ctx.body = {
code: '002',
msg: '该用户没有订单信息'
}
return;
}

// 获取所有的订单详细信息
const orders = await orderDao.GetOrder(user_id);

let ordersList = [];
// 生成每个订单的详细信息列表
for (let i = 0; i < ordersGroup.length; i++) {
const orderID = ordersGroup[i];
let tempOrder = [];

for (let j = 0; j < orders.length; j++) {
const order = orders[j];

if (orderID.order_id == order.order_id) {
// 获取每个商品详细信息
const product = await productDao.GetProductById(order.product_id);
order.product_name = product[0].product_name;
order.product_picture = product[0].product_picture;

tempOrder.push(order);
}
}
ordersList.push(tempOrder);
}

ctx.body = {
code: '001',
orders: ordersList
}

},
/**
* 添加用户订单信息
* @param {Object} ctx
*/
AddOrder: async (ctx) => {
let { user_id, products } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}

// 获取当前时间戳
const timeTemp = new Date().getTime();
// 生成订单id:用户id+时间戳(string)
const orderID = +("" + user_id + timeTemp);

let data = [];
// 根据数据库表结构生成字段信息
for (let i = 0; i < products.length; i++) {
const temp = products[i];
let product = [orderID, user_id, temp.productID, temp.num, temp.price, timeTemp];
data.push(...product);
}

try {
// 把订单信息插入数据库
const result = await orderDao.AddOrder(products.length, data);

// 插入成功
if (result.affectedRows == products.length) {
//删除购物车
let rows = 0;
for (let i = 0; i < products.length; i++) {
const temp = products[i];
const res = await shoppingCartDao.DeleteShoppingCart(user_id, temp.productID);
rows += res.affectedRows;
}
//判断删除购物车是否成功
if (rows != products.length) {
ctx.body = {
code: '002',
msg: '购买成功,但购物车没有更新成功'
}
return;
}

ctx.body = {
code: '001',
msg: '购买成功'
}
} else {
ctx.body = {
code: '004',
msg: '购买失败,未知原因'
}
}
} catch (error) {
reject(error);
}
}
}

+ 164
- 0
app/controllers/productController.js View File

@@ -0,0 +1,164 @@
/*
* @Description: 商品模块控制器
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 15:41:11
*/
const productDao = require('../models/dao/productDao');
module.exports = {
/**
* 获取商品分类
* @param {Object} ctx
*/
GetCategory: async ctx => {
const category = await productDao.GetCategory();

ctx.body = {
code: '001',
category
}
},
/**
* 根据商品分类名称获取首页展示的商品信息
* @param {Object} ctx
*/
GetPromoProduct: async ctx => {
let { categoryName } = ctx.request.body;
// 根据商品分类名称获取分类id
const categoryID = await productDao.GetCategoryId(categoryName);
// 根据商品分类id获取首页展示的商品信息
const Product = await productDao.GetPromoProduct(categoryID);

ctx.body = {
code: '001',
Product
}
},
/**
* 根据商品分类名称获取热门商品信息
* @param {Object} ctx
*/
GetHotProduct: async ctx => {
let { categoryName } = ctx.request.body;
const categoryID = [];

for (let i = 0; i < categoryName.length; i++) {
// 根据商品分类名称获取分类id
const category_id = await productDao.GetCategoryId(categoryName[i]);
categoryID.push(category_id);
}
// 根据商品分类id获取商品信息
const Product = await productDao.GetProductByCategory(categoryID, 0, 7);

ctx.body = {
code: '001',
Product
}
},
/**
* 分页获取所有的商品信息
* @param {Object} ctx
*/
GetAllProduct: async ctx => {
let { currentPage, pageSize } = ctx.request.body;
// 计算开始索引
const offset = (currentPage - 1) * pageSize;
const Product = await productDao.GetAllProduct(offset, pageSize);
// 获取所有的商品数量,用于前端分页计算
const total = (await productDao.GetAllProduct()).length;
ctx.body = {
code: '001',
Product,
total
}
},
/**
* 根据分类id,分页获取商品信息
* @param {Object} ctx
*/
GetProductByCategory: async ctx => {
let { categoryID, currentPage, pageSize } = ctx.request.body;
// 计算开始索引
const offset = (currentPage - 1) * pageSize;
// 分页获取该分类的商品信息
const Product = await productDao.GetProductByCategory(categoryID, offset, pageSize);
// 获取该分类所有的商品数量,用于前端分页计算
const total = (await productDao.GetProductByCategory(categoryID)).length;

ctx.body = {
code: '001',
Product,
total
}
},
/**
* 根据搜索条件,分页获取商品信息
* @param {Object} ctx
*/
GetProductBySearch: async ctx => {
let { search, currentPage, pageSize } = ctx.request.body;
// 计算开始索引
const offset = (currentPage - 1) * pageSize;
// 获取分类列表
const category = await productDao.GetCategory();

let Product;
let total;

for (let i = 0; i < category.length; i++) {
// 如果搜索条件为某个分类名称,直接返回该分类的商品信息
if (search == category[i].category_name) {
// 获取该分类的商品信息
Product = await productDao.GetProductByCategory(category[i].category_id, offset, pageSize);
// 获取该分类所有的商品数量,用于前端分页计算
total = (await productDao.GetProductByCategory(category[i].category_id)).length;

ctx.body = {
code: '001',
Product,
total
}
return;
}
}
// 否则返回根据查询条件模糊查询的商品分页结果
Product = await productDao.GetProductBySearch(search, offset, pageSize);
// 获取模糊查询的商品结果总数
total = (await productDao.GetProductBySearch(search)).length;

ctx.body = {
code: '001',
Product,
total
}
},
/**
* 根据商品id,获取商品详细信息
* @param {Object} ctx
*/
GetDetails: async ctx => {
let { productID } = ctx.request.body;

const Product = await productDao.GetProductById(productID);

ctx.body = {
code: '001',
Product,
}
},
/**
* 根据商品id,获取商品图片,用于食品详情的页面展示
* @param {Object} ctx
*/
GetDetailsPicture: async ctx => {
let { productID } = ctx.request.body;

const ProductPicture = await productDao.GetDetailsPicture(productID);

ctx.body = {
code: '001',
ProductPicture,
}
}
}

+ 21
- 0
app/controllers/resourcesController.js View File

@@ -0,0 +1,21 @@
/*
* @Description: 资源模块控制器
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 14:33:10
*/
const resourcesDao = require('../models/dao/resourcesDao');
module.exports = {
/**
* 获取轮播图数据
* @param {Object} ctx
*/
Carousel: async ctx => {
let carousel = await resourcesDao.Carousel();
ctx.body = {
code: '001',
carousel
}
}
}

+ 234
- 0
app/controllers/shoppingCartController.js View File

@@ -0,0 +1,234 @@
/*
* @Description: 购物车模块控制器
* @Author: hai-27
* @Date: 2020-02-19 16:15:14
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 15:58:46
*/
const shoppingCartDao = require('../models/dao/shoppingCartDao');
const productDao = require('../models/dao/productDao');
const checkLogin = require('../middleware/checkLogin');

let methods = {
/**
* 生成购物车详细信息
* @param {Object} data
*/
ShoppingCartData: async data => {
let shoppingCartData = [];
for (let i = 0; i < data.length; i++) {
const temp = data[i];
const product = await productDao.GetProductById(temp.product_id);

let shoppingCartDataTemp = {
id: temp.id,
productID: temp.product_id,
productName: product[0].product_name,
productImg: product[0].product_picture,
price: product[0].product_selling_price,
num: temp.num,
maxNum: Math.floor(product[0].product_num / 2),
check: false
};

shoppingCartData.push(shoppingCartDataTemp);
}
return shoppingCartData;
}
}

module.exports = {
/**
* 获取购物车信息
* @param {Object} ctx
*/
GetShoppingCart: async ctx => {
let { user_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}
// 获取购物车信息
const shoppingCart = await shoppingCartDao.GetShoppingCart(user_id);
// 生成购物车详细信息
const data = await methods.ShoppingCartData(shoppingCart);

ctx.body = {
code: '001',
shoppingCartData: data
}
},
/**
* 插入购物车信息
* @param {Object} ctx
*/
AddShoppingCart: async ctx => {
let { user_id, product_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}

let tempShoppingCart = await shoppingCartDao.FindShoppingCart(user_id, product_id);
//判断该用户的购物车是否存在该商品
if (tempShoppingCart.length > 0) {
//如果存在则把数量+1
const tempNum = tempShoppingCart[0].num + 1;

const product = await productDao.GetProductById(tempShoppingCart[0].product_id);
const maxNum = Math.floor(product[0].product_num / 2);
//判断数量是否达到限购数量
if (tempNum > maxNum) {
ctx.body = {
code: '003',
msg: '数量达到限购数量 ' + maxNum
}
return;
}

try {
// 更新购物车信息,把数量+1
const result = await shoppingCartDao.UpdateShoppingCart(tempNum, user_id, product_id);

if (result.affectedRows === 1) {
ctx.body = {
code: '002',
msg: '该商品已在购物车,数量 +1'
}
return;
}
} catch (error) {
reject(error);
}
} else {
//不存在则添加
try {
// 新插入购物车信息
const res = await shoppingCartDao.AddShoppingCart(user_id, product_id);
// 判断是否插入成功
if (res.affectedRows === 1) {
// 如果成功,获取该商品的购物车信息
const shoppingCart = await shoppingCartDao.FindShoppingCart(user_id, product_id);
// 生成购物车详细信息
const data = await methods.ShoppingCartData(shoppingCart);

ctx.body = {
code: '001',
msg: '添加购物车成功',
shoppingCartData: data
}
return;
}
} catch (error) {
reject(error);
}
}

ctx.body = {
code: '005',
msg: '添加购物车失败,未知错误'
}
},
/**
* 删除购物车信息
* @param {Object} ctx
*/
DeleteShoppingCart: async ctx => {
let { user_id, product_id } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}

// 判断该用户的购物车是否存在该商品
let tempShoppingCart = await shoppingCartDao.FindShoppingCart(user_id, product_id);

if (tempShoppingCart.length > 0) {
// 如果存在则删除
try {
const result = await shoppingCartDao.DeleteShoppingCart(user_id, product_id);
// 判断是否删除成功
if (result.affectedRows === 1) {
ctx.body = {
code: '001',
msg: '删除购物车成功'
}
return;
}
} catch (error) {
reject(error);
}
} else {
// 不存在则返回信息
ctx.body = {
code: '002',
msg: '该商品不在购物车'
}
}
},
/**
* 更新购物车商品数量
* @param {Object} ctx
*/
UpdateShoppingCart: async ctx => {
let { user_id, product_id, num } = ctx.request.body;
// 校验用户是否登录
if (!checkLogin(ctx, user_id)) {
return;
}
// 判断数量是否小于1
if (num < 1) {
ctx.body = {
code: '004',
msg: '数量不合法'
}
return;
}
// 判断该用户的购物车是否存在该商品
let tempShoppingCart = await shoppingCartDao.FindShoppingCart(user_id, product_id);

if (tempShoppingCart.length > 0) {
// 如果存在则修改

// 判断数量是否有变化
if (tempShoppingCart[0].num == num) {
ctx.body = {
code: '003',
msg: '数量没有发生变化'
}
return;
}
const product = await productDao.GetProductById(product_id);
const maxNum = Math.floor(product[0].product_num / 2);
// 判断数量是否达到限购数量
if (num > maxNum) {
ctx.body = {
code: '004',
msg: '数量达到限购数量 ' + maxNum
}
return;
}

try {
// 修改购物车信息
const result = await shoppingCartDao.UpdateShoppingCart(num, user_id, product_id);
// 判断是否修改成功
if (result.affectedRows === 1) {
ctx.body = {
code: '001',
msg: '修改购物车数量成功'
}
return;
}
} catch (error) {
reject(error);
}
} else {
//不存在则返回信息
ctx.body = {
code: '002',
msg: '该商品不在购物车'
}
}
}
}

+ 217
- 0
app/controllers/userController.js View File

@@ -0,0 +1,217 @@
/*
* @Description: 用户模块控制器
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-03-27 16:03:09
*/
const rp = require('request-promise');
const userDao = require('../models/dao/userDao');
const { checkUserInfo, checkUserName } = require('../middleware/checkUserInfo');

module.exports = {

/**
* 用户登录
* @param {Object} ctx
*/
Login: async ctx => {

let { userName, password } = ctx.request.body;

// 校验用户信息是否符合规则
if (!checkUserInfo(ctx, userName, password)) {
return;
}

// 连接数据库根据用户名和密码查询用户信息
let user = await userDao.Login(userName, password);
// 结果集长度为0则代表没有该用户
if (user.length === 0) {
ctx.body = {
code: '004',
msg: '用户名或密码错误'
}
return;
}

// 数据库设置用户名唯一
// 结果集长度为1则代表存在该用户
if (user.length === 1) {

const loginUser = {
user_id: user[0].user_id,
userName: user[0].userName
};
// 保存用户信息到session
ctx.session.user = loginUser;

ctx.body = {
code: '001',
user: loginUser,
msg: '登录成功'
}
return;
}

//数据库设置用户名唯一
//若存在user.length != 1 || user.length!=0
//返回未知错误
//正常不会出现
ctx.body = {
code: '500',
msg: '未知错误'
}
},
/**
* 微信小程序用户登录
* @param {Object} ctx
*/
miniProgramLogin: async ctx => {
const appid = 'wxeb6a44c58ffde6c6';
const secret = '9c40f33cf627f2e3a42f38b25e0687cc';
let { code } = ctx.request.body;

const api = `https://api.weixin.qq.com/sns/jscode2session?appid=${ appid }&secret=${ secret }&js_code=${ code }&grant_type=authorization_code`;
// 通过 wx.login 接口获得临时登录凭证 code 后
// 传到开发者服务器调用此接口完成登录流程。
const res = await rp.get({
json: true,
uri: api
})
const { session_key, openid } = res;

// 连接数据库根据用户名查询用户信息
let user = await userDao.FindUserName(openid);
if (user.length === 0) {
// 结果集长度为0则代表不存在该用户,先注册
try {
// 连接数据库插入用户信息
let registerResult = await userDao.Register(openid, openid);
if (registerResult.affectedRows === 1) {
// 操作所影响的记录行数为1,则代表注册成功
await login();// 登录
}
} catch (error) {
console.log(error)
}
} else if (user.length === 1) {
// 如果已经存在,直接登录
await login();
} else {
ctx.body = {
code: '500',
msg: '未知错误'
}
}
async function login () {
// 连接数据库根据用户名和密码查询用户信息
let tempUser = await userDao.Login(openid, openid);
if (tempUser.length === 0) {
// 登录失败
ctx.body = {
code: '004',
msg: '登录失败'
}
return;
}
if (tempUser.length === 1) {
// 登录成功
const loginUser = {
user_id: tempUser[0].user_id,
openId: openid,
sessionKey: session_key
};
// 保存用户信息到session
ctx.session.user = loginUser;

ctx.body = {
code: '001',
userId: tempUser[0].user_id,
msg: '登录成功'
}
return;
}
}
},
/**
* 查询是否存在某个用户名,用于注册时前端校验
* @param {Object} ctx
*/
FindUserName: async ctx => {
let { userName } = ctx.request.body;

// 校验用户名是否符合规则
if (!checkUserName(ctx, userName)) {
return;
}
// 连接数据库根据用户名查询用户信息
let user = await userDao.FindUserName(userName);
// 结果集长度为0则代表不存在该用户,可以注册
if (user.length === 0) {
ctx.body = {
code: '001',
msg: '用户名不存在,可以注册'
}
return;
}

//数据库设置用户名唯一
//结果集长度为1则代表存在该用户,不可以注册
if (user.length === 1) {
ctx.body = {
code: '004',
msg: '用户名已经存在,不能注册'
}
return;
}

//数据库设置用户名唯一,
//若存在user.length != 1 || user.length!=0
//返回未知错误
//正常不会出现
ctx.body = {
code: '500',
msg: '未知错误'
}
},
Register: async ctx => {
let { userName, password } = ctx.request.body;

// 校验用户信息是否符合规则
if (!checkUserInfo(ctx, userName, password)) {
return;
}
// 连接数据库根据用户名查询用户信息
// 先判断该用户是否存在
let user = await userDao.FindUserName(userName);

if (user.length !== 0) {
ctx.body = {
code: '004',
msg: '用户名已经存在,不能注册'
}
return;
}

try {
// 连接数据库插入用户信息
let registerResult = await userDao.Register(userName, password);
// 操作所影响的记录行数为1,则代表注册成功
if (registerResult.affectedRows === 1) {
ctx.body = {
code: '001',
msg: '注册成功'
}
return;
}
// 否则失败
ctx.body = {
code: '500',
msg: '未知错误,注册失败'
}
} catch (error) {
reject(error);
}
}
};

+ 13
- 0
app/middleware/RewriteUrl.js View File

@@ -0,0 +1,13 @@
/*
* @Description: 重写静态资源URL
* @Author: hai-27
* @Date: 2020-04-07 23:24:37
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 23:26:37
*/
module.exports = async (ctx, next) => {
if (ctx.url.startsWith('/public')) {
ctx.url = ctx.url.replace('/public', '');
}
await next();
}

+ 25
- 0
app/middleware/checkLogin.js View File

@@ -0,0 +1,25 @@
/*
* @Description: 判断是否登录(session中的用户id与请求体传过来的用户id是否一致)
* @Author: hai-27
* @Date: 2020-02-25 15:35:58
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 01:59:46
*/

/**
* 校验用户是否登录
* @param {Object} ctx
* @param {int} user_id
* @returns
*/
module.exports = function (ctx, user_id) {
// 判断请求传递的用户id 与 session中的用户id是否一致
if (user_id != ctx.session.user.user_id) {
ctx.body = {
code: '401',
msg: '用户名没有登录,请登录后再操作'
}
return false;
}
return true;
}

+ 74
- 0
app/middleware/checkUserInfo.js View File

@@ -0,0 +1,74 @@
/*
* @Description: 校验用户信息是否符合规则
* @Author: hai-27
* @Date: 2020-02-25 15:43:27
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 02:04:35
*/
module.exports = {
/**
* 校验用户信息是否符合规则
* @param {Object} ctx
* @param {string} userName
* @param {string} password
* @return:
*/
checkUserInfo: (ctx, userName = '', password = '') => {
// userName = userName ? userName : '';
// password = password ? password : '';
// 判断是否为空
if (userName.length === 0 || password.length === 0) {
ctx.body = {
code: '002',
msg: '用户名或密码不能为空'
}
return false;
}
// 用户名校验规则
const userNameRule = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/;
if (!userNameRule.test(userName)) {
ctx.body = {
code: '003',
msg: '用户名不合法(以字母开头,允许5-16字节,允许字母数字下划线)'
}
return false;
}
// 密码校验规则
const passwordRule = /^[a-zA-Z]\w{5,17}$/;
if (!passwordRule.test(password)) {
ctx.body = {
code: '003',
msg: '密码不合法(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)'
}
return false;
}

return true;
},
/**
* 校验用户名是否符合规则
* @param {type}
* @return:
*/
checkUserName: (ctx, userName = '') => {
// 判断是否为空
if (userName.length === 0) {
ctx.body = {
code: '002',
msg: '用户名不能为空'
}
return false;
}
// 用户名校验规则
const userNameRule = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/;
if (!userNameRule.test(userName)) {
ctx.body = {
code: '003',
msg: '用户名不合法(以字母开头,允许5-16字节,允许字母数字下划线)'
}
return false;
}

return true;
}
}

+ 18
- 0
app/middleware/error.js View File

@@ -0,0 +1,18 @@
/*
* @Description: 全局错误处理中间件
* @Author: hai-27
* @Date: 2020-04-07 23:11:48
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 23:13:33
*/
module.exports = async (ctx, next) => {
try {
await next();
} catch (error) {
console.log(error);
ctx.body = {
code: '500',
msg: '服务器未知错误'
}
}
}

+ 19
- 0
app/middleware/isLogin.js View File

@@ -0,0 +1,19 @@
/*
* @Description: 全局登录拦截器
* @Author: hai-27
* @Date: 2020-04-07 22:42:36
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:44:52
*/
module.exports = async (ctx, next) => {
if (ctx.url.startsWith('/user/')) {
if (!ctx.session.user) {
ctx.body = {
code: '401',
msg: '用户没有登录,请登录后再操作'
}
return;
}
}
await next();
}

+ 25
- 0
app/middleware/koaBodyConfig.js View File

@@ -0,0 +1,25 @@
/*
* @Description: koaBody 配置
* @Author: hai-27
* @Date: 2020-04-07 23:18:29
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 23:21:35
*/
let { uploadDir } = require('../../config');

const koaBodyConfig = {
multipart: true,
// parsedMethods默认是['POST', 'PUT', 'PATCH']
parsedMethods: ['POST', 'PUT', 'PATCH', 'GET', 'HEAD', 'DELETE'],
formidable: {
uploadDir: uploadDir, // 设置文件上传目录
keepExtensions: true, // 保持文件的后缀
maxFieldsSize: 2 * 1024 * 1024, // 文件上传大小限制
onFileBegin: (name, file) => { // 文件上传前的设置
// console.log(`name: ${name}`);
// console.log(file);
}
}
}

module.exports = koaBodyConfig;

+ 33
- 0
app/middleware/session.js View File

@@ -0,0 +1,33 @@
/*
* @Description: session配置
* @Author: hai-27
* @Date: 2020-04-07 22:28:43
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:29:28
*/
let store = {
storage: {},
set (key, session) {
this.storage[key] = session;
},
get (key) {
return this.storage[key];
},
destroy (key) {
delete this.storage[key];
}
}
let CONFIG = {
key: 'koa:session',
maxAge: 86400000,
autoCommit: true,
overwrite: true,
httpOnly: true,
signed: true,
rolling: false,
renew: false,
sameSite: null,
store
}

module.exports = CONFIG;

+ 31
- 0
app/models/dao/collectDao.js View File

@@ -0,0 +1,31 @@
/*
* @Description: 我的收藏模块数据持久层
* @Author: hai-27
* @Date: 2020-03-04 22:33:56
* @LastEditors: hai-27
* @LastEditTime: 2020-03-10 17:50:37
*/
const db = require('./db.js');

module.exports = {
// 连接数据库,把收藏商品信息插入数据库
AddCollect: async (user_id, product_id, timeTemp) => {
const sql = 'insert into collect values(null,?,?,?)';
return await db.query(sql, [user_id, product_id, timeTemp]);
},
// 连接数据库,获取用户的所有收藏商品信息
GetCollect: async (user_id) => {
const sql = 'select * from collect where user_id=?';
return await db.query(sql, user_id);
},
// 连接数据库,获取用户的某个收藏商品信息
FindCollect: async (user_id, product_id) => {
const sql = 'select * from collect where user_id=? and product_id=?';
return await db.query(sql, [user_id, product_id]);
},
// 连接数据库,删除用户的某个收藏商品信息
DeleteCollect: async (user_id, product_id) => {
const sql = 'delete from collect where user_id=? and product_id=?';
return await db.query(sql, [user_id, product_id]);
}
}

+ 40
- 0
app/models/dao/db.js View File

@@ -0,0 +1,40 @@
/*
* @Description: 数据库连接
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 13:20:11
*/
var mysql = require('mysql');
const { dbConfig } = require('../../../config');
var pool = mysql.createPool(dbConfig);

var db = {};

db.query = function (sql, params) {

return new Promise((resolve, reject) => {
// 取出链接
pool.getConnection(function (err, connection) {

if (err) {
reject(err);
return;
}

connection.query(sql, params, function (error, results, fields) {
console.log(`${ sql }=>${ params }`);
// 释放连接
connection.release();
if (error) {
reject(error);
return;
}
resolve(results);
});

});
});
}
// 导出对象
module.exports = db;

+ 30
- 0
app/models/dao/orderDao.js View File

@@ -0,0 +1,30 @@
/*
* @Description: 订单模块数据持久层
* @Author: hai-27
* @Date: 2020-02-24 16:36:19
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 14:31:56
*/
const db = require('./db.js');

module.exports = {
// 连接数据库获取所有的订单id
GetOrderGroup: async (user_id) => {
let sql = 'select order_id from orders where user_id = ? group by order_id desc';
return await db.query(sql, user_id);
},
// 连接数据库获取所有的订单详细信息
GetOrder: async (user_id) => {
let sql = 'select * from orders where user_id =? order by order_time desc';
return await db.query(sql, user_id);
},
// 连接数据库插入订单信息
AddOrder: async (length, data) => {
let sql = 'insert into orders values(null,?,?,?,?,?,?)';
for (let i = 0; i < length - 1; i++) {
sql += ",(null,?,?,?,?,?,?)"
}

return await db.query(sql, data);
}
}

+ 68
- 0
app/models/dao/productDao.js View File

@@ -0,0 +1,68 @@
/*
* @Description: 商品模块数据持久层
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 15:42:52
*/
const db = require('./db.js');

module.exports = {
// 连接数据库获取商品分类
GetCategory: async () => {
const sql = "select * from category";
return await db.query(sql, []);
},
// 连接数据库根据商品分类名称获取分类id
GetCategoryId: async (categoryName) => {
const sql = "select * from category where category_name = ?";
const category = await db.query(sql, [categoryName]);
return category[0].category_id;
},
// 连接数据库,根据商品分类id获取首页展示的商品信息
GetPromoProduct: async (categoryID) => {
const sql = "select * from product where category_id = ? order by product_sales desc limit 7";
return await db.query(sql, categoryID);
},
// 连接数据库,分页获取所有的商品信息
GetAllProduct: async (offset = 0, rows = 0) => {
let sql = "select * from product ";
if (rows != 0) {
sql += "limit " + offset + "," + rows;
}
return await db.query(sql, []);
},
// 连接数据库,根据商品分类id,分页获取商品信息
GetProductByCategory: async (categoryID, offset = 0, rows = 0) => {
let sql = "select * from product where category_id = ? ";

for (let i = 0; i < categoryID.length - 1; i++) {
sql += "or category_id = ? ";
}
if (rows != 0) {
sql += "order by product_sales desc limit " + offset + "," + rows;
}

return await db.query(sql, categoryID);
},
// 连接数据库,根据搜索条件,分页获取商品信息
GetProductBySearch: async (search, offset = 0, rows = 0) => {
let sql = `select * from product where product_name like "%${ search }%" or product_title like "%${ search }%" or product_intro like "%${ search }%"`;

if (rows != 0) {
sql += "order by product_sales desc limit " + offset + "," + rows;
}
return await db.query(sql, []);
},
// 连接数据库,根据商品id,获取商品详细信息
GetProductById: async (id) => {
const sql = 'select * from product where product_id = ?';
return await db.query(sql, id);
},
// 连接数据库,根据商品id,获取商品图片
GetDetailsPicture: async (productID) => {
const sql = "select * from product_picture where product_id = ? ";
return await db.query(sql, productID);
}
}

+ 16
- 0
app/models/dao/resourcesDao.js View File

@@ -0,0 +1,16 @@
/*
* @Description: 资源模块数据持久层
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 14:33:43
*/
const db = require('./db.js');

module.exports = {
// 连接数据库获取轮播图数据
Carousel: async () => {
const sql = 'select * from carousel';
return await db.query(sql, []);
}
}

+ 36
- 0
app/models/dao/shoppingCartDao.js View File

@@ -0,0 +1,36 @@
/*
* @Description: 购物车模块数据持久层
* @Author: hai-27
* @Date: 2020-02-19 16:17:19
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 15:58:55
*/
const db = require('./db.js');

module.exports = {
// 获取购物车信息
GetShoppingCart: async (user_id) => {
const sql = 'select * from shoppingCart where user_id = ?';
return await db.query(sql, user_id);
},
// 查询用户的购物车的某个商品
FindShoppingCart: async (user_id, product_id) => {
const sql = 'select * from shoppingCart where user_id = ? and product_id = ?';
return await db.query(sql, [user_id, product_id]);
},
// 新插入购物车信息
AddShoppingCart: async (user_id, product_id) => {
const sql = 'insert into shoppingCart values(null,?,?,1)';
return await db.query(sql, [user_id, product_id]);
},
// 更新购物车商品数量
UpdateShoppingCart: async (NewNum, user_id, product_id) => {
const sql = 'update shoppingCart set num =? where user_id =? and product_id =?';
return await db.query(sql, [NewNum, user_id, product_id]);
},
// 删除购物车信息
DeleteShoppingCart: async (user_id, product_id) => {
const sql = 'delete from shoppingCart where user_id =? and product_id =?';
return await db.query(sql, [user_id, product_id]);
}
}

+ 26
- 0
app/models/dao/userDao.js View File

@@ -0,0 +1,26 @@
/*
* @Description: 用户模块数据持久层
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-27 02:12:30
*/
const db = require('./db.js');

module.exports = {
// 连接数据库根据用户名和密码查询用户信息
Login: async (userName, password) => {
const sql = 'select * from users where userName = ? and password = ?';
return await db.query(sql, [userName, password]);
},
// 连接数据库根据用户名查询用户信息
FindUserName: async (userName) => {
const sql = 'select * from users where userName = ?';
return await db.query(sql, [userName]);
},
// 连接数据库插入用户信息
Register: async (userName, password) => {
const sql = 'insert into users values(null,?,?,null)';
return await db.query(sql, [userName, password]);
}
}

+ 26
- 0
app/routers/index.js View File

@@ -0,0 +1,26 @@
/*
* @Description: 汇总模块子路由
* @Author: hai-27
* @Date: 2020-04-07 22:51:48
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:57:35
*/
const Router = require('koa-router');

let Routers = new Router();

const userRouter = require('./router/userRouter');
const resourcesRouter = require('./router/resourcesRouter');
const productRouter = require('./router/productRouter');
const shoppingCartRouter = require('./router/shoppingCartRouter');
const orderRouter = require('./router/orderRouter');
const collectRouter = require('./router/collectRouter');

Routers.use(userRouter.routes());
Routers.use(resourcesRouter.routes());
Routers.use(productRouter.routes());
Routers.use(shoppingCartRouter.routes());
Routers.use(orderRouter.routes());
Routers.use(collectRouter.routes());

module.exports = Routers;

+ 18
- 0
app/routers/router/collectRouter.js View File

@@ -0,0 +1,18 @@
/*
* @Description: 我的收藏模块路由
* @Author: hai-27
* @Date: 2020-03-04 22:28:01
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:52:36
*/
const Router = require('koa-router');
const collectController = require('../../controllers/collectController')

let collectRouter = new Router();

collectRouter
.post('/user/collect/addCollect', collectController.AddCollect)
.post('/user/collect/getCollect', collectController.GetCollect)
.post('/user/collect/deleteCollect', collectController.DeleteCollect)

module.exports = collectRouter;

+ 17
- 0
app/routers/router/orderRouter.js View File

@@ -0,0 +1,17 @@
/*
* @Description: 订单模块路由
* @Author: hai-27
* @Date: 2020-02-24 16:29:26
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:52:48
*/
const Router = require('koa-router');
const orderController = require('../../controllers/orderController')

let orderRouter = new Router();

orderRouter
.post('/user/order/getOrder', orderController.GetOrder)
.post('/user/order/addOrder', orderController.AddOrder)

module.exports = orderRouter;

+ 23
- 0
app/routers/router/productRouter.js View File

@@ -0,0 +1,23 @@
/*
* @Description: 商品模块路由
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:52:56
*/
const Router = require('koa-router');
const productController = require('../../controllers/productController')

let productRouter = new Router();

productRouter
.post('/product/getAllProduct', productController.GetAllProduct)
.post('/product/getPromoProduct', productController.GetPromoProduct)
.post('/product/getHotProduct', productController.GetHotProduct)
.post('/product/getProductByCategory', productController.GetProductByCategory)
.post('/product/getCategory', productController.GetCategory)
.post('/product/getProductBySearch', productController.GetProductBySearch)
.post('/product/getDetails', productController.GetDetails)
.post('/product/getDetailsPicture', productController.GetDetailsPicture)
module.exports = productRouter;

+ 16
- 0
app/routers/router/resourcesRouter.js View File

@@ -0,0 +1,16 @@
/*
* @Description: 资源模块路由
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-25 22:36:30
*/
const Router = require('koa-router');
const resourcesController = require('../../controllers/resourcesController')

let resourcesRouter = new Router();

resourcesRouter
.post('/resources/carousel', resourcesController.Carousel)

module.exports = resourcesRouter;

+ 19
- 0
app/routers/router/shoppingCartRouter.js View File

@@ -0,0 +1,19 @@
/*
* @Description: 购物车模块路由
* @Author: hai-27
* @Date: 2020-02-19 16:11:18
* @LastEditors: hai-27
* @LastEditTime: 2020-04-07 22:53:07
*/
const Router = require('koa-router');
const shoppingCartController = require('../../controllers/shoppingCartController')

let shoppingCartRouter = new Router();

shoppingCartRouter
.post('/user/shoppingCart/getShoppingCart', shoppingCartController.GetShoppingCart)
.post('/user/shoppingCart/addShoppingCart', shoppingCartController.AddShoppingCart)
.post('/user/shoppingCart/deleteShoppingCart', shoppingCartController.DeleteShoppingCart)
.post('/user/shoppingCart/updateShoppingCart', shoppingCartController.UpdateShoppingCart)

module.exports = shoppingCartRouter;

+ 19
- 0
app/routers/router/userRouter.js View File

@@ -0,0 +1,19 @@
/*
* @Description: 用户模块路由
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-03-27 12:41:14
*/
const Router = require('koa-router');
const userController = require('../../controllers/userController')

let userRouter = new Router();

userRouter
.post('/users/login', userController.Login)
.post('/users/miniProgramLogin', userController.miniProgramLogin)
.post('/users/findUserName', userController.FindUserName)
.post('/users/register', userController.Register)

module.exports = userRouter;

+ 23
- 0
config.js View File

@@ -0,0 +1,23 @@
/*
* @Description: 全局配置信息
* @Author: hai-27
* @Date: 2020-02-07 16:51:56
* @LastEditors: hai-27
* @LastEditTime: 2020-02-28 23:21:30
*/
const path = require('path');

module.exports = {
Port: 3000, // 启动端口
staticDir: path.resolve('./public'), // 静态资源路径
uploadDir: path.join(__dirname, path.resolve('public/')), // 上传文件路径
// 数据库连接设置
dbConfig: {
connectionLimit: 10,
host: 'localhost',
port:'8889',
user: 'root',
password: 'root',
database: 'storeDB'
}
}

+ 104
- 0
docs/API.md View File

@@ -0,0 +1,104 @@
# 接口文档

## 用户模块

### 1. 登录

**请求URL:**

```
/users/login
```

**请求方式:**

```
Post
```

**参数说明:**

| 参数 | 是否必选 | 类型 | 说明 |
| :-: | :-: | :-: | :-: |
| userName | 是 | string | 用户名 |
| password | 是 | string | 密码 |

**返回示例:**

```javascript
{
"code": "001",
"user": {
"user_id": 1,
"userName": "admin"
},
"msg": "登录成功"
}
```



### 2. 查找用户名是否存在

**请求URL:**

```
/users/findUserName
```

**请求方式:**

```
Post
```

**参数说明:**

| 参数 | 是否必选 | 类型 | 说明 |
| :------: | :------: | :----: | :----: |
| userName | 是 | string | 用户名 |

**返回示例:**

```javascript
{
"code": "001",
"msg": "用户名不存在,可以注册"
}
```



### 3. 注册

**请求URL:**

```
/users/register
```

**请求方式:**

```
Post
```

**参数说明:**

| 参数 | 是否必选 | 类型 | 说明 |
| :------: | :------: | :----: | :----: |
| userName | 是 | string | 用户名 |
| password | 是 | string | 密码 |

**返回示例:**

```javascript
{
code: '001',
msg: '注册成功'
}
```



未完,有空继续写。

+ 982
- 0
package-lock.json View File

@@ -0,0 +1,982 @@
{
"name": "store-server",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
},
"@types/formidable": {
"version": "1.0.31",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz",
"integrity": "sha512-dIhM5t8lRP0oWe2HF8MuPvdd1TpPTjhDMAqemcq6oIZQCBQTovhBAdTQ5L5veJB4pdQChadmHuxtB0YzqvfU3Q==",
"requires": {
"@types/events": "*",
"@types/node": "*"
}
},
"@types/node": {
"version": "12.12.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz",
"integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA=="
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"negotiator": "0.6.2"
}
},
"ajv": {
"version": "6.12.0",
"resolved": "https://registry.npm.taobao.org/ajv/download/ajv-6.12.0.tgz",
"integrity": "sha1-BtYLlth7hFSlrauobnhU2mKdtLc=",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz",
"integrity": "sha1-jSR136tVO7M+d7VOWeiAu4ziMTY=",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.9.1",
"resolved": "https://registry.npm.taobao.org/aws4/download/aws4-1.9.1.tgz",
"integrity": "sha1-fjPY99RJs/ZzzXLeuavcVS2+Uo4="
},
"base64-js": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"bignumber.js": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
"integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ=="
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz",
"integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28="
},
"buffer": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz",
"integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==",
"requires": {
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
}
},
"bytes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
},
"cache-content-type": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
"integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
"requires": {
"mime-types": "^2.1.18",
"ylru": "^1.2.0"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"co-body": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz",
"integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==",
"requires": {
"inflation": "^2.0.0",
"qs": "^6.4.0",
"raw-body": "^2.2.0",
"type-is": "^1.6.14"
}
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.8.tgz",
"integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"content-disposition": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
"requires": {
"safe-buffer": "5.1.2"
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookies": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
"integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
"requires": {
"depd": "~2.0.0",
"keygrip": "~1.1.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"crc": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
"integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
"requires": {
"buffer": "^5.1.0"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"error-inject": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz",
"integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz",
"integrity": "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-3.1.1.tgz",
"integrity": "sha1-VFFFB3xQFJHjOxXsQIwpQ3bpSuQ="
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npm.taobao.org/form-data/download/form-data-2.3.3.tgz",
"integrity": "sha1-3M5SwF9kTymManq5Nr1yTO/786Y=",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.3",
"resolved": "https://registry.npm.taobao.org/har-validator/download/har-validator-5.1.3.tgz",
"integrity": "sha1-HvievT5JllV2de7ZiTEQ3DUPoIA=",
"requires": {
"ajv": "^6.5.5",
"har-schema": "^2.0.0"
}
},
"http-assert": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz",
"integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==",
"requires": {
"deep-equal": "~1.0.1",
"http-errors": "~1.7.2"
}
},
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
},
"inflation": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
"integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-class-hotfix": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz",
"integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ=="
},
"is-generator-function": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
"integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
},
"is-type-of": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz",
"integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==",
"requires": {
"core-util-is": "^1.0.2",
"is-class-hotfix": "~0.0.6",
"isstream": "~0.1.2"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjson-schema%2Fdownload%2Fjson-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz",
"integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
"integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
"requires": {
"tsscmp": "1.0.6"
}
},
"koa": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.11.0.tgz",
"integrity": "sha512-EpR9dElBTDlaDgyhDMiLkXrPwp6ZqgAIBvhhmxQ9XN4TFgW+gEz6tkcsNI6BnUbUftrKDjVFj4lW2/J2aNBMMA==",
"requires": {
"accepts": "^1.3.5",
"cache-content-type": "^1.0.0",
"content-disposition": "~0.5.2",
"content-type": "^1.0.4",
"cookies": "~0.8.0",
"debug": "~3.1.0",
"delegates": "^1.0.0",
"depd": "^1.1.2",
"destroy": "^1.0.4",
"encodeurl": "^1.0.2",
"error-inject": "^1.0.0",
"escape-html": "^1.0.3",
"fresh": "~0.5.2",
"http-assert": "^1.3.0",
"http-errors": "^1.6.3",
"is-generator-function": "^1.0.7",
"koa-compose": "^4.1.0",
"koa-convert": "^1.2.0",
"on-finished": "^2.3.0",
"only": "~0.0.2",
"parseurl": "^1.3.2",
"statuses": "^1.5.0",
"type-is": "^1.6.16",
"vary": "^1.1.2"
}
},
"koa-body": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.1.1.tgz",
"integrity": "sha512-rLb/KVD8qplEcK8Qsu6F4Xw+uHkmx3MWogDVmMX07DpjXizhw3pOEp1ja1MqqAcl0ei75AsrbGVDlySmsUrreA==",
"requires": {
"@types/formidable": "^1.0.31",
"co-body": "^5.1.1",
"formidable": "^1.1.1"
}
},
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"koa-convert": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz",
"integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
"requires": {
"co": "^4.6.0",
"koa-compose": "^3.0.0"
},
"dependencies": {
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
}
}
},
"koa-router": {
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-7.4.0.tgz",
"integrity": "sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==",
"requires": {
"debug": "^3.1.0",
"http-errors": "^1.3.1",
"koa-compose": "^3.0.0",
"methods": "^1.0.1",
"path-to-regexp": "^1.1.1",
"urijs": "^1.19.0"
},
"dependencies": {
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
}
}
},
"koa-send": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.0.tgz",
"integrity": "sha512-90ZotV7t0p3uN9sRwW2D484rAaKIsD8tAVtypw/aBU+ryfV+fR2xrcAwhI8Wl6WRkojLUs/cB9SBSCuIb+IanQ==",
"requires": {
"debug": "^3.1.0",
"http-errors": "^1.6.3",
"mz": "^2.7.0",
"resolve-path": "^1.4.0"
}
},
"koa-session": {
"version": "5.12.3",
"resolved": "https://registry.npmjs.org/koa-session/-/koa-session-5.12.3.tgz",
"integrity": "sha512-r1vRerk6z+J54TtgXPG+oYGj1vwrd889bz55hS7VykWvbtmPNb0q/N7arOHGV8dnstlRyZPP3xCJL20wIf9LwA==",
"requires": {
"crc": "^3.4.4",
"debug": "^3.1.0",
"is-type-of": "^1.0.0",
"uuid": "^3.3.2"
}
},
"koa-static": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
"integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
"requires": {
"debug": "^3.1.0",
"koa-send": "^5.0.0"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz",
"integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime-db": {
"version": "1.42.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
},
"mime-types": {
"version": "2.1.25",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
"integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
"requires": {
"mime-db": "1.42.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"mysql": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/mysql/-/mysql-2.17.1.tgz",
"integrity": "sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA==",
"requires": {
"bignumber.js": "7.2.1",
"readable-stream": "2.3.6",
"safe-buffer": "5.1.2",
"sqlstring": "2.3.1"
}
},
"mz": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"requires": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz",
"integrity": "sha1-R6ewFrqmi1+g7PPe4IqFxnmsZFU="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"only": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npm.taobao.org/psl/download/psl-1.8.0.tgz",
"integrity": "sha1-kyb4vPsBOtzABf3/BWrM4CDlHCQ="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
"integrity": "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
},
"qs": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.1.tgz",
"integrity": "sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA=="
},
"raw-body": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
"integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.3",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
}
}
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npm.taobao.org/request/download/request-2.88.2.tgz",
"integrity": "sha1-1zyRhzHLWofaBH4gcjQUb2ZNErM=",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz?cache=0&sync_timestamp=1585168908480&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.5.2.tgz",
"integrity": "sha1-yzroBuh0BERYTvFUzo7pjUA/PjY="
}
}
},
"request-promise": {
"version": "4.2.5",
"resolved": "https://registry.npm.taobao.org/request-promise/download/request-promise-4.2.5.tgz",
"integrity": "sha1-GGIixZrlEvNJff5NdanIRhvQBTw=",
"requires": {
"bluebird": "^3.5.0",
"request-promise-core": "1.1.3",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
}
},
"request-promise-core": {
"version": "1.1.3",
"resolved": "https://registry.npm.taobao.org/request-promise-core/download/request-promise-core-1.1.3.tgz",
"integrity": "sha1-6aPAgbUTgN/qZ3M2Bh/qh5qCnuk=",
"requires": {
"lodash": "^4.17.15"
}
},
"resolve-path": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
"integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
"requires": {
"http-errors": "~1.6.2",
"path-is-absolute": "1.0.1"
},
"dependencies": {
"http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
}
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
},
"sqlstring": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
"integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A="
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz",
"integrity": "sha1-+2YcC+8ps520B2nuOfpwCT1vaHc=",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/stealthy-require/download/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"thenify": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
"integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
"requires": {
"any-promise": "^1.0.0"
}
},
"thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
"integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
"requires": {
"thenify": ">= 3.1.0 < 4"
}
},
"toidentifier": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.5.0.tgz",
"integrity": "sha1-zZ+yoKodWhK0c72fuW+j3P9lreI=",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npm.taobao.org/uri-js/download/uri-js-4.2.2.tgz",
"integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=",
"requires": {
"punycode": "^2.1.0"
}
},
"urijs": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz",
"integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"ylru": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
"integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ=="
}
}
}

+ 21
- 0
package.json View File

@@ -0,0 +1,21 @@
{
"name": "store-server",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"koa": "^2.11.0",
"koa-body": "^4.1.1",
"koa-router": "^7.4.0",
"koa-session": "^5.12.3",
"koa-static": "^5.0.0",
"mysql": "^2.17.1",
"request": "^2.88.2",
"request-promise": "^4.2.5"
}
}

+ 118
- 0
public/docs/README.md View File

@@ -0,0 +1,118 @@
# Store(参考小米商城)

## 前言

2020年寒假尤其特殊,因为新型冠状病毒肺炎疫情,学校至今没有开学。想起上学期利用课余时间学习了`Vue.js`、`Node.js`,一直想做个完整的项目实战一下,但之前在学校并没有那么多的时间。现在恰好有时间,就想着做一个项目巩固之前学到的东西。

思来想去,最后决定模仿 [小米商城 ](www.mi.com)做一个电商项目。可能时间隔得有点久了,之前学的东西很多都差不多忘记了,做这个项目基本上都是看着官方的文档一点一点做的。在家里也免不了有各种各样的事情耽误了项目的进度。现在终于差不多做好了,分享出来,新手上路,如有错误,请多多指教。

## 说明

> 本项目前后端分离,前端参考 [小米商城](www.mi.com) 实现,但与小米官方没有关系,纯属个人瞎搞,若需要购买小米产品请到小米官方商城。

> 这是本项目的前端,后端请移步到[store-server](https://github.com/hai-27/store-server) 。

> 前端已经部署在阿里云,欢迎访问 [http://106.15.179.105/](http://106.15.179.105/) (没有兼容移动端,请使用电脑访问)。

> 后端也已经部署在阿里云,接口地址已经修改为线上地址,本地运行前端也可以正常访问后端。

> 本人在读本科大三,今年暑假即将开始实习,后面的时间可能没有那么的自由,但会不定期的更新完善该项目,如有问题请直接在 Issues 中提。

> 如果觉得这个项目还不错,您可以点右上角 `Star`支持一下, 谢谢! ^_^

## 项目简介

本项目前后端分离,前端基于`Vue`+`Vue-router`+`Vuex`+`Element-ui`+`Axios`,参考小米商城实现。后端基于`Node.js(Koa框架)`+`Mysql`实现。

前端包含了11个页面:首页、登录、注册、全部商品、商品详情页、关于我们、我的收藏、购物车、订单结算页面、我的订单以及错误处理页面。

实现了商品的展示、商品分类查询、关键字搜索商品、商品详细信息展示、登录、注册、用户购物车、订单结算、用户订单、用户收藏列表以及错误处理功能。

后端采取了MVC模式,根据前端需要的数据分模块设计了相应的接口、控制层、数据持久层。后端传送地址[store-server](https://github.com/hai-27/store-server) 。

## 技术栈

- **前端:**`Vue`+`Vue-router`+`Vuex`+`Element-ui`+`Axios`

- **后端:**`Node.js`、`Koa框架`

- **数据库:**`Mysql`

## 功能模块

### 登录

页面使用了element-ui的`Dialog`实现弹出蒙版对话框的效果,`登录`按钮设置在App.vue根组件,通过`vuex`中的`showLogin`状态控制登录框是否显示。

这样设计是为了既可以通过点击页面中的按钮登录,也可以是用户访问需要登录验证的页面或后端返回需要验证登录的提示后自动弹出登录框,减少了页面的跳转,简化用户操作。

用户输入的数据往往是不可靠的,所以本项目前后端都对登录信息进行了校验,前端基于element-ui的表单校验方式,自定义了校验规则进行校验。

### 注册

页面同样使用了element-ui的`Dialog`实现弹出蒙版对话框的效果,`注册`按钮设置在App.vue根组件,通过父子组件传值控制注册框是否显示。

用户输入的数据往往是不可靠的,所以本项目前后端同样都对注册信息进行了校验,前端基于element-ui的表单校验方式,自定义了校验规则进行校验。

### 首页

首页主要是对商品的展示,有轮播图展示推荐的商品,分类别对热门商品进行展示。

### 全部商品

全部商品页面集成了全部商品展示、商品分类查询,以及根据关键字搜索商品结果展示。

### 商品详情页

商品详情页主要是对某个商品的详细信息进行展示,用户可以在这里把喜欢的商品加入购物车或收藏列表。

### 我的购物车

购物车采用vuex实现,页面效果参考了小米商城的购物车。

详细实现过程请看:[基于Vuex实现小米商城购物车](https://github.com/hai-27/hai-27.github.io/blob/master/page/%E5%9F%BA%E4%BA%8EVuex%E5%AE%9E%E7%8E%B0%E5%B0%8F%E7%B1%B3%E5%95%86%E5%9F%8E%E8%B4%AD%E7%89%A9%E8%BD%A6.md)

### 订单结算

用户在购物车选择了准备购买的商品后,点击“去结算”按钮,会来到该页面。
用户在这里选择收货地址,确认订单的相关信息,然后确认购买。

### 我的收藏

用户在商品的详情页,可以通过点击加入 喜欢 按钮,把喜欢的商品加入到收藏列表。

### 我的订单

对用户的所有订单进行展示。

## 运行项目

**注意:**

- 后端接口地址已经修改为线上的地址,本地运行会直接分为我部署在服务器的后端。
- 为了方便测试,数据库数据没有加密,注册时切记**不要使用自己的常用密码**。
- 如果需要自己运行后端,请移步到[store-server](https://github.com/hai-27/store-server) clone后端项目,并修改前端的接口地址为您的服务器地址。

```
1. Clone project

git clone https://github.com/hai-27/vue-store.git

2. Project setup

cd vue-store
npm install

3. Compiles and hot-reloads for development

npm run serve

4. Compiles and minifies for production

npm run build
```


**作者** [hai-27](https://github.com/hai-27)

2020年3月8日

BIN
public/imgs/accessory/accessory-promo1.png View File

Before After

BIN
public/imgs/accessory/accessory-promo2.png View File

Before After

BIN
public/imgs/accessory/charger-10000mAh.png View File

Before After

BIN
public/imgs/accessory/charger-18w.png View File

Before After
Width: 229  |  Height: 229  |  Size: 16 KiB

BIN
public/imgs/accessory/charger-30w.png View File

Before After

BIN
public/imgs/accessory/charger-36w.png View File

Before After
Width: 229  |  Height: 229  |  Size: 16 KiB

BIN
public/imgs/accessory/charger-60w.png View File

Before After
Width: 229  |  Height: 229  |  Size: 17 KiB

BIN
public/imgs/accessory/charger-car-37w.png View File

Before After

BIN
public/imgs/accessory/charger-car.png View File

Before After
Width: 229  |  Height: 229  |  Size: 3.0 KiB

BIN
public/imgs/accessory/charger-tio.png View File

Before After
Width: 229  |  Height: 229  |  Size: 3.1 KiB

BIN
public/imgs/accessory/protectingMen-Mi-CC9.png View File

Before After

BIN
public/imgs/accessory/protectingMen-Mi-CC9e.png View File

Before After

BIN
public/imgs/accessory/protectingShell-Mi-9-red.png View File

Before After
Width: 800  |  Height: 800  |  Size: 144 KiB

BIN
public/imgs/accessory/protectingShell-Mi-9.png View File

Before After

BIN
public/imgs/accessory/protectingShell-Mi-9SE.png View File

Before After
Width: 800  |  Height: 800  |  Size: 43 KiB

BIN
public/imgs/accessory/protectingShell-Mi-CC9Pro.png View File

Before After
Width: 800  |  Height: 800  |  Size: 162 KiB

BIN
public/imgs/accessory/protectingShell-Mix-3.png View File

Before After
Width: 800  |  Height: 800  |  Size: 69 KiB

BIN
public/imgs/accessory/protectingShell-RedMi-K20&pro.png View File

Before After

BIN
public/imgs/accessory/protectingShell-RedMi-K20.png View File

Before After
Width: 800  |  Height: 800  |  Size: 27 KiB

BIN
public/imgs/appliance/AirCondition-F3W1.png View File

Before After
Width: 229  |  Height: 229  |  Size: 2.5 KiB

BIN
public/imgs/appliance/AirCondition-V1C1.png View File

Before After

BIN
public/imgs/appliance/MiTv-4A-32.png View File

Before After
Width: 229  |  Height: 229  |  Size: 59 KiB

BIN
public/imgs/appliance/MiTv-4A-65.png View File

Before After
Width: 229  |  Height: 229  |  Size: 20 KiB

BIN
public/imgs/appliance/MiTv-4C-55.png View File

Before After
Width: 229  |  Height: 229  |  Size: 52 KiB

BIN
public/imgs/appliance/MiTv-4X-43.png View File

Before After
Width: 229  |  Height: 229  |  Size: 41 KiB

BIN
public/imgs/appliance/MiTv-ArtTv-65.png View File

Before After

BIN
public/imgs/appliance/MiTv-E55A.png View File

Before After

BIN
public/imgs/appliance/MiTv-E65A.png View File

Before After

BIN
public/imgs/appliance/Washer-Pro-10.png View File

Before After

BIN
public/imgs/appliance/appliance-promo1.png View File

Before After

BIN
public/imgs/appliance/appliance-promo2.png View File

Before After

BIN
public/imgs/cms_1.jpg View File

Before After

BIN
public/imgs/cms_2.jpg View File

Before After

BIN
public/imgs/cms_3.jpg View File

Before After

BIN
public/imgs/cms_4.jpg View File

Before After

BIN
public/imgs/phone/Mi-CC9.png View File

Before After

BIN
public/imgs/phone/Redmi-7A.png View File

Before After

BIN
public/imgs/phone/Redmi-8.png View File

Before After

BIN
public/imgs/phone/Redmi-8A.png View File

Before After

BIN
public/imgs/phone/Redmi-Note8-pro.png View File

Before After

BIN
public/imgs/phone/Redmi-Note8.png View File

Before After

BIN
public/imgs/phone/Redmi-k30-5G.png View File

Before After

BIN
public/imgs/phone/Redmi-k30.png View File

Before After

BIN
public/imgs/phone/phone.png View File

Before After

BIN
public/imgs/phone/picture/AirCondition-F3W1-1.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 32 KiB

BIN
public/imgs/phone/picture/AirCondition-V1C1-1.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 57 KiB

BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MI → 9 View File


BIN
public/imgs/phone/picture/MiTv-4A → -1.jpg View File


BIN
public/imgs/phone/picture/MiTv-4A-32-1.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 148 KiB

BIN
public/imgs/phone/picture/MiTv-4A-32-2.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 147 KiB

BIN
public/imgs/phone/picture/MiTv-4A-32-3.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 60 KiB

BIN
public/imgs/phone/picture/MiTv-4A-32-4.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 321 KiB

BIN
public/imgs/phone/picture/MiTv-4C → -1.jpg View File


BIN
public/imgs/phone/picture/MiTv-4C → -2.jpg View File


BIN
public/imgs/phone/picture/MiTv-4C → -3.jpg View File


BIN
public/imgs/phone/picture/MiTv-4X → -1.jpg View File


BIN
public/imgs/phone/picture/MiTv-4X → -2.jpg View File


BIN
public/imgs/phone/picture/MiTv-4X → -3.jpg View File


BIN
public/imgs/phone/picture/MiTv-ArtTv-65-1.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 143 KiB

BIN
public/imgs/phone/picture/MiTv-E55A-1.jpg View File

Before After
Width: 800  |  Height: 800  |  Size: 140 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save