178 lines
6.0 KiB
Vue
178 lines
6.0 KiB
Vue
<template>
|
||
<div>
|
||
<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 lang="ts">
|
||
import { Options } from 'vue-class-component'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import prettyBytes from 'pretty-bytes'
|
||
import { MsgResult, Page } from '@/model/common.dto'
|
||
import BaseList from '@/model/baselist'
|
||
import { SourceImageModel } from '@/model/api/source-image'
|
||
import { h } from 'vue'
|
||
|
||
let selectedData: string[] = []
|
||
@Options({
|
||
name: 'SourceImage',
|
||
})
|
||
export default class SourceImage extends BaseList<Page> {
|
||
prettyBytes = prettyBytes
|
||
search = new Page()
|
||
allowUploadExt = ['jpg','jpeg','png','svg','ico']
|
||
sourceImageData: SourceImageModel[] = []
|
||
curModifyLabels: string[] = []
|
||
labelList: string[] = []
|
||
curId: string | null = null
|
||
modifyModal: boolean = false
|
||
isUploading: boolean = false
|
||
renderFunc(h: Function, option: any) {
|
||
return h('span', null, option.label)
|
||
}
|
||
get labels() {
|
||
return this.labelList.map(item => {
|
||
return { key: item, label: item }
|
||
})
|
||
}
|
||
async loadData(): Promise<void> {
|
||
this.loading = true
|
||
const data = await this.$http.get<Page, any>('/api/v1/source-image/list', {params:this.search})
|
||
selectedData = []
|
||
this.loading = false
|
||
this.total = data.total
|
||
this.sourceImageData = data.data
|
||
}
|
||
deleteAll(): void {
|
||
if(!selectedData.length) {
|
||
ElMessage.warning('请选择要删除的数据')
|
||
return
|
||
}
|
||
ElMessageBox.confirm(`是否确认删除选中的${selectedData.length}条数据?`, '确认删除', {type: 'warning'}).then(async () => {
|
||
await this.$http.delete('/api/v1/source-image/delete', {params:{_ids: selectedData}})
|
||
ElMessage.success('删除成功')
|
||
this.loadData()
|
||
}).catch(() => {})
|
||
}
|
||
dataSelect(selection: SourceImageModel[]): void {
|
||
selectedData = selection.map(item => item._id)
|
||
}
|
||
beforeUpload(file: File): boolean {
|
||
if(file.size > 10 << 20) {
|
||
ElMessage.warning('文件大小超过10MB')
|
||
return false
|
||
}
|
||
this.isUploading = true
|
||
return true
|
||
}
|
||
uploadSuccess(response: MsgResult): void {
|
||
if(response.status) {
|
||
ElMessage.success(response.message)
|
||
this.loadData()
|
||
} else {
|
||
ElMessage.warning(response.message)
|
||
}
|
||
this.isUploading = false
|
||
}
|
||
uploadError(error: Error): void {
|
||
this.isUploading = false
|
||
ElMessage.error(error.message)
|
||
}
|
||
preview(row: SourceImageModel): void {
|
||
ElMessageBox({
|
||
title: '图片预览',
|
||
message: h('img', { style: `width:500px`, src: `/api/v1/common/randomBg?id=${row._id}` }, ''),
|
||
showCancelButton: false,
|
||
confirmButtonText: '关闭',
|
||
customStyle: {width: '530px', maxWidth: 'unset'}
|
||
}).catch(() => {})
|
||
}
|
||
modifyTags(item: SourceImageModel): void {
|
||
this.curModifyLabels.length = 0
|
||
if(item.label) {
|
||
this.curModifyLabels.push(...item.label)
|
||
}
|
||
this.curId = item._id
|
||
this.modifyModal = true
|
||
}
|
||
async tarnsferChange(newTargetKeys: string[], direction: 'right' | 'left', moveKeys: string[]) {
|
||
await this.$http.post('/api/v1/source-image/updateLabel', {id: this.curId, labels: newTargetKeys})
|
||
}
|
||
created() {
|
||
this.$http.get<never, any>('/api/v1/common/config/image_label').then(data => {
|
||
this.labelList.push(...data)
|
||
this.loadData()
|
||
})
|
||
}
|
||
}
|
||
</script> |