group info
This commit is contained in:
@@ -15,7 +15,7 @@ export const keysApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 更新分组
|
// 更新分组
|
||||||
async updateGroup(groupId: number, group: Partial<Group>): Promise<void> {
|
async updateGroup(groupId: number, group: Partial<Group>): Promise<Group> {
|
||||||
const res = await http.put(`/groups/${groupId}`, group);
|
const res = await http.put(`/groups/${groupId}`, group);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
@@ -203,20 +203,4 @@ onMounted(() => {
|
|||||||
:deep(.n-grid-item) {
|
:deep(.n-grid-item) {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
|
||||||
:deep(.n-grid) {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
:deep(.n-grid) {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-value {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -180,13 +180,4 @@ function handleClose() {
|
|||||||
border-radius: var(--border-radius-sm);
|
border-radius: var(--border-radius-sm);
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.global-task-progress {
|
|
||||||
left: 20px;
|
|
||||||
right: 20px;
|
|
||||||
width: auto;
|
|
||||||
top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -97,8 +97,6 @@ import NavBar from "@/components/NavBar.vue";
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content-wrapper {
|
.content-wrapper {
|
||||||
width: 1400px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 24px 12px;
|
padding: 24px 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -248,18 +248,4 @@ onMounted(() => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
backdrop-filter: blur(4px);
|
backdrop-filter: blur(4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.chart-legend {
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-area {
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-svg {
|
|
||||||
height: 160px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -24,7 +24,7 @@ interface Props {
|
|||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: "update:show", value: boolean): void;
|
(e: "update:show", value: boolean): void;
|
||||||
(e: "success"): void;
|
(e: "success", value: Group): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置项类型
|
// 配置项类型
|
||||||
@@ -138,8 +138,8 @@ function loadGroupData() {
|
|||||||
: [{ url: "", weight: 1 }],
|
: [{ url: "", weight: 1 }],
|
||||||
channel_type: props.group.channel_type || "openai",
|
channel_type: props.group.channel_type || "openai",
|
||||||
sort: props.group.sort || 1,
|
sort: props.group.sort || 1,
|
||||||
test_model: props.group.config?.test_model || "",
|
test_model: props.group.test_model || "",
|
||||||
param_overrides: JSON.stringify(props.group.config?.param_overrides || {}, null, 2),
|
param_overrides: JSON.stringify(props.group.param_overrides || {}, null, 2),
|
||||||
config: {},
|
config: {},
|
||||||
configItems,
|
configItems,
|
||||||
});
|
});
|
||||||
@@ -241,17 +241,18 @@ async function handleSubmit() {
|
|||||||
config,
|
config,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let res: Group;
|
||||||
if (props.group?.id) {
|
if (props.group?.id) {
|
||||||
// 编辑模式
|
// 编辑模式
|
||||||
await keysApi.updateGroup(props.group.id, submitData);
|
res = await keysApi.updateGroup(props.group.id, submitData);
|
||||||
message.success("分组更新成功");
|
message.success("分组更新成功");
|
||||||
} else {
|
} else {
|
||||||
// 新建模式
|
// 新建模式
|
||||||
await keysApi.createGroup(submitData);
|
res = await keysApi.createGroup(submitData);
|
||||||
message.success("分组创建成功");
|
message.success("分组创建成功");
|
||||||
}
|
}
|
||||||
|
|
||||||
emit("success");
|
emit("success", res);
|
||||||
handleClose();
|
handleClose();
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
@@ -7,25 +7,32 @@ import {
|
|||||||
NCard,
|
NCard,
|
||||||
NCollapse,
|
NCollapse,
|
||||||
NCollapseItem,
|
NCollapseItem,
|
||||||
NDescriptions,
|
NFlex,
|
||||||
NDescriptionsItem,
|
NForm,
|
||||||
NGrid,
|
NFormItem,
|
||||||
NGridItem,
|
|
||||||
NSpin,
|
NSpin,
|
||||||
NTag,
|
NTag,
|
||||||
useMessage,
|
useMessage,
|
||||||
} from "naive-ui";
|
} from "naive-ui";
|
||||||
import { onMounted, ref, watch } from "vue";
|
import { onMounted, ref, watch } from "vue";
|
||||||
|
import GroupFormModal from "./GroupFormModal.vue";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
group: Group | null;
|
group: Group | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: "refresh", value: Group): void;
|
||||||
|
}
|
||||||
|
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
const stats = ref<GroupStats | null>(null);
|
const stats = ref<GroupStats | null>(null);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const message = useMessage();
|
const message = useMessage();
|
||||||
|
const showEditModal = ref(false);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loadStats();
|
loadStats();
|
||||||
@@ -53,7 +60,14 @@ async function loadStats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleEdit() {
|
function handleEdit() {
|
||||||
message.info("编辑分组功能开发中...");
|
showEditModal.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleGroupEdited(newGroup: Group) {
|
||||||
|
showEditModal.value = false;
|
||||||
|
if (newGroup) {
|
||||||
|
emit("refresh", newGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDelete() {
|
function handleDelete() {
|
||||||
@@ -136,16 +150,10 @@ function copyUrl(url: string) {
|
|||||||
<!-- 统计摘要区 -->
|
<!-- 统计摘要区 -->
|
||||||
<div class="stats-summary">
|
<div class="stats-summary">
|
||||||
<n-spin :show="loading" size="small">
|
<n-spin :show="loading" size="small">
|
||||||
<n-grid :cols="5" :x-gap="12" :y-gap="12" responsive="screen">
|
<n-flex class="status-cards-container">
|
||||||
<n-grid-item span="1">
|
<n-card :title="`${stats?.active_keys || 0} / ${stats?.total_keys || 0}`" size="large">
|
||||||
<n-card
|
|
||||||
:title="`${stats?.active_keys || 0} / ${stats?.total_keys || 0}`"
|
|
||||||
size="large"
|
|
||||||
>
|
|
||||||
<template #header-extra><span class="status-title">密钥数量</span></template>
|
<template #header-extra><span class="status-title">密钥数量</span></template>
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-grid-item>
|
|
||||||
<n-grid-item span="1">
|
|
||||||
<n-card
|
<n-card
|
||||||
class="status-card-failure"
|
class="status-card-failure"
|
||||||
:title="formatPercentage(stats?.failure_rate_24h || 0)"
|
:title="formatPercentage(stats?.failure_rate_24h || 0)"
|
||||||
@@ -153,23 +161,16 @@ function copyUrl(url: string) {
|
|||||||
>
|
>
|
||||||
<template #header-extra><span class="status-title">失败率</span></template>
|
<template #header-extra><span class="status-title">失败率</span></template>
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-grid-item>
|
|
||||||
<n-grid-item span="1">
|
|
||||||
<n-card :title="formatNumber(stats?.requests_1h || 0)" size="large">
|
<n-card :title="formatNumber(stats?.requests_1h || 0)" size="large">
|
||||||
<template #header-extra><span class="status-title">近1小时</span></template>
|
<template #header-extra><span class="status-title">近1小时</span></template>
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-grid-item>
|
|
||||||
<n-grid-item span="1">
|
|
||||||
<n-card :title="formatNumber(stats?.requests_24h || 0)" size="large">
|
<n-card :title="formatNumber(stats?.requests_24h || 0)" size="large">
|
||||||
<template #header-extra><span class="status-title">近24小时</span></template>
|
<template #header-extra><span class="status-title">近24小时</span></template>
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-grid-item>
|
|
||||||
<n-grid-item span="1">
|
|
||||||
<n-card :title="formatNumber(stats?.requests_7d || 0)" size="large">
|
<n-card :title="formatNumber(stats?.requests_7d || 0)" size="large">
|
||||||
<template #header-extra><span class="status-title">近7天</span></template>
|
<template #header-extra><span class="status-title">近7天</span></template>
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-grid-item>
|
</n-flex>
|
||||||
</n-grid>
|
|
||||||
</n-spin>
|
</n-spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -180,61 +181,73 @@ function copyUrl(url: string) {
|
|||||||
<div class="details-content">
|
<div class="details-content">
|
||||||
<div class="detail-section">
|
<div class="detail-section">
|
||||||
<h4 class="section-title">基础信息</h4>
|
<h4 class="section-title">基础信息</h4>
|
||||||
<n-descriptions :column="2" size="small">
|
<n-form label-placement="left" label-width="100px">
|
||||||
<n-descriptions-item label="分组名称">
|
<n-form-item label="分组名称:">
|
||||||
{{ group?.name || "-" }}
|
{{ group?.name || "-" }}
|
||||||
</n-descriptions-item>
|
</n-form-item>
|
||||||
<n-descriptions-item label="渠道类型">
|
<n-form-item label="显示名称:">
|
||||||
{{ group?.channel_type || "openai" }}
|
{{ group?.display_name || "-" }}
|
||||||
</n-descriptions-item>
|
</n-form-item>
|
||||||
<n-descriptions-item label="排序">{{ group?.sort || 0 }}</n-descriptions-item>
|
<n-form-item label="描述:">
|
||||||
<n-descriptions-item v-if="group?.description || ''" label="描述" :span="2">
|
{{ group?.description || "-" }}
|
||||||
{{ group?.description || "" }}
|
</n-form-item>
|
||||||
</n-descriptions-item>
|
<n-form-item label="渠道类型:">
|
||||||
</n-descriptions>
|
{{ group?.channel_type || "-" }}
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="测试模型:">
|
||||||
|
{{ group?.test_model || "-" }}
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="排序:">
|
||||||
|
{{ group?.sort || 0 }}
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="detail-section">
|
<div class="detail-section">
|
||||||
<h4 class="section-title">上游地址</h4>
|
<h4 class="section-title">上游地址</h4>
|
||||||
<n-descriptions :column="1" size="small">
|
<n-form label-placement="left" label-width="100px">
|
||||||
<n-descriptions-item
|
<n-form-item
|
||||||
v-for="(upstream, index) in group?.upstreams ?? []"
|
v-for="(upstream, index) in group?.upstreams ?? []"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="`上游 ${index + 1}`"
|
:label="`上游 ${index + 1}:`"
|
||||||
>
|
>
|
||||||
<span class="upstream-url">{{ upstream.url }}</span>
|
<span class="upstream-url">{{ upstream.url }}</span>
|
||||||
<n-tag size="small" type="info" class="upstream-weight">
|
<n-tag size="small" type="info" class="upstream-weight">
|
||||||
权重: {{ upstream.weight }}
|
权重: {{ upstream.weight }}
|
||||||
</n-tag>
|
</n-tag>
|
||||||
</n-descriptions-item>
|
</n-form-item>
|
||||||
</n-descriptions>
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="detail-section">
|
<div
|
||||||
<h4 class="section-title">配置信息</h4>
|
class="detail-section"
|
||||||
<n-descriptions :column="2" size="small">
|
v-if="
|
||||||
<n-descriptions-item v-if="group?.config?.test_model || ''" label="测试模型">
|
(group?.config && Object.keys(group.config).length > 0) || group?.param_overrides
|
||||||
{{ group?.config?.test_model || "" }}
|
"
|
||||||
</n-descriptions-item>
|
|
||||||
<n-descriptions-item v-if="group?.config?.request_timeout || 0" label="请求超时">
|
|
||||||
{{ group?.config?.request_timeout || 0 }}ms
|
|
||||||
</n-descriptions-item>
|
|
||||||
<n-descriptions-item
|
|
||||||
v-if="Object.keys(group?.config?.param_overrides || {}).length > 0"
|
|
||||||
label="参数覆盖"
|
|
||||||
:span="2"
|
|
||||||
>
|
>
|
||||||
|
<h4 class="section-title">高级配置</h4>
|
||||||
|
<n-form label-placement="left">
|
||||||
|
<n-form-item
|
||||||
|
v-for="(value, key) in group?.config || {}"
|
||||||
|
:key="key"
|
||||||
|
:label="`${key}:`"
|
||||||
|
>
|
||||||
|
{{ value || "-" }}
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item v-if="group?.param_overrides" label="参数覆盖:" :span="2">
|
||||||
<pre class="config-json">{{
|
<pre class="config-json">{{
|
||||||
JSON.stringify(group?.config?.param_overrides || "", null, 2)
|
JSON.stringify(group?.param_overrides || "", null, 2)
|
||||||
}}</pre>
|
}}</pre>
|
||||||
</n-descriptions-item>
|
</n-form-item>
|
||||||
</n-descriptions>
|
</n-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</n-collapse-item>
|
</n-collapse-item>
|
||||||
</n-collapse>
|
</n-collapse>
|
||||||
</div>
|
</div>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
|
<group-form-modal v-model:show="showEditModal" :group="group" @success="handleGroupEdited" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -305,6 +318,10 @@ function copyUrl(url: string) {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-cards-container:deep(.n-card) {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.status-card-failure .n-card-header__main) {
|
:deep(.status-card-failure .n-card-header__main) {
|
||||||
color: #d03050;
|
color: #d03050;
|
||||||
}
|
}
|
||||||
@@ -371,42 +388,7 @@ function copyUrl(url: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式网格 */
|
:deep(.n-form-item-feedback-wrapper) {
|
||||||
:deep(.n-grid) {
|
min-height: 0;
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.n-grid-item) {
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
:deep(.n-grid) {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-title {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
|
||||||
:deep(.n-grid) {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-actions {
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@@ -265,18 +265,4 @@ function handleGroupCreated() {
|
|||||||
.groups-list::-webkit-scrollbar-thumb:hover {
|
.groups-list::-webkit-scrollbar-thumb:hover {
|
||||||
background: rgba(0, 0, 0, 0.3);
|
background: rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.group-item {
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-name {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-meta {
|
|
||||||
font-size: 9px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -852,40 +852,4 @@ function changePageSize(size: number) {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 */
|
|
||||||
@media (max-width: 1200px) {
|
|
||||||
.keys-grid {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.toolbar {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: stretch;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toolbar-left,
|
|
||||||
.toolbar-right {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.keys-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-bottom {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.key-actions {
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -49,14 +49,4 @@ import { NSpace } from "naive-ui";
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.dashboard-title {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-subtitle {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -31,14 +31,17 @@ function handleGroupSelect(group: Group) {
|
|||||||
selectedGroup.value = group;
|
selectedGroup.value = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGroupRefresh() {
|
async function handleGroupRefresh() {
|
||||||
loadGroups();
|
await loadGroups();
|
||||||
|
if (selectedGroup.value) {
|
||||||
|
// 重新加载当前选中的分组信息
|
||||||
|
selectedGroup.value = groups.value.find(g => g.id === selectedGroup.value?.id) || null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="keys-container">
|
<div class="keys-container">
|
||||||
<div class="keys-content">
|
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<group-list
|
<group-list
|
||||||
:groups="groups"
|
:groups="groups"
|
||||||
@@ -62,28 +65,13 @@ function handleGroupRefresh() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.page-header {
|
.keys-container {
|
||||||
margin-bottom: 12px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
border-bottom: 1px solid #e9ecef;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keys-content {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
flex: 1;
|
width: 100%;
|
||||||
min-height: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@@ -97,7 +85,6 @@ function handleGroupRefresh() {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
min-width: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-info {
|
.group-info {
|
||||||
@@ -110,18 +97,4 @@ function handleGroupRefresh() {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
|
||||||
.keys-content {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -99,19 +99,4 @@ import { NCard, NH3, NSpace, NTag, NText } from "naive-ui";
|
|||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.placeholder-card {
|
|
||||||
margin: 0 16px;
|
|
||||||
padding: 32px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-title {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-subtitle {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
Reference in New Issue
Block a user