fix: page style
This commit is contained in:
@@ -110,7 +110,7 @@ const renderLineChart = () => {
|
|||||||
],
|
],
|
||||||
chart: {
|
chart: {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
height: 240,
|
height: 300,
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
animations: {
|
animations: {
|
||||||
@@ -221,7 +221,7 @@ const renderLineChart = () => {
|
|||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
responsive: [{ breakpoint: 768, options: { chart: { height: 200 }, legend: { position: 'bottom', offsetY: 0 } } }]
|
responsive: [{ breakpoint: 768, options: { chart: { height: 260 }, legend: { position: 'bottom', offsetY: 0 } } }]
|
||||||
}
|
}
|
||||||
lineChart = new ApexCharts(container, options)
|
lineChart = new ApexCharts(container, options)
|
||||||
lineChart.render()
|
lineChart.render()
|
||||||
@@ -247,7 +247,7 @@ const renderPieChart = () => {
|
|||||||
series: taskStats.value.map(item => item.count),
|
series: taskStats.value.map(item => item.count),
|
||||||
chart: {
|
chart: {
|
||||||
type: 'donut',
|
type: 'donut',
|
||||||
height: 200,
|
height: 260,
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
background: 'transparent',
|
background: 'transparent',
|
||||||
animations: {
|
animations: {
|
||||||
@@ -334,7 +334,7 @@ const renderPieChart = () => {
|
|||||||
style: { fontSize: '12px', fontFamily: 'Inter, sans-serif' },
|
style: { fontSize: '12px', fontFamily: 'Inter, sans-serif' },
|
||||||
y: { formatter: (val: number) => val + ' 次' }
|
y: { formatter: (val: number) => val + ' 次' }
|
||||||
},
|
},
|
||||||
responsive: [{ breakpoint: 768, options: { chart: { height: 200 }, legend: { position: 'bottom' } } }]
|
responsive: [{ breakpoint: 768, options: { chart: { height: 260 }, legend: { position: 'bottom' } } }]
|
||||||
}
|
}
|
||||||
pieChart = new ApexCharts(container, options)
|
pieChart = new ApexCharts(container, options)
|
||||||
pieChart.render()
|
pieChart.render()
|
||||||
@@ -401,13 +401,13 @@ onUnmounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-4 lg:grid-cols-10">
|
<div class="grid gap-4 lg:grid-cols-10">
|
||||||
<Card class="lg:col-span-7 h-[300px] sm:h-[340px]">
|
<Card class="lg:col-span-7 h-[400px] sm:h-[400px]">
|
||||||
<CardHeader class="pb-2">
|
<CardHeader class="pb-2">
|
||||||
<CardTitle class="text-base sm:text-lg">执行统计</CardTitle>
|
<CardTitle class="text-base sm:text-lg">执行统计</CardTitle>
|
||||||
<CardDescription class="text-xs sm:text-sm">最近{{ chartDays }}天任务执行情况</CardDescription>
|
<CardDescription class="text-xs sm:text-sm">最近{{ chartDays }}天任务执行情况</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent class="pb-8">
|
||||||
<div id="stats-chart" class="w-full h-[200px] sm:h-[240px]">
|
<div id="stats-chart" class="w-full h-[300px] sm:h-[300px]">
|
||||||
<div v-if="!chartsLoaded" class="h-full flex items-center justify-center text-muted-foreground text-sm">
|
<div v-if="!chartsLoaded" class="h-full flex items-center justify-center text-muted-foreground text-sm">
|
||||||
加载中...
|
加载中...
|
||||||
</div>
|
</div>
|
||||||
@@ -415,13 +415,13 @@ onUnmounted(() => {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card class="lg:col-span-3 h-[300px] sm:h-[340px]">
|
<Card class="lg:col-span-3 h-[400px] sm:h-[400px]">
|
||||||
<CardHeader class="pb-0">
|
<CardHeader class="pb-0">
|
||||||
<CardTitle class="text-base sm:text-lg">任务占比</CardTitle>
|
<CardTitle class="text-base sm:text-lg">任务占比</CardTitle>
|
||||||
<CardDescription class="text-xs sm:text-sm">最近{{ chartDays }}天任务执行分布</CardDescription>
|
<CardDescription class="text-xs sm:text-sm">最近{{ chartDays }}天任务执行分布</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent class="pt-0">
|
<CardContent class="pt-0 pb-8">
|
||||||
<div id="pie-chart" class="w-full h-[200px] sm:h-[240px]">
|
<div id="pie-chart" class="w-full h-[300px] sm:h-[300px]">
|
||||||
<div v-if="!chartsLoaded" class="h-full flex items-center justify-center text-muted-foreground text-sm">
|
<div v-if="!chartsLoaded" class="h-full flex items-center justify-center text-muted-foreground text-sm">
|
||||||
加载中...
|
加载中...
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,45 @@ const siteSubtitle = ref('轻量级定时任务管理系统')
|
|||||||
const siteIcon = ref('')
|
const siteIcon = ref('')
|
||||||
const demoMode = ref(false)
|
const demoMode = ref(false)
|
||||||
|
|
||||||
|
// 从 localStorage 加载缓存的站点设置
|
||||||
|
function loadCachedSettings() {
|
||||||
|
try {
|
||||||
|
const cached = localStorage.getItem('site_settings')
|
||||||
|
if (cached) {
|
||||||
|
const settings = JSON.parse(cached)
|
||||||
|
siteTitle.value = settings.title || '白虎面板'
|
||||||
|
siteSubtitle.value = settings.subtitle || '轻量级定时任务管理系统'
|
||||||
|
siteIcon.value = settings.icon || ''
|
||||||
|
demoMode.value = settings.demo_mode || false
|
||||||
|
document.title = siteTitle.value
|
||||||
|
|
||||||
|
// 设置 favicon
|
||||||
|
if (siteIcon.value && siteIcon.value.trim().startsWith('<svg')) {
|
||||||
|
const blob = new Blob([siteIcon.value], { type: 'image/svg+xml' })
|
||||||
|
const url = URL.createObjectURL(blob)
|
||||||
|
let link = document.querySelector("link[rel*='icon']") as HTMLLinkElement
|
||||||
|
if (!link) {
|
||||||
|
link = document.createElement('link')
|
||||||
|
link.rel = 'icon'
|
||||||
|
document.head.appendChild(link)
|
||||||
|
}
|
||||||
|
link.type = 'image/svg+xml'
|
||||||
|
link.href = url
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('加载缓存的站点设置失败:', e)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
async function loadSiteSettings() {
|
async function loadSiteSettings() {
|
||||||
|
// 先加载缓存
|
||||||
|
const hasCached = loadCachedSettings()
|
||||||
|
|
||||||
|
// 后台异步更新
|
||||||
try {
|
try {
|
||||||
const res = await api.settings.getPublicSite()
|
const res = await api.settings.getPublicSite()
|
||||||
siteTitle.value = res.title || '白虎面板'
|
siteTitle.value = res.title || '白虎面板'
|
||||||
@@ -27,11 +65,21 @@ async function loadSiteSettings() {
|
|||||||
siteIcon.value = res.icon || ''
|
siteIcon.value = res.icon || ''
|
||||||
demoMode.value = res.demo_mode || false
|
demoMode.value = res.demo_mode || false
|
||||||
document.title = siteTitle.value
|
document.title = siteTitle.value
|
||||||
|
|
||||||
|
// 保存到 localStorage
|
||||||
|
localStorage.setItem('site_settings', JSON.stringify({
|
||||||
|
title: siteTitle.value,
|
||||||
|
subtitle: siteSubtitle.value,
|
||||||
|
icon: siteIcon.value,
|
||||||
|
demo_mode: demoMode.value
|
||||||
|
}))
|
||||||
|
|
||||||
// 演示模式下自动填充账号密码
|
// 演示模式下自动填充账号密码
|
||||||
if (demoMode.value) {
|
if (demoMode.value) {
|
||||||
username.value = 'admin'
|
username.value = 'admin'
|
||||||
password.value = '123456'
|
password.value = '123456'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 favicon
|
// 设置 favicon
|
||||||
if (siteIcon.value && siteIcon.value.trim().startsWith('<svg')) {
|
if (siteIcon.value && siteIcon.value.trim().startsWith('<svg')) {
|
||||||
const blob = new Blob([siteIcon.value], { type: 'image/svg+xml' })
|
const blob = new Blob([siteIcon.value], { type: 'image/svg+xml' })
|
||||||
@@ -46,7 +94,11 @@ async function loadSiteSettings() {
|
|||||||
link.href = url
|
link.href = url
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// 使用默认值
|
// 如果没有缓存,使用默认值
|
||||||
|
if (!hasCached) {
|
||||||
|
siteTitle.value = '白虎面板'
|
||||||
|
siteSubtitle.value = '轻量级定时任务管理系统'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -232,14 +232,14 @@ async function save() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-2 sm:gap-3">
|
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-2 sm:gap-3">
|
||||||
<Label class="sm:text-right text-sm">超时/清理</Label>
|
<Label class="sm:text-right text-sm">超时/清理</Label>
|
||||||
<div class="sm:col-span-3 flex flex-wrap items-center gap-3">
|
<div class="sm:col-span-3 flex flex-wrap items-center gap-2">
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<Input v-model.number="form.timeout" type="number" placeholder="30" class="w-16 h-8 text-sm" />
|
<Input v-model.number="form.timeout" type="number" placeholder="30" class="w-20 h-9 text-sm" />
|
||||||
<span class="text-xs text-muted-foreground">分钟</span>
|
<span class="text-sm text-muted-foreground whitespace-nowrap">分钟</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<Select :model-value="cleanType" @update:model-value="(v) => cleanType = String(v || 'none')">
|
<Select :model-value="cleanType" @update:model-value="(v) => cleanType = String(v || 'none')">
|
||||||
<SelectTrigger class="w-20 h-8 text-sm">
|
<SelectTrigger class="w-24 h-9 text-sm">
|
||||||
<SelectValue placeholder="不清理" />
|
<SelectValue placeholder="不清理" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -248,7 +248,7 @@ async function save() {
|
|||||||
<SelectItem value="count">按条数</SelectItem>
|
<SelectItem value="count">按条数</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Input v-if="cleanType && cleanType !== 'none'" v-model.number="cleanKeep" type="number" :placeholder="cleanType === 'day' ? '天' : '条'" class="w-14 h-8 text-sm" />
|
<Input v-if="cleanType && cleanType !== 'none'" v-model.number="cleanKeep" type="number" :placeholder="cleanType === 'day' ? '7' : '100'" class="w-20 h-9 text-sm" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -217,14 +217,14 @@ async function save() {
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-2 sm:gap-3">
|
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-2 sm:gap-3">
|
||||||
<Label class="sm:text-right text-sm">超时/清理</Label>
|
<Label class="sm:text-right text-sm">超时/清理</Label>
|
||||||
<div class="sm:col-span-3 flex flex-wrap items-center gap-3">
|
<div class="sm:col-span-3 flex flex-wrap items-center gap-2">
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<Input v-model.number="form.timeout" type="number" placeholder="30" class="w-16 h-8 text-sm" />
|
<Input v-model.number="form.timeout" type="number" placeholder="30" class="w-20 h-9 text-sm" />
|
||||||
<span class="text-xs text-muted-foreground">分钟</span>
|
<span class="text-sm text-muted-foreground whitespace-nowrap">分钟</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<Select :model-value="cleanType" @update:model-value="(v) => cleanType = String(v || 'none')">
|
<Select :model-value="cleanType" @update:model-value="(v) => cleanType = String(v || 'none')">
|
||||||
<SelectTrigger class="w-20 h-8 text-sm">
|
<SelectTrigger class="w-24 h-9 text-sm">
|
||||||
<SelectValue placeholder="不清理" />
|
<SelectValue placeholder="不清理" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -233,7 +233,7 @@ async function save() {
|
|||||||
<SelectItem value="count">按条数</SelectItem>
|
<SelectItem value="count">按条数</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Input v-if="cleanType && cleanType !== 'none'" v-model.number="cleanKeep" type="number" :placeholder="cleanType === 'day' ? '天' : '条'" class="w-14 h-8 text-sm" />
|
<Input v-if="cleanType && cleanType !== 'none'" v-model.number="cleanKeep" type="number" :placeholder="cleanType === 'day' ? '7' : '100'" class="w-20 h-9 text-sm" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user