Skip to content

Commit

Permalink
[add] better refresh thumb api
Browse files Browse the repository at this point in the history
  • Loading branch information
VecHK committed Jan 7, 2024
1 parent b82d2d2 commit c8b4815
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 120 deletions.
14 changes: 12 additions & 2 deletions dashboard/src/api/image.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import request from '@/utils/request'

export const refreshThumbs = () =>
export const __AVATAR_THUMB_SIZE__ = 128

export const refreshThumb = (src, thumb_size) =>
request({
url: `admin/image/refresh-thumb`,
method: 'POST',
timeout: 0,
data: { src, thumb_size },
})

export const getAllAvailablePhoto = () =>
request({
url: 'admin/image/refresh-thumb',
url: `admin/image/available-photo`,
method: 'GET',
timeout: 0,
})
153 changes: 153 additions & 0 deletions dashboard/src/views/dashboard/components/refresh-thumbs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<template>
<div>
<ElButton
size="small"
type="primary"
icon="el-icon-refresh"
@click="processing || refreshThumbsConfirm()"
>刷新缩略图</ElButton>
<div v-if="show">
<ElProgress
:percentage="percentage('photo')"
:color="color('photo')"
/>
</div>
</div>
</template>

<script>
import { refreshThumb, getAllAvailablePhoto, __AVATAR_THUMB_SIZE__ } from '@/api/image'
import { getList as getMemberList } from '@/api/member'
export default {
data: () => ({
show: false,
processing: false,
member_progress: [],
photo_progress: [],
}),
watch: {
processing(val) {
if (val === true) {
this.show = true
}
}
},
mounted() {
},
methods: {
getProgress(property) {
const [total = 0, ...progress] = this[`${property}_progress`]
const success = progress.filter(p => p).length
const failure = progress.filter(p => !p).length
return [total, progress.length, success, failure]
},
percentage(property) {
const [total, progress] = this.getProgress(property)
if (total === 0) {
return 0
} else {
return Math.ceil(100 * (progress / total))
}
},
color(property) {
const [, , , failure] = this.getProgress(property)
if (failure > 0) {
return '#e6a23c'
} else {
return '#409eff'
}
},
Progress(property) {
const [total, progress, success, failure] = this.getProgress(property)
console.log('Progress', total, success, failure)
return {
per: (total === 0) ? 0 : 100 * (progress.length / total),
format: () => {
const [, , success, failure] = this.getProgress(property)
return `成功: ${success}${failure.length ? ` (失败: ${failure.length})` : ''}`
},
}
},
async refreshThumbs() {
const [photos, members] = await Promise.all([
getAllAvailablePhoto(), getMemberList()
])
const task_list = [
// eslint-disable-next-line no-extra-parens
...photos.map(p => (
() => {
return refreshThumb(p.src)
}
)),
// eslint-disable-next-line no-extra-parens
...members.map(m => (
() => {
return refreshThumb(m.avatar_src, __AVATAR_THUMB_SIZE__)
}
))
]
{
this.photo_progress = [task_list.length]
for (const task of task_list) {
try {
await task()
this.photo_progress = [...this.photo_progress, true]
} catch {
this.photo_progress = [...this.photo_progress, false]
}
}
const [, , , failure] = this.getProgress('photo')
if (failure > 0) {
this.$emit('warning', `${failure}个图片的缩略图刷新失败`)
}
}
},
async refreshThumbsConfirm() {
const confirm = await this.confirm('', `你确定要刷新吗?`, {
confirmButtonClass: 'el-button--warning',
})
if (!confirm) { return }
try {
this.processing = true
await this.refreshThumbs()
this.$emit('success', `缩略图已刷新`)
} 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>

<style lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>
74 changes: 41 additions & 33 deletions dashboard/src/views/dashboard/index.vue
Original file line number Diff line number Diff line change
@@ -1,62 +1,70 @@
<template>
<ElContainer
v-loading="loading"
style="padding-top: 20px; width: 1180px"
style="padding-top: 20px; width: 640px"
direction="vertical"
>
<ElHeader height="2em">
torzo gallery dashboard beta
<ElHeader v-if="alerts.length" height="auto">
<ElAlert
v-for="alert in alerts"
:key="alert.id"
:type="alert.type"
:title="alert.title"
/>
</ElHeader>

<ElMain>
<ElButton size="small" type="primary" icon="el-icon-refresh" @click="refreshThumbs">刷新缩略图</ElButton>
<RefreshThumbs
@error="handleError"
@warning="handleWarning"
@success="handleSuccess"
/>
</ElMain>
</ElContainer>
</template>

<script>
import RefreshThumbs from './components/refresh-thumbs.vue'
import { mapGetters } from 'vuex'
import { refreshThumbs as refreshThumbsApi } from '@/api/image'
let _ID_ = 0
const genID = () => ++_ID_
export default {
name: 'Dashboard',
components: {
RefreshThumbs,
},
data: () => ({
loading: false,
alerts: [],
}),
computed: {
...mapGetters([
'name'
])
},
mounted() {
},
methods: {
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)
appendAlert(type, title) {
this.alerts = [...this.alerts, {
type, title, id: genID()
}]
},
async refreshThumbs() {
const confirm = await this.confirm('', `你确定要刷新吗?`, {
confirmButtonClass: 'el-button--warning',
})
if (!confirm) {
return
}
try {
this.loading = true
await refreshThumbsApi()
this.$message.success(`缩略图已刷新`)
} catch (err) {
console.error('刷新失败', err)
this.$message.error(`刷新失败: ${err.message}`)
} finally {
this.loading = false
handleError(...args) { this.handleAlertEvent('error', ...args) },
handleWarning(...args) { this.handleAlertEvent('warning', ...args) },
handleSuccess(...args) { this.handleAlertEvent('success', ...args) },
handleAlertEvent(alert_type, ev_title, err) {
if (err) {
if (alert_type === 'error') {
console.error(`${ev_title}`, err)
} else if (alert_type === 'warning') {
console.warn(`${ev_title}`, err)
} else {
console.info(`${ev_title}`, err)
}
this.appendAlert(alert_type, `${ev_title}: ${err.message}`)
} else {
this.appendAlert(alert_type, ev_title)
}
},
}
Expand Down
4 changes: 3 additions & 1 deletion dashboard/src/views/member/detail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
>
<UploadImageBox
ref="UploadImageBox"
:thumb-size="128"
:thumb-size="avatar_thumb_size"
:preview-url="preview_url"
@upload-success="uploadSuccess"
/>
Expand All @@ -44,6 +44,7 @@
</template>

<script>
import { __AVATAR_THUMB_SIZE__ } from '@/api/image'
import { getDetail, create, update } from '@/api/member'
import UploadImageBox from '@/components/UploadImageBox'
Expand All @@ -54,6 +55,7 @@
},
data: () => ({
avatar_thumb_size: __AVATAR_THUMB_SIZE__,
loading: false,
preview_url: '',
form: {
Expand Down
Loading

0 comments on commit c8b4815

Please sign in to comment.