#
Junjie
10 天以前 581df60e3254d0e58a47f8266862e74d1c472368
#
3个文件已修改
742 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/OpenController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/index.html 695 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -40,6 +40,10 @@
    @Value("${mainProcessPlugin}")
    private String mainProcessPlugin;
    @Value("${app.version:1.0.0}")
    private String appVersion;
    @Value("${app.version-type:stable}")
    private String appVersionType;
    @Autowired
    private CommonService commonService;
    @Autowired
@@ -51,7 +55,7 @@
    @Autowired
    private DeviceConfigService deviceConfigService;
    //移库任务
    // 移库任务
    @PostMapping("/createLocMoveTask")
    @OpenApiLog(memo = "移库任务")
    public R createLocMoveTask(@RequestBody CreateLocMoveTaskParam param) {
@@ -65,7 +69,7 @@
        return R.error("生成移库任务失败");
    }
    //入库任务
    // 入库任务
    @PostMapping("/createInTask")
    @OpenApiLog(memo = "入库任务")
    public R createInTask(@RequestBody CreateInTaskParam param) {
@@ -79,7 +83,7 @@
        return R.error("生成入库任务失败");
    }
    //出库任务
    // 出库任务
    @PostMapping("/createOutTask")
    @OpenApiLog(memo = "出库任务")
    public R createOutTask(@RequestBody CreateOutTaskParam param) {
@@ -93,7 +97,7 @@
        return R.error("生成出库任务失败");
    }
    //批量出库任务
    // 批量出库任务
    @PostMapping("/createOutTaskBatch")
    @OpenApiLog(memo = "批量出库任务")
    @Transactional
@@ -143,10 +147,10 @@
    }
    @RequestMapping("/deviceStatus")
//    @OpenApiLog(memo = "获取设备状态")
    // @OpenApiLog(memo = "获取设备状态")
    public R getDeviceStatus() {
        HashMap<String, Object> map = new HashMap<>();
        //获取堆垛机数据
        // 获取堆垛机数据
        ArrayList<CrnProtocol> crnProtocols = new ArrayList<>();
        List<DeviceConfig> crnList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                .eq("device_type", String.valueOf(SlaveType.Crn)));
@@ -163,7 +167,7 @@
            crnProtocols.add(crnProtocol);
        }
        //获取RGV数据
        // 获取RGV数据
        ArrayList<RgvProtocol> rgvProtocols = new ArrayList<>();
        List<DeviceConfig> rgvList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
                .eq("device_type", String.valueOf(SlaveType.Rgv)));
