报警信息添加工位字段;
报警页面和首页自适应优化;
绑定首页设备控制和设备数据,与后台实时通讯;
15个文件已修改
2个文件已添加
605 ■■■■ 已修改文件
Admin.NET/WCS.Application/Entity/WcsAlarmInfo.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Entity/WcsPlc.cs 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/IPlcHub.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Hub/PlcHub.cs 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/PLC/PLCUtil.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoDto.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoOutput.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Service/WcsPlc/WcsPlcService.cs 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/wcs/wcsAlarmInfo.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/api/wcs/wcsPlc.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/alarmManage/index.vue 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/device/deviceInfo/index.vue 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/wcs/wcsAlarmInfo/component/editDialog.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Web/src/views/wcs/wcsAlarmInfo/index.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Admin.NET/WCS.Application/Entity/WcsAlarmInfo.cs
@@ -21,6 +21,13 @@
    [SugarColumn(ColumnName = "PlcPort", ColumnDescription = "PLCIP地址")]
    public int PlcPort { get; set; }
    
    /// <summary>
    /// 工位号
    /// </summary>
    [Required]
    [SugarColumn(ColumnName = "StationNum", ColumnDescription = "工位号", Length = 4)]
    public string StationNum { get; set; }
    /// <summary>
    /// 报警编号
    /// </summary>
Admin.NET/WCS.Application/Entity/WcsPlc.cs
@@ -1,4 +1,6 @@

using Org.BouncyCastle.Crypto;
namespace WCS.Application;
/// <summary>
@@ -46,4 +48,9 @@
    [SugarColumn(ColumnName = "Text", ColumnDescription = "描述", Length = 100)]
    public string? Text { get; set; }
    
    /// <summary>
    /// 是否连接
    /// </summary>
    [SugarColumn(IsIgnore = true)]
    public bool IsConn { get; set; } = false;
}
Admin.NET/WCS.Application/Hub/IPlcHub.cs
New file
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WCS.Application
{
    public interface IPlcHub
    {
        /// <summary>
        /// 下发PLC连接状态
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        Task PublicPlcConn(WcsPlc context);
        /// <summary>
        /// 下发工位状态
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        //Task PublicStationStatus(List<WcsDevice> context);
    }
}
Admin.NET/WCS.Application/Hub/PlcHub.cs
New file
@@ -0,0 +1,37 @@
using Furion.InstantMessaging;
using Microsoft.AspNetCore.SignalR;
namespace WCS.Application;
/// <summary>
/// 任务日志集线器
/// </summary>
[MapHub("/hubs/Plc")]
public class PlcHub : Hub<IPlcHub>
{
    private readonly IHubContext<PlcHub, IPlcHub> _plcHubContext;
    public PlcHub(IHubContext<PlcHub, IPlcHub> plcHubContext)
    {
        _plcHubContext = plcHubContext;
    }
    /// <summary>
    /// 下发PLC连接状态
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task PublicPlcConn(WcsPlc context)
    {
        await _plcHubContext.Clients.All.PublicPlcConn(context);
    }
    /// <summary>
    /// 下发工位状态
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    //public async Task PublicStationStatus(List<WcsDevice> context)
    //{
    //    await _plcHubContext.Clients.All.PublicStationStatus(context);
    //}
}
Admin.NET/WCS.Application/PLC/PLCTaskAction.cs
@@ -1,4 +1,5 @@
using Furion.Logging;
using Admin.NET.Core.Service;
using Furion.Logging;
using Microsoft.AspNetCore.SignalR;
namespace WCS.Application;
@@ -6,8 +7,14 @@
{
    //服务运行状态
    public static bool boRunningState = false;
    //脱机模式
    public static bool boOffline = false;
    //自刷新
    public static bool boRefresh = false;
    private static readonly ISqlSugarClient _db = SqlSugarSetup.ITenant.GetConnectionScope(SqlSugarConst.MainConfigId);
    private static readonly SysCacheService sysCacheService = App.GetRequiredService<SysCacheService>();
    private static readonly IHubContext<PlcHub, IPlcHub> _plcHubContext;
    private static List<WcsPlc> listPlc;
    private static List<WcsDevice> listPlcDevice;
@@ -34,7 +41,7 @@
        if (listPlcUtil.Count != 0)
        {
            cts.Cancel();
            listPlc = _db.Queryable<WcsPlc>().ToList();
            listPlc = _db.Queryable<WcsPlc>().Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine || s.Type == PLCTypeEnum.BoxConveyorLine).ToList();
            listPlcDevice = _db.Queryable<WcsDevice>().ToList();
            listPlcStation = _db.Queryable<WcsPosition>().ToList();
            //等待几秒钟,把已有线程取消掉再连接
@@ -125,6 +132,59 @@
            }, cts.Token);
        }
    }
    /// <summary>
    /// 连接状态线程
    /// </summary>
    public static void ConnectionStatus()
    {
        Task.Run(() =>
        {
            try
            {
                //取消线程 关闭PLC连接
                if (cts.Token.IsCancellationRequested)
                {
                    foreach (var modPlcUtil in listPlcUtil)
                    {
                        modPlcUtil.Close();
                    }
                    throw new OperationCanceledException();
                }
                //获取每个PLC连接状态
                foreach (var modPlc in listPlc)
                {
                    var modPlcUtil = listPlcUtil.FirstOrDefault(s => s.PlcId == modPlc.Id);
                    if (modPlcUtil == null)
                        modPlc.IsConn = false;
                    else
                        modPlc.IsConn = modPlcUtil.Connected;
                    if (sysCacheService.ExistKey("PLCCONN" + modPlc.Id))
                    {
                        var cachePlc = sysCacheService.Get<WcsPlc>("PLCCONN" + modPlc.Id);
                        if (cachePlc.IsConn != modPlc.IsConn)
                        {
                            //连接状态变更 通知前端
                            _plcHubContext.Clients.All.PublicPlcConn(modPlc);
                        }
                    }
                    sysCacheService.Set("PLCCONN" + modPlc.Id, modPlc);
                }
                Thread.Sleep(3000);
            }
            catch (OperationCanceledException)
            {
                sysCacheService.RemoveByPrefixKey("PLCCONN");
                Console.WriteLine("中止线程");
            }
            catch (Exception ex)
            {
                Log.Error(ex.Message, ex);
            }
        });
    }
    /// <summary>
    /// 停止服务
    /// </summary>
