ZengTao
2023-09-05 7870c2d4fd6da5269a87f53d584a36628fd8ef12
Merge branch 'master' of http://10.153.19.150:10101/r/CanadaMes
27个文件已修改
7个文件已添加
1个文件已删除
1299 ■■■■ 已修改文件
CanadaMes-ui/package-lock.json 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/lang/locales/en-US.json 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/lang/locales/zh-CN.json 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/layout/index.vue 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/layout/tag.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/main.js 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/store/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/store/module/tags.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/store/store,js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/utils/request.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Action.vue 127 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Parameter.vue 173 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Sign.vue 107 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/State.vue 84 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/device/alarm.vue 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/device/talkvue.vue 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/login/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/power/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/role/index.vue 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/user/index.vue 39 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/.idea/libraries/Maven__com_github_xingshuangs_iot_communication_1_4_2.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_websocket_2_3_2_RELEASE.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/.idea/libraries/Maven__org_springframework_spring_messaging_5_2_8_RELEASE.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/.idea/libraries/Maven__org_springframework_spring_websocket_5_2_8_RELEASE.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/pom.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/springboot-vue3.iml 4 ●●●● 补丁 | 查看 | 原始文档 | 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 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/config/AppRunnerConfig.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/controller/DefaultController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/controller/UserController.java 2 ●●● 补丁 | 查看 | 原始文档 | 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/package-lock.json
@@ -16,7 +16,8 @@
        "less-loader": "^6.2.0",
        "vue": "^2.6.11",
        "vue-i18n": "^8.26.5",
        "vue-router": "^3.3.4"
        "vue-router": "^3.3.4",
        "vuex": "^3.6.2"
      },
      "devDependencies": {
        "@vue/cli-plugin-babel": "~4.5.0",
@@ -13243,6 +13244,14 @@
      "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
      "dev": true
    },
    "node_modules/vuex": {
      "version": "3.6.2",
      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz",
      "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
      "peerDependencies": {
        "vue": "^2.0.0"
      }
    },
    "node_modules/watchpack": {
      "version": "1.7.5",
      "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.5.tgz",
@@ -25281,6 +25290,12 @@
      "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
      "dev": true
    },
    "vuex": {
      "version": "3.6.2",
      "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.2.tgz",
      "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
      "requires": {}
    },
    "watchpack": {
      "version": "1.7.5",
      "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.5.tgz",
CanadaMes-ui/package.json
@@ -16,7 +16,8 @@
    "less-loader": "^6.2.0",
    "vue": "^2.6.11",
    "vue-i18n": "^8.26.5",
    "vue-router": "^3.3.4"
    "vue-router": "^3.3.4",
    "vuex": "^3.6.2"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
CanadaMes-ui/src/lang/locales/en-US.json
@@ -36,5 +36,38 @@
    "northglassMESsystem":"NorthGlassMesSystem",
    "exit":"exit",
    "changePassword":"changePassword",
    "resetPassword": "resetPassword"
    "resetPassword": "resetPassword",
    "home":"Home",
    "role":"role",
    "langRoleManagement": "Role Management",
    "langRoleList": "Role List",
    "langEnterRoleName": "Please enter role name",
    "langAddRole": "Add Role",
    "langName": "Name",
    "langIsValid": "Is Valid",
    "langOperation": "Operation",
    "langPleaseSelect": "Please select",
    "langValid": "Valid",
    "langInvalid": "Invalid",
    "langAddRoleSuccess": "Add role successfully",
    "langEnterName": "Please enter name",
    "langLengthBetween": "Length should be between",
    "langAnd": "and",
    "langCharacters": "characters",
    "langEnterState": "Please enter state",
    "langUpdateState": "Update state successfully",
    "langEditRole": "Edit Role",
    "langEditRoleSuccess": "Edit role successfully",
    "langDeleteRoleConfirm": "Are you sure you want to delete this role?",
    "langPrompt": "Prompt",
    "langDeleteRoleSuccess": "Delete role successfully",
    "langCancelDelete": "Cancelled deleting",
    "langRoleName":"langRoleName",
    "updateSuccessMessage":"updateSuccessMessage",
    "paginationTotal": "Total {total}",
    "paginationSizes": "Items per page",
    "paginationPrev": "Previous",
    "paginationPager": "{currentPage}/{pageCount}",
    "paginationNext": "Next",
    "paginationJumper": "Jump to"
  }
