food.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. 'use strict';
  2. import {Food as FoodModel, Menu as MenuModel} from '../../models/shopping/food'
  3. import ShopModel from '../../models/shopping/shop'
  4. import BaseComponent from '../../prototype/baseComponent'
  5. import formidable from 'formidable'
  6. class Food extends BaseComponent{
  7. constructor(){
  8. super();
  9. this.defaultData = [{
  10. name: '热销榜',
  11. description: '大家喜欢吃,才叫真好吃。',
  12. icon_url: "5da3872d782f707b4c82ce4607c73d1ajpeg",
  13. is_selected: true,
  14. type: 1,
  15. foods: [],
  16. }, {
  17. name: '优惠',
  18. description: '美味又实惠, 大家快来抢!',
  19. icon_url: "4735c4342691749b8e1a531149a46117jpeg",
  20. type: 1,
  21. foods: [],
  22. }]
  23. this.initData = this.initData.bind(this);
  24. this.addFood = this.addFood.bind(this);
  25. this.getCategory = this.getCategory.bind(this);
  26. this.addCategory = this.addCategory.bind(this);
  27. this.getSpecfoods = this.getSpecfoods.bind(this);
  28. this.updateFood = this.updateFood.bind(this);
  29. }
  30. async initData(restaurant_id){
  31. for (let i = 0; i < this.defaultData.length; i++) {
  32. let category_id;
  33. try{
  34. category_id = await this.getId('category_id');
  35. }catch(err){
  36. console.log('获取category_id失败');
  37. throw new Error(err);
  38. }
  39. const defaultData = this.defaultData[i];
  40. const Category = {...defaultData, id: category_id, restaurant_id};
  41. const newFood = new MenuModel(Category);
  42. try{
  43. await newFood.save();
  44. console.log('初始化食品数据成功');
  45. }catch(err){
  46. console.log('初始化食品数据失败');
  47. throw new Error(err);
  48. }
  49. }
  50. }
  51. async getCategory(req, res, next){
  52. const restaurant_id = req.params.restaurant_id;
  53. try{
  54. const category_list = await MenuModel.find({restaurant_id});
  55. res.send({
  56. status: 1,
  57. category_list,
  58. })
  59. }catch(err){
  60. console.log('获取餐馆食品种类失败');
  61. res.send({
  62. status: 0,
  63. type: 'ERROR_GET_DATA',
  64. message: '获取数据失败'
  65. })
  66. }
  67. }
  68. async addCategory(req, res, next){
  69. const form = new formidable.IncomingForm();
  70. form.parse(req, async (err, fields, files) => {
  71. try{
  72. if (!fields.name) {
  73. throw new Error('必须填写食品类型名称');
  74. }else if(!fields.restaurant_id){
  75. throw new Error('餐馆ID错误');
  76. }
  77. }catch(err){
  78. console.log(err.message, err);
  79. res.send({
  80. status: 0,
  81. type: 'ERROR_PARAMS',
  82. message: err.message
  83. })
  84. return
  85. }
  86. let category_id;
  87. try{
  88. category_id = await this.getId('category_id');
  89. }catch(err){
  90. console.log('获取category_id失败');
  91. res.send({
  92. type: 'ERROR_DATA',
  93. message: '获取数据失败'
  94. })
  95. return
  96. }
  97. const foodObj = {
  98. name: fields.name,
  99. description: fields.description,
  100. restaurant_id: fields.restaurant_id,
  101. id: category_id,
  102. foods: [],
  103. }
  104. const newFood = new MenuModel(foodObj);
  105. try{
  106. await newFood.save();
  107. res.send({
  108. status: 1,
  109. success: '添加食品种类成功',
  110. })
  111. }catch(err){
  112. console.log('保存数据失败');
  113. res.send({
  114. status: 0,
  115. type: 'ERROR_IN_SAVE_DATA',
  116. message: '保存数据失败',
  117. })
  118. }
  119. })
  120. }
  121. async addFood(req, res, next){
  122. const form = new formidable.IncomingForm();
  123. form.parse(req, async (err, fields, files) => {
  124. console.log(fields)
  125. try{
  126. if (!fields.name) {
  127. throw new Error('必须填写食品名称');
  128. }else if(!fields.image_path){
  129. throw new Error('必须上传食品图片');
  130. }else if(!fields.specs.length){
  131. throw new Error('至少填写一种规格');
  132. }else if(!fields.category_id){
  133. throw new Error('食品类型ID错误');
  134. }else if(!fields.restaurant_id){
  135. throw new Error('餐馆ID错误');
  136. }
  137. }catch(err){
  138. console.log('前台参数错误');
  139. res.send({
  140. status: 0,
  141. type: 'ERROR_PARAMS',
  142. message: err.message
  143. })
  144. return
  145. }
  146. let category;
  147. let restaurant;
  148. try{
  149. category = await MenuModel.findOne({id: fields.category_id});
  150. restaurant = await ShopModel.findOne({id: fields.restaurant_id});
  151. }catch(err){
  152. console.log('获取食品类型和餐馆信息失败');
  153. res.send({
  154. status: 0,
  155. type: 'ERROR_DATA',
  156. message: '添加食品失败'
  157. })
  158. return
  159. }
  160. let item_id;
  161. try{
  162. item_id = await this.getId('item_id');
  163. }catch(err){
  164. console.log('获取item_id失败');
  165. res.send({
  166. status: 0,
  167. type: 'ERROR_DATA',
  168. message: '添加食品失败'
  169. })
  170. return
  171. }
  172. const rating_count = Math.ceil(Math.random()*1000);
  173. const month_sales = Math.ceil(Math.random()*1000);
  174. const tips = rating_count + "评价 月售" + month_sales + "份";
  175. const newFood = {
  176. name: fields.name,
  177. description: fields.description,
  178. image_path: fields.image_path,
  179. activity: null,
  180. attributes: [],
  181. restaurant_id: fields.restaurant_id,
  182. category_id: fields.category_id,
  183. satisfy_rate: Math.ceil(Math.random()*100),
  184. satisfy_count: Math.ceil(Math.random()*1000),
  185. item_id,
  186. rating: (3 + Math.random()*2).toFixed(1),
  187. rating_count,
  188. month_sales,
  189. tips,
  190. specfoods: [],
  191. specifications: [],
  192. }
  193. if (fields.activity) {
  194. newFood.activity = {
  195. image_text_color: 'f1884f',
  196. icon_color: 'f07373',
  197. image_text: fields.activity,
  198. }
  199. }
  200. if (fields.attributes.length) {
  201. fields.attributes.forEach(item => {
  202. let attr;
  203. switch(item){
  204. case '新':
  205. attr = {
  206. icon_color: '5ec452',
  207. icon_name: '新'
  208. }
  209. break;
  210. case '招牌':
  211. attr = {
  212. icon_color: 'f07373',
  213. icon_name: '招牌'
  214. }
  215. break;
  216. }
  217. newFood.attributes.push(attr);
  218. })
  219. }
  220. try{
  221. const [specfoods, specifications] = await this.getSpecfoods(fields, item_id);
  222. newFood.specfoods = specfoods;
  223. newFood.specifications = specifications;
  224. }catch(err){
  225. console.log('添加specs失败', err);
  226. res.send({
  227. status: 0,
  228. type: 'ERROR_DATA',
  229. message: '添加食品失败'
  230. })
  231. return
  232. }
  233. try{
  234. const foodEntity = await FoodModel.create(newFood);
  235. category.foods.push(foodEntity);
  236. category.markModified('foods');
  237. await category.save();
  238. res.send({
  239. status: 1,
  240. success: '添加食品成功',
  241. });
  242. }catch(err){
  243. console.log('保存食品到数据库失败', err);
  244. res.send({
  245. status: 0,
  246. type: 'ERROR_DATA',
  247. message: '添加食品失败'
  248. })
  249. }
  250. })
  251. }
  252. async getSpecfoods(fields, item_id){
  253. let specfoods = [], specifications = [];
  254. if (fields.specs.length < 2) {
  255. let food_id, sku_id;
  256. try{
  257. sku_id = await this.getId('sku_id');
  258. food_id = await this.getId('food_id');
  259. }catch(err){
  260. throw new Error('获取sku_id、food_id失败')
  261. }
  262. specfoods.push({
  263. packing_fee: fields.specs[0].packing_fee,
  264. price: fields.specs[0].price,
  265. specs: [],
  266. specs_name: fields.specs[0].specs,
  267. name: fields.name,
  268. item_id,
  269. sku_id,
  270. food_id,
  271. restaurant_id: fields.restaurant_id,
  272. recent_rating: (Math.random()*5).toFixed(1),
  273. recent_popularity: Math.ceil(Math.random()*1000),
  274. })
  275. }else{
  276. specifications.push({
  277. values: [],
  278. name: "规格"
  279. })
  280. for (let i = 0; i < fields.specs.length; i++) {
  281. let food_id, sku_id;
  282. try{
  283. sku_id = await this.getId('sku_id');
  284. food_id = await this.getId('food_id');
  285. }catch(err){
  286. throw new Error('获取sku_id、food_id失败')
  287. }
  288. specfoods.push({
  289. packing_fee: fields.specs[i].packing_fee,
  290. price: fields.specs[i].price,
  291. specs: [{
  292. name: "规格",
  293. value: fields.specs[i].specs
  294. }],
  295. specs_name: fields.specs[i].specs,
  296. name: fields.name,
  297. item_id,
  298. sku_id,
  299. food_id,
  300. restaurant_id: fields.restaurant_id,
  301. recent_rating: (Math.random()*5).toFixed(1),
  302. recent_popularity: Math.ceil(Math.random()*1000),
  303. })
  304. specifications[0].values.push(fields.specs[i].specs);
  305. }
  306. }
  307. return [specfoods, specifications]
  308. }
  309. async getMenu(req, res, next){
  310. const restaurant_id = req.query.restaurant_id;
  311. const allMenu = req.query.allMenu;
  312. if (!restaurant_id || !Number(restaurant_id)) {
  313. console.log('获取餐馆参数ID错误');
  314. res.send({
  315. status: 0,
  316. type: 'ERROR_PARAMS',
  317. message: '餐馆ID参数错误',
  318. })
  319. return
  320. }
  321. let filter;
  322. if (allMenu) {
  323. filter = {restaurant_id}
  324. }else{
  325. filter = {restaurant_id, $where: function(){return this.foods.length}};
  326. }
  327. try{
  328. const menu = await MenuModel.find(filter, '-_id');
  329. res.send(menu);
  330. }catch(err){
  331. console.log('获取食品数据失败', err);
  332. res.send({
  333. status: 0,
  334. type: 'GET_DATA_ERROR',
  335. message: '获取食品数据失败'
  336. })
  337. }
  338. }
  339. async getMenuDetail(req, res, next){
  340. const category_id = req.params.category_id;
  341. if (!category_id || !Number(category_id)) {
  342. console.log('获取Menu详情参数ID错误');
  343. res.send({
  344. status: 0,
  345. type: 'ERROR_PARAMS',
  346. message: 'Menu ID参数错误',
  347. })
  348. return
  349. }
  350. try{
  351. const menu = await MenuModel.findOne({id: category_id}, '-_id');
  352. res.send(menu)
  353. }catch(err){
  354. console.log('获取Menu详情失败', err);
  355. res.send({
  356. status: 0,
  357. type: 'GET_DATA_ERROR',
  358. message: '获取Menu详情失败'
  359. })
  360. }
  361. }
  362. async getFoods(req, res, next){
  363. const {restaurant_id, limit = 20, offset = 0} = req.query;
  364. try{
  365. let filter = {};
  366. if (restaurant_id && Number(restaurant_id)) {
  367. filter = {restaurant_id}
  368. }
  369. const foods = await FoodModel.find(filter, '-_id').limit(Number(limit)).skip(Number(offset));
  370. res.send(foods);
  371. }catch(err){
  372. console.log('获取食品数据失败', err);
  373. res.send({
  374. status: 0,
  375. type: 'GET_DATA_ERROR',
  376. message: '获取食品数据失败'
  377. })
  378. }
  379. }
  380. async getFoodsCount(req, res, next){
  381. const restaurant_id = req.query.restaurant_id;
  382. try{
  383. let filter = {};
  384. if (restaurant_id && Number(restaurant_id)) {
  385. filter = {restaurant_id}
  386. }
  387. const count = await FoodModel.find(filter).count();
  388. res.send({
  389. status: 1,
  390. count,
  391. })
  392. }catch(err){
  393. console.log('获取食品数量失败', err);
  394. res.send({
  395. status: 0,
  396. type: 'ERROR_TO_GET_COUNT',
  397. message: '获取食品数量失败'
  398. })
  399. }
  400. }
  401. async updateFood(req, res, next){
  402. const form = new formidable.IncomingForm();
  403. form.parse(req, async (err, fields, files) => {
  404. if (err) {
  405. console.log('获取食品信息form出错', err);
  406. res.send({
  407. status: 0,
  408. type: 'ERROR_FORM',
  409. message: '表单信息错误',
  410. })
  411. return
  412. }
  413. const {name, item_id, description = "", image_path, category_id, new_category_id} = fields;
  414. try{
  415. if (!name) {
  416. throw new Error('食品名称错误');
  417. }else if(!item_id || !Number(item_id)){
  418. throw new Error('食品ID错误');
  419. }else if(!category_id || !Number(category_id)){
  420. throw new Error('食品分类ID错误');
  421. }else if(!image_path){
  422. throw new Error('食品图片地址错误');
  423. }
  424. const [specfoods, specifications] = await this.getSpecfoods(fields, item_id);
  425. let newData;
  426. if (new_category_id !== category_id) {
  427. newData = {name, description, image_path, category_id: new_category_id, specfoods, specifications};
  428. const food = await FoodModel.findOneAndUpdate({item_id}, {$set: newData});
  429. const menu = await MenuModel.findOne({id: category_id})
  430. const targetmenu = await MenuModel.findOne({id: new_category_id})
  431. let subFood = menu.foods.id(food._id);
  432. subFood.set(newData)
  433. targetmenu.foods.push(subFood)
  434. targetmenu.markModified('foods');
  435. await targetmenu.save()
  436. await subFood.remove()
  437. await menu.save()
  438. }else{
  439. newData = {name, description, image_path, specfoods, specifications};
  440. const food = await FoodModel.findOneAndUpdate({item_id}, {$set: newData});
  441. const menu = await MenuModel.findOne({id: category_id})
  442. let subFood = menu.foods.id(food._id);
  443. subFood.set(newData)
  444. await menu.save()
  445. }
  446. res.send({
  447. status: 1,
  448. success: '修改食品信息成功',
  449. })
  450. }catch(err){
  451. console.log(err.message, err);
  452. res.send({
  453. status: 0,
  454. type: 'ERROR_UPDATE_FOOD',
  455. message: '更新食品信息失败',
  456. })
  457. }
  458. })
  459. }
  460. async deleteFood(req, res, next){
  461. const food_id = req.params.food_id;
  462. if (!food_id || !Number(food_id)) {
  463. console.log('food_id参数错误');
  464. res.send({
  465. status: 0,
  466. type: 'ERROR_PARAMS',
  467. message: 'food_id参数错误',
  468. })
  469. return
  470. }
  471. try{
  472. const food = await FoodModel.findOne({item_id: food_id});
  473. const menu = await MenuModel.findOne({id: food.category_id})
  474. let subFood = menu.foods.id(food._id);
  475. await subFood.remove()
  476. await menu.save()
  477. await food.remove()
  478. res.send({
  479. status: 1,
  480. success: '删除食品成功',
  481. })
  482. }catch(err){
  483. console.log('删除食品失败', err);
  484. res.send({
  485. status: 0,
  486. type: 'DELETE_FOOD_FAILED',
  487. message: '删除食品失败',
  488. })
  489. }
  490. }
  491. }
  492. export default new Food()