1、Plcaction类  接收前端message并 writeword   同时每10秒readword 发送给前端并渲染
2、用户token 设置为一天 ,超时自动跳转到登录页面
3、layout布局el-head 高度调整
14个文件已修改
5个文件已添加
986 ■■■■ 已修改文件
CanadaMes-ui/src/layout/index.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/store/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/store/module/tags.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/utils/request.js 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Action.vue 131 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Parameter.vue 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Sign.vue 111 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/State.vue 86 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/device/talkvue.vue 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/.idea/libraries/Maven__com_github_xingshuangs_iot_communication_1_4_2.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/pom.xml 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/springboot-vue3.iml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/component/PlcHold.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/component/Plcaction.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/component/WebSocketServer.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/config/AppRunnerConfig.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/controller/DefaultController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/entity/vo/Result.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/security/constant/SystemConstant.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/layout/index.vue
@@ -51,36 +51,33 @@
        </el-col>
      </el-aside>
    </div>
    <el-container>
      <div>
  </div>
      <el-header class="header-container">
        <!-- <div class="tagContainer">
               <tag></tag>
        </div>  -->
    <el-container  >
      <el-header class="header-container"    >
        
        <div class="tagContainer">
        <div class="tagContainer"  >
      <tag v-for="(tag, index) in tags" :key="index" :tag="tag" @removeTag="removeTag"></tag>
    </div>
        <el-menu :default-active="activePath1" class="el-menu-demo" mode="horizontal"
                 background-color="#576574" text-color="#fff" active-text-color="#ffd04b">
                 <div class="header-left">
          <el-button :icon="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'" @click="toggleCollapse"></el-button>
                 <div class="header-left"   >
          <el-button :icon="isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'" @click="toggleCollapse"   style="height:30px"></el-button>
        </div>
          <el-submenu index="1" class="user-icon">
        <template >
          <el-submenu index="1"  class="custom-submenu"  >
        
            <template slot="title">
              <el-avatar src="../assets/emi.png">
             <template slot="title">
              <el-avatar src="../assets/emi.png"  style="width:30px;height:30px;margin-top:2px;">
              </el-avatar>
            </template>
            <el-menu-item index="1-1" @click="logout">{{ $t('exit') }}</el-menu-item>
            <el-menu-item index="1-2" @click="showChangePasswordDialog">{{ $t('changePassword') }}</el-menu-item>
            </template>
            <el-menu-item index="1-1" @click="logout"  >{{ $t('exit') }}</el-menu-item>
            <el-menu-item index="1-2" @click="showChangePasswordDialog"  >{{ $t('changePassword') }}</el-menu-item>
          </el-submenu>
        </template>
          <template>
  <el-dialog title="修改密码" :visible.sync="dialogVisible" width="30%">
    <el-form ref="form" :model="formData" label-width="100px">
  <el-dialog title="修改密码" :visible.sync="dialogVisible" width="30%"   s>
    <el-form ref="form" :model="formData" label-width="100px"   >
      <el-form-item label="旧密码">
        <el-input v-model="formData.oldPassword" type="password" show-password></el-input>
      </el-form-item>
