ソースを参照

Add 食品管理

enilu 6 年 前
コミット
9fd073012b

ファイルの差分が大きいため隠しています
+ 1113 - 0
doc/initData/t_sys_file_info.sql


+ 10 - 8
flash-waimai-api/src/main/java/cn/enilu/flash/api/controller/business/FoodController.java

@@ -1,6 +1,7 @@
 package cn.enilu.flash.api.controller.business;
 
 import cn.enilu.flash.api.controller.BaseController;
+import cn.enilu.flash.bean.constant.factory.PageFactory;
 import cn.enilu.flash.bean.entity.front.Food;
 import cn.enilu.flash.bean.entity.front.Ids;
 import cn.enilu.flash.bean.entity.front.KeyValue;
@@ -9,7 +10,8 @@ import cn.enilu.flash.bean.vo.front.Rets;
 import cn.enilu.flash.dao.MongoRepository;
 import cn.enilu.flash.service.front.IdsService;
 import cn.enilu.flash.utils.Maps;
-import com.google.common.base.Strings;
+import cn.enilu.flash.utils.StringUtils;
+import cn.enilu.flash.utils.factory.Page;
 import org.nutz.json.Json;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -52,14 +54,14 @@ public class FoodController extends BaseController {
         return Rets.success();
     }
     @RequestMapping(value="/v2/foods",method = RequestMethod.GET)
