blog-admin-web/src/views/api/SourceImage.vue
2026-03-21 01:06:54 +08:00

180 lines
6.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="page-wrapper">
<el-alert type="info" show-icon :closable="false" >
<template #title>上传要求</template>
图片格式为{{allowUploadExt.join('、')}}文件大小不超过10MB
</el-alert>
<div class="btn-container" style="margin-top:10px;">
<el-upload
action="/api/source-image/upload"
accept="image/jpeg,image/png,image/svg+xml,image/x-icon"
name="image"
:headers="{token: store.state.loginInfo.token}"
:before-upload="beforeUpload"
:on-success="uploadSuccess"
:on-error="uploadError"
auto-upload
:show-file-list="false"
style="display: inline-block;margin-right: 10px;">
<el-button type="primary" icon="Upload" :loading="isUploading">上传图片</el-button>
</el-upload>
<el-button type="danger" @click="deleteAll" style="vertical-align: bottom">批量删除</el-button>
</div>
<div class="table-container">
<el-table :data="sourceImageData" v-loading="loading" stripe @selection-change="dataSelect">
<el-table-column type="selection" width="55" />
<el-table-column prop="hash" label="md5" width="300" />
<el-table-column prop="size" label="文件大小" >
<template #default="scope">
{{ prettyBytes(scope.row.size) }}
</template>
</el-table-column>
<el-table-column prop="mime" label="MIME" />
<el-table-column prop="label" label="标签" >
<template #default="scope">
<el-tag v-for="label in scope.row.label" :key="label" effect="plain">{{label}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="created_at" label="上传时间" >
<template #default="scope">
{{ datetimeFormat(scope.row.created_at) }}
</template>
</el-table-column>
<el-table-column label="操作" >
<template #default="scope">
<el-button link icon="EditPen" type="primary" plain @click="modifyTags(scope.row)" title="修改标签"></el-button>
<el-button link icon="View" plain @click="preview(scope.row)" title="预览"></el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="page-container">
<el-pagination background
:page-sizes="store.state.pageSizeOpts"
:layout="store.state.pageLayout"
:current-page="search.pageNum"
:total="total"
@size-change="pageSizeChange"
@current-change="pageChange">
</el-pagination>
</div>
<el-dialog v-model="modifyModal" title="修改标签" width="630px" @closed="loadData">
<el-transfer
v-model="curModifyLabels"
filterable
:render-content="renderFunc"
:titles="['可选标签', '已选标签']"
:format="{
noChecked: '${total}',
hasChecked: '${checked}/${total}',
}"
@change="tarnsferChange"
:data="labels"
></el-transfer>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, computed, h } from 'vue'
import { useStore } from 'vuex'
import { ElMessage, ElMessageBox } from 'element-plus'
import prettyBytes from 'pretty-bytes'
import { MsgResult, Page } from '@/model/common.dto'
import { useBaseList } from '@/model/baselist'
import { SourceImageModel } from '@/model/api/source-image'
import http from '@/utils/http'
const store = useStore()
const { loading, total, search, setLoadData, pageChange, pageSizeChange, datetimeFormat } = useBaseList(new Page())
const allowUploadExt = ['jpg', 'jpeg', 'png', 'svg', 'ico']
const sourceImageData = ref<SourceImageModel[]>([])
const curModifyLabels = ref<string[]>([])
const labelList = ref<string[]>([])
const curId = ref<string | null>(null)
const modifyModal = ref(false)
const isUploading = ref(false)
function renderFunc(h: Function, option: any) {
return h('span', null, option.label)
}
const labels = computed(() => {
return labelList.value.map(item => {
return { key: item, label: item }
})
})
let selectedData: string[] = []
async function loadData(): Promise<void> {
loading.value = true
const data = await http.get<Page, any>('/api/v2/source-image/list', {params: search})
selectedData = []
loading.value = false
total.value = data.total
sourceImageData.value = data.data
}
setLoadData(loadData)
function deleteAll(): void {
if (!selectedData.length) {
ElMessage.warning('请选择要删除的数据')
return
}
ElMessageBox.confirm(`是否确认删除选中的${selectedData.length}条数据?`, '确认删除', {type: 'warning'}).then(async () => {
await http.delete('/api/v2/source-image/delete', {params: {_ids: selectedData}})
ElMessage.success('删除成功')
loadData()
}).catch(() => {})
}
function dataSelect(selection: SourceImageModel[]): void {
selectedData = selection.map(item => item._id)
}
function beforeUpload(file: File): boolean {
if (file.size > 10 << 20) {
ElMessage.warning('文件大小超过10MB')
return false
}
isUploading.value = true
return true
}
function uploadSuccess(response: MsgResult): void {
if (response.status) {
ElMessage.success(response.message)
loadData()
} else {
ElMessage.warning(response.message)
}
isUploading.value = false
}
function uploadError(error: Error): void {
isUploading.value = false
ElMessage.error(error.message)
}
function preview(row: SourceImageModel): void {
ElMessageBox({
title: '图片预览',
message: h('img', { style: `width:500px`, src: `/api/v2/common/randomBg?id=${row._id}` }, ''),
showCancelButton: false,
confirmButtonText: '关闭',
customStyle: {width: '530px', maxWidth: 'unset'}
}).catch(() => {})
}
function modifyTags(item: SourceImageModel): void {
curModifyLabels.value.length = 0
if (item.label) {
curModifyLabels.value.push(...item.label)
}
curId.value = item._id
modifyModal.value = true
}
async function tarnsferChange(newTargetKeys: string[], direction: 'right' | 'left', moveKeys: string[]) {
await http.post('/api/v2/source-image/updateLabel', {id: curId.value, labels: newTargetKeys})
}
// created
http.get<never, any>('/api/v2/common/config/image_label').then(data => {
labelList.value.push(...data)
loadData()
})
</script>