chengjie 5 months ago
parent
commit
5056c174c5
1 changed files with 216 additions and 9 deletions
  1. 216 9
      public/mg/kylx365_db_admin.html

+ 216 - 9
public/mg/kylx365_db_admin.html

@@ -223,16 +223,21 @@
223 223
             overflow: auto;
224 224
             padding: 20px;
225 225
             background: white;
226
+            position: relative;
226 227
         }
227 228
 
228 229
         .table-container {
229 230
             width: 100%;
230 231
             overflow-x: auto;
232
+            max-height: calc(100vh - 380px); /* 减去其他元素的高度 */
233
+            overflow-y: auto;
234
+            position: relative; /* 为内部元素提供定位上下文 */
231 235
         }
232 236
 
233 237
         .data-table {
234 238
             width: 100%;
235
-            border-collapse: collapse;
239
+            border-collapse: separate; /* 改为separate以支持边框样式 */
240
+            border-spacing: 0; /* 消除单元格间距 */
236 241
             font-size: 14px;
237 242
         }
238 243
 
@@ -244,6 +249,21 @@
244 249
             position: sticky;
245 250
             top: 0;
246 251
             z-index: 10;
252
+            box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
253
+        }
254
+
255
+        /* 确保表头单元格背景色完整覆盖 */
256
+        .data-table thead th {
257
+            background: #F5F5F5;
258
+        }
259
+        
260
+        /* 优化表头在滚动时的视觉效果 */
261
+        .table-container:not(:hover) .data-table th {
262
+            transition: box-shadow 0.3s ease;
263
+        }
264
+        
265
+        .table-container:hover .data-table th {
266
+            box-shadow: 0 3px 5px -2px rgba(0, 0, 0, 0.2);
247 267
         }
248 268
 
249 269
         .data-table td {
@@ -481,6 +501,77 @@
481 501
             color: #CCCCCC;
482 502
             cursor: not-allowed;
483 503
         }
504
+
505
+        /* 完整内容弹出层样式 - 改进版 */
506
+        .complete-content-overlay {
507
+            position: fixed;
508
+            top: 0;
509
+            left: 0;
510
+            right: 0;
511
+            bottom: 0;
512
+            display: flex;
513
+            justify-content: center;
514
+            align-items: center;
515
+            z-index: 1000;
516
+            background-color: rgba(0, 0, 0, 0.5);
517
+            pointer-events: auto;
518
+        }
519
+        
520
+        .complete-content-container {
521
+            width: 80%;
522
+            max-width: 800px;
523
+            max-height: 80vh;
524
+            background-color: white;
525
+            border-radius: 8px;
526
+            padding: 20px;
527
+            padding-top: 50px; /* 为固定的关闭按钮留出空间 */
528
+            position: relative;
529
+            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
530
+            overflow: auto;
531
+            animation: fadeIn 0.3s ease-out;
532
+        }
533
+
534
+        @keyframes fadeIn {
535
+            from {
536
+                opacity: 0;
537
+                transform: translateY(20px);
538
+            }
539
+            to {
540
+                opacity: 1;
541
+                transform: translateY(0);
542
+            }
543
+        }
544
+        
545
+        .close-btn {
546
+            position: absolute;
547
+            right: 15px; /* 根据弹窗宽度计算位置 */
548
+            top: 15px; /* 根据弹窗位置计算 */
549
+            z-index: 1010; /* 确保按钮在最上层 */
550
+            width: 40px;
551
+            height: 40px;
552
+            display: flex;
553
+            align-items: center;
554
+            justify-content: center;
555
+            background: rgba(255, 255, 255, 0.9);
556
+            border: none;
557
+            border-radius: 50%;
558
+            font-size: 24px;
559
+            cursor: pointer;
560
+            color: #999;
561
+            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
562
+        }
563
+        
564
+        .close-btn:hover {
565
+            color: #333;
566
+            background: #fff;
567
+        }
568
+        
569
+        .complete-content {
570
+            white-space: pre-wrap;
571
+            word-break: break-word;
572
+            font-family: monospace;
573
+            line-height: 1.5;
574
+        }
484 575
     </style>
485 576
 </head>
486 577
 
@@ -610,7 +701,9 @@
610 701
                                             :key="'tr-'+rowIndex">
611 702
                                             <td v-for="(column, colIndex) in tableColumns" 