Admin.NET/WCS.Application/PLC/PLCUtil.cs
@@ -21,9 +21,9 @@
        _client = new SiemensClient((SiemensVersion)modPlc.PLCType, modPlc.IP, modPlc.Port);
        _client.Open();
    }
    public bool Connected()
    public bool Connected
    {
        return _client.Connected;
        get { return _client.Connected; }
    }
    public IoTClient.Result Open()
    {
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoDto.cs
@@ -22,6 +22,11 @@
    public int PlcPort { get; set; }
    /// <summary>
    /// 工位号
    /// </summary>
    public string StationNum { get; set; }
    /// <summary>
    /// 报警编号
    /// </summary>
    public string AlarmCode { get; set; }
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoInput.cs
@@ -19,6 +19,11 @@
    /// <summary>
    /// 报警编号
    /// </summary>
    public virtual string StationNum { get; set; }
    /// <summary>
    /// 报警编号
    /// </summary>
    public virtual string AlarmCode { get; set; }
    /// <summary>
@@ -143,6 +148,12 @@
    public override int PlcPort { get; set; }
    /// <summary>
    /// 工位号
    /// </summary>
    [Required(ErrorMessage = "工位号不能为空")]
    public override string StationNum { get; set; }
    /// <summary>
    /// 报警编号
    /// </summary>
    [Required(ErrorMessage = "报警编号不能为空")]
Admin.NET/WCS.Application/Service/WcsAlarmInfo/Dto/WcsAlarmInfoOutput.cs
@@ -21,6 +21,11 @@
    public int PlcPort { get; set; }
    /// <summary>
    /// 工位号
    /// </summary>
    public string StationNum { get; set; }
    /// <summary>
    /// 报警编号
    /// </summary>
    public string AlarmCode { get; set; }
Admin.NET/WCS.Application/Service/WcsAlarmInfo/WcsAlarmInfoService.cs
@@ -102,11 +102,24 @@
    [DisplayName("获取报警信息表列表")]
    public async Task<List<WcsAlarmInfoOutput>> List([FromQuery] PageWcsAlarmInfoInput input)
    {
        return await _wcsAlarmInfoRep.AsQueryable().Select<WcsAlarmInfoOutput>().ToListAsync();
        return await _wcsAlarmInfoRep.AsQueryable()
            //.WhereIF(!input.Status.IsNullOrEmpty(), s => s.Status == input.Status)
            .Select<WcsAlarmInfoOutput>().ToListAsync();
    }
    /// <summary>
    /// 复位报警
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Reset")]
    [DisplayName("复位报警")]
    public async Task Reset()
    {
        throw Oops.Bah("开发中");
    }
}
Admin.NET/WCS.Application/Service/WcsPlc/WcsPlcService.cs
@@ -1,4 +1,6 @@

