From bc56530307e0e92b94a1abb5d38368f04b92e990 Mon Sep 17 00:00:00 2001
From: zhang <zc857179121@qq.com>
Date: 星期四, 12 三月 2026 15:52:15 +0800
Subject: [PATCH] 1

---
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java                            |    3 
 zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java                                       |    2 
 zy-acs-hex/dashboard.html                                                                         |  728 +++++++++++---------
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/LoginController.java                           |   38 +
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/RouterController.java                          |    7 
 zy-acs-hex/src/main/webapp/views/index.html                                                       |  706 +++++++++++++++++---
 zy-acs-common/src/main/java/com/zy/acs/common/domain/mq/DeviceMessage.java                        |    2 
 zy-acs-hex/src/main/java/com/zy/acs/hex/enums/ProtocolType.java                                   |  101 ++
 zy-acs-hex/src/main/java/com/zy/acs/hex/utils/HttpGo.java                                         |   60 +
 zy-acs-hex/src/main/java/com/zy/acs/hex/domain/SelectOption.java                                  |   19 
 zy-acs-hex/src/main/java/com/zy/acs/hex/influxdb/task/InfluxDbScheduler.java                      |    2 
 zy-acs-hex/src/main/java/com/zy/acs/hex/domain/DeviceLog.java                                     |   18 
 zy-acs-hex/src/main/webapp/views/login.html                                                       |  148 ++-
 component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java |   19 
 component/component-Influxdb/src/main/java/com/zy/component/influxdb/domain/BaseMessage.java      |   12 
 zy-acs-hex/src/main/resources/application.yml                                                     |    5 
 zy-acs-hex/src/main/java/com/zy/acs/hex/config/WebMvcConfig.java                                  |    9 
 zy-acs-hex/src/main/java/com/zy/acs/hex/domain/GenericQuery.java                                  |   16 
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/ProxyController.java                           |   33 
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/SelectTypeController.java                      |   58 +
 zy-acs-hex/src/main/java/com/zy/acs/hex/enums/DirectionType.java                                  |   22 
 zy-acs-cv/src/main/resources/application.yml                                                      |    8 
 zy-acs-gateway/src/main/java/com/zy/acs/gateway/controller/UtilsController.java                   |   25 
 zy-acs-hex/src/main/java/com/zy/acs/hex/controller/DeviceLogController.java                       |   59 +
 24 files changed, 1,579 insertions(+), 521 deletions(-)

diff --git a/component/component-Influxdb/src/main/java/com/zy/component/influxdb/domain/BaseMessage.java b/component/component-Influxdb/src/main/java/com/zy/component/influxdb/domain/BaseMessage.java
new file mode 100644
index 0000000..ac5431c
--- /dev/null
+++ b/component/component-Influxdb/src/main/java/com/zy/component/influxdb/domain/BaseMessage.java
@@ -0,0 +1,12 @@
+package com.zy.component.influxdb.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class BaseMessage implements Serializable {
+
+    private Long timestamp;
+}
diff --git a/component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java b/component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java
index 14f96b2..924ee65 100644
--- a/component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java
+++ b/component/component-Influxdb/src/main/java/com/zy/component/influxdb/service/InfluxDBService.java
@@ -6,6 +6,7 @@
 import com.influxdb.v3.client.query.QueryOptions;
 import com.influxdb.v3.client.query.QueryType;
 import com.influxdb.v3.client.write.WritePrecision;
+import com.zy.component.influxdb.domain.BaseMessage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +16,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.time.Instant;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -68,17 +70,25 @@
         }
         return null;
     }
-
     /**
      * 鏌ヨ鏁版嵁
      *
      * @param sql sql璇彞
      * @return 鏌ヨ缁撴灉鍒楄〃
      */
-    public <T> List<T> queryPoints(String sql, Class<T> clazz) {
+    public <T  extends BaseMessage> List<T> queryPoints(String sql, Class<T> clazz) {
+       return queryPoints(sql,new HashMap<>(),clazz);
+    }
+    /**
+     * 鏌ヨ鏁版嵁
+     *
+     * @param sql sql璇彞
+     * @return 鏌ヨ缁撴灉鍒楄〃
+     */
+    public <T  extends BaseMessage> List<T> queryPoints(String sql,Map<String,Object> queryParams, Class<T> clazz) {
         try {
             // 鎵ц鏌ヨ
-            Stream<PointValues> queryPoints = influxDBClient.queryPoints(sql);
+            Stream<PointValues> queryPoints = influxDBClient.queryPoints(sql, queryParams);
             Field[] declaredFields = clazz.getDeclaredFields();
                 
             // 鍒涘缓涓�涓垪琛ㄧ敤浜庡瓨鍌ㄧ粨鏋�
@@ -124,10 +134,9 @@
                         }
                     }
                 }
+                newInstance.setTimestamp(point.getTimestamp().longValue());
                 return newInstance;
             }).collect(Collectors.toList());
