feat: 调整key 卡片样式
This commit is contained in:
@@ -91,7 +91,7 @@ const mockAPIKeys: APIKey[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
group_id: 2,
|
group_id: 1,
|
||||||
key_value: "gk-1234567890abcdef1234567890abcdef",
|
key_value: "gk-1234567890abcdef1234567890abcdef",
|
||||||
status: "active",
|
status: "active",
|
||||||
request_count: 450,
|
request_count: 450,
|
||||||
@@ -102,7 +102,51 @@ const mockAPIKeys: APIKey[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
group_id: 3,
|
group_id: 1,
|
||||||
|
key_value: "sf-1234567890abcdef1234567890abcdef",
|
||||||
|
status: "active",
|
||||||
|
request_count: 320,
|
||||||
|
failure_count: 0,
|
||||||
|
last_used_at: "2024-01-03T09:00:00Z",
|
||||||
|
created_at: "2024-01-03T00:00:00Z",
|
||||||
|
updated_at: "2024-01-03T00:00:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
group_id: 1,
|
||||||
|
key_value: "sf-1234567890abcdef1234567890abcdef",
|
||||||
|
status: "active",
|
||||||
|
request_count: 320,
|
||||||
|
failure_count: 0,
|
||||||
|
last_used_at: "2024-01-03T09:00:00Z",
|
||||||
|
created_at: "2024-01-03T00:00:00Z",
|
||||||
|
updated_at: "2024-01-03T00:00:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
group_id: 1,
|
||||||
|
key_value: "sf-1234567890abcdef1234567890abcdef",
|
||||||
|
status: "active",
|
||||||
|
request_count: 320,
|
||||||
|
failure_count: 0,
|
||||||
|
last_used_at: "2024-01-03T09:00:00Z",
|
||||||
|
created_at: "2024-01-03T00:00:00Z",
|
||||||
|
updated_at: "2024-01-03T00:00:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
group_id: 1,
|
||||||
|
key_value: "sf-1234567890abcdef1234567890abcdef",
|
||||||
|
status: "active",
|
||||||
|
request_count: 320,
|
||||||
|
failure_count: 0,
|
||||||
|
last_used_at: "2024-01-03T09:00:00Z",
|
||||||
|
created_at: "2024-01-03T00:00:00Z",
|
||||||
|
updated_at: "2024-01-03T00:00:00Z",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
group_id: 1,
|
||||||
key_value: "sf-1234567890abcdef1234567890abcdef",
|
key_value: "sf-1234567890abcdef1234567890abcdef",
|
||||||
status: "active",
|
status: "active",
|
||||||
request_count: 320,
|
request_count: 320,
|
||||||
|
@@ -79,9 +79,8 @@ function copyKey(key: APIKey) {
|
|||||||
async function testKey(_key: APIKey) {
|
async function testKey(_key: APIKey) {
|
||||||
try {
|
try {
|
||||||
window.$message.info("正在测试密钥...");
|
window.$message.info("正在测试密钥...");
|
||||||
// TODO: 实现密钥测试 API
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||||
const success = Math.random() > 0.3; // 模拟测试结果
|
const success = Math.random() > 0.3;
|
||||||
if (success) {
|
if (success) {
|
||||||
window.$message.success("密钥测试成功");
|
window.$message.success("密钥测试成功");
|
||||||
} else {
|
} else {
|
||||||
@@ -94,7 +93,6 @@ async function testKey(_key: APIKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleKeyVisibility(key: APIKey) {
|
function toggleKeyVisibility(key: APIKey) {
|
||||||
// TODO: 实现密钥显示/隐藏切换
|
|
||||||
window.$message.info(`切换密钥"${maskKey(key.key_value)}"显示状态功能开发中`);
|
window.$message.info(`切换密钥"${maskKey(key.key_value)}"显示状态功能开发中`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,10 +130,6 @@ async function deleteKey(key: APIKey) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDate(date: string) {
|
|
||||||
return new Date(date).toLocaleDateString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatRelativeTime(date: string) {
|
function formatRelativeTime(date: string) {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const target = new Date(date);
|
const target = new Date(date);
|
||||||
@@ -152,19 +146,6 @@ function formatRelativeTime(date: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStatusText(status: "active" | "inactive" | "error") {
|
|
||||||
switch (status) {
|
|
||||||
case "active":
|
|
||||||
return "有效";
|
|
||||||
case "inactive":
|
|
||||||
return "无效";
|
|
||||||
case "error":
|
|
||||||
return "错误";
|
|
||||||
default:
|
|
||||||
return "未知";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatusClass(status: "active" | "inactive" | "error") {
|
function getStatusClass(status: "active" | "inactive" | "error") {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "active":
|
case "active":
|
||||||
@@ -260,7 +241,6 @@ async function restoreAllInvalid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: 实现恢复所有无效密钥 API
|
|
||||||
window.$message.success("所有无效密钥已恢复");
|
window.$message.success("所有无效密钥已恢复");
|
||||||
await loadKeys();
|
await loadKeys();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -295,7 +275,6 @@ async function clearAllInvalid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: 实现清除所有无效密钥 API
|
|
||||||
window.$message.success("所有无效密钥已清除");
|
window.$message.success("所有无效密钥已清除");
|
||||||
await loadKeys();
|
await loadKeys();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -350,78 +329,58 @@ function changePageSize(size: number) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 密钥表格 -->
|
<!-- 密钥卡片网格 -->
|
||||||
<div class="table-container">
|
<div class="keys-grid-container">
|
||||||
<table class="key-table">
|
<div v-if="loading" class="loading-state">
|
||||||
<thead>
|
<div class="loading-spinner">加载中...</div>
|
||||||
<tr>
|
</div>
|
||||||
<th class="key-column">密钥 (Key)</th>
|
<div v-else-if="keys.length === 0" class="empty-state">
|
||||||
<th class="status-column">状态</th>
|
<div class="empty-text">没有找到匹配的密钥</div>
|
||||||
<th class="usage-column">24小时请求</th>
|
</div>
|
||||||
<th class="last-used-column">最后使用</th>
|
<div v-else class="keys-grid">
|
||||||
<th class="created-column">创建时间</th>
|
<div v-for="key in keys" :key="key.id" class="key-card" :class="getStatusClass(key.status)">
|
||||||
<th class="actions-column">操作</th>
|
<!-- 主要信息行:Key + 快速操作 -->
|
||||||
</tr>
|
<div class="key-main">
|
||||||
</thead>
|
<div class="key-section">
|
||||||
<tbody>
|
<span class="key-text" :title="key.key_value">{{ maskKey(key.key_value) }}</span>
|
||||||
<tr v-if="loading" class="loading-row">
|
<div class="quick-actions">
|
||||||
<td colspan="6" class="loading-cell">
|
<button @click="toggleKeyVisibility(key)" class="quick-btn" title="显示/隐藏">
|
||||||
<div class="loading-spinner">加载中...</div>
|
👁️
|
||||||
</td>
|
</button>
|
||||||
</tr>
|
<button @click="copyKey(key)" class="quick-btn" title="复制">📋</button>
|
||||||
<tr v-else-if="keys.length === 0" class="empty-row">
|
|
||||||
<td colspan="6" class="empty-cell">
|
|
||||||
<div class="empty-text">没有找到匹配的密钥</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr v-else v-for="key in keys" :key="key.id" class="key-row">
|
|
||||||
<td class="key-column">
|
|
||||||
<div class="key-content">
|
|
||||||
<span class="key-text" :title="key.key_value">{{ maskKey(key.key_value) }}</span>
|
|
||||||
<div class="key-actions">
|
|
||||||
<button @click="copyKey(key)" class="key-btn" title="复制">
|
|
||||||
<span class="icon">📋</span>
|
|
||||||
</button>
|
|
||||||
<button @click="toggleKeyVisibility(key)" class="key-btn" title="显示/隐藏">
|
|
||||||
<span class="icon">👁️</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
<td class="status-column">
|
</div>
|
||||||
<span :class="['status-badge', getStatusClass(key.status)]">
|
|
||||||
{{ getStatusText(key.status) }}
|
<!-- 统计信息 + 操作按钮行 -->
|
||||||
|
<div class="key-bottom">
|
||||||
|
<div class="key-stats">
|
||||||
|
<span class="stat-item">
|
||||||
|
请求
|
||||||
|
<strong>{{ key.request_count }}</strong>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
<span class="stat-item">
|
||||||
<td class="usage-column">
|
失败
|
||||||
<span class="usage-text">{{ key.request_count }} / {{ key.failure_count }}</span>
|
<strong>{{ key.failure_count }}</strong>
|
||||||
</td>
|
</span>
|
||||||
<td class="last-used-column">
|
<span class="stat-item">
|
||||||
<span class="time-text">
|
|
||||||
{{ key.last_used_at ? formatRelativeTime(key.last_used_at) : "从未使用" }}
|
{{ key.last_used_at ? formatRelativeTime(key.last_used_at) : "从未使用" }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</div>
|
||||||
<td class="created-column">
|
<div class="key-actions">
|
||||||
<span class="time-text">{{ formatDate(key.created_at) }}</span>
|
<button @click="testKey(key)" class="action-btn primary">测试</button>
|
||||||
</td>
|
<button
|
||||||
<td class="actions-column">
|
v-if="key.status !== 'active'"
|
||||||
<div class="action-buttons">
|
@click="restoreKey(key)"
|
||||||
<button @click="copyKey(key)" class="action-btn" title="复制">复制</button>
|
class="action-btn secondary"
|
||||||
<button @click="testKey(key)" class="action-btn" title="测试">测试</button>
|
>
|
||||||
<button
|
恢复
|
||||||
v-if="key.status !== 'active'"
|
</button>
|
||||||
@click="restoreKey(key)"
|
<button @click="deleteKey(key)" class="action-btn danger">删除</button>
|
||||||
class="action-btn"
|
</div>
|
||||||
title="恢复"
|
</div>
|
||||||
>
|
</div>
|
||||||
恢复
|
</div>
|
||||||
</button>
|
|
||||||
<button @click="deleteKey(key)" class="action-btn danger" title="删除">删除</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
@@ -606,183 +565,188 @@ function changePageSize(size: number) {
|
|||||||
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
|
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container {
|
/* 密钥卡片网格 */
|
||||||
|
.keys-grid-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-table {
|
.keys-grid {
|
||||||
width: 100%;
|
display: grid;
|
||||||
border-collapse: collapse;
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-card {
|
||||||
background: white;
|
background: white;
|
||||||
font-size: 13px;
|
border: 1px solid #e9ecef;
|
||||||
}
|
border-radius: 6px;
|
||||||
|
padding: 12px;
|
||||||
.key-table th,
|
transition: all 0.2s;
|
||||||
.key-table td {
|
|
||||||
padding: 8px 12px;
|
|
||||||
text-align: left;
|
|
||||||
border-bottom: 1px solid #e9ecef;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-table th {
|
|
||||||
background: #f8f9fa;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #495057;
|
|
||||||
font-size: 12px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-column {
|
|
||||||
width: 35%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-column {
|
|
||||||
width: 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.usage-column {
|
|
||||||
width: 15%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.last-used-column {
|
|
||||||
width: 15%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.created-column {
|
|
||||||
width: 15%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions-column {
|
|
||||||
width: 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-content {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-card:hover {
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 状态相关样式 */
|
||||||
|
.key-card.status-valid {
|
||||||
|
border-color: #10a37f;
|
||||||
|
background: #f8fff9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-card.status-invalid {
|
||||||
|
border-color: #dc3545;
|
||||||
|
background: #fff5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-card.status-error {
|
||||||
|
border-color: #ffc107;
|
||||||
|
background: #fffdf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主要信息行 */
|
||||||
|
.key-main {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-text {
|
.key-section {
|
||||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
display: flex;
|
||||||
font-size: 12px;
|
align-items: center;
|
||||||
color: #495057;
|
gap: 8px;
|
||||||
background: #f8f9fa;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 3px;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 底部统计和按钮行 */
|
||||||
|
.key-bottom {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-stats {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #6c757d;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item strong {
|
||||||
|
color: #495057;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.key-actions {
|
.key-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2px;
|
gap: 4px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-btn {
|
.key-text {
|
||||||
padding: 2px 4px;
|
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #495057;
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-btn {
|
||||||
|
padding: 4px 6px;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
transition: background-color 0.2s;
|
transition: background-color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-btn:hover {
|
.quick-btn:hover {
|
||||||
background: #e9ecef;
|
background: #e9ecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.key-btn .icon {
|
/* 统计信息行 */
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 10px;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: 600;
|
|
||||||
text-align: center;
|
|
||||||
min-width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-valid {
|
|
||||||
background: #d4edda;
|
|
||||||
color: #155724;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-invalid {
|
|
||||||
background: #f8d7da;
|
|
||||||
color: #721c24;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-error {
|
|
||||||
background: #fff3cd;
|
|
||||||
color: #856404;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-unknown {
|
|
||||||
background: #d1ecf1;
|
|
||||||
color: #0c5460;
|
|
||||||
}
|
|
||||||
|
|
||||||
.usage-text {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #495057;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-text {
|
|
||||||
font-size: 11px;
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
display: flex;
|
|
||||||
gap: 2px;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-btn {
|
.action-btn {
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
border: none;
|
border: 1px solid #dee2e6;
|
||||||
|
background: white;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
|
font-weight: 500;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background: #f8f9fa;
|
|
||||||
color: #495057;
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn:hover {
|
.action-btn:hover {
|
||||||
background: #e9ecef;
|
background: #f8f9fa;
|
||||||
border-color: #adb5bd;
|
}
|
||||||
|
|
||||||
|
.action-btn.primary {
|
||||||
|
border-color: #007bff;
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.primary:hover {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.secondary {
|
||||||
|
border-color: #6c757d;
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn.secondary:hover {
|
||||||
|
background: #6c757d;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.danger {
|
.action-btn.danger {
|
||||||
|
border-color: #dc3545;
|
||||||
color: #dc3545;
|
color: #dc3545;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn.danger:hover {
|
.action-btn.danger:hover {
|
||||||
background: #f8d7da;
|
background: #dc3545;
|
||||||
border-color: #dc3545;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-row,
|
/* 加载和空状态 */
|
||||||
.empty-row {
|
.loading-state,
|
||||||
height: 80px;
|
.empty-state {
|
||||||
}
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
.loading-cell,
|
align-items: center;
|
||||||
.empty-cell {
|
height: 200px;
|
||||||
text-align: center;
|
|
||||||
vertical-align: middle;
|
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,6 +758,7 @@ function changePageSize(size: number) {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 分页 */
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -823,6 +788,13 @@ function changePageSize(size: number) {
|
|||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.keys-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -834,15 +806,21 @@ function changePageSize(size: number) {
|
|||||||
.toolbar-right {
|
.toolbar-right {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.action-buttons {
|
@media (max-width: 768px) {
|
||||||
flex-direction: column;
|
.keys-grid {
|
||||||
gap: 1px;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn {
|
.key-bottom {
|
||||||
font-size: 9px;
|
flex-direction: column;
|
||||||
padding: 1px 4px;
|
align-items: flex-start;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-actions {
|
||||||
|
align-self: flex-end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Reference in New Issue
Block a user