wuyouming666
2023-09-08 1d9317aaf0364cb10d365166cb7696811e14d1d2
补充删除的文件
5个文件已添加
698 ■■■■■ 已修改文件
CanadaMes-ui/src/layout/index.vue 305 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/layout/tag.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/views/Electrical/Parameter.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/component/PlcParameter.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot-vue3/src/main/java/com/example/springboot/component/Plcaction.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CanadaMes-ui/src/layout/index.vue
New file
@@ -0,0 +1,305 @@
<template>
  <el-container style="flex: 1;">
    <div style="width: 200px;background-color: #222f3e" :style="{width: isCollapse?'70px':'250px'}">
      <el-aside :width="isCollapse?'70px':'250px'">
        <el-col :gutter="20">
          <el-row :span="4">
            <div class="logo" @click="goToHome">
              <div class="sys-name" v-show="!isCollapse">{{ $t('northglassMESsystem') }}</div>
            </div>
          </el-row>
          <el-row :span="20">
            <el-menu :default-active="activePath" class="el-menu-vertical-demo"
                      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">
                <!--一级菜单模板区域-->
                <template slot="title">
                  <!--图标-->
                  <i :class="item.icon"></i>
                  <!--文本-->
                  <span>{{ item.name }}</span>
                </template>
                <!--二级菜单-->
                <el-menu-item :index="'/'+menu.router"
                              v-for="menu in item.menuLists" :key="menu.id"
                              @click="addTag(menu.router)">
                  <template slot="title">
                    <!--图标-->
                    <i :class="menu.icon"></i>
                    <!--文本-->
                    <span>{{ menu.name }}</span>
                  </template>
                </el-menu-item>
              </el-submenu>
            </el-menu>
          </el-row>
        </el-col>
      </el-aside>
    </div>
    <el-container>
      <el-header class="header-container">
        <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" style="height:30px;"></el-button>
          </div>
          <div class="tagContainer" style="display: flex;">
  <tag v-for="(tag, index) in tags" :key="index" :tag="tag" @removeTag="removeTag(index)" @switchTag="switchTag(index)"></tag>
</div>
          <template>
            <el-submenu index="1" class="custom-submenu"  >
              <template slot="title">
                <el-avatar src="../assets/emi.png"   style="width:20px;height:20px;margin-top:30px;background-color: white;"></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-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>
                <el-form-item label="新密码">
                  <el-input v-model="formData.newPassword" type="password" show-password></el-input>
                </el-form-item>
                <el-form-item label="确认新密码">
                  <el-input v-model="formData.confirmPassword" type="password" show-password></el-input>
                </el-form-item>
              </el-form>
              <div slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible = false">取消</el-button>
                <el-button type="primary" @click="savePassword">保存</el-button>
              </div>
            </el-dialog>
          </template>
        </el-menu>
      </el-header>
      <el-main>
        <keep-alive>
          <router-view/>
        </keep-alive>
      </el-main>
    </el-container>
  </el-container>
