Quellcode durchsuchen

feat:新增登陆强制重置密码,删除一堆不在项目的依赖

apple vor 4 Tagen
Ursprung
Commit
3a16f4fc32
100 geänderte Dateien mit 315 neuen und 38032 gelöschten Zeilen
  1. BIN
      .DS_Store
  2. BIN
      js/.DS_Store
  3. 0 152
      js/PageJs/infoHomep.js
  4. 0 0
      js/PageJs/mainMenuDefHome.js
  5. 0 146
      js/PageJs/taskHomep.js
  6. 0 1
      js/PageJs/urgeHomep.js
  7. 0 0
      js/base.js
  8. 0 31
      js/cms.js
  9. 0 1
      js/common.js
  10. 0 0
      js/display.js
  11. 0 0
      js/edit.js
  12. 0 75
      js/form.js
  13. 0 14631
      js/jodit/ace.js
  14. 0 0
      js/jodit/beautify-html.min.js
  15. 0 0
      js/jodit/beautify.min.js
  16. 0 9
      js/jodit/jodit.js
  17. 0 0
      js/jodit/mode-html.js
  18. 0 0
      js/jodit/theme-idle_fingers.js
  19. 0 138
      js/vue/EventBus.js
  20. 0 233
      js/vue/icon-config.js
  21. 0 6142
      js/vue/ss-components.js
  22. 0 316
      js/vue/ss-echarts-compnents.js
  23. 0 1156
      js/vue/ss-index-components.js
  24. 0 203
      js/vue/tools.js
  25. 0 3854
      js/vue/vue-router.gloabl.js
  26. 0 268
      js/vue/vue3.js
  27. 0 0
      js/wdDrag.js
  28. 315 1
      page/login.html
  29. BIN
      skin/.DS_Store
  30. 0 6914
      skin/easy/css/base.css
  31. 0 305
      skin/easy/css/cropper.css
  32. 0 0
      skin/easy/css/element-plus.css
  33. 0 126
      skin/easy/css/font_4273728_tnvxftfb8j.css
  34. 0 750
      skin/easy/css/font_4279221_5h4vbt6831w.css
  35. 0 984
      skin/easy/css/iconfont.css
  36. 0 1
      skin/easy/css/jodit.css
  37. 0 36
      skin/easy/css/var.css
  38. 0 1051
      skin/easy/dlg.css
  39. BIN
      skin/easy/fonts/.smbdeleteAAAa00000012eea9
  40. BIN
      skin/easy/fonts/iconfont.ttf
  41. BIN
      skin/easy/fonts/iconfont.woff
  42. BIN
      skin/easy/fonts/iconfont.woff2
  43. BIN
      skin/easy/fonts/iconfont_4273728.woff2
  44. BIN
      skin/easy/fonts/iconfont_4279221.woff2
  45. 0 508
      skin/easy/gate.css
  46. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/)]BDJ_U}%HB2`9(~5X[_3H6.gif
  47. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/0iocntuq0mw77.gif
  48. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/1~CK74Y6~VGAWKZ0]3$9S@I.jpg
  49. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/2c06a90652cac5f927a377a7ee1fe333_5bad6ca91bd0b.gif
  50. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/3c7e711ca2adea83e957467144ce9d2e_5a557e794f261.gif
  51. BIN
      skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/3f27e969531aab06b0dbc7d1521aec99_b158b81479e745b4ab28925d38bd54bc.gif
  52. BIN
      skin/easy/help/PC/29d/c3c/dc6/da1/398/eb3/42c/c18/c11/ca3/01/9.png
  53. BIN
      skin/easy/help/PC/7f40ef61/565a6831/efb01283/7adbb1db/9ce6efb31aa5c42b3329ce03aaf5aae9_5b8b5b7301a57.gif
  54. BIN
      skin/easy/help/PC/ry/0fjcklyqviz95.gif
  55. BIN
      skin/easy/help/PC/ry/25def9e1846aab73ceca6d2d959ea08e_5b513d51c5b39.gif
  56. BIN
      skin/easy/help/PC/ry/XQADGBVNXRFCUZNQ`25UBC.jpg
  57. BIN
      skin/easy/help/PC/ry/mmexport1552022002827.jpg
  58. BIN
      skin/easy/help/PC/ry/喵喵2.gif
  59. BIN
      skin/easy/help/PC/ry/微信图片_20171012135344.png
  60. BIN
      skin/easy/help/PC/ws/20150816193536_AkCru.jpeg
  61. BIN
      skin/easy/help/PC/ws/mmexport1552019840260.jpg
  62. BIN
      skin/easy/help/PC/ws/微信图片_20170527092121.jpg
  63. BIN
      skin/easy/help/PC/ws/微信图片_20171012135344.png
  64. BIN
      skin/easy/help/cd/喵喵喵喵.gif
  65. BIN
      skin/easy/help/env/1_首页banner读书、行路,做新时代高素质健康行业接班人.jpg
  66. BIN
      skin/easy/help/env/3c7e711ca2adea83e957467144ce9d2e_5a557e794f261.gif
  67. BIN
      skin/easy/help/env/mobiledealWith.gif
  68. BIN
      skin/easy/help/env/mobilekcb-xs1.png
  69. BIN
      skin/easy/help/env/mobilekcb-xs2.png
  70. BIN
      skin/easy/help/env/mobileknow.jpg
  71. BIN
      skin/easy/help/env/mobileleft-right.gif
  72. BIN
      skin/easy/help/env/mobileopenFolder.gif
  73. BIN
      skin/easy/help/env/mobilereadMore.gif
  74. BIN
      skin/easy/help/env/mobileredLine.png
  75. BIN
      skin/easy/help/env/mobileresize.gif
  76. BIN
      skin/easy/help/env/mobileright.gif
  77. BIN
      skin/easy/help/env/mobilesearch1.gif
  78. BIN
      skin/easy/help/env/mobileseei.gif
  79. BIN
      skin/easy/help/env/mobilesetUp.gif
  80. BIN
      skin/easy/help/env/mobiletongji.png
  81. BIN
      skin/easy/help/env/mobile个人首页点击头像.gif
  82. BIN
      skin/easy/help/env/mobile任教课程表 --点名.gif
  83. BIN
      skin/easy/help/env/mobile任教课程表-课堂记录页面.gif
  84. BIN
      skin/easy/help/env/mobile喵喵喵喵.gif
  85. BIN
      skin/easy/help/env/mobile定制统计图.gif
  86. BIN
      skin/easy/help/env/mobile左右切换页面.gif
  87. BIN
      skin/easy/help/env/mobile日程操作.gif
  88. BIN
      skin/easy/help/env/mobile编辑统计图.gif
  89. BIN
      skin/easy/help/env/moblieAPP左右切换页面(最新).gif
  90. BIN
      skin/easy/help/env/个人首页头像.gif
  91. BIN
      skin/easy/help/env/兔狗3.jpg
  92. BIN
      skin/easy/help/env/喵2.gif
  93. BIN
      skin/easy/help/env/喵喵.gif
  94. BIN
      skin/easy/help/env/喵喵2.gif
  95. BIN
      skin/easy/help/env/喵喵喵.gif
  96. BIN
      skin/easy/help/env/喵喵喵喵.gif
  97. BIN
      skin/easy/help/env/定制统计图.gif
  98. BIN
      skin/easy/help/env/狗兔2.jpg
  99. BIN
      skin/easy/help/mobile/help_chart/tongji.png
  100. BIN
      skin/easy/help/mobile/help_chart/tongji_edit.png

BIN
.DS_Store


BIN
js/.DS_Store


+ 0 - 152
js/PageJs/infoHomep.js

@@ -1,152 +0,0 @@
-function init(img) {
-  var e = parseFloat("${edgzl}");
-  (e = isNaN("${edgzl}") ? 0 : e), (e = e > 0 ? e : 100);
-  var g = parseFloat("${grgzl}");
-  g = isNaN("${grgzl}") ? 0 : g;
-  var p = g / e;
-  function showTime() {
-    var t = new Date(),
-      e = t.getFullYear(),
-      i = t.getMonth() + 1,
-      n = t.getDate(),
-      o = t.getMinutes() < 10 ? "0" + t.getMinutes() : t.getMinutes();
-    $(".nowDateGrxx").text(
-      e + "\u5e74" + i + "\u6708" + n + "\u65e5 " + t.getHours() + ":" + o
-    );
-  }
-  $(".gzl1").css("width", 100 * (p > 1 ? 1 : p) + "%"),
-    $(".gzlpe").html((100 * p).toFixed(2)),
-    setInterval(showTime, 1e3);
-  var timer = null;
-  function tips(t, e) {
-    if (null != $("#" + e).html()) {
-      var i = $(t)[0].getBoundingClientRect(),
-        n = this.recursionIframe(),
-        o = i.left + n.left,
-        r = i.top + i.height + n.top,
-        s =
-          "<div class='whkDivHover' style = 'width:" +
-          $(t).width() +
-          "px; height: 102px; position: absolute; left: " +
-          o +
-          "px; top:" +
-          r +
-          "px; z-index:999999;' ><div class='popup-div smallScrollbar' style='width: 100%;padding: 0px;overflow:auto'><div class='smallScr cursor-click ' style='max-height: 120px;height: 100px;width: calc(100% - 2px);padding-right: 2px;box-sizing: border-box;margin-top: 2px;'>";
-      (s += $("#" + e)
-        .find(".smallScr")
-        .html()),
-        (s += "</div></div></div>"),
-        top.$("body").append(s);
-      var d = document.createElement("script");
-      $(d).append("initNiceScorll();"),
-        top.$("body").append(d),
-        top.$(".whkDivHover").find(".popup-div").show(),
-        top.$(".whkDivHover").mouseenter(function () {
-          clearTimeout(timer);
-        }),
-        top
-          .$(".whkDivHover")
-          .find(".popup-div")
-          .mouseleave(function () {
-            tipsHidden();
-          });
-    }
-  }
-  function tipsHidden() {
-    top.$(".whkDivHover").remove();
-  }
-  $(".dHover").mouseenter(function () {
-    tips($(this), "cardList");
-  }),
-    $(".dHover").mouseleave(function () {
-      clearTimeout(timer),
-        (timer = setTimeout(function () {
-          tipsHidden();
-        }, 100));
-    }),
-    $(".dHover2").mouseenter(function (t) {
-      t.stopPropagation(),
-        tips($(this), "cardList2"),
-        setTimeout(function () {
-          top.loadSmallScorll(top.$(".popup-div"));
-        }, 100);
-    }),
-    $(".dHover2").mouseleave(function (t) {
-      clearTimeout(timer),
-        (timer = setTimeout(function () {
-          tipsHidden();
-        }, 100));
-    }),
-    (this.recursionIframe = function (t) {
-      if ((t = t || window).parent == top && t.parent == t)
-        return { left: 0, top: 0 };
-      for (
-        var e,
-          i = t.parent,
-          n = i.document.getElementsByTagName("IFRAME"),
-          o = t.document.getElementsByTagName("IFRAME"),
-          r = 0;
-        r < o.length;
-        r++
-      ) {
-        if ((s = o[r]).contentWindow == t) {
-          e = s;
-          break;
-        }
-      }
-      for (r = 0; r < n.length; r++) {
-        var s;
-        if ((s = n[r]).contentWindow == t) {
-          e = s;
-          break;
-        }
-      }
-      var d = {
-        left: (function t(e) {
-          var i = e.offsetLeft;
-          return null != e.offsetParent && (i += t(e.offsetParent)), i;
-        })(e),
-        top: (function t(e) {
-          var i = e.offsetTop;
-          return null != e.offsetParent && (i += t(e.offsetParent)), i;
-        })(e),
-      };
-      if (i.parent != i) {
-        var l = this.recursionIframe(i);
-        (d.left += l.left), (d.top += l.top);
-      }
-      return d;
-    }),
-    $("#wh_content").find(".popup-div").hide(),
-    $("#rc_content").find(".popup-div").hide(),
-    $(".popup-div").hide(),
-    $("#wh_content").click(function () {
-      var url = window.a;
-      eval(url), $("div.zhdlsj").show(), $("#wh_content").hide();
-    });
-}
-$("#grtjList-div").mouseleave(function () {
-  $("#grtjList-child-div").css("display", "none");
-}),
-  $(".tjlb-child").mouseenter(function () {
-    $("#grtjList-child-div").css("display", "block");
-  }),
-  $("#grtjList-child-div").mouseleave(function () {
-    $("#grtjList-child-div").css("display", "none");
-  }),
-  loadSmallScorll($("#grtjList-child-div"));
-var divw = $(".grtjList-num").width();
-$(".grtjList-num").mouseleave(function () {
-  $(this).find("div[parentId]").css("display", "none");
-}),
-  $(".grtjList-num").mouseenter(function () {
-    var t = $(this).attr("id");
-    t &&
-      ($("div[parentId]").css("display", "none"),
-      $("div[parentId='" + t + "']").css("display", "block")),
-      $(".grtjList-child-num").width(divw);
-  }),
-  setTimeout(function () {
-    loadSmallScorll($(".grtjList-child-num"));
-  }, 100),
-  $(".grtjList-child-num").width(divw);

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/PageJs/mainMenuDefHome.js


+ 0 - 146
js/PageJs/taskHomep.js

@@ -1,146 +0,0 @@
-function init(img) {
-
-  //获取整体宽度
-var ztW = $('#shList').width();
-var ztW1 =ztW - 255 ;
-console.log(ztW,ztW1,ztW1 - 70)
-//动态给收起来的标题赋宽度值
-$(".bb1").css({
-// "max-width": ztW1 - 70 +'px'
-})
-console.log('被拖动了2');
-
-  var f = $(".shList").find(".file");
-  var trClass="";
-  //图标样式
-  var indenterClass="icon-folder icon-openFolder icon-point icon-doc icon-fullFolder icon-openFullFolder";
-  var hLineClass="";
-  var groupNum=99;
-  //文字样式
-  var titleClass="list-highlight list-highlight list2 list-highlight list-highlight";
-  $('#shList table').treetable({
-      expandable: true,
-      indent:"",
-      stringCollapse:"点击关闭",
-      stringExpand:"点击展开",
-      onNodeCollapse:function(a){
-          //console.log(this);
-
-          var trEle=$(this.treeCell).parent();
-          var titleEle=trEle.find(".title").removeClass(titleClass);
-          var indenter=$(this.indenter).removeClass(indenterClass);
-
-          if(this.children.length>groupNum){
-              indenter.addClass("icon-fullFolder")
-              titleEle.addClass("list-highlight");
-          }else{
-              indenter.addClass("icon-folder")
-              titleEle.addClass("list-highlight");
-          }
-         trEle.addClass(hLineClass);
-      },onNodeExpand:function(a){
-          var trEle=$(this.treeCell).parent();
-          var titleEle=trEle.find(".title").removeClass(titleClass);
-          var indenter=$(this.indenter).removeClass(indenterClass);
-
-          if(this.children.length>groupNum){
-              indenter.addClass("icon-openFullFolder");
-              titleEle.addClass("list-highlight")
-          }else{
-              indenter.addClass("icon-openFolder");
-              titleEle.addClass("list-highlight")
-          }
-
-          trEle.removeClass(hLineClass);
-          $(this.children[this.children.length-1].treeCell).parent().addClass(hLineClass);
-
-      },onNodeInitialized:function(){
-          //console.log(this);
-          var trEle=$(this.treeCell).parent().removeClass(hLineClass);
-          var titleEle=trEle.find(".title").removeClass(titleClass);
-          var indenter=$(this.indenter).removeClass(indenterClass);
-          //文件夹
-          if(this.children.length>0){
-              console.log(this);
-              console.log(this.children.length+" "+ groupNum+" "+(this.children.length> groupNum));
-              if(this.children.length> groupNum){
-                  indenter.addClass("icon-fullFolder")
-                  titleEle.addClass("list-highlight");
-              }else{
-                  indenter.addClass("icon-folder")
-                  titleEle.addClass("list-highlight");
-              }
-            trEle.find(".tdSj").click(function(){
-                  $(this).parent().find(".indenter").trigger("click");
-                  return false;
-            })
-          //单个
-          }else if(!this.parentId){
-              indenter.addClass("icon-doc")
-              titleEle.addClass("list2");
-
-          //子
-          }else {
-
-              indenter.addClass("icon-point")
-              titleEle.addClass("list2");
-          }
-          if(this.children.length>0||!this.parentId){
-              trEle.addClass(hLineClass);
-          }
-
-          var id=trEle.find("[id]").attr("id");
-
-          setTimeout(function(){
-            //console.log("gh:"+id+">"+document.querySelector("#"+id).offsetWidth+"  "+document.querySelector("#"+id).offsetHeight)
-            wd.display.initGrowHighByIds([id],"80px");
-          },500)
-      }
-  });
-  $.each(f, function() {
-      var itm = $(this);
-      if (typeof(itm.parent().parent().attr("data-tt-parent-id")) != "undefined") {
-          itm.css("margin-left", "2em");
-      }
-  });
-  //获取整体宽度
-  var bjW= $('.home-list-div').width() - 180;
-  var ztW = $('.dbtreetable').width();
-  //动态给左边赋宽度值
-  var tdW = ztW - 50;
-  $(".tdBt").width(tdW);
-  var leftW = $(".tdBt").width();
-   var aW=leftW - 100;
-  //动态给收起来的标题赋宽度值
-  $(".bb").css({
-    // "max-width": aW +'px'
-  })
-  //动态给放出来的标题赋宽度值
-  $(".btA").css({
-    // "max-width": bjW +'px'
-  })
-  //console.log('被拖动了')
-//$(".tdSj").click(function(){$(this).prev(".tdBt").children(".indenter").children("a").trigger("click")});
-
-$("[taskCount]").each(function(){
-  var taskCount=parseInt($(this).attr("taskCount"));
-  var c=taskCount;
-  if(isNaN(taskCount)||taskCount>groupNum)c="";
-  $(this).find(".indenter a").html(c);
-
-})
-
-  // wd.display.initGrowHighByIds(growHeightIds,"80px");
-// if($("#sybj_db_val").val() == undefined) {
-   //  console.error("sybj_db_val.....................")
-   //  $("body").append('<input type="hidden" value="1" id="sybj_db_val" />');
-   //  loadSmallScorll($("#sybj_db"));
-// }
-
-$(img).parents("[initurl]").find(".nicescroll-rails").remove();
- loadSmallScorll($(img).parents("[initurl]").find(".smallScrollbar"));
-//    $('.nicescroll-rails-vr').attr('style','padding-left: 0px;padding-right: 2px;width: 3px;z-index: 999999;background: transparent;cursor: default;position: absolute;top: 53px;left: 344px;height: 210px;display: block;')
- setTimeout(function(){
-  $('.db').parents('.ContainerForLoad').siblings('.nicescroll-rails-vr').css('padding-left','0.5px')
- },1000)
-}

+ 0 - 1
js/PageJs/urgeHomep.js

@@ -1 +0,0 @@
-function init(t){var r=$("#sqList").width()-255;$(".bb1").css({"max-width":r-70+"px"}),$(t).parents("[initurl]").find(".nicescroll-rails").remove(),loadSmallScorll($(t).parents("[initurl]").find(".smallScrollbar")),setTimeout((function(){$("#cb").parents(".ContainerForLoad").siblings(".nicescroll-rails-vr").attr("style","padding-left: 1px!important;padding-right: 2px;width: 3px;z-index: 999999;background: transparent;cursor: default;position: absolute;top: 53px;float: right;right: 0px; height: 300px;display: block;")}),2e3);for(var i=$(".listProgress-done").attr("percentage"),e=0;e<$(".listProgress-done").length;e++)(i=parseInt($(".listProgress-done").eq(e).attr("percentage")))>100&&(i=100),$(".listProgress-done").eq(e).attr("style","width:"+i+"%")}

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/base.js


+ 0 - 31
js/cms.js

@@ -1,31 +0,0 @@
-window.ss.cms||(window.ss.cms={});
-
-
-
-//查询子内容列表
-ss.display.querySubNrList = function (nrid, jlztm) {
-    var result = [];
-    $.ajax({
-        type: 'post',
-        url: "/service",
-        dataType: "json",
-        data: {
-            ssServ: "wrCmsList",    // wdService: "nrxtsy",。Lin
-            nrid: "T-" + nrid,
-            sfbf: 1,
-            jlztm: jlztm
-        },
-        async: false,
-        success: function (jsonData) {
-            for (var i = 0; i < jsonData.length; i++) {
-                result.push({
-                    name: jsonData[i].mc,
-                    value: jsonData[i].mswj,
-                    nrjslbm: jsonData[i].nrjslbm
-                });
-            }
-        }
-    });
-    return result;
-}
-

+ 0 - 1
js/common.js

@@ -1 +0,0 @@
-window.ss||(window.ss={}),ss.c={},ss.c.wdAjax=function(e){var t=function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;if("undefined"==typeof ActiveXObject)throw new Error("您的系统或浏览器不支持XHR对象!");for(var e=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(e){}}();function n(){200==t.status?"json"==e.dataType?e.success(JSON.parse(t.responseText)):e.success(t.responseText):e.error&&e.error("获取数据失败,错误代号为:"+t.status+"错误信息为:"+t.statusText)}e.url=e.url,e.data=function(e){var t=[];for(var n in e)t.push(encodeURIComponent(n)+"="+encodeURIComponent(e[n]));return t.join("&")}(e.data),"get"===e.type&&(e.url+="-1"==e.url.indexOf("?")?"?"+e.data:"&"+e.data),!0===e.async&&(t.onreadystatechange=function(){4==t.readyState&&n()}),t.open(e.type,e.url,e.async),"post"===e.type?(t.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),t.send(e.data)):t.send(null),!1===e.async&&n()};

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/display.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/edit.js


+ 0 - 75
js/form.js

@@ -1,75 +0,0 @@
-//表单操作相关js文件
-window.ss.form = window.ss.form || {};
-
-//提交表单的方法
-ss.form.submit = function (param){
-    const {
-        id, url, width, height, minHeight, maxHeight, targetWin
-    } = param;
-
-    //如果表单校验通过
-    if(window.ssVm&&window.ssVm.validateAllAndShowMsg()){
-        let f = null;//表单元素对象
-        if (id) {
-            // 如果id不为空,根据id获取元素
-            f = document.getElementById(id);
-        } else {
-            // 如果id为空,获取页面第一个form元素
-            f = document.querySelector('form');
-        }
-
-        if(!f){
-            alert('表单不存在');
-            return;
-        }
-
-        if(url)
-            f.action = url;
-
-        if (width && height && minHeight && maxHeight) {
-            ss.display.resizeComponent(
-                width,
-                height,
-                minHeight,
-                maxHeight
-            );
-        }
-
-        if(targetWin){
-            ss.form.submit2TargetWin(targetWin);
-        }else{
-            f.submit();
-        }
-
-        return true;
-    }else
-        return false;
-
-}
-
-
-ss.form.submit2TargetWin = function (targetWin) {
-    const firstForm = document.querySelector('form');
-    if(firstForm==null){
-        console.log("找不到form!");
-    }
-    var myform = firstForm.cloneNode(true);
-    myform.style.display = "none";
-    firstForm.parentNode.innerHTML = "";
-
-    targetWin.document.body.appendChild(myform);
-    myform.submit();
-}
-
-ss.form.confirm = function (title,msg,yesFun,noFun){
-    const isConfirmed = confirm(msg);
-    if (isConfirmed) {
-        console.log("用户确认yes");
-        if(yesFun)
-            yesFun();
-    } else {
-        console.log("用户取消");
-        if(noFun)
-            noFun();
-    }
-}

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 14631
js/jodit/ace.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/jodit/beautify-html.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/jodit/beautify.min.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 9
js/jodit/jodit.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/jodit/mode-html.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/jodit/theme-idle_fingers.js


+ 0 - 138
js/vue/EventBus.js

@@ -1,138 +0,0 @@
-class EventBus {
-    constructor() {
-        this.eventObject = {};
-        this.callbackId = 0;
-        this.state = {}
-        // console.log("eventBus初始化了")
-    }
-    // 发布事件
-    publish(eventName, ...args) {
-        // console.log("发布事件", eventName, ...args);
-        this.state[eventName] = args.length === 1 ? args[0] : args;
-
-        // 取出当前事件所有的回调函数
-        const callbackObject = this.eventObject[eventName];
-        if (!callbackObject) return console.warn(eventName + " not found!");
-        // 执行每一个回调函数
-        for (let id in callbackObject) {
-            // 执行时传入参数
-            // console.log("准备执行回调", id); // 确认回调即将执行
-            callbackObject[id](...args);
-            // console.log("回调执行完毕", id); // 确认回调执行完毕
-
-            // 只订阅一次的回调函数需要删除
-            if (id[0] === "d") {
-                delete callbackObject[id];
-            }
-        }
-    }
-    // 订阅事件
-    subscribe(eventName, callback) {
-        // console.log("订阅事件", eventName, callback);
-        // 初始化这个事件
-        if (!this.eventObject[eventName]) {
-            // 使用对象存储,注销回调函数的时候提高删除的效率
-            this.eventObject[eventName] = {};
-        }
-
-        const id = this.callbackId;
-        this.callbackId++;  // 确保每次调用后递增
-        // 存储订阅者的回调函数
-        // callbackId使用后需要自增,供下一个回调函数使用
-        this.eventObject[eventName][id] = callback;
-        // console.log("回调ID分配:", id); // 查看ID
-
-        // 每一次订阅事件,都生成唯一一个取消订阅的函数
-        const unSubscribe = () => {
-            // 清除这个订阅者的回调函数
-            delete this.eventObject[eventName][id];
-
-            // 如果这个事件没有订阅者了,也把整个事件对象清除
-            if (Object.keys(this.eventObject[eventName]).length === 0) {
-                delete this.eventObject[eventName];
-            }
-        };
-
-        return { unSubscribe };
-    }
-
-    // 只订阅一次
-    subscribeOnce(eventName, callback) {
-        // 初始化这个事件
-        if (!this.eventObject[eventName]) {
-            // 使用对象存储,注销回调函数的时候提高删除的效率
-            this.eventObject[eventName] = {};
-        }
-
-        // 标示为只订阅一次的回调函数
-        const id = "d" + this.callbackId++;
-
-        // 存储订阅者的回调函数
-        // callbackId使用后需要自增,供下一个回调函数使用
-        this.eventObject[eventName][id] = callback;
-
-        // 每一次订阅事件,都生成唯一一个取消订阅的函数
-        const unSubscribe = () => {
-            // 清除这个订阅者的回调函数
-            delete this.eventObject[eventName][id];
-
-            // 如果这个事件没有订阅者了,也把整个事件对象清除
-            if (Object.keys(this.eventObject[eventName]).length === 0) {
-                delete this.eventObject[eventName];
-            }
-        };
-
-        return { unSubscribe };
-    }
-    // 获取状态的新方法
-    getState(eventName) {
-        return this.state[eventName];
-    }
-    // 清除事件
-    clear(eventName) {
-        // 未提供事件名称,默认清除所有事件
-        if (!eventName) {
-            this.eventObject = {};
-            this.state = {};
-            return;
-        }
-        // 清除指定事件
-        delete this.eventObject[eventName];
-        delete this.state[eventName];
-    }
-}
-if (!window.sharedEventBus) {
-    window.sharedEventBus = new EventBus();
-    window.sharedEventBus.publish('folderPath', []);
-}
-
-export const eventBus = window.sharedEventBus;
-
-export const EVEN_VAR = {
-    // 系统编辑模式变化
-    systemEditModelChange: "systemEditModelChange",
-    // 显示项目弹窗
-    showProjectDialog: "showProjectDialog",
-    showKnowledgeDialog: "KnowledgeDialog",
-    showOrcDialog: "showOrcDialog",
-    showOrcListDialog: "showOrcListDialog",
-    showZhibiaoNodeDialog: "showZhibiaoNodeDialog",
-    showVerifyDialog: "showVerifyDialog",
-    showGlobalSearchDialog: "showGlobalSearchDialog",
-    // 1.2.2录入页校验
-    showAddUserInfoDialog: "showAddUserInfoDialog",
-    // 1.5.2.新增工作节点
-    showAddWorkNodeDialog: "showAddWorkNodeDialog",
-    // 知识库变动01
-    showKnowlegeDbViewerDialog: "showKnowlegeDbViewerDialog",
-    showKnowlegeDbChangeDialog: "showKnowlegeDbChangeDialog",
-    // 编辑器
-    showEditorDialog: "showEditorDialog",
-    // 添加预警窗口
-    showAddWaringDialog: "showAddWaringDialog",
-    // 空窗口
-    showEmptyDialog: "showEmptyDialog",
-    currentPage:"index.html",
-};
-
-

+ 0 - 233
js/vue/icon-config.js

@@ -1,233 +0,0 @@
-// 公共图标
-export const commonIcon = {
-    name: "common",
-    title: "公共图标",
-    prefix: "common-icon-",
-    family: "common-iconfont",
-    types: {
-      close: "close",
-      "close-circle": "close-circle",
-      "menu-square": "menu-square",
-      menu: "menu",
-      empty: "empty",
-      add: "add",
-      slant: "slant",
-      home: "home",
-      "double-arrow-right": "double-arrow-right",
-      layer: "layer",
-      activity: "activity",
-      love: "love",
-      "full-screen": "full-screen",
-      print: "print",
-      question: "question",
-      card: "card",
-      site: "site",
-      notice: "notice",
-      smile: "smile",
-      fontSize: "fontSize",
-      paperClip: "paperClip",
-      edit: "edit",
-      video: "video",
-      "arrow-double-left": "arrow-double-left",
-      "arrow-double-right": "arrow-double-right",
-      "arrow-double-up": "arrow-double-up",
-      "arrow-double-down": "arrow-double-down",
-      photo: "photo",
-    },
-  };
-  
-  // 项目图标
-  export const ssIcon = {
-    name: "ss",
-    prefix: "ss-icon-",
-    family: "ss-iconfont",
-    types: {
-      menu: "sanheng",
-      setting: "shezhi",
-      message: "duihua2",
-      refresh: "shaugxin",
-      reset: "chongzuo",
-      back: "tuihui",
-      "question-thin": "bangzhu",
-      question: "zaixianbangzhu",
-      "full-screen": "quanping",
-      "arrow-left": "shangyizhang",
-      "arrow-up": "xiangshangjiantou",
-      "arrow-right": "xiayizhang",
-      "arrow-down": "xiangxiajiantou",
-      close: "X",
-      "close-thin": "guanbi",
-      fontSize: "changyongyu",
-      "user-project": "xiuxue",
-      user: "yonghuming",
-      userGroup: "huiyi",
-      file: "wenben",
-      "arrow-left-line": "fanhui",
-      edit: "shouxie",
-      remark: "fuzhi",
-      love: "shoucang",
-      link: "a-lianjie1",
-      search: "a-fangda1",
-      check: "baocun-youshangjiao",
-      "check-thin": "baocun",
-      focus: "laiyuan",
-      "scale-out": "fangda",
-      "scale-in": "suoxiao",
-      "user-group": "renyuan-",
-      "search-result": "quanwenjiansuo",
-      send: "fasong",
-      "db-maintenance": "duixiang",
-      quit: "tuichu",
-      word: "word",
-      cloud: "xiazai",
-      todo: "daiban",
-      print: "dayin",
-      "edit-font-family": "ziti",
-      "edit-font-size": "zihao",
-      "alarm-clock": "cuiban",
-      lightning: "kuaijiefangwen",
-      qingjia: "qingjia",
-      shoufukuan: "shoufukuan",
-      kaoqin: "kaoqin",
-      "close-mark-fill": "guanbi_jiaobiao",
-      lock: "a-lock1",
-      "un-lock": "a-mima1",
-      "lock-fill": "suoping",
-      "topic-fill": "huanfu",
-      "list-fill": "lieshu",
-      "setting-fill": "shouyeshezhi",
-      "folder-collapse-fill": "folderShare",
-      "folder-expand-fill": "olderOpen",
-      "checked-fill-circle": "a-chenggong1",
-      "info-circle": "i",
-      "forbid-circle": "tingyong",
-      "minus-circle": "jianshao",
-      "mark-bottom-success": "gouxuan",
-      "mark-bottom-error": "bugouxuan",
-      "mark-bottom-warn": "bugouxuan",
-      notice: "gongshigonggao",
-      layer: "leibie",
-      scan: "saoyisao",
-      "check-code": "yanzhengma",
-      time: "shijian",
-      cancal: "chexiao",
-      "re-cancal": "fanhuishangyibu",
-      resize: "guangbiao-tuozhuai",
-      yaoyiyao: "yaoyiyaocu",
-  
-      anjian: "anjian",
-      renwu: "renwu",
-      shanchubiaoge: "shanchubiaoge",
-      duomeiti: "duomeiti",
-      shengqing: "shengqing",
-      baocunbintijiao: "baocunbintijiao",
-      bianqian: "bianqian",
-      shanchuhang: "shanchuhang",
-      shangjiaobiao: "shangjiaobiao",
-      charulie: "charulie",
-      shanchulie: "shanchulie",
-      buhuanrao: "buhuanrao",
-      biaoqing: "biaoqing",
-      excl: "excl",
-      home: "home",
-      baoguandan: "baoguandan",
-      jinyong: "jinyong",
-      biyanjing: "biyanjing",
-      qian: "qian",
-      piliang: "piliang",
-      dianji_02: "dianji-02",
-      biaoge: "biaoge",
-      guangbiaoBianji: "guangbiao-bianji",
-      bingtu: "bingtu",
-      gerenxuanzhi: "gerenxuanzhi",
-      suofang: "suofang",
-      xieti: "xieti",
-      fukuan: "fukuan",
-      kehuguanli: "kehuguanli",
-      faxian: "faxian",
-      dianzan: "dianzan",
-      fanxuan: "fanxuan",
-      gongwen: "gongwen",
-      neirongku: "neirongku",
-      xuanzhongJiaobiao: "xuanzhong_jiaobiao",
-      cangdan: "cangdan",
-      zuoduiqi: "zuoduiqi",
-      shouqi: "shouqi",
-      charuhang: "charuhang",
-      hebing: "hebing",
-      guangbiao: "guangbiao",
-      huodong: "huodong",
-      danwei: "danwei",
-      guanwang: "guanwang",
-      canshuxiang: "canshuxiang",
-      fenlei: "fenlei",
-      zuanshi: "zuanshi",
-      tuozhuai: "tuozhuai",
-      jiacu: "jiacu",
-      denglu: "denglu",
-      shubiaojiantou: "shubiaojiantou",
-      tupian: "tupian",
-      yanjing: "yanjing",
-      xiangmushezhi: "xiangmushezhi",
-      xiajiaobiao: "xiajiaobiao",
-      wupin: "wupin",
-      qiandaizi: "qiandaizi",
-      shunpai: "shunpai",
-      fujian: "fujian",
-      zhenghe: "zhenghe",
-      zhifangtu: "zhifangtu",
-      dingwei: "dingwei",
-      xietong: "xietong",
-      diannao: "diannao",
-      guanli: "guanli",
-      tupu: "tupu",
-      daochu: "daochu",
-      yewu: "yewu",
-      zhengshu: "zhengshu",
-      zitiyangshi: "zitiyangshi",
-      zuopaihuanrao: "zuopaihuanrao",
-      youpaihuanrao: "youpaihuanrao",
-      zitishanchu: "zitishanchu",
-      zihao2: "zihao2",
-      zhognjianduiqi: "zhognjianduiqi",
-      zitiyanse: "zitiyanse",
-      yiban: "yiban",
-      wangzhan: "wangzhan",
-      caogaoxiang: "caogaoxiang",
-      chanyeleibie: "chanyeleibie",
-      chaifen: "chaifen",
-      xiahuaxian: "xiahuaxian",
-      xiangyouhebing: "xiangyouhebing",
-      xueyuan: "xueyuan",
-      yikatong: "yikatong",
-      xiangxiahebing: "xiangxiahebing",
-      wentiliebiao: "wentiliebiao",
-      wenzhang: "wenzhang",
-      youduiqi: "youduiqi",
-      yujing: "yujing",
-      caozuoshibai1: "caozuoshibai1",
-      "anjian-1": "anjian-1",
-      duihua1: "duihua1",
-      jiahao: "jiahao",
-      "a-liucheng1": "a-liucheng1",
-      "a-liangduanduiqi1": "a-liangduanduiqi1",
-      "a-ljt1": "a-ljt1",
-      wenjianjia_zhankai: "wenjianjia_zhankai",
-      "wenjianjia_shouqi": "wenjianjia_shouqi",
-      grxzFuyongshanggezhi: "grxzFuyongshanggezhi",
-      grxzMorenzhi: "grxzMorenzhi",
-      grxzBuxuan: "grxzBuxuan",
-      yaoyiyao: "yaoyiyao",
-      PE: "PE",
-      fenzhi: "fenzhi",
-      xiangliang: "xiangliang",
-      huihe: "huihe",
-      linggan: "linggan",
-      kaishi: "kaishi",
-      jieshu: "jieshu",
-      quanxuan: "quanxuan",
-      quanbuguoqu: "quanbuguoqu",
-      biaoqian: "biaoqian",
-    },
-  };
-  

+ 0 - 6142
js/vue/ss-components.js

@@ -1,6142 +0,0 @@
-import { ssIcon, commonIcon } from "./icon-config.js";
-import * as IndexComponents from "./ss-index-components.js";
-import * as EchartComponents from "./ss-echarts-compnents.js";
-import { isNum, toStyleStr } from "./tools.js";
-import { EVEN_VAR } from "./EventBus.js";
-
-// import * as elements from "../lib/element-plus.js";
-(function () {
-  const {
-    createApp,
-    ref,
-    reactive,
-    watch,
-    onMounted,
-    onBeforeUnmount,
-    h,
-    computed,
-    resolveComponent,
-    watchEffect,
-    nextTick,
-    onVnodeMounted,
-    Teleport,
-    inject,
-    provide,
-  } = Vue;
-
-  // 弹窗默认遮罩z-index
-  let currentZIndex = 100;
-  //   目前已存在的弹窗
-  const topWindow = window.top;
-  topWindow.dialogInstances = topWindow.dialogInstances || [];
-  // 新建弹窗
-  function createSsDialogInstance(setting, callbackEvent) {
-    currentZIndex += 10; // 动态提升 z-index
-    const container = document.createElement("div");
-    document.body.appendChild(container);
-    const app = Vue.createApp({
-      render() {
-        return h(SsDialog, {
-          ...setting,
-          zIndex: currentZIndex,
-          onClose() {
-            document.body.removeChild(container); // 仅移除弹窗容器
-            const index = topWindow.dialogInstances.indexOf(app);
-            if (index > -1) {
-              topWindow.dialogInstances.splice(index, 1); // 移除实例
-            }
-            // 关闭后的回调
-            if (callbackEvent && typeof callbackEvent === "function") {
-              callbackEvent();
-            }
-            app.unmount(); // 仅卸载弹窗实例
-            if (container.parentNode) {
-              container.parentNode.removeChild(container); // 确保移除容器
-            }
-          },
-        });
-      },
-    });
-    topWindow.dialogInstances.push({ app, callbackEvent, container });
-    app.component("ss-mark", SsMark); // 注册 ss-mark 组件
-    app.component("ss-icon", SsIcon);
-    app.component("ss-full-style-header", SsFullStyleHeader); // 注册 ss-full-style-header 组件
-    app.mount(container);
-  }
-  // ss-breadcrumb 一级菜单页面面包屑
-  const SsBreadcrumb = {
-    name: "SsBreadcrumb",
-    props: {
-      level: {
-        type: Object,
-        default: null,
-      },
-    },
-    setup(props) {
-      const currentMenu = ref(null);
-      const folderPath = ref([]);
-      const eventBus = window.parent.sharedEventBus;
-
-      // 监听页面变化
-      onMounted(() => {
-        // 获取初始页面
-        currentMenu.value = eventBus.getState(EVEN_VAR.currentPage);
-        folderPath.value = eventBus.getState("folderPath") || [];
-
-        // 订阅页面变化
-        eventBus.subscribe(EVEN_VAR.currentPage, (page) => {
-          currentMenu.value = page;
-        });
-        eventBus.subscribe("folderPath", (path) => {
-          folderPath.value = path || [];
-        });
-      });
-      // 修改点击处理函数
-      const handlePathClick = (index) => {
-        if (props.level?.onBack) {
-          // 截取到点击的位置,后面的路径会被销毁
-          const newPath = folderPath.value.slice(0, index + 1);
-          eventBus.publish("folderPath", newPath);
-          // 返回到对应层级
-          const targetFolder = newPath[newPath.length - 1]?.folder || null;
-          props.level.onBack(targetFolder);
-        }
-      };
-      const SsCommonIcon = resolveComponent("SsCommonIcon");
-      return () =>
-          h("div", { class: "bread-crumb" }, [
-            currentMenu.value &&
-            h(
-                "div",
-                {
-                  onClick: () => {
-                    if (props.level?.onBack) {
-                      eventBus.publish("folderPath", []);
-                      props.level.onBack(null); // 返回到根目录
-                    } else {
-                      eventBus.publish(EVEN_VAR.currentPage, currentMenu.value);
-                    }
-                  },
-                },
-                currentMenu.value.label || currentMenu.value.name
-            ),
-
-            ...(folderPath.value || [])
-                .map((folder, index) => [
-                  h(SsCommonIcon, { class: "common-icon-arrow-right" }),
-                  h(
-                      "div",
-                      {
-                        class: "bread-crumb-item",
-                        onClick: () => handlePathClick(index),
-                        style: { cursor: "pointer" },
-                      },
-                      folder.title
-                  ),
-                ])
-                .flat(),
-          ]);
-    },
-  };
-
-  // ss-input form表单的输入
-  const SsInput = {
-    name: "SsInput",  
-    inheritAttrs: false, // 不直接继承属性到组件根元素
-    props: {
-      name: {
-        type: String,
-        required: true,
-        default: "",
-      },
-      // 接收 v-model 绑定的值
-      errTip: {
-        type: String,
-      },
-      required: {
-        type: Boolean,
-        default: false,
-      },
-      placeholder: {
-        type: String,
-        default: "请输入",
-      },
-      defaultValue: [String, Number],
-      modelValue: [String, Number],
-      // 新增:附件配置
-      fj: {
-        type: Object,
-        default: null,
-      },
-      // 新增:param 配置(用于附件功能)
-      param: {
-        type: Object,
-        default: null,
-      },
-      // 新增:高度配置
-      height: {
-        type: String,
-        default: "",
-      },
-    },
-    emits: ["update:modelValue", "input", "blur", "change"], // 允许更新 v-model 绑定的值
-    setup(props, { emit }) {
-
-      const errMsg = ref("");
-      const inputRef = ref(null);
-      const textareaRef = ref(null);
-      const inputValue = ref(props.modelValue || props.defaultValue || "");
-      const contentFloatingDiv = ref(false); // 控制浮动 DIV 的显示
-      const floatingDivPosition = ref("bottom"); // 'bottom' 或 'top'
-      const isFocused = ref(false); // 跟踪焦点状态
-
-      // 附件相关变量(仅在传入 param 时初始化)
-      let fjid = ref(null);
-      let fjName = null;
-      let mode = null;
-      if (props.param && props.param.button) {
-        fjid = ref(props.param.button.val);
-        fjName = props.param.button.desc;
-        mode = props.param.mode;
-      }
-
-      const showRequired = computed(() => {
-        // 检查是否有验证规则(通过 window.ssVm 判断)
-        const hasValidationRule = window.ssVm?.validations?.has(props.name);
-
-        if (!hasValidationRule) return false;
-        if (errMsg.value) return true;
-        if (!inputValue.value) return true;
-        return false;
-      });
-
-      // 计算floatdiv应该向上还是向下展开
-      const calculateFloatingDivPosition = () => {
-        nextTick(() => {
-          const textarea = inputRef.value;
-          if (!textarea) return;
-
-          const rect = textarea.getBoundingClientRect();
-          const viewportHeight = window.innerHeight;
-
-          // 预估floatdiv的高度(最多5行 * 20px + 上下padding + border)
-          const estimatedFloatDivHeight = 20 * 5 + 10 + 2; // 5行 + padding + border = 112px
-
-          // 检查下方空间
-          const spaceBelow = viewportHeight - rect.bottom;
-
-          // 如果下方空间不足,且上方空间足够,则向上展开
-          if (spaceBelow < estimatedFloatDivHeight && rect.top > estimatedFloatDivHeight) {
-            floatingDivPosition.value = "top";
-          } else {
-            floatingDivPosition.value = "bottom";
-          }
-        });
-      };
-
-      // 计算floatdiv的top偏移量
-      const getFloatingDivTop = computed(() => {
-        if (props.height) {
-          // 有height时,padding是5px
-          return '5px';
-        } else {
-          // 没有height时是单行居中,需要计算居中位置
-          // 假设input-container高度是32px(或者从CSS读取),单行20px
-          // 居中偏移 = (容器高度 - 行高) / 2 = (32 - 20) / 2 = 6px
-          return '6px';
-        }
-      });
-
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          console.log(result);
-
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-
-      // 使用 watch 监听 props.errTip 和 props.modelValue 的变化
-      watch(
-        () => props.errTip,
-        (newVal) => {
-          errMsg.value = newVal;
-        },
-        { immediate: true }
-      );
-      watch(
-        () => props.modelValue,
-        (newVal) => {
-          inputValue.value = newVal;
-        }
-      );
-
-      // 挂载时的逻辑
-      onMounted(() => {
-        errMsg.value = props.errTip;
-        inputValue.value = props.modelValue || props.defaultValue || "";
-      });
-      // 计算并调整textarea的高度
-      const adjustHeight = () => {
-        nextTick(() => {
-          const textarea = textareaRef.value;
-          if (!textarea) return;
-
-          // floatDiv的textarea始终自动计算高度,不受props.height影响
-          // 重置高度以获得正确的scrollHeight
-          textarea.style.height = "auto";
-          // 计算新高度 - 统一限制为5行
-          const lineHeight = parseInt(getComputedStyle(textarea).lineHeight, 10);
-          const maxHeight = lineHeight * 5; // 统一为5行
-          const newHeight = Math.min(textarea.scrollHeight, maxHeight);
-          textarea.style.height = `${newHeight}px`;
-        });
-      };
-
-      // 检查是否应该显示浮动窗口(需要同时满足:有焦点 + 内容超出)
-      const checkShouldShowFloatingDiv = () => {
-        const textarea = inputRef.value;
-        if (!textarea) return false;
-
-        // 判断内容是否超出:scrollHeight > clientHeight
-        // scrollHeight 是内容的完整高度(包括不可见部分)
-        // clientHeight 是可视区域高度(不包括滚动的部分)
-        const isOverflow = textarea.scrollHeight > textarea.clientHeight;
-
-        // 需要同时满足:有焦点 + 内容超出
-        return isFocused.value && isOverflow;
-      };
-
-      // 定义事件处理函数
-      const onInput = (event) => {
-        const newValue = event.target.value;
-        inputValue.value = newValue;
-        emit("update:modelValue", newValue);
-        validate(); // 输入时验证
-
-        nextTick(() => {
-          // 检查是否需要显示浮动div
-          contentFloatingDiv.value = checkShouldShowFloatingDiv();
-
-          // 如果需要显示floatdiv,计算其位置
-          if (contentFloatingDiv.value) {
-            calculateFloatingDivPosition();
-          }
-        });
-        adjustHeight();
-      };
-      const onFocus = (event) => {
-        // 设置焦点状态为true
-        isFocused.value = true;
-        adjustHeight();
-
-        // 检查是否应该显示浮动窗口
-        nextTick(() => {
-          contentFloatingDiv.value = checkShouldShowFloatingDiv();
-          if (contentFloatingDiv.value) {
-            calculateFloatingDivPosition();
-          }
-        });
-      };
-
-      // 失去焦点时进行验证
-      const onBlur = (event) => {
-        emit("blur", event.target);
-        validate(); // 失焦时验证
-
-        nextTick(() => {
-          // 如果焦点不在 textarea 上,则隐藏浮动 div
-          if (!document.activeElement.classList.contains("input-control")) {
-            isFocused.value = false;
-            contentFloatingDiv.value = false;
-          }
-        });
-      };
-      const onChange = (event) => {
-        inputValue.value = event.target.value || "";
-        emit("change", inputValue.value);
-      };
-      const onMouseover = (event) => {
-        nextTick(() => {
-          // setTimeout(contentFloatingDiv.value = true, 500)
-        });
-      };
-      const onMouseleave = (event) => {
-        // contentFloatingDiv.value = false
-      };
-
-      // 附件按钮点击处理(从 SsEditor 搬运)
-      const onAttachmentClick = (e) => {
-        e.preventDefault();
-
-        if (!props.param || !props.param.button) {
-          console.warn("未配置 param 参数");
-          return;
-        }
-
-        console.log("附件点击了");
-        console.log("param", props.param);
-        console.log("cmsAddUrl", props.param.button.cmsAddUrl);
-
-        // 如果 fjid 为空,先调用 cmsAddUrl 创建
-        if (fjid.value == null || fjid.value == "") {
-          $.ajax({
-            type: "post",
-            url: props.param.button.cmsAddUrl,
-            async: false,
-            data: {
-              name: "fjid",
-              ssNrObjName: "sh",
-              ssNrObjId: "",
-            },
-            success: function (_fjid) {
-              console.log("cmsAddUrl success", _fjid);
-              fjid.value = _fjid;
-            },
-          });
-        }
-
-        // 构建参数字符串
-        var str =
-          "&nrid=T-" +
-          fjid.value +
-          "&objectId=" +
-          fjid.value +
-          "&objectName=" +
-          fjName +
-          "&callback=" +
-          (window["fjidCallbackName"] || "");
-
-        console.log("str", str);
-
-        // 打开附件编辑对话框
-        SS.openDialog({
-          src: props.param.button.cmsUpdUrl + str,
-          headerTitle: "编辑",
-          width: 900,
-          high: 664,
-          zIndex: 51,
-        });
-      };
-
-      return {
-        errMsg,
-        inputValue,
-        showRequired,
-        onInput,
-        onBlur,
-        onChange,
-        onMouseover,
-        onMouseleave,
-        contentFloatingDiv,
-        floatingDivPosition,
-        getFloatingDivTop,
-        inputRef,
-        textareaRef,
-        onFocus,
-        onAttachmentClick,
-        fjid, // 附件 ID,用于隐藏字段
-      };
-    },
-    render() {
-      const { resolveComponent, h } = Vue;
-      const SsIcon = resolveComponent("ss-icon");
-      const SsEditorIcon = resolveComponent("SsEditorIcon");
-
-
-      // 构建主textarea的样式
-      const mainTextareaStyle = {};
-      if (this.height) {
-        mainTextareaStyle.height = "auto"
-        // mainTextareaStyle.paddingTop = '5px'; // 有高度时加上padding-top
-        // mainTextareaStyle.paddingBottom = '5px'; // 有高度时加上padding-bottom
-      } else {
-        // 没有指定height时,固定为单行高度
-        mainTextareaStyle.height = '20px'; // 行高20px
-        mainTextareaStyle.lineHeight = '20px'; // 确保单行垂直居中
-        mainTextareaStyle.display = 'flex';
-        mainTextareaStyle.marginBottom  = '5px';
-      }
-
-      // 如果有附件按钮,为按钮留出空间
-      if (this.fj || this.param) {
-        mainTextareaStyle.paddingRight = '75px';
-        
-      }
-
-      const mainTextareaRows = this.height ? Math.floor(parseFloat('80px') / 20) : 1
-
-      return h("div", { class: "input" }, [
-        h("div", { class: "input-container", }, [
-          h("div", { class: "input",style:"padding:5px 0"  }, [
-            h("textarea", {
-              ref: "inputRef",
-              class: "input-control",
-              name: this.name,
-              value: this.inputValue,
-              onInput: this.onInput,
-              onFocus: this.onFocus,
-              onBlur: this.onBlur,
-              onChange: this.onChange,
-              placeholder: this.placeholder,
-              onMouseover: this.onMouseover, // 监听鼠标悬停
-              onMouseleave: this.onMouseleave, // 监听鼠标离开
-              rows:mainTextareaRows,
-              ...this.$attrs,
-              style: mainTextareaStyle,
-              autocomplete: "off",
-            }),
-            // 附件按钮(优先使用 param,兼容旧的 fj)
-            this.param || this.fj
-              ? h(
-                  "button",
-                  {
-                    type: "button",
-                    class: "fj-button",
-                    onClick: this.param ? this.onAttachmentClick : (e) => {
-                      e.preventDefault();
-                      console.log("附件配置:", this.fj);
-                    },
-                  },
-                  [
-                   
-                      h(SsEditorIcon, {
-                        class: "editor-icon-link",
-                      }),
-                      h("span", { class: "fj-button-text" }, "附件")
-                    
-                  ]
-                )
-              : null,
-            // this.showRequired ? h("div", { class: "required" }) : null,
-          ]),
-          this.contentFloatingDiv || ""
-            ? h("div", {
-                class: "floating-div",
-                style: this.floatingDivPosition === "bottom"
-                  ? {
-                      // 向下展开: 覆盖原输入框,top对齐首行
-                      top: this.getFloatingDivTop,
-                      bottom: 'auto',
-                    }
-                  : {
-                      // 向上展开: 同样覆盖原输入框,但从底部开始计算
-                      top: 'auto',
-                      bottom: this.height ? '5px' : '6px', // 对齐到原textarea的底部padding位置
-                    }
-              }, [
-                h("textarea", {
-                  ref: "textareaRef",
-                  class: "input-control",
-                  value: this.inputValue,
-                  onInput: this.onInput,
-                  onBlur: this.onBlur,
-                  onFocus: this.onFocus,
-                  onMouseover: this.onMouseover, // 监听鼠标悬停
-                  onMouseleave: this.onMouseleave, // 监听鼠标离开
-                  autocomplete: "off",
-                  onVnodeMounted: (vnode) => {
-                    vnode.el.focus();
-                  },
-                }),
-              ])
-            : null,
-          // this.errMsg ? h(SsValidate, { errMsg: this.errMsg }) : null,
-        ]),
-        // 附件相关的隐藏字段(仅在有 param 时才渲染)
-        this.param && [
-          // fjid 隐藏字段(只有当 fjid 有值时才渲染)
-          this.fjid && this.fjid.value &&
-          h("input", {
-            type: "hidden",
-            name: "fjid",
-            value: this.fjid.value,
-          }),
-          // 其他隐藏字段根据 name 生成
-          /* 去掉。文本框不需要(这是富文本才有的) Ben 20251205
-          h("input", {
-          type: "hidden",
-          name: this.name.replace(/wj$/, "") + "Edit",
-          value: this.inputValue
-          }),
-          */
-          // h("input", {
-          //   type: "hidden",
-          //   name: this.name.replace(/wj$/, "") + "wj",
-          //   value: this.inputValue
-          // }),
-          /* 去掉。文本框不需要(这是富文本才有的) Ben 20251205
-          h("input", {
-          type: "hidden",
-          name: "ueditorpath",
-          value: this.name
-          }),
-          */
-        ],
-      ]);
-    },
-  };
-  // ss-normal-input 登录输入
-  const SsLoginInput = {
-    name: "SsLoginInput",
-    inheritAttrs: false,
-    props: {
-      errTip: {
-        type: String,
-      },
-
-      type: {
-        type: String,
-        default: "text",
-      },
-      required: {
-        type: Boolean,
-        default: false,
-      },
-      placeholder: {
-        type: String,
-        default: "请输入",
-      },
-      name: {
-        type: String,
-        default: "",
-      },
-      defaultValue: [String, Number],
-      modelValue: [String, Number],
-    },
-    emits: ["update:modelValue", "input", "blur", "change"], // 允许更新 v-model 绑定的值
-    setup(props, { emit }) {
-      const errMsg = ref("");
-      const inputRef = ref(null);
-      const textareaRef = ref(null);
-      const inputValue = ref(props.modelValue || props.defaultValue || "");
-
-      // 使用 watch 监听 props.errTip 和 props.modelValue 的变化
-      watch(
-          () => props.errTip,
-          (newVal) => {
-            errMsg.value = newVal;
-          },
-          { immediate: true }
-      );
-      watch(
-          () => props.modelValue,
-          (newVal) => {
-            inputValue.value = newVal;
-          }
-      );
-
-      // 挂载时的逻辑
-      onMounted(() => {
-        errMsg.value = props.errTip;
-        inputValue.value = props.modelValue || props.defaultValue || "";
-      });
-
-      // 定义事件处理函数
-      const onInput = (event) => {
-        const newValue = event.target.value;
-        inputValue.value = newValue;
-        emit("update:modelValue", newValue);
-      };
-      return { inputValue, onInput, inputRef, textareaRef };
-    },
-    render() {
-      return h("div", { class: "input" }, [
-        h("div", { class: "input-container" }, [
-          h("div", { class: "input" }, [
-            h("input", {
-              ref: "inputRef",
-              class: "input-control",
-              name: this.name,
-              value: this.inputValue,
-              onInput: this.onInput,
-              type: this.type,
-              placeholder: this.placeholder,
-              required: this.required,
-              ...this.$attrs,
-              autocomplete: "off",
-            }),
-            this.required ? h("div", { class: "required" }) : null,
-          ]),
-        ]),
-      ]);
-    },
-  };
-  // ss-login-button
-  const SsLoginButton = {
-    name: "SsLoginButton",
-    inheritAttrs: false,
-    props: {
-      class: {
-        type: String,
-        default: "",
-      },
-      text: {
-        type: String,
-        default: "",
-      },
-      type: {
-        type: String,
-        default: "button",
-      },
-    },
-    emits: ["click"],
-    setup(props, { emit }) {
-      // 定义事件处理函数
-      const onClick = (event) => {
-        // 发射一个 'click' 事件,你可以传递所需的参数
-        emit("click", event);
-      };
-
-      return { props, onClick };
-    },
-    render() {
-      const SsIcon = resolveComponent("ss-icon");
-      const SsLoginIcon = resolveComponent("ss-login-icon");
-      return h(
-          "button",
-          { class: "login-button", type: this.type, onClick: this.onClick },
-          [
-            h("span", [h(SsLoginIcon, { class: this.class })]),
-            h("span", {}, this.text),
-          ]
-      );
-    },
-  };
-  // ss-objp 下拉选择
-  const SsObjp = {
-    name: "SsObjp",
-    inheritAttrs: false,
-    props: {
-      filter: {
-        type: String,
-        required: false,
-      },
-      cb: {
-        type: String,
-        required: true,
-      },
-      url: {
-        type: String,
-        required: true,
-      },
-      name: {
-        type: String,
-        required: true,
-      },
-      width: {
-        type: String,
-        default: "100%",
-      },
-      placeholder: {
-        type: String,
-        default: "请选择",
-      },
-      inp: {
-        type: Boolean,
-        default: false,
-      },
-      opt: {
-        type: Array,
-        default: () => [],
-      },
-      errTip: String,
-      defaultValue: [String, Number],
-      modelValue: [String, Number],
-      direction: {
-        type: String,
-        default: "bottom",
-      },
-    },
-    emits: ["update:modelValue", "input", "blur", "change"],
-    setup(props, { emit }) {
-      const canInput = props.inp;
-      const errMsg = Vue.ref(props.errTip);
-      const selectItem = Vue.ref({});
-      let inputText = Vue.ref(""); // 用于存储输入框的文本
-      const popupWinVisible = Vue.ref(false);
-
-      const filteredOptions = Vue.ref(props.opt);
-      const popupDirection = Vue.ref("bottom");
-
-      // const showRequired = Vue.computed(() => {
-      //   const hasValidationRule = window.ssVm?.validations?.has(props.name);
-      //   if (!hasValidationRule) return false;
-      //   if (errMsg.value) return true;
-      //   if (!selectItem.value?.value) return true;
-      //   return false;
-      // });
-
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          // console.log("validate", window.ssVm.validateField(props.name));
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-
-      //在objPicker界面,选中value对应的项
-      const updateSelectItem = () => {
-        // console.log(props.opt);
-        const item = props.opt.find((it) => it.value === props.modelValue);
-        if (item) {
-          selectItem.value = item;
-          inputText.value = item.label;
-        } else {
-          selectItem.value = { label: "", value: "" };
-          inputText.value = "";
-        }
-        // validate();
-      };
-
-      Vue.watch(
-          () => props.errTip,
-          (newVal) => {
-            errMsg.value = newVal;
-          }
-      );
-
-      Vue.watch(() => props.modelValue, updateSelectItem, { immediate: true });
-      Vue.watch(
-          () => props.opt,
-          (newVal) => {
-            updateSelectItem();
-            filteredOptions.value = [...newVal];
-            // console.log("filteredOptions", filteredOptions.value);
-          }
-      );
-
-      //初始化objPicker在页面刚打开时的默认值
-      async function initDefaultValue() {
-        try {
-          if (props.url && props.cb && props.modelValue) {
-
-            let objectPickerParam;
-            let url = props.url;
-
-            //如果有定义过滤器
-            if (props.filter) {
-              //包含HTML实体的JSON字符串转为JSON对象,如原字符串是{&quot;dwid&quot;:&quot;88&quot;},注意key也必需用单引号包着
-              // const decodedString = props.filter.replace(/&quot;/g, '"'); // 转换为: {"dwid":"88"}
-              // objectPickerParam = JSON.parse(decodedString); // 转为json对象
-
-              const filterObj = props.filter; // 转为json对象
-              for (let k in filterObj) {
-                let v = filterObj[k];
-                url += "&" + k + "=" + v;
-              }
-
-              objectPickerParam = props.filter; // 转为json对象
-              objectPickerParam["input"] = props.inp;
-              objectPickerParam["codebook"] = props.cb;
-
-
-              // alert(url);
-            } else {
-              objectPickerParam = { input: props.inp, codebook: props.cb };
-            }
-
-            const objectPickerParamStr = JSON.stringify(objectPickerParam);
-
-            const params = new URLSearchParams();
-            params.append("objectpickerparam", objectPickerParamStr);
-            params.append("objectpickertype", "2");
-            params.append("objectpickervalue", props.modelValue); //需回显的值
-
-            // alert("1params:"+JSON.stringify(params));
-
-            axios
-                .post(props.url, params, {
-                  headers: {
-                    "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                  },
-                })
-                .then((response) => {
-                  // alert(JSON.stringify(response.data));
-
-                  if ("timeout" == response.data.statusText) {
-                    alert("网络超时!");
-                    return;
-                  }
-
-                  if (response.data.result) {
-                    const keys = Object.keys(response.data.result);
-                    if (keys.length === 1) {
-                      let code = keys[0];
-                      let desc = response.data.result[keys[0]];
-                      if (props.opt)
-                        props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
-                      else {
-                        props.opt = [];
-                      }
-                      props.opt.push({ label: desc, value: code });
-                      updateSelectItem();
-
-                      // alert('props.opt:'+JSON.stringify(props.opt));
-                    }
-                  }
-                });
-          }
-        } catch (error) {
-          // callback(null, error.message); // 失败回调,传递错误
-        }
-      }
-
-      // Vue.onMounted(updateSelectItem);
-
-      const doSelectItem = (item) => {
-        emit("update:modelValue", item.value);
-        selectItem.value = item;
-        inputText.value = item.label;
-        hidePopup();
-        nextTick(() => {
-          console.log(item.value + "@@@props.modelValue:" + props.modelValue);
-          validate();
-          if (window.ssVm) {
-            // 遍历所有验证规则,找到依赖当前字段的规则
-            for (const [field, rules] of window.ssVm.validations.entries()) {
-              for (const rule of rules) {
-                if (rule.opt?.relField === props.name) {
-                  // console.log("Found dependent field:", field); // 调试日志
-                  window.ssVm.validateField(field);
-                }
-              }
-            }
-          }
-        });
-      };
-
-      //可录入的objPicker,更新下拉菜单选项
-      async function updateOptionBYInputText(inpTxt) {
-        try {
-          let objectPickerParam;
-          let url = props.url;
-
-          if (props.url && props.cb) {
-            //如果有定义过滤器
-            if (props.filter) {
-
-              const filterObj = props.filter; // 转为json对象
-              for (let k in filterObj) {
-                let v = filterObj[k];
-                url += "&" + k + "=" + v;
-              }
-
-              //包含HTML实体的JSON字符串转为JSON对象,如原字符串是{&quot;dwid&quot;:&quot;88&quot;},注意key也必需用单引号包着
-              // const decodedString = props.filter.replace(/&quot;/g, '"'); // 转换为: {"dwid":"88"}
-              // objectPickerParam = JSON.parse(decodedString); // 转为json对象
-              objectPickerParam = props.filter;
-              objectPickerParam["input"] = props.inp;
-              objectPickerParam["codebook"] = props.cb;
-
-
-              // alert(url);
-            } else {
-              objectPickerParam = { input: props.inp, codebook: props.cb };
-            }
-
-            const objectPickerParamStr = JSON.stringify(objectPickerParam);
-            const params = new URLSearchParams();
-            params.append("objectpickerparam", objectPickerParamStr);
-            params.append("objectpickertype", "1");
-            if (props.inp && props.inp === "true") {
-              params.append("objectpickersearchAll", 0); //只查录入的值
-              params.append("objectpickerinput", inpTxt); //录入的值
-            } else {
-              params.append("objectpickersearchAll", 1);
-            }
-
-            axios
-                .post(url, params, {
-                  headers: {
-                    "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                  },
-                })
-                .then((response) => {
-                  if ("timeout" == response.data.statusText) {
-                    alert("网络超时!");
-                    return;
-                  }
-
-                  if (response.data.result) {
-                    const keys = Object.keys(response.data.result);
-                    // console.log("params:"+params+"@@response.data:"+JSON.stringify(response.data));
-                    if (keys.length > 0) {
-                      if (props.opt)
-                        props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
-                      else {
-                        props.opt = [];
-                      }
-                      for (let k in response.data.result) {
-                        props.opt.push({
-                          label: response.data.result[k],
-                          value: k,
-                        });
-                      }
-
-                      // console.log('###inpTxt:'+inpTxt+';');
-                      if (
-                          props.inp &&
-                          props.inp === "true" &&
-                          inpTxt.length > 0
-                      ) {
-                        //对于可录入的,用已录入的值作过滤
-
-                        filteredOptions.value = props.opt.filter((option) =>
-                            option.label
-                                .toLowerCase()
-                                .includes(inputText.value.toLowerCase())
-                        );
-                        filteredOptions.value.unshift({ label: "", value: "" });
-
-                        // console.log('###做了过滤:'+inputText.value.toLowerCase()+';');
-                      } else {
-                        filteredOptions.value = props.opt;
-                        filteredOptions.value.unshift({ label: "", value: "" });
-                      }
-
-                      if (!popupWinVisible.value) {
-                        popupWinVisible.value = true; // 确保下拉框在输入时打开
-                      }
-
-                      console.log("props.opt11:" + JSON.stringify(props.opt));
-                    }
-                  }
-                });
-          }
-        } catch (error) {
-          // callback(null, error.message); // 失败回调,传递错误
-        }
-      }
-
-      // 计算弹出方向的方法
-      const calculatePopupDirection = () => {
-        // 1. 获取select容器元素
-        const selectEl = document
-            .querySelector(`[name="${props.name}"]`)
-            ?.closest(".select-container");
-        if (!selectEl) return;
-
-        // 2. 获取位置信息
-        const selectRect = selectEl.getBoundingClientRect();
-        const viewportHeight = window.innerHeight;
-
-        // 3. 简单判断:如果下方剩余空间小于300px就向上弹出
-        const spaceBelow = viewportHeight - selectRect.bottom;
-
-        // 调试信息
-        // console.log('空间判断:', {
-        //   elementBottom: selectRect.bottom,
-        //   viewportHeight,
-        //   spaceBelow,
-        //   willPopUp: spaceBelow < 300,
-        //   popupDirection: popupDirection.value
-        // });
-
-        // 4. 设置方向
-        popupDirection.value = spaceBelow < 300 ? "top" : "bottom";
-      };
-
-      //点击下拉菜单的文本区域时,会触发的方法
-      function togglePopup() {
-        //可录入的objPicker,更新下拉菜单选项
-        updateOptionBYInputText(inputText.value);
-        // popupWinVisible.value = !popupWinVisible.value;
-        Vue.nextTick(() => {
-          calculatePopupDirection();
-        });
-      }
-
-      const hidePopup = () => {
-        popupWinVisible.value = false;
-      };
-
-      //点击下拉菜单的三角形时,会触发的方法
-      const suffixClick = () => {
-        //可录入的objPicker,更新下拉菜单选项
-        updateOptionBYInputText("");
-        // popupWinVisible.value = !popupWinVisible.value;
-        Vue.nextTick(() => {
-          calculatePopupDirection();
-        });
-        console.log("点三角");
-      };
-
-      //可录入的objPicker,录入项变化时,会触发
-      async function handleInputChange(event) {
-        inputText.value = event.target.value;
-        if (!inputText.value) {
-          inputText.value = "";
-        }
-
-        //可录入的objPicker,更新下拉菜单选项
-        updateOptionBYInputText(inputText.value);
-
-        // filteredOptions.value = props.opt.filter((option) =>
-        //     option.label.toLowerCase().includes(inputText.value.toLowerCase())
-        // );
-        // if (!popupWinVisible.value) {
-        //   popupWinVisible.value = true; // 确保下拉框在输入时打开
-        // }
-      }
-      Vue.onMounted(() => {
-        initDefaultValue();
-        window.addEventListener("resize", calculatePopupDirection);
-      });
-      Vue.onUnmounted(() => {
-        window.removeEventListener("resize", calculatePopupDirection);
-      });
-
-      return {
-        errMsg,
-        selectItem,
-        inputText,
-        canInput,
-        filteredOptions,
-        popupWinVisible,
-        popupDirection,
-        suffixClick,
-        togglePopup,
-        hidePopup,
-        doSelectItem,
-        handleInputChange,
-      };
-    },
-
-    template: `
-      <div class="input" style="position: relative" :style="{width: width}">
-        <div class="select-container" @mouseleave="hidePopup">
-          <div class="input" @click="togglePopup">
-            <input 
-              type="hidden"
-              :name="name"
-              :value="selectItem.value"
-              .value="selectItem.value" 
-            />
-            <input
-              v-model="inputText"
-              @input="handleInputChange"
-              v-if="canInput"
-              :placeholder="placeholder"
-              
-            />
-            
-            <input
-              v-else
-              :placeholder="placeholder"
-              :value="selectItem.label"
-              
-              disabled
-              style="pointer-events: none;"
-            />
-           
-            <div class="suffix" @click.stop="suffixClick">
-              <ss-form-icon :class="popupWinVisible ? 'form-icon-transform-select select' : 'form-icon-select'" />
-              
-            </div>
-          </div>
-         
-            
-          <div v-show="popupWinVisible" class="popup-win" :class="popupDirection">
-            <div v-if="opt && opt.length && filteredOptions.length > 0" class="popup-content">
-              <div class="content-area">
-                <div v-for="(item, index) in filteredOptions" :key="index" @click="doSelectItem(item)" :class="{ active: item.value === selectItem.value }">
-                  <span class="check-icon">
-                   
-                    <ss-form-icon class="form-icon-select-checked" />
-                  </span>
-                  <span>{{ item.label }}</span>
-                </div>
-              </div>
-            </div>
-            <div v-else class="popup-content"><div class="content-area"><div class="content-area"> <span>无选项</span></div></div></div>
-          </div>
-        </div>
-      </div>
-
-    `,
-  };
-  // ss-hidden 隐藏字段组件
-  const SsHidden = {
-    name: "SsHidden",
-    props: {
-      modelValue: String,
-      name: {
-        type: String,
-        required: true,
-      },
-      rule: {
-        type: String,
-        required: true,
-      },
-
-      param: {
-        type: String,
-        required: true,
-      },
-      url: {
-        type: String,
-        required: true,
-      },
-    },
-    emits: ["update:modelValue"],
-
-    setup(props, { emit }) {
-      const errMsg = Vue.ref("");
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          console.log("validate", window.ssVm.validateField(props.name));
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-      Vue.onMounted(() => {
-        /**
-         * 初始化级联菜单值初始值思路:
-         * 1. 带隐藏字段(即带编码规则)的级联菜单
-         *  在隐藏字段这,可以取到要回显的值和编码规则,从而计算出各级下拉菜单要回显的值。
-         *  然后通过ajax取各级级联菜单的值回显。
-         *  2. 不带隐藏字段的级联,只能在各个下拉菜单的setup事件中通过ajax取回显值回显
-         */
-
-        // 当同组级联下拉菜单选中值变化时,会调用本隐藏字段下面这方法设置隐藏字段值
-        window.addEventListener(
-            "cascader-setHiddenVal-" + props.name,
-            (event) => {
-              const { value } = event.detail;
-              emit("update:modelValue", value);
-              console.log(value);
-              setTimeout(() => {
-                validate();
-              }, 50);
-            }
-        );
-
-        // 如果有初始值,触发回显过程
-        if (props.modelValue) {
-          console.log("级联隐藏字段,开始回显,初始值:", props.modelValue);
-          triggerCascaderEcho(props.modelValue);
-          validate();
-        }
-      });
-
-      // 触发级联回显
-      const triggerCascaderEcho = (code) => {
-        /**
-         * 开始回显,初始值: 440304
-         * 解析后的所有值: Array(3)0: "440000"1: "440300"2: "440304"length: 3[[Prototype]]: Array(0)
-         */
-        const values = parseHiddenCodeForAll(code, props.rule);
-        console.log("解析后的所有值:", values);
-
-        // 转换为 JSON 对象
-        // const paramObj = JSON.parse(props.param);
-        const paramObj = props.param;
-        let selectArr = paramObj.fieldOrd; //保存本组级联菜单项的数组,如:['hksheng','hkshi','hkxian']
-        if (selectArr.length != values.length) {
-          // alert('属性'+props.name+'的值'+code+'与级联菜单中下拉菜单的数目不匹配!');
-          return;
-        }
-
-        // 按顺序触发回显,并增加延迟确保数据加载
-        /**
-         * 通过隐藏字段的setup事件,
-         * 循环遍历各级下拉菜单,并触发定义在下拉菜单中的'cascader-echo'事件,
-         * 在此事件中完成每个下拉菜单回显值操作(只取当前要回显的键值对显示,
-         * 下拉菜单所有的值,在点击下拉菜单时,才通过ajax取)。
-         */
-        values.forEach((value, index) => {
-          if (value) {
-            setTimeout(() => {
-              let upperVal = undefined;
-              if (index != 0) {
-                upperVal = values[index - 1];
-              }
-
-              const echoEvent = new CustomEvent(
-                  "cascader-echo-" + selectArr[index],
-                  {
-                    detail: {
-                      name: props.name,
-                      value: value,
-                      // level: index + 1,
-                      isAuto: true, // 标记为自动回显
-                      upperVal: upperVal,
-                    },
-                  }
-              );
-
-              console.log(props.name + "--upperValue:" + upperVal);
-
-              window.dispatchEvent(echoEvent);
-            }, index * 500); // 每级增加500ms延迟
-          }
-        });
-      };
-
-      // 解析所有级别的代码
-      const parseHiddenCodeForAll = (code, rule) => {
-        if (!code || !rule) return [];
-
-        // 获取规则中每段的长度
-        const segments = [];
-        let currentChar = rule[0];
-        let currentLength = 1;
-
-        for (let i = 1; i < rule.length; i++) {
-          if (rule[i] === currentChar) {
-            currentLength++;
-          } else {
-            segments.push(currentLength);
-            currentChar = rule[i];
-            currentLength = 1;
-          }
-        }
-        segments.push(currentLength);
-
-        // 解析每一级的值
-        const values = [];
-        let position = 0;
-
-        segments.forEach((length, index) => {
-          const value = code
-              .substring(0, position + length)
-              .padEnd(rule.length, "0");
-          values.push(value);
-          position += length;
-        });
-
-        return values;
-      };
-      watchEffect(() => {});
-      return {};
-    },
-    template: `<input type="hidden" :name="name" :value="modelValue">`,
-  };
-  // ss-cascader 级联选择器
-  const SsCcp = {
-    name: "SsCcp",
-    inheritAttrs: false,
-    props: {
-      modelValue: String,
-
-      name: {
-        type: String,
-        required: true,
-      },
-      level: {
-        type: Number,
-        required: true,
-      },
-      opt: {
-        type: Array,
-        default: () => [],
-      },
-      placeholder: {
-        type: String,
-        default: "请选择",
-      },
-      width: {
-        type: String,
-        default: "150px",
-      },
-      direction: {
-        type: String,
-        default: "bottom",
-      },
-      mode: {
-        type: String,
-        default: "1",
-      },
-
-      //级联菜单配置参数,如果是数组,则代表本下拉菜单是多套级联菜单共用的第一级菜单。如果是对象,则只有一套级联菜单用此下拉菜单。
-      param: {
-        type: String,
-        required: true,
-      },
-      //向后台拿数据的url
-      url: {
-        type: String,
-        required: true,
-      },
-    },
-    emits: ["update:modelValue", "change"],
-
-    setup(props, { emit }) {
-      // alert('级联菜单初始化:'+props.name+':--:'+props.modelValue);
-      const selectItem = Vue.ref({ label: props.placeholder, value: "" });
-      const popupWinVisible = Vue.ref(false);
-      const isAutoEcho = Vue.ref(false); // 用于标记是否是自动回显
-      const upperValue = Vue.ref(""); //上级下拉菜单当前值,在初始化下拉菜单默认值时,和上级下拉菜单的值变化时,修改此upperValue变量
-      const popupDirection = Vue.ref("bottom");
-
-      //有隐藏字段的下拉菜单,加载菜单项并展开事件
-      // 被上级下拉菜单选中值后,触发本下拉菜单刷新菜单项并弹出显示
-      window.addEventListener("cascader-open-" + props.name, async (event) => {
-        const { upperVal } = event.detail;
-        upperValue.value = upperVal;
-        console.log(
-            "22props.name:" +
-            props.name +
-            ",22props.upperValue:" +
-            upperValue.value
-        );
-
-        selectItem.value = ""; //清除本下拉菜单当前选中的值
-        emit("update:modelValue", ""); //通知父级
-
-        //清空下拉菜单,并设置第一项的值为placeholder
-        clearAndInit1stOpt();
-
-        //下个下拉菜单名
-        let nextSelName = getNextSel(props.name, props.param.fieldOrd);
-        if (nextSelName) {
-          //清下个下拉菜单选中值和选项
-          event = new CustomEvent("cascader-cleanOpt-" + nextSelName, {
-            detail: {},
-          });
-          window.dispatchEvent(event);
-        }
-
-        showPopup();
-      });
-
-      //设置mode2的下级下拉菜单的上级菜单当前值
-      function setNextSelectUpperValue() {
-        //设置下级菜单的上级菜单当前值upperValue
-        let paramArr = undefined;
-        if (Array.isArray(props.param)) {
-          paramArr = props.param;
-        } else {
-          paramArr = [];
-          paramArr.push(props.param);
-        }
-
-        for (const oneParam of paramArr) {
-          //下个下拉菜单名
-          const nextSelName = getNextSel(props.name, oneParam.fieldOrd);
-          if (nextSelName) {
-            setTimeout(() => {
-              const openNextEvent = new CustomEvent(
-                  "cascade-setUpperVal-" + nextSelName,
-                  {
-                    detail: {
-                      upperVal: props.modelValue,
-                    },
-                  }
-              );
-              window.dispatchEvent(openNextEvent);
-            }, 100);
-          }
-        } // end for
-      }
-
-      // 把上级 级联下拉菜单的值,设置进本组件的事件
-      window.addEventListener("cascade-setUpperVal-" + props.name, (event) => {
-        // alert('props.name:'+props.name+',props.upperValue:'+event.detail.upperVal);
-        const { upperVal } = event.detail;
-        upperValue.value = upperVal;
-
-        // console.log('props.name:'+props.name+',props.upperValue:'+upperValue.value);
-      });
-
-      //清空下拉菜单,并设置第一项的值为空
-      function clearAndInit1stOpt() {
-        if (props.opt)
-          props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
-        else {
-          props.opt = [];
-        }
-        props.opt.push({ label: "", value: "" });
-      }
-
-      //获取下一级下拉菜单,如果下一级下拉菜单不存在,则返回undefined
-      function getNextSel(selName, selNameArr) {
-        // 检查参数有效性
-        if (!Array.isArray(selNameArr) || selNameArr.length === 0) {
-          return undefined;
-        }
-
-        // 查找当前元素的索引
-        const currentIndex = selNameArr.indexOf(selName);
-
-        // 如果元素不存在或已经是最后一个元素,返回undefined
-        if (currentIndex === -1 || currentIndex === selNameArr.length - 1) {
-          return undefined;
-        }
-
-        // 返回下一个元素
-        return selNameArr[currentIndex + 1];
-      }
-
-      // 处理选择事件
-      const doSelectItem = (item) => {
-        selectItem.value = item;
-        emit("update:modelValue", item.value); //修改本下拉菜单在vue中保存的值
-
-        // alert('item.value:'+item.value);
-        if (props.mode === "1") {
-          // mode 1 模式:修改隐藏字段值
-
-          let event = new CustomEvent(
-              "cascader-setHiddenVal-" + props.param.combField,
-              {
-                detail: {
-                  value: item.value,
-                },
-              }
-          );
-          window.dispatchEvent(event);
-        }
-        emit("change", item.value); //触发配置的change方法
-
-        //设置下级菜单的上级菜单当前值upperValue
-        let paramArr = undefined;
-        if (Array.isArray(props.param)) {
-          paramArr = props.param;
-        } else {
-          paramArr = [];
-          paramArr.push(props.param);
-        }
-
-        for (const oneParam of paramArr) {
-          //下个下拉菜单名
-          const nextSelName = getNextSel(props.name, oneParam.fieldOrd);
-          if (nextSelName) {
-            setTimeout(() => {
-              const openNextEvent = new CustomEvent(
-                  "cascader-open-" + nextSelName,
-                  {
-                    detail: {
-                      upperVal: item.value,
-                    },
-                  }
-              );
-              window.dispatchEvent(openNextEvent);
-            }, 100);
-          }
-        } // end for
-
-        hidePopup();
-
-        //下个下拉菜单名
-        // let nextSelName = getNextSel(props.name, props.param.fieldOrd);
-        // if(nextSelName){
-        //   // //设置下一级下拉菜单中保存的本下拉菜单值(upperValue)
-        //   // event = new CustomEvent('cascade-setUpperVal-'+nextSelName, {
-        //   //   detail: {
-        //   //     value: item.value
-        //   //   }
-        //   // });
-        //   // window.dispatchEvent(event);
-        //
-        //   //触发下一级下拉菜单,重新初始化下拉菜单项并弹出显示
-        //   event = new CustomEvent('cascader-open-' +nextSelName, {
-        //     detail: {
-        //       upperVal: item.value
-        //     }
-        //   });
-        //   window.dispatchEvent(event);
-        // }
-
-        // 只在手动选择时自动展开下一级
-        // if (!isAutoEcho.value) {
-        //   const nextLevel = props.level + 1;
-        //   setTimeout(() => {
-        //     const openNextEvent = new CustomEvent('open-next-cascader', {
-        //       detail: {
-        //         name: props.name,
-        //         level: nextLevel
-        //       }
-        //     });
-        //     window.dispatchEvent(openNextEvent);
-        //   }, 100);
-        // }
-      };
-
-      // 监听下一级展开事件 (仅 mode 2)
-      window.addEventListener("cascade-open", (event) => {
-        if (props.mode === "2") {
-          const { level } = event.detail;
-          if (level === props.level) {
-            popupWinVisible.value = true;
-          }
-        }
-      });
-
-      if (props.mode === "1") {
-        //如果是有隐藏字段的下拉菜单
-        // 监听回显事件
-        window.addEventListener(
-            "cascader-echo-" + props.name,
-            async (event) => {
-              const { name, value, isAuto, upperVal } = event.detail;
-              // level,
-              if (upperVal) {
-                upperValue.value = upperVal;
-                console.log(
-                    "value:" +
-                    value +
-                    ",upperValue:" +
-                    upperValue +
-                    ",初始化级联组件时props.name:" +
-                    props.name
-                );
-              }
-
-              // if (name === props.name && level === props.level) {
-              // 设置自动回显标记
-              isAutoEcho.value = true;
-
-              // if (props.opt.length === 0) {
-              // const loadDataEvent = new CustomEvent('cascader-load-data', {
-              //   detail: {
-              //     name: props.name,
-              //     level: props.level,
-              //     value: value
-              //   }
-              // });
-              // window.dispatchEvent(loadDataEvent);
-
-              //下面的代码只用于页面刚打开时,初始化级联菜单的回显值。
-
-              //Vue.watch用于监听数据的变化,并在数据变化时执行特定的回调函数。
-              //这段代码使用了 Vue.js 的 watch API 来监听 props.opt 的变化,如果props.opt有变化,则自动
-
-              //   const unwatch = Vue.watch(
-              //       () => props.opt,                // 监听的数据源(props.opt)
-              //       (newOptions) => {              // 回调函数
-              //         if (newOptions.length > 0) { // 条件判断
-              //           matchAndSelect(value);     // 执行逻辑
-              //           unwatch();                 // 停止监听
-              //         }
-              //       },
-              //       { immediate: true }            // 配置:立即触发一次
-              //   );
-              // } else {
-              //   matchAndSelect(value);
-              // }
-
-              // 初始化级联菜单在页面刚打开时的默认值
-              async function initDefaultValue(value) {
-                try {
-                  // alert(1);
-                  if (props.url && props.param
-                      // && props.modelValue 对于有rule编码规则的级联菜单(即mode=1),modelValue一定是空的,所以注释掉,修复mode=1的级联菜单无法回显问题。Ben(20251124)
-                  ) {
-                    // alert(2);
-                    /**
-                     *         let objectPickerParam=
-                     *             {"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"hksheng,hkshi,hkxian\"," +
-                     *                     "\"name\":\"hksheng\"," +
-                     *                     "\"cascadingName\":\"dq\",\"cascadingInputsName\":\"hkdqm\"," +
-                     *                     "\"codebook\":\"sheng\"}",
-                     *                 "objectpickertype":2,
-                     *                 "objectpickervalue":"440000"
-                     *             };
-                     */
-
-                    const objectPickerParam = {
-                      input: "false",
-                      cascadingLevel: props.param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
-                      name: props.name, //本下拉菜单名
-                      cascadingName: props.param.name, //级联菜单名
-                      cascadingInputsName: props.param.combField, //对象属性,即隐藏字段名,如:hkdqm
-                      codebook: props.param.codebook,
-                    };
-
-                    const objectPickerParamStr =
-                        JSON.stringify(objectPickerParam);
-
-                    const params = new URLSearchParams();
-                    params.append("objectpickerparam", objectPickerParamStr);
-                    params.append("objectpickertype", "2");
-                    params.append("objectpickervalue", value); //需回显的值
-
-                    axios
-                        .post(props.url, params, {
-                          headers: {
-                            "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                          },
-                        })
-                        .then((response) => {
-                          // alert(JSON.stringify(response.data));
-
-                          if ("timeout" == response.data.statusText) {
-                            alert("网络超时!");
-                            return;
-                          }
-
-                          if (response.data.result) {
-                            const keys = Object.keys(response.data.result);
-                            if (keys.length === 1) {
-                              let code = keys[0];
-                              let desc = response.data.result[keys[0]];
-                              clearAndInit1stOpt();
-                              props.opt.push({ label: desc, value: code });
-
-                              if (value) matchAndSelect(value);
-                              // updateSelectItem();
-
-                              // alert('props.opt:'+JSON.stringify(props.opt));
-                            }
-                          }
-                        });
-                  }
-                } catch (error) {
-                  alert(error);
-                  // callback(null, error.message); // 失败回调,传递错误
-                }
-              }
-
-              //下面的代码只用于页面刚打开时,初始化级联菜单的回显值。
-              initDefaultValue(value);
-
-              // 延迟重置自动回显标记
-              setTimeout(() => {
-                isAutoEcho.value = false;
-              }, 500);
-            }
-        );
-
-        // 被上级下拉菜单触发的,清除选中值和下拉菜单选项
-        window.addEventListener(
-            "cascader-cleanOpt-" + props.name,
-            async (event) => {
-              upperValue.value = "";
-
-              selectItem.value = ""; //清除本下拉菜单当前选中的值
-              emit("update:modelValue", ""); //通知父级
-
-              //清空所有下拉菜单项
-              if (props.opt) {
-                props.opt.length = 0;
-              } else {
-                props.opt = [];
-              }
-
-              //下个下拉菜单名
-              let nextSelName = getNextSel(props.name, props.param.fieldOrd);
-              // alert('nextSelName:'+nextSelName+'--,props.name:'+props.name);
-              if (nextSelName) {
-                //清下个下拉菜单选中值和选项
-                event = new CustomEvent("cascader-cleanOpt-" + nextSelName, {
-                  detail: {},
-                });
-                window.dispatchEvent(event);
-              }
-            }
-        );
-      } else if (props.mode === "2") {
-        //没隐藏字段的下拉菜单,在这初始化默认值
-
-        let needInitParam = undefined;
-        if (Array.isArray(props.param)) {
-          needInitParam = props.param[props.param.length - 1]; //只初始化数组最后一项
-          console.log("needInitParam最后一项:" + JSON.stringify(needInitParam));
-        } else {
-          needInitParam = props.param;
-        }
-
-        // 初始化级联菜单在页面刚打开时的默认值
-        async function initDefaultValue(value, param) {
-          try {
-            // alert(1);
-            if (props.url && param && props.modelValue) {
-              // alert(2);
-              /**
-               *        let param=
-               *             {"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"rylbm,gwid\"," +
-               *                     "\"name\":\"gwid\",\"cascadingName\":\"rylb_gw\"," +
-               *                     "\"codebook\":\"gwByRylb\"}",
-               *                 "objectpickertype":2,
-               *                 "objectpickervalue":"102121"};
-               */
-
-                  // alert('props.name:'+props.name+',props.param.fieldOrd:'+props.param.fieldOrd);
-
-              const objectPickerParam = {
-                    input: "false",
-                    cascadingLevel: param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
-                    name: props.name, //本下拉菜单名
-                    cascadingName: param.name, //级联菜单名
-                    codebook: param.codebook,
-                  };
-
-              const objectPickerParamStr = JSON.stringify(objectPickerParam);
-
-              const sendParams = new URLSearchParams();
-              sendParams.append("objectpickerparam", objectPickerParamStr);
-              sendParams.append("objectpickertype", "2");
-              sendParams.append("objectpickervalue", value); //需回显的值
-
-              axios
-                  .post(props.url, sendParams, {
-                    headers: {
-                      "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                    },
-                  })
-                  .then((response) => {
-                    // alert(JSON.stringify(response.data));
-
-                    if ("timeout" == response.data.statusText) {
-                      alert("网络超时!");
-                      return;
-                    }
-
-                    if (response.data.result) {
-                      const keys = Object.keys(response.data.result);
-
-                      console.log(
-                          "name:" +
-                          props.name +
-                          ",@@级联初始化默认值value:" +
-                          value +
-                          "--param:" +
-                          JSON.stringify(param) +
-                          "--objectPickerParamStr:" +
-                          objectPickerParamStr +
-                          "--response.data:" +
-                          JSON.stringify(response.data)
-                      );
-
-                      if (keys.length === 1) {
-                        let code = keys[0];
-                        let desc = response.data.result[keys[0]];
-
-                        if (props.opt)
-                          props.opt.length = 0; //通过修改数组的length属性,直接清空数组元素,内存会被自动释放。这是性能最优的方式
-                        else {
-                          props.opt = [];
-                        }
-                        props.opt.push({ label: desc, value: code });
-
-                        if (value) matchAndSelect(value);
-
-                        console.log(
-                            "GOOD mode2回显的默认值:" +
-                            JSON.stringify({ label: desc, value: code }) +
-                            "--props.param:" +
-                            JSON.stringify(param)
-                        );
-
-                        // updateSelectItem();
-
-                        // alert('props.opt:'+JSON.stringify(props.opt));
-                      }
-                    }
-                  });
-            }
-          } catch (error) {
-            alert(error);
-            // callback(null, error.message); // 失败回调,传递错误
-          }
-
-          // 重置自动回显标记
-          isAutoEcho.value = false;
-        }
-
-        // 初始化级联菜单在页面刚打开时的默认值
-        initDefaultValue(props.modelValue, needInitParam);
-
-        //设置mode2的下级下拉菜单的上级菜单当前值
-        setNextSelectUpperValue();
-      }
-
-      //选中要回显的默认值
-      const matchAndSelect = (value) => {
-        const matchedOption = props.opt.find((opt) => opt.value === value);
-        if (matchedOption) {
-          selectItem.value = matchedOption;
-          emit("update:modelValue", value);
-          emit("change", value);
-        }
-      };
-
-      const calculatePopupDirection = () => {
-        // 1. 获取select容器元素
-        const selectEl = document.querySelector(
-            `[name="${props.name}"]`
-        )?.nextElementSibling;
-        console.log("selectEl:" + selectEl, props.name);
-        if (!selectEl) return;
-
-        // 2. 获取位置信息
-        const selectRect = selectEl.getBoundingClientRect();
-        const viewportHeight = window.innerHeight;
-
-        // 3. 简单判断:如果下方剩余空间小于300px就向上弹出
-        const spaceBelow = viewportHeight - selectRect.bottom;
-
-        // 调试信息
-        console.log("空间判断:", {
-          elementBottom: selectRect.bottom,
-          viewportHeight,
-          spaceBelow,
-          willPopUp: spaceBelow < 300,
-          popupDirection: popupDirection.value,
-        });
-
-        // 4. 设置方向
-        popupDirection.value = spaceBelow < 300 ? "top" : "bottom";
-      };
-      //级联菜单点击事件
-      const togglePopup = () => {
-        if (!popupWinVisible.value) {
-          //如果当前下拉菜单是隐藏的,先ajax重新加载下拉菜单项,再显示。
-
-          showPopup();
-        } else {
-          hidePopup();
-        }
-      };
-
-      //显示下拉菜单,在此之前先清除下拉菜单项
-      const showPopup = () => {
-        //清空下拉菜单,并设置第一项的值为空
-        clearAndInit1stOpt();
-        Vue.nextTick(() => {
-          calculatePopupDirection();
-        });
-        let url = props.url;
-        let filterObj = props.param.filter;
-
-        if (filterObj) {
-          for (let k in filterObj) {
-            let v = filterObj[k];
-            url += "&" + k + "=" + v;
-          }
-        }
-
-        if (props.mode === "1") {
-          //如果是有隐藏字段的下拉菜单
-
-          console.log("666url:" + url);
-
-          // alert('url:'+url);
-
-          // 获取级联菜单所有下拉菜单项
-          async function getSelectItems(value) {
-            try {
-              // alert(1);
-              if (props.url && props.param) {
-                // alert(2);
-                /**
-                 *            param={"objectpickerparam":"{\"input\":\"false\",\"cascadingLevel\":\"hksheng,hkshi,hkxian\"," +
-                 *                     "\"name\":\"hksheng\",\"cascadingName\":\"dq\"," +
-                 *                     "\"cascadingInputsName\":\"hkdqm\",\"codebook\":\"sheng\"}",
-                 *                 "objectpickertype":1,//2表示获取要回显的一项,1表示获取所有下拉菜单项
-                 *                 "upperValue":"440000"
-                 *             };
-                 */
-
-                const objectPickerParam = {
-                  input: "false",
-                  cascadingLevel: props.param.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
-                  name: props.name, //本下拉菜单名
-                  cascadingName: props.param.name, //级联菜单名
-                  cascadingInputsName: props.param.combField, //对象属性,即隐藏字段名,如:hkdqm
-                  codebook: props.param.codebook,
-                };
-
-                console.log("mode1 upperValue.value:" + upperValue.value);
-
-                const objectPickerParamStr = JSON.stringify(objectPickerParam);
-
-                const params = new URLSearchParams();
-                params.append("objectpickerparam", objectPickerParamStr);
-                params.append("objectpickertype", "1");
-                if (upperValue.value) {
-                  params.append("upperValue", upperValue.value);
-                }
-                // params.append('objectpickervalue', value); //需回显的值
-
-                axios
-                    .post(url, params, {
-                      headers: {
-                        "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                      },
-                    })
-                    .then((response) => {
-                      if ("timeout" == response.data.statusText) {
-                        alert("网络超时!");
-                        return;
-                      }
-
-                      if (response.data.result) {
-                        const keys = Object.keys(response.data.result);
-                        console.log(
-                            "params:" +
-                            params +
-                            "@@response.data:" +
-                            JSON.stringify(response.data)
-                        );
-
-                        if (keys.length > 0) {
-                          for (let k in response.data.result) {
-                            props.opt.push({
-                              label: response.data.result[k],
-                              value: k,
-                            });
-                          }
-
-                          if (!popupWinVisible.value) {
-                            popupWinVisible.value = true; // 确保下拉框打开
-                          }
-
-                          console.log("props.opt11:" + JSON.stringify(props.opt));
-                        }
-                      }
-                    });
-              }
-            } catch (error) {
-              alert(error);
-              // callback(null, error.message); // 失败回调,传递错误
-            }
-          }
-
-          getSelectItems(props.modelValue);
-        } else if (props.mode === "2") {
-          //没隐藏字段的下拉菜单
-
-          let needInitParam = undefined;
-          if (Array.isArray(props.param)) {
-            needInitParam = props.param[props.param.length - 1]; //只初始化数组最后一项
-            console.log(
-                "needInitParam最后一项:" + JSON.stringify(needInitParam)
-            );
-          } else {
-            needInitParam = props.param;
-          }
-
-          // 获取级联菜单所有下拉菜单项
-          async function getSelectItems(value, sendParam) {
-            try {
-              // alert(1);
-              if (props.url && sendParam) {
-                // alert(2);
-                /**
-                 *            param="{\"input\":\"false\",\"cascadingLevel\":\"dwid,sjryid\",
-                 *            \"ryid\":\"111121\",\"name\":\"sjryid\",
-                 *            \"cascadingName\":\"dw_sjry\",\"codebook\":\"sjryByDw\"}"
-                 */
-
-                const objectPickerParam = {
-                  input: "false",
-                  cascadingLevel: sendParam.fieldOrd.join(","), //如:"hksheng,hkshi,hkxian"
-                  name: props.name, //本下拉菜单名
-                  cascadingName: sendParam.name, //级联菜单名
-                  codebook: sendParam.codebook,
-                };
-
-                console.log("mode2 upperValue.value:" + upperValue.value);
-
-                const objectPickerParamStr = JSON.stringify(objectPickerParam);
-
-                const params = new URLSearchParams();
-                params.append("objectpickerparam", objectPickerParamStr);
-                params.append("objectpickertype", "1");
-                if (upperValue.value) {
-                  params.append("upperValue", upperValue.value);
-                }
-                // params.append('objectpickervalue', value); //需回显的值
-
-                axios
-                    .post(url, params, {
-                      headers: {
-                        "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                      },
-                    })
-                    .then((response) => {
-                      if ("timeout" == response.data.statusText) {
-                        alert("网络超时!");
-                        return;
-                      }
-
-                      if (response.data.result) {
-                        const keys = Object.keys(response.data.result);
-                        console.log(
-                            "params:" +
-                            params +
-                            "@@response.data:" +
-                            JSON.stringify(response.data)
-                        );
-
-                        if (keys.length > 0) {
-                          for (let k in response.data.result) {
-                            props.opt.push({
-                              label: response.data.result[k],
-                              value: k,
-                            });
-                          }
-
-                          if (!popupWinVisible.value) {
-                            popupWinVisible.value = true; // 确保下拉框打开
-                          }
-
-                          console.log("props.opt11:" + JSON.stringify(props.opt));
-                        }
-                      }
-                    });
-              }
-            } catch (error) {
-              alert(error);
-              // callback(null, error.message); // 失败回调,传递错误
-            }
-          }
-
-          getSelectItems(props.modelValue, needInitParam);
-
-          // popupWinVisible.value = !popupWinVisible.value;
-        }
-      };
-
-      const hidePopup = () => {
-        popupWinVisible.value = false;
-      };
-
-      // 合并所有的 onMounted 逻辑
-      Vue.onMounted(() => {
-        window.addEventListener("resize", calculatePopupDirection);
-
-        // 1. 监听展开下一级事件
-        window.addEventListener("open-next-cascader", (event) => {
-          const { name, level } = event.detail;
-          if (name === props.name && level === props.level) {
-            popupWinVisible.value = true;
-          }
-        });
-
-        // 2. 监听级联事件
-        window.addEventListener("cascader-change", (event) => {
-          const { name, level, value } = event.detail;
-          if (name === props.name && level < props.level) {
-            selectItem.value = { label: "", value: "" };
-            emit("update:modelValue", "");
-            if (ssHidden) {
-              ssHidden.updateValue(value);
-            }
-          }
-        });
-      });
-      Vue.onUnmounted(() => {
-        window.removeEventListener("resize", calculatePopupDirection);
-      });
-      // 监听值变化,处理回显 (mode 2)
-      Vue.watch(
-          () => props.modelValue,
-          (newVal) => {
-            if (props.mode === "2" && newVal) {
-              // 使用 watchEffect 替代嵌套的 watch
-              Vue.watchEffect(() => {
-                if (props.opt.length > 0) {
-                  const matchedOption = props.opt.find(
-                      (opt) => opt.value === newVal
-                  );
-                  if (matchedOption) {
-                    selectItem.value = matchedOption;
-                  }
-                }
-              });
-            } else {
-              // 原有的值变化处理
-              const item = props.opt.find((it) => it.value === newVal);
-              if (item) {
-                selectItem.value = item;
-              } else {
-                selectItem.value = { label: "", value: "" };
-              }
-            }
-          },
-          { immediate: true }
-      );
-
-      // 监听选项变化,当数据加载完成时进行匹配
-      Vue.watch(
-          () => props.opt,
-          (newOptions) => {
-            if (newOptions.length > 0) {
-              const matchedOption = newOptions.find(
-                  (opt) => opt.value === selectItem.value.value
-              );
-              if (matchedOption) {
-                selectItem.value = matchedOption;
-                emit("update:modelValue", matchedOption.value);
-                emit("change", matchedOption.value);
-              }
-            }
-          }
-      );
-
-      return {
-        selectItem,
-        popupWinVisible,
-        popupDirection,
-        togglePopup,
-        hidePopup,
-        doSelectItem,
-      };
-    },
-
-    template: `
-      <div class="input ss-ccp-container" style="position: relative" :style="{width: width}">
-        <input type="hidden" :name="name" :value="modelValue">
-        <div class="select-container" @mouseleave="hidePopup">
-          <div class="input" @click="togglePopup">
-            <input 
-              type="hidden"
-              :name="name"
-              :value="selectItem.value"
-            />
-            <input
-              :placeholder="placeholder"
-              :value="selectItem.label"
-              disabled
-              style="pointer-events: none;"
-            />
-            <div class="suffix">
-              <ss-form-icon :class="popupWinVisible ? 'form-icon-transform-select select' : 'form-icon-select'" />
-            </div>
-          </div>
-
-          <div v-show="popupWinVisible" class="popup-win " :class="popupDirection">
-            <div v-if="opt && opt.length > 0" class="popup-content">
-              <div class="content-area">
-                <div 
-                  v-for="(item, index) in opt" 
-                  :key="index" 
-                  @click="doSelectItem(item)" 
-                  :class="{ active: item.value === selectItem.value }"
-                >
-                  <span class="check-icon">
-                    <ss-form-icon class="form-icon-select-checked" />
-                  </span>
-                  <span>{{ item.label }}</span>
-                </div>
-              </div>
-            </div>
-            <div v-else class="popup-content">
-              <div class="content-area">
-                <div class="content-area">
-                  <span>无选项</span>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    `,
-  };
-  // ss-date-picker 日期时间选择器组件
-  const SsDatePicker = {
-    name: "SsDatePicker",
-    props: {
-      modelValue: {
-        type: [String, Number, Date],
-        default: "",
-      },
-      name: {
-        type: String,
-        required: true,
-      },
-      type: {
-        type: String,
-        default: "date",
-        validator: (value) => ["date", "datetime", "time"].includes(value),
-      },
-      fmt: {
-        type: String,
-        default: null,
-      },
-      placeholder: {
-        type: String,
-        default: "",
-      },
-      width: {
-        type: String,
-        default: "100%",
-      },
-    },
-
-    emits: ["update:modelValue"],
-
-    setup(props, { emit }) {
-      const errMsg = ref("");
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          console.log("validate", window.ssVm.validateField(props.name));
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-      // 根据type确定默认格式
-      const defaultFormat = computed(() => {
-        switch (props.type) {
-          case "datetime":
-            return "YYYY-MM-DD HH:mm:ss";
-          case "date":
-            return "YYYY-MM-DD";
-          case "time":
-            return "HH:mm:ss";
-        }
-      });
-      const convertJavaFormatToElement = (javaFormat) => {
-        if (!javaFormat) return null;
-        return javaFormat
-            .replace("yyyy", "YYYY")
-            .replace("MM", "MM")
-            .replace("dd", "DD")
-            .replace("HH", "HH")
-            .replace("mm", "mm")
-            .replace("ss", "ss");
-      };
-
-      const finalFormat = computed(() => {
-        if (props.fmt) {
-          return convertJavaFormatToElement(props.fmt);
-        }
-        return defaultFormat.value;
-      });
-
-      // 使用 resolveComponent 获取组件
-      const ElDatePicker = resolveComponent("ElDatePicker");
-      const ElTimePicker = resolveComponent("ElTimePicker");
-      const SsFormIcon = resolveComponent("SsFormIcon");
-      const ElIcon = resolveComponent("ElIcon");
-
-      const handleValueUpdate = (val) => {
-        emit("update:modelValue", val);
-        emit("change", val); // 同时触发 change 事件
-        setTimeout(() => {
-          validate();
-        }, 50);
-      };
-      const dateType = computed(() => {
-        const fmt = props.fmt || "";
-        if (fmt.includes("HH:mm:ss")) {
-          return "datetime";
-        } else if (fmt.includes("HH:mm")) {
-          return "datetime";
-        } else if (fmt.includes("mm:ss")) {
-          return "time";
-        }
-        return "date";
-      });
-
-      let useTimePicker = true;
-      //"yyyy-MM-dd HH:mm:ss";  "日期字符串格式在java的写法",传到本组件fmt属性也是按这个格式
-      if (props.fmt) {
-        //有fmt属性,则以fmt属性优先判断类型
-        if (/[dMy]/.test(props.fmt)) {
-          //如果有传入日期格式,且含年月日
-          useTimePicker = false;
-        } else {
-          useTimePicker = true;
-        }
-      } else if (props.type !== "time") {
-        useTimePicker = false;
-      }
-
-      return () =>
-          h("div", { class: "ss-date-picker", style: { width: props.width } }, [
-            h("input", {
-              type: "hidden",
-              name: props.name,
-              value: props.modelValue,
-            }),
-            // 选择组件
-            h(useTimePicker ? ElTimePicker : ElDatePicker, {
-              modelValue: props.modelValue,
-              "onUpdate:modelValue": handleValueUpdate,
-              type: dateType.value,
-              format: finalFormat.value,
-              "value-format": finalFormat.value,
-              clearable: true,
-              placeholder: props.placeholder,
-              class: "custom-date-picker", // 用于自定义样式
-              "time-arrow-control": props.type === "datetime", // 修改这里
-              size: "large", // 添加这一行,改为 large 尺寸
-              style: { width: "100%" },
-              "prefix-icon": h(SsFormIcon, { class: "form-icon-time" }),
-            }),
-          ]);
-    },
-  };
-  // ss-icon 图标
-  const SsIcon = {
-    name: "SsIcon",
-    props: {
-      name: { type: String, required: true },
-      size: { type: [Number, String], default: 16 },
-      unit: { type: String, default: "px" },
-      color: String,
-      type: {
-        type: String,
-        default: ssIcon.name,
-        validator: function (value) {
-          return [ssIcon, commonIcon].some((icon) => icon.name === value);
-        },
-      },
-    },
-    emits: ["update:modelValue", "input", "blur", "change"],
-    setup(props, { emit }) {
-      const useIconType = computed(() => {
-        return [ssIcon, commonIcon].find(
-            (iconConfig) => iconConfig.name === props.type
-        );
-      });
-      const iconName = computed(() => {
-        const iconConfig = useIconType.value; // 注意:使用 .value 来访问响应式引用的值
-        if (!iconConfig) {
-          console.error(`Icon type "${props.type}" not found.`);
-          return "";
-        }
-        const iconType = iconConfig.types[props.name];
-        if (!iconType) {
-          console.error(
-              `Icon name "${props.name}" not found in type "${props.type}".`
-          );
-          return "";
-        }
-        return `${iconConfig.prefix}${iconType}`;
-      });
-
-      // 类似地,你可以计算 fontFamily 和 style
-      const fontFamily = computed(() => {
-        return useIconType.value ? useIconType.value.family : "";
-      });
-      // console.log(iconName.value,fontFamily.value)
-      const style = computed(() => {
-        const sizeStyle = isNum(props.size)
-            ? `${props.size}${props.unit}`
-            : props.size;
-        const styleObj = {
-          fontSize: sizeStyle,
-          color: props.color || "",
-        };
-        return toStyleStr(styleObj);
-      });
-
-      // 使用渲染函数定义模板逻辑
-      return () =>
-          h("i", {
-            class: ["icon-container", iconName.value, fontFamily.value],
-            style: style.value,
-          });
-    },
-  };
-  // 通用icon
-  const SsCommonIcon = {
-    name: "SsCommonIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("i", {
-            class: props.class + " common-icon",
-          });
-    },
-  };
-  // 登录页icon
-  const SsLoginIcon = {
-    name: "SsLoginIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " login-icon",
-          });
-    },
-  };
-  // 弹窗icon
-  const SsDialogIcon = {
-    name: "SsDialogIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("i", {
-            class: props.class + " dialog-icon",
-          });
-    },
-  };
-  // 全局左侧导航图标组件
-  const SsNavIcon = {
-    name: "SsNavIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " nav-icon",
-          });
-    },
-  };
-  // 顶部工具栏图标组件
-  const SsHeaderIcon = {
-    name: "SsHeaderIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " header-icon",
-          });
-    },
-  };
-  // 全局菜单图标组件
-  const SsGolbalMenuIcon = {
-    name: "SsGolbalMenuIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " global-menu-icon",
-          });
-    },
-  };
-  // 全局查询列表卡片图标
-  const SsCartListIcon = {
-    name: "SsCartListIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " cart-list-icon",
-          });
-    },
-  };
-  // 全局底部工具栏图标组件
-  const SsQuickIcon = {
-    name: "SsQuickIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " quick-icon",
-          });
-    },
-  };
-  // 表单组件icon
-  const SsFormIcon = {
-    name: "SsFormIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " form-icon",
-          });
-    },
-  };
-  // 弹窗底部按钮icon
-  const SsBottomDivIcon = {
-    name: "SsBottomDivIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("div", {
-            class: props.class + " bottom-div-icon",
-          });
-    },
-  };
-  // editor组件icon
-  const SsEditorIcon = {
-    name: "SsEditorIcon",
-    props: {
-      class: {
-        type: String,
-        required: true,
-      },
-    },
-    setup(props) {
-      return () =>
-          h("i", {
-            class: props.class + " editor-icon",
-          });
-    },
-  };
-  // ss-validate校验器
-  const SsValidate = {
-    name: "SsValidate",
-    props: {
-      errMsg: { type: String },
-      textAlign: { type: String, default: "left" },
-      style: { type: Object, default: () => ({}) },
-    },
-    template: `<div class="validate-vline"></div>
-    <div class="validate-tip" :style="style">
-      <div class="tip" :style="{ textAlign: textAlign }">{{ errMsg }}</div>
-      <div class="tip-more" :style="{ textAlign: textAlign }">{{ errMsg }}</div>
-    </div>`,
-  };
-  // ss-onoff-array 多选按钮 数组形式
-  const SsonoffArray = {
-    name: "SsonoffArray",
-    props: {
-      name: {
-        type: String,
-        required: true,
-      },
-      opt: {
-        type: Array,
-        default: () => [],
-      },
-      defaultValue: [String, Number, Array],
-      modelValue: [String, Number, Array],
-      multiple: {
-        // 新增多选模式属性
-        type: Boolean,
-        default: false,
-      },
-    },
-    emits: ["update:modelValue"], // 允许更新 v-model 绑定的值
-    setup(props, { emit }) {
-      console.log("多选按钮", props.opt);
-      // 使用数组来存储选中值
-      const checkedValue = ref(
-          props.multiple
-              ? Array.isArray(props.defaultValue)
-                  ? props.defaultValue
-                  : []
-              : props.defaultValue
-      );
-      const errMsg = ref(props.errTip);
-
-      // 生成icon名字
-      const genIconName = (itemValue) => {
-        if (props.multiple) {
-          return checkedValue.value.includes(itemValue)
-              ? "form-icon-onoff-checked"
-              : "form-icon-onoff-unchecked";
-        }
-        return checkedValue.value === itemValue
-            ? "form-icon-onoff-checked"
-            : "form-icon-onoff-unchecked";
-      };
-      // 选中项
-      const selectItem = (value) => {
-        if (props.multiple) {
-          // 多选模式
-          const index = checkedValue.value.indexOf(value);
-          if (index === -1) {
-            checkedValue.value = [...checkedValue.value, value];
-          } else {
-            checkedValue.value = checkedValue.value.filter((v) => v !== value);
-          }
-        } else {
-          // 单选模式
-          checkedValue.value = value;
-        }
-
-        emit("update:modelValue", checkedValue.value);
-        nextTick(() => {
-          // 触发验证
-          if (window.ssVm) {
-            window.ssVm.validateField(props.name);
-          }
-        });
-      };
-
-      return { checkedValue, genIconName, selectItem };
-    },
-    // 使用渲染函数定义模板逻辑
-    render() {
-      const SsFormIcon = resolveComponent("ss-form-icon");
-      return h("div", { class: "radio-container" }, [
-        // 根据情况创建 input
-        this.multiple
-            ? this.checkedValue.length
-                ? // 多选且有选中值:为选中项创建 input
-                this.checkedValue.map((value) =>
-                    h("input", {
-                      type: "checkbox",
-                      name: this.name,
-                      value: value,
-                      checked: true,
-                      style: { display: "none" },
-                    })
-                )
-                : // 多选但没有选中值:创建一个空值 input
-                h("input", {
-                  type: "hidden",
-                  name: this.name,
-                  value: "",
-                })
-            : // 单选模式:创建一个 input
-            h("input", {
-              type: "hidden",
-              name: this.name,
-              value: this.checkedValue || "",
-            }),
-
-        this.opt.map((item, i) =>
-            h(
-                "div",
-                {
-                  key: i,
-                  class: {
-                    checked: this.multiple
-                        ? this.checkedValue.includes(item.value)
-                        : this.checkedValue === item.value,
-                  },
-                  style: { width: item.width },
-                  onClick: () => this.selectItem(item.value),
-                },
-                [
-                  h("span", null, item.label),
-                  h("div", { class: "mark" }, [
-                    h(SsFormIcon, {
-                      class: this.genIconName(item.value),
-                    }),
-                  ]),
-                ]
-            )
-        ),
-      ]);
-    },
-  };
-
-  // ss-onoff 一个按钮
-  const Ssonoff = {
-    name: "Ssonoff",
-    props: {
-      name: {
-        type: String,
-        required: true,
-      },
-      label: {
-        type: String,
-        required: true,
-      },
-      value: {
-        type: [String, Number],
-        required: true,
-      },
-      width: {
-        type: String,
-        default: "",
-      },
-      modelValue: [String, Number, Array],
-      multiple: {
-        type: Boolean,
-        default: false,
-      },
-      null: {
-        type: Boolean,
-        default: true,
-      },
-    },
-    emits: ["update:modelValue"],
-
-    setup(props, { emit }) {
-      const parseModelValue = (val) => {
-        if (!val) return [];
-        // 如果以逗号开头,去掉开头的逗号
-        const cleanValue = val.toString().replace(/^,+/, "");
-        if (cleanValue.includes("|")) {
-          return cleanValue.split("|");
-        }
-        if (cleanValue.includes(",")) {
-          return cleanValue.split(",");
-        }
-        return [cleanValue];
-      };
-      // 判断当前按钮是否选中
-      const isChecked = computed(() => {
-        if (props.multiple) {
-          const currentValue = parseModelValue(props.modelValue);
-          return currentValue.includes(props.value.toString());
-
-          // return Array.isArray(props.modelValue) && props.modelValue.includes(props.value);
-        }
-        return (props.modelValue+'') === (props.value+'');//强转为字符串类型再比较(改之前是数字类型和字符串类型作比较,永远为false) Ben 20251206
-      });
-
-      // 切换选中状态
-      const toggleSelect = () => {
-        if (props.multiple) {
-          const currentValue = parseModelValue(props.modelValue);
-          const index = currentValue.indexOf(props.value.toString());
-          let newValue;
-
-          if (index === -1) {
-            // 选中当前项
-            newValue = [...currentValue, props.value];
-          } else {
-            // 取消选中当前项
-            const filteredValue = currentValue.filter((v) => v !== props.value.toString());
-
-            // 如果不允许为空且取消后为空,则阻止取消操作
-            if (!props.null && filteredValue.length === 0) {
-              return; // 阻止取消最后一项
-            }
-
-            newValue = filteredValue;
-          }
-          emit("update:modelValue", newValue.join(","));
-        } else {
-          // 单选模式
-          const currentValue = parseModelValue(props.modelValue);
-          const isCurrentlySelected = currentValue.includes(props.value.toString());
-
-          if (!isCurrentlySelected) {
-            // 选中当前项
-            emit("update:modelValue", props.value);
-          } else {
-            // 取消选中当前项
-            // 如果不允许为空且当前只有这一项被选中,则阻止取消操作
-            if (!props.null && currentValue.length === 1) {
-              return; // 阻止取消唯一选中项
-            }
-            emit("update:modelValue", "");
-          }
-        }
-
-        nextTick(() => {
-          // 触发验证
-          if (window.ssVm) {
-            window.ssVm.validateField(props.name);
-          }
-        });
-      };
-
-      return { isChecked, toggleSelect };
-    },
-
-    render() {
-      const SsFormIcon = resolveComponent("ss-form-icon");
-      return h("div", { class: "radio-container2" }, [
-        // 隐藏的表单元素
-        this.multiple
-            ? h("input", {
-              type: "hidden",
-              name: `${this.name}`, // 多选模式下使用数组形式的 name
-              value: this.isChecked ? this.value : "",
-            })
-            : this.isChecked &&
-            h("input", {
-              // 只有当前按钮被选中时才创建 input
-              type: "hidden",
-              name: this.name,
-              value: this.value,
-            }),
-
-        // 按钮显示
-        h(
-            "div",
-            {
-              class: { checked: this.isChecked },
-              style: { width: this.width },
-              onClick: this.toggleSelect,
-            },
-            [
-              h("span", null, this.label),
-              h("div", { class: "mark" }, [
-                h(SsFormIcon, {
-                  class: this.isChecked
-                      ? "form-icon-onoff-checked"
-                      : "form-icon-onoff-unchecked",
-                }),
-              ]),
-            ]
-        ),
-      ]);
-    },
-  };
-
-  // ss-textarea
-  const SsTextarea = {
-    name: "SsTextarea",
-    props: {
-      name: {
-        type: String,
-        required: true,
-      },
-      placeholder: {
-        type: String,
-        default: "请输入",
-      },
-      defaultValue: [String, Number],
-      modelValue: [String, Number],
-    },
-    emits: ["update:modelValue"],
-    setup(props, { emit }) {
-      const inputValue = ref(props.modelValue || props.defaultValue || "");
-
-      // 监听 modelValue 变化
-      watch(
-          () => props.modelValue,
-          (newVal) => {
-            inputValue.value = newVal;
-          }
-      );
-
-      // 输入事件处理
-      const onInput = (event) => {
-        const newValue = event.target.value;
-        inputValue.value = newValue;
-        emit("update:modelValue", newValue);
-        // 触发验证
-        if (window.ssVm) {
-          window.ssVm.validateField(props.name);
-        }
-      };
-
-      // 失焦时验证
-      const onBlur = () => {
-        if (window.ssVm) {
-          window.ssVm.validateField(props.name);
-        }
-      };
-
-      return { inputValue, onInput, onBlur };
-    },
-    render() {
-      return h("div", { class: "textarea-container" }, [
-        h("div", { class: "textarea" }, [
-          // 添加隐藏的 input 用于验证
-          h("input", {
-            type: "hidden",
-            name: this.name,
-            value: this.inputValue || "",
-          }),
-          h("textarea", {
-            placeholder: this.placeholder,
-            value: this.inputValue,
-            onInput: this.onInput,
-            onBlur: this.onBlur,
-          }),
-        ]),
-      ]);
-    },
-  };
-  // ss-editor 富文本编辑器 基于Jodit
-  const SsEditor = {
-    name: "SsEditor",
-    props: {
-      modelValue: {
-        type: String,
-        default: "",
-      },
-      name: {
-        type: String,
-        default: "",
-      },
-      url: {
-        type: String,
-        default: "",
-      },
-      height: {
-        type: [Number, String],
-        default: 400,
-      },
-      placeholder: {
-        type: String,
-        default: "请输入内容",
-      },
-      readonly: {
-        type: Boolean,
-        default: false,
-      },
-      uploadUrl: {
-        type: String,
-        default: "/ulByHttp",//原值为“upload” Ben(20251205)
-      },
-      param: {
-        type: Object,
-        default: () => ({}),
-      },
-    },
-
-    emits: ["update:modelValue", "ready", "change"],
-
-    setup(props, { emit }) {
-      const SsEditorIcon = resolveComponent("SsEditorIcon");
-      const editorRef = ref(null);
-      let editorContent = '';//保存富文本编辑器里面的富文本内容
-      const uniqueId = "editor-" + Date.now();
-      const errMsg = Vue.ref("");
-      let fjid = ref(props.param.button.val);
-      let fjName = props.param.button.desc;
-      let mode = props.param.mode;
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          console.log("validate", window.ssVm.validateField(props.name));
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-      onMounted(() => {
-        validate();
-        const editor = Jodit.make(`#${uniqueId}`, {
-          height: props.height,
-          placeholder: props.placeholder,
-          readonly: props.readonly,
-          language: "zh_cn",
-          i18n: {
-            zh_cn: {
-              Link: "链接",
-              URL: "链接",
-              "No follow": "无跟踪",
-              "Class name": "类名",
-              Image: "图片",
-              File: "文件",
-              "Line height": "行高",
-              Alternative: "描述",
-              "Alternative text": "描述",
-              "Lower Alpha": "小写字母",
-              "Upper Alpha": "大写字母",
-              "Upper Roman": "大写罗马数字",
-              "Lower Roman": "小写罗马数字",
-              "Lower Greek": "小写希腊字母",
-              "Lower Letter": "小写字母",
-              "Upper Letter": "大写字母",
-            },
-          },
-          showXPathInStatusbar: false,
-          showCharsCounter: false,
-          showWordsCounter: false,
-          allowResizeY: false,
-          toolbarSticky: false,
-
-          statusbar: false,
-          uploader: {
-            url: props.uploadUrl,
-            format: "json",
-            method: "POST",
-            filesVariableName: function (i) {
-              return "imgs[" + i + "]";
-            },
-            headers: {
-              Accept: "application/json",
-            },
-            prepareData: function (formData) {
-              // 这里可以在发送前处理表单数据
-              return formData;
-            },
-            isSuccess: function (resp) {
-              console.log("isSuccess resp:", resp);
-              return resp.code === 0;
-            },
-            getMessage: function (resp) {
-              console.log("getMessage resp:", resp);
-              return resp.msg || "上传失败";
-            },
-            process: function (resp) {
-              console.log("process resp:", resp);
-              return resp.data.url;
-            },
-            error: function (e) {
-              console.error("上传失败:", e.message);
-            },
-            defaultHandlerSuccess: function (resp) {
-              console.log("上传成功:", resp);
-            },
-            defaultHandlerError: function (err) {
-              console.error("上传错误:", err);
-            },
-            contentType: function (requestData) {
-              // 可以根据需要修改 Content-Type
-              return false; // 让浏览器自动设置
-            },
-          },
-
-          // 自定义字体列表
-          controls: {
-            font: {
-              list: {
-                Arial: "Arial",
-                SimSun: "宋体",
-                SimHei: "黑体",
-                "Microsoft YaHei": "微软雅黑",
-                KaiTi: "楷体",
-                FangSong: "仿宋",
-                "Times New Roman": "Times New Roman",
-                "Courier New": "Courier New",
-              },
-            },
-            customLinkButton: {
-              name: "link",
-              tooltip: "附件",
-              exec: function (editor) {
-                // 按钮点击时的处理函数
-                console.log("附件点击了");
-                console.log("param", props.param);
-                console.log("cmsAddUrl",props.param.button.cmsAddUrl);
-
-                if (fjid.value == null || fjid.value == "") {
-                  $.ajax({
-                    type: "post",
-                    url: props.param.button.cmsAddUrl,
-                    async: false,
-                    data: {
-                      name: "fjid",
-                      ssNrObjName: "sh",
-                      ssNrObjId: "",
-                    },
-                    success: function (_fjid) {
-                      console.log("cmsAddUrl success", _fjid);
-                      fjid.value = _fjid;
-                    },
-                  });
-                }
-                var str =
-                    "&nrid=T-" +
-                    fjid.value +
-                    "&objectId=" +
-                    fjid.value +
-                    "&objectName=" +
-                    fjName +
-                    "&callback=" +
-                    (window["fjidCallbackName"] || "");
-                console.log("str", str);
-                SS.openDialog({
-                  src: props.param.button.cmsUpdUrl + str,
-                  headerTitle: "编辑",
-                  width: 900,
-                  high: 664,
-                  zIndex:51
-                });
-                // ss.display.showComponent({
-                //   show: ["wdDialog"],
-                //   url: props.param.button.cmsUpdUrl + str,
-                //   title: "编辑",
-                //   width: 900,
-                //   high: 664,
-                // });
-              },
-            },
-          },
-          toolbarAdaptive: true,
-          buttons: [
-            "fullsize",
-            "bold",
-            "italic",
-            "underline",
-            "strikethrough",
-            "eraser",
-            "|",
-            "font",
-            "fontsize",
-            "brush",
-            "paragraph",
-            "|",
-            "left",
-            "center",
-            "right",
-            "justify",
-            "|",
-            "ul",
-            "ol",
-            "indent",
-            "outdent",
-            "|",
-            "image",
-            "table",
-            "customLinkButton",
-            "print",
-            "|",
-            "undo",
-            "redo",
-            "find",
-          ],
-          // 中等宽度时显示的按钮
-          buttonsMD: [
-            "fullsize",
-            "bold",
-            "italic",
-            "underline",
-            "strikethrough",
-            "eraser",
-            "|",
-            "font",
-            "fontsize",
-            "brush",
-            "paragraph",
-            "|",
-            "font",
-            "fontsize",
-            "|",
-            "left",
-            "center",
-            "right",
-            "justify",
-            "|",
-            "image",
-            "customLinkButton",
-            "|",
-            "dots", // 其余按钮会自动进入 dots 菜单
-          ],
-
-          // 小屏幕时显示的按钮
-          buttonsSM: ["fullsize", "bold", "italic", "|", "image", "|", "dots"],
-
-          // 超小屏幕时显示的按钮
-          buttonsXS: ["fullsize", "bold", "|", "dots"],
-          // 设置响应式断点
-          sizeLG: 1024, // 大屏幕
-          sizeMD: 768, // 中等屏幕
-          sizeSM: 576, // 小屏幕
-          // 自定义图标
-          getIcon: function (name, clearName) {
-            // 定义图标映射
-            const iconMap = {
-              bold: "editor-icon-bold",
-              italic: "editor-icon-italic",
-              underline: "editor-icon-underline",
-              strikethrough: "editor-icon-strikethrough",
-              eraser: "editor-icon-eraser",
-              copyformat: "editor-icon-copyformat",
-              font: "editor-icon-font",
-              fontsize: "editor-icon-fontsize",
-              brush: "editor-icon-brush",
-              paragraph: "editor-icon-paragraph",
-              left: "editor-icon-align-left",
-              center: "editor-icon-align-center",
-              right: "editor-icon-align-right",
-              justify: "editor-icon-align-justify",
-              ul: "editor-icon-ul",
-              ol: "editor-icon-ol",
-              indent: "editor-icon-indent",
-              outdent: "editor-icon-outdent",
-              image: "editor-icon-image",
-              file: "editor-icon-file",
-              video: "editor-icon-video",
-              table: "editor-icon-table",
-              link: "editor-icon-link",
-              source: "editor-icon-source",
-              eye: "editor-icon-preview",
-              fullsize: "editor-icon-fullsize",
-              shrink: "editor-icon-fullsize-exit", // 添加退出全屏图标
-
-              print: "editor-icon-print",
-              undo: "editor-icon-undo",
-              redo: "editor-icon-redo",
-              search: "editor-icon-find",
-              selectall: "editor-icon-selectall",
-            };
-            // 获取对应的图标类名
-            const iconClass = iconMap[clearName] || iconMap[name];
-
-            if (iconClass) {
-              // 返回带有我们自定义图标类的 span 元素
-              return `<span class="editor-icon ${iconClass}"></span>`;
-            }
-
-            return null;
-          },
-        });
-
-
-
-        // 设置初始值
-        editor.value = editorContent;
-        // editor.value = props.modelValue;
-
-        // 监听变化
-        editor.events.on("change", () => {
-          // emit("update:modelValue", editor.value);
-          editorContent = editor.value;
-          // alert('editorContent:'+editorContent);
-          let contentElements = document.getElementsByName(props.name.replace(/wj$/, "") + "Edit");
-          if(contentElements.length>0){
-            contentElements[0].value = editorContent;
-          }
-          emit("change", editor.value);
-          setTimeout(() => {
-            validate();
-          }, 50);
-        });
-
-        // 保存编辑器实例
-        editorRef.value = editor;
-
-        emit("ready", editor);
-
-        //回显编辑器富文本文件
-        if (props.url ) {
-          const params = new URLSearchParams();
-
-        if(mode)
-          params.append("mode", mode);
-
-          if(props.modelValue)
-            params.append("path", props.modelValue);
-
-          // alert('props.url:'+props.url+',props.modelValue:'+props.modelValue);
-
-          axios
-              .post(props.url, params, {
-                headers: {
-                  "Content-Type": "application/x-www-form-urlencoded", // 必须手动设置!
-                },
-              })
-              .then((response) => {
-                // alert(JSON.stringify(response.data));
-
-                if ("timeout" == response.data.statusText) {
-                  alert("网络超时!");
-                  return;
-                }
-
-                let content = response.data.content;
-                if (content) {
-                  // editor.value = content;
-                  editorRef.value.value = content;
-                  editorContent = content;
-                  // alert('editor.value:'+editor.value)
-                }
-
-                let filePath = response.data.path;
-                // alert('response.data:'+JSON.stringify(response.data));
-                if(filePath){
-                  props.modelValue = filePath;
-                  emit("update:modelValue", filePath);
-                }
-              });
-        }
-      });
-
-      // 监听值变化
-      watch(
-          // () => props.modelValue,
-          () => editorContent,
-          (newValue) => {
-            if (editorRef.value && newValue !== editorRef.value.value) {
-              editorRef.value.value = newValue || "";
-            }
-          }
-      );
-
-      // 监听只读状态变化
-      watch(
-          () => props.readonly,
-          (newValue) => {
-            if (editorRef.value) {
-              editorRef.value.setReadOnly(newValue);
-            }
-          }
-      );
-
-      // 组件销毁时清理
-      onBeforeUnmount(() => {
-        if (editorRef.value) {
-          editorRef.value.destruct();
-        }
-      });
-
-      return () =>
-          h("div", { class: "ss-editor-container" }, [
-            fjid.value &&
-            h("input", {
-              type: "hidden",
-              name: "fjid",
-              value: fjid.value,
-            }),
-            h("input", {
-              type: "hidden",
-              name: props.name.replace(/wj$/, "") + "Edit",
-              value: editorContent
-              // value: props.modelValue,
-            }),
-            h("input", {
-              type: "hidden",
-              name: props.name.replace(/wj$/, "") + "wj",
-              value: props.modelValue
-              // value: props.url
-            }),
-            h("input", { type: "hidden", name: "ueditorpath", value: "mswj" }),
-            h("textarea", { id: uniqueId }),
-          ]);
-    },
-  };
-  // 弹窗右边图标
-  const SsFullStyleHeader = {
-    name: "SsFullStyleHeader",
-    props: {
-      title: {
-        type: String,
-        default: "标题",
-      },
-    },
-    emits: ["close"],
-    setup(props, { emit }) {
-      // console.log(props.title)
-      const onClose = () => {
-        emit("close");
-      };
-      const SsIcon = resolveComponent("ss-icon");
-      return () =>
-          h("div", { class: "header-container" }, [
-            h("div", { class: "title" }, props.title),
-            h("div", { class: "handle-bar" }, [
-              h("div", { class: "left-bar" }, [
-                h(SsDialogIcon, { class: "dialog-icon-download" }),
-                h(SsDialogIcon, { class: "dialog-icon-print" }),
-                h(SsDialogIcon, { class: "dialog-icon-setting" }),
-                h(SsDialogIcon, { class: "dialog-icon-collect" }),
-                h(SsDialogIcon, { class: "dialog-icon-help" }),
-                h(SsDialogIcon, { class: "dialog-icon-full-screen" }),
-                h(SsDialogIcon, { class: "dialog-icon-lock" }),
-              ]),
-              h("div", { class: "close-bar", onClick: onClose }, [
-                h(SsDialogIcon, { class: "dialog-icon-close" }),
-              ]),
-            ]),
-          ]);
-    },
-  };
-  // ss-dialog弹窗
-  const SsDialog = {
-    name: "SsDialog",
-    props: {
-      src: {
-        type: String,
-      },
-      headerTitle: {
-        type: String,
-        // required: true,
-        default: "弹窗",
-      },
-      width: {
-        type: String,
-        default: "1400",
-      },
-      height: {
-        type: String,
-        default: "600",
-      },
-      params: {
-        type: Object,
-        default: () => ({}),
-      },
-      zIndex: {
-        type: Number,
-        default: 1000,
-      },
-    },
-    emits: ["close"],
-    setup(props, { slots, emit }) {
-      // 关闭窗口方法
-      const onClose = () => {
-        emit("close");
-      };
-      const showHeader = ref(true);
-      const headerVisible = ref(false);
-      const popupHieght = ref(props.height);
-      // 状态:存储位置信息
-      const position = reactive({
-        // 页面居中
-        x: (window.innerWidth - props.width) / 2,
-        y: (window.innerHeight - popupHieght.value) / 2,
-        isDragging: false,
-        offsetX: 0,
-        offsetY: 0,
-      });
-      // 鼠标按下时设置起始坐标并开始拖拽
-      const startDrag = (event) => {
-        position.isDragging = true;
-        position.offsetX = event.clientX - position.x;
-        position.offsetY = event.clientY - position.y;
-      };
-      // 鼠标移动时更新位置
-      const onDrag = (event) => {
-        if (position.isDragging) {
-          position.x = event.clientX - position.offsetX;
-          position.y = event.clientY - position.offsetY;
-        }
-      };
-      // 鼠标放开时结束拖拽
-      const endDrag = () => {
-        position.isDragging = false;
-      };
-      // 监听来自 iframe 的消息
-      const handleMessage = (event) => {
-        //  顶天立地
-        if (event.data && typeof event.data.hasScrollBar !== "undefined") {
-          if (event.data.hasScrollBar) {
-            //   console.log(event);
-            position.y = 10;
-            showHeader.value = false;
-            headerVisible.value = true;
-            popupHieght.value = window.innerHeight - 20;
-            //   console.log(popupHieght.value);
-            document.querySelector(".body").style.height = "100%";
-            document.querySelector(".body").style.paddingTop = "30px";
-            document.querySelector(".header-container ").style.position =
-                "absolute";
-            document.querySelector(".header-container ").style.zIndex = "10";
-          }
-        }
-      };
-      // 鼠标移入关闭按钮区域时显示头部
-      const onMouseEnterCloseButton = () => {
-        headerVisible.value = false;
-      };
-      // 鼠标移出关闭按钮区域时隐藏头部
-      const onMouseLeaveCloseButton = () => {
-        headerVisible.value = true;
-      };
-      // 在组件挂载时添加全局事件监听器
-      Vue.onMounted(() => {
-        // 如果传过来的高度大于窗口高度,则设置为窗口高度减去20 否则保持传过来的高度
-        popupHieght.value =
-            popupHieght.value > window.innerHeight
-                ? window.innerHeight - 20
-                : popupHieght.value;
-        const container = document.querySelector(".header-container");
-        if (container) {
-          container.addEventListener("mousedown", startDrag);
-        }
-        document.addEventListener("mousemove", onDrag);
-        document.addEventListener("mouseup", endDrag);
-        window.addEventListener("message", handleMessage);
-      });
-
-      // 在组件卸载时移除全局事件监听器
-      Vue.onUnmounted(() => {
-        document.removeEventListener("mousemove", onDrag);
-        document.removeEventListener("mouseup", endDrag);
-        window.removeEventListener("message", handleMessage);
-      });
-      const SsMark = resolveComponent("ss-mark");
-      const SsFullStyleHeader = resolveComponent("ss-full-style-header");
-      // render函数定义组件结构
-      return () =>
-          h(
-              Teleport,
-              { to: "body" }, // 使用 Teleport 将弹窗内容挂载到 body
-              h(SsMark, { }, [
-                h(
-                    "div",
-                    {
-                      class: "popup-container",
-                      style: {
-                        position: "absolute",
-                        left: `${position.x}px`,
-                        top: `${position.y}px`,
-                        width: props.width + "px",
-                        height: popupHieght.value + "px",
-                        zIndex: props.zIndex, // 确保弹窗在最上层
-                      },
-                    },
-                    [
-                      h(SsFullStyleHeader, {
-                        class: "header",
-                        title: props.headerTitle,
-                        onClose: onClose,
-                        onMousedown: startDrag, // 绑定拖动事件
-                        onMouseUp: endDrag,
-                        ...(!showHeader.value && {
-                          onMouseenter: onMouseEnterCloseButton,
-                          onMouseleave: onMouseLeaveCloseButton,
-                        }),
-                        style: {
-                          cursor: position.isDragging ? "grabbing" : "grab",
-                          visibility: headerVisible.value ? "hidden" : "visible",
-                        },
-                      }),
-                      h(
-                          "div",
-                          {
-                            class: "body",
-                            style: {},
-                          },
-                          [
-                            h("iframe", {
-                              src: props.src,
-                              frameborder: 0,
-                              style: { width: "100%", height: "100%" },
-                            }),
-                          ]
-                      ),
-                      headerVisible.value &&
-                      h("div", {
-                        class: "close-button",
-
-                        onMouseenter: onMouseEnterCloseButton,
-                        onMouseleave: onMouseLeaveCloseButton,
-                        style: {
-                          position: "absolute",
-                          top: "0",
-                          right: "0",
-                          // background: 'black',
-                          width: "60px",
-                          height: "60px",
-                          cursor: "pointer",
-                        },
-                      }),
-                    ]
-                ),
-              ])
-          );
-    },
-  };
-  // ss-mark遮罩层
-  const SsMark = {
-    name: "SsMark",
-
-    setup(props, { slots, emit }) {
-      return () =>
-          h("div", { class: "dialog-container" }, [
-            h("div", { class: "mark-content" }, [
-              h("div", { class: "dialog-contianer" }, [
-                slots.default ? slots.default() : "",
-              ]),
-            ]),
-          ]);
-    },
-  };
-  // ss-bottom-button 底部按钮
-  const SsBottomButton = {
-    name: "SsBottomButton",
-    props: {
-      text: {
-        type: String,
-        required: true,
-      },
-      type: {
-        type: String,
-        default: "button",
-      },
-      iconClass: {
-        type: String,
-      },
-      class: {
-        type: String,
-        default: "",
-      },
-      onclick: {
-        type: [Function, String],
-        default: null,
-      },
-    },
-    setup(props, { emit }) {
-      const SsBottomDivIcon = Vue.resolveComponent("ss-bottom-div-icon");
-      return () =>
-          h(
-              "button",
-              {
-                class: props.class,
-                onClick: (e) => {
-                  e.stopPropagation();
-                  if (props.onclick) {
-                    // 如果是函数直接调用
-                    if (typeof props.onclick === "function") {
-                      props.onclick(e);
-                    } else if (typeof props.onclick === "string") {
-                      // 如果是字符串,使用直接的方法执行
-                      // 临时存储按钮元素到全局变量
-                      window.__ss_current_button = e.currentTarget;
-
-                      // 直接执行代码,使用eval以保留原始上下文
-                      try {
-                        eval(props.onclick);
-                      } finally {
-                        // 清理全局变量
-                        delete window.__ss_current_button;
-                      }
-                    }
-                  }
-                },
-                type: props.type,
-              },
-              [
-                h("span", null, [
-                  h(SsBottomDivIcon, {
-                    class: props.iconClass,
-                  }),
-                ]),
-                h("span", null, props.text),
-              ]
-          );
-    },
-  };
-  // ss-search搜索框
-  const SsSearch = {
-    name: "SsSearch",
-    props: {
-      theme: {
-        type: String,
-        default: "light",
-        validator: function (value) {
-          return ["dark", "light"].includes(value);
-        },
-      },
-      placeholder: {
-        type: String,
-        default: "请输入搜索条件",
-      },
-    },
-    setup(props, { emit }) {
-      const onClick = () => {
-        console.log("Search clicked");
-        emit("click");
-      };
-      const SsIcon = Vue.resolveComponent("ss-icon");
-      return () =>
-          Vue.h(
-              "div",
-              {
-                class: ["search-container", props.theme],
-                onClick: onClick,
-              },
-              [
-                Vue.h("input", {
-                  placeholder: props.placeholder,
-                  disabled: true,
-                }),
-                Vue.h(SsIcon, {
-                  name: "search-result",
-                  size: "20px",
-                }),
-              ]
-          );
-    },
-  };
-  // ss-cart-item 菜单页面的卡片 左右结构
-  const SsCartItem = {
-    name: "SsCartItem",
-    props: {
-      active: Boolean,
-      item: {
-        type: Object,
-        default: () => ({
-          thumb: "images/example/project-img.png",
-          title: "广州(国际)科技成果转化天河基地专",
-          description: "佳能中国广州分公司",
-          all: 50,
-          finish: 5,
-        }),
-      },
-    },
-    setup(props, { emit }) {
-      const item = props.item;
-
-      const itemWidth = Vue.computed(() => {
-        const containerWidth =
-            document.body.clientWidth || document.body.scrollWidth - 520;
-        const halfWidth = containerWidth / 2;
-        if (halfWidth < 480) {
-          return Math.min(containerWidth, 702) + "px";
-        } else {
-          return Math.min(halfWidth, 702) + "px";
-        }
-      });
-
-      const onItemClick = (e) => {
-        emit("click", e);
-      };
-
-      return {
-        item,
-        itemWidth,
-        onItemClick,
-      };
-    },
-    render() {
-      const SsIcon = Vue.resolveComponent("ss-icon");
-      return Vue.h(
-          "div",
-          {
-            class: { "item-container": true, active: this.active },
-            onClick: this.onItemClick,
-            style: { width: this.itemWidth },
-          },
-          [
-            Vue.h("div", { class: "header" }, [
-              Vue.h(SsIcon, { name: "setting", size: "20px" }),
-            ]),
-            Vue.h("div", { class: "body" }, [
-              Vue.h("div", { class: "left" }, [
-                Vue.h("img", {
-                  src: this.item.thumb,
-                  alt: "Thumbnail",
-                  class: "imgUnHandle",
-                  style: { "object-fit": "cover", width: "100%", height: "100%" },
-                }),
-              ]),
-              Vue.h("div", { class: "right" }, [
-                Vue.h("div", { class: "title" }, this.item.title),
-                Vue.h("div", { class: "desc" }, this.item.description),
-                Vue.h("div", { class: "progress" }, [
-                  Vue.h(
-                      "div",
-                      {
-                        style: {
-                          width: `${(this.item.finish / this.item.all) * 100}%`,
-                        },
-                      },
-                      [Vue.h("div", `${this.item.finish}/${this.item.all}`)]
-                  ),
-                ]),
-              ]),
-            ]),
-          ]
-      );
-    },
-  };
-  // ss-cart-item2 菜单页面的卡片 上下结构
-  const SsCartItem2 = {
-    name: "SsCartItem2",
-    props: {
-      active: Boolean,
-      item: {
-        type: Object,
-        default: () => ({
-          thumb: "images/example/project-img.png",
-          title: "广州(国际)科技成果转化天河基地专",
-          description: "佳能中国广州分公司",
-          all: 50,
-          finish: 5,
-        }),
-      },
-    },
-    setup(props, { emit }) {
-      const item = props.item;
-      const itemWidth = Vue.computed(() => {
-        const containerWidth =
-            document.body.clientWidth || document.body.scrollWidth - 520;
-        const halfWidth = containerWidth / 2;
-        if (halfWidth < 480) {
-          return Math.min(containerWidth, 702) + "px";
-        } else {
-          return Math.min(halfWidth, 702) + "px";
-        }
-      });
-
-      const onItemClick = (e) => {
-        emit("click", e);
-      };
-
-      return {
-        item,
-        itemWidth,
-        onItemClick,
-      };
-    },
-
-    render() {
-      const SsIcon = Vue.resolveComponent("ss-icon");
-      return Vue.h(
-          "div",
-          {
-            class: { "item-container2": true, active: this.active },
-            onClick: this.onItemClick,
-            style: { width: this.itemWidth },
-          },
-          [
-            Vue.h("div", { class: "action-bar" }, [
-              Vue.h(SsIcon, { name: "setting", size: "20px" }),
-            ]),
-            Vue.h("div", { class: "header" }, [
-              Vue.h("div", { class: "title" }, `${this.item.title}`),
-            ]),
-            Vue.h("div", { class: "body" }, [
-              Vue.h("div", { class: "left" }, [
-                Vue.h("img", {
-                  src: this.item.thumb,
-                  alt: "Thumbnail",
-                  class: "imgUnHandle",
-                  style: { "object-fit": "cover", width: "100%", height: "100%" },
-                }),
-              ]),
-              Vue.h("div", { class: "right" }, [
-                Vue.h("div", { class: "content" }, this.item.description),
-                Vue.h("div", { class: "tip" }, [
-                  Vue.h("div", { class: "progress" }, [
-                    Vue.h(
-                        "div",
-                        {
-                          style: {
-                            width: `${(this.item.finish / this.item.all) * 100}%`,
-                          },
-                        },
-                        [Vue.h("div", `${this.item.finish}/${this.item.all}`)]
-                    ),
-                  ]),
-                ]),
-              ]),
-            ]),
-          ]
-      );
-    },
-  };
-  // ss-list-card 通用列表卡片
-  const SsListCard = {
-    name: "SsListCard",
-    props: {
-      item: {
-        type: Object,
-        required: true,
-      },
-    },
-    emits: ["click", "change"],
-    setup(props, { emit }) {
-      const item = props.item;
-      const itemWidth = Vue.computed(() => {
-        const containerWidth =
-            document.body.clientWidth || document.body.scrollWidth;
-        if (containerWidth > 1200) {
-          return "30%";
-        }
-        return "45%";
-      });
-      const onItemClick = (e) => {
-        // 清除所有类型卡片的 active 状态
-        const allListCards = document.querySelectorAll(
-            ".knowledge-item-container"
-        );
-        const allFolderCards = document.querySelectorAll(".ss-folder-list");
-
-        allListCards.forEach((card) => card.classList.remove("active"));
-        allFolderCards.forEach((card) => card.classList.remove("active"));
-
-        // 设置当前项的 active 状态
-        e.currentTarget.classList.add("active");
-        props.item.onclick();
-      };
-      const onItemChange = (e, icon, index) => {
-        e.stopPropagation(); // 阻止事件冒泡到卡片
-        props.item.buttons[0].onclick();
-        // emit("change", { item: props.item, icon, index });
-      };
-      return {
-        item,
-        itemWidth,
-        onItemClick,
-        onItemChange,
-      };
-    },
-
-    data() {
-      return {
-        showButtons: false,
-      };
-    },
-
-    render() {
-      const SsCartListIcon = Vue.resolveComponent("ss-cart-list-icon");
-      return Vue.h(
-          "div",
-          {
-            class: { "knowledge-item-container": true, active: this.item.active },
-            onClick: this.onItemClick,
-            style: { width: this.itemWidth },
-          },
-          [
-            this.item?.buttons?.length > 0 &&
-            Vue.h(
-                "div",
-                {
-                  class: "header",
-                  onMouseenter: () => (this.showButtons = true),
-                  onMouseleave: () => (this.showButtons = false),
-                  onClick: (e) => this.onItemChange(e, this.item.buttons[0], 0),
-                },
-                [
-                  // 只在有按钮时渲染设置图标
-                  // this.item?.buttons?.length > 0 &&
-                  Vue.h("div", {
-                    class: "cart-list-setting cart-list-icon",
-                    title: this.item?.buttons?.[0]?.title,
-                  }),
-
-                  // 鼠标移入时显示按钮列表,与图标同级
-                  // this.item?.buttons?.length > 0 &&
-                  this.showButtons &&
-                  this.item?.buttons?.length > 1 &&
-                  Vue.h(
-                      "div",
-                      {
-                        class: "cart-list-button-popup",
-                      },
-                      this.item.buttons.map((btn) =>
-                          Vue.h(
-                              "div",
-                              {
-                                onClick: (e) => {
-                                  e.stopPropagation();
-                                  btn.onclick?.();
-                                },
-                              },
-                              [
-                                // 如果有 class,显示对应的图标
-                                btn.class &&
-                                Vue.h(SsCartListIcon, {
-                                  class: [btn.class],
-                                }),
-                                // 显示按钮文本
-                                Vue.h("span", null, btn.title),
-                              ]
-                          )
-                      )
-                  ),
-                ]
-            ),
-
-            Vue.h("div", { class: "body" }, [
-              Vue.h("div", { class: "box-header" }, [
-                Vue.h("div", `${this.item.title}`),
-              ]),
-              Vue.h(
-                  "div",
-                  {
-                    class: !this.item.thumb ? "no-thumb box-body" : "box-body",
-                  },
-                  [
-                    this.item.thumb
-                        ? Vue.h("div", { class: "left" }, [
-                          Vue.h("img", {
-                            src: this.item.thumb,
-                            alt: "Thumbnail",
-                            class: "imgUnHandle",
-                            style: {
-                              "object-fit": "cover",
-                              width: "100%",
-                              height: "100%",
-                            },
-                          }),
-                        ])
-                        : null,
-                    Vue.h("div", { class: "right" }, [
-                      ...this.item.tags.map((tag) => {
-                        const [key, value] = Object.entries(tag)[0];
-                        return Vue.h(
-                            "div",
-                            {
-                              class: "title",
-                              title: `${key}: ${value}`,
-                            },
-                            `${key}: ${value}`
-                        );
-                      }),
-                    ]),
-                  ]
-              ),
-            ]),
-          ]
-      );
-    },
-  };
-  // ss-folder-card 文件夹卡片
-  const SsFolderCard = {
-    name: "SsFolderCard",
-    props: {
-      item: {
-        type: Object,
-        required: true,
-      },
-    },
-    data() {
-      return {
-        showButtons: false,
-      };
-    },
-    emits: ["click", "change"],
-    setup(props, { emit }) {
-      const item = props.item;
-      const showChildren = ref(false);
-      const eventBus = window.parent.sharedEventBus;
-
-      const itemWidth = Vue.computed(() => {
-        const containerWidth =
-            document.body.clientWidth || document.body.scrollWidth;
-        return containerWidth > 1200 ? "45%" : "90%";
-      });
-      onMounted(() => {
-        eventBus.subscribe("folderPath", (path) => {
-          const currentPath = path || [];
-          // 如果当前文件夹不在路径中,则销毁视图
-          if (
-              !currentPath.some((item) => item.folder.title === props.item.title)
-          ) {
-            showChildren.value = false;
-          }
-        });
-      });
-      const onItemClick = (e) => {
-        if (e && e.stopPropagation) {
-          e.stopPropagation();
-        }
-        // 单击只处理 active 状态
-        if (e && e.currentTarget) {
-          const allListCards = document.querySelectorAll(
-              ".knowledge-item-container"
-          );
-          const allFolderCards = document.querySelectorAll(".ss-folder-list");
-
-          allListCards.forEach((card) => card.classList.remove("active"));
-          allFolderCards.forEach((card) => card.classList.remove("active"));
-
-          e.currentTarget.classList.add("active");
-        } else {
-          // 如果是数据对象,需要找到对应的 DOM 元素
-          const allListCards = document.querySelectorAll(
-              ".knowledge-item-container"
-          );
-          const allFolderCards = document.querySelectorAll(".ss-folder-list");
-          allListCards.forEach((card) => card.classList.remove("active"));
-          allFolderCards.forEach((card) => card.classList.remove("active"));
-          // 找到标题匹配的文件夹元素
-          const targetFolder = Array.from(allFolderCards).find((card) =>
-              card.textContent.includes(e.title)
-          );
-
-          if (targetFolder) {
-            targetFolder.classList.add("active");
-          }
-        }
-        emit("click", item);
-      };
-      // 修改双击处理函数
-      const handleFolderDblClick = (folder, e) => {
-        if (e) e.stopPropagation();
-        if (folder.children?.length) {
-          showChildren.value = true;
-          const pathInfo = {
-            title: folder.title,
-            folder: folder,
-          };
-          const currentPath = eventBus.getState("folderPath") || [];
-          if (!currentPath.some((item) => item.title === folder.title)) {
-            eventBus.publish("folderPath", [...currentPath, pathInfo]);
-          }
-        }
-      };
-      const onItemChange = (e, icon, index) => {
-        e.stopPropagation();
-        props.item.buttons[0].onclick();
-        // emit("change", { item: props.item, icon, index });
-      };
-      return {
-        item,
-        itemWidth,
-        showChildren,
-        onItemClick,
-        onItemChange,
-        handleFolderDblClick,
-      };
-    },
-    render() {
-      const SsCartListIcon = Vue.resolveComponent("ss-cart-list-icon");
-      if (this.showChildren) {
-        return h(SsFolderCartView, {
-          folder: this.item,
-        });
-      }
-      return Vue.h(
-          "div",
-          {
-            class: { "ss-folder-list": true, active: this.item.active },
-            onClick: (e) => {
-              e.stopPropagation();
-              this.onItemClick(e);
-            },
-            onDblclick: (e) => this.handleFolderDblClick(this.item, e),
-            style: { width: this.itemWidth },
-          },
-          [
-            // 文件夹特有的装饰元素
-            Vue.h("div", { class: "ss-folder-list-trapezoid" }),
-            Vue.h("div", { class: "ss-folder-list-top-transparent" }),
-            Vue.h("div", { class: "ss-folder-list-top" }),
-            Vue.h("div", { class: "ss-folder-list-right" }),
-
-            // header 部分(按钮)
-            this.item?.buttons?.length > 0 &&
-            Vue.h(
-                "div",
-                {
-                  class: "header",
-                  onMouseenter: () => (this.showButtons = true),
-                  onMouseleave: () => (this.showButtons = false),
-                  onClick: (e) => this.onItemChange(e, this.item.buttons[0], 0),
-                },
-                [
-                  // this.item?.buttons?.length > 0 &&
-                  Vue.h("div", {
-                    class: "cart-list-setting cart-list-icon",
-                    title: this.item?.buttons?.[0]?.title,
-                  }),
-
-                  // this.item?.buttons?.length > 0 &&
-                  this.showButtons &&
-                  this.item?.buttons?.length > 1 &&
-                  Vue.h(
-                      "div",
-                      {
-                        class: "cart-list-button-popup",
-                      },
-                      this.item.buttons.map((btn) =>
-                          Vue.h(
-                              "div",
-                              {
-                                onClick: (e) => {
-                                  e.stopPropagation();
-                                  btn.onclick?.();
-                                },
-                              },
-                              [
-                                btn.class &&
-                                Vue.h(SsCartListIcon, {
-                                  class: [btn.class],
-                                }),
-                                Vue.h("span", null, btn.title),
-                              ]
-                          )
-                      )
-                  ),
-                ]
-            ),
-            // body 部分
-            Vue.h("div", { class: "body" }, [
-              Vue.h("div", { class: "box-header" }, [
-                Vue.h("div", null, this.item.title),
-              ]),
-              Vue.h(
-                  "div",
-                  {
-                    class: !this.item.thumb ? "no-thumb box-body" : "box-body",
-                  },
-                  [
-                    this.item.thumb
-                        ? Vue.h("div", { class: "left" }, [
-                          Vue.h("img", {
-                            src: this.item.thumb,
-                            alt: "Thumbnail",
-                            class: "imgUnHandle",
-                            style: {
-                              "object-fit": "cover",
-                              width: "100%",
-                              height: "100%",
-                            },
-                          }),
-                        ])
-                        : null,
-                    Vue.h("div", { class: "right" }, [
-                      ...this.item.tags.map((tag) => {
-                        const [key, value] = Object.entries(tag)[0];
-                        return Vue.h(
-                            "div",
-                            {
-                              class: "title",
-                              title: `${key}: ${value}`,
-                            },
-                            `${key}: ${value}`
-                        );
-                      }),
-                    ]),
-                  ]
-              ),
-            ]),
-          ]
-      );
-    },
-  };
-  // SsFolderCartView 组件 - 用于显示文件夹内容
-  const SsFolderCartView = {
-    name: "SsFolderCartView",
-    props: {
-      folder: {
-        type: Object,
-        required: true,
-      },
-    },
-    emits: ["click"],
-    setup(props, { emit }) {
-      const eventBus = window.parent.sharedEventBus;
-      const currentFolder = ref(props.folder);
-      const showChildren = ref(false);
-
-      const onItemClick = (e) => {
-        if (e && e.stopPropagation) {
-          e.stopPropagation();
-        }
-        // 单击只处理 active 状态
-        if (e && e.currentTarget) {
-          const allListCards = document.querySelectorAll(
-              ".knowledge-item-container"
-          );
-          const allFolderCards = document.querySelectorAll(".ss-folder-list");
-
-          allListCards.forEach((card) => card.classList.remove("active"));
-          allFolderCards.forEach((card) => card.classList.remove("active"));
-
-          e.currentTarget.classList.add("active");
-        } else {
-          // 如果是数据对象,需要找到对应的 DOM 元素
-          const allListCards = document.querySelectorAll(
-              ".knowledge-item-container"
-          );
-          const allFolderCards = document.querySelectorAll(".ss-folder-list");
-
-          allListCards.forEach((card) => card.classList.remove("active"));
-          allFolderCards.forEach((card) => card.classList.remove("active"));
-
-          // 找到标题匹配的文件夹元素
-          const targetFolder = Array.from(allFolderCards).find((card) =>
-              card.textContent.includes(e.title)
-          );
-
-          if (targetFolder) {
-            targetFolder.classList.add("active");
-          }
-        }
-        emit("click", props.folder);
-      };
-      const handleFolderDblClick = (folder, e) => {
-        if (e) e.stopPropagation();
-        if (folder.children?.length) {
-          showChildren.value = true;
-          const pathInfo = {
-            title: folder.title,
-            folder: folder,
-          };
-          const currentPath = eventBus.getState("folderPath") || [];
-          if (!currentPath.some((item) => item.title === folder.title)) {
-            eventBus.publish("folderPath", [...currentPath, pathInfo]);
-            currentFolder.value = folder;
-          }
-        }
-      };
-
-      const goBack = (targetFolder) => {
-        if (targetFolder === null) {
-          // 返回根目录
-          eventBus.publish("folderPath", []);
-        } else {
-          currentFolder.value = targetFolder;
-        }
-      };
-
-      return {
-        currentFolder,
-        showChildren,
-        onItemClick,
-        handleFolderDblClick,
-        goBack,
-      };
-    },
-
-    render() {
-      return h(
-          "div",
-          {
-            class: "page-container",
-            style: {
-              position: "fixed",
-              top: 0,
-              left: 0,
-              width: "100%",
-              height: "100%",
-              background: "var(--lightgray)",
-              padding: "20px 0",
-              zIndex: 1000,
-            },
-          },
-          [
-            // 搜索栏
-            h("div", { class: "search-bar" }, [
-              h("div", { class: "search-bar-contaienr" }, [
-                h(SsBreadcrumb, {
-                  level: {
-                    onBack: this.goBack,
-                  },
-                }),
-              ]),
-            ]),
-
-            // 内容区域
-            h(
-                "div",
-                {
-                  class: "content-area item-content-area",
-                  style: { gap: "20px" },
-                },
-                [
-                  ...(this.currentFolder.children || []).map((child, index) =>
-                      h(child.children ? SsFolderCard : SsListCard, {
-                        key: index,
-                        item: child,
-                        onClick: (e) => this.onItemClick(e),
-                        onDblclick: (e) => this.handleFolderDblClick(child, e),
-                      })
-                  ),
-                ]
-            ),
-          ]
-      );
-    },
-  };
-
-  // ss-page分页
-  const SsPage = {
-    name: "SsPage",
-    props: {
-      total: {
-        type: Number,
-        required: true,
-      },
-
-      size: {
-        type: Number,
-        default: 10,
-      },
-      page: {
-        type: Number,
-        default: 1,
-      },
-      onChange: {
-        type: Function,
-        default: () => {},
-      },
-    },
-    setup(props) {
-      const totalItems = ref(props.total); // 总条目数
-      const totalPages = ref(Math.ceil(props.total / props.size));
-      const currentPage = ref(props.page); // 当前页码
-
-      // 计算显示的信息
-      const pageInfo = ref(
-          `共${totalItems.value}条,第 ${currentPage.value}/${totalPages.value} 页`
-      );
-
-      // 上一页的逻辑
-      const goToPreviousPage = (e) => {
-        e.preventDefault(); // 阻止默认行为
-        if (currentPage.value > 1) {
-          currentPage.value -= 1;
-          updatePageInfo();
-          props.onChange?.({
-            pageNo: currentPage.value, // 当前页码
-            rowNumPer: props.size, // 每页条数
-            rowNum: props.total, // 总记录数
-          });
-        }
-      };
-
-      // 下一页的逻辑
-      const goToNextPage = (e) => {
-        e.preventDefault(); // 阻止默认行为
-        if (currentPage.value < totalPages.value) {
-          currentPage.value += 1;
-          updatePageInfo();
-          props.onChange?.({
-            pageNo: currentPage.value, // 当前页码
-            rowNumPer: props.size, // 每页条数
-            rowNum: props.total, // 总记录数
-          });
-        }
-      };
-
-      // 更新页码信息的函数
-      const updatePageInfo = () => {
-        pageInfo.value = `共${totalItems.value}条,第 ${currentPage.value}/${totalPages.value} 页`;
-      };
-
-      return {
-        pageInfo,
-        totalPages,
-        goToPreviousPage,
-        goToNextPage,
-      };
-    },
-
-    render(props, { slots, emit }) {
-      return Vue.h("div", { class: "pager-container" }, [
-        Vue.h("input", { type: "hidden", name: "rowNum", value: props.total }),
-        Vue.h("input", {
-          type: "hidden",
-          name: "rowNumPer",
-          value: props.size,
-        }),
-        Vue.h("input", {
-          type: "hidden",
-          name: "pageCount",
-          value: this.totalPages,
-        }),
-        Vue.h("input", { type: "hidden", name: "pageNo", value: props.page }),
-        Vue.h("div", { class: "pager-content" }, [
-          Vue.h("div", { class: "info" }, this.pageInfo),
-          Vue.h(
-              "div",
-              { class: "btn" },
-              Vue.h(
-                  "button",
-                  { onClick: (e) => this.goToPreviousPage(e) },
-                  "上一页"
-              )
-          ),
-          Vue.h(
-              "div",
-              { class: "btn" },
-              Vue.h("button", { onClick: (e) => this.goToNextPage(e) }, "下一页")
-          ),
-        ]),
-      ]);
-    },
-  };
-  // ss-right-info 一级页面右边栏
-  const SSRightInfo = {
-    name: "SSRightInfo",
-    setup() {
-      // 初始化响应式数据
-      const item = ref({
-        thumb: "images/example/project-img.png", // 更换为适合你项目的实际路径
-        title: "工业和信息化产业高质量发展资金",
-      });
-
-      return {
-        item,
-      };
-    },
-    render() {
-      return Vue.h("div", { class: "info-container" }, [
-        Vue.h("div", { class: "header" }, [
-          Vue.h("div", [
-            Vue.h("img", {
-              src: this.item.thumb,
-              class: "imgUnHandle",
-              style: { "object-fit": "cover", width: "100%", height: "100%" },
-            }), // 将 ImageViewer 替换为 img 标签
-          ]),
-          Vue.h("div", [Vue.h("div", this.item.title)]),
-        ]),
-        Vue.h("div", { class: "section-container" }, [
-          Vue.h("div", { class: "section" }, [
-            Vue.h("div", { class: "title" }, "合同"),
-            Vue.h("div", { class: "text" }, "合同总金额:42,399,320"),
-            Vue.h(
-                "div",
-                { class: "a" },
-                "《工业和信息化产业高质量发展资金补助合同》"
-            ),
-          ]),
-          Vue.h("div", { class: "section" }, [
-            Vue.h("div", { class: "title" }, "发票"),
-            Vue.h("div", { class: "text" }, "应开发票总额:42,399,320"),
-            Vue.h("div", { class: "text" }, "已开发票金额:17,235,345"),
-            Vue.h("div", { class: "text" }, "未开发票金额:25,163,975"),
-          ]),
-          Vue.h("div", { class: "section" }, [
-            Vue.h("div", { class: "title" }, "项目组成员"),
-            Vue.h("div", { class: "text" }, "我司:3人"),
-            Vue.h("div", { class: "text" }, "对方:2人"),
-            Vue.h("div", { class: "text" }, "项目负责人:张三"),
-          ]),
-          Vue.h("div", { class: "section" }, [
-            Vue.h("div", { class: "title" }, "采购"),
-            Vue.h("div", { class: "text" }, "总额:999,320"),
-            Vue.h("div", { class: "text" }, "已付金额:335,345"),
-            Vue.h("div", { class: "text" }, "未付金额:663,975"),
-          ]),
-        ]),
-      ]);
-    },
-  };
-  //
-  const SsSuccessPopup = {
-    name: "SsSuccessPopup",
-    props: {
-      right: {
-        type: String,
-        default: "20px",
-      },
-      bottom: {
-        type: String,
-        default: "calc(100% + 5px)",
-      },
-    },
-    setup(props, { expose }) {
-      // 响应式状态:是否可见
-      const visible = ref(false);
-
-      // 计算样式
-      const style = computed(() => {
-        return {
-          "--message-dialog-right": props.right,
-          "--message-dialog-bottom": props.bottom,
-        };
-      });
-
-      // 显示对话框的方法
-      const show = () => {
-        visible.value = true;
-      };
-
-      // 隐藏对话框的方法
-      const hide = () => {
-        visible.value = false;
-      };
-
-      // 将方法暴露给外部使用
-      expose({ show, hide });
-
-      // 返回渲染函数
-      return () => {
-        if (!visible.value) return null;
-        const SsIcon = resolveComponent("ss-icon");
-        return h(
-            "div",
-            {
-              class: "success-popup",
-              style: style.value,
-              onClick: (e) => e.stopPropagation(),
-            },
-            [
-              h("div", { class: "left" }, [
-                h("div", { class: "icon" }, [
-                  h(SsIcon, { name: "check", size: "36px" }),
-                ]),
-              ]),
-              h("div", { class: "right" }, [
-                h("div", { class: "title" }, "提交成功"),
-                h("div", { class: "desc" }, "您的信息已成功提交。"),
-              ]),
-            ]
-        );
-      };
-    },
-  };
-  const SsErrorDialog = {
-    name: "SsErrorDialog",
-    setup(props, { emit }) {
-      const visible = ref(false);
-
-      const style = computed(() => {
-        return {};
-      });
-
-      const show = () => {
-        visible.value = true;
-      };
-
-      const hide = () => {
-        visible.value = false;
-      };
-
-      const onBack = () => {
-        emit("back");
-        hide();
-      };
-
-      return {
-        visible,
-        style,
-        show,
-        hide,
-        onBack,
-      };
-    },
-    render() {
-      const SsIcon = resolveComponent("ss-icon");
-      return this.visible
-          ? h(
-              "div",
-              {
-                class: "errorDialog",
-                style: this.style,
-                onClick: (event) => event.stopPropagation(),
-              },
-              [
-                h("div", { class: "body" }, [
-                  h("div", { class: "left" }, [
-                    h("div", { class: "icon" }, [
-                      h(SsIcon, { name: "close", size: "36px" }),
-                    ]),
-                  ]),
-                  h("div", { class: "right" }, [
-                    h("div", { class: "title" }, "操作失败"),
-                    h("div", { class: "desc" }, "请点击返回以继续。"),
-                  ]),
-                ]),
-                h("div", { class: "footer" }, [
-                  h("div", { class: "left" }),
-                  h("div", { class: "right" }, [
-                    h(
-                        "div",
-                        {
-                          class: "btn",
-                          onClick: this.onBack,
-                        },
-                        [h(SsIcon, { name: "arrow-left-line" }), h("div", "返回")]
-                    ),
-                  ]),
-                ]),
-              ]
-          )
-          : null;
-    },
-  };
-  /**
-   * 审核链条
-   * @name ss-verify
-   * @param { Array } verify-list 审核节点列表
-   * @property { Array } verify-list 审核节点列表
-   * @example <ss-verify :verify-list="verifyList"></ss-verify>
-   * verify-list [
-   *    {
-   *        groupName: "",  // 群组名称
-   *        open: true, // 默认是否展开
-   *        children:[ //群组里的人员
-   *           {
-   *            thumb: "images/example/user-4.png", // 头像
-   *             name: "李丽思 ", // 姓名
-   *             role: "人事处处长",  // 角色
-   *             description: "同意。",  // 审核意见
-   *             time: "09:38 08/11", // 审核时间
-   *             video: false,  // false不显示/true显示 视频icon
-   *             link: false,  // false不显示/true显示 链接icon 后续应该是附件
-   *           }
-   *        ]
-   *    }
-   *  ]
-   */
-  const SsVerify = {
-    name: "SsVerify",
-    props: {
-      verifyList: {
-        type: Array,
-        required: true,
-      },
-    },
-    setup(props) {
-      const toggleOpen = (item) => {
-        item.open = !item.open;
-      };
-      onMounted(() => {
-        setTimeout(() => {
-          const lastOpenGroup = document.querySelector(".group-item-last-open");
-          console.log("lastOpenGroup", lastOpenGroup);
-          if (lastOpenGroup) {
-            const nodes = $(lastOpenGroup).find(".verify-node-container");
-            if (nodes.length) {
-              let totalHeight = 0;
-              const gudingHeight = 100;
-
-              if (nodes.length === 1) {
-                totalHeight = gudingHeight;
-              } else {
-                // 累加除最后一个节点外的所有节点高度
-                for (let i = 0; i < nodes.length - 1; i++) {
-                  totalHeight += $(nodes[i]).outerHeight();
-                }
-                totalHeight += gudingHeight;
-              }
-
-              console.log("节点信息:", {
-                节点总数: nodes.length,
-                计算后的高度: totalHeight,
-              });
-
-              lastOpenGroup.style.setProperty(
-                  "--group-line-height",
-                  `${totalHeight}px`
-              );
-            }
-          }
-        }, 0);
-      });
-      return {
-        toggleOpen,
-      };
-    },
-    render() {
-      const SsIcon = resolveComponent("ss-icon");
-      const SsCommonIcon = resolveComponent("ss-common-icon");
-      const SsVerifyNode = resolveComponent("ss-verify-node");
-      return h(
-          "div",
-          { class: "verify-nodes" },
-          this.verifyList.map((item, i) =>
-              h(
-                  "div",
-                  {
-                    key: i,
-                    class: {
-                      "group-item": true,
-                      "group-item-last-open":
-                          i === this.verifyList.length - 1 && item.open,
-                    },
-                  },
-                  [
-                    h(
-                        "div",
-                        {
-                          class: "group-item-title",
-                          onClick: () => this.toggleOpen(item),
-                        },
-                        [
-                          h("div", { class: "icon" }, [
-                            item.open
-                                ? h(SsCommonIcon, { class: "common-icon-folder-open" })
-                                : h(SsCommonIcon, { class: "common-icon-folder-close" }),
-                            h(
-                                "div",
-                                {
-                                  class: "num",
-                                  style: { top: item.open ? "60%" : "55%" },
-                                },
-                                item.children?.length || 0
-                            ),
-                          ]),
-                          h("div", { class: "name" }, item.groupName),
-                        ]
-                    ),
-                    item.open && item.children?.length > 0
-                        ? h(
-                            "div",
-                            { class: "group-item-children" },
-                            item.children.map((citem, j) =>
-                                h(SsVerifyNode, {
-                                  key: j,
-                                  item: citem,
-                                  // isGroup: i + 1 !== this.verifyList.length,
-                                  isGroup: true,
-                                })
-                            )
-                        )
-                        : null,
-                  ]
-              )
-          )
-      );
-    },
-  };
-
-  /**
-   * 审核页面的审核节点
-   * @name ss-verify-node
-   * @param {Object} item 审核节点信息
-   * @param {Boolean} isGroup 是否为分组节点
-   */
-  const SsVerifyNode = {
-    name: "SsVerifyNode",
-    props: {
-      item: {
-        type: Object,
-        required: true,
-      },
-      isGroup: {
-        type: Boolean,
-        default: false,
-      },
-    },
-    render() {
-      const SsIcon = resolveComponent("ss-icon");
-      const SsCommonIcon = resolveComponent("ss-common-icon");
-      return Vue.h("div", { class: "verify-node-container" }, [
-        Vue.h("div", { class: "info" }, [
-          Vue.h("div", { class: "avatar" }, [
-            Vue.h("img", {
-              src: this.item.thumb,
-              style: {
-                width: "50px",
-                height: "50px",
-                borderRadius: "50%",
-              },
-            }),
-          ]),
-          Vue.h("div", { class: "desc" }, [
-            Vue.h("div", this.item.name),
-            Vue.h("div", this.item.role),
-          ]),
-          Vue.h("div", { class: "link" }, [
-            Vue.h("div", [
-              this.item.video
-                  ? Vue.h(SsCommonIcon, { class: "common-icon-video" })
-                  : null,
-              this.item.link
-                  ? Vue.h(SsCommonIcon, {
-                    class: "common-icon-paper-clip",
-                  })
-                  : null,
-            ]),
-          ]),
-        ]),
-        Vue.h(
-            "div",
-            {
-              class: {
-                description: true,
-                link: this.isGroup,
-              },
-              attrs: { "data-num": "3" },
-            },
-            [Vue.h("div", this.item.description)]
-        ),
-        Vue.h("div", { class: "time" }, this.item.time),
-      ]);
-    },
-  };
-  /**
-   * 智能识别图片的左侧图片播放 可以放大缩小旋转图片
-   * @name ss-orc-img-box
-   * @param { Object } image-obj 包含图片的url, 和图片的名称
-   *
-   */
-  const SsOrcImgBox = {
-    name: "SsOrcImgBox",
-    props: {
-      imageObj: {
-        type: Object,
-        required: true,
-      },
-    },
-    setup(props) {
-      const zoom = ref(1);
-      const rotation = ref(0);
-      const containerWidth = ref(0);
-      const containerHeight = ref(0);
-      const container = ref(null);
-      const imgPosition = ref({ x: 0, y: 0 });
-      const isDragging = ref(false);
-      const lastMousePosition = ref({ x: 0, y: 0 });
-      const imgStyle = computed(() => ({
-        width: `${zoom.value * 100}%`,
-        height: `${zoom.value * 100}%`,
-        transform: `rotate(${rotation.value}deg) translate(${imgPosition.value.x}px, ${imgPosition.value.y}px)`,
-        transformOrigin: "center center",
-        cursor: isDragging.value ? "grabbing" : "grab",
-      }));
-
-      const resetZoom = () => {
-        zoom.value = 1;
-        rotation.value = rotation.value + 90;
-        imgPosition.value = { x: 0, y: 0 };
-      };
-
-      const handleRangeChange = (event) => {
-        const value = event.target.value / 50; // 0 到 100 映射到 0 到 2 的缩放
-        zoom.value = Math.max(value, 0.1); // 设置最小缩放值为 0.1
-      };
-      const updateImgBoxDimensions = () => {
-        if (container.value) {
-          containerWidth.value = container.value.clientWidth;
-          containerHeight.value = container.value.clientHeight;
-        }
-      };
-      const onMouseDown = (event) => {
-        isDragging.value = true;
-        lastMousePosition.value = { x: event.clientX, y: event.clientY };
-      };
-
-      const onMouseMove = (event) => {
-        if (isDragging.value) {
-          const dx = event.clientX - lastMousePosition.value.x;
-          const dy = event.clientY - lastMousePosition.value.y;
-
-          // 防止旋转后拖动的x,y反转
-          // 首先将当前旋转角度从度数转换为弧度,因为 JavaScript 的 Math 库使用弧度
-          const angle = rotation.value * (Math.PI / 180);
-          // 使用基本的二维旋转矩阵将原始位移 dx 和 dy 转换为旋转后的位移 rotatedDx 和 rotatedDy。
-          const rotatedDx = dx * Math.cos(angle) + dy * Math.sin(angle);
-          const rotatedDy = dy * Math.cos(angle) - dx * Math.sin(angle);
-
-          imgPosition.value = {
-            x: imgPosition.value.x + rotatedDx,
-            y: imgPosition.value.y + rotatedDy,
-          };
-          lastMousePosition.value = { x: event.clientX, y: event.clientY };
-        }
-      };
-
-      const onMouseUp = () => {
-        isDragging.value = false;
-      };
-      onMounted(() => {
-        nextTick(() => {
-          updateImgBoxDimensions();
-          window.addEventListener("resize", updateImgBoxDimensions);
-          window.addEventListener("mousemove", onMouseMove);
-          window.addEventListener("mouseup", onMouseUp);
-        });
-      });
-
-      return {
-        zoom,
-        rotation,
-        container,
-        imgStyle,
-        resetZoom,
-        handleRangeChange,
-        containerWidth,
-        containerHeight,
-        onMouseDown,
-        imgPosition,
-      };
-    },
-    render() {
-      const SsIcon = resolveComponent("ss-icon");
-      return h("div", { class: "ocr-img-box" }, [
-        h("div", { class: "img-bar" }, [
-          h("div", this.imageObj.name),
-          h("div", { class: "action-bar" }, [
-            h("div", { class: "ocr-img-range-box" }, [
-              h("input", {
-                type: "range",
-                min: 0,
-                max: 100,
-                value: this.zoom * 50, // 初始位置为50
-                onInput: this.handleRangeChange,
-              }),
-              h("span", { class: "line" }),
-            ]),
-            h(SsIcon, {
-              name: "reset",
-              size: "26px",
-              onClick: this.resetZoom,
-            }),
-          ]),
-        ]),
-        h("div", { class: "img-viewer", ref: "container" }, [
-          h(
-              "div",
-              {
-                class: "img-box",
-                style: {
-                  width: `${this.containerWidth}px`,
-                  height: `${this.containerHeight}px`,
-                  overflow: "hidden",
-                  position: "relative",
-                },
-              },
-              [
-                h("img", {
-                  src: this.imageObj.thumb,
-                  style: this.imgStyle,
-                  class: "zoomable-img",
-                  onMousedown: this.onMouseDown,
-                }),
-              ]
-          ),
-        ]),
-      ]);
-    },
-  };
-  // 搜索输入框组件
-  const SsSearchInput = {
-    name: "SsSearchInput",
-    props: {
-      name: String,
-      placeholder: String,
-      width: {
-        type: String,
-        default: "100px",
-      },
-      modelValue: String,
-    },
-    emits: ["update:modelValue", "search"],
-    setup(props, { emit }) {
-      const handleInput = (e) => {
-        emit("update:modelValue", e.target.value);
-      };
-      const handleKeyup = (e) => {
-        if (e.key === "Enter") {
-          emit("search");
-        }
-      };
-
-      return { handleInput, handleKeyup };
-    },
-    render() {
-      return h(
-          "div",
-          {
-            class: "input",
-            style: this.width ? { width: this.width } : undefined,
-          },
-          [
-            h("input", {
-              name: this.name,
-              placeholder: this.placeholder,
-              value: this.modelValue,
-              onInput: this.handleInput,
-              onKeyup: this.handleKeyup,
-            }),
-          ]
-      );
-    },
-  };
-  // ss-search-date-picker 日期时间选择器组件
-  const SsSearchDatePicker = {
-    name: "SsSearchDatePicker",
-    props: {
-      modelValue: {
-        type: [String, Number, Date],
-        default: "",
-      },
-      name: {
-        type: String,
-        required: true,
-      },
-      type: {
-        type: String,
-        default: "date",
-        validator: (value) => ["date", "datetime", "time"].includes(value),
-      },
-      fmt: {
-        type: String,
-        default: null,
-      },
-      placeholder: {
-        type: String,
-        default: "",
-      },
-      width: {
-        type: String,
-        default: "100%",
-      },
-    },
-
-    emits: ["update:modelValue"],
-
-    setup(props, { emit }) {
-      const errMsg = ref("");
-      const validate = () => {
-        if (window.ssVm) {
-          const result = window.ssVm.validateField(props.name);
-          console.log("validate", window.ssVm.validateField(props.name));
-          errMsg.value = result.valid ? "" : result.message;
-        }
-      };
-      // 根据type确定默认格式
-      const defaultFormat = computed(() => {
-        switch (props.type) {
-          case "datetime":
-            return "YYYY-MM-DD HH:mm:ss";
-          case "date":
-            return "YYYY-MM-DD";
-          case "time":
-            return "HH:mm:ss";
-        }
-      });
-
-      const convertJavaFormatToElement = (javaFormat) => {
-        if (!javaFormat) return null;
-        return javaFormat
-            .replace("yyyy", "YYYY")
-            .replace("MM", "MM")
-            .replace("dd", "DD")
-            .replace("HH", "HH")
-            .replace("mm", "mm")
-            .replace("ss", "ss");
-      };
-
-      const finalFormat = computed(() => {
-        if (props.fmt) {
-          return convertJavaFormatToElement(props.fmt);
-        }
-        return defaultFormat.value;
-      });
-
-      // 使用 resolveComponent 获取组件
-      const ElDatePicker = resolveComponent("ElDatePicker");
-      const ElTimePicker = resolveComponent("ElTimePicker");
-      const SsFormIcon = resolveComponent("SsFormIcon");
-      const ElIcon = resolveComponent("ElIcon");
-      let useTimePicker = true;
-      //"yyyy-MM-dd HH:mm:ss";  "日期字符串格式在java的写法",传到本组件fmt属性也是按这个格式
-      if (props.fmt) {
-        //有fmt属性,则以fmt属性优先判断类型
-        if (/[dMy]/.test(props.fmt)) {
-          //如果有传入日期格式,且含年月日
-          useTimePicker = false;
-        } else {
-          useTimePicker = true;
-        }
-      } else if (props.type !== "time") {
-        useTimePicker = false;
-      }
-      const dateType = computed(() => {
-        const fmt = props.fmt || "";
-        if (fmt.includes("HH:mm:ss")) {
-          return "datetime";
-        } else if (fmt.includes("HH:mm")) {
-          return "datetime";
-        } else if (fmt.includes("mm:ss")) {
-          return "time";
-        }
-        return "date";
-      });
-      const handleValueUpdate = (val) => {
-        emit("update:modelValue", val);
-        emit("change", val); // 同时触发 change 事件
-        setTimeout(() => {
-          validate();
-        }, 50);
-      };
-      return () =>
-          h(
-              "div",
-              { class: "ss-search-date-picker", style: { width: props.width } },
-              [
-                h("input", {
-                  type: "hidden",
-                  name: props.name,
-                  value: props.modelValue,
-                }),
-                h(useTimePicker ? ElTimePicker : ElDatePicker, {
-                  modelValue: props.modelValue,
-                  "onUpdate:modelValue": handleValueUpdate,
-                  type: dateType.value,
-                  format: finalFormat.value,
-                  "value-format": finalFormat.value,
-                  clearable: true,
-                  placeholder: props.placeholder,
-                  class: "custom-date-picker", // 用于自定义样式
-                  "time-arrow-control": props.type === "datetime", // 修改这里
-                  size: "large", // 添加这一行,改为 large 尺寸
-                  style: { width: "100%" },
-                  "prefix-icon": h(SsFormIcon, { class: "form-icon-time" }),
-                }),
-              ]
-          );
-    },
-  };
-  // 搜索按钮组件(包含下拉按钮)
-  const SsSearchButton = {
-    name: "SsSearchButton",
-    props: {
-      text: {
-        type: String,
-        required: true,
-      },
-      iconClass: {
-        type: String,
-        required: false,
-      },
-      opt: {
-        type: Array,
-        default: () => [],
-      },
-      checkId: {
-        type: String,
-        default: "0",
-      },
-    },
-    emits: ["click"],
-    setup(props, { emit }) {
-      const currentId = ref(props.checkId || "0");
-      const showPopup = ref(false);
-
-      const handleMouseEnter = () => {
-        showPopup.value = true;
-      };
-
-      const handleMouseLeave = () => {
-        showPopup.value = false;
-      };
-
-      // 添加点击事件处理,阻止默认行为
-      const handleClick = (e) => {
-        e.preventDefault();
-        if (props.opt?.length > 0) {
-          const selectedOption =
-              currentId.value === "0"
-                  ? props.opt[0]
-                  : props.opt.find((opt) => opt.id === currentId.value);
-
-          if (selectedOption) {
-            selectedOption.callback?.();
-          }
-        } else {
-          emit("click", e);
-        }
-      };
-      // 获取显示文本
-      const getDisplayText = () => {
-        if (!props.opt?.length) return props.text;
-
-        const selectedOption =
-            currentId.value === "0"
-                ? props.opt[0]
-                : props.opt.find((opt) => opt.id === currentId.value);
-
-        return selectedOption ? selectedOption.desc : props.opt[0].desc;
-      };
-
-      return () =>
-          h(
-              "button",
-              {
-                class:
-                    props.opt?.length > 0
-                        ? "ss-drop-button ss-drop-button-more"
-                        : "ss-drop-button",
-                type: "button", // 明确指定按钮类型为 button
-                onMouseenter: handleMouseEnter,
-                onMouseleave: handleMouseLeave,
-                onClick: handleClick, // 添加点击事件处理
-              },
-              [
-                props.iconClass
-                    ? h("span", {
-                      class: props.iconClass,
-                      style: { fontFamily: "iconfont", marginRight: "5px" },
-                    })
-                    : null,
-                h("span", getDisplayText()),
-                props.opt.length > 0 &&
-                showPopup.value &&
-                h(
-                    "div",
-                    {
-                      class: "popup",
-                    },
-                    props.opt.map((item) =>
-                        h(
-                            "div",
-                            {
-                              onClick: (e) => {
-                                e.preventDefault(); // 选项点击也阻止默认行为
-                                e.stopPropagation(); // 阻止事件冒泡
-                                currentId.value = item.id; // 更新当前选中的ID
-                                item.callback();
-                                showPopup.value = false; // 选择后关闭弹窗
-                              },
-                            },
-                            item.desc
-                        )
-                    )
-                ),
-              ]
-          );
-    },
-  };
-  // 下拉按钮组件
-  const SsDropButton = {
-    name: "SsDropButton",
-    props: {
-      text: {
-        type: String,
-        required: true,
-      },
-      iconClass: {
-        type: String,
-        required: true,
-      },
-      opt: {
-        type: Array,
-        default: () => [],
-      },
-      checkId: {
-        type: String,
-        default: "0",
-      },
-      onclick: {
-        type: Function,
-        default: null,
-      },
-    },
-    setup(props) {
-      const currentId = ref(props.checkId || "0");
-      const showPopup = ref(false);
-
-      const handleMouseEnter = () => {
-        showPopup.value = true;
-      };
-
-      const handleMouseLeave = () => {
-        showPopup.value = false;
-      };
-
-      // 添加点击事件处理,阻止默认行为
-      const handleClick = (e) => {
-        e.preventDefault();
-        if (props.opt?.length > 0) {
-          const selectedOption =
-              currentId.value === "0"
-                  ? props.opt[0]
-                  : props.opt.find((opt) => opt.id === currentId.value);
-
-          if (selectedOption) {
-            selectedOption.callback?.();
-          }
-        } else if (props.onclick) {
-          props.onclick();
-        }
-      };
-      // 获取显示文本
-      const getDisplayText = () => {
-        if (!props.opt?.length) return props.text;
-
-        const selectedOption =
-            currentId.value === "0"
-                ? props.opt[0]
-                : props.opt.find((opt) => opt.id === currentId.value);
-
-        return selectedOption ? selectedOption.desc : props.opt[0].desc;
-      };
-
-      return () =>
-          h(
-              "button",
-              {
-                class:
-                    props.opt?.length > 0
-                        ? "ss-drop-button ss-drop-button-more"
-                        : "ss-drop-button",
-                type: "button", // 明确指定按钮类型为 button
-                onMouseenter: handleMouseEnter,
-                onMouseleave: handleMouseLeave,
-                onClick: handleClick, // 添加点击事件处理
-              },
-              [
-                h("span", {
-                  class: props.iconClass,
-                  style: { fontFamily: "iconfont" },
-                }),
-                h("span", getDisplayText()),
-                props.opt.length > 0 &&
-                showPopup.value &&
-                h(
-                    "div",
-                    {
-                      class: "popup",
-                    },
-                    props.opt.map((item) =>
-                        h(
-                            "div",
-                            {
-                              onClick: (e) => {
-                                e.preventDefault(); // 选项点击也阻止默认行为
-                                e.stopPropagation(); // 阻止事件冒泡
-                                currentId.value = item.id; // 更新当前选中的ID
-                                item.callback();
-                                showPopup.value = false; // 选择后关闭弹窗
-                              },
-                            },
-                            item.desc
-                        )
-                    )
-                ),
-              ]
-          );
-    },
-  };
-  /**
-   * 二级页面标签组件
-   * @name ss-sub-tab
-   * @description 用于展示二级页面的布局组件,包含左侧垂直标签导航(支持分组)和右侧iframe内容区
-   * @property {String} headerImage - 左侧顶部图片地址
-   * @property {Array} menuList - 菜单配置列表
-   * @property {Object} [activeMenu] - 当前选中的菜单项,不传则自动选择第一个可选菜单
-   * @property {Array} footerButtons - 底部按钮配置列表
-
-   */
-  const SsSubTab = {
-    name: "SsSubTab",
-    props: {
-      headerImage: {
-        type: String,
-        default: "",
-      },
-      menuList: {
-        type: Array,
-        required: true,
-      },
-      activeMenu: {
-        // 只需要传入标题
-        type: String,
-        default: "",
-      },
-      footerButtons: {
-        type: Array,
-        default: () => [],
-      },
-      leftDisplay: {
-        type: Boolean,
-        default: true,
-      },
-    },
-    emits: ["menu-change", "footer-click"],
-    setup(props, { emit }) {
-      // 根据标题找到对应的菜单项
-      const findMenuByTitle = (title) => {
-        for (const item of props.menuList) {
-          if (item.children?.length > 0) {
-            const child = item.children.find((c) => c.title === title);
-            if (child) return child;
-          } else if (item.title === title) {
-            return item;
-          }
-        }
-        return null;
-      };
-
-      // 计算默认选中的菜单项
-      const defaultActiveMenu = computed(() => {
-        if (props.activeMenu) {
-          const menu = findMenuByTitle(props.activeMenu);
-          if (menu) return menu;
-        }
-
-        const firstItem = props.menuList[0];
-        if (!firstItem) return null;
-
-        return firstItem.children?.length > 0
-            ? firstItem.children[0]
-            : firstItem;
-      });
-
-      const currentMenu = ref(defaultActiveMenu.value);
-
-      // 监听外部activeMenu变化
-      watch(
-          () => props.activeMenu,
-          (newTitle) => {
-            if (newTitle) {
-              const menu = findMenuByTitle(newTitle);
-              if (menu) {
-                currentMenu.value = menu;
-              }
-            }
-          }
-      );
-
-      // 选择菜单项时触发 menu-change 钩子
-      const selectItem = (item) => {
-        currentMenu.value = item;
-        emit("menu-change", item);
-      };
-
-      // 处理底部按钮点击
-      const handleFooterClick = (button, index) => {
-        emit("footer-click", { button, index });
-      };
-
-      return {
-        currentMenu,
-        selectItem,
-        handleFooterClick,
-      };
-    },
-    template: `
-          <div class="project-edit-container">
-              <div class="left-side" v-if="leftDisplay">
-              
-                  <!-- 头部图片 -->
-                  <div v-if="headerImage" class="menu-header">
-                      <div class="thumb">
-                          <img :src="headerImage" style="object-fit: cover;width: 100%;height: 100%;" />
-                      </div>
-                  </div>
-
-                  <!-- 菜单内容 -->
-                  <div class="menu-content">
-                      <div class="scroll-view">
-                          <template v-for="(menuItem, i) in menuList" :key="i">
-                              <!-- 分组菜单 -->
-                              <div v-if="menuItem.children?.length > 0" class="group">
-                                  <div class="menu-item" @click="menuItem.open = !menuItem.open">
-                                      <span>{{ menuItem.title }}</span>
-                                      
-                                      <span class="arrow">
-                                          <ss-icon :name="menuItem.open ? 'arrow-up' : 'arrow-down'" size="20px" />
-                                      </span>
-                                  </div>
-                                  <div v-show="menuItem.open" class="group-detail">
-                                      <div v-for="(item, j) in menuItem.children" 
-                                          :key="j" 
-                                          class="menu-item"
-                                          :class="{ active: item.name === currentMenu?.name }"
-                                          @click="selectItem(item)"
-                                      >
-                                          {{ item.title }}
-                                           
-                                           &nbsp;
-                                          <span class="menu-item-point" v-if="item.cgxList || item.objectList"></span>
-                                      </div>
-                                  </div>
-                              </div>
-                              <!-- 普通菜单项 -->
-                              <div v-else 
-                                  class="menu-item"
-                                  :class="{ active: menuItem.name === currentMenu?.name }"
-                                  @click="selectItem(menuItem)"
-                              >
-                                    {{ menuItem.title }}
-                                   &nbsp;
-                                  <span class="menu-item-point" v-if="menuItem.cgxList || menuItem.objectList"></span>
-                              </div>
-                          </template>
-                      </div>
-                  </div>
-                  
-                  <!-- 底部按钮 -->
-                  <div v-if="footerButtons.length > 0" 
-                      class="sub-tab-menu-footer"
-                      @click="footerButtons[0].onclick"
-                  >
-                      <div>{{ footerButtons[0].text }}</div>
-                      <ss-icon 
-                          v-if="footerButtons.length > 1" 
-                          name="arrow-up" 
-                          size="24px" 
-                      />
-                      
-                      <!-- 悬浮按钮 -->
-                      <div v-if="footerButtons.length > 1" class="sub-tab-menu-popup">
-                          <div v-for="(button, index) in footerButtons.slice(1)" 
-                              :key="index"
-                              @click.stop="button.onclick"
-                          >
-                              {{ button.text }}
-                          </div>
-                      </div>
-                  </div>
-                  
-              </div>
-
-              <!-- 右侧内容区域 -->
-              <div class="content-area fit-height-content" style="overflow: hidden;" :style="!leftDisplay ? { width: '100%' } : {}">
-                 
-                  <template v-for="(menuItem, i) in menuList" :key="i">
-                      <iframe 
-                          :src="menuItem.url"
-                          style="height: 100%;width: 100%;"
-                          frameborder="0"
-                          class="sub-tab-iframe"
-                          :id="i === 0 ? 'sub-tab-iframe' : ''"
-                          v-show="currentMenu?.name === menuItem.name"
-                      />
-                  </template>
-              </div>
-          </div>
-      `,
-  };
-  // <iframe
-  //     v-if="currentMenu?.url"
-  //     :src="currentMenu.url"
-  //     style="height: 100%;width: 100%;"
-  //     frameborder="0"
-  //     id="sub-tab-iframe"
-  // />
-
-  // ss-photo-upload 通用图片上传组件
-  const SsImgUpload = {
-    name: "SsImgUpload",
-    props: {
-      name: {
-        type: String,
-        required: true,
-      },
-      // 图片URL,用于回显
-      // url: {
-      //   type: String,
-      //   default: "",
-      // },
-      // 样式类名
-      class: {
-        type: String,
-        required: true,
-      },
-      // 裁剪配置
-      cropperOpt: {
-        type: Object,
-        default: () => ({
-          width: 360,
-          height: 360,
-          aspectRatio: 1,
-        }),
-      },
-      //上传图片url(未加图片名参数之前的部分)
-      ulUrl: {
-        type: String,
-        required: true,
-      },
-      //下载图片url(未加图片名参数之前的部分)
-      dlUrl: {
-        type: String,
-        required: true,
-      },
-      modelValue: [String, Number],
-    },
-
-    emits: ["update:modelValue"],
-
-    setup(props, { emit }) {
-      const inputId = Vue.computed(
-          () => `file_${Vue.getCurrentInstance().uid}`
-      );
-      //修改图片初始显示路径
-      let pathVal = ref(props.modelValue);
-      let picUrl = ref("");
-      if (props.modelValue) {
-        picUrl.value = props.dlUrl + "&path=" + props.modelValue;
-      }
-
-      Vue.onMounted(() => {
-        window.SS.cropper.init({
-          el: $(`#${inputId.value}`),
-          photoSize: {
-            width: props.cropperOpt.width,
-            height: props.cropperOpt.height,
-          },
-          aspectRatio: props.cropperOpt.aspectRatio,
-          uploadUrl: props.ulUrl,
-          success: (path) => {
-            pathVal.value = path;
-            picUrl.value = props.dlUrl + "&path=" + path;
-            emit("update:modelValue", path);
-          },
-        });
-      });
-
-      return () =>
-          h("div", { class: [props.class] }, [
-            h("input", {
-              type: "file",
-              accept: "image/*",
-              id: inputId.value,
-              style: { display: "none" },
-            }),
-            h("input", {
-              type: "hidden",
-              name: props.name,
-              value: pathVal.value,
-            }),
-            h(
-                "div",
-                {
-                  style: {
-                    width: "100%",
-                    height: "100%",
-                  },
-                  onClick: () => $(`#${inputId.value}`).click(),
-                },
-                [
-                  picUrl.value &&
-                  h("img", {
-                    src: picUrl.value,
-                    style:
-                        "width: 100%; height: 100%;object-fit: inherit;position: relative;z-index: 11;",
-                  }),
-                ]
-            ),
-          ]);
-    },
-  };
-
-  // 初始化函数,负责创建和挂载 Vue 应用
-  // window.SS = { dom: {} };
-  /**
-   * 获取当前窗口的父窗口
-   * @returns {Window} 父窗口对象
-   */
-  window.SS.topWin = (function (p, c) {
-    while (p != c) {
-      c = p;
-      p = p.parent;
-    }
-    return c;
-  })(window.parent, window);
-
-  window.SS.createSsDialogInstance = createSsDialogInstance;
-  /**
-   * 创建弹窗
-   * @param {Object} setting
-   * @param {Function} callbackEvent
-   */
-  window.SS.openDialog = function (setting, callbackEvent) {
-    if (setting.params) {
-      const encodedParams = encodeURIComponent(JSON.stringify(setting.params));
-      setting.src +=
-          (setting.src.includes("?") ? "&" : "?") + "params=" + encodedParams;
-    }
-
-    if (window.parent && window.parent !== window) {
-      window.parent.SS.createSsDialogInstance(setting, callbackEvent);
-    } else {
-      createSsDialogInstance(setting, callbackEvent);
-    }
-  };
-  //关闭弹窗
-  window.SS.closeDialog = function () {
-    console.log("关闭弹窗");
-    if (topWindow.dialogInstances.length > 0) {
-      const instance = topWindow.dialogInstances.pop();
-      console.log("instance", instance);
-      console.log("instance.callbackEvent", instance.callbackEvent);
-      console.log(
-          "instance.callbackEvent.end",
-          typeof instance.callbackEvent === "function"
-      );
-      if (instance.callbackEvent) {
-        // 判断是否有end回调并执行
-        if (typeof instance.callbackEvent === "function") {
-          instance.callbackEvent();
-        }
-        if (typeof instance.callbackEvent.end === "function") {
-          instance.callbackEvent.end();
-        }
-      }
-      instance.app.unmount(); // 卸载最后一个实例
-      if (instance.container && instance.container.parentNode) {
-        instance.container.parentNode.removeChild(instance.container); // 移除容器
-      }
-    }
-  };
-
-  /**
-   * 裁剪插件
-   */
-  window.SS.cropper = {
-    init: function (setting) {
-      if (!window.top.SS) window.top.SS = {};
-      // 重要:确保 cropper 对象的完整初始化
-      if (!window.top.SS.cropper) {
-        window.top.SS.cropper = {
-          settings: new Map(),
-          _backupSettings: {},
-          getSetting: this.getSetting,
-          clearSetting: this.clearSetting,
-          debug: this.debug,
-        };
-      } else if (!window.top.SS.cropper.settings) {
-        // 如果 cropper 存在但 settings 不存在,重新初始化 settings
-        window.top.SS.cropper.settings = new Map();
-        window.top.SS.cropper._backupSettings = {};
-      }
-      const uploaderId = `uploader_${Date.now()}_${Math.random()
-          .toString(36)
-          .substr(2, 9)}`;
-
-      window.top.SS.cropper.settings.set(uploaderId, setting);
-      window.top.SS.cropper._backupSettings[uploaderId] = setting;
-
-      setting.box = setting.box || "1";
-      var winSetting = {
-        headerTitle: "图片裁剪",
-        src: "/js/cropper/cropper.jsp",//原来在"/newUI/page/cropper.jsp" Ben(20251205)
-        width: "900",
-        height: "500",
-      };
-
-      $(setting.el).change(function () {
-        if (!window.SS.cropper.verify(setting)) {
-          $(setting.el).val(""); // 清空文件选择
-          return false;
-        }
-        var files = this.files;
-        if (files && files.length) {
-          if (!window.SS.cropper.verifySize($(setting.el)[0], 5)) {
-            $(setting.el).val(""); // 清空文件选择
-            alert("文件大小不能超过5M,请重新选择");
-            return false;
-          }
-          var URL = window.URL || window.webkitURL;
-          var file = files[0];
-          setting.file = file;
-
-          if (
-              /^image\/\w+$/.test(file.type) &&
-              /\.(jpg|jpeg|png|)$/i.test(file.name)
-          ) {
-            var uploadedImageURL = URL.createObjectURL(file);
-            setting.data = uploadedImageURL;
-            setting.fileName = file.name;
-            // console.log()
-            winSetting.params = {
-              ...setting,
-              uploaderId,
-            };
-            console.log("ss-componets中change之后的winSetting", winSetting);
-            SS.openDialog(winSetting, {
-              success: function (win) {
-                console.log("裁剪插件成功");
-                // win.cropperSetting = setting;
-              },
-              end: function () {
-                console.log("裁剪插件结束");
-                $(setting.el).val(""); // 清空文件选择
-              },
-            });
-          } else {
-            alert("请选择图片文件,支持jpg、jpeg、png格式");
-          }
-        }
-      });
-      return uploaderId;
-    },
-    verify: function (setting) {
-      if (!setting) {
-        console.error(" cropper setting is not undefined! ");
-        return false;
-      }
-      if (!setting.el) {
-        console.error(" cropper setting.el is not undefined! ");
-        return false;
-      }
-      if (setting.photoSize) {
-        if (
-            (!setting.photoSize.width && setting.photoSize.height) ||
-            (!setting.photoSize.height && setting.photoSize.width)
-        ) {
-          console.error(
-              " cropper setting.photoSize { width, height } is not undefined! "
-          );
-          return false;
-        }
-      }
-      if (!setting.box) {
-        setting.box = "1";
-      }
-
-      if (!setting.aspectRatio) {
-        setting.aspectRatio = 1 / 1;
-      }
-
-      return true;
-    },
-    verifySize: function (fileEl, maxSize) {
-      // 判断是否为IE浏览器: /msie/i.test(navigator.userAgent) 为一个简单正则
-      var isIE = /msie/i.test(navigator.userAgent) && !window.opera;
-      var fileSize = 0;
-      if (isIE && !fileEl.files) {
-        // IE浏览器
-        var filePath = fileEl.value; // 获得上传文件的绝对路径
-        var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
-        var file = fileSystem.GetFile(filePath);
-        fileSize = file.Size; // 文件大小,单位:b
-      } else {
-        // 非IE浏览器
-        fileSize = fileEl.files[0].size;
-      }
-
-      var size = fileSize / 1024 / 1024;
-      return !(size > maxSize);
-    },
-    // 获取特定上传组件的setting
-    getSetting: function (uploaderId) {
-      if (!window.top.SS?.cropper) {
-        console.warn("顶层窗口中未找到 SS.cropper");
-        return null;
-      }
-
-      // 优先从 Map 中获取
-      let setting = window.top.SS.cropper.settings.get(uploaderId);
-
-      // 如果 Map 中没有,尝试从备份中获取
-      if (!setting && window.top.SS.cropper._backupSettings[uploaderId]) {
-        console.log("从备份中恢复 setting");
-        setting = window.top.SS.cropper._backupSettings[uploaderId];
-        // 恢复到 Map 中
-        window.top.SS.cropper.settings.set(uploaderId, setting);
-      }
-
-      return setting;
-    },
-
-    // 清理特定上传组件的setting
-    clearSetting: function (uploaderId) {
-      if (!window.top.SS?.cropper) return;
-
-      window.top.SS.cropper.settings.delete(uploaderId);
-      delete window.top.SS.cropper._backupSettings[uploaderId];
-      console.log(
-          "清理设置后的 Map size:",
-          window.top.SS.cropper.settings.size
-      );
-    },
-  };
-
-  /**
-   * 获取url中的参数
-   * @returns {Object}
-   */
-  window.SS.getQueryParams = function () {
-    const params = {};
-    const queryString = window.location.search.substring(1);
-    const pairs = queryString.split("&");
-    for (let i = 0; i < pairs.length; i++) {
-      const pair = pairs[i].split("=");
-      params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
-    }
-    if (params.params) {
-      try {
-        params.params = JSON.parse(params.params);
-      } catch (e) {
-        console.error("Failed to parse params:", e);
-      }
-    }
-
-    return params;
-  };
-
-  /**
-   * 创建vue应用
-   * @param {Object} config 配置项
-   * @values {String} config.el 挂载的元素
-   * @values {Boolean} config.isDialogPage 是否是弹窗页面 决定了是否可以使用顶天立地
-   * @values {Object} config.vueOptions vue配置项
-   * @returns {Object} vue实例
-   */
-  window.SS.dom.initializeFormApp = function (config) {
-    const { el, isDialogPage = false, ...vueOptions } = config;
-    const app = createApp({
-      ...vueOptions,
-    });
-    // 如果是弹窗iframe里面的html的话 给当前的页面挂上事件 实现顶天立地的效果
-    if (isDialogPage) {
-      function checkScroll() {
-        // 选出所有fit-height-content的元素 如果有滚动条
-        const elements = document.querySelectorAll(".fit-height-content");
-        let hasScrollBar = false;
-        // 检查元素是否有滚动条 检查当前窗口的所有元素
-        // 如果有滚动条,则将结果设置为true
-        elements.forEach((el) => {
-          if (el.scrollHeight > el.clientHeight) {
-            hasScrollBar = true;
-          }
-        });
-        // 将结果发送给父窗口
-        window.parent.postMessage({ hasScrollBar }, "*");
-      }
-
-      function addScrollListeners() {
-        const elements = document.querySelectorAll("div");
-        elements.forEach((el) => {
-          el.addEventListener("scroll", checkScroll);
-        });
-      }
-      const observer = new MutationObserver((mutations) => {
-        addScrollListeners();
-        checkScroll();
-      });
-
-      observer.observe(document.body, {
-        childList: true,
-        subtree: true,
-      });
-
-      window.addEventListener("resize", checkScroll);
-    }
-    // 注册组件
-    app.component("SsLoginIcon", SsLoginIcon);
-    app.component("SsMark", SsMark);
-    app.component("SsFullStyleHeader", SsFullStyleHeader);
-    app.component("SsDialog", SsDialog);
-    app.component("SsInput", SsInput);
-    app.component("SsObjp", SsObjp);
-    app.component("SsHidden", SsHidden);
-    app.component("SsCcp", SsCcp);
-    app.component("SsDatePicker", SsDatePicker);
-    app.component("SsIcon", SsIcon);
-    app.component("SsCommonIcon", SsCommonIcon);
-    app.component("SsBreadcrumb", SsBreadcrumb);
-    app.component("SsEditor", SsEditor);
-    app.component("SsDialogIcon", SsDialogIcon);
-    app.component("SsBottomButton", SsBottomButton);
-    app.component("SsNavIcon", SsNavIcon);
-    app.component("SsHeaderIcon", SsHeaderIcon);
-    app.component("SsGolbalMenuIcon", SsGolbalMenuIcon);
-    app.component("SsCartListIcon", SsCartListIcon);
-    app.component("SsQuickIcon", SsQuickIcon);
-    app.component("SsFormIcon", SsFormIcon);
-    app.component("SsBottomDivIcon", SsBottomDivIcon);
-    app.component("SsEditorIcon", SsEditorIcon);
-    app.component("SsValidate", SsValidate);
-    app.component("SsOnoff", Ssonoff);
-    app.component("SsonoffArray", SsonoffArray);
-    app.component("SsTextarea", SsTextarea);
-    app.component("SsLoginInput", SsLoginInput);
-    app.component("SsLoginButton", SsLoginButton);
-    app.component("SsSearch", SsSearch);
-    app.component("SsCartItem", SsCartItem);
-    app.component("SsCartItem2", SsCartItem2);
-    app.component("SsListCard", SsListCard);
-    app.component("SsFolderCard", SsFolderCard);
-    app.component("SsFolderCartView", SsFolderCartView);
-    app.component("SsPage", SsPage);
-    app.component("SsRightInfo", SSRightInfo);
-    app.component("SsSuccessPopup", SsSuccessPopup);
-    app.component("SsErrorDialog", SsErrorDialog);
-    app.component("SsVerify", SsVerify);
-    app.component("SsVerifyNode", SsVerifyNode);
-    app.component("SsOrcImgBox", SsOrcImgBox);
-    app.component("ss-search-input", SsSearchInput);
-    app.component("ss-search-date-picker", SsSearchDatePicker);
-
-    app.component("ss-search-button", SsSearchButton);
-    app.component("ss-drop-button", SsDropButton);
-    app.component("ss-sub-tab", SsSubTab);
-    app.component("ss-img", SsImgUpload);
-    // 设置为中文
-    app.use(ElementPlus, {
-      locale: ElementPlusLocaleZhCn,
-    });
-    // console.log(ElementPlus);
-    // 确保 ElementPlusIconsVue
-    // if (window.ElementPlusIconsVue) {
-    //   // 注册 Element Plus 图标组件
-    //   for (const [key, component] of Object.entries(
-    //     window.ElementPlusIconsVue
-    //   )) {
-    //     console.log(key, component);
-    //     app.component(key, component);
-    //   }
-    // }
-    // 挂载首页的组件
-    for (const componentName in IndexComponents) {
-      app.component(componentName, IndexComponents[componentName]);
-    }
-    // 挂载echarts的组件
-    for (const componentName in EchartComponents) {
-      app.component(componentName, EchartComponents[componentName]);
-    }
-    // 挂载 Vue 应用
-    const vm = app.mount(el);
-    vm.data = vueOptions.data();
-
-    return vm;
-  };
-})();

+ 0 - 316
js/vue/ss-echarts-compnents.js

@@ -1,316 +0,0 @@
-// import { isNum, toStyleStr } from "../lib/tools.js";
-// import {eventBus,EVEN_VAR} from "../lib/EventBus.js";、
-import { debounce } from "./tools.js";
-export const MoneyStatistics = {
-    name: 'MoneyStatistics',
-    setup() {
-        // 初始化响应式引用
-        const chartInstance = Vue.ref(null);
-        const chartOption = {
-            xAxis: {
-                type: "category",
-                data: [
-                    "1万以下",
-                    "1-10万",
-                    "10-50万",
-                    "50-100万",
-                    "100-300万",
-                    "300-500万",
-                    "500-1000万",
-                    "1000-3000万",
-                    "3000万以上",
-                ],
-            },
-            yAxis: {
-                type: "value",
-            },
-            series: [
-                {
-                    data: [6, 12, 18, 23, 25, 30, 12, 7, 3],
-                    type: "bar",
-                },
-            ],
-        };
-        
-        const win = Vue.ref({ width: window.innerWidth });  // 假设宽度是浏览器窗口宽度
-        const domStyle = Vue.computed(() => {
-            const domWidth = (win.value.width - 140) / 2;
-            const initSize = { width: 890, height: 378 };
-            // 根据窗口大小调整宽高
-            if (domWidth < initSize.width / 2 || domWidth > initSize.width) {
-                return {
-                    width: initSize.width + "px",
-                    height: initSize.height + "px",
-                };
-            } else {
-                return {
-                    width: domWidth + "px",
-                    height: (domWidth * initSize.height) / initSize.width + "px",
-                };
-            }
-        });
-
-        // 初始化图表和调整大小
-        const initChart = () => {
-            const element = document.getElementById("statistics-chart");
-            if (element) {
-                chartInstance.value = echarts.init(element);
-                chartInstance.value.setOption(chartOption);
-            }
-        };
-        const resizeChart = debounce(() => chartInstance.value?.resize?.(), 80);
-
-        return {
-            domStyle,
-            initChart,
-            resizeChart,
-            onSetting: () => console.log("点击了设置按钮"),
-            onRefresh: () => console.log("点击了刷新按钮"),
-        };
-    },
-    mounted() {
-        this.initChart();
-    },
-    render() {
-        const HeaderContainer = Vue.resolveComponent('header-container');
-        
-        return Vue.h('div', { class: 'statistics-container', style: this.domStyle }, [
-            Vue.h('div', { class: 'header' }, [
-                Vue.h(HeaderContainer, { title: "金额分布", onSetting: this.onSetting, onRefresh: this.onRefresh })
-            ]),
-            Vue.h('div', { class: 'body' }, [
-                Vue.h('div', { id: "statistics-chart", class: 'chart-container' })
-            ])
-        ]);
-    }
-};
-export const DepartmentStatistics = {
-    name: 'DepartmentStatistics',
-    setup() {
-        const chartInstance = Vue.ref(null);
-        const chartOption = Vue.computed(() => ({
-            title: {
-                text: "Referer of a Website",
-                subtext: "Fake Data",
-                left: "center",
-            },
-            tooltip: {
-                trigger: "item",
-            },
-            legend: {
-                orient: "vertical",
-                left: "left",
-            },
-            series: [
-                {
-                    name: "Access From",
-                    type: "pie",
-                    radius: "50%",
-                    data: [
-                        { value: 1048, name: "Search Engine" },
-                        { value: 735, name: "Direct" },
-                        { value: 580, name: "Email" },
-                        { value: 484, name: "Union Ads" },
-                        { value: 300, name: "Video Ads" }
-                    ],
-                    emphasis: {
-                        itemStyle: {
-                            shadowBlur: 10,
-                            shadowOffsetX: 0,
-                            shadowColor: "rgba(0, 0, 0, 0.5)"
-                        }
-                    }
-                }
-            ]
-        }));
-
-        const win = Vue.ref({ width: window.innerWidth });
-        const domStyle = Vue.computed(() => {
-            const domWidth = (win.value.width - 140) / 2;
-            const initSize = { width: 890, height: 378 };
-            if (domWidth < initSize.width / 2 || domWidth > initSize.width) {
-                return {
-                    width: initSize.width + "px",
-                    height: initSize.height + "px",
-                };
-            } else {
-                return {
-                    width: domWidth + "px",
-                    height: (domWidth * initSize.height) / initSize.width + "px",
-                };
-            }
-        });
-        const initChart = () => {
-            const element = document.getElementById("statistics-chart-department");
-            if (element) {
-                chartInstance.value = echarts.init(element);
-                chartInstance.value.setOption(chartOption.value);
-            }
-        };
-        const resizeChart = debounce(() => chartInstance.value?.resize?.(), 80);
-
-        return {
-            domStyle,
-            initChart,
-            resizeChart,
-            onSetting: () => console.log("点击了设置按钮"),
-            onRefresh: () => console.log("点击了刷新按钮"),
-        };
-    },
-    mounted() {
-        this.initChart();
-    },
-    render() {
-        const HeaderContainer = Vue.resolveComponent('header-container');
-        return Vue.h('div', { class: 'statistics-container', style: this.domStyle }, [
-            Vue.h('div', { class: 'header' }, [
-                Vue.h(HeaderContainer, { title: "省内项目主管部门分布", onSetting: this.onSetting, onRefresh: this.onRefresh })
-            ]),
-            Vue.h('div', { class: 'body' }, [
-                Vue.h('div', { id: "statistics-chart-department", class: 'chart-container' })
-            ])
-        ]);
-    }
-};
-export const ProjectReportStatistics = {
-    name: 'ProjectReportStatistics',
-    setup() {
-        const win = Vue.ref({ width: window.innerWidth });
-        const domStyle = Vue.computed(() => {
-            const domWidth = (win.value.width - 140) / 2;
-            const initSize = { width: 890, height: 444 };
-            if (domWidth < initSize.width / 2 || domWidth > initSize.width) {
-                return {
-                    width: initSize.width + "px",
-                    height: initSize.height + "px",
-                };
-            } else {
-                return {
-                    width: domWidth + "px",
-                    height: (domWidth * initSize.height) / initSize.width + "px",
-                };
-            }
-        });
-
-        const list = Vue.ref([
-            {
-                title: "年度项目收付款情况",
-                columns: [
-                    "客户名称", "项目", "项目状态", "负责人", "金额", "款项进度", "客户联系人", "联系电话"
-                ]
-            },
-            {
-                title: "年度项目合同情况汇总表",
-                columns: [
-                    "客户名称", "名称", "状态", "金额", "签订日期", "到期日期", "业务负责人"
-                ]
-            },
-            {
-                title: "项目省内分布报表",
-                columns: ["区域", "数量", "总金额", "项目", "客户", "状态"]
-            }
-        ]);
-
-        return {
-            domStyle,
-            list,
-            onSetting: () => console.log("点击了设置按钮"),
-            onRefresh: () => console.log("点击了刷新按钮"),
-        };
-    },
-    render() {
-        const HeaderContainer = Vue.resolveComponent('header-container');
-        return Vue.h('div', { class: 'statistics-container', style: this.domStyle }, [
-            Vue.h('div', { class: 'header' }, [
-                Vue.h(HeaderContainer, { title: "项目情况报表", onSetting: this.onSetting, onRefresh: this.onRefresh })
-            ]),
-            Vue.h('div', { class: 'body' }, this.list.map((item, i) =>
-                Vue.h('div', { key: i, class: 'table-container' }, [
-                    Vue.h('div', { class: 'title' }, item.title),
-                    Vue.h('div', { class: 'table-columns' }, item.columns.map((tableItem, j) =>
-                        Vue.h('div', { key: j, class: 'table-item' }, tableItem)
-                    ))
-                ])
-            ))
-        ]);
-    }
-};
-
-export const IndustryStatistics = {
-    name: 'IndustryStatistics',
-    setup() {
-        // Initialize reactive references
-        const win = Vue.ref({ width: window.innerWidth });
-        const chartInstance = Vue.ref(null);
-        const domStyle = Vue.computed(() => {
-            const domWidth = (win.value.width - 140) / 2;
-            const initSize = { width: 890, height: 444 };
-            if (domWidth < initSize.width / 2 || domWidth > initSize.width) {
-                return {
-                    width: initSize.width + "px",
-                    height: initSize.height + "px",
-                };
-            } else {
-                return {
-                    width: domWidth + "px",
-                    height: (domWidth * initSize.height) / initSize.width + "px",
-                };
-            }
-        });
-
-        const chartOption = {
-            xAxis: {
-                type: "category",
-                data: [
-                    "1万以下", "1-10万", "10-50万", "50-100万", "100-300万",
-                    "300-500万", "500-1000万", "1000-3000万", "3000万以上"
-                ]
-            },
-            yAxis: {
-                type: "value"
-            },
-            series: [{
-                data: [6, 12, 18, 23, 25, 30, 12, 7, 3],
-                type: "bar"
-            }]
-        };
-
-        const initChart = () => {
-            chartInstance.value = echarts.init(document.getElementById("statistics-chart-industry"));
-            chartInstance.value.setOption(chartOption);
-        };
-
-        const onSetting = () => console.log("Clicked on settings button");
-        const onRefresh = () => console.log("Clicked on refresh button");
-
-        const resizeChart = debounce(() => {
-            chartInstance.value?.resize();
-        }, 80);
-
-        Vue.onMounted(() => {
-            initChart();
-            window.addEventListener('resize', resizeChart);
-        });
-
-        Vue.onUnmounted(() => {
-            window.removeEventListener('resize', resizeChart);
-        });
-
-        return {
-            domStyle,
-            onSetting,
-            onRefresh,
-        };
-    },
-    render() {
-        const HeaderContainer = Vue.resolveComponent('header-container');
-        return Vue.h('div', { class: 'statistics-container', style: this.domStyle }, [
-            Vue.h('div', { class: 'header' }, [
-                Vue.h(HeaderContainer, { title: "项目产业分布", onSetting: this.onSetting, onRefresh: this.onRefresh })
-            ]),
-            Vue.h('div', { class: 'body' }, [
-                Vue.h('div', { id: 'statistics-chart-industry', class: 'chart-container' })
-            ])
-        ]);
-    }
-};

+ 0 - 1156
js/vue/ss-index-components.js

@@ -1,1156 +0,0 @@
-import { isNum, toStyleStr } from "./tools.js";
-import { eventBus, EVEN_VAR } from "./EventBus.js";
-// import { debounce } from "../lib/tools.js";
-// 首页组件的名字
-const winName = {
-    launch: "launch",
-    Notice: "Notice",
-    Statistics: "Statistics",
-    TodoList: "TodoList",
-    UrgingList: "UrgingList",
-    UserInfo: "UserInfo",
-};
-// 尺寸窗口名字
-const size2Win = (name) => `${name}-${document.body.clientWidth}`;
-// 加载尺寸
-const loadWinSize = function (name) {
-    const val = localStorage.getItem(size2Win(name));
-    if (val) {
-        try {
-            return JSON.parse(val) || {};
-        } catch (err) {
-            return {};
-        }
-    } else {
-        return {};
-    }
-};
-const saveWinSize = function (name, obj) {
-    localStorage.setItem(size2Win(name), JSON.stringify(obj));
-};
-
-// 全局头部
-export const GlobalHeader = {
-    name: 'GlobalHeader',
-    props: {
-        menuData: {
-            type: Array,
-            required: true
-        },
-        iconItems: {
-            type: Array,
-            required: true
-        }
-    },
-    setup(props) {
-
-        //原值为'/newUI/skin/easy/images/logo/full-logo.png' Ben(20251205)
-        const fullLogo = Vue.ref('/skin/easy/images/logo/full-logo.png'); // 需要指定完整路径
-
-
-        const convertMenuData = (menuData) => {
-            return menuData.map(item => ({
-              id: item.id, //菜单id
-              pid: item.pid, //父菜单id
-              label: item.desc, //菜单名称
-              component: item.url, //菜单链接
-              js: item.js, //菜单要执行的js
-              class: item.icon, // 如果icon为空则使用默认class
-              itemType: item.type, //菜单 1:菜单项 2:菜单组
-            }));
-        };
-        const menuItemsNew = Vue.ref(convertMenuData(props.menuData));
-        Vue.watchEffect(() => {
-            if (props.menuData && props.menuData.length) {
-                menuItemsNew.value = convertMenuData(props.menuData);
-                console.log('Header menu items updated:', menuItemsNew.value);
-            }
-        });
-
-        
-        
-        const menuItems = Vue.ref([]);
-        const breadCrumbs = Vue.ref([
-            { label: '首页', component: '/index.html' },
-        ]);
-        const iconItems = Vue.ref(props.iconItems);
-        const onClickMenuItemsNew = (item) => {
-            console.log(item.component, item.js)
-            if (item.component && item.js) {
-                eval(item.js)
-            } else if(item.component){
-                eventBus.publish(EVEN_VAR.currentPage, item.component);
-            } else {
-                eval(item.js)
-            }
-        };
-        const onClickMenuItem = (item) => {
-            if (item.type == 'page') {
-                eventBus.publish(EVEN_VAR.currentPage, item.component);
-                breadCrumbs.value[0] = item
-            } else if (item.type == 'dialog') {
-                SS.openDialog({
-                    headerTitle: item.label,
-                    src: '.'+item.component,
-                    height: item.height,
-                    width:item.width
-                });
-            }
-        };
-        const breadCrumbClick = (item) => {
-            eventBus.publish(EVEN_VAR.currentPage, item.component);
-            breadCrumbs.value[0] = item
-        }
-        const gotoSearch = () => {
-            eventBus.publish(EVEN_VAR.showGlobalSearchDialog);
-        };
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        const SsHeaderIcon = Vue.resolveComponent('ss-header-icon');
-        const SsGolbalMenuIcon = Vue.resolveComponent('ss-golbal-menu-icon');
-        // 引入搜索框
-        const SsSearch = Vue.resolveComponent('ss-search');
-        // 处理面包屑导航
-        const renderBreadcrumbs = () => {
-            const breadcrumbElements = [Vue.h(SsIcon, { class: "home-icon", name: "home", type: "common", size: "22px" })];
-            // 遍历面包屑数组,添加面包屑和分隔符
-            breadCrumbs.value.forEach((crumb, index) => {
-                // 添加面包屑链接
-                breadcrumbElements.push(
-                    Vue.h('span', { onClick: () => breadCrumbClick(crumb) }, crumb.label)
-                );
-                // 除了最后一个元素,每个面包屑后添加分隔符图标
-                if (index < breadCrumbs.value.length - 1) {
-                    breadcrumbElements.push(
-                        Vue.h(SsIcon, { class: "split-icon", size: "12px", name: "double-arrow-right", type: "common" })
-                    );
-                }
-            });
-            return breadcrumbElements;
-        };
-        return () => Vue.h('div', { class: 'block-self flex-between-center global-header-container' }, [
-            Vue.h('div', { class: 'icon-area flex-start-center' }, [
-                Vue.h('div', { class: 'logo', onClick: () => console.log('Home clicked') }, [
-                    Vue.h('div', { class: 'img' }, [
-                        Vue.h('img', { src: fullLogo.value })
-                    ]),
-                    Vue.h('div', { class: 'menu', onClick: Vue.withModifiers(() => { }, ['stop']) },
-                        // menuItems.value.map(item =>
-                        //     Vue.h('div', { onClick: () => onClickMenuItem(item) },[
-                        //         Vue.h(SsGolbalMenuIcon, { class: item.class || '' }),
-                        //         item.label
-                        //     ])
-                        // )
-                        menuItemsNew.value.map(item =>
-                            Vue.h('div', { onClick: () => onClickMenuItemsNew(item) },[
-                                Vue.h(SsGolbalMenuIcon, { class: item.class || '' }),
-                                item.label
-                            ])
-                        )
-                    )
-                ]),
-                // Vue.h('div', { class: 'bread-crumb', style: { height: "100% !important" } }, [
-                    // Vue.h('div', { class: 'content' }, renderBreadcrumbs())
-                // ])
-            ]),
-            Vue.h('div', { class: 'menu-area' },
-                Vue.h('div', { class: 'search-area' }, [
-                    Vue.h(SsSearch, { theme: 'dark', placeholder: '跨对象搜索', onClick: gotoSearch })
-                ]),
-                iconItems.value.map(icon =>
-                    Vue.h('div', { class: 'icon-item', onClick: icon.action, style: { display: icon.condition ? (icon.condition() ? 'block' : 'none') : 'block' } }, [
-                        Vue.h(SsHeaderIcon, { class: icon.class })
-                    ])
-                )
-            )
-        ]);
-    }
-};
-// 全局菜单
-export const GlobalMenu = {
-    name: 'GlobalMenu',
-    props: {
-        menuItems: {
-            type: Array,
-            required: true
-        },
-        initialSize: {
-            type: String,
-            default: 'min'
-        },
-        // onMenuClick: {
-        //     type: Function,
-        //     required: true,
-        //     default: () => {}
-        // }
-    },
-    setup(props) {
-        const menuItemsNew = Vue.ref([]);
-        
-        const activeItem = Vue.ref(''); // 默认选中第一个菜单项
-     
-        // 将后台返回的菜单数据转换为树结构
-        const convertMenuDataToTree = (menuData) => {
-            // 先转换格式
-            const formattedData = menuData.map(item => ({
-                id: item.id,
-                pid: item.pid,
-                name: item.desc,
-                component: item.url,
-                js: item.js,
-                class: item.type == 1 ? 'nav-icon-folder-close' : item.icon || 'header-home',
-                itemType: item.type,
-                children: []
-            }));
-        
-            // 创建一个映射表,方便查找
-            const map = {};
-            formattedData.forEach(item => {
-                map[item.id] = item;
-            });
-        
-            // 构建树结构
-            const treeData = [];
-            formattedData.forEach(item => {
-                if (item.pid && map[item.pid]) {
-                    // 如果有父节点,就放到父节点的children中
-                    if (!map[item.pid].children) {
-                        map[item.pid].children = [];
-                    }
-                    map[item.pid].children.push(item);
-                } else {
-                    // 没有父节点就是顶层节点
-                    treeData.push(item);
-                }
-            });
-        
-            return treeData;
-        };
-         // 添加 watchEffect 来监听 props.menuItems 的变化
-         Vue.watchEffect(() => {
-            if (props.menuItems && props.menuItems.length) {
-                menuItemsNew.value = convertMenuDataToTree(props.menuItems);
-                activeItem.value = menuItemsNew.value[0]?.name || '';
-                console.log('Menu items updated:', menuItemsNew.value);
-                if(menuItemsNew.value[0]?.component){
-                    eventBus.publish(EVEN_VAR.currentPage, menuItemsNew.value[0]?.component);
-                }else{
-                    eventBus.publish(EVEN_VAR.currentPage, menuItemsNew.value[0]?.children[0]?.component);
-                }
-
-            }
-        });
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        const SsNavIcon = Vue.resolveComponent('ss-nav-icon');
-        // 移动状态控制逻辑到组件内
-        const leftSideTypeDict = {
-            min: { key: "min", icon: "arrow-double-right" },
-            max: { key: "max", icon: "arrow-double-left" },
-        };
-        
-        const leftSideType = Vue.ref(leftSideTypeDict[props.initialSize]);
-        let waitLeftSideChangeTimer = null;
-        
-        // 控制子菜单展开状态
-        const expandedMenus = Vue.ref(new Set());
-
-        const onMenuClick = (item) => {
-            console.log(item)
-            console.log(activeItem.value)
-            if(item.component && item.js){
-                eval(item.js)
-            } else if(item.component){
-                eventBus.publish(EVEN_VAR.currentPage, item.component);
-            }else{
-                eval(item.js)
-            }
-        }
-        const toggleLeftSideType = () => {
-            leftSideType.value = 
-                leftSideType.value.key === 'min' ? leftSideTypeDict.max : leftSideTypeDict.min;
-        };
-
-        const doChangeLeftSideType2Max = () => {
-            if (leftSideType.value.key === 'min') {
-                clearTimeout(waitLeftSideChangeTimer);
-                waitLeftSideChangeTimer = setTimeout(() => {
-                    leftSideType.value = leftSideTypeDict.max;
-                }, 1000);
-            }
-        };
-
-        const onLeaveLeftMenuArea = () => {
-            if (waitLeftSideChangeTimer) {
-                clearTimeout(waitLeftSideChangeTimer);
-                waitLeftSideChangeTimer = null;
-                leftSideType.value = leftSideTypeDict.min;
-            }
-        };
-
-        return () => Vue.h('div', { class: 'left-side' }, [
-            Vue.h('div', { 
-                class: 'left-side-container',
-                size: leftSideType.value.key
-            }, [
-                // 收缩按钮
-                Vue.h('div', { 
-                    class: 'btn-size',
-                    onClick: toggleLeftSideType
-                }, [
-                    Vue.h(SsIcon, {
-                        name: leftSideType.value.icon,
-                        type: 'common',
-                        size: '12px'
-                    })
-                ]),
-                // 左侧内容
-                Vue.h('div', {
-                    class: 'left-side-content',
-                    onMouseenter: doChangeLeftSideType2Max,
-                    onMousemove: doChangeLeftSideType2Max,
-                    onMouseleave: onLeaveLeftMenuArea
-                }, [
-                    // 菜单项列表
-                    ...menuItemsNew.value.map(icon => [
-                        // 父菜单项
-                        Vue.h('div', { 
-                            class:['menu-item',{active:activeItem.value === icon.name}],
-                            onClick: () => {
-                                activeItem.value = icon.name;
-                                if (icon.children.length > 0) {
-                                    if (expandedMenus.value.has(icon.name)) {
-                                        expandedMenus.value.delete(icon.name);
-                                    } else {
-                                        expandedMenus.value.add(icon.name);
-                                    }
-                                } else {
-                                    onMenuClick(icon);
-
-                                }
-                            }
-                        }, [
-                            Vue.h('div', { class: 'menu-item-content' }, [
-                                Vue.h(SsNavIcon, { 
-                                    // 如果是文件夹类型(type == 1),根据展开状态设置不同的class
-                                    class: icon.itemType == 1 ? 
-                                        (expandedMenus.value.has(icon.name) ? 'nav-icon-folder-open' : 'nav-icon-folder-close') 
-                                        : (icon.class || '')
-                                }),
-                                Vue.h('div', { class: 'menu-item-label' }, icon.name || ''),
-                                Vue.h('div', { class: 'edit-mark' }, [
-                                    Vue.h(SsIcon, { name: 'close-mark-fill', size: '36px' })
-                                ])
-                            ])
-                        ]),
-                        // 子菜单项(与父菜单项同级)
-                        ...(icon.children && expandedMenus.value.has(icon.name) ? 
-                            icon.children.map(child => 
-                                Vue.h('div', { 
-                                    class:['menu-item',{active:activeItem.value === child.name}],
-                                    onClick: (e) => {
-                                        activeItem.value = child.name;
-                                        e.stopPropagation();
-                                        onMenuClick(child);
-                                    }
-                                }, [
-                                    Vue.h('div', { class: 'menu-item-content' }, [
-                                        Vue.h('div', { class: 'icon-container' }, [  // 添加图标容器
-                                            Vue.h(SsNavIcon, { 
-                                                class: child.class || ''
-                                            }),
-                                            Vue.h('div', { class: 'menu-item-dot' })  // 小圆点放在图标容器内
-                                        ]),
-                                        Vue.h('div', { class: 'menu-item-label' }, child.name),
-                                        Vue.h('div', { class: 'edit-mark' }, [
-                                            Vue.h(SsIcon, { name: 'close-mark-fill', size: '36px' })
-                                        ])
-                                    ])
-                                ])
-                            ) : []
-                        )
-                    ]).flat(),
-                    // 添加按钮
-                    Vue.h('div', { class: 'menu-item add-menu-btn' }, [
-                        Vue.h('div', { class: 'add' }, [
-                            Vue.h(SsNavIcon, { class: 'nav-icon-add' })
-                        ])
-                    ])
-                ])
-            ])
-        ]);
-    }
-};
-// 基础组件 首页组件头部
-export const HeaderContainer = {
-    name: 'HeaderContainer',
-    props: {
-        title: String,
-        icon: String,
-    },
-    emits: ['setting', 'refresh'],
-    setup(props, { emit }) {
-        const onSetting = () => {
-            emit('setting');
-        };
-        const onRefresh = () => {
-            emit('refresh');
-        };
-        return {
-            props,
-            onSetting,
-            onRefresh
-        };
-    },
-    render() {
-        const SsIcon = Vue.resolveComponent('ss-icon');
-       
-        return Vue.h('div', { class: 'edit-box-header-container' }, [
-            Vue.h('div', { class: ['title', { visibility: !!(this.props.icon || this.props.title) }] }, [
-                this.props.icon ? Vue.h('div', { class: 'icon', onClick: this.onRefresh }, [
-                    Vue.h(SsIcon, { class: 'normal', name: this.props.icon, size: '22px' }),
-                    Vue.h(SsIcon, { class: 'hover', name: 'refresh', size: '22px' })
-                ]) : null,
-                Vue.h('div', this.props.title)
-            ]),
-            Vue.h('div', { class: 'handle-bar' }, [
-                Vue.h('div', { class: 'left-bar' }), // Assuming left-bar is empty
-                Vue.h('div', { class: 'setting', onClick: this.onSetting }, [
-                    Vue.h(SsIcon, { name: 'setting', size: '22px' })
-                ])
-            ])
-        ]);
-    }
-};
-// 基础组件 首页组件边框
-export const EditBox = {
-    name: 'EditBox',
-    setup(props, { emit, slots }) {
-        const mousePos = Vue.reactive({
-            rightCenter: "right-center",
-            rightBottom: "right-bottom",
-            bottomCenter: "bottom-center",
-        });
-        const curActionMousePos = Vue.ref("");
-        const editBoxContainer = Vue.ref(null);
-        const onMousemove = (e) => {
-            if (e.buttons === 1 && curActionMousePos.value) {
-                const dom = editBoxContainer.value;
-                if (dom) {
-                    const zoom = Number(document.body.style.zoom || 1);
-                    const winRect = dom.getBoundingClientRect();
-                    const { x: xSource, y: ySource } = e;
-                    const x = xSource / zoom;
-                    const y = ySource / zoom;
-                    const val = {
-                        left: winRect.left,
-                        top: winRect.top,
-                        width: winRect.width,
-                        height: winRect.height,
-                    };
-
-                    const toHObj = (source) => ({
-                        ...source,
-                        height: Math.abs(y - source.top),
-                        top: y >= 0 ? source.top : source.top + (y - source.top),
-                    });
-
-                    const toWObj = (source) => ({
-                        ...source,
-                        width: Math.abs(x - source.left),
-                        left: x >= 0 ? source.left : source.left + (x - source.left),
-                    });
-
-                    if (curActionMousePos.value === mousePos.bottomCenter) {
-                        emit("size", toHObj(val));
-                    } else if (curActionMousePos.value === mousePos.rightCenter) {
-                        emit("size", toWObj(val));
-                    } else if (curActionMousePos.value === mousePos.rightBottom) {
-                        emit("size", toWObj(toHObj(val)));
-                    }
-                }
-            }
-        };
-        const onMouseup = () => {
-            curActionMousePos.value = "";
-        };
-        const onMouseDown = (pos) => {
-            console.log(pos)
-            curActionMousePos.value = pos;
-        };
-        Vue.onMounted(() => {
-            document.body.addEventListener("mousemove", onMousemove);
-            document.body.addEventListener("mouseup", onMouseup);
-        });
-        Vue.onUnmounted(() => {
-            document.body.removeEventListener("mousemove", onMousemove);
-            document.body.removeEventListener("mouseup", onMouseup);
-        });
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        return () => Vue.h('div', { class: 'edit-box-container', ref: editBoxContainer }, [
-            Vue.h('div', { class: ['edit-tools', { active: !!curActionMousePos.value }] }, [
-                Vue.h('div', { class: 'close' }, [
-                    Vue.h(SsIcon, { name: "close-mark-fill", size: "36px" })
-                ]),
-                Vue.h('div', { class: 'right-center', onMousedown: () => onMouseDown(mousePos.rightCenter) }, [
-                    Vue.h('div', { class: 'icon' }, [
-                        Vue.h(SsIcon, { name: "resize", size: "30px" })
-                    ])
-                ]),
-                Vue.h('div', { class: 'right-bottom', onMousedown: () => onMouseDown(mousePos.rightBottom) }, [
-                    Vue.h('div', { class: 'icon' }, [
-                        Vue.h(SsIcon, { name: "resize", size: "30px" })
-                    ])
-                ]),
-                Vue.h('div', { class: 'bottom-center', onMousedown: () => onMouseDown(mousePos.bottomCenter) }, [
-                    Vue.h('div', { class: 'icon' }, [
-                        Vue.h(SsIcon, { name: "resize", size: "30px" })
-                    ])
-                ])
-            ]),
-            Vue.h('div', { class: 'content-area' }, slots.default ? slots.default() : [])
-        ]);
-    }
-};
-// 基础组件 头像
-export const Avatar = {
-    name: 'Avatar',
-    props: {
-        url: {
-            type: String,
-            required: true
-        },
-        size: {
-            type: [String, Number],
-            default: 50
-        },
-        unit: {
-            type: String,
-            default: 'px'
-        },
-        shape: {
-            validator: function (value) {
-                return ['circle', 'round'].includes(value);
-            },
-            default: 'circle'
-        }
-    },
-    setup(props) {
-        // 计算属性,转换尺寸并添加单位
-        const style = Vue.computed(() => {
-            const addUnit = (n) => isNum(n) ? `${n}${props.unit}` : (n || '');
-            const styleObj = {
-                width: addUnit(props.size),
-                height: addUnit(props.size),
-            };
-            return toStyleStr(styleObj);
-        });
-
-        // 返回渲染函数所需要的数据
-        return {
-            props,
-            style
-        };
-    },
-    render() {
-        return Vue.h('img', {
-            src: this.props.url,
-            style: this.style.value,
-            class: ['avatar-container', this.props.shape]
-        });
-    }
-};
-
-// 基础组件 文件夹或者文件的组件
-export const FolderContainer = {
-    name: 'FolderContainer',
-    props: {
-        list: {
-            type: Array,
-            required: true,
-        },
-        draggable: {
-            type: Boolean,
-            default: false,
-        },
-    },
-    setup(props, { emit }) {
-        const toggleFolder = (index, isFolder) => {
-            const item = props.list[index];
-            if (isFolder) {
-                item.open = !item.open;
-            }
-        };
-
-        const onClickItem = (item) => {
-            emit('click', item);
-        };
-
-        const onItemStartDrag = (e, item) => {
-            e.dataTransfer.setData("text/plain", JSON.stringify(item));
-            console.log("开始拖拽的对象是=>", { item });
-        };
-
-        const onItemDrop = (e, item, pre) => {
-            var data = e.dataTransfer.getData("text/plain");
-            try {
-                const obj = JSON.parse(data);
-                item.children.push(obj);
-                console.log("目标对象=>", { e, item, pre, obj });
-            } catch (err) {
-                console.log("拖拽的节点不正确", { item, err });
-            }
-        };
-
-        return {
-            toggleFolder,
-            onClickItem,
-            onItemStartDrag,
-            onItemDrop,
-        };
-    },
-    render() {
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        return Vue.h('div', { class: 'folder-container' }, this.list.map((groupItem, i) => {
-            return Vue.h('div', { class: 'group-item', key: i }, [
-                Vue.h('div', {
-                    class: ['group-title', { active: !!groupItem.curActionMousePos }],
-                    onDrop: $event => this.onItemDrop($event, groupItem),
-                    onDragover: $event => $event.preventDefault(),
-                }, [
-                    groupItem.type === 'folder' ? Vue.h('div', {
-                        class: 'folder',
-                        onClick: $event => this.toggleFolder(i, groupItem.type === 'folder'),
-                        'data-num': groupItem.children.length,
-                    }, [
-                        groupItem.open ? Vue.h(SsIcon, { name: 'folder-expand-fill' }) : Vue.h(SsIcon, { name: 'folder-collapse-fill' })
-                    ]) : groupItem.type === 'file' ? Vue.h(SsIcon, { name: 'file' }) : null,
-                    Vue.h('div', groupItem.title)
-                ]),
-                groupItem.children.length > 0 && groupItem.open ? Vue.h('ul', {
-                    class: 'group-childs',
-                    onDrop: $event => this.onItemDrop($event, groupItem),
-                    onDragover: $event => $event.preventDefault(),
-                }, groupItem.children.map((item, j) => {
-                    return Vue.h('li', {
-                        key: j,
-                        draggable: this.draggable,
-                        onDragstart: $event => this.onItemStartDrag($event, item),
-                        onDrop: $event => this.onItemDrop($event, groupItem, item),
-                        onDragover: $event => $event.preventDefault(),
-                        onClick: () => this.onClickItem(item),
-                    }, [
-                        Vue.h('div', item.title),
-                        Vue.h('div', item.time)
-                    ]);
-                })) : null
-            ]);
-        }));
-    }
-};
-// 个人卡片
-export const UserInfo = {
-    name: 'UserInfo',
-    props: {
-        obj: {
-            type: Object,
-            default: () => ({})
-        }
-    },
-    setup(props, { emit }) {
-        const winInfo = Vue.reactive(loadWinSize(winName.UserInfo));
-        const onSetting = () => {
-            console.log("点击了设置按钮");
-        };
-        const onRefresh = () => {
-            console.log("点击了刷新按钮");
-        };
-        const onSizeChange = (rect) => {
-
-            const style = {};
-            for (const key in rect) {
-                style[key] = rect[key] + 'px';
-            }
-            saveWinSize(winName.UserInfo, style);
-            Object.assign(winInfo, style);
-        };
-        return {
-            winInfo,
-            onSetting,
-            onRefresh,
-            onSizeChange,
-            props
-        };
-    },
-    render() {
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        return Vue.h('div', { class: 'user-info-container can-resize-box', style: this.winInfo },
-            Vue.h(EditBox, {
-                onSize: this.onSizeChange
-            }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' },
-                        Vue.h(HeaderContainer, {
-                            onSetting: this.onSetting,
-                            onRefresh: this.onRefresh
-                        })
-                    ),
-                    Vue.h('div', { class: 'body' }, [
-                        Vue.h('div', { class: 'user-info', style: "margin-bottom: 18px" }, [
-                            Vue.h('div', { class: 'avatar' },
-                                Vue.h(Avatar, {
-                                    url: '../images/example/user-avatar.png',
-                                    size: '90px'
-                                })
-                            ),
-                            Vue.h('div', { class: 'info' }, [
-                                Vue.h('p', this.props.obj.name + ',上午好!'),
-                                Vue.h('p', '最近登录时间:2024年/08/08 13:03'),
-                                Vue.h('p', '明天有暴雨,记得出门带伞噢!')
-                            ])
-                        ]),
-                        Vue.h('div', { class: 'progress-bar' }, [
-                            Vue.h('div', { class: 'progress' }, [
-                                Vue.h('div', { class: 'line', style: 'width: 60%' }, [
-                                    Vue.h('div', '60%(课时)')
-                                ])
-                            ])
-                        ]),
-                        Vue.h('div', { class: 'other-info' }, [
-                            Vue.h('div', {}, [
-                                Vue.h(SsIcon, { name: "userGroup", size: "22px" }),
-                                Vue.h('div', {}, "《关于公司全面预算规划会议》"),
-                            ]),
-                            Vue.h('div', {}, [
-                                Vue.h(SsIcon, { name: "card", type: "common", size: "22px" }),
-                                Vue.h('div', {}, "一卡通余额:**************"),
-                            ]),
-                            Vue.h('div', {}, [
-                                Vue.h(SsIcon, { name: "site", type: "common", size: "22px" }),
-                                Vue.h('div', {}, "个人网站:xxx.xxx.xxx"),
-                            ]),
-                        ])
-                    ])
-                ]
-            })
-        );
-    }
-};
-// 待办
-export const TodoList = {
-    name: 'TodoList',
-    setup() {
-        const todoGroupList = Vue.reactive([
-            {
-                title: "草稿",
-                type: "folder",
-                open: false,
-                children: [
-                    { title: "被退回", time: "08/10 18:12" },
-                    { title: "项目立项申请", time: "08/10 18:12" },
-                    { title: "报销申请", time: "08/10 18:12" },
-                    { title: "资产领用申请", time: "08/10 18:12" },
-                ],
-            },
-            {
-                title: "被退回",
-                type: "folder",
-                open: true,
-                children: [
-                    { title: "被退回", time: "08/10 18:12" },
-                    { title: "项目立项申请", time: "08/10 18:12" },
-                    { title: "报销申请", time: "08/10 18:12" },
-                    { title: "资产领用申请", time: "08/10 18:12" },
-                ],
-            },
-            {
-                title: "2020-高薪技术业项目申报",
-                type: "file",
-                children: [],
-            },
-        ]);
-        const winInfo = Vue.ref(loadWinSize(winName.TodoList));
-        const onSetting = () => {
-            console.log("Clicked on settings button");
-        };
-        const onRefresh = () => {
-            console.log("Clicked on refresh button");
-        };
-        const onSizeChange = (rect) => {
-            console.log(rect)
-            const style = {};
-            for (const key in rect) {
-                style[key] = rect[key] + "px";
-            }
-            saveWinSize(winName.TodoList, style);
-            winInfo.value = style;
-        };
-        const onItemClick = (e) => {
-            console.log("===>>>", e);
-        };
-        Vue.onMounted(() => {
-            // console.log("TodoList component is mounted");
-        });
-
-        return () => Vue.h('div', { class: 'todo-list-container can-resize-box', style: winInfo.value },
-            Vue.h(EditBox, { onSize: onSizeChange }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' }, [
-                        Vue.h(HeaderContainer, {
-                            title: "待办",
-                            icon: "todo",
-                            onSetting,
-                            onRefresh
-                        })
-                    ]),
-                    Vue.h('div', { class: 'body' }, [
-                        Vue.h(FolderContainer, { list: todoGroupList, onClick: onItemClick })
-                    ])
-                ]
-            })
-        )
-    }
-};
-// 催办
-export const UrgingList = {
-    name: 'UrgingList',
-    setup() {
-
-        const todoGroupList = Vue.reactive([
-            {
-                title: "项目",
-                type: "folder",
-                open: true,
-                children: [
-                    { title: "《高新技术企业认定》项目报销", time: "08/10 18:12" },
-                    { title: "日常办公报销", time: "08/10 18:12" },
-                    { title: "固定资产维修费用报销", time: "08/10 18:12" },
-                ],
-            },
-            {
-                title: "报销",
-                type: "folder",
-                open: true,
-                children: [
-                    {
-                        title: "2020-企业-技术改造专项资金项目-立项申请",
-                        time: "08/10 18:12",
-                    },
-                ],
-            },
-            {
-                title: "2020-高薪技术企业项目申报",
-                type: "file",
-                children: [],
-            },
-            {
-                title: "2020-高薪技术企业项目申报-技术改造专项资金项目-立项申请",
-                type: "file",
-                children: [],
-            },
-        ]);
-
-        const winInfo = Vue.ref(loadWinSize(winName.UrgingList));
-
-        const onSetting = () => {
-            console.log("Clicked on settings button");
-        };
-
-        const onRefresh = () => {
-            console.log("Clicked on refresh button");
-        };
-
-        const onSizeChange = (rect) => {
-            const style = {};
-            for (const key in rect) {
-                style[key] = rect[key] + "px";
-            }
-            saveWinSize(winName.UrgingList, style);
-            winInfo.value = style;
-        };
-
-        return () =>
-            Vue.h('div', { class: 'todo-list-container can-resize-box', style: winInfo.value }, Vue.h(EditBox, { onSize: onSizeChange }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' }, [
-                        Vue.h(HeaderContainer, {
-                            title: "催办",
-                            icon: "alarm-clock",
-                            onSetting,
-                            onRefresh
-                        })
-                    ]),
-                    Vue.h('div', { class: 'body' }, [
-                        Vue.h(FolderContainer, { list: todoGroupList })
-                    ])
-                ]
-            })
-            )
-    }
-};
-// 公示公告
-export const Notice = {
-    name: 'Notice',
-    setup() {
-        const list = Vue.reactive([
-            { title: "关于2022年度中层干部的任免公告", time: "10/08 08:30" },
-            { title: "2022年重组团队从心出发", time: "10/08 08:30" },
-            { title: "关于单位进入粤港澳创新创业大赛决赛", time: "10/08 08:30" },
-            { title: "关于2022年度中层干部的任免公告", time: "10/08 08:30" },
-        ]);
-
-        const winInfo = Vue.ref(loadWinSize(winName.Notice));
-
-        const onSetting = () => {
-            console.log("Clicked on settings button");
-        };
-
-        const onRefresh = () => {
-            console.log("Clicked on refresh button");
-        };
-
-        const onSizeChange = (rect) => {
-            const style = {};
-            for (const key in rect) {
-                style[key] = rect[key] + "px";
-            }
-            saveWinSize(winName.Notice, style);
-            winInfo.value = style;
-        };
-        const SsIcon = Vue.resolveComponent('ss-icon');
-
-
-        return () => Vue.h('div', { class: 'notice-list-container can-resize-box', style: winInfo.value }, [
-            Vue.h(EditBox, { onSize: onSizeChange }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' }, [
-                        Vue.h(HeaderContainer, {
-                            title: "公示公告",
-                            icon: "notice",
-                            onSetting: onSetting,
-                            onRefresh: onRefresh
-                        })
-                    ]),
-                    Vue.h('div', { class: 'body' }, list.map((item, i) =>
-                        Vue.h('div', { key: i }, [
-                            Vue.h('div', [
-                                Vue.h(SsIcon, { name: "file", size: "22px" }),
-                                Vue.h('span', item.title)
-                            ]),
-                            Vue.h('div', item.time)
-                        ])
-                    ))
-                ]
-            })
-        ]);
-    }
-};
-// 快捷发起
-export const Launch = {
-    name: 'Launch',
-    setup() {
-        const winInfo = Vue.ref(loadWinSize(winName.launch));
-        const popupInfo = Vue.reactive({
-            status: false,
-            height: 100,
-            width: 100,
-            left: 0,
-            top: 0,
-        });
-        const popupStyle = Vue.computed(() => {
-            const { width, height, left, top } = popupInfo;
-            return {
-                left: `${left - (130 - width) / 2}px`,
-                top: `${top + height}px`,
-            };
-        });
-        const items = Vue.reactive([
-            { name: "qingjia", text: "请假" },
-            {
-                name: "shoufukuan",
-                text: "收付款",
-                hasPopup: true,
-                popupContent: [
-                    { text: "收款" },
-                    { text: "付款" }
-                ]
-            },
-            {
-                name: "kaoqin",
-                text: "考勤",
-                hasPopup: true,
-                popupContent: [
-                    { text: "2" },
-                    { text: "3" }
-                ]
-
-            }
-        ]);
-        const onSetting = () => console.log("Clicked on settings button");
-        const onRefresh = () => console.log("Clicked on refresh button");
-        const onMouseMove = (e, item) => {
-            console.log("鼠标进入了",item.text)
-            showPopupDialog(e, item)
-        };
-
-        const onMouseleave = (e,item) => {
-            console.log("鼠标离开了",item.text)
-            popupInfo.status = false;
-        };
-        const showPopupDialog = (e, item) => {
-            const dom = e.target.closest('.item');
-            if (dom) {
-                const rect = dom.getBoundingClientRect();
-                popupInfo.height = rect.height;
-                popupInfo.left = rect.left;
-                popupInfo.top = rect.top;
-                popupInfo.width = rect.width;
-                setTimeout(() => {
-                    popupInfo.status = true;
-                }, 600)
-            }
-        };
-        const onSizeChange = (rect) => {
-            const style = {};
-            for (const key in rect) style[key] = rect[key] + "px";
-            saveWinSize(winName.launch, style);
-            winInfo.value = style;
-        };
-        // Vue.onMounted(() => console.log("LaunchContainer component is mounted"));
-        const SsIcon = Vue.resolveComponent('ss-icon');
-        return () => Vue.h('div', { class: 'launch-container can-resize-box', style: winInfo.value }, [
-            Vue.h(EditBox, { onSize: onSizeChange }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' }, [
-                        Vue.h(HeaderContainer, { title: "快捷发起", icon: "lightning", onSetting, onRefresh })
-                    ]),
-                    Vue.h('div', { class: 'body' }, items.map(item =>
-                        Vue.h('div', { class: 'item', onMousemove: e => onMouseMove(e, item), onMouseleave: e => onMouseleave(e, item) }, [
-                            Vue.h(SsIcon, {
-                                class: item.hasPopup && item.popupContent.length > 0 ? "mark-down" : "",
-                                name: item.name,
-                                size: "36px"
-                            }),
-                            Vue.h('div', { class: 'text' }, item.text),
-                            item.hasPopup && popupInfo.status ? Vue.h('div', { class: 'popup', style: popupStyle.value }, item.popupContent.map(content =>
-                                Vue.h('div', content.text)
-                            )) : null
-                        ])
-                    ))
-                ]
-            })
-        ])
-    }
-};
-// 项目实时统计图
-export const Statistics = {
-    name: 'Statistics',
-    setup() {
-        const winInfo = Vue.ref(loadWinSize(winName.Statistics));
-        const chartInstance = Vue.ref(null);
-        const option = {
-            tooltip: {
-                trigger: "axis",
-                axisPointer: {
-                    type: "cross",
-                    crossStyle: {
-                        color: "#999",
-                    },
-                },
-            },
-            legend: {
-                data: ["项目金额", "成本"]
-            },
-            xAxis: [{
-                type: "category",
-                data: ["2月", "3月", "4���", "5月", "6月", "7月", "8月", "9月", "10月", "11月"],
-                axisPointer: {
-                    type: "shadow"
-                },
-            }],
-            yAxis: [{
-                type: "value",
-                name: "单位:万(RMB)",
-                min: 0,
-                max: 1000,
-                interval: 200,
-                axisLabel: {
-                    formatter: "{value} "
-                },
-            }, {
-                type: "value",
-                name: "成本",
-                min: 0,
-                max: 1000,
-                interval: 200,
-                axisLabel: {
-                    formatter: "{value}"
-                },
-            }],
-            series: [{
-                name: "项目金额",
-                type: "bar",
-                tooltip: {
-                    valueFormatter: function (value) {
-                        return value + " ml";
-                    }
-                },
-                data: [250, 850, 500, 650, 450, 850, 780, 450, 700, 850]
-            }, {
-                name: "成本",
-                type: "line",
-                yAxisIndex: 1,
-                tooltip: {
-                    valueFormatter: function (value) {
-                        return value;
-                    }
-                },
-                data: [400, 390, 580, 590, 430, 420, 430, 550, 230, 250]
-            }]
-        }
-        // 初始化echants
-        const initChart = () => {
-            const chartDom = document.getElementById("statistics-chart");
-            if (!chartDom) return;
-            chartInstance.value = echarts.init(chartDom);
-            chartInstance.value.setOption(option);
-        };
-
-        const onSetting = () => console.log("Clicked on settings button");
-        const onRefresh = () => {
-            console.log("Clicked on refresh button");
-            if (chartInstance.value) {
-                chartInstance.value.clear();
-                initChart();  // Reinitialize the chart to reflect any new data or settings
-            }
-        };
-
-        const onSizeChange = (rect) => {
-            const style = {};
-            for (const key in rect) style[key] = rect[key] + "px";
-            saveWinSize(winName.Statistics, style);
-            winInfo.value = style;
-            if (chartInstance.value) {
-                chartInstance.value.resize();
-            }
-        };
-
-        Vue.onMounted(() => {
-            // console.log("StatisticsContainer component is mounted");
-            initChart();  // Initialize the chart when component is mounted
-        });
-
-        // return { winInfo, onSetting, onRefresh, onSizeChange };
-        return () => Vue.h('div', { class: 'statistics-container can-resize-box', style: winInfo.value }, [
-            Vue.h(EditBox, { onSize: onSizeChange }, {
-                default: () => [
-                    Vue.h('div', { class: 'header' }, [
-                        Vue.h(HeaderContainer, { title: "项目实时统计图", icon: "layer", onSetting, onRefresh })
-                    ]),
-                    Vue.h('div', { class: 'body' }, [
-                        Vue.h('div', { id: 'statistics-chart', class: 'chart-container' })
-                    ])
-                ]
-            })
-        ]);
-    },
-
-};

+ 0 - 203
js/vue/tools.js

@@ -1,203 +0,0 @@
-export var camelToKebab = function (camelStr) {
-    const isUpper = camelStr[0].charCodeAt(0) >= 65 && camelStr[0].charCodeAt(0) <= 90;
-    const handleStr = camelStr.replace(/([A-Z])/g, "-$1").toLowerCase();
-    let kebabStr = handleStr;
-    if (isUpper) {
-      kebabStr = handleStr.slice(1);
-    }
-    const newKebabArr = [];
-    const kebabSplitArr = kebabStr.split("-");
-    kebabSplitArr.forEach((item, index) => {
-      if (item.length > 1) {
-        newKebabArr.push(item);
-      } else {
-        let combineStr = "";
-        const subKebabArr = kebabSplitArr.slice(index);
-        for (let i = 0; i < subKebabArr.length; i++) {
-          if (subKebabArr[i].length > 1)
-            break;
-          combineStr += subKebabArr[i];
-        }
-        newKebabArr.push(combineStr);
-        kebabSplitArr.splice(index + 1, combineStr.length - 1);
-      }
-    });
-    return newKebabArr.join("-");
-  };
-export var isNum = function (num) {
-    return typeof num === "number" && !isNaN(num);
-  };
-export var toStyleStr = (styleObj, unit = "rpx") => {
-    if (Array.isArray(styleObj)) {
-      return styleObj.join(";");
-    } else {
-      if (typeof styleObj === "object" && styleObj !== null) {
-        let style = [];
-        for (const k in styleObj) {
-          if (typeof k === "string") {
-            let val = styleObj[k];
-            if (val !== void 0) {
-              if (typeof val === "number") {
-                if (addUnitAttr.includes(k)) {
-                  val = val + unit;
-                }
-              }
-              style.push(`${camelToKebab(k)}:${val}`);
-            }
-          }
-        }
-        return style.length > 0 ? style.join(";") + ";" : "";
-      } else {
-        return styleObj;
-      }
-    }
-  };
-
-function isObject(value) {
-  var type = typeof value;
-  return value != null && (type == 'object' || type == 'function');
-}
-function toNumber(value) {
-  if (typeof value == 'number') {
-    return value;
-  }
-  if (isSymbol(value)) {
-    return NAN;
-  }
-  if (isObject(value)) {
-    var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
-    value = isObject(other) ? (other + '') : other;
-  }
-  if (typeof value != 'string') {
-    return value === 0 ? value : +value;
-  }
-  value = value.replace(reTrim, '');
-  var isBinary = reIsBinary.test(value);
-  return (isBinary || reIsOctal.test(value))
-    ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
-    : (reIsBadHex.test(value) ? NAN : +value);
-}
-export function debounce(func, wait, options) {
-    var lastArgs,
-        lastThis,
-        maxWait,
-        result,
-        timerId,
-        lastCallTime,
-        lastInvokeTime = 0,
-        leading = false,
-        maxing = false,
-        trailing = true;
-
-    if (typeof func != 'function') {
-      throw new TypeError(FUNC_ERROR_TEXT);
-    }
-    wait = toNumber(wait) || 0;
-    if (isObject(options)) {
-      leading = !!options.leading;
-      maxing = 'maxWait' in options;
-      maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
-      trailing = 'trailing' in options ? !!options.trailing : trailing;
-    }
-
-    function invokeFunc(time) {
-      var args = lastArgs,
-          thisArg = lastThis;
-
-      lastArgs = lastThis = undefined;
-      lastInvokeTime = time;
-      result = func.apply(thisArg, args);
-      return result;
-    }
-
-    function leadingEdge(time) {
-      // Reset any `maxWait` timer.
-      lastInvokeTime = time;
-      // Start the timer for the trailing edge.
-      timerId = setTimeout(timerExpired, wait);
-      // Invoke the leading edge.
-      return leading ? invokeFunc(time) : result;
-    }
-
-    function remainingWait(time) {
-      var timeSinceLastCall = time - lastCallTime,
-          timeSinceLastInvoke = time - lastInvokeTime,
-          timeWaiting = wait - timeSinceLastCall;
-
-      return maxing
-        ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
-        : timeWaiting;
-    }
-
-    function shouldInvoke(time) {
-      var timeSinceLastCall = time - lastCallTime,
-          timeSinceLastInvoke = time - lastInvokeTime;
-
-      // Either this is the first call, activity has stopped and we're at the
-      // trailing edge, the system time has gone backwards and we're treating
-      // it as the trailing edge, or we've hit the `maxWait` limit.
-      return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
-        (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
-    }
-
-    function timerExpired() {
-      var time = now();
-      if (shouldInvoke(time)) {
-        return trailingEdge(time);
-      }
-      // Restart the timer.
-      timerId = setTimeout(timerExpired, remainingWait(time));
-    }
-
-    function trailingEdge(time) {
-      timerId = undefined;
-
-      // Only invoke if we have `lastArgs` which means `func` has been
-      // debounced at least once.
-      if (trailing && lastArgs) {
-        return invokeFunc(time);
-      }
-      lastArgs = lastThis = undefined;
-      return result;
-    }
-
-    function cancel() {
-      if (timerId !== undefined) {
-        clearTimeout(timerId);
-      }
-      lastInvokeTime = 0;
-      lastArgs = lastCallTime = lastThis = timerId = undefined;
-    }
-
-    function flush() {
-      return timerId === undefined ? result : trailingEdge(now());
-    }
-
-    function debounced() {
-      var time = now(),
-          isInvoking = shouldInvoke(time);
-
-      lastArgs = arguments;
-      lastThis = this;
-      lastCallTime = time;
-
-      if (isInvoking) {
-        if (timerId === undefined) {
-          return leadingEdge(lastCallTime);
-        }
-        if (maxing) {
-          // Handle invocations in a tight loop.
-          timerId = setTimeout(timerExpired, wait);
-          return invokeFunc(lastCallTime);
-        }
-      }
-      if (timerId === undefined) {
-        timerId = setTimeout(timerExpired, wait);
-      }
-      return result;
-    }
-    debounced.cancel = cancel;
-    debounced.flush = flush;
-    return debounced;
-}
-

+ 0 - 3854
js/vue/vue-router.gloabl.js

@@ -1,3854 +0,0 @@
-/*!
-  * vue-router v4.3.2
-  * (c) 2024 Eduardo San Martin Morote
-  * @license MIT
-  */
-var VueRouter = (function (exports, vue) {
-  'use strict';
-
-  const isBrowser = typeof document !== 'undefined';
-
-  function isESModule(obj) {
-      return obj.__esModule || obj[Symbol.toStringTag] === 'Module';
-  }
-  const assign = Object.assign;
-  function applyToParams(fn, params) {
-      const newParams = {};
-      for (const key in params) {
-          const value = params[key];
-          newParams[key] = isArray(value)
-              ? value.map(fn)
-              : fn(value);
-      }
-      return newParams;
-  }
-  const noop = () => { };
-  /**
-   * Typesafe alternative to Array.isArray
-   * https://github.com/microsoft/TypeScript/pull/48228
-   */
-  const isArray = Array.isArray;
-
-  function warn(msg) {
-      // avoid using ...args as it breaks in older Edge builds
-      const args = Array.from(arguments).slice(1);
-      console.warn.apply(console, ['[Vue Router warn]: ' + msg].concat(args));
-  }
-
-  /**
-   * Encoding Rules (␣ = Space)
-   * - Path: ␣ " < > # ? { }
-   * - Query: ␣ " < > # & =
-   * - Hash: ␣ " < > `
-   *
-   * On top of that, the RFC3986 (https://tools.ietf.org/html/rfc3986#section-2.2)
-   * defines some extra characters to be encoded. Most browsers do not encode them
-   * in encodeURI https://github.com/whatwg/url/issues/369, so it may be safer to
-   * also encode `!'()*`. Leaving un-encoded only ASCII alphanumeric(`a-zA-Z0-9`)
-   * plus `-._~`. This extra safety should be applied to query by patching the
-   * string returned by encodeURIComponent encodeURI also encodes `[\]^`. `\`
-   * should be encoded to avoid ambiguity. Browsers (IE, FF, C) transform a `\`
-   * into a `/` if directly typed in. The _backtick_ (`````) should also be
-   * encoded everywhere because some browsers like FF encode it when directly
-   * written while others don't. Safari and IE don't encode ``"<>{}``` in hash.
-   */
-  // const EXTRA_RESERVED_RE = /[!'()*]/g
-  // const encodeReservedReplacer = (c: string) => '%' + c.charCodeAt(0).toString(16)
-  const HASH_RE = /#/g; // %23
-  const AMPERSAND_RE = /&/g; // %26
-  const SLASH_RE = /\//g; // %2F
-  const EQUAL_RE = /=/g; // %3D
-  const IM_RE = /\?/g; // %3F
-  const PLUS_RE = /\+/g; // %2B
-  /**
-   * NOTE: It's not clear to me if we should encode the + symbol in queries, it
-   * seems to be less flexible than not doing so and I can't find out the legacy
-   * systems requiring this for regular requests like text/html. In the standard,
-   * the encoding of the plus character is only mentioned for
-   * application/x-www-form-urlencoded
-   * (https://url.spec.whatwg.org/#urlencoded-parsing) and most browsers seems lo
-   * leave the plus character as is in queries. To be more flexible, we allow the
-   * plus character on the query, but it can also be manually encoded by the user.
-   *
-   * Resources:
-   * - https://url.spec.whatwg.org/#urlencoded-parsing
-   * - https://stackoverflow.com/questions/1634271/url-encoding-the-space-character-or-20
-   */
-  const ENC_BRACKET_OPEN_RE = /%5B/g; // [
-  const ENC_BRACKET_CLOSE_RE = /%5D/g; // ]
-  const ENC_CARET_RE = /%5E/g; // ^
-  const ENC_BACKTICK_RE = /%60/g; // `
-  const ENC_CURLY_OPEN_RE = /%7B/g; // {
-  const ENC_PIPE_RE = /%7C/g; // |
-  const ENC_CURLY_CLOSE_RE = /%7D/g; // }
-  const ENC_SPACE_RE = /%20/g; // }
-  /**
-   * Encode characters that need to be encoded on the path, search and hash
-   * sections of the URL.
-   *
-   * @internal
-   * @param text - string to encode
-   * @returns encoded string
-   */
-  function commonEncode(text) {
-      return encodeURI('' + text)
-          .replace(ENC_PIPE_RE, '|')
-          .replace(ENC_BRACKET_OPEN_RE, '[')
-          .replace(ENC_BRACKET_CLOSE_RE, ']');
-  }
-  /**
-   * Encode characters that need to be encoded on the hash section of the URL.
-   *
-   * @param text - string to encode
-   * @returns encoded string
-   */
-  function encodeHash(text) {
-      return commonEncode(text)
-          .replace(ENC_CURLY_OPEN_RE, '{')
-          .replace(ENC_CURLY_CLOSE_RE, '}')
-          .replace(ENC_CARET_RE, '^');
-  }
-  /**
-   * Encode characters that need to be encoded query values on the query
-   * section of the URL.
-   *
-   * @param text - string to encode
-   * @returns encoded string
-   */
-  function encodeQueryValue(text) {
-      return (commonEncode(text)
-          // Encode the space as +, encode the + to differentiate it from the space
-          .replace(PLUS_RE, '%2B')
-          .replace(ENC_SPACE_RE, '+')
-          .replace(HASH_RE, '%23')
-          .replace(AMPERSAND_RE, '%26')
-          .replace(ENC_BACKTICK_RE, '`')
-          .replace(ENC_CURLY_OPEN_RE, '{')
-          .replace(ENC_CURLY_CLOSE_RE, '}')
-          .replace(ENC_CARET_RE, '^'));
-  }
-  /**
-   * Like `encodeQueryValue` but also encodes the `=` character.
-   *
-   * @param text - string to encode
-   */
-  function encodeQueryKey(text) {
-      return encodeQueryValue(text).replace(EQUAL_RE, '%3D');
-  }
-  /**
-   * Encode characters that need to be encoded on the path section of the URL.
-   *
-   * @param text - string to encode
-   * @returns encoded string
-   */
-  function encodePath(text) {
-      return commonEncode(text).replace(HASH_RE, '%23').replace(IM_RE, '%3F');
-  }
-  /**
-   * Encode characters that need to be encoded on the path section of the URL as a
-   * param. This function encodes everything {@link encodePath} does plus the
-   * slash (`/`) character. If `text` is `null` or `undefined`, returns an empty
-   * string instead.
-   *
-   * @param text - string to encode
-   * @returns encoded string
-   */
-  function encodeParam(text) {
-      return text == null ? '' : encodePath(text).replace(SLASH_RE, '%2F');
-  }
-  /**
-   * Decode text using `decodeURIComponent`. Returns the original text if it
-   * fails.
-   *
-   * @param text - string to decode
-   * @returns decoded string
-   */
-  function decode(text) {
-      try {
-          return decodeURIComponent('' + text);
-      }
-      catch (err) {
-          warn(`Error decoding "${text}". Using original value`);
-      }
-      return '' + text;
-  }
-
-  const TRAILING_SLASH_RE = /\/$/;
-  const removeTrailingSlash = (path) => path.replace(TRAILING_SLASH_RE, '');
-  /**
-   * Transforms a URI into a normalized history location
-   *
-   * @param parseQuery
-   * @param location - URI to normalize
-   * @param currentLocation - current absolute location. Allows resolving relative
-   * paths. Must start with `/`. Defaults to `/`
-   * @returns a normalized history location
-   */
-  function parseURL(parseQuery, location, currentLocation = '/') {
-      let path, query = {}, searchString = '', hash = '';
-      // Could use URL and URLSearchParams but IE 11 doesn't support it
-      // TODO: move to new URL()
-      const hashPos = location.indexOf('#');
-      let searchPos = location.indexOf('?');
-      // the hash appears before the search, so it's not part of the search string
-      if (hashPos < searchPos && hashPos >= 0) {
-          searchPos = -1;
-      }
-      if (searchPos > -1) {
-          path = location.slice(0, searchPos);
-          searchString = location.slice(searchPos + 1, hashPos > -1 ? hashPos : location.length);
-          query = parseQuery(searchString);
-      }
-      if (hashPos > -1) {
-          path = path || location.slice(0, hashPos);
-          // keep the # character
-          hash = location.slice(hashPos, location.length);
-      }
-      // no search and no query
-      path = resolveRelativePath(path != null ? path : location, currentLocation);
-      // empty path means a relative query or hash `?foo=f`, `#thing`
-      return {
-          fullPath: path + (searchString && '?') + searchString + hash,
-          path,
-          query,
-          hash: decode(hash),
-      };
-  }
-  /**
-   * Stringifies a URL object
-   *
-   * @param stringifyQuery
-   * @param location
-   */
-  function stringifyURL(stringifyQuery, location) {
-      const query = location.query ? stringifyQuery(location.query) : '';
-      return location.path + (query && '?') + query + (location.hash || '');
-  }
-  /**
-   * Strips off the base from the beginning of a location.pathname in a non-case-sensitive way.
-   *
-   * @param pathname - location.pathname
-   * @param base - base to strip off
-   */
-  function stripBase(pathname, base) {
-      // no base or base is not found at the beginning
-      if (!base || !pathname.toLowerCase().startsWith(base.toLowerCase()))
-          return pathname;
-      return pathname.slice(base.length) || '/';
-  }
-  /**
-   * Checks if two RouteLocation are equal. This means that both locations are
-   * pointing towards the same {@link RouteRecord} and that all `params`, `query`
-   * parameters and `hash` are the same
-   *
-   * @param stringifyQuery - A function that takes a query object of type LocationQueryRaw and returns a string representation of it.
-   * @param a - first {@link RouteLocation}
-   * @param b - second {@link RouteLocation}
-   */
-  function isSameRouteLocation(stringifyQuery, a, b) {
-      const aLastIndex = a.matched.length - 1;
-      const bLastIndex = b.matched.length - 1;
-      return (aLastIndex > -1 &&
-          aLastIndex === bLastIndex &&
-          isSameRouteRecord(a.matched[aLastIndex], b.matched[bLastIndex]) &&
-          isSameRouteLocationParams(a.params, b.params) &&
-          stringifyQuery(a.query) === stringifyQuery(b.query) &&
-          a.hash === b.hash);
-  }
-  /**
-   * Check if two `RouteRecords` are equal. Takes into account aliases: they are
-   * considered equal to the `RouteRecord` they are aliasing.
-   *
-   * @param a - first {@link RouteRecord}
-   * @param b - second {@link RouteRecord}
-   */
-  function isSameRouteRecord(a, b) {
-      // since the original record has an undefined value for aliasOf
-      // but all aliases point to the original record, this will always compare
-      // the original record
-      return (a.aliasOf || a) === (b.aliasOf || b);
-  }
-  function isSameRouteLocationParams(a, b) {
-      if (Object.keys(a).length !== Object.keys(b).length)
-          return false;
-      for (const key in a) {
-          if (!isSameRouteLocationParamsValue(a[key], b[key]))
-              return false;
-      }
-      return true;
-  }
-  function isSameRouteLocationParamsValue(a, b) {
-      return isArray(a)
-          ? isEquivalentArray(a, b)
-          : isArray(b)
-              ? isEquivalentArray(b, a)
-              : a === b;
-  }
-  /**
-   * Check if two arrays are the same or if an array with one single entry is the
-   * same as another primitive value. Used to check query and parameters
-   *
-   * @param a - array of values
-   * @param b - array of values or a single value
-   */
-  function isEquivalentArray(a, b) {
-      return isArray(b)
-          ? a.length === b.length && a.every((value, i) => value === b[i])
-          : a.length === 1 && a[0] === b;
-  }
-  /**
-   * Resolves a relative path that starts with `.`.
-   *
-   * @param to - path location we are resolving
-   * @param from - currentLocation.path, should start with `/`
-   */
-  function resolveRelativePath(to, from) {
-      if (to.startsWith('/'))
-          return to;
-      if (!from.startsWith('/')) {
-          warn(`Cannot resolve a relative location without an absolute path. Trying to resolve "${to}" from "${from}". It should look like "/${from}".`);
-          return to;
-      }
-      if (!to)
-          return from;
-      const fromSegments = from.split('/');
-      const toSegments = to.split('/');
-      const lastToSegment = toSegments[toSegments.length - 1];
-      // make . and ./ the same (../ === .., ../../ === ../..)
-      // this is the same behavior as new URL()
-      if (lastToSegment === '..' || lastToSegment === '.') {
-          toSegments.push('');
-      }
-      let position = fromSegments.length - 1;
-      let toPosition;
-      let segment;
-      for (toPosition = 0; toPosition < toSegments.length; toPosition++) {
-          segment = toSegments[toPosition];
-          // we stay on the same position
-          if (segment === '.')
-              continue;
-          // go up in the from array
-          if (segment === '..') {
-              // we can't go below zero, but we still need to increment toPosition
-              if (position > 1)
-                  position--;
-              // continue
-          }
-          // we reached a non-relative path, we stop here
-          else
-              break;
-      }
-      return (fromSegments.slice(0, position).join('/') +
-          '/' +
-          toSegments.slice(toPosition).join('/'));
-  }
-
-  var NavigationType;
-  (function (NavigationType) {
-      NavigationType["pop"] = "pop";
-      NavigationType["push"] = "push";
-  })(NavigationType || (NavigationType = {}));
-  var NavigationDirection;
-  (function (NavigationDirection) {
-      NavigationDirection["back"] = "back";
-      NavigationDirection["forward"] = "forward";
-      NavigationDirection["unknown"] = "";
-  })(NavigationDirection || (NavigationDirection = {}));
-  /**
-   * Starting location for Histories
-   */
-  const START = '';
-  // Generic utils
-  /**
-   * Normalizes a base by removing any trailing slash and reading the base tag if
-   * present.
-   *
-   * @param base - base to normalize
-   */
-  function normalizeBase(base) {
-      if (!base) {
-          if (isBrowser) {
-              // respect <base> tag
-              const baseEl = document.querySelector('base');
-              base = (baseEl && baseEl.getAttribute('href')) || '/';
-              // strip full URL origin
-              base = base.replace(/^\w+:\/\/[^\/]+/, '');
-          }
-          else {
-              base = '/';
-          }
-      }
-      // ensure leading slash when it was removed by the regex above avoid leading
-      // slash with hash because the file could be read from the disk like file://
-      // and the leading slash would cause problems
-      if (base[0] !== '/' && base[0] !== '#')
-          base = '/' + base;
-      // remove the trailing slash so all other method can just do `base + fullPath`
-      // to build an href
-      return removeTrailingSlash(base);
-  }
-  // remove any character before the hash
-  const BEFORE_HASH_RE = /^[^#]+#/;
-  function createHref(base, location) {
-      return base.replace(BEFORE_HASH_RE, '#') + location;
-  }
-
-  function getElementPosition(el, offset) {
-      const docRect = document.documentElement.getBoundingClientRect();
-      const elRect = el.getBoundingClientRect();
-      return {
-          behavior: offset.behavior,
-          left: elRect.left - docRect.left - (offset.left || 0),
-          top: elRect.top - docRect.top - (offset.top || 0),
-      };
-  }
-  const computeScrollPosition = () => ({
-      left: window.scrollX,
-      top: window.scrollY,
-  });
-  function scrollToPosition(position) {
-      let scrollToOptions;
-      if ('el' in position) {
-          const positionEl = position.el;
-          const isIdSelector = typeof positionEl === 'string' && positionEl.startsWith('#');
-          /**
-           * `id`s can accept pretty much any characters, including CSS combinators
-           * like `>` or `~`. It's still possible to retrieve elements using
-           * `document.getElementById('~')` but it needs to be escaped when using
-           * `document.querySelector('#\\~')` for it to be valid. The only
-           * requirements for `id`s are them to be unique on the page and to not be
-           * empty (`id=""`). Because of that, when passing an id selector, it should
-           * be properly escaped for it to work with `querySelector`. We could check
-           * for the id selector to be simple (no CSS combinators `+ >~`) but that
-           * would make things inconsistent since they are valid characters for an
-           * `id` but would need to be escaped when using `querySelector`, breaking
-           * their usage and ending up in no selector returned. Selectors need to be
-           * escaped:
-           *
-           * - `#1-thing` becomes `#\31 -thing`
-           * - `#with~symbols` becomes `#with\\~symbols`
-           *
-           * - More information about  the topic can be found at
-           *   https://mathiasbynens.be/notes/html5-id-class.
-           * - Practical example: https://mathiasbynens.be/demo/html5-id
-           */
-          if (typeof position.el === 'string') {
-              if (!isIdSelector || !document.getElementById(position.el.slice(1))) {
-                  try {
-                      const foundEl = document.querySelector(position.el);
-                      if (isIdSelector && foundEl) {
-                          warn(`The selector "${position.el}" should be passed as "el: document.querySelector('${position.el}')" because it starts with "#".`);
-                          // return to avoid other warnings
-                          return;
-                      }
-                  }
-                  catch (err) {
-                      warn(`The selector "${position.el}" is invalid. If you are using an id selector, make sure to escape it. You can find more information about escaping characters in selectors at https://mathiasbynens.be/notes/css-escapes or use CSS.escape (https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape).`);
-                      // return to avoid other warnings
-                      return;
-                  }
-              }
-          }
-          const el = typeof positionEl === 'string'
-              ? isIdSelector
-                  ? document.getElementById(positionEl.slice(1))
-                  : document.querySelector(positionEl)
-              : positionEl;
-          if (!el) {
-              warn(`Couldn't find element using selector "${position.el}" returned by scrollBehavior.`);
-              return;
-          }
-          scrollToOptions = getElementPosition(el, position);
-      }
-      else {
-          scrollToOptions = position;
-      }
-      if ('scrollBehavior' in document.documentElement.style)
-          window.scrollTo(scrollToOptions);
-      else {
-          window.scrollTo(scrollToOptions.left != null ? scrollToOptions.left : window.scrollX, scrollToOptions.top != null ? scrollToOptions.top : window.scrollY);
-      }
-  }
-  function getScrollKey(path, delta) {
-      const position = history.state ? history.state.position - delta : -1;
-      return position + path;
-  }
-  const scrollPositions = new Map();
-  function saveScrollPosition(key, scrollPosition) {
-      scrollPositions.set(key, scrollPosition);
-  }
-  function getSavedScrollPosition(key) {
-      const scroll = scrollPositions.get(key);
-      // consume it so it's not used again
-      scrollPositions.delete(key);
-      return scroll;
-  }
-  // TODO: RFC about how to save scroll position
-  /**
-   * ScrollBehavior instance used by the router to compute and restore the scroll
-   * position when navigating.
-   */
-  // export interface ScrollHandler<ScrollPositionEntry extends HistoryStateValue, ScrollPosition extends ScrollPositionEntry> {
-  //   // returns a scroll position that can be saved in history
-  //   compute(): ScrollPositionEntry
-  //   // can take an extended ScrollPositionEntry
-  //   scroll(position: ScrollPosition): void
-  // }
-  // export const scrollHandler: ScrollHandler<ScrollPosition> = {
-  //   compute: computeScroll,
-  //   scroll: scrollToPosition,
-  // }
-
-  let createBaseLocation = () => location.protocol + '//' + location.host;
-  /**
-   * Creates a normalized history location from a window.location object
-   * @param base - The base path
-   * @param location - The window.location object
-   */
-  function createCurrentLocation(base, location) {
-      const { pathname, search, hash } = location;
-      // allows hash bases like #, /#, #/, #!, #!/, /#!/, or even /folder#end
-      const hashPos = base.indexOf('#');
-      if (hashPos > -1) {
-          let slicePos = hash.includes(base.slice(hashPos))
-              ? base.slice(hashPos).length
-              : 1;
-          let pathFromHash = hash.slice(slicePos);
-          // prepend the starting slash to hash so the url starts with /#
-          if (pathFromHash[0] !== '/')
-              pathFromHash = '/' + pathFromHash;
-          return stripBase(pathFromHash, '');
-      }
-      const path = stripBase(pathname, base);
-      return path + search + hash;
-  }
-  function useHistoryListeners(base, historyState, currentLocation, replace) {
-      let listeners = [];
-      let teardowns = [];
-      // TODO: should it be a stack? a Dict. Check if the popstate listener
-      // can trigger twice
-      let pauseState = null;
-      const popStateHandler = ({ state, }) => {
-          const to = createCurrentLocation(base, location);
-          const from = currentLocation.value;
-          const fromState = historyState.value;
-          let delta = 0;
-          if (state) {
-              currentLocation.value = to;
-              historyState.value = state;
-              // ignore the popstate and reset the pauseState
-              if (pauseState && pauseState === from) {
-                  pauseState = null;
-                  return;
-              }
-              delta = fromState ? state.position - fromState.position : 0;
-          }
-          else {
-              replace(to);
-          }
-          // Here we could also revert the navigation by calling history.go(-delta)
-          // this listener will have to be adapted to not trigger again and to wait for the url
-          // to be updated before triggering the listeners. Some kind of validation function would also
-          // need to be passed to the listeners so the navigation can be accepted
-          // call all listeners
-          listeners.forEach(listener => {
-              listener(currentLocation.value, from, {
-                  delta,
-                  type: NavigationType.pop,
-                  direction: delta
-                      ? delta > 0
-                          ? NavigationDirection.forward
-                          : NavigationDirection.back
-                      : NavigationDirection.unknown,
-              });
-          });
-      };
-      function pauseListeners() {
-          pauseState = currentLocation.value;
-      }
-      function listen(callback) {
-          // set up the listener and prepare teardown callbacks
-          listeners.push(callback);
-          const teardown = () => {
-              const index = listeners.indexOf(callback);
-              if (index > -1)
-                  listeners.splice(index, 1);
-          };
-          teardowns.push(teardown);
-          return teardown;
-      }
-      function beforeUnloadListener() {
-          const { history } = window;
-          if (!history.state)
-              return;
-          history.replaceState(assign({}, history.state, { scroll: computeScrollPosition() }), '');
-      }
-      function destroy() {
-          for (const teardown of teardowns)
-              teardown();
-          teardowns = [];
-          window.removeEventListener('popstate', popStateHandler);
-          window.removeEventListener('beforeunload', beforeUnloadListener);
-      }
-      // set up the listeners and prepare teardown callbacks
-      window.addEventListener('popstate', popStateHandler);
-      // TODO: could we use 'pagehide' or 'visibilitychange' instead?
-      // https://developer.chrome.com/blog/page-lifecycle-api/
-      window.addEventListener('beforeunload', beforeUnloadListener, {
-          passive: true,
-      });
-      return {
-          pauseListeners,
-          listen,
-          destroy,
-      };
-  }
-  /**
-   * Creates a state object
-   */
-  function buildState(back, current, forward, replaced = false, computeScroll = false) {
-      return {
-          back,
-          current,
-          forward,
-          replaced,
-          position: window.history.length,
-          scroll: computeScroll ? computeScrollPosition() : null,
-      };
-  }
-  function useHistoryStateNavigation(base) {
-      const { history, location } = window;
-      // private variables
-      const currentLocation = {
-          value: createCurrentLocation(base, location),
-      };
-      const historyState = { value: history.state };
-      // build current history entry as this is a fresh navigation
-      if (!historyState.value) {
-          changeLocation(currentLocation.value, {
-              back: null,
-              current: currentLocation.value,
-              forward: null,
-              // the length is off by one, we need to decrease it
-              position: history.length - 1,
-              replaced: true,
-              // don't add a scroll as the user may have an anchor, and we want
-              // scrollBehavior to be triggered without a saved position
-              scroll: null,
-          }, true);
-      }
-      function changeLocation(to, state, replace) {
-          /**
-           * if a base tag is provided, and we are on a normal domain, we have to
-           * respect the provided `base` attribute because pushState() will use it and
-           * potentially erase anything before the `#` like at
-           * https://github.com/vuejs/router/issues/685 where a base of
-           * `/folder/#` but a base of `/` would erase the `/folder/` section. If
-           * there is no host, the `<base>` tag makes no sense and if there isn't a
-           * base tag we can just use everything after the `#`.
-           */
-          const hashIndex = base.indexOf('#');
-          const url = hashIndex > -1
-              ? (location.host && document.querySelector('base')
-                  ? base
-                  : base.slice(hashIndex)) + to
-              : createBaseLocation() + base + to;
-          try {
-              // BROWSER QUIRK
-              // NOTE: Safari throws a SecurityError when calling this function 100 times in 30 seconds
-              history[replace ? 'replaceState' : 'pushState'](state, '', url);
-              historyState.value = state;
-          }
-          catch (err) {
-              {
-                  warn('Error with push/replace State', err);
-              }
-              // Force the navigation, this also resets the call count
-              location[replace ? 'replace' : 'assign'](url);
-          }
-      }
-      function replace(to, data) {
-          const state = assign({}, history.state, buildState(historyState.value.back, 
-          // keep back and forward entries but override current position
-          to, historyState.value.forward, true), data, { position: historyState.value.position });
-          changeLocation(to, state, true);
-          currentLocation.value = to;
-      }
-      function push(to, data) {
-          // Add to current entry the information of where we are going
-          // as well as saving the current position
-          const currentState = assign({}, 
-          // use current history state to gracefully handle a wrong call to
-          // history.replaceState
-          // https://github.com/vuejs/router/issues/366
-          historyState.value, history.state, {
-              forward: to,
-              scroll: computeScrollPosition(),
-          });
-          if (!history.state) {
-              warn(`history.state seems to have been manually replaced without preserving the necessary values. Make sure to preserve existing history state if you are manually calling history.replaceState:\n\n` +
-                  `history.replaceState(history.state, '', url)\n\n` +
-                  `You can find more information at https://next.router.vuejs.org/guide/migration/#usage-of-history-state.`);
-          }
-          changeLocation(currentState.current, currentState, true);
-          const state = assign({}, buildState(currentLocation.value, to, null), { position: currentState.position + 1 }, data);
-          changeLocation(to, state, false);
-          currentLocation.value = to;
-      }
-      return {
-          location: currentLocation,
-          state: historyState,
-          push,
-          replace,
-      };
-  }
-  /**
-   * Creates an HTML5 history. Most common history for single page applications.
-   *
-   * @param base -
-   */
-  function createWebHistory(base) {
-      base = normalizeBase(base);
-      const historyNavigation = useHistoryStateNavigation(base);
-      const historyListeners = useHistoryListeners(base, historyNavigation.state, historyNavigation.location, historyNavigation.replace);
-      function go(delta, triggerListeners = true) {
-          if (!triggerListeners)
-              historyListeners.pauseListeners();
-          history.go(delta);
-      }
-      const routerHistory = assign({
-          // it's overridden right after
-          location: '',
-          base,
-          go,
-          createHref: createHref.bind(null, base),
-      }, historyNavigation, historyListeners);
-      Object.defineProperty(routerHistory, 'location', {
-          enumerable: true,
-          get: () => historyNavigation.location.value,
-      });
-      Object.defineProperty(routerHistory, 'state', {
-          enumerable: true,
-          get: () => historyNavigation.state.value,
-      });
-      return routerHistory;
-  }
-
-  /**
-   * Creates an in-memory based history. The main purpose of this history is to handle SSR. It starts in a special location that is nowhere.
-   * It's up to the user to replace that location with the starter location by either calling `router.push` or `router.replace`.
-   *
-   * @param base - Base applied to all urls, defaults to '/'
-   * @returns a history object that can be passed to the router constructor
-   */
-  function createMemoryHistory(base = '') {
-      let listeners = [];
-      let queue = [START];
-      let position = 0;
-      base = normalizeBase(base);
-      function setLocation(location) {
-          position++;
-          if (position !== queue.length) {
-              // we are in the middle, we remove everything from here in the queue
-              queue.splice(position);
-          }
-          queue.push(location);
-      }
-      function triggerListeners(to, from, { direction, delta }) {
-          const info = {
-              direction,
-              delta,
-              type: NavigationType.pop,
-          };
-          for (const callback of listeners) {
-              callback(to, from, info);
-          }
-      }
-      const routerHistory = {
-          // rewritten by Object.defineProperty
-          location: START,
-          // TODO: should be kept in queue
-          state: {},
-          base,
-          createHref: createHref.bind(null, base),
-          replace(to) {
-              // remove current entry and decrement position
-              queue.splice(position--, 1);
-              setLocation(to);
-          },
-          push(to, data) {
-              setLocation(to);
-          },
-          listen(callback) {
-              listeners.push(callback);
-              return () => {
-                  const index = listeners.indexOf(callback);
-                  if (index > -1)
-                      listeners.splice(index, 1);
-              };
-          },
-          destroy() {
-              listeners = [];
-              queue = [START];
-              position = 0;
-          },
-          go(delta, shouldTrigger = true) {
-              const from = this.location;
-              const direction = 
-              // we are considering delta === 0 going forward, but in abstract mode
-              // using 0 for the delta doesn't make sense like it does in html5 where
-              // it reloads the page
-              delta < 0 ? NavigationDirection.back : NavigationDirection.forward;
-              position = Math.max(0, Math.min(position + delta, queue.length - 1));
-              if (shouldTrigger) {
-                  triggerListeners(this.location, from, {
-                      direction,
-                      delta,
-                  });
-              }
-          },
-      };
-      Object.defineProperty(routerHistory, 'location', {
-          enumerable: true,
-          get: () => queue[position],
-      });
-      return routerHistory;
-  }
-
-  /**
-   * Creates a hash history. Useful for web applications with no host (e.g. `file://`) or when configuring a server to
-   * handle any URL is not possible.
-   *
-   * @param base - optional base to provide. Defaults to `location.pathname + location.search` If there is a `<base>` tag
-   * in the `head`, its value will be ignored in favor of this parameter **but note it affects all the history.pushState()
-   * calls**, meaning that if you use a `<base>` tag, it's `href` value **has to match this parameter** (ignoring anything
-   * after the `#`).
-   *
-   * @example
-   * ```js
-   * // at https://example.com/folder
-   * createWebHashHistory() // gives a url of `https://example.com/folder#`
-   * createWebHashHistory('/folder/') // gives a url of `https://example.com/folder/#`
-   * // if the `#` is provided in the base, it won't be added by `createWebHashHistory`
-   * createWebHashHistory('/folder/#/app/') // gives a url of `https://example.com/folder/#/app/`
-   * // you should avoid doing this because it changes the original url and breaks copying urls
-   * createWebHashHistory('/other-folder/') // gives a url of `https://example.com/other-folder/#`
-   *
-   * // at file:///usr/etc/folder/index.html
-   * // for locations with no `host`, the base is ignored
-   * createWebHashHistory('/iAmIgnored') // gives a url of `file:///usr/etc/folder/index.html#`
-   * ```
-   */
-  function createWebHashHistory(base) {
-      // Make sure this implementation is fine in terms of encoding, specially for IE11
-      // for `file://`, directly use the pathname and ignore the base
-      // location.pathname contains an initial `/` even at the root: `https://example.com`
-      base = location.host ? base || location.pathname + location.search : '';
-      // allow the user to provide a `#` in the middle: `/base/#/app`
-      if (!base.includes('#'))
-          base += '#';
-      if (!base.endsWith('#/') && !base.endsWith('#')) {
-          warn(`A hash base must end with a "#":\n"${base}" should be "${base.replace(/#.*$/, '#')}".`);
-      }
-      return createWebHistory(base);
-  }
-
-  function isRouteLocation(route) {
-      return typeof route === 'string' || (route && typeof route === 'object');
-  }
-  function isRouteName(name) {
-      return typeof name === 'string' || typeof name === 'symbol';
-  }
-
-  /**
-   * Initial route location where the router is. Can be used in navigation guards
-   * to differentiate the initial navigation.
-   *
-   * @example
-   * ```js
-   * import { START_LOCATION } from 'vue-router'
-   *
-   * router.beforeEach((to, from) => {
-   *   if (from === START_LOCATION) {
-   *     // initial navigation
-   *   }
-   * })
-   * ```
-   */
-  const START_LOCATION_NORMALIZED = {
-      path: '/',
-      name: undefined,
-      params: {},
-      query: {},
-      hash: '',
-      fullPath: '/',
-      matched: [],
-      meta: {},
-      redirectedFrom: undefined,
-  };
-
-  const NavigationFailureSymbol = Symbol('navigation failure' );
-  /**
-   * Enumeration with all possible types for navigation failures. Can be passed to
-   * {@link isNavigationFailure} to check for specific failures.
-   */
-  exports.NavigationFailureType = void 0;
-  (function (NavigationFailureType) {
-      /**
-       * An aborted navigation is a navigation that failed because a navigation
-       * guard returned `false` or called `next(false)`
-       */
-      NavigationFailureType[NavigationFailureType["aborted"] = 4] = "aborted";
-      /**
-       * A cancelled navigation is a navigation that failed because a more recent
-       * navigation finished started (not necessarily finished).
-       */
-      NavigationFailureType[NavigationFailureType["cancelled"] = 8] = "cancelled";
-      /**
-       * A duplicated navigation is a navigation that failed because it was
-       * initiated while already being at the exact same location.
-       */
-      NavigationFailureType[NavigationFailureType["duplicated"] = 16] = "duplicated";
-  })(exports.NavigationFailureType || (exports.NavigationFailureType = {}));
-  // DEV only debug messages
-  const ErrorTypeMessages = {
-      [1 /* ErrorTypes.MATCHER_NOT_FOUND */]({ location, currentLocation }) {
-          return `No match for\n ${JSON.stringify(location)}${currentLocation
-            ? '\nwhile being at\n' + JSON.stringify(currentLocation)
-            : ''}`;
-      },
-      [2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */]({ from, to, }) {
-          return `Redirected from "${from.fullPath}" to "${stringifyRoute(to)}" via a navigation guard.`;
-      },
-      [4 /* ErrorTypes.NAVIGATION_ABORTED */]({ from, to }) {
-          return `Navigation aborted from "${from.fullPath}" to "${to.fullPath}" via a navigation guard.`;
-      },
-      [8 /* ErrorTypes.NAVIGATION_CANCELLED */]({ from, to }) {
-          return `Navigation cancelled from "${from.fullPath}" to "${to.fullPath}" with a new navigation.`;
-      },
-      [16 /* ErrorTypes.NAVIGATION_DUPLICATED */]({ from, to }) {
-          return `Avoided redundant navigation to current location: "${from.fullPath}".`;
-      },
-  };
-  /**
-   * Creates a typed NavigationFailure object.
-   * @internal
-   * @param type - NavigationFailureType
-   * @param params - { from, to }
-   */
-  function createRouterError(type, params) {
-      // keep full error messages in cjs versions
-      {
-          return assign(new Error(ErrorTypeMessages[type](params)), {
-              type,
-              [NavigationFailureSymbol]: true,
-          }, params);
-      }
-  }
-  function isNavigationFailure(error, type) {
-      return (error instanceof Error &&
-          NavigationFailureSymbol in error &&
-          (type == null || !!(error.type & type)));
-  }
-  const propertiesToLog = ['params', 'query', 'hash'];
-  function stringifyRoute(to) {
-      if (typeof to === 'string')
-          return to;
-      if (to.path != null)
-          return to.path;
-      const location = {};
-      for (const key of propertiesToLog) {
-          if (key in to)
-              location[key] = to[key];
-      }
-      return JSON.stringify(location, null, 2);
-  }
-
-  // default pattern for a param: non-greedy everything but /
-  const BASE_PARAM_PATTERN = '[^/]+?';
-  const BASE_PATH_PARSER_OPTIONS = {
-      sensitive: false,
-      strict: false,
-      start: true,
-      end: true,
-  };
-  // Special Regex characters that must be escaped in static tokens
-  const REGEX_CHARS_RE = /[.+*?^${}()[\]/\\]/g;
-  /**
-   * Creates a path parser from an array of Segments (a segment is an array of Tokens)
-   *
-   * @param segments - array of segments returned by tokenizePath
-   * @param extraOptions - optional options for the regexp
-   * @returns a PathParser
-   */
-  function tokensToParser(segments, extraOptions) {
-      const options = assign({}, BASE_PATH_PARSER_OPTIONS, extraOptions);
-      // the amount of scores is the same as the length of segments except for the root segment "/"
-      const score = [];
-      // the regexp as a string
-      let pattern = options.start ? '^' : '';
-      // extracted keys
-      const keys = [];
-      for (const segment of segments) {
-          // the root segment needs special treatment
-          const segmentScores = segment.length ? [] : [90 /* PathScore.Root */];
-          // allow trailing slash
-          if (options.strict && !segment.length)
-              pattern += '/';
-          for (let tokenIndex = 0; tokenIndex < segment.length; tokenIndex++) {
-              const token = segment[tokenIndex];
-              // resets the score if we are inside a sub-segment /:a-other-:b
-              let subSegmentScore = 40 /* PathScore.Segment */ +
-                  (options.sensitive ? 0.25 /* PathScore.BonusCaseSensitive */ : 0);
-              if (token.type === 0 /* TokenType.Static */) {
-                  // prepend the slash if we are starting a new segment
-                  if (!tokenIndex)
-                      pattern += '/';
-                  pattern += token.value.replace(REGEX_CHARS_RE, '\\$&');
-                  subSegmentScore += 40 /* PathScore.Static */;
-              }
-              else if (token.type === 1 /* TokenType.Param */) {
-                  const { value, repeatable, optional, regexp } = token;
-                  keys.push({
-                      name: value,
-                      repeatable,
-                      optional,
-                  });
-                  const re = regexp ? regexp : BASE_PARAM_PATTERN;
-                  // the user provided a custom regexp /:id(\\d+)
-                  if (re !== BASE_PARAM_PATTERN) {
-                      subSegmentScore += 10 /* PathScore.BonusCustomRegExp */;
-                      // make sure the regexp is valid before using it
-                      try {
-                          new RegExp(`(${re})`);
-                      }
-                      catch (err) {
-                          throw new Error(`Invalid custom RegExp for param "${value}" (${re}): ` +
-                              err.message);
-                      }
-                  }
-                  // when we repeat we must take care of the repeating leading slash
-                  let subPattern = repeatable ? `((?:${re})(?:/(?:${re}))*)` : `(${re})`;
-                  // prepend the slash if we are starting a new segment
-                  if (!tokenIndex)
-                      subPattern =
-                          // avoid an optional / if there are more segments e.g. /:p?-static
-                          // or /:p?-:p2
-                          optional && segment.length < 2
-                              ? `(?:/${subPattern})`
-                              : '/' + subPattern;
-                  if (optional)
-                      subPattern += '?';
-                  pattern += subPattern;
-                  subSegmentScore += 20 /* PathScore.Dynamic */;
-                  if (optional)
-                      subSegmentScore += -8 /* PathScore.BonusOptional */;
-                  if (repeatable)
-                      subSegmentScore += -20 /* PathScore.BonusRepeatable */;
-                  if (re === '.*')
-                      subSegmentScore += -50 /* PathScore.BonusWildcard */;
-              }
-              segmentScores.push(subSegmentScore);
-          }
-          // an empty array like /home/ -> [[{home}], []]
-          // if (!segment.length) pattern += '/'
-          score.push(segmentScores);
-      }
-      // only apply the strict bonus to the last score
-      if (options.strict && options.end) {
-          const i = score.length - 1;
-          score[i][score[i].length - 1] += 0.7000000000000001 /* PathScore.BonusStrict */;
-      }
-      // TODO: dev only warn double trailing slash
-      if (!options.strict)
-          pattern += '/?';
-      if (options.end)
-          pattern += '$';
-      // allow paths like /dynamic to only match dynamic or dynamic/... but not dynamic_something_else
-      else if (options.strict)
-          pattern += '(?:/|$)';
-      const re = new RegExp(pattern, options.sensitive ? '' : 'i');
-      function parse(path) {
-          const match = path.match(re);
-          const params = {};
-          if (!match)
-              return null;
-          for (let i = 1; i < match.length; i++) {
-              const value = match[i] || '';
-              const key = keys[i - 1];
-              params[key.name] = value && key.repeatable ? value.split('/') : value;
-          }
-          return params;
-      }
-      function stringify(params) {
-          let path = '';
-          // for optional parameters to allow to be empty
-          let avoidDuplicatedSlash = false;
-          for (const segment of segments) {
-              if (!avoidDuplicatedSlash || !path.endsWith('/'))
-                  path += '/';
-              avoidDuplicatedSlash = false;
-              for (const token of segment) {
-                  if (token.type === 0 /* TokenType.Static */) {
-                      path += token.value;
-                  }
-                  else if (token.type === 1 /* TokenType.Param */) {
-                      const { value, repeatable, optional } = token;
-                      const param = value in params ? params[value] : '';
-                      if (isArray(param) && !repeatable) {
-                          throw new Error(`Provided param "${value}" is an array but it is not repeatable (* or + modifiers)`);
-                      }
-                      const text = isArray(param)
-                          ? param.join('/')
-                          : param;
-                      if (!text) {
-                          if (optional) {
-                              // if we have more than one optional param like /:a?-static we don't need to care about the optional param
-                              if (segment.length < 2) {
-                                  // remove the last slash as we could be at the end
-                                  if (path.endsWith('/'))
-                                      path = path.slice(0, -1);
-                                  // do not append a slash on the next iteration
-                                  else
-                                      avoidDuplicatedSlash = true;
-                              }
-                          }
-                          else
-                              throw new Error(`Missing required param "${value}"`);
-                      }
-                      path += text;
-                  }
-              }
-          }
-          // avoid empty path when we have multiple optional params
-          return path || '/';
-      }
-      return {
-          re,
-          score,
-          keys,
-          parse,
-          stringify,
-      };
-  }
-  /**
-   * Compares an array of numbers as used in PathParser.score and returns a
-   * number. This function can be used to `sort` an array
-   *
-   * @param a - first array of numbers
-   * @param b - second array of numbers
-   * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
-   * should be sorted first
-   */
-  function compareScoreArray(a, b) {
-      let i = 0;
-      while (i < a.length && i < b.length) {
-          const diff = b[i] - a[i];
-          // only keep going if diff === 0
-          if (diff)
-              return diff;
-          i++;
-      }
-      // if the last subsegment was Static, the shorter segments should be sorted first
-      // otherwise sort the longest segment first
-      if (a.length < b.length) {
-          return a.length === 1 && a[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */
-              ? -1
-              : 1;
-      }
-      else if (a.length > b.length) {
-          return b.length === 1 && b[0] === 40 /* PathScore.Static */ + 40 /* PathScore.Segment */
-              ? 1
-              : -1;
-      }
-      return 0;
-  }
-  /**
-   * Compare function that can be used with `sort` to sort an array of PathParser
-   *
-   * @param a - first PathParser
-   * @param b - second PathParser
-   * @returns 0 if both are equal, < 0 if a should be sorted first, > 0 if b
-   */
-  function comparePathParserScore(a, b) {
-      let i = 0;
-      const aScore = a.score;
-      const bScore = b.score;
-      while (i < aScore.length && i < bScore.length) {
-          const comp = compareScoreArray(aScore[i], bScore[i]);
-          // do not return if both are equal
-          if (comp)
-              return comp;
-          i++;
-      }
-      if (Math.abs(bScore.length - aScore.length) === 1) {
-          if (isLastScoreNegative(aScore))
-              return 1;
-          if (isLastScoreNegative(bScore))
-              return -1;
-      }
-      // if a and b share the same score entries but b has more, sort b first
-      return bScore.length - aScore.length;
-      // this is the ternary version
-      // return aScore.length < bScore.length
-      //   ? 1
-      //   : aScore.length > bScore.length
-      //   ? -1
-      //   : 0
-  }
-  /**
-   * This allows detecting splats at the end of a path: /home/:id(.*)*
-   *
-   * @param score - score to check
-   * @returns true if the last entry is negative
-   */
-  function isLastScoreNegative(score) {
-      const last = score[score.length - 1];
-      return score.length > 0 && last[last.length - 1] < 0;
-  }
-
-  const ROOT_TOKEN = {
-      type: 0 /* TokenType.Static */,
-      value: '',
-  };
-  const VALID_PARAM_RE = /[a-zA-Z0-9_]/;
-  // After some profiling, the cache seems to be unnecessary because tokenizePath
-  // (the slowest part of adding a route) is very fast
-  // const tokenCache = new Map<string, Token[][]>()
-  function tokenizePath(path) {
-      if (!path)
-          return [[]];
-      if (path === '/')
-          return [[ROOT_TOKEN]];
-      if (!path.startsWith('/')) {
-          throw new Error(`Route paths should start with a "/": "${path}" should be "/${path}".`
-              );
-      }
-      // if (tokenCache.has(path)) return tokenCache.get(path)!
-      function crash(message) {
-          throw new Error(`ERR (${state})/"${buffer}": ${message}`);
-      }
-      let state = 0 /* TokenizerState.Static */;
-      let previousState = state;
-      const tokens = [];
-      // the segment will always be valid because we get into the initial state
-      // with the leading /
-      let segment;
-      function finalizeSegment() {
-          if (segment)
-              tokens.push(segment);
-          segment = [];
-      }
-      // index on the path
-      let i = 0;
-      // char at index
-      let char;
-      // buffer of the value read
-      let buffer = '';
-      // custom regexp for a param
-      let customRe = '';
-      function consumeBuffer() {
-          if (!buffer)
-              return;
-          if (state === 0 /* TokenizerState.Static */) {
-              segment.push({
-                  type: 0 /* TokenType.Static */,
-                  value: buffer,
-              });
-          }
-          else if (state === 1 /* TokenizerState.Param */ ||
-              state === 2 /* TokenizerState.ParamRegExp */ ||
-              state === 3 /* TokenizerState.ParamRegExpEnd */) {
-              if (segment.length > 1 && (char === '*' || char === '+'))
-                  crash(`A repeatable param (${buffer}) must be alone in its segment. eg: '/:ids+.`);
-              segment.push({
-                  type: 1 /* TokenType.Param */,
-                  value: buffer,
-                  regexp: customRe,
-                  repeatable: char === '*' || char === '+',
-                  optional: char === '*' || char === '?',
-              });
-          }
-          else {
-              crash('Invalid state to consume buffer');
-          }
-          buffer = '';
-      }
-      function addCharToBuffer() {
-          buffer += char;
-      }
-      while (i < path.length) {
-          char = path[i++];
-          if (char === '\\' && state !== 2 /* TokenizerState.ParamRegExp */) {
-              previousState = state;
-              state = 4 /* TokenizerState.EscapeNext */;
-              continue;
-          }
-          switch (state) {
-              case 0 /* TokenizerState.Static */:
-                  if (char === '/') {
-                      if (buffer) {
-                          consumeBuffer();
-                      }
-                      finalizeSegment();
-                  }
-                  else if (char === ':') {
-                      consumeBuffer();
-                      state = 1 /* TokenizerState.Param */;
-                  }
-                  else {
-                      addCharToBuffer();
-                  }
-                  break;
-              case 4 /* TokenizerState.EscapeNext */:
-                  addCharToBuffer();
-                  state = previousState;
-                  break;
-              case 1 /* TokenizerState.Param */:
-                  if (char === '(') {
-                      state = 2 /* TokenizerState.ParamRegExp */;
-                  }
-                  else if (VALID_PARAM_RE.test(char)) {
-                      addCharToBuffer();
-                  }
-                  else {
-                      consumeBuffer();
-                      state = 0 /* TokenizerState.Static */;
-                      // go back one character if we were not modifying
-                      if (char !== '*' && char !== '?' && char !== '+')
-                          i--;
-                  }
-                  break;
-              case 2 /* TokenizerState.ParamRegExp */:
-                  // TODO: is it worth handling nested regexp? like :p(?:prefix_([^/]+)_suffix)
-                  // it already works by escaping the closing )
-                  // https://paths.esm.dev/?p=AAMeJbiAwQEcDKbAoAAkP60PG2R6QAvgNaA6AFACM2ABuQBB#
-                  // is this really something people need since you can also write
-                  // /prefix_:p()_suffix
-                  if (char === ')') {
-                      // handle the escaped )
-                      if (customRe[customRe.length - 1] == '\\')
-                          customRe = customRe.slice(0, -1) + char;
-                      else
-                          state = 3 /* TokenizerState.ParamRegExpEnd */;
-                  }
-                  else {
-                      customRe += char;
-                  }
-                  break;
-              case 3 /* TokenizerState.ParamRegExpEnd */:
-                  // same as finalizing a param
-                  consumeBuffer();
-                  state = 0 /* TokenizerState.Static */;
-                  // go back one character if we were not modifying
-                  if (char !== '*' && char !== '?' && char !== '+')
-                      i--;
-                  customRe = '';
-                  break;
-              default:
-                  crash('Unknown state');
-                  break;
-          }
-      }
-      if (state === 2 /* TokenizerState.ParamRegExp */)
-          crash(`Unfinished custom RegExp for param "${buffer}"`);
-      consumeBuffer();
-      finalizeSegment();
-      // tokenCache.set(path, tokens)
-      return tokens;
-  }
-
-  function createRouteRecordMatcher(record, parent, options) {
-      const parser = tokensToParser(tokenizePath(record.path), options);
-      // warn against params with the same name
-      {
-          const existingKeys = new Set();
-          for (const key of parser.keys) {
-              if (existingKeys.has(key.name))
-                  warn(`Found duplicated params with name "${key.name}" for path "${record.path}". Only the last one will be available on "$route.params".`);
-              existingKeys.add(key.name);
-          }
-      }
-      const matcher = assign(parser, {
-          record,
-          parent,
-          // these needs to be populated by the parent
-          children: [],
-          alias: [],
-      });
-      if (parent) {
-          // both are aliases or both are not aliases
-          // we don't want to mix them because the order is used when
-          // passing originalRecord in Matcher.addRoute
-          if (!matcher.record.aliasOf === !parent.record.aliasOf)
-              parent.children.push(matcher);
-      }
-      return matcher;
-  }
-
-  /**
-   * Creates a Router Matcher.
-   *
-   * @internal
-   * @param routes - array of initial routes
-   * @param globalOptions - global route options
-   */
-  function createRouterMatcher(routes, globalOptions) {
-      // normalized ordered array of matchers
-      const matchers = [];
-      const matcherMap = new Map();
-      globalOptions = mergeOptions({ strict: false, end: true, sensitive: false }, globalOptions);
-      function getRecordMatcher(name) {
-          return matcherMap.get(name);
-      }
-      function addRoute(record, parent, originalRecord) {
-          // used later on to remove by name
-          const isRootAdd = !originalRecord;
-          const mainNormalizedRecord = normalizeRouteRecord(record);
-          {
-              checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent);
-          }
-          // we might be the child of an alias
-          mainNormalizedRecord.aliasOf = originalRecord && originalRecord.record;
-          const options = mergeOptions(globalOptions, record);
-          // generate an array of records to correctly handle aliases
-          const normalizedRecords = [
-              mainNormalizedRecord,
-          ];
-          if ('alias' in record) {
-              const aliases = typeof record.alias === 'string' ? [record.alias] : record.alias;
-              for (const alias of aliases) {
-                  normalizedRecords.push(assign({}, mainNormalizedRecord, {
-                      // this allows us to hold a copy of the `components` option
-                      // so that async components cache is hold on the original record
-                      components: originalRecord
-                          ? originalRecord.record.components
-                          : mainNormalizedRecord.components,
-                      path: alias,
-                      // we might be the child of an alias
-                      aliasOf: originalRecord
-                          ? originalRecord.record
-                          : mainNormalizedRecord,
-                      // the aliases are always of the same kind as the original since they
-                      // are defined on the same record
-                  }));
-              }
-          }
-          let matcher;
-          let originalMatcher;
-          for (const normalizedRecord of normalizedRecords) {
-              const { path } = normalizedRecord;
-              // Build up the path for nested routes if the child isn't an absolute
-              // route. Only add the / delimiter if the child path isn't empty and if the
-              // parent path doesn't have a trailing slash
-              if (parent && path[0] !== '/') {
-                  const parentPath = parent.record.path;
-                  const connectingSlash = parentPath[parentPath.length - 1] === '/' ? '' : '/';
-                  normalizedRecord.path =
-                      parent.record.path + (path && connectingSlash + path);
-              }
-              if (normalizedRecord.path === '*') {
-                  throw new Error('Catch all routes ("*") must now be defined using a param with a custom regexp.\n' +
-                      'See more at https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes.');
-              }
-              // create the object beforehand, so it can be passed to children
-              matcher = createRouteRecordMatcher(normalizedRecord, parent, options);
-              if (parent && path[0] === '/')
-                  checkMissingParamsInAbsolutePath(matcher, parent);
-              // if we are an alias we must tell the original record that we exist,
-              // so we can be removed
-              if (originalRecord) {
-                  originalRecord.alias.push(matcher);
-                  {
-                      checkSameParams(originalRecord, matcher);
-                  }
-              }
-              else {
-                  // otherwise, the first record is the original and others are aliases
-                  originalMatcher = originalMatcher || matcher;
-                  if (originalMatcher !== matcher)
-                      originalMatcher.alias.push(matcher);
-                  // remove the route if named and only for the top record (avoid in nested calls)
-                  // this works because the original record is the first one
-                  if (isRootAdd && record.name && !isAliasRecord(matcher))
-                      removeRoute(record.name);
-              }
-              if (mainNormalizedRecord.children) {
-                  const children = mainNormalizedRecord.children;
-                  for (let i = 0; i < children.length; i++) {
-                      addRoute(children[i], matcher, originalRecord && originalRecord.children[i]);
-                  }
-              }
-              // if there was no original record, then the first one was not an alias and all
-              // other aliases (if any) need to reference this record when adding children
-              originalRecord = originalRecord || matcher;
-              // TODO: add normalized records for more flexibility
-              // if (parent && isAliasRecord(originalRecord)) {
-              //   parent.children.push(originalRecord)
-              // }
-              // Avoid adding a record that doesn't display anything. This allows passing through records without a component to
-              // not be reached and pass through the catch all route
-              if ((matcher.record.components &&
-                  Object.keys(matcher.record.components).length) ||
-                  matcher.record.name ||
-                  matcher.record.redirect) {
-                  insertMatcher(matcher);
-              }
-          }
-          return originalMatcher
-              ? () => {
-                  // since other matchers are aliases, they should be removed by the original matcher
-                  removeRoute(originalMatcher);
-              }
-              : noop;
-      }
-      function removeRoute(matcherRef) {
-          if (isRouteName(matcherRef)) {
-              const matcher = matcherMap.get(matcherRef);
-              if (matcher) {
-                  matcherMap.delete(matcherRef);
-                  matchers.splice(matchers.indexOf(matcher), 1);
-                  matcher.children.forEach(removeRoute);
-                  matcher.alias.forEach(removeRoute);
-              }
-          }
-          else {
-              const index = matchers.indexOf(matcherRef);
-              if (index > -1) {
-                  matchers.splice(index, 1);
-                  if (matcherRef.record.name)
-                      matcherMap.delete(matcherRef.record.name);
-                  matcherRef.children.forEach(removeRoute);
-                  matcherRef.alias.forEach(removeRoute);
-              }
-          }
-      }
-      function getRoutes() {
-          return matchers;
-      }
-      function insertMatcher(matcher) {
-          let i = 0;
-          while (i < matchers.length &&
-              comparePathParserScore(matcher, matchers[i]) >= 0 &&
-              // Adding children with empty path should still appear before the parent
-              // https://github.com/vuejs/router/issues/1124
-              (matcher.record.path !== matchers[i].record.path ||
-                  !isRecordChildOf(matcher, matchers[i])))
-              i++;
-          matchers.splice(i, 0, matcher);
-          // only add the original record to the name map
-          if (matcher.record.name && !isAliasRecord(matcher))
-              matcherMap.set(matcher.record.name, matcher);
-      }
-      function resolve(location, currentLocation) {
-          let matcher;
-          let params = {};
-          let path;
-          let name;
-          if ('name' in location && location.name) {
-              matcher = matcherMap.get(location.name);
-              if (!matcher)
-                  throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {
-                      location,
-                  });
-              // warn if the user is passing invalid params so they can debug it better when they get removed
-              {
-                  const invalidParams = Object.keys(location.params || {}).filter(paramName => !matcher.keys.find(k => k.name === paramName));
-                  if (invalidParams.length) {
-                      warn(`Discarded invalid param(s) "${invalidParams.join('", "')}" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.`);
-                  }
-              }
-              name = matcher.record.name;
-              params = assign(
-              // paramsFromLocation is a new object
-              paramsFromLocation(currentLocation.params, 
-              // only keep params that exist in the resolved location
-              // only keep optional params coming from a parent record
-              matcher.keys
-                  .filter(k => !k.optional)
-                  .concat(matcher.parent ? matcher.parent.keys.filter(k => k.optional) : [])
-                  .map(k => k.name)), 
-              // discard any existing params in the current location that do not exist here
-              // #1497 this ensures better active/exact matching
-              location.params &&
-                  paramsFromLocation(location.params, matcher.keys.map(k => k.name)));
-              // throws if cannot be stringified
-              path = matcher.stringify(params);
-          }
-          else if (location.path != null) {
-              // no need to resolve the path with the matcher as it was provided
-              // this also allows the user to control the encoding
-              path = location.path;
-              if (!path.startsWith('/')) {
-                  warn(`The Matcher cannot resolve relative paths but received "${path}". Unless you directly called \`matcher.resolve("${path}")\`, this is probably a bug in vue-router. Please open an issue at https://github.com/vuejs/router/issues/new/choose.`);
-              }
-              matcher = matchers.find(m => m.re.test(path));
-              // matcher should have a value after the loop
-              if (matcher) {
-                  // we know the matcher works because we tested the regexp
-                  params = matcher.parse(path);
-                  name = matcher.record.name;
-              }
-              // location is a relative path
-          }
-          else {
-              // match by name or path of current route
-              matcher = currentLocation.name
-                  ? matcherMap.get(currentLocation.name)
-                  : matchers.find(m => m.re.test(currentLocation.path));
-              if (!matcher)
-                  throw createRouterError(1 /* ErrorTypes.MATCHER_NOT_FOUND */, {
-                      location,
-                      currentLocation,
-                  });
-              name = matcher.record.name;
-              // since we are navigating to the same location, we don't need to pick the
-              // params like when `name` is provided
-              params = assign({}, currentLocation.params, location.params);
-              path = matcher.stringify(params);
-          }
-          const matched = [];
-          let parentMatcher = matcher;
-          while (parentMatcher) {
-              // reversed order so parents are at the beginning
-              matched.unshift(parentMatcher.record);
-              parentMatcher = parentMatcher.parent;
-          }
-          return {
-              name,
-              path,
-              params,
-              matched,
-              meta: mergeMetaFields(matched),
-          };
-      }
-      // add initial routes
-      routes.forEach(route => addRoute(route));
-      return { addRoute, resolve, removeRoute, getRoutes, getRecordMatcher };
-  }
-  function paramsFromLocation(params, keys) {
-      const newParams = {};
-      for (const key of keys) {
-          if (key in params)
-              newParams[key] = params[key];
-      }
-      return newParams;
-  }
-  /**
-   * Normalizes a RouteRecordRaw. Creates a copy
-   *
-   * @param record
-   * @returns the normalized version
-   */
-  function normalizeRouteRecord(record) {
-      return {
-          path: record.path,
-          redirect: record.redirect,
-          name: record.name,
-          meta: record.meta || {},
-          aliasOf: undefined,
-          beforeEnter: record.beforeEnter,
-          props: normalizeRecordProps(record),
-          children: record.children || [],
-          instances: {},
-          leaveGuards: new Set(),
-          updateGuards: new Set(),
-          enterCallbacks: {},
-          components: 'components' in record
-              ? record.components || null
-              : record.component && { default: record.component },
-      };
-  }
-  /**
-   * Normalize the optional `props` in a record to always be an object similar to
-   * components. Also accept a boolean for components.
-   * @param record
-   */
-  function normalizeRecordProps(record) {
-      const propsObject = {};
-      // props does not exist on redirect records, but we can set false directly
-      const props = record.props || false;
-      if ('component' in record) {
-          propsObject.default = props;
-      }
-      else {
-          // NOTE: we could also allow a function to be applied to every component.
-          // Would need user feedback for use cases
-          for (const name in record.components)
-              propsObject[name] = typeof props === 'object' ? props[name] : props;
-      }
-      return propsObject;
-  }
-  /**
-   * Checks if a record or any of its parent is an alias
-   * @param record
-   */
-  function isAliasRecord(record) {
-      while (record) {
-          if (record.record.aliasOf)
-              return true;
-          record = record.parent;
-      }
-      return false;
-  }
-  /**
-   * Merge meta fields of an array of records
-   *
-   * @param matched - array of matched records
-   */
-  function mergeMetaFields(matched) {
-      return matched.reduce((meta, record) => assign(meta, record.meta), {});
-  }
-  function mergeOptions(defaults, partialOptions) {
-      const options = {};
-      for (const key in defaults) {
-          options[key] = key in partialOptions ? partialOptions[key] : defaults[key];
-      }
-      return options;
-  }
-  function isSameParam(a, b) {
-      return (a.name === b.name &&
-          a.optional === b.optional &&
-          a.repeatable === b.repeatable);
-  }
-  /**
-   * Check if a path and its alias have the same required params
-   *
-   * @param a - original record
-   * @param b - alias record
-   */
-  function checkSameParams(a, b) {
-      for (const key of a.keys) {
-          if (!key.optional && !b.keys.find(isSameParam.bind(null, key)))
-              return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`);
-      }
-      for (const key of b.keys) {
-          if (!key.optional && !a.keys.find(isSameParam.bind(null, key)))
-              return warn(`Alias "${b.record.path}" and the original record: "${a.record.path}" must have the exact same param named "${key.name}"`);
-      }
-  }
-  /**
-   * A route with a name and a child with an empty path without a name should warn when adding the route
-   *
-   * @param mainNormalizedRecord - RouteRecordNormalized
-   * @param parent - RouteRecordMatcher
-   */
-  function checkChildMissingNameWithEmptyPath(mainNormalizedRecord, parent) {
-      if (parent &&
-          parent.record.name &&
-          !mainNormalizedRecord.name &&
-          !mainNormalizedRecord.path) {
-          warn(`The route named "${String(parent.record.name)}" has a child without a name and an empty path. Using that name won't render the empty path child so you probably want to move the name to the child instead. If this is intentional, add a name to the child route to remove the warning.`);
-      }
-  }
-  function checkMissingParamsInAbsolutePath(record, parent) {
-      for (const key of parent.keys) {
-          if (!record.keys.find(isSameParam.bind(null, key)))
-              return warn(`Absolute path "${record.record.path}" must have the exact same param named "${key.name}" as its parent "${parent.record.path}".`);
-      }
-  }
-  function isRecordChildOf(record, parent) {
-      return parent.children.some(child => child === record || isRecordChildOf(record, child));
-  }
-
-  /**
-   * Transforms a queryString into a {@link LocationQuery} object. Accept both, a
-   * version with the leading `?` and without Should work as URLSearchParams
-
-   * @internal
-   *
-   * @param search - search string to parse
-   * @returns a query object
-   */
-  function parseQuery(search) {
-      const query = {};
-      // avoid creating an object with an empty key and empty value
-      // because of split('&')
-      if (search === '' || search === '?')
-          return query;
-      const hasLeadingIM = search[0] === '?';
-      const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&');
-      for (let i = 0; i < searchParams.length; ++i) {
-          // pre decode the + into space
-          const searchParam = searchParams[i].replace(PLUS_RE, ' ');
-          // allow the = character
-          const eqPos = searchParam.indexOf('=');
-          const key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));
-          const value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));
-          if (key in query) {
-              // an extra variable for ts types
-              let currentValue = query[key];
-              if (!isArray(currentValue)) {
-                  currentValue = query[key] = [currentValue];
-              }
-              currentValue.push(value);
-          }
-          else {
-              query[key] = value;
-          }
-      }
-      return query;
-  }
-  /**
-   * Stringifies a {@link LocationQueryRaw} object. Like `URLSearchParams`, it
-   * doesn't prepend a `?`
-   *
-   * @internal
-   *
-   * @param query - query object to stringify
-   * @returns string version of the query without the leading `?`
-   */
-  function stringifyQuery(query) {
-      let search = '';
-      for (let key in query) {
-          const value = query[key];
-          key = encodeQueryKey(key);
-          if (value == null) {
-              // only null adds the value
-              if (value !== undefined) {
-                  search += (search.length ? '&' : '') + key;
-              }
-              continue;
-          }
-          // keep null values
-          const values = isArray(value)
-              ? value.map(v => v && encodeQueryValue(v))
-              : [value && encodeQueryValue(value)];
-          values.forEach(value => {
-              // skip undefined values in arrays as if they were not present
-              // smaller code than using filter
-              if (value !== undefined) {
-                  // only append & with non-empty search
-                  search += (search.length ? '&' : '') + key;
-                  if (value != null)
-                      search += '=' + value;
-              }
-          });
-      }
-      return search;
-  }
-  /**
-   * Transforms a {@link LocationQueryRaw} into a {@link LocationQuery} by casting
-   * numbers into strings, removing keys with an undefined value and replacing
-   * undefined with null in arrays
-   *
-   * @param query - query object to normalize
-   * @returns a normalized query object
-   */
-  function normalizeQuery(query) {
-      const normalizedQuery = {};
-      for (const key in query) {
-          const value = query[key];
-          if (value !== undefined) {
-              normalizedQuery[key] = isArray(value)
-                  ? value.map(v => (v == null ? null : '' + v))
-                  : value == null
-                      ? value
-                      : '' + value;
-          }
-      }
-      return normalizedQuery;
-  }
-
-  /**
-   * RouteRecord being rendered by the closest ancestor Router View. Used for
-   * `onBeforeRouteUpdate` and `onBeforeRouteLeave`. rvlm stands for Router View
-   * Location Matched
-   *
-   * @internal
-   */
-  const matchedRouteKey = Symbol('router view location matched' );
-  /**
-   * Allows overriding the router view depth to control which component in
-   * `matched` is rendered. rvd stands for Router View Depth
-   *
-   * @internal
-   */
-  const viewDepthKey = Symbol('router view depth' );
-  /**
-   * Allows overriding the router instance returned by `useRouter` in tests. r
-   * stands for router
-   *
-   * @internal
-   */
-  const routerKey = Symbol('router' );
-  /**
-   * Allows overriding the current route returned by `useRoute` in tests. rl
-   * stands for route location
-   *
-   * @internal
-   */
-  const routeLocationKey = Symbol('route location' );
-  /**
-   * Allows overriding the current route used by router-view. Internally this is
-   * used when the `route` prop is passed.
-   *
-   * @internal
-   */
-  const routerViewLocationKey = Symbol('router view location' );
-
-  /**
-   * Create a list of callbacks that can be reset. Used to create before and after navigation guards list
-   */
-  function useCallbacks() {
-      let handlers = [];
-      function add(handler) {
-          handlers.push(handler);
-          return () => {
-              const i = handlers.indexOf(handler);
-              if (i > -1)
-                  handlers.splice(i, 1);
-          };
-      }
-      function reset() {
-          handlers = [];
-      }
-      return {
-          add,
-          list: () => handlers.slice(),
-          reset,
-      };
-  }
-
-  function registerGuard(record, name, guard) {
-      const removeFromList = () => {
-          record[name].delete(guard);
-      };
-      vue.onUnmounted(removeFromList);
-      vue.onDeactivated(removeFromList);
-      vue.onActivated(() => {
-          record[name].add(guard);
-      });
-      record[name].add(guard);
-  }
-  /**
-   * Add a navigation guard that triggers whenever the component for the current
-   * location is about to be left. Similar to {@link beforeRouteLeave} but can be
-   * used in any component. The guard is removed when the component is unmounted.
-   *
-   * @param leaveGuard - {@link NavigationGuard}
-   */
-  function onBeforeRouteLeave(leaveGuard) {
-      if (!vue.getCurrentInstance()) {
-          warn('getCurrentInstance() returned null. onBeforeRouteLeave() must be called at the top of a setup function');
-          return;
-      }
-      const activeRecord = vue.inject(matchedRouteKey, 
-      // to avoid warning
-      {}).value;
-      if (!activeRecord) {
-          warn('No active route record was found when calling `onBeforeRouteLeave()`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?');
-          return;
-      }
-      registerGuard(activeRecord, 'leaveGuards', leaveGuard);
-  }
-  /**
-   * Add a navigation guard that triggers whenever the current location is about
-   * to be updated. Similar to {@link beforeRouteUpdate} but can be used in any
-   * component. The guard is removed when the component is unmounted.
-   *
-   * @param updateGuard - {@link NavigationGuard}
-   */
-  function onBeforeRouteUpdate(updateGuard) {
-      if (!vue.getCurrentInstance()) {
-          warn('getCurrentInstance() returned null. onBeforeRouteUpdate() must be called at the top of a setup function');
-          return;
-      }
-      const activeRecord = vue.inject(matchedRouteKey, 
-      // to avoid warning
-      {}).value;
-      if (!activeRecord) {
-          warn('No active route record was found when calling `onBeforeRouteUpdate()`. Make sure you call this function inside a component child of <router-view>. Maybe you called it inside of App.vue?');
-          return;
-      }
-      registerGuard(activeRecord, 'updateGuards', updateGuard);
-  }
-  function guardToPromiseFn(guard, to, from, record, name, runWithContext = fn => fn()) {
-      // keep a reference to the enterCallbackArray to prevent pushing callbacks if a new navigation took place
-      const enterCallbackArray = record &&
-          // name is defined if record is because of the function overload
-          (record.enterCallbacks[name] = record.enterCallbacks[name] || []);
-      return () => new Promise((resolve, reject) => {
-          const next = (valid) => {
-              if (valid === false) {
-                  reject(createRouterError(4 /* ErrorTypes.NAVIGATION_ABORTED */, {
-                      from,
-                      to,
-                  }));
-              }
-              else if (valid instanceof Error) {
-                  reject(valid);
-              }
-              else if (isRouteLocation(valid)) {
-                  reject(createRouterError(2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */, {
-                      from: to,
-                      to: valid,
-                  }));
-              }
-              else {
-                  if (enterCallbackArray &&
-                      // since enterCallbackArray is truthy, both record and name also are
-                      record.enterCallbacks[name] === enterCallbackArray &&
-                      typeof valid === 'function') {
-                      enterCallbackArray.push(valid);
-                  }
-                  resolve();
-              }
-          };
-          // wrapping with Promise.resolve allows it to work with both async and sync guards
-          const guardReturn = runWithContext(() => guard.call(record && record.instances[name], to, from, canOnlyBeCalledOnce(next, to, from) ));
-          let guardCall = Promise.resolve(guardReturn);
-          if (guard.length < 3)
-              guardCall = guardCall.then(next);
-          if (guard.length > 2) {
-              const message = `The "next" callback was never called inside of ${guard.name ? '"' + guard.name + '"' : ''}:\n${guard.toString()}\n. If you are returning a value instead of calling "next", make sure to remove the "next" parameter from your function.`;
-              if (typeof guardReturn === 'object' && 'then' in guardReturn) {
-                  guardCall = guardCall.then(resolvedValue => {
-                      // @ts-expect-error: _called is added at canOnlyBeCalledOnce
-                      if (!next._called) {
-                          warn(message);
-                          return Promise.reject(new Error('Invalid navigation guard'));
-                      }
-                      return resolvedValue;
-                  });
-              }
-              else if (guardReturn !== undefined) {
-                  // @ts-expect-error: _called is added at canOnlyBeCalledOnce
-                  if (!next._called) {
-                      warn(message);
-                      reject(new Error('Invalid navigation guard'));
-                      return;
-                  }
-              }
-          }
-          guardCall.catch(err => reject(err));
-      });
-  }
-  function canOnlyBeCalledOnce(next, to, from) {
-      let called = 0;
-      return function () {
-          if (called++ === 1)
-              warn(`The "next" callback was called more than once in one navigation guard when going from "${from.fullPath}" to "${to.fullPath}". It should be called exactly one time in each navigation guard. This will fail in production.`);
-          // @ts-expect-error: we put it in the original one because it's easier to check
-          next._called = true;
-          if (called === 1)
-              next.apply(null, arguments);
-      };
-  }
-  function extractComponentsGuards(matched, guardType, to, from, runWithContext = fn => fn()) {
-      const guards = [];
-      for (const record of matched) {
-          if (!record.components && !record.children.length) {
-              warn(`Record with path "${record.path}" is either missing a "component(s)"` +
-                  ` or "children" property.`);
-          }
-          for (const name in record.components) {
-              let rawComponent = record.components[name];
-              {
-                  if (!rawComponent ||
-                      (typeof rawComponent !== 'object' &&
-                          typeof rawComponent !== 'function')) {
-                      warn(`Component "${name}" in record with path "${record.path}" is not` +
-                          ` a valid component. Received "${String(rawComponent)}".`);
-                      // throw to ensure we stop here but warn to ensure the message isn't
-                      // missed by the user
-                      throw new Error('Invalid route component');
-                  }
-                  else if ('then' in rawComponent) {
-                      // warn if user wrote import('/component.vue') instead of () =>
-                      // import('./component.vue')
-                      warn(`Component "${name}" in record with path "${record.path}" is a ` +
-                          `Promise instead of a function that returns a Promise. Did you ` +
-                          `write "import('./MyPage.vue')" instead of ` +
-                          `"() => import('./MyPage.vue')" ? This will break in ` +
-                          `production if not fixed.`);
-                      const promise = rawComponent;
-                      rawComponent = () => promise;
-                  }
-                  else if (rawComponent.__asyncLoader &&
-                      // warn only once per component
-                      !rawComponent.__warnedDefineAsync) {
-                      rawComponent.__warnedDefineAsync = true;
-                      warn(`Component "${name}" in record with path "${record.path}" is defined ` +
-                          `using "defineAsyncComponent()". ` +
-                          `Write "() => import('./MyPage.vue')" instead of ` +
-                          `"defineAsyncComponent(() => import('./MyPage.vue'))".`);
-                  }
-              }
-              // skip update and leave guards if the route component is not mounted
-              if (guardType !== 'beforeRouteEnter' && !record.instances[name])
-                  continue;
-              if (isRouteComponent(rawComponent)) {
-                  // __vccOpts is added by vue-class-component and contain the regular options
-                  const options = rawComponent.__vccOpts || rawComponent;
-                  const guard = options[guardType];
-                  guard &&
-                      guards.push(guardToPromiseFn(guard, to, from, record, name, runWithContext));
-              }
-              else {
-                  // start requesting the chunk already
-                  let componentPromise = rawComponent();
-                  if (!('catch' in componentPromise)) {
-                      warn(`Component "${name}" in record with path "${record.path}" is a function that does not return a Promise. If you were passing a functional component, make sure to add a "displayName" to the component. This will break in production if not fixed.`);
-                      componentPromise = Promise.resolve(componentPromise);
-                  }
-                  guards.push(() => componentPromise.then(resolved => {
-                      if (!resolved)
-                          return Promise.reject(new Error(`Couldn't resolve component "${name}" at "${record.path}"`));
-                      const resolvedComponent = isESModule(resolved)
-                          ? resolved.default
-                          : resolved;
-                      // replace the function with the resolved component
-                      // cannot be null or undefined because we went into the for loop
-                      record.components[name] = resolvedComponent;
-                      // __vccOpts is added by vue-class-component and contain the regular options
-                      const options = resolvedComponent.__vccOpts || resolvedComponent;
-                      const guard = options[guardType];
-                      return (guard &&
-                          guardToPromiseFn(guard, to, from, record, name, runWithContext)());
-                  }));
-              }
-          }
-      }
-      return guards;
-  }
-  /**
-   * Allows differentiating lazy components from functional components and vue-class-component
-   * @internal
-   *
-   * @param component
-   */
-  function isRouteComponent(component) {
-      return (typeof component === 'object' ||
-          'displayName' in component ||
-          'props' in component ||
-          '__vccOpts' in component);
-  }
-  /**
-   * Ensures a route is loaded, so it can be passed as o prop to `<RouterView>`.
-   *
-   * @param route - resolved route to load
-   */
-  function loadRouteLocation(route) {
-      return route.matched.every(record => record.redirect)
-          ? Promise.reject(new Error('Cannot load a route that redirects.'))
-          : Promise.all(route.matched.map(record => record.components &&
-              Promise.all(Object.keys(record.components).reduce((promises, name) => {
-                  const rawComponent = record.components[name];
-                  if (typeof rawComponent === 'function' &&
-                      !('displayName' in rawComponent)) {
-                      promises.push(rawComponent().then(resolved => {
-                          if (!resolved)
-                              return Promise.reject(new Error(`Couldn't resolve component "${name}" at "${record.path}". Ensure you passed a function that returns a promise.`));
-                          const resolvedComponent = isESModule(resolved)
-                              ? resolved.default
-                              : resolved;
-                          // replace the function with the resolved component
-                          // cannot be null or undefined because we went into the for loop
-                          record.components[name] = resolvedComponent;
-                          return;
-                      }));
-                  }
-                  return promises;
-              }, [])))).then(() => route);
-  }
-
-  // TODO: we could allow currentRoute as a prop to expose `isActive` and
-  // `isExactActive` behavior should go through an RFC
-  function useLink(props) {
-      const router = vue.inject(routerKey);
-      const currentRoute = vue.inject(routeLocationKey);
-      let hasPrevious = false;
-      let previousTo = null;
-      const route = vue.computed(() => {
-          const to = vue.unref(props.to);
-          if ((!hasPrevious || to !== previousTo)) {
-              if (!isRouteLocation(to)) {
-                  if (hasPrevious) {
-                      warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- previous to:`, previousTo, `\n- props:`, props);
-                  }
-                  else {
-                      warn(`Invalid value for prop "to" in useLink()\n- to:`, to, `\n- props:`, props);
-                  }
-              }
-              previousTo = to;
-              hasPrevious = true;
-          }
-          return router.resolve(to);
-      });
-      const activeRecordIndex = vue.computed(() => {
-          const { matched } = route.value;
-          const { length } = matched;
-          const routeMatched = matched[length - 1];
-          const currentMatched = currentRoute.matched;
-          if (!routeMatched || !currentMatched.length)
-              return -1;
-          const index = currentMatched.findIndex(isSameRouteRecord.bind(null, routeMatched));
-          if (index > -1)
-              return index;
-          // possible parent record
-          const parentRecordPath = getOriginalPath(matched[length - 2]);
-          return (
-          // we are dealing with nested routes
-          length > 1 &&
-              // if the parent and matched route have the same path, this link is
-              // referring to the empty child. Or we currently are on a different
-              // child of the same parent
-              getOriginalPath(routeMatched) === parentRecordPath &&
-              // avoid comparing the child with its parent
-              currentMatched[currentMatched.length - 1].path !== parentRecordPath
-              ? currentMatched.findIndex(isSameRouteRecord.bind(null, matched[length - 2]))
-              : index);
-      });
-      const isActive = vue.computed(() => activeRecordIndex.value > -1 &&
-          includesParams(currentRoute.params, route.value.params));
-      const isExactActive = vue.computed(() => activeRecordIndex.value > -1 &&
-          activeRecordIndex.value === currentRoute.matched.length - 1 &&
-          isSameRouteLocationParams(currentRoute.params, route.value.params));
-      function navigate(e = {}) {
-          if (guardEvent(e)) {
-              return router[vue.unref(props.replace) ? 'replace' : 'push'](vue.unref(props.to)
-              // avoid uncaught errors are they are logged anyway
-              ).catch(noop);
-          }
-          return Promise.resolve();
-      }
-      // devtools only
-      if (isBrowser) {
-          const instance = vue.getCurrentInstance();
-          if (instance) {
-              const linkContextDevtools = {
-                  route: route.value,
-                  isActive: isActive.value,
-                  isExactActive: isExactActive.value,
-                  error: null,
-              };
-              // @ts-expect-error: this is internal
-              instance.__vrl_devtools = instance.__vrl_devtools || [];
-              // @ts-expect-error: this is internal
-              instance.__vrl_devtools.push(linkContextDevtools);
-              vue.watchEffect(() => {
-                  linkContextDevtools.route = route.value;
-                  linkContextDevtools.isActive = isActive.value;
-                  linkContextDevtools.isExactActive = isExactActive.value;
-                  linkContextDevtools.error = isRouteLocation(vue.unref(props.to))
-                      ? null
-                      : 'Invalid "to" value';
-              }, { flush: 'post' });
-          }
-      }
-      /**
-       * NOTE: update {@link _RouterLinkI}'s `$slots` type when updating this
-       */
-      return {
-          route,
-          href: vue.computed(() => route.value.href),
-          isActive,
-          isExactActive,
-          navigate,
-      };
-  }
-  const RouterLinkImpl = /*#__PURE__*/ vue.defineComponent({
-      name: 'RouterLink',
-      compatConfig: { MODE: 3 },
-      props: {
-          to: {
-              type: [String, Object],
-              required: true,
-          },
-          replace: Boolean,
-          activeClass: String,
-          // inactiveClass: String,
-          exactActiveClass: String,
-          custom: Boolean,
-          ariaCurrentValue: {
-              type: String,
-              default: 'page',
-          },
-      },
-      useLink,
-      setup(props, { slots }) {
-          const link = vue.reactive(useLink(props));
-          const { options } = vue.inject(routerKey);
-          const elClass = vue.computed(() => ({
-              [getLinkClass(props.activeClass, options.linkActiveClass, 'router-link-active')]: link.isActive,
-              // [getLinkClass(
-              //   props.inactiveClass,
-              //   options.linkInactiveClass,
-              //   'router-link-inactive'
-              // )]: !link.isExactActive,
-              [getLinkClass(props.exactActiveClass, options.linkExactActiveClass, 'router-link-exact-active')]: link.isExactActive,
-          }));
-          return () => {
-              const children = slots.default && slots.default(link);
-              return props.custom
-                  ? children
-                  : vue.h('a', {
-                      'aria-current': link.isExactActive
-                          ? props.ariaCurrentValue
-                          : null,
-                      href: link.href,
-                      // this would override user added attrs but Vue will still add
-                      // the listener, so we end up triggering both
-                      onClick: link.navigate,
-                      class: elClass.value,
-                  }, children);
-          };
-      },
-  });
-  // export the public type for h/tsx inference
-  // also to avoid inline import() in generated d.ts files
-  /**
-   * Component to render a link that triggers a navigation on click.
-   */
-  const RouterLink = RouterLinkImpl;
-  function guardEvent(e) {
-      // don't redirect with control keys
-      if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey)
-          return;
-      // don't redirect when preventDefault called
-      if (e.defaultPrevented)
-          return;
-      // don't redirect on right click
-      if (e.button !== undefined && e.button !== 0)
-          return;
-      // don't redirect if `target="_blank"`
-      // @ts-expect-error getAttribute does exist
-      if (e.currentTarget && e.currentTarget.getAttribute) {
-          // @ts-expect-error getAttribute exists
-          const target = e.currentTarget.getAttribute('target');
-          if (/\b_blank\b/i.test(target))
-              return;
-      }
-      // this may be a Weex event which doesn't have this method
-      if (e.preventDefault)
-          e.preventDefault();
-      return true;
-  }
-  function includesParams(outer, inner) {
-      for (const key in inner) {
-          const innerValue = inner[key];
-          const outerValue = outer[key];
-          if (typeof innerValue === 'string') {
-              if (innerValue !== outerValue)
-                  return false;
-          }
-          else {
-              if (!isArray(outerValue) ||
-                  outerValue.length !== innerValue.length ||
-                  innerValue.some((value, i) => value !== outerValue[i]))
-                  return false;
-          }
-      }
-      return true;
-  }
-  /**
-   * Get the original path value of a record by following its aliasOf
-   * @param record
-   */
-  function getOriginalPath(record) {
-      return record ? (record.aliasOf ? record.aliasOf.path : record.path) : '';
-  }
-  /**
-   * Utility class to get the active class based on defaults.
-   * @param propClass
-   * @param globalClass
-   * @param defaultClass
-   */
-  const getLinkClass = (propClass, globalClass, defaultClass) => propClass != null
-      ? propClass
-      : globalClass != null
-          ? globalClass
-          : defaultClass;
-
-  const RouterViewImpl = /*#__PURE__*/ vue.defineComponent({
-      name: 'RouterView',
-      // #674 we manually inherit them
-      inheritAttrs: false,
-      props: {
-          name: {
-              type: String,
-              default: 'default',
-          },
-          route: Object,
-      },
-      // Better compat for @vue/compat users
-      // https://github.com/vuejs/router/issues/1315
-      compatConfig: { MODE: 3 },
-      setup(props, { attrs, slots }) {
-          warnDeprecatedUsage();
-          const injectedRoute = vue.inject(routerViewLocationKey);
-          const routeToDisplay = vue.computed(() => props.route || injectedRoute.value);
-          const injectedDepth = vue.inject(viewDepthKey, 0);
-          // The depth changes based on empty components option, which allows passthrough routes e.g. routes with children
-          // that are used to reuse the `path` property
-          const depth = vue.computed(() => {
-              let initialDepth = vue.unref(injectedDepth);
-              const { matched } = routeToDisplay.value;
-              let matchedRoute;
-              while ((matchedRoute = matched[initialDepth]) &&
-                  !matchedRoute.components) {
-                  initialDepth++;
-              }
-              return initialDepth;
-          });
-          const matchedRouteRef = vue.computed(() => routeToDisplay.value.matched[depth.value]);
-          vue.provide(viewDepthKey, vue.computed(() => depth.value + 1));
-          vue.provide(matchedRouteKey, matchedRouteRef);
-          vue.provide(routerViewLocationKey, routeToDisplay);
-          const viewRef = vue.ref();
-          // watch at the same time the component instance, the route record we are
-          // rendering, and the name
-          vue.watch(() => [viewRef.value, matchedRouteRef.value, props.name], ([instance, to, name], [oldInstance, from, oldName]) => {
-              // copy reused instances
-              if (to) {
-                  // this will update the instance for new instances as well as reused
-                  // instances when navigating to a new route
-                  to.instances[name] = instance;
-                  // the component instance is reused for a different route or name, so
-                  // we copy any saved update or leave guards. With async setup, the
-                  // mounting component will mount before the matchedRoute changes,
-                  // making instance === oldInstance, so we check if guards have been
-                  // added before. This works because we remove guards when
-                  // unmounting/deactivating components
-                  if (from && from !== to && instance && instance === oldInstance) {
-                      if (!to.leaveGuards.size) {
-                          to.leaveGuards = from.leaveGuards;
-                      }
-                      if (!to.updateGuards.size) {
-                          to.updateGuards = from.updateGuards;
-                      }
-                  }
-              }
-              // trigger beforeRouteEnter next callbacks
-              if (instance &&
-                  to &&
-                  // if there is no instance but to and from are the same this might be
-                  // the first visit
-                  (!from || !isSameRouteRecord(to, from) || !oldInstance)) {
-                  (to.enterCallbacks[name] || []).forEach(callback => callback(instance));
-              }
-          }, { flush: 'post' });
-          return () => {
-              const route = routeToDisplay.value;
-              // we need the value at the time we render because when we unmount, we
-              // navigated to a different location so the value is different
-              const currentName = props.name;
-              const matchedRoute = matchedRouteRef.value;
-              const ViewComponent = matchedRoute && matchedRoute.components[currentName];
-              if (!ViewComponent) {
-                  return normalizeSlot(slots.default, { Component: ViewComponent, route });
-              }
-              // props from route configuration
-              const routePropsOption = matchedRoute.props[currentName];
-              const routeProps = routePropsOption
-                  ? routePropsOption === true
-                      ? route.params
-                      : typeof routePropsOption === 'function'
-                          ? routePropsOption(route)
-                          : routePropsOption
-                  : null;
-              const onVnodeUnmounted = vnode => {
-                  // remove the instance reference to prevent leak
-                  if (vnode.component.isUnmounted) {
-                      matchedRoute.instances[currentName] = null;
-                  }
-              };
-              const component = vue.h(ViewComponent, assign({}, routeProps, attrs, {
-                  onVnodeUnmounted,
-                  ref: viewRef,
-              }));
-              if (isBrowser &&
-                  component.ref) {
-                  // TODO: can display if it's an alias, its props
-                  const info = {
-                      depth: depth.value,
-                      name: matchedRoute.name,
-                      path: matchedRoute.path,
-                      meta: matchedRoute.meta,
-                  };
-                  const internalInstances = isArray(component.ref)
-                      ? component.ref.map(r => r.i)
-                      : [component.ref.i];
-                  internalInstances.forEach(instance => {
-                      // @ts-expect-error
-                      instance.__vrv_devtools = info;
-                  });
-              }
-              return (
-              // pass the vnode to the slot as a prop.
-              // h and <component :is="..."> both accept vnodes
-              normalizeSlot(slots.default, { Component: component, route }) ||
-                  component);
-          };
-      },
-  });
-  function normalizeSlot(slot, data) {
-      if (!slot)
-          return null;
-      const slotContent = slot(data);
-      return slotContent.length === 1 ? slotContent[0] : slotContent;
-  }
-  // export the public type for h/tsx inference
-  // also to avoid inline import() in generated d.ts files
-  /**
-   * Component to display the current route the user is at.
-   */
-  const RouterView = RouterViewImpl;
-  // warn against deprecated usage with <transition> & <keep-alive>
-  // due to functional component being no longer eager in Vue 3
-  function warnDeprecatedUsage() {
-      const instance = vue.getCurrentInstance();
-      const parentName = instance.parent && instance.parent.type.name;
-      const parentSubTreeType = instance.parent && instance.parent.subTree && instance.parent.subTree.type;
-      if (parentName &&
-          (parentName === 'KeepAlive' || parentName.includes('Transition')) &&
-          typeof parentSubTreeType === 'object' &&
-          parentSubTreeType.name === 'RouterView') {
-          const comp = parentName === 'KeepAlive' ? 'keep-alive' : 'transition';
-          warn(`<router-view> can no longer be used directly inside <transition> or <keep-alive>.\n` +
-              `Use slot props instead:\n\n` +
-              `<router-view v-slot="{ Component }">\n` +
-              `  <${comp}>\n` +
-              `    <component :is="Component" />\n` +
-              `  </${comp}>\n` +
-              `</router-view>`);
-      }
-  }
-
-  function getDevtoolsGlobalHook() {
-      return getTarget().__VUE_DEVTOOLS_GLOBAL_HOOK__;
-  }
-  function getTarget() {
-      // @ts-ignore
-      return (typeof navigator !== 'undefined' && typeof window !== 'undefined')
-          ? window
-          : typeof global !== 'undefined'
-              ? global
-              : {};
-  }
-  const isProxyAvailable = typeof Proxy === 'function';
-
-  const HOOK_SETUP = 'devtools-plugin:setup';
-  const HOOK_PLUGIN_SETTINGS_SET = 'plugin:settings:set';
-
-  let supported;
-  let perf;
-  function isPerformanceSupported() {
-      var _a;
-      if (supported !== undefined) {
-          return supported;
-      }
-      if (typeof window !== 'undefined' && window.performance) {
-          supported = true;
-          perf = window.performance;
-      }
-      else if (typeof global !== 'undefined' && ((_a = global.perf_hooks) === null || _a === void 0 ? void 0 : _a.performance)) {
-          supported = true;
-          perf = global.perf_hooks.performance;
-      }
-      else {
-          supported = false;
-      }
-      return supported;
-  }
-  function now() {
-      return isPerformanceSupported() ? perf.now() : Date.now();
-  }
-
-  class ApiProxy {
-      constructor(plugin, hook) {
-          this.target = null;
-          this.targetQueue = [];
-          this.onQueue = [];
-          this.plugin = plugin;
-          this.hook = hook;
-          const defaultSettings = {};
-          if (plugin.settings) {
-              for (const id in plugin.settings) {
-                  const item = plugin.settings[id];
-                  defaultSettings[id] = item.defaultValue;
-              }
-          }
-          const localSettingsSaveId = `__vue-devtools-plugin-settings__${plugin.id}`;
-          let currentSettings = Object.assign({}, defaultSettings);
-          try {
-              const raw = localStorage.getItem(localSettingsSaveId);
-              const data = JSON.parse(raw);
-              Object.assign(currentSettings, data);
-          }
-          catch (e) {
-              // noop
-          }
-          this.fallbacks = {
-              getSettings() {
-                  return currentSettings;
-              },
-              setSettings(value) {
-                  try {
-                      localStorage.setItem(localSettingsSaveId, JSON.stringify(value));
-                  }
-                  catch (e) {
-                      // noop
-                  }
-                  currentSettings = value;
-              },
-              now() {
-                  return now();
-              },
-          };
-          if (hook) {
-              hook.on(HOOK_PLUGIN_SETTINGS_SET, (pluginId, value) => {
-                  if (pluginId === this.plugin.id) {
-                      this.fallbacks.setSettings(value);
-                  }
-              });
-          }
-          this.proxiedOn = new Proxy({}, {
-              get: (_target, prop) => {
-                  if (this.target) {
-                      return this.target.on[prop];
-                  }
-                  else {
-                      return (...args) => {
-                          this.onQueue.push({
-                              method: prop,
-                              args,
-                          });
-                      };
-                  }
-              },
-          });
-          this.proxiedTarget = new Proxy({}, {
-              get: (_target, prop) => {
-                  if (this.target) {
-                      return this.target[prop];
-                  }
-                  else if (prop === 'on') {
-                      return this.proxiedOn;
-                  }
-                  else if (Object.keys(this.fallbacks).includes(prop)) {
-                      return (...args) => {
-                          this.targetQueue.push({
-                              method: prop,
-                              args,
-                              resolve: () => { },
-                          });
-                          return this.fallbacks[prop](...args);
-                      };
-                  }
-                  else {
-                      return (...args) => {
-                          return new Promise(resolve => {
-                              this.targetQueue.push({
-                                  method: prop,
-                                  args,
-                                  resolve,
-                              });
-                          });
-                      };
-                  }
-              },
-          });
-      }
-      async setRealTarget(target) {
-          this.target = target;
-          for (const item of this.onQueue) {
-              this.target.on[item.method](...item.args);
-          }
-          for (const item of this.targetQueue) {
-              item.resolve(await this.target[item.method](...item.args));
-          }
-      }
-  }
-
-  function setupDevtoolsPlugin(pluginDescriptor, setupFn) {
-      const descriptor = pluginDescriptor;
-      const target = getTarget();
-      const hook = getDevtoolsGlobalHook();
-      const enableProxy = isProxyAvailable && descriptor.enableEarlyProxy;
-      if (hook && (target.__VUE_DEVTOOLS_PLUGIN_API_AVAILABLE__ || !enableProxy)) {
-          hook.emit(HOOK_SETUP, pluginDescriptor, setupFn);
-      }
-      else {
-          const proxy = enableProxy ? new ApiProxy(descriptor, hook) : null;
-          const list = target.__VUE_DEVTOOLS_PLUGINS__ = target.__VUE_DEVTOOLS_PLUGINS__ || [];
-          list.push({
-              pluginDescriptor: descriptor,
-              setupFn,
-              proxy,
-          });
-          if (proxy)
-              setupFn(proxy.proxiedTarget);
-      }
-  }
-
-  /**
-   * Copies a route location and removes any problematic properties that cannot be shown in devtools (e.g. Vue instances).
-   *
-   * @param routeLocation - routeLocation to format
-   * @param tooltip - optional tooltip
-   * @returns a copy of the routeLocation
-   */
-  function formatRouteLocation(routeLocation, tooltip) {
-      const copy = assign({}, routeLocation, {
-          // remove variables that can contain vue instances
-          matched: routeLocation.matched.map(matched => omit(matched, ['instances', 'children', 'aliasOf'])),
-      });
-      return {
-          _custom: {
-              type: null,
-              readOnly: true,
-              display: routeLocation.fullPath,
-              tooltip,
-              value: copy,
-          },
-      };
-  }
-  function formatDisplay(display) {
-      return {
-          _custom: {
-              display,
-          },
-      };
-  }
-  // to support multiple router instances
-  let routerId = 0;
-  function addDevtools(app, router, matcher) {
-      // Take over router.beforeEach and afterEach
-      // make sure we are not registering the devtool twice
-      if (router.__hasDevtools)
-          return;
-      router.__hasDevtools = true;
-      // increment to support multiple router instances
-      const id = routerId++;
-      setupDevtoolsPlugin({
-          id: 'org.vuejs.router' + (id ? '.' + id : ''),
-          label: 'Vue Router',
-          packageName: 'vue-router',
-          homepage: 'https://router.vuejs.org',
-          logo: 'https://router.vuejs.org/logo.png',
-          componentStateTypes: ['Routing'],
-          app,
-      }, api => {
-          if (typeof api.now !== 'function') {
-              console.warn('[Vue Router]: You seem to be using an outdated version of Vue Devtools. Are you still using the Beta release instead of the stable one? You can find the links at https://devtools.vuejs.org/guide/installation.html.');
-          }
-          // display state added by the router
-          api.on.inspectComponent((payload, ctx) => {
-              if (payload.instanceData) {
-                  payload.instanceData.state.push({
-                      type: 'Routing',
-                      key: '$route',
-                      editable: false,
-                      value: formatRouteLocation(router.currentRoute.value, 'Current Route'),
-                  });
-              }
-          });
-          // mark router-link as active and display tags on router views
-          api.on.visitComponentTree(({ treeNode: node, componentInstance }) => {
-              if (componentInstance.__vrv_devtools) {
-                  const info = componentInstance.__vrv_devtools;
-                  node.tags.push({
-                      label: (info.name ? `${info.name.toString()}: ` : '') + info.path,
-                      textColor: 0,
-                      tooltip: 'This component is rendered by &lt;router-view&gt;',
-                      backgroundColor: PINK_500,
-                  });
-              }
-              // if multiple useLink are used
-              if (isArray(componentInstance.__vrl_devtools)) {
-                  componentInstance.__devtoolsApi = api;
-                  componentInstance.__vrl_devtools.forEach(devtoolsData => {
-                      let label = devtoolsData.route.path;
-                      let backgroundColor = ORANGE_400;
-                      let tooltip = '';
-                      let textColor = 0;
-                      if (devtoolsData.error) {
-                          label = devtoolsData.error;
-                          backgroundColor = RED_100;
-                          textColor = RED_700;
-                      }
-                      else if (devtoolsData.isExactActive) {
-                          backgroundColor = LIME_500;
-                          tooltip = 'This is exactly active';
-                      }
-                      else if (devtoolsData.isActive) {
-                          backgroundColor = BLUE_600;
-                          tooltip = 'This link is active';
-                      }
-                      node.tags.push({
-                          label,
-                          textColor,
-                          tooltip,
-                          backgroundColor,
-                      });
-                  });
-              }
-          });
-          vue.watch(router.currentRoute, () => {
-              // refresh active state
-              refreshRoutesView();
-              api.notifyComponentUpdate();
-              api.sendInspectorTree(routerInspectorId);
-              api.sendInspectorState(routerInspectorId);
-          });
-          const navigationsLayerId = 'router:navigations:' + id;
-          api.addTimelineLayer({
-              id: navigationsLayerId,
-              label: `Router${id ? ' ' + id : ''} Navigations`,
-              color: 0x40a8c4,
-          });
-          // const errorsLayerId = 'router:errors'
-          // api.addTimelineLayer({
-          //   id: errorsLayerId,
-          //   label: 'Router Errors',
-          //   color: 0xea5455,
-          // })
-          router.onError((error, to) => {
-              api.addTimelineEvent({
-                  layerId: navigationsLayerId,
-                  event: {
-                      title: 'Error during Navigation',
-                      subtitle: to.fullPath,
-                      logType: 'error',
-                      time: api.now(),
-                      data: { error },
-                      groupId: to.meta.__navigationId,
-                  },
-              });
-          });
-          // attached to `meta` and used to group events
-          let navigationId = 0;
-          router.beforeEach((to, from) => {
-              const data = {
-                  guard: formatDisplay('beforeEach'),
-                  from: formatRouteLocation(from, 'Current Location during this navigation'),
-                  to: formatRouteLocation(to, 'Target location'),
-              };
-              // Used to group navigations together, hide from devtools
-              Object.defineProperty(to.meta, '__navigationId', {
-                  value: navigationId++,
-              });
-              api.addTimelineEvent({
-                  layerId: navigationsLayerId,
-                  event: {
-                      time: api.now(),
-                      title: 'Start of navigation',
-                      subtitle: to.fullPath,
-                      data,
-                      groupId: to.meta.__navigationId,
-                  },
-              });
-          });
-          router.afterEach((to, from, failure) => {
-              const data = {
-                  guard: formatDisplay('afterEach'),
-              };
-              if (failure) {
-                  data.failure = {
-                      _custom: {
-                          type: Error,
-                          readOnly: true,
-                          display: failure ? failure.message : '',
-                          tooltip: 'Navigation Failure',
-                          value: failure,
-                      },
-                  };
-                  data.status = formatDisplay('❌');
-              }
-              else {
-                  data.status = formatDisplay('✅');
-              }
-              // we set here to have the right order
-              data.from = formatRouteLocation(from, 'Current Location during this navigation');
-              data.to = formatRouteLocation(to, 'Target location');
-              api.addTimelineEvent({
-                  layerId: navigationsLayerId,
-                  event: {
-                      title: 'End of navigation',
-                      subtitle: to.fullPath,
-                      time: api.now(),
-                      data,
-                      logType: failure ? 'warning' : 'default',
-                      groupId: to.meta.__navigationId,
-                  },
-              });
-          });
-          /**
-           * Inspector of Existing routes
-           */
-          const routerInspectorId = 'router-inspector:' + id;
-          api.addInspector({
-              id: routerInspectorId,
-              label: 'Routes' + (id ? ' ' + id : ''),
-              icon: 'book',
-              treeFilterPlaceholder: 'Search routes',
-          });
-          function refreshRoutesView() {
-              // the routes view isn't active
-              if (!activeRoutesPayload)
-                  return;
-              const payload = activeRoutesPayload;
-              // children routes will appear as nested
-              let routes = matcher.getRoutes().filter(route => !route.parent ||
-                  // these routes have a parent with no component which will not appear in the view
-                  // therefore we still need to include them
-                  !route.parent.record.components);
-              // reset match state to false
-              routes.forEach(resetMatchStateOnRouteRecord);
-              // apply a match state if there is a payload
-              if (payload.filter) {
-                  routes = routes.filter(route => 
-                  // save matches state based on the payload
-                  isRouteMatching(route, payload.filter.toLowerCase()));
-              }
-              // mark active routes
-              routes.forEach(route => markRouteRecordActive(route, router.currentRoute.value));
-              payload.rootNodes = routes.map(formatRouteRecordForInspector);
-          }
-          let activeRoutesPayload;
-          api.on.getInspectorTree(payload => {
-              activeRoutesPayload = payload;
-              if (payload.app === app && payload.inspectorId === routerInspectorId) {
-                  refreshRoutesView();
-              }
-          });
-          /**
-           * Display information about the currently selected route record
-           */
-          api.on.getInspectorState(payload => {
-              if (payload.app === app && payload.inspectorId === routerInspectorId) {
-                  const routes = matcher.getRoutes();
-                  const route = routes.find(route => route.record.__vd_id === payload.nodeId);
-                  if (route) {
-                      payload.state = {
-                          options: formatRouteRecordMatcherForStateInspector(route),
-                      };
-                  }
-              }
-          });
-          api.sendInspectorTree(routerInspectorId);
-          api.sendInspectorState(routerInspectorId);
-      });
-  }
-  function modifierForKey(key) {
-      if (key.optional) {
-          return key.repeatable ? '*' : '?';
-      }
-      else {
-          return key.repeatable ? '+' : '';
-      }
-  }
-  function formatRouteRecordMatcherForStateInspector(route) {
-      const { record } = route;
-      const fields = [
-          { editable: false, key: 'path', value: record.path },
-      ];
-      if (record.name != null) {
-          fields.push({
-              editable: false,
-              key: 'name',
-              value: record.name,
-          });
-      }
-      fields.push({ editable: false, key: 'regexp', value: route.re });
-      if (route.keys.length) {
-          fields.push({
-              editable: false,
-              key: 'keys',
-              value: {
-                  _custom: {
-                      type: null,
-                      readOnly: true,
-                      display: route.keys
-                          .map(key => `${key.name}${modifierForKey(key)}`)
-                          .join(' '),
-                      tooltip: 'Param keys',
-                      value: route.keys,
-                  },
-              },
-          });
-      }
-      if (record.redirect != null) {
-          fields.push({
-              editable: false,
-              key: 'redirect',
-              value: record.redirect,
-          });
-      }
-      if (route.alias.length) {
-          fields.push({
-              editable: false,
-              key: 'aliases',
-              value: route.alias.map(alias => alias.record.path),
-          });
-      }
-      if (Object.keys(route.record.meta).length) {
-          fields.push({
-              editable: false,
-              key: 'meta',
-              value: route.record.meta,
-          });
-      }
-      fields.push({
-          key: 'score',
-          editable: false,
-          value: {
-              _custom: {
-                  type: null,
-                  readOnly: true,
-                  display: route.score.map(score => score.join(', ')).join(' | '),
-                  tooltip: 'Score used to sort routes',
-                  value: route.score,
-              },
-          },
-      });
-      return fields;
-  }
-  /**
-   * Extracted from tailwind palette
-   */
-  const PINK_500 = 0xec4899;
-  const BLUE_600 = 0x2563eb;
-  const LIME_500 = 0x84cc16;
-  const CYAN_400 = 0x22d3ee;
-  const ORANGE_400 = 0xfb923c;
-  // const GRAY_100 = 0xf4f4f5
-  const DARK = 0x666666;
-  const RED_100 = 0xfee2e2;
-  const RED_700 = 0xb91c1c;
-  function formatRouteRecordForInspector(route) {
-      const tags = [];
-      const { record } = route;
-      if (record.name != null) {
-          tags.push({
-              label: String(record.name),
-              textColor: 0,
-              backgroundColor: CYAN_400,
-          });
-      }
-      if (record.aliasOf) {
-          tags.push({
-              label: 'alias',
-              textColor: 0,
-              backgroundColor: ORANGE_400,
-          });
-      }
-      if (route.__vd_match) {
-          tags.push({
-              label: 'matches',
-              textColor: 0,
-              backgroundColor: PINK_500,
-          });
-      }
-      if (route.__vd_exactActive) {
-          tags.push({
-              label: 'exact',
-              textColor: 0,
-              backgroundColor: LIME_500,
-          });
-      }
-      if (route.__vd_active) {
-          tags.push({
-              label: 'active',
-              textColor: 0,
-              backgroundColor: BLUE_600,
-          });
-      }
-      if (record.redirect) {
-          tags.push({
-              label: typeof record.redirect === 'string'
-                  ? `redirect: ${record.redirect}`
-                  : 'redirects',
-              textColor: 0xffffff,
-              backgroundColor: DARK,
-          });
-      }
-      // add an id to be able to select it. Using the `path` is not possible because
-      // empty path children would collide with their parents
-      let id = record.__vd_id;
-      if (id == null) {
-          id = String(routeRecordId++);
-          record.__vd_id = id;
-      }
-      return {
-          id,
-          label: record.path,
-          tags,
-          children: route.children.map(formatRouteRecordForInspector),
-      };
-  }
-  //  incremental id for route records and inspector state
-  let routeRecordId = 0;
-  const EXTRACT_REGEXP_RE = /^\/(.*)\/([a-z]*)$/;
-  function markRouteRecordActive(route, currentRoute) {
-      // no route will be active if matched is empty
-      // reset the matching state
-      const isExactActive = currentRoute.matched.length &&
-          isSameRouteRecord(currentRoute.matched[currentRoute.matched.length - 1], route.record);
-      route.__vd_exactActive = route.__vd_active = isExactActive;
-      if (!isExactActive) {
-          route.__vd_active = currentRoute.matched.some(match => isSameRouteRecord(match, route.record));
-      }
-      route.children.forEach(childRoute => markRouteRecordActive(childRoute, currentRoute));
-  }
-  function resetMatchStateOnRouteRecord(route) {
-      route.__vd_match = false;
-      route.children.forEach(resetMatchStateOnRouteRecord);
-  }
-  function isRouteMatching(route, filter) {
-      const found = String(route.re).match(EXTRACT_REGEXP_RE);
-      route.__vd_match = false;
-      if (!found || found.length < 3) {
-          return false;
-      }
-      // use a regexp without $ at the end to match nested routes better
-      const nonEndingRE = new RegExp(found[1].replace(/\$$/, ''), found[2]);
-      if (nonEndingRE.test(filter)) {
-          // mark children as matches
-          route.children.forEach(child => isRouteMatching(child, filter));
-          // exception case: `/`
-          if (route.record.path !== '/' || filter === '/') {
-              route.__vd_match = route.re.test(filter);
-              return true;
-          }
-          // hide the / route
-          return false;
-      }
-      const path = route.record.path.toLowerCase();
-      const decodedPath = decode(path);
-      // also allow partial matching on the path
-      if (!filter.startsWith('/') &&
-          (decodedPath.includes(filter) || path.includes(filter)))
-          return true;
-      if (decodedPath.startsWith(filter) || path.startsWith(filter))
-          return true;
-      if (route.record.name && String(route.record.name).includes(filter))
-          return true;
-      return route.children.some(child => isRouteMatching(child, filter));
-  }
-  function omit(obj, keys) {
-      const ret = {};
-      for (const key in obj) {
-          if (!keys.includes(key)) {
-              // @ts-expect-error
-              ret[key] = obj[key];
-          }
-      }
-      return ret;
-  }
-
-  /**
-   * Creates a Router instance that can be used by a Vue app.
-   *
-   * @param options - {@link RouterOptions}
-   */
-  function createRouter(options) {
-      const matcher = createRouterMatcher(options.routes, options);
-      const parseQuery$1 = options.parseQuery || parseQuery;
-      const stringifyQuery$1 = options.stringifyQuery || stringifyQuery;
-      const routerHistory = options.history;
-      if (!routerHistory)
-          throw new Error('Provide the "history" option when calling "createRouter()":' +
-              ' https://next.router.vuejs.org/api/#history.');
-      const beforeGuards = useCallbacks();
-      const beforeResolveGuards = useCallbacks();
-      const afterGuards = useCallbacks();
-      const currentRoute = vue.shallowRef(START_LOCATION_NORMALIZED);
-      let pendingLocation = START_LOCATION_NORMALIZED;
-      // leave the scrollRestoration if no scrollBehavior is provided
-      if (isBrowser && options.scrollBehavior && 'scrollRestoration' in history) {
-          history.scrollRestoration = 'manual';
-      }
-      const normalizeParams = applyToParams.bind(null, paramValue => '' + paramValue);
-      const encodeParams = applyToParams.bind(null, encodeParam);
-      const decodeParams = 
-      // @ts-expect-error: intentionally avoid the type check
-      applyToParams.bind(null, decode);
-      function addRoute(parentOrRoute, route) {
-          let parent;
-          let record;
-          if (isRouteName(parentOrRoute)) {
-              parent = matcher.getRecordMatcher(parentOrRoute);
-              if (!parent) {
-                  warn(`Parent route "${String(parentOrRoute)}" not found when adding child route`, route);
-              }
-              record = route;
-          }
-          else {
-              record = parentOrRoute;
-          }
-          return matcher.addRoute(record, parent);
-      }
-      function removeRoute(name) {
-          const recordMatcher = matcher.getRecordMatcher(name);
-          if (recordMatcher) {
-              matcher.removeRoute(recordMatcher);
-          }
-          else {
-              warn(`Cannot remove non-existent route "${String(name)}"`);
-          }
-      }
-      function getRoutes() {
-          return matcher.getRoutes().map(routeMatcher => routeMatcher.record);
-      }
-      function hasRoute(name) {
-          return !!matcher.getRecordMatcher(name);
-      }
-      function resolve(rawLocation, currentLocation) {
-          // const objectLocation = routerLocationAsObject(rawLocation)
-          // we create a copy to modify it later
-          currentLocation = assign({}, currentLocation || currentRoute.value);
-          if (typeof rawLocation === 'string') {
-              const locationNormalized = parseURL(parseQuery$1, rawLocation, currentLocation.path);
-              const matchedRoute = matcher.resolve({ path: locationNormalized.path }, currentLocation);
-              const href = routerHistory.createHref(locationNormalized.fullPath);
-              {
-                  if (href.startsWith('//'))
-                      warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`);
-                  else if (!matchedRoute.matched.length) {
-                      warn(`No match found for location with path "${rawLocation}"`);
-                  }
-              }
-              // locationNormalized is always a new object
-              return assign(locationNormalized, matchedRoute, {
-                  params: decodeParams(matchedRoute.params),
-                  hash: decode(locationNormalized.hash),
-                  redirectedFrom: undefined,
-                  href,
-              });
-          }
-          if (!isRouteLocation(rawLocation)) {
-              warn(`router.resolve() was passed an invalid location. This will fail in production.\n- Location:`, rawLocation);
-              rawLocation = {};
-          }
-          let matcherLocation;
-          // path could be relative in object as well
-          if (rawLocation.path != null) {
-              if ('params' in rawLocation &&
-                  !('name' in rawLocation) &&
-                  // @ts-expect-error: the type is never
-                  Object.keys(rawLocation.params).length) {
-                  warn(`Path "${rawLocation.path}" was passed with params but they will be ignored. Use a named route alongside params instead.`);
-              }
-              matcherLocation = assign({}, rawLocation, {
-                  path: parseURL(parseQuery$1, rawLocation.path, currentLocation.path).path,
-              });
-          }
-          else {
-              // remove any nullish param
-              const targetParams = assign({}, rawLocation.params);
-              for (const key in targetParams) {
-                  if (targetParams[key] == null) {
-                      delete targetParams[key];
-                  }
-              }
-              // pass encoded values to the matcher, so it can produce encoded path and fullPath
-              matcherLocation = assign({}, rawLocation, {
-                  params: encodeParams(targetParams),
-              });
-              // current location params are decoded, we need to encode them in case the
-              // matcher merges the params
-              currentLocation.params = encodeParams(currentLocation.params);
-          }
-          const matchedRoute = matcher.resolve(matcherLocation, currentLocation);
-          const hash = rawLocation.hash || '';
-          if (hash && !hash.startsWith('#')) {
-              warn(`A \`hash\` should always start with the character "#". Replace "${hash}" with "#${hash}".`);
-          }
-          // the matcher might have merged current location params, so
-          // we need to run the decoding again
-          matchedRoute.params = normalizeParams(decodeParams(matchedRoute.params));
-          const fullPath = stringifyURL(stringifyQuery$1, assign({}, rawLocation, {
-              hash: encodeHash(hash),
-              path: matchedRoute.path,
-          }));
-          const href = routerHistory.createHref(fullPath);
-          {
-              if (href.startsWith('//')) {
-                  warn(`Location "${rawLocation}" resolved to "${href}". A resolved location cannot start with multiple slashes.`);
-              }
-              else if (!matchedRoute.matched.length) {
-                  warn(`No match found for location with path "${rawLocation.path != null ? rawLocation.path : rawLocation}"`);
-              }
-          }
-          return assign({
-              fullPath,
-              // keep the hash encoded so fullPath is effectively path + encodedQuery +
-              // hash
-              hash,
-              query: 
-              // if the user is using a custom query lib like qs, we might have
-              // nested objects, so we keep the query as is, meaning it can contain
-              // numbers at `$route.query`, but at the point, the user will have to
-              // use their own type anyway.
-              // https://github.com/vuejs/router/issues/328#issuecomment-649481567
-              stringifyQuery$1 === stringifyQuery
-                  ? normalizeQuery(rawLocation.query)
-                  : (rawLocation.query || {}),
-          }, matchedRoute, {
-              redirectedFrom: undefined,
-              href,
-          });
-      }
-      function locationAsObject(to) {
-          return typeof to === 'string'
-              ? parseURL(parseQuery$1, to, currentRoute.value.path)
-              : assign({}, to);
-      }
-      function checkCanceledNavigation(to, from) {
-          if (pendingLocation !== to) {
-              return createRouterError(8 /* ErrorTypes.NAVIGATION_CANCELLED */, {
-                  from,
-                  to,
-              });
-          }
-      }
-      function push(to) {
-          return pushWithRedirect(to);
-      }
-      function replace(to) {
-          return push(assign(locationAsObject(to), { replace: true }));
-      }
-      function handleRedirectRecord(to) {
-          const lastMatched = to.matched[to.matched.length - 1];
-          if (lastMatched && lastMatched.redirect) {
-              const { redirect } = lastMatched;
-              let newTargetLocation = typeof redirect === 'function' ? redirect(to) : redirect;
-              if (typeof newTargetLocation === 'string') {
-                  newTargetLocation =
-                      newTargetLocation.includes('?') || newTargetLocation.includes('#')
-                          ? (newTargetLocation = locationAsObject(newTargetLocation))
-                          : // force empty params
-                              { path: newTargetLocation };
-                  // @ts-expect-error: force empty params when a string is passed to let
-                  // the router parse them again
-                  newTargetLocation.params = {};
-              }
-              if (newTargetLocation.path == null &&
-                  !('name' in newTargetLocation)) {
-                  warn(`Invalid redirect found:\n${JSON.stringify(newTargetLocation, null, 2)}\n when navigating to "${to.fullPath}". A redirect must contain a name or path. This will break in production.`);
-                  throw new Error('Invalid redirect');
-              }
-              return assign({
-                  query: to.query,
-                  hash: to.hash,
-                  // avoid transferring params if the redirect has a path
-                  params: newTargetLocation.path != null ? {} : to.params,
-              }, newTargetLocation);
-          }
-      }
-      function pushWithRedirect(to, redirectedFrom) {
-          const targetLocation = (pendingLocation = resolve(to));
-          const from = currentRoute.value;
-          const data = to.state;
-          const force = to.force;
-          // to could be a string where `replace` is a function
-          const replace = to.replace === true;
-          const shouldRedirect = handleRedirectRecord(targetLocation);
-          if (shouldRedirect)
-              return pushWithRedirect(assign(locationAsObject(shouldRedirect), {
-                  state: typeof shouldRedirect === 'object'
-                      ? assign({}, data, shouldRedirect.state)
-                      : data,
-                  force,
-                  replace,
-              }), 
-              // keep original redirectedFrom if it exists
-              redirectedFrom || targetLocation);
-          // if it was a redirect we already called `pushWithRedirect` above
-          const toLocation = targetLocation;
-          toLocation.redirectedFrom = redirectedFrom;
-          let failure;
-          if (!force && isSameRouteLocation(stringifyQuery$1, from, targetLocation)) {
-              failure = createRouterError(16 /* ErrorTypes.NAVIGATION_DUPLICATED */, { to: toLocation, from });
-              // trigger scroll to allow scrolling to the same anchor
-              handleScroll(from, from, 
-              // this is a push, the only way for it to be triggered from a
-              // history.listen is with a redirect, which makes it become a push
-              true, 
-              // This cannot be the first navigation because the initial location
-              // cannot be manually navigated to
-              false);
-          }
-          return (failure ? Promise.resolve(failure) : navigate(toLocation, from))
-              .catch((error) => isNavigationFailure(error)
-              ? // navigation redirects still mark the router as ready
-                  isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)
-                      ? error
-                      : markAsReady(error) // also returns the error
-              : // reject any unknown error
-                  triggerError(error, toLocation, from))
-              .then((failure) => {
-              if (failure) {
-                  if (isNavigationFailure(failure, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {
-                      if (// we are redirecting to the same location we were already at
-                          isSameRouteLocation(stringifyQuery$1, resolve(failure.to), toLocation) &&
-                          // and we have done it a couple of times
-                          redirectedFrom &&
-                          // @ts-expect-error: added only in dev
-                          (redirectedFrom._count = redirectedFrom._count
-                              ? // @ts-expect-error
-                                  redirectedFrom._count + 1
-                              : 1) > 30) {
-                          warn(`Detected a possibly infinite redirection in a navigation guard when going from "${from.fullPath}" to "${toLocation.fullPath}". Aborting to avoid a Stack Overflow.\n Are you always returning a new location within a navigation guard? That would lead to this error. Only return when redirecting or aborting, that should fix this. This might break in production if not fixed.`);
-                          return Promise.reject(new Error('Infinite redirect in navigation guard'));
-                      }
-                      return pushWithRedirect(
-                      // keep options
-                      assign({
-                          // preserve an existing replacement but allow the redirect to override it
-                          replace,
-                      }, locationAsObject(failure.to), {
-                          state: typeof failure.to === 'object'
-                              ? assign({}, data, failure.to.state)
-                              : data,
-                          force,
-                      }), 
-                      // preserve the original redirectedFrom if any
-                      redirectedFrom || toLocation);
-                  }
-              }
-              else {
-                  // if we fail we don't finalize the navigation
-                  failure = finalizeNavigation(toLocation, from, true, replace, data);
-              }
-              triggerAfterEach(toLocation, from, failure);
-              return failure;
-          });
-      }
-      /**
-       * Helper to reject and skip all navigation guards if a new navigation happened
-       * @param to
-       * @param from
-       */
-      function checkCanceledNavigationAndReject(to, from) {
-          const error = checkCanceledNavigation(to, from);
-          return error ? Promise.reject(error) : Promise.resolve();
-      }
-      function runWithContext(fn) {
-          const app = installedApps.values().next().value;
-          // support Vue < 3.3
-          return app && typeof app.runWithContext === 'function'
-              ? app.runWithContext(fn)
-              : fn();
-      }
-      // TODO: refactor the whole before guards by internally using router.beforeEach
-      function navigate(to, from) {
-          let guards;
-          const [leavingRecords, updatingRecords, enteringRecords] = extractChangingRecords(to, from);
-          // all components here have been resolved once because we are leaving
-          guards = extractComponentsGuards(leavingRecords.reverse(), 'beforeRouteLeave', to, from);
-          // leavingRecords is already reversed
-          for (const record of leavingRecords) {
-              record.leaveGuards.forEach(guard => {
-                  guards.push(guardToPromiseFn(guard, to, from));
-              });
-          }
-          const canceledNavigationCheck = checkCanceledNavigationAndReject.bind(null, to, from);
-          guards.push(canceledNavigationCheck);
-          // run the queue of per route beforeRouteLeave guards
-          return (runGuardQueue(guards)
-              .then(() => {
-              // check global guards beforeEach
-              guards = [];
-              for (const guard of beforeGuards.list()) {
-                  guards.push(guardToPromiseFn(guard, to, from));
-              }
-              guards.push(canceledNavigationCheck);
-              return runGuardQueue(guards);
-          })
-              .then(() => {
-              // check in components beforeRouteUpdate
-              guards = extractComponentsGuards(updatingRecords, 'beforeRouteUpdate', to, from);
-              for (const record of updatingRecords) {
-                  record.updateGuards.forEach(guard => {
-                      guards.push(guardToPromiseFn(guard, to, from));
-                  });
-              }
-              guards.push(canceledNavigationCheck);
-              // run the queue of per route beforeEnter guards
-              return runGuardQueue(guards);
-          })
-              .then(() => {
-              // check the route beforeEnter
-              guards = [];
-              for (const record of enteringRecords) {
-                  // do not trigger beforeEnter on reused views
-                  if (record.beforeEnter) {
-                      if (isArray(record.beforeEnter)) {
-                          for (const beforeEnter of record.beforeEnter)
-                              guards.push(guardToPromiseFn(beforeEnter, to, from));
-                      }
-                      else {
-                          guards.push(guardToPromiseFn(record.beforeEnter, to, from));
-                      }
-                  }
-              }
-              guards.push(canceledNavigationCheck);
-              // run the queue of per route beforeEnter guards
-              return runGuardQueue(guards);
-          })
-              .then(() => {
-              // NOTE: at this point to.matched is normalized and does not contain any () => Promise<Component>
-              // clear existing enterCallbacks, these are added by extractComponentsGuards
-              to.matched.forEach(record => (record.enterCallbacks = {}));
-              // check in-component beforeRouteEnter
-              guards = extractComponentsGuards(enteringRecords, 'beforeRouteEnter', to, from, runWithContext);
-              guards.push(canceledNavigationCheck);
-              // run the queue of per route beforeEnter guards
-              return runGuardQueue(guards);
-          })
-              .then(() => {
-              // check global guards beforeResolve
-              guards = [];
-              for (const guard of beforeResolveGuards.list()) {
-                  guards.push(guardToPromiseFn(guard, to, from));
-              }
-              guards.push(canceledNavigationCheck);
-              return runGuardQueue(guards);
-          })
-              // catch any navigation canceled
-              .catch(err => isNavigationFailure(err, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)
-              ? err
-              : Promise.reject(err)));
-      }
-      function triggerAfterEach(to, from, failure) {
-          // navigation is confirmed, call afterGuards
-          // TODO: wrap with error handlers
-          afterGuards
-              .list()
-              .forEach(guard => runWithContext(() => guard(to, from, failure)));
-      }
-      /**
-       * - Cleans up any navigation guards
-       * - Changes the url if necessary
-       * - Calls the scrollBehavior
-       */
-      function finalizeNavigation(toLocation, from, isPush, replace, data) {
-          // a more recent navigation took place
-          const error = checkCanceledNavigation(toLocation, from);
-          if (error)
-              return error;
-          // only consider as push if it's not the first navigation
-          const isFirstNavigation = from === START_LOCATION_NORMALIZED;
-          const state = !isBrowser ? {} : history.state;
-          // change URL only if the user did a push/replace and if it's not the initial navigation because
-          // it's just reflecting the url
-          if (isPush) {
-              // on the initial navigation, we want to reuse the scroll position from
-              // history state if it exists
-              if (replace || isFirstNavigation)
-                  routerHistory.replace(toLocation.fullPath, assign({
-                      scroll: isFirstNavigation && state && state.scroll,
-                  }, data));
-              else
-                  routerHistory.push(toLocation.fullPath, data);
-          }
-          // accept current navigation
-          currentRoute.value = toLocation;
-          handleScroll(toLocation, from, isPush, isFirstNavigation);
-          markAsReady();
-      }
-      let removeHistoryListener;
-      // attach listener to history to trigger navigations
-      function setupListeners() {
-          // avoid setting up listeners twice due to an invalid first navigation
-          if (removeHistoryListener)
-              return;
-          removeHistoryListener = routerHistory.listen((to, _from, info) => {
-              if (!router.listening)
-                  return;
-              // cannot be a redirect route because it was in history
-              const toLocation = resolve(to);
-              // due to dynamic routing, and to hash history with manual navigation
-              // (manually changing the url or calling history.hash = '#/somewhere'),
-              // there could be a redirect record in history
-              const shouldRedirect = handleRedirectRecord(toLocation);
-              if (shouldRedirect) {
-                  pushWithRedirect(assign(shouldRedirect, { replace: true }), toLocation).catch(noop);
-                  return;
-              }
-              pendingLocation = toLocation;
-              const from = currentRoute.value;
-              // TODO: should be moved to web history?
-              if (isBrowser) {
-                  saveScrollPosition(getScrollKey(from.fullPath, info.delta), computeScrollPosition());
-              }
-              navigate(toLocation, from)
-                  .catch((error) => {
-                  if (isNavigationFailure(error, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {
-                      return error;
-                  }
-                  if (isNavigationFailure(error, 2 /* ErrorTypes.NAVIGATION_GUARD_REDIRECT */)) {
-                      // Here we could call if (info.delta) routerHistory.go(-info.delta,
-                      // false) but this is bug prone as we have no way to wait the
-                      // navigation to be finished before calling pushWithRedirect. Using
-                      // a setTimeout of 16ms seems to work but there is no guarantee for
-                      // it to work on every browser. So instead we do not restore the
-                      // history entry and trigger a new navigation as requested by the
-                      // navigation guard.
-                      // the error is already handled by router.push we just want to avoid
-                      // logging the error
-                      pushWithRedirect(error.to, toLocation
-                      // avoid an uncaught rejection, let push call triggerError
-                      )
-                          .then(failure => {
-                          // manual change in hash history #916 ending up in the URL not
-                          // changing, but it was changed by the manual url change, so we
-                          // need to manually change it ourselves
-                          if (isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ |
-                              16 /* ErrorTypes.NAVIGATION_DUPLICATED */) &&
-                              !info.delta &&
-                              info.type === NavigationType.pop) {
-                              routerHistory.go(-1, false);
-                          }
-                      })
-                          .catch(noop);
-                      // avoid the then branch
-                      return Promise.reject();
-                  }
-                  // do not restore history on unknown direction
-                  if (info.delta) {
-                      routerHistory.go(-info.delta, false);
-                  }
-                  // unrecognized error, transfer to the global handler
-                  return triggerError(error, toLocation, from);
-              })
-                  .then((failure) => {
-                  failure =
-                      failure ||
-                          finalizeNavigation(
-                          // after navigation, all matched components are resolved
-                          toLocation, from, false);
-                  // revert the navigation
-                  if (failure) {
-                      if (info.delta &&
-                          // a new navigation has been triggered, so we do not want to revert, that will change the current history
-                          // entry while a different route is displayed
-                          !isNavigationFailure(failure, 8 /* ErrorTypes.NAVIGATION_CANCELLED */)) {
-                          routerHistory.go(-info.delta, false);
-                      }
-                      else if (info.type === NavigationType.pop &&
-                          isNavigationFailure(failure, 4 /* ErrorTypes.NAVIGATION_ABORTED */ | 16 /* ErrorTypes.NAVIGATION_DUPLICATED */)) {
-                          // manual change in hash history #916
-                          // it's like a push but lacks the information of the direction
-                          routerHistory.go(-1, false);
-                      }
-                  }
-                  triggerAfterEach(toLocation, from, failure);
-              })
-                  // avoid warnings in the console about uncaught rejections, they are logged by triggerErrors
-                  .catch(noop);
-          });
-      }
-      // Initialization and Errors
-      let readyHandlers = useCallbacks();
-      let errorListeners = useCallbacks();
-      let ready;
-      /**
-       * Trigger errorListeners added via onError and throws the error as well
-       *
-       * @param error - error to throw
-       * @param to - location we were navigating to when the error happened
-       * @param from - location we were navigating from when the error happened
-       * @returns the error as a rejected promise
-       */
-      function triggerError(error, to, from) {
-          markAsReady(error);
-          const list = errorListeners.list();
-          if (list.length) {
-              list.forEach(handler => handler(error, to, from));
-          }
-          else {
-              {
-                  warn('uncaught error during route navigation:');
-              }
-              console.error(error);
-          }
-          // reject the error no matter there were error listeners or not
-          return Promise.reject(error);
-      }
-      function isReady() {
-          if (ready && currentRoute.value !== START_LOCATION_NORMALIZED)
-              return Promise.resolve();
-          return new Promise((resolve, reject) => {
-              readyHandlers.add([resolve, reject]);
-          });
-      }
-      function markAsReady(err) {
-          if (!ready) {
-              // still not ready if an error happened
-              ready = !err;
-              setupListeners();
-              readyHandlers
-                  .list()
-                  .forEach(([resolve, reject]) => (err ? reject(err) : resolve()));
-              readyHandlers.reset();
-          }
-          return err;
-      }
-      // Scroll behavior
-      function handleScroll(to, from, isPush, isFirstNavigation) {
-          const { scrollBehavior } = options;
-          if (!isBrowser || !scrollBehavior)
-              return Promise.resolve();
-          const scrollPosition = (!isPush && getSavedScrollPosition(getScrollKey(to.fullPath, 0))) ||
-              ((isFirstNavigation || !isPush) &&
-                  history.state &&
-                  history.state.scroll) ||
-              null;
-          return vue.nextTick()
-              .then(() => scrollBehavior(to, from, scrollPosition))
-              .then(position => position && scrollToPosition(position))
-              .catch(err => triggerError(err, to, from));
-      }
-      const go = (delta) => routerHistory.go(delta);
-      let started;
-      const installedApps = new Set();
-      const router = {
-          currentRoute,
-          listening: true,
-          addRoute,
-          removeRoute,
-          hasRoute,
-          getRoutes,
-          resolve,
-          options,
-          push,
-          replace,
-          go,
-          back: () => go(-1),
-          forward: () => go(1),
-          beforeEach: beforeGuards.add,
-          beforeResolve: beforeResolveGuards.add,
-          afterEach: afterGuards.add,
-          onError: errorListeners.add,
-          isReady,
-          install(app) {
-              const router = this;
-              app.component('RouterLink', RouterLink);
-              app.component('RouterView', RouterView);
-              app.config.globalProperties.$router = router;
-              Object.defineProperty(app.config.globalProperties, '$route', {
-                  enumerable: true,
-                  get: () => vue.unref(currentRoute),
-              });
-              // this initial navigation is only necessary on client, on server it doesn't
-              // make sense because it will create an extra unnecessary navigation and could
-              // lead to problems
-              if (isBrowser &&
-                  // used for the initial navigation client side to avoid pushing
-                  // multiple times when the router is used in multiple apps
-                  !started &&
-                  currentRoute.value === START_LOCATION_NORMALIZED) {
-                  // see above
-                  started = true;
-                  push(routerHistory.location).catch(err => {
-                      warn('Unexpected error when starting the router:', err);
-                  });
-              }
-              const reactiveRoute = {};
-              for (const key in START_LOCATION_NORMALIZED) {
-                  Object.defineProperty(reactiveRoute, key, {
-                      get: () => currentRoute.value[key],
-                      enumerable: true,
-                  });
-              }
-              app.provide(routerKey, router);
-              app.provide(routeLocationKey, vue.shallowReactive(reactiveRoute));
-              app.provide(routerViewLocationKey, currentRoute);
-              const unmountApp = app.unmount;
-              installedApps.add(app);
-              app.unmount = function () {
-                  installedApps.delete(app);
-                  // the router is not attached to an app anymore
-                  if (installedApps.size < 1) {
-                      // invalidate the current navigation
-                      pendingLocation = START_LOCATION_NORMALIZED;
-                      removeHistoryListener && removeHistoryListener();
-                      removeHistoryListener = null;
-                      currentRoute.value = START_LOCATION_NORMALIZED;
-                      started = false;
-                      ready = false;
-                  }
-                  unmountApp();
-              };
-              // TODO: this probably needs to be updated so it can be used by vue-termui
-              if (isBrowser) {
-                  addDevtools(app, router, matcher);
-              }
-          },
-      };
-      // TODO: type this as NavigationGuardReturn or similar instead of any
-      function runGuardQueue(guards) {
-          return guards.reduce((promise, guard) => promise.then(() => runWithContext(guard)), Promise.resolve());
-      }
-      return router;
-  }
-  function extractChangingRecords(to, from) {
-      const leavingRecords = [];
-      const updatingRecords = [];
-      const enteringRecords = [];
-      const len = Math.max(from.matched.length, to.matched.length);
-      for (let i = 0; i < len; i++) {
-          const recordFrom = from.matched[i];
-          if (recordFrom) {
-              if (to.matched.find(record => isSameRouteRecord(record, recordFrom)))
-                  updatingRecords.push(recordFrom);
-              else
-                  leavingRecords.push(recordFrom);
-          }
-          const recordTo = to.matched[i];
-          if (recordTo) {
-              // the type doesn't matter because we are comparing per reference
-              if (!from.matched.find(record => isSameRouteRecord(record, recordTo))) {
-                  enteringRecords.push(recordTo);
-              }
-          }
-      }
-      return [leavingRecords, updatingRecords, enteringRecords];
-  }
-
-  /**
-   * Returns the router instance. Equivalent to using `$router` inside
-   * templates.
-   */
-  function useRouter() {
-      return vue.inject(routerKey);
-  }
-  /**
-   * Returns the current route location. Equivalent to using `$route` inside
-   * templates.
-   */
-  function useRoute() {
-      return vue.inject(routeLocationKey);
-  }
-
-  exports.RouterLink = RouterLink;
-  exports.RouterView = RouterView;
-  exports.START_LOCATION = START_LOCATION_NORMALIZED;
-  exports.createMemoryHistory = createMemoryHistory;
-  exports.createRouter = createRouter;
-  exports.createRouterMatcher = createRouterMatcher;
-  exports.createWebHashHistory = createWebHashHistory;
-  exports.createWebHistory = createWebHistory;
-  exports.isNavigationFailure = isNavigationFailure;
-  exports.loadRouteLocation = loadRouteLocation;
-  exports.matchedRouteKey = matchedRouteKey;
-  exports.onBeforeRouteLeave = onBeforeRouteLeave;
-  exports.onBeforeRouteUpdate = onBeforeRouteUpdate;
-  exports.parseQuery = parseQuery;
-  exports.routeLocationKey = routeLocationKey;
-  exports.routerKey = routerKey;
-  exports.routerViewLocationKey = routerViewLocationKey;
-  exports.stringifyQuery = stringifyQuery;
-  exports.useLink = useLink;
-  exports.useRoute = useRoute;
-  exports.useRouter = useRouter;
-  exports.viewDepthKey = viewDepthKey;
-
-  return exports;
-
-})({}, Vue);

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 268
js/vue/vue3.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
js/wdDrag.js


+ 315 - 1
page/login.html

@@ -166,6 +166,60 @@
           </div>
         </div>
       </div>
+
+      <!-- 修改初始密码弹窗 -->
+      <div v-if="resetPwdModal.show" class="reset-pwd-mask">
+        <div class="reset-pwd-modal">
+          <div class="reset-pwd-header">
+            <div class="reset-pwd-title">请修改初始密码</div>
+          </div>
+          <div class="reset-pwd-body">
+            <div class="pwd-strength-msg">
+              {{ resetPwdModal.pwdStrengthMsg }}
+            </div>
+            <div class="reset-pwd-form">
+              <div class="reset-pwd-input-item">
+                <input
+                  :type="showNewPwd ? 'text' : 'password'"
+                  v-model="resetPwdForm.newPwd"
+                  placeholder="请输入新密码"
+                  class="reset-pwd-input"
+                />
+                <div class="eye-icon" @click="showNewPwd = !showNewPwd">
+                  <Icon
+                    :name="showNewPwd ? 'icon-yanjing-kai' : 'icon-yanjing-bi'"
+                    size="28"
+                    color="#999"
+                  ></Icon>
+                </div>
+              </div>
+              <div class="reset-pwd-input-item">
+                <input
+                  :type="showConfirmPwd ? 'text' : 'password'"
+                  v-model="resetPwdForm.confirmPwd"
+                  placeholder="请确认新密码"
+                  class="reset-pwd-input"
+                />
+                <div class="eye-icon" @click="showConfirmPwd = !showConfirmPwd">
+                  <Icon
+                    :name="showConfirmPwd ? 'icon-yanjing-kai' : 'icon-yanjing-bi'"
+                    size="28"
+                    color="#999"
+                  ></Icon>
+                </div>
+              </div>
+            </div>
+            <button
+              class="reset-pwd-btn"
+              :class="{ 'disabled': resetPwdLoading }"
+              :disabled="resetPwdLoading"
+              @click="handleResetPwd"
+            >
+              {{ resetPwdLoading ? '保存中...' : '保存' }}
+            </button>
+          </div>
+        </div>
+      </div>
     </div>
 
     <script>
@@ -207,6 +261,21 @@
                 title: "",
                 content: "",
               },
+              // 修改初始密码弹窗状态
+              resetPwdModal: {
+                show: false,
+                yhid: "",
+                yhm: "",
+                pwdStrengthMsg: "",
+              },
+              // 修改密码表单
+              resetPwdForm: {
+                newPwd: "",
+                confirmPwd: "",
+              },
+              showNewPwd: false,
+              showConfirmPwd: false,
+              resetPwdLoading: false,
             };
           },
 
@@ -384,6 +453,17 @@
 
                 // 检查是否有错误信息
                 if (response && response.data && response.data.msg) {
+                  // 检测是否需要修改初始密码
+                  if (
+                    response.data.msg.includes("请修改初始密码") ||
+                    response.data.msg.includes("请修改密码")
+                  ) {
+                    this.hideLoadingMask();
+                    this.isLogging = false;
+                    // 显示修改密码弹窗
+                    this.openResetPwdModal(response.data);
+                    return;
+                  }
                   // 登录失败,显示错误信息
                   console.error("❌ 登录失败:", response.data.msg);
                   this.showToast(response.data.msg, "error");
@@ -517,6 +597,129 @@
             closeAgreementDrawer() {
               this.agreementDrawer.show = false;
             },
+
+            // 打开修改初始密码弹窗
+            openResetPwdModal(data) {
+              this.resetPwdModal = {
+                show: true,
+                yhid: data.yhid || "",
+                yhm: data.yhm || "",
+                pwdStrengthMsg:
+                  data.pwdStrengthMsg ||
+                  "密码不能包含账号,最小6个字符,最大16个字符",
+              };
+              // 清空表单
+              this.resetPwdForm = {
+                newPwd: "",
+                confirmPwd: "",
+              };
+            },
+
+            // 校验密码强度(前端校验,与PC端一致)
+            validatePassword(password, yhm) {
+              // 获取密码强度要求
+              const msg = this.resetPwdModal.pwdStrengthMsg || "";
+
+              // 检查最小长度
+              if (msg.includes("最小6个字符") && password.length < 6) {
+                return { valid: false, msg: "密码长度不能小于6位" };
+              }
+              // 检查最大长度
+              if (msg.includes("最大16个字符") && password.length > 16) {
+                return { valid: false, msg: "密码长度不能大于16位" };
+              }
+              // 检查必须包含大小写字母和数字
+              if (
+                msg.includes("必须含有和字母和大小写字母和数字") ||
+                msg.includes("必须含有大小写字母和数字")
+              ) {
+                if (
+                  !/[a-z]/.test(password) ||
+                  !/[A-Z]/.test(password) ||
+                  !/\d/.test(password)
+                ) {
+                  return {
+                    valid: false,
+                    msg: "密码必须同时包含大小写字母和数字",
+                  };
+                }
+              }
+              // 检查不能包含账号
+              if (msg.includes("密码不能包含账号") && yhm) {
+                if (password.includes(yhm)) {
+                  return { valid: false, msg: "密码不能包含账号" };
+                }
+              }
+
+              return { valid: true, msg: "" };
+            },
+
+            // 提交修改密码
+            async handleResetPwd() {
+              const { newPwd, confirmPwd } = this.resetPwdForm;
+              const { yhid, yhm } = this.resetPwdModal;
+
+              // 校验输入
+              if (!newPwd) {
+                this.showToast("请输入新密码", "warning");
+                return;
+              }
+              if (!confirmPwd) {
+                this.showToast("请确认新密码", "warning");
+                return;
+              }
+              if (newPwd !== confirmPwd) {
+                this.showToast("新密码与确认密码不一致", "error");
+                return;
+              }
+
+              // 前端校验密码强度
+              const validateResult = this.validatePassword(newPwd, yhm);
+              if (!validateResult.valid) {
+                this.showToast(validateResult.msg, "error");
+                return;
+              }
+
+              this.resetPwdLoading = true;
+
+              try {
+                const response = await $.ajax({
+                  url: "/service?ssServ=updPwd",
+                  data: {
+                    yhid: yhid,
+                    newPassword: newPwd,
+                    againNewPassword: confirmPwd,
+                  },
+                  type: "POST",
+                  dataType: "json",
+                });
+
+                console.log("修改密码响应:", response);
+
+                // 判断是否成功(有msg且包含"成功",或没有错误信息)
+                if (response.msg && response.msg.includes("成功")) {
+                  // 修改成功
+                  this.showToast(response.msg, "success");
+                  this.resetPwdModal.show = false;
+                  // 清空密码输入框,保留账号
+                  this.form.password = "";
+                  this.resetPwdForm.newPwd = "";
+                  this.resetPwdForm.confirmPwd = "";
+                } else if (response.msg && response.msg.includes("失败")) {
+                  this.showToast(response.msg, "error");
+                } else {
+                  this.showToast(
+                    response.msg || response.message || "密码修改失败",
+                    "error"
+                  );
+                }
+              } catch (error) {
+                console.error("修改密码失败:", error);
+                this.showToast("修改密码失败,请重试", "error");
+              } finally {
+                this.resetPwdLoading = false;
+              }
+            },
           },
         });
 
@@ -848,7 +1051,7 @@
         padding: 12px 20px;
         border-radius: 4px;
         font-size: 14px;
-        z-index: 10001;
+        z-index: 10010;
         max-width: 80%;
         text-align: center;
       }
@@ -1067,6 +1270,117 @@
         margin-bottom: 12px;
       }
 
+      /* 修改初始密码弹窗样式 */
+      .reset-pwd-mask {
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background: rgba(0, 0, 0, 0.7);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        z-index: 10005;
+      }
+
+      .reset-pwd-modal {
+        width: calc(100% - 20px);
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        background: #fff;
+        border-radius: 4px;
+        transform: translate(-50%, -50%);
+        border: 1px solid #d3d4d5;
+        overflow: hidden;
+      }
+
+      .reset-pwd-header {
+        padding: 20px;
+        text-align: left;
+        border-bottom: 1px solid #f0f0f0;
+      }
+
+      .reset-pwd-title {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+      }
+
+      .reset-pwd-body {
+        padding: 20px;
+      }
+
+      .pwd-strength-msg {
+        font-size: 13px;
+        color: #ff6b6b;
+        margin-bottom: 15px;
+        padding: 10px;
+        background: #fff5f5;
+        border-radius: 4px;
+        line-height: 1.5;
+      }
+
+      .reset-pwd-form {
+        margin-bottom: 20px;
+      }
+
+      .reset-pwd-input-item {
+        position: relative;
+        margin-bottom: 12px;
+        display: flex;
+      }
+
+      .reset-pwd-input {
+        width: 100%;
+        height: 44px;
+        padding: 0 40px 0 15px;
+        border: 1px solid #d5d8dc;
+        border-radius: 4px;
+        font-size: 15px;
+        outline: none;
+        transition: border-color 0.2s;
+      }
+
+      .reset-pwd-input:focus {
+        border-color: #575d6d;
+      }
+
+      .reset-pwd-input-item .eye-icon {
+        position: absolute;
+        right: 10px;
+        top: 50%;
+        transform: translateY(-50%);
+        padding: 10px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        cursor: pointer;
+        z-index: 10;
+      }
+
+      .reset-pwd-btn {
+        width: 100%;
+        height: 44px;
+        background: #575d6d;
+        color: white;
+        border: none;
+        border-radius: 4px;
+        font-size: 16px;
+        cursor: pointer;
+        transition: background 0.2s;
+      }
+
+      .reset-pwd-btn:hover {
+        background: #494e5b;
+      }
+
+      .reset-pwd-btn.disabled {
+        background: #cccccc;
+        cursor: not-allowed;
+      }
+
       /* 响应式设计 */
       /* @media (max-width: 480px) {
             .popup-content {

BIN
skin/.DS_Store


+ 0 - 6914
skin/easy/css/base.css

@@ -1,6914 +0,0 @@
-@import url(var.css);
-
-/* 证件照 */
-.id-photo{
-  width: 153px;
-  height: 213px;
-  background: #e8e8e8;
-  background-size: cover;
-  cursor: pointer;
-  position: relative;
-}
-.id-photo::before {
-  content: "\e605";
-  font-size: 100px;
-  font-family: "iconfont";
-  color: #ccc;
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  pointer-events: none; 
-  z-index: 1;  /* 确保图标在内容后面 */
-  /* 其他定位属性 */
-}
-/* 生活照 */
-.life-photo{
-  width: 144px;
-  height: 144px;
-  border-radius: 50%;
-  background:#e8e8e8;
-  background-size: contain;
-  cursor: pointer;
-  position: relative;
-}
-.life-photo::before {
-  content: "\e605";
-  font-size: 80px;
-  font-family: "iconfont";
-  color: #ccc;
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  pointer-events: none; 
-  z-index: 1;
-}
-.life-photo img{
-  border-radius: 50%;
-}
-/* 图标相关开始 */
-/* 通用icon */
-.common-icon{
-  font-size: 22px;
-  font-family: "iconfont";
-
-}
-.common-icon-add::before{
-  content: "\e60d";
-  color: #999999;
-
-}
-.common-icon-setting::before{
-  content: "\e630";
-  /* color: #999999; */
-}
-/* 减少 */
-.common-icon-reduce::before{
-  content: "\e6a2";
-  color: #EB6100;
-}
-/* 附件 */
-.common-icon-paper-clip::before{
-  content: "\e676";
-  color: #999999;
-}
-.common-icon-change::before{
-  font-size: 16px;
-  content: "→";
-  color: red;
-}
-/* 表情 */
-.common-icon-smile::before{
-  content: "\e616";
-  color: #999999;
-}
-/* 常用语 */
-.common-icon-common-words::before{
-  content: "\e69d";
-  color: #999999;
-}
-/* 手写 */
-.common-icon-handwriting::before{
-  content: "\e6ab";
-  color: #999999;
-}
-/* 视频播放 */
-.common-icon-video::before{
-  content: "\e699";
-  color: #999999;
-}
-/* 文件夹-关闭 */
-.common-icon-folder-close::before{
-  content: "\e60b";
-  color: #999999;
-}
-/* 文件夹-打开 */
-.common-icon-folder-open::before{
-  content: "\e60c";
-  color: #999999;
-}
-/* 文件 */
-.common-icon-file::before{
-  content: "\e69e";
-  color: #999999;
-}
-/* 刷新 */
-.common-icon-refresh::before{
-  content: "\e635";
-  color: #999;
-}
-/* 待办 */ 
-.common-icon-todo::before{
-  content: "\e65c";
-  color: #999;
-}
-/* 催办 */
-.common-icon-urge::before{
-  content: "\e664";
-  color: #999;
-}
-/* 快捷发起 */
-.common-icon-quick-start::before{
-  content: "\e6a6";
-  color: #999;
-}
-/* 公告 */
-.common-icon-notice::before{
-  content: "\e6ac";
-  color: #999;
-}
-/* 统计图 */
-.common-icon-chart::before{
-  content: "\e6a5";
-  color: #999;
-}
-/* 请假 */
-.common-icon-leave-big::before{
-  font-size: 36px;
-  content: "\e6af";
-  color: #999999;
-}
-/* 收付款 */
-.common-icon-receipt-big::before{
-  font-size: 36px;
-  content: "\e68e";
-  color: #999999;
-}
-/* 考勤 */
-.common-icon-attendance-big::before{
-  font-size: 36px;
-  content: "\e694";
-  color: #999999;
-}
-/* 会议 */
-.common-icon-meeting::before{
-  content: "\e692";
-  color: #999999;
-}
-/* 一卡通 */
-.common-icon-card::before{
-  content: "\e6a0";
-  color: #999999;
-}
-/* 个人网站 */
-.common-icon-site::before{
-  content: "\e6ae";
-  color: #999999;
-}
-.common-icon-arrow-right{
-  font-size: 14px;
-}
-.common-icon-arrow-right::before{
-  content: "\e640";
-}
-.common-icon-arrow-top::before{
-  content: "\e63f";
-}
-.common-icon-arrow-bottom:before {
-  content: "\e63e";
-}
-.common-icon-arrow-bottom:before {
-  content: "\e63e";
-}
-.common-icon-paixu:before {
-  content: "\e6e7";
-}
-.common-icon-jiaoshi:before {
-  content: "\e6e6";
-}
-.common-icon-renyuan2:before {
-  content: "\e6aa";
-}
-.common-icon-xueyuan:before {
-  content: "\e623";
-}
-
-/* 通用icon结束 */
-/* 全局左侧导航开始 */
-.nav-icon {
-  font-size: 22px;
-  font-family: "iconfont";
-  padding: 10px;
-  color: #565d6d;
-}
-.nav-icon-home::before {
-  content: "\e690";
-}
-.nav-icon-person::before {
-  content: "\e605";
-}
-.nav-icon-knowledge::before {
-  content: "\e62c";
-}
-.nav-icon-statistics::before {
-  content: "\e68a";
-}
-.nav-icon-category::before {
-  content: "\e652";
-}
-.nav-icon-add::before {
-  content: "\e60d";
-}
-.nav-icon-search::before {
-  content: "\e62f";
-}
-.nav-icon-folder-close::before{
-  content: "\e60b";
-  font-size: 19px;
-}
-.nav-icon-folder-open::before{
-  content: "\e60c";
-  font-size: 19px;
-}
-/* 岗位 */
-.nav-icon-post::before{
-  content: "\e69c";
-}
-/* 单位 */
-.nav-icon-unit::before{
-  content: "\e662";
-}
-/* 全局左侧导航结束 */
-/* 顶部导航开始 */
-.header-icon {
-  /* 基础样式 */
-  width: 36px;
-  height: 36px;
-  font-size: 22px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  font-family: "iconfont";
-  border-radius: 4px;
-  border: 1px solid var(--icon-item-border-color, transparent);
-}
-
-.header-icon:hover {
-  --icon-item-border-color: #edf1f5;
-}
-
-.header-help::after {
-  content: "\e6a7";
-  /* 帮助图标 */
-}
-
-.header-setting::after {
-  content: "\e60e";
-  /* 设置图标 */
-}
-
-.header-save::after {
-  content: "\e68d";
-  /* 设置图标 */
-}
-
-.header-menu::after {
-  content: "\e6ad";
-  /* 菜单图标 */
-}
-
-.header-home::after {
-  content: "\e600";
-  /* 主页图标 */
-}
-.header-skin::after {
-  content: "\e689";
-  /* 换肤图标 */
-}
-
-.header-lock::after {
-  content: "\e69f";
-  /* 锁定图标 */
-}
-
-.header-logout {
-  width: 48px;
-  height: 48px;
-  font-size: 33px;
-}
-
-.header-logout:hover {
-  background-color: #000;
-}
-
-.header-logout::after {
-  content: "\e6a1";
-  /* 退出图标 */
-}
-
-/* 顶部导航结束 */
-/* 全局菜单图标开始 */
-.global-menu-icon {
-  font-size: 16px;
-  font-family: "iconfont";
-  /* padding: 10px; */
-}
-/* 全局菜单图标结束 */
-/* 全局查询列表卡片 */
-.cart-list-icon {
-  font-size: 22px;
-  font-family: "iconfont";
-  /* padding: 10px; */
-}
-.cart-list-setting::before {
-  content: "\e630";
-  color: #dddddd;
-}
-
-/* 弹窗底部按钮icon */
-.bottom-div-icon{
-  font-size: 20px;
-  font-family: "iconfont";
-}
-.bottom-div-save::before{
-  content: "\e68d";
-}
-.bottom-div-close{
-  display: flex;
-  align-items: center;
-}
-.bottom-div-close::before{
-  content: "\e693";
-  font-size: 16px;
-}
-.bottom-div-back::before{
-  content: "\e638";
-}
-/* 表单组件icon开始 */
-.form-icon{
-  font-size: 18px;
-  font-family: "iconfont";
-}
-
-.form-icon-select::before{
-  content: "\e63e";
-}
-.form-icon-transform-select::before{
-  content: "\e63f";
-}
-.form-icon-select-checked::before{
-  content: "\e68d";
-}
-
-.form-icon-onoffbutton-checked::before{
-  content: "\e62d";
-}
-.form-icon-onoffbutton-unchecked::before{
-  content: "\e62b";
-}
-.form-icon-time::before{
-  content: "\e606";
-}
-.form-icon-prev-month::before{
-  content: "\e641";
-}
-.form-icon-prev-year::before{
-  content: "\e6b1";
-}
-.form-icon-next-month::before{
-  content: "\e640";
-}
-.form-icon-next-year::before{
-  content: "\e6b2";
-}
-/* 表单组件icon结束 */
-/* 登录页icon开始 */
-.login-icon{
-  font-size: 22px;
-  font-family: "iconfont";
-}
-.login-icon-user::before{
-  content: "\e605";
-}
-.login-icon-password::before{
-  content: "\e607";
-}
-.login-icon-check-code::before{
-  content: "\e608";
-}
-.login-icon-time::before{
-  content: "\e606";
-}
-.login-icon-loginin::before{
-  content: "\e6a1";
-}
-.login-icon-yaoyiyao::before{
-  content: "\e60f";
-}
-.login-icon-change-user{
-  position: absolute;
-  top: 0;
-  right: 0;
-  width: 22px !important;
-  height: 22px;
-  margin-right: 5px;
-  margin-top: 5px;
-  cursor: pointer;
-}
-.login-icon-change-user::before{
-  content: "\e609";
-}
-/* 登录页icon结束 */
-/* 弹窗icon开始 */
-.dialog-icon{
-  font-size: 22px;
-  font-family: "iconfont";
-}
-/* 关闭 */
-.dialog-icon-close::before{
-  content: "\e693";
-  font-size: 28px;
-}
-/* 下载 */
-.dialog-icon-download::before{
-  content: "\e691";
-}
-/* 打印 */
-.dialog-icon-print::before{
-  content: "\e66f";
-}
-/* 设置 */
-.dialog-icon-setting::before{
-  content: "\e630";
-}
-/* 收藏 */
-.dialog-icon-collect::before{
-  content: "\e698";
-}
-/* 帮助 */
-.dialog-icon-help::before{
-  content: "\e6cd";
-}
-/* 全屏 */
-.dialog-icon-full-screen::before{
-  content: "\e6ca";
-}
-/* 锁屏 */
-.dialog-icon-lock::before{
-  content: "\e697";
-}
-
-/* editor相关图标开始 */
-.editor-icon{
-  font-size: 16px;
-  font-family: "iconfont";
-  color: #666666;
-}
-/* 加粗 */
-.editor-icon-bold::before{
-  content: "\e68b";
-}
-/* 斜体 */
-.editor-icon-italic::before{
-  content: "\e66b";
-}
-/* 下划线 */
-.editor-icon-underline::before{
-  content: "\e685";
-}
-/* 删除线 */
-.editor-icon-strikethrough::before{
-  content: "\e66e";
-}
-
-/* 加粗 */
-.editor-icon-bold::before{
-  content: "\e68b";
-}
-/* 斜体 */
-.editor-icon-italic::before{
-  content: "\e66b";
-}
-/* 下划线 */
-.editor-icon-underline::before{
-  content: "\e685";
-}
-/* 删除线 */
-.editor-icon-strikethrough::before{
-  content: "\e66e";
-}
-
-/* 清除格式 */
-.editor-icon-eraser::before{
-  content: "\e6c2";
-}
-/* 复制格式 */
-.editor-icon-copyformat::before{
-  content: "\e68b";
-}
-/* 字体 */
-.editor-icon-font::before{
-  content: "\e680";
-}
-/* 字号 */
-.editor-icon-fontsize::before{
-  content: "\e67d";
-}
-/* 文字颜色 */
-.editor-icon-brush::before{
-  content: "\e681";
-}
-/* 段落 */
-.editor-icon-paragraph::before{
-  content: "\e682";
-}
-/* 左对齐 */
-.editor-icon-align-left::before{
-  content: "\e67e";
-}
-/* 居中对齐 */
-.editor-icon-align-center::before{
-  content: "\e67b";
-}
-/* 右对齐 */
-.editor-icon-align-right::before{
-  content: "\e67f";
-}
-/* 两端对齐 */
-.editor-icon-align-justify::before{
-  content: "\e67c";
-}
-/* 无序列表 */
-.editor-icon-ul::before{
-  content: "\e6c3";
-}
-/* 有序列表 */
-.editor-icon-ol::before{
-  content: "\e6c7";
-}
-/* 增加缩进 */
-.editor-icon-indent::before{
-  content: "\e6c8";
-}
-/* 减少缩进 */
-.editor-icon-outdent::before{
-  content: "\e6c9";
-}
-/* 图片 */
-.editor-icon-image::before{
-  content: "\e683";
-}
-/* 文件 */
-.editor-icon-file::before{
-  content: "\e668";
-}
-/* 视频 */
-.editor-icon-video::before{
-  content: "\e699";
-}
-/* 表格 */
-.editor-icon-table::before{
-  content: "\e677";
-}
-/* 链接 */
-.editor-icon-link::before{
-  content: "\e676";
-}
-/* 源代码 */
-.editor-icon-source::before{
-  content: "\e68b";
-}
-/* 预览 */
-.editor-icon-preview::before{
-  content: "\e642";
-}
-/* 全屏 */
-.editor-icon-fullsize::before{
-  content: "\e6c4";
-}
-/* 退出全屏 */
-.editor-icon-fullsize-exit::before{
-  content: "\e6cb";
-}
-/* 打印 */
-.editor-icon-print::before{
-  content: "\e66f";
-}
-/* 撤销 */
-.editor-icon-undo::before{
-  content: "\e688";
-}
-/* 重做 */
-.editor-icon-redo::before{
-  content: "\e686";
-}
-/* 查找 */
-.editor-icon-find::before{
-  content: "\e62f";
-}
-/* 全选 */
-.editor-icon-selectall::before{
-  content: "\e68b";
-}
-/* 隐藏原有的 SVG */
-.jodit-toolbar-button__trigger svg {
-  display: none;
-}
-
-/* 添加我们自己的图标 */
-.jodit-toolbar-button__trigger::after {
-  content: "\e63e";  
-  font-family: "iconfont" !important; 
-  font-size: 12px;
-}
-.jodit-toolbar-button_with-trigger_true{
-  margin-right: 4px !important;
-}
-.jodit-toolbar-button_with-trigger_true>.jodit-toolbar-button__button{
-  width: 20px !important;
-  min-width: 20px !important;
-}
-/* editor相关图标结束 */
-/* 弹窗icon结束 */
-/* 图标相关结束 */
-.self-block {
-  width: 100%;
-  height: 100%;
-}
-
-body * {
-  box-sizing: border-box;
-}
-
-html,
-body {
-  margin: 0;
-  padding: 0;
-}
-
-html,
-body,
-#app {
-  width: 100%;
-  height: 100%;
-  /* min-width: 1024px; */
-}
-
-i{
-  font-style: normal;
-}
-
-input::placeholder ,textarea::placeholder{
-  color: #999;
-}
-
-/*定义滚动条高宽及背景
- 高宽分别对应横竖滚动条的尺寸*/
-::-webkit-scrollbar {
-  width: 8px;
-  /* background-color: #F5F5F5; */
-  border-radius: 4px;
-  margin: 0 6px;
-}
-
-/*定义滚动条轨道
-  内阴影+圆角*/
-::-webkit-scrollbar-track {
-  border-radius: 4px;
-  background-color: #F5F5F5;
-}
-
-/*定义滑块
-  内阴影+圆角*/
-::-webkit-scrollbar-thumb {
-  border-radius: 4px;
-  background-color: #c1c1c1;
-}
-
-
-/* 页面布局 */
-.layout-container {
-  --header-height: 70px;
-  --left-side-width: 60px;
-  width: 100%;
-  height: 100%;
-  position: relative;
-  overflow: hidden;
-}
-
-.layout-container .header {
-  height: var(--header-height);
-  width: 100%;
-  box-sizing: border-box;
-}
-
-.layout-container .content-area {
-  width: 100%;
-  height: calc(100% - var(--header-height));
-  padding-right: 6px;
-}
-
-.layout-container .content-area:after {
-  content: "";
-  display: block;
-  width: 0;
-  height: 0;
-  clear: both;
-}
-
-.layout-container .left-side {
-  float: left;
-  height: 100%;
-  width: var(--left-side-width);
-  position: relative;
-}
-
-.layout-container .left-side-container {
-  --left-size-width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: var(--left-size-width);
-  transition: width 0.2s;
-}
-
-.layout-container .left-side-container[size="max"] {
-  --left-size-width: 230px;
-}
-
-.layout-container .btn-size {
-  position: absolute;
-  bottom: 0;
-  left: calc(100% + 1px);
-  width: 16px;
-  height: 18px;
-  background: #fff;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-  z-index: 100;
-  --border-color: #dddfe6;
-  border-bottom: 1px solid var(--border-color);
-  border-right: 1px solid var(--border-color);
-}
-
-.layout-container .btn-size::before {
-  content: "";
-  position: absolute;
-  left: -7px;
-  top: -22px;
-  width: 22px;
-  height: 22px;
-  background: #fff;
-  transform-origin: 100% 100%;
-  transform: rotate(-45deg);
-  z-index: 1;
-  border-right: 1px solid var(--border-color);
-}
-
-.layout-container .btn-size .icon-container {
-  position: absolute;
-  z-index: 2;
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  padding: 0 0 1px 1px;
-}
-
-.layout-container .left-side-content {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 100;
-  overflow: hidden;
-  background: #fafbfe;
-  
-  /* display: flex;
-  flex-direction: column;
-  justify-content: flex-start;
-  align-items: center; */
-
-}
-
-.layout-container .left-side-content:hover {
-  overflow-x: hidden;
-  overflow-y: auto;
-}
-
-.layout-container .left-side-content:after {
-  content: "";
-  height: 100%;
-  width: 1px;
-  position: absolute;
-  left: 100%;
-  top: 0;
-  background: #dadee2;
-  box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.24);
-}
-
-.layout-container  .main-content {
-  float: right;
-  height: 100%;
-  width: calc(100% - var(--left-side-width));
-}
-
-.layout-container[sys-mode="edit"] {
-  --edit-box-tools-display: block;
-}
-
-.layout-container[sys-mode="edit"] .can-resize-box:hover {
-  --block-title-visible: hidden;
-}
-
-.flex-start-center {
-  display: flex;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.flex-between-center {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-/* 公共头部区域开始 */
-.global-header-container {
-  background: var(--lightdark);
-  color: var(--white);
-  height: 100%
-}
-
-.global-header-container>div {
-  height: 100%;
-}
-
-.global-header-container .logo {
-  height: 100%;
-  width: 183px;
-  cursor: pointer;
-  position: relative;
-  z-index: 200;
-}
-
-.global-header-container .logo::after {
-  position: absolute;
-  content: "";
-  width: 0;
-  height: 50%;
-  top: calc(50% - 50% / 2);
-  right: 0;
-  border-right: 1px solid var(--lightdark-sub);
-}
-
-.global-header-container .logo:hover {
-  --header-menu-visible: visible;
-}
-
-.global-header-container .logo .img {
-  padding: 12px 30px 12px calc(var(--space-size) / 2);
-  height: 100%;
-  width: 100%;
-}
-
-.global-header-container .img img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: contain;
-}
-
-.global-header-container .menu {
-  visibility: var(--header-menu-visible, hidden);
-  transition: top 0.3s;
-  font-size: 14px;
-  color: #333;
-  top: 100%;
-  left: 0;
-  position: absolute;
-  /* width: 100%; */
-  background: #393d51;
-  border-top: 1px solid #dddfe6;
-  padding: 10px 2px;
-  border-bottom-right-radius: 4px;
-  border-bottom-left-radius: 4px;
-}
-
-.global-header-container .menu>div {
-  height: 36px;
-  color: var(--header-menu-color, #fff);
-  background: var(--header-menu-bg, transparent);
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  padding-left: 8px;
-  padding-right: 8px;
-  gap: 10px;
-  white-space: nowrap;
-}
-
-.global-header-container .menu>div:hover {
-  --header-menu-color: #333;
-  --header-menu-bg: #fffdfd;
-}
-
-.global-header-container .bread-crumb {
-  padding-left: 30px;
-  padding-top: 30px;
-  font-size: 18px;
-  color: var(--white);
-}
-
-.global-header-container.bread-crumb .content {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.global-header-container.bread-crumb .home-icon {
-  margin-right: calc(var(--space-size) / 2);
-  margin-top: -2px;
-}
-
-.global-header-container.bread-crumb .split-icon {
-  margin: 0 var(--space-size);
-}
-
-.global-header-container.bread-crumb .content a {
-  color: inherit;
-  text-decoration: none;
-}
-
-.global-header-container .menu-area {
-  padding-top: 10px;
-  padding-right: var(--space-size);
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  gap: 12px;
-}
-
-.global-header-container .search-area {
-  padding: 0 1em;
-  width: 350px;
-  height: 40px;
-}
-
-
-/* 顶部菜单全局搜索框 */
-.search-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-  border: none;
-  border-radius: 5px;
-  overflow: hidden;
-  --search-input-font-size: 16px;
-  --search-bg: var(--white, #fff);
-  --search-color: var(--dark, #252835);
-  --input-placeholder-color: #666;
-  background: var(--search-bg);
-  color: var(--search-color);
-}
-
-.search-container.dark {
-  --search-bg: var(--dark, #252835);
-  --search-color: var(--white, #fff);
-  --input-placeholder-color: #9c9fa7;
-}
-
-.search-container input {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  z-index: 1;
-  color: inherit;
-  padding: 0 1em;
-  border: unset;
-  font-size: var(--search-input-font-size);
-  background: unset;
-}
-
-.search-container input:disabled {
-  cursor: pointer;
-}
-
-.search-container input:focus {
-  outline: unset;
-}
-
-.search-container input::-moz-placeholder {
-  color: var(--input-placeholder-color, #666);
-}
-
-.search-container input::placeholder {
-  color: var(--input-placeholder-color, #666);
-}
-
-.search-container .icon-container {
-  right: 15px;
-  top: 50%;
-  transform: translateY(-50%);
-  position: absolute;
-  z-index: 2;
-  pointer-events: none;
-  padding-left: 10px;
-  background: var(--search-bg);
-}
-
-/* 公共头部区域结束 */
-
-/* 全局左部边框开始 */
-.left-side-container {
-  width: 100%;
-  height: 100%;
-  padding: 0;
-  background: #fafbfe;
-  /* overflow-y: auto;
-  overflow-x: hidden; */
-}
-/* 菜单项小圆点 */
-.menu-item-dot {
-  width: 5px;
-  height: 5px;
-  border-radius: 50%;
-  background-color: #8e8e8e;
-  position: absolute;
-  right: 5px;
-  /* 调整右侧位置 */
-  bottom: 5px;
-  /* 调整底部位置 */
-  font-size: 16px;
-  /* 调整圆点大小 */
-}
-
-.left-side-container .menu-item {
-  height: 60px;
-  width: 100%;
-  box-sizing: border-box;
-  color: var(--lightdark);
-  cursor: pointer;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.left-side-container .add-menu-btn {
-  display: var(--menu-add-btn-display, none);
-}
-
-.left-side-container .add {
-  width: 45px;
-  height: 45px;
-  border-radius: 5px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  box-shadow: 0 1px 4px #ccc;
-}
-
-.left-side-container .menu-item-content {
-  width: 100%;
-  height: 100%;
-  padding: 0 8px;
-  gap: 5px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  position: relative;
-  --edit-mark-display: none;
-}
-
-.left-side-container .menu-item-content:hover {
-  --edit-mark-display: var(--menu-edit-mark-display, none);
-}
-
-.left-side-container .menu-item-label {
-  height: 1.5em;
-  overflow: hidden;
-  transition: all 0.5s;
-  font-size: 18px;
-  color: #565d6d;
-  opacity: var(--menu-item-label-opacity, 0);
-  visibility: var(--menu-item-label-visible, hidden);
-}
-
-.left-side-container .edit-mark {
-  display: var(--edit-mark-display);
-  right: -1px;
-  top: -1px;
-  position: absolute;
-  color: #c3c6ca;
-}
-
-.left-side-container .edit-mark:hover {
-  color: #333;
-}
-
-.left-side-container .menu-item-content:hover {
-  background: #edf1f5;
-}
-
-.left-side-container .menu-item-content:hover.edit .mark {
-  display: block;
-}
-
-.left-side-container .icon-container {
-  position: relative;
-  padding: 10px;
-  box-sizing: content-box;
-  width: 24px;
-  height: 24px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  flex-shrink: 0;
-}
-.left-side-container .active{
-  background: #edf1f5;
-}
-/* 全局左部边框结束 */
-
-/* 一级页面搜索开始 */
-.search-bar-contaienr {
-  height: 100%;
-  width: 100%;
-  padding: 0 20px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  gap: 20px;
-  --col-lg-3: 270px;
-  position: relative;
-
-}
-
-.search-bar-contaienr input {
-  padding: 8px 10px;
-  margin: 0;
-  outline: unset;
-  border: 1px solid #c4c7cc;
-  border-radius: 3px;
-  font-size: 14px;
-}
-
-
-
-.search-bar-contaienr button {
-  font-size: 14px;
-  outline: unset;
-  border: unset;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  /* gap: 5px; */
-  padding: 8px 20px;
-  border-radius: 3px;
-  margin: 0;
-  cursor: pointer;
-  border: 1px solid #c4c7cc;
-}
-
-.search-bar-contaienr button:hover {
-  background: #393d51;
-  border: 1px solid #393d51;
-  color: #fff;
-}
-
-.search-bar-contaienr .add {
-  position: relative;
-}
-
-.search-bar-contaienr .popup {
-  position: absolute;
-  top: calc(100% + 15px);
-  right: 0;
-  width: 100%;
-  height: 130px;
-  background-color: #393d51;
-  border-radius: 5px;
-  padding: 10px 0;
-  z-index: 10;
-}
-
-.search-bar-contaienr .popup::after {
-  content: "";
-  width: 1em;
-  height: 1em;
-  background: #393d51;
-  position: absolute;
-  right: 1.5em;
-  top: -0.5em;
-  transform: rotate(45deg);
-}
-.search-bar-contaienr .popup >div {
-  border-bottom: 1px solid #303445;
-}
-.search-bar-contaienr .popup >div:last-child {
-  border-bottom: unset;
-}
-
-.search-bar-contaienr button.add>div.popup>div {
-  color: #d8d8d8;
-  font-size: 14px;
-  padding: 8px 20px;
-  cursor: pointer;
-}
-
-.search-bar-contaienr button.add>div.popup>div:not(:last-child) {
-  border-bottom: 1px solid #303445;
-}
-
-.search-bar-contaienr button.add>div.popup>div:hover {
-  background: #fffdfd;
-  color: #333;
-}
-
-
-.search-bar-contaienr>div {
-  height: 32px;
-}
-
-.search-bar-contaienr>.input {
-  border: 1px solid #c4c7cc;
-  border-radius: 3px;
-  font-size: 14px;
-}
-
-.search-bar-contaienr>div.input>input {
-  height: 100%;
-  width: 100%;
-  padding: 8px 10px;
-  margin: 0;
-  outline: unset;
-  border: unset;
-  border-radius: inherit;
-  background: unset;
-  font-size: inherit;
-}
-
-
-
-.search-bar-contaienr button {
-  height: 32px;
-  font-size: 14px;
-  outline: unset;
-  border: unset;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  /* gap: 5px; */
-  padding: 0 20px;
-  border-radius: 3px;
-  margin: 0;
-  cursor: pointer;
-  background: var(--btn-bg, unset);
-  color: var(--btn-color, #999999);
-  border: 1px solid var(--btn-border-color, #c4c7cc);
-}
-
-.search-bar-contaienr button:hover {
-  --btn-bg: #393d51;
-  --btn-color: #fff;
-}
-
-.search-bar-contaienr .input {
-  width: var(--col-lg-3);
-  height: 32px;
-  /* border: 1px solid #c4c7cc; */
-  border-radius: 4px;
-  position: relative;
-}
-
-.search-bar-contaienr .input>input {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 1;
-  outline: unset;
-  border: unset;
-  background: unset;
-  padding: 0 15px;
-  line-height: 32px;
-  font-size: 14px;
-}
-
-.search-bar-contaienr .input>input::-moz-placeholder {
-  color: #999;
-}
-
-.search-bar-contaienr .input>input::placeholder {
-  color: #999;
-}
-
-.search-bar-contaienr .bar {
-  padding: 0 10px;
-  position: absolute;
-  top: 0;
-  right: 0;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  color: #c4c7cc;
-  gap: 12px;
-}
-
-.search-bar-contaienr .bar .icon-container {
-  position: relative;
-  display: block;
-}
-
-.search-bar-contaienr .bar .icon-container:not(:last-child)::after {
-  content: "";
-  position: absolute;
-  top: 50%;
-  left: calc(100% + 12px);
-  transform: translateY(-50%);
-  width: 0;
-  height: 20px;
-  border-right: 1px solid #c4c7cc;
-}
-
-
-
-.search-bar-contaienr button {
-  font-size: 16px;
-  outline: unset;
-  border: unset;
-  color: #999;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  /* gap: 5px; */
-  padding: 0 20px;
-  border-radius: 4px;
-  margin: 0;
-  /* line-height: 2em; */
-  cursor: pointer;
-  background: var(--btn-bg, unset);
-  color: var(--btn-color, #999999);
-  border: 1px solid var(--btn-border-color, #c4c7cc);
-}
-
-.search-bar-contaienr button:hover {
-  --btn-bg: #393d51;
-  --btn-color: #fff;
-}
-.search-bar-contaienr .popup-win.bottom{
-  top: 100% !important;
-}
-.search-bar-contaienr .select-container .suffix>div{
-  width: 30px !important;
-  height: 30px !important;
-}
-/* 一级页面搜索结束 */
-
-/* 知识库卡片开始 */
-.knowledge-item-container {
-  width: 573px;
-  /* height: 220px; */
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  border: 1px solid #dddfe6;
-  --header-display: none;
-  --header-color: #999;
-}
-
-.knowledge-item-container:hover {
-  --header-display: flex;
-  box-shadow: 8px 8px 0px #3a3e513d;
-}
-
-.knowledge-item-container:hover .cart-list-setting{
-  display: block;
-}
-/* .knowledge-item-container:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dddfe6;
-} */
-.knowledge-item-container.active{
-  box-shadow: 8px 8px 0px #3a3e513d;
-}
-.knowledge-item-container.active .header{
-  border-radius: unset;
-}
-/* .knowledge-item-container.active::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #585e6e;
-} */
-
-.knowledge-item-container .active {
-  border: 1px solid #ddd;
-}
-
-.knowledge-item-container .action-bar {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.knowledge-item-container>div.action-bar:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.knowledge-item-container .header {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.knowledge-item-container .header:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-.knowledge-item-container .header:hover .cart-list-setting::before{
-  color: #ffffff;
-}
-.knowledge-item-container .body {
-  padding: 20px 25px;
-}
-
-.knowledge-item-container .box-header>div:first-child {
-  color: #333333;
-  font-size: 20px;
-  line-height: 2em;
-}
-
-.knowledge-item-container .box-body {
-  /* height: 140px; */
-  color: #333;
-  padding: 10px 0;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: flex-end;
-  --right-padding-left: 20px;
-  --right-width: calc(100% - 86px);
-}
-
-.knowledge-item-container .no-thumb {
-  --right-padding-left: 0;
-  --right-width: 100%;
-}
-
-.knowledge-item-container .left {
-  width: 88px !important;
-  height: 121px !important;
-  border: 1px solid #f6f6f6;
-}
-
-.knowledge-item-container .left>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-  display: block;
-}
-
-.knowledge-item-container .right {
-  width: var(--right-width);
-  padding-left: var(--right-padding-left);
-  padding-top: 5px;
-}
-
-.knowledge-item-container .right .title {
-  font-size: 16px;
-  color: #666666;
-  line-height: 2em;
-  /* padding-right: 1em; */
-  line-height: 24px;
-  display: -webkit-box;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 1;
-  -webkit-box-orient: vertical;
-}
-
-.knowledge-item-container  .desc {
-  margin-top: 10px;
-  font-size: 14px;
-  color: #999999;
-  line-height: 1.8em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  gap: 20px;
-}
-/* 知识库卡片结束 */
-/* 知识库文件夹开始 */
-.ss-folder-list-trapezoid {
-  width: 100px;
-  height: 0;
-  /* border-left: 25px solid transparent; */
-  border-right: 30px solid transparent;
-  border-bottom: 20px solid #fafbfe;
-  border-radius: 4px 0 0 0;
-  position: absolute;
-  top: 0px;
-  left: 0;
-  z-index: 11;
-}
-.ss-folder-list-top-transparent {
-  width: 100%;
-  height: 10px;
-  position: absolute;
-  top: 0;
-  left: 0;
-  background: transparent;
-  border-radius: 4px 4px 0 0;
-  z-index: 1;
-}
-.ss-folder-list-top {
-  width: 100%;
-  height: 10px;
-  position: absolute;
-  top: 10px;
-  left: 0;
-  background: #dcdee5;
-  border-radius: 4px 4px 0 0;
-}
-.ss-folder-list-right {
-  width: 8px;
-  height: calc(100% - 10px);
-  position: absolute;
-  bottom: 0;
-  right: 0px;
-  background: #dcdee5;
-  border-radius: 0 4px 4px 0;
-}
-
-.ss-folder-list {
-  width: 573px;
-  /* height: 220px; */
-  box-shadow: -3px 6px 5px #a1a3a6;
-  background: transparent;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  /* border: 1px solid #dddfe6; */
-  --header-display: none;
-  --header-color: #999;
-}
-
-.ss-folder-list:hover {
-  --header-display: flex;
-  box-shadow: 8px 8px 0px #3a3e513d;
-}
-.ss-folder-list:hover
-  .ss-folder-list-top-transparent {
-  background: #dcdee5;
-  border-radius: unset;
-}
-.ss-folder-list:hover .ss-folder-list-top,
-.ss-folder-list:hover .ss-folder-list-right {
-  border-radius: unset;
-}
-.ss-folder-list:hover .cart-list-setting {
-  display: block;
-}
-/* .ss-folder-list:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dcdee5;
-} */
-.ss-folder-list.active{
-  box-shadow: 8px 8px 0px #3a3e513d;
-}
-.ss-folder-list.active .header {
-  border-radius: unset;
-}
-.ss-folder-list.active
-  .ss-folder-list-top-transparent {
-  background: #585e6e;
-  border-radius: unset;
-}
-/* .ss-folder-list.active::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #585e6e;
-} */
-
-.ss-folder-list .active {
-  border: 1px solid #ddd;
-}
-
-.ss-folder-list .action-bar {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.ss-folder-list > div.action-bar:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.ss-folder-list .header {
-  background-color: #fafbfe;
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 20px;
-  right: 8px;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.ss-folder-list .header:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-.ss-folder-list .header:hover .cart-list-setting::before {
-  color: #ffffff;
-}
-.ss-folder-list .body {
-  margin: 20px 0 0 0;
-  height: calc(100% - 20px);
-  background: #fafbfe;
-}
-
-.ss-folder-list .box-header > div:first-child {
-  color: #333333;
-  font-size: 20px;
-  line-height: 2em;
-}
-.ss-folder-list .box-header,
-.ss-folder-list .box-body {
-  background-color: #fafbfe;
-  padding: 0 25px;
-}
-.ss-folder-list .box-body {
-  /* height: 140px; */
-  color: #333;
-  padding: 10px 25px ;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: flex-end;
-  --right-padding-left: 20px;
-  --right-width: calc(100% - 210px);
-}
-
-.ss-folder-list .no-thumb {
-  --right-padding-left: 0;
-  --right-width: 100%;
-}
-
-.ss-folder-list .left {
-  width: 215px !important;
-  height: 121px !important;
-  border: 1px solid #f6f6f6;
-}
-
-.ss-folder-list .left > img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-  display: block;
-}
-
-.ss-folder-list .right {
-  width: var(--right-width);
-  padding-left: var(--right-padding-left);
-  padding-top: 5px;
-}
-
-.ss-folder-list .right .title {
-  font-size: 16px;
-  color: #666666;
-  line-height: 2em;
-  /* padding-right: 1em; */
-  line-height: 24px;
-  display: -webkit-box;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 1;
-  -webkit-box-orient: vertical;
-}
-
-.ss-folder-list .desc {
-  margin-top: 10px;
-  font-size: 14px;
-  color: #999999;
-  line-height: 1.8em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  gap: 20px;
-}
-/* 知识库文件夹结束 */
-
-/* 一级页面卡片左右结构开始 */
-.item-container {
-  width: 702px;
-  height: 148px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  --header-display: none;
-  --header-color: #999;
-}
-
-.item-container:hover {
-  --header-display: flex;
-}
-
-.item-container:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dddfe6;
-}
-
-.item-container .active {
-  border: 1px solid #ddd;
-}
-
-.item-container .header {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.item-container .header:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.item-container .body {
-  height: 100%;
-  padding: 12px var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.item-container .left {
-  padding: 10px;
-  width: 150px;
-}
-
-.item-container .right {
-  width: calc(100% - 150px);
-}
-
-.item-container .right .title {
-  font-size: 22px;
-  color: #333;
-  line-height: 2em;
-  padding-right: 1em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.item-container .desc {
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.item-container .progress {
-  margin-top: 5px;
-  background: #edeff0;
-  width: 100%;
-  height: 22px;
-  border-radius: 11px;
-  padding: 0 65px 0 10px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  cursor: pointer;
-}
-
-.item-container .progress:hover {
-  --progress-color: #006cf1;
-}
-
-.item-container  .progress>div {
-  height: 4px;
-  position: relative;
-  border-radius: 2px;
-  background: var(--progress-color, #666666);
-}
-
-.item-container  .progress>div>div {
-  position: absolute;
-  top: 50%;
-  left: calc(100% + 10px);
-  transform: translateY(-50%);
-  font-size: 12px;
-}
-
-.page-container .content-area .left {
-  width: calc(100% - var(--project-detail-width) - 6px);
-  height: 100%;
-  overflow-y: auto;
-  /* margin-right: 6px; */
-}
-
-.page-container .content-area .left .left-content {
-  width: 100%;
-  padding: 10px;
-  display: flex;
-  flex-wrap: wrap;
-  align-content: flex-start;
-  gap: 16px;
-  overflow-y: hidden;
-}
-
-/* 一级页面卡片左右结构结束 */
-
-/* 一级页面卡片上下结构开始 */
-.item-container2 {
-  width: 573px;
-  height: 170px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  border: 1px solid #dddfe6;
-  --header-display: none;
-  --header-color: #999;
-}
-
-.item-container2:hover {
-  --header-display: flex;
-}
-
-.item-container2:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dddfe6;
-}
-
-.item-container2 .active {
-  border: 1px solid #ddd;
-}
-
-.item-container2 .header {
-  padding: 10px 60px 2px 20px;
-}
-
-.item-container2 .title {
-  font-size: 22px;
-  color: #333;
-  line-height: 2em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.item-container2 .body {
-  padding: 0 var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.item-container2 .body>div {
-  height: 100px;
-}
-
-.item-container2 .body .left {
-  width: 180px;
-  background: #fafbfe;
-  border: 1px solid #f6f6f6;
-}
-
-.item-container2 .body .left img {
-  width: 100%;
-  height: 100%;
-}
-
-.item-container2 .body .right {
-  width: calc(100% - 180px);
-  padding: 5px 0 0 20px;
-}
-
-.item-container2  .content {
-  height: 60px;
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-  display: -webkit-box;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.item-container2  .tip {
-  margin-top: 5px;
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.item-container2 .action-bar {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.item-container2 .action-bar:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.item-container2 .progress {
-  margin-top: 5px;
-  background: #edeff0;
-  width: 100%;
-  height: 22px;
-  border-radius: 11px;
-  padding: 0 65px 0 10px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  cursor: pointer;
-}
-
-.item-container2 .progress:hover {
-  --progress-color: #006cf1;
-}
-
-.item-container2 .progress>div {
-  height: 4px;
-  position: relative;
-  border-radius: 2px;
-  background: var(--progress-color, #666666);
-}
-
-.item-container2 .progress>div>div {
-  position: absolute;
-  top: 50%;
-  left: calc(100% + 10px);
-  transform: translateY(-50%);
-  font-size: 12px;
-}
-
-/* 一级页面卡片上下结构结束 */
-
-
-.form-container {
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  padding-right: 6px;
-  position: relative;
-}
-
-.form-container .content-box {
-  height: calc(100% - 80px);
-  overflow-y: auto;
-  padding: 25px 24px;
-  box-sizing: border-box;
-}
-
-.form-container .content-box .table-container {
-  width: 100%;
-  border-collapse: collapse;
-  font-size: 16px;
-  color: #333;
-  table-layout: fixed;
-}
-
-
-.form-container th {
-  /* width: 200px; */
-  height: 60px;
-  text-align: right;
-  font-weight: normal;
-  background: #f8f9fb;
-  padding: 15px;
-  color: #666666;
-  border: 1px solid #e2e4ec;
-  font-size: 16px;
-}
-
-.form-container td { 
-  /* width: 360px; //不写死 td 的宽度 Xu(20251208)*/ 
-  height: 60px;
-  padding: 0;
-  box-sizing: border-box;
-  border: 1px solid #e2e4ec;
-  position: relative;
-}
-
-.form-container .required {
-  position: absolute;
-
-  height: 100%;
-  width: 0;
-  top: 0;
-  left: 0;
-  border-left: 2px solid #ff0000;
-}
-
-.form-container .photo {
-  width: 100%;
-  /* height: 240px; */
-  display: flex;
-  flex-direction: row;
-  /* justify-content: space-between; */
-  align-items: flex-end;
-  padding: 15px;
-  gap: 15px;
-}
-
-
-
-/* .form-container .photo>.left {
-  height: 214px;
-  border-radius: 2px;
-  position: relative;
-  padding: 0 5px;
-} */
-
-.form-container .left>div.content {
-  width: 100%;
-  height: 100%;
-  background: #ebebeb;
-}
-
-.form-container .left>div.content>div.icon {
-  position: absolute;
-  top: 30px;
-  left: 50%;
-  transform: translateX(-50%);
-}
-
-.form-container .left>div.content>div.text {
-  position: absolute;
-  left: 50%;
-  bottom: 35px;
-  transform: translateX(-50%);
-  font-size: 16px;
-}
-
-.form-container .right {
-  display: flex;
-  align-items: flex-end;
-  justify-content: center;
-}
-
-.form-container .right>div.content {
-  width: 144px;
-  height: 144px;
-  background: #ebebeb;
-  opacity: 1;
-  border: 1px solid #edeff0;
-  border-radius: 50%;
-  position: relative;
-}
-
-.form-container .right>div.content>div.icon {
-  position: absolute;
-  top: 20px;
-  left: 50%;
-  transform: translateX(-50%);
-}
-
-.form-container .right>div.content>div.text {
-  position: absolute;
-  bottom: 25px;
-  left: 50%;
-  transform: translateX(-50%);
-}
-
-.form-container td>.input {
-  width: 100%;
-  height: 100%;
-}
-
-.form-container td>.area {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  width: 100%;
-  height: 100%;
-}
-
-.form-container td>.area>div {
-  height: 100%;
-}
-
-.form-container  td>div.img {
-  height: 120px;
-  display: block;
-  padding: 8px 22px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.form-container  td>div.img>img {
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.form-container  td>div.p {
-  font-size: 16px;
-  color: #333333;
-  padding: 20px 22px;
-}
-
-
-
-.input-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-}
-
-.input-container>div {
-  position: absolute;
-}
-
-.input-container .input {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  position: relative;
-  --input-required-display: block;
-  display: flex;
-  align-items: center;
-}
-
-.input-container>.input>input,
-.input-container>.input>textarea {
-  outline: unset;
-  border: unset;
-  background: unset;
-  width: 100%;
-  height: 100%;
-  font-size: inherit;
-  /* 不在这里设置padding,由后面的规则或JS设置 */
-  box-sizing: border-box;
-  text-overflow: ellipsis;
-  resize: none; /* 禁止textarea手动调整大小 */
-  overflow: hidden; /* 完全隐藏滚动条 */
-  line-height: 20px; /* 设置行高 */
-}
-.input-container>.input>textarea {
-  padding-left: 15px; /* 左右padding保持 */
-  padding-right: 15px;
-  font-family: inherit; /* 继承字体 */
-  /* 上下padding由JS动态设置,不在这里固定 */
-}
-.input-container>.input>input {
-  padding: 0 15px; /* input元素的padding */
-}
-.input-container>.input>input::placeholder,
-.input-container>.input>textarea::placeholder,
-.select-container .input>input::placeholder,
-.custom-date-picker .el-input__inner::placeholder,
-.custom-date-picker .el-input__inner::placeholder{
-  color: #999;
-}
-
-/* 附件按钮样式 */
-.fj-button {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-  width: 60px;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-direction: column;
-  color: #666666;
-  font-size: 16px;
-  gap: 5px;
-  background: #f0f0f0;
-  border: none;
-  border-left: 1px solid #ddd;
-  cursor: pointer;
-  z-index: 10;
-  padding: 0;
-}
-.fj-button:hover {
-  background: #e0e0e0;
-}
-/* 级联 */
-.ss-ccp-container{
-  float: left;
-}
-/* 选择框样式开始 */
-.select-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-}
-
-.select-container>div {
-  position: absolute;
-  z-index: 4;
-}
-
-.select-container .input {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  cursor: pointer;
-}
-
-.select-container .input>input {
-  outline: unset;
-  border: unset;
-  background: unset;
-  width: 100%;
-  height: 100%;
-  padding: 0 15px;
-  font-size: inherit;
-  color: #000;
-  /* pointer-events: none; */
-}
-.select-container .input>input::placeholder{
-  color: #999;
-}
-.select-container .suffix {
-  position: absolute;
-  top: 0;
-  right: 0;
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  padding: 15px 0;
-  z-index: 11;
-}
-
-.select-container .suffix>div{
-  width: 37px;
-  height: 37px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  opacity: 1;
-  background: var(--icon-bg, transparent);
-  color: #c3c7cb;
-  border-radius: 4px;
-}
-
-.select-container .suffix>div.select {
-  --icon-bg: #393d51;
-  color: #ffffff !important;
-}
-
-
-.select-container .popup-win {
-  width: auto;
-  min-width: 100%;
-  left: 0;
-  /* transform: translateX(-50%); */
-  z-index: 999;
-  padding-top: 10px;
-  --popup-content-bg: #393d51;
-}
-
-.select-container .popup-win.bottom {
-  top: calc(100% - var(--select-popup-bottom-offset, 10px));
-}
-
-.select-container .popup-win.bottom::after {
-  content: "";
-  width: 14px;
-  height: 14px;
-  background: var(--popup-content-bg);
-  position: absolute;
-  right: 28px;
-  transform: rotate(45deg);
-  top: 5px;
-}
-.select-container .popup-win.top {
-  bottom: calc(100%);
-}
-
-.select-container .popup-win.top::after {
-  content: "";
-  width: 14px;
-  height: 14px;
-  background: var(--popup-content-bg);
-  position: absolute;
-  right: 28px;
-  transform: rotate(45deg);
-  bottom: -5px;
-}
-
-.select-container .popup-content {
-  background: var(--popup-content-bg);
-  position: relative;
-  border-radius: 4px;
-  color: #fff;
-  padding: 15px 2px;
-}
-
-.select-container .popup-win .content-area {
-  width: auto;
-  max-height: 200px;
-  overflow-y: auto;
-  --scrollbar-track-color: transparent;
-  --scrollbar-thumb-color: #000;
-}
-
-
-.select-container .popup-win .content-area::-webkit-scrollbar {
-  width: 10px;
-  height: 10px;
-}
-
-.select-container .popup-win .content-area::-webkit-scrollbar-thumb {
-  border-radius: 10px;
-  background: var(--scrollbar-thumb-color, transparent);
-}
-
-.select-container .popup-win .content-area::-webkit-scrollbar-track {
-  border-radius: 10px;
-  background: var(--scrollbar-track-color, transparent);
-}
-
-.select-container .popup-win .content-area>div {
-  width: auto;
-  white-space: nowrap;
-  position: relative;
-  height: 36px;
-  padding: 0 22px;
-  font-size: 14px;
-  color: var(--item-color, #fff);
-  background: var(--item-bg, transparent);
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  cursor: pointer;
-}
-
-.select-container .popup-win .content-area>div:hover {
-  --item-color: #000;
-  --item-bg: #fffdfd;
-}
-
-.select-container .popup-win .content-area>div>span.check-icon {
-  position: absolute;
-  top: 50%;
-  transform: translateY(-50%) scale(0.75);
-  left: 0;
-  padding-right: 8px;
-  visibility: var(--check-icon-visible, hidden);
-}
-
-.select-container .popup-win .content-area>div.active {
-  --check-icon-visible: visible;
-}
-
-/* radio */
-.radio-container {
-  display: flex;
-  align-content: flex-start;
-  gap: 20px;
-  padding: 0 20px;
-}
-
-.radio-container>div {
-  position: relative;
-  padding: 5px 10px;
-  border: 1px solid #bfc1c6;
-  border-radius: 2px;
-  overflow: hidden;
-  cursor: pointer;
-  text-align: center;
-  --radio-color: #c3c6ca;
-  color: var(--radio-color);
-}
-
-.radio-container .checked {
-  --radio-color: #393d51;
-}
-
-.radio-container .mark {
-  position: absolute;
-  bottom: 1px;
-  right: 0;
-  color: inherit;
-  width: 18px;
-  height: 18px;
-}
-
-.radio-container2 {
-  display: inline-flex;
-  align-content: flex-start;
-  gap: 20px;
-  margin-left: 15px;
-}
-
-.radio-container2>div {
-  position: relative;
-  padding: 5px 18px;
-  border: 1px solid #bfc1c6;
-  border-radius: 2px;
-  overflow: hidden;
-  cursor: pointer;
-  text-align: center;
-  --radio-color: #c3c6ca;
-  color: var(--radio-color);
-}
-
-.radio-container2 .checked {
-  --radio-color: #393d51;
-}
-
-.radio-container2 .mark {
-  position: absolute;
-  bottom: 1px;
-  right: 0;
-  color: inherit;
-  width: 18px;
-  height: 18px;
-}
-/* textarea */
-
-.textarea-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-}
-
-.textarea-container>div {
-  position: absolute;
-}
-
-.textarea-container .textarea {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-}
-
-.textarea-container textarea {
-  outline: unset;
-  border: unset;
-  background: unset;
-  width: 100%;
-  height: 100%;
-  padding: 15px;
-  line-height: 2em;
-  font-size: inherit;
-  resize: unset;
-}
-.textarea-container textarea::placeholder{
-  color: #999;
-}
-/* 错误提示开始 */
-.err-tip {
-  --err-tip-color: #ef5d0c;
-  font-size: 12px;
-  color: var(--err-tip-color);
-  bottom: 0;
-  left: 0;
-  width: 100%;
-  cursor: pointer;
-  position: relative;
-  line-height: 15px;
-}
-
-.err-tip>div.tip {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 100%;
-  padding: 5px 15px 2px 15px;
-}
-
-.err-tip::after {
-  content: "";
-  position: absolute;
-  bottom: 0;
-  left: 2px;
-  width: calc(100% - 2px* 2);
-  /* border-bottom: 2px solid var(--err-tip-color); */
-  z-index: 1;
-}
-
-.err-tip:hover {
-  --more-tip-visible: visible;
-  --more-tip-opacity: 1;
-}
-
-.err-tip>.tip-more {
-  transition: opacity 0.2s ease-in-out 0.6s;
-  opacity: var(--more-tip-opacity, 0);
-  visibility: var(--more-tip-visible, hidden);
-  background: #ffffff;
-  border-radius: 4px;
-  border: 1px solid var(--err-tip-color);
-  position: absolute;
-  top: 0;
-  left: 2px;
-  width: calc(100% - 2px* 2);
-  padding: 4px 12.5px;
-  z-index: 5;
-}
-.err-tip>.tip-more>p{
-  margin: 0;
-  background-color: #ffffff;
-}
-
-/* 错误提示开始 */
-.validate-vline{
-  width:6px;
-  height:100%;
-  position:absolute;
-  left:0;
-  top:0;
-  background-color:#ff0000;
-}
-.validate-tip {
-  --err-tip-color: #ef5d0c;
-  font-size: 16px;
-  color: var(--err-tip-color);
-  bottom: 0;
-  left: 0;
-  width: 100%;
-  cursor: pointer;
-  position: relative;
-  line-height: 15px;
-}
-
-.validate-tip>div.tip {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 100%;
-  padding: 5px 15px 2px 10px;
-}
-
-.validate-tip::after {
-  content: "";
-  position: absolute;
-  bottom: 0;
-  left: 2px;
-  width: calc(100% - 2px* 2);
-  /* border-bottom: 2px solid var(--err-tip-color); */
-  z-index: 1;
-}
-
-.validate-tip:hover {
-  --more-tip-visible: visible;
-  --more-tip-opacity: 1;
-}
-
-.validate-tip>.tip-more {
-  transition: opacity 0.2s ease-in-out 0.6s;
-  opacity: var(--more-tip-opacity, 0);
-  visibility: var(--more-tip-visible, hidden);
-  background: #fff;
-  border-radius: 4px;
-  border: 1px solid var(--err-tip-color);
-  position: absolute;
-  top: 0;
-  left: 2px;
-  width: calc(100% - 2px* 2);
-  padding: 4px 12.5px;
-  z-index: 3;
-}
-/* 错误提示结束 */
-.floating-div {
-  background-color: white;
-  position: absolute;
-  padding: 5px;
-  width: 100%;
-  /* top和bottom会通过JS动态设置 */
-  z-index: 11;
-  left: 0;
-  border: 1px solid #ccc;
-  height: auto;
-  box-sizing: border-box;
-  /* 其他样式 */
-}
-
-.floating-div textarea {
-  /* 设置 textarea 的样式 */
-  width: 100%;
-  resize: none;
-  border: none;
-  outline: none;
-  height: auto;
-  /* overflow-y: hidden; 隐藏滚动条 */
-  max-height: calc(20px * 5 + 10px); /* 统一为5行 + padding */
-  line-height: 20px;
-  font-size: 16px;
-  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
-  /* padding: 5px; */
-}
-
-/* 弹窗头部样式开始 */
-.header-container {
-  width: 100%;
-  height: 100%;
-  padding-left: var(--space-size);
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.header-container .title {
-  font-size: 18px;
-}
-
-.header-container .title.visibility {
-  --title-visibility: visible;
-}
-
-.header-container .title:hover {
-  --header-icon-refresh: block;
-  --header-icon-normal: none;
-}
-
-.header-container .normal {
-  display: var(--header-icon-normal);
-}
-
-.header-container .hover {
-  display: var(--header-icon-refresh);
-  cursor: pointer;
-}
-
-.header-container .handle-bar {
-  --pop-win-header-color: #c3c6ca;
-  color: var(--pop-win-header-color);
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.header-container .left-bar {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 6px;
-  padding-right: 14px;
-  color: inherit;
-  margin-right: 54px;
-}
-
-.header-container .left-bar .dialog-icon {
-  cursor: pointer;
-  padding: 6px;
-  width: 36px;
-  height: 36px;
-  border-radius: 4px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.header-container .left-bar .dialog-icon:hover {
-  background: #c4c7cc;
-  color: #fff;
-}
-
-.header-container .setting {
-  visibility: var(--block-title-visible, hidden);
-  width: 60px;
-  height: 60px;
-  border-top-right-radius: 4px;
-  position: relative;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-}
-
-.header-container .setting:hover {
-  color: #fff;
-  background: #575d6d;
-}
-
-.header-container .setting:hover::before {
-  display: none;
-}
-
-.header-container .close-bar {
-  width: 60px;
-  height: 60px;
-  border-top-right-radius: 4px;
-  position: relative;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-  position: absolute;
-  right: 0;
-  top: 0;
-}
-
-.header-container .close-bar::before {
-  width: 0;
-  height: 24px;
-  border-left: 1px solid #c3c6ca;
-  content: "";
-  position: absolute;
-  top: 50%;
-  left: 0;
-  transform: translateY(-50%);
-}
-
-.header-container .close-bar:hover {
-  color: #fff;
-  background: #575d6d;
-}
-
-.header-container .close-bar:hover::before {
-  display: none;
-}
-/* 弹窗头部样式结束 */
-
-
-/* 弹窗样式开始 */
-.popup-container {
-  height: 100%;
-  width: 100%;
-  background: var(--white);
-  font-size: initial;
-  box-shadow: 10px 0px 10px 0px rgba(0, 0, 0, 0.3);
-  border-radius: 4px;
-}
-
-
-.popup-container>div {
-  width: 100%;
-}
-
-.popup-container .header {
-  height: 60px;
-  border-bottom: 2px solid var(--lightgray);
-  background-color: white;
-  border-radius: 4px;
-}
-
-.popup-container .body {
-  height: calc(100% - 60px);
-}
-
-.popup-container .dialog-body {
-  width: 500px;
-  height: 300px;
-  background: red;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  position: absolute;
-}
-
-.dialog-container {
-  width: 100%;
-  height: 100%;
-  position: fixed;
-  top: 0;
-  left: 0;
-  pointer-events: none;
-  background: transparent;
-  font-size: 0;
-  z-index: 1000;
-}
-
-.dialog-container .mark-content {
-  width: 100%;
-  height: 100%;
-  pointer-events: all;
-  position: relative;
-  -webkit-backdrop-filter: blur(3px);
-  backdrop-filter: blur(3px);
-  background: rgba(0, 0, 0, 0.2);
-}
-
-/* 登录部分 */
-
-.login-container {
-  width: 100%;
-  height: 100%;
-  background-size: cover;
-  background-color: antiquewhite;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  position: fixed;
-  z-index: 99999;
-  left: 0;
-  top: 0;
-}
-
-.login-container>div {
-  height: 100%;
-}
-
-.login-container .left {
-  width: calc(100% - 510px);
-}
-
-.login-container .right {
-  width: 510px;
-  background: rgba(255, 255, 255, 0.2);
-  position: relative;
-}
-
-.login-container .right>div.content-area {
-  height: calc(100% - 70px);
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.login-container .login-box {
-  width: 432px;
-  height: 494px;
-  background: rgba(255, 255, 255, 0.9);
-  box-shadow: 0px 5px 5px 0px rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
-}
-
-.login-container .login-box>div {
-  width: 100%;
-}
-
-.login-container .box-header {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  padding: 42px;
-}
-
-.login-container .box-header>img {
-  width: 348px;
-  height: 98px;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.login-container .box-container {
-  height: calc(100% - 182px - 40px);
-  position: relative;
-}
-
-.login-container .box-form {
-  padding: 0 37px;
-}
-
-.login-container>div.right>div.content-area>div.login-box>div.box-container>form.box-form>div.form-item {
-  width: 100%;
-  height: 37px;
-  position: relative;
-  display: flex;
-  margin-bottom: 20px;
-  background: #ffffff;
-  border: 1px solid #575d6d;
-  border-radius: 4px;
-}
-
-.login-container .icon {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  width: 46px;
-  height: 100%;
-  background: #575d6d;
-  color: #fff;
-}
-
-.login-container .icon-container {
-  display: block;
-}
-
-.login-container .check-code {
-  width: 140px;
-  height: 35px;
-}
-
-.login-container .check-code img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-}
-
-.login-container .input,
-.login-container .select {
-  flex: 1;
-  height: 100%;
-}
-
-.login-container .input input,
-.login-container .select input,
-.login-container .input select,
-.login-container .select select {
-  width: 100%;
-  height: 100%;
-  outline: none;
-  border: unset;
-  background: transparent;
-  padding: 0 10px;
-  font-size: 18px;
-  color: #333;
-}
-
-.login-container .form-bar {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.login-button {
-  cursor: pointer;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 10px;
-  width: 161px;
-  height: 37px;
-  background: #ffffff;
-  border-radius: 4px;
-  outline: unset;
-  font-size: 18px;
-  --btn-color: #333333;
-  --btn-bg: #fff;
-  --btn-border-color: #575d6d;
-  color: var(--btn-color);
-  background-color: var(--btn-bg);
-  border: 1px solid var(--btn-border-color);
-}
-
-.login-button[theme="primary"],
-.login-button:hover {
-  --btn-bg: #575d6d;
-  --btn-color: #fff;
-}
-
-.login-container .err-tip {
-  bottom: -32px;
-  position: absolute;
-  padding-left: 40px;
-}
-
-.login-container .err-tip::after {
-  bottom: -8px;
-}
-
-.login-container .time {
-  position: absolute;
-  left: 10px;
-  width: 12px;
-  bottom: 0;
-}
-
-.login-container .time>div {
-  width: 12px;
-  height: 12px;
-  opacity: 1;
-  margin-bottom: 8px;
-  border-radius: 50%;
-  border: 1px solid #ef5d0c;
-}
-
-.login-container .fill {
-  background: #ef5d0c;
-}
-
-.login-container .box-container>div.err-tip>div.tip {
-  color: #ef5d0c;
-  font-size: 18px;
-  bottom: -30px;
-  left: 10px;
-  padding: 5px 15px 2px 0;
-}
-
-.login-container .box-footer {
-  height: 40px;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.login-container .box-footer>div {
-  height: 100%;
-}
-
-.login-container .box-footer>div.left {
-  width: calc(100% - 40px);
-}
-
-.login-container .box-footer>div.right {
-  width: 40px;
-  cursor: pointer;
-}
-
-.login-container .footer {
-  padding: 0 40px;
-  height: 70px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  font-size: 18px;
-  color: #fff;
-}
-
-.login-container .mask {
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  z-index: 100;
-  position: absolute;
-  background: rgba(255, 255, 255, 0.2);
-  padding-bottom: 70px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.login-container .qrcode-box {
-  width: 432px;
-  height: 494px;
-  background: rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  position: relative;
-}
-
-.login-container .qrcode-box::after {
-  content: "";
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  left: 0;
-  z-index: 0;
-  background: rgba(0, 0, 0, 0.2);
-  filter: blur(1px);
-}
-
-.login-container .qr {
-  width: 340px;
-  height: 340px;
-  position: absolute;
-  z-index: 1;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  background: #f7f7f7;
-  box-shadow: 5px 0px 5px 0px rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
-  padding: 20px;
-}
-
-.login-container .qr>img {
-  user-drag: none;
-  -webkit-user-drag: none;
-  -khtml-user-drag: none;
-  -webkit-touch-callout: none;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  user-select: none;
-  width: 100%;
-  height: 100%;
-}
-
-.login-container>div.right>div.mask>div.qrcode-box>div.tip {
-  position: absolute;
-  bottom: 1em;
-  left: 0;
-  width: 100%;
-  text-align: center;
-  z-index: 10;
-  font-size: 18px;
-  color: #ff0000;
-}
-
-.lockscreen-container .login-box{
-  height: auto;
-  position: relative;
-}
-.lockscreen-container .box-header{
-  display: flex;
-  flex-direction: column;
-  padding: 15px;
-  margin: 41px 0;
-}
-.lockscreen-container .box-header img{
-  width: 100px;
-  height: 100px;
-  border-radius: 50%;
-}
-.lockscreen-container .right{
-  opacity: 0;
-  visibility: hidden;
-  transition: opacity 0.3s ease, visibility 0.3s ease;
-}
-  
-.lockscreen-container .right--visible {
-  opacity: 1;
-  visibility: visible;
-}
-.lockscreen-container  .left {
-  cursor: pointer;
-}
-/* 登陆相关结束  */
-
-/* 首页组件头部 */
-.edit-box-header-container {
-  width: 100%;
-  height: 100%;
-  padding-left: var(--space-size);
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.edit-box-header-container .title {
-  font-size: 18px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-  visibility: var(--title-visibility, hidden);
-  --header-icon-refresh: none;
-  --header-icon-normal: block;
-}
-
-.edit-box-header-container .title.visibility {
-  --title-visibility: visible;
-}
-
-.edit-box-header-container .title:hover {
-  --header-icon-refresh: block;
-  --header-icon-normal: none;
-}
-
-.edit-box-header-container .normal {
-  display: var(--header-icon-normal);
-}
-
-.edit-box-header-container .hover {
-  display: var(--header-icon-refresh);
-  cursor: pointer;
-}
-
-.edit-box-header-container .handle-bar {
-  --pop-win-header-color: #c3c6ca;
-  color: var(--pop-win-header-color);
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.edit-box-header-container .left-bar {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 12px;
-  padding-right: 14px;
-  color: inherit;
-}
-
-.edit-box-header-container .left-bar .icon-container {
-  cursor: pointer;
-  padding: 6px;
-  width: 36px;
-  height: 36px;
-  border-radius: 4px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.edit-box-header-container .left-bar .icon-container:hover {
-  background: #c4c7cc;
-  color: #fff;
-}
-
-.edit-box-header-container .setting {
-  visibility: var(--block-title-visible, hidden);
-  width: 60px;
-  height: 60px;
-  border-top-right-radius: 4px;
-  position: relative;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-}
-
-.edit-box-header-container .setting:hover {
-  color: #fff;
-  background: #575d6d;
-}
-
-.edit-box-header-container .setting:hover::before {
-  display: none;
-}
-
-.user-info-container {
-  width: 590px;
-  height: 400px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: var(--white);
-  border-radius: 2px;
-  --block-title-visible: hidden;
-}
-
-.user-info-container:hover {
-  --block-title-visible: visible;
-  box-shadow: 0 0 0 8px #dddfe6;
-  border-radius: 1px;
-}
-
-
-.user-info-container .body {
-  padding: 0 var(--space-size, 20px) var(--space-size, 20px) var(--space-size, 20px);
-}
-
-.user-info-container  .user-info {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.user-info-container .avatar {
-  width: 94px;
-  height: 94px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-}
-
-.user-info-container  .info {
-  width: calc(100% - 120px);
-}
-
-.user-info-container  .info>p {
-  padding: 0;
-  margin: 0;
-  cursor: pointer;
-}
-
-.user-info-container  .info>p:first-child {
-  font-size: 16px;
-  color: #333;
-  margin-bottom: 10px;
-}
-
-.user-info-container  .info>p:not(:first-child) {
-  font-size: 14px;
-  color: #808080;
-  line-height: 22px;
-}
-
-.user-info-container  .progress-bar {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.user-info-container .progress {
-  width: calc(100% - 0px);
-  height: 20px;
-  font-size: 12px;
-  padding: 0 90px 0 10px;
-  background: var(--lightgray);
-  border-radius: 10px;
-  --progress-color: #666666;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.user-info-container .progress:hover {
-  --progress-color: #0072f1;
-}
-
-.user-info-container .line {
-  background: var(--progress-color);
-  width: 0%;
-  height: 4px;
-  position: relative;
-  border-radius: 2px;
-}
-
-.user-info-container .line>div {
-  position: absolute;
-  top: 50%;
-  left: calc(100% + 1em);
-  transform: translateY(-50%);
-  width: 5.5em;
-}
-
-.user-info-container .bar {
-  padding-left: 10px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  height: 0px;
-  cursor: pointer;
-}
-
-.user-info-container .other-info {
-  padding: 10px 0;
-  color: #666;
-  font-size: 16px;
-}
-
-.user-info-container  .other-info>div {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 20px;
-  padding: 15px 0;
-}
-
-.edit-box-container {
-  width: 100%;
-  height: 100%;
-  position: relative;
-  overflow: hidden;
-}
-
-.edit-box-container>div {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-}
-
-.edit-box-container .edit-tools {
-  --direction-icon-visible: hidden;
-  display: var(--edit-box-tools-display, none);
-  z-index: 2;
-}
-
-.edit-box-container .edit-tools:hover,
-.edit-box-container .edit-tools.active {
-  --direction-icon-visible: visible;
-}
-
-.edit-box-container .edit-tools>div {
-  position: absolute;
-  pointer-events: all;
-  cursor: pointer;
-  display: flex;
-}
-
-.edit-box-container .close {
-  height: 36px;
-  width: 36px;
-  top: 0;
-  right: 0;
-  color: var(--edit-tool-bar-close-color, #c3c6ca);
-  visibility: var(--direction-icon-visible);
-}
-
-.edit-box-container .close:hover {
-  --edit-tool-bar-close-color: #575d6d;
-}
-
-.edit-box-container .right-center {
-  visibility: var(--direction-icon-visible);
-  height: 30px;
-  width: 30px;
-  top: 50%;
-  transform: translateY(-50%);
-  right: 0;
-  justify-content: flex-end;
-  align-items: flex-end;
-}
-
-.edit-box-container .right-center::before {
-  content: "";
-  right: 0;
-  top: 0;
-  width: 4px;
-  height: 100%;
-  background: #999999;
-  border-radius: 2px;
-  position: absolute;
-}
-
-.edit-box-container .right-center .icon {
-  height: 30px;
-  width: 30px;
-  transform: rotate(90deg);
-}
-
-.edit-box-container .right-bottom {
-  visibility: var(--direction-icon-visible);
-  width: 36px;
-  height: 36px;
-  bottom: 0;
-  right: 0;
-  justify-content: flex-end;
-  align-items: flex-end;
-}
-
-.edit-box-container .right-bottom::before {
-  content: "";
-  right: 0;
-  top: 0;
-  width: 3px;
-  height: 100%;
-  background: #999999;
-  border-radius: 2px;
-  position: absolute;
-}
-
-.edit-box-container .right-bottom::after {
-  content: "";
-  left: 0;
-  bottom: 0;
-  width: 100%;
-  height: 3px;
-  background: #999999;
-  border-radius: 2px;
-  position: absolute;
-}
-
-.edit-box-container .right-bottom>.icon {
-  width: 30px;
-  height: 30px;
-  transform: rotate(-45deg);
-}
-
-.edit-box-container .bottom-center {
-  visibility: var(--direction-icon-visible);
-  height: 36px;
-  width: 36px;
-  left: 50%;
-  transform: translateX(-50%);
-  bottom: 0;
-  justify-content: center;
-  align-items: flex-end;
-}
-
-.edit-box-container .bottom-center::before {
-  content: "";
-  left: 0;
-  bottom: 0;
-  width: 100%;
-  height: 4px;
-  background: #999999;
-  border-radius: 2px;
-  position: absolute;
-  z-index: 0;
-}
-
-.edit-box-container .bottom-center>.icon {
-  height: 30px;
-  width: 30px;
-  transform: rotate(180deg);
-}
-
-.edit-box-container>.content-area {
-  z-index: 1;
-}
-
-.page-content {
-  width: 100%;
-  height: 100%;
-  padding: 20px;
-  display: flex;
-  flex-wrap: wrap;
-  align-content: flex-start;
-  gap: 15px;
-  overflow-y: hidden;
-  background: var(--lightgray);
-}
-
-.page-content:hover {
-  overflow-y: auto;
-}
-
-.folder-container {
-  width: 100%;
-  height: 100%;
-  overflow-y: hidden;
-}
-
-.folder-container:hover {
-  overflow-y: auto;
-}
-
-.folder-container .group-item {
-  --hover-bg: #edf1f5;
-  padding-right: 6px;
-  color: #333;
-}
-
-.folder-container  .group-title {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-  color: #333;
-  cursor: pointer;
-  padding: 15px var(--space-size, 20px);
-}
-
-.folder-container .group-title:hover {
-  background: var(--hover-bg);
-}
-
-.folder-container .group-title>div.folder {
-  position: relative;
-}
-
-.folder-container .group-title>div.folder::after {
-  content: attr(data-num);
-  position: absolute;
-  font-size: 14px;
-  color: #999;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -45%) scale(0.9);
-}
-
-.folder-container .group-childs {
-  padding-left: 40px;
-  margin: 0;
-}
-
-.folder-container .group-childs>li {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  list-style-type: none;
-  cursor: pointer;
-  position: relative;
-  padding: 12px 5px 12px 20px;
-  border-bottom: 1px solid #eee;
-}
-
-.folder-container .group-childs>li::before {
-  position: absolute;
-  content: "";
-  top: 50%;
-  left: 5px;
-  transform: translateY(-50%);
-  width: 0.25em;
-  height: 0.25em;
-  border-radius: 50%;
-  background-color: #666;
-}
-
-.folder-container .group-childs>li:hover {
-  background: var(--hover-bg);
-}
-
-.folder-container .group-childs>li>div:first-child {
-  color: #333;
-  font-size: 16px;
-}
-
-.folder-container .group-childs>li>div:nth-child(2) {
-  color: #999;
-}
-
-.todo-list-container {
-  width: 590px;
-  height: 400px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: var(--white);
-  border-radius: 2px;
-  --block-title-visible: hidden;
-}
-
-.todo-list-container:hover {
-  --block-title-visible: visible;
-  box-shadow: 0 0 0 8px #dddfe6;
-  border-radius: 1px;
-}
-
-.todo-list-container .body {
-  border-top: 1px solid #eaeaea;
-  height: calc(100% - 57px);
-  overflow-y: hidden;
-  padding: 12px 6px 12px 0px;
-  box-sizing: border-box;
-}
-
-.notice-list-container {
-  width: 590px;
-  height: 242px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: var(--white);
-  border-radius: 2px;
-  --block-title-visible: hidden;
-}
-
-.notice-list-container:hover {
-  --block-title-visible: visible;
-  box-shadow: 0 0 0 8px #dddfe6;
-  border-radius: 1px;
-}
-
-.notice-list-container .header {
-  border-bottom: 1px solid #eaeaea;
-}
-
-.notice-list-container .body {
-  width: calc(100% - 6px);
-
-  height: calc(100% - 57px);
-  overflow-y: hidden;
-  padding: 12px var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-}
-
-.notice-list-container .body:hover {
-  overflow-y: auto;
-}
-
-.notice-list-container .body>div {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  padding: 15px 0;
-}
-
-.notice-list-container .body>div>div:first-child {
-  gap: 5px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.notice-list-container .body>div>div:nth-child(2) {
-  color: #999999;
-}
-
-.launch-container {
-  width: 590px;
-  height: 204px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: var(--white);
-  border-radius: 2px;
-  --block-title-visible: hidden;
-}
-
-.launch-container:hover {
-  --block-title-visible: visible;
-  box-shadow: 0 0 0 8px #dddfe6;
-  border-radius: 1px;
-}
-
-.launch-container .body {
-  border-top: 1px solid #eaeaea;
-  height: calc(100% - 57px);
-  overflow-y: auto;
-  padding: 12px var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #808080;
-  display: flex;
-  align-content: flex-start;
-  flex-wrap: wrap;
-  font-size: 12px;
-  gap: 20px;
-}
-
-.launch-container .body>div {
-  cursor: pointer;
-  width: 60px;
-  height: 100px;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-  position: relative;
-}
-
-.launch-container .body>div:hover {
-  --popup-visible: visible;
-}
-
-.launch-container .body>div>.common-icon {
-  color: #b4b5b5;
-  width: 60px;
-  height: 60px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  background: var(--item-bg, transparent);
-  position: relative;
-  --item-mark-color: #999999;
-}
-
-.launch-container .body>div>.common-icon:hover {
-  --item-bg: #edf1f5;
-  --item-mark-color: #3a3e51;
-}
-
-.launch-container .body>div>.common-icon.mark-down::after {
-  content: "";
-  width: 0;
-  height: 0;
-  border-width: 6px 6px 6px 6px;
-  border-style: solid;
-  border-color: transparent var(--item-mark-color) var(--item-mark-color) transparent;
-  position: absolute;
-  bottom: 0;
-  right: 0;
-}
-
-.launch-container  .text {
-  padding-top: 4px;
-  font-size: 16px;
-}
-
-.launch-container .popup {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 130px;
-  height: 90px;
-  --popup-bg: #3a3e51;
-  visibility: var(--popup-visible, hidden);
-  background: var(--popup-bg);
-  padding: 16px 2px 0 2px;
-  border-radius: 4px;
-  z-index: 1111;
-}
-
-.launch-container .popup::before {
-  width: 100%;
-  height: 12px;
-  background: transparent;
-  content: "";
-  position: absolute;
-  top: -12px;
-  left: 0;
-}
-
-.launch-container .popup::after {
-  content: "";
-  background: var(--popup-bg);
-  width: 12px;
-  height: 12px;
-  position: absolute;
-  top: -6px;
-  right: 30px;
-  transform: rotate(45deg);
-}
-
-.launch-container .popup>div {
-  height: 36px;
-  width: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  padding: 0 15px;
-  font-size: 14px;
-  background: var(--item-bg, transparent);
-  color: var(--item-color, #fff);
-}
-
-.launch-container .popup>div:hover {
-  --item-bg: #fff;
-  --item-color: #333;
-}
-
-.statistics-container {
-  width: 1200px;
-  height: 475px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: var(--white);
-  border-radius: 2px;
-  --block-title-visible: hidden;
-}
-
-.statistics-container:hover {
-  --block-title-visible: visible;
-  box-shadow: 0 0 0 8px #dddfe6;
-  border-radius: 1px;
-}
-
-.statistics-container .body {
-  /* border-top: 1px solid #eaeaea; */
-  height: calc(100% - 57px);
-  overflow-y: auto;
-  padding: 12px var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-}
-
-.statistics-container .body .chart-container {
-  width: 100%;
-  height: 100%;
-}
-
-.page-container {
-  width: 100%;
-  height: 100%;
-  /* padding: 20px 0; */
-}
-
-.page-container[sys-mode="edit"] {
-  --edit-box-tools-display: block;
-}
-
-.page-container .search-bar {
-  margin-top: 20px;
-  width: 100%;
-  height: 40px;
-  position: relative;
-}
-
-.page-container .item-content-area {
-  height: calc(100% - 75px);
-  width: 100%;
-  margin-top: 10px;
-  padding: 10px 0 100px 20px;
-  display: flex;
-  flex-wrap: wrap;
-  align-content: flex-start;
-  overflow-y: auto;
-  --project-detail-width: 370px;
-}
-
-.page-container .content-area .pager-bar {
-  width: 100%;
-  height: 80px;
-  padding: 20px;
-}
-
-.page-container .content-area>div.project-detail {
-  padding-right: 20px;
-  width: var(--project-detail-width);
-  height: 100%;
-}
-
-/* 分页开始 */
-.pager-container {
-  width: 98%;
-  margin: 0 auto;
-  /* height: 100%; */
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-}
-
-.pager-container .pager-content {
-  border-radius: 4px;
-  height: 32px;
-  color: #999999;
-  font-size: 18px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-}
-
-.pager-container .pager-content>div {
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.pager-container  .info {
-  padding: 0 20px;
-  border: 1px solid var(--btn-border, #c4c7cc);
-  border-top-left-radius: 4px;
-  border-bottom-left-radius: 4px;
-}
-
-.pager-container .btn>button {
-  height: 100%;
-  background: #edf1f5;
-  width: 84px;
-  outline: unset;
-  cursor: pointer;
-  font-size: inherit;
-  color: var(--btn-color, #999999);
-  border: 1px solid var(--btn-border, #c4c7cc);
-}
-
-.pager-container .btn>button:hover {
-  --btn-border: transparent;
-  --btn-color: #fff;
-  background: #393d51;
-}
-
-.pager-container .btn:last-child>button {
-  border-top-right-radius: 4px;
-  border-bottom-right-radius: 4px;
-}
-
-/* 分页结束 */
-/* 一级页面右边信息栏开始 */
-.info-container {
-  width: 100%;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 2px;
-  position: relative;
-  overflow-y: auto;
-  height: 100%;
-}
-
-.info-container .header {
-  width: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  padding: 10px 20px;
-  border-bottom: 1px solid #cfd2d7;
-}
-
-.info-container .header>div {
-  height: 40px;
-  display: flex;
-  align-items: center;
-}
-
-.info-container .header>div:first-child {
-  width: 80px;
-}
-
-.info-container .header>div:last-child {
-  padding-left: 5px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: flex-end;
-  width: calc(70%);
-  color: #333333;
-  font-size: 18px;
-}
-
-.info-container .header>div:last-child>div {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.info-container .section-container {
-  padding: 0 20px;
-}
-
-.info-container  .section {
-  padding: 8px 0;
-  --title-tip-height: 6px;
-}
-
-.info-container   .section:not(:last-child) {
-  border-bottom: 1px solid #edf1f5;
-}
-
-.info-container   .section:hover {
-  --title-tip-height: 18px;
-}
-
-.info-container   .section>div.title {
-  color: #333333;
-  font-size: 18px;
-  line-height: 3em;
-  position: relative;
-  padding-left: 20px;
-}
-
-.info-container   .section .title:before {
-  transition: height 0.5s;
-  content: "";
-  width: 6px;
-  height: var(--title-tip-height);
-  border-radius: 3px;
-  position: absolute;
-  left: 5px;
-  top: 50%;
-  transform: translateY(-50%);
-  background: #333;
-}
-
-.info-container   .section> .a {
-  --a-color: #333;
-  color: var(--a-color);
-  font-size: 16px;
-  line-height: 2.5em;
-  cursor: pointer;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.info-container   .section .a:hover {
-  --a-color: #006cf1;
-}
-
-.info-container   .section .text {
-  color: #333333;
-  font-size: 16px;
-  line-height: 2.5em;
-}
-
-/* 一级页面右边信息栏结束 */
-
-/* 统计图 */
-.page-statistics .content-area {
-  padding: 20px;
-  height: calc(100% - 80px);
-  display: flex;
-  flex-wrap: wrap;
-  align-content: flex-start;
-  gap: 20px;
-  overflow-y: auto;
-}
-
-.project-report-statistics .statistics-container:hover {
-  --block-title-visible: visible;
-}
-
-.project-report-statistics  .body {
-  /* border-top: 1px solid #eaeaea; */
-  height: calc(100% - 57px);
-  overflow-y: auto;
-  padding: 12px var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-}
-
-.project-report-statistics  .table-container {
-  border: 1px solid #dddfe6;
-  margin-bottom: 22px;
-  overflow-x: auto;
-  background: var(--table-bg, #fff);
-}
-
-.project-report-statistics  .table-container::-webkit-scrollbar {
-  width: 0;
-  height: 0;
-}
-
-.project-report-statistics  .table-container::-webkit-scrollbar-thumb {
-  border-radius: 0;
-  -webkit-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.2);
-  background: var(--scrollbar-thumb-color, #c1c1c1);
-}
-
-.project-report-statistics  .table-container::-webkit-scrollbar-track {
-  border-radius: 0;
-  -webkit-box-shadow: inset 0 0 0 rgba(0, 0, 0, 0.2);
-  background: var(--scrollbar-track-color, transparent);
-}
-
-.project-report-statistics  .table-container:hover {
-  --table-bg: #edf1f5;
-}
-
-.project-report-statistics  .title {
-  position: relative;
-  padding: 15px 20px 15px 35px;
-  font-size: 16px;
-  border-bottom: 1px solid #dddfe6;
-}
-
-.project-report-statistics  .title::before {
-  content: "";
-  position: absolute;
-  top: 50%;
-  left: 20px;
-  transform: translateY(-50%);
-  width: 5px;
-  height: 5px;
-  background: #333333;
-  border-radius: 50%;
-}
-
-.project-report-statistics  .table-columns {
-  display: flex;
-  flex-wrap: nowrap;
-}
-
-.project-report-statistics  .table-columns>div {
-  flex-shrink: 0;
-  padding: 10px 20px;
-  border-right: 1px solid #dddfe6;
-}
-
-/* 跨对象弹窗开始 */
-.search-dialog-content {
-  width: 900px;
-  height: 100vh;
-  position: relative;
-  position: absolute;
-  left: 50%;
-  top: 50%;
-  transform: translate(-50%, -50%);
-  font-size: initial;
-  color: #333;
-  /* padding: 0 100px; */
-  background: #ffffff;
-  /* box-shadow: 0px 10px 5px 0px rgba(0, 0, 0, 0.3); */
-  border-radius: 4px;
-  /* height: 100%; */
-  padding: 0 100px 30px 100px;
-}
-
-.search-dialog-content>div {
-  width: 100%;
-}
-
-.search-dialog-content .header {
-  height: 130px;
-}
-
-.search-dialog-content .input-area {
-  width: 100%;
-  height: 53px;
-  color: #666;
-  font-size: 18px;
-  position: relative;
-  border: 1px solid #999999;
-  border-radius: 4px;
-  overflow: hidden;
-}
-
-.search-dialog-content .input-area>input {
-  position: absolute;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  line-height: 53px;
-  padding: 0 20px;
-  font-size: inherit;
-  outline: unset;
-  border: unset;
-  z-index: 1;
-}
-
-.search-dialog-content .search-btn {
-  position: absolute;
-  top: 0;
-  right: 0;
-  font-size: inherit;
-  color: inherit;
-  height: 100%;
-  padding: 0 17px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-  z-index: 2;
-  --search-btn-bg: transparent;
-  --search-btn-color: #666666;
-  --search-btn-left-border-visible: visible;
-  background: var(--search-btn-bg);
-  color: var(--search-btn-color);
-}
-
-.search-dialog-content .search-btn:hover {
-  --search-btn-color: #fff;
-  --search-btn-bg: #242835;
-  --search-btn-left-border-visible: hidden;
-}
-
-.search-dialog-content .search-btn::after {
-  visibility: var(--search-btn-left-border-visible);
-  position: absolute;
-  top: 50%;
-  left: 0;
-  transform: translateY(-50%);
-  width: 0;
-  height: 60%;
-  border-left: 1px solid #999999;
-  content: "";
-}
-
-.search-dialog-content .sort {
-  padding: 10px 0;
-  font-size: 14px;
-  color: #a9a9a9;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.search-dialog-content .list {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-}
-
-.search-dialog-content .list>div {
-  padding: 5px 10px;
-  cursor: pointer;
-}
-
-.search-dialog-content .active {
-  background-color: #e8f9fc;
-  color: #0066ff;
-  border-radius: 2px;
-}
-
-.search-dialog-content .time {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  gap: 10px;
-}
-
-.search-dialog-content .res {
-  color: #999999;
-  font-size: 12px;
-}
-
-.search-dialog-content .search-res {
-  height: calc(100% - 130px);
-  overflow-y: auto;
-  padding: 10px 10px 0 0;
-  margin-bottom: 5px;
-}
-
-.search-dialog-content .search-item {
-  margin-bottom: 20px;
-}
-
-.search-dialog-content .search-item.style-1>div.title {
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-}
-
-.search-dialog-content .search-item.style-1>div.detail {
-  padding: 5px 0;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.search-dialog-content .search-item.style-1>div.detail>div.thumb {
-  width: 77px;
-  height: 95px;
-}
-
-.search-dialog-content .search-item.style-1>div.detail>div.thumb>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.search-dialog-content .search-item.style-1>div.detail>div.info {
-  width: calc(100% - 77px);
-  padding-left: 10px;
-}
-
-.search-dialog-content .search-item.style-1>div.detail>div.info>div.title,
-.search-dialog-content .search-item.style-1>div.detail>div.info>div.subtitle {
-  color: #333;
-  font-size: 16px;
-  line-height: 1.5em;
-}
-
-.search-dialog-content .search-item.style-1>div.detail>div.info>div.desc {
-  margin-top: 5px;
-  color: #666666;
-  font-size: 14px;
-}
-
-.search-dialog-content .search-item.style-2>div.title {
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-}
-
-.search-dialog-content .search-item.style-2>div.desc {
-  color: #666666;
-  font-size: 14px;
-}
-
-.search-dialog-content .search-item.style-3>div.title {
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-}
-
-.search-dialog-content .search-item.style-3>div.group-list {
-  margin-top: 10px;
-}
-
-.search-dialog-content .search-item.style-3 .gitem {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  align-items: flex-start;
-}
-
-.search-dialog-content .search-item.style-3 .gitem:not(:last-child) {
-  margin-bottom: 20px;
-}
-
-.search-dialog-content .search-item.style-3  .thumb {
-  width: 180px;
-  height: 99px;
-}
-
-.search-dialog-content .search-item.style-3  .thumb>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.search-dialog-content .search-item.style-3  .info {
-  width: calc(100% - 180px);
-  padding-left: 10px;
-}
-
-.search-dialog-content .search-item.style-3  .info>div.title {
-  color: #666666;
-  font-size: 16px;
-}
-
-.search-dialog-content .search-item.style-3  .info>div.desc {
-  margin-top: 5px;
-  color: #666666;
-  font-size: 14px;
-}
-
-.search-dialog-content .search-item.style-3  .info>div.source {
-  margin-top: 5px;
-  color: #666666;
-  font-size: 12px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 5px;
-}
-
-.search-dialog-content .search-item.style-3  .info>div.source .icon-container {
-  color: rgba(0, 0, 0, 0.3);
-}
-
-/* 跨对象弹窗结束 */
-
-/* 项目基本信息开始 */
-.project-edit-container {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  overflow: hidden;
-}
-
-.project-edit-container>div {
-  height: 100%;
-}
-
-.project-edit-container .left-side {
-  width: 180px !important;
-  border-right: 1px solid #e2e4ec;
-  background-color: #edf1f5;
-}
-
-.project-edit-container .left-side>div {
-  width: 100%;
-}
-
-.project-edit-container .menu-header {
-  height: 120px;
-  border-bottom: 1px solid #d8dae3;
-}
-
-.project-edit-container .menu-content {
-  height: calc(100% - 60px);
-}
-
-.project-edit-container .menu-content .scroll-view {
-  width: 100%;
-  height: 100%;
-  overflow-y: auto;
-  font-size: 18px;
-}
-
-.project-edit-container .menu-item,
-.project-edit-container .group .menu-item {
-  padding: 20px 12px 20px 30px;
-  cursor: pointer;
-  position: relative;
-  color: #333333;
-  display: flex;
-  align-items: center;
-}
-
-.project-edit-container .menu-item .arrow{
-  position: absolute;
-  left: 180px;
-}
-
-.menu-item-point{
-  width: 6px;
-  height: 6px;
-  display: block;
-  border-radius: 50%;
-  background: #666;
-  
-}
-
-.project-edit-container .menu-item>.icon-container,
-.project-edit-container .group .menu-item>.icon-container {
-  margin-left: 10px;
-}
-
-.project-edit-container .menu-item::after,
-.project-edit-container .group .menu-item::after {
-  content: "";
-  width: calc(100% - 10px * 2);
-  height: 0;
-  display: block;
-  position: absolute;
-  bottom: -1px;
-  left: 10px;
-  border-bottom: 1px solid #d8dae3;
-}
-
-.project-edit-container .menu-item.active,
-.project-edit-container .group .menu-item.active {
-  background: #fff;
-}
-
-.project-edit-container .menu-item.active::after,
-.project-edit-container .group .menu-item.active::after {
-  border-bottom-color: transparent;
-}
-
-.project-edit-container .group {
-  width: 100%;
-}
-
-/* .project-edit-container  .group-detail {
-  padding-left: 10px;
-} */
-
-.project-edit-container  .group-detail .menu-item {
-  padding-left: 44px;
-}
-
-/* .project-edit-container .group-detail .menu-item::before {
-  content: "";
-  height: 6px;
-  width: 6px;
-  border-radius: 50%;
-  position: absolute;
-  top: 50%;
-  left: 30px;
-  background: #666;
-  transform: translateY(-50%);
-  position: relative;
-} */
-
-.sub-tab-menu-footer {
-  height: 60px;
-  flex-shrink: 0;
-  background: #afb8d0;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 10px;
-  font-size: 20px;
-  color: #fff;
-  cursor: pointer;
-  position: relative;
-}
-
-.sub-tab-menu-footer:hover {
-  background: #393d51;
-}
-
-.sub-tab-menu-popup {
-  position: absolute;
-  bottom: 76px;
-  left: 0;
-  right: 0;
-  display: none;
-
-}
-
-.sub-tab-menu-popup>div {
-  height: 76px;
-  flex-shrink: 0;
-  background: #afb8d0;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 10px;
-  font-size: 20px;
-  color: #fff;
-  cursor: pointer;
-  position: relative;
-}
-
-.sub-tab-menu-popup>div::after {
-  content: "";
-  width: 90%;
-  height: 1px;
-  display: block;
-  position: absolute;
-  bottom: 0;
-  left: 50%;
-  transform: translateX(-50%);
-  background: #ffffff;
-}
-
-.sub-tab-menu-popup>div:hover {
-  background: #393d51;
-}
-
-/* 鼠标悬浮时显示弹出菜单 */
-.sub-tab-menu-footer:hover .sub-tab-menu-popup {
-  display: block;
-}
-
-.project-edit-container>div.content-area {
-  width: calc(100% - 180px);
-  overflow-y: auto;
-}
-
-/* 项目基本信息结束 */
-
-/* 项目基本信息中的基本信息表格 */
-
-.base-container {
-  width: 100%;
-  padding: 32px;
-}
-
-.base-container .base-content {
-  width: 100%;
-  --border-color: #e2e4ec;
-  border-left: 1px solid var(--border-color);
-  border-top: 1px solid var(--border-color);
-}
-
-.base-container  .tr {
-  display: flex;
-  width: 1200px;
-  border-bottom: 1px solid var(--border-color);
-}
-
-.base-container  .tr>div {
-  flex-shrink: 0;
-  border-right: 1px solid var(--border-color);
-}
-
-.base-container  .th {
-  width: 200px;
-  height: 60px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  padding-right: 10px;
-  background: #f8f9fb;
-}
-
-.base-container  .td {
-  width: 400px;
-  height: 60px;
-  padding-left: 10px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  background: #ffffff;
-}
-
-.base-container  .th-1 {
-  width: 200px;
-  line-height: 3em;
-  padding-right: 10px;
-  background: #f8f9fb;
-  text-align: right;
-}
-
-.base-container  .td-1 {
-  width: 1000px;
-  padding: 10px;
-  background: #ffffff;
-}
-
-.base-container  .td-1>p {
-  padding: 5px;
-  margin: 0;
-}
-
-/* 项目基本信息中的内容表格 */
-.itembaseinfo-content-container {
-  width: 100%;
-  height: 100%;
-  padding-left: 32px;
-}
-
-.itembaseinfo-content-container .search-bar {
-  width: 100%;
-  height: 60px;
-}
-
-.itembaseinfo-content-container .content-area {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 20px;
-  height: calc(100% - 80px);
-  width: calc(100% - 8px);
-  padding: 12px;
-  overflow-y: auto;
-
-}
-
-.itembaseinfo-content-container .table-container {
-  width: 1200px;
-  border-collapse: collapse;
-}
-
-.itembaseinfo-content-container   th {
-  background: #f5f6fa;
-}
-
-.itembaseinfo-content-container   td,
-.itembaseinfo-content-container   th {
-  border: 1px solid #d8dae3;
-  padding: 20px;
-}
-
-.itembaseinfo-content-container   tr:nth-child(odd) {
-  background: #fafafa;
-}
-
-.itembaseinfo-content-container   td[data-num]::before {
-  content: attr(data-num);
-  width: 100%;
-  font-size: inherit;
-  color: #333;
-  padding-right: 5px;
-}
-
-.itembaseinfo-content-container   td.layer-2 {
-  text-indent: 2em;
-}
-
-.itembaseinfo-content-container   td.danger {
-  color: #ff0000;
-}
-
-.itembaseinfo-item-container {
-  width: 573px;
-  height: 170px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  border: 1px solid #dddfe6;
-  --header-display: none;
-  --header-color: #999;
-}
-
-.itembaseinfo-item-container:hover {
-  --header-display: flex;
-}
-
-.itembaseinfo-item-container:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dddfe6;
-}
-
-.itembaseinfo-item-container .active {
-  border: 1px solid #ddd;
-}
-
-.itembaseinfo-item-container .action-bar {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.itembaseinfo-item-container .action-bar:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.itembaseinfo-item-container .header {
-  padding: 10px 60px 2px 20px;
-}
-
-.itembaseinfo-item-container .title {
-  font-size: 22px;
-  color: #333;
-  line-height: 2em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.itembaseinfo-item-container .body {
-  padding: 0 var(--space-size, 20px);
-  box-sizing: border-box;
-  color: #333;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.itembaseinfo-item-container .body>div {
-  height: 100px;
-}
-
-.itembaseinfo-item-container .left {
-  width: 71px;
-  background: #fafbfe;
-  border: 1px solid #f6f6f6;
-}
-
-.itembaseinfo-item-container .left img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-}
-
-.itembaseinfo-item-container .right {
-  width: calc(100% - 71px);
-  padding: 5px 0 0 20px;
-}
-
-.itembaseinfo-item-container .content {
-  height: 60px;
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-  display: -webkit-box;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.itembaseinfo-item-container .tip {
-  margin-top: 5px;
-  font-size: 18px;
-  color: #666;
-  line-height: 1.8em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-/* 智能识别开始 */
-.ocr-container {
-  width: 100%;
-  height: 100%;
-}
-
-.ocr-container>div {
-  width: 100%;
-}
-
-.ocr-container .content-area {
-  height: calc(100% - 60px);
-  overflow-y: hidden;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.ocr-container .content-area>div {
-  width: 50%;
-  height: 100%;
-  overflow-y: hidden;
-  margin-right: 6px;
-}
-
-.ocr-container .left-side {
-  --scroll-track-color: #e2e4ec;
-}
-
-.ocr-img-box {
-  width: 100%;
-  height: 100%;
-  background-color: #e2e4ec;
-}
-
-.ocr-img-box .img-bar {
-  height: 60px;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  padding: 0 20px;
-  background: #f8f6f7;
-  font-size: 24px;
-  color: #666666;
-  box-sizing: border-box;
-  border-right: 10px solid var(--scroll-track-color);
-}
-
-.ocr-img-box .img-bar>div {
-  width: 50%;
-  flex-shrink: 0;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.ocr-img-box  .action-bar {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  color: #d5d4db;
-  border-top: 0;
-}
-
-.ocr-img-box .img-bar .action-bar .progress {
-  width: 185px;
-  height: 4px;
-  border-radius: 2px;
-  background: #d5d4db;
-  margin-right: 20px;
-  position: relative;
-  cursor: pointer;
-}
-
-.ocr-img-box .img-bar .action-bar .progress .buoy {
-  position: absolute;
-  width: 18px;
-  height: 18px;
-  border-radius: 50%;
-  border: 2px solid #c3c6ca;
-  top: 50%;
-  transform: translateY(-50%);
-  left: 0;
-  background: #fff;
-  cursor: pointer;
-}
-
-.ocr-img-box .img-bar .action-bar .icon-container {
-  cursor: pointer;
-}
-
-.ocr-img-box .img-viewer {
-  height: calc(100% - 60px);
-  width: calc(100% - 10px);
-  position: relative;
-  overflow: hidden;
-  background: #e2e4ec;
-}
-
-.ocr-img-range-box input[type=range] {
-  position: relative;
-  z-index: 12;
-  -webkit-appearance: none;
-  /*清除系统默认样式*/
-  width: 185px;
-  height: 4px;
-  border-radius: 2px;
-  background: #d5d4db;
-  background-size: 75% 100%;
-}
-
-/*拖动块的样式*/
-.ocr-img-range-box input[type=range]::-webkit-slider-thumb {
-  -webkit-appearance: none;
-  /*清除系统默认样式*/
-  width: 18px;
-  height: 18px;
-  background: #fff;
-  /*拖动块背景*/
-  border-radius: 50%;
-  /*外观设置为圆形*/
-  border: 2px solid #c3c6ca;
-}
-
-.ocr-img-range-box {
-  position: relative;
-  width: 185px;
-  display: flex;
-  align-items: center;
-  /* 垂直居中 */
-}
-
-.ocr-img-range-box .line {
-  width: 5px;
-  height: 18px;
-  background-color: #d5d4db;
-  position: absolute;
-  left: 50%;
-  transform: translateX(-50%);
-  height: 18px;
-}
-
-.ocr-img-range-box {
-  display: flex;
-  align-items: center;
-}
-
-.zoomable-img {
-  object-fit: contain;
-  transition: transform 0.3s, width 0.3s, height 0.3s;
-}
-
-.ocr-img-box .img-viewer .img-box {
-  width: 100%;
-  overflow-y: hidden;
-  background: white;
-}
-
-.ocr-img-box .img-viewer .img-box::-webkit-scrollbar {
-  width: 8px;
-  height: 8px;
-}
-
-.ocr-img-box .img-viewer .img-box::-webkit-scrollbar-thumb {
-  border-radius: 4px;
-  background: #575d6d;
-}
-
-.ocr-img-box .img-viewer .img-box::-webkit-scrollbar-track {
-  background: var(--scroll-track-color);
-}
-
-.ocr-img-box .img-viewer .img-box>img {
-  user-drag: none;
-  -webkit-user-drag: none;
-  -khtml-user-drag: none;
-  -webkit-touch-callout: none;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  user-select: none;
-  margin: 0 auto;
-  display: block;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.ocr-container .content-area .right-side {
-  overflow-y: auto;
-
-  padding: 20px;
-}
-
-.ocr-container .content-area .table-container {
-  width: 100%;
-  border-collapse: collapse;
-}
-
-.ocr-container .content-area .table-container.table-header {
-  margin-bottom: 20px;
-}
-
-.ocr-container .table-container th,
-.ocr-container .table-container td {
-  border: 1px solid #e2e4ec;
-}
-
-.ocr-container .table-container th {
-  width: 30%;
-  text-align: right;
-  font-weight: normal;
-  background: #f8f9fb;
-  padding: 15px;
-  color: #666666;
-  font-size: 16px;
-}
-
-.ocr-container .table-container td {
-  width: 70%;
-  padding: 0;
-}
-
-.ocr-container .table-container td>input {
-  width: 100%;
-  outline: none;
-  padding: 15px;
-  line-height: 1em;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-}
-
-.ocr-container .table-container td>textarea {
-  width: 100%;
-  height: 120px;
-  resize: none;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-.ocr-container .table-container td>select {
-  width: 100%;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-
-
-.ocr-container .content-box {
-  height: calc(100% - 60px);
-  overflow-y: auto;
-  padding: 20px;
-}
-
-.ocr-container .table-container {
-  width: 100%;
-  border-collapse: collapse;
-}
-
-.ocr-container .table-container th,
-.ocr-container .table-container td {
-  border: 1px solid #e2e4ec;
-}
-
-.ocr-container .table-container th {
-  width: 30%;
-  text-align: right;
-  font-weight: normal;
-  background: #f8f9fb;
-  padding: 15px;
-  color: #666666;
-  font-size: 16px;
-}
-
-.ocr-container .table-container td {
-  width: 70%;
-  padding: 0;
-}
-
-.ocr-container .table-container td>input {
-  width: 100%;
-  outline: none;
-  padding: 15px;
-  line-height: 1em;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-}
-
-.ocr-container .table-container td>textarea {
-  width: 100%;
-  height: 120px;
-  resize: none;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-.ocr-container .table-container td>select {
-  width: 100%;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-.ocr-container .table-container td>div.p {
-  font-size: 16px;
-  color: #333333;
-  padding: 20px 22px;
-}
-
-.ocr-container .table-container td>div.img {
-  height: 120px;
-  display: block;
-  padding: 8px 22px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.ocr-container .table-container td>div.img>img {
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-/* 智能识别结束 */
-/* 智能识别列表开始 */
-.ocr-list-container {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  position: relative;
-}
-
-.ocr-list-container>div {
-  height: 100%;
-}
-
-.ocr-list-container .left-side {
-  width: 220px;
-}
-
-.ocr-list-container .left-side .action-bar {
-  border-right: 2px solid var(--action-bar-bg);
-  height: 60px;
-  --action-bar-bg: #afb8d0;
-  --action-bar-color: #fff;
-  background: var(--action-bar-bg);
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 20px;
-  color: var(--action-bar-color);
-  font-size: 18px;
-  cursor: pointer;
-}
-
-.ocr-list-container .left-side .action-bar:hover {
-  --action-bar-bg: #242835;
-  --action-bar-color: #fff;
-}
-
-.ocr-list-container .left-side>div {
-  background: #edf1f5;
-}
-
-.ocr-list-container .left-side .content-box {
-  border-right: 2px solid #e2e4ec;
-  height: calc(100% - 60px);
-  overflow-y: auto;
-  padding: 20px 10px;
-}
-
-.ocr-list-container .left-side  .item {
-  width: 100%;
-  height: 143px;
-  border: 1px solid #e2e4ec;
-  margin-bottom: 25px;
-  background: #f8f9fb;
-  position: relative;
-  cursor: pointer;
-  padding: 2px 0;
-}
-
-.ocr-list-container .left-side  .thumb {
-  height: 100px;
-  width: 100%;
-  overflow: hidden;
-}
-
-.ocr-list-container .left-side .thumb>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.ocr-list-container .left-side .title {
-  color: #333333;
-  font-size: 16px;
-  padding: 10px;
-}
-
-.ocr-list-container .left-side .status-tip {
-  position: absolute;
-  width: 28px;
-  height: 28px;
-  bottom: 0;
-  right: 0;
-}
-
-.ocr-list-container .left-side .status-tip.error {
-  color: #ff0000;
-}
-
-.ocr-list-container .left-side .status-tip.warn {
-  color: #ffa800;
-}
-
-.ocr-list-container .left-side .status-tip.success {
-  color: #3cb700;
-}
-
-.ocr-list-container .left-side .item.active {
-  outline: 8px solid #afb8d0;
-}
-
-.ocr-list-container .left-side .item:not(.ocr-list-container .left-side .item.active):hover {
-  outline: 15px solid #dddfe6;
-}
-
-.ocr-list-container .right-side {
-  width: calc(100% - 220px);
-}
-
-.ocr-list-container .right-side .content-box {
-  height: calc(100% - 60px);
-  overflow-y: auto;
-  padding: 20px;
-}
-
-.ocr-list-container .right-side .table-container {
-  width: 100%;
-  border-collapse: collapse;
-}
-
-.ocr-list-container .right-side .table-container.table-header {
-  margin-bottom: 20px;
-}
-
-.ocr-list-container .right-side .table-container tr.hide {
-  visibility: hidden;
-}
-
-.ocr-list-container .right-side .table-container tr.hide * {
-  padding: 0 !important;
-  margin: 0 !important;
-  border: unset !important;
-  outline: unset !important;
-}
-
-.ocr-list-container .right-side .table-container th,
-.ocr-list-container .right-side .table-container td {
-  border: 1px solid #e2e4ec;
-}
-
-.ocr-list-container .right-side .table-container th {
-  width: 200px;
-  text-align: right;
-  font-weight: normal;
-  background: #f8f9fb;
-  padding: 15px;
-  color: #666666;
-  font-size: 16px;
-}
-
-.ocr-list-container .right-side .table-container td {
-  padding: 0;
-}
-
-.ocr-list-container .right-side .table-container td:not([colspan]) {
-  width: 360px;
-}
-
-.ocr-list-container .right-side .table-container td[colspan="3"] {
-  width: calc(100% - 200px);
-}
-
-.ocr-list-container .right-side .table-container td>input {
-  width: 100%;
-  outline: none;
-  padding: 15px;
-  line-height: 1em;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-}
-
-.ocr-list-container .right-side .table-container td>textarea {
-  width: 100%;
-  height: 120px;
-  resize: none;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-.ocr-list-container .right-side .table-container td>select {
-  width: 100%;
-  outline: none;
-  border: unset;
-  color: #333333;
-  font-size: 16px;
-  padding: 15px;
-}
-
-/* 智能识别列表结束 */
-/* 成功弹窗开始 */
-.success-popup {
-  position: absolute;
-  bottom: var(--message-dialog-bottom, calc(100% + 5px));
-  right: var(--message-dialog-right, 0);
-  width: 459px;
-  height: 150px;
-  background: #ffffff;
-  border: 1px solid #ade791;
-  box-shadow: 10px 10px 5px 0px rgba(61, 187, 0, 0.3);
-  border-radius: 4px;
-  color: #333;
-  font-size: 18px;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.success-popup>div.left {
-  width: 180px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.success-popup .icon {
-  width: 82px;
-  height: 82px;
-  background: #3dbb00;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  border-radius: 50%;
-  color: #fff;
-}
-
-.success-popup>.right {
-  width: calc(100% - 180px);
-}
-
-.success-popup>.right>div {
-  text-align: left;
-}
-
-.success-popup .title {
-  font-size: 36px;
-  color: #666666;
-}
-
-.success-popup .desc {
-  margin-top: 10px;
-  font-size: 24px;
-  color: #333;
-}
-
-/* 失败弹窗开始 */
-.errorDialog {
-  position: absolute;
-  left: 50%;
-  top: 50%;
-  transform: translate(-50%, -50%);
-  width: 587px;
-  height: 300px !important;
-  background: #ffffff;
-  border: 1px solid #e1adad;
-  box-shadow: 0px 10px 5px 0px rgba(236, 59, 56, 0.3);
-  border-radius: 4px;
-  color: #333;
-  font-size: 18px;
-}
-
-.errorDialog .body {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  padding: 50px 20px;
-}
-
-.errorDialog .left {
-  width: 180px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.errorDialog .icon {
-  width: 82px;
-  height: 82px;
-  background: #ec3b38;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  border-radius: 50%;
-  color: #fff;
-}
-
-.errorDialog .body>.right {
-  width: calc(100% - 180px);
-}
-
-.errorDialog .body>.right>div {
-  text-align: left;
-}
-
-.errorDialog .title {
-  font-size: 36px;
-  color: #666666;
-}
-
-.errorDialog .desc {
-  margin-top: 10px;
-  font-size: 24px;
-  color: #333;
-}
-
-.errorDialog .footer {
-  padding: 10px 40px;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.errorDialog .btn {
-  cursor: pointer;
-  width: 120px;
-  height: 42px;
-  background: #ef5d0c;
-  border: 1px solid #f5904b;
-  border-radius: 4px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 15px;
-  color: #fff;
-}
-
-/* 审核开始 */
-.verify-container {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.verify-container>div {
-  height: 100%;
-}
-
-/* 左侧主内容区域 */
-.verify-container .left-side {
-  width: 100%; /* 默认状态下,右侧只占10px */
-  transition: width 0.3s ease;
-  position: relative;
-}
-
-.verify-container .left-side>div {
-  border-right: 2px solid #e2e4ec;
-}
-
-.verify-container  .content-box {
-  height: calc(100% - 60px * 2 - 30px);
-  padding: 20px 24px;
-  border-bottom: 1px solid #e2e4ec;
-  overflow-y: auto;
-}
-
-.verify-container .content-box>div {
-  background: #ffffff;
-  border: 1px solid #dddfe6;
-  border-radius: 4px;
-  padding: 24px;
-  position: relative;
-}
-
-.verify-container .content-box>div:not(:last-child) {
-  margin-bottom: 20px;
-}
-
-.verify-container .handle-bar {
-  position: absolute;
-  top: 1px;
-  left: 1px;
-  font-weight: bold;
-  cursor: pointer;
-}
-
-.verify-container .member-box .box-header .title {
-  color: #333;
-  font-size: 18px;
-  line-height: 1.8em;
-}
-
-.verify-container .member-box .box-body {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  gap: 6px;
-}
-
-.verify-container .box-body>div {
-  height: 112px;
-}
-
-.verify-container .avatar {
-  width: 81px;
-}
-
-.verify-container .left-side .box-body .avatar>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: contain;
-  object-fit: contain;
-}
-
-.verify-container .left-side .box-body .info {
-  width: calc(100% - 81px);
-  padding-left: 24px;
-}
-
-.verify-container .left-side .box-body .info .table {
-  padding: 5px 0 15px 0;
-}
-
-.verify-container .left-side .box-body .info .table>table {
-  border-collapse: collapse;
-}
-
-.verify-container .left-side .box-body .info .table>table td {
-  border: 1px solid #dddfe6;
-  padding: 5px 32px;
-  text-align: center;
-  color: #333;
-  font-size: 16px;
-}
-
-.verify-container .left-side .box-body .info .description {
-  color: #666;
-  font-size: 16px;
-}
-
-.verify-container .left-side .zhengshu-box .box-header .title {
-  color: #333;
-  font-size: 18px;
-  line-height: 1.8em;
-}
-
-.verify-container .left-side .zhengshu-box .box-body {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.verify-container .left-side .box-body>div {
-  height: 103px;
-}
-
-.verify-container .left-side .avatar {
-  width: 145px;
-}
-
-.verify-container .left-side .avatar>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-}
-
-.verify-container .left-side .info {
-  padding-left: 24px;
-  width: calc(100% - 145px);
-}
-
-.verify-container .left-side .p {
-  font-size: 16px;
-  color: #333;
-  padding: 5px 0 15px 0;
-}
-
-.verify-container .left-side .p>p {
-  line-height: 1.5em;
-  padding: 0;
-  margin: 0;
-}
-
-.verify-container .left-side .tip {
-  font-size: 16px;
-  color: #666666;
-}
-
-.verify-container .action-bar-1 {
-  border-top: 1px solid #e2e4ec;
-  position: absolute;
-  width: 100%;
-  bottom: 60px;
-  height: 90px;
-  background: #ffffff;
-}
-
-.verify-container .action-list {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  height: 50px;
-  padding: 0 28px;
-  gap: 28px;
-}
-
-.verify-container .action-list>.span {
-  cursor: pointer;
-}
-
-.verify-container .input-area {
-  height: 40px;
-  padding: 0 28px;
-}
-
-.verify-container .input-area>textarea,
-.verify-container .input-area>input {
-  padding: 0;
-  line-height: 40px;
-  width: 100%;
-  height: 100%;
-  resize: none;
-  font-size: 18px;
-  outline: unset;
-  border: unset;
-  background: unset;
-}
-
-.verify-container .action-bar-2 {
-  height: 50px;
-  background: #ffffff;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  padding: 10px 20px 10px 20px;
-  gap: 20px;
-  color: #999999;
-  font-size: 18px;
-}
-
-.verify-container .action-bar-2>button {
-  font-size: inherit;
-  --action-bar-bg: transparent;
-  --action-bar-color: inherit;
-  --action-bar-border: #bfc1c6;
-  background: var(--action-bar-bg);
-  border: 1px solid var(--action-bar-border);
-  color: var(--action-bar-color);
-  outline: none;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 10px;
-  padding: 5px 20px;
-  border-radius: 4px;
-  cursor: pointer;
-}
-
-.verify-container .btn-primary:hover {
-  --action-bar-bg: #242835;
-  --action-bar-border: #242835;
-  --action-bar-color: #fff;
-}
-
-.verify-container .btn-danger:hover {
-  --action-bar-bg: #f19149;
-  --action-bar-color: #fff;
-  --action-bar-border: #f19149;
-}
-
-.verify-container .right-side {
-  width: 16px; 
-  height: 100%;
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  background: transparent;
-  transition: width 0.3s ease;
-  overflow: hidden; /* 超出部分隐藏 */
-  z-index: 10001; /* 确保在左侧内容之上 */
-}
-
-.verify-container .right-side-div {
-  width: 280px;
-  overflow-y: auto;
-  background: #edf1f5;
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-}
-.verify-container .right-side-div .header {
-  border-bottom: 2px solid #e2e4ec;
-}
-
-/* 右侧边栏 - 展开状态 */
-.verify-container .right-side.expanded {
-  width: 296px;
-}
-
-.verify-container .right-side .btn-toggle::before{
-	content: "";
-    position: absolute;
-    left: -8px;
-    top: -4px;
-    width: 20px;
-    height: 20px;
-    transform-origin: 100% 100%;
-    transform: rotate(49deg);
-    z-index: 1;
-    border-left: 1px solid #d2d2d2;
-    background: #ffffff;
-}
-.verify-container .right-side .btn-toggle {
-  position: absolute;
-  bottom: 25%;
-  left: 0;
-  transform: translateY(30%);
-  width: 16px;
-  height: 16px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  cursor: pointer;
-  z-index: 10;
-  border:1px solid #d2d2d2;
-  border-right: none;
-  border-top: none;
-  background: #ffffff;
-}
-.verify-container .right-side .icon-container{
-	background: #fff;
-	position:relative;
-	z-index: 1000;
-}
-/* 右侧内容容器 - 只在展开状态显示 */
-.verify-container .right-side-content {
-  opacity: 0;
-  transition: opacity 0.2s ease;
-  width: 100%;
-  height: 100%;
-  padding-left: 16px; /* 留出箭头区域 */
-  box-sizing: border-box;
-  position: relative;
-  z-index: 1000;
-}
-
-/* 展开状态下显示内容 */
-.verify-container .right-side.expanded .right-side-content {
-  opacity: 1;
-}
-
-.verify-nodes {
-  flex: 1;
-  overflow-y: auto;
-  padding: 20px 0;
-  margin-right: 6px;
-}
-
-.verify-nodes .group-item {
-  margin-bottom: 12px;
-  padding: 8px 0 8px 20px;
-}
-
-.verify-nodes .group-item {
-  position: relative;
-}
-/* .verify-nodes .group-item::before {
-  position: absolute;
-  content: "";
-  width: 0;
-  height: 50%;
-  border-left: 1px solid #a0a0a0;
-  top: 37px;
-  left: 30px;
-}*/
-.verify-nodes .group-item:not(:last-child)::after {
-  position: absolute;
-  content: "";
-  width: 0;
-  height: calc(100% - 20px);
-  border-left: 1px solid #a0a0a0;
-  top: 37px;
-  left: 30px;
-} 
-.verify-nodes .group-item-last-open::after {
-  position: absolute;
-  content: "";
-  width: 0;
-  height: var(--group-line-height);
-  border-left: 1px solid #a0a0a0;
-  top: 37px;
-  left: 30px;
-}
-.verify-nodes .group-item-title {
-  cursor: pointer;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-}
-
-.verify-nodes .group-item .icon {
-  color: #666666;
-  position: relative;
-}
-
-.verify-nodes .group-item .num {
-  position: absolute;
-  top: 60%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  color: #999999;
-  font-size: 14px;
-}
-
-.verify-nodes .group-item-children {
-
-  padding-left: 20px;
-}
-
-.verify-node-container {
-  padding: 16px 0;
-}
-
-.verify-node-container>.info {
-  padding: 0 10px;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  height: 60px;
-}
-
-
-.verify-node-container>.info>.avatar {
-  width: 50px;
-  height: 50px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.verify-node-container>.info>.desc {
-  width: calc(100% - 60px - 60px);
-  color: #333333;
-  font-size: 14px;
-  line-height: 1.6em;
-  padding: 0 10px;
-  display: flex;
-  flex-direction: column;
-  justify-content: flex-end;
-}
-
-.verify-node-container>.info>.desc>div {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.verify-node-container>.info>.link {
-  width: 60px;
-}
-
-.verify-node-container>.info>.link>div {
-  padding-top: 30px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 10px;
-  color: #555c6b;
-}
-
-.verify-node-container .description {
-  /* margin-top: 5px; */
-  padding: 10px;
-}
-
-.verify-node-container .description.link {
-  position: relative;
-}
-
-.verify-node-container .description.link::before {
-  position: absolute;
-  width: 20px;
-  content: "";
-  height: 0;
-  border-bottom: 1px solid #a0a0a0;
-  top: 30px;
-  left: -10px;
-}
-
-.verify-node-container .description.link::after {
-  position: absolute;
-  width: 16px;
-  content: attr(data-num);
-  height: 16px;
-  border-radius: 50%;
-  background: #edf1f5;
-  border: 1px solid #a0a0a0;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  font-size: 12px;
-  top: 21px;
-  left: -18px;
-  z-index: 100;
-}
-
-.verify-node-container .description>div {
-  width: 100%;
-  background: #fff;
-  border-radius: 3px;
-  position: relative;
-  padding: 8px 17px;
-  color: #333333;
-  font-size: 14px;
-}
-
-.verify-node-container .description>div::before {
-  content: "";
-  width: 10px;
-  height: 10px;
-  background: #fff;
-  position: absolute;
-  left: 26px;
-  top: -5px;
-  transform: rotate(45deg);
-  border-radius: 2px;
-}
-
-.verify-node-container .time {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  color: #666666;
-  font-size: 14px;
-  padding: 0 10px;
-}
-
-/* 审核结束 */
-/* 知识库弹窗查看项目 */
-.know-item-container {
-  width: 587px;
-  height: 157px;
-  box-shadow: 2px 2px 5px #e7e8e8;
-  background: #fafbfe;
-  border-radius: 4px;
-  position: relative;
-  cursor: pointer;
-  --header-display: none;
-  --header-color: #999;
-}
-
-.know-item-container:hover {
-  --header-display: flex;
-}
-
-.know-item-container:hover::after {
-  --border-size: 8px;
-  position: absolute;
-  width: 100%;
-  height: 100%;
-  top: calc(-1 * var(--border-size));
-  left: calc(-1 * var(--border-size));
-  content: "";
-  border-radius: 4px;
-  pointer-events: none;
-  box-sizing: content-box;
-  border: var(--border-size) solid #dddfe6;
-}
-
-.know-item-container.active {
-  border: 1px solid #ddd;
-}
-
-.know-item-container .header {
-  width: 48px;
-  height: 48px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  display: var(--header-display);
-  color: var(--header-color);
-  top: 0;
-  right: 0;
-  position: absolute;
-  border-top-right-radius: 4px;
-}
-
-.know-item-container .header:hover {
-  --header-color: #fff;
-  background: #575d6d;
-}
-
-.know-item-container .body {
-  padding: 0px 25px;
-}
-
-.know-item-container .box-header {
-  height: 50px;
-  padding: 15px 0 5px 0;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.know-item-container .box-header .title {
-  width: 100%;
-  color: #333333;
-  font-size: 22px;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-}
-
-.know-item-container .box-header .title>div {
-  flex-shrink: 0;
-}
-
-.know-item-container .box-header .title .p {
-  width: calc(100% - 50px);
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-.know-item-container .box-body {
-  height: 57px;
-  color: #333;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  --right-padding-left: 12px;
-  --right-width: calc(100% - 100px);
-}
-
-.know-item-container .no-thumb {
-  --right-padding-left: 0;
-  --right-width: 100%;
-}
-
-.know-item-container .left {
-  width: 100px;
-  height: 100%;
-}
-
-.know-item-container .left>img {
-  width: 100%;
-  height: 100%;
-  -o-object-fit: cover;
-  object-fit: cover;
-  display: block;
-}
-
-.know-item-container .right {
-  width: var(--right-width);
-  padding-left: var(--right-padding-left);
-}
-
-.know-item-container .right .title {
-  font-size: 16px;
-  color: #666666;
-  line-height: 24px;
-  display: -webkit-box;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  -webkit-line-clamp: 2;
-  -webkit-box-orient: vertical;
-}
-
-.know-item-container .box-footer {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  flex-direction: column;
-  height: 47px;
-}
-
-.know-item-container .box-footer>div {
-  width: 100%;
-}
-
-.know-item-container .box-footer .info {
-  margin-top: 5px;
-  font-size: 14px;
-  color: #999999;
-  line-height: 1.2em;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  gap: 20px;
-}
-
-.know-item-container .progress {
-  margin-top: 2px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  --status-color: #3172f1;
-}
-
-.know-item-container .progress.error {
-  --status-color: #ff0000;
-}
-
-.know-item-container .progress.waiting {
-  --status-color: #3172f1;
-}
-
-.know-item-container .status {
-  font-size: 12px;
-  padding-right: 1em;
-  color: var(--status-color);
-}
-
-.know-item-container .line {
-  flex: 1;
-  padding: 10px 0;
-  position: relative;
-}
-
-.know-item-container .line::after {
-  content: "";
-  background: #edf1f5;
-  width: 100%;
-  height: 2px;
-  border-radius: 1px;
-  position: absolute;
-  top: 50%;
-  left: 0;
-  transform: translateY(-50%);
-  z-index: 1;
-}
-
-.know-item-container .line>div {
-  z-index: 2;
-  width: 100%;
-  height: 2px;
-  border-radius: 1px;
-  position: absolute;
-  top: 50%;
-  left: 0;
-  transform: translateY(-50%);
-  background: var(--status-color);
-}
-
-.know-item-container .bar {
-  color: #c3c7cb;
-  padding-left: 1em;
-}
-
-/* 增加预警 */
-.editor-container {
-  width: 100%;
-  height: 100%;
-}
-
-.editor-container .content-box {
-  height: calc(100% - 60px);
-  padding: 25px 24px;
-}
-
-.editor-container .header {
-  height: 172px;
-}
-
-.editor-container .header>table {
-  border-collapse: collapse;
-}
-
-.editor-container .header th,
-.editor-container .header td {
-  border: 1px solid #e2e4ec;
-  padding: 20px;
-}
-
-.editor-container .header th {
-  width: 160px;
-  background: #f8f9fb;
-  color: #666666;
-  font-size: 16px;
-  text-align: right;
-  font-weight: normal;
-}
-
-.editor-container .header td {
-  color: var(--td-default-color, #333);
-  font-size: 16px;
-}
-
-.editor-container .desc {
-  --td-default-color: #666;
-}
-
-.editor-container .content-box .header select {
-  width: 100px;
-  font-size: inherit;
-  height: 100%;
-  outline: unset;
-  border: unset;
-  color: #999;
-}
-
-.editor-container .content-box .body {
-  height: calc(100% - 172px);
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-  gap: 20px;
-}
-
-.editor-container .content-box .body>div {
-  width: 50%;
-  height: 100%;
-  border: 1px solid #e7e8e8;
-  box-shadow: 2px 3px 5px 0px rgba(0, 0, 0, 0.06);
-}
-
-.editor-container .content-box .body>div>div {
-  width: 100%;
-}
-
-.editor-container .item-header {
-  height: 60px;
-  border-bottom: 1px solid #eaeaea;
-  padding: 0 20px;
-  font-size: 22px;
-  color: #4d4d4d;
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.editor-container .item-header-left {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  gap: 10px;
-}
-
-.editor-container .item-header-left .icon-container {
-  color: #989898;
-}
-
-.editor-container .item-header-right {
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 5px;
-}
-
-.editor-container .item-header-right input {
-  width: 100px;
-  height: 24px;
-  border: 1px solid #eaeaea;
-  border-radius: 2px;
-  outline: none;
-  padding: 0 10px;
-}
-
-.editor-container .item-header-right .icon-container {
-  color: #c3c7cb;
-}
-
-.editor-container .item-body {
-  padding-right: 6px;
-  height: calc(100% - 60px);
-  overflow-y: auto;
-}
-
-.editor-container .box-body {
-  width: 100%;
-  height: 100%;
-  overflow-y: auto;
-  overflow: hidden;
-  border: 1px solid #e2e4ec;
-}
-
-.editor-container .content-area {
-  width: 100%;
-}
-
-.editor-container .action-bar {
-  height: 60px;
-  color: #c3c6ca;
-  border-bottom: 1px solid #dedfdf;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-}
-
-.editor-container .action-bar .group {
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-start;
-  align-items: center;
-  position: relative;
-}
-
-.editor-container .action-bar .group::after {
-  content: "";
-  width: 0;
-  height: 60%;
-  top: 50%;
-  position: absolute;
-  right: 0;
-  border-right: 1px solid #efeff0;
-  transform: translateY(-50%);
-}
-
-.editor-container .action-bar .group>div {
-  width: 50px;
-  height: 60px;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-}
-
-.editor-container .content-area {
-  height: calc(100% - 60px);
-}
-
-.editor-container .content-area textarea {
-  width: 100%;
-  height: 100%;
-  resize: none;
-  outline: unset;
-  border: unset;
-  padding: 10px 20px;
-  font-size: 16px;
-  color: #333;
-}
-
-/* 弹窗底部按钮样式 */
-.bottom-div{
-  height: 60px;
-  background: white;
-  border-top: 1px solid #e2e4ec;
-  display: flex;
-  flex-direction: row;
-  justify-content: flex-end;
-  align-items: center;
-  padding: 0 20px;
-  gap: 20px;
-  color: #999999;
-  font-size: 18px;
-  position: absolute;
-  width: 100%;
-  bottom: 0;
-  background: #fff !important;
-}
-
-.bottom-div button {
-  font-size: 18px;
-  --bottom-div-bg: transparent;
-  --bottom-div-color: inherit;
-  --bottom-div-border: #bfc1c6;
-  background: var(--bottom-div-bg);
-  border: 1px solid var(--bottom-div-border);
-  color: var(--bottom-div-color);
-  outline: none;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  gap: 5px;
-  padding: 5px 20px;
-  border-radius: 4px;
-  cursor: pointer;
-}
-
-.bottom-div button:hover {
-  --bottom-div-bg: #242835;
-  --bottom-div-color: #fff;
-}
-.bottom-div  .bottom-button-reject:hover{
-  --bottom-div-bg: #e65505 ;
-  --bottom-div-color: #fff;
-  --bottom-div-border: #e65505;
-}
-
-/* 下拉按钮开始 */
-.ss-drop-button {
-  height: 36px;
-  font-size: 16px;
-  color: #999;
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-items: center;
-  padding: 0 20px;
-  border-radius: 4px;
-  margin: 0;
-  /* line-height: 2em; */
-  cursor: pointer;
-  background: var(--btn-bg, unset);
-  color: var(--btn-color, #999999);
-  border: 1px solid var(--btn-border-color, #c4c7cc);
-  position: relative;
-}
-
-.ss-drop-button:hover {
-  --btn-bg: #393d51;
-  --btn-color: #fff;
-}
-
-.ss-drop-button .popup {
-  position: absolute;
-  top: calc(100% + 12px);
-  right: 0;
-  background-color: #393d51;
-  border-radius: 5px;
-  padding: 10px 4px;
-  z-index: 10;
-  height: auto;
-}
-
-.ss-drop-button .popup::before {
-  content: "";
-  position: absolute;
-  top: -12px;
-  /* 与弹窗的 top: calc(100% + 12px) 对应 */
-  left: 0;
-  right: 0;
-  height: 12px;
-  background: transparent;
-  /* 透明背景 */
-}
-
-.ss-drop-button .popup::after {
-  content: "";
-  width: 0.8em;
-  height: 0.8em;
-  background: #393d51;
-  position: absolute;
-  right: 1.5em;
-  top: -0.4em;
-  transform: rotate(45deg);
-
-}
-
-.ss-drop-button .popup div {
-  padding: 5px 15px;
-  cursor: pointer;
-  white-space: nowrap;
-}
-
-.ss-drop-button .popup div:hover {
-  background: #fffdfd;
-  color: #333;
-}
-.ss-drop-button-more::before{
-  width: 6px;
-  height: 6px;
-  content: '';
-  border-radius: 50%;
-  background-color: #8e8e8e;
-  position: absolute;
-  right: 4px;
-  top: 4px;
-}
-/* 下拉按钮结束 */
-/* 通用查询卡片下拉按钮开始 */
-.cart-list-button-popup{
-  position: absolute;
-  top: calc(100% + 8px);
-  right: -8px;
-  background-color: #393d51;
-  border-radius: 5px;
-  padding: 10px 4px;
-  z-index: 10;
-}
-.cart-list-button-popup::before {
-  content: "";
-  position: absolute;
-  top: -10px;
-  left: 0;
-  right: 0;
-  height: 10px;
-  background: transparent;
-}
-
-.cart-list-button-popup::after {
-  content: "";
-  width: 0.6em;
-  height: 0.6em;
-  background: #393d51;
-  position: absolute;
-  right: 1.7em;
-  top: -0.3em;
-  transform: rotate(45deg);
-}
-.cart-list-button-popup>div {
-  padding: 5px 15px;
-  cursor: pointer;
-  white-space: nowrap;
-  font-size: 16px;
-  display: flex;
-  align-items: center;
-}
-.cart-list-button-popup .cart-list-icon{
-  margin-right: 5px;
-  font-size: 16px;
-}
-.cart-list-button-popup>div:hover {
-  background: #fffdfd;
-  color: #333;
-}
-.cart-list-button-popup>div:hover .cart-list-icon::before{
-  color: #333333 !important;
-}
-/* 通用查询卡片下拉按钮结束 */
-
-/* 一级页面面包屑 */
-.bread-crumb{
-  display: flex;
-  align-items: center;
-  position: absolute;
-  left: 20px;
-  gap: 10px;
-  height: 100%;
-  z-index: 111;
-  color: #999999;
-}
-.bread-crumb>div{
-  cursor: pointer;
-}
-
-
-/* 日期选择器样式 */
-
-.el-date-table,.el-time-spinner__item{
-  font-size: 14px;
-}
-.custom-date-picker  .el-icon{
-  font-size: 16px;
-  color: #333;
-}
-.custom-date-picker .el-input__wrapper {
-  box-shadow: none !important;
-  display: flex;
-  align-items: center;
-}
-.custom-date-picker .el-input__inner::placeholder {
-  color: #999;
-
-}
-.custom-date-picker .el-input__inner {
-  font-size: 16px !important;
-  font-weight: normal;
-  height: 32px;
-  line-height: 33px;
-  color: #000;
-}
-.today .el-date-table-cell__text{
-  border: 1px solid #000;
-  border-radius: 50%;
-}
-.el-picker-panel__icon-btn{
-  margin-top: 0;
-}
-.el-date-picker__time-header{
-  padding: 12px 5px;
-  border-bottom: none;
-}
-.el-picker-panel__footer,.el-time-panel__footer{
-  border-top: none;
-  padding: 5px 10px 10px;
-}
-.el-button--small{
-  font-size: 14px;
-  padding: 14px 16px;
-
-}
-.el-time-panel__footer{
-  height: auto;
-  line-height: 25px;
-  display: flex;
-  justify-content: flex-end;
-}
-.el-time-panel__btn{
-  font-size: 14px;
-  height: 24px;
-  padding: 14px 16px;
-  margin:0;
-  line-height: unset;
-  display: flex;
-  align-items: center;
-}
-.el-input--small{
-  font-size: 16px;
-}
-.el-input--small .el-input__wrapper{
-  padding: 8px 7px 6px;
-}
-.jodit-container:not(.jodit_inline){
-  border: none !important;
-}
-/* 搜索区域的日期选择器 */
-.ss-search-date-picker input:focus,.el-picker-panel .el-input__inner:focus{
-  border:1px solid #c4c7cc !important;
-  outline: none;
-}
-.ss-search-date-picker .custom-date-picker  .el-icon{
-  font-size: 16px;
-  color: #333;
-}
-.ss-search-date-picker  .el-input--large .el-input__wrapper{
-  padding:0;
-}
-.ss-search-date-picker .el-input__wrapper {
-  height: 32px;
-  width: 100%;
-  padding:0;
-}
-.ss-search-date-picker .el-input__prefix, .ss-search-date-picker .el-input__suffix {
-  display: none;
-}
-.ss-search-date-picker .custom-date-picker .el-input__inner::placeholder {
-  color: #333;
-
-}
-.ss-search-date-picker .custom-date-picker .el-input__inner {
-  width: 100%;
-  font-size: 14px !important;
-  font-weight: normal;
-  height: 32px;
-  line-height: 33px;
-  font-family: 'SimHei', 'Microsoft YaHei', 'Helvetica Neue', Helvetica;
-}
-.ss-search-date-picker .el-input__inner::placeholder {
-  font-family: 'SimHei', 'Microsoft YaHei', 'Helvetica Neue', Helvetica !important;
-  color: #999999 !important;
-}
-.el-picker-panel .el-input__inner{
-  width: 100% !important;
-}

+ 0 - 305
skin/easy/css/cropper.css

@@ -1,305 +0,0 @@
-/*!
- * Cropper v4.0.0
- * https://github.com/fengyuanchen/cropper
- *
- * Copyright (c) 2014-2018 Chen Fengyuan
- * Released under the MIT license
- *
- * Date: 2018-04-01T06:26:32.417Z
- */
-
- .cropper-container {
-    direction: ltr;
-    font-size: 0;
-    line-height: 0;
-    position: relative;
-    -ms-touch-action: none;
-    touch-action: none;
-    -webkit-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-  }
-  
-  .cropper-container img {/*Avoid margin top issue (Occur only when margin-top <= -height)
-   */
-    display: block;
-    height: 100%;
-    image-orientation: 0deg;
-    max-height: none !important;
-    max-width: none !important;
-    min-height: 0 !important;
-    min-width: 0 !important;
-    width: 100%;
-  }
-  
-  .cropper-wrap-box,
-  .cropper-canvas,
-  .cropper-drag-box,
-  .cropper-crop-box,
-  .cropper-modal {
-    bottom: 0;
-    left: 0;
-    position: absolute;
-    right: 0;
-    top: 0;
-  }
-  
-  .cropper-wrap-box,
-  .cropper-canvas {
-    overflow: hidden;
-  }
-  
-  .cropper-drag-box {
-    background-color: #fff;
-    opacity: 0;
-  }
-  
-  .cropper-modal {
-    background-color: #000;
-    opacity: .5;
-  }
-  
-  .cropper-view-box {
-    display: block;
-    height: 100%;
-    outline-color: rgba(51, 153, 255, 0.75);
-    outline: 1px solid #39f;
-    overflow: hidden;
-    width: 100%;
-  }
-  
-  .cropper-dashed {
-    border: 0 dashed #eee;
-    display: block;
-    opacity: .5;
-    position: absolute;
-  }
-  
-  .cropper-dashed.dashed-h {
-    border-bottom-width: 1px;
-    border-top-width: 1px;
-    height: 33.33333%;
-    left: 0;
-    top: 33.33333%;
-    width: 100%;
-  }
-  
-  .cropper-dashed.dashed-v {
-    border-left-width: 1px;
-    border-right-width: 1px;
-    height: 100%;
-    left: 33.33333%;
-    top: 0;
-    width: 33.33333%;
-  }
-  
-  .cropper-center {
-    display: block;
-    height: 0;
-    left: 50%;
-    opacity: .75;
-    position: absolute;
-    top: 50%;
-    width: 0;
-  }
-  
-  .cropper-center:before,
-  .cropper-center:after {
-    background-color: #eee;
-    content: ' ';
-    display: block;
-    position: absolute;
-  }
-  
-  .cropper-center:before {
-    height: 1px;
-    left: -3px;
-    top: 0;
-    width: 7px;
-  }
-  
-  .cropper-center:after {
-    height: 7px;
-    left: 0;
-    top: -3px;
-    width: 1px;
-  }
-  
-  .cropper-face,
-  .cropper-line,
-  .cropper-point {
-    display: block;
-    height: 100%;
-    opacity: .1;
-    position: absolute;
-    width: 100%;
-  }
-  
-  .cropper-face {
-    background-color: #fff;
-    left: 0;
-    top: 0;
-  }
-  
-  .cropper-line {
-    background-color: #39f;
-  }
-  
-  .cropper-line.line-e {
-    cursor: ew-resize;
-    right: -3px;
-    top: 0;
-    width: 5px;
-  }
-  
-  .cropper-line.line-n {
-    cursor: ns-resize;
-    height: 5px;
-    left: 0;
-    top: -3px;
-  }
-  
-  .cropper-line.line-w {
-    cursor: ew-resize;
-    left: -3px;
-    top: 0;
-    width: 5px;
-  }
-  
-  .cropper-line.line-s {
-    bottom: -3px;
-    cursor: ns-resize;
-    height: 5px;
-    left: 0;
-  }
-  
-  .cropper-point {
-    background-color: #39f;
-    height: 5px;
-    opacity: .75;
-    width: 5px;
-  }
-  
-  .cropper-point.point-e {
-    cursor: ew-resize;
-    margin-top: -3px;
-    right: -3px;
-    top: 50%;
-  }
-  
-  .cropper-point.point-n {
-    cursor: ns-resize;
-    left: 50%;
-    margin-left: -3px;
-    top: -3px;
-  }
-  
-  .cropper-point.point-w {
-    cursor: ew-resize;
-    left: -3px;
-    margin-top: -3px;
-    top: 50%;
-  }
-  
-  .cropper-point.point-s {
-    bottom: -3px;
-    cursor: s-resize;
-    left: 50%;
-    margin-left: -3px;
-  }
-  
-  .cropper-point.point-ne {
-    cursor: nesw-resize;
-    right: -3px;
-    top: -3px;
-  }
-  
-  .cropper-point.point-nw {
-    cursor: nwse-resize;
-    left: -3px;
-    top: -3px;
-  }
-  
-  .cropper-point.point-sw {
-    bottom: -3px;
-    cursor: nesw-resize;
-    left: -3px;
-  }
-  
-  .cropper-point.point-se {
-    bottom: -3px;
-    cursor: nwse-resize;
-    height: 20px;
-    opacity: 1;
-    right: -3px;
-    width: 20px;
-  }
-  
-  @media (min-width: 768px) {
-    .cropper-point.point-se {
-      height: 15px;
-      width: 15px;
-    }
-  }
-  
-  @media (min-width: 992px) {
-    .cropper-point.point-se {
-      height: 10px;
-      width: 10px;
-    }
-  }
-  
-  @media (min-width: 1200px) {
-    .cropper-point.point-se {
-      height: 5px;
-      opacity: .75;
-      width: 5px;
-    }
-  }
-  
-  .cropper-point.point-se:before {
-    background-color: #39f;
-    bottom: -50%;
-    content: ' ';
-    display: block;
-    height: 200%;
-    opacity: 0;
-    position: absolute;
-    right: -50%;
-    width: 200%;
-  }
-  
-  .cropper-invisible {
-    opacity: 0;
-  }
-  
-  .cropper-bg {
-    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
-  }
-  
-  .cropper-hide {
-    display: block;
-    height: 0;
-    position: absolute;
-    width: 0;
-  }
-  
-  .cropper-hidden {
-    display: none !important;
-  }
-  
-  .cropper-move {
-    cursor: move;
-  }
-  
-  .cropper-crop {
-    cursor: crosshair;
-  }
-  
-  .cropper-disabled .cropper-drag-box,
-  .cropper-disabled .cropper-face,
-  .cropper-disabled .cropper-line,
-  .cropper-disabled .cropper-point {
-    cursor: not-allowed;
-  }

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
skin/easy/css/element-plus.css


+ 0 - 126
skin/easy/css/font_4273728_tnvxftfb8j.css

@@ -1,126 +0,0 @@
-@font-face {
-    font-family: "common-iconfont"; /* Project id 4273728 */
-    src: 
-        url('../fonts/iconfont_4273728.woff2') format('woff2');
-  }
-  
-  .common-iconfont {
-    font-family: "common-iconfont" !important;
-    font-size: 16px;
-    font-style: normal;
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
-  }
-  
-  .common-icon-photo:before {
-    content: "\e89c";
-  }
-  
-  .common-icon-arrow-double-right:before {
-    content: "\eb9a";
-  }
-  
-  .common-icon-arrow-double-left:before {
-    content: "\eb9b";
-  }
-  
-  .common-icon-arrow-double-down:before {
-    content: "\eb9c";
-  }
-  
-  .common-icon-arrow-double-up:before {
-    content: "\eb9d";
-  }
-  
-  .common-icon-video:before {
-    content: "\e61e";
-  }
-  
-  .common-icon-smile1:before {
-    content: "\e761";
-  }
-  
-  .common-icon-fontSize:before {
-    content: "\e63f";
-  }
-  
-  .common-icon-paperClip:before {
-    content: "\ea36";
-  }
-  
-  .common-icon-edit:before {
-    content: "\e668";
-  }
-  
-  .common-icon-notice:before {
-    content: "\e614";
-  }
-  
-  .common-icon-site:before {
-    content: "\e67b";
-  }
-  
-  .common-icon-card:before {
-    content: "\e620";
-  }
-  
-  .common-icon-question:before {
-    content: "\e666";
-  }
-  
-  .common-icon-print:before {
-    content: "\e6c9";
-  }
-  
-  .common-icon-full-screen:before {
-    content: "\eb99";
-  }
-  
-  .common-icon-love:before {
-    content: "\e83f";
-  }
-  
-  .common-icon-activity:before {
-    content: "\e621";
-  }
-  
-  .common-icon-layer:before {
-    content: "\e603";
-  }
-  
-  .common-icon-home:before {
-    content: "\e6b8";
-  }
-  
-  .common-icon-double-arrow-right:before {
-    content: "\e624";
-  }
-  
-  .common-icon-slant:before {
-    content: "\e6ae";
-  }
-  
-  .common-icon-close:before {
-    content: "\e723";
-  }
-  
-  .common-icon-close-circle:before {
-    content: "\e725";
-  }
-  
-  .common-icon-menu-square:before {
-    content: "\e651";
-  }
-  
-  .common-icon-menu:before {
-    content: "\eb71";
-  }
-  
-  .common-icon-empty:before {
-    content: "\e708";
-  }
-  
-  .common-icon-add:before {
-    content: "\eb72";
-  }
-  

+ 0 - 750
skin/easy/css/font_4279221_5h4vbt6831w.css

@@ -1,750 +0,0 @@
-@font-face {
-    font-family: "ss-iconfont"; /* Project id 4279221 */
-    src: 
-        url('../fonts/iconfont_4279221.woff2') format('woff2');
-  }
-  
-  .ss-iconfont {
-    font-family: "ss-iconfont" !important;
-    font-size: 16px;
-    font-style: normal;
-    -webkit-font-smoothing: antialiased;
-    -moz-osx-font-smoothing: grayscale;
-  }
-  
-  .ss-icon-quanxuan:before {
-    content: "\e6b6";
-  }
-  
-  .ss-icon-quanbuguoqu:before {
-    content: "\e6b7";
-  }
-  
-  .ss-icon-biaoqian:before {
-    content: "\e6b5";
-  }
-  
-  .ss-icon-grxzFuyongshanggezhi:before {
-    content: "\e6b2";
-  }
-  
-  .ss-icon-grxzMorenzhi:before {
-    content: "\e6b3";
-  }
-  
-  .ss-icon-grxzBuxuan:before {
-    content: "\e6b4";
-  }
-  
-  .ss-icon-yaoyiyaocu:before {
-    content: "\e6b1";
-  }
-  
-  .ss-icon-yaoyiyao:before {
-    content: "\e6b0";
-  }
-  
-  .ss-icon-PE:before {
-    content: "\e6af";
-  }
-  
-  .ss-icon-fenzhi:before {
-    content: "\e6ac";
-  }
-  
-  .ss-icon-xiangliang:before {
-    content: "\e6ad";
-  }
-  
-  .ss-icon-huihe:before {
-    content: "\e6ae";
-  }
-  
-  .ss-icon-linggan:before {
-    content: "\e6ab";
-  }
-  
-  .ss-icon-kaishi:before {
-    content: "\e6a9";
-  }
-  
-  .ss-icon-jieshu:before {
-    content: "\e6aa";
-  }
-  
-  .ss-icon-lieshu:before {
-    content: "\e6a1";
-  }
-  
-  .ss-icon-biaoqing:before {
-    content: "\e68c";
-  }
-  
-  .ss-icon-shanchuhang:before {
-    content: "\e665";
-  }
-  
-  .ss-icon-shanchulie:before {
-    content: "\e697";
-  }
-  
-  .ss-icon-shanchubiaoge:before {
-    content: "\e69a";
-  }
-  
-  .ss-icon-neirongku:before {
-    content: "\e63a";
-  }
-  
-  .ss-icon-charulie:before {
-    content: "\e65c";
-  }
-  
-  .ss-icon-cangdan:before {
-    content: "\e67e";
-  }
-  
-  .ss-icon-charuhang:before {
-    content: "\e662";
-  }
-  
-  .ss-icon-tuozhuai:before {
-    content: "\e601";
-  }
-  
-  .ss-icon-word:before {
-    content: "\e689";
-  }
-  
-  .ss-icon-excl:before {
-    content: "\e63f";
-  }
-  
-  .ss-icon-zhenghe:before {
-    content: "\e636";
-  }
-  
-  .ss-icon-xiuxue:before {
-    content: "\e600";
-  }
-  
-  .ss-icon-bugouxuan:before {
-    content: "\e6a8";
-  }
-  
-  .ss-icon-caozuoshibai1:before {
-    content: "\e69b";
-  }
-  
-  .ss-icon-anjian-1:before {
-    content: "\e6a3";
-  }
-  
-  .ss-icon-bangzhu:before {
-    content: "\e6a4";
-  }
-  
-  .ss-icon-baocunbintijiao:before {
-    content: "\e6a5";
-  }
-  
-  .ss-icon-baocun-youshangjiao:before {
-    content: "\e6a6";
-  }
-  
-  .ss-icon-baocun:before {
-    content: "\e6a7";
-  }
-  
-  .ss-icon-cuiban:before {
-    content: "\e68d";
-  }
-  
-  .ss-icon-biyanjing:before {
-    content: "\e68e";
-  }
-  
-  .ss-icon-a-fangda1:before {
-    content: "\e68f";
-  }
-  
-  .ss-icon-folderShare:before {
-    content: "\e690";
-  }
-  
-  .ss-icon-fenlei:before {
-    content: "\e691";
-  }
-  
-  .ss-icon-baoguandan:before {
-    content: "\e692";
-  }
-  
-  .ss-icon-chaifen:before {
-    content: "\e693";
-  }
-  
-  .ss-icon-diannao:before {
-    content: "\e694";
-  }
-  
-  .ss-icon-dingwei:before {
-    content: "\e695";
-  }
-  
-  .ss-icon-danwei:before {
-    content: "\e696";
-  }
-  
-  .ss-icon-fanhui:before {
-    content: "\e698";
-  }
-  
-  .ss-icon-canshuxiang:before {
-    content: "\e699";
-  }
-  
-  .ss-icon-chexiao:before {
-    content: "\e69c";
-  }
-  
-  .ss-icon-biaoge:before {
-    content: "\e69d";
-  }
-  
-  .ss-icon-buhuanrao:before {
-    content: "\e69e";
-  }
-  
-  .ss-icon-bingtu:before {
-    content: "\e69f";
-  }
-  
-  .ss-icon-caogaoxiang:before {
-    content: "\e6a0";
-  }
-  
-  .ss-icon-anjian:before {
-    content: "\e6a2";
-  }
-  
-  .ss-icon-gerenxuanzhi:before {
-    content: "\e677";
-  }
-  
-  .ss-icon-fanxuan:before {
-    content: "\e678";
-  }
-  
-  .ss-icon-a-chenggong1:before {
-    content: "\e679";
-  }
-  
-  .ss-icon-chongzuo:before {
-    content: "\e67a";
-  }
-  
-  .ss-icon-gongshigonggao:before {
-    content: "\e67b";
-  }
-  
-  .ss-icon-dianji-02:before {
-    content: "\e67c";
-  }
-  
-  .ss-icon-fangda:before {
-    content: "\e67d";
-  }
-  
-  .ss-icon-duihua2:before {
-    content: "\e67f";
-  }
-  
-  .ss-icon-daiban:before {
-    content: "\e680";
-  }
-  
-  .ss-icon-huanfu:before {
-    content: "\e681";
-  }
-  
-  .ss-icon-duomeiti:before {
-    content: "\e682";
-  }
-  
-  .ss-icon-guangbiao:before {
-    content: "\e683";
-  }
-  
-  .ss-icon-guangbiao-tuozhuai:before {
-    content: "\e684";
-  }
-  
-  .ss-icon-dianzan:before {
-    content: "\e685";
-  }
-  
-  .ss-icon-bianqian:before {
-    content: "\e686";
-  }
-  
-  .ss-icon-denglu:before {
-    content: "\e687";
-  }
-  
-  .ss-icon-guanbi_jiaobiao:before {
-    content: "\e688";
-  }
-  
-  .ss-icon-daochu:before {
-    content: "\e68a";
-  }
-  
-  .ss-icon-changyongyu:before {
-    content: "\e68b";
-  }
-  
-  .ss-icon-faxian:before {
-    content: "\e65f";
-  }
-  
-  .ss-icon-saoyisao:before {
-    content: "\e660";
-  }
-  
-  .ss-icon-gouxuan:before {
-    content: "\e661";
-  }
-  
-  .ss-icon-fuzhi:before {
-    content: "\e663";
-  }
-  
-  .ss-icon-kuaijiefangwen:before {
-    content: "\e664";
-  }
-  
-  .ss-icon-shijian:before {
-    content: "\e666";
-  }
-  
-  .ss-icon-suoping:before {
-    content: "\e667";
-  }
-  
-  .ss-icon-laiyuan:before {
-    content: "\e668";
-  }
-  
-  .ss-icon-dayin:before {
-    content: "\e669";
-  }
-  
-  .ss-icon-quanping:before {
-    content: "\e66a";
-  }
-  
-  .ss-icon-guanli:before {
-    content: "\e66b";
-  }
-  
-  .ss-icon-fasong:before {
-    content: "\e66c";
-  }
-  
-  .ss-icon-kehuguanli:before {
-    content: "\e66d";
-  }
-  
-  .ss-icon-duihua1:before {
-    content: "\e66e";
-  }
-  
-  .ss-icon-fukuan:before {
-    content: "\e66f";
-  }
-  
-  .ss-icon-i:before {
-    content: "\e670";
-  }
-  
-  .ss-icon-hebing:before {
-    content: "\e671";
-  }
-  
-  .ss-icon-olderOpen:before {
-    content: "\e672";
-  }
-  
-  .ss-icon-jiacu:before {
-    content: "\e673";
-  }
-  
-  .ss-icon-guangbiao-bianji:before {
-    content: "\e674";
-  }
-  
-  .ss-icon-jiahao:before {
-    content: "\e675";
-  }
-  
-  .ss-icon-chanyeleibie:before {
-    content: "\e676";
-  }
-  
-  .ss-icon-qiandaizi:before {
-    content: "\e647";
-  }
-  
-  .ss-icon-a-lock1:before {
-    content: "\e648";
-  }
-  
-  .ss-icon-renwu:before {
-    content: "\e649";
-  }
-  
-  .ss-icon-wenzhang:before {
-    content: "\e64a";
-  }
-  
-  .ss-icon-a-liucheng1:before {
-    content: "\e64b";
-  }
-  
-  .ss-icon-a-lianjie1:before {
-    content: "\e64c";
-  }
-  
-  .ss-icon-shunpai:before {
-    content: "\e64d";
-  }
-  
-  .ss-icon-shouyeshezhi:before {
-    content: "\e64e";
-  }
-  
-  .ss-icon-tupu:before {
-    content: "\e64f";
-  }
-  
-  .ss-icon-leibie:before {
-    content: "\e650";
-  }
-  
-  .ss-icon-tuichu:before {
-    content: "\e651";
-  }
-  
-  .ss-icon-huiyi:before {
-    content: "\e652";
-  }
-  
-  .ss-icon-quanwenjiansuo:before {
-    content: "\e653";
-  }
-  
-  .ss-icon-duixiang:before {
-    content: "\e654";
-  }
-  
-  .ss-icon-jinyong:before {
-    content: "\e655";
-  }
-  
-  .ss-icon-kaoqin:before {
-    content: "\e656";
-  }
-  
-  .ss-icon-huodong:before {
-    content: "\e657";
-  }
-  
-  .ss-icon-shouqi:before {
-    content: "\e658";
-  }
-  
-  .ss-icon-guanwang:before {
-    content: "\e659";
-  }
-  
-  .ss-icon-a-liangduanduiqi1:before {
-    content: "\e65a";
-  }
-  
-  .ss-icon-shouxie:before {
-    content: "\e65b";
-  }
-  
-  .ss-icon-shoucang:before {
-    content: "\e65d";
-  }
-  
-  .ss-icon-gongwen:before {
-    content: "\e65e";
-  }
-  
-  .ss-icon-guanbi:before {
-    content: "\e643";
-  }
-  
-  .ss-icon-shangyizhang:before {
-    content: "\e644";
-  }
-  
-  .ss-icon-shangjiaobiao:before {
-    content: "\e645";
-  }
-  
-  .ss-icon-wentiliebiao:before {
-    content: "\e646";
-  }
-  
-  .ss-icon-youduiqi:before {
-    content: "\e62d";
-  }
-  
-  .ss-icon-shaugxin:before {
-    content: "\e62e";
-  }
-  
-  .ss-icon-youpaihuanrao:before {
-    content: "\e62f";
-  }
-  
-  .ss-icon-xiazai:before {
-    content: "\e630";
-  }
-  
-  .ss-icon-zhengshu:before {
-    content: "\e631";
-  }
-  
-  .ss-icon-yewu:before {
-    content: "\e632";
-  }
-  
-  .ss-icon-tuihui:before {
-    content: "\e633";
-  }
-  
-  .ss-icon-fujian:before {
-    content: "\e634";
-  }
-  
-  .ss-icon-xiangxiajiantou:before {
-    content: "\e635";
-  }
-  
-  .ss-icon-shubiaojiantou:before {
-    content: "\e637";
-  }
-  
-  .ss-icon-a-ljt1:before {
-    content: "\e638";
-  }
-  
-  .ss-icon-suoxiao:before {
-    content: "\e639";
-  }
-  
-  .ss-icon-xiajiaobiao:before {
-    content: "\e63b";
-  }
-  
-  .ss-icon-fanhuishangyibu:before {
-    content: "\e63c";
-  }
-  
-  .ss-icon-X:before {
-    content: "\e63d";
-  }
-  
-  .ss-icon-qian:before {
-    content: "\e63e";
-  }
-  
-  .ss-icon-wenjianjia_zhankai:before {
-    content: "\e640";
-  }
-  
-  .ss-icon-home:before {
-    content: "\e641";
-  }
-  
-  .ss-icon-tingyong:before {
-    content: "\e642";
-  }
-  
-  .ss-icon-xuanzhong_jiaobiao:before {
-    content: "\e613";
-  }
-  
-  .ss-icon-zaixianbangzhu:before {
-    content: "\e614";
-  }
-  
-  .ss-icon-qingjia:before {
-    content: "\e615";
-  }
-  
-  .ss-icon-xiayizhang:before {
-    content: "\e616";
-  }
-  
-  .ss-icon-shengqing:before {
-    content: "\e617";
-  }
-  
-  .ss-icon-wupin:before {
-    content: "\e618";
-  }
-  
-  .ss-icon-zitiyanse:before {
-    content: "\e619";
-  }
-  
-  .ss-icon-suofang:before {
-    content: "\e61a";
-  }
-  
-  .ss-icon-yanjing:before {
-    content: "\e61b";
-  }
-  
-  .ss-icon-tupian:before {
-    content: "\e61c";
-  }
-  
-  .ss-icon-piliang:before {
-    content: "\e61d";
-  }
-  
-  .ss-icon-xiangshangjiantou:before {
-    content: "\e61e";
-  }
-  
-  .ss-icon-shezhi:before {
-    content: "\e61f";
-  }
-  
-  .ss-icon-wenben:before {
-    content: "\e620";
-  }
-  
-  .ss-icon-yonghuming:before {
-    content: "\e621";
-  }
-  
-  .ss-icon-shoufukuan:before {
-    content: "\e622";
-  }
-  
-  .ss-icon-xueyuan:before {
-    content: "\e623";
-  }
-  
-  .ss-icon-xiangxiahebing:before {
-    content: "\e624";
-  }
-  
-  .ss-icon-sanheng:before {
-    content: "\e625";
-  }
-  
-  .ss-icon-zihao:before {
-    content: "\e626";
-  }
-  
-  .ss-icon-jianshao:before {
-    content: "\e627";
-  }
-  
-  .ss-icon-a-mima1:before {
-    content: "\e628";
-  }
-  
-  .ss-icon-zuopaihuanrao:before {
-    content: "\e629";
-  }
-  
-  .ss-icon-xiangyouhebing:before {
-    content: "\e62a";
-  }
-  
-  .ss-icon-zitiyangshi:before {
-    content: "\e62b";
-  }
-  
-  .ss-icon-renyuan-:before {
-    content: "\e62c";
-  }
-  
-  .ss-icon-xiangmushezhi:before {
-    content: "\e602";
-  }
-  
-  .ss-icon-yiban:before {
-    content: "\e603";
-  }
-  
-  .ss-icon-wangzhan:before {
-    content: "\e604";
-  }
-  
-  .ss-icon-yujing:before {
-    content: "\e605";
-  }
-  
-  .ss-icon-zitishanchu:before {
-    content: "\e606";
-  }
-  
-  .ss-icon-yikatong:before {
-    content: "\e607";
-  }
-  
-  .ss-icon-xieti:before {
-    content: "\e608";
-  }
-  
-  .ss-icon-xietong:before {
-    content: "\e609";
-  }
-  
-  .ss-icon-zuanshi:before {
-    content: "\e60a";
-  }
-  
-  .ss-icon-zihao2:before {
-    content: "\e60b";
-  }
-  
-  .ss-icon-zhognjianduiqi:before {
-    content: "\e60c";
-  }
-  
-  .ss-icon-zuoduiqi:before {
-    content: "\e60d";
-  }
-  
-  .ss-icon-wenjianjia-shouqi:before {
-    content: "\e60e";
-  }
-  
-  .ss-icon-xiahuaxian:before {
-    content: "\e60f";
-  }
-  
-  .ss-icon-zhifangtu:before {
-    content: "\e610";
-  }
-  
-  .ss-icon-ziti:before {
-    content: "\e611";
-  }
-  
-  .ss-icon-yanzhengma:before {
-    content: "\e612";
-  }
-  

+ 0 - 984
skin/easy/css/iconfont.css

@@ -1,984 +0,0 @@
-@font-face {
-  font-family: "iconfont"; /* Project id 4810824 */
-  src: url('../fonts/iconfont.woff2') format('woff2'),
-}
-.iconfont {
-  font-family: "iconfont" !important;
-  font-size: 16px;
-  font-style: normal;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-.icon-kehulaifang:before {
-  content: "\e6f2";
-}
-
-.icon-qiehuan_xi:before {
-  content: "\e6f1";
-}
-
-.icon-qiehuan:before {
-  content: "\e6f0";
-}
-
-.icon-xunchajilu:before {
-  content: "\e6ef";
-}
-
-.icon-jinchujilu:before {
-  content: "\e6ee";
-}
-
-.icon-richeng:before {
-  content: "\e6ed";
-}
-
-.icon-men:before {
-  content: "\e6ec";
-}
-
-.icon-gangwei:before {
-  content: "\e6eb";
-}
-
-.icon-banji:before {
-  content: "\e6e9";
-}
-
-.icon-qunzu:before {
-  content: "\e6ea";
-}
-
-.icon-cheliang:before {
-  content: "\e6e8";
-}
-
-.icon-paixu:before {
-  content: "\e6e7";
-}
-
-.icon-jiaoshi:before {
-  content: "\e6e6";
-}
-
-.icon-a-binghangfenzhi:before {
-  content: "\e6e5";
-}
-
-.icon-banjie:before {
-  content: "\e6e4";
-}
-
-.icon-huiqian:before {
-  content: "\e6e3";
-}
-
-.icon-zhihang:before {
-  content: "\e6e2";
-}
-
-.icon-chaosong:before {
-  content: "\e6e1";
-}
-
-.icon-lianxian:before {
-  content: "\e6e0";
-}
-
-.icon-sanjiaogantanhao:before {
-  content: "\e6df";
-}
-
-.icon-huidaodingbu:before {
-  content: "\e6de";
-}
-
-.icon-yishuzhao_nv:before {
-  content: "\e6dc";
-}
-
-.icon-yishuzhao_nan:before {
-  content: "\e6dd";
-}
-
-.icon-xiawu:before {
-  content: "\e6d9";
-}
-
-.icon-night:before {
-  content: "\e6da";
-}
-
-.icon-shangwu:before {
-  content: "\e6db";
-}
-
-.icon-a-dianhua01:before {
-  content: "\e6d8";
-}
-
-.icon-cheliangyuyue:before {
-  content: "\e6d7";
-}
-
-.icon-xiaofeijilu:before {
-  content: "\e6d6";
-}
-
-.icon-dianming:before {
-  content: "\e6d5";
-}
-
-.icon-xuncha:before {
-  content: "\e6d3";
-}
-
-.icon-a-yuanxingren2:before {
-  content: "\e6d4";
-}
-
-.icon-yuyan:before {
-  content: "\e6d2";
-}
-
-.icon-tongjitu:before {
-  content: "\e6d1";
-}
-
-.icon-gerenxinxi:before {
-  content: "\e6d0";
-}
-
-.icon-yishuzhao:before {
-  content: "\e6cf";
-}
-
-.icon-zhengjianzhao:before {
-  content: "\e6ce";
-}
-
-.icon-wenhao_xi:before {
-  content: "\e6cd";
-}
-
-.icon-a-quanping_xi:before {
-  content: "\e6ca";
-}
-
-.icon-tuichuquanping:before {
-  content: "\e6cb";
-}
-
-.icon-tuichuquanping_xi:before {
-  content: "\e6cc";
-}
-
-.icon-fansuojin:before {
-  content: "\e6c9";
-}
-
-.icon-bianhao:before {
-  content: "\e6c7";
-}
-
-.icon-suojin:before {
-  content: "\e6c8";
-}
-
-.icon-xuanxiangka:before {
-  content: "\e6c6";
-}
-
-.icon-gerenxuanzhi:before {
-  content: "\e6c5";
-}
-
-.icon-a-quanping:before {
-  content: "\e6c4";
-}
-
-.icon-fuhao:before {
-  content: "\e6c3";
-}
-
-.icon-saozhou:before {
-  content: "\e6c2";
-}
-
-.icon-gouxuankuang:before {
-  content: "\e6c0";
-}
-
-.icon-gouxuankuang-xuanzhong:before {
-  content: "\e6c1";
-}
-
-.icon-zhuanhuan:before {
-  content: "\e6bf";
-}
-
-.icon-jinchu:before {
-  content: "\e6be";
-}
-
-.icon-qiye:before {
-  content: "\e6b5";
-}
-
-.icon-yinshipin-mian:before {
-  content: "\e6b6";
-}
-
-.icon-zhengfu:before {
-  content: "\e6b7";
-}
-
-.icon-yinpin-mian:before {
-  content: "\e6b8";
-}
-
-.icon-zhengshu:before {
-  content: "\e6b9";
-}
-
-.icon-shipin-mian:before {
-  content: "\e6ba";
-}
-
-.icon-tingtong:before {
-  content: "\e6bb";
-}
-
-.icon-yinbo:before {
-  content: "\e6bc";
-}
-
-.icon-guangbo:before {
-  content: "\e6bd";
-}
-
-.icon-laba:before {
-  content: "\e6b4";
-}
-
-.icon-shoufukuan:before {
-  content: "\e6b3";
-}
-
-.icon-xiangzuoshuangjiantou:before {
-  content: "\e6b1";
-}
-
-.icon-xiangyoushuangjiantou:before {
-  content: "\e6b2";
-}
-
-.icon-gouwuche:before {
-  content: "\e6b0";
-}
-
-.icon-qingjia:before {
-  content: "\e6af";
-}
-
-.icon-diqiu2:before {
-  content: "\e6ae";
-}
-
-.icon-lieshu:before {
-  content: "\e6ad";
-}
-
-.icon-gonggao:before {
-  content: "\e6ac";
-}
-
-.icon-shouxie:before {
-  content: "\e6ab";
-}
-
-.icon-renyuan2:before {
-  content: "\e6aa";
-}
-
-.icon-lifangti:before {
-  content: "\e6a9";
-}
-
-.icon-i:before {
-  content: "\e6a8";
-}
-
-.icon-suoping-mian:before {
-  content: "\e69f";
-}
-
-.icon-kapian:before {
-  content: "\e6a0";
-}
-
-.icon-tuichu-mian:before {
-  content: "\e6a1";
-}
-
-.icon-jianhao:before {
-  content: "\e6a2";
-}
-
-.icon-saoyisao:before {
-  content: "\e6a3";
-}
-
-.icon-saoyisao2:before {
-  content: "\e6a4";
-}
-
-.icon-liebiao:before {
-  content: "\e6a5";
-}
-
-.icon-shandian:before {
-  content: "\e6a6";
-}
-
-.icon-wenhao:before {
-  content: "\e6a7";
-}
-
-.icon-fukuan:before {
-  content: "\e68e";
-}
-
-.icon-queding:before {
-  content: "\e68f";
-}
-
-.icon-shouye:before {
-  content: "\e690";
-}
-
-.icon-xiazai:before {
-  content: "\e691";
-}
-
-.icon-huiyi:before {
-  content: "\e692";
-}
-
-.icon-X-xi:before {
-  content: "\e693";
-}
-
-.icon-kaoqin:before {
-  content: "\e694";
-}
-
-.icon-suo-kai:before {
-  content: "\e695";
-}
-
-.icon-quanxiangzuo:before {
-  content: "\e696";
-}
-
-.icon-suo-guan:before {
-  content: "\e697";
-}
-
-.icon-shoucang:before {
-  content: "\e698";
-}
-
-.icon-bofangqi:before {
-  content: "\e699";
-}
-
-.icon-shubiao-bianji:before {
-  content: "\e69a";
-}
-
-.icon-shubiaodianji:before {
-  content: "\e69b";
-}
-
-.icon-fenleiqi:before {
-  content: "\e69c";
-}
-
-.icon-changyongyu:before {
-  content: "\e69d";
-}
-
-.icon-a-wenben1:before {
-  content: "\e69e";
-}
-
-.icon-zihao:before {
-  content: "\e67d";
-}
-
-.icon-zuoduanduiqi:before {
-  content: "\e67e";
-}
-
-.icon-youduanduiqi:before {
-  content: "\e67f";
-}
-
-.icon-ziti:before {
-  content: "\e680";
-}
-
-.icon-zitiyanse:before {
-  content: "\e681";
-}
-
-.icon-zitiyangshi:before {
-  content: "\e682";
-}
-
-.icon-tupian:before {
-  content: "\e683";
-}
-
-.icon-pinxing:before {
-  content: "\e684";
-}
-
-.icon-xiahuaxian:before {
-  content: "\e685";
-}
-
-.icon-a-zhongzuo1:before {
-  content: "\e686";
-}
-
-.icon-leida:before {
-  content: "\e687";
-}
-
-.icon-fanhuishangyibu:before {
-  content: "\e688";
-}
-
-.icon-yifu-mian:before {
-  content: "\e689";
-}
-
-.icon-canshu:before {
-  content: "\e68a";
-}
-
-.icon-jiacu:before {
-  content: "\e68b";
-}
-
-.icon-canshushezhi:before {
-  content: "\e68c";
-}
-
-.icon-baocun:before {
-  content: "\e68d";
-}
-
-.icon-xieti:before {
-  content: "\e66b";
-}
-
-.icon-wenzishangjiaobiao:before {
-  content: "\e66c";
-}
-
-.icon-wenziyouhuanrao:before {
-  content: "\e66d";
-}
-
-.icon-huaxianzi:before {
-  content: "\e66e";
-}
-
-.icon-dayinji:before {
-  content: "\e66f";
-}
-
-.icon-wenzishunpai:before {
-  content: "\e670";
-}
-
-.icon-wenzizuohuanrao:before {
-  content: "\e671";
-}
-
-.icon-chaifen:before {
-  content: "\e672";
-}
-
-.icon-hebing:before {
-  content: "\e673";
-}
-
-.icon-xiangyouhebing:before {
-  content: "\e674";
-}
-
-.icon-xiangxiahebing:before {
-  content: "\e675";
-}
-
-.icon-a-lianjie1:before {
-  content: "\e676";
-}
-
-.icon-biaoge:before {
-  content: "\e677";
-}
-
-.icon-quanwenjiansuo:before {
-  content: "\e678";
-}
-
-.icon-shanchubiaoge:before {
-  content: "\e679";
-}
-
-.icon-duixiang:before {
-  content: "\e67a";
-}
-
-.icon-zhongjianduiqi:before {
-  content: "\e67b";
-}
-
-.icon-liangduanduiqi:before {
-  content: "\e67c";
-}
-
-.icon-bingtu:before {
-  content: "\e658";
-}
-
-.icon-gou-mian:before {
-  content: "\e659";
-}
-
-.icon-huizhang:before {
-  content: "\e65a";
-}
-
-.icon-duihuapaopao2:before {
-  content: "\e65b";
-}
-
-.icon-daiban:before {
-  content: "\e65c";
-}
-
-.icon-zuoshangjiaobiao:before {
-  content: "\e65d";
-}
-
-.icon-wenben:before {
-  content: "\e65e";
-}
-
-.icon-ifuhao:before {
-  content: "\e65f";
-}
-
-.icon-caogaoxiang:before {
-  content: "\e660";
-}
-
-.icon-gongwen:before {
-  content: "\e661";
-}
-
-.icon-dasha:before {
-  content: "\e662";
-}
-
-.icon-yiban:before {
-  content: "\e663";
-}
-
-.icon-naoling:before {
-  content: "\e664";
-}
-
-.icon-wenzidise:before {
-  content: "\e665";
-}
-
-.icon-diqiu:before {
-  content: "\e666";
-}
-
-.icon-X-cu:before {
-  content: "\e667";
-}
-
-.icon-wendang:before {
-  content: "\e668";
-}
-
-.icon-wenzibuhuanrao:before {
-  content: "\e669";
-}
-
-.icon-wenzixiajiaobiao:before {
-  content: "\e66a";
-}
-
-.icon-zhifangtu:before {
-  content: "\e647";
-}
-
-.icon-piliangdaoru:before {
-  content: "\e648";
-}
-
-.icon-leidasaomiao:before {
-  content: "\e649";
-}
-
-.icon-xietong:before {
-  content: "\e64a";
-}
-
-.icon-zuanshi:before {
-  content: "\e64b";
-}
-
-.icon-taishidiannao:before {
-  content: "\e64c";
-}
-
-.icon-guanlian:before {
-  content: "\e64d";
-}
-
-.icon-fanghe:before {
-  content: "\e64e";
-}
-
-.icon-fuzhi:before {
-  content: "\e64f";
-}
-
-.icon-deng:before {
-  content: "\e650";
-}
-
-.icon-daochu:before {
-  content: "\e651";
-}
-
-.icon-sifangge:before {
-  content: "\e652";
-}
-
-.icon-jiantou:before {
-  content: "\e653";
-}
-
-.icon-lajitong:before {
-  content: "\e654";
-}
-
-.icon-duihuapaopao:before {
-  content: "\e655";
-}
-
-.icon-liucheng:before {
-  content: "\e656";
-}
-
-.icon-xiangzuojiantou2:before {
-  content: "\e657";
-}
-
-.icon-fangdajing:before {
-  content: "\e633";
-}
-
-.icon-suoxiao:before {
-  content: "\e634";
-}
-
-.icon-xunhuan:before {
-  content: "\e635";
-}
-
-.icon-wentiliebiao:before {
-  content: "\e636";
-}
-
-.icon-mubiao:before {
-  content: "\e637";
-}
-
-.icon-tuihui:before {
-  content: "\e638";
-}
-
-.icon-tingyong:before {
-  content: "\e639";
-}
-
-.icon-zhongzuo:before {
-  content: "\e63a";
-}
-
-.icon-zhifeiji:before {
-  content: "\e63b";
-}
-
-.icon-qiandaizi-mian:before {
-  content: "\e63c";
-}
-
-.icon-qianfuhao:before {
-  content: "\e63d";
-}
-
-.icon-xiangxiajiantou:before {
-  content: "\e63e";
-}
-
-.icon-xiangshangjiantou:before {
-  content: "\e63f";
-}
-
-.icon-xiangyoujiantou:before {
-  content: "\e640";
-}
-
-.icon-xiangzuojiantou:before {
-  content: "\e641";
-}
-
-.icon-yanjing-kai:before {
-  content: "\e642";
-}
-
-.icon-dianzan:before {
-  content: "\e643";
-}
-
-.icon-qizhi:before {
-  content: "\e644";
-}
-
-.icon-dangan:before {
-  content: "\e645";
-}
-
-.icon-dingwei:before {
-  content: "\e646";
-}
-
-.icon-charuhang:before {
-  content: "\e621";
-}
-
-.icon-tuozhuai:before {
-  content: "\e622";
-}
-
-.icon-xueyuan:before {
-  content: "\e623";
-}
-
-.icon-jinyong:before {
-  content: "\e624";
-}
-
-.icon-excel:before {
-  content: "\e625";
-}
-
-.icon-xiangshangshengjiantou:before {
-  content: "\e626";
-}
-
-.icon-word:before {
-  content: "\e627";
-}
-
-.icon-xiuxue:before {
-  content: "\e628";
-}
-
-.icon-lianjie:before {
-  content: "\e629";
-}
-
-.icon-X-mian:before {
-  content: "\e62a";
-}
-
-.icon-bugouxuan:before {
-  content: "\e62b";
-}
-
-.icon-neirongku:before {
-  content: "\e62c";
-}
-
-.icon-gouxuan:before {
-  content: "\e62d";
-}
-
-.icon-fenlei1:before {
-  content: "\e62e";
-}
-
-.icon-chazhao:before {
-  content: "\e62f";
-}
-
-.icon-chilun:before {
-  content: "\e630";
-}
-
-.icon-yanjing-bi:before {
-  content: "\e631";
-}
-
-.icon-shuben:before {
-  content: "\e632";
-}
-
-.icon-jiahao:before {
-  content: "\e60d";
-}
-
-.icon-shezhi-mian:before {
-  content: "\e60e";
-}
-
-.icon-yaoyiyaoshouji-kongxin:before {
-  content: "\e60f";
-}
-
-.icon-bianji:before {
-  content: "\e610";
-}
-
-.icon-biaoqian:before {
-  content: "\e611";
-}
-
-.icon-fanhuijiantou:before {
-  content: "\e612";
-}
-
-.icon-quanxuan:before {
-  content: "\e613";
-}
-
-.icon-gongcheng:before {
-  content: "\e614";
-}
-
-.icon-kuangxuanzhong:before {
-  content: "\e615";
-}
-
-.icon-biaoqing:before {
-  content: "\e616";
-}
-
-.icon-xiangji:before {
-  content: "\e617";
-}
-
-.icon-a-kuangrujiantou:before {
-  content: "\e618";
-}
-
-.icon-kuang-kaikou:before {
-  content: "\e619";
-}
-
-.icon-huihe:before {
-  content: "\e61a";
-}
-
-.icon-jieshu:before {
-  content: "\e61b";
-}
-
-.icon-dengpao:before {
-  content: "\e61c";
-}
-
-.icon-kaishi:before {
-  content: "\e61d";
-}
-
-.icon-shanchulie:before {
-  content: "\e61e";
-}
-
-.icon-shanchuhang:before {
-  content: "\e61f";
-}
-
-.icon-charulie:before {
-  content: "\e620";
-}
-
-.icon-jinru:before {
-  content: "\e600";
-}
-
-.icon-a-yuanxingren:before {
-  content: "\e601";
-}
-
-.icon-chenggong:before {
-  content: "\e602";
-}
-
-.icon-yaoyiyao-mian:before {
-  content: "\e603";
-}
-
-.icon-tuichu:before {
-  content: "\e604";
-}
-
-.icon-renyuan:before {
-  content: "\e605";
-}
-
-.icon-shijian:before {
-  content: "\e606";
-}
-
-.icon-kaisuo:before {
-  content: "\e607";
-}
-
-.icon-anquandunpai:before {
-  content: "\e608";
-}
-
-.icon-qiehuanyonghu:before {
-  content: "\e609";
-}
-
-.icon-a-wenjianjia:before {
-  content: "\e60a";
-}
-
-.icon-wenjianjia-he:before {
-  content: "\e60b";
-}
-
-.icon-wenjianjia-kai:before {
-  content: "\e60c";
-}
-

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 1
skin/easy/css/jodit.css


+ 0 - 36
skin/easy/css/var.css

@@ -1,36 +0,0 @@
-html{
-    --danger: #cc3600;
-    --primary: #6b9eee;
-    --warn: #dc6a12;
-    --success: #7ebf50;
-    --words: #373737;
-    --lightWords: #999;
-    --lightgray: #edf1f5;
-    --gray: #b4b8bc;
-    --lightdark: #3a3e51;
-    --lightdark-sub: #555a6b;
-    --dark: #252835;
-    --white: #fff;
-    --space-size: 20px;
-    --el-color-primary: #393d51 !important;
-}
-.left-side-container[size="max"] {
---menu-item-label-visible: visible;
---menu-item-label-opacity: 1;
-}
-.layout-container[sys-mode="edit"] {
---menu-add-btn-display: flex;
---menu-edit-mark-display: block;
-}
-.imgUnHandle {
-    user-drag: none;
-    -webkit-user-drag: none;
-    -khtml-user-drag: none;
-    -webkit-touch-callout: none;
-    -webkit-user-select: none;
-    -khtml-user-select: none;
-    -moz-user-select: none;
-    -ms-user-select: none;
-    user-select: none;
-  }
-  

+ 0 - 1051
skin/easy/dlg.css

@@ -1,1051 +0,0 @@
-
-/* 新添加样式    设置dhtmlx_wins_body_inner顶部边框*/
-.dhtmlx_wins_body_inner{
-	/* border-top:2px solid #edf1f5; */
-}
-
-/*  修改样式		设置弹窗圆角*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_body_outer
-, .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_body_outer {
-	position: absolute;
-	overflow: hidden;
-	left: 0px;
-	top: 0px;
-	background-color: #fff;
-	/* border: #bcbdbf 1px solid; */
-	border-radius: 4px;
-}
-
-/*   修改样式   设置弹窗标题位置*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_title
-, .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_title{
-	position: absolute;
-	top: 0px;
-	height: 37px;
-	line-height:27px;
-	vertical-align: middle;
-	padding-left: 5px;
-	left: 0px;
-	cursor: default;
-	white-space: nowrap;
-	overflow: hidden;
-	-moz-user-select: none;
-	font-size: 16px;
-	color: #333;
-	font-family: 'SimHei','Microsoft YaHei', 'Helvetica Neue', Helvetica!important;
-	text-indent: 6px;
-	font-weight: normal;
-}
-
-/*  修改样式 设置弹窗按钮区域距离顶部的距离*/
-/* buttons */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_btns {
-	position: absolute;
-	right: 0px;
-	top: 0px;
-	display: flex;
-	align-items: center;
-	/* height: 60px; */
-}
-
-/* active window */
-/*20180827  修改样式  活动状态弹窗样式*/
-div.dhtmlx_window_active{
-	box-shadow: 7px 7px 5px rgba(0, 0, 0, 0.25);
-	border-radius: 4px;
-}
-
-/* .dhtmlx_button_editWdHelp_save_default,.dhtmlx_button_editWdHelp_save_over_default{
-	background: url("image/dialog-wdRecord-save.png") center center no-repeat;
-} */
-
-/*    修改样式   设置弹窗按钮大小 */
-div.dhtmlx_wins_btns_button {
-	margin-left: 5px;
-	float: left;
-	width: 36px;
-	height: 36px;
-}
-
-
-/*--------------------------------------------------------上方为需要改动的样式------------------------------------------*/
-
-
-
-
-
-
-/*原样式*/
-
-
-.test--------{
-	position: absolute;
-	overflow: hidden;
-	left: 0px;
-	top: 0px;
-	background-color: #fff;
-	border: #a4bed4 1px solid;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_body_outer div.dhtmlx_wins_body_inner
-, .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_body_outer div.dhtmlx_wins_body_inner{
-	border-top: 1px solid #e2e4ec;
-	position: absolute;
-	overflow: hidden;
-	/*margin-top: 20px;*/
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active .dhtmlx_wins_no_header
-, .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive .dhtmlx_wins_no_header{ /* will added to div.dhtmlx_wins_body_inner in case of no header */
-	border-top: #c2d5dc 6px solid !important;
-}
-
-.animate{
-	animation: move .35s ease-in-out;
-	position:absolute; 
-}
-@keyframes move{
-	from{
-		left:-300px;
-	}
-	to {
-		left:0px;
-	}
-}
-
-@-webkit-keyframes move{
-	from {
-		left:-300px;
-	}
-	to {
-		left:0px;
-	}
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_title a
-, .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_title a{
-    color: #666;
-    font-size: 18px;
-	font-family: "SimHei",Georgia,Serif !important;
-    text-decoration: none;
-}
-/* active progress */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_progress 
- {
-	background-image: url("image/active/progress.gif");
-}
-
-
-/* active buttons */
-/* close */
-
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_close_disabled 
-,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_close_disabled 
- {
-	background-position: -96px -48px;
-}
-
-/* minmax1 */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax1_default {
-	background-position: -64px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax1_disabled {
-	background-position: -64px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax1_over_default {
-	background-position: -64px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax1_over_pressed {
-	background-position: -64px -32px;
-}
-/* minmax2 */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax2_default {
-	background-position: -80px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax2_disabled {
-	background-position: -80px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax2_over_default {
-	background-position: -80px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_minmax2_over_pressed {
-	background-position: -80px -32px;
-}
-/* park */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_park_default {
-	background-position: -48px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_park_disabled {
-	background-position: -48px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_park_over_default {
-	background-position: -48px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_park_over_pressed {
-	background-position: -48px -32px;
-}
-/* stick */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_stick_default {
-	background-position: 0px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_stick_disabled {
-	background-position: 0px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_stick_over_default {
-	background-position: 0px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_stick_over_pressed {
-	background-position: 0px -32px;
-}
-/* sticked */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_sticked_default {
-	background-position: -16px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_sticked_disabled {
-	background-position: -16px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_sticked_over_default {
-	background-position: -16px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_sticked_over_pressed {
-	background-position: -16px -32px;
-}
-/* help */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_help_default {
-	background-position: -32px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_help_disabled {
-	background-position: -32px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_help_over_default {
-	background-position: -32px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_help_over_pressed {
-	background-position: -32px -32px;
-}
-/* dock */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_dock_default {
-	background-position: -112px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_dock_disabled {
-	background-position: -112px -48px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_dock_over_default {
-	background-position: -112px -16px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_dock_over_pressed {
-	background-position: -112px -32px;
-}
-
-
-/* inactive window */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_body_outer {
-	position: absolute;
-	overflow: hidden;
-	left: 0px;
-	top: 0px;
-	background-color: #fff;
-	border: #a4bed4 1px solid;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_body_outer div.dhtmlx_wins_body_inner {
-	position: absolute;
-	overflow: hidden;
-	border-top: none;
-	/*申请人弹出窗背景灰色问题*/
-	/*background-color: #ebebeb;*/
-	/*border: #ebebeb 2px solid !important;*/
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive .dhtmlx_wins_no_header { /* will added to div.dhtmlx_wins_body_inner in case of no header */
-	border-top: #c2d5dc 6px solid;
-}
-/* .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_title {
-	position: absolute;
-	top: 0px;
-	height: 29px;
-	line-height: 29px;
-	vertical-align: middle;
-	padding-left: 28px;
-	left: 0px;
-	color: #686868;
-	font-family: Tahoma;
-	font-size: 11px;
-	font-weight: bold;
-	cursor: default;
-	white-space: nowrap;
-	overflow: hidden;
-	-moz-user-select: none;
-} */
-/*inactive progress*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_progress {
-	background-image: url("image/inactive/progress.gif");
-}
-/*inactive butons
-close*/
-
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_close_disabled {
-	background-position: -96px -112px;
-}
-
-
-/* minmax1 */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax1_default {
-	background-position: -64px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax1_disabled {
-	background-position: 0px 0px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax1_over_default {
-	background-position: -64px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax1_over_pressed {
-	background-position: -64px -96px;
-}
-/* minmax2 */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax2_default {
-	background-position: -80px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax2_disabled {
-	background-position: -80px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax2_over_default {
-	background-position: -80px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_minmax2_over_pressed {
-	background-position: -80px -96px;
-}
-/*park*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_park_default {
-	background-position: -48px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_park_disabled {
-	background-position: -48px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_park_over_default {
-	background-position: -48px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_park_over_pressed {
-	background-position: -48px -96px;
-}
-/*stick*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_stick_default {
-	background-position: 0px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_stick_disabled {
-	background-position: 0px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_stick_over_default {
-	background-position: 0px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_stick_over_pressed {
-	background-position: 0px -96px;
-}
-/*sticked*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_sticked_default {
-	background-position: -16px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_sticked_disabled {
-	background-position: -16px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_sticked_over_default {
-	background-position: -16px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_sticked_over_pressed {
-	background-position: -16px -96px;
-}
-/*help*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_help_default {
-	background-position: -32px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_help_disabled {
-	background-position: -32px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_help_over_default {
-	background-position: -32px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_help_over_pressed {
-	background-position: -32px -96px;
-}
-/*dock*/
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_dock_default {
-	background-position: -112px -64px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_dock_disabled {
-	background-position: -112px -112px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_dock_over_default {
-	background-position: -112px -80px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_dock_over_pressed {
-	background-position: -112px -96px;
-}
-
-/* common */
-/* content blocker */
-/*
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_main_content_blocker {
-	position: absolute;
-	left: 0px;
-	top: 0px;
-	width: 101%;
-	height: 101%;
-	filter: alpha(opacity=0);
-	-moz-opacity: 0;
-	opacity: 0;
-	background: #FFFFFF;
-	z-index: 1;
-	-moz-user-select: none;
-}
-*/
-/* window icon */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_icon {
-	position: absolute;
-	top: 15px;
-	left: 5px;
-	width: 16px;
-	height: 16px;
-	border: none;
-	z-index: 1;
-	-moz-user-select: none;
-	background-repeat: no-repeat;
-	font-size: 1px;
-}
-
-
-/*关闭*/
-
-/*
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_main_content {
-	position: relative;
-	left: 0px;
-	top: 0px;
-	overflow: hidden;
-}
-*/
-/* resizers */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_resizer_t {
-	display: none;
-	position: absolute;
-	left: 0px;
-	top: 0px;
-	width: 100%;
-	height: 0; /* should be generated by script */
-	font-size: 1px;
-	background: #FFFFFF;
-	z-index: 1;
-	filter: alpha(opacity=0);
-	-moz-opacity: 0;
-	opacity: 0;
-	-moz-user-select: none;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_resizer_l {
-	display: none;
-	position: absolute;
-	left: 0px;
-	top: 0px;
-	width: 0; /* should be generated by script */
-	height: 100%;
-	font-size: 1px;
-	background: #FFFFFF;
-	z-index: 1;
-	filter: alpha(opacity=0);
-	-moz-opacity: 0;
-	opacity: 0;
-	-moz-user-select: none;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_resizer_r {
-	display: none;
-	position: absolute;
-	right: 0px;
-	top: 0px;
-	width: 0; /* should be generated by script */
-	height: 100%;
-	font-size: 1px;
-	background: #FFFFFF;
-	z-index: 1;
-	filter: alpha(opacity=0);
-	-moz-opacity: 0;
-	opacity: 0;
-	-moz-user-select: none;
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_resizer_b {
-	display: none;
-	position: absolute;
-	left: 0px;
-	bottom: 0px;
-	width: 100%;
-	height: 0; /* should be generated by script */
-	font-size: 1px;
-	background: #FFFFFF;
-	z-index: 1;
-	filter: alpha(opacity=0);
-	-moz-opacity: 0;
-	opacity: 0;
-	-moz-user-select: none;
-}
-/* progress */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_wins_progress {
-	position: absolute;
-	top: 5px;
-	left: 5px;
-	width: 16px;
-	height: 16px;
-	background-repeat: no-repeat;
-}
-/* statusbar */
-.dhtmlx_skin_dhx_skyblue div.dhxcont_sb_container {
-	position: relative;
-	height: 24px;
-}
-.dhtmlx_skin_dhx_skyblue div.dhxcont_sb_container div.dhxcont_statusbar {
-	position: relative;
-	top: 2px;
-	height: 22px;
-	line-height: 22px;
-	background-image: url("image/statusbar_bg.gif");
-	background-repeat: repeat-x;
-	width: auto;
-	padding: 0px 4px;
-	overflow: hidden;
-	white-space: nowrap;
-	border-top: none;
-	border-bottom: none;
-	border-left: #a4bed4 1px solid;
-	border-right: #a4bed4 1px solid;
-	font-family: Tahoma;
-	font-size: 11px;
-	vertical-align: middle;
-	color: #000000;
-}
-/*
-.dhtmlx_skin_dhx_skyblue div.dhxcont_statusbar {
-	position: absolute;
-	width: 100%;
-	bottom: 0px;
-	_bottom: -1px;
-	border-top: #c2d5dc 1px solid;
-	background-image: url("image/statusbar_bg.gif");
-	background-repeat: repeat-x;
-	width: 100%;
-	overflow: hidden;
-	font-family: Tahoma;
-	font-size: 11px;
-	vertical-align: middle;
-	line-height: 17px;
-	-moz-user-select: none;
-	cursor: default;
-	padding-left: 4px;
-	color: #7393ae;
-}
-*/
-
-
-.dhtmlx_skin_dhx_skyblue div.white_line {
-	/*注释原因:ry_input边框会增加白边*/
-	/*border-left: #FFFFFF 1px solid;
-	border-right: #FFFFFF 1px solid;
-	border-top: #FFFFFF 1px solid;*/
-	height: 100%;
-}
-.dhtmlx_skin_dhx_skyblue div.white_line2 {
-	position: absolute;
-	bottom: 0px;
-z-index:-1 !important;
-	/* height: 10px; */
-	width: 100%;
-	/*注释原因:ry_input边框会增加白边*/
-	/*border-bottom: #FFFFFF 1px solid;*/
-	/* font-size: 1px; */
-	/*background:#e8e9eb;*/
-}
-
-.dhtmlx_skin_dhx_skyblue .dhtmlxMenu_in_Window {
-	aborder-bottom: #cedce8 1px solid;
-	border-bottom: #a4bed4 1px solid;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*wdShare*/
-
-
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdShare_disabled 
- {	
- 	background-position: -2px -1px;
-	background-image: url("image/wdShareBIG.png");
-}
-
-
-
-
-
-
-
-
-
-/**
- * wdHelp_copyhashcode
- */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_default{
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/* background-position: 59px 0px; */
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-ID.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_disabled 
-,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_disabled 
- {	
- 	background-position: -371px -22px;
-	background-image: url("image/wdHelp_copyhashcode.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_over_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_over_default {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-ID-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_over_pressed,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_copyhashcode_over_pressed {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-ID-hover.png");
-}
-
-/**
- * wdHelp_pin
- */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_default{
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	 /*background-position: -59px 0px;*/ 
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_disabled 
-,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_disabled 
- {	
- 	/*background-position: -371px -22px;*/
-	background-image: url("image/popWindow-lock-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_over_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_over_default {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_over_pressed ,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_pin_over_pressed {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock-hover.png");
-}
-
-/**
- * wdHelp_unpin
- */
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_default{
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	 /*background-position: -59px 0px;*/ 
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_disabled 
-,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_disabled 
- {	
- 	/*background-position: -371px -22px;*/
-	background-image: url("image/popWindow-lock-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_over_default,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_over_default {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock-hover.png");
-}
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_over_pressed,
-.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_wdHelp_unpin_over_pressed {
-	cursor:pointer;
-	width:36px;
-	height:36px;
-	/*background-position: -59px 0px;*/
-	background-repeat:no-repeat;
-	background-image: url("image/popWindow-lock-hover.png");
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-/**
- * change_on
- */
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_on_default,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_on_default{
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 /* background-position: 59px 0px; */
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_on_disabled 
- ,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_on_disabled 
-  {	
-	  background-position: -371px -22px;
-	 background-image: url("image/popWindow-fullscreen.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_on_over_default,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_on_over_default {
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 /*background-position: -59px 0px;*/
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen-hover.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_on_over_pressed ,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_on_over_pressed {
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 /*background-position: -59px 0px;*/
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen-hover.png");
- }
- 
-/**
- * change_off
- */
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_off_default,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_off_default{
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_off_disabled 
- ,.dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_off_disabled 
-  {	
-	  background-position: -371px -22px;
-	 background-image: url("image/popWindow-fullscreen.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_off_over_default,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_off_over_default {
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 /*background-position: -59px 0px;*/
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen-hover.png");
- }
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_active div.dhtmlx_wins_btns .dhtmlx_button_change_off_over_pressed ,
- .dhtmlx_skin_dhx_skyblue div.dhtmlx_window_inactive div.dhtmlx_wins_btns .dhtmlx_button_change_off_over_pressed {
-	 cursor:pointer;
-	 width:36px;
-	 height:36px;
-	 /*background-position: -59px 0px;*/
-	 background-repeat:no-repeat;
-	 background-image: url("image/popWindow-fullscreen-active.png");
- }
- /*编辑选项卡按钮*/
-.icon-set{
-    display: inline-block;
-    width: 36px;
-    height: 36px;
-    background: url(image/svg_icon/xuanxiangka.svg) center center no-repeat;
-	background-size: 22px;
-}
-.icon-set:hover{
-    background: #383d50 url(image/svg_icon/xuanxiangka_hover.svg) center center no-repeat;
-	background-size: 22px;
-	border-radius: 4px;
-}
-.icon-set:active{
-    background: #000 url(image/svg_icon/xuanxiangka_hover.svg) center center no-repeat;
-	background-size: 22px;
-	border-radius: 4px;
-}
-/* 打钩按钮 */
-.icon-ok{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-ok.png) center center no-repeat;
-}
-.icon-ok:hover{
-    background: url(image/icon-ok-hover.png) center center no-repeat;
-}
-.icon-ok:active{
-    background: url(image/icon-ok-active.png) center center no-repeat;
-}
-/* 收藏按钮 */
-.icon-favorite{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/svg_icon/shoucang.svg) center center no-repeat;
-	border-radius: 4px;
-	background-size: 24px;
-}
-.icon-favorite:hover{
-    background: #383d50 url(image/svg_icon/shoucang.svg) center center no-repeat;
-	border-radius: 4px;
-	background-size: 24px;
-}
-.icon-favorite:active{
-    background: #000 url(image/svg_icon/shoucang.svg) center center no-repeat;
-	border-radius: 4px;
-	background-size: 24px;
-}
-/* 帮助按钮 */
-.icon-help{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-help.png) center center no-repeat;
-}
-.icon-help:hover{
-    background: url(image/icon-help-hover.png) center center no-repeat;
-}
-.icon-help:active{
-    background: url(image/icon-help-active.png) center center no-repeat;
-}
-/* 下载按钮 */
-.icon-download{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-download.png) center center no-repeat;
-}
-.icon-download:hover{
-    background: url(image/icon-download-hover.png) center center no-repeat;
-}
-.icon-download:active{
-    background: url(image/icon-download-active.png) center center no-repeat;
-}
-/* 锁定按钮 */
-.icon-lock{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/svg_icon/lock.svg) center center no-repeat;
-	background-size: 18px;
-}
-.icon-lock:hover{
-    background:#383d50 url(image/svg_icon/lock_hover.svg) center center no-repeat;
-	background-size: 18px;
-	border-radius: 4px;
-}
-.icon-lock:active{
-    background:#000 url(image/svg_icon/lock_hover.svg) center center no-repeat;
-	background-size: 18px;
-	border-radius: 4px;
-}
-/* 编辑个人选值按钮 */
-.icon-setValue{
-    display: inline-block;
-    width: 36px;
-    height: 36px;
-    background: url(image/svg_icon/gerenxuanzhi.svg) center center no-repeat;
-	background-size: 22px;
-}
-.icon-setValue:hover{
-    background:#383d50 url(image/svg_icon/gerenxuanzhi_hover.svg) center center no-repeat;
-	background-size: 22px;
-	border-radius: 4px;
-}
-.icon-setValue:active{
-    background:#000 url(image/svg_icon/gerenxuanzhi_hover.svg) center center no-repeat;
-	background-size: 22px;
-	border-radius: 4px;
-}
-/* 编辑帮助按钮 */
-.icon-setHelp{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-setHelp.png) center center no-repeat;
-}
-.icon-setHelp:hover{
-    background: url(image/icon-setHelp-hover.png) center center no-repeat;
-}
-.icon-setHelp:active{
-    background: url(image/icon-setHelp-active.png) center center no-repeat;
-}
-/* (内容)属性按钮 */
-.icon-property{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-property.png) center center no-repeat;
-}
-.icon-property:hover{
-    background: url(image/icon-property-hover.png) center center no-repeat;
-}
-.icon-property:active{
-    background: url(image/icon-property-active.png) center center no-repeat;
-}
-/* 变动查看-关按钮 */
-.icon-history{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-history.png) center center no-repeat;
-}
-.icon-history:hover{
-    background: url(image/icon-history-hover.png) center center no-repeat;
-}
-.icon-history:active{
-    background: url(image/icon-history-active.png) center center no-repeat;
-}
-/* 变动查看-开按钮 */
-.icon-historyOn{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-historyOn.png) center center no-repeat;
-}
-.icon-historyOn:hover{
-    background: url(image/icon-historyOn-hover.png) center center no-repeat;
-}
-.icon-historyOn:active{
-    background: url(image/icon-historyOn-active.png) center center no-repeat;
-}
-/* 已收藏按钮 */
-.icon-favoriteOn{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-favoriteOn.png) center center no-repeat;
-}
-.icon-favoriteOn:hover{
-    background: url(image/icon-favoriteOn-hover.png) center center no-repeat;
-}
-.icon-favoriteOn:active{
-    background: url(image/icon-favoriteOn-active.png) center center no-repeat;
-}
-/* 关闭按钮 */
-.largeIcon-close{
-    display: inline-block;
-    width: 48px !important;
-    height: 48px !important;
-	position: relative;
-    background: url(image/svg_icon/guanbi.svg) center center no-repeat;
-	background-size: 28px;
-}
-
-.largeIcon-close:hover{
-    background:#383d50 url(image/svg_icon/guanbi_hover.svg) center center no-repeat;
-	background-size: 28px;
-}
-.largeIcon-close:active{
-    background:#000 url(image/svg_icon/guanbi_hover.svg) center center no-repeat;
-	background-size: 28px;
-}
-.largeIcon-close::before{
-	width: 0;
-    height: 24px;
-    /* border-left: 1px solid  #383d50; */
-    content: "";
-    position: absolute;
-    top: 50%;
-    left: 0;
-    transform: translateY(-50%);
-}
-/* 全屏按钮 */
-.icon-fullscreen{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/svg_icon/quanping.svg) center center no-repeat;
-	background-size: 28px;
-}
-.icon-fullscreen:hover{
-    background: #383d50 url(image/svg_icon/quanping.svg) center center no-repeat;
-	background-size: 28px;
-	border-radius: 4px;
-}
-.icon-fullscreen:active{
-    background: #000 url(image/svg_icon/quanping.svg) center center no-repeat;
-	background-size: 28px;
-	border-radius: 4px;
-}
-/* 退出全屏按钮 */
-.icon-restore{
-    display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-restore.png) center center no-repeat;
-}
-.icon-restore:hover{
-    background: url(image/icon-restore-hover.png) center center no-repeat;
-}
-.icon-restore:active{
-    background: url(image/icon-restore-active.png) center center no-repeat;
-}
-
-/*quan_pin_button to bofang*/
-.dialog-restoreButton{
-	display: inline-block;
-    width: 22px;
-    height: 22px;
-    background: url(image/icon-fullscreen.png) center center no-repeat;
-}
-.dialog-restoreButton:hover{
-    background: url(image/icon-fullscreen-hover.png) center center no-repeat;
-}
-.dialog-restoreButton:active{
-    background: url(image/icon-fullscreen-active.png) center center no-repeat;
-}

BIN
skin/easy/fonts/.smbdeleteAAAa00000012eea9


BIN
skin/easy/fonts/iconfont.ttf


BIN
skin/easy/fonts/iconfont.woff


BIN
skin/easy/fonts/iconfont.woff2


BIN
skin/easy/fonts/iconfont_4273728.woff2


BIN
skin/easy/fonts/iconfont_4279221.woff2


+ 0 - 508
skin/easy/gate.css

@@ -1,508 +0,0 @@
-/*-----------------gate.css--------------*/
-.xx {
-	text-align: center;
-	color: #FFF;
-	font-family: 'MicrosoftYaHei [Regular]';
-	font-size: 14px;
-	margin-top: -6px;
-	line-height: 20px;
-}
-
-.xm {
-	/* line-height: 50px; */
-	margin-top: 12px;
-	/*margin-left: 57px;*/
-}
-
-#lfxx th {
-	text-align: right !important;
-}
-
-#yylf th {
-	text-align: right !important;
-}
-
-.bottomright {
-	position: absolute;
-	right: 29px;
-	border: 0px;
-	bottom: 29px;
-	/* padding: 8px; */
-}
-
-.qrcode-text {
-	font-family: "SIL Hei";
-	font-size: 14px;
-	line-height: 24px;
-	color: #FFF;
-	display: block;
-	text-align: center;
-	letter-spacing: 1px;
-}
-
-.hugeInvertLogo {
-	width: 569px;
-	height: 569px;
-}
-
-#sfzh::-webkit-input-placeholder {
-	font-size: 20px;
-	color: #6c9ed7;
-}
-
-#sfzh::-moz-placeholder {
-	/* Mozilla Firefox 19+ */
-	font-size: 20px;
-	color: #6c9ed7;
-}
-
-#sfzh:-moz-placeholder {
-	/* Mozilla Firefox 4 to 18 */
-	font-size: 20px;
-	color: #6c9ed7;
-}
-
-#sfzh:-ms-input-placeholder {
-	/* Internet Explorer 10-11 */
-	font-size: 20px;
-	color: #6c9ed7;
-}
-
-#leave,
-#back,
-#cancle {
-	width: 150px;
-	height: 50px;
-	font-size: 30px;
-	margin: 0;
-}
-
-#leave,
-#back {
-	margin-right: 100px;
-}
-
-.content-largeText input {
-	width: 388px;
-	height: 50px;
-	padding-left: 5px !important;
-	font-family: Microsoft YaHei;
-	font-size: 36px;
-	color: #000000;
-	line-height: 30px;
-	/* padding:5px 0 11px 19px;*/
-	margin-left: 1px;
-	border: 2px solid #cccccc;
-	border-radius: 2px;
-	outline-color: #6b9ed6;
-}
-
-.content-largeText input:hover {
-	border-color: #6b9ed6;
-}
-
-
-.content-largeText textarea {
-	width: 388px !important;
-	/*height: 50px !important;*/
-	font-family: Microsoft YaHei;
-	color: #000000;
-	line-height: 30px;
-	font-size: 36px;
-	padding-top: 6px !important;
-	/* padding: 5px 0 11px 5px;*/
-	/*margin-left: 18px;*/
-	border: 2px solid #cccccc;
-	border-radius: 2px;
-	outline-color: #6b9ed6;
-	margin-top: 1px;
-}
-
-.content-largeText td {
-	vertical-align: bottom;
-}
-
-
-.objectPickerNameDiv-jfbmid>.icon-down {
-	right: 8px !important;
-	top: 6px;
-}
-
-.objectPickerNameDiv-jfbjid>.icon-down {
-	right: 8px !important;
-	top: 6px;
-}
-
-.objectPickerNameDiv-xbm>.icon-down {
-	right: 8px !important;
-	top: 6px;
-}
-
-.objectPickerNameDiv-jfryid>.icon-down {
-	right: 8px !important;
-	top: 6px;
-}
-
-.objectPickerNameDiv-syid>.icon-down {
-	right: 8px !important;
-	top: 6px;
-
-}
-
-.getDateInfo {
-	opacity: 0.65;
-	position: absolute;
-	bottom: 30px;
-	left: 25px;
-	z-index: 100;
-	font-family: 'SIL Hei';
-	font-size: 24px;
-	color: #ffffff;
-	line-height: 21.5px;
-	border: 1px solid #dae6eb;
-	border-radius: 3px;
-	width: 206px;
-	height: 18px;
-	padding: 11px 30px 12px 21px;
-}
-
-.getDateInfo span {
-	margin-right: 35px;
-}
-
-.userInfo {
-	opacity: 0.65;
-
-	z-index: 100;
-	font-family: 'SIL Hei';
-	font-size: 24px;
-	color: #ffffff;
-	line-height: 21.5px;
-	border: 1px solid #dae6eb;
-	border-radius: 3px;
-	/* width: 206px; */
-	height: 18px;
-	padding: 11px 21px 12px 21px;
-
-	gap: 20px;
-	display: flex;
-	justify-content: center;
-}
-
-.popup-div {
-	width: 388px !important;
-	min-width: 388px !important;
-	/*margin-left: 18px;*/
-}
-
-.popup-div>.scrollbar {
-	padding-right: 0px !important;
-	min-width: 385px !important;
-
-}
-
-.popupList {
-	height: 40px !important;
-	line-height: 36px !important;
-	font-size: 30px !important;
-	white-space: nowrap;
-	overflow: hidden;
-}
-
-.smallButton.icon-down {
-	box-shadow: none !important;
-	background-image: url(image/dialog-select-icon.png) !important;
-	background-position: center center !important;
-	z-index: 9999;
-	right: 0px !important;
-	width: 40px !important;
-	height: 40px !important;
-}
-
-#jfsy {
-	line-height: 40px !important;
-	padding-top: 0px !important;
-	margin-top: 0px !important;
-}
-
-#objectPickergrowheightjfbmid {
-	height: 50px !important;
-}
-
-#objectPickergrowheightjfbjid {
-	height: 50px !important;
-}
-
-#objectPickergrowheightxbm {
-	height: 50px !important;
-}
-
-#objectPickergrowheightjfryid {
-	height: 50px !important;
-}
-
-#objectPickergrowheightsyid {
-	width: 389px !important;
-	height: 50px !important;
-}
-
-#ascrail2006 {
-	display: none !important;
-}
-
-.objectPickerNameDiv-syid {
-	margin-top: 1px;
-}
-
-.input-div-selected {
-	border: 0px !important;
-	box-shadow: 0px 0px 0px #FFF !important;
-	top: 1px !important;
-	left: 61px !important;
-	outline-color: #6b9ed6 !important;
-}
-
-#objectPickergrowheightxbm:hover {
-	border-color: #6b9ed6 !important;
-}
-
-#objectPickergrowheightxbm:active {
-	border-color: #6b9ed6;
-}
-
-#objectPickergrowheightjfbmid:hover {
-	border-color: #6b9ed6 !important;
-}
-
-#objectPickergrowheightjfbmid:active {
-	border-color: #6b9ed6;
-}
-
-#objectPickergrowheightjfbjid:hover {
-	border-color: #6b9ed6 !important;
-}
-
-#objectPickergrowheightjfbjid:active {
-	border-color: #6b9ed6 !important;
-}
-
-#jfsy:hover {
-	border-color: #6b9ed6 !important;
-}
-
-#jfsy:active {
-	border-color: #6b9ed6 !important;
-}
-
-
-/* 许汝桦202106022 边框 未经过叶老大确定 */
-.mainState-inportantrRed {
-	border: 15px solid #ff5a4b !important;
-	box-sizing: border-box;
-	background: #f9dcdb !important;
-}
-
-.mainState-inportantrRed>div {
-	margin-left: 46px !important;
-	margin-top: 47px !important;
-}
-
-div#ryxxlb::-webkit-scrollbar {
-	display: none;
-}
-
-#jcjllb::-webkit-scrollbar {
-	width: 0 !important;
-}
-
-.ryxxlb-child {
-	z-index: -3 !important;
-}
-
-.jcjllb-child {
-	z-index: -3 !important;
-}
-
-/* 绿色 */
-.mainState-green {
-	background-color: #c7ffe0 !important;
-}
-
-/*红色*/
-.mainState-orange {
-	background-color: #f9dcdb !important;
-}
-
-/*蓝色*/
-.mainState-blue {
-	background-color: #c7e0ff !important;
-}
-
-/* 三区域布局容器 - 固定三个位置 */
-#ryxxlb {
-	position: absolute;
-	width: 100%;
-	height: calc(100% - 60px);
-	display: grid;
-	grid-template-columns: 475px 535px 475px;
-	grid-template-areas: "left center right";
-	justify-content: center;
-	align-items: center;
-	gap: 30px;
-	padding: 0 50px;
-}
-
-/* 所有卡片的基础样式 */
-.ryxxlb-child {
-	transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
-	position: relative;
-	border: 1px white solid;
-	border-radius: 5px;
-	display: flex;
-	flex-direction: column;
-	justify-content: center;
-	align-items: center;
-	padding: 40px 30px;
-}
-
-/* 左边位置 - 小卡片 */
-.ryxxlb-child-left {
-	grid-area: left;
-	width: 475px;
-	height: 750px;
-	opacity: 0.9;
-	box-sizing: border-box;
-}
-
-/* 中间位置 - 大卡片 */
-.ryxxlb-child-center {
-	grid-area: center;
-	width: 535px;
-	height: 845px;
-	z-index: 10;
-	opacity: 1;
-	box-sizing: border-box;
-}
-
-/* 右边位置 - 小卡片 */
-.ryxxlb-child-right {
-	grid-area: right;
-	width: 475px;
-	height: 750px;
-	opacity: 0.9;
-	box-sizing: border-box;
-}
-
-/* 从中间移动到左边的动画 */
-@keyframes moveToLeft {
-	from {
-		grid-area: center;
-		width: 535px;
-		height: 845px;
-		opacity: 1;
-	}
-
-	to {
-		grid-area: left;
-		width: 475px;
-		height: 750px;
-		opacity: 0.9;
-	}
-}
-
-/* 从中间移动到右边的动画 */
-@keyframes moveToRight {
-	from {
-		grid-area: center;
-		width: 535px;
-		height: 845px;
-		opacity: 1;
-	}
-
-	to {
-		grid-area: right;
-		width: 475px;
-		height: 750px;
-		opacity: 0.9;
-	}
-}
-
-/* 淡入动画 */
-@keyframes fadeIn {
-	from {
-		opacity: 0;
-		transform: scale(0.9);
-	}
-
-	to {
-		opacity: 1;
-		transform: scale(1);
-	}
-}
-
-/* 淡出动画 */
-@keyframes fadeOut {
-	from {
-		opacity: 1;
-	}
-
-	to {
-		opacity: 0;
-		transform: scale(0.8);
-	}
-}
-
-/* 左右两边卡片的照片尺寸 */
-.ryxxlb-child-left .card-photo,
-.ryxxlb-child-right .card-photo {
-	width: 405px !important;
-	height: 548px !important;
-}
-
-/* 中间卡片的照片尺寸 */
-.ryxxlb-child-center .card-photo {
-	width: 455px !important;
-	height: 616px !important;
-}
-
-/* 左右两边卡片的姓名班级容器 */
-.ryxxlb-child-left .name-class-container,
-.ryxxlb-child-right .name-class-container {
-	font-size: 46px !important;
-}
-
-/* 中间卡片的姓名班级容器 */
-.ryxxlb-child-center .name-class-container {
-	font-size: 52px !important;
-}
-
-/* 左右两边卡片的状态文字 */
-.ryxxlb-child-left .status-text,
-.ryxxlb-child-right .status-text {
-	font-size: 46px !important;
-}
-
-/* 中间卡片的状态文字 */
-.ryxxlb-child-center .status-text {
-	font-size: 52px !important;
-}
-
-/* 进校状态文字颜色 */
-.status-enter {
-	color: #0006ff !important;
-}
-
-/* 离校状态文字颜色 */
-.status-leave {
-	color: #007339 !important;
-}
-
-/* 请假状态文字颜色 */
-.status-vacation {
-	color: #ff1212 !important;
-}
-
-/* 淡出动画类 */
-.fade-out {
-	animation: fadeOut 0.4s ease-out forwards;
-}

BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/)]BDJ_U}%HB2`9(~5X[_3H6.gif


BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/0iocntuq0mw77.gif


BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/1~CK74Y6~VGAWKZ0]3$9S@I.jpg


BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/2c06a90652cac5f927a377a7ee1fe333_5bad6ca91bd0b.gif


BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/3c7e711ca2adea83e957467144ce9d2e_5a557e794f261.gif


BIN
skin/easy/help/PC/04527db3/e38af5bd/8d7fbee0/342213b1/3f27e969531aab06b0dbc7d1521aec99_b158b81479e745b4ab28925d38bd54bc.gif


BIN
skin/easy/help/PC/29d/c3c/dc6/da1/398/eb3/42c/c18/c11/ca3/01/9.png


BIN
skin/easy/help/PC/7f40ef61/565a6831/efb01283/7adbb1db/9ce6efb31aa5c42b3329ce03aaf5aae9_5b8b5b7301a57.gif


BIN
skin/easy/help/PC/ry/0fjcklyqviz95.gif


BIN
skin/easy/help/PC/ry/25def9e1846aab73ceca6d2d959ea08e_5b513d51c5b39.gif


BIN
skin/easy/help/PC/ry/XQADGBVNXRFCUZNQ`25UBC.jpg


BIN
skin/easy/help/PC/ry/mmexport1552022002827.jpg


BIN
skin/easy/help/PC/ry/喵喵2.gif


BIN
skin/easy/help/PC/ry/微信图片_20171012135344.png


BIN
skin/easy/help/PC/ws/20150816193536_AkCru.jpeg


BIN
skin/easy/help/PC/ws/mmexport1552019840260.jpg


BIN
skin/easy/help/PC/ws/微信图片_20170527092121.jpg


BIN
skin/easy/help/PC/ws/微信图片_20171012135344.png


BIN
skin/easy/help/cd/喵喵喵喵.gif


BIN
skin/easy/help/env/1_首页banner读书、行路,做新时代高素质健康行业接班人.jpg


BIN
skin/easy/help/env/3c7e711ca2adea83e957467144ce9d2e_5a557e794f261.gif


BIN
skin/easy/help/env/mobiledealWith.gif


BIN
skin/easy/help/env/mobilekcb-xs1.png


BIN
skin/easy/help/env/mobilekcb-xs2.png


BIN
skin/easy/help/env/mobileknow.jpg


BIN
skin/easy/help/env/mobileleft-right.gif


BIN
skin/easy/help/env/mobileopenFolder.gif


BIN
skin/easy/help/env/mobilereadMore.gif


BIN
skin/easy/help/env/mobileredLine.png


BIN
skin/easy/help/env/mobileresize.gif


BIN
skin/easy/help/env/mobileright.gif


BIN
skin/easy/help/env/mobilesearch1.gif


BIN
skin/easy/help/env/mobileseei.gif


BIN
skin/easy/help/env/mobilesetUp.gif


BIN
skin/easy/help/env/mobiletongji.png


BIN
skin/easy/help/env/mobile个人首页点击头像.gif


BIN
skin/easy/help/env/mobile任教课程表 --点名.gif


BIN
skin/easy/help/env/mobile任教课程表-课堂记录页面.gif


BIN
skin/easy/help/env/mobile喵喵喵喵.gif


BIN
skin/easy/help/env/mobile定制统计图.gif


BIN
skin/easy/help/env/mobile左右切换页面.gif


BIN
skin/easy/help/env/mobile日程操作.gif


BIN
skin/easy/help/env/mobile编辑统计图.gif


BIN
skin/easy/help/env/moblieAPP左右切换页面(最新).gif


BIN
skin/easy/help/env/个人首页头像.gif


BIN
skin/easy/help/env/兔狗3.jpg


BIN
skin/easy/help/env/喵2.gif


BIN
skin/easy/help/env/喵喵.gif


BIN
skin/easy/help/env/喵喵2.gif


BIN
skin/easy/help/env/喵喵喵.gif


BIN
skin/easy/help/env/喵喵喵喵.gif


BIN
skin/easy/help/env/定制统计图.gif


BIN
skin/easy/help/env/狗兔2.jpg


BIN
skin/easy/help/mobile/help_chart/tongji.png


BIN
skin/easy/help/mobile/help_chart/tongji_edit.png


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.