using Admin.NET.Core.Service;
namespace WCS.Application;
/// <summary>
@@ -8,9 +10,11 @@
public class WcsPlcService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<WcsPlc> _wcsPlcRep;
    public WcsPlcService(SqlSugarRepository<WcsPlc> wcsPlcRep)
    private readonly SysCacheService _sysCacheService;
    public WcsPlcService(SqlSugarRepository<WcsPlc> wcsPlcRep, SysCacheService sysCacheService)
    {
        _wcsPlcRep = wcsPlcRep;
        _sysCacheService = sysCacheService;
    }
    /// <summary>
@@ -105,6 +109,34 @@
        return await _wcsPlcRep.AsQueryable().Select<WcsPlcOutput>().ToListAsync();
    }
    /// <summary>
    /// 获取PLC连接状态和服务状态
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "ListStatus")]
    [DisplayName("获取PLC连接状态")]
    public async Task<dynamic> ListStatus([FromQuery] PageWcsPlcInput input)
    {
        var listPlc = await _wcsPlcRep.AsQueryable()
            .Where(s => s.Type == PLCTypeEnum.StackingMachine || s.Type == PLCTypeEnum.ConveyorLine || s.Type == PLCTypeEnum.BoxConveyorLine)
            .ToListAsync();
        foreach (var modPlc in listPlc)
        {
            if (_sysCacheService.ExistKey("PlcConn" + modPlc.Id))
            {
                var cachePlc = _sysCacheService.Get<WcsPlc>("PlcConn" + modPlc.Id);
                modPlc.IsConn = cachePlc.IsConn;
            }
            else
            {
                modPlc.IsConn = false;
            }
        }
        //服务状态
        var modService = new { PLCTaskAction.boRunningState, PLCTaskAction.boOffline, PLCTaskAction.boRefresh };
        return new { listPlc, modService };
    }
}
Web/src/api/wcs/wcsAlarmInfo.ts
@@ -5,6 +5,8 @@
  UpdateWcsAlarmInfo = '/api/wcsAlarmInfo/update',
  PageWcsAlarmInfo = '/api/wcsAlarmInfo/page',
  DetailWcsAlarmInfo = '/api/wcsAlarmInfo/detail',
  ListWcsAlarmInfo = '/api/wcsAlarmInfo/list',
  ResetWcsAlarmInfo = '/api/wcsAlarmInfo/reset',
}
// 增加报警信息表
@@ -47,4 +49,18 @@
            data: { id },
        });
// 报警信息列表
export const listWcsAlarmInfo = (params?: any) =>
    request({
            url: Api.ListWcsAlarmInfo,
            method: 'get',
            data: params,
        });
// 复位
export const resetWcsAlarmInfo = (params?: any) =>
    request({
            url: Api.ResetWcsAlarmInfo,
            method: 'post',
            data: params,
        });
Web/src/api/wcs/wcsPlc.ts
@@ -5,6 +5,7 @@
  UpdateWcsPlc = '/api/wcsPlc/update',
  PageWcsPlc = '/api/wcsPlc/page',
  DetailWcsPlc = '/api/wcsPlc/detail',
  ListStatus='/api/wcsPlc/ListStatus'
}
// 增加PLC
@@ -48,3 +49,10 @@
        });
// 获取PLC连接状态和服务状态
export const listStatus = () =>
    request({
            url: Api.ListStatus,
            method: 'get'
        });
