Просмотр исходного кода

Merge branch 'master' of http://39.98.38.2:13000/dumingliang/gw-basic

啥意思
Lin Qilong 1 месяц назад
Родитель
Сommit
e064443a78

+ 13 - 14
gw-admin/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>goldenwater</artifactId>
         <groupId>com.goldenwater</groupId>
+        <artifactId>tba-sbh</artifactId>
         <version>3.9.2</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -16,7 +16,12 @@
     </description>
 
     <dependencies>
-
+        <!-- 达梦数据库驱动 -->
+        <dependency>
+            <groupId>com.dameng</groupId>
+            <artifactId>DmJdbcDriver18</artifactId>
+            <version>8.1.1.193</version>
+        </dependency>
         <!-- spring-boot-devtools -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -30,12 +35,6 @@
             <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
         </dependency>
 
-         <!-- Mysql驱动包 -->
-        <dependency>
-            <groupId>com.mysql</groupId>
-            <artifactId>mysql-connector-j</artifactId>
-        </dependency>
-
         <!-- 核心模块-->
         <dependency>
             <groupId>com.goldenwater</groupId>
@@ -71,15 +70,15 @@
                     </execution>
                 </executions>
             </plugin>
-            <plugin>   
-                <groupId>org.apache.maven.plugins</groupId>   
-                <artifactId>maven-war-plugin</artifactId>   
-                <version>3.1.0</version>   
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
                 <configuration>
                     <failOnMissingWebXml>false</failOnMissingWebXml>
                     <warName>${project.artifactId}</warName>
-                </configuration>   
-           </plugin>   
+                </configuration>
+            </plugin>
         </plugins>
         <finalName>${project.artifactId}</finalName>
     </build>

+ 8 - 7
gw-admin/src/main/resources/application-druid.yml → gw-admin/src/main/resources/application-dev.yml

@@ -7,7 +7,7 @@ goldenwater:
   # 版权年份
   copyrightYear: 2026
   # 文件路径 示例( Windows配置D:/goldenwater/uploadPath,Linux配置 /home/goldenwater/uploadPath)
-  profile: D:/goldenwater/uploadPath
+  profile: D:/gw/uploadPath
   # 获取ip地址开关
   addressEnabled: false
   # 验证码类型 math 数字计算 char 字符验证
@@ -16,13 +16,14 @@ goldenwater:
 spring:
   datasource:
     type: com.alibaba.druid.pool.DruidDataSource
-    driverClassName: com.mysql.cj.jdbc.Driver
+    driverClassName: dm.jdbc.driver.DmDriver
     druid:
       # 主库数据源
       master:
-        url: jdbc:mysql://39.98.38.2:13306/gw_basic?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-        username: root
-        password: GW@js1601
+        url: jdbc:dm://39.98.38.2:30236/GW_BASIC
+        #url: jdbc:dm://192.168.0.145:30236/WEPL
+        username: GW_BASIC
+        password: Gw./16001
       # 从库数据源
       slave:
         # 从数据源开关/默认关闭
@@ -96,7 +97,7 @@ spring:
       # 端口,默认为6379
       port: 16379
       # 数据库索引
-      database: 14
+      database: 15
       # 密码
       password: ZjsthGw1125
       # 连接超时时间
@@ -136,7 +137,7 @@ springdoc:
     tags-sorter: alpha
   group-configs:
     - group: 'default'
-      display-name: '测试模块'
+      display-name: '水保护模块'
       paths-to-match: '/**'
       packages-to-scan: com.goldenwater.web.controller.tool
 # knife4j 配置

+ 153 - 0
gw-admin/src/main/resources/application-test.yml

@@ -0,0 +1,153 @@
+# 项目相关配置
+goldenwater:
+  # 名称
+  name: GW
+  # 版本
+  version: 3.9.2
+  # 版权年份
+  copyrightYear: 2026
+  # 文件路径 示例( Windows配置D:/goldenwater/uploadPath,Linux配置 /home/goldenwater/uploadPath)
+  profile: D:/szybh/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数字计算 char 字符验证
+  captchaType: math
+# 数据源配置
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: dm.jdbc.driver.DmDriver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:dm://192.168.0.145:30236/GW_BASIC
+        #url: jdbc:dm://192.168.0.145:30236/WEPL
+        username: GW_BASIC
+        password: Gw./16001
+      # 从库数据源
+      slave:
+        # 从数据源开关/默认关闭
+        enabled: false
+        url:
+        username:
+        password:
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置连接超时时间
+      connectTimeout: 30000
+      # 配置网络超时时间
+      socketTimeout: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: goldenwater
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  jackson:
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  data:
+    # redis 配置
+    redis:
+      # 地址
+      host: 192.168.0.146
+      # 端口,默认为6379
+      port: 6379
+      # 数据库索引
+      database: 15
+      # 密码
+      password: ZjsthGw1125
+      # 连接超时时间
+      timeout: 10s
+      lettuce:
+        pool:
+          # 连接池中的最小空闲连接
+          min-idle: 0
+          # 连接池中的最大空闲连接
+          max-idle: 8
+          # 连接池的最大数据库连接数
+          max-active: 8
+          # #连接池最大阻塞等待时间(使用负值表示没有限制)
+          max-wait: -1ms
+# 防盗链配置
+referer:
+  # 防盗链开关
+  enabled: false
+  # 允许的域名列表
+  allowed-domains: localhost,127.0.0.1,goldenwater.vip,www.goldenwater.vip
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*
+# Springdoc配置
+springdoc:
+  api-docs:
+    path: /v3/api-docs
+  swagger-ui:
+    enabled: true
+    path: /swagger-ui.html
+    tags-sorter: alpha
+  group-configs:
+    - group: 'default'
+      display-name: '水保护模块'
+      paths-to-match: '/**'
+      packages-to-scan: com.goldenwater.web.controller.tool
+# knife4j 配置
+knife4j:
+  enable: true           # 是否启用 knife4j 页面
+  production: false      # 生产模式设置,true会关闭调试功能
+  basic:
+    enable: false        # 是否启用基础认证(可选)
+    username: ruoyi      # 基础认证用户名
+    password: 123456     # 基础认证密码
+  setting:
+    swagger-model-name: 金水系统文档  # 模型名称
+    language: zh-CN      # 界面语言设置为中文

+ 2 - 2
gw-admin/src/main/resources/application.yml

@@ -37,7 +37,7 @@ spring:
     # 国际化资源文件路径
     basename: i18n/messages
   profiles:
-    active: druid
+    active: dev
 
 # token配置
 token:
@@ -59,7 +59,7 @@ mybatis:
 
 # PageHelper分页插件
 pagehelper:
-  helperDialect: mysql
+  helperDialect: dm
   supportMethodsArguments: true
   params: count=countSql
 

+ 1 - 1
gw-common/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>goldenwater</artifactId>
         <groupId>com.goldenwater</groupId>
+        <artifactId>tba-sbh</artifactId>
         <version>3.9.2</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
gw-framework/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>goldenwater</artifactId>
         <groupId>com.goldenwater</groupId>
+        <artifactId>tba-sbh</artifactId>
         <version>3.9.2</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
gw-quartz/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>goldenwater</artifactId>
         <groupId>com.goldenwater</groupId>
+        <artifactId>tba-sbh</artifactId>
         <version>3.9.2</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
gw-system/pom.xml

@@ -3,8 +3,8 @@
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <parent>
-        <artifactId>goldenwater</artifactId>
         <groupId>com.goldenwater</groupId>
+        <artifactId>tba-sbh</artifactId>
         <version>3.9.2</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 3 - 3
gw-system/src/main/resources/mapper/system/SysMenuMapper.xml

@@ -50,13 +50,13 @@
 	</select>
 	
 	<select id="selectMenuTreeAll" resultMap="SysMenuResult">
-		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
 		from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
 		order by m.parent_id, m.order_num
 	</select>
 	
 	<select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
-		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
 		from sys_menu m
 		left join sys_role_menu rm on m.menu_id = rm.menu_id
 		left join sys_user_role ur on rm.role_id = ur.role_id
@@ -75,7 +75,7 @@
 	</select>
     
     <select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
-		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
 		from sys_menu m
 			 left join sys_role_menu rm on m.menu_id = rm.menu_id
 			 left join sys_user_role ur on rm.role_id = ur.role_id

+ 2 - 2
gw-ui/.env.development

@@ -8,7 +8,7 @@ VITE_APP_PORT = 25022
 # 前端基础路径
 VITE_APP_BASE_TITLE = '/gw'
 # 北京金水管理系统/开发环境
-VITE_SERVICE_BASE_TITLE = '/dev-api'
+VITE_SERVICE_BASE_TITLE = '/gw-api'
 
 # 后端接口基础路径
-VITE_SERVER_URL = 'http://localhost:8080'
+VITE_SERVER_URL = 'http://127.0.0.1:8080/'

+ 2 - 2
gw-ui/.env.production

@@ -8,10 +8,10 @@ VITE_APP_PORT = 25022
 # 前端基础路径
 VITE_APP_BASE_TITLE = '/gw'
 # 北京金水管理系统/生产环境
-VITE_SERVICE_BASE_TITLE = '/prod-api'
+VITE_SERVICE_BASE_TITLE = '/gw-api'
 
 # 后端接口基础路径
-VITE_SERVER_URL = 'http://localhost:8080'
+VITE_SERVER_URL = 'http://39.98.38.2:18055/gw-api'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS = gzip

+ 2 - 2
gw-ui/.env.staging

@@ -10,10 +10,10 @@ VITE_APP_PORT = 25022
 VITE_APP_BASE_TITLE = '/gw'
 
 # 北京金水管理系统/生产环境
-VITE_SERVICE_BASE_TITLE = '/stage-api'
+VITE_SERVICE_BASE_TITLE = '/gw-api'
 
 # 后端接口基础路径
-VITE_SERVER_URL = 'http://localhost:8080'
+VITE_SERVER_URL = 'http://39.98.38.2:18055/gw-api'
 
 # 是否在打包时开启压缩,支持 gzip 和 brotli
 VITE_BUILD_COMPRESS = gzip

+ 214 - 212
gw-ui/index.html

@@ -1,215 +1,217 @@
-<!DOCTYPE html>
+<!doctype html>
 <html>
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+    <meta name="renderer" content="webkit" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
+    />
+    <link rel="icon" href="/favicon.ico" />
+    <title>%VITE_APP_TITLE%</title>
+    <!--[if lt IE 11
+      ]><script>
+        window.location.href = "/html/ie.html";
+      </script><!
+    [endif]-->
+    <style>
+      html,
+      body,
+      #app {
+        height: 100%;
+        margin: 0px;
+        padding: 0px;
+      }
 
-<head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-  <meta name="renderer" content="webkit">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-  <link rel="icon" href="/favicon.ico">
-  <title>%VITE_APP_TITLE%</title>
-  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
-  <style>
-    html,
-    body,
-    #app {
-      height: 100%;
-      margin: 0px;
-      padding: 0px;
-    }
-
-    .chromeframe {
-      margin: 0.2em 0;
-      background: #ccc;
-      color: #000;
-      padding: 0.2em 0;
-    }
-
-    #loader-wrapper {
-      position: fixed;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 999999;
-    }
-
-    #loader {
-      display: block;
-      position: relative;
-      left: 50%;
-      top: 50%;
-      width: 150px;
-      height: 150px;
-      margin: -75px 0 0 -75px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 2s linear infinite;
-      -ms-animation: spin 2s linear infinite;
-      -moz-animation: spin 2s linear infinite;
-      -o-animation: spin 2s linear infinite;
-      animation: spin 2s linear infinite;
-      z-index: 1001;
-    }
-
-    #loader:before {
-      content: "";
-      position: absolute;
-      top: 5px;
-      left: 5px;
-      right: 5px;
-      bottom: 5px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -webkit-animation: spin 3s linear infinite;
-      -moz-animation: spin 3s linear infinite;
-      -o-animation: spin 3s linear infinite;
-      -ms-animation: spin 3s linear infinite;
-      animation: spin 3s linear infinite;
-    }
-
-    #loader:after {
-      content: "";
-      position: absolute;
-      top: 15px;
-      left: 15px;
-      right: 15px;
-      bottom: 15px;
-      border-radius: 50%;
-      border: 3px solid transparent;
-      border-top-color: #FFF;
-      -moz-animation: spin 1.5s linear infinite;
-      -o-animation: spin 1.5s linear infinite;
-      -ms-animation: spin 1.5s linear infinite;
-      -webkit-animation: spin 1.5s linear infinite;
-      animation: spin 1.5s linear infinite;
-    }
-
-
-    @-webkit-keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
-      }
-
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
-      }
-    }
-
-    @keyframes spin {
-      0% {
-        -webkit-transform: rotate(0deg);
-        -ms-transform: rotate(0deg);
-        transform: rotate(0deg);
-      }
-
-      100% {
-        -webkit-transform: rotate(360deg);
-        -ms-transform: rotate(360deg);
-        transform: rotate(360deg);
-      }
-    }
-
-
-    #loader-wrapper .loader-section {
-      position: fixed;
-      top: 0;
-      width: 51%;
-      height: 100%;
-      background: #7171C6;
-      z-index: 1000;
-      -webkit-transform: translateX(0);
-      -ms-transform: translateX(0);
-      transform: translateX(0);
-    }
-
-    #loader-wrapper .loader-section.section-left {
-      left: 0;
-    }
-
-    #loader-wrapper .loader-section.section-right {
-      right: 0;
-    }
-
-
-    .loaded #loader-wrapper .loader-section.section-left {
-      -webkit-transform: translateX(-100%);
-      -ms-transform: translateX(-100%);
-      transform: translateX(-100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader-wrapper .loader-section.section-right {
-      -webkit-transform: translateX(100%);
-      -ms-transform: translateX(100%);
-      transform: translateX(100%);
-      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
-    }
-
-    .loaded #loader {
-      opacity: 0;
-      -webkit-transition: all 0.3s ease-out;
-      transition: all 0.3s ease-out;
-    }
-
-    .loaded #loader-wrapper {
-      visibility: hidden;
-      -webkit-transform: translateY(-100%);
-      -ms-transform: translateY(-100%);
-      transform: translateY(-100%);
-      -webkit-transition: all 0.3s 1s ease-out;
-      transition: all 0.3s 1s ease-out;
-    }
-
-    .no-js #loader-wrapper {
-      display: none;
-    }
-
-    .no-js h1 {
-      color: #222222;
-    }
-
-    #loader-wrapper .load_title {
-      font-family: 'Open Sans';
-      color: #FFF;
-      font-size: 19px;
-      width: 100%;
-      text-align: center;
-      z-index: 9999999999999;
-      position: absolute;
-      top: 60%;
-      opacity: 1;
-      line-height: 30px;
-    }
-
-    #loader-wrapper .load_title span {
-      font-weight: normal;
-      font-style: italic;
-      font-size: 13px;
-      color: #FFF;
-      opacity: 0.5;
-    }
-  </style>
-</head>
-
-<body>
-  <div id="app">
-    <div id="loader-wrapper">
-      <div id="loader"></div>
-      <div class="loader-section section-left"></div>
-      <div class="loader-section section-right"></div>
-      <div class="load_title">正在加载系统资源,请耐心等待</div>
-    </div>
-  </div>
-  <script type="module" src="/src/main.js"></script>
-</body>
+      .chromeframe {
+        margin: 0.2em 0;
+        background: #ccc;
+        color: #000;
+        padding: 0.2em 0;
+      }
+
+      #loader-wrapper {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        z-index: 999999;
+      }
+
+      #loader {
+        display: block;
+        position: relative;
+        left: 50%;
+        top: 50%;
+        width: 150px;
+        height: 150px;
+        margin: -75px 0 0 -75px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -webkit-animation: spin 2s linear infinite;
+        -ms-animation: spin 2s linear infinite;
+        -moz-animation: spin 2s linear infinite;
+        -o-animation: spin 2s linear infinite;
+        animation: spin 2s linear infinite;
+        z-index: 1001;
+      }
+
+      #loader:before {
+        content: "";
+        position: absolute;
+        top: 5px;
+        left: 5px;
+        right: 5px;
+        bottom: 5px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -webkit-animation: spin 3s linear infinite;
+        -moz-animation: spin 3s linear infinite;
+        -o-animation: spin 3s linear infinite;
+        -ms-animation: spin 3s linear infinite;
+        animation: spin 3s linear infinite;
+      }
+
+      #loader:after {
+        content: "";
+        position: absolute;
+        top: 15px;
+        left: 15px;
+        right: 15px;
+        bottom: 15px;
+        border-radius: 50%;
+        border: 3px solid transparent;
+        border-top-color: #fff;
+        -moz-animation: spin 1.5s linear infinite;
+        -o-animation: spin 1.5s linear infinite;
+        -ms-animation: spin 1.5s linear infinite;
+        -webkit-animation: spin 1.5s linear infinite;
+        animation: spin 1.5s linear infinite;
+      }
+
+      @-webkit-keyframes spin {
+        0% {
+          -webkit-transform: rotate(0deg);
+          -ms-transform: rotate(0deg);
+          transform: rotate(0deg);
+        }
+
+        100% {
+          -webkit-transform: rotate(360deg);
+          -ms-transform: rotate(360deg);
+          transform: rotate(360deg);
+        }
+      }
+
+      @keyframes spin {
+        0% {
+          -webkit-transform: rotate(0deg);
+          -ms-transform: rotate(0deg);
+          transform: rotate(0deg);
+        }
+
+        100% {
+          -webkit-transform: rotate(360deg);
+          -ms-transform: rotate(360deg);
+          transform: rotate(360deg);
+        }
+      }
+
+      #loader-wrapper .loader-section {
+        position: fixed;
+        top: 0;
+        width: 51%;
+        height: 100%;
+        background: #7171c6;
+        z-index: 1000;
+        -webkit-transform: translateX(0);
+        -ms-transform: translateX(0);
+        transform: translateX(0);
+      }
+
+      #loader-wrapper .loader-section.section-left {
+        left: 0;
+      }
 
