فهرست منبع

添加了Sse前端通知工具和python接口

0714Star 6 ماه پیش
والد
کامیت
7f052380ad
32فایلهای تغییر یافته به همراه405 افزوده شده و 65 حذف شده
  1. 0 1
      .idea/misc.xml
  2. 1 1
      display_model_for_smartagriculture/public/api.js
  3. 2 1
      display_model_for_smartagriculture/public/config.js
  4. 1 1
      display_model_for_smartagriculture/src/App.vue
  5. 2 4
      display_model_for_smartagriculture/src/main.js
  6. 1 1
      display_model_for_smartagriculture/src/utils/request.js
  7. 1 0
      springboot/src/main/java/com/example/common/config/JwtInterceptor.java
  8. 3 1
      springboot/src/main/java/com/example/common/config/WebConfig.java
  9. 6 2
      springboot/src/main/java/com/example/controller/OrdersController.java
  10. 128 0
      springboot/src/main/java/com/example/controller/SseEmmiterController.java
  11. 19 2
      springboot/src/main/java/com/example/service/OrdersService.java
  12. 27 0
      springboot/src/main/java/com/example/service/SseEmmiterService.java
  13. 1 1
      springboot/src/main/resources/mapper/OrdersMapper.xml
  14. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/common/main.js.map
  15. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/components/my-login/my-login.js.map
  16. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/components/my-userinfo/my-userinfo.js.map
  17. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/pages/home/home.js.map
  18. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map
  19. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/subpkg/login/login.js.map
  20. 0 0
      uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/subpkg/order/order.js.map
  21. 2 1
      vue/.env.development
  22. 3 2
      vue/.env.production
  23. 0 0
      vue/src/assets/audio/tipMusic.mp3
  24. 0 0
      vue/src/assets/video/GrassMontior.mp4
  25. 0 0
      vue/src/assets/video/monitor1.mp4
  26. BIN
      vue/src/assets/video/监控视频.mp4
  27. 2 4
      vue/src/components/viewMonitor.vue
  28. 7 3
      vue/src/main.js
  29. 55 15
      vue/src/views/Manager.vue
  30. 1 1
      vue/src/views/manager/AI/Monitor.vue
  31. 136 24
      vue/src/views/manager/AI/PestAnalysis.vue
  32. 7 0
      vue/src/views/manager/Shop/ShopOrders.vue

+ 0 - 1
.idea/misc.xml

@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ASMSmaliIdeaPluginConfiguration">
     <asm skipDebug="true" skipFrames="true" skipCode="false" expandFrames="false" />

+ 1 - 1
display_model_for_smartagriculture/public/api.js

@@ -1,7 +1,7 @@
 import axios from 'axios';
 const config = {
 	// baseURL: process.env.baseURL
-	baseURL: 'http://localhost:3000/data/',
+	baseURL: 'http://118.89.54.252:3000/data/',
 	timeout: 1000,
 	headers: {
 		'Content-Type': 'application/json',

+ 2 - 1
display_model_for_smartagriculture/public/config.js

@@ -156,7 +156,8 @@ export default {
 			}
 		]
 	},
