5353 </el-button >
5454 </div >
5555
56+ <div class =" server-search" >
57+ <el-input
58+ v-model =" searchQuery"
59+ placeholder =" 搜索服务器..."
60+ clearable
61+ :prefix-icon =" Search"
62+ />
63+ </div >
64+
5665 <div class =" server-list" >
5766 <el-tree
5867 :data =" serverTree"
5968 node-key =" id"
6069 :default-expanded-keys =" expandedKeys"
6170 :expand-on-click-node =" false"
6271 @node-click =" handleServerClick"
72+ @node-dblclick =" handleServerDblClick"
6373 @node-expand =" handleNodeExpand"
6474 @node-collapse =" handleNodeCollapse"
6575 >
178188import { ref , computed , onMounted } from ' vue'
179189import { useRouter } from ' vue-router'
180190import { ElMessage , ElMessageBox } from ' element-plus'
181- import { Plus , Folder , Monitor , Connection , Lock , More , Edit , Delete , User , SwitchButton , UserFilled } from ' @element-plus/icons-vue'
191+ import { Plus , Folder , Monitor , Connection , Lock , More , Edit , Delete , User , SwitchButton , UserFilled , Search } from ' @element-plus/icons-vue'
182192import { useServersStore } from ' @/stores/servers'
183193import { useAuthStore } from ' @/stores/auth'
184194import ServerForm from ' @/components/ServerForm.vue'
@@ -191,6 +201,7 @@ const showAddServerDialog = ref(false)
191201const showEditServerDialog = ref (false )
192202const editingServerId = ref (null )
193203const editingServerName = ref (' ' )
204+ const searchQuery = ref (' ' )
194205
195206// 分组展开状态持久化 (sessionStorage)
196207const EXPANDED_KEYS_STORAGE_KEY = ' webssh_dashboard_expanded_keys'
@@ -216,8 +227,18 @@ const handleNodeCollapse = (data) => {
216227const serverTree = computed (() => {
217228 const groups = {}
218229
230+ let filteredServers = serversStore .servers
231+ if (searchQuery .value ) {
232+ const q = searchQuery .value .toLowerCase ()
233+ filteredServers = filteredServers .filter (server => {
234+ return server .name ? .toLowerCase ().includes (q) ||
235+ server .host ? .toLowerCase ().includes (q) ||
236+ server .group_name ? .toLowerCase ().includes (q)
237+ })
238+ }
239+
219240 // 按分组组织服务器
220- serversStore . servers .forEach (server => {
241+ filteredServers .forEach (server => {
221242 const groupName = server .group_name || ' Default'
222243 if (! groups[groupName]) {
223244 groups[groupName] = []
@@ -243,9 +264,18 @@ const serverTree = computed(() => {
243264})
244265
245266// 处理服务器点击
246- const handleServerClick = (data ) => {
267+ const handleServerClick = (data , node ) => {
247268 if (data .type === ' server' ) {
248269 router .push (` /terminal/${ data .serverId } ` )
270+ } else if (data .type === ' group' && node) {
271+ node .expanded = ! node .expanded
272+ }
273+ }
274+
275+ // 处理服务器双击
276+ const handleServerDblClick = (data , node ) => {
277+ if (data .type === ' group' && node) {
278+ node .expanded = ! node .expanded
249279 }
250280}
251281
@@ -393,9 +423,11 @@ onMounted(async () => {
393423}
394424
395425.sidebar {
396- background : white ;
397- border-right : 1px solid #e4e7ed ;
398- padding : 20px ;
426+ background: rgba (255 , 255 , 255 , 0.65 );
427+ backdrop- filter: blur (20px );
428+ - webkit- backdrop- filter: blur (20px );
429+ border- right: 1px solid rgba (0 , 0 , 0 , 0.1 );
430+ padding: 24px 20px ;
399431 display: flex;
400432 flex- direction: column;
401433}
@@ -404,13 +436,39 @@ onMounted(async () => {
404436 display: flex;
405437 justify- content: space- between;
406438 align- items: center;
407- margin-bottom : 20 px ;
439+ margin- bottom: 24px ;
408440}
409441
410442.sidebar - header h2 {
411443 margin: 0 ;
412- color : #333 ;
444+ color: #1c1c1e ;
413445 font- size: 18px ;
446+ font- weight: 600 ;
447+ letter- spacing: - 0 .5px ;
448+ font- family: - apple- system, BlinkMacSystemFont, " Segoe UI" , Roboto, Helvetica, Arial, sans- serif;
449+ }
450+
451+ .server - search {
452+ margin- bottom: 20px ;
453+ }
454+
455+ .server - search : deep (.el - input__wrapper ) {
456+ background- color: rgba (0 , 0 , 0 , 0.05 );
457+ border- radius: 8px ;
458+ box- shadow: none ! important;
459+ border: 1px solid rgba (0 , 0 , 0 , 0.08 );
460+ transition: all 0 .2s ;
461+ }
462+
463+ .server - search : deep (.el - input__wrapper .is - focus ) {
464+ background- color: rgba (255 , 255 , 255 , 1 );
465+ border- color: #007AFF ;
466+ box- shadow: 0 0 0 3px rgba (0 , 122 , 255 , 0.2 ) ! important;
467+ }
468+
469+ .server - search : deep (.el - input__inner ) {
470+ color: #1c1c1e ;
471+ font- family: - apple- system, BlinkMacSystemFont, " Segoe UI" , Roboto, Helvetica, Arial, sans- serif;
414472}
415473
416474.server - list {
@@ -420,11 +478,48 @@ onMounted(async () => {
420478}
421479
422480/* 树形组件样式调整 */
481+ : deep (.el - tree ) {
482+ background: transparent;
483+ }
484+
423485: deep (.el - tree - node__content ) {
424- height : 56px !important ;
425- padding : 0 16px !important ;
426- margin-bottom : 0 !important ;
427- transition : all 0.3s ease !important ;
486+ height: auto ! important;
487+ padding: 4px 8px ! important;
488+ margin- bottom: 2px ! important;
489+ border- radius: 8px ;
490+ transition: all 0 .2s ease ! important;
491+ }
492+
493+ : deep (.el - tree - node__content : hover ) {
494+ background- color: rgba (0 , 0 , 0 , 0.06 ) ! important;
495+ }
496+
497+ : deep (.el - tree- node .is - current > .el - tree- node__content: has (.server - node)) {
498+ background- color: #007AFF ! important;
499+ color: white;
500+ }
501+
502+ : deep (.el - tree- node .is - current > .el - tree- node__content: has (.group - node)) {
503+ background- color: transparent ! important;
504+ }
505+
506+ : deep (.el - tree- node .is - current > .el - tree- node__content .server - node .server - name),
507+ : deep (.el - tree - node .is - current > .el - tree - node__content .server - node .server - address ) {
508+ color: white ! important;
509+ }
510+
511+ : deep (.el - tree - node .is - current > .el - tree - node__content .server - node .server - name : hover ) {
512+ color: white ! important;
513+ }
514+
515+ : deep (.el - tree - node .is - current > .el - tree - node__content .server - actions ) {
516+ background- color: transparent;
517+ border- color: rgba (255 , 255 , 255 , 0.4 );
518+ color: white;
519+ }
520+
521+ : deep (.el - tree - node .is - current > .el - tree - node__content .server - actions : hover ) {
522+ background- color: rgba (255 , 255 , 255 , 0.2 );
428523}
429524
430525: deep (.el - tree - node ) {
@@ -435,72 +530,76 @@ onMounted(async () => {
435530 display: flex;
436531 align- items: center;
437532 width: 100 % ;
438- padding : 6 px 0 ;
533+ padding: 2px 0 ;
439534 min- height: 48px ;
440535 box- sizing: border- box;
441536}
442537
443538.group - node {
444539 font- weight: 600 ;
445- color : #333 ;
446- padding : 8px 0 ;
447- min-height : 40px ;
540+ color: #1c1c1e ;
541+ padding: 8px 4px ;
542+ min- height: auto;
543+ font- family: - apple- system, BlinkMacSystemFont, " Segoe UI" , Roboto, Helvetica, Arial, sans- serif;
544+ display: flex;
545+ align- items: center;
546+ gap: 8px ;
448547}
449548
450549.server - node {
451550 display: flex;
452551 justify- content: space- between;
453552 align- items: center;
454553 width: 100 % ;
455- padding : 8px ;
456- border-radius : 4px ;
457- transition : all 0.3s ;
458- min-height : 56px ;
554+ padding: 6px ;
555+ border- radius: 6px ;
556+ min- height: auto;
459557 box- sizing: border- box;
460558}
461559
462560.server - node: hover {
463- background-color : #f5f7fa ;
561+ background- color: transparent; /* rely on node content hover */
464562}
465563
466564.server - info- wrapper {
467565 flex: 1 ;
468- margin : 0 8 px ;
566+ margin: 0 10px ;
469567 min- width: 0 ;
470568}
471569
472570.server - name {
473571 font- weight: 500 ;
474572 font- size: 14px ;
475- color : #333 ;
573+ color: #1c1c1e ;
476574 cursor: pointer;
477575 margin- bottom: 2px ;
576+ font- family: - apple- system, BlinkMacSystemFont, " Segoe UI" , Roboto, Helvetica, Arial, sans- serif;
478577}
479578
480579.server - name: hover {
481- color : #409eff ;
580+ color: #007AFF ;
482581}
483582
484583.server - address {
485584 font- size: 11px ;
486- color : #999 ;
487- opacity : 0.8 ;
585+ color: rgba ( 28 , 28 , 30 , 0.6 ) ;
586+ font - family : ui - monospace, SFMono - Regular, " SF Mono " , Menlo, Consolas, monospace ;
488587}
489588
490589.server - actions {
491590 padding: 4px 8px ;
492- border : 1px solid #dcdfe6 ;
493- border-radius : 4 px ;
494- background-color : white ;
495- color : #606266 ;
496- transition : all 0.3 s ;
591+ border: 1px solid rgba ( 0 , 0 , 0 , 0.1 ) ;
592+ border- radius: 6px ;
593+ background- color: rgba ( 255 , 255 , 255 , 0.8 ) ;
594+ color: #1c1c1e ;
595+ transition: all 0 .2s ;
497596 white- space: nowrap;
498597}
499598
500599.server - actions: hover {
501- border-color : #409eff ;
502- color : #409eff ;
503- background-color : #f0f7ff ;
600+ border- color: #007AFF ;
601+ color: #007AFF ;
602+ background- color: rgba ( 0 , 122 , 255 , 0.1 ) ;
504603}
505604
506605.action - text {
0 commit comments