CanadaMes-ui/src/lang/locales/zh-CN.json
@@ -31,11 +31,47 @@
  "langPassword": "密码",
  "langState": "状态",
  "langSelect": "请选择",
  "langCancel": "取消",
  "langConfirm": "确定",
  "langEditUserTitle": "修改用户",
  "northglassMESsystem":"北玻MES系统",
  "exit":"退出",
  "changePassword":"修改密码"
  "changePassword":"修改密码",
  "resetPassword": "重置密码",
  "home":"主页",
  "role":"角色",
    "langRoleManagement": "角色管理",
    "langRoleList": "角色列表",
    "langEnterRoleName": "请输入角色名称",
    "langAddRole": "添加角色",
    "langName": "名称",
    "langIsValid": "是否有效",
    "langOperation": "操作",
    "langPleaseSelect": "请选择",
    "langValid": "有效",
    "langInvalid": "无效",
    "langConfirm": "确定",
    "langCancel": "取消",
    "langAddRoleSuccess": "添加角色成功",
    "langEnterName": "请输入名称",
    "langLengthBetween": "长度在",
    "langAnd": "和",
    "langCharacters": "个字符之间",
    "langEnterState": "请输入状态",
    "langUpdateState": "状态更新成功",
    "langEditRole": "编辑角色",
    "langEditRoleSuccess": "编辑角色成功",
    "langDeleteRoleConfirm": "确定要删除该角色吗?",
    "langPrompt": "提示",
    "langDeleteRoleSuccess": "删除角色成功",
    "langCancelDelete": "已取消删除",
    "langRoleName":"角色名称",
    "updateSuccessMessage":"更新成功",
    "paginationTotal": "共 {total} 条",
    "paginationSizes": "每页显示",
    "paginationPrev": "上一页",
    "paginationPager": "{currentPage}/{pageCount}",
    "paginationNext": "下一页",
    "paginationJumper": "跳至"
  }
  
CanadaMes-ui/src/layout/index.vue
@@ -5,7 +5,7 @@
      <el-aside :width="isCollapse?'70px':'250px'">
        <el-col :gutter="20">
          <el-row :span="4">
            <div class="logo">
            <div class="logo" @click="goToHome">
              <div class="sys-name" v-show="!isCollapse">{{ $t('northglassMESsystem') }}</div>
            </div>
          </el-row>
@@ -14,6 +14,15 @@
                     background-color="#222f3e" text-color="#fff" active-text-color="#ffd04b"
                     :collapse="isCollapse" :unique-opened="true"
                     :collapse-transition="false" :router="true">
                     <el-menu-item index="/" @click="goToHome">
  <template slot="title">
    <!--图标-->
    <i class="el-icon-menu"></i>
    <!--文本-->
    <span>{{ $t('home') }}</span>
  </template>
</el-menu-item>
              <!--一级菜单-->
              <el-submenu :index="item.id.toString()" v-for="item in menuList" :key="item.id">
                <!--一级菜单模板区域-->
@@ -26,7 +35,7 @@
                <!--二级菜单-->
                <el-menu-item :index="'/'+menu.router"
                              v-for="menu in item.menuLists" :key="menu.id"
                              @click="saveNavState('/'+menu.router)">
                              @click="saveNavState('/'+menu.router)"   @select="saveNavState" :default-active="$route.path">
                  <template slot="title">
                    <!--图标-->
                    <i :class="menu.icon"></i>
@@ -34,7 +43,9 @@
                    <span>{{ menu.name }}</span>
                  </template>
                </el-menu-item>
              </el-submenu>
            </el-menu>
          </el-row>
        </el-col>
@@ -43,26 +54,29 @@
    <el-container>
     
      <el-header class="header-container">
        <!-- <div class="tagContainer">
               <tag></tag>
        </div> -->
        <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>
          <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="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png">
              <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>
          </el-submenu>
        </template>
          <template>
  <el-dialog title="修改密码" :visible.sync="dialogVisible" width="30%">
  <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>
@@ -96,13 +110,18 @@
import {changePassword} from '../api/user'
import {removeToken} from "../utils/auth";
import LanguageMixin from '../lang/LanguageMixin'
// import Tag from '../layout/tag.vue';
import { mapState, mapMutations } from 'vuex';
 import Tag from '../layout/tag.vue';
 import store from '../store';
