style modify
This commit is contained in:
parent
75167ae9e7
commit
fb109cd9ba
BIN
assets/images/common/plana_e.png
Normal file
BIN
assets/images/common/plana_e.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 111 KiB |
@ -1,5 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import {computed} from "vue";
|
||||
import {pos} from "ipx";
|
||||
|
||||
const props = defineProps<{
|
||||
post: IPost
|
||||
@ -15,28 +16,21 @@ const randomId = computed(() => pid.data.value!)
|
||||
|
||||
<template>
|
||||
<nuxt-link :title="post.title"
|
||||
class="container relative h-56 overflow-hidden rounded-2xl text-white hover:cursor-pointer hover:text-amber-200 hover:shadow-lg"
|
||||
class="container relative overflow-hidden rounded-2xl bg-white transition-all duration-300 ease-in-out h-[31rem] hover:-translate-y-2 hover:cursor-pointer hover:shadow"
|
||||
:to="{name: 'article-cid', params: {cid: post.cid}}">
|
||||
<!-- 图片 -->
|
||||
<div class="container h-full">
|
||||
<div class="relative">
|
||||
<!-- 渐变 -->
|
||||
<div class="absolute top-0 right-0 bottom-0 left-0 bg-gradient-to-t from-white"></div>
|
||||
<img v-if="thumbUrl" :src="thumbUrl" alt=""
|
||||
class="h-full w-full object-cover object-center transition-all duration-300 hover:scale-110">
|
||||
class="aspect-video w-full h-auto object-cover object-center">
|
||||
<card-article-default-image :id="randomId"/>
|
||||
</div>
|
||||
<!-- 文字部分 -->
|
||||
<div class="container relative">
|
||||
<div class="absolute bottom-0 h-12 w-full truncate bg-black bg-opacity-60 p-2 leading-8 backdrop-blur-3xl">
|
||||
<span class="px-1 text-xl font-bold transition-all">{{ post.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分类 -->
|
||||
<div class="absolute top-0 left-0 m-2 rounded-lg bg-black bg-opacity-60 px-2 text-white backdrop-blur-3xl">
|
||||
<span>{{ post.category }}</span>
|
||||
</div>
|
||||
<!-- 日期 -->
|
||||
<div class="absolute right-0 bottom-12 m-2 rounded-lg bg-black bg-opacity-60 px-2 text-white backdrop-blur-3xl">
|
||||
<font-awesome-icon :icon="['far', 'clock']" class="mr-1 text-sm"/>
|
||||
<span>{{ post.date.year }}-{{ post.date.month }}-{{ post.date.day }}</span>
|
||||
<div class="px-5">
|
||||
<!-- 标题 -->
|
||||
<h4 class="text-2xl font-bold">{{ post.title }}</h4>
|
||||
<p class="mt-4 text-lg px-1 text-gray-700">{{ post.digest }}</p>
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
@ -16,6 +16,6 @@ defineProps<{
|
||||
|
||||
<style scoped>
|
||||
img {
|
||||
@apply h-full w-full object-cover object-center transition-all duration-300 hover:scale-110
|
||||
@apply aspect-[16/10] w-full h-auto object-cover object-center
|
||||
}
|
||||
</style>
|
@ -1,25 +1,18 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
title: string
|
||||
mainColor: string
|
||||
subColor: string
|
||||
url: string
|
||||
icon: string[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mb-4 flex justify-between text-2xl font-bold text-white">
|
||||
<div :class="[mainColor]" class="flex w-max items-center justify-center overflow-hidden rounded-2xl">
|
||||
<div :class="[subColor]" class="flex h-full w-14 items-center justify-center rounded-2xl px-4 py-2 text-center">
|
||||
<div class="my-16 relative">
|
||||
<h3 class="text-5xl font-bold text-blue-400 relative z-10">{{ title }}</h3>
|
||||
<div class="h-12 w-auto text-5xl text-blue-200 absolute left-48 top-0 -translate-y-6">
|
||||
<font-awesome-icon :icon="icon"/>
|
||||
</div>
|
||||
<span class="px-4">{{ title }}</span>
|
||||
</div>
|
||||
<a :class="[mainColor]" :href="url" class="rounded-2xl px-4 py-2">
|
||||
<font-awesome-icon :icon="['fas', 'chevron-right']"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
@ -3,6 +3,7 @@ defineProps<{
|
||||
loading: boolean
|
||||
error: boolean
|
||||
empty: boolean
|
||||
errMsg?: object
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['reload'])
|
||||
@ -24,13 +25,26 @@ const handleReload = () => {
|
||||
</div>
|
||||
<div v-else class="w-full">
|
||||
<!-- 错误处理 -->
|
||||
<div v-if="error" class="flex h-56 flex-col items-center justify-center" @click="handleReload">
|
||||
<span class="mb-4 text-8xl">❌</span>
|
||||
<span class="text-center text-2xl font-bold">载入错误</span>
|
||||
<div v-if="error" @click="handleReload">
|
||||
<div class="flex items-center justify-center gap-8">
|
||||
<p class="text-2xl text-gray-700 border-2 border-black py-2 px-8 rounded-full rounded-br-lg">载入错误</p>
|
||||
<img class="h-32 w-auto relative" src="~/assets/images/common/plana_e.png" alt="">
|
||||
</div>
|
||||
<div v-if="errMsg" class="bg-white mt-4 p-4 border border-dashed rounded-md" style="font-family: 'LXGW WenKai Mono', monospace">
|
||||
{{ errMsg }}
|
||||
</div>
|
||||
<p class="text-right text-xs">(点击重试)</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- 正式内容 -->
|
||||
<span v-if="empty" class="text-center text-2xl font-bold">最近没有动态</span>
|
||||
<div v-if="empty">
|
||||
<div v-if="empty" class="flex items-center justify-center gap-8" @click="handleReload">
|
||||
<p class="text-2xl text-gray-700 border-2 border-black py-2 px-8 rounded-full rounded-br-lg">最近没有动态~</p>
|
||||
<img class="h-32 w-auto relative" src="~/assets/images/common/plana_e.png" alt="">
|
||||
</div>
|
||||
<p class="text-right text-xs">(点击重试)</p>
|
||||
</div>
|
||||
|
||||
<slot v-else name="default"/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,7 +43,9 @@ export function get<DataT, ErrorT>(url: string, options?: UseFetchOptions<DataT>
|
||||
return async (): Promise<DataT> => {
|
||||
if (result != null) {
|
||||
await result.refresh()
|
||||
return result.data.value
|
||||
if (result.status.value === 'success')
|
||||
return result.data.value
|
||||
throw result.error
|
||||
}
|
||||
|
||||
result = await requestCore(url, {
|
||||
|
4
middleware/00.loading.global.ts
Normal file
4
middleware/00.loading.global.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export default defineNuxtRouteMiddleware(() => {
|
||||
const {$mitt} = useNuxtApp()
|
||||
$mitt.emit('startLoading', true)
|
||||
})
|
@ -1,5 +1,5 @@
|
||||
export default defineNuxtRouteMiddleware((to, from) =>{
|
||||
if (to.meta.maintenance === true && !import.meta.env.DEV)
|
||||
export default defineNuxtRouteMiddleware((to, _) => {
|
||||
if (to.meta.maintenance === true && import.meta.env.DEV)
|
||||
return navigateTo('/error/maintenance')
|
||||
return true
|
||||
})
|
@ -47,5 +47,8 @@ export default defineNuxtConfig({
|
||||
gitApiKey: 'fb8aec429ea7d0a36f7238dbffda9d2d66c7b045',
|
||||
baseURL: 'https://cantyonion.site'
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
host: '0.0.0.0'
|
||||
}
|
||||
})
|
@ -1,6 +1,11 @@
|
||||
<script lang="ts" setup>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
|
||||
type errObj = {
|
||||
blog?: object,
|
||||
git?: object
|
||||
}
|
||||
|
||||
const {$mitt} = useNuxtApp()
|
||||
const recentPosts = ref<IPost[] | null>(null);
|
||||
const recentActivities = ref<IActivity[] | null>(null);
|
||||
@ -12,9 +17,18 @@ const isError = ref({
|
||||
blog: false,
|
||||
git: false
|
||||
});
|
||||
const errMsg = ref<errObj>({
|
||||
blog: undefined,
|
||||
git: undefined
|
||||
})
|
||||
|
||||
const config = useRuntimeConfig()
|
||||
const getBlogRecentPost = get<IBlogResponse<IPostsData>, any>('/blog/index.php/api/posts')
|
||||
const getBlogRecentPost = get<IBlogResponse<IPostsData>, any>('/blog/index.php/api/posts', {
|
||||
params: {
|
||||
showDigest: "excerpt",
|
||||
limit: 100
|
||||
}
|
||||
})
|
||||
const getActivity = get<IActivity[], any>('/git/api/v1/users/cantyonion/activities/feeds', {
|
||||
headers: {
|
||||
Authorization: ` ${config.public.gitApiKey}`
|
||||
@ -51,10 +65,13 @@ const activitiesData = computed((): IActivity<IContent>[] => {
|
||||
const reloadPosts = async () => {
|
||||
try {
|
||||
isLoading.value.blog = true
|
||||
isError.value.blog = false
|
||||
const postData = await getBlogRecentPost()
|
||||
recentPosts.value = postData!.data.dataSet
|
||||
if (postData !== null)
|
||||
recentPosts.value = postData.data.dataSet
|
||||
} catch (e) {
|
||||
isError.value.blog = true
|
||||
errMsg.value.blog = e as object
|
||||
}
|
||||
finally {
|
||||
isLoading.value.blog = false
|
||||
@ -64,16 +81,18 @@ const reloadPosts = async () => {
|
||||
const reloadActivities = async () => {
|
||||
try {
|
||||
isLoading.value.git = true
|
||||
isError.value.git = false
|
||||
recentActivities.value = await getActivity()
|
||||
} catch (e) {
|
||||
isError.value.git = true
|
||||
errMsg.value.git = e as object
|
||||
}
|
||||
finally {
|
||||
isLoading.value.git = false
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([reloadPosts(), reloadActivities()])
|
||||
await Promise.allSettled([reloadPosts(), reloadActivities()])
|
||||
|
||||
onMounted(() => {
|
||||
$mitt.emit('startLoading', false)
|
||||
@ -84,16 +103,15 @@ onMounted(() => {
|
||||
<!-- 个人介绍 -->
|
||||
<card-full-screen-intro-card/>
|
||||
|
||||
<div class="container mx-auto mt-8 xl:max-w-screen-xl">
|
||||
<div class="container mx-auto xl:max-w-screen-xl">
|
||||
<!-- 博客部分 -->
|
||||
<section class="w-full px-4 sm:px-0">
|
||||
<!-- 标题部分 -->
|
||||
<card-title :icon="['fas', 'blog']" main-color="bg-rose-500" sub-color="bg-rose-600" title="最新博文"
|
||||
url="/blog/"/>
|
||||
<card-title :icon="['fas', 'blog']" title="最近文章"/>
|
||||
|
||||
<card-section-card :empty="!hasPosts" :error="isError.blog" :loading="isLoading.blog" @reload="reloadPosts">
|
||||
<card-section-card :empty="!hasPosts" :error="isError.blog" :loading="isLoading.blog" @reload="reloadPosts" :err-msg="errMsg.blog">
|
||||
<template v-slot:default>
|
||||
<div class="grid w-full grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<div class="grid w-full grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<card-article-card v-for="item in postsData" :key="item.cid" :post="item"/>
|
||||
</div>
|
||||
</template>
|
||||
@ -102,10 +120,9 @@ onMounted(() => {
|
||||
|
||||
<!-- Git部分 -->
|
||||
<section class="my-4 w-full px-4 sm:px-0">
|
||||
<card-title :icon="['fas', 'code']" main-color="bg-green-500" sub-color="bg-green-600" title="最近活动"
|
||||
url="/git/"/>
|
||||
<card-title :icon="['fas', 'code']" title="最近活动"/>
|
||||
|
||||
<card-section-card :empty="!hasActivities" :error="isError.git" :loading="isLoading.git" @reload="reloadActivities">
|
||||
<card-section-card :empty="!hasActivities" :error="isError.git" :loading="isLoading.git" @reload="reloadActivities" :err-msg="errMsg.git">
|
||||
<template v-slot:default>
|
||||
<div class="grid w-full grid-cols-1 gap-4 lg:grid-cols-2">
|
||||
<card-git-card v-for="item in activitiesData" :key="item.id" :commit="item"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user