@@ -240,13 +244,13 @@
    @OpenApiLog(memo = "查询任务")
    public R queryTask(@RequestBody QueryTaskParam param) {
        EntityWrapper<WrkMast> wrapper = new EntityWrapper<>();
        if(param.getTaskNo() != null) {
        if (param.getTaskNo() != null) {
            wrapper.eq("wms_wrk_no", param.getTaskNo());
        }
        if(param.getTaskType() != null) {
        if (param.getTaskType() != null) {
            WrkIoType ioType = WrkIoType.get(param.getTaskType());
            if(ioType == null) {
            if (ioType == null) {
                return R.error("任务类型不存在");
            }
            wrapper.eq("io_type", ioType.id);
@@ -260,15 +264,23 @@
        return R.ok();
    }
    @GetMapping("/getSystemVersion")
    public R getSystemVersion() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("version", appVersion);
        map.put("versionType", appVersionType);
        return R.ok().add(map);
    }
    @GetMapping("/getFakeSystemRunStatus")
    public R getFakeSystemRunStatus() {
        HashMap<String, Object> map = new HashMap<>();
        if(mainProcessPlugin.contains("Fake")) {
        if (mainProcessPlugin.contains("Fake")) {
            map.put("running", false);
            map.put("isFake", true);
            Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
            if(config != null) {
                if(config.getValue().equals("Y")) {
            if (config != null) {
                if (config.getValue().equals("Y")) {
                    map.put("running", true);
                }
            }
@@ -282,7 +294,7 @@
    @OpenApiLog(memo = "启动仿真模拟")
    public R startFakeSystem() {
        Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
        if(config != null) {
        if (config != null) {
            config.setValue("Y");
            configService.updateById(config);
        }
@@ -293,7 +305,7 @@
    @OpenApiLog(memo = "停止仿真模拟")
    public R stopFakeSystem() {
        Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
        if(config != null) {
        if (config != null) {
            config.setValue("N");
            configService.updateById(config);
        }
src/main/resources/application.yml
@@ -1,3 +1,8 @@
# 系统版本信息
app:
  version: 1.0.0
  version-type: dev  # stable 或 dev
server:
  port: 9090
  servlet:
src/main/webapp/views/index.html
@@ -1,11 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>浙江中扬 - 自动化立体仓库 - WCS</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="../static/layui/css/layui.css" media="all">
  <link rel="stylesheet" href="../static/css/admin.css?v=318" media="all">
  <link rel="stylesheet" href="../static/css/loader.css" media="all">
@@ -13,6 +15,7 @@
    .layui-logo img {
      width: 25px;
    }
    .layui-logo cite {
      font-size: 18px;
      font-weight: 400;
@@ -21,35 +24,49 @@
    /* 弹窗样式 */
    .popup {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0,0,0,0.5);
        display: none;
        justify-content: center;
        align-items: center;
        z-index: 9999;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      display: none;
      justify-content: center;
      align-items: center;
      z-index: 9999;
    }
    .popup-content {
        background-color: #fff;
        padding: 20px;
        border-radius: 5px;
        box-shadow: 0px 0px 20px rgba(0,0,0,0.3);
        text-align: center;
      background-color: #fff;
      padding: 20px;
      border-radius: 5px;
      box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.3);
      text-align: center;
    }
    /* AI助手抽屉动画 */
    @keyframes slideInRight {
      from { transform: translate3d(100%, 0, 0); opacity: 0; }
      to { transform: translate3d(0, 0, 0); opacity: 1; }
      from {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
      to {
        transform: translate3d(0, 0, 0);
        opacity: 1;
      }
    }
    @keyframes slideOutRight {
      from { transform: translate3d(0, 0, 0); opacity: 1; }
      to { transform: translate3d(100%, 0, 0); opacity: 0; }
      from {
        transform: translate3d(0, 0, 0);
        opacity: 1;
      }
      to {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
    }
    .ai-drawer-layer {
@@ -64,355 +81,388 @@
    }
  </style>
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
  <!-- 头部 -->
  <div class="layui-header">
    <div class="layui-logo">
      <img src="../static/images/zy-logo-dark.png" style="display: inline-block; width: 60%;height: auto">
      <!--          <span style="margin-top: 0; letter-spacing: 10px">中扬立库</span>-->
      <!--          <img src="../static/image/logo.svg"/>-->
      <!--          <cite>中扬 - Zoneyung</cite>-->
    </div>
  <div class="layui-layout layui-layout-admin">
    <!-- 头部 -->
    <div class="layui-header">
      <div class="layui-logo">
        <img src="../static/images/zy-logo-dark.png" style="display: inline-block; width: 60%;height: auto">
        <!--          <span style="margin-top: 0; letter-spacing: 10px">中扬立库</span>-->
        <!--          <img src="../static/image/logo.svg"/>-->
        <!--          <cite>中扬 - Zoneyung</cite>-->
      </div>
    <ul class="layui-nav layui-layout-left">
      <li class="layui-nav-item" lay-unselect>
        <a ew-event="flexible" title="侧边伸缩"><i class="layui-icon layui-icon-shrink-right"></i></a>
      </li>
      <li class="layui-nav-item" lay-unselect>
        <a ew-event="refresh" title="刷新"><i class="layui-icon layui-icon-refresh-3"></i></a>
      </li>
    </ul>
    <ul class="layui-nav layui-layout-right">
<!--      <li class="layui-nav-item" lay-unselect>-->
<!--        <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a>-->
<!--      </li>-->
      <li class="layui-nav-item" lay-unselect id="fakeShow" style="display: none;user-select: none;margin-right: 10px;">
        <div style="color: red;" id="fakeShowText">仿真模拟运行中</div>
      </li>
      <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;">
        <div style="color: red;">临时许可证有效期:<span id="licenseDays">29</span>天</div>
      </li>
      <li class="layui-nav-item layui-hide-xs" lay-unselect>
        <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a>
      </li>
      <li class="layui-nav-item" lay-unselect>
        <a>
          <cite id="username" style="margin-right: 5px">管理员</cite>
        </a>
        <dl class="layui-nav-child">
          <dd lay-unselect><a ew-href="detail.html?resourceId=8">基本资料</a></dd>
          <hr>
          <dd lay-unselect><a id="logout">退出</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item" lay-unselect>
        <a ew-event="theme" title="主题"><i class="layui-icon layui-icon-more-vertical"></i></a>
      </li>
    </ul>
  </div>
  <!-- 侧边栏 -->
  <div class="layui-side">
    <div class="layui-side-scroll">
      <ul id="menu-main" class="layui-nav layui-nav-tree arrow2" lay-filter="admin-side-nav" lay-shrink="_all">
      <ul class="layui-nav layui-layout-left">
        <li class="layui-nav-item" lay-unselect>
          <a ew-event="flexible" title="侧边伸缩"><i class="layui-icon layui-icon-shrink-right"></i></a>
        </li>
        <li class="layui-nav-item" lay-unselect>
          <a ew-event="refresh" title="刷新"><i class="layui-icon layui-icon-refresh-3"></i></a>
        </li>
      </ul>
      <ul class="layui-nav layui-layout-right">
        <!--      <li class="layui-nav-item" lay-unselect>-->
        <!--        <a ew-event="note" title="便签"><i class="layui-icon layui-icon-note"></i></a>-->
        <!--      </li>-->
        <li class="layui-nav-item" lay-unselect id="fakeShow"
          style="display: none;user-select: none;margin-right: 10px;">
          <div style="color: red;" id="fakeShowText">仿真模拟运行中</div>
        </li>
        <li class="layui-nav-item" lay-unselect id="licenseShow" style="display: none;user-select: none;">
          <div style="color: red;">临时许可证有效期:<span id="licenseDays">29</span>天</div>
        </li>
        <li class="layui-nav-item layui-hide-xs" lay-unselect>
          <a ew-event="fullScreen" title="全屏"><i class="layui-icon layui-icon-screen-full"></i></a>
        </li>
        <li class="layui-nav-item" lay-unselect>
          <a>
            <cite id="username" style="margin-right: 5px">管理员</cite>
          </a>
          <dl class="layui-nav-child">
            <dd lay-unselect><a ew-href="detail.html?resourceId=8">基本资料</a></dd>
            <hr>
            <dd lay-unselect><a id="logout">退出</a></dd>
          </dl>
        </li>
        <li class="layui-nav-item" lay-unselect>
          <a ew-event="theme" title="主题"><i class="layui-icon layui-icon-more-vertical"></i></a>
        </li>
      </ul>
    </div>
  </div>
  <!-- 主体部分 -->
  <div class="layui-body"></div>
  <!-- 底部 -->
  <div class="layui-footer layui-text">
    copyright © 2026 浙江中扬立库技术有限公司 all rights reserved.
    <span class="pull-right">Version 1.0.0</span>
  </div>
</div>
<!--初始化加载层-->
<div class="layuimini-loader">
  <div class="layuimini-loader-inner"></div>
</div>
<!-- 弹窗内容 -->
<div class="popup" id="popup">
    <div class="popup-content">
        <h2 style="font-size: 28px;margin-bottom: 10px;">许可证即将过期</h2>
        <div id="popup-text" style="font-size: 28px;color: red"></div>
        <button style="background-color: #007bff;color: #fff;border: none;padding: 10px 20px;border-radius: 5px;cursor: pointer;font-size: 16px;" onclick="hidePopup()">关闭</button>
    <!-- 侧边栏 -->
    <div class="layui-side">
      <div class="layui-side-scroll">
        <ul id="menu-main" class="layui-nav layui-nav-tree arrow2" lay-filter="admin-side-nav" lay-shrink="_all">
        </ul>
      </div>
    </div>
</div>
<!-- 右下角SVG动画 -->
<div id="ai-assistant-btn" style="position: fixed; bottom: 40px; right: 20px; z-index: 9999; cursor: pointer;">
</div>
    <!-- 主体部分 -->
    <div class="layui-body"></div>
    <!-- 底部 -->
    <div class="layui-footer layui-text">
      copyright © 2026 浙江中扬立库技术有限公司 all rights reserved.
      <span class="pull-right" id="system-version">Version loading...</span>
    </div>
<script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../static/layui/layui.js"></script>
<script type="text/javascript" src="../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../static/js/common.js"></script>
<script>
  console.log('%c 中扬立库平台 %c 1.0.0','background-color:rgb(53,73,94);color: #fff;border-radius:2px 0 0 2px;padding:2px 4px;','background-color:rgb(25,190,107);color: #fff;border-radius:0 2px 2px 0;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;');
  $(function () {
    // 注入AI助手图标
    $('#ai-assistant-btn').html(getAiIconHtml(60, 60));
  </div>
    if ("" === localStorage.getItem('token')) {
      top.location.href = baseUrl + "/login";
    }
  });
  <!--初始化加载层-->
  <div class="layuimini-loader">
    <div class="layuimini-loader-inner"></div>
  </div>
  // 显示弹窗
  function showPopup(res) {
      document.getElementById('popup').style.display = 'block';
      // 获取弹出窗口内容的容器元素
      var popupText = document.getElementById('popup-text');
      // 假设后台返回的字符串为 responseString
      if (res!==""){
          // 获取当前日期
          const currentDate = new Date();
          // 创建新日期对象并添加天数
          const newDate = new Date();
          newDate.setDate(currentDate.getDate() + res + 1);
          // 将字符串设置为弹窗内容的文本
          popupText.textContent = "许可证将于" + new Intl.DateTimeFormat('zh-CN').format(newDate) + "过期,剩余有效期:" + res + "天!";
      }else {
          document.getElementById('popup').style.display = 'none';
      }
  }
  <!-- 弹窗内容 -->
  <div class="popup" id="popup">
    <div class="popup-content">
      <h2 style="font-size: 28px;margin-bottom: 10px;">许可证即将过期</h2>
      <div id="popup-text" style="font-size: 28px;color: red"></div>
      <button
        style="background-color: #007bff;color: #fff;border: none;padding: 10px 20px;border-radius: 5px;cursor: pointer;font-size: 16px;"
        onclick="hidePopup()">关闭</button>
    </div>
  </div>
  // 隐藏弹窗
  function hidePopup() {
      document.getElementById('popup').style.display = 'none';
  }
  <!-- 右下角SVG动画 -->
  <div id="ai-assistant-btn" style="position: fixed; bottom: 40px; right: 20px; z-index: 9999; cursor: pointer;">
  </div>
  layui.config({
    base: baseUrl + "/static/layui/lay/modules/"
  }).extend({
    notice: 'notice/notice',
  }).use(['index', 'element', 'layer', 'admin', 'notice'], function () {
    var $ = layui.jquery;
    var index = layui.index;
    var element = layui.element;
    var layer = layui.layer;
    var admin = layui.admin;
    var notice = layui.notice;
  <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script>
  <script type="text/javascript" src="../static/layui/layui.js"></script>
  <script type="text/javascript" src="../static/js/handlebars/handlebars-v4.5.3.js"></script>
  <script type="text/javascript" src="../static/js/common.js"></script>
  <script>
    // 版本信息变量
    var systemVersion = '...';
    var systemVersionType = '';
    var easywebIframeMsg = localStorage.getItem("easyweb-iframe");
    if (!isEmpty(easywebIframeMsg)) {
      var easywebIframeObj = JSON.parse(easywebIframeMsg);
      if (easywebIframeObj.defaultTheme === undefined) {
        admin.changeTheme("theme-colorful");
      }
    }
    let fakeRunning = false
    let fakeStatusInterval = null
    function checkFakeStatus() {
    // 加载系统版本信息
    function loadSystemVersion() {
      $.ajax({
        url: baseUrl + "/openapi/getFakeSystemRunStatus",
        headers: {'token': localStorage.getItem('token')},
        url: baseUrl + "/openapi/getSystemVersion",
        headers: { 'token': localStorage.getItem('token') },
        method: 'GET',
        success: function (res) {
          if (res.code === 200) {
            if(res.data.isFake) {
              $("#fakeShow").show()
              let running = res.data.running
              if (running) {
                $("#fakeShowText").text("仿真模拟运行中")
              } else {
                $("#fakeShowText").text("仿真模拟未运行")
              }
              fakeRunning = running
              if (!fakeStatusInterval) {
                fakeStatusInterval = setInterval(checkFakeStatus, 1000);
              }
            }else {
              $("#fakeShow").hide()
              if (fakeStatusInterval) {
                clearInterval(fakeStatusInterval);
                fakeStatusInterval = null;
              }
            }
          }else {
            top.location.href = baseUrl + "/login";
            systemVersion = res.data.version;
            systemVersionType = res.data.versionType;
            var versionTypeLabel = systemVersionType === 'stable' ? '' : ' (' + systemVersionType + ')';
            var versionTypeColor = systemVersionType === 'stable' ? 'rgb(25,190,107)' : 'rgb(245,166,35)';
            // 更新页脚版本显示
            $('#system-version').html('Version ' + systemVersion + '<span style="margin-left:5px;padding:1px 6px;font-size:12px;border-radius:3px;background-color:' + versionTypeColor + ';color:#fff;">' + systemVersionType + '</span>');
            // 控制台输出版本信息
            console.log('%c 中扬立库平台 %c ' + systemVersion + ' %c ' + systemVersionType + ' ', 'background-color:rgb(53,73,94);color: #fff;border-radius:2px 0 0 2px;padding:2px 4px;', 'background-color:rgb(25,190,107);color: #fff;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;', 'background-color:' + versionTypeColor + ';color: #fff;border-radius:0 2px 2px 0;padding:2px 4px;font: 9pt "Apercu Regular", Georgia, "Times New Roman", Times, serif;');
          }
        }
      });
    }
    checkFakeStatus();
    $("#fakeShow").on("click", function () {
      if (fakeRunning) {
        layer.confirm('确定要停止仿真模拟吗?', function (index) {
          layer.close(index);
          $.ajax({
            url: baseUrl + "/openapi/stopFakeSystem",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
              if (res.code === 200) {
                layer.msg("仿真模拟已停止", {icon: 1});
                $("#fakeShowText").text("仿真模拟未运行")
              } else {
                layer.msg(res.msg, {icon: 2});
              }
            }
          });
        });
    $(function () {
      // 注入AI助手图标
      $('#ai-assistant-btn').html(getAiIconHtml(60, 60));
      if ("" === localStorage.getItem('token')) {
        top.location.href = baseUrl + "/login";
      }
      // 加载版本信息
      loadSystemVersion();
    });
    // 显示弹窗
    function showPopup(res) {
      document.getElementById('popup').style.display = 'block';
      // 获取弹出窗口内容的容器元素
      var popupText = document.getElementById('popup-text');
      // 假设后台返回的字符串为 responseString
      if (res !== "") {
        // 获取当前日期
        const currentDate = new Date();
        // 创建新日期对象并添加天数
        const newDate = new Date();
        newDate.setDate(currentDate.getDate() + res + 1);
        // 将字符串设置为弹窗内容的文本
        popupText.textContent = "许可证将于" + new Intl.DateTimeFormat('zh-CN').format(newDate) + "过期,剩余有效期:" + res + "天!";
      } else {
        layer.confirm('确定要启动仿真模拟吗?', function (index) {
          layer.close(index);
          $.ajax({
            url: baseUrl + "/openapi/startFakeSystem",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            success: function (res) {
              if (res.code === 200) {
                layer.msg("仿真模拟已启动", {icon: 1});
                $("#fakeShowText").text("仿真模拟运行中")
        document.getElementById('popup').style.display = 'none';
      }
    }
    // 隐藏弹窗
    function hidePopup() {
      document.getElementById('popup').style.display = 'none';
    }
    layui.config({
      base: baseUrl + "/static/layui/lay/modules/"
    }).extend({
      notice: 'notice/notice',
    }).use(['index', 'element', 'layer', 'admin', 'notice'], function () {
      var $ = layui.jquery;
      var index = layui.index;
      var element = layui.element;
      var layer = layui.layer;
      var admin = layui.admin;
      var notice = layui.notice;
      var easywebIframeMsg = localStorage.getItem("easyweb-iframe");
      if (!isEmpty(easywebIframeMsg)) {
        var easywebIframeObj = JSON.parse(easywebIframeMsg);
        if (easywebIframeObj.defaultTheme === undefined) {
          admin.changeTheme("theme-colorful");
        }
      }
      let fakeRunning = false
      let fakeStatusInterval = null
      function checkFakeStatus() {
        $.ajax({
          url: baseUrl + "/openapi/getFakeSystemRunStatus",
          headers: { 'token': localStorage.getItem('token') },
          method: 'GET',
          success: function (res) {
            if (res.code === 200) {
              if (res.data.isFake) {
                $("#fakeShow").show()
                let running = res.data.running
                if (running) {
                  $("#fakeShowText").text("仿真模拟运行中")
                } else {
                  $("#fakeShowText").text("仿真模拟未运行")
                }
                fakeRunning = running
                if (!fakeStatusInterval) {
                  fakeStatusInterval = setInterval(checkFakeStatus, 1000);
                }
              } else {
                layer.msg(res.msg, {icon: 2});
                $("#fakeShow").hide()
                if (fakeStatusInterval) {
                  clearInterval(fakeStatusInterval);
                  fakeStatusInterval = null;
                }
              }
            } else {
              top.location.href = baseUrl + "/login";
            }
          }
        });
      }
      checkFakeStatus();
      $("#fakeShow").on("click", function () {
        if (fakeRunning) {
          layer.confirm('确定要停止仿真模拟吗?', function (index) {
            layer.close(index);
            $.ajax({
              url: baseUrl + "/openapi/stopFakeSystem",
              headers: { 'token': localStorage.getItem('token') },
              method: 'POST',
              success: function (res) {
                if (res.code === 200) {
                  layer.msg("仿真模拟已停止", { icon: 1 });
                  $("#fakeShowText").text("仿真模拟未运行")
                } else {
                  layer.msg(res.msg, { icon: 2 });
                }
              }
            });
          });
        });
      }
    });
    $.ajax({
      url: baseUrl + "/menu/auth",
      headers: {'token': localStorage.getItem('token')},
      method: 'POST',
      // async: false,
      success: function (res) {
        // 关闭加载动画
        $('.layuimini-loader').fadeOut();
        if (res.code === 200) {
          var tpl = $('#menuTpl').html();
          var template = Handlebars.compile(tpl);
          var html = template(res);
          $("#menu-main").html(html);
          element.init();
        } else if (res.code === 403) {
          top.location.href = baseUrl + "/login";
        } else {
          layer.msg(res.msg, {icon: 2});
          layer.confirm('确定要启动仿真模拟吗?', function (index) {
            layer.close(index);
            $.ajax({
              url: baseUrl + "/openapi/startFakeSystem",
              headers: { 'token': localStorage.getItem('token') },
              method: 'POST',
              success: function (res) {
                if (res.code === 200) {
                  layer.msg("仿真模拟已启动", { icon: 1 });
                  $("#fakeShowText").text("仿真模拟运行中")
                } else {
                  layer.msg(res.msg, { icon: 2 });
                }
              }
            });
          });
        }
      }
    });
      });
    $.ajax({
      url: baseUrl + "/license/getLicenseDays",
      headers: {'token': localStorage.getItem('token')},
      method: 'POST',
      success: function (res) {
        if (res.code == 200) {
          let days = res.data
          if (days <= 30) {
            $("#licenseShow").show()
            $("#licenseDays").html(days)
      $.ajax({
        url: baseUrl + "/menu/auth",
        headers: { 'token': localStorage.getItem('token') },
        method: 'POST',
        // async: false,
        success: function (res) {
          // 关闭加载动画
          $('.layuimini-loader').fadeOut();
          if (res.code === 200) {
            var tpl = $('#menuTpl').html();
            var template = Handlebars.compile(tpl);
            var html = template(res);
            $("#menu-main").html(html);
            element.init();
          } else if (res.code === 403) {
            top.location.href = baseUrl + "/login";
          } else {
            layer.msg(res.msg, { icon: 2 });
          }
          if (days <= 15) {
             showPopup(days)
          }
        }else {
          top.location.href = baseUrl + "/login";
        }
      }
    });
      });
    // 默认加载主页
    index.loadHome({
      menuPath: baseUrl+'/views/watch/console.html',
      menuName: '<i class="layui-icon layui-icon-home"></i>'
    });
      $.ajax({
        url: baseUrl + "/license/getLicenseDays",
        headers: { 'token': localStorage.getItem('token') },
        method: 'POST',
        success: function (res) {
          if (res.code == 200) {
            let days = res.data
            if (days <= 30) {
              $("#licenseShow").show()
              $("#licenseDays").html(days)
            }
    $('#username').text(localStorage.getItem('username'));
            if (days <= 15) {
              showPopup(days)
            }
          } else {
            top.location.href = baseUrl + "/login";
          }
        }
      });
    $(document).on('click','#logout', function () {
      window.location.href = "login.html";
      localStorage.removeItem('token');
      localStorage.removeItem('username');
      admin.closeAllTabs();
    });
      // 默认加载主页
      index.loadHome({
        menuPath: baseUrl + '/views/watch/console.html',
        menuName: '<i class="layui-icon layui-icon-home"></i>'
      });
    // 替换退出按钮变量
    var logout = document.getElementById('logout');
    var url = logout.getAttribute('href');
    logout.setAttribute('href', baseUrl + "/login");
      $('#username').text(localStorage.getItem('username'));
    // AI助手弹窗索引
    var aiLayerIndex = null;
      $(document).on('click', '#logout', function () {
        window.location.href = "login.html";
        localStorage.removeItem('token');
        localStorage.removeItem('username');
        admin.closeAllTabs();
      });
    // AI助手图标悬浮提示
    $('#ai-assistant-btn').on('mouseenter', function(){
      // 替换退出按钮变量
      var logout = document.getElementById('logout');
      var url = logout.getAttribute('href');
      logout.setAttribute('href', baseUrl + "/login");
      // AI助手弹窗索引
      var aiLayerIndex = null;
      // AI助手图标悬浮提示
      $('#ai-assistant-btn').on('mouseenter', function () {
        this.index = layer.tips('AI助手', this, {
            tips: [1, '#333'], // 上方显示,深色背景
            time: -1 // 不自动关闭
          tips: [1, '#333'], // 上方显示,深色背景
          time: -1 // 不自动关闭
        });
    }).on('mouseleave', function(){
      }).on('mouseleave', function () {
        layer.close(this.index);
    }).on('click', function () {
      }).on('click', function () {
        // 如果已经打开过且未销毁,直接显示
        if (aiLayerIndex !== null && $('#layui-layer' + aiLayerIndex).length > 0) {
            var $layero = $('#layui-layer' + aiLayerIndex);
            var $shade = $('#layui-layer-shade' + aiLayerIndex);
          var $layero = $('#layui-layer' + aiLayerIndex);
          var $shade = $('#layui-layer-shade' + aiLayerIndex);
            // 显示并重置状态
            $shade.show().css('opacity', 0.1);
            $layero.show();
            // 重新触发进入动画
            $layero.removeClass('ai-drawer-layer-close');
            $layero.removeClass('ai-drawer-layer');
            void $layero.get(0).offsetWidth; // 触发重绘
            $layero.addClass('ai-drawer-layer');
            return;
          // 显示并重置状态
          $shade.show().css('opacity', 0.1);
          $layero.show();
          // 重新触发进入动画
          $layero.removeClass('ai-drawer-layer-close');
          $layero.removeClass('ai-drawer-layer');
          void $layero.get(0).offsetWidth; // 触发重绘
          $layero.addClass('ai-drawer-layer');
          return;
        }
        layer.open({
            type: 2,
            title: false, // 隐藏默认标题栏,更简洁
            closeBtn: 0, // 隐藏关闭按钮,点击遮罩关闭
            shadeClose: false, // 改为手动控制关闭,以便播放动画
            shade: 0.1,
            area: ['600px', '100%'],
            offset: 'r', // 右侧悬浮
            anim: -1, // 禁用默认动画,使用CSS动画
            isOutAnim: false,
            skin: 'ai-drawer-layer', // 自定义皮肤
            content: 'ai/diagnosis.html',
            success: function(layero, index){
                aiLayerIndex = index; // 记录索引
                // 背景模糊效果
                var shadeId = layero.attr('id').replace('layui-layer', 'layui-layer-shade');
                var $shade = $('#' + shadeId);
                $shade.css({
                    'backdrop-filter': 'blur(3px)',
                    'transition': 'opacity 0.8s'
                });
                // 点击遮罩关闭(带动画)
                $shade.on('click', function() {
                    layero.addClass('ai-drawer-layer-close');
                    $shade.css('opacity', 0);
                    setTimeout(function(){
                        // layer.close(index); // 不销毁,改为隐藏
                        layero.hide();
                        $shade.hide();
                    }, 400);
                });
            }
        });
    });
          type: 2,
          title: false, // 隐藏默认标题栏,更简洁
          closeBtn: 0, // 隐藏关闭按钮,点击遮罩关闭
          shadeClose: false, // 改为手动控制关闭,以便播放动画
          shade: 0.1,
          area: ['600px', '100%'],
          offset: 'r', // 右侧悬浮
          anim: -1, // 禁用默认动画,使用CSS动画
          isOutAnim: false,
          skin: 'ai-drawer-layer', // 自定义皮肤
          content: 'ai/diagnosis.html',
          success: function (layero, index) {
            aiLayerIndex = index; // 记录索引
  });
</script>
<script type="text/html" id="menuTpl">
            // 背景模糊效果
            var shadeId = layero.attr('id').replace('layui-layer', 'layui-layer-shade');
            var $shade = $('#' + shadeId);
            $shade.css({
              'backdrop-filter': 'blur(3px)',
              'transition': 'opacity 0.8s'
            });
            // 点击遮罩关闭(带动画)
            $shade.on('click', function () {
              layero.addClass('ai-drawer-layer-close');
              $shade.css('opacity', 0);
              setTimeout(function () {
                // layer.close(index); // 不销毁,改为隐藏
                layero.hide();
                $shade.hide();
              }, 400);
            });
          }
        });
      });
    });
  </script>
  <script type="text/html" id="menuTpl">
  {{#each data}}
  <li class="layui-nav-item">
    <a><i class="layui-icon {{this.menuIcon}}"></i>&emsp;<cite>{{this.menu}}</cite></a>
@@ -425,6 +475,5 @@
  {{/each}}
</script>
</body>
</html>
</html>