</template>
<script>
import { selectList } from '../api/menuList'
import { changePassword } from '../api/user'
import { removeToken } from "../utils/auth";
import LanguageMixin from '../lang/LanguageMixin'
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: '',
        newPassword: '',
        confirmPassword: ''
      },
      menuList: [],
      isCollapse: false,
      activePath: '',
      activePath1: '',
      menuListForm: {
        pageSize: 1,
        pageNum: -1
      }
    }
  },
  components: {
    Tag
  },
  created() {
    selectList(this.menuListForm).then(res => {
      this.menuList = res.data
      const language = this.$i18n.locale;
      if (language === 'en-US') {
        this.replaceChineseWithEnglish(this.menuList);
      }
      // 记录上一次激活的菜单
      this.activePath = window.sessionStorage.getItem('activePath')
    });
  },
  computed: {
    ...mapState('tags', ['tags'])
  },
  methods: {
    logout: function () {
      removeToken()
      this.$router.push('/login')
    },
    goToHome() {
      this.$router.push('/home');
    },
    ...mapMutations('tags', ['addTag', 'removeTag', 'switchTag']),
    addTag(router) {
  let submenuItem;
  const menuItem = this.menuList.find(item => item.menuLists.some(menu => menu.router === router));
  if (menuItem) {
    submenuItem = menuItem.menuLists.find(menu => menu.router === router);
  }
  if (submenuItem) {
    const tag = submenuItem.router;
    this.$store.commit('tags/addTag', tag);
  }
},
    removeTag(index) {
      this.$store.commit('tags/removeTag', index); // 从 Vuex Store 中移除标签
    },
    showChangePasswordDialog() {
      this.dialogVisible = true;
    },
    savePassword() {
      const { oldPassword, newPassword, confirmPassword } = this.formData;
      if (newPassword !== confirmPassword) {
        this.$message.error('新密码与确认密码不一致');
        return;
      }
      changePassword({oldPassword, newPassword}).then(res => {
        console.log(res.data);
        this.$message.success('密码修改成功');
        removeToken()
        this.$router.push('/login')
      }).catch(() => {
      });
      this.dialogVisible = false;
    },
    toggleCollapse: function () {
      this.isCollapse = !this.isCollapse;
    },
    replaceChineseWithEnglish(menuData) {
      // 定义中英文对照关系对象
      const translation = {
        '用户管理': 'UserManagement',
        '用户列表': 'UserList',
        '设备管理': 'DeviceManagement',
        '报警信息': 'AlarmInformation',
        '参数下发': 'ParameterSetting',
        '开关控制': 'SwitchControl',
        'I/O状态': 'I/O Status',
        '权限管理': 'PermissionManagement',
        '权限列表': 'PermissionList',
        '角色管理': 'RoleManagement',
        '角色列表': 'RoleList',
        '电气管理': 'Electrical management'
        // 根据实际需求继续添加对照关系
      };
      menuData.forEach(menu => {
        menu.name = translation[menu.name] || menu.name;
        menu.menuLists && menu.menuLists.forEach(subMenu => {
          subMenu.name = translation[subMenu.name] || subMenu.name;
        });
      });
    }
  },
  watch: {
    '$route'(to) {
      // 切换路由时更新激活的标签
      const tag = this.menuList.some(item => item.menuLists.some(menu => '/' + menu.router === to.path));
      if (tag) {
        this.activeTag = tag;
      }
    }
  }
}
</script>
<style scoped lang="less">
.el-menu--horizontal > .el-submenu .el-submenu__title {
  height: 45px !important;
}
.custom-submenu  {
 height: 90px   !important;
}
.header-container {
 height: 30px   !important; /* 设置较小的高度 */
}
.header-left {
 margin-right: auto;
width:30px;
}
.el-aside {
 height: 100vh;
 background-color: #222f3e;
 line-height: 200px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
 width: 200px;
 min-height: 400px;
}
.el-menu-demo {
 display: flex;
 width: 100%;
 height: 100%;
 justify-content: flex-end;
 align-items: center;
}
.el-menu-vertical-demo {
 border: 0;
}
.logo {
 background-color: #222f3e;
 display: flex;
 justify-content: center;
 align-items: center;
 height: 60px;
 .sys-name {
   font-size: 20px;
   color: #ffffff;
   margin-left: 10px;
 }
}
.el-header {
 background-color: #576574;
}
</style>
CanadaMes-ui/src/layout/tag.vue
New file
@@ -0,0 +1,70 @@
<template>
  <keep-alive>
    <div
      class="tag"
      :class="{ active: isActive }"
      @click="switchTag(tag)">
      <span>{{ tag }}</span>
      <i class="el-icon-close" @click.stop="removeTag(tag)"></i>
    </div>
  </keep-alive>
