mirror of https://github.com/halo-dev/halo-admin
parent
e13d086236
commit
9d020c073e
|
@ -72,12 +72,6 @@
|
||||||
|
|
||||||
<template v-for="(group, groupIndex) in widgetsGroup" :key="groupIndex">
|
<template v-for="(group, groupIndex) in widgetsGroup" :key="groupIndex">
|
||||||
<div v-if="activeId === group.id" class="mt-4">
|
<div v-if="activeId === group.id" class="mt-4">
|
||||||
<VAlert
|
|
||||||
v-if="group.notice"
|
|
||||||
:description="group.notice"
|
|
||||||
class="mb-4"
|
|
||||||
title="提示"
|
|
||||||
/>
|
|
||||||
<grid-layout
|
<grid-layout
|
||||||
:col-num="12"
|
:col-num="12"
|
||||||
:is-draggable="false"
|
:is-draggable="false"
|
||||||
|
@ -114,7 +108,6 @@ import {
|
||||||
IconDashboard,
|
IconDashboard,
|
||||||
IconSave,
|
IconSave,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
VAlert,
|
|
||||||
VButton,
|
VButton,
|
||||||
VModal,
|
VModal,
|
||||||
VPageHeader,
|
VPageHeader,
|
||||||
|
@ -125,17 +118,13 @@ import { ref } from "vue";
|
||||||
import { useStorage } from "@vueuse/core";
|
import { useStorage } from "@vueuse/core";
|
||||||
import cloneDeep from "lodash.clonedeep";
|
import cloneDeep from "lodash.clonedeep";
|
||||||
|
|
||||||
const settings = ref(false);
|
|
||||||
const widgetsModal = ref(false);
|
|
||||||
const activeId = ref("post");
|
|
||||||
|
|
||||||
const widgetsGroup = [
|
const widgetsGroup = [
|
||||||
{
|
{
|
||||||
id: "post",
|
id: "post",
|
||||||
label: "文章",
|
label: "文章",
|
||||||
widgets: [
|
widgets: [
|
||||||
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "PostStatsWidget" },
|
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "PostStatsWidget" },
|
||||||
{ x: 3, y: 0, w: 6, h: 10, i: 1, widget: "RecentPublishedWidget" },
|
{ x: 0, y: 0, w: 6, h: 10, i: 1, widget: "RecentPublishedWidget" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -148,15 +137,9 @@ const widgetsGroup = [
|
||||||
label: "用户",
|
label: "用户",
|
||||||
widgets: [
|
widgets: [
|
||||||
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "UserStatsWidget" },
|
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "UserStatsWidget" },
|
||||||
{ x: 3, y: 0, w: 6, h: 10, i: 1, widget: "RecentLoginWidget" },
|
{ x: 0, y: 0, w: 6, h: 10, i: 1, widget: "RecentLoginWidget" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: "plugin-journal",
|
|
||||||
label: "日志",
|
|
||||||
notice: "此组件由插件 plugin-journal 提供",
|
|
||||||
widgets: [{ x: 0, y: 0, w: 5, h: 8, i: 0, widget: "JournalPublishWidget" }],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: "other",
|
id: "other",
|
||||||
label: "其他",
|
label: "其他",
|
||||||
|
@ -167,29 +150,25 @@ const widgetsGroup = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const settings = ref(false);
|
||||||
|
const widgetsModal = ref(false);
|
||||||
|
const activeId = ref(widgetsGroup[0].id);
|
||||||
|
|
||||||
const layout = useStorage("widgets", [
|
const layout = useStorage("widgets", [
|
||||||
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "PostStatsWidget" },
|
{ x: 0, y: 0, w: 3, h: 3, i: 0, widget: "PostStatsWidget" },
|
||||||
{ x: 3, y: 0, w: 3, h: 3, i: 1, widget: "UserStatsWidget" },
|
{ x: 3, y: 0, w: 3, h: 3, i: 1, widget: "UserStatsWidget" },
|
||||||
{ x: 6, y: 0, w: 3, h: 3, i: 2, widget: "CommentStatsWidget" },
|
{ x: 6, y: 0, w: 3, h: 3, i: 2, widget: "CommentStatsWidget" },
|
||||||
{ x: 9, y: 0, w: 3, h: 3, i: 3, widget: "ViewsStatsWidget" },
|
{ x: 9, y: 0, w: 3, h: 3, i: 3, widget: "ViewsStatsWidget" },
|
||||||
|
{ x: 8, y: 3, w: 4, h: 10, i: 4, widget: "RecentLoginWidget" },
|
||||||
|
{ x: 0, y: 3, w: 4, h: 10, i: 5, widget: "QuickLinkWidget" },
|
||||||
{
|
{
|
||||||
x: 5,
|
x: 4,
|
||||||
y: 3,
|
y: 3,
|
||||||
w: 4,
|
w: 4,
|
||||||
h: 10,
|
h: 10,
|
||||||
i: 4,
|
i: 6,
|
||||||
widget: "RecentPublishedWidget",
|
widget: "RecentPublishedWidget",
|
||||||
},
|
},
|
||||||
{ x: 9, y: 3, w: 3, h: 10, i: 5, widget: "RecentLoginWidget" },
|
|
||||||
{
|
|
||||||
x: 0,
|
|
||||||
y: 13,
|
|
||||||
w: 4,
|
|
||||||
h: 10,
|
|
||||||
i: 6,
|
|
||||||
widget: "JournalPublishWidget",
|
|
||||||
},
|
|
||||||
{ x: 0, y: 3, w: 5, h: 10, i: 7, widget: "QuickLinkWidget" },
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
|
|
@ -3,7 +3,6 @@ import Dashboard from "./Dashboard.vue";
|
||||||
import { IconDashboard } from "@halo-dev/components";
|
import { IconDashboard } from "@halo-dev/components";
|
||||||
|
|
||||||
import CommentStatsWidget from "./widgets/CommentStatsWidget.vue";
|
import CommentStatsWidget from "./widgets/CommentStatsWidget.vue";
|
||||||
import JournalPublishWidget from "./widgets/JournalPublishWidget.vue";
|
|
||||||
import PostStatsWidget from "./widgets/PostStatsWidget.vue";
|
import PostStatsWidget from "./widgets/PostStatsWidget.vue";
|
||||||
import QuickLinkWidget from "./widgets/QuickLinkWidget.vue";
|
import QuickLinkWidget from "./widgets/QuickLinkWidget.vue";
|
||||||
import RecentLoginWidget from "./widgets/RecentLoginWidget.vue";
|
import RecentLoginWidget from "./widgets/RecentLoginWidget.vue";
|
||||||
|
@ -15,7 +14,6 @@ export default definePlugin({
|
||||||
name: "dashboardModule",
|
name: "dashboardModule",
|
||||||
components: [
|
components: [
|
||||||
CommentStatsWidget,
|
CommentStatsWidget,
|
||||||
JournalPublishWidget,
|
|
||||||
PostStatsWidget,
|
PostStatsWidget,
|
||||||
QuickLinkWidget,
|
QuickLinkWidget,
|
||||||
RecentLoginWidget,
|
RecentLoginWidget,
|
||||||
|
|
|
@ -1,9 +1,23 @@
|
||||||
<script lang="ts" name="CommentStatsWidget" setup>
|
<script lang="ts" name="CommentStatsWidget" setup>
|
||||||
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { VCard } from "@halo-dev/components";
|
import { VCard } from "@halo-dev/components";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
|
||||||
|
const commentTotal = ref<number>(0);
|
||||||
|
|
||||||
|
const handleFetchComments = async () => {
|
||||||
|
const { data } =
|
||||||
|
await apiClient.extension.comment.listcontentHaloRunV1alpha1Comment();
|
||||||
|
commentTotal.value = data.total;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(handleFetchComments);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard class="h-full">
|
<VCard class="h-full">
|
||||||
<dt class="truncate text-sm font-medium text-gray-500">评论</dt>
|
<dt class="truncate text-sm font-medium text-gray-500">评论</dt>
|
||||||
<dd class="mt-1 text-3xl font-semibold text-gray-900">53</dd>
|
<dd class="mt-1 text-3xl font-semibold text-gray-900">
|
||||||
|
{{ commentTotal }}
|
||||||
|
</dd>
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
<script lang="ts" name="JournalPublishWidget" setup>
|
|
||||||
import { VButton, VCard, VTextarea } from "@halo-dev/components";
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<VCard
|
|
||||||
:body-class="['h-full', 'overflow-y-auto']"
|
|
||||||
class="h-full"
|
|
||||||
title="日志发表"
|
|
||||||
>
|
|
||||||
<VTextarea :rows="6" />
|
|
||||||
<template #footer>
|
|
||||||
<VButton type="secondary">发布</VButton>
|
|
||||||
</template>
|
|
||||||
</VCard>
|
|
||||||
</template>
|
|
|
@ -10,12 +10,12 @@ const { users } = useUserFetch({ fetchOnMounted: true });
|
||||||
class="h-full"
|
class="h-full"
|
||||||
title="最近登录"
|
title="最近登录"
|
||||||
>
|
>
|
||||||
<div class="h-full p-4">
|
<div class="h-full">
|
||||||
<ul class="divide-y divide-gray-200" role="list">
|
<ul class="divide-y divide-gray-200" role="list">
|
||||||
<li
|
<li
|
||||||
v-for="(user, index) in users"
|
v-for="(user, index) in users"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="cursor-pointer py-4 hover:bg-gray-50"
|
class="cursor-pointer p-4 hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<div class="flex flex-shrink-0 items-center">
|
<div class="flex flex-shrink-0 items-center">
|
||||||
|
@ -34,8 +34,8 @@ const { users } = useUserFetch({ fetchOnMounted: true });
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<time class="text-sm text-gray-500" datetime="2020-01-07 20:00">
|
<time class="text-sm text-gray-500">
|
||||||
2020-01-07 20:00
|
{{ user.status?.lastLoginAt }}
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
<script lang="ts" name="RecentPublishedWidget" setup>
|
<script lang="ts" name="RecentPublishedWidget" setup>
|
||||||
import { VCard, VSpace } from "@halo-dev/components";
|
import { VCard, VSpace } from "@halo-dev/components";
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import type { Post } from "@halo-dev/api-client";
|
import type { ListedPost } from "@halo-dev/api-client";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { formatDatetime } from "@/utils/date";
|
import { formatDatetime } from "@/utils/date";
|
||||||
|
|
||||||
const posts = ref<Post[]>([] as Post[]);
|
const posts = ref<ListedPost[]>([] as ListedPost[]);
|
||||||
|
|
||||||
const handleFetchPosts = async () => {
|
const handleFetchPosts = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } =
|
const { data } = await apiClient.post.listPosts({
|
||||||
await apiClient.extension.post.listcontentHaloRunV1alpha1Post();
|
sort: "PUBLISH_TIME",
|
||||||
|
publishPhase: "PUBLISHED",
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
});
|
||||||
posts.value = data.items;
|
posts.value = data.items;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to fetch posts", e);
|
console.error("Failed to fetch posts", e);
|
||||||
|
@ -23,19 +27,19 @@ onMounted(handleFetchPosts);
|
||||||
<VCard
|
<VCard
|
||||||
:body-class="['h-full', '!p-0', 'overflow-y-auto']"
|
:body-class="['h-full', '!p-0', 'overflow-y-auto']"
|
||||||
class="h-full"
|
class="h-full"
|
||||||
title="最近发布"
|
title="最近文章"
|
||||||
>
|
>
|
||||||
<div class="h-full p-4">
|
<div class="h-full">
|
||||||
<ul class="divide-y divide-gray-200" role="list">
|
<ul class="divide-y divide-gray-200" role="list">
|
||||||
<li
|
<li
|
||||||
v-for="(post, index) in posts"
|
v-for="(post, index) in posts"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="cursor-pointer py-4 hover:bg-gray-50"
|
class="cursor-pointer p-4 hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
<div class="flex items-center space-x-4">
|
<div class="flex items-center space-x-4">
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="truncate text-sm font-medium text-gray-900">
|
<p class="truncate text-sm font-medium text-gray-900">
|
||||||
{{ post.spec.title }}
|
{{ post.post.spec.title }}
|
||||||
</p>
|
</p>
|
||||||
<div class="mt-1 flex">
|
<div class="mt-1 flex">
|
||||||
<VSpace>
|
<VSpace>
|
||||||
|
@ -47,7 +51,7 @@ onMounted(handleFetchPosts);
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<time class="text-sm text-gray-500">
|
<time class="text-sm text-gray-500">
|
||||||
{{ formatDatetime(post.metadata.creationTimestamp) }}
|
{{ formatDatetime(post.post.spec.publishTime) }}
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue