Compare commits
2 Commits
735d913bf4
...
570406309e
| Author | SHA1 | Date | |
|---|---|---|---|
| 570406309e | |||
| 1ba0e6c40b |
@@ -22,6 +22,12 @@ export const queryBlogApi = (currentPage: number, pageSize: number): Promise<IPa
|
|||||||
params: { currentPage, pageSize }
|
params: { currentPage, pageSize }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const queryUnapprovedBlogApi = (): Promise<IBlog[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/blog/unapproved',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
export const queryBlogByIdApi = (id: number): Promise<IBlog> =>
|
export const queryBlogByIdApi = (id: number): Promise<IBlog> =>
|
||||||
cloudService({
|
cloudService({
|
||||||
url: `/blog-api/blog/${id}/content`,
|
url: `/blog-api/blog/${id}/content`,
|
||||||
|
|||||||
54
src/apis/stats.ts
Normal file
54
src/apis/stats.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { cloudService } from './index'
|
||||||
|
|
||||||
|
import { IStatsChart } from 'vue3-common/types'
|
||||||
|
import { IBlogOverview } from '@/types/blog'
|
||||||
|
|
||||||
|
export const queryOverviewStatsApi = (): Promise<IBlogOverview> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/overview',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryCategoryStatsApi = (): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/category',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryApprovedMonthlyStatsApi = (year: number): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/approved/monthly',
|
||||||
|
method: 'get',
|
||||||
|
params: { year }
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryVisitMonthlyStatsApi = (year: number): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/visit/monthly',
|
||||||
|
method: 'get',
|
||||||
|
params: { year }
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryVisitRankStatsApi = (): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/visit/rank',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryReadRankStatsApi = (): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/read/rank',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const queryCommentRankStatsApi = (): Promise<IStatsChart[]> =>
|
||||||
|
cloudService({
|
||||||
|
url: '/blog-api/stats/comment/rank',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
1
src/icons/svg/admin/blogUnapproved.svg
Normal file
1
src/icons/svg/admin/blogUnapproved.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1761548520883" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1595" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M729.301333 42.666667c79.552 0 142.72 69.504 145.28 154.666666L874.666667 202.666667V576h32a74.666667 74.666667 0 0 1 74.56 70.570667L981.333333 650.666667v256a74.666667 74.666667 0 0 1-74.666666 74.666666h-789.333334A74.666667 74.666667 0 0 1 42.666667 906.666667v-256A74.666667 74.666667 0 0 1 117.333333 576H149.333333V202.666667c0-85.76 61.568-157.034667 140.416-159.914667L294.698667 42.666667h434.602666zM216.832 640H117.333333a10.666667 10.666667 0 0 0-10.666666 10.666667v256a10.666667 10.666667 0 0 0 10.666666 10.666666h789.333334a10.666667 10.666667 0 0 0 10.666666-10.666666v-256a10.666667 10.666667 0 0 0-10.666666-10.666667h-78.421334a10.666667 10.666667 0 0 0-6.912 2.538667l-126.890666 107.733333a74.666667 74.666667 0 0 1-48.32 17.728H381.226667a74.666667 74.666667 0 0 1-52.522667-21.589333l-104.405333-103.317334a10.666667 10.666667 0 0 0-7.488-3.093333zM729.301333 106.666667H294.698667c-42.666667 0-79.104 39.658667-81.28 91.136L213.333333 202.666667V576h3.498667a74.666667 74.666667 0 0 1 49.194667 18.517333l3.328 3.072 104.384 103.317334a10.666667 10.666667 0 0 0 7.509333 3.093333h264.874667a10.666667 10.666667 0 0 0 6.890666-2.538667l126.912-107.733333a74.666667 74.666667 0 0 1 30.72-15.637333L810.666667 202.666667c0-52.202667-35.114667-93.44-77.397334-95.893334L729.301333 106.666667zM629.333333 448a32 32 0 0 1 0 64h-234.666666a32 32 0 0 1 0-64h234.666666z m64-192a32 32 0 0 1 0 64h-362.666666a32 32 0 0 1 0-64h362.666666z" fill="" p-id="1596"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -4,9 +4,17 @@ import {
|
|||||||
IBlogLatest, IBlogNestedComment, IBlogStats, INewBlog, IQueryBlog
|
IBlogLatest, IBlogNestedComment, IBlogStats, INewBlog, IQueryBlog
|
||||||
} from '@/types/blog'
|
} from '@/types/blog'
|
||||||
import {
|
import {
|
||||||
addBlogApi, addBlogCommentApi, deleteBlogApi,
|
addBlogApi,
|
||||||
queryBlogApi, queryBlogByIdApi,
|
addBlogCommentApi,
|
||||||
queryBlogCategoryApi, queryBlogCommentApi, queryBlogStatsApi, queryLatestBlogApi, updateBlogApi
|
deleteBlogApi,
|
||||||
|
queryBlogApi,
|
||||||
|
queryBlogByIdApi,
|
||||||
|
queryBlogCategoryApi,
|
||||||
|
queryBlogCommentApi,
|
||||||
|
queryBlogStatsApi,
|
||||||
|
queryLatestBlogApi,
|
||||||
|
queryUnapprovedBlogApi,
|
||||||
|
updateBlogApi
|
||||||
} from '@/apis/blog.ts'
|
} from '@/apis/blog.ts'
|
||||||
import { IHandleApi } from 'vue3-common/types'
|
import { IHandleApi } from 'vue3-common/types'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
@@ -16,6 +24,7 @@ import { flattenToTwoLevel } from '@/utils/blog/blogUtil.ts'
|
|||||||
export const useBlogStore = defineStore('blog', {
|
export const useBlogStore = defineStore('blog', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
blogList: [] as IBlog[],
|
blogList: [] as IBlog[],
|
||||||
|
unapprovedBlogList: [] as IBlog[],
|
||||||
blogCommentList: [] as IBlogComment[],
|
blogCommentList: [] as IBlogComment[],
|
||||||
blogNestedCommentList: [] as IBlogNestedComment[],
|
blogNestedCommentList: [] as IBlogNestedComment[],
|
||||||
currentBlogComment: {
|
currentBlogComment: {
|
||||||
@@ -66,7 +75,8 @@ export const useBlogStore = defineStore('blog', {
|
|||||||
totalSize: 1
|
totalSize: 1
|
||||||
},
|
},
|
||||||
isScrollEnd: false,
|
isScrollEnd: false,
|
||||||
progressValue: '0%'
|
progressValue: '0%',
|
||||||
|
isRefresh: false
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async queryBlogList() {
|
async queryBlogList() {
|
||||||
@@ -75,6 +85,9 @@ export const useBlogStore = defineStore('blog', {
|
|||||||
this.blogList = result.records
|
this.blogList = result.records
|
||||||
this.pageInfo.totalSize = result.total
|
this.pageInfo.totalSize = result.total
|
||||||
},
|
},
|
||||||
|
async queryUnapprovedBlogList() {
|
||||||
|
this.unapprovedBlogList = await queryUnapprovedBlogApi()
|
||||||
|
},
|
||||||
async queryBlogById(id: number) {
|
async queryBlogById(id: number) {
|
||||||
this.currentBlog = await queryBlogByIdApi(id)
|
this.currentBlog = await queryBlogByIdApi(id)
|
||||||
await this.queryBlogComment(this.currentBlogId)
|
await this.queryBlogComment(this.currentBlogId)
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ $transition-time: 0.28s;
|
|||||||
background-color: #FFFFFF;
|
background-color: #FFFFFF;
|
||||||
border: 1px solid #FFFFFF;
|
border: 1px solid #FFFFFF;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 5px 5px 5px #CFCFCF;
|
box-shadow: 1px 1px 2px #CFCFCF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,3 +84,11 @@ export interface IBlogNestedComment {
|
|||||||
comment: IBlogComment;
|
comment: IBlogComment;
|
||||||
replies: IBlogComment[];
|
replies: IBlogComment[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IBlogOverview {
|
||||||
|
blogCount: number;
|
||||||
|
categoryCount: number;
|
||||||
|
wordCount: number;
|
||||||
|
greatCount: number;
|
||||||
|
visitCount: number;
|
||||||
|
}
|
||||||
|
|||||||
96
src/views/blog/unapproved.vue
Normal file
96
src/views/blog/unapproved.vue
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<div class="admin-module">
|
||||||
|
<div class="button-container">
|
||||||
|
<el-button type="primary" @click="addNewBlogClick">新增文章</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-table
|
||||||
|
:data="blogStore.unapprovedBlogList"
|
||||||
|
border stripe
|
||||||
|
:header-cell-style="tableHeaderStyle()"
|
||||||
|
:cell-style="tableCellStyle()"
|
||||||
|
:row-style="tableRowStyle()"
|
||||||
|
class="card-item">
|
||||||
|
<el-table-column type="index" align="center" width="50" />
|
||||||
|
<el-table-column prop="title" label="标题" align="center" min-width="15%"/>
|
||||||
|
<el-table-column prop="category" label="类别" align="center" min-width="10%" />
|
||||||
|
<el-table-column label="精品" align="center" min-width="5%">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag type="success" v-if="scope.row.isGreat">是</el-tag>
|
||||||
|
<el-tag type="danger" v-else>否</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="置顶" align="center" min-width="5%">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag type="success" v-if="scope.row.topValue > 1">是</el-tag>
|
||||||
|
<el-tag type="danger" v-else>否</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="wordCount" label="字数" align="center" min-width="10%" />
|
||||||
|
<el-table-column prop="visitCount" label="阅读次数" align="center" min-width="10%" />
|
||||||
|
<el-table-column label="是否发布" align="center" min-width="10%">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag type="success" v-if="scope.row.isApproved">已发布</el-tag>
|
||||||
|
<el-tag type="danger" v-else>草稿</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column fixed="right" label="操作" align="center" width="300">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" @click="previewBlogClick(scope.row)">预览</el-button>
|
||||||
|
<el-button type="primary" @click="editBlogClick(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="danger" @click="deleteBlogClick(scope.row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { useBlogStore } from '@/store/blog.ts'
|
||||||
|
import { IBlog } from '@/types/blog.ts'
|
||||||
|
import { commonElMessageBox, tableCellStyle, tableHeaderStyle, tableRowStyle } from 'vue3-common/utils/elUtil'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const blogStore = useBlogStore()
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await blogStore.queryUnapprovedBlogList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击新增博客按钮
|
||||||
|
*/
|
||||||
|
const addNewBlogClick = () => {
|
||||||
|
router.push({ name: 'BlogDetailId', params: { id: 0 } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击预览博客按钮
|
||||||
|
* @param blog 博客
|
||||||
|
*/
|
||||||
|
const previewBlogClick = async (blog: IBlog) => {
|
||||||
|
await router.push({ name: 'BlogPreviewId', params: { id: blog.id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击编辑博客按钮
|
||||||
|
* @param blog 博客
|
||||||
|
*/
|
||||||
|
const editBlogClick = async (blog: IBlog) => {
|
||||||
|
await router.push({ name: 'BlogDetailId', params: { id: blog.id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击删除博客按钮
|
||||||
|
* @param blog 博客
|
||||||
|
*/
|
||||||
|
const deleteBlogClick = (blog: IBlog) => {
|
||||||
|
blogStore.blogApiType = 'DELETE'
|
||||||
|
|
||||||
|
commonElMessageBox('是否确认删除该博客?').then(() => {
|
||||||
|
blogStore.handleBlogApi(blog.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -1,13 +1,198 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="admin-module">
|
<div class="admin-module blog-dashboard">
|
||||||
Dashboard
|
<div class="blog-overview">
|
||||||
|
<el-statistic class="card-item" title="博客总数" :value="blogDashboard.overview.blogCount" />
|
||||||
|
|
||||||
|
<el-statistic class="card-item" title="类别总数" :value="blogDashboard.overview.categoryCount" />
|
||||||
|
|
||||||
|
<el-statistic class="card-item" title="字数统计" :value="blogDashboard.overview.wordCount" />
|
||||||
|
|
||||||
|
<el-statistic class="card-item" title="访问统计" :value="blogDashboard.overview.visitCount" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="blog-chart">
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊每月博客发布统计</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="approvedMonthlyChartRef"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊每月博客访问统计</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="visitMonthlyChartRef"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊博客访问数量排行</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="visitRankChartRef"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊博客类别统计</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="categoryChartRef"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊博客阅读时长排行</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="readRankChartRef"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chart-container card-item">
|
||||||
|
<div class="content">
|
||||||
|
<span class="title">📊博客评论数量排行</span>
|
||||||
|
</div>
|
||||||
|
<div class="chart" ref="commentRankChartRef"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import { barChartOptions, lineChartOptions, pieChartOptions } from 'vue3-common/utils/eChartsUtil'
|
||||||
|
import { useAppStore } from '@/store/app.ts'
|
||||||
|
import {
|
||||||
|
queryApprovedMonthlyStatsApi, queryCategoryStatsApi, queryCommentRankStatsApi, queryOverviewStatsApi,
|
||||||
|
queryReadRankStatsApi,
|
||||||
|
queryVisitMonthlyStatsApi,
|
||||||
|
queryVisitRankStatsApi
|
||||||
|
} from '@/apis/stats'
|
||||||
|
import { IBlogOverview } from '@/types/blog'
|
||||||
|
|
||||||
|
const appStore = useAppStore()
|
||||||
|
|
||||||
|
const approvedMonthlyChartRef = ref<HTMLElement>()
|
||||||
|
const visitMonthlyChartRef = ref<HTMLElement>()
|
||||||
|
const visitRankChartRef = ref<HTMLElement>()
|
||||||
|
const categoryChartRef = ref<HTMLElement>()
|
||||||
|
const readRankChartRef = ref<HTMLElement>()
|
||||||
|
const commentRankChartRef = ref<HTMLElement>()
|
||||||
|
|
||||||
|
let approvedMonthlyChart: echarts.ECharts
|
||||||
|
let visitMonthlyChart: echarts.ECharts
|
||||||
|
let visitRankChart: echarts.ECharts
|
||||||
|
let categoryChart: echarts.ECharts
|
||||||
|
let readRankChart: echarts.ECharts
|
||||||
|
let commentRankChart: echarts.ECharts
|
||||||
|
|
||||||
|
const blogDashboard = reactive({
|
||||||
|
overview: {
|
||||||
|
blogCount: 0,
|
||||||
|
categoryCount: 0,
|
||||||
|
wordCount: 0,
|
||||||
|
greatCount: 0,
|
||||||
|
visitCount: 0
|
||||||
|
} as IBlogOverview
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
approvedMonthlyChart = echarts.init(approvedMonthlyChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
visitMonthlyChart = echarts.init(visitMonthlyChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
visitRankChart = echarts.init(visitRankChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
categoryChart = echarts.init(categoryChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
readRankChart = echarts.init(readRankChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
commentRankChart = echarts.init(commentRankChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
|
||||||
|
|
||||||
|
updateChart()
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateChart = async () => {
|
||||||
|
blogDashboard.overview = await queryOverviewStatsApi()
|
||||||
|
|
||||||
|
const approvedMonthlyData = await queryApprovedMonthlyStatsApi(2025)
|
||||||
|
const approvedXAxis = approvedMonthlyData.map((item) => item.name)
|
||||||
|
const approvedYAxis = approvedMonthlyData.map((item) => item.value)
|
||||||
|
approvedMonthlyChart.setOption(lineChartOptions('日期', approvedXAxis, '数量(篇)', approvedYAxis))
|
||||||
|
|
||||||
|
const visitMonthlyData = await queryVisitMonthlyStatsApi(2025)
|
||||||
|
const visitMonthlyXAxis = visitMonthlyData.map((item) => item.name)
|
||||||
|
const visitMonthlyYAxis = visitMonthlyData.map((item) => item.value)
|
||||||
|
visitMonthlyChart.setOption(lineChartOptions('日期', visitMonthlyXAxis, '访问量(人)', visitMonthlyYAxis))
|
||||||
|
|
||||||
|
const visitRankData = await queryVisitRankStatsApi()
|
||||||
|
const visitRankXAxis = visitRankData.map((item) => item.name)
|
||||||
|
const visitRankYAxis = visitRankData.map((item) => item.value)
|
||||||
|
visitRankChart.setOption(barChartOptions('名称', visitRankXAxis, '访问量(人)', visitRankYAxis))
|
||||||
|
|
||||||
|
const categoryData = await queryCategoryStatsApi()
|
||||||
|
categoryChart.setOption(pieChartOptions('类别', '篇', categoryData))
|
||||||
|
|
||||||
|
const readRankData = await queryReadRankStatsApi()
|
||||||
|
const readRankXAxis = readRankData.map((item) => item.name)
|
||||||
|
const readRankYAxis = readRankData.map((item) => item.value)
|
||||||
|
readRankChart.setOption(barChartOptions('名称', readRankXAxis, '时长(分钟)', readRankYAxis))
|
||||||
|
|
||||||
|
const commentRankData = await queryCommentRankStatsApi()
|
||||||
|
const commentRankXAxis = commentRankData.map((item) => item.name)
|
||||||
|
const commentRankYAxis = commentRankData.map((item) => item.value)
|
||||||
|
commentRankChart.setOption(barChartOptions('名称', commentRankXAxis, '评论量(个)', commentRankYAxis))
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss">
|
||||||
|
.blog-dashboard {
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.blog-overview {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.el-statistic {
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
.el-statistic__head {
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-statistic__number {
|
||||||
|
font-size: xx-large;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-chart {
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 40px 1fr;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 0 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid #009FA8;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
height: 300px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ export const metaList: IRouteMetaConfig = {
|
|||||||
title: '类别管理',
|
title: '类别管理',
|
||||||
icon: 'admin-blogCategory'
|
icon: 'admin-blogCategory'
|
||||||
},
|
},
|
||||||
|
'/blog/unapproved': {
|
||||||
|
title: '草稿箱',
|
||||||
|
icon: 'admin-blogUnapproved'
|
||||||
|
},
|
||||||
'/blog/detail/:id': {
|
'/blog/detail/:id': {
|
||||||
title: '',
|
title: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
|
|||||||
Reference in New Issue
Block a user