-	defaultconfig: [{
+	defaultconfig: [
+		{
 		key: 'theme',
 		value: 'dark',
 		label: '界面主题',

+ 1 - 1
display_model_for_smartagriculture/src/App.vue

@@ -293,7 +293,7 @@ export default {
     exit: function() {
       utils.showconfirm('确定要退出吗?');
 
-      const redirectUrl ="http://"+this.$Url+"/home"
+      const redirectUrl ="http://118.89.54.252:3441/home"
       window.location.href = redirectUrl;
     },
     /**

+ 2 - 4
display_model_for_smartagriculture/src/main.js

@@ -15,14 +15,12 @@ import '/public/dark_theme.css';
 
 import App from './App.vue'
 import router from './router'
-// import request from "./utils/request";
-
-
+// const url = 'http://118.89.54.252:3441/'
 var app = createApp(App);
 // vue3 给原型上挂载属性
 app.config.globalProperties.$echarts = echarts;
 app.config.globalProperties.$request = request;
-app.config.globalProperties.$Url = "localhost:3441"
+// app.config.globalProperties.$Url = url
 for (const name in ElIcons) {
 	app.component(name, ElIcons[name])
 }

+ 1 - 1
display_model_for_smartagriculture/src/utils/request.js

@@ -2,7 +2,7 @@ import axios from 'axios'
 
 // 创建可一个新的axios对象
 const request = axios.create({
-    baseURL: "https://69b89r4952.yicp.fun",   // 后端的接口地址  ip:port // process.env.VUE_APP_BASEURL
+    baseURL: 'http://118.89.54.252:2441',//this.$Url,   // 后端的接口地址  ip:port // process.env.VUE_APP_BASEURL
     timeout: 30000                          // 30s请求超时
 })
 

+ 1 - 0
springboot/src/main/java/com/example/common/config/JwtInterceptor.java

@@ -36,6 +36,7 @@ public class JwtInterceptor implements HandlerInterceptor {
     private AdminStoreService adminStoreService;
     @Resource
     private UserService userService;
+
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
         // 1. 从http请求的header中获取token

+ 3 - 1
springboot/src/main/java/com/example/common/config/WebConfig.java

@@ -19,6 +19,8 @@ public class WebConfig implements  WebMvcConfigurer {
                 .excludePathPatterns("/")
                 .excludePathPatterns("/login")
                 .excludePathPatterns("/register")
-                .excludePathPatterns("/files/**");
+                .excludePathPatterns("/files/**")
+                .excludePathPatterns("/sse/**")
+        ;
     }
 }

+ 6 - 2
springboot/src/main/java/com/example/controller/OrdersController.java

@@ -30,6 +30,9 @@ public class OrdersController {
     private OrdersService ordersService;
     @Resource
     private SaleStatementService saleStatementService;
+
+    @Resource
+    private SseEmmiterController sseEmmiterController;
     /**
      * 获取店铺未完成的订单个数
      * @param shopId
@@ -106,8 +109,9 @@ public class OrdersController {
 //            saleStatement.setTimeOver(DateUtil.now());
 //            saleStatementService.add(saleStatement);
 //        });
-
-        return Result.success(ordersService.selectById(orders.getId()));
+        Orders dbOrder = ordersService.selectById(orders.getId());
+        ordersService.updateClientCount(dbOrder.getStoreId());
+        return Result.success(ordersService.selectById(dbOrder.getId()));
     }
 
     /**

+ 128 - 0
springboot/src/main/java/com/example/controller/SseEmmiterController.java

@@ -0,0 +1,128 @@
+package com.example.controller;
+
+import com.example.service.OrdersService;
+import com.example.service.SseEmmiterService;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.logging.Logger;
+
+/**
+ * 时间通知控件
+ *
+ * @author 熊浩毅
+ * @time 2024-05-11 8:50
+ * @Description
+ */
+@RestController
+@RequestMapping("/sse")
+public class SseEmmiterController {
+    private static AtomicInteger count = new AtomicInteger(0);
+
+    @Resource
+    private  SseEmmiterService sseEmmiterService ;
+    /**
+     * 使用map 根据storeId获取对应的SseEmitter
+     */
+    private static final Map<Integer, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();
+    @Resource
+    private OrdersService ordersService ;
+    /**
+     * 创建用户连接器返回SseEmitter
+     * @param storeId
+     * @return
+     */
+    @GetMapping(path = "/subscribe/{storeId}",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+    public SseEmitter subscribe(@PathVariable("storeId") Integer storeId) throws IOException {
+        SseEmitter sseEmitter = new SseEmitter(0L);
+        // 设置前端的重试时间为15s,如果不加这个发送一下,前端就不会显示连接成功
+        sseEmitter.send("连接成功");
+        // 注册回调
+        sseEmitter.onCompletion(completionCallBack(storeId));
+        sseEmitter.onTimeout(timeOutCallBack(storeId));
+        sseEmitter.onError(errorCallBack(storeId));
+
+        sseEmitterMap.put(storeId,sseEmitter);
+        // 数量+1
+        count.getAndIncrement();
+        return  sseEmitter;
+    }
+
+    /**
+     * 测试接口
+     * @param storeId 通知的店铺id
+     * @param message 通知信息
+     */
+
+    public void sendMessage(Integer storeId,Object message){
+        if(sseEmitterMap.containsKey(storeId)){
+            try{
+                SseEmitter sseEmitter = sseEmitterMap.get(storeId);
+                sseEmitter.send(message);
+            } catch (IOException e) {
+                remove(storeId);
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @GetMapping("orderCounts")
+    public void sendMessageOfCount(Integer storeId,String message){
+        if(sseEmitterMap.containsKey(storeId)){
+            SseEmitter sseEmitter = sseEmitterMap.get(storeId);
+            String data = "{'type':'orderCount','count':10}";
+
+        }
+    }
+    private void remove(Integer storeId){
+        sseEmitterMap.remove(storeId);
+    }
+
+
+    //////////////////////////
+    /**
+     * 移除的回调
+     * @param storeId
+     * @return
+     */
+    private Runnable completionCallBack(Integer storeId){
+        return ()->{
+
+        };
+    }
+
+    /**
+     * 超时的回调
+     * @param storeId
+     * @return
+     */
+    private Runnable timeOutCallBack(Integer storeId){
+        return ()->{
+
+        };
+    }
+
+    /**
+     * 错误的回调
+     *
+     * @param storeId
+     * @return
+     */
+    private Consumer<Throwable> errorCallBack(Integer storeId){
+        return throwable->{
+
+        };
+    }
+}

+ 19 - 2
springboot/src/main/java/com/example/service/OrdersService.java

@@ -7,6 +7,7 @@ import com.example.common.enums.OrderStatusDELIVERY;
 import com.example.common.enums.OrderStatusToShop;
 import com.example.common.enums.OrderType;
 import com.example.common.enums.ResultCodeEnum;
+import com.example.controller.SseEmmiterController;
 import com.example.entity.Account;
 import com.example.entity.Orders;
 import com.example.entity.Product;
@@ -24,6 +25,7 @@ import com.github.pagehelper.util.StringUtil;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -31,7 +33,6 @@ import java.util.List;
  **/
 @Service
 public class OrdersService {
-
     @Resource
     private OrdersMapper ordersMapper;
     @Resource
@@ -39,7 +40,8 @@ public class OrdersService {
     @Resource
     private ProductMapper productMapper;
     static final Integer costTime = 1200; //1200s 20分支
-
+    @Resource
+    private SseEmmiterController sseEmmiterController; //
     public Integer getNumsWithShopId(Integer shopId){
         return ordersMapper.getUnfinishedNums(shopId);
     }
@@ -73,9 +75,24 @@ public class OrdersService {
 
         ordersMapper.insert(orders);
         Orders resOrders = ordersMapper.selectById(orders.getId());
+
+        // 通知客户端更新订单数量
+        updateClientCount(resOrders.getStoreId());
         return resOrders;
         //this.setCache(orders.getId()); // 设置缓存 但是这里插入前是没有orders的id的应该怎么处理
     }
+
+    /**
+     * 更新storeId 订单数量
+     */
+    public void updateClientCount(Integer storeId){
+        Integer numsWithShopId = getNumsWithShopId(storeId);
+        HashMap<String ,Object> resData = new HashMap<>();
+        resData.put("type","orderCount");
+        resData.put("count",numsWithShopId);
+        sseEmmiterController.sendMessage(storeId,resData);
+    }
+
     /**
      * 删除
      */

+ 27 - 0
springboot/src/main/java/com/example/service/SseEmmiterService.java

@@ -0,0 +1,27 @@
+package com.example.service;
+
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * 功能:
+ *
+ * @author 熊浩毅
+ * @time 2024-05-11 9:01
+ * @Description
+ */
+@Service
+public class SseEmmiterService {
+    @Resource
+    private OrdersService ordersService;
+
+    /**
+     * 获取订单数量的回调函数
+     * @param storeId
+     * @return
+     */
+    public Integer ordersCountCallback(Integer storeId){
+        return ordersService.getNumsWithShopId(storeId);
+    }
+}

+ 1 - 1
springboot/src/main/resources/mapper/OrdersMapper.xml

@@ -108,7 +108,7 @@
             <if test="transCode != null"> and trans_code like concat('%', #{transCode}, '%')</if>
             <if test="storeId != null"> and store_id = #{storeId}</if>
         </where>
-        order by orders.id desc
+        order by orders.order_state desc, orders.id desc
     </select>
 
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/common/main.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/components/my-login/my-login.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/components/my-userinfo/my-userinfo.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/pages/home/home.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/pages/index/index.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/subpkg/login/login.js.map


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
uniapp/unpackage/dist/dev/.sourcemap/mp-weixin/subpkg/order/order.js.map


+ 2 - 1
vue/.env.development

@@ -1,2 +1,3 @@
 VUE_APP_BASEURL='http://localhost:2441'
-VUE_FLASK_BASEURL='http://localhost:5000'
+VUE_APP_VISIBLE_URL='http://localhost:3000'
+VUE_APP_FLASK_URL='http://localhost:4441'

+ 3 - 2
vue/.env.production

@@ -1,2 +1,3 @@
-VUE_APP_BASEURL='http://:2441'
-VUE_FLASK_BASEURL='http://localhost:5000'
+VUE_APP_BASEURL='http://118.89.54.252:2441'
+VUE_APP_VISIBLE_URL='http://118.89.54.252:3000'
+VUE_APP_FLASK_URL='http://118.89.54.252:4441'

+ 0 - 0
vue/src/assets/audio/提示音.mp3 → vue/src/assets/audio/tipMusic.mp3


+ 0 - 0
vue/src/assets/video/草原监控.mp4 → vue/src/assets/video/GrassMontior.mp4


+ 0 - 0
vue/src/assets/video/稻田监控.mp4 → vue/src/assets/video/monitor1.mp4


BIN
vue/src/assets/video/监控视频.mp4


+ 2 - 4
vue/src/components/viewMonitor.vue

@@ -42,14 +42,12 @@ export default {
   },
   data() {
     return {
-      videoList: [require("../assets/video/稻田监控.mp4"), require("../assets/video/草原监控.mp4")],
+      videoList: [require("../assets/video/monitor1.mp4"), require("../assets/video/GrassMontior.mp4")],
       imgList: [
         require("../assets/imgs/bg.jpg"),
         require("../assets/imgs/bg.jpg"),
-        // require("../assets/imgs/bg.jpg"),
-        // require("../assets/imgs/bg.jpg"),
       ],
-      selectedVideo: require("../assets/video/稻田监控.mp4"),//没用
+      selectedVideo: require("../assets/video/monitor1.mp4"),//没用
     };
   },
   methods: {

+ 7 - 3
vue/src/main.js

@@ -16,10 +16,14 @@ Vue.config.productionTip = false
 // Vue.prototype.$monment = monment
 Vue.prototype.$echarts= echarts
 Vue.prototype.$request = request
+
 Vue.prototype.$baseUrl = process.env.VUE_APP_BASEURL
-Vue.prototype.$flaskUrl= process.env.VUE_APP_FLASKURL
+Vue.prototype.$visibleUrl = process.env.VUE_APP_VISIBLE_URL
+Vue.prototype.$flaskUrl= process.env.VUE_APP_FLASK_URL
 Vue.use(ElementUI, {size: "small"})
-new Vue({
+const vue = new Vue({
     router,
     render: h => h(App)
-}).$mount('#app')
+})
+vue.$mount('#app')
+Vue.prototype.$bus = vue // vue组件自带EventBus

+ 55 - 15
vue/src/views/Manager.vue

@@ -99,11 +99,11 @@
 
       <!--  数据表格  -->
       <div class="manager-main-right">
-        <router-view @update:user="updateUser" />
+        <router-view @update:user="updateUser"  />
       </div>
     </div>
-  <audio ref="audioPlayer" muted="muted"src="../assets/audio/提示音.mp3" >
-<!--    <source >-->
+  <audio ref="audioPlayer">
+    <source  muted="muted"  src="../assets/audio/tipMusic.mp3">
   </audio>
   </div>
 </template>
@@ -114,10 +114,12 @@ export default {
   data() {
     return {
       user: JSON.parse(localStorage.getItem('xm-user') || '{}'),
-      linkUrl: 'http://localhost:3000/#/index',
-      audioUrl: require('@/assets/audio/提示音.mp3'),
+      linkUrl: this.$visibleUrl,//process.env.VUE_VISIBLE_URL,
+      audioUrl: require('@/assets/audio/tipMusic.mp3'),
       ordersCount:null,
       timer:null,
+      source:null, // 连接
+      canPlay:false, // 点击交互页面后方可播放音频
     }
   },
   created() {
@@ -125,13 +127,23 @@ export default {
       this.$message.error("请登陆后重试!")
       this.$router.push('/login')
     }
-
+    const that = this
+    function callback (){
+      that.canPlay = true;
+      console.log("click")
+      document.removeEventListener("click",callback);
+    }
+    document.addEventListener("click",callback)
   },
   mounted(){
     // TODO 计时器
-    // setTimeout(()=>{
-    // },2000)
-    this.timer =  setInterval(this.getUnfinishedNums, 1000)
+    // this.timer =  setInterval(this.getUnfinishedNums, 1000)
+    this.ordersCount = this.getUnfinishedNums()
+    this.source = new EventSource(this.$baseUrl+'/sse/subscribe/'+this.user.storeId)
+    // 监听事件
+    this.source.addEventListener('open',this.onOpen,false)
+    this.source.addEventListener('message',this.onMessage,false)
+    this.source.addEventListener('error',this.onError,false)
   },
   unmounted() {
     clearTimeout(this.timer)
@@ -140,6 +152,7 @@ export default {
     updateUser() {
       this.user = JSON.parse(localStorage.getItem('xm-user') || '{}')   // 重新获取下用户的最新信息
     },
+
     goToPerson() {
         this.$router.push('/audit')
     },
@@ -150,14 +163,41 @@ export default {
     },
     getUnfinishedNums(){
       this.$request.get("/orders/getnums/"+this.user?.storeId).then(res=>{
-        if(res.data>this.ordersCount){
-          // console.log(this.$refs.audioPlayer)
-          // this.$refs.audioPlayer.play(); // 播放音效
-          // this.$emit("UpdateShopData")
-        }
-        this.ordersCount = res.data==0?null:res.data
+        // if(res.data>this.ordersCount){
+        //   if(this.canPlay)
+        //     this.$refs.audioPlayer.play(); // 播放音效
+        // }
+        this.updateAndPlay(this.ordersCount,res.data)
+        // this.ordersCount = res.data==0?null:res.data
       })
 
+    },
+    updateAndPlay(cur,newCount){ // 增多播放音效
+      if(newCount>cur){
+        if(this.canPlay)
+          this.$refs.audioPlayer.play(); // 播放音效
+      }
+      this.ordersCount = newCount==0?null:newCount
+    },
+    onOpen(e){
+    },
+    onMessage(e){
+      console.log(e,"onMessage")
+      if(e.data){
+        try{
+          var parse = JSON.parse(e.data);
+          if(parse.type=="orderCount"){
+            this.updateAndPlay(this.ordersCount,parse.count)
+            console.log(this.ordersCount,"ordersCount")
+            this.$bus.$emit("update:store") // 更新视图
+          }
+        }catch (e){
+          // console.error(e.message)
+        }
+      }
+    },
+    onError(e){
+
     }
   }
 }

+ 1 - 1
vue/src/views/manager/AI/Monitor.vue

@@ -8,7 +8,7 @@ export default {
   },
   data(){
     return{
-      videoUrl:require("@/assets/video/稻田监控.mp4"),
+      videoUrl:require("@/assets/video/monitor1.mp4"),
       img:require("@/assets/imgs/bg.jpg")
     }
   }

+ 136 - 24
vue/src/views/manager/AI/PestAnalysis.vue

@@ -3,22 +3,22 @@
   <div class="container">
 
     <div class="result-container">
-<!--      <span style="width: 400px;height: 300px">自定义</span>-->
+      <!--      <span style="width: 400px;height: 300px">自定义</span>-->
       <el-skeleton style="width:600px;height: 300px" :loading="isLoading" animated>
         <template slot="template">
           <el-skeleton-item
               variant="image"
               style="width: 600px; height: 300px;"
           />
-<!--          <div style="padding: 14px;">-->
-<!--            <el-skeleton-item variant="h3" style="width: 50%;" />-->
-<!--            <div-->
-<!--                style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"-->
-<!--            >-->
-<!--              <el-skeleton-item variant="text" style="margin-right: 16px;" />-->
-<!--              <el-skeleton-item variant="text" style="width: 30%;" />-->
-<!--            </div>-->
-<!--          </div>-->
+          <!--          <div style="padding: 14px;">-->
+          <!--            <el-skeleton-item variant="h3" style="width: 50%;" />-->
+          <!--            <div-->
+          <!--                style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"-->
+          <!--            >-->
+          <!--              <el-skeleton-item variant="text" style="margin-right: 16px;" />-->
+          <!--              <el-skeleton-item variant="text" style="width: 30%;" />-->
+          <!--            </div>-->
+          <!--          </div>-->
         </template>
         <template>
           <el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
@@ -36,35 +36,48 @@
         </template>
       </el-skeleton>
 
-<!--      <el-card style="width: 700px;height: 300px">-->
-<!--&lt;!&ndash;      &ndash;&gt;-->
-<!--      <el-image  :src="resPic" v-if="resPic!=null">-->
-<!--        <div slot="placeholder" class="image-slot">-->
-<!--          加载结果<span class="dot">...</span>-->
-<!--        </div>-->
-<!--      </el-image>-->
-<!--    </el-card>-->
+      <!--      <el-card style="width: 700px;height: 300px">-->
+      <!--&lt;!&ndash;      &ndash;&gt;-->
+      <!--      <el-image  :src="resPic" v-if="resPic!=null">-->
+      <!--        <div slot="placeholder" class="image-slot">-->
+      <!--          加载结果<span class="dot">...</span>-->
+      <!--        </div>-->
+      <!--      </el-image>-->
+      <!--    </el-card>-->
     </div>
 
+<!--    <div class="upload-container">-->
+<!--      <el-upload-->
+<!--          class="avatar-uploader"-->
+<!--          :action="'/files/upload'"-->
+<!--          :headers="{ token: user.token }"-->
+<!--          list-type="picture"-->
+<!--          :on-success="handleUploadSuccess"-->
+<!--      >-->
+<!--        <el-button type="primary">上传商品害虫图片</el-button>-->
+<!--      </el-upload>-->
+<!--    </div>-->
     <div class="upload-container">
       <el-upload
           class="avatar-uploader"
-          :action="$baseUrl + '/files/upload'"
+          :action="'/files/upload'"
           :headers="{ token: user.token }"
           list-type="picture"
           :on-success="handleUploadSuccess"
+          :http-request="uploadInStream"
       >
         <el-button type="primary">上传商品害虫图片</el-button>
       </el-upload>
     </div>
 
-
   </div>
 
 </template>
 
 <script>
 
+import axios from "axios";
+
 export default {
   name: "PestAnalysis",
   data() {
@@ -72,7 +85,7 @@ export default {
       user :JSON.parse(localStorage.getItem('xm-user') || '{}'),
       uploadResult: null,
       returnResult: null,
-      flaskBaseUrl: '', // Flask地址
+      flaskBaseUrl: this.$flaskUrl, // Flask地址
       resPic:null,
       isLoading:false,
     };
@@ -84,10 +97,109 @@ export default {
         this.resPic = require("/src/assets/imgs/query_result.png")
         this.isLoading = false; // 加载完成
       },2000)
-      var fileReader = new FileReader();
+
       return file
     },
-    uploadImg(){
+    fileToBase64(file){ // 获取文件base64
+      return new Promise((resolve,reject)=>{
+        const reader = new FileReader();
+        reader.readAsDataURL(file);
+        reader.onload = (e)=>resolve(reader.result.split(",").pop());
+        reader.onerror = (error)=>reject(error);
+      });
+    },
+    fileToByteStream(file){
+      return new Promise((resolve,reject)=>{
+        const reader = new FileReader();
+        reader.readAsBinaryString(file);
+        reader.onload = (e)=>resolve(reader.result);
+        reader.onerror = (error)=>reject(error);
+      });
+    },
+    fileToArrayBuffer(file){
+      return new Promise((resolve,reject)=>{
+        const reader = new FileReader();
+        reader.readAsArrayBuffer(file);
+        reader.onload = (e)=>resolve(reader.result);
+        reader.onerror = (error)=>reject(error);
+      });
+    },
+    bytesToBlobGetImgUrl(bytes){ //
+      var blob = new Blob([bytes],{type:'image/jpeg'})
+      var imgUrl =  URL.createObjectURL(blob)
+      return imgUrl
+    },
+    upload(upload){ // 上传文件信息
+      const file = upload.file
+      this.fileToBase64(file).then(base64=>{
+        // console.log(base64)
+        axios.post(this.flaskBaseUrl+'/upload',{
+          base64
+        }).then(res=>{
+          console.log(JSON.parse(res),"res")
+        })
+      })
+    },
+    uploadInStream(upload){
+      const file = upload.file
+      this.fileToArrayBuffer(file).then(arrayBuffer=>{
+
+        const bytes = new Uint8Array(arrayBuffer)
+        const formData = new FormData();
+        axios.post(this.flaskBaseUrl+'/query',bytes,{
+          headers: {
+            'Content-Type': 'multipart/form-data'
+          }
+        }).then(res=>{
+          this.resPic = 'data:image/jpeg;base64,'+res.data
+        })
+
+      })
+
+    },
+    uploadStream(upload){
+      const file = upload.file
+      this.fileToArrayBuffer(file).then(arrayBuffer=>{
+        const bytes = new Uint8Array(arrayBuffer)
+        // formData.append("file",bytes)
+        console.log(bytes)
+        axios.post(this.flaskBaseUrl+'/query',{
+          "file":JSON.stringify(bytes)
+        },{
+          headers: {
+            'Content-Type': 'application/json'
+          }
+        }).then(res=>{
+          console.log(res,"res")
+        })
+      })
+    },
+    uploadImg(upload){
+      const file = upload.file
+
+      const onProgress = file.onProgress
+      const onSucess = file.onSucess
+      let xhr // 全局请求
+      var reader = new FileReader();
+      reader.onload = e=>{
+        var result = e.target.result;
+        const base64 = result.split(',').pop()
+        xhr = new XMLHttpRequest()
+        console.log(reader.result,e,"readerE",upload)
+        // TODO
+        xhr.onload= function(){
+          const resp = JSON.parse(xhr.responseText) // 获取响应结果
+        }
+        xhr.upload.onprogress = (e)=>{
+          const percent = Math.floor((e.loaded / e.total)*100 )
+          console.log(percent,"percent!")
+        }
+        console.log(result)
+      }
+      reader.onFinished = e=>{
+
+      }
+      reader.readAsDataURL(file)
 
     },
   }
@@ -116,4 +228,4 @@ export default {
 .result-container {
   margin-top: 20px; /* 调整上方间距 */
 }
-</style>
+</style>

+ 7 - 0
vue/src/views/manager/Shop/ShopOrders.vue

@@ -255,6 +255,10 @@ export default {
   },
   created() {
     this.load(1)
+
+  },
+  mounted(){
+    this.$bus.$on("update:store",this.updateOrders)
   },
   methods: {
     handleAdd() {   // 新增数据
@@ -365,6 +369,9 @@ export default {
         });
         this.$message.success("修改成功")
       })
+    },
+    updateOrders(){
+      this.load(1)
     }
 
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است