export default {
  name: "Layout",
  store,
  mixins: [LanguageMixin],
  data() {
    return {
      activeTag: '', // 当前激活的标签
      dialogVisible: false,
      formData: {
        oldPassword: '',
@@ -120,9 +139,9 @@
      }
    }
  },
  // components: {
  //   Tag
  // },
   components: {
   Tag
   },
  created() {
    selectList(this.menuListForm).then(res => {
      this.menuList = res.data
@@ -135,12 +154,36 @@
      this.activePath = window.sessionStorage.getItem('activePath')
    });
  },
  computed: {
    ...mapState('tags', ['tags'])
  },
  methods: {
    logout: function () {
      removeToken()
      this.$router.push('/login')
    },
    goToHome() {
    this.$router.push('/home');
  },
   // 使用 mapMutations 辅助函数调用 Store 中的 mutations
   ...mapMutations('tags', ['addTag', 'removeTag']),
    // 切换标签时触发的方法
    saveNavState(activePath) {
      window.sessionStorage.setItem('activePath', activePath);
      const menuItem = this.menuList.find(item => item.menuLists.some(menu => menu.router === activePath));
      if (menuItem) {
        const submenuItem = menuItem.menuLists.find(menu => menu.router === activePath);
        if (submenuItem) {
          const tag = submenuItem.name;
          this.$store.commit('tags/addTag', tag);  // 调用 Vuex Store 中的 addTag mutation
        }
      }
    },
    // 关闭标签时触发的方法
    removeTag(tag) {
      this.removeTag(tag); // 从 Vuex Store 中移除标签
    },
 
    showChangePasswordDialog() {
@@ -173,9 +216,9 @@
    toggleCollapse: function () {
      this.isCollapse = !this.isCollapse;
    },
    saveNavState: function (activePath) {
      window.sessionStorage.setItem('activePath', activePath)
    },
    // saveNavState: function (activePath) {
    //   window.sessionStorage.setItem('activePath', activePath)
    // },
    replaceChineseWithEnglish(menuData) {
      // 定义中英文对照关系对象
      const translation = {
@@ -209,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;
@@ -256,7 +314,7 @@
}
.el-header {
  padding: 0;
  background-color: #576574;
}
</style>
CanadaMes-ui/src/layout/tag.vue
@@ -1,91 +1,59 @@
<template>
    <div class="_tag">
      <el-scrollbar style="margin-right: 6px;">
        <div class="left">
          <el-tag
            v-for="tag in tagsList"
            :key="tag.title"
            :closable="!tag.hideclose"
            :type="isActive(tag)"
            @close="removeTag(tag)"
            @click="handleTagClick(tag)"
          >
            <router-link :to="tag.path" class="tag-title">{{ tag.title }}</router-link>
          </el-tag>
  <div class="tagContainer">
    <div v-for="(tag, index) in tags" :key="index" class="tagItem">
      {{ tag }}
      <span class="closeBtn" @click="removeTag(index)">x</span>
        </div>
      </el-scrollbar>
      <el-dropdown @command="handleCloseBtn" class="_dropdown">
        <el-button type="primary" size="small">
          标签选项
          <i class="el-icon-arrow-down el-icon--right"></i>
        </el-button>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command="closeOther">关闭其它</el-dropdown-item>
          <el-dropdown-item command="closeAll">关闭所有</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </div>
  </template>
  
  <script>
  import { mapState, mapMutations } from "vuex";
import { mapState, mapMutations } from 'vuex';
  
  export default {
    computed: {
      ...mapState("tags", ["tagsList"]),
      activeTag() {
        return this.tagsList.find(tag => tag.path === this.$route.fullPath);
      }
    ...mapState('tags', { // 这里添加了 'tags' 模块的命名空间前缀
      tags: state => state.tags.tags
    })
    },
    methods: {
      ...mapMutations("tags", ["removeTag"]),
      handleCloseBtn(command) {
        if (command === "closeOther") {
          const activeTag = this.activeTag;
          if (!activeTag || activeTag.hideclose) return;
          this.$store.commit("tags/removeOtherTags", activeTag);
        } else if (command === "closeAll") {
          this.$store.commit("tags/removeAllTags");
          this.$router.push({ name: "sadmasMain" });
        }
      },
      isActive(tag) {
        return tag.path === this.$route.fullPath ? "" : "info";
      },
      handleTagClick(tag) {
        this.$router.push(tag.path);
      }
    },
    watch: {
      $route(newValue) {
        const isExist = this.tagsList.some(item => item.path === newValue.fullPath);
        if (!isExist) {
          this.$store.commit("tags/addTag", {
            title: newValue.meta.title || "",
            path: newValue.fullPath,
            hideclose: newValue.meta.hideclose || false
          });
    ...mapMutations('tag', ['removeTag']),
    saveNavState(activePath) {
    window.sessionStorage.setItem('activePath', activePath);
    const menuItem = this.menuList.find(item => item.menuLists.some(menu => menu.router === activePath));
    if (menuItem) {
      const submenuItem = menuItem.menuLists.find(menu => menu.router === activePath);
      if (submenuItem) {
        const tag = submenuItem.name;
        this.addTag(tag); // 添加标签到 Vuex Store
        }
      }
    }
  };
  }
}
  </script>
  
  <style scoped>
  ._tag {
    display: flex;
    align-items: center;
    padding: 10px;
  }
  .left {
.tagContainer {
    display: flex;
    flex-wrap: wrap;
  margin-bottom: 10px;
  }
  
  .tag-title {
.tagItem {
  background-color: #eee;
  border-radius: 4px;
  padding: 4px 8px;
  margin-right: 8px;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
}
.closeBtn {
  margin-left: 4px;
  color: red;
    cursor: pointer;
  }
  </style>
CanadaMes-ui/src/main.js
@@ -8,12 +8,13 @@
import VueI18n from 'vue-i18n'
import zhCN from './lang/locales/zh-CN.json' // 中文语言包
import enUS from './lang/locales/en-US.json' // 英文语言包
import store from './store'
// import store from './store'
Vue.use(VueI18n)
const i18n = new VueI18n({
  locale: 'zh-CN', // 设置默认语言为中文
  locale: 'en-US',
  messages: {
    'zh-CN': zhCN, // 注册中文语言包
    'en-US': enUS // 注册英文语言包
@@ -34,6 +35,7 @@
new Vue({
    router,
    i18n,
    store,
    render: h => h(App)
}).$mount('#app');
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/store/store,js
File was deleted
CanadaMes-ui/src/utils/request.js
@@ -15,10 +15,23 @@
                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>
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>
CanadaMes-ui/src/views/Electrical/Parameter.vue
@@ -2,80 +2,151 @@
  <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>
    <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>
  <div>Parameter</div>
    </el-row>
  <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>
  let socket;
export default {
  name: "Parameter",
  // data () {
  //   return {
  //     sbList: {
  //       records: [],
  //     }
  //   }
  // }
  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; // 如果收到空数据,则直接返回,不执行后续逻辑
  }
  let obj = JSON.parse(msg.data);
  this.record.params[0] = obj.params[0];
  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];
    }
  }
  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));
}
  }
  }
</script>
<style lang="less" scoped>
.el-row {
  margin-bottom: 20px;
  &:last-child {
    margin-bottom: 0;
  }
}
.el-col {
  border-radius: 4px;
  margin: 10px;
  <style>
  .kuai_div {
  width: 30%;
  margin-bottom: 15px;
}
.el-input {
  width: 70px;
  height: 30px;
  border: none;
}
.bg-purple-dark {
  background: #99a9bf;
  .el-input__inner {
  border: 1px solid black;
}
.bg-purple {
  background: #d3dce6;
  .in_mc .el-input__inner {
  border: none;
}
.bg-purple-light {
  background: #e5e9f2;
  #btn_div {
  width: 100%;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
.row-bg {
  padding: 10px 0;
  background-color: #f9fafc;
  #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>
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;
}
.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>
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/alarm.vue
@@ -1,41 +1,42 @@
<template>
  <div class="app">
    <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="/device/iostate" tag="el-button" type="text">IO状态</router-link>
      <router-link to="/device/alarm" tag="el-button" type="text">报警信息</router-link>
      <router-link to="/device/parameter" tag="el-button" type="text">参数下发</router-link>
      <router-link to="/device/control" tag="el-button" type="text">开关控制</router-link>
    </el-breadcrumb>
    <div>报警信息</div>
  <div>
    <p>{{ receivedMessage }}</p>
    <button @click="sendMessage">Send Message</button>
    </div>
  </template>
  
  <script>
  export default {
    name: "alarm",
  name:'alarm',
  data() {
    return {
      websocket: null,
      receivedMessage: ''
    };
  },
  mounted() {
    this.websocket = new WebSocket('ws://localhost:8080');
   
    this.websocket.onopen = () => {
      console.log('WebSocket connection opened');
    };
    this.websocket.onmessage = (event) => {
      this.receivedMessage = event.data;
    };
    this.websocket.onclose = () => {
      console.log('WebSocket connection closed');
    };
  },
  methods: {
    sendMessage() {
      if (this.websocket.readyState === WebSocket.OPEN) {
        this.websocket.send('Hello WebSocket!');
      } else {
        console.log('WebSocket connection is not open');
    }
    }
  }
};
  </script>
  <style lang="less" scoped>
  .el-table {
    margin-top: 15px;
    font-size: 12px;
  }
  .el-pagination {
    margin-top: 15px;
  }
  .app .el-card {
    width: 99%;
  }
  </style>
CanadaMes-ui/src/views/device/talkvue.vue
@@ -1,6 +1,14 @@
<template>
  <!-- <button v-on: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>
CanadaMes-ui/src/views/login/index.vue
@@ -1,6 +1,6 @@
<template>
  <div class="login_container">
    <div class="system_title">{{ $t('systemTitle') }}</div>
    <div class="system_title"  >{{ $t('northglassMESsystem') }}</div>
    <div class="login_box">
      <!--头像区域-->
      <!-- <div class="avatar_box">
@@ -139,7 +139,8 @@
  font-weight: bold;
  text-align: center;
  margin-bottom: 20px;
 top:50px;
  position: relative; top: 100px;
}
.btns {
  display: flex;
CanadaMes-ui/src/views/power/index.vue
@@ -56,7 +56,7 @@
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="queryInfo.pageNum"
          :page-sizes="[10, 20, 30, 40]"
          :page-sizes="[6, 12, 18, 24]"
          :page-size="queryInfo.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="powerList.total">
@@ -157,7 +157,7 @@
    return {
      queryInfo: {
        pageNum: 1,
        pageSize: 10
        pageSize: 6
      },
      powerList: {
        records: [],
CanadaMes-ui/src/views/role/index.vue
@@ -2,30 +2,30 @@
  <div class="app">
    <!--面包屑导航区域-->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>角色管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
      <el-breadcrumb-item :to="{ path: '/home' }">{{$t('langHome')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('langRoleManagement')}}</el-breadcrumb-item>
      <el-breadcrumb-item>{{$t('langRoleList')}}</el-breadcrumb-item>
    </el-breadcrumb>
    <!--卡片视图区域-->
    <el-card class="el-card">
      <el-row :gutter="20">
        <!--搜索与添加区域-->
        <el-col :span="6">
          <el-input placeholder="请输入角色名称" v-model="queryInfo.name" clearable @clear="getRoleList()">
  <el-input :placeholder="$t('langEnterRoleName')" v-model="queryInfo.name" clearable @clear="getRoleList()">
            <el-button slot="append" icon="el-icon-search" @click="getRoleList()"></el-button>
          </el-input>
        </el-col>
        <!--添加区域-->
        <el-col :span="4">
          <el-button type="primary" @click="showAddDialog">添加角色</el-button>
          <el-button type="primary" @click="showAddDialog">{{$t('langAddRole')}}</el-button>
        </el-col>
      </el-row>
      <!--角色列表区域-->
      <el-table :data="roleList.records" border stripe>
        <el-table-column label="#" type="index"></el-table-column>
        <el-table-column label="名称" prop="name"></el-table-column>
        <el-table-column label="创建时间" prop="createTime"></el-table-column>
        <el-table-column label="是否有效">
  <el-table-column :label="$t('langRoleName')" prop="name"></el-table-column>
  <el-table-column :label="$t('langCreateTime')" prop="createTime"></el-table-column>
  <el-table-column :label="$t('langIsValid')">
          <template slot-scope="scope">
            <el-switch :active-value=1
                       :inactive-value=0
@@ -34,17 +34,15 @@
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column label="操作">
        <el-table-column :label="$t('langOperation')">
          <template slot-scope="scope">
            <!--修改-->
            <el-tooltip effect="dark" content="修改" placement="top" :enterable="false">
              <el-button type="primary" icon="el-icon-edit" size="mini"
                         @click="showEditDialog(scope.row)"></el-button>
  <el-tooltip effect="dark" :content="$t('langEdit')" placement="top" :enterable="false">
    <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row)"></el-button>
            </el-tooltip>
            <!--删除-->
            <el-tooltip effect="dark" content="删除" placement="top" :enterable="false">
              <el-button type="danger" icon="el-icon-delete" size="mini"
                         @click="removeById(scope.row)"></el-button>
  <el-tooltip effect="dark" :content="$t('langDelete')" placement="top" :enterable="false">
    <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeById(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
@@ -62,17 +60,17 @@
    </el-card>
    <!--添加角色的对话框-->
    <el-dialog
        title="添加角色"
        :title="$t('langAddRole')"
        :visible.sync="addDialogVisible"
        width="50%"
        @close="addDialogClosed">
      <!--内容主体区域-->
      <el-form :model="addRoleForm" :rules="addRoleRules" ref="addRoleRef" label-width="70px">
        <el-form-item label="名称" prop="name">
      <el-form :model="addRoleForm" :rules="addRoleRules" ref="addRoleRef" label-width="130px">
        <el-form-item :label="$t('langRoleName')" prop="name">
          <el-input v-model="addRoleForm.name"></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="state">
          <el-select v-model="addRoleForm.state" placeholder="请选择">
        <el-form-item :label="$t('langState')" prop="state">
          <el-select v-model="addRoleForm.state" placeholder="$t('langPleaseSelect')">
            <el-option v-for="(item,index) in options"
                       :key="index"
                       :value="item.value"
@@ -82,22 +80,22 @@
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
    <el-button @click="addDialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="addRole">确 定</el-button>
    <el-button @click="addDialogVisible = false">{{$t('langCancel')}}</el-button>
    <el-button type="primary" @click="addRole">{{$t('langConfirm')}}</el-button>
  </span>
    </el-dialog>
    <!--修改角色的对话框-->
    <el-dialog
        title="修改角色"
        :title="$t('langEditRole')"
        :visible.sync="editDialogVisible"
        width="50%">
      <!--内容主体区域-->
      <el-form :model="editRoleForm" :rules="addRoleRules" ref="addRoleRef" label-width="70px">
        <el-form-item label="名称" prop="name">
      <el-form :model="editRoleForm" :rules="addRoleRules" ref="addRoleRef" label-width="130px">
        <el-form-item :label="$t('langRoleName')" prop="name">
          <el-input v-model="editRoleForm.name"></el-input>
        </el-form-item>
        <el-form-item label="状态" prop="state">
          <el-select v-model="editRoleForm.state" placeholder="请选择">
        <el-form-item :label="$t('langState')" prop="state">
          <el-select v-model="editRoleForm.state" placeholder="$t('langPleaseSelect')">
            <el-option v-for="(item,index) in options"
                       :key="index"
                       :value="item.value"
@@ -107,8 +105,8 @@
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
    <el-button @click="editDialogVisible = false">取 消</el-button>
    <el-button type="primary" @click="editRoleInfo">确 定</el-button>
    <el-button @click="editDialogVisible = false">{{$t('langCancel')}}</el-button>
    <el-button type="primary" @click="editRoleInfo">{{$t('langConfirm')}}</el-button>
  </span>
    </el-dialog>
  </div>
@@ -116,9 +114,11 @@
<script>
import {getById, removeById, saveOrUpdate, selectPage} from "../../api/role";
import LanguageMixin from '../../lang/LanguageMixin'
export default {
  name: "Role",
  mixins: [LanguageMixin],
  data() {
    return {
      queryInfo: {
CanadaMes-ui/src/views/user/index.vue
@@ -71,10 +71,14 @@
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="queryInfo.pageNum"
          :page-sizes="[10, 20, 30, 40]"
      :page-sizes="[6, 12, 18, 24]"
          :page-size="queryInfo.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="userList.total">
      :total="userList.total"
      :prev-text="$t('pagination.prev')"
      :next-text="$t('pagination.next')"
      :pager-count="7"
      :layout="layout"
    >
      </el-pagination>
    </el-card>
    <!--添加用户的对话框-->
@@ -131,7 +135,7 @@
        <el-form-item :label="$t('langUsername')" prop="username">
          <el-input v-model="editUserForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="角色" prop="roleId">
        <el-form-item :label="$t('role')" prop="roleId">
          <el-select filterable v-model="editUserForm.roleId" placeholder="请选择">
            <el-option v-for="item in roleList"
                       :key="item.id"
@@ -170,11 +174,13 @@
export default {
  name: "User",
  mixins: [LanguageMixin],
  data() {
    return {
      layout: 'total, sizes, prev, pager, next, jumper',
      queryInfo: {
        pageNum: 1,
        pageSize: 10
        pageSize: 6
      },
      userList: {
        records: [],
@@ -227,6 +233,7 @@
        this.userList.records = res.data.records;
        this.userList.total = res.data.total
      });
//       test().then(res => {
//         console.log(res.data)
//       });
@@ -255,17 +262,31 @@
  this.roleList = res.data;
});
    },
    // stateChange(info) {
    //   saveOrUpdate(info).then(() => {
    //     this.$message.success("更新状态成功")
    //   });
    // },
    stateChange(info) {
      saveOrUpdate(info).then(() => {
        this.$message.success("更新状态成功")
    const successMessage = this.$t('updateSuccessMessage');
    this.$message.success(successMessage);
      });
    },
    resetPassword(info) {
  this.$confirm('确认重置密码为默认值吗?', '重置密码', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      resetPass(info).then(() => {
        this.$message.success("密码已重置为默认值");
        this.$message.success('密码已重置为默认值');
      });
    })
    .catch(() => {
      // 用户取消重置密码操作
    });
  },
    showEditDialog(id) {
      getById({id: id}).then(res => {
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/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_websocket_2_3_2_RELEASE.xml
New file
@@ -0,0 +1,13 @@
<component name="libraryTable">
  <library name="Maven: org.springframework.boot:spring-boot-starter-websocket:2.3.2.RELEASE">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-websocket/2.3.2.RELEASE/spring-boot-starter-websocket-2.3.2.RELEASE.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-websocket/2.3.2.RELEASE/spring-boot-starter-websocket-2.3.2.RELEASE-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/boot/spring-boot-starter-websocket/2.3.2.RELEASE/spring-boot-starter-websocket-2.3.2.RELEASE-sources.jar!/" />
    </SOURCES>
  </library>
</component>
springboot-vue3/.idea/libraries/Maven__org_springframework_spring_messaging_5_2_8_RELEASE.xml
New file
@@ -0,0 +1,13 @@
<component name="libraryTable">
  <library name="Maven: org.springframework:spring-messaging:5.2.8.RELEASE">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-messaging/5.2.8.RELEASE/spring-messaging-5.2.8.RELEASE.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-messaging/5.2.8.RELEASE/spring-messaging-5.2.8.RELEASE-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-messaging/5.2.8.RELEASE/spring-messaging-5.2.8.RELEASE-sources.jar!/" />
    </SOURCES>
  </library>
</component>
springboot-vue3/.idea/libraries/Maven__org_springframework_spring_websocket_5_2_8_RELEASE.xml
New file
@@ -0,0 +1,13 @@
<component name="libraryTable">
  <library name="Maven: org.springframework:spring-websocket:5.2.8.RELEASE">
    <CLASSES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-websocket/5.2.8.RELEASE/spring-websocket-5.2.8.RELEASE.jar!/" />
    </CLASSES>
    <JAVADOC>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-websocket/5.2.8.RELEASE/spring-websocket-5.2.8.RELEASE-javadoc.jar!/" />
    </JAVADOC>
    <SOURCES>
      <root url="jar://$MAVEN_REPOSITORY$/org/springframework/spring-websocket/5.2.8.RELEASE/spring-websocket-5.2.8.RELEASE-sources.jar!/" />
    </SOURCES>
  </library>
</component>
springboot-vue3/pom.xml
@@ -119,6 +119,10 @@
            <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>
springboot-vue3/springboot-vue3.iml
@@ -176,5 +176,9 @@
    <orderEntry type="library" name="Maven: org.apache.xmlgraphics:batik-xml:1.14" level="project" />
    <orderEntry type="library" name="Maven: xml-apis:xml-apis-ext:1.3.04" level="project" />
    <orderEntry type="library" name="Maven: org.apache.xmlgraphics:batik-codec:1.14" level="project" />
    <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;
@@ -25,14 +27,17 @@
public class WebSocketServer {
    
   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)
@@ -16,6 +17,7 @@
       //
       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/controller/UserController.java
@@ -97,7 +97,7 @@
    @ApiOperation(value = "分页查询用户")
    @GetMapping("/selectPage")
    @RequiresRoles({"admin"})
//    @RequiresRoles({"admin"})
    @RequiresPermissions({"user:select"})
    public Result selectPage(UserVo userVO) {
        return Result.success(userService.selectPage(userVO));
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天
     */