Parcourir la source

硬件API接口调用页面

lxf il y a 2 ans
Parent
commit
9d909bf482

+ 3 - 3
.env.development

@@ -4,15 +4,15 @@ ENV = 'development'
 # 尔泓/开发环境
 VUE_APP_BASE_API = '/api'
 
-VUE_APP_ACTION_URL='http://www.printmat.cn:8181/api/blade-resource/local/file/upload'
+VUE_APP_ACTION_URL='http://192.168.1.164:8181/api/blade-resource/local/file/upload'
 
-VUE_APP_EXPRESSAGE_URL='http://www.printmat.cn:8181/api/saas-production/saas/production/expressagereconciliation/save'
+VUE_APP_EXPRESSAGE_URL='http://192.168.1.164:8181/api/saas-production/saas/production/expressagereconciliation/save'
 
 VUE_APP_IMG_URL='http://www.printmat.cn:8181/file'
 
 VUE_APP_FILE_PREFIX='ftp://www.printmat.cn/'
 
-VUE_APP_MESSAGE_URL='ws://www.printmat.cn:8181/api'
+VUE_APP_MESSAGE_URL='ws://192.168.1.164:8181/api'
 
 VUE_APP_TIME = 3000000
 

+ 3 - 3
.env.staging

@@ -6,15 +6,15 @@ ENV = 'staging'
 # 尔泓/开发环境
 VUE_APP_BASE_API = '/api'
 
-VUE_APP_ACTION_URL='http://116.205.162.119:8181/blade-resource/local/file/upload'
+VUE_APP_ACTION_URL='http://192.168.1.164:8181/blade-resource/local/file/upload'
 
-VUE_APP_EXPRESSAGE_URL='http://116.205.162.119:8181/saas-production/saas/production/expressagereconciliation/save'
+VUE_APP_EXPRESSAGE_URL='http://192.168.1.164:8181/saas-production/saas/production/expressagereconciliation/save'
 
 VUE_APP_IMG_URL='http://www.printmat.cn:8181/file'
 
 VUE_APP_FILE_PREFIX='ftp://www.printmat.cn/'
 
-VUE_APP_MESSAGE_URL='ws://116.205.162.119:8181'
+VUE_APP_MESSAGE_URL='ws://192.168.1.164:8181'
 
 VUE_APP_TIME = 3000000
 

+ 19 - 0
src/api/shengde/productionSystem/demo/simulation.js

@@ -0,0 +1,19 @@
+import request from '@/router/axios'
+
+//获取图档路径
+export function getDrawing(data = {}) {
+  return request({
+    url: '/saas-production/saas/production/code/third/api/getDrawing',
+    method: 'post',
+    data: data,
+  })
+}
+
+//激光标刻完成
+export function laserEngraving(data ={}) {
+  return request({
+    url: '/saas-production/saas/production/code/third/api/check/laserengraving',
+    method: 'post',
+    data: data,
+  })
+}

+ 9 - 0
src/api/shengde/productionSystem/productionOperation/artificial/index.js

@@ -33,6 +33,15 @@ export function pushNoRfidArtificialLaser(data) {
   })
 }
 