Web/src/views/device/alarmManage/index.vue
@@ -1,32 +1,28 @@
<template>
    <div class="sys-user-container">
      <splitpanes>
        <pane size="22">
        <el-row>
            <el-col :span="5">
            <el-row style="display: flex;text-align: center;justify-content: center;height: 40px;">
                <el-button type="warning" style="width: 95%;height: 30px;">报警复位</el-button>
                    <el-button type="warning" style="width: 95%;height: 30px;" @click="reset">报警复位</el-button>
            </el-row>
            <el-table :data="tableData" border style="width: 100%" :default-sort = "{prop: 'date', order: 'descending'}">
                <el-table-column prop="variable" label="变量" sortable width="80"></el-table-column>
                <el-table-column prop="desc" label="描述" width="120"></el-table-column>
                <el-table-column prop="address" label="位置" width="80"></el-table-column>
                <el-table-column prop="date" label="时间" sortable width="80"></el-table-column>
                <el-table :data="tableData" border style="width: 100%" v-loading="loading"
                    :default-sort="{ prop: 'date', order: 'descending' }">
                    <el-table-column prop="alarmCode" label="变量" align="center"></el-table-column>
                    <el-table-column prop="alarmName" label="描述" align="center"></el-table-column>
                    <el-table-column prop="stationNum" label="位置" align="center"></el-table-column>
                    <el-table-column prop="alarmTime" label="时间" align="center"></el-table-column>
            </el-table>
        </pane>
        <pane size="78" style="position: relative;background-color: #fff;">
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }">
            </el-col>
            <el-col :span="19">
                <div class="card-page">
                    <el-button type="primary" :plain="isPlain1" @click="floorTogglePlain(1)">一层平面</el-button>
                    <el-button type="primary" :plain="isPlain2" @click="floorTogglePlain(2)">二层平面</el-button>
                    <el-button type="primary" :plain="isPlain3" @click="floorTogglePlain(3)">三层平面</el-button>
                </div>
            </el-card>
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }" class="card-line">
                <div style="margin: 40px; height: 50%;">
                <div class="grid-container-line">
                    <div
                        v-for="cell in cellsDataLine"
                        :key="cell.Id">
                        <div v-if="cell.IsShow === 0"
                            class="grid-item-line">
                        <div v-for="cell in cellsDataLine" :key="cell.Id">
                            <div v-if="cell.IsShow === 0" class="grid-item-line">
                            <div class="grid-item-line-end">
                                {{cell.EndLocat}}
                            </div>
@@ -37,24 +33,17 @@
                        </div>
                    </div>
                </div>
            </el-card>
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }" class="card">
                <div class="grid-container">
                    <div
                        v-for="cell in cellsData"
                        :key="cell.Id">
                        <div
                            v-if="cell.IsShow === 0"
                            :class="['grid-item', { 'active': cell.IsUse === 1 }, { 'active2': cell.IsUse === 2 }]"
                            >
                            <!-- 临时用的code需增加点位字段替换 -->
                        <div v-for="cell in cellsData" :key="cell.Id">
                            <div v-if="cell.IsShow === 0"
                                :class="['grid-item', { 'active': cell.IsUse === 1 }, { 'active2': cell.IsUse === 2 }]">
                            <div>{{ cell.Code }}</div>
                        </div>
                    </div>
                </div>
            </el-card>
        </pane>
      </splitpanes>
                </div>
            </el-col>
        </el-row>
    </div>
  </template>
  
@@ -63,18 +52,23 @@
  import { Splitpanes, Pane } from 'splitpanes';
  import 'splitpanes/dist/splitpanes.css';
  import { Vue2 } from 'vue-demi';
import { listWcsAlarmInfo, resetWcsAlarmInfo } from '/@/api/wcs/wcsAlarmInfo';
  const  tableData= [{
          variable:'MB100.0',
          desc:'报警描述',
          address: '205工位',
          date: '2024-08-29'
        }, {
          variable:'MB102.0',
          desc:'报警描述',
          address: '202工位',
          date: '2024-08-28'
        }];