</template>
<script>
export default {
  props: {
    tag: {
      type: String,
      required: true
    },
    activeTag: {
      type: String,
      required: true
    }
  },
  computed: {
    isActive() {
      return this.tag === this.activeTag;
    },
    tagData() {
      return this.$store.getters.getTagData(this.tag);
    }
  },
  methods: {
    removeTag(tag) {
      this.$emit('removeTag', tag);
    },
    switchTag(tag) {
  this.$emit('switchTag', tag);
  this.$router.push('/' + tag); // 切换到指定路由
}
  }
}
</script>
<style scoped>
.tag {
  display: inline-block;
  margin-right: 10px;
  padding: 4px 10px;
  border-radius: 4px;
  background-color: #f0f0f0;
  cursor: pointer;
}
.tag.active {
  background-color: #409eff;
  color: #fff;
}
.tag span {
  margin-right: 5px;
}
.tag i {
  margin-left: 5px;
  font-size: 5px;
  cursor: pointer;
}
</style>
CanadaMes-ui/src/views/Electrical/Parameter.vue
New file
@@ -0,0 +1,174 @@
<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">Electrical</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>
      <router-link to="/Electrical/alarm" tag="el-button" type="text">Alarm</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()" id="xiafa"  :disabled="isButtonDisabled">下发参数</el-button>
      </div>
      <div class="kuai_div" v-for="(item, index) in record.xyData" :key="index">
  <el-input style="width: 280px; border:none;" class="in_mc" v-model="item.name" readonly></el-input>
  <span style="margin-right: 5px; width: 50px;">{{ item.value }}</span>
  <span style="margin-right: 5px; font-size: 14px;">|</span>
  <input v-model="item.value2" type="number" style="width: 30px; margin-right: 5px; margin-top: 5px; font-size: 16px;">
</div>
    </el-form>
  </div>
</template>
<script>
let socket;
export default {
  name: "Parameter",
  data() {
    return {
      record: {
        params: [100, 200, 10, 10, 10, 10],
        xyData: [
          { name: "conveyor Velocity(Auto FAST)", value: 0, value2: 0 },
          { name: "conveyor Velocity(Auto SLOW)", value: 0, value2: 0 },
          { name: "conveyor Velocity(Manual)", value: 0 ,value2: 0 },
          { name: "A01 A02 TURN JOG Velocity", value: 0, value2: 0 },
          { name: "A01 A02 TRAVEL JOG Velocity", value: 0, value2: 0 },
          { name: "B01 B02 TRAVEL JOG Velocity", value: 0, value2: 0 },
          { name: "A01 A02 TURN POS Velocity AUTO", value: 0, value2: 0 },
          { name: "A01 A02 TURN POS Velocity manual", value: 0, value2: 0 },
          { name: "A01 A02 TRAVEL POS Velocity AUTO", value: 0, value2: 0 },
          { name: "A01 A02 TRAVEL POS Velocity manual", value: 0, value2: 0 },
          { name: "B01 B02 TRAVEL POS Velocity AUTO", value: 0, value2: 0 },
          { name: "B01 B02 TRAVEL POS Velocity manual", value: 0, value2: 0 }
        ],
        canshu: []
      },
      messagepack: {
        data: { taskname: "" }
      },
      queryInfo: {
        data: "1",
        pageSize: 10
      }
    };
  },
  created() {
    this.initWebSocket();
    this.isButtonDisabled = true;
  },
  methods: {
    initWebSocket() {
      let viewname = "Parameter";
      if (typeof WebSocket === "undefined") {
        console.log("您的浏览器不支持WebSocket");
      } else {
        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];
  this.record.state = obj.state[0];
  let isButtonDisabled = this.record.state.includes(1);
  // 判断state中是否存在1
  console.log(isButtonDisabled)
  this.isButtonDisabled = isButtonDisabled; // 将判断结果保存到变量isButtonDisabled中
  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.value2)); // 转换为整数数组
      console.log(this.messagepack);
      socket?.send(JSON.stringify(this.messagepack));
    },
    handleChange(index, value) {
      this.record.xyData[index].value = value;
    }
  }
};
</script>
<style>
.kuai_div {
  width: calc(100% / 3);
  margin-bottom: 15px;
}
.el-input__inner {
  border: 1px solid black;
}
.in_mc{
  border:none;
}
#btn_div {
  width: 100%;
}
#btn_div .el-button {
  float: right;
}
input[type="number"]::-webkit-inner-spin-button,
  input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
  input[type="number"] {
    -moz-appearance: textfield; /* Firefox中禁用上下箭头 */
  }
