qianduan 11 месяцев назад
Родитель
Сommit
b87514d1ea

+ 28 - 0
src/api/condition.js

@@ -0,0 +1,28 @@
+import request from '@/utils/request'
+
+// 获取钢瓶状态列表
+export function getCylinderStatus(parameter) {
+  return request({
+    url: '/api/gas-cylinder-status',
+    method: 'get',
+    params: parameter
+  })
+}
+
+// 添加钢瓶状态
+export function addCylinderStatus(parameter) {
+  return request({
+    url: '/api/gas-cylinder-status',
+    method: 'post',
+    data: parameter
+  })
+}
+
+// 删除钢瓶状态
+export function delCylinderStatus(parameter) {
+  return request({
+    url: '/api/gas-cylinder-status',
+    method: 'delete',
+    data: parameter
+  })
+}

BIN
src/assets/entertained.mp3


BIN
src/assets/image/decorate.png


BIN
src/assets/image/empty.png


BIN
src/assets/image/incoming.png


+ 16 - 2
src/components/pagination.vue

@@ -1,8 +1,7 @@
 <template>
   <div class="card_input">
     <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage"
-      :page-sizes="pageSizes" :pager-count="pagerCountnum" layout="total, sizes, prev, pager, next,jumper"
-      :total="total">
+      :page-sizes="pageSizes" :pager-count="pagerCountnum" :layout="layout" :total="total">
     </el-pagination>
   </div>
 </template>
@@ -23,6 +22,10 @@
         type: Number,
         default: 7,
       },