-</html>
+      #loader-wrapper .loader-section.section-right {
+        right: 0;
+      }
+
+      .loaded #loader-wrapper .loader-section.section-left {
+        -webkit-transform: translateX(-100%);
+        -ms-transform: translateX(-100%);
+        transform: translateX(-100%);
+        -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+        transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+      }
+
+      .loaded #loader-wrapper .loader-section.section-right {
+        -webkit-transform: translateX(100%);
+        -ms-transform: translateX(100%);
+        transform: translateX(100%);
+        -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+        transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+      }
+
+      .loaded #loader {
+        opacity: 0;
+        -webkit-transition: all 0.3s ease-out;
+        transition: all 0.3s ease-out;
+      }
+
+      .loaded #loader-wrapper {
+        visibility: hidden;
+        -webkit-transform: translateY(-100%);
+        -ms-transform: translateY(-100%);
+        transform: translateY(-100%);
+        -webkit-transition: all 0.3s 1s ease-out;
+        transition: all 0.3s 1s ease-out;
+      }
+
+      .no-js #loader-wrapper {
+        display: none;
+      }
+
+      .no-js h1 {
+        color: #222222;
+      }
+
+      #loader-wrapper .load_title {
+        font-family: "Open Sans";
+        color: #fff;
+        font-size: 19px;
+        width: 100%;
+        text-align: center;
+        z-index: 9999999999999;
+        position: absolute;
+        top: 60%;
+        opacity: 1;
+        line-height: 30px;
+      }
+
+      #loader-wrapper .load_title span {
+        font-weight: normal;
+        font-style: italic;
+        font-size: 13px;
+        color: #fff;
+        opacity: 0.5;
+      }
+    </style>
+  </head>
+
+  <body>
+    <div id="app">
+      <div id="loader-wrapper">
+        <div id="loader"></div>
+        <div class="loader-section section-left"></div>
+        <div class="loader-section section-right"></div>
+        <div class="load_title">正在加载系统资源,请耐心等待</div>
+      </div>
+    </div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

+ 6 - 2
gw-ui/package.json

@@ -6,8 +6,11 @@
   "license": "MIT",
   "type": "module",
   "scripts": {
-    "dev": "vite",
-    "build:prod": "vite build",
+    "dev": "vite --mode development",
+    "prod": "vite --mode production",
+    "stag": "vite --mode staging",
+    "build:dev": "vite build --mode development",
+    "build:prod": "vite build --mode production",
     "build:stage": "vite build --mode staging",
     "preview": "vite preview"
   },
@@ -25,6 +28,7 @@
     "element-plus": "2.13.1",
     "file-saver": "2.0.5",
     "fuse.js": "7.1.0",
+    "js-base64": "^3.7.8",
     "js-beautify": "1.15.4",
     "js-cookie": "3.0.5",
     "jsencrypt": "3.3.2",

+ 2 - 0
gw-ui/src/assets/styles/index.scss

