ui(import-hub): 优化 skills.sh 卡片布局

- skills.sh 卡片改为列布局:
  顶部:图标+名称+URL(左侧)+ 访问按钮(右上)
  中部:URL 输入框(全宽)
  底部:检测名称预览 + 导入按钮(右下)
- 加大"说明"与平台卡片的间距(margin-top: space-xl)
- 导入按钮与名称预览在右侧同一行,间距更协调
This commit is contained in:
QihuAI Design committed 2026-07-16 16:00:35 +08:00
1 parent 0e6f1931e1
commit 4d27dd3429
2 files changed
+72 -39

No files matched your search

+33 -4
View File
@@ -1066,10 +1066,17 @@
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
.hub-platforms {
display: flex;
flex-direction: column;
gap: var(--space-md);
margin-top: var(--space-xl);
}
.hub-platform-card { .hub-platform-card {
display: flex; display: flex;
align-items: center; flex-direction: column;
justify-content: space-between; gap: var(--space-md);
padding: var(--space-md); padding: var(--space-md);
background: var(--color-bg-tertiary); background: var(--color-bg-tertiary);
border: 1px solid var(--color-border-light); border: 1px solid var(--color-border-light);
@@ -1081,10 +1088,18 @@
border-color: var(--color-accent-light); border-color: var(--color-accent-light);
} }
.hub-platform-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-md);
}
.hub-platform-info { .hub-platform-info {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-md); gap: var(--space-md);
min-width: 0;
} }
.hub-platform-icon { .hub-platform-icon {
@@ -1529,8 +1544,22 @@
.hub-import-col { .hub-import-col {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: var(--space-sm);
flex: 1; width: 100%;
}
.hub-import-actions {
display: flex;
align-items: center;
justify-content: flex-end;
gap: var(--space-sm);
min-height: 32px;
}
.hub-url-input.full {
width: 100%;
padding: var(--space-sm) var(--space-md);
font-size: var(--text-sm);
} }
.hub-name-preview { .hub-name-preview {
+39 -35
View File
@@ -1067,16 +1067,16 @@ const mcpClient = new MCPClient({
<div className="hub-platforms"> <div className="hub-platforms">
{platforms.map(p => ( {platforms.map(p => (
<div key={p.id} className="hub-platform-card"> <div key={p.id} className="hub-platform-card">
<div className="hub-platform-info"> <div className="hub-platform-header">
<div className="hub-platform-icon"> <div className="hub-platform-info">
<ImportIcon /> <div className="hub-platform-icon">
<ImportIcon />
</div>
<div>
<strong>{p.name}</strong>
<span className="hub-platform-url">{p.url}</span>
</div>
</div> </div>
<div>
<strong>{p.name}</strong>
<span className="hub-platform-url">{p.url}</span>
</div>
</div>
<div className="hub-platform-actions">
<button <button
className="hub-visit-btn" className="hub-visit-btn"
onClick={() => handleVisit(p.url)} onClick={() => handleVisit(p.url)}
@@ -1086,38 +1086,42 @@ const mcpClient = new MCPClient({
</svg> </svg>
访问 访问
</button> </button>
{appType === 'skill' ? ( </div>
{appType === 'skill' ? (
<>
<div className="hub-import-col"> <div className="hub-import-col">
<div className="hub-import-row"> <input
<input type="url"
type="url" className="hub-url-input full"
className="hub-url-input" placeholder="粘贴目标链接..."
placeholder="粘贴目标链接..." value={importUrl[p.id] || ''}
value={importUrl[p.id] || ''} onChange={e => setImportUrl(prev => ({ ...prev, [p.id]: e.target.value }))}
onChange={e => setImportUrl(prev => ({ ...prev, [p.id]: e.target.value }))} disabled={importingId === p.id}
disabled={importingId === p.id} />
/> <div className="hub-import-actions">
{importUrl[p.id]?.trim() && (
<span className="hub-name-preview">
检测名称: <strong>{extractSkillName(importUrl[p.id], p.name)}</strong>
</span>
)}
<button <button
className="hub-import-btn" className="hub-import-btn"
onClick={() => handleImport(p.id)} onClick={() => handleImport(p.id)}
disabled={!importUrl[p.id]?.trim() || importingId !== null} disabled={!importUrl[p.id]?.trim() || importingId !== null}
> >
{importingId === p.id ? ( {importingId === p.id ? (
<span className="hub-importing-text"> <span className="hub-importing-text">
<div className="audit-spinner tiny" /> <div className="audit-spinner tiny" />
{statusMsg} {statusMsg}
</span> </span>
) : '导入'} ) : '导入'}
</button> </button>
</div>
{importUrl[p.id]?.trim() && (
<div className="hub-name-preview">
检测名称: <strong>{extractSkillName(importUrl[p.id], p.name)}</strong>
</div> </div>
)} </div>
</div> </>
) : ( ) : (
<div className="hub-import-row"> <div className="hub-import-col">
<div className="hub-import-actions">
<button <button
className="hub-import-btn" className="hub-import-btn"
onClick={() => handleImport(p.id)} onClick={() => handleImport(p.id)}
@@ -1131,8 +1135,8 @@ const mcpClient = new MCPClient({
) : '导入'} ) : '导入'}
</button> </button>
</div> </div>
)} </div>
</div> )}
</div> </div>
))} ))}
</div> </div>