612 703
                                                 :key="'td-'+rowIndex+'-'+colIndex"
613
-                                                v-show="!column.startsWith('__')">
704
+                                                v-show="!column.startsWith('__')"
705
+                                                @dblclick="formatTableCell(row[column]).endsWith('...') ? showCompleteField(row, column) : copyColumnName(formatTableCell(row[column]))"
706
+                                                >
614 707
                                                 {{ formatTableCell(row[column]) }}
615 708
                                             </td>
616 709
                                         </tr>
@@ -641,6 +734,16 @@
641 734
 
642 735
         <!-- Toast提示 -->
643 736
         <div class="toast" :class="{ show: showToast, [toastType]: showToast }">{{ toastMessage }}</div>
737
+        
738
+        <!-- 完整内容弹出层 -->
739
+        <div v-if="showCompleteContent" class="complete-content-overlay" @click.self="closeCompleteContent">
740
+            <div class="complete-content-container">
741
+                <button class="close-btn" @click="closeCompleteContent">×</button>
742
+                <div class="complete-content" @dblclick="copyToClipboard(completeContent)">
743
+                    {{ completeContent }}
744
+                </div>
745
+            </div>
746
+        </div>
644 747
     </div>
645 748
 
646 749
     <script>
@@ -665,7 +768,11 @@
665 768
                 allResults: [],
666 769
                 tableColumnsList: [], // 存储表格字段列表
667 770
                 limitOptions: [10, 100, 500, 1000, 2000, 3000], // LIMIT选项
668
-                selectedLimit: 100 // 默认选中的LIMIT值
771
+                selectedLimit: 100, // 默认选中的LIMIT值
772
+                showCompleteContent: false,
773
+                completeContent: '',
774
+                currentRow: null,
775
+                currentColumn: null
669 776
             },
670 777
             computed: {
671 778
                 
@@ -824,10 +931,19 @@
824 931
                 // 选择表格
825 932
                 selectTable(table) {
826 933
                     this.selectedTable = table;
827
-                    this.sqlQuery = `SELECT * FROM ${table} LIMIT 100;`;
828
-
934
+                    
829 935
                     // 获取表格字段列表
830 936
                     this.loadTableColumns(table);
937
+                    
938
+                    // 监听字段列表变化,当加载完成后构建查询语句
939
+                    this.$watch('tableColumnsList', (newVal) => {
940
+                        if (newVal && newVal.length > 0) {
941
+                            const columns = newVal.map(col => `\`${col.name}\``).join(',');
942
+                            this.sqlQuery = `SELECT ${columns} FROM \`${table}\` LIMIT 100;`;
943
+                        } else {
944
+                            this.sqlQuery = `SELECT * FROM \`${table}\` LIMIT 100;`;
945
+                        }
946
+                    }, {immediate: true});
831 947
                 },
832 948
 
833 949
                 // 加载表格字段列表
@@ -1009,6 +1125,8 @@
1009 1125
                 insertColumnName(columnName) {
1010 1126
                     // 获取文本框元素
1011 1127
                     const textarea = document.querySelector('.sql-textarea');
1128
+                    // 添加反引号的字段名
1129
+                    const quotedColumnName = `\`${columnName}\``;
1012 1130
 
1013 1131
                     // 如果文本框存在
1014 1132
                     if (textarea) {
@@ -1021,19 +1139,19 @@
1021 1139
                         const textAfter = this.sqlQuery.substring(endPos);
1022 1140
 
1023 1141
                         // 更新SQL查询
1024
-                        this.sqlQuery = textBefore + columnName + textAfter;
1142
+                        this.sqlQuery = textBefore + quotedColumnName + textAfter;
1025 1143
 
1026 1144
                         // 设置新的光标位置
1027 1145
                         this.$nextTick(() => {
1028 1146
                             textarea.focus();
1029
-                            textarea.selectionStart = startPos + columnName.length;
1030
-                            textarea.selectionEnd = startPos + columnName.length;
1147
+                            textarea.selectionStart = startPos + quotedColumnName.length;
1148
+                            textarea.selectionEnd = startPos + quotedColumnName.length;
1031 1149
                         });
1032 1150
 
1033 1151
                         this.showToastMessage(`已插入字段 "${columnName}" 到查询`, 'info');
1034 1152
                     } else {
1035 1153
                         // 如果无法获取文本框元素,则直接在末尾添加
1036
-                        this.sqlQuery += ' ' + columnName;
1154
+                        this.sqlQuery += ' ' + quotedColumnName;
1037 1155
                     }
1038 1156
                 },
1039 1157
 
@@ -1236,6 +1354,95 @@
1236 1354
                     return value;
1237 1355
                 },