@@ -255,13 +252,28 @@
</script>
<style scoped lang="less">
.header-container {
  display: flex;
  justify-content: flex-start;
// .header-container {
//   display: flex;
//   justify-content: flex-start;
//   height: 10px; /* 设置较小的高度 */
// }
.custom-submenu  {
  height: 90px   !important;
}
.header-container {
  height: 30px   !important; /* 设置较小的高度 */
 }
.header-left {
  margin-right: auto;
}
.el-aside {
  height: 100vh;
@@ -302,7 +314,7 @@
}
.el-header {
  padding: 0;
  background-color: #576574;
}
</style>
CanadaMes-ui/src/store/index.js
New file
@@ -0,0 +1,14 @@
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import tags from './module/tags';
Vue.use(Vuex);
export default new Vuex.Store({
  modules: {
    tags,
  },
  // 其他配置
});
CanadaMes-ui/src/store/module/tags.js
New file
@@ -0,0 +1,22 @@
const state = {
  tags: []
};
const mutations = {
  addTag(state, tag) {
    if (!state.tags.includes(tag)) {
      state.tags.push(tag);
    }
  },
  removeTag(state, tag) {
    const index = state.tags.indexOf(tag);
    if (index !== -1) {
      state.tags.splice(index, 1);
    }
  }
};
export default {
  state,
  mutations
};
CanadaMes-ui/src/utils/request.js
@@ -1,5 +1,5 @@
import axios from 'axios'
import {Message} from 'element-ui'
import { Message } from 'element-ui'
const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_API,
@@ -9,16 +9,29 @@
service.interceptors.response.use(
    response => {
        const res = response.data
        if (res.code !== 1 && res.code !== "200") {
        if (res.code !== 1 && res.code !== "200" ) {
            Message({
                message: res.msg || 'Error',
                type: 'error',
                duration: 5 * 1000
            })
            return Promise.reject(new Error(res.msg || 'Error'))
            if (res == 403) {
                window.location.href = '/login'
            }else{
                return Promise.reject(new Error(res.msg || 'Error')
                )
            }
        } else {
            return res
        }
    },
    error => {
        console.log('err' + error)
CanadaMes-ui/src/views/Electrical/Action.vue
@@ -2,38 +2,131 @@
  <div class="app">
    <!--面包屑导航区域-->
    <el-breadcrumb separator-class="el-icon-arrow-right" class="el-breadcrumb">
      <el-breadcrumb-item :to="{ path: '/home' }">{{ $t('langHome') }}</el-breadcrumb-item>
      <el-breadcrumb-item>设备管理</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Parameter' }">参数</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Action' }">开关控制</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Sign' }">IO状态</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/State' }">报警信息</el-breadcrumb-item>
      <router-link to="/home" tag="el-button" type="text">{{ $t('langHome') }}</router-link>
      <el-button type="text">设备管理</el-button>
      <router-link to="/Electrical/Parameter" tag="el-button" type="text">Parameter</router-link>
      <router-link to="/Electrical/Action" tag="el-button" type="text">Action</router-link>
      <router-link to="/Electrical/Sign" tag="el-button" type="text">Sign</router-link>
      <router-link to="/Electrical/State" tag="el-button" type="text">State</router-link>
    </el-breadcrumb>
    <div>开关控制</div>
    <div>Action</div>
    <el-form label-width="100px" style="display: flex;flex-wrap: wrap;" :model="{ records }">
      <div class="kuai_sb" v-for="item in records" :key="item.id">
        <el-input v-model="item.mingcheng" style="width: 280px;" class="in_mc"></el-input>
        <!-- <el-input v-model="item.zhuangtai" style="width: 80px;"></el-input> -->
        <el-switch v-model="item.zhuangtai" active-color="#13ce66" active-value="1" inactive-value="2"></el-switch>
      </div>
      <div class="kuai_div">
  <el-input style="width: 280px;" class="in_mc" value="conveyor Velocity(Auto SLOW)"></el-input>
  <el-input v-for="(param, index) in record.params[0]" :key="index" v-model="record.params[0][index]" style="width: 80px;"></el-input>
</div>
<button @click="send()">测试发送</button>
    </el-form>
  </div>
</template>
<script>
<script >
let socket;
export default {
  name: "Action",
  data () {
    return {
      records: [
        { id: 1, mingcheng: 'conveyor Velocity(Auto SLOW)', zhuangtai: "1" },
        { id: 2, mingcheng: 'B01 B02 TRAVEL POS Velocity AUTO', zhuangtai: "2" },
        { id: 3, mingcheng: 'B01 B02 TRAVEL JOG Velocity', zhuangtai: "2" },
        { id: 4, mingcheng: 'conveyor Velocity(Manual)', zhuangtai: "1" }
      ],
      messagepack: {
        data: { taskname: "" }
      },
      record: {
      params: [0,0,0,0,0,0]
    },
    }
  },
  created () {
    this.init();
    //console.log(this.records);
  },
  methods: {
    init () {
      let viewname = "talkvue";
      if (typeof (WebSocket) == "undefined") {
        console.log("您的浏览器不支持WebSocket");
      } else {
        //console.log("您的浏览器支持WebSocket");
        let socketUrl = "ws://" + "localhost:8888" + "/springboot-vue3/api/talk/" + viewname;
        if (socket != null) {
          socket.close();
          socket = null;
        }
        // 开启一个websocket服务
        socket = new WebSocket(socketUrl);
        //打开事件
        socket.onopen = function () {
          console.log("websocket已打开");
        };
        //  浏览器端收消息,获得从服务端发送过来的文本消息
        socket.onmessage = function (msg) {
  console.log("收到数据====" + msg.data);
  let obj = JSON.parse(msg.data);
  this.$set(this.record.params, 0, obj.params[0]);
  console.log( this.record.params[0])
}.bind(this);
        //关闭事件
        socket.onclose = function () {
          console.log("websocket已关闭");
        };
        //发生了错误事件
        socket.onerror = function () {
          console.log("websocket发生了错误");
        }
      }
    },
    send () {
      this.messagepack.data = { taskname: "前端到后台" };
      socket?.send(JSON.stringify(this.messagepack));  // 将组装好的json发送给服务端,由服务端进行转发
    }
  }
}
</script>
<style lang="less" scoped>
.el-table {
  margin-top: 15px;
  font-size: 12px;
<style>
.kuai_sb {
  width: 30%;
  margin-bottom: 15px;
}
.el-pagination {
  margin-top: 15px;
.el-input {
  border: none;
  .el-input__inner {
    border: 1 solid black;
  }
}
.app .el-card {
  width: 99%;
.in_mc {
  .el-input__inner {
    border: none;
  }
}
</style>
</style>
CanadaMes-ui/src/views/Electrical/Parameter.vue
@@ -1,81 +1,152 @@
<template>
  <div class="app">
    <!--面包屑导航区域-->
    <el-breadcrumb separator-class="el-icon-arrow-right" class="el-breadcrumb">
      <el-breadcrumb-item :to="{ path: '/home' }">{{ $t('langHome') }}</el-breadcrumb-item>
      <el-breadcrumb-item>设备管理</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Parameter' }">参数</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Action' }">开关控制</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Sign' }">IO状态</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/State' }">报警信息</el-breadcrumb-item>
    </el-breadcrumb>
    <div>参数</div>
    <el-row :gutter="40" style="display: flex;flex-wrap: wrap;">
      <el-col :span="7">
        <div class="grid-content bg-purple">
          <el-input prop="sbname"></el-input>
          <el-input prop="sbdata"></el-input>
        </div>
      </el-col>
    </el-row>
  <!--面包屑导航区域-->
  <el-breadcrumb separator-class="el-icon-arrow-right" class="el-breadcrumb">
  <router-link to="/home" tag="el-button" type="text">{{ $t('langHome') }}</router-link>
  <el-button type="text">设备管理</el-button>
  <router-link to="/Electrical/Parameter" tag="el-button" type="text">Parameter</router-link>
  <router-link to="/Electrical/Action" tag="el-button" type="text">Action</router-link>
  <router-link to="/Electrical/Sign" tag="el-button" type="text">Sign</router-link>
  <router-link to="/Electrical/State" tag="el-button" type="text">State</router-link>
  </el-breadcrumb>
  <div>Parameter</div>
  <el-form label-width="100px" style="display: flex;flex-wrap: wrap;" :model="messagepack.data">
    <div id="btn_div">
      <el-button type="primary" @click="send()">下发参数</el-button>
    </div>
    <div class="kuai_div" v-for="(item, index) in record.xyData" :key="index">
      <el-input style="width: 280px;" class="in_mc" v-model="item.name"  readonly></el-input>
      <el-input v-model="item.value" style="width: 80px;"></el-input>
    </div>
  </el-form>
  </div>
</template>
<script>
export default {
  </template>
  <script>
  let socket;
  export default {
  name: "Parameter",
  // data () {
  //   return {
  //     sbList: {
  //       records: [],
  //     }
  //   }
  // }
}
</script>
<style lang="less" scoped>
.el-row {
  margin-bottom: 20px;
  &:last-child {
    margin-bottom: 0;
  data() {
  return {
  record: {
  params: [0, 0, 0, 0, 0, 0],
  xyData: [{ name: "conveyor Velocity(Auto SLOW)", value: 0 },
    { name: "B01 B02 TRAVEL POS Velocity AUTO", value: 0 },
    { name: "B01 B02 TRAVEL JOG Velocity", value: 0 },
    { name: "conveyor Velocity(Manual)", value: 0},
    { name: "B01 B02 TRAVEL JOG Velocity", value: 0},
    { name: "conveyor Velocity(Manual)", value: 0 }],
  canshu: [
  'conveyor Velocity(Auto SLOW)',
  'B01 B02 TRAVEL POS Velocity AUTO',
  'B01 B02 TRAVEL JOG Velocity',
  'conveyor Velocity(Manual)',
  'B01 B02 TRAVEL JOG Velocity',
  'conveyor Velocity(Manual)'
  ],
  },
  messagepack: {
  data: { taskname: "" }
  },
  queryInfo: {
  data: "1",
  pageSize: 10
  },
  }
}
  },
  created() {
  this.initWebSocket();
  },
  methods: {
  initWebSocket() {
  let viewname = "action";
    if (typeof WebSocket == "undefined") {
      console.log("您的浏览器不支持WebSocket");
    } else {
      //console.log("您的浏览器支持WebSocket");
      let socketUrl = "ws://" + "localhost:8888" + "/springboot-vue3/api/talk/" + viewname;
      if (socket != null) {
        socket.close();
        socket = null;
      }
      // 开启一个websocket服务
      socket = new WebSocket(socketUrl);
      // 打开事件
      socket.onopen = function () {
        console.log("websocket已打开");
      };
      // 收到消息
      socket.onmessage = (msg) => {
  if (!msg.data) {
    return; // 如果收到空数据,则直接返回,不执行后续逻辑
  }
.el-col {
  border-radius: 4px;
  margin: 10px;
}
  let obj = JSON.parse(msg.data);
  this.record.params[0] = obj.params[0];
.el-input {
  width: 70px;
  height: 30px;
}
  for (let a = 0; a <= this.record.params[0].length - 1; a++) {
    if (!this.record.xyData[a]) {
      this.record.xyData[a] = { name: this.record.canshu[a], value: this.record.params[0][a] };
    } else {
      this.record.xyData[a].value = this.record.params[0][a];
    }
  }
.bg-purple-dark {
  background: #99a9bf;
  console.log(this.record.xyData);
  this.$forceUpdate();
};
      // 关闭事件
      socket.onclose = function () {
        console.log("websocket已关闭");
      };
      // 发生错误事件
      socket.onerror = function () {
        console.log("websocket发生了错误");
      }
    }
  },
  send() {
  this.messagepack.data = this.record.xyData.map(item => parseInt(item.value)); // 转换为整数数组
  console.log(this.messagepack);
  socket?.send(JSON.stringify(this.messagepack));
}
.bg-purple {
  background: #d3dce6;
}
.bg-purple-light {
  background: #e5e9f2;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
}
</style>
  }
  }
  </script>
  <style>
  .kuai_div {
  width: 30%;
  margin-bottom: 15px;
  }
  .el-input {
  border: none;
  }
  .el-input__inner {
  border: 1px solid black;
  }
  .in_mc .el-input__inner {
  border: none;
  }
  #btn_div {
  width: 100%;
  }
  #btn_div .el-button {
  float: right;
  }
  </style>
CanadaMes-ui/src/views/Electrical/Sign.vue
@@ -2,38 +2,113 @@
  <div class="app">
    <!--面包屑导航区域-->
    <el-breadcrumb separator-class="el-icon-arrow-right" class="el-breadcrumb">
      <el-breadcrumb-item :to="{ path: '/home' }">{{ $t('langHome') }}</el-breadcrumb-item>
      <el-breadcrumb-item>设备管理</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Parameter' }">参数</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Action' }">开关控制</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Sign' }">IO状态</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/State' }">报警信息</el-breadcrumb-item>
      <router-link to="/home" tag="el-button" type="text">{{ $t('langHome') }}</router-link>
      <el-button type="text">设备管理</el-button>
      <router-link to="/Electrical/Parameter" tag="el-button" type="text">Parameter</router-link>
      <router-link to="/Electrical/Action" tag="el-button" type="text">Action</router-link>
      <router-link to="/Electrical/Sign" tag="el-button" type="text">Sign</router-link>
      <router-link to="/Electrical/State" tag="el-button" type="text">State</router-link>
    </el-breadcrumb>
    <div>IO状态</div>
    <div>Sign</div>
    <div style="padding-right: 30px;display: flex;flex-wrap: wrap;">
      <div class="kuai_sb" v-for="item in records" :key="item.id">
        <el-col class="deng" :class="getStatusClass(item.zhuangtai)">
          <!-- <el-input v-model="item.zhuangtai" style="width: 280px;display: none;"
            class="in_mc"></el-input>-->
        </el-col>
        <el-input v-model="item.mingcheng" style="width: 280px;" class="in_mc"></el-input>
        <!-- <el-switch v-model="item.zhuangtai" active-color="#13ce66" active-value="1" inactive-value="2"></el-switch> -->
      </div>
    </div>
  </div>
</template>
<script>
<script >
export default {
  name: "Sign",
  data () {
    return {
      records: [
        { id: 1, mingcheng: 'conveyor Velocity(Auto SLOW)', zhuangtai: "1" },
        { id: 2, mingcheng: 'B01 B02 TRAVEL POS Velocity AUTO', zhuangtai: "2" },
        { id: 3, mingcheng: 'B01 B02 TRAVEL JOG Velocity', zhuangtai: "2" },
        { id: 4, mingcheng: 'conveyor Velocity(Manual)', zhuangtai: "2" }
      ]
    }
  },
  created () {
  },
  methods: {
    getStatusClass (zhuangtai) {
      if (zhuangtai === "2") {
        return "dow";
      } else {
        return "op";
      }
    }
  }
}
</script>
<style lang="less" scoped>
.el-table {
  margin-top: 15px;
  font-size: 12px;
<style>
* {
  margin: 0;
  padding: 0;
}
.el-pagination {
  margin-top: 15px;
.el-input__inner {
  text-align: center;
  width: 100%;
}
.app .el-card {
  width: 99%;
.kuai_sb {
  text-align: center;
  width: 30%;
  margin-bottom: 15px;
}
</style>
.el-input {
  .el-input__inner {
    border: 1 solid black;
  }
}
.in_mc {
  .el-input__inner {
    border: none;
  }
}
.deng {
  margin-left: 40%;
  display: inline-block;
  background: #A0A0A0;
  border: 0.1875em solid white;
  border-radius: 50%;
  height: 5em;
  width: 5em;
  box-shadow: 0.375em 0.375em 0 0 rgba(214, 214, 214, 0.125);
}
.op {
  background-color: #00ff22;
}
.dow {
  background-color: #A0A0A0;
}
</style>
CanadaMes-ui/src/views/Electrical/State.vue
@@ -2,38 +2,90 @@
  <div class="app">
    <!--面包屑导航区域-->
    <el-breadcrumb separator-class="el-icon-arrow-right" class="el-breadcrumb">
      <el-breadcrumb-item :to="{ path: '/home' }">{{ $t('langHome') }}</el-breadcrumb-item>
      <el-breadcrumb-item>设备管理</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Parameter' }">参数</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Action' }">开关控制</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/Sign' }">IO状态</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/Electrical/State' }">报警信息</el-breadcrumb-item>
      <router-link to="/home" tag="el-button" type="text">{{ $t('langHome') }}</router-link>
      <el-button type="text">设备管理</el-button>
      <router-link to="/Electrical/Parameter" tag="el-button" type="text">Parameter</router-link>
      <router-link to="/Electrical/Action" tag="el-button" type="text">Action</router-link>
      <router-link to="/Electrical/Sign" tag="el-button" type="text">Sign</router-link>
      <router-link to="/Electrical/State" tag="el-button" type="text">State</router-link>
    </el-breadcrumb>
    <div>报警信息</div>
    <div>State</div>
    <el-form label-width="100px" style="display: flex;flex-wrap: wrap;" :model="{ records }">
      <div id="btn_div">
        <el-button type="primary">下发参数</el-button>
      </div>
      <div class="kuai_div" v-for="item in records" :key="item.id">
        <el-input v-model="item.mingcheng" style="width: 280px;" class="in_mc"></el-input>
        <el-input v-model="item.zhuangtai" style="width: 80px;"></el-input>
      </div>
    </el-form>
  </div>
</template>
<script>
<script >
export default {
  name: "State",
  data () {
    return {
      records: [
        { id: 1, mingcheng: 'conveyor Velocity(Auto SLOW)', zhuangtai: "1" },
        { id: 2, mingcheng: 'B01 B02 TRAVEL POS Velocity AUTO', zhuangtai: "2" },
        { id: 3, mingcheng: 'B01 B02 TRAVEL JOG Velocity', zhuangtai: "2" },
        { id: 4, mingcheng: 'conveyor Velocity(Manual)', zhuangtai: "2" }
      ]
    }
  },
  created () {
  },
  methods: {
  }
}
</script>
<style lang="less" scoped>
.el-table {
  margin-top: 15px;
  font-size: 12px;
<style>
.kuai_div {
  width: 30%;
  margin-bottom: 15px;
}
.el-pagination {
  margin-top: 15px;
.el-input {
  border: none;
  .el-input__inner {
    border: 1 solid black;
  }
}
.app .el-card {
  width: 99%;
.in_mc {
  .el-input__inner {
    border: none;
  }
}
#btn_div {
  width: 100%;
}
#btn_div .el-button {
  float: right;
}
</style>
CanadaMes-ui/src/views/device/talkvue.vue
@@ -1,6 +1,14 @@
<template>
  <!-- <button v-on:click="send">测试发送</button> -->
  <button @click="send()">测试发送</button>
  <div>
    <button @click="send()">测试发送</button>
  <button @click="ttt()">测试发送</button>
  </div>
</template>
    
<script>
@@ -13,6 +21,7 @@
      messagepack: {
        data: { taskname:"" }
      },
      qqqq:{},
      queryInfo: {
        data: "1",
        pageSize: 10
@@ -21,6 +30,7 @@
  },
  created() {
    this.init();
  },
  methods:
  {
@@ -47,8 +57,9 @@
        socket.onmessage = function (msg) {
          console.log("收到数据====" + msg.data)
          //let data = JSON.parse(msg.data)  // 对收到的json数据进行解析, 类似这样的: {"users": [{"username": "zhang"},{ "username": "admin"}]}
          // 对收到的json数据进行解析, 类似这样的: {"users": [{"username": "zhang"},{ "username": "admin"}]}
          this.qqqq= JSON.parse(msg.data);
console.log(this.qqqq);
        };
        //关闭事件
        socket.onclose = function () {
@@ -63,7 +74,11 @@
    send() {
      this.messagepack.data =  {taskname:"前端到后台"} ;
      socket?.send(JSON.stringify(this.messagepack));  // 将组装好的json发送给服务端,由服务端进行转发
    }
    },
    ttt() {
      console.log(this.qqqq)
    },
  }
}
</script>
springboot-vue3/.idea/libraries/Maven__com_github_xingshuangs_iot_communication_1_4_2.xml
New file
@@ -0,0 +1,13 @@
<component name="libraryTable">
  <library name="Maven: com.github.xingshuangs:iot-communication:1.4.2">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/com/github/xingshuangs/iot-communication/1.4.2/iot-communication-1.4.2.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/com/github/xingshuangs/iot-communication/1.4.2/iot-communication-1.4.2-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/com/github/xingshuangs/iot-communication/1.4.2/iot-communication-1.4.2-sources.jar!/" />
    </SOURCES>
  </library>
</component>
springboot-vue3/pom.xml
New file
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.canadames</groupId>
    <artifactId>canadames</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>canadames</name>
    <description>canadames System</description>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <encoding>UTF-8</encoding>
        <java.version>8</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <spring-boot.version>2.3.2.RELEASE</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.4</version>
        </dependency>
        <!--参数校验-->
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <!--JWT-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.7</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.7</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.7</version>
            <scope>runtime</scope>
        </dependency>
        <!--shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-starter</artifactId>
            <version>1.8.0</version>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <!-- swagger -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!-- swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.xingshuangs</groupId>
            <artifactId>iot-communication</artifactId>
            <version>1.4.2</version>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
         </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>nexus-aliyun</id>
            <name>nexus-aliyun</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>
springboot-vue3/springboot-vue3.iml
@@ -179,5 +179,6 @@
    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-websocket:2.3.2.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-messaging:5.2.8.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: org.springframework:spring-websocket:5.2.8.RELEASE" level="project" />
    <orderEntry type="library" name="Maven: com.github.xingshuangs:iot-communication:1.4.2" level="project" />
  </component>
</module>
springboot-vue3/src/main/java/com/example/springboot/component/PlcHold.java
@@ -2,9 +2,6 @@
import java.util.List;
import javax.websocket.Session;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
public class PlcHold extends Thread {
@@ -13,7 +10,7 @@
        while (this != null) {
            try {
                Thread.sleep(15000);
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
@@ -26,11 +23,19 @@
            //推送到前端
            JSONObject jsonObject = new JSONObject();
            jsonObject.append("params", new short[] { 0, 1, 2, 3, 4, 5, });
            jsonObject.append("params", new short[] { 0, 1, 2, 3, 4, 5 });
            WebSocketServer sendwServer = WebSocketServer.sessionMap.get("talkvue");
            if (sendwServer != null) {
                sendwServer.sendMessage(jsonObject.toString());
            }
            JSONObject jsonObject2 = new JSONObject();
            jsonObject2.append("params", new short[] { 0, 3, 2, 3, 4, 5 });
            WebSocketServer sendwServer2 = WebSocketServer.sessionMap.get("action");
            if (sendwServer2 != null) {
                sendwServer2.sendMessage(jsonObject2.toString());
            }
        }
    }
}
springboot-vue3/src/main/java/com/example/springboot/component/Plcaction.java
New file
@@ -0,0 +1,73 @@
package com.example.springboot.component;
import cn.hutool.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class Plcaction extends Thread {
    @Override
    public void run() {
        while (this != null) {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            List<Short> paramlist = S7control.getinstance().ReadWord("DB100.DBW", 12);
            JSONObject jsonObject = new JSONObject();
            jsonObject.append("params", paramlist);
            WebSocketServer sendwServer = WebSocketServer.sessionMap.get("action");
            if (sendwServer != null) {
                sendwServer.sendMessage(jsonObject.toString());
            }
            WebSocketServer webSocketServer = WebSocketServer.sessionMap.get("action");
            if (webSocketServer != null) {
                List<String> messages = webSocketServer.getMessages();
                List<String> addressList = new ArrayList<>();
                addressList.add("DB100.DBW0");
                addressList.add("DB100.DBW2");
                addressList.add("DB100.DBW4");
                addressList.add("DB100.DBW6");
                addressList.add("DB100.DBW8");
                addressList.add("DB100.DBW10");
                addressList.add("DB100.DBW12");
                addressList.add("DB100.DBW14");
                addressList.add("DB100.DBW16");
                addressList.add("DB100.DBW18");
                addressList.add("DB100.DBW20");
                addressList.add("DB100.DBW22");
                if (!messages.isEmpty()) {
                    // 将最后一个消息转换为 short 类型的列表
                    String lastMessage = messages.get(messages.size() - 1);
                    System.out.println("messages:" + messages);
                    String[] parts = lastMessage.split(",");
                    List<Short> messageValues = new ArrayList<>();
                    for (String part : parts) {
                        try {
                            // 使用正则表达式清除非数字字符
                            String cleanedPart = part.replaceAll("[^0-9-]", "");
                            short value = Short.parseShort(cleanedPart.trim());
                            messageValues.add(value);
                        } catch (NumberFormatException e) {
                            // 如果无法解析为 short 类型,则忽略该部分
                            e.printStackTrace();
                        }
                    }
                    // 将消息值写入 PLC
//                    S7control.getinstance().WriteWord(addressList, messageValues);
                    System.out.println("messageValues:" + messageValues);
                    // 清空消息列表
                    messages.clear();
                }
            }
        }
    }
}
springboot-vue3/src/main/java/com/example/springboot/component/WebSocketServer.java
@@ -1,5 +1,7 @@
package com.example.springboot.component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
@@ -23,16 +25,19 @@
@ServerEndpoint(value = "/api/talk/{username}")
@Component
public class WebSocketServer {
   private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
   private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    private List<String> messages;
    /**
     * 记录当前在线连接数
     */
    public static final Map<String, WebSocketServer> sessionMap = new ConcurrentHashMap<>();
    
    private String username;
    private Session session;
    String username;
    Session session;
    public WebSocketServer() {
        this.messages = new ArrayList<>();
    }
    /**
     * 连接建立成功调用的方法
     */
@@ -75,11 +80,11 @@
    public void onMessage(String message, Session session, @PathParam("username") String username) {
        log.info("服务端收到用户username={}的消息:{}", username, message);
        JSONObject obj = JSONUtil.parseObj(message);
         String text = obj.getStr("data"); 
         JSONObject jsonObject = new JSONObject();
         jsonObject.set("message", "ngng");
         jsonObject.set("message", text);
        this.messages.add(text);
         this.sendMessage(jsonObject.toString()); //JSONUtil.toJsonStr(jsonObject)
    }
@@ -115,4 +120,11 @@
        }
    }
    public List<String> getMessages() {
        return messages;
    }
    public void clearMessages() {
        messages.clear();
    }
}
springboot-vue3/src/main/java/com/example/springboot/config/AppRunnerConfig.java
@@ -5,7 +5,8 @@
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import com.example.springboot.component.PlcHold;
import com.example.springboot.component.Plcaction;
@Component
@Order(1)
@@ -15,7 +16,8 @@
        // TODO Auto-generated method stub
       //
       System.out.println("启动完成");
       new PlcHold().start();
    }
        new Plcaction().start();
    }
}
springboot-vue3/src/main/java/com/example/springboot/controller/DefaultController.java
@@ -82,7 +82,8 @@
            } catch (DisabledAccountException e) {
                return Result.fail("帐号已被禁用");
            } catch (ExpiredCredentialsException e) {
                return Result.fail("帐号已过期");
                return Result.fail("请重新登录");
            } catch (UnknownAccountException e) {
                return Result.fail("帐号不存在");
            } catch (UnauthorizedException e) {
springboot-vue3/src/main/java/com/example/springboot/entity/vo/Result.java
@@ -8,6 +8,7 @@
    private String msg;
    private Object data;
    public static Result success(Object data) {
        Result result = new Result();
        result.setCode(1);
springboot-vue3/src/main/java/com/example/springboot/security/constant/SystemConstant.java
@@ -9,7 +9,8 @@
    /**
     * rememberMe 为 false 的时候过期时间是1个小时
     */
    public static final long EXPIRATION = 60 * 60L;
    public static final long EXPIRATION = 60 * 60 * 24L;
    /**
     * rememberMe 为 true 的时候过期时间是7天
     */