+// 无RFID激光雕刻数据推送
+export function productQrCode(data) {
+  return request({
+    url: `/saas-production/saas/production/code/third/api/productQrcode`,
+    method: 'post',
+    data: data,
+  })
+}
+
 // 激光扫码
 export function pushArtificialLaser(data) {
   return request({

+ 1 - 1
src/components/ProductDetails/ProductMaterial.vue

@@ -71,7 +71,7 @@
                 </div>
               </template>
             </el-table-column>
-            <el-table-column label="设计图" align="center" width="80" v-if="userInfo.subsidiaryId">
+            <el-table-column label="设计图" align="center" width="80">
               <template slot-scope="scope">
                 <div v-if="scope.row.designSketch">
                   <img

+ 548 - 0
src/views/shengde/productionSystem/demo/artificial/index.vue

@@ -0,0 +1,548 @@
+<template>
+  <div class="main">
+    <BarCodeScan @handle="handleBarcode"></BarCodeScan>
+    <div class="body">
+      <div class="left" v-show="dataObj.contractCode">
+        <div class="img">
+          <img :src="pathPrefix + dataObj.magPath" id="img" alt="" />
+        </div>
+        <div class="img">
+          <img :src="pathPrefix + dataObj.imgPath" id="img1" alt="" />
+        </div>
+        <div class="info">
+          <div style="height: calc(100vh - 194px - 40px); overflow-y: auto; overflow-x: hidden">
+            <div style="text-align: right; padding-right: 8px; color: white">
+              <span style="font-size: 16px; font-weight: 700" v-if="dataObj.completNum">{{ Number(dataObj.completNum) }}</span>
+              <span style="font-size: 16px; font-weight: 700" v-else>0</span>
+              <span style="font-size: 16px; font-weight: 700"> / </span>
+              <span style="font-size: 16px; font-weight: 700" v-if="dataObj.quantity">{{ Number(dataObj.quantity) }}</span>
+              <span style="font-size: 16px; font-weight: 700" v-else>0</span>
+            </div>
+            <div class="item">
+              <div class="t">
+                <div class="title">共享文件夹 :</div>
+                <a class="val" :href="getPath(dataObj.artworkDocument)">{{ dataObj.artworkDocument }}</a>
+              </div>
+            </div>
+            <div class="item">
+              <div class="t">
+                <div class="title">订单号 :</div>
+                <div class="val">{{ dataObj.contractCode }}</div>
+              </div>
+            </div>
+            <div class="item">
+              <div class="t">
+                <div class="title">SKU品号 :</div>
+                <div class="val">{{ dataObj.productCode }}</div>
+              </div>
+              <div class="t">
+                <div class="title">SKU品名 :</div>
+                <div class="val">{{ dataObj.productColorName }}</div>
+              </div>
+            </div>
+            <div class="item">
+              <div class="t">
+                <div class="title">BOM品号 :</div>
+                <div class="val">{{ dataObj.bomColorCode }}</div>
+              </div>
+              <div class="t">
+                <div class="title">BOM品名 :</div>
+                <div class="val">{{ dataObj.bomColorName }}</div>
+              </div>
+              <div class="t">
+                <div class="title">BOM尺寸 :</div>
+                <div class="val" v-if="dataObj.productLong !== '' && dataObj.productWide !== ''">
+                  {{ `${dataObj.productLong}*${dataObj.productWide}*${dataObj.productHigh}` }}
+                </div>
+              </div>
+              <div class="t">
+                <div class="title">打印面数 :</div>
+                <div class="val" v-if="dataObj.identification == 1">单面</div>
+                <div class="val" v-else>双面</div>
+              </div>
+            </div>
+            <div class="use-time">
+              <div class="title">生产工序用时 :</div>
+              <div class="val">{{ useTime }} 秒</div>
+            </div>
+          </div>
+          <div style="position: absolute; bottom: 20px; width: 100%">
+            <div style="text-align: center">
+              <el-button size="medium" type="primary" @click="handleComplete">完成</el-button>
+              <el-button size="medium" @click="clean()" v-db-click>返回</el-button>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="none" v-show="!dataObj.contractCode">
+        <div style="text-align: center; padding: 8px">
+          <span style="font-size: 24px; padding-left: 8px">生产任务</span>
+        </div>
+        <div style="padding: 8px 0 0 8px; border-radius: 1px; margin: 0 8px">
+          <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
+            <el-form-item label="订单号" prop="contractCode">
+              <el-input v-model="queryParams.contractCode" placeholder="请输入订单号" size="small" @keyup.enter.native="handleQuery" />
+            </el-form-item>
+            <el-form-item label="SKU品号" prop="productColorCode">
+              <el-input v-model="queryParams.productColorCode" placeholder="请输入SKU品号" size="small" @keyup.enter.native="handleQuery" />
+            </el-form-item>
+            <el-form-item label="SKU品名" prop="productColorName">
+              <el-input v-model="queryParams.productColorName" placeholder="请输入SKU品名" size="small" @keyup.enter.native="handleQuery" />
+            </el-form-item>
+            <el-form-item>
+              <el-button size="small" @click="handleQuery" class="searchBtn">搜索</el-button>
+              <el-button size="small" @click="resetQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+        </div>
+        <div style="height: calc(100vh - 110px - 50px - 48px - 56px); overflow-y: auto; padding: 0 8px">
+          <div
+            v-for="(item, index) in quickList"
+            :key="index"
+            style="margin: 16px 8px 0 8px; padding: 20px; cursor: pointer; box-shadow: 0px 0px 10px #ccc"
+            @click="clickQuick(item)"
+            v-db-click
+          >
+            <el-row>
+              <el-col :span="5">
+                <span>{{ item.contractCode }}</span>
+              </el-col>
+              <el-col :span="5" style="padding-left: 8px">
+                <span>{{ item.productColorCode }}</span>
+              </el-col>
+              <el-col :span="10" style="padding-left: 8px">
+                <span>{{ item.productColorName }}</span>
+              </el-col>
+              <el-col :span="4" style="padding-right: 8px; text-align: right">
+                <el-button size="small" @click="scanTheCode(item)" class="searchBtn">模拟扫码</el-button>
+              </el-col>
+            </el-row>
+          </div>
+          <br />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as API from '@/api/shengde/productionSystem/productionOperation/artificial'
+import { mapGetters } from 'vuex'
+import panzoom from 'panzoom' //缩放
+import { getInformationDetail } from '@/api/shengde/productionSystem/productionOperation/pack'
+import Utils from '@/util/transit'
+import BarCodeScan from '@/components/BarCodeScan/index'
+import { getUid } from '@/util/saas.js'
+
+export default {
+  name: 'artificial',
+  components: { BarCodeScan },
+  data() {
+    return {
+      pathPrefix: process.env.VUE_APP_IMG_URL,
+      filePrefix: process.env.VUE_APP_FILE_PREFIX,
+      ws: null, //建立的webSocket连接
+      lockReconnect: false, //是否真正建立连接
+      timeout: 28 * 1000, //30秒一次心跳
+      timeoutObj: null, //心跳倒计时
+      serverTimeoutObj: null, //心跳倒计时
+      timeoutnum: null, //断开 重连倒计时
+      useTime: 0, //这个工单用时时长
+      useTimeObj: null,
+      workTime: '', //工单开始时间,从websoket拿到消息开始算起
+      dataObj: {
+        productCode: '',
+        productHigh: '',
+        productColorName: '',
+        magPath: '',
+        artworkDocument: '',
+        imgPath: '',
+        productLong: '',
+        productWide: '',
+        contractCode: '',
+        bomColorCode: '',
+        bomColorName: '',
+        qrCode: '',
+      },
+      completeObj: {
+        qrCode: '',
+        workShipId: '1559814502814339074',
+        rfid: '0',
+      },
+      quickList: [],
+      status: true,
+      queryParams: {
+        contractCode: '',
+        productColorName: '',
+        productColorCode: '',
+      },
+    }
+  },
+  computed: mapGetters(['userInfo']),
+  created() {
+    this.initWebSocket()
+    this.clickRefresh()
+  },
+  mounted() {
+    panzoom(document.getElementById('img'))
+    panzoom(document.getElementById('img1'))
+    Utils.$on('webSocketClose', () => {
+      this.ws.close()
+      //清除时间
+      clearTimeout(this.timeoutObj)
+      clearTimeout(this.serverTimeoutObj)
+    })
+  },
+  methods: {
+    handleBarcode(val) {
+      API.pushArtificialLaser({ qrCode: val }).then()
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.clickRefresh()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    initWebSocket() {
+      this.ws = new WebSocket(process.env.VUE_APP_MESSAGE_URL + '/saas-socket/saas/socket/websocket/notice?userId=' + this.userInfo.user_id + '_22') //增加 '_22' 是为了同个userId可有websorket唯一身份标识
+      this.ws.onopen = this.onopen
+      this.ws.onmessage = this.onmessage
+      this.ws.onclose = this.onclose
+      this.ws.onerror = this.onerror
+    },
+    onopen() {
+      this.ws.send('ping')
+      //开启心跳
+      this.start()
+    },
+    onmessage(e) {
+      let data = JSON.parse(e.data)
+      console.log(data.data.details.rows, '人工激光websocket消息')
+      //过滤websokect测试消息
+      if (data.data.details.rows[0] !== '测试发送消息') {
+        let obj = JSON.parse(data.data.details.rows[0]) //此次推送的整个对象
+        console.log(obj, '消息')
+        if (obj.notice.msgType === 22) {
+          let newObj = JSON.parse(obj.notice.content) //取出此次推送的数据
+          if (newObj.userId === this.userInfo.user_id) {
+            //userId相同证明是此账号的数据
+            newObj.artworkDocument = this.filePrefix + newObj.artworkDocument
+            newObj.artworkDocument = newObj.artworkDocument.replace(/\//g, '\\')
+            this.dataObj = newObj
+            this.completeObj.qrCode = newObj.qrCode
+            if (this.workTime) {
+              clearInterval(this.useTimeObj)
+              this.useTime = 0
+            }
+            this.workTime = new Date() //记录工单的开始时间
+            this.useTimeObj = setInterval(() => {
+              this.useTime = this.useTime + 1
+            }, 1000) //纪录生产耗时
+          }
+        }
+      }
+      this.reset()
+    },
+    clean() {
+      this.dataObj = {
+        productCode: '',
+        productHigh: '',
+        productColorName: '',
+        magPath: '',
+        artworkDocument: '',
+        imgPath: '',
+        productLong: '',
+        productWide: '',
+        contractCode: '',
+        bomColorCode: '',
+        bomColorName: '',
+        qrCode: '',
+      }
+      this.completeObj = {
+        qrCode: '',
+        workShipId: '1559814502814339074',
+        rfid: '0',
+      }
+      this.useTimeObj && clearInterval(this.useTimeObj)
+      this.workTime = ''
+      this.useTime = 0
+      this.clickRefresh()
+    },
+    onclose() {
+      console.log('close')
+      this.reconnect()
+    },
+    onerror() {
+      console.log('error')
+      this.reconnect()
+    },
+    start() {
+      // //开启心跳
+      // var self = this
+      // self.timeoutObj && clearTimeout(self.timeoutObj)
+      // self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj)
+      // self.timeoutObj = setTimeout(() => {
+        //   //这里发送一个心跳,后端收到后,返回一个心跳消息,
+        //   if (self.ws.readyState == 1) {
+          //     //如果连接正常
+          //     self.ws.send('ping')
+      //   } else {
+        //     //否则重连
+        //     self.reconnect()
+        //   }
+        // }, self.timeout)
+        var self = this
+        self.timeoutObj && clearTimeout(self.timeoutObj)
+        self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj)
+        self.timeoutObj = setTimeout(() => {
+          console.log('111')
+          //这里发送一个心跳,后端收到后,返回一个心跳消息,
+          if (self.ws.readyState == 1) {
+            //如果连接正常
+            self.ws.send('heartCheck')
+          } else {
+            //否则重连
+            self.reconnect()
+          }
+          self.serverTimeoutObj = setTimeout(function () {
+            //超时关闭
+            console.log('人工激光超时')
+            self.ws.close()
+            setTimeout(() => {
+              self.reconnect()
+          }, 1000)
+        }, self.timeout)
+      }, self.timeout)
+    },
+    reconnect() {
+      //重新连接
+      let that = this
+      if (that.lockReconnect) {
+        return
+      }
+      that.lockReconnect = true
+      //没连接上会一直重连,设置延迟避免请求过多
+      that.timeoutnum && clearTimeout(that.timeoutnum)
+      that.timeoutnum = setTimeout(() => {
+        //新连接
+        that.initWebSocket()
+        that.lockReconnect = false
+      }, 5000)
+    },
+    reset() {
+      //重置心跳
+      let that = this
+      //清除时间
+      clearTimeout(that.timeoutObj)
+      clearTimeout(that.serverTimeoutObj)
+      //重启心跳
+      that.start()
+    },
+    handleComplete() {
+      API.complete(this.completeObj).then(() => {
+        this.msgSuccess('操作成功!')
+        this.clean()
+      })
+    },
+    getPath(val) {
+      if (val) {
+        let path = val.replace(/\\/g, '/')
+        return 'printer://' + path + '/'
+      }
+      return ''
+    },
+    clickRefresh() {
+      getInformationDetail(this.queryParams).then((res) => {
+        this.quickList = res.data.data
+      })
+    },
+    clickQuick(item) {
+      if (this.status) {
+        this.status = false
+        API.pushNoRfidArtificialLaser({ taskId: item.id }).then()
+      }
+      setTimeout(() => {
+        this.status = true
+      }, 2000)
+    },
+    scanTheCode(item) {
+      API.productQrCode({ qrcode: item.id + '-' + getUid() }).then()
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+::v-deep {
+  .btn {
+    width: 100%;
+  }
+  .el-card__body {
+    padding: 20px;
+  }
+}
+.main {
+  height: calc(100vh - 110px);
+  overflow-y: auto;
+  background-color: white;
+  display: flex;
+  flex-direction: column;
+  .head {
+    height: 80px;
+    display: flex;
+    align-items: center;
+    border-bottom: 2px solid #fff;
+    position: relative;
+    div {
+      color: #fff;
+      font-size: 28px;
+    }
+    .logo {
+      padding-left: 30px;
+      .img {
+        // width: 200px;
+        height: 60px;
+        object-fit: contain;
+      }
+    }
+    .now-time {
+      margin-left: 10vw;
+      display: flex;
+
+      .time {
+        margin: 0px 15px 0px 5px;
+      }
+      .el-icon-time {
+        position: relative;
+        top: 7px;
+      }
+      .el-icon-time,
+      .time,
+      .week {
+        font-size: 30px;
+      }
+    }
+    .work-name {
+      position: absolute;
+      right: 0;
+      padding: 0 30px;
+    }
+  }
+  .body {
+    flex: 1;
+    padding: 20px;
+    display: flex;
+    .left {
+      // margin-right: 3%;
+      width: 100%;
+      display: flex;
+      background: #404a59;
+      border-radius: 3px;
+      // box-shadow: 0px 0px 10px #fff;
+      .img {
+        // box-sizing: border-box;
+        margin-right: 2%;
+        box-shadow: 0px 0px 10px #fff;
+        padding: 20px;
+        height: calc(100vh - 194px);
+        width: 23%;
+        // margin: 20px;
+        overflow: hidden;
+        // border: 1px solid red;
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: contain;
+        }
+      }
+      .info {
+        padding: 20px;
+        width: 50%;
+        box-shadow: 0px 0px 10px #fff;
+        position: relative;
+        height: calc(100vh - 194px);
+        overflow-y: auto;
+        overflow-x: hidden;
+        // border: 1px solid red;
+        .item {
+          padding: 2vh 0;
+          border-bottom: 2px dashed #fff;
+          .t {
+            display: flex;
+            .title {
+              font-size: 16px;
+              color: rgb(215, 215, 215);
+              width: 170px;
+            }
+            .val {
+              color: #fff;
+              flex: 1;
+              font-size: 16px;
+              font-weight: 700;
+            }
+          }
+        }
+        // .btnBox {
+        //   width: 50%;
+        //   position: absolute;
+        //   bottom: 20px;
+        //   left: 50%;
+        //   transform: translate(-50%, 0);
+        // }
+      }
+      .use-time {
+        display: flex;
+        margin-top: 2vh;
+        align-items: center;
+        .title {
+          color: rgb(215, 215, 215);
+          width: 170px;
+          font-size: 16px;
+        }
+        .val {
+          color: #fff;
+          flex: 1;
+          font-size: 18px;
+          font-weight: 700;
+        }
+      }
+    }
+    .right {
+      width: 20%;
+      div {
+        font-size: 14px;
+        color: rgb(215, 215, 215);
+      }
+      .r-head {
+        font-size: 20px;
+        width: 150px;
+        padding-bottom: 2px;
+        border-bottom: 1px solid rgb(215, 215, 215);
+      }
+      .list {
+        .line {
+          display: flex;
+          margin: 10px 0px;
+          .detail {
+            margin-left: 10px;
+          }
+        }
+      }
+    }
+  }
+}
+.none {
+  width: 60vw;
+  height: calc(100vh - 110px - 50px);
+  margin: auto;
+  margin-top: 10px;
+}
+.searchBtn {
+  background: #20b2aa;
+  color: #fff;
+  border: 1px solid #20b2aa;
+}
+</style>

+ 528 - 0
src/views/shengde/productionSystem/demo/pack/index.vue

@@ -0,0 +1,528 @@
+<template>
+  <div class="main">
+    <BarCodeScan @handle="handleBarcode"></BarCodeScan>
+    <div class="btnWln" v-if="dataObj.dataResource === '1'">
+      <el-row type="flex">
+        <el-col :span="8">
+          <div style="color: #f59a23; font-size: 14px; border-bottom: 2px solid #f59a23; height: 40px; width: 140px">万里牛订单</div>
+        </el-col>
+        <el-col :span="8" style="text-align: center">
+          <el-button @click="clickCancel" size="small" v-if="dataObj.contractProductId" v-db-click>返回</el-button>
+        </el-col>
+        <el-col :span="8" style="text-align: right"> </el-col>
+      </el-row>
+    </div>
+    <div class="btn" v-else>
+      <el-row type="flex">
+        <el-col :span="8"> </el-col>
+        <el-col :span="8" style="text-align: center">
+          <el-button @click="clickCancel" size="small" v-if="dataObj.contractProductId" v-db-click>返回</el-button>
+        </el-col>
+        <el-col :span="8" style="text-align: right"> </el-col>
+      </el-row>
+    </div>
+    <div class="body" v-if="dataObj.contractProductId">
+      <div class="left" :class="[dataObj.dataResource === '1' ? 'orange' : 'white']">
+        <LabelTemplate title="设计图"></LabelTemplate>
+        <div style="padding-left: 2vw; margin-top: 20px">
+          <div class="img">
+            <img v-if="dataObj.imgPath" :src="pathPrefix + dataObj.imgPath" alt="" @click="openFile(pathPrefix + dataObj.imgPath)" />
+          </div>
+        </div>
+      </div>
+      <div style="width: 82%">
+        <div style="display: flex">
+          <div class="middle" :class="[dataObj.dataResource === '1' ? 'orange' : 'white']">
+            <LabelTemplate title="产品信息"></LabelTemplate>
+            <div style="padding-left: 2vw; margin-top: 20px">
+              <div class="detail">
+                <div class="att">
+                  <span>订单号: {{ dataObj.contractCode }}</span>
+                  <span v-if="dataObj.tradeNo"> ({{ dataObj.tradeNo }})</span>
+                </div>
+                <div class="att">产品:{{ dataObj.productName }}</div>
+                <div class="att">品号:{{ dataObj.productColorCode }}</div>
+                <div class="att">品名:{{ dataObj.productColorName }}</div>
+                <div class="att">
+                  包装要求:
+                  <div v-html="dataObj.packageRemarks"></div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="right" :class="[dataObj.dataResource === '1' ? 'orange' : 'white']">
+            <div style="display: flex">
+              <LabelTemplate title="包材备料"></LabelTemplate>
+            </div>
+            <div style="padding-left: 2vw; margin-top: 20px">
+              <el-table border :data="dataObj.bomColorList" size="small" :row-style="{ height: '35px' }" :cell-style="{ padding: '0' }">
+                <el-table-column label="序号" type="index" align="center" width="50" />
+                <el-table-column label="品号" prop="specCode" width="100" />
+                <el-table-column label="品名" prop="nameChinese" />
+                <el-table-column label="数量" align="right" width="60">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.singleQuantity">{{ Number(scope.row.singleQuantity) }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="none" v-else>
+      <div style="text-align: center; padding: 8px">
+        <span style="font-size: 24px; padding-left: 8px">生产任务</span>
+      </div>
+      <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
+        <el-form-item label="订单号" prop="contractCode">
+          <el-input v-model="queryParams.contractCode" placeholder="请输入订单号" size="small" @keyup.enter.native="handleQuery" />
+        </el-form-item>
+        <el-form-item label="SKU品号" prop="productColorCode">
+          <el-input v-model="queryParams.productColorCode" placeholder="请输入SKU品号" size="small" @keyup.enter.native="handleQuery" />
+        </el-form-item>
+        <el-form-item label="SKU品名" prop="productColorName">
+          <el-input v-model="queryParams.productColorName" placeholder="请输入SKU品名" size="small" @keyup.enter.native="handleQuery" />
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" @click="handleQuery" class="searchBtn">搜索</el-button>
+          <el-button size="small" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <div style="height: calc(100vh - 110px - 40px - 50px - 30px - 48px - 48px); overflow-y: auto; padding: 0 8px">
+        <div v-for="(item, index) in quickList" :key="index" style="display: flex" v-db-click>
+          <div style="width: calc(100% - 100px); margin-top: 16px; box-shadow: 0px 0px 10px #ccc; padding: 20px; cursor: pointer" @click="clickQuick(item)">
+            <el-row>
+              <el-col :span="5">
+                <span>{{ item.contractCode }}</span>
+              </el-col>
+              <el-col :span="5" style="padding-left: 8px">
+                <span>{{ item.productColorCode }}</span>
+              </el-col>
+              <el-col :span="10" style="padding-left: 8px">
+                <span>{{ item.productColorName }}</span>
+              </el-col>
+              <el-col :span="4" style="padding-right: 8px; text-align: right">
+                <el-button size="small" @click="scanTheCode(item)" class="searchBtn">模拟扫码</el-button>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+        <br />
+      </div>
+    </div>
+
+    <!-- 打印生产面单 -->
+    <el-dialog :visible.sync="dialogVisible" title="打印生产面单" width="40%" append-to-body>
+      <el-form label-width="100px" :model="form" ref="form" :rules="rules">
+        <el-form-item label="工位:" prop="antno">
+          <el-input v-model="form.antno" placeholder="请输入"> </el-input>
+        </el-form-item>
+      </el-form>
+      <el-row style="text-align: center; margin-top: 30px">
+        <el-button size="small" @click="handleCancel">取 消</el-button>
+        <el-button size="small" type="primary" @click="handleSubmit">保 存</el-button>
+      </el-row>
+    </el-dialog>
+
+    <!-- 验证密码 -->
+    <el-dialog title="验证密码" v-if="openCheckPWD" :visible.sync="openCheckPWD" width="30%" append-to-body>
+      <el-form ref="ruleForm" :model="pwd" label-width="110px" @submit.native.prevent>
+        <el-form-item label="密码:" prop="projectPrice" class="other-charges">
+          <el-input v-model="pwd" size="small" placeholder="请输入密码" @keyup.enter.native="clickPassword" />
+        </el-form-item>
+        <div style="width: 100%; text-align: center">
+          <el-button type="primary" @click="clickPassword" size="small" v-db-click>确 认</el-button>
+          <el-button size="small" @click="openCheckPWD = false">取 消</el-button>
+        </div>
+      </el-form>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import LabelTemplate from '@/components/LabelTemplate'
+import * as API from '@/api/shengde/productionSystem/productionOperation/pack'
+import { mapGetters } from 'vuex'
+import Utils from '@/util/transit'
+import BarCodeScan from '@/components/BarCodeScan/index'
+import { getUid } from '@/util/saas.js'
+
+export default {
+  name: 'pack',
+  components: { LabelTemplate, BarCodeScan },
+  computed: mapGetters(['userInfo']),
+  data() {
+    return {
+      pathPrefix: process.env.VUE_APP_IMG_URL,
+      station: null,
+      dialogVisible: false,
+      form: {
+        antno: '',
+        userId: '',
+      },
+      rules: {
+        antno: [{ required: true, message: '请输入工位', trigger: 'blur' }],
+      },
+      ws: null, //建立的webSocket连接
+      lockReconnect: false, //是否真正建立连接
+      timeout: 28 * 1000, //30秒一次心跳
+      timeoutObj: null, //心跳倒计时
+      serverTimeoutObj: null, //心跳倒计时
+      timeoutnum: null, //断开 重连倒计时
+      dataObj: {
+        contractProductId: '',
+      },
+      quickList: [],
+      openCheckPWD: false,
+      pwd: '',
+      rowData: {},
+      uuid: '',
+      status: true,
+      AKeyStatus: false,
+      queryParams: {
+        contractCode: '',
+        productColorName: '',
+        productColorCode: '',
+      },
+    }
+  },
+  created() {
+    this.clickRefresh()
+  },
+  mounted() {
+    this.getDetails()
+    this.initWebSocket()
+    Utils.$on('webSocketClose', () => {
+      this.ws.close()
+      //清除时间
+      clearTimeout(this.timeoutObj)
+      clearTimeout(this.serverTimeoutObj)
+    })
+  },
+  methods: {
+    handleBarcode(val) {
+      API.packScanCode({ qrCode: val }).then()
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.clickRefresh()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    initWebSocket() {
+      this.ws = new WebSocket(process.env.VUE_APP_MESSAGE_URL + '/saas-socket/saas/socket/websocket/notice?userId=' + this.userInfo.user_id + '_bz')
+      this.ws.onopen = this.onopen
+      this.ws.onmessage = this.onmessage
+      this.ws.onclose = this.onclose
+      this.ws.onerror = this.onerror
+    },
+    onopen() {
+      this.ws.send('ping')
+      //开启心跳
+      this.start()
+    },
+    onmessage(e) {
+      let data = JSON.parse(e.data)
+      console.log(data.data.details.rows, '包装websocket消息')
+      //过滤为websokect测试消息
+      if (data.data.details.rows[0] !== '测试发送消息') {
+        let obj = JSON.parse(data.data.details.rows[0]) //此次推送的整个对象
+        console.log(obj, '包装')
+        let value = JSON.parse(obj.notice.content)
+        if (obj.notice.msgType === 20 || obj.notice.msgType === 21 || obj.notice.msgType === 25) {
+          if (obj.notice.msgType === 21) {
+            this.AKeyStatus = false
+            this.uuid = value.code
+          } else if (obj.notice.msgType === 25) {
+            this.AKeyStatus = true
+            this.uuid = value.id
+          }
+          API.getPackingDetails({ id: value.id }).then((res) => {
+            this.dataObj = res.data.data
+          })
+        }
+      }
+      this.reset()
+    },
+    onclose() {
+      console.log('close')
+      this.reconnect()
+    },
+    onerror() {
+      console.log('error')
+      this.reconnect()
+    },
+    reset() {
+      //重置心跳
+      let that = this
+      //清除时间
+      clearTimeout(that.timeoutObj)
+      //重启心跳
+      that.start()
+    },
+    start() {
+      var self = this
+      self.timeoutObj && clearTimeout(self.timeoutObj)
+      self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj)
+      self.timeoutObj = setTimeout(() => {
+        //这里发送一个心跳,后端收到后,返回一个心跳消息,
+        if (self.ws.readyState == 1) {
+          //如果连接正常
+          self.ws.send('heartCheck')
+        } else {
+          //否则重连
+          self.reconnect()
+        }
+        self.serverTimeoutObj = setTimeout(function () {
+          //超时关闭
+          console.log('包装超时')
+          self.ws.close()
+          setTimeout(() => {
+            self.reconnect()
+          }, 1000)
+        }, self.timeout)
+      }, self.timeout)
+    },
+    reconnect() {
+      //重新连接
+      let that = this
+      if (that.lockReconnect) {
+        return
+      }
+      that.lockReconnect = true
+      //没连接上会一直重连,设置延迟避免请求过多
+      that.timeoutnum && clearTimeout(that.timeoutnum)
+      that.timeoutnum = setTimeout(() => {
+        //新连接
+        that.initWebSocket()
+        that.lockReconnect = false
+      }, 5000)
+    },
+    handleOpen() {
+      this.dialogVisible = true
+      if (this.station) {
+        this.getDetails()
+      }
+    },
+    getDetails() {
+      API.getStation(this.userInfo.user_id).then((res) => {
+        this.form = res.data.data
+        this.station = res.data.data.antno
+      })
+    },
+    handleCancel() {
+      this.dialogVisible = false
+      this.form = {
+        num: '',
+      }
+    },
+    handleSubmit() {
+      this.$refs['form'].validate((valid) => {
+        if (valid) {
+          this.form.userId = this.userInfo.user_id
+          if (this.form.id) {
+            API.bindStation(this.form).then(() => {
+              this.station = this.form.antno
+              this.initWebSocket()
+              this.msgSuccess('修改成功!')
+              this.handleCancel()
+            })
+          } else {
+            API.bindStation(this.form).then(() => {
+              this.station = this.form.antno
+              this.initWebSocket()
+              this.msgSuccess('保存成功!')
+              this.handleCancel()
+            })
+          }
+        } else {
+          return false
+        }
+      })
+    },
+    openFile(path) {
+      window.open(path)
+    },
+    clickQuick(item) {
+      if (this.status) {
+        this.status = false
+        API.getPackagingDetails({ id: item.id }).then()
+      }
+      setTimeout(() => {
+        this.status = true
+      }, 2000)
+    },
+    clickSubmit() {
+      if (this.AKeyStatus) {
+        API.batchPackComplete({ id: this.uuid }).then(() => {
+          this.msgSuccess('包装完成')
+          this.dataObj = {
+            contractProductId: '',
+          }
+          this.clickRefresh()
+        })
+      } else {
+        API.packWorkComplete({ qrCode: this.uuid }).then(() => {
+          this.msgSuccess('包装完成')
+          this.dataObj = {
+            contractProductId: '',
+          }
+          this.clickRefresh()
+        })
+      }
+    },
+    clickRefresh() {
+      API.getInformationDetail(this.queryParams).then((res) => {
+        this.quickList = res.data.data
+      })
+    },
+    clickOneClickPacking(item) {
+      this.rowData = item
+      this.pwd = ''
+      this.openCheckPWD = true
+    },
+    clickPassword() {
+      if (this.pwd) {
+        if (this.pwd === 'sd2022') {
+          this.msgSuccess('验证成功')
+          API.getBatchPackagingDetails({ id: this.rowData.id }).then(() => {
+            this.clickRefresh()
+            this.openCheckPWD = false
+          })
+        } else {
+          this.msgInfo('密码验证错误')
+        }
+      } else {
+        this.msgInfo('请输入密码')
+      }
+    },
+    clickCancel() {
+      this.dataObj = {
+        contractProductId: '',
+      }
+      this.clickRefresh()
+    },
+    scanTheCode(item) {
+      API.packScanCode({ qrCode: item.id + '-' + getUid() }).then()
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+::v-deep {
+  .el-button {
+    border-radius: 0;
+  }
+  .el-input__inner {
+    height: 28px;
+    line-height: 28px;
+  }
+  .el-table .cell {
+    font-size: 12px;
+  }
+  .el-card__body {
+    padding: 20px;
+  }
+  .one-click-packing {
+    width: 56px;
+    padding: 8px 0;
+    margin: 16px 0 0 16px;
+    border-radius: 50px !important;
+  }
+  .hideInput {
+    .el-input__inner {
+      height: 0px;
+      line-height: 0px;
+      border: 0 !important;
+      padding: 0 !important;
+    }
+  }
+}
+.main {
+  height: calc(100vh - 110px);
+  overflow-y: auto;
+  padding: 20px;
+  background: #fff;
+  .btn {
+    padding: 0 8px;
+    // border: 1px solid lightskyblue;
+    border-radius: 1px;
+    // background-color: #e9f5fb;
+    height: 48px;
+    line-height: 48px;
+  }
+  .btnWln {
+    padding: 0 8px;
+    height: 48px;
+    line-height: 48px;
+  }
+  .body {
+    margin-top: 10px;
+    display: flex;
+    .left,
+    .right {
+      padding-right: 20px;
+    }
+    .white {
+      box-shadow: 0px 0px 10px #ccc;
+    }
+    .orange {
+      box-shadow: 0px 0px 10px #f59a23;
+    }
+    .left {
+      width: 18%;
+      margin: 0px 10px;
+      height: calc(100vh - 210px);
+      overflow-y: auto;
+      .img {
+        width: 100%;
+        height: 100%;
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: contain;
+          cursor: pointer;
+        }
+      }
+    }
+    .middle {
+      width: 52%;
+      margin: 0px 10px;
+      height: calc(100vh - 210px);
+      // height: calc(65vh - 210px);
+      overflow-y: auto;
+      .detail {
+        margin-left: 20px;
+        .att {
+          margin-bottom: 20px;
+          font-size: 12px;
+        }
+      }
+    }
+    .right {
+      width: 48%;
+      margin: 0px 10px;
+      box-sizing: border-box;
+      height: calc(100vh - 210px);
+      // height: calc(65vh - 210px);
+      overflow-y: auto;
+    }
+  }
+}
+.none {
+  width: 60vw;
+  height: calc(100vh - 110px - 40px - 50px - 30px);
+  margin: auto;
+  // margin-top: 30px;
+}
+.searchBtn {
+  background: #20b2aa;
+  color: #fff;
+  border: 1px solid #20b2aa;
+}
+</style>

+ 72 - 0
src/views/shengde/productionSystem/demo/simulation/index.vue

@@ -0,0 +1,72 @@
+<template>
+  <el-card class="box-card">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" @submit.native.prevent>
+      <el-form-item>
+        <el-button size="small" @click="getList" class="searchBtn">搜索</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- <el-table :data="tableList" :cell-style="{ padding: '0' }" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+      <el-table-column label="AAAA" align="center" prop="AAAA" />
+      <el-table-column label="操作" align="center" width="140" fixed="right">
+        <template slot-scope="scope">
+          <el-button type="text" @click="clickUpdate(scope.row)" v-db-click>修改</el-button>
+          <el-button type="text" @click="clickRemove(scope.row)" v-db-click>删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table> -->
+  </el-card>
+</template>
+
+<script>
+import * as API from '@/api/shengde/productionSystem/demo/simulation'
+
+export default {
+  name: 'simulation',
+  data() {
+    return {
+      queryParams: {},
+      tableList: [],
+    }
+  },
+  created() {},
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      API.getDrawing({}).then((res) => {
+        console.log(res)
+      })
+    },
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+* {
+  font-size: 12px;
+}
+.box-card {
+  height: calc(100vh - 110px);
+  overflow-y: auto;
+}
+.searchBtn {
+  background: #20b2aa;
+  color: #fff;
+  border: 1px solid #20b2aa;
+}
+::v-deep {
+  .el-input__inner {
+    border-radius: 1px;
+  }
+  .el-button--small {
+    border-radius: 1px;
+  }
+  .tableHeader th {
+    background-color: #edf0f5;
+    height: 35px;
+    padding: 0;
+  }
+}
+</style>

+ 3 - 2
src/views/shengde/productionSystem/productionOperation/artificial/index.vue

@@ -90,8 +90,8 @@
               <el-input v-model="queryParams.productColorName" placeholder="请输入SKU品名" size="small" @keyup.enter.native="handleQuery" />
             </el-form-item>
             <el-form-item>
-              <el-button size="mini" @click="handleQuery" class="searchBtn">搜索</el-button>
-              <el-button size="mini" @click="resetQuery">重置</el-button>
+              <el-button size="small" @click="handleQuery" class="searchBtn">搜索</el-button>
+              <el-button size="small" @click="resetQuery">重置</el-button>
             </el-form-item>
           </el-form>
         </div>
@@ -115,6 +115,7 @@
               </el-col>
             </el-row>
           </div>
+          <br />
         </div>
       </div>
     </div>

+ 1 - 0
src/views/shengde/productionSystem/productionOperation/batching/already.vue

@@ -211,6 +211,7 @@ export default {
             let obj = { ...this.rowData, sort: i, uid: getUid() }
             arr.push(obj)
           }
+          console.log(arr);
           this.QRcodeList = arr
           this.$nextTick(() => {
             for (let i = 0; i < this.QRcodeList.length; i++) {

+ 2 - 2
src/views/shengde/productionSystem/productionOperation/pack/index.vue

@@ -85,8 +85,8 @@
           <el-input v-model="queryParams.productColorName" placeholder="请输入SKU品名" size="small" @keyup.enter.native="handleQuery" />
         </el-form-item>
         <el-form-item>
-          <el-button size="mini" @click="handleQuery" class="searchBtn">搜索</el-button>
-          <el-button size="mini" @click="resetQuery">重置</el-button>
+          <el-button size="small" @click="handleQuery" class="searchBtn">搜索</el-button>
+          <el-button size="small" @click="resetQuery">重置</el-button>
         </el-form-item>
       </el-form>
       <div style="height: calc(100vh - 110px - 40px - 50px - 30px - 48px - 48px); overflow-y: auto; padding: 0 8px">

+ 2 - 1
vue.config.js

@@ -57,8 +57,9 @@ module.exports = {
     proxy: {
       [process.env.VUE_APP_BASE_API]: {
         //本地服务接口地址
-        target: 'http://www.printmat.cn:8866',
+        // target: 'http://www.printmat.cn:8866',
         // target: 'http://116.205.162.119:8866',
+        target: 'http://192.168.1.164:8866',
         changeOrigin: true,
         pathRewrite: {
           [`^${process.env.VUE_APP_BASE_API}`]: '/',