-    public Object list(@RequestParam("restaurant_id") String restaurantId,
-                       @RequestParam(value = "offset", defaultValue = "0") Integer offset,
-                       @RequestParam(value = "limit", defaultValue = "20") Integer limit) {
-        restaurantId="11";
-        if (Strings.isNullOrEmpty(restaurantId) || "undefined".equals(restaurantId)) {
-            return mongoRepository.findAll(Food.class);
+    public Object list(@RequestParam(value = "restaurant_id",required = false) Long restaurantId
+                       ) {
+        //restaurantId="11";
+        Page<Food> page = new PageFactory<Food>().defaultPage();
+        if (StringUtils.isNullOrEmpty(restaurantId) || "undefined".equals(restaurantId)) {
+            return Rets.success(mongoRepository.queryPage(page,Food.class));
         } else {
-            return mongoRepository.findAll(Food.class,"restaurant_id",Long.valueOf(restaurantId));
+            return Rets.success(mongoRepository.queryPage(page,Food.class,Maps.newHashMap("restaurant_id",restaurantId)));
         }
     }
 

+ 4 - 5
flash-waimai-api/src/main/java/cn/enilu/flash/api/controller/business/ShopController.java

@@ -42,12 +42,12 @@ public class ShopController extends BaseController {
 
     public Object getShop(@PathVariable("id")Long id) {
         Object data = mongoRepository.findOne(id,"shops");
-        return data ;
+        return Rets.success(data) ;
     }
 
     @RequestMapping(value = "restaurants",method = RequestMethod.GET)
-
-    public Object listShop(@RequestParam(value = "latitude",required = false) String latitude, @RequestParam(value = "longitude",required = false) String longitude) {
+    public Object listShop(@RequestParam(value = "latitude",required = false) String latitude,
+                           @RequestParam(value = "longitude",required = false) String longitude) {
         if (com.google.common.base.Strings.isNullOrEmpty(latitude) || "undefined".equals(latitude)
                 || com.google.common.base.Strings.isNullOrEmpty(longitude) || "undefined".equals(longitude)) {
             Page<Shop> page = new PageFactory<Shop>().defaultPage();
@@ -220,8 +220,7 @@ public class ShopController extends BaseController {
     }
 
 
-    @RequestMapping(value = "/v2/menu{id}",method = RequestMethod.GET)
-
+    @RequestMapping(value = "/v2/menu/{id}",method = RequestMethod.GET)
     public Object getMenus(@PathVariable("id")Long id){
         return Rets.success(mongoRepository.findOne(id,"menus"));
     }

+ 8 - 0
flash-waimai-core/src/main/java/cn/enilu/flash/dao/MongoRepository.java

@@ -111,8 +111,16 @@ public class MongoRepository {
     }
 
     public <T> Page<T> queryPage(Page<T> page,Class<T> klass) {
+       return queryPage(page,klass,null);
+    }
+
+    public <T> Page<T> queryPage(Page<T> page,Class<T> klass,Map<String,Object> params) {
         Pageable pageable = PageRequest.of(page.getCurrent() - 1, page.getSize(), Sort.Direction.DESC,"id");
         Query query = new Query();
+        if(params!=null &&!params.isEmpty()) {
+            Criteria criteria = criteria(params);
+            query = Query.query(criteria);
+        }
         List<T> list = mongoTemplate.find(query.with(pageable),klass);
         Long count = count(klass);
         page.setTotal(count.intValue());

+ 2 - 2
flash-waimai-core/src/main/java/cn/enilu/flash/service/system/FileService.java

@@ -129,7 +129,7 @@ public class FileService extends BaseService<FileInfo,Long,FileInfoRepository> {
     }
 
     public FileInfo getByName(String fileName) {
-//        File file = new File("d:\\data\\flash-waimai\\runtime\\upload");
+//        File file = new File("E:\\flash-waimai\\img\\foods");
 //        File[] imglist = file.listFiles();
 //        List<FileInfo> fileInfoList = Lists.newArrayList();
 //        for(int i=0;i<imglist.length;i++){
@@ -140,7 +140,7 @@ public class FileService extends BaseService<FileInfo,Long,FileInfoRepository> {
 //            }
 //            fileInfo = new FileInfo();
 //            fileInfo.setRealFileName(name);
-//            fileInfo.setOriginalFileName("商铺图片/"+name);
+//            fileInfo.setOriginalFileName("食品图片");
 //            fileInfoList.add(fileInfo);
 //        }
 //        fileInfoRepository.saveAll(fileInfoList);

+ 4 - 8
flash-waimai-core/src/main/java/cn/enilu/flash/utils/HttpClients.java

@@ -14,9 +14,7 @@ import org.apache.http.client.utils.URLEncodedUtils;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.message.BasicNameValuePair;
-import org.nutz.json.Json;
 import org.nutz.lang.Files;
-import org.nutz.mapl.Mapl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -246,13 +244,11 @@ public class HttpClients {
 	}
 
 	public static void main(String[] args) {
-		String json = Files.read(new File("e:\\flash-waimai\\shop.txt"));
-		Map map = Json.fromJson(Map.class,json);
-		List list = (List) Mapl.cell(map,"data.records");
+		List<String> list = Files.readLines(new File("e:\\flash-waimai\\food_img.json"));
+
 		for(int i=0;i<list.size();i++){
-			Map rec = (Map) list.get(i);
-			String img = (String) rec.get("image_path");
-			downloadImg("http://localhost:8002/img/"+img,"e:\\flash-waimai\\img\\shop\\"+img);
+		String img = list.get(i);
+			downloadImg("http://elm.cangdu.org/img/"+img,"e:\\flash-waimai\\img\\foods\\"+img);
 		}
 		System.out.println(list.size());
 

+ 36 - 0
flash-waimai-manage/src/api/business/shop.js

@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+/**
+ * 获取餐馆详细信息
+ */
+
+// export const getResturantDetail = restaurant_id => fetch('/shopping/restaurant/' + restaurant_id);
+export function getResturantDetail(id) {
+  return request({
+    url: '/shopping/restaurant/' + id,
+    method: 'get'
+  })
+}
+/**
+ * 获取menu列表
+ */
+
+// export const getMenu = data => fetch('/shopping/v2/menu', data);
+export function getMenu(params) {
+  return request({
+    url: '/shopping/v2/menu/',
+    method: 'get',
+    params
+  })
+}
+/**
+ * 获取menu详情
+ */
+
+// export const getMenuById = category_id => fetch('/shopping/v2/menu/' + category_id);
+export function getMenuById(category_id) {
+  return request({
+    url: '/shopping/v2/menu/' + category_id,
+    method: 'get'
+  })
+}

+ 28 - 4
flash-waimai-manage/src/api/getData.js

@@ -40,8 +40,6 @@ export function searchplace(cityid, value) {
   })
 }
 
-
-
 /**
  * category 种类列表
  */
@@ -54,6 +52,7 @@ export function foodCategory(params) {
     method: 'get'
   })
 }
+
 /**
  * 获取餐馆列表
  */
@@ -68,7 +67,6 @@ export function getResturants(params) {
   })
 }
 
-
 /**
  * 获取餐馆数量
  */
@@ -102,7 +100,33 @@ export function updateResturant(params) {
 
 export function deleteResturant(id) {
   return request({
-    url: '/shopping/restaurant/'+id,
+    url: '/shopping/restaurant/' + id,
     method: 'delete'
   })
 }
+
+/**
+ * 获取食品列表
+ */
+
+// export const getFoods = data => fetch('/shopping/v2/foods', data)
+export function getFoods(params) {
+  return request({
+    url: '/shopping/v2/foods',
+    method: 'get',
+    params
+  })
+}
+
+/**
+ * 更新食品信息
+ */
+
+// export const updateFood = data => fetch('/shopping/v2/updatefood', data, 'POST');
+export function updateFood(params) {
+  return request({
+    url: '/shopping/v2/updatefood',
+    method: 'post',
+    params
+  })
+}

+ 1 - 1
flash-waimai-manage/src/lang/en.js

@@ -38,7 +38,7 @@ export default {
     size: 'Global Size'
   },
   login: {
-    title: 'web-flash',
+    title: 'flash-waimai',
     logIn: 'Log in',
     username: 'Username',
     password: 'Password'

+ 1 - 1
flash-waimai-manage/src/lang/zh.js

@@ -38,7 +38,7 @@ export default {
     size: '布局大小'
   },
   login: {
-    title: 'web-flash',
+    title: 'flash-waimai',
     logIn: '登录',
     username: '账号',
     password: '密码'

+ 14 - 2
flash-waimai-manage/src/router/index.js

@@ -68,15 +68,27 @@ export const constantRouterMap = [
     alwaysShow: true,
     meta: {
       roles: ['administrator', 'developer'],
-      title: '数据管理',
+      title: '业务管理',
       icon: 'message'
   },
     children: [
       {
         path: 'shop',
         name: 'shop',
-        component:() => import('@/views/data/shop/shopList'),
+        component:() => import('@/views/business/shop/index'),
         meta: { title: '商铺管理' }
+      },
+      {
+        path: 'food',
+        name: 'food',
+        component:() => import('@/views/business/food/index'),
+        meta: { title: '食品管理' }
+      },
+      {
+        path: 'order',
+        name: 'order',
+        component:() => import('@/views/business/order/index'),
+        meta: { title: '订单管理' }
       }
     ]
   },

+ 0 - 1
flash-waimai-manage/src/utils/request.js

@@ -36,7 +36,6 @@ service.interceptors.response.use(
      */
     const res = response.data
     if (res.code !== 20000) {
-
       // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
       if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
       }

+ 256 - 0
flash-waimai-manage/src/views/business/food/food.js

@@ -0,0 +1,256 @@
+import { getApiUrl } from '@/utils/utils'
+import { baseUrl, baseImgPath } from '@/config/env'
+
+import {
+  getFoods,
+  updateFood,
+  deleteFood
+} from '@/api/getData'
+import { getResturantDetail, getMenuById, getMenu } from '@/api/business/shop'
+export default {
+  data() {
+    return {
+      baseUrl,
+      baseImgPath,
+      restaurant_id: null,
+      city: {},
+      offset: 0,
+      limit: 20,
+      count: 0,
+      tableData: [],
+      currentPage: 1,
+      selectTable: {},
+      dialogFormVisible: false,
+      menuOptions: [],
+      selectMenu: {},
+      selectIndex: null,
+      specsForm: {
+        specs: '',
+        packing_fee: 0,
+        price: 20
+      },
+      specsFormrules: {
+        specs: [
+          { required: true, message: '请输入规格', trigger: 'blur' }
+        ]
+      },
+      specsFormVisible: false,
+      expendRow: [],
+      total: 0,
+      listQuery: {
+        page: 1,
+        limit: 20
+      }
+    }
+  },
+  created() {
+    this.restaurant_id = this.$route.query.restaurant_id
+    this.initData()
+  },
+  computed: {
+    specs: function() {
+      let specs = []
+      if (this.selectTable.specfoods) {
+        this.selectTable.specfoods.forEach(item => {
+          specs.push({
+            specs: item.specs_name,
+            packing_fee: item.packing_fee,
+            price: item.price
+          })
+        })
+      }
+      return specs
+    }
+  },
+  methods: {
+    async initData() {
+      this.fetchData()
+    },
+    async getMenu() {
+      this.menuOptions = []
+      try {
+        console.log('seltable',this.selectTable)
+        const menuResponse = await getMenu({ restaurant_id: this.selectTable.restaurant_id, allMenu: true })
+        const menu = menuResponse.data
+        menu.forEach((item, index) => {
+          this.menuOptions.push({
+            label: item.name,
+            value: item.id,
+            index
+          })
+        })
+      } catch (err) {
+        console.log('获取食品种类失败', err)
+      }
+    },
+    async fetchData() {
+      getFoods({
+        page: this.listQuery.page,
+        limit: this.listQuery.limit,
+        restaurant_id: this.restaurant_id
+      }).then(response => {
+        this.tableData = []
+        const foods = response.data.records
+        this.total = response.data.total
+        foods.forEach((item, index) => {
+          const tableData = {}
+          tableData.name = item.name
+          tableData.item_id = item.item_id
+          tableData.description = item.description
+          tableData.rating = item.rating
+          tableData.month_sales = item.month_sales
+          tableData.restaurant_id = item.restaurant_id
+          tableData.category_id = item.category_id
+          tableData.image_path = item.image_path
+          tableData.specfoods = item.specfoods
+          tableData.index = index
+          this.tableData.push(tableData)
+        })
+      })
+    },
+    tableRowClassName(row, index) {
+      if (index === 1) {
+        return 'info-row'
+      } else if (index === 3) {
+        return 'positive-row'
+      }
+      return ''
+    },
+    addspecs() {
+      this.specs.push({ ...this.specsForm })
+      this.specsForm.specs = ''
+      this.specsForm.packing_fee = 0
+      this.specsForm.price = 20
+      this.specsFormVisible = false
+    },
+    deleteSpecs(index) {
+      this.specs.splice(index, 1)
+    },
+    handleSizeChange(val) {
+      console.log(`每页 ${val} 条`)
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val
+      this.offset = (val - 1) * this.limit
+      this.fetchData()
+    },
+    expand(row, status) {
+      if (status) {
+        this.getSelectItemData(row)
+      } else {
+        const index = this.expendRow.indexOf(row.index)
+        this.expendRow.splice(index, 1)
+      }
+    },
+    handleEdit(row) {
+      this.getSelectItemData(row, 'edit')
+      this.dialogFormVisible = true
+    },
+    async getSelectItemData(row, type) {
+      const response = await getResturantDetail(row.restaurant_id)
+      const restaurant = response.data
+      const categoryResponse = await getMenuById(row.category_id)
+      const category = categoryResponse.data
+      this.selectTable = {
+        ...row, ...{
+          restaurant_name: restaurant.name,
+          restaurant_address: restaurant.address,
+          category_name: category.name,
+          image: getApiUrl() + '/file/getImgStream?fileName=' + row.image_path
+        }
+      }
+
+      this.selectMenu = { label: category.name, value: row.category_id }
+      this.tableData.splice(row.index, 1, { ...this.selectTable })
+      this.$nextTick(() => {
+        this.expendRow.push(row.index)
+      })
+      if (type === 'edit' && this.restaurant_id !== row.restaurant_id) {
+        this.getMenu()
+      }
+    },
+    handleSelect(index) {
+      this.selectIndex = index
+      this.selectMenu = this.menuOptions[index]
+    },
+    async handleDelete(index, row) {
+      try {
+        const res = await deleteFood(row.item_id)
+        if (res.status === 1) {
+          this.$message({
+            type: 'success',
+            message: '删除食品成功'
+          })
+          this.tableData.splice(index, 1)
+        } else {
+          throw new Error(res.message)
+        }
+      } catch (err) {
+        this.$message({
+          type: 'error',
+          message: err.message
+        })
+        console.log('删除食品失败')
+      }
+    },
+    handleServiceAvatarScucess(res, file) {
+      if (res.status === 1) {
+        this.selectTable.image_path = res.image_path
+      } else {
+        this.$message.error('上传图片失败!')
+      }
+    },
+    beforeAvatarUpload(file) {
+      const isRightType = (file.type === 'image/jpeg') || (file.type === 'image/png')
+      const isLt2M = file.size / 1024 / 1024 < 2
+
+      if (!isRightType) {
+        this.$message.error('上传头像图片只能是 JPG 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!')
+      }
+      return isRightType && isLt2M
+    },
+    async updateFood() {
+      this.dialogFormVisible = false
+      try {
+        const subData = { new_category_id: this.selectMenu.value, specs: this.specs }
+        const postData = { ...this.selectTable, ...subData }
+        console.log('postdata',postData)
+        const res = await updateFood(postData)
+        console.log(res)
+        if (res.status === 1) {
+          this.$message({
+            type: 'success',
+            message: '更新食品信息成功'
+          })
+          this.getFoods()
+        } else {
+          this.$message({
+            type: 'error',
+            message: res.message
+          })
+        }
+      } catch (err) {
+        console.log('更新餐馆信息失败', err)
+      }
+    },
+    fetchNext() {
+      this.listQuery.page = this.listQuery.page + 1
+      this.fetchData()
+    },
+    fetchPrev() {
+      this.listQuery.page = this.listQuery.page - 1
+      this.fetchData()
+    },
+    fetchPage(page) {
+      this.listQuery.page = page
+      this.fetchData()
+    },
+    changeSize(limit) {
+      this.listQuery.limit = limit
+      this.fetchData()
+    }
+  }
+}

+ 210 - 0
flash-waimai-manage/src/views/business/food/index.vue

@@ -0,0 +1,210 @@
+<template>
+  <div class="fillcontain">
+    <div class="table_container">
+      <el-table
+        :data="tableData"
+        @expand='expand'
+        :expand-row-keys='expendRow'
+        :row-key="row => row.index"
+        style="width: 100%">
+        <el-table-column type="expand">
+          <template slot-scope="props">
+            <el-form label-position="left" inline class="demo-table-expand">
+              <el-form-item label="食品名称">
+                <span>{{ props.row.name }}</span>
+              </el-form-item>
+              <el-form-item label="餐馆名称">
+                <span>{{ props.row.restaurant_name }}</span>
+              </el-form-item>
+              <el-form-item label="食品 ID">
+                <span>{{ props.row.item_id }}</span>
+              </el-form-item>
+              <el-form-item label="餐馆 ID">
+                <span>{{ props.row.restaurant_id }}</span>
+              </el-form-item>
+              <el-form-item label="食品介绍">
+                <span>{{ props.row.description }}</span>
+              </el-form-item>
+              <el-form-item label="餐馆地址">
+                <span>{{ props.row.restaurant_address }}</span>
+              </el-form-item>
+              <el-form-item label="食品评分">
+                <span>{{ props.row.rating }}</span>
+              </el-form-item>
+              <el-form-item label="食品分类">
+                <span>{{ props.row.category_name }}</span>
+              </el-form-item>
+              <el-form-item label="月销量">
+                <span>{{ props.row.month_sales }}</span>
+              </el-form-item>
+            </el-form>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="食品名称"
+          prop="name">
+        </el-table-column>
+        <el-table-column
+          label="食品介绍"
+          prop="description">
+        </el-table-column>
+        <el-table-column
+          label="评分"
+          prop="rating">
+        </el-table-column>
+        <el-table-column label="操作" width="160">
+          <template slot-scope="scope">
+            <el-button
+              size="small"
+              @click="handleEdit(scope.row)">编辑</el-button>
+            <el-button
+              size="small"
+              type="danger"
+              @click="handleDelete(scope.$index, scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :page-sizes="[10, 20, 50, 100,500]"
+        :page-size="listQuery.limit"
+        :total="total"
+        @size-change="changeSize"
+        @current-change="fetchPage"
+        @prev-click="fetchPrev"
+        @next-click="fetchNext">
+      </el-pagination>
+      <el-dialog title="修改食品信息"     :visible.sync="dialogFormVisible">
+        <el-form :model="selectTable">
+          <el-form-item label="食品名称" label-width="100px">
+            <el-input v-model="selectTable.name" auto-complete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="食品介绍" label-width="100px">
+            <el-input v-model="selectTable.description"></el-input>
+          </el-form-item>
+          <el-form-item label="食品分类" label-width="100px">
+            <el-select v-model="selectIndex" :placeholder="selectMenu.label" @change="handleSelect">
+              <el-option
+                v-for="item in menuOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.index">
+              </el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="食品图片" label-width="100px">
+            <el-upload
+              class="avatar-uploader"
+              :action="baseUrl + '/v1/addimg/food'"
+              :show-file-list="false"
+              :on-success="handleServiceAvatarScucess"
+              :before-upload="beforeAvatarUpload">
+              <img v-if="selectTable.image_path" :src="selectTable.image" class="avatar">
+              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+            </el-upload>
+          </el-form-item>
+        </el-form>
+        <el-row style="overflow: auto; text-align: center;">
+          <el-table
+            :data="specs"
+            style="margin-bottom: 20px;"
+            :row-class-name="tableRowClassName">
+            <el-table-column
+              prop="specs"
+              label="规格">
+            </el-table-column>
+            <el-table-column
+              prop="packing_fee"
+              label="包装费">
+            </el-table-column>
+            <el-table-column
+              prop="price"
+              label="价格">
+            </el-table-column>
+            <el-table-column label="操作" >
+              <template slot-scope="scope">
+                <el-button
+                  size="small"
+                  type="danger"
+                  @click="deleteSpecs(scope.$index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <el-button type="primary" @click="specsFormVisible = true" style="margin-bottom: 10px;">添加规格</el-button>
+        </el-row>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="dialogFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="updateFood">确 定</el-button>
+        </div>
+      </el-dialog>
+
+
+      <el-dialog title="添加规格"  :visible.sync="specsFormVisible" >
+        <el-form :rules="specsFormrules" :model="specsForm">
+          <el-form-item label="规格" label-width="100px" prop="specs">
+            <el-input v-model="specsForm.specs" auto-complete="off"></el-input>
+          </el-form-item>
+          <el-form-item label="包装费" label-width="100px">
+            <el-input-number v-model="specsForm.packing_fee" :min="0" :max="100"></el-input-number>
+          </el-form-item>
+          <el-form-item label="价格" label-width="100px">
+            <el-input-number v-model="specsForm.price" :min="0" :max="10000"></el-input-number>
+          </el-form-item>
+        </el-form>
+        <div slot="footer" class="dialog-footer">
+          <el-button @click="specsFormVisible = false">取 消</el-button>
+          <el-button type="primary" @click="addspecs">确 定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script src="./food.js"></script>
+
+<style lang="less">
+  .demo-table-expand {
+    font-size: 0;
+  }
+  .demo-table-expand label {
+    width: 90px;
+    color: #99a9bf;
+  }
+  .demo-table-expand .el-form-item {
+    margin-right: 0;
+    margin-bottom: 0;
+    width: 50%;
+  }
+  .table_container{
+    padding: 20px;
+  }
+  .Pagination{
+    display: flex;
+    justify-content: flex-start;
+    margin-top: 8px;
+  }
+  .avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+  }
+  .avatar-uploader .el-upload:hover {
+    border-color: #20a0ff;
+  }
+  .avatar-uploader-icon {
+    font-size: 28px;
+    color: #8c939d;
+    width: 120px;
+    height: 120px;
+    line-height: 120px;
+    text-align: center;
+  }
+  .avatar {
+    width: 120px;
+    height: 120px;
+    display: block;
+  }
+</style>

+ 1 - 1
flash-waimai-manage/src/views/data/shop/shopList.vue

@@ -132,7 +132,7 @@
   </div>
 </template>
 
-<script src="./shopList.js"></script>
+<script src="./order.js"></script>
 
 
 <style lang="less">

flash-waimai-manage/src/views/data/shop/shopList.js → flash-waimai-manage/src/views/business/order/order.js


+ 182 - 0
flash-waimai-manage/src/views/business/shop/index.vue

@@ -0,0 +1,182 @@
+<template>
+
+  <div class="app-container">
+    <div class="block">
+    <div class="fillcontain">
+        <div class="table_container">
+            <el-table
+                :data="tableData"
+                style="width: 100%">
+                <el-table-column type="expand">
+                  <template slot-scope="props">
+                    <el-form label-position="left" inline class="demo-table-expand">
+                      <el-form-item label="店铺名称">
+                        <span>{{ props.row.name }}</span>
+                      </el-form-item>
+                      <el-form-item label="店铺地址">
+                        <span>{{ props.row.address }}</span>
+                      </el-form-item>
+                      <el-form-item label="店铺介绍">
+                        <span>{{ props.row.description }}</span>
+                      </el-form-item>
+                      <el-form-item label="店铺 ID">
+                        <span>{{ props.row.id }}</span>
+                      </el-form-item>
+                      <el-form-item label="联系电话">
+                        <span>{{ props.row.phone }}</span>
+                      </el-form-item>
+                      <el-form-item label="评分">
+                        <span>{{ props.row.rating }}</span>
+                      </el-form-item>
+                      <el-form-item label="销售量">
+                        <span>{{ props.row.recent_order_num }}</span>
+                      </el-form-item>
+                      <el-form-item label="分类">
+                        <span>{{ props.row.category }}</span>
+                      </el-form-item>
+                    </el-form>
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  label="店铺名称"
+                  prop="name">
+                </el-table-column>
+                <el-table-column
+                  label="店铺地址"
+                  prop="address">
+                </el-table-column>
+                <el-table-column
+                  label="店铺介绍"
+                  prop="description">
+                </el-table-column>
+                <el-table-column label="操作" width="300">
+                  <template slot-scope="scope">
+                    <el-button
+                      size="mini"
+                      type="primary"
+                      @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
+                    <el-button
+                      size="mini"
+                      type="success"
+                      @click="addFood(scope.$index, scope.row)">添加食品</el-button>
+                    <el-button
+                      size="mini"
+                      type="danger"
+                      @click="handleDelete(scope.$index, scope.row)">删除</el-button>
+                  </template>
+                </el-table-column>
+            </el-table>
+          <el-pagination
+            background
+            layout="total, sizes, prev, pager, next, jumper"
+            :page-sizes="[10, 20, 50, 100,500]"
+            :page-size="listQuery.limit"
+            :total="total"
+            @size-change="changeSize"
+            @current-change="fetchPage"
+            @prev-click="fetchPrev"
+            @next-click="fetchNext">
+          </el-pagination>
+            <el-dialog title="修改店铺信息"
+                       :visible.sync="dialogFormVisible"
+            >
+                <el-form :model="selectTable">
+
+                    <el-form-item label="店铺名称" label-width="100px">
+                        <el-input v-model="selectTable.name" auto-complete="off"></el-input>
+                    </el-form-item>
+
+                    <el-form-item label="详细地址" label-width="100px">
+                        <el-autocomplete
+                          v-model="address.address"
+                          :fetch-suggestions="querySearchAsync"
+                          placeholder="请输入地址"
+                          style="width: 100%;"
+                          @select="addressSelect"
+                        ></el-autocomplete>
+                        <span>当前城市:{{city.name}}</span>
+                    </el-form-item>
+                    <el-form-item label="店铺介绍" label-width="100px">
+                        <el-input v-model="selectTable.description"></el-input>
+                    </el-form-item>
+                    <el-form-item label="联系电话" label-width="100px">
+                        <el-input v-model="selectTable.phone"></el-input>
+                    </el-form-item>
+                    <el-form-item label="店铺分类" label-width="100px">
+                        <el-cascader
+                          :options="categoryOptions"
+                          v-model="selectedCategory"
+                          change-on-select
+                        ></el-cascader>
+                    </el-form-item>
+                    <el-form-item label="商铺图片" label-width="100px">
+                        <el-upload
+                          class="avatar-uploader"
+                          :action="baseUrl + '/v1/addimg/shop'"
+                          :show-file-list="false"
+                          :on-success="handleServiceAvatarScucess"
+                          :before-upload="beforeAvatarUpload">
+                          <img v-if="selectTable.image_path" :src="selectTable.image" class="avatar">
+                          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                        </el-upload>
+                    </el-form-item>
+                </el-form>
+              <div slot="footer" class="dialog-footer">
+                <el-button @click="dialogFormVisible = false">取 消</el-button>
+                <el-button type="primary" @click="updateShop">确 定</el-button>
+              </div>
+            </el-dialog>
+        </div>
+    </div>
+    </div>
+  </div>
+</template>
+
+<script src="./shop.js"></script>
+
+
+<style lang="less">
+    .demo-table-expand {
+        font-size: 0;
+    }
+    .demo-table-expand label {
+        width: 90px;
+        color: #99a9bf;
+    }
+    .demo-table-expand .el-form-item {
+        margin-right: 0;
+        margin-bottom: 0;
+        width: 50%;
+    }
+    .table_container{
+        padding: 20px;
+    }
+    .Pagination{
+        display: flex;
+        justify-content: flex-start;
+        margin-top: 8px;
+    }
+    .avatar-uploader .el-upload {
+        border: 1px dashed #d9d9d9;
+        border-radius: 6px;
+        cursor: pointer;
+        position: relative;
+        overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+        border-color: #20a0ff;
+    }
+    .avatar-uploader-icon {
+        font-size: 28px;
+        color: #8c939d;
+        width: 120px;
+        height: 120px;
+        line-height: 120px;
+        text-align: center;
+    }
+    .avatar {
+        width: 120px;
+        height: 120px;
+        display: block;
+    }
+</style>

+ 224 - 0
flash-waimai-manage/src/views/business/shop/shop.js

@@ -0,0 +1,224 @@
+import { getApiUrl } from '@/utils/utils'
+import {
+  cityGuess,
+  getResturants,
+  getResturantsCount,
+  foodCategory,
+  updateResturant,
+  searchplace,
+  deleteResturant
+} from '@/api/getData'
+
+export default {
+  data() {
+    return {
+      city: {},
+
+      // offset: 0,
+      // limit: 20,
+      count: 0,
+      baseUrl: getApiUrl(),
+      tableData: [],
+      currentPage: 1,
+      selectTable: {},
+      dialogFormVisible: false,
+      categoryOptions: [],
+      selectedCategory: [],
+      address: {},
+      total: 0,
+      listQuery: {
+        page: 1,
+        limit: 20
+      }
+    }
+  },
+  created() {
+    this.initData()
+  },
+
+  methods: {
+    async initData() {
+      try {
+        cityGuess().then(response => {
+          this.city = response.data
+          getResturantsCount().then(response2 => {
+            this.count = response2.count
+            this.fetchData()
+          })
+        })
+      } catch (err) {
+        console.log('获取数据失败', err)
+      }
+    },
+    async getCategory() {
+      try {
+        const response = await foodCategory()
+        const categories = response.data
+        categories.forEach(item => {
+          if (item.sub_categories.length) {
+            const addnew = {
+              value: item.name,
+              label: item.name,
+              children: []
+            }
+            item.sub_categories.forEach((subitem, index) => {
+              if (index === 0) {
+                return
+              }
+              addnew.children.push({
+                value: subitem.name,
+                label: subitem.name
+              })
+            })
+            this.categoryOptions.push(addnew)
+          }
+        })
+      } catch (err) {
+        console.log('获取商铺种类失败', err)
+      }
+    },
+    async fetchData() {
+      // const {latitude, longitude} = this.city;
+      const latitude = ''
+      const longitude = ''
+      getResturants({ page: this.listQuery.page, limit: this.listQuery.limit }).then(response => {
+        console.log(response)
+        const restaurants = response.data.records
+        this.total = response.data.total
+        this.tableData = []
+        restaurants.forEach(item => {
+          const tableData = {}
+          tableData.name = item.name
+          tableData.address = item.address
+          tableData.description = item.description
+          tableData.id = item.id
+          tableData.phone = item.phone
+          tableData.rating = item.rating
+          tableData.recent_order_num = item.recent_order_num
+          tableData.category = item.category
+          tableData.image_path = item.image_path
+          this.tableData.push(tableData)
+        })
+      })
+    },
+    handleSizeChange(val) {
+      console.log(`每页 ${val} 条`)
+    },
+    handleCurrentChange(val) {
+      this.currentPage = val
+      this.offset = (val - 1) * this.limit
+      this.getResturants()
+    },
+    fetchNext() {
+      this.listQuery.page = this.listQuery.page + 1
+      this.fetchData()
+    },
+    fetchPrev() {
+      this.listQuery.page = this.listQuery.page - 1
+      this.fetchData()
+    },
+    fetchPage(page) {
+      this.listQuery.page = page
+      this.fetchData()
+    },
+    changeSize(limit) {
+      this.listQuery.limit = limit
+      this.fetchData()
+    },
+    handleEdit(index, row) {
+      this.selectTable = row
+      this.selectTable.image = getApiUrl() + '/file/getImgStream?fileName=' + row.image_path
+      console.log(this.selectTable)
+      this.address.address = row.address
+      this.dialogFormVisible = true
+      this.selectedCategory = row.category.split('/')
+      if (!this.categoryOptions.length) {
+        this.getCategory()
+      }
+    },
+    addFood(index, row) {
+      this.$router.push({ path: 'addGoods', query: { restaurant_id: row.id } })
+    },
+    async handleDelete(index, row) {
+      try {
+        const res = await deleteResturant(row.id)
+        if (res.status == 1) {
+          this.$message({
+            type: 'success',
+            message: '删除店铺成功'
+          })
+          this.tableData.splice(index, 1)
+        } else {
+          throw new Error(res.message)
+        }
+      } catch (err) {
+        this.$message({
+          type: 'error',
+          message: err.message
+        })
+        console.log('删除店铺失败')
+      }
+    },
+    async querySearchAsync(queryString, cb) {
+      if (queryString) {
+        try {
+          const cityList = await searchplace(this.city.id, queryString)
+          if (cityList instanceof Array) {
+            cityList.map(item => {
+              item.value = item.address
+              return item
+            })
+            cb(cityList)
+          }
+        } catch (err) {
+          console.log(err)
+        }
+      }
+    },
+    addressSelect(vale) {
+      const { address, latitude, longitude } = vale
+      this.address = { address, latitude, longitude }
+    },
+    handleServiceAvatarScucess(res, file) {
+      if (res.status == 1) {
+        this.selectTable.image_path = res.image_path
+      } else {
+        this.$message.error('上传图片失败!')
+      }
+    },
+    beforeAvatarUpload(file) {
+      const isRightType = (file.type === 'image/jpeg') || (file.type === 'image/png')
+      const isLt2M = file.size / 1024 / 1024 < 2
+
+      if (!isRightType) {
+        this.$message.error('上传头像图片只能是 JPG 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!')
+      }
+      return isRightType && isLt2M
+    },
+    async updateShop() {
+      this.dialogFormVisible = false
+      try {
+        Object.assign(this.selectTable, this.address)
+        this.selectTable.category = this.selectedCategory.join('/')
+        console.log(this.selectTable)
+        updateResturant(this.selectTable).then(response => {
+          this.$message({
+            type: 'success',
+            message: '更新店铺信息成功'
+          })
+          this.getResturants()
+        })
+
+      } catch (err) {
+        console.log('更新餐馆信息失败', err)
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      }
+    }
+  }
+}