修改首页目录表格样式
This commit is contained in:
@@ -1,18 +1,28 @@
|
||||
<template>
|
||||
<div class="w-full bg-gray-50 dark:bg-gray-900 min-h-screen mt-4">
|
||||
<!-- 响应式卡片网格 -->
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 max-w-8xl mx-auto">
|
||||
<!--
|
||||
这个div使用了Tailwind CSS的类来实现响应式的卡片网格布局:
|
||||
- grid:将容器设置为网格布局。
|
||||
- grid-cols-1:在小屏幕下每行显示1列。
|
||||
- sm:grid-cols-2:在中等屏幕(sm及以上)每行显示2列。
|
||||
- lg:grid-cols-3:在大屏幕(lg及以上)每行显示3列。
|
||||
- gap-4:网格项之间有统一的间距。
|
||||
- max-w-8xl:设置最大宽度为8xl,防止内容过宽。
|
||||
- mx-auto:左右自动外边距,使网格居中显示。
|
||||
-->
|
||||
<div class="grid grid-cols-1 xs:grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-3 2xl:grid-cols-4 gap-4 w-full mx-auto">
|
||||
<div v-for="item in firstLevelItems" :key="item.path"
|
||||
class="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-5 sm:p-6 shadow-sm hover:shadow-md transition-all duration-200 cursor-pointer"
|
||||
@click="navigateTo(item.path)">
|
||||
|
||||
<!-- 卡片头部 -->
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<h2 class="text-xl sm:text-xl lg:text-2xl font-bold text-gray-900 dark:text-white leading-tight">
|
||||
<h2 class="font-sans text-xl sm:text-xl lg:text-2xl font-bold text-gray-900 dark:text-white leading-tight">
|
||||
{{ item.title }}
|
||||
</h2>
|
||||
<span class="text-sm sm:text-base lg:text-lg text-gray-600 dark:text-gray-400 font-normal">
|
||||
<sum class="text-primary mr-0.3">{{ getChildrenCount(item) }}</sum>篇
|
||||
<span class="text-primary mr-0.3">{{ getChildrenCount(item) }}</span>篇
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -26,10 +36,10 @@
|
||||
border-b border-gray-200 dark:border-gray-700 pt-2">
|
||||
|
||||
<div class="flex items-center flex-1 min-w-0 pl-1 ">
|
||||
<Icon :name="child.icon || 'i-lucide-file-text'" class="mr-2 text-gray-400" size="14" />
|
||||
<span class="text-base font-sans">{{ child.title }}</span>
|
||||
<UIcon :name="(typeof child.icon === 'string' ? child.icon : 'i-lucide-file-text')" class="mr-2 text-gray-400" size="14" />
|
||||
<span class="text-base font-medium font-sans">{{ child.title }}</span>
|
||||
</div>
|
||||
<Icon name="i-lucide-chevron-right" class="text-gray-400 flex-shrink-0 ml-2" size="16" />
|
||||
<UIcon name="i-lucide-chevron-right" class="text-gray-400 flex-shrink-0 ml-2" size="16" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
24
app/components/content/ButtonGroup.vue
Normal file
24
app/components/content/ButtonGroup.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="button-group">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// ButtonGroup 组件用于水平排列多个按钮
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.button-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 确保按钮之间有合适的间距 */
|
||||
.button-group > * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
@@ -1,9 +1,13 @@
|
||||
<template>
|
||||
<NuxtLink :to="to || href" :target="(blank && '_blank') || target">
|
||||
<UButton :variant="variant" :size="size">
|
||||
<Icon v-if="leftIcon" :name="leftIcon" class="mr-1" />
|
||||
<ContentSlot unwrap="p" />
|
||||
<Icon v-if="rightIcon" :name="rightIcon" class="ml-1" />
|
||||
<UButton
|
||||
:variant="variant"
|
||||
:size="size"
|
||||
class="button-link"
|
||||
>
|
||||
<SmartIcon v-if="leftIcon" :name="leftIcon" class="icon-left" />
|
||||
<slot />
|
||||
<SmartIcon v-if="rightIcon" :name="rightIcon" class="icon-right" />
|
||||
</UButton>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
@@ -20,3 +24,78 @@ defineProps<{
|
||||
blank?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.button-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.2rem;
|
||||
padding: 0.3rem;
|
||||
border-radius: 0.5rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
transition: all 0.2s ease;
|
||||
text-decoration: none;
|
||||
|
||||
}
|
||||
|
||||
.button-link:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.button-link:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
/* 实心按钮样式(蓝色按钮) */
|
||||
:deep(.u-button--solid) {
|
||||
background-color: #3b82f6;
|
||||
color: white;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
|
||||
:deep(.u-button--solid:hover) {
|
||||
background-color: #2563eb;
|
||||
border-color: #2563eb;
|
||||
}
|
||||
|
||||
/* 边框按钮样式(GitHub按钮) */
|
||||
:deep(.u-button--outline) {
|
||||
background-color: white;
|
||||
color: #3b82f6;
|
||||
border-color: #3b82f6;
|
||||
}
|
||||
|
||||
:deep(.u-button--outline:hover) {
|
||||
background-color: #eff6ff;
|
||||
border-color:var(--primary);
|
||||
}
|
||||
|
||||
/* 图标按钮样式(Ghost图标) */
|
||||
:deep(.u-button--ghost) {
|
||||
background-color: transparent;
|
||||
color: #3b82f6;
|
||||
border-color: transparent;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
:deep(.u-button--ghost:hover) {
|
||||
background-color: #eff6ff;
|
||||
color: #2563eb;
|
||||
}
|
||||
|
||||
.icon-left {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-right {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<!-- Iconify Icons -->
|
||||
<Icon v-if="isIconName(name)" :name="name" :size="size" />
|
||||
<Icon v-if="checkIcon(name)" :name :size />
|
||||
<!-- Emojis -->
|
||||
<span
|
||||
v-else-if="isEmoji(name)"
|
||||
v-else-if="/(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/g.test(name)"
|
||||
:style="`font-size: ${size}px;`"
|
||||
>{{ name }}</span>
|
||||
<!-- Link -->
|
||||
@@ -16,23 +16,17 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { stringToIcon, validateIconName } from '@iconify/utils';
|
||||
|
||||
const { size = 16 } = defineProps<{
|
||||
name: string;
|
||||
size?: number;
|
||||
}>();
|
||||
|
||||
function isIconName(name: string): boolean {
|
||||
function checkIcon(name: string): boolean {
|
||||
if (name.includes('http'))
|
||||
return false;
|
||||
|
||||
// 简单的图标名称检查,以 i- 开头或包含常见图标集
|
||||
return name.startsWith('i-') ||
|
||||
name.includes('lucide') ||
|
||||
name.includes('heroicons') ||
|
||||
name.includes('simple-icons');
|
||||
}
|
||||
|
||||
function isEmoji(name: string): boolean {
|
||||
return /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/g.test(name);
|
||||
return validateIconName(stringToIcon(name));
|
||||
}
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user