const loading = ref(false);
const tableData = ref<any>([]);
const handleQuery = async () => {
    loading.value = true;
    var res = await listWcsAlarmInfo({ status: 1 });
    tableData.value = res.data.result;
    loading.value = false;
};
handleQuery();
//复位报警
const reset = async () => {
    await resetWcsAlarmInfo();
    await handleQuery();
}
  //堆垛机数据
  const cellsDataLine=[
@@ -100,7 +94,7 @@
    { Id: 20, Code: '020', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 21, Code: '021', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 22, Code: '022', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 23, Code: '023', LineCode:'05',EndLocat:'',IsShow: 0, IsUse: 0,BoxHeight:300 },
    { Id: 23, Code: '023', LineCode: '05', EndLocat: '', IsShow: 0, IsUse: 0, BoxHeight: 100 },
    { Id: 24, Code: '024', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10},
    { Id: 25, Code: '025', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 26, Code: '026', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
@@ -1913,6 +1907,7 @@
        display: flex;
        align-items: center;
    }
    .card-page{
        width: 100%;
        height: 30px;
@@ -1922,28 +1917,40 @@
        align-items: center;
        text-align: center;
    }
    .card-page>button{
        width: 150px;
        height: 30px;
    }
    .card-line{
        border: none;
        background-color: transparent;
        position:absolute;
        z-index: 99;
    }
    .grid-container-line{
        display: grid;
        grid-template-columns: repeat(51, 25px); /* 每列宽度 */
        grid-template-rows: repeat(1, 310px);  /* 每行高度 */
        gap: 0px; /* Gap between cells */
    grid-template-columns: repeat(51, 1fr);
    /* 自适应列宽 */
    grid-template-rows: 1fr;
    /* 自适应行高 */
    gap: 0;
        margin-top: 25px;
    width: 100%;
    /* 宽度自适应 */
    height: 1fr;
    /* 高度自适应 */
    }
    .grid-item-line{
        text-align: center;
        line-height: 50px; /* Vertical center the content */
        font-size: 12px; /* Adjust font size */
        width: 25px;
    line-height: 50px;
    /* Vertical center the content */
    font-size: 12px;
    /* Adjust font size */
    width: 30px;
        height: 100%;
        color: #fff;
        font-size: 14px;
@@ -1951,6 +1958,7 @@
        display: flex;
        justify-content: center;
    }
    .grid-item-line-end{
        width:80px;
        height: 25px;
@@ -1965,22 +1973,25 @@
        text-align: center;
        color: #fff;
    }
    .grid-item-line-box{
        width: 15px;
        height: 15px;
    width: 20px;
    height: 20px;
        background-color:rgb(97, 250, 145);
        position: absolute;
        display: flex;
        text-align: center;
        justify-content: center;
        align-items: center; /* Added to vertically center the text */
    align-items: center;
    /* Added to vertically center the text */
        text-align: center;
        color: black;
    }
    .grid-item-line-child{
        height: 100%;
    height: 220px;
        width: 3px;
        background-color: #9c9c9c;
    background-color: #000000;
    }
    .card{
@@ -1990,32 +2001,74 @@
        z-index: 90;
        margin-top: 310px;
    }
      .grid-container {
    margin-top: 10px;
        width: 100%;
        display: grid;
        grid-template-columns: repeat(51, 25px); /* 每列宽度 */
        grid-template-rows: repeat(12, 30px);  /* 每行高度 */
        gap: 0px; /* Gap between cells */
    grid-template-columns: repeat(51, 1fr);
    /* 每列宽度 */
    grid-template-rows: repeat(12, 1fr);
    /* 每行高度 */
    gap: 0px;
    /* Gap between cells */
    }
    .grid-item {
        background-color: #9c9c9c;
        border: 1px solid #797777;
        text-align: center;
        line-height: 35px;
        font-size: 12px;
        width: 25px;
        height: 30px;
    line-height: 1.4vw;
    /* 行高 */
    width: 100%;
    /* 自适应宽度 */
    height: 100%;
    /* 自适应高度 */
        color: #fff;
        font-size: 14px;
    font-size: 0.7vw;
    }
.card {
    width: 100%;
    position: absolute;
    border-top: none;
    z-index: 90;
    margin-top: 310px;
}
.grid-container {
    margin-top: 10px;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(51, 1fr);
    /* 每列宽度 */
    grid-template-rows: repeat(12, 1fr);
    /* 每行高度 */
    gap: 0px;
    /* Gap between cells */
}
.grid-item {
    background-color: #9c9c9c;
    border: 1px solid #797777;
    text-align: center;
    line-height: 1.4vw;
    /* 行高 */
    width: 100%;
    /* 自适应宽度 */
    height: 100%;
    /* 自适应高度 */
    color: #fff;
    font-size: 0.6vw;
}
    .active {
        background-color: rgb(57, 141, 251); /* IsUse 为1时背景颜色为蓝色 */
    background-color: rgb(57, 141, 251);
    /* IsUse 为1时背景颜色为蓝色 */
        color: #f5f5f5;
    }
    .active2>div {
        display: none;
    }
  </style>
Web/src/views/device/deviceInfo/index.vue
@@ -1,68 +1,45 @@
<template>
    <div class="sys-user-container">
      <splitpanes>
        <pane size="10">
        <el-row>
            <el-col :span="3">
          <el-collapse v-model="activeName">
            <el-collapse-item title="设备控制" name="1">
              <el-card
                class="box-card"
                shadow="hover">
                <el-switch v-model="value1" active-text="" inactive-text="程序服务"></el-switch>
                        <el-card class="box-card" shadow="hover">
                            <el-switch v-model="state.boRunningState" active-text="" inactive-text="程序服务"></el-switch>
              </el-card>
              <el-card
                class="box-card"
                shadow="hover"
                style="margin-top: 3px;">
                <el-switch v-model="value2" active-text="" inactive-text="脱机模式"></el-switch>
                        <el-card class="box-card" shadow="hover" style="margin-top: 3px;">
                            <el-switch v-model="state.boOffline" active-text="" inactive-text="脱机模式"></el-switch>
              </el-card>
              <el-card
                class="box-card"
                shadow="hover"
                style="margin-top: 3px;">
                <el-switch v-model="value3" active-text="" inactive-text="自刷新"></el-switch>
                        <el-card class="box-card" shadow="hover" style="margin-top: 3px;">
                            <el-switch v-model="state.boRefresh" active-text="" inactive-text="自刷新"></el-switch>
              </el-card>
            </el-collapse-item>
  
            <el-collapse-item title="堆垛机" name="2">
              <div style="overflow-x: auto;white-space: nowrap;height: 380px;">
                <el-card
                  v-for="(stacker, index) in stackers"
                  :key="index"
                  class="box-card"
                  shadow="hover"
                  style="margin-top: 3px;">
                  <el-switch v-model="stacker.value" :inactive-text="`${index + 1}号堆垛机`"></el-switch>
                        <div style="overflow-x: auto;white-space: nowrap;">
                            <el-card v-for="(stacker, index) in stackers" :key="index" class="box-card" shadow="hover">
                                <el-switch v-model="stacker.isConn" :inactive-text="`${stacker.text}`"></el-switch>
                </el-card>
              </div>
            </el-collapse-item>
  
            <el-collapse-item title="输送线" name="3">
              <el-card
                v-for="(conveyor, index) in conveyors"
                :key="index"
                class="box-card"
                shadow="hover"
                style="margin-top: 3px;">
                <el-switch v-model="conveyor.value" :inactive-text="`${index + 1}楼输送线`"></el-switch>
                        <el-card v-for="(conveyor, index) in conveyors" :key="index" class="box-card" shadow="hover">
                            <el-switch v-model="conveyor.isConn" :inactive-text="`${conveyor.text}`"></el-switch>
              </el-card>
            </el-collapse-item>
          </el-collapse>
        </pane>
        <pane size="90" style="position: relative;background-color: #fff;">
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }">
            </el-col>
            <el-col :span="21">
                <div class="card-page">
                    <el-button type="primary" :plain="isPlain1" @click="floorTogglePlain(1)">一层平面</el-button>
                    <el-button type="primary" :plain="isPlain2" @click="floorTogglePlain(2)">二层平面</el-button>
                    <el-button type="primary" :plain="isPlain3" @click="floorTogglePlain(3)">三层平面</el-button>
                </div>
            </el-card>
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }" class="card-line">
                <div style="margin: 40px; height: 50%;">
                <div class="grid-container-line">
                    <div
                        v-for="cell in cellsDataLine"
                        :key="cell.Id">
                        <div v-if="cell.IsShow === 0"
                            class="grid-item-line">
                        <div v-for="cell in cellsDataLine" :key="cell.Id">
                            <div v-if="cell.IsShow === 0" class="grid-item-line">
                            <div class="grid-item-line-end">
                                {{cell.EndLocat}}
                            </div>
