feat: 静态首页
parent
68beb08f90
commit
3f3366fde4
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div
|
||||
ref="chartRef"
|
||||
class="w-full h-full"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const props = defineProps({
|
||||
option: Object,
|
||||
});
|
||||
|
||||
const chartRef = ref(null);
|
||||
let chartInstance = null;
|
||||
|
||||
onMounted(() => {
|
||||
if (chartRef.value) {
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
chartInstance.setOption(props.option);
|
||||
|
||||
// 响应式调整
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
chartInstance.resize();
|
||||
});
|
||||
resizeObserver.observe(chartRef.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.option,
|
||||
(newVal) => {
|
||||
if (chartInstance) {
|
||||
chartInstance.setOption(newVal);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
</script>
|
||||
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="recent-note-card bg-white p-4 rounded-lg transition-all hover:bg-gray-50 cursor-pointer border border-gray-200 hover:border-blue-300">
|
||||
<h4 class="font-medium text-lg mb-1 truncate text-gray-800">{{ title }}</h4>
|
||||
<div class="flex items-center text-sm text-gray-500 mb-2">
|
||||
<span class="bg-blue-100 text-blue-600 px-2 py-0.5 rounded text-xs mr-2">{{ category }}</span>
|
||||
<span>{{ date }}</span>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<span
|
||||
v-for="(tag, index) in tags"
|
||||
:key="index"
|
||||
class="bg-gray-100 text-gray-600 px-2 py-0.5 rounded text-xs"
|
||||
>
|
||||
{{ tag }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
title: String,
|
||||
category: String,
|
||||
date: String,
|
||||
tags: Array,
|
||||
});
|
||||
</script>
|
||||
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div
|
||||
class="stat-card p-6 rounded-xl shadow-md transition-all duration-300 hover:shadow-lg"
|
||||
:class="bgColor"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-600">{{ title }}</p>
|
||||
<h3
|
||||
class="text-3xl font-bold mt-2"
|
||||
:class="color"
|
||||
>
|
||||
{{ value }}
|
||||
</h3>
|
||||
</div>
|
||||
<el-icon
|
||||
:size="40"
|
||||
:class="`${color} opacity-80`"
|
||||
>
|
||||
<component :is="icon" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
icon: String,
|
||||
title: String,
|
||||
value: [String, Number],
|
||||
color: String,
|
||||
bgColor: String,
|
||||
});
|
||||
</script>
|
||||
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<div
|
||||
v-for="item in data"
|
||||
:key="item.name"
|
||||
class="tech-item"
|
||||
>
|
||||
<div class="flex justify-between text-sm mb-1 text-gray-700">
|
||||
<span>{{ item.name }}</span>
|
||||
<span>{{ item.progress }}%</span>
|
||||
</div>
|
||||
<div class="w-full bg-gray-200 rounded-full h-2.5">
|
||||
<div
|
||||
class="h-2.5 rounded-full transition-all duration-1000 ease-out"
|
||||
:class="item.color"
|
||||
:style="{ width: `${item.progress}%` }"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
data: Array,
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in New Issue