Skip to content

Commit

Permalink
[add] Dashboard Home statistic
Browse files Browse the repository at this point in the history
  • Loading branch information
VecHK committed Jan 8, 2024
1 parent 568c3b8 commit 8462e2c
Show file tree
Hide file tree
Showing 12 changed files with 248 additions and 53 deletions.
6 changes: 3 additions & 3 deletions dashboard/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"dependencies": {
"axios": "0.21.1",
"element-ui": "^2.15.4",
"element-ui": "^2.15.14",
"js-cookie": "2.2.0",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
Expand Down
7 changes: 7 additions & 0 deletions dashboard/src/api/statistic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import request from '@/utils/request'

export const getStatistic = () =>
request({
url: `admin/statistic`,
method: 'GET',
})
5 changes: 3 additions & 2 deletions dashboard/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ if (process.env.NODE_ENV === 'production') {
}

// set ElementUI lang to EN
Vue.use(ElementUI, { locale })
// Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)
Vue.use(ElementUI)
console.log('ElementUI', ElementUI)

Vue.config.productionTip = false

Expand Down
53 changes: 22 additions & 31 deletions dashboard/src/views/dashboard/components/refresh-thumbs.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
<template>
<div>
<ElProgress
v-if="processing"
:percentage="percentage"
:color="color"
/>
<ElButton
v-else-if="showButton"
size="small"
type="primary"
icon="el-icon-refresh"
@click="processing || refreshThumbsConfirm()"
>刷新缩略图</ElButton>
<ElProgress
v-if="show_progress"
:percentage="percentage"
:color="color"
/>
</div>
</template>

Expand All @@ -21,6 +22,10 @@ import { getList as getMemberList } from '@/api/member'
const initProgress = () => ({ total: 0, success: 0, failure: 0 })
export default {
props: {
showButton: { type: Boolean, default: true }
},
data: () => ({
...initProgress(),
processing: false,
Expand Down Expand Up @@ -74,35 +79,21 @@ export default {
}
}
},
async refreshThumbsConfirm() {
const confirm = await this.confirm('', `你确定要刷新吗?`, {
confirmButtonClass: 'el-button--warning',
})
if (!confirm) { return }
try {
this.processing = true
await this.refreshThumbs()
if (this.failure === 0) {
this.$emit('success', `所有缩略图已刷新`)
async refreshThumbsConfirmProcessing() {
if (this.processing === false) {
try {
this.processing = true
await this.refreshThumbs()
if (this.failure === 0) {
this.$emit('success', `所有缩略图已刷新`)
}
} catch (err) {
this.$emit('error', '刷新缓存失败', err)
} finally {
this.processing = false
}
} catch (err) {
this.$emit('error', '刷新缓存失败', err)
} finally {
this.processing = false
}
},
async confirm(title, content, appendOpt = {}) {
const opt = Object.assign({
confirmButtonText: '确定',
cancelButtonText: '取消',
confirmButtonClass: 'el-button--warning',
showClose: false,
}, appendOpt)
return this.$confirm(content, title, opt)
.then(() => true)
.catch(() => false)
},
}
}
</script>
Expand Down
121 changes: 108 additions & 13 deletions dashboard/src/views/dashboard/index.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,81 @@
<template>
<ElContainer
v-loading="loading"
style="padding-top: 20px; width: 640px"
direction="vertical"
>
<ElMain>
<ElAlert v-for="alert in alerts" :key="alert.id" :type="alert.type" :title="alert.title" style="margin-bottom: 10px;" />
<RefreshThumbs @error="handleError" @warning="handleWarning" @success="handleSuccess" @info="handleInfo" />
<ElContainer v-loading="loading" style="width: 640px" direction="vertical">
<ElMain height="auto">
<ElRow :gutter="30">
<ElCol :span="20">
<ElAlert
v-for="alert in alerts"
:key="alert.id"
style="margin-bottom: 10px;"
show-icon
:type="alert.type"
:title="alert.title"
:description="alert.description"
@close="handleAlertClose(alert.id)"
/>
</ElCol>
</ElRow>

<ElRow :gutter="20" style="padding: 20px 0">
<ElCol :span="4">
<ElStatistic title="总投稿数">
<template slot="formatter">{{ statistic.available_photo_count }}</template>
</ElStatistic>
</ElCol>
<ElCol :span="8">
<ElStatistic title="图片占用空间">
<template slot="prefix">
<ElLink style="opacity: 0" icon="el-icon-refresh" size="mini">清理</ElLink>
</template>
<template slot="formatter">{{ statistic.src_total_size }}</template>
<template slot="suffix">
<el-popconfirm
confirm-button-text="是的"
cancel-button-text="不了"
icon="el-icon-info"
icon-color="red"
title="你确定要清理吗?这将移除图片库中没有被引用的图片"
@confirm="handleClickCleanImagePool"
>
<ElLink slot="reference" icon="el-icon-refresh" size="mini">清理</ElLink>
</el-popconfirm>
</template>
</ElStatistic>
</ElCol>

<ElCol :span="10">
<ElStatistic title="缩略图占用空间">
<template slot="prefix">
<ElLink style="opacity: 0" icon="el-icon-refresh" size="mini">重新生成</ElLink>
</template>
<template slot="formatter">{{ statistic.thumb_total_size }}</template>
<template slot="suffix">
<el-popconfirm
confirm-button-text="是的"
cancel-button-text="不了"
icon="el-icon-info"
icon-color="red"
title="你确定要重新生成吗?(这将花费一些时间,请在完成前不要离开本页面)"
@confirm="handleClickRefreshThumb"
>
<ElLink slot="reference" icon="el-icon-refresh" size="mini">重新生成</ElLink>
</el-popconfirm>
</template>
</ElStatistic>
</ElCol>
</ElRow>

<ElRow :gutter="30">
<ElCol :span="20" direction="vertical">
<RefreshThumbs ref="refreshThumbs" :show-button="false" @error="handleError" @warning="handleWarning" @success="handleSuccess" @info="handleInfo" />
</ElCol>
</ElRow>
</ElMain>
</ElContainer>
</template>

<script>
import { getStatistic } from '@/api/statistic'
import RefreshThumbs from './components/refresh-thumbs.vue'
import { v4 as uuidv4 } from 'uuid'
Expand All @@ -26,11 +90,11 @@ function ConsolePrint(alert_type) {
function HandleAlertEvent(alert_type) {
const consolePrint = ConsolePrint(alert_type).bind(console)
return function(title, err) {
if (err) {
if (err instanceof Error) {
consolePrint(`${title}`, err)
this.addAlert(alert_type, `${title}: ${err.message}`)
this.addAlert(alert_type, title, err.message)
} else {
this.addAlert(alert_type, title)
this.addAlert(alert_type, title, err)
}
}
}
Expand All @@ -43,12 +107,43 @@ export default {
data: () => ({
loading: false,
alerts: [],
statistic: {
available_photo_count: 'N/A',
src_total_size: 'N/A',
thumb_total_size: 'N/A',
}
}),
mounted() {
this.refresh()
},
methods: {
addAlert(type, title) {
this.alerts = [...this.alerts, { id: uuidv4(), type, title }]
async refresh() {
try {
this.loading = true
this.statistic = await getStatistic()
} finally {
this.loading = false
}
},
handleClickCleanImagePool() {
},
handleClickRefreshThumb() {
this.$refs.refreshThumbs.refreshThumbsConfirmProcessing().finally(() => {
this.refresh()
})
},
handleAlertClose(remove_id) {},
addAlert(type, title, description) {
console.log('desc', description)
this.alerts = [...this.alerts, { id: uuidv4(), type, title, description }]
},
handleError: HandleAlertEvent('error'),
handleWarning: HandleAlertEvent('warning'),
handleSuccess: HandleAlertEvent('success'),
Expand Down
3 changes: 2 additions & 1 deletion server/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "eslint-config-egg",
"rules": {
"no-else-return": [0],
"no-lone-blocks": [0]
"no-lone-blocks": [0],
"no-extra-parens": [0]
}
}
77 changes: 77 additions & 0 deletions server/app/controller/admin/statistic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict';

const { filesize } = require('filesize');
// const getFolderSize = require('get-folder-size');
const fs = require('fs');
const path = require('path');

async function getFileSize(path) {
try {
const { size } = await fs.promises.stat(path);
return size;
} catch (e) {
return 0;
}
}

module.exports = app => {
class StatisticController extends app.Controller {
async getAvailablePhotoList(ctx) {
let photo_list = [];

const galleries = await ctx.model.Gallery.findAll();

for (const gallery of galleries) {
const photos = await ctx.model.Photo.findAll({
where: { gallery_id: gallery.id },
});
photo_list = [ ...photo_list, ...photos ];
}

return photo_list;
}
async getAllMemberList(ctx) {
const member_list = await ctx.model.Member.findAll({});
return member_list;
}

async getSrcTotalSize(ctx, image_path, src_list) {
const full_src_list = src_list
.map(ctx.app.serviceClasses.image.allFilename)
.flat();

let total = 0;
for (const src of full_src_list) {
const size = await getFileSize(path.join(image_path, src));
total = total + size;
}
return total;
}

async show(ctx) {
const [ available_photo_list, member_list ] = await Promise.all([
this.getAvailablePhotoList(ctx),
this.getAllMemberList(ctx),
]);

const src_list = [
...available_photo_list.map(p => p.src),
...member_list.map(m => m.avatar_src),
];

const { imageSavePath, imageThumbSavePath } = ctx.app.config;

const [ src_total_size_raw, thumb_total_size_raw ] = await Promise.all([
this.getSrcTotalSize(ctx, imageSavePath, src_list),
this.getSrcTotalSize(ctx, imageThumbSavePath, src_list),
]);

ctx.backData(200, {
available_photo_count: available_photo_list.length,
src_total_size: filesize(src_total_size_raw),
thumb_total_size: filesize(thumb_total_size_raw),
});
}
}
return StatisticController;
};
2 changes: 2 additions & 0 deletions server/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ module.exports = app => {

setRouter('post', 'admin/login', controller.admin.auth.login);

setAdminRouter('get', 'statistic', controller.admin.statistic.show);

setAdminRouter('post', 'image/upload', controller.admin.image.upload);
setAdminRouter('post', 'image/refresh-thumb', controller.admin.image.refreshThumb);
setAdminRouter('get', 'image/available-photo', controller.admin.image.getAllAvailablePhoto);
Expand Down
9 changes: 9 additions & 0 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8462e2c

Please sign in to comment.