1238 1356
 
1357
+                // 显示完整字段内容
1358
+                showCompleteField(row, column) {
1359
+                    // 检查当前单元格内容是否有省略
1360
+                    const cellContent = this.formatTableCell(row[column]);
1361
+                    if (!cellContent.includes('...')) {
1362
+                        return;
1363
+                    }
1364
+                    
1365
+                    this.currentRow = row;
1366
+                    this.currentColumn = column;
1367
+                    this.showCompleteContent = true;
1368
+                    this.completeContent = '加载中...';
1369
+                    
1370
+                    // 查找主键字段 - 优先使用实际存在的列名
1371
+                    let primaryKey = null;
1372
+                    
1373
+                    // 检查当前行是否有id字段
1374
+                    if ('id' in row) {
1375
+                        primaryKey = 'id';
1376
+                    } 
1377
+                    // 检查是否有ID字段(大写)
1378
+                    else if ('ID' in row) {
1379
+                        primaryKey = 'ID';
1380
+                    }
1381
+                    // 检查表字段列表中是否有id字段
1382
+                    else if (this.tableColumnsList.some(col => col.name.toLowerCase() === 'id')) {
1383
+                        primaryKey = 'id';
1384
+                    }
1385
+                    // 检查表字段列表中是否有ID字段(大写)
1386
+                    else if (this.tableColumnsList.some(col => col.name === 'ID')) {
1387
+                        primaryKey = 'ID';
1388
+                    }
1389
+                    // 使用第一个存在的字段作为主键
1390
+                    else if (this.tableColumnsList.length > 0) {
1391
+                        const firstCol = this.tableColumnsList[0].name;
1392
+                        if (firstCol in row) {
1393
+                            primaryKey = firstCol;
1394
+                        }
1395
+                    }
1396
+                    
1397
+                    if (!primaryKey || !row[primaryKey]) {
1398
+                        this.completeContent = '无法确定主键字段或主键值为空';
1399
+                        return;
1400
+                    }
1401
+                    
1402
+                    // 构建查询SQL
1403
+                    const sql = `SELECT \`${column}\` FROM \`${this.selectedTable}\` WHERE \`${primaryKey}\`='${row[primaryKey]}';`;
1404
+                    
1405
+                    // 调用API获取完整数据
1406
+                    fetch('/api/RunKylx365DBSql', {
1407
+                        method: 'POST',
1408
+                        headers: {
1409
+                            'Content-Type': 'application/json',
1410
+                        },
1411
+                        body: JSON.stringify({
1412
+                            sql: sql,
1413
+                            IsCompleteField: true
1414
+                        })
1415
+                    })
1416
+                    .then(response => response.json())
1417
+                    .then(data => {
1418
+                        if (data && data.result && data.result.length > 0) {
1419
+                            this.completeContent = this.formatTableCell(data.result[0][column]);
1420
+                        } else {
1421
+                            this.completeContent = '未获取到完整数据';
1422
+                        }
1423
+                    })
1424
+                    .catch(error => {
1425
+                        this.completeContent = '获取完整数据失败: ' + error.message;
1426
+                    });
1427
+                },
1428
+                
1429
+                // 关闭完整内容弹出层
1430
+                closeCompleteContent() {
1431
+                    this.showCompleteContent = false;
1432
+                    this.completeContent = '';
1433
+                    this.currentRow = null;
1434
+                    this.currentColumn = null;
1435
+                },
1436
+                
1437
+                // 复制到剪贴板
1438
+                copyToClipboard(text) {
1439
+                    navigator.clipboard.writeText(text).then(() => {
1440
+                        this.showToastMessage('已复制到剪贴板', 'success');
1441
+                    }).catch(err => {
1442
+                        this.showToastMessage('复制失败: ' + err, 'error');
1443
+                    });
1444
+                },
1445
+                
1239 1446
                 // 显示提示消息
1240 1447
                 showToastMessage(message, type = 'info') {
1241 1448
                     this.toastMessage = message;