-                
-            logger.info("鏌ヨ鏁版嵁锛歿}", result);
             return result;
         } catch (Exception e) {
             logger.error("Failed to query data from the database.");
diff --git a/zy-acs-common/src/main/java/com/zy/acs/common/domain/mq/DeviceMessage.java b/zy-acs-common/src/main/java/com/zy/acs/common/domain/mq/DeviceMessage.java
index d45dc7e..c1ab843 100644
--- a/zy-acs-common/src/main/java/com/zy/acs/common/domain/mq/DeviceMessage.java
+++ b/zy-acs-common/src/main/java/com/zy/acs/common/domain/mq/DeviceMessage.java
@@ -9,12 +9,14 @@
 
 @Data
 @AllArgsConstructor
+@NoArgsConstructor
 public class DeviceMessage implements Serializable {
 
     private String sourceHexStr;
 
     private Long timestamp = System.currentTimeMillis();
 
+
     public DeviceMessage(String sourceHexStr) {
         this.sourceHexStr = sourceHexStr;
     }
diff --git a/zy-acs-cv/src/main/resources/application.yml b/zy-acs-cv/src/main/resources/application.yml
index 0a4f054..2199fc9 100644
--- a/zy-acs-cv/src/main/resources/application.yml
+++ b/zy-acs-cv/src/main/resources/application.yml
@@ -35,10 +35,10 @@
         mark: 10
         max-retries: 3
         retry-delay: 800
-      - type: FAKEUSER
-        mark: 20
-        max-retries: 2
-        retry-delay: 800
+#      - type: FAKEUSER
+#        mark: 20
+#        max-retries: 2
+#        retry-delay: 800
       - type: APPLYLOC
         mark: 30
         max-retries: 2
diff --git a/zy-acs-gateway/src/main/java/com/zy/acs/gateway/controller/UtilsController.java b/zy-acs-gateway/src/main/java/com/zy/acs/gateway/controller/UtilsController.java
new file mode 100644
index 0000000..5f5bdf1
--- /dev/null
+++ b/zy-acs-gateway/src/main/java/com/zy/acs/gateway/controller/UtilsController.java
@@ -0,0 +1,25 @@
+package com.zy.acs.gateway.controller;
+
+import com.zy.acs.framework.common.R;
+import com.zy.acs.gateway.utils.PacCoder;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+
+@RestController
+@Slf4j
+@RequestMapping(value = "/utils")
+public class UtilsController {
+
+    /**
+     * 鏌ヨ鏈�鏂扮殑鍗佹潯鏁版嵁
+     *
+     * @return
+     */
+    @RequestMapping(value = "/decode/{hex}")
+    @ResponseBody
+    public R query(@PathVariable String hex) {
+        return R.ok(PacCoder.decode(hex));
+    }
+
+}
diff --git a/zy-acs-hex/dashboard.html b/zy-acs-hex/dashboard.html
index 378c261..3e8001b 100644
--- a/zy-acs-hex/dashboard.html
+++ b/zy-acs-hex/dashboard.html
@@ -19,21 +19,27 @@
             font-family: 'Inter', sans-serif;
             background-color: #f5f7fa;
         }
+
         .layui-card {
             margin-bottom: 16px;
         }
+
         .layui-card-header {
             font-weight: 600;
         }
+
         .status-online {
             color: #10b981;
         }
+
         .status-offline {
             color: #ef4444;
         }
+
         .chart-container {
             height: 300px;
         }
+
         .realtime-container {
             height: 160px;
             overflow-y: auto;
@@ -41,352 +47,422 @@
     </style>
 </head>
 <body>
-    <div id="app">
-        <!-- 椤堕儴瀵艰埅鏍� -->
-        <lay-header height="60px" bg-color="#fff" shadow>
-            <template #left>
-                <div class="flex items-center space-x-2">
-                    <i class="fa fa-android text-2xl" style="color: #3b82f6"></i>
-                    <h1 class="text-xl font-bold" style="color: #1e293b">鏈哄櫒浜烘暟鎹洃鎺�</h1>
-                </div>
-            </template>
-            <template #right>
-                <div class="flex items-center space-x-4">
-                    <lay-input placeholder="鎼滅储鏈哄櫒浜�..." prefix-icon="search" style="width: 200px"></lay-input>
-                    <lay-button type="primary" @click="refreshData">
-                        <i class="fa fa-refresh mr-1"></i> 鍒锋柊
-                    </lay-button>
-                </div>
-            </template>
-        </lay-header>
+<div id="app">
+    <!-- 椤堕儴瀵艰埅鏍� -->
+    <lay-header height="60px" bg-color="#fff" shadow>
+        <template #left>
+            <div class="flex items-center space-x-2">
+                <i class="fa fa-android text-2xl" style="color: #3b82f6"></i>
+                <h1 class="text-xl font-bold" style="color: #1e293b">鏈哄櫒浜烘暟鎹洃鎺�</h1>
+            </div>
+        </template>
+        <template #right>
+            <div class="flex items-center space-x-4">
+                <lay-input placeholder="鎼滅储鏈哄櫒浜�..." prefix-icon="search" style="width: 200px"></lay-input>
+                <lay-button type="primary" @click="refreshData">
+                    <i class="fa fa-refresh mr-1"></i> 鍒锋柊
+                </lay-button>
+            </div>
+        </template>
+    </lay-header>
 
-        <!-- 涓诲唴瀹瑰尯 -->
-        <lay-container style="padding: 20px">
-            <!-- 鐘舵�佹瑙� -->
-            <lay-row :gutter="16">
-                <lay-col :span="6">
-                    <lay-card shadow>
-                        <div class="flex items-center justify-between">
-                            <div>
-                                <p style="color: #64748b; font-size: 14px">鎬绘満鍣ㄤ汉鏁�</p>
-                                <h3 style="font-size: 24px; font-weight: bold; color: #1e293b">24</h3>
-                            </div>
-                            <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #dbeafe; display: flex; align-items: center; justify-content: center">
-                                <i class="fa fa-microchip text-xl" style="color: #3b82f6"></i>
-                            </div>
+    <!-- 涓诲唴瀹瑰尯 -->
+    <lay-container style="padding: 20px">
+        <!-- 鐘舵�佹瑙� -->
+        <lay-row :gutter="16">
+            <lay-col :span="6">
+                <lay-card shadow>
+                    <div class="flex items-center justify-between">
+                        <div>
+                            <p style="color: #64748b; font-size: 14px">鎬绘満鍣ㄤ汉鏁�</p>
+                            <h3 style="font-size: 24px; font-weight: bold; color: #1e293b">24</h3>
                         </div>
-                    </lay-card>
-                </lay-col>
-                <lay-col :span="6">
-                    <lay-card shadow>
-                        <div class="flex items-center justify-between">
-                            <div>
-                                <p style="color: #64748b; font-size: 14px">鍦ㄧ嚎鏈哄櫒浜�</p>
-                                <h3 style="font-size: 24px; font-weight: bold; color: #10b981">18</h3>
-                            </div>
-                            <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #d1fae5; display: flex; align-items: center; justify-content: center">
-                                <i class="fa fa-check-circle text-xl" style="color: #10b981"></i>
-                            </div>
-                        </div>
-                    </lay-card>
-                </lay-col>
-                <lay-col :span="6">
-                    <lay-card shadow>
-                        <div class="flex items-center justify-between">
-                            <div>
-                                <p style="color: #64748b; font-size: 14px">绂荤嚎鏈哄櫒浜�</p>
-                                <h3 style="font-size: 24px; font-weight: bold; color: #ef4444">6</h3>
-                            </div>
-                            <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #fee2e2; display: flex; align-items: center; justify-content: center">
-                                <i class="fa fa-exclamation-circle text-xl" style="color: #ef4444"></i>
-                            </div>
-                        </div>
-                    </lay-card>
-                </lay-col>
-                <lay-col :span="6">
-                    <lay-card shadow>
-                        <div class="flex items-center justify-between">
-                            <div>
-                                <p style="color: #64748b; font-size: 14px">浠婃棩鏁版嵁閲�</p>
-                                <h3 style="font-size: 24px; font-weight: bold; color: #f59e0b">1.2k</h3>
-                            </div>
-                            <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #fef3c7; display: flex; align-items: center; justify-content: center">
-                                <i class="fa fa-database text-xl" style="color: #f59e0b"></i>
-                            </div>
-                        </div>
-                    </lay-card>
-                </lay-col>
-            </lay-row>
-
-            <!-- 鏁版嵁鍥捐〃 -->
-            <lay-row :gutter="16" style="margin-top: 16px">
-                <lay-col :span="12">
-                    <lay-card shadow>
-                        <template #header>
-                            <div class="flex justify-between items-center">
-                                <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">涓婅鏁版嵁瓒嬪娍</h2>
-                                <div class="flex space-x-2">
-                                    <lay-button size="sm" type="primary">灏忔椂</lay-button>
-                                    <lay-button size="sm">澶�</lay-button>
-                                    <lay-button size="sm">鍛�</lay-button>
-                                </div>
-                            </div>
-                        </template>
-                        <div class="chart-container">
-                            <canvas ref="upDataChart"></canvas>
-                        </div>
-                    </lay-card>
-                </lay-col>
-                <lay-col :span="12">
-                    <lay-card shadow>
-                        <template #header>
-                            <div class="flex justify-between items-center">
-                                <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">涓嬭鏁版嵁瓒嬪娍</h2>
-                                <div class="flex space-x-2">
-                                    <lay-button size="sm" type="primary">灏忔椂</lay-button>
-                                    <lay-button size="sm">澶�</lay-button>
-                                    <lay-button size="sm">鍛�</lay-button>
-                                </div>
-                            </div>
-                        </template>
-                        <div class="chart-container">
-                            <canvas ref="downDataChart"></canvas>
-                        </div>
-                    </lay-card>
-                </lay-col>
-            </lay-row>
-
-            <!-- 璁惧鏁版嵁琛ㄦ牸 -->
-            <lay-card shadow style="margin-top: 16px">
-                <template #header>
-                    <div class="flex justify-between items-center">
-                        <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">鏈哄櫒浜烘暟鎹垪琛�</h2>
-                        <div class="flex space-x-2">
-                            <lay-button size="sm">
-                                <i class="fa fa-filter mr-1"></i> 绛涢��
-                            </lay-button>
-                            <lay-button size="sm">
-                                <i class="fa fa-download mr-1"></i> 瀵煎嚭
-                            </lay-button>
+                        <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #dbeafe; display: flex; align-items: center; justify-content: center">
+                            <i class="fa fa-microchip text-xl" style="color: #3b82f6"></i>
                         </div>
                     </div>
-                </template>
-                <lay-table :data="devices" :height="400">
-                    <lay-table-column prop="id" label="璁惧ID" width="120"></lay-table-column>
-                    <lay-table-column prop="name" label="璁惧鍚嶇О" width="150"></lay-table-column>
-                    <lay-table-column prop="status" label="鐘舵��" width="100">
-                        <template #default="{ row }">
-                            <lay-badge v-if="row.status === 'online'" type="success">鍦ㄧ嚎</lay-badge>
-                            <lay-badge v-else type="danger">绂荤嚎</lay-badge>
-                        </template>
-                    </lay-table-column>
-                    <lay-table-column prop="upData" label="涓婅鏁版嵁" width="120"></lay-table-column>
-                    <lay-table-column prop="downData" label="涓嬭鏁版嵁" width="120"></lay-table-column>
-                    <lay-table-column prop="lastComm" label="鏈�鍚庨�氫俊" width="150"></lay-table-column>
-                    <lay-table-column label="鎿嶄綔" width="150">
-                        <template #default="{ row }">
-                            <lay-button size="sm" type="primary" style="margin-right: 8px">
-                                <i class="fa fa-eye"></i>
-                            </lay-button>
-                            <lay-button size="sm" type="warning" style="margin-right: 8px">
-                                <i class="fa fa-edit"></i>
-                            </lay-button>
-                            <lay-button size="sm" type="danger">
-                                <i class="fa fa-trash"></i>
-                            </lay-button>
-                        </template>
-                    </lay-table-column>
-                </lay-table>
-                <div class="flex justify-between items-center mt-4">
-                    <p style="color: #64748b; font-size: 14px">鏄剧ず 1-10 鏉★紝鍏� 24 鏉�</p>
-                    <lay-pagination
+                </lay-card>
+            </lay-col>
+            <lay-col :span="6">
+                <lay-card shadow>
+                    <div class="flex items-center justify-between">
+                        <div>
+                            <p style="color: #64748b; font-size: 14px">鍦ㄧ嚎鏈哄櫒浜�</p>
+                            <h3 style="font-size: 24px; font-weight: bold; color: #10b981">18</h3>
+                        </div>
+                        <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #d1fae5; display: flex; align-items: center; justify-content: center">
+                            <i class="fa fa-check-circle text-xl" style="color: #10b981"></i>
+                        </div>
+                    </div>
+                </lay-card>
+            </lay-col>
+            <lay-col :span="6">
+                <lay-card shadow>
+                    <div class="flex items-center justify-between">
+                        <div>
+                            <p style="color: #64748b; font-size: 14px">绂荤嚎鏈哄櫒浜�</p>
+                            <h3 style="font-size: 24px; font-weight: bold; color: #ef4444">6</h3>
+                        </div>
+                        <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #fee2e2; display: flex; align-items: center; justify-content: center">
+                            <i class="fa fa-exclamation-circle text-xl" style="color: #ef4444"></i>
+                        </div>
+                    </div>
+                </lay-card>
+            </lay-col>
+            <lay-col :span="6">
+                <lay-card shadow>
+                    <div class="flex items-center justify-between">
+                        <div>
+                            <p style="color: #64748b; font-size: 14px">浠婃棩鏁版嵁閲�</p>
+                            <h3 style="font-size: 24px; font-weight: bold; color: #f59e0b">1.2k</h3>
+                        </div>
+                        <div style="width: 48px; height: 48px; border-radius: 50%; background-color: #fef3c7; display: flex; align-items: center; justify-content: center">
+                            <i class="fa fa-database text-xl" style="color: #f59e0b"></i>
+                        </div>
+                    </div>
+                </lay-card>
+            </lay-col>
+        </lay-row>
+
+        <!-- 鏁版嵁鍥捐〃 -->
+        <lay-row :gutter="16" style="margin-top: 16px">
+            <lay-col :span="12">
+                <lay-card shadow>
+                    <template #header>
+                        <div class="flex justify-between items-center">
+                            <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">涓婅鏁版嵁瓒嬪娍</h2>
+                            <div class="flex space-x-2">
+                                <lay-button size="sm" type="primary">灏忔椂</lay-button>
+                                <lay-button size="sm">澶�</lay-button>
+                                <lay-button size="sm">鍛�</lay-button>
+                            </div>
+                        </div>
+                    </template>
+                    <div class="chart-container">
+                        <canvas ref="upDataChart"></canvas>
+                    </div>
+                </lay-card>
+            </lay-col>
+            <lay-col :span="12">
+                <lay-card shadow>
+                    <template #header>
+                        <div class="flex justify-between items-center">
+                            <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">涓嬭鏁版嵁瓒嬪娍</h2>
+                            <div class="flex space-x-2">
+                                <lay-button size="sm" type="primary">灏忔椂</lay-button>
+                                <lay-button size="sm">澶�</lay-button>
+                                <lay-button size="sm">鍛�</lay-button>
+                            </div>
+                        </div>
+                    </template>
+                    <div class="chart-container">
+                        <canvas ref="downDataChart"></canvas>
+                    </div>
+                </lay-card>
+            </lay-col>
+        </lay-row>
+
+        <!-- 璁惧鏁版嵁琛ㄦ牸 -->
+        <lay-card shadow style="margin-top: 16px">
+            <template #header>
+                <div class="flex justify-between items-center">
+                    <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">鏈哄櫒浜烘暟鎹垪琛�</h2>
+                    <div class="flex space-x-2">
+                        <lay-button size="sm">
+                            <i class="fa fa-filter mr-1"></i> 绛涢��
+                        </lay-button>
+                        <lay-button size="sm">
+                            <i class="fa fa-download mr-1"></i> 瀵煎嚭
+                        </lay-button>
+                    </div>
+                </div>
+            </template>
+            <lay-table :data="devices" :height="400">
+                <lay-table-column prop="id" label="璁惧ID" width="120"></lay-table-column>
+                <lay-table-column prop="name" label="璁惧鍚嶇О" width="150"></lay-table-column>
+                <lay-table-column prop="status" label="鐘舵��" width="100">
+                    <template #default="{ row }">
+                        <lay-badge v-if="row.status === 'online'" type="success">鍦ㄧ嚎</lay-badge>
+                        <lay-badge v-else type="danger">绂荤嚎</lay-badge>
+                    </template>
+                </lay-table-column>
+                <lay-table-column prop="upData" label="涓婅鏁版嵁" width="120"></lay-table-column>
+                <lay-table-column prop="downData" label="涓嬭鏁版嵁" width="120"></lay-table-column>
+                <lay-table-column prop="lastComm" label="鏈�鍚庨�氫俊" width="150"></lay-table-column>
+                <lay-table-column label="鎿嶄綔" width="150">
+                    <template #default="{ row }">
+                        <lay-button size="sm" type="primary" style="margin-right: 8px">
+                            <i class="fa fa-eye"></i>
+                        </lay-button>
+                        <lay-button size="sm" type="warning" style="margin-right: 8px">
+                            <i class="fa fa-edit"></i>
+                        </lay-button>
+                        <lay-button size="sm" type="danger">
+                            <i class="fa fa-trash"></i>
+                        </lay-button>
+                    </template>
+                </lay-table-column>
+            </lay-table>
+            <div class="flex justify-between items-center mt-4">
+                <p style="color: #64748b; font-size: 14px">鏄剧ず 1-10 鏉★紝鍏� 24 鏉�</p>
+                <lay-pagination
                         v-model:current="currentPage"
                         v-model:limit="pageSize"
                         :total="total"
                         :limits="[10, 20, 50, 100]"
                         layout="prev, pager, next, jumper, sizes, total"
-                    ></lay-pagination>
-                </div>
-            </lay-card>
-
-            <!-- 瀹炴椂鏁版嵁鏇存柊 -->
-            <lay-card shadow style="margin-top: 16px">
-                <template #header>
-                    <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">瀹炴椂鏁版嵁鏇存柊</h2>
-                </template>
-                <div class="realtime-container p-2 border border-gray-200 rounded-lg">
-                    <div v-for="(item, index) in realtimeData" :key="index" class="py-1 border-b border-gray-100">
-                        <span style="color: #64748b; font-size: 12px">{{ item.timestamp }}</span>
-                        <span style="color: #1e293b; margin-left: 10px">{{ item.message }}</span>
-                    </div>
-                </div>
-            </lay-card>
-        </lay-container>
-
-        <!-- 椤佃剼 -->
-        <lay-footer height="60px" bg-color="#fff" shadow>
-            <div class="text-center" style="color: #64748b; font-size: 14px">
-                漏 2026 鏈哄櫒浜烘暟鎹洃鎺х郴缁� | 鐗堟湰 1.0.0
+                ></lay-pagination>
             </div>
-        </lay-footer>
-    </div>
+        </lay-card>
 
-    <script>
-        const { createApp, ref, onMounted } = Vue;
-        const app = createApp({
-            components: {
-                LayHeader: layui.LayHeader,
-                LayContainer: layui.LayContainer,
-                LayRow: layui.LayRow,
-                LayCol: layui.LayCol,
-                LayCard: layui.LayCard,
-                LayInput: layui.LayInput,
-                LayButton: layui.LayButton,
-                LayTable: layui.LayTable,
-                LayTableColumn: layui.LayTableColumn,
-                LayBadge: layui.LayBadge,
-                LayPagination: layui.LayPagination,
-                LayFooter: layui.LayFooter
-            },
-            setup() {
-                // 妯℃嫙鏈哄櫒浜烘暟鎹�
-                const devices = ref([
-                    { id: 'ROB-001', name: '閰嶉�佹満鍣ㄤ汉1鍙�', status: 'online', upData: '2.4KB', downData: '0.8KB', lastComm: '2鍒嗛挓鍓�' },
-                    { id: 'ROB-002', name: '閰嶉�佹満鍣ㄤ汉2鍙�', status: 'online', upData: '1.8KB', downData: '0.5KB', lastComm: '5鍒嗛挓鍓�' },
-                    { id: 'ROB-003', name: '宸℃鏈哄櫒浜�1鍙�', status: 'offline', upData: '0KB', downData: '0KB', lastComm: '2灏忔椂鍓�' },
-                    { id: 'ROB-004', name: '閰嶉�佹満鍣ㄤ汉3鍙�', status: 'online', upData: '3.2KB', downData: '1.2KB', lastComm: '1鍒嗛挓鍓�' },
-                    { id: 'ROB-005', name: '宸℃鏈哄櫒浜�2鍙�', status: 'online', upData: '1.5KB', downData: '0.6KB', lastComm: '3鍒嗛挓鍓�' },
-                    { id: 'ROB-006', name: '閰嶉�佹満鍣ㄤ汉4鍙�', status: 'offline', upData: '0KB', downData: '0KB', lastComm: '5灏忔椂鍓�' },
-                    { id: 'ROB-007', name: '宸℃鏈哄櫒浜�3鍙�', status: 'online', upData: '2.1KB', downData: '0.9KB', lastComm: '4鍒嗛挓鍓�' },
-                    { id: 'ROB-008', name: '閰嶉�佹満鍣ㄤ汉5鍙�', status: 'online', upData: '2.8KB', downData: '1.1KB', lastComm: '2鍒嗛挓鍓�' },
-                    { id: 'ROB-009', name: '宸℃鏈哄櫒浜�4鍙�', status: 'offline', upData: '0KB', downData: '0KB', lastComm: '1澶╁墠' },
-                    { id: 'ROB-010', name: '閰嶉�佹満鍣ㄤ汉6鍙�', status: 'online', upData: '1.9KB', downData: '0.7KB', lastComm: '6鍒嗛挓鍓�' }
-                ]);
+        <!-- 瀹炴椂鏁版嵁鏇存柊 -->
+        <lay-card shadow style="margin-top: 16px">
+            <template #header>
+                <h2 style="font-size: 16px; font-weight: 600; color: #1e293b">瀹炴椂鏁版嵁鏇存柊</h2>
+            </template>
+            <div class="realtime-container p-2 border border-gray-200 rounded-lg">
+                <div v-for="(item, index) in realtimeData" :key="index" class="py-1 border-b border-gray-100">
+                    <span style="color: #64748b; font-size: 12px">{{ item.timestamp }}</span>
+                    <span style="color: #1e293b; margin-left: 10px">{{ item.message }}</span>
+                </div>
+            </div>
+        </lay-card>
+    </lay-container>
 
-                // 鍒嗛〉鏁版嵁
-                const currentPage = ref(1);
-                const pageSize = ref(10);
-                const total = ref(24);
+    <!-- 椤佃剼 -->
+    <lay-footer height="60px" bg-color="#fff" shadow>
+        <div class="text-center" style="color: #64748b; font-size: 14px">
+            漏 2026 鏈哄櫒浜烘暟鎹洃鎺х郴缁� | 鐗堟湰 1.0.0
+        </div>
+    </lay-footer>
+</div>
 
-                // 瀹炴椂鏁版嵁
-                const realtimeData = ref([]);
+<script>
+    const {createApp, ref, onMounted} = Vue;
+    const app = createApp({
+        components: {
+            LayHeader: layui.LayHeader,
+            LayContainer: layui.LayContainer,
+            LayRow: layui.LayRow,
+            LayCol: layui.LayCol,
+            LayCard: layui.LayCard,
+            LayInput: layui.LayInput,
+            LayButton: layui.LayButton,
+            LayTable: layui.LayTable,
+            LayTableColumn: layui.LayTableColumn,
+            LayBadge: layui.LayBadge,
+            LayPagination: layui.LayPagination,
+            LayFooter: layui.LayFooter
+        },
+        setup() {
+            // 妯℃嫙鏈哄櫒浜烘暟鎹�
+            const devices = ref([
+                {
+                    id: 'ROB-001',
+                    name: '閰嶉�佹満鍣ㄤ汉1鍙�',
+                    status: 'online',
+                    upData: '2.4KB',
+                    downData: '0.8KB',
+                    lastComm: '2鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-002',
+                    name: '閰嶉�佹満鍣ㄤ汉2鍙�',
+                    status: 'online',
+                    upData: '1.8KB',
+                    downData: '0.5KB',
+                    lastComm: '5鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-003',
+                    name: '宸℃鏈哄櫒浜�1鍙�',
+                    status: 'offline',
+                    upData: '0KB',
+                    downData: '0KB',
+                    lastComm: '2灏忔椂鍓�'
+                },
+                {
+                    id: 'ROB-004',
+                    name: '閰嶉�佹満鍣ㄤ汉3鍙�',
+                    status: 'online',
+                    upData: '3.2KB',
+                    downData: '1.2KB',
+                    lastComm: '1鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-005',
+                    name: '宸℃鏈哄櫒浜�2鍙�',
+                    status: 'online',
+                    upData: '1.5KB',
+                    downData: '0.6KB',
+                    lastComm: '3鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-006',
+                    name: '閰嶉�佹満鍣ㄤ汉4鍙�',
+                    status: 'offline',
+                    upData: '0KB',
+                    downData: '0KB',
+                    lastComm: '5灏忔椂鍓�'
+                },
+                {
+                    id: 'ROB-007',
+                    name: '宸℃鏈哄櫒浜�3鍙�',
+                    status: 'online',
+                    upData: '2.1KB',
+                    downData: '0.9KB',
+                    lastComm: '4鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-008',
+                    name: '閰嶉�佹満鍣ㄤ汉5鍙�',
+                    status: 'online',
+                    upData: '2.8KB',
+                    downData: '1.1KB',
+                    lastComm: '2鍒嗛挓鍓�'
+                },
+                {
+                    id: 'ROB-009',
+                    name: '宸℃鏈哄櫒浜�4鍙�',
+                    status: 'offline',
+                    upData: '0KB',
+                    downData: '0KB',
+                    lastComm: '1澶╁墠'
+                },
+                {
+                    id: 'ROB-010',
+                    name: '閰嶉�佹満鍣ㄤ汉6鍙�',
+                    status: 'online',
+                    upData: '1.9KB',
+                    downData: '0.7KB',
+                    lastComm: '6鍒嗛挓鍓�'
+                }
+            ]);
 
-                // 鍥捐〃寮曠敤
-                const upDataChart = ref(null);
-                const downDataChart = ref(null);
+            // 鍒嗛〉鏁版嵁
+            const currentPage = ref(1);
+            const pageSize = ref(10);
+            const total = ref(24);
 
-                // 鍒锋柊鏁版嵁
-                const refreshData = () => {
-                    console.log('鍒锋柊鏁版嵁');
-                    // 杩欓噷鍙互娣诲姞瀹為檯鐨勫埛鏂伴�昏緫
-                };
+            // 瀹炴椂鏁版嵁
+            const realtimeData = ref([]);
 
-                // 鍒濆鍖栧浘琛�
-                const initCharts = () => {
-                    // 涓婅鏁版嵁鍥捐〃
-                    const upCtx = upDataChart.value.getContext('2d');
-                    new Chart(upCtx, {
-                        type: 'line',
-                        data: {
-                            labels: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
-                            datasets: [{
-                                label: '涓婅鏁版嵁 (KB)',
-                                data: [12, 19, 15, 25, 22, 30, 28, 35],
-                                borderColor: '#3b82f6',
-                                backgroundColor: 'rgba(59, 130, 246, 0.1)',
-                                tension: 0.4,
-                                fill: true
-                            }]
+            // 鍥捐〃寮曠敤
+            const upDataChart = ref(null);
+            const downDataChart = ref(null);
+
+            // 鍒锋柊鏁版嵁
+            const refreshData = () => {
+                console.log('鍒锋柊鏁版嵁');
+                // 杩欓噷鍙互娣诲姞瀹為檯鐨勫埛鏂伴�昏緫
+            };
+
+            // 鍒濆鍖栧浘琛�
+            const initCharts = () => {
+                // 涓婅鏁版嵁鍥捐〃
+                const upCtx = upDataChart.value.getContext('2d');
+                new Chart(upCtx, {
+                    type: 'line',
+                    data: {
+                        labels: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
+                        datasets: [{
+                            label: '涓婅鏁版嵁 (KB)',
+                            data: [12, 19, 15, 25, 22, 30, 28, 35],
+                            borderColor: '#3b82f6',
+                            backgroundColor: 'rgba(59, 130, 246, 0.1)',
+                            tension: 0.4,
+                            fill: true
+                        }]
+                    },
+                    options: {
+                        responsive: true,
+                        maintainAspectRatio: false,
+                        plugins: {
+                            legend: {
+                                display: false
+                            }
                         },
-                        options: {
-                            responsive: true,
-                            maintainAspectRatio: false,
-                            plugins: {
-                                legend: {
-                                    display: false
-                                }
-                            },
-                            scales: {
-                                y: {
-                                    beginAtZero: true
-                                }
+                        scales: {
+                            y: {
+                                beginAtZero: true
                             }
                         }
-                    });
-
-                    // 涓嬭鏁版嵁鍥捐〃
-                    const downCtx = downDataChart.value.getContext('2d');
-                    new Chart(downCtx, {
-                        type: 'line',
-                        data: {
-                            labels: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
-                            datasets: [{
-                                label: '涓嬭鏁版嵁 (KB)',
-                                data: [5, 8, 6, 12, 10, 15, 13, 18],
-                                borderColor: '#10b981',
-                                backgroundColor: 'rgba(16, 185, 129, 0.1)',
-                                tension: 0.4,
-                                fill: true
-                            }]
-                        },
-                        options: {
-                            responsive: true,
-                            maintainAspectRatio: false,
-                            plugins: {
-                                legend: {
-                                    display: false
-                                }
-                            },
-                            scales: {
-                                y: {
-                                    beginAtZero: true
-                                }
-                            }
-                        }
-                    });
-                };
-
-                // 妯℃嫙瀹炴椂鏁版嵁鏇存柊
-                const simulateRealtimeData = () => {
-                    const messages = [
-                        'ROB-001 閰嶉�佹満鍣ㄤ汉1鍙�: 杩愯涓紝浣嶇疆: A1鍖�',
-                        'ROB-002 閰嶉�佹満鍣ㄤ汉2鍙�: 寰呮満涓紝浣嶇疆: B2鍖�',
-                        'ROB-004 閰嶉�佹満鍣ㄤ汉3鍙�: 鍏呯數涓紝鐢甸噺: 85%',
-                        'ROB-005 宸℃鏈哄櫒浜�2鍙�: 宸℃涓紝宸插畬鎴�3/5浠诲姟',
-                        'ROB-007 宸℃鏈哄櫒浜�3鍙�: 寰呮満涓紝浣嶇疆: C3鍖�',
-                        'ROB-008 閰嶉�佹満鍣ㄤ汉5鍙�: 杩愯涓紝浣嶇疆: D4鍖�'
-                    ];
-
-                    setInterval(() => {
-                        const message = messages[Math.floor(Math.random() * messages.length)];
-                        const timestamp = new Date().toLocaleTimeString();
-                        realtimeData.value.unshift({ timestamp, message });
-                        // 闄愬埗鏄剧ず鏉℃暟
-                        if (realtimeData.value.length > 20) {
-                            realtimeData.value.pop();
-                        }
-                    }, 2000);
-                };
-
-                // 椤甸潰鍔犺浇瀹屾垚鍚庡垵濮嬪寲
-                onMounted(() => {
-                    initCharts();
-                    simulateRealtimeData();
+                    }
                 });
 
-                return {
-                    devices,
-                    currentPage,
-                    pageSize,
-                    total,
-                    realtimeData,
-                    upDataChart,
-                    downDataChart,
-                    refreshData
-                };
-            }
-        });
-        app.mount('#app');
-    </script>
+                // 涓嬭鏁版嵁鍥捐〃
+                const downCtx = downDataChart.value.getContext('2d');
+                new Chart(downCtx, {
+                    type: 'line',
+                    data: {
+                        labels: ['00:00', '03:00', '06:00', '09:00', '12:00', '15:00', '18:00', '21:00'],
+                        datasets: [{
+                            label: '涓嬭鏁版嵁 (KB)',
+                            data: [5, 8, 6, 12, 10, 15, 13, 18],
+                            borderColor: '#10b981',
+                            backgroundColor: 'rgba(16, 185, 129, 0.1)',
+                            tension: 0.4,
+                            fill: true
+                        }]
+                    },
+                    options: {
+                        responsive: true,
+                        maintainAspectRatio: false,
+                        plugins: {
+                            legend: {
+                                display: false
+                            }
+                        },
+                        scales: {
+                            y: {
+                                beginAtZero: true
+                            }
+                        }
+                    }
+                });
+            };
+
+            // 妯℃嫙瀹炴椂鏁版嵁鏇存柊
+            const simulateRealtimeData = () => {
+                const messages = [
+                    'ROB-001 閰嶉�佹満鍣ㄤ汉1鍙�: 杩愯涓紝浣嶇疆: A1鍖�',
+                    'ROB-002 閰嶉�佹満鍣ㄤ汉2鍙�: 寰呮満涓紝浣嶇疆: B2鍖�',
+                    'ROB-004 閰嶉�佹満鍣ㄤ汉3鍙�: 鍏呯數涓紝鐢甸噺: 85%',
+                    'ROB-005 宸℃鏈哄櫒浜�2鍙�: 宸℃涓紝宸插畬鎴�3/5浠诲姟',
+                    'ROB-007 宸℃鏈哄櫒浜�3鍙�: 寰呮満涓紝浣嶇疆: C3鍖�',
+                    'ROB-008 閰嶉�佹満鍣ㄤ汉5鍙�: 杩愯涓紝浣嶇疆: D4鍖�'
+                ];
+
+                setInterval(() => {
+                    const message = messages[Math.floor(Math.random() * messages.length)];
+                    const timestamp = new Date().toLocaleTimeString();
+                    realtimeData.value.unshift({timestamp, message});
+                    // 闄愬埗鏄剧ず鏉℃暟
+                    if (realtimeData.value.length > 20) {
+                        realtimeData.value.pop();
+                    }
+                }, 2000);
+            };
+
+            // 椤甸潰鍔犺浇瀹屾垚鍚庡垵濮嬪寲
+            onMounted(() => {
+                initCharts();
+                simulateRealtimeData();
+            });
+
+            return {
+                devices,
+                currentPage,
+                pageSize,
+                total,
+                realtimeData,
+                upDataChart,
+                downDataChart,
+                refreshData
+            };
+        }
+    });
+    app.mount('#app');
+</script>
 </body>
 </html>
\ No newline at end of file
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/config/WebMvcConfig.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/config/WebMvcConfig.java
index 5cb4541..ff35e3d 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/config/WebMvcConfig.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/config/WebMvcConfig.java
@@ -3,7 +3,6 @@
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.AsyncHandlerInterceptor;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -36,28 +35,28 @@
 
     @Bean
     public AsyncHandlerInterceptor getAsyncHandlerInterceptor() {
-        return new AsyncHandlerInterceptor(){
+        return new AsyncHandlerInterceptor() {
             @Override
             public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-               cors(response);
+                cors(response);
                 return true;
             }
         };
     }
 
 
-
     @Override
     public void addResourceHandlers(ResourceHandlerRegistry registry) {
         // 閰嶇疆闈欐�佽祫婧愬鐞嗗櫒
         registry.addResourceHandler("/static/**")
+                .addResourceLocations("classpath:/static/")
                 .addResourceLocations("/static/");
         // 閰嶇疆瑙嗗浘鏂囦欢澶勭悊鍣�
         registry.addResourceHandler("/views/**")
                 .addResourceLocations("/views/");
     }
 
-    public static void cors(HttpServletResponse response){
+    public static void cors(HttpServletResponse response) {
         // 璺ㄥ煙璁剧疆
         response.setHeader("Access-Control-Max-Age", "3600");
         response.setHeader("Access-Control-Allow-Origin", "*");
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/DeviceLogController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/DeviceLogController.java
index 047b845..8a8e6b2 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/DeviceLogController.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/DeviceLogController.java
@@ -1,16 +1,20 @@
 package com.zy.acs.hex.controller;
 
-import com.zy.acs.common.domain.mq.DeviceMessage;
+import com.influxdb.v3.client.PointValues;
 import com.zy.acs.framework.common.R;
+import com.zy.acs.hex.domain.DeviceLog;
 import com.zy.component.influxdb.service.InfluxDBService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.bind.annotation.*;
 
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
 @RestController
 @Slf4j
@@ -28,10 +32,49 @@
      */
     @GetMapping(value = "/query")
     @ResponseBody
-    public R query() {
-        List<DeviceMessage> deviceMessages = influxDBService.queryPoints("select * from device order by time desc limit 10", DeviceMessage.class);
-        return R.ok(deviceMessages);
+    public R query(@RequestParam(required = false, defaultValue = "device") String measurement,
+                   @RequestParam(required = false) Map<String, Object> conditions,
+                   @RequestParam(required = false, defaultValue = "100") Integer limit,
+                   @RequestParam(required = false, defaultValue = "time") String orderBy,
+                   @RequestParam(required = false, defaultValue = "DESC") String orderDirection) {
+        return R.ok(getData(measurement, conditions, limit, orderBy, orderDirection));
     }
 
 
+    /**
+     * 閫氱敤鏌ヨ鏂规硶锛屾敮鎸佸姩鎬佹潯浠�
+     */
+    private List<DeviceLog> getData(String measurement, Map<String, Object> conditions,int limit, String orderBy, String orderDirection) {
+        // 鏋勫缓鏌ヨ璇彞
+        StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM ").append(measurement).append(" WHERE 1=1");
+        Map<String, Object> params = new HashMap<>();
+
+        // 鍔ㄦ�佹坊鍔犳潯浠�
+        if (conditions != null && !conditions.isEmpty()) {
+            if (conditions.get("startTime") != null) {
+                if (conditions.get("startTime") != null) {
+                    sqlBuilder.append(" AND ").append("time").append(" >= :").append("startTime");
+                    params.put("startTime", conditions.get("startTime"));
+                }
+            }else if (conditions.get("endTime") != null) {
+                if (conditions.get("endTime") != null) {
+                    sqlBuilder.append(" AND ").append("time").append(" <= :").append("endTime");
+                    params.put("endTime", conditions.get("endTime"));
+                }
+            }else {
+                conditions.forEach((key, value) -> {
+                    if (value != null) {
+                        sqlBuilder.append(" AND ").append(key).append(" = :").append(key);
+                        params.put(key, value);
+                    }
+                });
+            }
+        }
+        // 娣诲姞鎺掑簭鍜岄檺鍒�
+        sqlBuilder.append(" ORDER BY ").append(orderBy).append(" ").append(orderDirection);
+        sqlBuilder.append(" LIMIT :limit");
+        params.put("limit", limit);
+        return influxDBService.queryPoints(sqlBuilder.toString(),params, DeviceLog.class);
+    }
+
 }
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/LoginController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/LoginController.java
new file mode 100644
index 0000000..6b15004
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/LoginController.java
@@ -0,0 +1,38 @@
+package com.zy.acs.hex.controller;
+
+import com.zy.acs.framework.common.R;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 鐧诲綍鎺у埗鍣�
+ */
+@RestController
+@RequestMapping(value = "/login")
+public class LoginController {
+
+    @Value("${login.username}")
+    private String username;
+
+    @Value("${login.password}")
+    private String password;
+
+    /**
+     * 鐧诲綍鎺ュ彛
+     *
+     * @param user 鐢ㄦ埛鍚�
+     * @param pass 瀵嗙爜
+     * @return 鐧诲綍缁撴灉
+     */
+    @PostMapping(value = "/auth")
+    public R login(@RequestParam String user, @RequestParam String pass) {
+        if (username.equals(user) && password.equals(pass)) {
+            return R.ok("鐧诲綍鎴愬姛");
+        } else {
+            return R.error("鐢ㄦ埛鍚嶆垨瀵嗙爜閿欒");
+        }
+    }
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/ProxyController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/ProxyController.java
new file mode 100644
index 0000000..0730ecf
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/ProxyController.java
@@ -0,0 +1,33 @@
+package com.zy.acs.hex.controller;
+
+import com.zy.acs.framework.common.R;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+@RestController
+@RequestMapping(value = "/proxy")
+public class ProxyController {
+
+    private final RestTemplate restTemplate = new RestTemplate();
+
+    @GetMapping(value = "/decode")
+    public R decode(@RequestParam String hexData) {
+        try {
+            String url = "http://127.0.0.1:9060/utils/decode/" + hexData;
+            HttpHeaders headers = new HttpHeaders();
+            headers.set("Content-Type", "application/json");
+            HttpEntity<String> entity = new HttpEntity<>(headers);
+            ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.GET, entity, Object.class);
+            return R.ok(response.getBody());
+        } catch (Exception e) {
+            return R.error("瑙f瀽澶辫触: " + e.getMessage());
+        }
+    }
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/RouterController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/RouterController.java
index 9fcbbc2..9d931ac 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/RouterController.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/RouterController.java
@@ -1,6 +1,5 @@
 package com.zy.acs.hex.controller;
 
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -13,12 +12,10 @@
 public class RouterController {
 
 
-
-
     @RequestMapping("/")
     public void index(HttpServletResponse response) {
         try {
-            response.sendRedirect(  "/views/index.html");
+            response.sendRedirect("/views/index.html");
         } catch (Exception ex) {
             ex.printStackTrace();
         }
@@ -27,7 +24,7 @@
     @RequestMapping("/login")
     public void login(HttpServletResponse response) {
         try {
-            response.sendRedirect(  "/views/login.html");
+            response.sendRedirect("/views/login.html");
         } catch (Exception ex) {
             ex.printStackTrace();
         }
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/SelectTypeController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/SelectTypeController.java
new file mode 100644
index 0000000..bd954a1
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/SelectTypeController.java
@@ -0,0 +1,58 @@
+package com.zy.acs.hex.controller;
+
+import com.zy.acs.framework.common.R;
+import com.zy.acs.hex.domain.SelectOption;
+import com.zy.acs.hex.enums.DirectionType;
+import com.zy.acs.hex.enums.ProtocolType;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@RestController
+@Slf4j
+@RequestMapping(value = "/deviceLog")
+public class SelectTypeController {
+
+
+    /**
+     * 鏌ヨ娑堟伅绫诲瀷
+     *
+     * @return
+     */
+    @GetMapping(value = "/queryType")
+    @ResponseBody
+    public R queryType() {
+        DirectionType[] values = DirectionType.values();
+        List<SelectOption> messageTypes = new ArrayList<>();
+        for (DirectionType value : values) {
+            messageTypes.add(new SelectOption(value.getText(), value.name().toLowerCase()));
+        }
+        return R.ok(messageTypes);
+    }
+
+    /**
+     * 鏌ヨ鏍囩绫诲瀷
+     *
+     * @return
+     */
+    @GetMapping(value = "/queryEvent")
+    @ResponseBody
+    public R queryEvent(@RequestParam(required = false) DirectionType directionType) {
+        List<SelectOption> messageTypes = new ArrayList<>();
+        if (directionType == null) {
+            ProtocolType[] values = ProtocolType.values();
+            for (ProtocolType value : values) {
+                messageTypes.add(new SelectOption(value.name(), value.getDirection().getText() + "-" + value.getDes() + value.name()));
+            }
+            return R.ok(messageTypes);
+        }
+        List<ProtocolType> protocolTypes = ProtocolType.listByDirectionType(directionType);
+        for (ProtocolType value : protocolTypes) {
+            messageTypes.add(new SelectOption(value.name(), value.getDirection().getText() + "-" + value.getDes() + value.name()));
+        }
+        return R.ok(messageTypes);
+    }
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java
index ba77e21..37c4386 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/controller/TestController.java
@@ -2,6 +2,7 @@
 
 import com.zy.acs.common.domain.mq.DeviceMessage;
 import com.zy.acs.hex.constant.RabbitConstant;
+import com.zy.acs.hex.domain.DeviceLog;
 import com.zy.component.influxdb.service.InfluxDBService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.amqp.rabbit.core.RabbitTemplate;
@@ -68,7 +69,7 @@
     @GetMapping(value = "/query2")
     @ResponseBody
     public Object queryTest2() {
-        return influxDBService.queryPoints("select * from device order by time desc limit 10", DeviceMessage.class);
+        return influxDBService.queryPoints("select * from device order by time desc limit 10", DeviceLog.class);
     }
 
 }
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/DeviceLog.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/DeviceLog.java
new file mode 100644
index 0000000..bfd76fc
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/DeviceLog.java
@@ -0,0 +1,18 @@
+package com.zy.acs.hex.domain;
+
+import com.zy.component.influxdb.domain.BaseMessage;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DeviceLog extends BaseMessage implements Serializable {
+
+    private String deviceId;
+
+    private String event;
+
+    private String type;
+
+    private String sourceHexStr;
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/GenericQuery.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/GenericQuery.java
new file mode 100644
index 0000000..6fb4f5d
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/GenericQuery.java
@@ -0,0 +1,16 @@
+package com.zy.acs.hex.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+public class GenericQuery implements Serializable {
+
+        private Map<String, Object> conditions = new HashMap<>(); // 鍔ㄦ�佹煡璇㈡潯浠�
+        private int limit = 100; // 榛樿杩斿洖100鏉�
+        private String orderBy = "time"; // 榛樿鎸夋椂闂存帓搴�
+        private String orderDirection = "DESC"; // 榛樿闄嶅簭
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/SelectOption.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/SelectOption.java
new file mode 100644
index 0000000..d679807
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/domain/SelectOption.java
@@ -0,0 +1,19 @@
+package com.zy.acs.hex.domain;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class SelectOption implements Serializable {
+    private String value;
+    private String label;
+
+    public SelectOption() {
+    }
+
+    public SelectOption(String value, String label) {
+        this.value = value;
+        this.label = label;
+    }
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/DirectionType.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/DirectionType.java
new file mode 100644
index 0000000..bcc1c7a
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/DirectionType.java
@@ -0,0 +1,22 @@
+package com.zy.acs.hex.enums;
+
+public enum DirectionType {
+
+    DOWN("涓嬭"),
+    UP("涓婅"),
+    ;
+
+    private String text;
+
+    DirectionType(String text) {
+        this.text = text;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/ProtocolType.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/ProtocolType.java
new file mode 100644
index 0000000..cb5c9fd
--- /dev/null
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/enums/ProtocolType.java
@@ -0,0 +1,101 @@
+package com.zy.acs.hex.enums;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鏍囪瘑鏋氫妇
+ * Created by vincent on 2019-04-02
+ */
+public enum ProtocolType {
+
+    // 涓嬭 -------------------------------------------------------------------
+
+    PATH_COMMAND(0x01, "璺緞鏁版嵁鍖�", DirectionType.DOWN),
+
+    PICK_PLACE_ACK(0x06, "鍙栨斁璐у簲绛斿寘", DirectionType.DOWN),
+
+    ACTION_COMMAND(0x02, "鍔ㄤ綔鍛戒护鍖�", DirectionType.DOWN),
+
+    HEARTBEAT_COMMAND(0x03, "蹇冭烦鍖�", DirectionType.DOWN),
+
+    FAULT_CLEAR_COMMAND(0x04, "鏁呴殰鍛戒护鍖�", DirectionType.DOWN),
+
+    ACTIVATION_COMMAND(0x80, "婵�娲诲寘", DirectionType.DOWN),
+
+    LOGIN_ACK(0xF0, "鐧诲綍搴旂瓟鍖�", DirectionType.DOWN),
+
+    ACTION_SUCCESS_ACK(0xA1, "鍔ㄤ綔瀹屾垚鎴愬姛搴旂瓟", DirectionType.DOWN),
+
+    ACTION_FAIL_ACK(0xA0, "鍔ㄤ綔瀹屾垚澶辫触搴旂瓟", DirectionType.DOWN),
+
+    PATH_ACK_RESPONSE(0xB1, "璺緞鏁版嵁鍖呭洖澶峚ck", DirectionType.DOWN),
+
+    // 涓婅 -------------------------------------------------------------------
+
+    PATH_ACK(0x01, "璺緞搴旂瓟鍖�", DirectionType.UP),
+
+    PICK_PLACE_REQUEST(0x06, "鍙栨斁璐ц姹傚寘", DirectionType.UP),
+
+    COMMAND_ACK(0x02, "鍛戒护搴旂瓟鍖�", DirectionType.UP),
+
+    ACTION_COMPLETE(0x11, "鍔ㄤ綔瀹屾垚鍖�", DirectionType.UP),
+
+    DATA_CODE_REPORT(0x12, "鏈夌爜瀹炴椂鏁版嵁鍖�", DirectionType.UP),
+
+    DATA_WITHOUT_CODE_REPORT(0x13, "鏃犵爜瀹炴椂鏁版嵁鍖�", DirectionType.UP),
+
+    HEARTBEAT_REPORT(0x03, "蹇冭烦鍖�", DirectionType.UP),
+
+    FAULT_REPORT(0x04, "鏁呴殰鏁版嵁鍖�", DirectionType.UP),
+
+    HANDLE_FALUT_ACK(0x14, "鏁呴殰娓呴櫎搴旂瓟鍖�", DirectionType.UP),
+
+    SILO_REPORT(0x70, "鏂欎粨淇℃伅鍖�", DirectionType.UP),
+
+    LOGIN_REPORT(0xF0, "鏈哄櫒浜虹櫥闄嗘暟鎹寘", DirectionType.UP),
+
+    ;
+
+    private final int code;   // 缂栫爜
+    private final String des; // 鎻忚堪
+    private final DirectionType direction;
+
+    ProtocolType(int code, String des, DirectionType direction) {
+        this.code = code;
+        this.des = des;
+        this.direction = direction;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDes() {
+        return des;
+    }
+
+    public DirectionType getDirection() {
+        return direction;
+    }
+
+    public static List<ProtocolType> listByDirectionType(DirectionType direction) {
+        List<ProtocolType> protocolTypes = new ArrayList<ProtocolType>();
+        for (ProtocolType type : ProtocolType.values()) {
+            if (type.getDirection() == direction) {
+                protocolTypes.add(type);
+            }
+        }
+        return protocolTypes;
+    }
+
+    public static ProtocolType getByCode(int code, DirectionType direction) {
+        for (ProtocolType type : ProtocolType.values()) {
+            if (type.getCode() == code && type.getDirection() == direction) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/influxdb/task/InfluxDbScheduler.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/influxdb/task/InfluxDbScheduler.java
index 903e203..807069a 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/influxdb/task/InfluxDbScheduler.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/influxdb/task/InfluxDbScheduler.java
@@ -61,7 +61,7 @@
                 parames.put("retention-period", retentionPeriod);
                 HttpGo.HttpResponse postResponse = this.http.postJson(createDatabaseUrl, headers, JSON.toJSONString(parames));
                 log.info("鏄惁鍒涘缓鏁版嵁搴擄細{}", postResponse);
-            }else {
+            } else {
                 log.info("鏁版嵁搴擄細{}", response.body());
             }
         } catch (IOException e) {
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/HttpGo.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/HttpGo.java
index a0d27f5..9fce2c9 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/HttpGo.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/HttpGo.java
@@ -18,7 +18,7 @@
 
 /**
  * Minimal OkHttp wrapper: GET / POST only.
- *
+ * <p>
  * - fluent API (get / postJson / postForm)
  * - default singleton instance (thread-safe)
  * - per-request headers + default headers
@@ -41,7 +41,9 @@
                 : Collections.unmodifiableMap(new LinkedHashMap<>(defaultHeaders));
     }
 
-    /** Shared default instance (safe SSL by default). */
+    /**
+     * Shared default instance (safe SSL by default).
+     */
     public static HttpGo defaults() {
         return Holder.DEFAULT;
     }
@@ -78,12 +80,16 @@
 
     // ===================== POST =====================
 
-    /** POST JSON string payload (null/blank -> "{}"). */
+    /**
+     * POST JSON string payload (null/blank -> "{}").
+     */
     public HttpResponse postJson(String url, String json) throws IOException {
         return postJson(url, null, json);
     }
 
-    /** POST JSON string payload (null/blank -> "{}"). */
+    /**
+     * POST JSON string payload (null/blank -> "{}").
+     */
     public HttpResponse postJson(String url, Map<String, String> headers, String json) throws IOException {
         String payload = (json == null || json.trim().isEmpty()) ? "{}" : json;
         RequestBody body = RequestBody.create(payload, JSON);
@@ -99,12 +105,16 @@
         return execute(rb.build());
     }
 
-    /** POST x-www-form-urlencoded fields. */
+    /**
+     * POST x-www-form-urlencoded fields.
+     */
     public HttpResponse postForm(String url, Map<String, String> formFields) throws IOException {
         return postForm(url, null, formFields);
     }
 
-    /** POST x-www-form-urlencoded fields. */
+    /**
+     * POST x-www-form-urlencoded fields.
+     */
     public HttpResponse postForm(String url, Map<String, String> headers, Map<String, String> formFields) throws IOException {
         FormBody.Builder fb = new FormBody.Builder(DEFAULT_CHARSET);
         if (formFields != null) {
@@ -169,10 +179,21 @@
             this.tookMs = tookMs;
         }
 
-        public int statusCode() { return statusCode; }
-        public Headers headers() { return headers; }
-        public String body() { return body; }
-        public long tookMs() { return tookMs; }
+        public int statusCode() {
+            return statusCode;
+        }
+
+        public Headers headers() {
+            return headers;
+        }
+
+        public String body() {
+            return body;
+        }
+
+        public long tookMs() {
+            return tookMs;
+        }
 
         public boolean is2xx() {
             return statusCode >= 200 && statusCode < 300;
@@ -219,7 +240,9 @@
             return this;
         }
 
-        /** Trust ALL certificates. ONLY for internal testing/self-signed endpoints. */
+        /**
+         * Trust ALL certificates. ONLY for internal testing/self-signed endpoints.
+         */
         public Builder trustAllSsl(boolean enable) {
             this.trustAllSsl = enable;
             return this;
@@ -250,9 +273,18 @@
         TrustAll() {
             try {
                 this.trustManager = new X509TrustManager() {
-                    @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { }
-                    @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { }
-                    @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
+                    @Override
+                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
+                    }
+
+                    @Override
+                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
+                    }
+
+                    @Override
+                    public X509Certificate[] getAcceptedIssuers() {
+                        return new X509Certificate[0];
+                    }
                 };
 
                 SSLContext sslContext = SSLContext.getInstance("TLS");
diff --git a/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java b/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java
index 48e614b..89ab200 100644
--- a/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java
+++ b/zy-acs-hex/src/main/java/com/zy/acs/hex/utils/StrUtils.java
@@ -16,7 +16,7 @@
         String[] parts = routingKey.split("\\.");
         if (parts.length == 4) {
             Map<String, String> data = new HashMap<>();
-            data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_TYPE, parts[1]);
+            data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_TYPE, parts[1].toUpperCase());
             data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_DEVICEID, parts[2]);
             data.put(InfluxDBConstant.DEVICE_MEASUREMENT_TAG_EVENT, parts[3]);
             return data;
diff --git a/zy-acs-hex/src/main/resources/application.yml b/zy-acs-hex/src/main/resources/application.yml
index 6901000..8e935c9 100644
--- a/zy-acs-hex/src/main/resources/application.yml
+++ b/zy-acs-hex/src/main/resources/application.yml
@@ -33,3 +33,8 @@
   #token: apiv3_116RKycNhxbf62Nys4zthC05aRD-aidzhEpEpLtsFuedhJTaCtVklNrzHs9LHxBWMuzDclBHVgToGoQuWGiIIA
   retention-period: 30d
   createDatabaseUrl: ${influxdb3.url}/api/v3/configure/database
+
+# 鐧诲綍閰嶇疆
+login:
+  username: admin
+  password: admin123
diff --git a/zy-acs-hex/src/main/webapp/views/index.html b/zy-acs-hex/src/main/webapp/views/index.html
index 63acba4..47f972d 100644
--- a/zy-acs-hex/src/main/webapp/views/index.html
+++ b/zy-acs-hex/src/main/webapp/views/index.html
@@ -10,156 +10,650 @@
             padding: 0;
             box-sizing: border-box;
         }
+
         body {
-            font-family: Arial, sans-serif;
-            background-color: #f0f2f5;
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+            background-color: #f5f7fa;
+            color: #333;
         }
+
         .header {
-            background-color: #1890ff;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
             color: white;
-            padding: 15px 20px;
+            padding: 15px 30px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+        }
+
+        .header h1 {
+            font-size: 22px;
+            font-weight: 600;
+        }
+
+        .header button {
+            background-color: rgba(255, 255, 255, 0.2);
+            color: white;
+            border: 1px solid rgba(255, 255, 255, 0.3);
+            padding: 8px 20px;
+            border-radius: 20px;
+            cursor: pointer;
+            font-size: 14px;
+            transition: all 0.3s ease;
+        }
+
+        .header button:hover {
+            background-color: rgba(255, 255, 255, 0.3);
+        }
+
+        .container {
+            padding: 30px;
+        }
+
+        .filter-section {
+            background-color: white;
+            padding: 20px;
+            border-radius: 12px;
+            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
+            margin-bottom: 20px;
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+            gap: 15px;
+            animation: fadeIn 0.5s ease-in-out;
+        }
+
+        @keyframes fadeIn {
+            from {
+                opacity: 0;
+                transform: translateY(20px);
+            }
+            to {
+                opacity: 1;
+                transform: translateY(0);
+            }
+        }
+
+        .filter-group {
+            display: flex;
+            flex-direction: column;
+        }
+
+        .filter-group label {
+            margin-bottom: 8px;
+            font-weight: 500;
+            color: #666;
+            font-size: 14px;
+        }
+
+        .filter-group select,
+        .filter-group input {
+            padding: 10px 12px;
+            border: 2px solid #e0e0e0;
+            border-radius: 8px;
+            font-size: 14px;
+            transition: border-color 0.3s ease;
+        }
+
+        .filter-group select:focus,
+        .filter-group input:focus {
+            outline: none;
+            border-color: #667eea;
+            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+        }
+
+        .filter-actions {
+            grid-column: 1 / -1;
+            display: flex;
+            gap: 10px;
+            margin-top: 10px;
+        }
+
+        .btn {
+            padding: 10px 20px;
+            border: none;
+            border-radius: 8px;
+            font-size: 14px;
+            font-weight: 500;
+            cursor: pointer;
+            transition: all 0.3s ease;
+        }
+
+        .btn-primary {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+        }
+
+        .btn-primary:hover {
+            transform: translateY(-2px);
+            box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+        }
+
+        .btn-secondary {
+            background-color: #f0f0f0;
+            color: #333;
+        }
+
+        .btn-secondary:hover {
+            background-color: #e0e0e0;
+        }
+
+        .log-section {
+            background-color: white;
+            border-radius: 12px;
+            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
+            overflow: hidden;
+        }
+
+        .log-header {
+            padding: 20px;
+            border-bottom: 1px solid #f0f0f0;
             display: flex;
             justify-content: space-between;
             align-items: center;
         }
-        .header h1 {
-            font-size: 20px;
+
+        .log-header h2 {
+            font-size: 18px;
+            font-weight: 600;
+            color: #333;
         }
-        .header button {
-            background-color: transparent;
-            color: white;
-            border: 1px solid white;
-            padding: 5px 15px;
-            border-radius: 4px;
-            cursor: pointer;
+
+        .log-content {
+            padding: 0;
         }
-        .header button:hover {
-            background-color: rgba(255,255,255,0.1);
-        }
-        .container {
-            padding: 20px;
-        }
-        .refresh-btn {
-            background-color: #1890ff;
-            color: white;
-            border: none;
-            padding: 8px 16px;
-            border-radius: 4px;
-            cursor: pointer;
-            margin-bottom: 20px;
-        }
-        .refresh-btn:hover {
-            background-color: #40a9ff;
-        }
+
         table {
             width: 100%;
             border-collapse: collapse;
-            background-color: white;
-            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
         }
+
         th, td {
-            padding: 12px;
+            padding: 15px 20px;
             text-align: left;
-            border-bottom: 1px solid #ddd;
+            border-bottom: 1px solid #f0f0f0;
         }
+
         th {
-            background-color: #f5f5f5;
-            font-weight: bold;
+            background-color: #f9f9f9;
+            font-weight: 600;
+            color: #666;
+            font-size: 14px;
+            text-transform: uppercase;
+            letter-spacing: 0.5px;
         }
+
         tr:hover {
-            background-color: #f5f5f5;
+            background-color: #f9f9f9;
         }
+
+        td {
+            font-size: 14px;
+            color: #555;
+        }
+
         .loading {
             text-align: center;
-            padding: 20px;
-            color: #666;
+            padding: 60px;
+            color: #999;
+            font-size: 16px;
         }
+
         .error {
             text-align: center;
-            padding: 20px;
-            color: red;
+            padding: 60px;
+            color: #ff4d4f;
+            font-size: 16px;
+        }
+
+        .empty {
+            text-align: center;
+            padding: 60px;
+            color: #999;
+            font-size: 16px;
+        }
+
+        .status-badge {
+            display: inline-block;
+            padding: 4px 12px;
+            border-radius: 12px;
+            font-size: 12px;
+            font-weight: 500;
+        }
+
+        .status-up {
+            background-color: #e6f7ee;
+            color: #52c41a;
+        }
+
+        .status-down {
+            background-color: #fff2e8;
+            color: #fa8c16;
+        }
+
+        @media (max-width: 768px) {
+            .container {
+                padding: 15px;
+            }
+
+            .filter-section {
+                grid-template-columns: 1fr;
+            }
+
+            .filter-actions {
+                flex-direction: column;
+            }
+
+            .btn {
+                width: 100%;
+            }
+
+            table {
+                display: block;
+                overflow-x: auto;
+            }
         }
     </style>
 </head>
 <body>
-    <div class="header">
-        <h1>鏈哄櫒浜轰笂涓嬭鏃ュ織</h1>
-        <button id="logoutBtn">鐧诲嚭</button>
+<div class="header">
+    <h1>鏈哄櫒浜轰笂涓嬭鏃ュ織</h1>
+    <button id="logoutBtn">鐧诲嚭</button>
+</div>
+<div class="container">
+    <div class="filter-section">
+        <div class="filter-group">
+            <label for="deviceId">灏忚溅缂栧彿</label>
+            <input type="text" id="deviceId" placeholder="璇疯緭鍏ュ皬杞︾紪鍙�">
+        </div>
+        <div class="filter-group">
+            <label for="messageType">娑堟伅绫诲瀷</label>
+            <select id="messageType">
+                <option value="">鍏ㄩ儴</option>
+                <!-- 浠庡悗鍙版帴鍙h幏鍙� -->
+            </select>
+        </div>
+        <div class="filter-group">
+            <label for="tag">鏍囩</label>
+            <select id="tag">
+                <option value="">鍏ㄩ儴</option>
+                <!-- 浠庡悗鍙版帴鍙h幏鍙� -->
+            </select>
+        </div>
+        <div class="filter-group">
+            <label for="startTime">寮�濮嬫椂闂�</label>
+            <input type="datetime-local" id="startTime" step="1">
+        </div>
+        <div class="filter-group">
+            <label for="endTime">缁撴潫鏃堕棿</label>
+            <input type="datetime-local" id="endTime" step="1">
+        </div>
+        <div class="filter-actions">
+            <button class="btn btn-primary" id="searchBtn">鏌ヨ</button>
+            <button class="btn btn-secondary" id="resetBtn">閲嶇疆</button>
+            <button class="btn btn-secondary" id="refreshBtn">鍒锋柊</button>
+        </div>
     </div>
-    <div class="container">
-        <button class="refresh-btn" id="refreshBtn">鍒锋柊鏁版嵁</button>
-        <div id="loading" class="loading">鍔犺浇涓�...</div>
-        <div id="error" class="error" style="display: none;"></div>
-        <table id="logTable" style="display: none;">
-            <thead>
-                <tr>
-                    <th>鏃堕棿</th>
-                    <th>璁惧ID</th>
-                    <th>娑堟伅绫诲瀷</th>
-                    <th>娑堟伅鍐呭</th>
-                </tr>
-            </thead>
-            <tbody id="logTableBody">
-            </tbody>
-        </table>
+
+    <div class="log-section">
+        <div class="log-header">
+            <h2>鏃ュ織璁板綍</h2>
+            <span id="recordCount">鍏� 0 鏉¤褰�</span>
+        </div>
+        <div class="log-content">
+            <div id="loading" class="loading">鍔犺浇涓�...</div>
+            <div id="error" class="error" style="display: none;"></div>
+            <div id="empty" class="empty" style="display: none;">鏆傛棤绗﹀悎鏉′欢鐨勬棩蹇楄褰�</div>
+            <table id="logTable" style="display: none;">
+                <thead>
+                        <tr>
+                            <th>鏃堕棿</th>
+                            <th>璁惧ID</th>
+                            <th>娑堟伅绫诲瀷</th>
+                            <th>鏍囩</th>
+                            <th>娑堟伅鍐呭</th>
+                            <th>鎿嶄綔</th>
+                        </tr>
+                    </thead>
+                <tbody id="logTableBody">
+                </tbody>
+            </table>
+        </div>
     </div>
-    <script>
-        // 妫�鏌ョ櫥褰曠姸鎬�
-        function checkLogin() {
-            if (!localStorage.getItem('loggedIn')) {
-                window.location.href = '/login';
-            }
-        }
-        
-        // 鐧诲嚭鍔熻兘
-        document.getElementById('logoutBtn').addEventListener('click', function() {
-            localStorage.removeItem('loggedIn');
+</div>
+<script>
+    // 妫�鏌ョ櫥褰曠姸鎬�
+    function checkLogin() {
+        if (!localStorage.getItem('loggedIn')) {
             window.location.href = '/login';
-        });
-        
-        // 鍔犺浇鏃ュ織鏁版嵁
-        function loadLogData() {
-            document.getElementById('loading').style.display = 'block';
-            document.getElementById('error').style.display = 'none';
-            document.getElementById('logTable').style.display = 'none';
-            
-            fetch('/deviceLog/query')
-                .then(response => response.json())
-                .then(data => {
-                    document.getElementById('loading').style.display = 'none';
-                    if (data && data.length > 0) {
+        }
+    }
+
+    // 鐧诲嚭鍔熻兘
+    document.getElementById('logoutBtn').addEventListener('click', function () {
+        localStorage.removeItem('loggedIn');
+        window.location.href = '/login';
+    });
+
+    // 閲嶇疆绛涢�夋潯浠�
+    document.getElementById('resetBtn').addEventListener('click', function () {
+        document.getElementById('deviceId').value = '';
+        document.getElementById('messageType').value = '';
+        document.getElementById('tag').value = '';
+        document.getElementById('startTime').value = '';
+        document.getElementById('endTime').value = '';
+        loadLogData();
+    });
+
+    // 鏌ヨ鎸夐挳鐐瑰嚮浜嬩欢
+    document.getElementById('searchBtn').addEventListener('click', loadLogData);
+
+    // 鍒锋柊鎸夐挳鐐瑰嚮浜嬩欢
+    document.getElementById('refreshBtn').addEventListener('click', loadLogData);
+
+    // 鍔犺浇鏃ュ織鏁版嵁
+    function loadLogData() {
+        document.getElementById('loading').style.display = 'block';
+        document.getElementById('error').style.display = 'none';
+        document.getElementById('empty').style.display = 'none';
+        document.getElementById('logTable').style.display = 'none';
+
+        // 鑾峰彇绛涢�夋潯浠�
+        const deviceId = document.getElementById('deviceId').value;
+        const messageType = document.getElementById('messageType').value;
+        const tag = document.getElementById('tag').value;
+        const startTime = document.getElementById('startTime').value;
+        const endTime = document.getElementById('endTime').value;
+
+        // 鏋勫缓鏌ヨ鍙傛暟
+        const params = new URLSearchParams();
+        if (deviceId) params.append('deviceId', deviceId);
+        if (messageType) params.append('type', messageType);
+        if (tag) params.append('event', tag);
+        if (startTime) {
+            // 浣跨敤鍘熷鐨勬棩鏈熸牸寮�
+            params.append('startTime', startTime+"Z");
+        }
+        if (endTime) {
+            // 浣跨敤鍘熷鐨勬棩鏈熸牸寮�
+            params.append('endTime', endTime+"Z");
+        }
+
+        // 璋冪敤鏌ヨ鎺ュ彛
+        fetch(`/deviceLog/query?${params.toString()}`)
+            .then(response => response.json())
+            .then(data => {
+                document.getElementById('loading').style.display = 'none';
+
+                // 妫�鏌ユ帴鍙h繑鍥炴牸寮�
+                if (data && data.code === 200 && data.data) {
+                    // 搴旂敤绛涢�夋潯浠讹紙濡傛灉鍚庡彴娌℃湁澶勭悊绛涢�夛級
+                    let filteredData = data.data;
+                    if (deviceId) {
+                        // 妯$硦鍖归厤璁惧ID
+                        filteredData = filteredData.filter(item => {
+                            return item.deviceId && item.deviceId.includes(deviceId);
+                        });
+                    }
+                    if (messageType) {
+                        // 鐩存帴浣跨敤messageType杩涜鍖归厤
+                        filteredData = filteredData.filter(item => {
+                            return item.type && item.type === messageType;
+                        });
+                    }
+                    if (tag) {
+                        // 浣跨敤event瀛楁浣滀负鏍囩杩涜绛涢��
+                        filteredData = filteredData.filter(item => {
+                            return item.event && item.event === tag;
+                        });
+                    }
+                    if (startTime) {
+                        const start = new Date(startTime).getTime();
+                        filteredData = filteredData.filter(item => {
+                            const itemTime = new Date(item.timestamp).getTime();
+                            return itemTime >= start;
+                        });
+                    }
+                    if (endTime) {
+                        const end = new Date(endTime).getTime();
+                        filteredData = filteredData.filter(item => {
+                            const itemTime = new Date(item.timestamp).getTime();
+                            return itemTime <= end;
+                        });
+                    }
+
+                    // 鏇存柊璁板綍鏁�
+                    document.getElementById('recordCount').textContent = `鍏� ${filteredData.length} 鏉¤褰昤;
+
+                    if (filteredData && filteredData.length > 0) {
                         document.getElementById('logTable').style.display = 'table';
                         const tbody = document.getElementById('logTableBody');
                         tbody.innerHTML = '';
-                        
-                        data.forEach(item => {
-                            const row = document.createElement('tr');
-                            row.innerHTML = `
-                                <td>${item.time || '-'}</td>
-                                <td>${item.deviceId || '-'}</td>
-                                <td>${item.messageType || '-'}</td>
-                                <td>${item.messageContent || '-'}</td>
-                            `;
-                            tbody.appendChild(row);
-                        });
+
+                        filteredData.forEach(item => {
+                                const row = document.createElement('tr');
+                                const statusClass = item.type === 'up' ? 'status-up' : 'status-down';
+                                const statusText = item.type === 'up' ? '涓婅' : '涓嬭';
+                                const sourceHexStr = item.sourceHexStr || '';
+                                
+                                // 鏍煎紡鍖栨椂闂存埑
+                                let formattedTime = '-';
+                                if (item.timestamp) {
+                                    try {
+                                        const date = new Date(item.timestamp/1000/1000);
+                                        formattedTime = date.toLocaleString('zh-CN', {
+                                            year: 'numeric',
+                                            month: '2-digit',
+                                            day: '2-digit',
+                                            hour: '2-digit',
+                                            minute: '2-digit',
+                                            second: '2-digit'
+                                        });
+                                    } catch (e) {
+                                        formattedTime = item.timestamp;
+                                    }
+                                }
+                                
+                                row.innerHTML = `
+                                    <td>${formattedTime}</td>
+                                    <td>${item.deviceId || '-'}</td>
+                                    <td><span class="status-badge ${statusClass}">${statusText}</span></td>
+                                    <td>${item.event || '-'}</td>
+                                    <td>${sourceHexStr}</td>
+                                    <td>
+                                        <button class="btn btn-secondary parse-btn" data-hex="${sourceHexStr}">瑙f瀽</button>
+                                    </td>
+                                `;
+                                tbody.appendChild(row);
+                            });
+                            
+                            // 涓鸿В鏋愭寜閽坊鍔犵偣鍑讳簨浠�
+                            document.querySelectorAll('.parse-btn').forEach(btn => {
+                                btn.addEventListener('click', function() {
+                                    const hexData = this.getAttribute('data-hex');
+                                    console.log('瑙f瀽鎸夐挳鐐瑰嚮锛宧exData:', hexData);
+                                    if (hexData) {
+                                        parseHexData(hexData);
+                                    } else {
+                                        alert('娌℃湁鍙В鏋愮殑娑堟伅鍐呭');
+                                    }
+                                });
+                            });
                     } else {
-                        document.getElementById('error').textContent = '鏆傛棤鏃ュ織鏁版嵁';
-                        document.getElementById('error').style.display = 'block';
+                        document.getElementById('empty').style.display = 'block';
                     }
-                })
-                .catch(error => {
-                    document.getElementById('loading').style.display = 'none';
-                    document.getElementById('error').textContent = '鍔犺浇鏁版嵁澶辫触: ' + error.message;
+                } else {
+                    document.getElementById('error').textContent = '鍔犺浇鏁版嵁澶辫触: ' + (data.message || '鏈煡閿欒');
                     document.getElementById('error').style.display = 'block';
-                });
+                }
+            })
+            .catch(error => {
+                document.getElementById('loading').style.display = 'none';
+                document.getElementById('error').textContent = '鍔犺浇鏁版嵁澶辫触: ' + error.message;
+                document.getElementById('error').style.display = 'block';
+            });
+    }
+
+    // 浠庡悗鍙版帴鍙h幏鍙栨秷鎭被鍨嬪拰鏍囩
+    function loadFilterOptions() {
+        // 鑾峰彇娑堟伅绫诲瀷
+        fetch('/deviceLog/queryType')
+            .then(response => response.json())
+            .then(data => {
+                if (data && data.code === 200 && data.data) {
+                    const messageTypeSelect = document.getElementById('messageType');
+                    messageTypeSelect.innerHTML = '<option value="">鍏ㄩ儴</option>';
+                    data.data.forEach(type => {
+                        const option = document.createElement('option');
+                        option.value = type.label;
+                        option.textContent = type.value;
+                        messageTypeSelect.appendChild(option);
+                    });
+                    // 娑堟伅绫诲瀷鍙樺寲鏃讹紝閲嶆柊鍔犺浇鏍囩
+                    messageTypeSelect.addEventListener('change', function () {
+                        loadTags(this.value);
+                    });
+                    // 鍒濆鍔犺浇鏍囩
+                    loadTags('');
+                }
+            })
+            .catch(error => {
+                console.error('鍔犺浇娑堟伅绫诲瀷澶辫触:', error);
+            });
+    }
+
+    // 鍔犺浇鏍囩
+    function loadTags(directionType) {
+        let url = '/deviceLog/queryEvent';
+        if (directionType) {
+            url += '?directionType=' + directionType;
+        }
+        fetch(url)
+            .then(response => response.json())
+            .then(data => {
+                if (data && data.code === 200 && data.data) {
+                    const tagSelect = document.getElementById('tag');
+                    tagSelect.innerHTML = '<option value="">鍏ㄩ儴</option>';
+                    data.data.forEach(tag => {
+                        const option = document.createElement('option');
+                        option.value = tag.value;
+                        option.textContent = tag.label;
+                        tagSelect.appendChild(option);
+                    });
+                }
+            })
+            .catch(error => {
+                console.error('鍔犺浇鏍囩澶辫触:', error);
+            });
+    }
+
+    // 瑙f瀽鍗佸叚杩涘埗鏁版嵁
+    function parseHexData(hexData) {
+        console.log('寮�濮嬭В鏋愶紝hexData:', hexData);
+        
+        // 鍏堝叧闂箣鍓嶇殑鍔犺浇鐘舵�佸拰缁撴灉寮圭獥
+        const oldLoading = document.getElementById('parseLoading');
+        if (oldLoading) {
+            oldLoading.remove();
         }
         
-        // 鍒锋柊鎸夐挳鐐瑰嚮浜嬩欢
-        document.getElementById('refreshBtn').addEventListener('click', loadLogData);
+        const oldResult = document.querySelector('[id^="resultDiv"]');
+        if (oldResult) {
+            oldResult.remove();
+        }
+        
+        // 鏄剧ず鍔犺浇鐘舵��
+        const loadingDiv = document.createElement('div');
+        loadingDiv.className = 'loading';
+        loadingDiv.textContent = '瑙f瀽涓�...';
+        loadingDiv.style.position = 'fixed';
+        loadingDiv.style.top = '50%';
+        loadingDiv.style.left = '50%';
+        loadingDiv.style.transform = 'translate(-50%, -50%)';
+        loadingDiv.style.backgroundColor = 'rgba(255, 255, 255, 0.9)';
+        loadingDiv.style.padding = '20px';
+        loadingDiv.style.borderRadius = '8px';
+        loadingDiv.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)';
+        loadingDiv.id = 'parseLoading';
+        document.body.appendChild(loadingDiv);
+        
+        // 鏋勫缓璇锋眰URL
+const url = `/proxy/decode?hexData=${encodeURIComponent(hexData)}`;
+console.log('璇锋眰URL:', url);
+        
+        // 璋冪敤瑙f瀽鎺ュ彛
+        fetch(url, {
+            method: 'GET',
+            headers: {
+                'Content-Type': 'application/json',
+                'Accept': 'application/json'
+            },
+            mode: 'cors' // 鍏佽璺ㄥ煙璇锋眰
+        })
+        .then(response => {
+            console.log('鍝嶅簲鐘舵��:', response.status);
+            console.log('鍝嶅簲澶�:', response.headers);
+            if (!response.ok) {
+                throw new Error(`瑙f瀽澶辫触锛岀姸鎬佺爜: ${response.status}`);
+            }
+            return response.json();
+        })
+        .then(data => {
+            console.log('瑙f瀽缁撴灉:', data);
+            // 绉婚櫎鍔犺浇鐘舵��
+            document.getElementById('parseLoading').remove();
+            
+            // 鏄剧ず瑙f瀽缁撴灉
+            const resultDiv = document.createElement('div');
+            resultDiv.id = 'resultDiv_' + Date.now(); // 娣诲姞鍞竴ID
+            resultDiv.style.position = 'fixed';
+            resultDiv.style.top = '50%';
+            resultDiv.style.left = '50%';
+            resultDiv.style.transform = 'translate(-50%, -50%)';
+            resultDiv.style.backgroundColor = 'white';
+            resultDiv.style.padding = '20px';
+            resultDiv.style.borderRadius = '8px';
+            resultDiv.style.boxShadow = '0 2px 20px rgba(0,0,0,0.2)';
+            resultDiv.style.maxWidth = '80%';
+            resultDiv.style.maxHeight = '80%';
+            resultDiv.style.overflow = 'auto';
+            resultDiv.style.zIndex = '1000';
+            
+            // 鏋勫缓缁撴灉HTML
+            let resultHTML = '<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">';
+            resultHTML += '<h3 style="margin: 0;">瑙f瀽缁撴灉</h3>';
+            resultHTML += '<button id="closeResult" style="padding: 5px 10px; background-color: #f0f0f0; color: #333; border: none; border-radius: 4px; cursor: pointer;">脳</button>';
+            resultHTML += '</div>';
+            resultHTML += '<pre style="background-color: #f5f5f5; padding: 10px; border-radius: 4px; font-family: monospace; margin: 0;">';
+            resultHTML += JSON.stringify(data, null, 2);
+            resultHTML += '</pre>';
+            
+            resultDiv.innerHTML = resultHTML;
+            document.body.appendChild(resultDiv);
+            
+            // 鍏抽棴鎸夐挳鐐瑰嚮浜嬩欢
+            document.getElementById('closeResult').addEventListener('click', function() {
+                resultDiv.remove();
+            });
+        })
+        .catch(error => {
+            console.error('瑙f瀽閿欒:', error);
+            // 绉婚櫎鍔犺浇鐘舵��
+            document.getElementById('parseLoading').remove();
+            
+            // 鏄剧ず璇︾粏鐨勯敊璇俊鎭�
+            let errorMessage = '瑙f瀽澶辫触: ' + error.message;
+            if (error.message.includes('Failed to fetch')) {
+                errorMessage += '\n鍙兘鐨勫師鍥狅細\n1. 瑙f瀽鏈嶅姟鏈惎鍔╘n2. 璺ㄥ煙闂\n3. 缃戠粶杩炴帴闂';
+            }
+            alert(errorMessage);
+        });
+    }
         
         // 椤甸潰鍔犺浇鏃舵鏌ョ櫥褰曠姸鎬佸苟鍔犺浇鏁版嵁
         checkLogin();
+        loadFilterOptions();
         loadLogData();
-    </script>
+</script>
 </body>
 </html>
\ No newline at end of file
diff --git a/zy-acs-hex/src/main/webapp/views/login.html b/zy-acs-hex/src/main/webapp/views/login.html
index f39e7b1..707fb4c 100644
--- a/zy-acs-hex/src/main/webapp/views/login.html
+++ b/zy-acs-hex/src/main/webapp/views/login.html
@@ -10,95 +10,153 @@
             padding: 0;
             box-sizing: border-box;
         }
+
         body {
-            font-family: Arial, sans-serif;
-            background-color: #f0f2f5;
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
             display: flex;
             justify-content: center;
             align-items: center;
             height: 100vh;
         }
+
         .login-container {
             background-color: white;
             padding: 40px;
-            border-radius: 8px;
-            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+            border-radius: 12px;
+            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
             width: 100%;
             max-width: 400px;
+            animation: fadeIn 0.5s ease-in-out;
         }
+
+        @keyframes fadeIn {
+            from {
+                opacity: 0;
+                transform: translateY(20px);
+            }
+            to {
+                opacity: 1;
+                transform: translateY(0);
+            }
+        }
+
         h2 {
             text-align: center;
             margin-bottom: 30px;
             color: #333;
+            font-size: 24px;
+            font-weight: 600;
         }
+
         .form-group {
             margin-bottom: 20px;
         }
+
         label {
             display: block;
             margin-bottom: 8px;
             color: #666;
+            font-weight: 500;
         }
+
         input {
             width: 100%;
-            padding: 10px;
-            border: 1px solid #ddd;
-            border-radius: 4px;
+            padding: 12px 16px;
+            border: 2px solid #e0e0e0;
+            border-radius: 8px;
             font-size: 16px;
+            transition: border-color 0.3s ease;
         }
+
+        input:focus {
+            outline: none;
+            border-color: #667eea;
+            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
+        }
+
         button {
             width: 100%;
-            padding: 12px;
-            background-color: #1890ff;
+            padding: 14px;
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
             color: white;
             border: none;
-            border-radius: 4px;
+            border-radius: 8px;
             font-size: 16px;
+            font-weight: 600;
             cursor: pointer;
             margin-top: 10px;
+            transition: transform 0.2s ease;
         }
+
         button:hover {
-            background-color: #40a9ff;
+            transform: translateY(-2px);
         }
+
+        button:active {
+            transform: translateY(0);
+        }
+
         .error-message {
-            color: red;
-            margin-top: 10px;
+            color: #ff4d4f;
+            margin-top: 12px;
             text-align: center;
+            font-size: 14px;
         }
     </style>
 </head>
 <body>
-    <div class="login-container">
-        <h2>鏈哄櫒浜烘棩蹇楃郴缁�</h2>
-        <form id="loginForm">
-            <div class="form-group">
-                <label for="username">鐢ㄦ埛鍚�</label>
-                <input type="text" id="username" name="username" required>
-            </div>
-            <div class="form-group">
-                <label for="password">瀵嗙爜</label>
-                <input type="password" id="password" name="password" required>
-            </div>
-            <button type="submit">鐧诲綍</button>
-            <div id="errorMessage" class="error-message"></div>
-        </form>
-    </div>
-    <script>
-        document.getElementById('loginForm').addEventListener('submit', function(e) {
-            e.preventDefault();
-            const username = document.getElementById('username').value;
-            const password = document.getElementById('password').value;
-            
-            // 绠�鍗曠殑鐧诲綍楠岃瘉锛堝疄闄呴」鐩腑搴旇璋冪敤鍚庣API锛�
-            if (username === 'admin' && password === 'admin123') {
-                // 瀛樺偍鐧诲綍鐘舵��
-                localStorage.setItem('loggedIn', 'true');
-                // 璺宠浆鍒颁富椤甸潰
-                window.location.href = '/';
-            } else {
-                document.getElementById('errorMessage').textContent = '鐢ㄦ埛鍚嶆垨瀵嗙爜閿欒';
-            }
-        });
-    </script>
+<div class="login-container">
+    <h2>鏈哄櫒浜烘棩蹇楃郴缁�</h2>
+    <form id="loginForm">
+        <div class="form-group">
+            <label for="username">鐢ㄦ埛鍚�</label>
+            <input type="text" id="username" name="username" required>
+        </div>
+        <div class="form-group">
+            <label for="password">瀵嗙爜</label>
+            <input type="password" id="password" name="password" required>
+        </div>
+        <button type="submit">鐧诲綍</button>
+        <div id="errorMessage" class="error-message"></div>
+    </form>
+</div>
+<script>
+    document.getElementById('loginForm').addEventListener('submit', function (e) {
+        e.preventDefault();
+        const username = document.getElementById('username').value;
+        const password = document.getElementById('password').value;
+        const errorMessage = document.getElementById('errorMessage');
+
+        // 鏄剧ず鍔犺浇鐘舵��
+        errorMessage.textContent = '鐧诲綍涓�...';
+
+        // 璋冪敤鍚庣鐧诲綍鎺ュ彛
+        fetch('/login/auth', {
+            method: 'POST',
+            headers: {
+                'Content-Type': 'application/x-www-form-urlencoded'
+            },
+            body: `user=${encodeURIComponent(username)}&pass=${encodeURIComponent(password)}`
+        })
+            .then(response => response.json())
+            .then(data => {
+                if (data && data.code === 200) {
+                    // 鐧诲綍鎴愬姛锛屽瓨鍌ㄧ櫥褰曠姸鎬�
+                    localStorage.setItem('loggedIn', 'true');
+                    // 璺宠浆鍒颁富椤甸潰
+                    window.location.href = '/';
+                } else {
+                    // 鐧诲綍澶辫触锛屾樉绀洪敊璇俊鎭�
+                    errorMessage.textContent = data.message || '鐢ㄦ埛鍚嶆垨瀵嗙爜閿欒';
+                }
+            })
+            .catch(error => {
+                // 缃戠粶閿欒锛屾樉绀洪敊璇俊鎭�
+                errorMessage.textContent = '鐧诲綍澶辫触锛岃绋嶅悗閲嶈瘯';
+                console.error('鐧诲綍澶辫触:', error);
+            });
+    });
+</script>
 </body>
 </html>
\ No newline at end of file

--
Gitblit v1.9.1