</style>
springboot-vue3/src/main/java/com/example/springboot/component/PlcParameter.java
New file
@@ -0,0 +1,63 @@
package com.example.springboot.component;
import cn.hutool.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class PlcParameter extends Thread {
    @Override
    public void run() {
        while (this != null) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            List<Short> paramlist = S7control.getinstance().ReadWord("DB100.DBW", 12);
            List<Short> state = S7control.getinstance().ReadWord("DB103.DBW0", 10);
            JSONObject jsonObject = new JSONObject();
            jsonObject.append("params", new short[]{1111,121, 3232, 0, 1, 0, 1, 0, 1, 0, 1, 0});
            jsonObject.append("state", new short[]{0, 1, 0, 0, 0, 0, 0,0, 0, 0});
            WebSocketServer sendwServer = WebSocketServer.sessionMap.get("Parameter");
            if (sendwServer != null) {
                sendwServer.sendMessage(jsonObject.toString());
            }
            WebSocketServer webSocketServer = WebSocketServer.sessionMap.get("Parameter");
            if (webSocketServer != null) {
                List<String> messages = webSocketServer.getMessages();
                String addressList = "DB100.DBW0";
                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);
                    System.out.println("addressList:" + addressList);
                    // 清空消息列表
                    webSocketServer.clearMessages();
                }
            }
        }
    }
}
springboot-vue3/src/main/java/com/example/springboot/component/Plcaction.java
New file
@@ -0,0 +1,86 @@
package com.example.springboot.component;
import cn.hutool.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Plcaction extends Thread {
  @Override
  public void run() {
    while (this != null) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
//      List<Boolean> paramlist = S7control.getinstance().ReadBits("DB100.DBW", 12);
////
//      JSONObject jsonObject = new JSONObject();
//      jsonObject.append("params", new short[]{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0});
//      List<Boolean> paramlist = S7control.getinstance().ReadBits("DB100.DBW", 12);
      Boolean[] values = {false, true,false, true,false, true,false, true,false, true,false, true,false, true,false, true,false, true,false, true,false, true};
      List<Boolean> paramlist = new ArrayList<>(Arrays.asList(values));
      if (paramlist == null) {
      } else {
        short[] params = new short[paramlist.size()];
        for (int i = 0; i < paramlist.size(); i++) {
          boolean value = paramlist.get(i);
          params[i] = value ? (short) 1 : (short) 0;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.append("params", params);
        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();
          String addressList = "DB100.DBW0";
          if (!messages.isEmpty()) {
            // 将最后一个消息转换为整数类型的列表
            String lastMessage = messages.get(messages.size() - 1);
            System.out.println("messages:" + messages);
            String[] parts = lastMessage.split(",");
            List<Integer> messageValues = new ArrayList<>();
            for (String part : parts) {
              try {
                // 使用正则表达式清除非数字字符
                String cleanedPart = part.replaceAll("[^0-9-]", "");
                Integer value = Integer.parseInt(cleanedPart.trim());
                messageValues.add(value);
              } catch (NumberFormatException e) {
                // 如果无法解析为整数类型,则忽略该部分
                e.printStackTrace();
              }
            }
            // 将消息值转换为布尔列表
            List<Boolean> messageBooleans = new ArrayList<>();
            for (Integer value : messageValues) {
              messageBooleans.add(value == 0 ? true : false);
            }
            // 将布尔列表写入 PLC
            S7control.getinstance().WriteBit(addressList, messageBooleans);
            System.out.println("messageValues:" + messageBooleans);
            System.out.println("addressList:" + addressList);
          // 清空消息列表
          webSocketServer.clearMessages();
        }
      }
    }
  }
}