数字督察一体化平台-前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

425 lines
15 KiB

<template>
<el-button @click="show = true"
>上传
<template #icon>
<icon name="el-icon-upload-filled" />
</template>
</el-button>
<el-dialog
title="上传佐证材料"
v-model="show"
width="60vw"
:close-on-click-modal="false"
>
<el-row :gutter="20" style="min-height: 60vh">
<el-col :span="12">
<el-upload
drag
multiple
:action="`${BASE_PATH}/file/upload`"
:headers="{ Authorization: getToken() }"
:before-upload="beforeUpload"
@progress="uploadProgress"
@success="handleSuccess"
@error="handleError"
:show-file-list="false"
>
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
将文件拖拽到此处或<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip">文件大小限制为 100MB</div>
</template>
</el-upload>
</el-col>
<el-col :span="12">
<div class="flex gap v-center" style="height: 32px">
<span style="font-size: 12px" v-if="activeFileIds.length"
>选中{{ activeFileIds.length }}个文件</span
>
<el-select
size="small"
style="width: 200px"
v-model="fileClassId"
clearable
>
<el-option
v-for="item in fileClasss"
:value="item.id"
:label="item.classTitle"
/>
</el-select>
<div v-if="activeFileIds.length">
<el-button
type="primary"
size="small"
plain
@click="handleUpdateFileClass"
:disabled="!fileClassId"
>修改文件分类</el-button
>
<el-button
size="small"
@click="
activeFileIds = [];
fileClassId = '';
"
>取消选中</el-button
>
</div>
</div>
<el-scrollbar max-height="500px">
<div style="margin: 2px">
<p>
<span class="text-danger">未分类</span>
<span
style="font-size: 12px; color: #999"
class="ml-10"
>可单击选择下面文件进行分类</span
>
</p>
<div class="flex gap">
<template
v-for="(item, index) in fileList.filter(
(item) => !item.fileClassId
)"
:key="index"
>
<template v-if="item.loading">
<el-progress
type="circle"
:percentage="item.percent"
:width="80"
color="var(--primary-color)"
></el-progress>
</template>
<div
v-else
class="pointer"
@click="
() => {
if (
activeFileIds.includes(item.uid)
) {
activeFileIds.splice(
activeFileIds.indexOf(
item.uid
),
1
);
} else {
activeFileIds.push(item.uid);
}
}
"
>
<div
class="item flex end v-center column text-center"
:title="item.fileName"
:active="
activeFileIds.includes(item.uid)
"
>
<icon
:name="getIconName(item.fileName)"
:size="40"
/>
<span class="filename">{{
item.fileName
}}</span>
<a
class="remove-btn"
@click.stop="remove(index)"
>
<icon
name="el-icon-CircleCloseFilled"
:size="16"
/>
</a>
</div>
</div>
</template>
</div>
<div v-for="item in fileClasss" class="file-class-item">
<header class="text-primary">
{{ item.classTitle }}
</header>
<div class="flex gap file-class-body">
<template
v-for="(item, index) in fileList.filter(
(file) => file.fileClassId === item.id
)"
:key="index"
>
<template v-if="item.loading">
<el-progress
type="circle"
:percentage="item.percent"
:width="80"
color="var(--primary-color)"
></el-progress>
</template>
<div
v-else
class="pointer"
@click="
() => {
if (
activeFileIds.includes(
item.uid
)
) {
activeFileIds.splice(
activeFileIds.indexOf(
item.uid
),
1
);
} else {
activeFileIds.push(
item.uid
);
}
}
"
>
<div
class="item flex end v-center column text-center"
:title="item.fileName"
:active="
activeFileIds.includes(item.uid)
"
>
<icon
:name="
getIconName(item.fileName)
"
:size="40"
/>
<span class="filename">{{
item.fileName
}}</span>
<a
class="remove-btn"
@click.stop="remove(index)"
>
<icon
name="el-icon-CircleCloseFilled"
:size="16"
/>
</a>
</div>
</div>
</template>
</div>
</div>
</div>
</el-scrollbar>
</el-col>
</el-row>
<footer class="flex end mt-20">
<el-button type="primary" size="large" @click="handleSubmit"
>确定</el-button
>
</footer>
</el-dialog>
</template>
<script setup>
import { getToken } from "@/utils/token";
import { BASE_PATH } from "@/api/request";
import feedback from "@/utils/feedback";
import { getIconName } from "@/utils/util";
import {
ProblemSources
} from "@/enums/dictEnums";
const props = defineProps({
files: {
type: Array,
default: () => [],
},
problemSourcesCode: {
type: String,
default: "",
},
});
const emit = defineEmits(["update:files"]);
const show = ref(false);
const fileList = ref(props.files);
const activeFileIds = ref([]);
const fileClassId = ref("");
const fileClasss = ref([]);
if (props.problemSourcesCode === ProblemSources.JWDC) {
fileClasss.value = [
{
id: 1,
classTitle: "容错免责样本申请表",
classRemarks: "",
},
{
id: 2,
classTitle:
"针对群众不满意原因,提供无过错的音视频、微信或短信截图等证明资料",
classRemarks: "",
},
{
id: 3,
classTitle: "110、122接处警开始、结束及处置过程中的视频截图",
classRemarks: "",
},
{
id: 4,
classTitle: "自动回访不满意后所对的回访录音",
classRemarks: "",
},
{
id: 5,
classTitle: "单位/个人所做其他工作",
classRemarks: "",
},
];
}
function beforeUpload(file) {
fileList.value.push({
uid: file.uid,
percent: 0,
loading: true,
fileName: file.name,
});
}
function uploadProgress(progressEvent, file) {
const filterFiles = fileList.value.filter((item) => file.uid === item.uid);
if (filterFiles.length) {
filterFiles[0].percent = parseInt(progressEvent.percent);
}
}
function handleSuccess(data, file) {
if (data.code !== 200) {
return;
}
const filterFiles = fileList.value.filter((item) => file.uid === item.uid);
if (filterFiles.length) {
filterFiles[0].fileName = data.data.fileName;
filterFiles[0].filePath = data.data.filePath;
filterFiles[0].loading = false;
}
}
function handleError(e) {
console.log(e);
feedback.msgError("上传失败!");
}
function handleUpdateFileClass() {
fileList.value
.filter((item) => activeFileIds.value.includes(item.uid))
.forEach((file) => {
file.fileClassId = fileClassId.value;
});
activeFileIds.value = [];
fileClassId.value = "";
}
function handleSubmit() {
debugger;
emit(
"update:files",
fileList.value.filter((item) => item.filePath)
);
show.value = false;
}
function remove(index) {
const files = [...props.files];
files.splice(index, 1);
emit("update:files", files);
}
</script>
<style lang="scss" scoped>
.el-upload {
--el-upload-dragger-padding-horizontal: 80px;
}
.item {
width: 80px;
height: 80px;
margin-bottom: 12px;
border-radius: 2px;
color: var(--primary-color);
position: relative;
border: 1px solid transparent;
border-radius: 10px;
&:hover {
background-color: #ededed;
border-color: var(--primary-color);
span.filename {
font-weight: 700;
}
}
&[active="true"] {
background-color: #ededed;
border-color: var(--primary-color);
}
span.filename {
line-height: 1.2;
font-size: 12px;
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
margin-top: 10px;
overflow: hidden;
}
.img-box {
width: 80px;
height: 80px;
background-size: cover;
background-position: center;
border-radius: 2px;
&:hover {
outline: 2px solid #ff9800;
}
}
.remove-btn {
position: absolute;
top: -8px;
right: -8px;
display: block;
border-radius: 50%;
height: 16px;
background-color: #fff;
color: #666;
&:hover {
color: red;
cursor: pointer;
}
}
}
.file-class-item {
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
margin-bottom: 10px;
header {
padding: 4px 8px;
border-bottom: 1px solid #e4e7ed;
}
.file-class-body {
min-height: 20px;
padding: 4px 8px;
}
}
:deep() {
.el-dialog .el-dialog__body {
background-color: #f5f5f5;
}
}
</style>