@@ -73,61 +50,46 @@
                        </div>
                    </div>
                </div>
            </el-card>
            <el-card shadow="hover" :body-style="{ paddingBottom: '0', padding: '10px' }" class="card">
                <div class="grid-container">
                    <div
                        v-for="cell in cellsData"
                        :key="cell.Id">
                        <div
                            v-if="cell.IsShow === 0"
                            :class="['grid-item', { 'active': cell.IsUse === 1 }, { 'active2': cell.IsUse === 2 }]"
                            >
                            <!-- 临时用的code需增加点位字段替换 -->
                        <div v-for="cell in cellsData" :key="cell.Id">
                            <div v-if="cell.IsShow === 0"
                                :class="['grid-item', { 'active': cell.IsUse === 1 }, { 'active2': cell.IsUse === 2 }]">
                            <div>{{ cell.Code }}</div>
                        </div>
                    </div>
                </div>
            </el-card>
        </pane>
      </splitpanes>
                </div>
            </el-col>
        </el-row>
    </div>
  </template>
  
  <script lang="ts" setup>
  import { ref, reactive } from 'vue';
  import { Splitpanes, Pane } from 'splitpanes';
  import 'splitpanes/dist/splitpanes.css';
  import { Vue2 } from 'vue-demi';
import { listStatus } from '/@/api/wcs/wcsPlc';
const state = ref<any>({});
const stackers = ref<any>({});
const conveyors = ref<any>({});
// 查询状态
const handleQuery = async () => {
    var res = await listStatus();
    state.value = res.data.result.modService;
    stackers.value = res.data.result.listPlc.filter(s => s.type == 0);
    conveyors.value = res.data.result.listPlc.filter(s => s.type == 1 || s.type == 4);
};
handleQuery();
  const activeName = ['1', '2', '3'];
  const value1 = ref(false);
  const value2 = ref(false);
  const value3 = ref(false);
  const stackers = reactive([
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
    { value: false },
  ]);
  const conveyors = reactive([
    { value: false },
    { value: false },
    { value: false },
  ]);
  //堆垛机数据
  const cellsDataLine=[
      { Id: 1, Code: '001', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 2, Code: '002', LineCode:'01',EndLocat:'01010101',IsShow: 0, IsUse: 0,BoxHeight:190 },
    { Id: 2, Code: '002', LineCode: '01', EndLocat: '01010101', IsShow: 0, IsUse: 0, BoxHeight: 10 },
    { Id: 3, Code: '003', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 4, Code: '004', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 5, Code: '005', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
@@ -148,7 +110,7 @@
    { Id: 20, Code: '020', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 21, Code: '021', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 22, Code: '022', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 23, Code: '023', LineCode:'05',EndLocat:'',IsShow: 0, IsUse: 0,BoxHeight:300 },
    { Id: 23, Code: '023', LineCode: '05', EndLocat: '', IsShow: 0, IsUse: 0, BoxHeight: 200 },
    { Id: 24, Code: '024', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10},
    { Id: 25, Code: '025', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
    { Id: 26, Code: '026', LineCode:'',EndLocat:'',IsShow: 1, IsUse: 0,BoxHeight:10 },
@@ -1960,7 +1922,9 @@
        padding: 0;
        display: flex;
        align-items: center;
    margin-top: 3px;
    }
    .card-page{
        width: 100%;
        height: 30px;
@@ -1970,27 +1934,35 @@
        align-items: center;
        text-align: center;
    }
    .card-page>button{
        width: 150px;
        height: 30px;
    }
    .card-line{
        border: none;
        background-color: transparent;
        position:absolute;
        z-index: 99;
    }
    .grid-container-line{
        display: grid;
        grid-template-columns: repeat(51, 30px); /* 每列宽度 */
        grid-template-rows: repeat(1, 310px);  /* 每行高度 */
        gap: 0px; /* Gap between cells */
    grid-template-columns: repeat(51, 1fr); /* 自适应列宽 */
    grid-template-rows: 1fr; /* 自适应行高 */
    gap: 0;
        margin-top: 25px;
    width: 100%; /* 宽度自适应 */
    height: 1fr; /* 高度自适应 */
    }
    .grid-item-line{
        text-align: center;
        line-height: 50px; /* Vertical center the content */
        font-size: 12px; /* Adjust font size */
    line-height: 50px;
    /* Vertical center the content */
    font-size: 12px;
    /* Adjust font size */
        width: 30px;
        height: 100%;
        color: #fff;
@@ -1999,6 +1971,7 @@
        display: flex;
        justify-content: center;
    }
    .grid-item-line-end{
        width:80px;
        height: 25px;
@@ -2013,6 +1986,7 @@
        text-align: center;
        color: #fff;
    }
    .grid-item-line-box{
        width: 20px;
        height: 20px;
@@ -2021,14 +1995,16 @@
        display: flex;
        text-align: center;
        justify-content: center;
        align-items: center; /* Added to vertically center the text */
    align-items: center;
    /* Added to vertically center the text */
        text-align: center;
        color: black;
    }
    .grid-item-line-child{
        height: 100%;
    height: 220px;
        width: 3px;
        background-color: #9c9c9c;
    background-color: #000000;
    }
    .card{
@@ -2038,32 +2014,37 @@
        z-index: 90;
        margin-top: 310px;
    }
      .grid-container {
    margin-top: 10px;
        width: 100%;
        display: grid;
        grid-template-columns: repeat(51, 30px); /* 每列宽度 */
        grid-template-rows: repeat(12, 35px);  /* 每行高度 */
        gap: 0px; /* Gap between cells */
    grid-template-columns: repeat(51, 1fr);
    /* 每列宽度 */
    grid-template-rows: repeat(12, 1fr);
    /* 每行高度 */
    gap: 0px;
    /* Gap between cells */
    }
    .grid-item {
        background-color: #9c9c9c;
        border: 1px solid #797777;
        text-align: center;
        line-height: 35px;
        font-size: 12px;
        width: 30px;
        height: 35px;
    line-height: 1.4vw; /* 行高 */
    width: 100%; /* 自适应宽度 */
    height: 100%; /* 自适应高度 */
        color: #fff;
        font-size: 14px;
    font-size: 0.7vw;
    }
    .active {
        background-color: rgb(57, 141, 251); /* IsUse 为1时背景颜色为蓝色 */
    background-color: rgb(57, 141, 251);
    /* IsUse 为1时背景颜色为蓝色 */
        color: #f5f5f5;
    }
    .active2>div {
        display: none;
    }
  </style>
Web/src/views/wcs/wcsAlarmInfo/component/editDialog.vue
@@ -27,6 +27,13 @@
                        
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="工位号" prop="stationNum">
                            <el-input v-model="ruleForm.stationNum" placeholder="请输入工位号" maxlength="20" show-word-limit clearable />
                        </el-form-item>
                    </el-col>
                    <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                        <el-form-item label="报警编号" prop="alarmCode">
                            <el-input v-model="ruleForm.alarmCode" placeholder="请输入报警编号" maxlength="20" show-word-limit clearable />
                            
@@ -102,6 +109,7 @@
    const rules = ref<FormRules>({
        plcIP: [{required: true, message: '请输入PLCIP地址!', trigger: 'blur',},],
        plcPort: [{required: true, message: '请输入PLCIP地址!', trigger: 'blur',},],
        stationNum: [{required: true, message: '请输入工位号!', trigger: 'blur',},],
        alarmCode: [{required: true, message: '请输入报警编号!', trigger: 'blur',},],
    });
Web/src/views/wcs/wcsAlarmInfo/index.vue
@@ -55,6 +55,7 @@
        <el-table-column type="index" label="序号" width="55" align="center" />
        <el-table-column prop="plcIP" label="PLCIP地址" show-overflow-tooltip="" />
        <el-table-column prop="plcPort" label="PLCIP端口" show-overflow-tooltip="" />
        <el-table-column prop="stationNum" label="工位号" show-overflow-tooltip="" />
        <el-table-column prop="alarmCode" label="报警编号" show-overflow-tooltip="" />
        <el-table-column prop="alarmName" label="报警描述" show-overflow-tooltip="" />
        <el-table-column prop="ledIP" label="显示屏ip地址" show-overflow-tooltip="" />