From 694e0455691a5aa9d4c49c4755284eeb052f6ccf Mon Sep 17 00:00:00 2001 From: gaoxq <376340421@qq.com> Date: Sat, 30 Aug 2025 15:26:27 +0800 Subject: [PATCH] =?UTF-8?q?API=E6=95=B0=E6=8D=AE=E8=A1=A8=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../capi/sys/controller/dataController.java | 206 ++++- .../capi/sys/controller/sysController.java | 15 + src/main/java/com/mini/capi/utils/vSql.java | 10 + .../templates/views/data/detail.html | 767 +++++++++++++----- .../resources/templates/views/data/list.html | 24 +- src/main/resources/templates/views/demo.html | 713 ++++++++++------ src/main/resources/templates/views/icon.html | 312 +++++++ 7 files changed, 1555 insertions(+), 492 deletions(-) create mode 100644 src/main/java/com/mini/capi/sys/controller/sysController.java create mode 100644 src/main/java/com/mini/capi/utils/vSql.java create mode 100644 src/main/resources/templates/views/icon.html diff --git a/src/main/java/com/mini/capi/sys/controller/dataController.java b/src/main/java/com/mini/capi/sys/controller/dataController.java index 8d100a0..6f2b5a2 100644 --- a/src/main/java/com/mini/capi/sys/controller/dataController.java +++ b/src/main/java/com/mini/capi/sys/controller/dataController.java @@ -1,18 +1,222 @@ package com.mini.capi.sys.controller; +import com.mini.capi.biz.domain.DbConfig; +import com.mini.capi.biz.domain.SyncTask; +import com.mini.capi.biz.service.DbConfigService; +import com.mini.capi.biz.service.SyncTaskService; +import com.mini.capi.config.DataSourceConfig; +import jakarta.annotation.Resource; +import lombok.Data; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import java.io.Serializable; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + @Controller public class dataController { + + @Resource + private SyncTaskService syncTaskService; + + + @Resource + private DbConfigService dbConfigService; + @GetMapping("/Sys/data/list") public String listPage() { return "views/data/list"; } + + @Data + static class TabDetail implements Serializable { + private String createTime; + private String dbName; + private String tableName; + private String tableDesc; + private String dataLength; + private String updateTime; + + public TabDetail(String createTime, String dbName, String tableName, String tableDesc, String dataLength, String updateTime) { + this.createTime = createTime; + this.dbName = dbName; + this.tableName = tableName; + this.tableDesc = tableDesc; + this.dataLength = dataLength; + this.updateTime = updateTime; + } + } + + @Data + static class TabColumns implements Serializable { + private String tableName; + private String sort; + private String colName; + private String colType; + private String colDesc; + private String keyType; + + public TabColumns(String tableName, String sort, String colName, String colType, String colDesc, String keyType) { + this.tableName = tableName; + this.sort = sort; + this.colName = colName; + this.colType = colType; + this.colDesc = colDesc; + this.keyType = keyType; + } + } + + + public static String buildSelect(List columns, TabDetail table) { + if (columns == null || columns.isEmpty() || table == null) { + return "-- no columns or table info"; + } + + StringBuilder sb = new StringBuilder("SELECT\n"); + for (int i = 0; i < columns.size(); i++) { + TabColumns c = columns.get(i); + sb.append(" "); + if (i > 0) sb.append(","); + sb.append(quote(c.getColName())) + .append(" -- ") + .append(nullToEmpty(c.getColDesc())) + .append('\n'); + } + sb.append("FROM ") + .append(quote(table.getDbName())) + .append('.') + .append(quote(table.getTableName())) + .append(" -- ") + .append(nullToEmpty(table.getTableDesc())) + .append(";\n"); + return sb.toString(); + } + + /* ---------- 生成 CREATE TABLE ---------- */ + public static String buildDDL(List columns, TabDetail table) { + if (columns == null || columns.isEmpty() || table == null) { + return "-- no columns or table info"; + } + + StringBuilder sb = new StringBuilder("CREATE TABLE ") + .append(quote(table.getDbName())) + .append('.') + .append(quote(table.getTableName())) + .append(" (\n"); + + for (TabColumns c : columns) { + sb.append(" ") + .append(leftPad(quote(c.getColName()), 20)) // 左对齐宽度可自行调整 + .append(leftPad(mapType(c.getColType()), 18)) + .append(" NOT NULL"); + + String comment = nullToEmpty(c.getColDesc()); + if (!comment.isEmpty()) { + sb.append(" COMMENT '").append(comment).append('\''); + } + sb.append(",\n"); + } + + // 主键:约定 id 字段 + boolean hasId = columns.stream().anyMatch(c -> "id".equalsIgnoreCase(c.getColName())); + if (hasId) { + sb.append(" PRIMARY KEY (").append(quote("id")).append(")\n"); + } else { + sb.setLength(sb.length() - 2); // 去掉最后一个逗号 + sb.append("\n"); + } + + sb.append(")\nCOMMENT='") + .append(nullToEmpty(table.getTableDesc())) + .append("';\n"); + return sb.toString(); + } + + /* ---------- 工具 ---------- */ + private static String nullToEmpty(String s) { + return s == null ? "" : s; + } + + private static String quote(String name) { + return "`" + name + "`"; + } + + private static String leftPad(String val, int len) { + return String.format("%-" + len + "s", val); + } + + /** + * 简单类型映射,可根据需要扩充 + **/ + private static String mapType(String colType) { + if (colType == null) return "varchar(50)"; + return colType.trim(); + } + + @GetMapping("/Sys/data/getTableDetail") - public String getTableDetail(String taskId) { + public String getTableDetail(String taskId, Model model) { + SyncTask task = syncTaskService.getById(taskId); + DbConfig dbConfig = dbConfigService.getById(task.getSourceDbId()); + List data; + List columns; + try { + JdbcTemplate jdbcTemplate = DataSourceConfig.createJdbcTemplate(dbConfig); + // 补充参数传递 + String querySql = "SELECT CREATE_TIME,TABLE_NAME,TABLE_COMMENT,MAX_DATA_LENGTH,UPDATE_TIME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?"; + data = jdbcTemplate.query( + querySql, + (rs, rowNum) -> new TabDetail( + rs.getString("CREATE_TIME"), + dbConfig.getDbName(), + rs.getString("TABLE_NAME"), + rs.getString("TABLE_COMMENT"), + rs.getString("MAX_DATA_LENGTH"), + rs.getString("UPDATE_TIME") + ), + dbConfig.getDbName(), + task.getSourceTable() + ); + data.sort(Comparator.comparing(TabDetail::getTableName)); + } catch (Exception e) { + data = Collections.emptyList(); + System.out.println(e.getMessage()); + } + + try { + JdbcTemplate jdbcTemplate = DataSourceConfig.createJdbcTemplate(dbConfig); + // 补充参数传递 + String querySql = "SELECT TABLE_NAME,ORDINAL_POSITION,COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT,COLUMN_KEY FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?"; + columns = jdbcTemplate.query( + querySql, + (rs, rowNum) -> new TabColumns( + rs.getString("TABLE_NAME"), + rs.getString("ORDINAL_POSITION"), + rs.getString("COLUMN_NAME"), + rs.getString("COLUMN_TYPE"), + rs.getString("COLUMN_COMMENT"), + rs.getString("COLUMN_KEY") + ), + dbConfig.getDbName(), + task.getSourceTable() + ); + columns.sort(Comparator.comparing(TabColumns::getSort)); + } catch (Exception e) { + columns = Collections.emptyList(); + System.out.println(e.getMessage()); + } + model.addAttribute("data", data); + model.addAttribute("columns", columns); + model.addAttribute("ddlSql", buildDDL(columns, data.get(0))); + model.addAttribute("selectSql", buildSelect(columns, data.get(0))); return "views/data/detail"; } + + } diff --git a/src/main/java/com/mini/capi/sys/controller/sysController.java b/src/main/java/com/mini/capi/sys/controller/sysController.java new file mode 100644 index 0000000..1b12368 --- /dev/null +++ b/src/main/java/com/mini/capi/sys/controller/sysController.java @@ -0,0 +1,15 @@ +package com.mini.capi.sys.controller; + + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class sysController { + + + @GetMapping("/Sys/sys/icon") + public String getIcon() { + return "views/icon"; + } +} diff --git a/src/main/java/com/mini/capi/utils/vSql.java b/src/main/java/com/mini/capi/utils/vSql.java new file mode 100644 index 0000000..be900cd --- /dev/null +++ b/src/main/java/com/mini/capi/utils/vSql.java @@ -0,0 +1,10 @@ +package com.mini.capi.utils; + +public class vSql { + + + private vSql() {} + + + +} diff --git a/src/main/resources/templates/views/data/detail.html b/src/main/resources/templates/views/data/detail.html index 0bda1a2..5f653d2 100644 --- a/src/main/resources/templates/views/data/detail.html +++ b/src/main/resources/templates/views/data/detail.html @@ -14,48 +14,54 @@ } body { - background: linear-gradient(135deg, #f8f9fc 0%, #eef2f6 100%); + background: linear-gradient(135deg, #e6f7ff 0%, #f0f7ff 100%); min-height: 100vh; - padding: 20px; + padding: 10px; /* 核心:距离页面两边10px */ color: #2c3e50; - overflow: hidden; /* 禁止页面整体滚动 */ + overflow: hidden; } .container { - max-width: 1400px; - margin: 20px auto; + max-width: 100%; + margin: 0 auto; /* 水平居中,同时借助body的10px padding实现边缘距离 */ display: flex; - gap: 25px; - height: calc(100vh - 40px); /* 让容器占用整个屏幕高度 */ + gap: 15px; + height: calc(100vh - 20px); /* 减去body上下10px padding,占满垂直空间 */ } .panel { background: white; border-radius: 16px; - box-shadow: 0 8px 30px rgba(0, 0, 100, 0.08); + box-shadow: 0 4px 20px rgba(0, 120, 255, 0.08); overflow: hidden; transition: transform 0.3s ease; display: flex; flex-direction: column; + height: 100%; /* 面板高度铺满容器,避免内容溢出 */ } .panel:hover { - transform: translateY(-5px); + transform: translateY(-3px); } .panel-header { - background: linear-gradient(135deg, #4a69bd 0%, #1e3799 100%); + background: linear-gradient(135deg, #4096ff 0%, #165dff 100%); color: white; - padding: 18px 25px; - font-size: 1.3rem; + padding: 16px 20px; + font-size: 1.2rem; border-bottom: 1px solid rgba(255, 255, 255, 0.15); + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; /* 表头不压缩 */ } .panel-content { - padding: 25px; - flex: 1; + padding: 20px; + flex: 1; /* 内容区占据剩余高度 */ display: flex; flex-direction: column; + overflow: hidden; /* 关键:父容器隐藏溢出,确保子滚动容器生效 */ } .left-panel { @@ -67,23 +73,25 @@ } .info-card { - background: #f8f9ff; + background: #eef7ff; border-radius: 12px; - padding: 20px; - margin-bottom: 22px; - border-left: 4px solid #4a69bd; + padding: 18px; + margin-bottom: 18px; + border-left: 4px solid #4096ff; + flex-shrink: 0; /* 信息卡片不压缩 */ } .info-row { display: flex; - margin-bottom: 14px; + margin-bottom: 12px; align-items: center; + line-height: 1.5; } .info-label { font-weight: 600; - color: #4a69bd; - width: 120px; + color: #165dff; + width: 110px; position: relative; } @@ -100,33 +108,48 @@ .button-panel { display: flex; - gap: 12px; - margin-bottom: 25px; - border-bottom: 1px solid #e9ecef; - padding-bottom: 20px; - flex-shrink: 0; /* 防止按钮区随内容滚动 */ + gap: 10px; + margin-bottom: 15px; + border-bottom: 1px solid #e6f0ff; + padding-bottom: 12px; + flex-shrink: 0; /* 按钮区不压缩,固定高度 */ + flex-wrap: wrap; /* 小屏幕按钮换行 */ } .button { - background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); - padding: 10px 22px; + background: linear-gradient(135deg, #f0f7ff 0%, #e6f0ff 100%); + padding: 9px 18px; border-radius: 8px; font-weight: 600; - color: #4a69bd; + color: #165dff; cursor: pointer; - border: 1px solid #dee2e6; - transition: all 0.3s ease; + border: 1px solid #d1e0ff; + transition: all 0.25s ease; + display: flex; + align-items: center; + gap: 6px; } .button:hover { - background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%); - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); + background: linear-gradient(135deg, #e6f0ff 0%, #d1e0ff 100%); + box-shadow: 0 3px 6px rgba(64, 150, 255, 0.1); } .button.active { - background: linear-gradient(135deg, #4a69bd 0%, #1e3799 100%); + background: linear-gradient(135deg, #4096ff 0%, #165dff 100%); color: white; - border-color: #1e3799; + border-color: #165dff; + } + + /* 1. 字段信息面板:滚动容器修复(确保滚动条必现) */ + .table-scroll-container { + flex: 1; /* 占据内容区剩余高度 */ + overflow-y: auto; /* 内容溢出时显示垂直滚动条 */ + overflow-x: auto; /* 小屏幕列宽不足时显示水平滚动条 */ + border-radius: 12px; + margin-bottom: 10px; + box-shadow: 0 3px 12px rgba(0, 120, 255, 0.05); + min-height: 100px; /* 最小高度,避免内容过少时容器塌陷 */ } table { @@ -135,131 +158,386 @@ border-spacing: 0; border-radius: 12px; overflow: hidden; - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); background: white; + table-layout: fixed; /* 固定列宽,避免表头错位 */ + min-width: 600px; /* 表格最小宽度,确保小屏幕触发水平滚动 */ } th { - background: linear-gradient(135deg, #4a69bd 0%, #1e3799 100%); + background: linear-gradient(135deg, #4096ff 0%, #165dff 100%); color: white; font-weight: 600; - padding: 16px 15px; + padding: 14px 15px; text-align: left; border-right: 1px solid rgba(255, 255, 255, 0.15); position: sticky; top: 0; - z-index: 10; + z-index: 20; + background-clip: padding-box; /* 防止背景透色 */ + /* 列宽分配:适配内容优先级 */ + width: 100px; } + th:nth-child(1) { + width: 80px; + } + + /* 序号 */ + th:nth-child(2) { + width: 180px; + } + + /* 字段名称 */ + th:nth-child(3) { + width: 150px; + } + + /* 字段类型 */ + th:nth-child(4) { + width: 200px; + } + + /* 描述(增加宽度,减少换行) */ + th:nth-child(5) { + width: 120px; + } + + /* 键类型 */ + th:last-child { border-right: none; } td { - padding: 14px 15px; - border-bottom: 1px solid #e9ecef; + padding: 12px 15px; + border-bottom: 1px solid #e6f0ff; color: #495057; + width: 100px; + word-wrap: break-word; /* 长文本换行,避免列宽异常 */ + word-break: break-all; + } + + td:nth-child(1) { + width: 80px; + } + + td:nth-child(2) { + width: 180px; + } + + td:nth-child(3) { + width: 150px; + } + + td:nth-child(4) { + width: 200px; + } + + td:nth-child(5) { + width: 120px; } tr:nth-child(even) { - background-color: #f8f9ff; + background-color: #f7fbff; } tr:hover td { - background-color: rgba(74, 105, 189, 0.08); + background-color: rgba(64, 150, 255, 0.08); } .primary-key { - background-color: #e3f2fd; - color: #0d47a1; + background-color: #e6f4ff; + color: #165dff; font-weight: 600; - padding: 3px 10px; + padding: 2px 8px; border-radius: 50px; - font-size: 0.85rem; + font-size: 0.8rem; } .index-key { background-color: #e8f5e9; - color: #1b5e20; - padding: 3px 10px; + color: #00864e; + padding: 2px 8px; border-radius: 50px; - font-size: 0.85rem; + font-size: 0.8rem; } .stats-row { display: flex; - gap: 20px; - margin-top: 15px; + gap: 15px; + margin-top: 12px; color: #6c757d; - font-size: 0.9rem; + font-size: 0.85rem; + flex-shrink: 0; /* 统计行不压缩 */ } .stat-item { display: flex; align-items: center; - gap: 6px; + gap: 5px; } .time-ago { - color: #e74c3c; + color: #ff4d4f; font-weight: 500; + font-size: 0.85rem; + } + + /* 2. SQL面板:滚动容器修复(同字段面板逻辑) */ + .sql-container { + flex: 1; /* 占据剩余高度 */ + display: flex; + flex-direction: column; + margin-bottom: 10px; + border-radius: 12px; + box-shadow: 0 3px 12px rgba(0, 120, 255, 0.05); + overflow: hidden; + min-height: 100px; /* 最小高度,避免塌陷 */ + } + + .sql-toolbar { + background: #f0f7ff; + padding: 8px 15px; + border-bottom: 1px solid #e6f0ff; + display: flex; + justify-content: flex-end; + gap: 8px; + flex-shrink: 0; /* 工具条不压缩 */ + } + + .sql-copy-btn { + background: #4096ff; + color: white; + border: none; + border-radius: 6px; + padding: 6px 12px; + font-size: 0.85rem; + cursor: pointer; + display: flex; + align-items: center; + gap: 5px; + transition: background 0.2s ease; + } + + .sql-copy-btn:hover { + background: #165dff; + } + + /* SQL输入框:确保滚动条生效 */ + .sql-input { + flex: 1; /* 占据SQL容器剩余高度 */ + background: white; + padding: 15px; + font-family: 'Consolas', 'Monaco', monospace; + font-size: 0.9rem; + color: #333; + white-space: pre-wrap; + line-height: 1.6; + overflow-y: auto; /* 垂直滚动 */ + overflow-x: auto; /* 水平滚动(长SQL语句) */ + outline: none; + border: none; + contenteditable: true; + min-height: 80px; /* 输入框最小高度 */ + } + + + /* 移除pre标签默认样式干扰(适配动态SQL) */ + .sql-input pre { + margin: 0; + padding: 0; + border: none; + background: transparent; + font-family: inherit; + font-size: inherit; + line-height: inherit; + white-space: inherit; /* 继承sql-input的换行规则 */ + } + + /* SQL高亮样式(不破坏格式) */ + .sql-keyword { color: #d73a49; font-weight: 600; } + .sql-table { color: #005cc5; } + .sql-column { color: #6f42c1; } + .sql-comment { color: #6a737d; } + + /* 复制提示 */ + .copy-toast { + position: fixed; + bottom: 30px; + right: 30px; + background: rgba(0, 120, 255, 0.9); + color: white; + padding: 8px 16px; + border-radius: 6px; + font-size: 0.85rem; + opacity: 0; + transition: opacity 0.3s ease; + z-index: 100; + } + + .copy-toast.show { + opacity: 1; + } + + /* 统一滚动条样式(确保所有滚动容器外观一致) */ + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + ::-webkit-scrollbar-thumb { + background: #4096ff; + border-radius: 4px; + transition: background 0.2s ease; + } + + ::-webkit-scrollbar-thumb:hover { + background: #165dff; + } + + ::-webkit-scrollbar-track { + background: rgba(64, 150, 255, 0.1); + border-radius: 4px; + } + + /* 内容面板切换基础样式 */ + .content-panel { + display: none; + flex: 1; + flex-direction: column; + overflow: hidden; /* 子容器溢出控制 */ + } + + .content-panel.active { + display: flex; + } + + /* 3. 小屏幕/页面缩小适配(确保滚动条正常触发) */ + @media (max-width: 1200px) { + .container { + gap: 10px; + } + + .panel-content { + padding: 15px; + } + + th, td { + padding: 12px 10px; + font-size: 0.85rem; + } + + th:nth-child(4) { + width: 180px; + } + + /* 小屏幕压缩描述列宽 */ + td:nth-child(4) { + width: 180px; + } } @media (max-width: 1000px) { .container { flex-direction: column; - height: auto; + height: auto; /* 垂直布局时容器高度自适应 */ + max-height: calc(100vh - 20px); /* 但不超过屏幕高度 */ + overflow: hidden; + } + + .table-scroll-container, + .sql-container { + max-height: 300px; /* 移动端限制最大高度,确保滚动 */ + } + + /* 移动端表格列宽进一步压缩 */ + th:nth-child(2) { + width: 150px; + } + + th:nth-child(3) { + width: 120px; + } + + th:nth-child(4) { + width: 150px; + } + + td:nth-child(2) { + width: 150px; + } + + td:nth-child(3) { + width: 120px; + } + + td:nth-child(4) { + width: 150px; } } - .table-scroll-container { - flex: 1; - overflow-y: auto; - border-radius: 12px; - max-height: calc(100vh - 320px); /* 确保独立滚动 */ - box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); - } + @media (max-width: 600px) { + .button { + padding: 8px 12px; + font-size: 0.85rem; + } - /* 自定义滚动条样式 */ - .table-scroll-container::-webkit-scrollbar { - width: 8px; - height: 8px; - } + .info-label { + width: 90px; + } - .table-scroll-container::-webkit-scrollbar-thumb { - background: #4a69bd; - border-radius: 4px; - } + /* 超小屏幕表格列宽最小化 */ + th { + padding: 10px 8px; + } - .table-scroll-container::-webkit-scrollbar-track { - background: rgba(74, 105, 189, 0.1); - border-radius: 4px; + td { + padding: 10px 8px; + } + + th:nth-child(2) { + width: 120px; + } + + th:nth-child(4) { + width: 120px; + } + + td:nth-child(2) { + width: 120px; + } + + td:nth-child(4) { + width: 120px; + } }
+
- 表基础信息 + + 表基础信息
-
+
数据库
-
work
+

表名称
-
biz_cities
+
表描述
-
市区信息表
+

存储量
-
333条
+

@@ -267,183 +545,226 @@
创建时间
- 2025-08-29 15:54:41 - (2小时前) +

更新时间
- 2025-08-29 15:54:41 - (2小时前) +

- + 1 个主键
- + 2 个索引
- - 13 个字段 + + 20 个字段
+
- 表结构信息 + + 表结构操作
+
-
- 字段信息 +
+ + 字段信息
-
- 生成SELECT +
+ + 生成SELECT
-
- 生成DDL +
+ + 生成DDL
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
序号字段名称字段类型描述键类型
1iddatetime主键
2create_timevarchar记录时间
3province_codevarchar省份编码索引
4city_codevarchar市区编码
5city_namevarchar市区名称
6area_codevarchar市区区号
7area_typevarchar市区级别
8update_timevarchar更新时间
9data_statusvarchar数据状态
10f_tenant_idvarchar租户id
11f_flow_iddatetime流程id索引
12f_flow_task_iddatetime流程任务主键
13f_flow_statebigint流程任务状态
14f_created_byvarchar创建人
15f_updated_byvarchar更新人
16f_versionint版本号
+ +
+
+ + + + + + + + + + + + + + + + + + + +
序号字段名称字段类型描述键类型
+
+
+ + +
+
+
+ +
+
+

+                    
+
+
+ + +
+
+
+ +
+
+

+                    
+
+ + +
复制成功!
+ + \ No newline at end of file diff --git a/src/main/resources/templates/views/data/list.html b/src/main/resources/templates/views/data/list.html index 5c734bc..fab37db 100644 --- a/src/main/resources/templates/views/data/list.html +++ b/src/main/resources/templates/views/data/list.html @@ -23,13 +23,20 @@ }; @@ -63,9 +70,10 @@
+
-
+
@@ -74,7 +82,7 @@
-
+
@@ -90,7 +98,7 @@ const $ = sel => document.querySelector(sel); const $$ = sel => document.querySelectorAll(sel); - /* Toast */ + /* Toast 提示组件 */ function showToast(msg) { const t = document.createElement('div'); t.className = 'fixed bottom-4 right-4 bg-gray-800 text-white px-4 py-2 rounded-lg shadow-lg z-50'; @@ -100,7 +108,7 @@ } /***************************************************************** - * 1. 加载数据库下拉框 + * 1. 加载数据库下拉框数据 *****************************************************************/ fetch('getDbList') .then(r => r.json()) @@ -117,7 +125,7 @@ .catch(() => showToast('获取数据库列表失败')); /***************************************************************** - * 2. 加载/渲染表格卡片 + * 2. 加载/渲染表格卡片列表 *****************************************************************/ function loadTableList() { const dbId = $('#dbSelect').value; @@ -171,7 +179,7 @@ $('#searchBtn').addEventListener('click', loadTableList); /***************************************************************** - * 4. 表详情弹窗 + * 4. 表详情弹窗控制 *****************************************************************/ function openDetailDialog(taskId) { const dialog = $('#detailDialog'); @@ -180,7 +188,7 @@ dialog.showModal(); } - // 点击遮罩关闭弹窗 + // 点击弹窗遮罩关闭弹窗 $('#detailDialog').addEventListener('click', e => { if (e.target === $('#detailDialog')) $('#detailDialog').close(); }); diff --git a/src/main/resources/templates/views/demo.html b/src/main/resources/templates/views/demo.html index 45a251d..1574b5e 100644 --- a/src/main/resources/templates/views/demo.html +++ b/src/main/resources/templates/views/demo.html @@ -1,4 +1,3 @@ - @@ -9,17 +8,24 @@ - + - \ No newline at end of file + diff --git a/src/main/resources/templates/views/icon.html b/src/main/resources/templates/views/icon.html new file mode 100644 index 0000000..16276bc --- /dev/null +++ b/src/main/resources/templates/views/icon.html @@ -0,0 +1,312 @@ + + + + + + Font Awesome 4.7.0 所有图标 + + + + + + +
+
+

Font Awesome 4.7.0 图标库

+

完整展示所有图标及其代码

+
+
+ +
+
+
+ + +
+
+ + + + + + + +
+
+ +
+ +
+
+ +
+
+

Font Awesome 4.7.0 图标展示 | 使用 Font Awesome

+
+
+ + + +