+      layout: {
+        type: String,
+        default: 'total, sizes, prev, pager, next,jumper',
+      },
       pageSizes: {
         type: Array,
         default: () => {
@@ -83,4 +86,15 @@
     background-color: unset;
   }
 
+  ::v-deep .el-pager li.btn-quicknext {
+    color: #fff !important;
+  }
+
+  ::v-deep .el-pager li.btn-quickprev {
+    color: #fff !important;
+  }
+
+  ::v-deep .el-pager li:hover {
+    color: #409EFF !important;
+  }
 </style>

+ 1 - 0
src/router/generator-routers.js

@@ -22,6 +22,7 @@ const constantRouterComponents = {
   aerationInspection: () => import('@/views/manufacture/aerationInspection'),
   wanderAbout: () => import('@/views/manufacture/wanderAbout'),
   equipment: () => import('@/views/manufacture/equipment'),
+  cylinderCondition: () => import('@/views/manufacture/cylinderCondition'),
   // 客户中心
   agentOrdering: () => import('@/views/customer/agentOrdering'),
   orderProcessing: () => import('@/views/customer/orderProcessing'),

+ 1 - 0
src/store/modules/user.js

@@ -52,6 +52,7 @@ const user = {
         // api/user
         // 连接后端接口,根据前端请求的用户信息,后端返回唯一对应的随机token
         login(userInfo).then(response => {
+          console.log(response,9)
           const data = response
           if (data.code == 200) {
             // commit会触发mutations,存储token

+ 14 - 10
src/utils/request.js

@@ -15,7 +15,7 @@ const Url = "https://gascylinder.baozhida.cn/gas_cylinder"
 const request = axios.create({
   // API 请求的默认前缀
   baseURL: process.env.NODE_ENV === 'production' ? Url : '/api',
-  timeout: 6000, // 请求超时时间
+  timeout: 10000, // 请求超时时间
   withCredentials: false,
   headers: {
     'Content-Type': 'application/json',
@@ -25,17 +25,21 @@ const request = axios.create({
 
 // 异常拦截处理器
 const errorHandler = (error) => {
-  console.log(error, 222)
-  if (error.response) {
-    const data = error.response.data
-    if (error.response.status === 403) {
-      Message.error(data.message)
-    }
-    if (error.response.status === 401) {
-      Message.error(data.message)
+  if (error.message == 'timeout of 10000ms exceeded') {
+    Message.error('当前网络不稳定,请更换网络重试')
+    return error
+  } else {
+    if (error.response) {
+      const data = error.response.data
+      if (error.response.status === 403) {
+        Message.error(data.message)
+      }
+      if (error.response.status === 401) {
+        Message.error(data.message)
+      }
     }
+    return Promise.reject(error)
   }
-  // return Promise.reject(error)
 }
 
 // request interceptor

+ 37 - 0
src/utils/vue-sse.js

@@ -0,0 +1,37 @@
+import Vue from 'vue';
+
+const VueSSE = {
+  install(Vue, options) {
+    const sse = new EventSource('http://localhost:8990/ees');
+
+    Vue.prototype.$sse = {
+      addListener(event, callback) {
+        sse.addEventListener(event, (e) => {
+          callback(JSON.parse(e.data));
+        });
+      },
+      removeListener(event, callback) {
+        sse.removeEventListener(event, callback);
+      }
+    };
+
+    Vue.mixin({
+      created() {
+        if (this.$options.sse) {
+          this.$options.sse.forEach((eventHandler) => {
+            this.$sse.addListener(eventHandler.event, eventHandler.callback);
+          });
+        }
+      },
+      beforeDestroy() {
+        if (this.$options.sse) {
+          this.$options.sse.forEach((eventHandler) => {
+            this.$sse.removeListener(eventHandler.event, eventHandler.callback);
+          });
+        }
+      }
+    });
+  }
+};
+
+export default VueSSE;

+ 250 - 0
src/views/common/Base.vue

@@ -32,6 +32,21 @@
       <div class="main">
         <router-view></router-view>
       </div>
+      <div class="card_callingSystem" v-show="entranceRight" :class="entranceRight ? 'slide-left' : ''">
+        <div class="center_in " :class="entranceRight ? 'shake-lr' : ''" id="card_system">
+          <img class="calling_img" src="../../assets/image/incoming.png" alt="" />
+        </div>
+        <div class="card_ad_phone">
+          <div class="ad_title">客户来电</div>
+          <div class="phone_title">{{ phone }}</div>
+        </div>
+        <div class="bottom_btn_add">
+          <div class="btn_add_card center_in" @click="addOrder">
+            添加订单
+          </div>
+        </div>
+      </div>
+      <!-- <audio ref="alarmAudio" loop src="@/assets/entertained.mp3"></audio> -->
     </div>
   </div>
 
@@ -60,6 +75,9 @@
         timer: undefined,
         hourMinuteSecond: null,
         firmName: '',
+        phone: '17673255548',
+        entranceRight: false,
+        errNumber: 0,
       }
     },
     watch: {
@@ -83,6 +101,17 @@
       })
     },
     created() {
+      this.$nextTick(() => {
+        this.sse();
+        let testDom = document.getElementById('card_system')
+        testDom.addEventListener('animationend', function(event) {
+          // 移除再添加动画样式  重新触发动画
+          testDom.classList.remove('shake-lr')
+          setTimeout(() => {
+            testDom.classList.add('shake-lr')
+          }, 1000)
+        });
+      })
       Bus.$on('collapse', isCollapse => {
         this.collapse = isCollapse;
       });
@@ -126,6 +155,58 @@
           }
         }
         return result
+      },
+      sse() {
+        let that = this
+        // 创建EventSource实例
+        const eventSource = new EventSource('http://127.0.0.1:8990/ees');
+        // 订阅事件
+        eventSource.addEventListener('message', function(event) {
+          // 处理收到的消息
+          let arr = event.data
+
+          function getContentBetween(source, start, end) {
+            const pattern = new RegExp(start + '(.*?)' + end, 's');
+            const match = source.match(pattern);
+            return match ? match[1] : '';
+          }
+
+          // 示例使用
+          const start = 'local=sip:';
+          const end = '@';
+          const content = getContentBetween(arr, start, end);
+          if (content) {
+            that.entranceRight = true
+            // const audio = that.$refs.alarmAudio;
+            // audio.play();
+            // audio.addEventListener('ended', () => {
+            //   audio.pause();
+            //   audio.currentTime = 0;
+            // });
+          }
+          that.phone = content
+        });
+        eventSource.addEventListener('error', function(event) {
+          // 处理错误
+          if (that.errNumber == 3) {
+            console.error('SSE Error', event);
+            eventSource.close()
+          } else {
+            that.errNumber++
+          }
+        });
+      },
+      // 添加订单
+      addOrder() {
+        let that = this
+        that.$router.push({
+          name: 'agentOrdering',
+          query: {
+            flag: true,
+            phone: that.phone,
+          }
+        })
+        that.entranceRight = false
       }
     },
     beforeDestroy() {
@@ -150,6 +231,145 @@
     overflow: hidden;
   }
 
+  .card_callingSystem {
+    z-index: 999;
+    position: absolute;
+    bottom: 20px;
+    right: 20px;
+    width: 250px;
+    height: 180px;
+    background-color: rgba(0, 0, 0, 0.5);
+    border-radius: 10px;
+    padding: 10px;
+    border: 2px solid rgba(255, 255, 255, 0.3);
+  }
+
+  .shake-lr {
+    -webkit-animation: shake-lr 1s cubic-bezier(0.455, 0.030, 0.515, 0.955) both;
+    animation: shake-lr 1s cubic-bezier(0.455, 0.030, 0.515, 0.955) both;
+  }
+
+  @-webkit-keyframes shake-lr {
+
+    0%,
+    100% {
+      -webkit-transform: rotate(0deg);
+      transform: rotate(0deg);
+      -webkit-transform-origin: 50% 50%;
+      transform-origin: 50% 50%;
+    }
+
+    10% {
+      -webkit-transform: rotate(8deg);
+      transform: rotate(8deg);
+    }
+
+    20%,
+    40%,
+    60% {
+      -webkit-transform: rotate(-10deg);
+      transform: rotate(-10deg);
+    }
+
+    30%,
+    50%,
+    70% {
+      -webkit-transform: rotate(10deg);
+      transform: rotate(10deg);
+    }
+
+    80% {
+      -webkit-transform: rotate(-8deg);
+      transform: rotate(-8deg);
+    }
+
+    90% {
+      -webkit-transform: rotate(8deg);
+      transform: rotate(8deg);
+    }
+  }
+
+  @keyframes shake-lr {
+
+    0%,
+    100% {
+      -webkit-transform: rotate(0deg);
+      transform: rotate(0deg);
+      -webkit-transform-origin: 50% 50%;
+      transform-origin: 50% 50%;
+    }
+
+    10% {
+      -webkit-transform: rotate(8deg);
+      transform: rotate(8deg);
+    }
+
+    20%,
+    40%,
+    60% {
+      -webkit-transform: rotate(-10deg);
+      transform: rotate(-10deg);
+    }
+
+    30%,
+    50%,
+    70% {
+      -webkit-transform: rotate(10deg);
+      transform: rotate(10deg);
+    }
+
+    80% {
+      -webkit-transform: rotate(-8deg);
+      transform: rotate(-8deg);
+    }
+
+    90% {
+      -webkit-transform: rotate(8deg);
+      transform: rotate(8deg);
+    }
+  }
+
+  .calling_img {
+    width: 60px;
+    height: 60px;
+  }
+
+  .card_ad_phone {
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+    justify-content: center;
+  }
+
+  .ad_title {
+    font-size: 20px;
+    color: #fff;
+    font-weight: bold;
+  }
+
+  .phone_title {
+    color: #fff;
+    font-size: 30px;
+    font: 600 35px mFont;
+  }
+
+  .bottom_btn_add {
+    display: flex;
+    justify-content: center;
+  }
+
+  .btn_add_card {
+    cursor: pointer;
+    margin-top: 10px;
+    color: #fff;
+    width: 100px;
+    height: 30px;
+    font-size: 14px;
+    border-radius: 40px;
+    background-color: #67C23A;
+  }
+
   .container {
     width: 100%;
     height: 100%;
@@ -243,4 +463,34 @@
     position: absolute;
     margin-top: 10px;
   }
+
+
+  .slide-left {
+    -webkit-animation: slide-left 1s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
+    animation: slide-left 1s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
+  }
+
+  @-webkit-keyframes slide-left {
+    0% {
+      -webkit-transform: translateX(0);
+      transform: translateX(0);
+    }
+
+    100% {
+      -webkit-transform: translateX(-20px);
+      transform: translateX(-20px);
+    }
+  }
+
+  @keyframes slide-left {
+    0% {
+      -webkit-transform: translateX(0);
+      transform: translateX(0);
+    }
+
+    100% {
+      -webkit-transform: translateX(-20px);
+      transform: translateX(-20px);
+    }
+  }
 </style>

+ 18 - 6
src/views/customer/agentOrdering.vue

@@ -141,6 +141,12 @@
       }
     },
     mounted() {
+      let flag = this.$route.query.flag
+      if (flag) {
+        this.staffDialogVisible = true
+        this.ruleForm.phone = this.$route.query.phone
+        this.numberSearch(this.ruleForm.phone)
+      }
       const dataList = formRules();
       this.formRuleList = dataList;
       this.getDistributionStore()
@@ -180,18 +186,24 @@
         }).then(res => {
           if (res.code == 200) {
             const arr = res.data
-            this.ruleForm.type = arr.type
+            // this.ruleForm.type = arr.type
+            this.$set(this.ruleForm, 'type', arr.type)
             if (arr.type == 0) {
-              this.ruleForm.name = arr.shopName
+              // this.ruleForm.name = arr.shopName
+              this.$set(this.ruleForm, 'name', arr.shopName)
             } else {
-              this.ruleForm.name = arr.principalName
+              // this.ruleForm.name = arr.principalName
+              this.$set(this.ruleForm, 'name', arr.principalName)
             }
-            this.ruleForm.address = arr.address
-            this.ruleForm.remark = arr.remark
+            // this.ruleForm.address = arr.address
+            this.$set(this.ruleForm, 'address', arr.address)
+            // this.ruleForm.remark = arr.remark
+            this.$set(this.ruleForm, 'remark', arr.remark)
             var arr1 = []
             arr1.push(arr.city)
             arr1.push(arr.area)
-            this.ruleForm.cityRegion = arr1
+            this.$set(this.ruleForm, 'cityRegion', arr1)
+            // this.ruleForm.cityRegion = arr1
             this.ruleForm.lng = arr.lng
             this.ruleForm.lat = arr.lat
             this.$refs.childRules.curLoading = false

+ 302 - 0
src/views/manufacture/cylinderCondition.vue

@@ -0,0 +1,302 @@
+<template>
+  <!-- 钢瓶状态 -->
+  <div class="card_cylinder_condition">
+    <!-- 重瓶区域 -->
+    <div class="card_bottle">
+      <div class="card_district">
+        <div class="herderArea center_in title_green">重瓶区</div>
+        <div class="same_row_in card_add_cylinder">
+          <el-input style="margin-right: 10px;" v-model="input" placeholder="输入单位内编号搜索"></el-input>
+          <el-button type="primary" size="medium" icon="el-icon-plus" @click="AddCylinder(1)">添加</el-button>
+        </div>
+        <div style="width: calc(100% - 30px);padding: 0px 15px 15px 15px;" v-if="bottleData.length > 0">
+          <div class="card_item_condition" v-for="(item,index) in bottleData" :key="index">
+            <div class="same_row_in">
+              <span class="item_index">{{index + 1}}</span>
+              <div class="card_item_code">{{item.inner_code}}</div>
+            </div>
+            <div class="card_red">删除</div>
+          </div>
+        </div>
+        <div v-else><el-empty :image="require('../../assets/image/empty.png')" description="暂无燃气瓶"></el-empty></div>
+        <div class="card_pagination center_in">
+          <pagination :total="Pagination.Total" :pagerCountnum="5" layout="prev, pager, next, jumper"
+            :currentPage="Pagination.PageIndex" @changeSize="changeSize" @changeCurrent="changeCurrent">
+          </pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 空瓶区 -->
+    <div class="card_bottle">
+      <div class="card_district">
+        <div class="herderArea center_in title_yellow">空瓶区</div>
+        <div class="same_row_in card_add_cylinder">
+          <el-input style="margin-right: 10px;" v-model="input" placeholder="输入单位内编号搜索"></el-input>
+          <el-button type="primary" size="medium" icon="el-icon-plus" @click="AddCylinder(2)">添加</el-button>
+        </div>
+        <div style="width: calc(100% - 30px);padding: 0px 15px 15px 15px;" v-if="bottleData1.length > 0">
+          <div class="card_item_condition" v-for="(item,index) in bottleData1" :key="index">
+            <div class="same_row_in">
+              <span class="item_index">{{index + 1}}</span>
+              <div class="card_item_code">{{item.inner_code}}</div>
+            </div>
+            <div class="card_red">删除</div>
+          </div>
+        </div>
+        <div v-else><el-empty :image="require('../../assets/image/empty.png')" description="暂无燃气瓶"></el-empty></div>
+        <div class="card_pagination center_in">
+          <pagination :total="Pagination1.Total" :pagerCountnum="5" layout="prev, pager, next, jumper"
+            :currentPage="Pagination1.PageIndex" @changeSize="changeSize1" @changeCurrent="changeCurrent1">
+          </pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 不合格瓶区 -->
+    <div class="card_bottle">
+      <div class="card_district">
+        <div class="herderArea center_in title_red">不合格瓶区</div>
+        <div class="same_row_in card_add_cylinder">
+          <el-input style="margin-right: 10px;" v-model="input" placeholder="输入单位内编号搜索"></el-input>
+          <el-button type="primary" size="medium" icon="el-icon-plus" @click="AddCylinder(3)">添加</el-button>
+        </div>
+        <div style="width: calc(100% - 30px);padding: 0px 15px 15px 15px;" v-if="bottleData2.length > 0">
+          <div class="card_item_condition" v-for="(item,index) in bottleData2" :key="index">
+            <div class="same_row_in">
+              <span class="item_index">{{index + 1}}</span>
+              <div class="card_item_code">{{item.inner_code}}</div>
+            </div>
+            <div class="card_red">删除</div>
+          </div>
+        </div>
+        <div v-else><el-empty :image="require('../../assets/image/empty.png')" description="暂无燃气瓶"></el-empty></div>
+        <div class="card_pagination center_in">
+          <pagination :total="Pagination2.Total" :pagerCountnum="5" layout="prev, pager, next, jumper"
+            :currentPage="Pagination2.PageIndex" @changeSize="changeSize2" @changeCurrent="changeCurrent2">
+          </pagination>
+        </div>
+      </div>
+    </div>
+    <!-- 添加钢瓶 -->
+    <el-dialog title="添加" :visible.sync="staffDialogVisible" width="600px" :close-on-click-modal="false"
+      @close="closeDialog">
+      <forms ref="childRules" :formNewList="formRuleList" :ruleForm="ruleForm" labelWidth="100px"></forms>
+      <span slot="footer" class="dialog-footer">
+        <el-button plain @click="staffDialogVisible = false">取 消</el-button>
+        <el-button type="primary" :loading="confirmLoading" @click="handleAdd">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import {
+    getCylinderStatus,
+    addCylinderStatus,
+    delCylinderStatus
+  } from '@/api/condition'
+  import pagination from '@/components/pagination'
+  import forms from '@/components/forms'
+  export default {
+    components: {
+      pagination,
+      forms
+    },
+    data() {
+      return {
+        input: '',
+        // 重瓶
+        Pagination: {
+          PageIndex: 1,
+          PageSize: 10,
+          Total: 0,
+        },
+        bottleData: [],
+        // 空瓶
+        Pagination1: {
+          PageIndex: 1,
+          PageSize: 10,
+          Total: 0,
+        },
+        bottleData1: [],
+        // 不合格瓶区
+        Pagination2: {
+          PageIndex: 1,
+          PageSize: 10,
+          Total: 0,
+        },
+        bottleData2: [],
+        staffDialogVisible: false,
+        formRuleList: [],
+        ruleForm: {
+          name: '',
+          price: '',
+          remark: '',
+        },
+        confirmLoading: false,
+      }
+    },
+    mounted() {
+      this.getList(1)
+      this.getList1(2)
+      this.getList2(3)
+    },
+    methods: {
+      getList(state) {
+        getCylinderStatus({
+          status: state,
+        }).then(res => {
+          if (res.code == 200) {
+            this.bottleData = res.data.list
+            this.Pagination.Total = res.data.count
+          }
+        })
+      },
+      getList1(state) {
+        getCylinderStatus({
+          status: state,
+        }).then(res => {
+          if (res.code == 200) {
+            this.bottleData1 = res.data.list
+            this.Pagination1.Total = res.data.count
+          }
+        })
+      },
+      getList2(state) {
+        getCylinderStatus({
+          status: state,
+        }).then(res => {
+          if (res.code == 200) {
+            this.bottleData2 = res.data.list
+            this.Pagination2.Total = res.data.count
+          }
+        })
+      },
+      // 添加钢瓶
+      AddCylinder(type) {
+        console.log(type, 222)
+        this.staffDialogVisible = true
+      },
+      handleAdd() {
+
+      },
+      // 重瓶区域
+      changeSize(val) {
+        this.Pagination.PageSize = val
+        this.getList()
+      },
+      changeCurrent(val) {
+        this.Pagination.PageIndex = val
+        this.getList()
+      },
+      // 空瓶区
+      changeSize1(val) {
+        this.Pagination1.PageSize = val
+        this.getList1()
+      },
+      changeCurrent1(val) {
+        this.Pagination1.PageIndex = val
+        this.getList1()
+      },
+      // 不合格瓶区
+      changeSize2(val) {
+        this.Pagination2.PageSize = val
+        this.getList2()
+      },
+      changeCurrent2(val) {
+        this.Pagination2.PageIndex = val
+        this.getList2()
+      },
+      // 弹窗关闭
+      closeDialog() {
+        this.staffDialogVisible = false
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  .card_cylinder_condition {
+    display: flex;
+    width: 100%;
+    height: 100%;
+  }
+
+  .card_bottle {
+    padding: 10px 10px 15px 10px;
+    flex: 1;
+  }
+
+  .card_district {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    width: 100%;
+    height: 100%;
+    // background-color: #354233;
+    background-color: rgba(13, 162, 203, 0.1);
+    border-radius: 10px;
+  }
+
+  .herderArea {
+    font-size: 22px;
+    font-weight: 500;
+    margin-top: 15px;
+    width: 250px;
+    height: 35px;
+    background: url(../../assets/image/decorate.png) no-repeat;
+    background-size: 100% 100%;
+  }
+
+  .card_add_cylinder {
+    width: calc(100% - 30px);
+    margin: 15px;
+  }
+
+  .card_pagination {
+    position: absolute;
+    bottom: 20px;
+    left: 20px;
+    right: 20px;
+    overflow: hidden;
+  }
+
+  .card_item_condition {
+    margin: 10px 0px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid rgba(255, 255, 255, .2) !important;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+
+  .item_index {
+    color: #fff;
+    font-size: 18px;
+  }
+
+  .card_item_code {
+    margin-left: 10px;
+    color: #fff;
+    font-size: 18px;
+  }
+
+  .card_red {
+    cursor: pointer;
+    color: #F56C6C;
+    font-size: 18px;
+  }
+
+  .title_green {
+    color: #67C23A;
+  }
+
+  .title_yellow {
+    color: #E6A23C;
+  }
+
+  .title_red {
+    color: #F56C6C;
+  }
+</style>

+ 5 - 2
src/views/user/Login.vue

@@ -41,7 +41,8 @@
             </template>
             <i class="el-icon-view el-input__icon" slot="suffix" @click="handleIconClick"></i>
           </el-input> -->
-          <el-input placeholder="密码" v-model="ruleForm.password" show-password @change="submitForm('ruleForm')">
+          <el-input placeholder="密码" v-model="ruleForm.password" show-password
+            @keyup.enter.native="submitForm('ruleForm')">
             <template slot="prepend">
               <i class="el-icon-lock icon_login"></i>
             </template>
@@ -77,7 +78,9 @@
         checked: true,
         ruleForm: {
           phone: '',
-          verifyCode: ''
+          verifyCode: '',
+          username: 'admin',
+          password: '123456'
         },
         rules: {
           phone: [{