@@ -123,6 +123,8 @@ aside {
 //main-container全局样式
 .app-container {
   padding: 20px;
+  height: 100%;
+  overflow: hidden;
 }
 
 .components-container {

+ 184 - 189
gw-ui/src/assets/styles/sidebar.scss

@@ -5,7 +5,7 @@
   .main-container {
     min-height: 100%;
     transition: margin-left .28s;
-    margin-left: vars.$base-sidebar-width;
+    // margin-left: vars.$base-sidebar-width;
     position: relative;
   }
 
@@ -13,195 +13,190 @@
     margin-left: 0!important;
   }
 
-  .sidebar-container {
-    transition: width 0.28s;
-    width: vars.$base-sidebar-width !important;
-    height: 100%;
-    position: fixed;
-    font-size: 0px;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    z-index: 1001;
-    overflow: hidden;
-    -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
-    box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
-
-    // reset element-ui css
-    .horizontal-collapse-transition {
-      transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
-    }
-
-    .scrollbar-wrapper {
-      overflow-x: hidden !important;
-    }
-
-    .el-scrollbar__bar.is-vertical {
-      right: 0px;
-    }
-
-    .el-scrollbar {
-      height: 100%;
-    }
-
-    &.has-logo {
-      .el-scrollbar {
-        height: calc(100% - 50px);
-      }
-    }
-
-    .is-horizontal {
-      display: none;
-    }
-
-    a {
-      display: inline-block;
-      width: 100%;
-      overflow: hidden;
-    }
-
-    .svg-icon {
-      margin-right: 10px !important;
-    }
-
-    .el-menu {
-      border: none;
-      height: 100%;
-      width: 100% !important;
-    }
-
-    .el-menu-item, .menu-title {
-      overflow: hidden !important;
-      text-overflow: ellipsis !important;
-      white-space: nowrap !important;
-      height: 44px !important;
-      line-height: 44px !important;
-    }
-
-    .el-menu-item .el-menu-tooltip__trigger {
-      display: inline-block !important;
-    }
-
-    // menu hover
-    .sub-menu-title-noDropdown,
-    .el-sub-menu__title {
-      &:hover {
-        background-color: rgba(0, 0, 0, 0.06);
-      }
-    }
-
-    & .theme-dark .is-active > .el-sub-menu__title {
-      color: vars.$base-menu-color-active !important;
-    }
-
-    & .nest-menu .el-sub-menu>.el-sub-menu__title,
-    & .el-sub-menu .el-menu-item {
-      min-width: vars.$base-sidebar-width !important;
-
-      &:hover {
-        background-color: rgba(0, 0, 0, 0.06);
-      }
-    }
-
-    & .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
-    & .theme-dark .el-sub-menu .el-menu-item {
-      background-color: vars.$base-sub-menu-background;
-
-      &:hover {
-        background-color: vars.$base-sub-menu-hover !important;
-      }
-    }
-
-    // theme-dark 深色主题
-    &.theme-dark {
-      box-shadow: 2px 0 8px rgba(0, 0, 0, 0.4);
-      border-right: none;
-
-      .el-menu-item.is-active {
-        position: relative;
-
-        &::before {
-          content: '';
-          position: absolute;
-          inset: 0;
-          background-color: var(--current-color-dark-bg, rgba(64, 158, 255, 0.2));
-          border-right: 3px solid var(--current-color, #409eff);
-          pointer-events: none;
-          z-index: 1;
-        }
-      }
-
-      .el-sub-menu.is-active > .el-sub-menu__title {
-        color: var(--current-color, #409eff) !important;
-      }
-
-      .el-menu-item:not(.is-active),
-      .submenu-title-noDropdown,
-      .el-sub-menu__title {
-        position: relative;
-
-        &::before {
-          content: '';
-          position: absolute;
-          inset: 0;
-          background-color: transparent;
-          pointer-events: none;
-          z-index: 1;
-          transition: background-color 0.2s;
-        }
-
-        &:hover::before {
-          background-color: var(--current-color-dark-bg, rgba(64, 158, 255, 0.2));
-        }
-      }
-    }
+  // .sidebar-container {
+  //   transition: width 0.28s;
+  //   width: vars.$base-sidebar-width !important;
+  //   height: 100%;
+  //   z-index: 1001;
+  //   overflow: hidden;
+  //   -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
+  //   box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
+
+  //   // reset element-ui css
+  //   .horizontal-collapse-transition {
+  //     transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
+  //   }
+
+  //   .scrollbar-wrapper {
+  //     overflow-x: hidden !important;
+  //   }
+
+  //   .el-scrollbar__bar.is-vertical {
+  //     right: 0px;
+  //   }
+
+  //   .el-scrollbar {
+  //     height: 100%;
+  //   }
+
+  //   &.has-logo {
+  //     .el-scrollbar {
+  //       height: calc(100% - 50px);
+  //     }
+  //   }
+
+  //   .is-horizontal {
+  //     display: none;
+  //   }
+
+  //   a {
+  //     display: inline-block;
+  //     width: 100%;
+  //     overflow: hidden;
+  //   }
+
+  //   .svg-icon {
+  //     margin-right: 10px !important;
+  //   }
+
+  //   .el-menu {
+  //     border: none;
+  //     height: 100%;
+  //     width: 100% !important;
+  //   }
+
+  //   .el-menu-item, .menu-title {
+  //     overflow: hidden !important;
+  //     text-overflow: ellipsis !important;
+  //     white-space: nowrap !important;
+  //     height: 44px !important;
+  //     line-height: 44px !important;
+  //   }
+
+  //   .el-menu-item .el-menu-tooltip__trigger {
+  //     display: inline-block !important;
+  //   }
+
+  //   // menu hover
+  //   .sub-menu-title-noDropdown,
+  //   .el-sub-menu__title {
+  //     &:hover {
+  //       background-color: rgba(0, 0, 0, 0.06);
+  //     }
+  //   }
+
+  //   & .theme-dark .is-active > .el-sub-menu__title {
+  //     color: vars.$base-menu-color-active !important;
+  //   }
+
+  //   & .nest-menu .el-sub-menu>.el-sub-menu__title,
+  //   & .el-sub-menu .el-menu-item {
+  //     min-width: vars.$base-sidebar-width !important;
+
+  //     &:hover {
+  //       background-color: rgba(0, 0, 0, 0.06);
+  //     }
+  //   }
+
+  //   & .theme-dark .nest-menu .el-sub-menu>.el-sub-menu__title,
+  //   & .theme-dark .el-sub-menu .el-menu-item {
+  //     background-color: vars.$base-sub-menu-background;
+
+  //     &:hover {
+  //       background-color: vars.$base-sub-menu-hover !important;
+  //     }
+  //   }
+
+  //   // theme-dark 深色主题
+  //   &.theme-dark {
+  //     box-shadow: 2px 0 8px rgba(0, 0, 0, 0.4);
+  //     border-right: none;
+
+  //     .el-menu-item.is-active {
+  //       position: relative;
+
+  //       &::before {
+  //         content: '';
+  //         position: absolute;
+  //         inset: 0;
+  //         background-color: var(--current-color-dark-bg, rgba(64, 158, 255, 0.2));
+  //         border-right: 3px solid var(--current-color, #409eff);
+  //         pointer-events: none;
+  //         z-index: 1;
+  //       }
+  //     }
+
+  //     .el-sub-menu.is-active > .el-sub-menu__title {
+  //       color: var(--current-color, #409eff) !important;
+  //     }
+
+  //     .el-menu-item:not(.is-active),
+  //     .submenu-title-noDropdown,
+  //     .el-sub-menu__title {
+  //       position: relative;
+
+  //       &::before {
+  //         content: '';
+  //         position: absolute;
+  //         inset: 0;
+  //         background-color: transparent;
+  //         pointer-events: none;
+  //         z-index: 1;
+  //         transition: background-color 0.2s;
+  //       }
+
+  //       &:hover::before {
+  //         background-color: var(--current-color-dark-bg, rgba(64, 158, 255, 0.2));
+  //       }
+  //     }
+  //   }
     
-    // theme-light 浅色主题
-    &.theme-light {
-      border-right: 1px solid #e8eaf0;
-      box-shadow: none;
-
-      .el-menu-item,
-      .el-sub-menu__title {
-        color: rgba(0, 0, 0, 0.65);
-      }
-
-      .el-menu-item.is-active {
-        color: var(--current-color, #409eff) !important;
-        position: relative;
-
-        &::before {
-          content: '';
-          position: absolute;
-          inset: 0;
-          background-color: var(--current-color-light, #ecf5ff);
-          border-right: 3px solid var(--current-color, #409eff);
-          pointer-events: none;
-          z-index: 1;
-        }
-      }
-
-      .el-sub-menu.is-active > .el-sub-menu__title {
-        color: var(--current-color, #409eff) !important;
-      }
-
-      .el-menu-item:not(.is-active):hover,
-      .submenu-title-noDropdown:hover,
-      .el-sub-menu__title:hover {
-        background-color: #f5f7fa;
-        color: rgba(0, 0, 0, 0.85) !important;
-      }
-
-      .nest-menu .el-sub-menu > .el-sub-menu__title,
-      .el-sub-menu .el-menu-item {
-        background-color: #fafafa;
-
-        &:hover {
-          background-color: #f0f5ff;
-        }
-      }
-    }
-  }
+  //   // theme-light 浅色主题
+  //   &.theme-light {
+  //     border-right: 1px solid #e8eaf0;
+  //     box-shadow: none;
+
+  //     .el-menu-item,
+  //     .el-sub-menu__title {
+  //       color: rgba(0, 0, 0, 0.65);
+  //     }
+
+  //     .el-menu-item.is-active {
+  //       color: var(--current-color, #409eff) !important;
+  //       position: relative;
+
+  //       &::before {
+  //         content: '';
+  //         position: absolute;
+  //         inset: 0;
+  //         background-color: var(--current-color-light, #ecf5ff);
+  //         border-right: 3px solid var(--current-color, #409eff);
+  //         pointer-events: none;
+  //         z-index: 1;
+  //       }
+  //     }
+
+  //     .el-sub-menu.is-active > .el-sub-menu__title {
+  //       color: var(--current-color, #409eff) !important;
+  //     }
+
+  //     .el-menu-item:not(.is-active):hover,
+  //     .submenu-title-noDropdown:hover,
+  //     .el-sub-menu__title:hover {
+  //       background-color: #f5f7fa;
+  //       color: rgba(0, 0, 0, 0.85) !important;
+  //     }
+
+  //     .nest-menu .el-sub-menu > .el-sub-menu__title,
+  //     .el-sub-menu .el-menu-item {
+  //       background-color: #fafafa;
+
+  //       &:hover {
+  //         background-color: #f0f5ff;
+  //       }
+  //     }
+  //   }
+  // }
 
   .hideSidebar {
     .sidebar-container {

+ 11 - 0
gw-ui/src/assets/styles/variables.module.scss

@@ -23,6 +23,11 @@ $menuLightActiveText: #409EFF;
 // 基础变量
 $base-sidebar-width: 200px;
 $sideBarWidth: 200px;
+$base-sidebar-collapsed-width: 54px;
+$base-top-navbar-height: 50px;
+$menuBg: #304156;
+$menuText: #bfcbd9;
+$menuActiveText: #409EFF;
 
 // 菜单暗色变量
 $base-menu-color: rgba(255,255,255,.65);
@@ -63,6 +68,12 @@ $--color-info: #909399;
   colorWarning: $--color-warning;
   colorDanger: $--color-danger;
   colorInfo: $--color-info;
+  baseSidebarWidth: $base-sidebar-width;
+  baseSidebarCollapsedWidth: $base-sidebar-collapsed-width;
+  baseTopNavbarHeight: $base-top-navbar-height;
+  menuBg: $menuBg;
+  menuText: $menuText;
+  menuActiveText: $menuActiveText;
 }
 
 // CSS变量定义

+ 20 - 16
gw-ui/src/layout/components/AppMain.vue

@@ -3,7 +3,11 @@
     <router-view v-slot="{ Component, route }">
       <transition name="fade-transform" mode="out-in">
         <keep-alive :include="tagsViewStore.cachedViews">
-          <component v-if="!route.meta.link" :is="Component" :key="route.path"/>
+          <component
+            v-if="!route.meta.link"
+            :is="Component"
+            :key="route.path"
+          />
         </keep-alive>
       </transition>
     </router-view>
@@ -13,24 +17,24 @@
 </template>
 
 <script setup>
-import copyright from "./Copyright/index"
-import iframeToggle from "./IframeToggle/index"
-import useTagsViewStore from '@/store/modules/tagsView'
+import copyright from "./Copyright/index";
+import iframeToggle from "./IframeToggle/index";
+import useTagsViewStore from "@/store/modules/tagsView";
 
-const route = useRoute()
-const tagsViewStore = useTagsViewStore()
+const route = useRoute();
+const tagsViewStore = useTagsViewStore();
 
 onMounted(() => {
-  addIframe()
-})
+  addIframe();
+});
 
 watchEffect(() => {
-  addIframe()
-})
+  addIframe();
+});
 
 function addIframe() {
   if (route.meta.link) {
-    useTagsViewStore().addIframeView(route)
+    useTagsViewStore().addIframeView(route);
   }
 }
 </script>
@@ -38,7 +42,7 @@ function addIframe() {
 <style lang="scss" scoped>
 .app-main {
   /* 50= navbar  50  */
-  min-height: calc(100vh - 50px);
+  min-height: calc(100vh - 60px);
   width: 100%;
   position: relative;
   overflow: hidden;
@@ -47,7 +51,7 @@ function addIframe() {
 .fixed-header + .app-main {
   overflow-y: auto;
   scrollbar-gutter: auto;
-  height: calc(100vh - 50px);
+  height: calc(100vh - 60px);
   min-height: 0px;
 }
 
@@ -56,7 +60,7 @@ function addIframe() {
 }
 
 .fixed-header + .app-main {
-  margin-top: 50px;
+  margin-top: 60px;
 }
 
 .hasTagsView {
@@ -92,8 +96,8 @@ function addIframe() {
     .fixed-header + .app-main {
       padding-bottom: max(17px, calc(constant(safe-area-inset-bottom) + 10px));
       padding-bottom: max(17px, calc(env(safe-area-inset-bottom) + 10px));
-      height: calc(100svh - 50px);
-      height: calc(100dvh - 50px);
+      height: calc(100svh - 60px);
+      height: calc(100dvh - 60px);
     }
 
     .hasTagsView .fixed-header + .app-main {

+ 0 - 3
gw-ui/src/layout/components/Navbar.vue

@@ -39,9 +39,6 @@
             <router-link to="/user/profile">
               <el-dropdown-item>个人中心</el-dropdown-item>
             </router-link>
-            <el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
-                <span>布局设置</span>
-            </el-dropdown-item>
             <el-dropdown-item command="lockScreen">
                 <span>锁定屏幕</span>
             </el-dropdown-item>

+ 181 - 88
gw-ui/src/layout/components/Sidebar/SidebarItem.vue

@@ -1,100 +1,193 @@
+<!-- layout/components/Sidebar/SidebarItem.vue -->
 <template>
-  <div v-if="!item.hidden">
-    <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
-      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
-        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
-          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>
-          <template #title><span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span></template>
-        </el-menu-item>
-      </app-link>
-    </template>
-
-    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
-      <template v-if="item.meta" #title>
-        <svg-icon :icon-class="item.meta && item.meta.icon" />
-        <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>
-      </template>
-
-      <sidebar-item
-        v-for="(child, index) in item.children"
-        :key="child.path + index"
-        :is-nest="true"
-        :item="child"
-        :base-path="resolvePath(child.path)"
-        class="nest-menu"
+  <template v-if="!item.hidden">
+    <!-- 有子菜单 -->
+    <div v-if="item.children && item.children.length > 0" class="sub-menu">
+      <div class="sub-menu-title" @click="toggleSubGroup">
+        <svg-icon
+          v-if="item.meta?.icon"
+          :icon-class="item.meta.icon"
+          class="menu-icon"
+        />
+        <span class="menu-text" v-if="!isCollapse">{{ item.meta?.title }}</span>
+        <span class="sub-arrow" v-if="!isCollapse">
+          {{ expandedSubGroup ? "▼" : "▶" }}
+        </span>
+      </div>
+      <div class="sub-menu-items" v-show="expandedSubGroup || isCollapse">
+        <sidebar-item
+          v-for="child in item.children"
+          :key="child.path"
+          :item="child"
+          :parent-path="getChildFullPath(child.path)"
+          :is-collapse="isCollapse"
+          :active-path="activePath"
+          @menu-click="handleMenuClick"
+        />
+      </div>
+    </div>
+
+    <!-- 没有子菜单 -->
+    <div
+      v-else
+      :class="[
+        'sub-menu-item',
+        {
+          active:
+            activePath === getFullPath ||
+            activePath.startsWith(getFullPath + '/'),
+        },
+      ]"
+      @click="handleMenuClick(getFullPath)"
+    >
+      <svg-icon
+        v-if="item.meta?.icon"
+        :icon-class="item.meta.icon"
+        class="menu-icon"
       />
-    </el-sub-menu>
-  </div>
+      <span class="menu-text">{{ item.meta?.title }}</span>
+    </div>
+  </template>
 </template>
 
-<script setup>
-import { isExternal } from '@/utils/validate'
-import AppLink from './Link'
-import { getNormalPath } from '@/utils/goldenwater'
+<script>
+import { ref, watch } from "vue";
 
-const props = defineProps({
-  // route object
-  item: {
-    type: Object,
-    required: true
+export default {
+  name: "SidebarItem",
+  props: {
+    item: {
+      type: Object,
+      required: true,
+    },
+    parentPath: {
+      type: String,
+      default: "",
+    },
+    isCollapse: {
+      type: Boolean,
+      default: false,
+    },
+    activePath: {
+      type: String,
+      default: "",
+    },
   },
-  isNest: {
-    type: Boolean,
-    default: false
+  emits: ["menu-click"],
+  setup(props, { emit }) {
+    const expandedSubGroup = ref(false);
+
+    const getFullPath = computed(() => {
+      let path = props.item.path;
+      if (!path.startsWith("/") && props.parentPath) {
+        path = props.parentPath + "/" + path;
+      }
+      return path;
+    });
+
+    const getChildFullPath = (childPath) => {
+      if (childPath.startsWith("/")) {
+        return childPath;
+      }
+      return getFullPath.value;
+    };
+
+    const toggleSubGroup = () => {
+      expandedSubGroup.value = !expandedSubGroup.value;
+    };
+
+    const handleMenuClick = (path) => {
+      emit("menu-click", path);
+    };
+
+    // 自动展开当前路由对应的父级菜单
+    watch(
+      () => props.activePath,
+      (newPath) => {
+        if (
+          newPath === getFullPath.value ||
+          newPath.startsWith(getFullPath.value + "/")
+        ) {
+          expandedSubGroup.value = true;
+        }
+      },
+      { immediate: true },
+    );
+
+    return {
+      expandedSubGroup,
+      getFullPath,
+      getChildFullPath,
+      toggleSubGroup,
+      handleMenuClick,
+    };
   },
-  basePath: {
-    type: String,
-    default: ''
-  }
-})
-
-const onlyOneChild = ref({})
-
-function hasOneShowingChild(children = [], parent) {
-  if (!children) {
-    children = []
-  }
-  const showingChildren = children.filter(item => {
-    if (item.hidden) {
-      return false
-    }
-    onlyOneChild.value = item
-    return true
-  })
-
-  // When there is only one child router, the child router is displayed by default
-  if (showingChildren.length === 1) {
-    return true
-  }
-
-  // Show parent if there are no child router to display
-  if (showingChildren.length === 0) {
-    onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
-    return true
-  }
-
-  return false
+};
+</script>
+
+<style scoped>
+.sub-menu {
+  margin-bottom: 2px;
 }
 
-function resolvePath(routePath, routeQuery) {
-  if (isExternal(routePath)) {
-    return routePath
-  }
-  if (isExternal(props.basePath)) {
-    return props.basePath
-  }
-  if (routeQuery) {
-    let query = JSON.parse(routeQuery)
-    return { path: getNormalPath(props.basePath + '/' + routePath), query: query }
-  }
-  return getNormalPath(props.basePath + '/' + routePath)
+.sub-menu-title {
+  padding: 0 20px 0 44px;
+  height: 40px;
+  line-height: 40px;
+  color: #bfcbd9;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  position: relative;
 }
 
-function hasTitle(title){
-  if (title.length > 5) {
-    return title
-  } else {
-    return ""
-  }
+.sub-menu-title:hover {
+  background-color: #263445;
+  color: #fff;
 }
-</script>
+
+.sub-arrow {
+  position: absolute;
+  right: 20px;
+  font-size: 12px;
+}
+
+.sub-menu-items {
+  overflow: hidden;
+}
+
+.sub-menu-item {
+  padding: 0 20px 0 68px;
+  height: 36px;
+  line-height: 36px;
+  color: #bfcbd9;
+  cursor: pointer;
+  white-space: nowrap;
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.sub-menu-item:hover {
+  background-color: #263445;
+  color: #fff;
+}
+
+.sub-menu-item.active {
+  background-color: #409eff;
+  color: #fff;
+}
+
+/* 收起时的样式 */
+.sidebar-container.collapsed .sub-menu-title,
+.sidebar-container.collapsed .sub-menu-item {
+  justify-content: center;
+  padding: 0;
+}
+
+.sidebar-container.collapsed .menu-text,
+.sidebar-container.collapsed .sub-arrow {
+  display: none;
+}
+</style>

+ 268 - 94
gw-ui/src/layout/components/Sidebar/index.vue

@@ -1,104 +1,278 @@
+<!-- layout/components/Sidebar/index.vue -->
 <template>
-  <div :class="['sidebar-theme-wrapper', {'has-logo':showLogo}, sideTheme]" class="sidebar-container">
-    <logo v-if="showLogo" :collapse="isCollapse" />
-    <el-scrollbar wrap-class="scrollbar-wrapper">
-      <el-menu
-        :default-active="activeMenu"
-        :collapse="isCollapse"
-        :background-color="getMenuBackground"
-        :text-color="getMenuTextColor"
-        :unique-opened="true"
-        :active-text-color="theme"
-        :collapse-transition="false"
-        mode="vertical"
-        :class="sideTheme"
-      >
-        <sidebar-item
-          v-for="(route, index) in sidebarRouters"
-          :key="route.path + index"
-          :item="route"
-          :base-path="route.path"
-        />
-      </el-menu>
-    </el-scrollbar>
+  <div class="sidebar-container" :class="{ collapsed: isCollapse }">
+    <el-menu
+      :default-active="activeMenu"
+      :collapse="isCollapse"
+      background-color="#ffffff"
+      text-color="#606266"
+      active-text-color="#409eff"
+      :collapse-transition="false"
+      unique-opened
+      class="sidebar-menu"
+    >
+      <template v-for="item in menuList" :key="item.path">
+        <!-- 有子菜单的项 -->
+        <el-sub-menu
+          v-if="item.children && item.children.length > 0"
+          :index="getFullPath(item.path)"
+        >
+          <template #title>
+            <svg-icon v-if="item.meta?.icon" :icon-class="item.meta.icon" />
+            <span>{{ item.meta?.title }}</span>
+          </template>
+          <!-- 二级菜单 -->
+          <template v-for="child in item.children" :key="child.path">
+            <el-sub-menu
+              v-if="child.children && child.children.length > 0"
+              :index="getFullPath(child.path, item.path)"
+            >
+              <template #title>
+                <svg-icon
+                  v-if="child.meta?.icon"
+                  :icon-class="child.meta.icon"
+                />
+                <span>{{ child.meta?.title }}</span>
+              </template>
+              <!-- 三级菜单 -->
+              <el-menu-item
+                v-for="subChild in child.children"
+                :key="subChild.path"
+                :index="getFullPath(subChild.path, child.path, item.path)"
+                @click="handleMenuClick(subChild, child, item)"
+              >
+                <svg-icon
+                  v-if="subChild.meta?.icon"
+                  :icon-class="subChild.meta.icon"
+                />
+                <span>{{ subChild.meta?.title }}</span>
+              </el-menu-item>
+            </el-sub-menu>
+            <!-- 二级菜单(无子菜单) -->
+            <el-menu-item
+              v-else
+              :index="getFullPath(child.path, item.path)"
+              @click="handleMenuClick(child, item)"
+            >
+              <svg-icon v-if="child.meta?.icon" :icon-class="child.meta.icon" />
+              <span>{{ child.meta?.title }}</span>
+            </el-menu-item>
+          </template>
+        </el-sub-menu>
+
+        <!-- 没有子菜单的一级菜单项 -->
+        <el-menu-item
+          v-else
+          :index="getFullPath(item.path)"
+          @click="handleMenuClick(item)"
+        >
+          <svg-icon v-if="item.meta?.icon" :icon-class="item.meta.icon" />
+          <span>{{ item.meta?.title }}</span>
+        </el-menu-item>
+      </template>
+    </el-menu>
+
+    <div class="collapse-btn" @click="toggleCollapse">
+      <span class="btn-text">{{ isCollapse ? "▶" : "◀" }}</span>
+    </div>
   </div>
 </template>
 
-<script setup>
-import Logo from './Logo'
-import SidebarItem from './SidebarItem'
-import variables from '@/assets/styles/variables.module.scss'
-import useAppStore from '@/store/modules/app'
-import useSettingsStore from '@/store/modules/settings'
-import usePermissionStore from '@/store/modules/permission'
-
-const route = useRoute()
-const appStore = useAppStore()
-const settingsStore = useSettingsStore()
-const permissionStore = usePermissionStore()
-
-const sidebarRouters = computed(() => permissionStore.sidebarRouters)
-const showLogo = computed(() => settingsStore.sidebarLogo)
-const sideTheme = computed(() => settingsStore.sideTheme)
-const theme = computed(() => settingsStore.theme)
-const isCollapse = computed(() => !appStore.sidebar.opened)
-
-// 获取菜单背景色
-const getMenuBackground = computed(() => {
-  if (settingsStore.isDark) {
-    return 'var(--sidebar-bg)'
-  }
-  return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBg
-})
-
-// 获取菜单文字颜色
-const getMenuTextColor = computed(() => {
-  if (settingsStore.isDark) {
-    return 'var(--sidebar-text)'
-  }
-  return sideTheme.value === 'theme-dark' ? variables.menuText : variables.menuLightText
-})
-
-const activeMenu = computed(() => {
-  const { meta, path } = route
-  if (meta.activeMenu) {
-    return meta.activeMenu
-  }
-  return path
-})
-</script>
+<script>
+import { computed } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import useAppStore from "@/store/modules/app";
+import usePermissionStore from "@/store/modules/permission";
 
-<style lang="scss" scoped>
-.sidebar-container {
-  background-color: v-bind(getMenuBackground);
-  
-  .scrollbar-wrapper {
-    background-color: v-bind(getMenuBackground);
-  }
-
-  .el-menu {
-    border: none;
-    height: 100%;
-    width: 100% !important;
-    
-    .el-menu-item, .el-sub-menu__title {
-      &:hover {
-        background-color: var(--menu-hover, rgba(0, 0, 0, 0.06)) !important;
+export default {
+  name: "Sidebar",
+  props: {
+    topMenuKey: {
+      type: String,
+      default: "",
+    },
+  },
+  setup(props) {
+    const route = useRoute();
+    const router = useRouter();
+    const appStore = useAppStore();
+    const permissionStore = usePermissionStore();
+
+    const isCollapse = computed(() => appStore.sidebar.isCollapse);
+
+    // 当前激活的菜单
+    const activeMenu = computed(() => {
+      return route.path;
+    });
+
+    // 获取菜单列表
+    const menuList = computed(() => {
+      const routes = permissionStore.sidebarRouters || [];
+      console.log("sidebarRouters:", routes);
+      console.log("topMenuKey:", props.topMenuKey);
+
+      if (!routes.length) return [];
+
+      if (props.topMenuKey) {
+        const current = routes.find((item) => item.path === props.topMenuKey);
+        if (current && current.children) {
+          return current.children.filter((child) => !child.hidden);
+        }
+      }
+
+      const firstMenu = routes[0];
+      if (firstMenu && firstMenu.children) {
+        return firstMenu.children.filter((child) => !child.hidden);
       }
-    }
-
-    .el-menu-item {
-      color: v-bind(getMenuTextColor);
-      
-      &.is-active {
-        color: var(--menu-active-text, #409eff);
-        background-color: var(--menu-hover, rgba(0, 0, 0, 0.06)) !important;
+
+      return [];
+    });
+
+    // 获取完整路径
+    const getFullPath = (path, parentPath = "", grandParentPath = "") => {
+      if (path.startsWith("/")) {
+        return path;
       }
-    }
 
-    .el-sub-menu__title {
-      color: v-bind(getMenuTextColor);
-    }
-  }
+      // 三级菜单:topMenuKey + 一级/二级/三级
+      if (grandParentPath && parentPath) {
+        return (
+          props.topMenuKey +
+          "/" +
+          grandParentPath +
+          "/" +
+          parentPath +
+          "/" +
+          path
+        );
+      }
+
+      // 二级菜单:topMenuKey + 一级/二级
+      if (parentPath) {
+        return props.topMenuKey + "/" + parentPath + "/" + path;
+      }
+
+      // 一级菜单:topMenuKey + 一级
+      return props.topMenuKey + "/" + path;
+    };
+
+    // 点击菜单
+    const handleMenuClick = (
+      item,
+      parentItem = null,
+      grandParentItem = null,
+    ) => {
+      let fullPath = "";
+
+      if (grandParentItem && parentItem) {
+        // 三级菜单:topMenuKey/一级/二级/三级
+        fullPath =
+          props.topMenuKey +
+          "/" +
+          grandParentItem.path +
+          "/" +
+          parentItem.path +
+          "/" +
+          item.path;
+      } else if (parentItem) {
+        // 二级菜单:topMenuKey/一级/二级
+        fullPath = props.topMenuKey + "/" + parentItem.path + "/" + item.path;
+      } else {
+        // 一级菜单:topMenuKey/一级
+        fullPath = props.topMenuKey + "/" + item.path;
+      }
+
+      console.log("跳转路径:", fullPath);
+      router.push(fullPath);
+    };
+
+    // 收起/展开
+    const toggleCollapse = () => {
+      appStore.sidebar.isCollapse = !appStore.sidebar.isCollapse;
+    };
+
+    return {
+      menuList,
+      isCollapse,
+      activeMenu,
+      getFullPath,
+      handleMenuClick,
+      toggleCollapse,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.sidebar-container {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  background-color: #ffffff;
+  border-right: 1px solid #e4e7ed;
+}
+
+.sidebar-menu {
+  flex: 1;
+  border: none;
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+
+:deep(.el-menu) {
+  border-right: none;
+  background-color: #ffffff;
+}
+
+:deep(.el-sub-menu__title) {
+  color: #606266;
+  background-color: #ffffff;
+}
+
+:deep(.el-sub-menu__title:hover) {
+  background-color: #f5f7fa !important;
+  color: #303133 !important;
+}
+
+:deep(.el-menu-item) {
+  color: #606266;
+  background-color: #ffffff;
+}
+
+:deep(.el-menu-item:hover) {
+  background-color: #f5f7fa !important;
+  color: #303133 !important;
+}
+
+:deep(.el-menu-item.is-active) {
+  background-color: #ecf5ff !important;
+  color: #409eff !important;
+}
+
+.sidebar-container.collapsed :deep(.el-sub-menu__title span) {
+  display: none;
+}
+
+.sidebar-container.collapsed :deep(.el-menu-item span) {
+  display: none;
+}
+
+.collapse-btn {
+  height: 44px;
+  line-height: 44px;
+  text-align: center;
+  color: #606266;
+  cursor: pointer;
+  border-top: 1px solid #e4e7ed;
+  background-color: #ffffff;
+}
+
+.collapse-btn:hover {
+  background-color: #f5f7fa;
+  color: #303133;
+}
+
+.btn-text {
+  font-size: 16px;
 }
 </style>

+ 264 - 0
gw-ui/src/layout/components/TopNavbar/index.vue

@@ -0,0 +1,264 @@
+<!-- layout/components/TopNavbar/index.vue -->
+<template>
+  <div class="top-navbar">
+    <div class="logo-area">
+      <span class="logo-text">若依管理系统</span>
+    </div>
+
+    <div class="menu-area">
+      <!-- 首页菜单 -->
+      <div
+        :class="[
+          'menu-link',
+          { active: activeMenu === '/' || activeMenu === '/index' },
+        ]"
+        @click="handleMenuClick('/index')"
+      >
+        首页
+      </div>
+
+      <!-- 动态菜单 -->
+      <div
+        v-for="item in topMenus"
+        :key="item.path"
+        :class="['menu-link', { active: activeMenu === item.path }]"
+        @click="handleMenuClick(item.path)"
+      >
+        {{ item.meta?.title }}
+      </div>
+    </div>
+
+    <div class="right-menu">
+      <el-dropdown
+        @command="handleCommand"
+        class="avatar-container"
+        trigger="hover"
+      >
+        <div class="avatar-wrapper">
+          <!-- 用户图标 -->
+          <svg-icon icon-class="user" class="user-icon" />
+          <!-- 用户名 - 添加溢出处理 -->
+          <span
+            class="user-nickname"
+            :title="userStore.nickName || userStore.name"
+          >
+            {{ userStore.nickName || userStore.name }}
+          </span>
+          <!-- 下拉箭头 -->
+          <el-icon class="dropdown-icon">
+            <ArrowDown />
+          </el-icon>
+        </div>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <router-link to="/user/profile">
+              <el-dropdown-item>个人中心</el-dropdown-item>
+            </router-link>
+            <el-dropdown-item command="lockScreen">
+              <span>锁定屏幕</span>
+            </el-dropdown-item>
+            <el-dropdown-item divided command="logout">
+              <span>退出登录</span>
+            </el-dropdown-item>
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
+    </div>
+  </div>
+</template>
+
+<script>
+import { computed, ref } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import { ElMessageBox } from "element-plus";
+import { ArrowDown } from "@element-plus/icons-vue";
+import usePermissionStore from "@/store/modules/permission";
+import useUserStore from "@/store/modules/user";
+import useSettingsStore from "@/store/modules/settings";
+import useLockStore from "@/store/modules/lock";
+
+export default {
+  name: "TopNavbar",
+  components: {
+    ArrowDown,
+  },
+  props: {
+    activeMenu: {
+      type: String,
+      default: "",
+    },
+  },
+  emits: ["menu-click", "setLayout"],
+  setup(props, { emit }) {
+    const route = useRoute();
+    const router = useRouter();
+    const permissionStore = usePermissionStore();
+    const userStore = useUserStore();
+    const settingsStore = useSettingsStore();
+    const lockStore = useLockStore();
+
+    const isFullscreen = ref(false);
+
+    const topMenus = computed(() => {
+      const routes = permissionStore.topbarRouters || [];
+      return routes.filter((item) => item.meta?.title && !item.hidden);
+    });
+
+    const handleMenuClick = (path) => {
+      emit("menu-click", path);
+    };
+
+    const handleCommand = (command) => {
+      switch (command) {
+        case "setLayout":
+          emit("setLayout");
+          break;
+        case "lockScreen":
+          lockScreen();
+          break;
+        case "logout":
+          logout();
+          break;
+        default:
+          break;
+      }
+    };
+
+    const lockScreen = () => {
+      const currentPath = route.fullPath;
+      lockStore.lockScreen(currentPath);
+      router.push("/lock");
+    };
+
+    const logout = () => {
+      ElMessageBox.confirm("确定注销并退出系统吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          userStore.logOut().then(() => {
+            location.href = "/index";
+          });
+        })
+        .catch(() => {});
+    };
+
+    return {
+      topMenus,
+      userStore,
+      settingsStore,
+      isFullscreen,
+      handleMenuClick,
+      handleCommand,
+    };
+  },
+};
+</script>
+
+<style scoped>
+.top-navbar {
+  height: 60px;
+  background: #217ff4;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 30px;
+  box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
+}
+
+.logo-area {
+  width: 260px;
+  flex-shrink: 0;
+}
+
+.logo-text {
+  color: #fff;
+  font-size: 20px;
+  font-weight: bold;
+}
+
+.menu-area {
+  flex: 1;
+  display: flex;
+  gap: 8px;
+  margin: 0 30px;
+  overflow-x: auto;
+}
+
+.menu-link {
+  padding: 0 24px;
+  height: 60px;
+  line-height: 60px;
+  color: #fff;
+  cursor: pointer;
+  font-size: 18px;
+  font-weight: 500;
+  letter-spacing: 1px;
+  white-space: nowrap;
+  flex-shrink: 0;
+}
+
+.menu-link:hover {
+  background: rgba(255, 255, 255, 0.15);
+}
+
+.menu-link.active {
+  background: rgba(255, 255, 255, 0.25);
+}
+
+.right-menu {
+  display: flex;
+  align-items: center;
+  color: #fff;
+  flex-shrink: 0;
+  height: 100%;
+}
+
+.avatar-container {
+  margin-right: 0;
+  padding-right: 0;
+}
+
+.avatar-wrapper {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  cursor: pointer;
+  padding: 0 12px;
+  height: 60px;
+  max-width: 200px;
+}
+
+.avatar-wrapper:hover {
+  background: rgba(255, 255, 255, 0.15);
+}
+
+.user-icon {
+  width: 18px;
+  height: 18px;
+  color: #fff;
+  flex-shrink: 0;
+}
+
+.user-nickname {
+  font-size: 14px;
+  color: #fff;
+  max-width: 120px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  flex-shrink: 1;
+}
+
+.dropdown-icon {
+  font-size: 14px;
+  color: #fff;
+  transition: transform 0.3s;
+  flex-shrink: 0;
+}
+
+.avatar-container:hover .dropdown-icon {
+  transform: rotate(180deg);
+}
+</style>

+ 134 - 89
gw-ui/src/layout/index.vue

@@ -1,116 +1,161 @@
+<!-- layout/index.vue -->
 <template>
-  <div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme, '--current-color-light': theme + '1a', '--current-color-dark-bg': theme + '33' }">
-    <div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
-    <sidebar v-if="!sidebar.hide" class="sidebar-container" />
-    <div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
-      <div :class="{ 'fixed-header': fixedHeader }">
-        <navbar @setLayout="setLayout" />
-        <tags-view v-if="needTagsView" />
+  <div
+    class="app-wrapper"
+    :style="{
+      '--current-color': theme,
+      '--current-color-light': theme + '1a',
+      '--current-color-dark-bg': theme + '33',
+    }"
+  >
+    <!-- 顶部一级菜单栏 -->
+    <top-navbar
+      v-if="!sidebar.hide"
+      :active-menu="activeTopMenu"
+      @menu-click="handleTopMenuClick"
+      @setLayout="openSettings"
+    />
+
+    <!-- 下方区域:左右结构 -->
+    <div class="main-layout">
+      <!-- 左侧二三级菜单 -->
+      <div class="sidebar-wrapper" :class="{ collapsed: isCollapse }">
+        <sidebar v-if="!sidebar.hide" :top-menu-key="activeTopMenu" />
+      </div>
+
+      <!-- 右侧内容区域 -->
+      <div class="content-wrapper">
+        <app-main />
+        <settings ref="settingRef" />
       </div>
-      <app-main />
-      <settings ref="settingRef" />
     </div>
   </div>
 </template>
 
 <script setup>
-import { useWindowSize } from '@vueuse/core'
-import Sidebar from './components/Sidebar/index.vue'
-import { AppMain, Navbar, Settings, TagsView } from './components'
-import useAppStore from '@/store/modules/app'
-import useSettingsStore from '@/store/modules/settings'
-
-const settingsStore = useSettingsStore()
-const theme = computed(() => settingsStore.theme)
-const sidebar = computed(() => useAppStore().sidebar)
-const device = computed(() => useAppStore().device)
-const needTagsView = computed(() => settingsStore.tagsView)
-const fixedHeader = computed(() => settingsStore.fixedHeader)
-
-const classObj = computed(() => ({
-  hideSidebar: !sidebar.value.opened,
-  openSidebar: sidebar.value.opened,
-  withoutAnimation: sidebar.value.withoutAnimation,
-  mobile: device.value === 'mobile'
-}))
-
-const { width, height } = useWindowSize()
-const WIDTH = 992 // refer to Bootstrap's responsive design
-
-watch(() => device.value, () => {
-  if (device.value === 'mobile' && sidebar.value.opened) {
-    useAppStore().closeSideBar({ withoutAnimation: false })
-  }
-})
-
-watchEffect(() => {
-  if (width.value - 1 < WIDTH) {
-    useAppStore().toggleDevice('mobile')
-    useAppStore().closeSideBar({ withoutAnimation: true })
-  } else {
-    useAppStore().toggleDevice('desktop')
+import { computed, ref, watch, onMounted } from "vue";
+import { useRoute, useRouter } from "vue-router";
+import TopNavbar from "./components/TopNavbar/index.vue";
+import Sidebar from "./components/Sidebar/index.vue";
+import { AppMain, Settings } from "./components";
+import useAppStore from "@/store/modules/app";
+import useSettingsStore from "@/store/modules/settings";
+import usePermissionStore from "@/store/modules/permission";
+
+const settingsStore = useSettingsStore();
+const permissionStore = usePermissionStore();
+const appStore = useAppStore();
+const route = useRoute();
+const router = useRouter();
+
+// 首页路径
+const HOME_PATH = "/index";
+
+// 计算属性
+const theme = computed(() => settingsStore.theme);
+const sidebar = computed(() => appStore.sidebar);
+const isCollapse = computed(() => appStore.sidebar.isCollapse);
+
+// 当前选中的顶级菜单
+const activeTopMenu = ref("");
+
+// 获取当前选中的顶级菜单
+const getCurrentTopMenu = () => {
+  const currentPath = route.path;
+
+  // 如果是首页,选中首页菜单
+  if (currentPath === HOME_PATH) {
+    return HOME_PATH;
   }
-})
-
-function handleClickOutside() {
-  useAppStore().closeSideBar({ withoutAnimation: false })
-}
 
-const settingRef = ref(null)
-function setLayout() {
-  settingRef.value.openSetting()
-}
-</script>
+  try {
+    const routes = permissionStore.topbarRouters || [];
+    const firstLevel = "/" + currentPath.split("/")[1];
+    const matched = routes.find((r) => r.path === firstLevel);
+    return matched?.path || HOME_PATH;
+  } catch (error) {
+    return HOME_PATH;
+  }
+};
 
-<style lang="scss" scoped>
-@use "@/assets/styles/mixin.scss" as mix;
-@use "@/assets/styles/variables.module.scss" as vars;
+// 处理顶级菜单点击
+function handleTopMenuClick(menuPath) {
+  activeTopMenu.value = menuPath;
 
-.app-wrapper {
-  @include mix.clearfix;
-  position: relative;
-  height: 100%;
-  width: 100%;
+  // 如果点击的是首页,直接跳转
+  if (menuPath === HOME_PATH) {
+    router.push(HOME_PATH);
+    return;
+  }
 
-  &.mobile.openSidebar {
-    position: fixed;
-    top: 0;
+  // 其他菜单:跳转到第一个子路由
+  const routes = permissionStore.topbarRouters || [];
+  const targetRoute = routes.find((r) => r.path === menuPath);
+
+  if (targetRoute && targetRoute.children && targetRoute.children.length > 0) {
+    const firstChild = targetRoute.children.find((child) => !child.hidden);
+    if (firstChild) {
+      let fullPath = firstChild.path;
+      if (!fullPath.startsWith("/")) {
+        fullPath = menuPath + "/" + fullPath;
+      }
+      router.push(fullPath);
+    }
   }
 }
 
-.main-container:has(.fixed-header) {
-  height: 100vh;
-  overflow: hidden;
+// 打开设置面板
+const settingRef = ref(null);
+function openSettings() {
+  if (settingRef.value) {
+    settingRef.value.openSetting();
+  }
 }
 
-.drawer-bg {
-  background: #000;
-  opacity: 0.3;
-  width: 100%;
-  top: 0;
+// 监听路由变化,更新选中的顶级菜单
+watch(
+  () => route.path,
+  () => {
+    activeTopMenu.value = getCurrentTopMenu();
+  },
+  { immediate: true },
+);
+
+onMounted(() => {
+  // 如果当前是根路径,跳转到首页
+  if (route.path === "/") {
+    router.push(HOME_PATH);
+  }
+  activeTopMenu.value = getCurrentTopMenu();
+});
+</script>
+
+<style scoped>
+.app-wrapper {
   height: 100%;
-  position: absolute;
-  z-index: 999;
+  display: flex;
+  flex-direction: column;
 }
 
-.fixed-header {
-  position: fixed;
-  top: 0;
-  right: 0;
-  z-index: 9;
-  width: calc(100% - #{vars.$base-sidebar-width});
-  transition: width 0.28s;
+.main-layout {
+  flex: 1;
+  display: flex;
+  overflow: hidden;
 }
 
-.hideSidebar .fixed-header {
-  width: calc(100% - 54px);
+.sidebar-wrapper {
+  width: 210px;
+  transition: width 0.3s;
+  flex-shrink: 0;
 }
 
-.sidebarHide .fixed-header {
-  width: 100%;
+.sidebar-wrapper.collapsed {
+  width: 64px;
 }
 
-.mobile .fixed-header {
-  width: 100%;
+.content-wrapper {
+  flex: 1;
+  overflow: auto;
+  background: #f0f2f6;
 }
-</style>
+</style>

+ 61 - 44
gw-ui/src/store/modules/app.js

@@ -1,46 +1,63 @@
-import Cookies from 'js-cookie'
-
-const useAppStore = defineStore(
-  'app',
-  {
-    state: () => ({
-      sidebar: {
-        opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
-        withoutAnimation: false,
-        hide: false
-      },
-      device: 'desktop',
-      size: Cookies.get('size') || 'default'
-    }),
-    actions: {
-      toggleSideBar(withoutAnimation) {
-        if (this.sidebar.hide) {
-          return false
-        }
-        this.sidebar.opened = !this.sidebar.opened
-        this.sidebar.withoutAnimation = withoutAnimation
-        if (this.sidebar.opened) {
-          Cookies.set('sidebarStatus', 1)
-        } else {
-          Cookies.set('sidebarStatus', 0)
-        }
-      },
-      closeSideBar({ withoutAnimation }) {
-        Cookies.set('sidebarStatus', 0)
-        this.sidebar.opened = false
-        this.sidebar.withoutAnimation = withoutAnimation
-      },
-      toggleDevice(device) {
-        this.device = device
-      },
-      setSize(size) {
-        this.size = size
-        Cookies.set('size', size)
-      },
-      toggleSideBarHide(status) {
-        this.sidebar.hide = status
+// store/modules/app.js
+import Cookies from "js-cookie";
+import { defineStore } from "pinia";
+
+const useAppStore = defineStore("app", {
+  state: () => ({
+    sidebar: {
+      opened: Cookies.get("sidebarStatus")
+        ? !!+Cookies.get("sidebarStatus")
+        : true,
+      withoutAnimation: false,
+      isCollapse: false,
+      hide: false,
+    },
+    size: Cookies.get("size") || "default",
+  }),
+
+  actions: {
+    // 切换侧边栏的展开/收起
+    toggleSideBar(withoutAnimation) {
+      if (this.sidebar.hide) {
+        return false;
+      }
+      this.sidebar.opened = !this.sidebar.opened;
+      this.sidebar.isCollapse = !this.sidebar.isCollapse;
+      this.sidebar.withoutAnimation = withoutAnimation;
+
+      if (this.sidebar.opened) {
+        Cookies.set("sidebarStatus", 1);
+      } else {
+        Cookies.set("sidebarStatus", 0);
       }
-    }
-  })
+    },
+
+    // 收起侧边栏
+    collapseSideBar({ withoutAnimation }) {
+      if (this.sidebar.hide) return false;
+      this.sidebar.isCollapse = true;
+      this.sidebar.opened = false;
+      this.sidebar.withoutAnimation = withoutAnimation;
+      Cookies.set("sidebarStatus", 0);
+    },
+
+    // 展开侧边栏
+    expandSideBar({ withoutAnimation }) {
+      if (this.sidebar.hide) return false;
+      this.sidebar.isCollapse = false;
+      this.sidebar.opened = true;
+      this.sidebar.withoutAnimation = withoutAnimation;
+      Cookies.set("sidebarStatus", 1);
+    },
+
+    toggleSideBarHide(status) {
+      this.sidebar.hide = status;
+    },
+  },
+
+  getters: {
+    isSidebarCollapse: (state) => state.sidebar.isCollapse,
+  },
+});
 
-export default useAppStore
+export default useAppStore;

+ 2 - 1
gw-ui/src/utils/request.js

@@ -6,6 +6,7 @@ import { tansParams, blobValidate } from '@/utils/goldenwater'
 import cache from '@/plugins/cache'
 import { saveAs } from 'file-saver'
 import useUserStore from '@/store/modules/user'
+import { Base64 } from 'js-base64'
 
 let downloadLoadingInstance
 // 是否显示重新登录
@@ -88,7 +89,7 @@ service.interceptors.response.use(res => {
         ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
           isRelogin.show = false
           useUserStore().logOut().then(() => {
-            location.href = '/index'
+            location.href = "/gw/index";
           })
       }).catch(() => {
         isRelogin.show = false

+ 1 - 1126
gw-ui/src/views/index.vue

@@ -1,1131 +1,6 @@
 <template>
   <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>北京金水后台管理框架</h2>
-        <p>
-          一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了北京金水管理系统,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
-        </p>
-        <p>
-          <b>当前版本:</b> <span>v{{ version }}</span>
-        </p>
-        <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button
-            type="primary"
-            icon="Cloudy"
-            plain
-            @click="goTarget('https://gitee.com/y_project/RuoYi-Vue')"
-            >访问码云</el-button
-          >
-          <el-button
-            icon="HomeFilled"
-            plain
-            @click="goTarget('http://goldenwater.vip')"
-            >访问主页</el-button
-          >
-        </p>
-      </el-col>
-
-      <el-col :sm="24" :lg="12" style="padding-left: 50px">
-        <el-row>
-          <el-col :span="12">
-            <h2>技术选型</h2>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="6">
-            <h4>后端技术</h4>
-            <ul>
-              <li>SpringBoot</li>
-              <li>Spring Security</li>
-              <li>JWT</li>
-              <li>MyBatis</li>
-              <li>Druid</li>
-              <li>Fastjson</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-          <el-col :span="6">
-            <h4>前端技术</h4>
-            <ul>
-              <li>Vue</li>
-              <li>Vuex</li>
-              <li>Element-ui</li>
-              <li>Axios</li>
-              <li>Sass</li>
-              <li>Quill</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-        </el-row>
-      </el-col>
-    </el-row>
-    <el-divider />
-    <el-row :gutter="20">
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <template v-slot:header>
-            <div class="clearfix">
-              <span>联系信息</span>
-            </div>
-          </template>
-          <div class="body">
-            <p>
-              <i class="el-icon-s-promotion"></i> 官网:<el-link
-                href="http://www.goldenwater.vip"
-                target="_blank"
-                >http://www.goldenwater.vip</el-link
-              >
-            </p>
-            <p>
-              <i class="el-icon-user-solid"></i> QQ群:<s> 满937441 </s> <s> 满887144332 </s>
-              <s> 满180251782 </s> <s> 满104180207 </s> <s> 满186866453 </s> <s> 满201396349 </s>
-              <s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s> 
-              <s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s> 
-              <s> 满101046199 </s> <s> 满136919097 </s> <s> 满143961921 </s> <s> 满174951577 </s> 
-              <s> 满161281055 </s> <s> 满138988063 </s> <s> 满151450850 </s> <s> 满224622315 </s>
-              <s> 满287842588 </s> <s> 满187944233 </s> <s> 满228578329 </s> <s> 满191164766 </s>
-              <s> 满174569686 </s> <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632" target="_blank">127358632</a>
-            </p>
-            <p>
-              <i class="el-icon-chat-dot-round"></i> 微信:<a
-                href="javascript:;"
-                >/ *北京金水</a
-              >
-            </p>
-            <p>
-              <i class="el-icon-money"></i> 支付宝:<a
-                href="javascript:;"
-                class="支付宝信息"
-                >/ *北京金水</a
-              >
-            </p>
-          </div>
-        </el-card>
-      </el-col>
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <template v-slot:header>
-            <div class="clearfix">
-              <span>更新日志</span>
-            </div>
-          </template>
-          <el-collapse accordion>
-            <el-collapse-item title="v3.9.2 - 2026-03-26">
-              <ol>
-                <li>新增锁定屏幕功能</li>
-                <li>首页新增通知公告消息提醒</li>
-                <li>添加持久化标签页开关功能</li>
-                <li>菜单搜索支持文本高亮&数量提示</li>
-                <li>添加菜单路由地址和名称的校验规则</li>
-                <li>字典类型列表新增抽屉效果详细信息</li>
-                <li>升级axios到最新版本0.30.3</li>
-                <li>使用SpringDoc代替Swagger</li>
-                <li>升级spring-boot到最新版本4.0.3</li>
-                <li>升级yauaa到最新版本8.1.0</li>
-                <li>升级oshi到最新版本6.10.0</li>
-                <li>升级druid到最新版本1.2.28</li>
-                <li>升级fastjson到最新版2.0.61</li>
-                <li>升级pagehelper到最新版2.1.1</li>
-                <li>优化操作日志详细页面</li>
-                <li>更新在线IP地址查询url</li>
-                <li>部门管理支持批量保存排序</li>
-                <li>菜单管理支持批量保存排序</li>
-                <li>菜单管理列表新增类型显示</li>
-                <li>代码生成模板支持TypeScript版本</li>
-                <li>优化菜单主题风格显示</li>
-                <li>优化topbar顶部菜单样式</li>
-                <li>优化点击任务名称查看详细</li>
-                <li>优化字典类型属性提醒说明</li>
-                <li>优化防重提交间隔时间可自定义</li>
-                <li>优化页签功能&支持全屏按钮操作</li>
-                <li>优化RightToolbar搜索栏切换动画</li>
-                <li>修复Excel自定义格式样式污染问题</li>
-                <li>优化isAdmin方法统一到SecurityUtils</li>
-                <li>优化定时任务详情页展示&补充执行时间字段</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.9.1 - 2025-12-18">
-              <ol>
-                <li>支持防盗链功能</li>
-                <li>菜单导航设置支持纯顶部</li>
-                <li>使用yauaa代替bitwalker</li>
-                <li>用户头像更换后移除旧头像文件</li>
-                <li>支持Excel导出对象的多个子列表</li>
-                <li>升级oshi到最新版本6.9.1</li>
-                <li>升级druid到最新版本1.2.27</li>
-                <li>升级fastjson到最新版2.0.60</li>
-                <li>升级spring-security到5.7.14</li>
-                <li>升级tomcat到最新版本9.0.112</li>
-                <li>升级commons.io到最新版本2.21.0</li>
-                <li>用户导入添加验证提示</li>
-                <li>显示列信息支持对象格式</li>
-                <li>忽略用户密码字段的JSON序列化</li>
-                <li>网页标题设置新增SET_TITLE方法</li>
-                <li>自动识别json对象白名单配置范围缩小</li>
-                <li>登录/注册页面底部版权信息修改为读取配置</li>
-                <li>修复用户归属部门无法修改为空问题</li>
-                <li>修复固定头部时出现的导航栏偏移问题</li>
-                <li>修复v3时间控件between选择后清空报错问题</li>
-                <li>修复comboReadDict属性下多个sheet出现的报错</li>
-                <li>修复表单构建移除所有控件后切换路由回来空白问题</li>
-                <li>优化布局设置显示</li>
-                <li>优化字典组件值宽松匹配</li>
-                <li>优化获取字典类型值的方法</li>
-                <li>优化生成代码下载的zip文件名</li>
-                <li>优化日志记录参数拼装提升效率</li>
-                <li>优化导入文件检查标题行不能为空</li>
-                <li>优化表单构建关闭页签销毁复制插件</li>
-                <li>优化Excel统计行数值的单元格样式显示</li>
-                <li>优化数据权限控制逻辑,放开permission限制</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.9.0 - 2025-05-28">
-              <ol>
-                <li>优化菜单搜索查询页</li>
-                <li>导航栏显示昵称&设置</li>
-                <li>菜单管理新增路由名称</li>
-                <li>添加底部版权信息&开关</li>
-                <li>分配角色禁用不允许勾选</li>
-                <li>Excel导入导出支持多图片</li>
-                <li>添加页签图标显示开关功能</li>
-                <li>上传组件新增拖动排序属性</li>
-                <li>显隐列组件支持全选/全不选</li>
-                <li>初始密码支持自定义修改策略</li>
-                <li>账号密码支持自定义更新周期</li>
-                <li>代码生成列表支持按时间排序</li>
-                <li>支持富文本复制粘贴图片上传至url</li>
-                <li>支持文件&图片组件自定义地址&参数</li>
-                <li>升级tomcat到最新版本9.0.105</li>
-                <li>升级oshi到最新版本6.8.1</li>
-                <li>升级fastjson到最新版2.0.57</li>
-                <li>升级commons.io到最新版本2.19.0</li>
-                <li>package.json移除runjs依赖</li>
-                <li>package.json移除eslint依赖</li>
-                <li>package.json移除vue-meta依赖</li>
-                <li>修复代码生成主子表校验必填失效问题</li>
-                <li>优化前端树结构性能问题</li>
-                <li>优化前端处理路由函数代码</li>
-                <li>优化文件上传组件新增类型</li>
-                <li>优化顶部菜单搜索栏为多层级显示</li>
-                <li>优化文件&图片上传组件新增disabled属性</li>
-                <li>优化空指针异常时无法获取错误信息问题</li>
-                <li>优化定时任务字符包含多个括号导致数据错误</li>
-                <li>优化登录&注册页表头使用VUE_APP_TITLE配置值</li>
-                <li>优化导出Excel日期格式双击离开后与设定的格式不一致问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.9 - 2024-12-30">
-              <ol>
-                <li>用户管理支持分栏拖动</li>
-                <li>修改主题样式本地读取</li>
-                <li>用户头像http(s)链接支持</li>
-                <li>用户管理过滤掉已禁用部门</li>
-                <li>支持自定义显示Excel属性列</li>
-                <li>操作日志记录DELETE请求参数</li>
-                <li>白名单支持对通配符路径匹配</li>
-                <li>校检文件名是否包含特殊字符</li>
-                <li>代码生成创建表屏蔽违规的字符</li>
-                <li>菜单面包屑导航支持多层级显示</li>
-                <li>Excel注解支持wrapText是否允许内容换行</li>
-                <li>代码生成新增配置是否允许文件覆盖到本地</li>
-                <li>修复角色禁用权限不失效问题</li>
-                <li>修复代码生成上级菜单显示问题</li>
-                <li>修复导出子列表对象只能在最后的问题</li>
-                <li>修复TopNav无法正确获取active的问题</li>
-                <li>修复默认关闭Tags-Views内链页面打不开</li>
-                <li>升级oshi到最新版本6.6.5</li>
-                <li>升级tomcat到最新版本9.0.96</li>
-                <li>升级fastjson到最新版2.0.53</li>
-                <li>升级logback到最新版本1.2.13</li>
-                <li>升级spring-framework到最新版本5.3.39</li>
-                <li>升级quill到最新版本2.0.2</li>
-                <li>升级axios到最新版本0.28.1</li>
-                <li>优化身份证脱敏正则</li>
-                <li>优化权限更新后同步缓存</li>
-                <li>优化查询时间范围日期格式</li>
-                <li>优化参数键值更换为多行文本</li>
-                <li>优化导入带标题文件关闭清理</li>
-                <li>优化上传图片带域名不增加前缀</li>
-                <li>优化特殊字符密码修改失败问题</li>
-                <li>优化无用户编号不校验数据权限</li>
-                <li>优化TopNav内链菜单点击没有高亮</li>
-                <li>优化菜单管理切换Mini布局错乱问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.8 - 2024-06-30">
-              <ol>
-                <li>菜单管理新增路由名称</li>
-                <li>新增数据脱敏过滤注解</li>
-                <li>用户密码新增非法字符验证</li>
-                <li>限制用户操作数据权限范围</li>
-                <li>代码生成新增创建表结构功能</li>
-                <li>定时任务白名单配置范围缩小</li>
-                <li>优化代码生成主子表关联查询方式</li>
-                <li>Excel注解新增属性comboReadDict</li>
-                <li>Excel注解ColumnType类型新增文本</li>
-                <li>新增国际化资源文件配置</li>
-                <li>升级oshi到最新版本6.6.1</li>
-                <li>升级druid到最新版本1.2.23</li>
-                <li>升级core-js到最新版本3.37.1</li>
-                <li>更新HttpUtils中的User-Agent</li>
-                <li>更新compressionPlugin到6.1.2以兼容node18+</li>
-                <li>升级spring-security到安全版本,防止漏洞风险</li>
-                <li>升级spring-framework到安全版本,防止漏洞风险</li>
-                <li>优化自定义XSS注解匹配方式</li>
-                <li>优化缓存监控键名列表排序显示</li>
-                <li>优化定时任务日志默认按时间排序</li>
-                <li>优化默认文件大小超过2G无效的问题</li>
-                <li>优化查表特殊字符使用反斜杠进行转义</li>
-                <li>优化定时任务cron表达式小时配置显示错误问题</li>
-                <li>优化多个自定数据权限使用in查询,避免多次拼接</li>
-                <li>优化导入Excel时设置dictType属性重复查缓存问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.7 - 2023-12-08">
-              <ol>
-                <li>操作日志记录部门名称</li>
-                <li>全局数据存储用户编号</li>
-                <li>新增编程式判断资源访问权限</li>
-                <li>操作日志列表新增IP地址查询</li>
-                <li>定时任务新增页去除状态选项</li>
-                <li>代码生成支持选择前端模板类型</li>
-                <li>显隐列组件支持复选框弹出类型</li>
-                <li>通用排序属性orderBy参数限制长度</li>
-                <li>Excel自定义数据处理器增加单元格/工作簿对象</li>
-                <li>升级oshi到最新版本6.4.8</li>
-                <li>升级druid到最新版本1.2.20</li>
-                <li>升级fastjson到最新版2.0.43</li>
-                <li>升级pagehelper到最新版1.4.7</li>
-                <li>升级commons.io到最新版本2.13.0</li>
-                <li>升级element-ui到最新版本2.15.14</li>
-                <li>修复五级路由缓存无效问题</li>
-                <li>修复外链带端口出现的异常</li>
-                <li>修复树模板父级编码变量错误</li>
-                <li>修复字典表详情页面搜索问题</li>
-                <li>修复内链iframe没有传递参数问题</li>
-                <li>修复自定义字典样式不生效的问题</li>
-                <li>修复字典缓存删除方法参数错误问题</li>
-                <li>修复Excel导入数据临时文件无法删除问题</li>
-                <li>修复未登录带参数访问成功后参数丢失问题</li>
-                <li>修复HeaderSearch组件跳转query参数丢失问题</li>
-                <li>修复代码生成导入后必填项与数据库不匹配问题</li>
-                <li>修复Excels导入时无法获取到dictType字典值问题</li>
-                <li>优化下载zip方法新增遮罩层</li>
-                <li>优化头像上传参数新增文件名称</li>
-                <li>优化字典标签支持自定义分隔符</li>
-                <li>优化菜单管理类型为按钮状态可选</li>
-                <li>优化前端防重复提交数据大小限制</li>
-                <li>优化TopNav菜单没有图标svg不显示</li>
-                <li>优化数字金额大写转换精度丢失问题</li>
-                <li>优化富文本Editor组件检验图片格式</li>
-                <li>优化页签在Firefox浏览器被遮挡的问题</li>
-                <li>优化个人中心/基本资料修改时数据显示问题</li>
-                <li>优化缓存监控图表支持跟随屏幕大小自适应调整</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.6 - 2023-06-30">
-              <ol>
-                <li>支持登录IP黑名单限制</li>
-                <li>新增监控页面图标显示</li>
-                <li>操作日志新增消耗时间属性</li>
-                <li>屏蔽定时任务bean违规的字符</li>
-                <li>日志管理使用索引提升查询性能</li>
-                <li>日志注解支持排除指定的请求参数</li>
-                <li>支持自定义隐藏属性列过滤子对象</li>
-                <li>升级oshi到最新版本6.4.3</li>
-                <li>升级druid到最新版本1.2.16</li>
-                <li>升级fastjson到最新版2.0.34</li>
-                <li>升级spring-boot到最新版本2.5.15</li>
-                <li>升级element-ui到最新版本2.15.13</li>
-                <li>移除apache/commons-fileupload依赖</li>
-                <li>修复页面切换时布局错乱的问题</li>
-                <li>修复匿名注解Anonymous空指针问题</li>
-                <li>修复路由跳转被阻止时内部产生报错信息问题</li>
-                <li>修复isMatchedIp的参数判断产生空指针的问题</li>
-                <li>修复用户多角色数据权限可能出现权限抬升的情况</li>
-                <li>修复开启TopNav后一级菜单路由参数设置无效问题</li>
-                <li>修复DictTag组件value没有匹配的值时则展示value</li>
-                <li>优化文件下载出现的异常</li>
-                <li>优化选择图标组件高亮回显</li>
-                <li>优化弹窗后导航栏偏移的问题</li>
-                <li>优化修改密码日志存储明文问题</li>
-                <li>优化页签栏关闭其他出现的异常问题</li>
-                <li>优化页签关闭左侧选项排除首页选项</li>
-                <li>优化关闭当前tab页跳转最右侧tab页</li>
-                <li>优化缓存列表清除操作提示不变的问题</li>
-                <li>优化字符未使用下划线不进行驼峰式处理</li>
-                <li>优化用户导入更新时需获取用户编号问题</li>
-                <li>优化侧边栏的平台标题与VUE_APP_TITLE保持同步</li>
-                <li>优化导出Excel时设置dictType属性重复查缓存问题</li>
-                <li>连接池Druid支持新的配置connectTimeout和socketTimeout</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.5 - 2023-01-01">
-              <ol>
-                <li>定时任务违规的字符</li>
-                <li>重置时取消部门选中</li>
-                <li>新增返回警告消息提示</li>
-                <li>忽略不必要的属性数据返回</li>
-                <li>修改参数键名时移除前缓存配置</li>
-                <li>导入更新用户数据前校验数据权限</li>
-                <li>兼容Excel下拉框内容过多无法显示的问题</li>
-                <li>升级echarts到最新版本5.4.0</li>
-                <li>升级core-js到最新版本3.25.3</li>
-                <li>升级oshi到最新版本6.4.0</li>
-                <li>升级kaptcha到最新版2.3.3</li>
-                <li>升级druid到最新版本1.2.15</li>
-                <li>升级fastjson到最新版2.0.20</li>
-                <li>升级pagehelper到最新版1.4.6</li>
-                <li>优化弹窗内容过多展示不全问题</li>
-                <li>优化swagger-ui静态资源使用缓存</li>
-                <li>开启TopNav没有子菜单隐藏侧边栏</li>
-                <li>删除fuse无效选项maxPatternLength</li>
-                <li>优化导出对象的子列表为空会出现[]问题</li>
-                <li>优化编辑头像时透明部分会变成黑色问题</li>
-                <li>优化小屏幕上修改头像界面布局错位的问题</li>
-                <li>修复代码生成勾选属性无效问题</li>
-                <li>修复文件上传组件格式验证问题</li>
-                <li>修复回显数据字典数组异常问题</li>
-                <li>修复sheet超出最大行数异常问题</li>
-                <li>修复Log注解GET请求记录不到参数问题</li>
-                <li>修复调度日志点击多次数据不变化的问题</li>
-                <li>修复主题颜色在Drawer组件不会加载问题</li>
-                <li>修复文件名包含特殊字符的文件无法下载问题</li>
-                <li>修复table中更多按钮切换主题色未生效修复问题</li>
-                <li>修复某些特性的环境生成代码变乱码TXT文件问题</li>
-                <li>修复代码生成图片/文件/单选时选择必填无法校验问题</li>
-                <li>修复某些特性的情况用户编辑对话框中角色和部门无法修改问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.4 - 2022-09-26">
-              <ol>
-                <li>数据逻辑删除不进行唯一验证</li>
-                <li>Excel注解支持导出对象的子列表方法</li>
-                <li>Excel注解支持自定义隐藏属性列</li>
-                <li>Excel注解支持backgroundColor属性设置背景色</li>
-                <li>支持配置密码最大错误次数/锁定时间</li>
-                <li>登录日志新增解锁账户功能</li>
-                <li>通用下载方法新增config配置选项</li>
-                <li>支持多权限字符匹配角色数据权限</li>
-                <li>页面内嵌iframe切换tab不刷新数据</li>
-                <li>操作日志记录支持排除敏感属性字段</li>
-                <li>修复多文件上传报错出现的异常问题</li>
-                <li>修复图片预览组件src属性为null值控制台报错问题</li>
-                <li>升级oshi到最新版本6.2.2</li>
-                <li>升级fastjson到最新版2.0.14</li>
-                <li>升级pagehelper到最新版1.4.3</li>
-                <li>升级core-js到最新版本3.25.2</li>
-                <li>升级element-ui到最新版本2.15.10</li>
-                <li>优化任务过期不执行调度</li>
-                <li>优化字典数据使用store存取</li>
-                <li>优化修改资料头像被覆盖的问题</li>
-                <li>优化修改用户登录账号重复验证</li>
-                <li>优化代码生成同步后值NULL问题</li>
-                <li>优化定时任务支持执行父类方法</li>
-                <li>优化用户个人信息接口防止修改部门</li>
-                <li>优化布局设置使用el-drawer抽屉显示</li>
-                <li>优化没有权限的用户编辑部门缺少数据</li>
-                <li>优化日志注解记录限制请求地址的长度</li>
-                <li>优化excel/scale属性导出单元格数值类型</li>
-                <li>优化日志操作中重置按钮时重复查询的问题</li>
-                <li>优化多个相同角色数据导致权限SQL重复问题</li>
-                <li>优化表格上右侧工具条(搜索按钮显隐&右侧样式凸出)</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.3 - 2022-06-27">
-              <ol>
-                <li>新增缓存列表菜单功能</li>
-                <li>代码生成树表新增(展开/折叠)</li>
-                <li>Excel注解支持color字体颜色</li>
-                <li>新增Anonymous匿名访问不鉴权注解</li>
-                <li>用户头像上传限制只能为图片格式</li>
-                <li>接口使用泛型使其看到响应属性字段</li>
-                <li>检查定时任务bean所在包名是否为白名单配置</li>
-                <li>添加页签openPage支持传递参数</li>
-                <li>用户缓存信息添加部门ancestors祖级列表</li>
-                <li>升级element-ui到最新版本2.15.8</li>
-                <li>升级oshi到最新版本6.1.6</li>
-                <li>升级druid到最新版本1.2.11</li>
-                <li>升级fastjson到最新版2.0.8</li>
-                <li>升级spring-boot到最新版本2.5.14</li>
-                <li>降级jsencrypt版本兼容IE浏览器</li>
-                <li>删除多余的salt字段</li>
-                <li>新增获取不带后缀文件名称方法</li>
-                <li>新增获取配置文件中的属性值方法</li>
-                <li>新增内容编码/解码方便插件集成使用</li>
-                <li>字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)</li>
-                <li>优化设置分页参数默认值</li>
-                <li>优化对空字符串参数处理的过滤</li>
-                <li>优化显示顺序orderNum类型为整型</li>
-                <li>优化表单构建按钮不显示正则校验</li>
-                <li>优化字典数据回显样式下拉框显示值</li>
-                <li>优化R响应成功状态码与全局保持一致</li>
-                <li>优化druid开启wall过滤器出现的异常问题</li>
-                <li>优化用户管理左侧树型组件增加选中高亮保持</li>
-                <li>优化新增用户与角色信息&用户与岗位信息逻辑</li>
-                <li>优化默认不启用压缩文件缓存防止node_modules过大</li>
-                <li>修复字典数据显示不全问题</li>
-                <li>修复操作日志查询类型条件为0时会查到所有数据</li>
-                <li>修复Excel注解prompt/combo同时使用不生效问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.2 - 2022-04-01">
-              <ol>
-                <li>前端支持设置是否需要防止数据重复提交</li>
-                <li>开启TopNav没有子菜单情况隐藏侧边栏</li>
-                <li>侧边栏菜单名称过长悬停显示标题</li>
-                <li>用户访问控制时校验数据权限,防止越权</li>
-                <li>导出Excel时屏蔽公式,防止CSV注入风险</li>
-                <li>组件ImagePreview支持多图预览显示</li>
-                <li>组件ImageUpload支持多图同时选择上传</li>
-                <li>组件FileUpload支持多文件同时选择上传</li>
-                <li>服务监控新增运行参数信息显示</li>
-                <li>定时任务目标字符串过滤特殊字符</li>
-                <li>定时任务目标字符串验证包名白名单</li>
-                <li>代码生成列表图片支持预览</li>
-                <li>代码生成编辑修改打开新页签</li>
-                <li>代码生成新增Java类型Boolean</li>
-                <li>代码生成子表支持日期/字典配置</li>
-                <li>代码生成同步保留必填/类型选项</li>
-                <li>升级oshi到最新版本6.1.2</li>
-                <li>升级fastjson到最新版1.2.80</li>
-                <li>升级pagehelper到最新版1.4.1</li>
-                <li>升级spring-boot到最新版本2.5.11</li>
-                <li>升级spring-boot-mybatis到最新版2.2.2</li>
-                <li>添加遗漏的分页参数合理化属性</li>
-                <li>修改npm即将过期的注册源地址</li>
-                <li>修复分页组件请求两次问题</li>
-                <li>修复通用文件下载接口跨域问题</li>
-                <li>修复Xss注解字段值为空时的异常问题</li>
-                <li>修复选项卡点击右键刷新丢失参数问题</li>
-                <li>修复表单清除元素位置未垂直居中问题</li>
-                <li>修复服务监控中运行参数显示条件错误</li>
-                <li>修复导入Excel时字典字段类型为Long转义为空问题</li>
-                <li>修复登录超时刷新页面跳转登录页面还提示重新登录问题</li>
-                <li>优化加载字典缓存数据</li>
-                <li>优化IP地址获取到多个的问题</li>
-                <li>优化任务队列满时任务拒绝策略</li>
-                <li>优化文件上传兼容Weblogic环境</li>
-                <li>优化定时任务默认保存到内存中执行</li>
-                <li>优化部门修改缩放后出现的错位问题</li>
-                <li>优化Excel格式化不同类型的日期对象</li>
-                <li>优化菜单表关键字导致的插件报错问题</li>
-                <li>优化Oracle用户头像列为空时不显示问题</li>
-                <li>优化页面若未匹配到字典标签则返回原字典值</li>
-                <li>优化修复登录失效后多次请求提示多次弹窗问题</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.1 - 2022-01-01">
-              <ol>
-                <li>新增Vue3前端代码生成模板</li>
-                <li>新增图片预览组件</li>
-                <li>新增压缩插件实现打包Gzip</li>
-                <li>自定义xss校验注解实现</li>
-                <li>自定义文字复制剪贴指令</li>
-                <li>代码生成预览支持复制内容</li>
-                <li>路由支持单独配置菜单或角色权限</li>
-                <li>用户管理部门查询选择节点后分页参数初始</li>
-                <li>修复用户分配角色属性错误</li>
-                <li>修复打包后字体图标偶现的乱码问题</li>
-                <li>修复菜单管理重置表单出现的错误</li>
-                <li>修复版本差异导致的懒加载报错问题</li>
-                <li>修复Cron组件中周回显问题</li>
-                <li>修复定时任务多参数逗号分隔的问题</li>
-                <li>修复根据ID查询列表可能出现的主键溢出问题</li>
-                <li>修复tomcat配置参数已过期问题</li>
-                <li>升级clipboard到最新版本2.0.8</li>
-                <li>升级oshi到最新版本v5.8.6</li>
-                <li>升级fastjson到最新版1.2.79</li>
-                <li>升级spring-boot到最新版本2.5.8</li>
-                <li>升级log4j2到2.17.1,防止漏洞风险</li>
-                <li>优化下载解析blob异常提示</li>
-                <li>优化代码生成字典组重复问题</li>
-                <li>优化查询用户的角色组&岗位组代码</li>
-                <li>优化定时任务cron表达式小时设置24</li>
-                <li>优化用户导入提示溢出则显示滚动条</li>
-                <li>优化防重复提交标识组合为(key+url+header)</li>
-                <li>优化分页方法设置成通用方便灵活调用</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.8.0 - 2021-12-01">
-              <ol>
-                <li>新增配套并同步的Vue3前端版本</li>
-                <li>新增通用方法简化模态/缓存/下载/权限/页签使用</li>
-                <li>优化导出数据/使用通用下载方法</li>
-                <li>Excel注解支持自定义数据处理器</li>
-                <li>Excel注解支持导入导出标题信息</li>
-                <li>Excel导入支持@Excels注解</li>
-                <li>新增组件data-dict,简化数据字典使用</li>
-                <li>新增Jaxb依赖,防止jdk8以上出现的兼容错误</li>
-                <li>生产环境使用路由懒加载提升页面响应速度</li>
-                <li>修复五级以上菜单出现的404问题</li>
-                <li>防重提交注解支持配置间隔时间/提示消息</li>
-                <li>日志注解新增是否保存响应参数</li>
-                <li>任务屏蔽违规字符&参数忽略双引号中的逗号</li>
-                <li>升级SpringBoot到最新版本2.5.6</li>
-                <li>升级pagehelper到最新版1.4.0</li>
-                <li>升级spring-boot-mybatis到最新版2.2.0</li>
-                <li>升级oshi到最新版本v5.8.2</li>
-                <li>升级druid到最新版1.2.8</li>
-                <li>升级velocity到最新版本2.3</li>
-                <li>升级fastjson到最新版1.2.78</li>
-                <li>升级axios到最新版本0.24.0</li>
-                <li>升级dart-sass到版本1.32.13</li>
-                <li>升级core-js到最新版本3.19.1</li>
-                <li>升级jsencrypt到最新版本3.2.1</li>
-                <li>升级js-cookie到最新版本3.0.1</li>
-                <li>升级file-saver到最新版本2.0.5</li>
-                <li>升级sass-loader到最新版本10.1.1</li>
-                <li>升级element-ui到最新版本2.15.6</li>
-                <li>新增sendGet无参请求方法</li>
-                <li>禁用el-tag组件的渐变动画</li>
-                <li>代码生成点击预览重置激活tab</li>
-                <li>AjaxResult重写put方法,以方便链式调用</li>
-                <li>优化登录/验证码请求headers不设置token</li>
-                <li>优化用户个人信息接口防止修改用户名</li>
-                <li>优化Cron表达式生成器关闭时销毁避免缓存</li>
-                <li>优化注册成功提示消息类型success</li>
-                <li>优化aop语法,使用spring自动注入注解</li>
-                <li>优化记录登录信息,移除不必要的修改</li>
-                <li>优化mybatis全局默认的执行器</li>
-                <li>优化Excel导入图片可能出现的异常</li>
-                <li>修复代码生成模板主子表删除缺少事务</li>
-                <li>修复日志记录可能出现的转换异常</li>
-                <li>修复代码生成复选框字典遗漏问题</li>
-                <li>修复关闭xss功能导致可重复读RepeatableFilter失效</li>
-                <li>修复字符串无法被反转义问题</li>
-                <li>修复后端主子表代码模板方法名生成错误问题</li>
-                <li>修复xss过滤后格式出现的异常</li>
-                <li>修复swagger没有指定dataTypeClass导致启动出现warn日志</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.7.0 - 2021-09-13">
-              <ol>
-                <li>参数管理支持配置验证码开关</li>
-                <li>新增是否开启用户注册功能</li>
-                <li>定时任务支持在线生成cron表达式</li>
-                <li>菜单管理支持配置路由参数</li>
-                <li>支持自定义注解实现接口限流</li>
-                <li>Excel注解支持Image图片导入</li>
-                <li>自定义弹层溢出滚动样式</li>
-                <li>自定义可拖动弹窗宽度指令</li>
-                <li>自定义可拖动弹窗高度指令</li>
-                <li>修复任意账户越权问题</li>
-                <li>修改时检查用户数据权限范围</li>
-                <li>修复保存配置主题颜色失效问题</li>
-                <li>新增暗色菜单风格主题</li>
-                <li>菜单&部门新增展开/折叠功能</li>
-                <li>页签新增关闭左侧&添加图标</li>
-                <li>顶部菜单排除隐藏的默认路由</li>
-                <li>顶部菜单同步系统主题样式</li>
-                <li>跳转路由高亮相对应的菜单栏</li>
-                <li>代码生成主子表多选行数据</li>
-                <li>日期范围支持添加多组</li>
-                <li>升级element-ui到最新版本2.15.5</li>
-                <li>升级oshi到最新版本v5.8.0</li>
-                <li>升级commons.io到最新版本v2.11.0</li>
-                <li>定时任务屏蔽ldap远程调用</li>
-                <li>定时任务屏蔽http(s)远程调用</li>
-                <li>补充定时任务表字段注释</li>
-                <li>定时任务对检查异常进行事务回滚</li>
-                <li>启用父部门状态排除顶级节点</li>
-                <li>富文本新增上传文件大小限制</li>
-                <li>默认首页使用keep-alive缓存</li>
-                <li>修改代码生成字典回显样式</li>
-                <li>自定义分页合理化传入参数</li>
-                <li>修复字典组件值为整形不显示问题</li>
-                <li>修复定时任务日志执行状态显示</li>
-                <li>角色&菜单新增字段属性提示信息</li>
-                <li>修复角色分配用户页面参数类型错误提醒</li>
-                <li>优化布局设置动画特效</li>
-                <li>优化异常处理信息</li>
-                <li>优化错误token导致的解析异常</li>
-                <li>密码框新增显示切换密码图标</li>
-                <li>定时任务新增更多操作</li>
-                <li>更多操作按钮添加权限控制</li>
-                <li>导入用户样式优化</li>
-                <li>提取通用方法到基类控制器</li>
-                <li>优化使用权限工具获取用户信息</li>
-                <li>优化用户不能删除自己</li>
-                <li>优化XSS跨站脚本过滤</li>
-                <li>优化代码生成模板</li>
-                <li>验证码默认20s超时</li>
-                <li>BLOB下载时清除URL对象引用</li>
-                <li>代码生成导入表按创建时间排序</li>
-                <li>修复代码生成页面数据编辑保存之后总是跳转第一页的问题</li>
-                <li>修复带safari浏览器无法格式化utc日期格式yyyy-MM-dd'T'HH:mm:ss.SSS问题</li>
-                <li>多图上传组件移除多余的api地址&验证失败导致图片删除问题&无法删除相应图片修复</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.6.0 - 2021-07-12">
-              <ol>
-                <li>角色管理新增分配用户功能</li>
-                <li>用户管理新增分配角色功能</li>
-                <li>日志列表支持排序操作</li>
-                <li>优化参数&字典缓存操作</li>
-                <li>系统布局配置支持动态标题开关</li>
-                <li>菜单路由配置支持内链访问</li>
-                <li>默认访问后端首页新增提示语</li>
-                <li>富文本默认上传返回url类型</li>
-                <li>新增自定义弹窗拖拽指令</li>
-                <li>全局注册常用通用组件</li>
-                <li>全局挂载字典标签组件</li>
-                <li>ImageUpload组件支持多图片上传</li>
-                <li>FileUpload组件支持多文件上传</li>
-                <li>文件上传组件添加数量限制属性</li>
-                <li>富文本编辑组件添加类型属性</li>
-                <li>富文本组件工具栏配置视频</li>
-                <li>封装通用iframe组件</li>
-                <li>限制超级管理员不允许操作</li>
-                <li>用户信息长度校验限制</li>
-                <li>分页组件新增pagerCount属性</li>
-                <li>添加bat脚本执行应用</li>
-                <li>升级oshi到最新版本v5.7.4</li>
-                <li>升级element-ui到最新版本2.15.2</li>
-                <li>升级pagehelper到最新版1.3.1</li>
-                <li>升级commons.io到最新版本v2.10.0</li>
-                <li>升级commons.fileupload到最新版本v1.4</li>
-                <li>升级swagger到最新版本v3.0.0</li>
-                <li>修复关闭confirm提示框控制台报错问题</li>
-                <li>修复存在的SQL注入漏洞问题</li>
-                <li>定时任务屏蔽rmi远程调用</li>
-                <li>修复用户搜索分页变量错误</li>
-                <li>修复导出角色数据范围翻译缺少仅本人</li>
-                <li>修复表单构建选择下拉选择控制台报错问题</li>
-                <li>优化图片工具类读取文件</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.5.0 - 2021-05-25">
-              <ol>
-                <li>新增菜单导航显示风格TopNav(false为左侧导航菜单,true为顶部导航菜单)</li>
-                <li>布局设置支持保存&重置配置</li>
-                <li>修复树表数据显示不全&加载慢问题</li>
-                <li>新增IE浏览器版本过低提示页面</li>
-                <li>用户登录后记录最后登录IP&时间</li>
-                <li>页面导出按钮点击之后添加遮罩</li>
-                <li>富文本编辑器支持自定义上传地址</li>
-                <li>富文本编辑组件新增readOnly属性</li>
-                <li>页签TagsView新增关闭右侧功能</li>
-                <li>显隐列组件加载初始默认隐藏列</li>
-                <li>关闭头像上传窗口还原默认图片</li>
-                <li>个人信息添加手机&邮箱重复验证</li>
-                <li>代码生成模板导出按钮点击后添加遮罩</li>
-                <li>代码生成模板树表操作列添加新增按钮</li>
-                <li>代码生成模板修复主子表字段重名问题</li>
-                <li>升级fastjson到最新版1.2.76</li>
-                <li>升级druid到最新版本v1.2.6</li>
-                <li>升级mybatis到最新版3.5.6 阻止远程代码执行漏洞</li>
-                <li>升级oshi到最新版本v5.6.0</li>
-                <li>velocity剔除commons-collections版本,防止3.2.1版本的反序列化漏洞</li>
-                <li>数据监控页默认账户密码防止越权访问</li>
-                <li>修复firefox下表单构建拖拽会新打卡一个选项卡</li>
-                <li>修正后端导入表权限标识</li>
-                <li>修正前端操作日志&登录日志权限标识</li>
-                <li>设置Redis配置HashKey序列化</li>
-                <li>删除操作日志记录信息</li>
-                <li>上传媒体类型添加视频格式</li>
-                <li>修复请求形参未传值记录日志异常问题</li>
-                <li>优化xss校验json请求条件</li>
-                <li>树级结构更新子节点使用replaceFirst</li>
-                <li>优化ExcelUtil空值处理</li>
-                <li>日志记录过滤BindingResult对象,防止异常</li>
-                <li>修改主题后mini类型按钮无效问题</li>
-                <li>优化通用下载完成后删除节点</li>
-                <li>通用Controller添加响应返回消息</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.4.0 - 2021-02-22">
-              <ol>
-                <li>代码生成模板支持主子表</li>
-                <li>表格右侧工具栏组件支持显隐列</li>
-                <li>图片组件添加预览&移除功能</li>
-                <li>Excel注解支持Image图片导出</li>
-                <li>操作按钮组调整为朴素按钮样式</li>
-                <li>代码生成支持文件上传组件</li>
-                <li>代码生成日期控件区分范围</li>
-                <li>代码生成数据库文本类型生成表单文本域</li>
-                <li>用户手机邮箱&菜单组件修改允许空字符串</li>
-                <li>升级SpringBoot到最新版本2.2.13 提升启动速度</li>
-                <li>升级druid到最新版本v1.2.4</li>
-                <li>升级fastjson到最新版1.2.75</li>
-                <li>升级element-ui到最新版本2.15.0</li>
-                <li>修复IE11浏览器报错问题</li>
-                <li>优化多级菜单之间切换无法缓存的问题</li>
-                <li>修复四级菜单无法显示问题</li>
-                <li>修正侧边栏静态路由丢失问题</li>
-                <li>修复角色管理-编辑角色-功能权限显示异常</li>
-                <li>配置文件新增redis数据库索引属性</li>
-                <li>权限工具类增加admin判断</li>
-                <li>角色非自定义权限范围清空选择值</li>
-                <li>修复导入数据为负浮点数时丢失精度问题</li>
-                <li>移除path-to-regexp正则匹配插件</li>
-                <li>修复生成树表代码异常</li>
-                <li>修改ip字段长度防止ipv6地址长度不够</li>
-                <li>防止get请求参数值为false或0等特殊值会导致无法正确的传参</li>
-                <li>登录后push添加catch防止出现检查错误</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.3.0 - 2020-12-14">
-              <ol>
-                <li>新增缓存监控功能</li>
-                <li>支持主题风格配置</li>
-                <li>修复多级菜单之间切换无法缓存的问题</li>
-                <li>多级菜单自动配置组件</li>
-                <li>代码生成预览支持高亮显示</li>
-                <li>支持Get请求映射Params参数</li>
-                <li>删除用户和角色解绑关联</li>
-                <li>去除用户手机邮箱部门必填验证</li>
-                <li>Excel支持注解align对齐方式</li>
-                <li>Excel支持导入Boolean型数据</li>
-                <li>优化头像样式,鼠标移入悬停遮罩</li>
-                <li>代码生成预览提供滚动机制</li>
-                <li>代码生成删除多余的数字float类型</li>
-                <li>修正转换字符串的目标字符集属性</li>
-                <li>回显数据字典防止空值报错</li>
-                <li>日志记录增加过滤多文件场景</li>
-                <li>修改缓存Set方法可能导致嵌套的问题</li>
-                <li>移除前端一些多余的依赖</li>
-                <li>防止安全扫描YUI出现的风险提示</li>
-                <li>修改node-sass为dart-sass</li>
-                <li>升级SpringBoot到最新版本2.1.18</li>
-                <li>升级poi到最新版本4.1.2</li>
-                <li>升级oshi到最新版本v5.3.6</li>
-                <li>升级bitwalker到最新版本1.21</li>
-                <li>升级axios到最新版本0.21.0</li>
-                <li>升级element-ui到最新版本2.14.1</li>
-                <li>升级vue到最新版本2.6.12</li>
-                <li>升级vuex到最新版本3.6.0</li>
-                <li>升级vue-cli到版本4.5.9</li>
-                <li>升级vue-router到最新版本3.4.9</li>
-                <li>升级vue-cli到最新版本4.4.6</li>
-                <li>升级vue-cropper到最新版本0.5.5</li>
-                <li>升级clipboard到最新版本2.0.6</li>
-                <li>升级core-js到最新版本3.8.1</li>
-                <li>升级echarts到最新版本4.9.0</li>
-                <li>升级file-saver到最新版本2.0.4</li>
-                <li>升级fuse.js到最新版本6.4.3</li>
-                <li>升级js-beautify到最新版本1.13.0</li>
-                <li>升级js-cookie到最新版本2.2.1</li>
-                <li>升级path-to-regexp到最新版本6.2.0</li>
-                <li>升级quill到最新版本1.3.7</li>
-                <li>升级screenfull到最新版本5.0.2</li>
-                <li>升级sortablejs到最新版本1.10.2</li>
-                <li>升级vuedraggable到最新版本2.24.3</li>
-                <li>升级chalk到最新版本4.1.0</li>
-                <li>升级eslint到最新版本7.15.0</li>
-                <li>升级eslint-plugin-vue到最新版本7.2.0</li>
-                <li>升级lint-staged到最新版本10.5.3</li>
-                <li>升级runjs到最新版本4.4.2</li>
-                <li>升级sass-loader到最新版本10.1.0</li>
-                <li>升级script-ext-html-webpack-plugin到最新版本2.1.5</li>
-                <li>升级svg-sprite-loader到最新版本5.1.1</li>
-                <li>升级vue-template-compiler到最新版本2.6.12</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.2.1 - 2020-11-18">
-              <ol>
-                <li>阻止任意文件下载漏洞</li>
-                <li>代码生成支持上传控件</li>
-                <li>新增图片上传组件</li>
-                <li>调整默认首页</li>
-                <li>升级druid到最新版本v1.2.2</li>
-                <li>mapperLocations配置支持分隔符</li>
-                <li>权限信息调整</li>
-                <li>调整sql默认时间</li>
-                <li>解决代码生成没有bit类型的问题</li>
-                <li>升级pagehelper到最新版1.3.0</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v3.2.0 - 2020-10-10">
-              <ol>
-                <li>升级springboot版本到2.1.17 提升安全性</li>
-                <li>升级oshi到最新版本v5.2.5</li>
-                <li>升级druid到最新版本v1.2.1</li>
-                <li>升级jjwt到版本0.9.1</li>
-                <li>升级fastjson到最新版1.2.74</li>
-                <li>修改sass为node-sass,避免el-icon图标乱码</li>
-                <li>代码生成支持同步数据库</li>
-                <li>代码生成支持富文本控件</li>
-                <li>代码生成页面时不忽略remark属性</li>
-                <li>代码生成添加select必填选项</li>
-                <li>Excel导出类型NUMERIC支持精度浮点类型</li>
-                <li>Excel导出targetAttr优化获取值,防止get方法不规范</li>
-                <li>Excel注解支持自动统计数据总和</li>
-                <li>Excel注解支持设置BigDecimal精度&舍入规则</li>
-                <li>菜单&数据权限新增(展开/折叠 全选/全不选 父子联动)</li>
-                <li>允许用户分配到部门父节点</li>
-                <li>菜单新增是否缓存keep-alive</li>
-                <li>表格操作列间距调整</li>
-                <li>限制系统内置参数不允许删除</li>
-                <li>富文本组件优化,支持自定义高度&图片冲突问题</li>
-                <li>富文本工具栏样式对齐</li>
-                <li>导入excel整形值校验优化</li>
-                <li>修复页签关闭所有时固定标签路由不刷新问题</li>
-                <li>表单构建布局型组件新增按钮</li>
-                <li>左侧菜单文字过长显示省略号</li>
-                <li>修正根节点为子部门时,树状结构显示问题</li>
-                <li>修正调用目标字符串最大长度</li>
-                <li>修正菜单提示信息错误</li>
-                <li>修正定时任务执行一次权限标识</li>
-                <li>修正数据库字符串类型nvarchar</li>
-                <li>优化递归子节点</li>
-                <li>优化数据权限判断</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v3.1.0 - 2020-08-13">
-              <ol>
-                <li>表格工具栏右侧添加刷新&显隐查询组件</li>
-                <li>后端支持CORS跨域请求</li>
-                <li>代码生成支持选择上级菜单</li>
-                <li>代码生成支持自定义路径</li>
-                <li>代码生成支持复选框</li>
-                <li>Excel导出导入支持dictType字典类型</li>
-                <li>Excel支持分割字符串组内容</li>
-                <li>验证码类型支持(数组计算、字符验证)</li>
-                <li>升级vue-cli版本到4.4.4</li>
-                <li>修改 node-sass 为 dart-sass</li>
-                <li>表单类型为Integer/Long设置整形默认值</li>
-                <li>代码生成器默认mapper路径与默认mapperScan路径不一致</li>
-                <li>优化防重复提交拦截器</li>
-                <li>优化上级菜单不能选择自己</li>
-                <li>修复角色的权限分配后,未实时生效问题</li>
-                <li>修复在线用户日志记录类型</li>
-                <li>修复富文本空格和缩进保存后不生效问题</li>
-                <li>修复在线用户判断逻辑</li>
-                <li>唯一限制条件只返回单条数据</li>
-                <li>添加获取当前的环境配置方法</li>
-                <li>超时登录后页面跳转到首页</li>
-                <li>全局异常状态汉化拦截处理</li>
-                <li>HTML过滤器改为将html转义</li>
-                <li>检查字符支持小数点&降级改成异常提醒</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v3.0.0 - 2020-07-20">
-              <ol>
-                <li>单应用调整为多模块项目</li>
-                <li>升级element-ui版本到2.13.2</li>
-                <li>删除babel,提高编译速度。</li>
-                <li>新增菜单默认主类目</li>
-                <li>编码文件名修改为uuid方式</li>
-                <li>定时任务cron表达式验证</li>
-                <li>角色权限修改时已有权限未自动勾选异常修复</li>
-                <li>防止切换权限用户后登录出现404</li>
-                <li>Excel支持sort导出排序</li>
-                <li>创建用户不允许选择超级管理员角色</li>
-                <li>修复代码生成导入表结构出现异常页面不提醒问题</li>
-                <li>修复代码生成点击多次表修改数据不变化的问题</li>
-                <li>修复头像上传成功二次打开无法改变裁剪框大小和位置问题</li>
-                <li>修复布局为small者mini用户表单显示错位问题</li>
-                <li>修复热部署导致的强换异常问题</li>
-                <li>修改用户管理复选框宽度,防止部分浏览器出现省略号</li>
-                <li>IpUtils工具,清除Xss特殊字符,防止Xff注入攻击</li>
-                <li>生成domain 如果是浮点型 统一用BigDecimal</li>
-                <li>定时任务调整label-width,防止部署出现错位</li>
-                <li>调整表头固定列默认样式</li>
-                <li>代码生成模板调整,字段为String并且必填则加空串条件</li>
-                <li>代码生成字典Integer/Long使用parseInt</li>
-                <li>
-                  修复dict_sort不可update为0的问题&查询返回增加dict_sort升序排序
-                </li>
-                <li>修正岗位导出权限注解</li>
-                <li>禁止加密密文返回前端</li>
-                <li>修复代码生成页面中的查询条件创建时间未生效的问题</li>
-                <li>修复首页搜索菜单外链无法点击跳转问题</li>
-                <li>修复菜单管理选择图标,backspace删除时不过滤数据</li>
-                <li>用户管理部门分支节点不可检查&显示计数</li>
-                <li>数据范围过滤属性调整</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.3.0 - 2020-06-01">
-              <ol>
-                <li>升级fastjson到最新版1.2.70 修复高危安全漏洞</li>
-                <li>dev启动默认打开浏览器</li>
-                <li>vue-cli使用默认source-map</li>
-                <li>slidebar eslint报错优化</li>
-                <li>当tags-view滚动关闭右键菜单</li>
-                <li>字典管理添加缓存读取</li>
-                <li>参数管理支持缓存操作</li>
-                <li>支持一级菜单(和主页同级)在main区域显示</li>
-                <li>限制外链地址必须以http(s)开头</li>
-                <li>tagview & sidebar 主题颜色与element ui(全局)同步</li>
-                <li>修改数据源类型优先级,先根据方法,再根据类</li>
-                <li>支持是否需要设置token属性,自定义返回码消息。</li>
-                <li>swagger请求前缀加入配置。</li>
-                <li>登录地点设置内容过长则隐藏显示</li>
-                <li>修复定时任务执行一次按钮后不提示消息问题</li>
-                <li>修改上级部门(选择项排除本身和下级)</li>
-                <li>通用http发送方法增加参数 contentType 编码类型</li>
-                <li>更换IP地址查询接口</li>
-                <li>修复页签变量undefined</li>
-                <li>添加校验部门包含未停用的子部门</li>
-                <li>修改定时任务详情下次执行时间日期显示错误</li>
-                <li>角色管理查询设置默认排序字段</li>
-                <li>swagger添加enable参数控制是否启用</li>
-                <li>只对json类型请求构建可重复读取inputStream的request</li>
-                <li>修改代码生成字典字段int类型没有自动选中问题</li>
-                <li>vuex用户名取值修正</li>
-                <li>表格树模板去掉多余的)</li>
-                <li>代码生成序号修正</li>
-                <li>全屏情况下不调整上外边距</li>
-                <li>代码生成Date字段添加默认格式</li>
-                <li>用户管理角色选择权限控制</li>
-                <li>修复路由懒加载报错问题</li>
-                <li>模板sql.vm添加菜单状态</li>
-                <li>设置用户名称不能修改</li>
-                <li>dialog添加append-to-body属性,防止ie遮罩</li>
-                <li>菜单区分状态和显示隐藏功能</li>
-                <li>升级fastjson到最新版1.2.68 修复安全加固</li>
-                <li>修复代码生成如果选择字典类型缺失逗号问题</li>
-                <li>登录请求params更换为data,防止暴露url</li>
-                <li>日志返回时间格式处理</li>
-                <li>添加handle控制允许拖动的元素</li>
-                <li>布局设置点击扩大范围</li>
-                <li>代码生成列属性排序查询</li>
-                <li>代码生成列支持拖动排序</li>
-                <li>修复时间格式不支持ios问题</li>
-                <li>表单构建添加父级class,防止冲突</li>
-                <li>定时任务并发属性修正</li>
-                <li>角色禁用&菜单隐藏不查询权限</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.2.0 - 2020-03-18">
-              <ol>
-                <li>系统监控新增定时任务功能</li>
-                <li>添加一个打包Web工程bat</li>
-                <li>修复页签鼠标滚轮按下的时候,可以关闭不可关闭的tag</li>
-                <li>修复点击退出登录有时会无提示问题</li>
-                <li>修复防重复提交注解无效问题</li>
-                <li>修复通知公告批量删除异常问题</li>
-                <li>添加菜单时路由地址必填限制</li>
-                <li>代码生成字段描述可编辑</li>
-                <li>修复用户修改个人信息导致缓存不过期问题</li>
-                <li>个人信息创建时间获取正确属性值</li>
-                <li>操作日志详细显示正确类型</li>
-                <li>导入表单击行数据时选中对应的复选框</li>
-                <li>批量替换表前缀逻辑调整</li>
-                <li>固定重定向路径表达式</li>
-                <li>升级element-ui版本到2.13.0</li>
-                <li>操作日志排序调整</li>
-                <li>修复charts切换侧边栏或者缩放窗口显示bug</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.1.0 - 2020-02-24">
-              <ol>
-                <li>新增表单构建</li>
-                <li>代码生成支持树表结构</li>
-                <li>新增用户导入</li>
-                <li>修复动态加载路由页面刷新问题</li>
-                <li>修复地址开关无效问题</li>
-                <li>汉化错误提示页面</li>
-                <li>代码生成已知问题修改</li>
-                <li>修复多数据源下配置关闭出现异常处理</li>
-                <li>添加HTML过滤器,用于去除XSS漏洞隐患</li>
-                <li>修复上传头像控制台出现异常</li>
-                <li>修改用户管理分页不正确的问题</li>
-                <li>修复验证码记录提示错误</li>
-                <li>修复request.js缺少Message引用</li>
-                <li>修复表格时间为空出现的异常</li>
-                <li>添加Jackson日期反序列化时区配置</li>
-                <li>调整根据用户权限加载菜单数据树形结构</li>
-                <li>调整成功登录不恢复按钮,防止多次点击</li>
-                <li>修改用户个人资料同步缓存信息</li>
-                <li>修复页面同时出现el-upload和Editor不显示处理</li>
-                <li>修复在角色管理页修改菜单权限偶尔未选中问题</li>
-                <li>配置文件新增redis密码属性</li>
-                <li>设置mybatis全局的配置文件</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-
-            <el-collapse-item title="v2.0.0 - 2019-12-02">
-              <ol>
-                <li>新增代码生成</li>
-                <li>新增@RepeatSubmit注解,防止重复提交</li>
-                <li>新增菜单主目录添加/删除操作</li>
-                <li>日志记录过滤特殊对象,防止转换异常</li>
-                <li>修改代码生成路由脚本错误</li>
-                <li>用户上传头像实时同步缓存,无需重新登录</li>
-                <li>调整切换页签后不重新加载数据</li>
-                <li>添加jsencrypt实现参数的前端加密</li>
-                <li>系统退出删除用户缓存记录</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v1.1.0 - 2019-11-11">
-              <ol>
-                <li>新增在线用户管理</li>
-                <li>新增按钮组功能实现(批量删除、导出、清空)</li>
-                <li>新增查询条件重置按钮</li>
-                <li>新增Swagger全局Token配置</li>
-                <li>新增后端参数校验</li>
-                <li>修复字典管理页面的日期查询异常</li>
-                <li>修改时间函数命名防止冲突</li>
-                <li>去除菜单上级校验,默认为顶级</li>
-                <li>修复用户密码无法修改问题</li>
-                <li>修复菜单类型为按钮时不显示权限标识</li>
-                <li>其他细节优化</li>
-              </ol>
-            </el-collapse-item>
-            <el-collapse-item title="v1.0.0 - 2019-10-08">
-              <ol>
-                <li>北京金水前后端分离系统正式发布</li>
-              </ol>
-            </el-collapse-item>
-          </el-collapse>
-        </el-card>
-      </el-col>
-      <el-col :xs="24" :sm="24" :md="12" :lg="8">
-        <el-card class="update-log">
-          <template v-slot:header>
-            <div class="clearfix">
-              <span>捐赠支持</span>
-            </div>
-          </template>
-          <div class="body">
-            <img
-              src="@/assets/images/pay.png"
-              alt="donate"
-              style="width:100%"
-            />
-            <span style="display: inline-block; height: 30px; line-height: 30px"
-              >你可以请作者喝杯咖啡表示鼓励</span
-            >
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+ 这是首页,版本号:{{ version }}
   </div>
 </template>
 

+ 1 - 3
pom.xml

@@ -5,7 +5,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>com.goldenwater</groupId>
-    <artifactId>goldenwater</artifactId>
+    <artifactId>tba-sbh</artifactId>
     <version>3.9.2</version>
 
     <name>goldenwater</name>
@@ -133,7 +133,6 @@
                 <artifactId>kaptcha</artifactId>
                 <version>${kaptcha.version}</version>
             </dependency>
-
             <!-- 定时任务-->
             <dependency>
                 <groupId>com.goldenwater</groupId>
@@ -161,7 +160,6 @@
                 <artifactId>gw-common</artifactId>
                 <version>${goldenwater.version}</version>
             </dependency>
-
         </dependencies>
     </dependencyManagement>