本笔记仅提供el-upload附件预览的思路,不保证完全cv就可以使用。
需修改fileUploadYt.vue中后端接口返回的数据格式;
如果你是vue3项目,还需要在temp.vue中修改@vue-office的导入方式,直接打开我的注释并且删除旧的导入即可。
Vue2+element文件上传预览的功能实现
https://blog.csdn.net/m0_74149462/article/details/129025238?ops_request_misc=%257B%2522request%255Fid%2522%253A%25225da3c6f21ac258714348fabc2f30021a%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=5da3c6f21ac258714348fabc2f30021a&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-3-129025238-null-null.nonecase&utm_term=%E9%A2%84%E8%A7%88&spm=1018.2226.3001.4450el-upload文件上传组件的封装
https://blog.csdn.net/m0_74149462/article/details/130361411?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522c439a6f34bedbeba7f67cdadb8d2ab4d%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=c439a6f34bedbeba7f67cdadb8d2ab4d&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-130361411-null-null.nonecase&utm_term=el-upload&spm=1018.2226.3001.4450

需要用到的插件
"@vue-office/docx": "^1.6.3", "@vue-office/excel": "^1.7.14", "@vue-office/pdf": "^2.0.10", "@vue-office/pptx": "^1.0.1",
// 如果是vue2项目的话还需要安装这个 "@vue/composition-api": "^1.7.2", "vue-demi": "^0.14.10",
1. 新建/filePreviewer页面
每次点击预览都会跳到这个页面,该页面接收两个参数fileType:文件类型和fileSrc:文件地址【可以是流或者cdn链接如:192.....0/a.docx】

javascript
{
path: "/filePreviewer",
component: () => import("@/components/filePreviewer/filePreviewer.vue"),
hidden: true
},
2. 配置filePreviewer
filePreviewer.vue
html
<template>
<div class="file-previewer">
<!-- <div class="file-previewer-header">-->
<!-- <el-page-header @back="goBack">-->
<!-- <template #content>-->
<!-- <span class="text-large font-600 mr-3"> {{ title }} </span>-->
<!-- </template>-->
<!-- <div class="mt-4 text-sm font-bold"></div>-->
<!-- </el-page-header>-->
<!-- </div>-->
<div class="file-previewer-content">
<Temp
ref="tempRef"
:fileType="fileType"
:fileSrc="fileSrc"
v-bind="$attrs"
/>
</div>
</div>
</template>
<script>
import Temp from "@/components/filePreviewer/temp.vue";
import { getToken } from "@/utils/auth";
import axios from "axios";
import sysCode from "@/utils/sysCode";
import { blobValidate } from "@/utils/publicFun";
import NewMessage from "@/utils/rewriteElMessage";
export default {
name: "FilePreviewer",
components: {
Temp
},
props: {
title: {
type: String,
required: false
},
pageType: {
type: Number,
default: 2
}
},
data() {
return {
fileType: "",
fileSrc: "",
fileKey: null,
interfaceParams: {} // 接口参数
};
},
methods: {
goBack() {
this.pageType = 1;
this.$emit("close");
},
async getFileBlob(obj) {
const { interfaceUrl, key } = obj;
try {
const response = await axios.post(
interfaceUrl,
{
...this.interfaceParams
},
{
headers: {
Authorization: getToken(),
"Token-Code-Header": sysCode.trading
},
responseType: "blob"
}
);
const isLogin = await blobValidate(response.data);
if (!isLogin) {
const resText = await new Response(response.data).text();
const rspObj = JSON.parse(resText);
const errMsg = rspObj.message || "文件获取失败";
NewMessage.error({
message: errMsg,
type: "error",
duration: 5 * 1000
});
return null;
}
this.fileSrc = response.data;
this.fileType = "docx";
console.log("文件预览设置成功", {
fileSrc: this.fileSrc,
blobSize: response.data.size,
blobType: response.data.type
});
return response.data;
} catch (error) {
console.error("获取文件流失败:", error);
NewMessage.error({
message: "获取文件出现错误,请联系管理员!",
type: "error",
duration: 5 * 1000
});
return null;
}
},
async getFile(obj) {
const { interfaceUrl, fetchType, key } = obj;
const url = interfaceUrl;
const header = {
authorization: getToken(),
"token-code-header": "system"
};
try {
if (fetchType === "get") {
const response = await fetch(url, {
method: "GET",
headers: header
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
// 注意:这里需要根据实际情况调整,Vue2中可能需要使用其他方式存储
// this.docx = await blob.arrayBuffer();
this.fileSrc = await blob.arrayBuffer();
} else if (fetchType === "post") {
await this.getFileBlob(obj);
}
} catch (error) {
console.error("获取文档失败:", error);
this.loading = false;
this.errorHandler();
}
}
},
mounted() {
const obj = this.$route.query;
this.$nextTick(() => {
/* 通过接口获取文件流 */
if (obj.key) {
this.fileKey = obj.key;
this.interfaceParams = JSON.parse(
localStorage.getItem(obj.key) || "{}"
);
localStorage.setItem(obj.key, JSON.stringify(this.interfaceParams));
this.getFile(obj);
return;
}
/* 直接获取文件地址 */
this.fileType = obj.fileType;
this.fileSrc = obj.fileSrc;
});
},
destroyed() {
if (this.fileKey) {
localStorage.removeItem(this.fileKey);
}
}
};
</script>
<style lang="scss" scoped>
.file-previewer {
width: 100%;
//height: calc(100vh - 100px);
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-between;
&-header {
padding: 20px 0;
height: 40px;
}
&-content {
height: 100%;
//height: calc(100% - 70px);
}
::v-deep .el-page-header__back {
&:hover {
color: var(--el-color-primary);
}
}
}
</style>
temp.vue
html
<template>
<div class="temp" v-loading="loading">
<vue-office-docx
class="temp"
v-if="fileType === 'docx'"
:src="fileSrc"
@rendered="renderedHandler"
@error="errorHandler"
/>
<vue-office-excel
class="temp"
v-if="fileType === 'excel'"
:src="fileSrc"
:options="excelOptions"
@rendered="renderedHandler"
@error="errorHandler"
/>
<vue-office-pdf
class="temp"
v-if="fileType === 'pdf'"
:src="fileSrc"
@rendered="renderedHandler"
@error="errorHandler"
/>
<vue-office-pptx
class="temp"
v-if="fileType === 'pptx'"
:src="fileSrc"
@rendered="renderedHandler"
@error="errorHandler"
/>
</div>
</template>
<script>
import VueOfficeDocx from "@vue-office/docx";
// import VueOfficeDocx from "@vue-office/docx/lib/v3/vue-office-docx.mjs";
import "@vue-office/docx/lib/index.css";
// import "@vue-office/docx/lib/v3/index.css";
import VueOfficeExcel from "@vue-office/excel";
// import VueOfficeExcel from "@vue-office/excel/lib/v3/vue-office-excel.mjs";
import "@vue-office/excel/lib/index.css";
// import "@vue-office/excel/lib/v3/index.css";
import VueOfficePdf from "@vue-office/pdf";
// import VueOfficePdf from "@vue-office/pdf/lib/v3/vue-office-pdf.mjs";
import VueOfficePptx from "@vue-office/pptx";
// import VueOfficePptx from "@vue-office/pptx/lib/v3/vue-office-pptx.mjs";
export default {
name: "OfficeViewer",
components: {
VueOfficeDocx,
VueOfficeExcel,
VueOfficePdf,
VueOfficePptx
},
props: {
fileType: {
type: String,
required: true,
validator: value => ["docx", "excel", "pdf", "pptx"].includes(value)
},
fileSrc: {
type: [String, Blob, ArrayBuffer],
required: true
},
excelOptions: {
type: Object,
default: () => {
return {
xls: false,
minColLength: 0,
minRowLength: 0,
widthOffset: 10,
heightOffset: 10,
beforeTransformData: workbookData => {
return workbookData;
},
transformData: workbookData => {
return workbookData;
}
};
}
}
},
data() {
return {
loading: true
};
},
methods: {
renderedHandler() {
this.loading = false;
this.$emit("rendered");
console.log("渲染完成");
},
errorHandler() {
this.loading = false;
this.$emit("error");
console.log("渲染失败");
},
/**
* @Event 方法
* @description: 通过流地址预览 Demo
* @author: mhf
* @time: 2025-07-21 17:06:57
**/
async viewByBlob() {
const url = "/reservoirRealData/reservoirReport/export?id=313";
const header = {
authorization:
"eyJhbGciOiJIUzI1NiJ9.eyJ0b2tlbktleSI6IjY1Yjk4NWZhMWY2NzQyZGU5N2Q5NmQyZjI4MTU2YzQxIiwiZGVwdElkIjoxMDEsInVzZXJOYW1lIjoiYWRtaW4iLCJ1c2VySWQiOjEwfQ.p2AVdvAZtFVfhK_YTkG1dr9jfJKR-qD_8JJ6bv4Vw4k",
"token-code-header": "system"
};
try {
const response = await fetch(url, {
method: "GET",
headers: header
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const blob = await response.blob();
// 注意:这里需要根据实际情况调整,Vue2中可能需要使用其他方式存储
// this.docx = await blob.arrayBuffer();
} catch (error) {
console.error("获取文档失败:", error);
this.loading = false;
this.errorHandler();
}
}
},
mounted() {
this.loading = true;
}
};
</script>
<style scoped lang="scss">
.temp {
width: 100%;
height: 100%;
overflow: auto;
}
</style>
3. 文件上传组件封装fileUploadYt.vue
html
<!--
* @Description: 文件上传通用 组件 页面
* @Author: mhf
* @Date: 2023-04-24 18:32:39
* @Desc: 具体使用请参考 attachConfigDialog.vue 页面
* @Warning: 弹窗中使用该组件时,需设置 v-if="dialogVisible" 否则将会存在文件缓存
-->
<template>
<div class="">
<el-upload
class="upload-demo"
ref="uploadFile"
:disabled="utilsObj.isDisabled"
:action="actionUrl"
:headers="headerObj"
:file-list="utilsObj.fileList"
:limit="utilsObj.limitNum"
:http-request="handleUpload"
:multiple="utilsObj.isMultiple"
:on-preview="handlePreview"
:on-success="handleSuccess"
:on-remove="handleRemove"
:before-upload="handBeforeUpload"
:on-exceed="handleExceed"
>
<!-- 上传按钮样式选择 -->
<div v-if="utilsObj.typeStyle === 0">
<!-- 按钮样式 -->
<el-button
:disabled="utilsObj.isDisabled"
size="small"
icon="iconfont if-biaodancaozuo-xinzeng"
class=""
>{{ utilsObj.content || "附件" }}
</el-button>
</div>
<!-- el-icon样式 -->
<div v-if="utilsObj.typeStyle === 1">
<div v-if="!utilsObj.isDisabled" class="fileBox">
<i class="iconfont if-daochu" />
<div>{{ utilsObj.content || "点击上传" }}</div>
<div class="tips">
<div class="red">
<i class="el-icon-remove"></i>涉密工作及涉密信息请勿上传
</div>
<div class="yellow">
<i class="el-icon-warning yellow"></i
>重要文件请修改好文件名称再上传
</div>
</div>
</div>
</div>
<!-- 若自定义样式,请使用插槽:<slot></slot> -->
<div v-if="utilsObj.typeStyle === 2">
<slot name="customBtn" />
</div>
<el-progress
v-if="singlePartFileProgress > 0 && singlePartFileProgress < 100"
class="progress"
:percentage="singlePartFileProgress"
/>
<!-- 上传按钮样式选择 -->
<div slot="file" slot-scope="{ file }" class="file-slot">
<div class="file-slot-content">
<i class="el-icon-upload-success el-icon-circle-check"></i>
<div class="file-slot-content-name">{{ file.name }}</div>
<el-button
v-if="isPreviewable(file)"
type="text"
class="file-slot-content-preview"
icon="el-icon-document"
@click="filePreview(file)"
>
预览
</el-button>
<el-button
type="text"
class="file-slot-content-preview"
icon="el-icon-download"
@click="handlePreview(file)"
>
下载
</el-button>
<el-button
v-if="!utilsObj.isDisabled"
type="text"
class="file-slot-content-remove"
icon="el-icon-delete"
@click="handleRemove(file)"
>
删除
</el-button>
</div>
</div>
</el-upload>
</div>
</template>
<script>
import { getToken } from "@/utils/auth";
import { upLoad, upLoadChunk } from "@/api/system/config";
export default {
name: "Index",
components: {},
props: {
/* 注意: 如果props里面的对象有默认参数时,必须用函数return一个对象 */
utilsObj: {
type: Object,
default: () => ({
isDisabled: false, // 是否禁用
fileList: [], // 附件列表
limitNum: 3, // 限制上传的文件数量 (个)
fileSize: 50, // 单文件上传大小(MB)
typeStyle: 0, // 文件上传的样式控制
isMultiple: false, // 是否支持同时选择多个文件
content: null // 上传按钮展示的文字内容
})
}, // 附件上传的配置项
headerObj: {
type: Object,
default: function () {
return {
Authorization: getToken(),
"Token-Code-Header": this.$tokenCodeHeader
};
}
}, // 文件上传请求头参数 --- token
url: {
type: String,
default: "/annexAction/upload"
},
chunkSize: {
type: Number, //分块大小
default: 10
}
},
data() {
return {
resFileArr: [], // 最终需要的文件数据
chunkFile: {}, //分片上传文件信息
singlePartFileProgress: 0, //文件上传进度
processTimer: null //文件上传定时器
};
},
computed: {
// 附件上传的配置项
actionUrl() {
return process.env.VUE_APP_BASE_API + this.url;
}
},
created() {},
mounted() {
setTimeout(() => {
if (this.utilsObj.fileList) {
this.resFileArr = this.utilsObj.fileList;
}
}, 500);
},
methods: {
/**
* @Event 方法 文件切片
* @description: 将文件切割成多块
* */
sliceFile(file, chunkSize) {
const chunks = [];
let offset = 0;
while (offset < file.size) {
const chunk = file.slice(offset, offset + chunkSize);
chunks.push(chunk);
offset += chunkSize;
}
return chunks;
},
// 分片上传文件
async uploadFileChunks(file, chunkSize) {
console.log("file", file, this.chunkFile);
const chunks = this.sliceFile(file, chunkSize);
console.log(chunks);
let exeCount = 1;
for (let i = 0; i < chunks.length; i++) {
const formData = new FormData();
formData.append("file", chunks[i]);
formData.append("fileName", this.chunkFile.file.name);
formData.append("fileUid", this.chunkFile.file.uid);
formData.append("partIndex", i + 1);
formData.append("partTotalNum", chunks.length);
try {
if (this.processTimer) {
clearInterval(this.processTimer);
}
this.processTimer = setInterval(() => {
if (
this.singlePartFileProgress +
Math.floor(100 / chunks.length / 10) <
Math.floor((100 / chunks.length) * exeCount)
) {
let process =
Math.floor(100 / chunks.length / 10) <= 0
? 1
: Math.floor(100 / chunks.length / 10);
this.singlePartFileProgress =
this.singlePartFileProgress + process;
}
}, 500);
const res = await upLoadChunk(formData);
console.log(res);
if (res.code === 1) {
this.singlePartFileProgress = Math.floor(
(100 / chunks.length) * exeCount
);
exeCount++;
if (this.processTimer) {
clearInterval(this.processTimer);
}
if (i + 1 == chunks.length) {
this.singlePartFileProgress = 100;
this.handleSuccess(res);
}
} else {
this.$message.error(res.msg);
}
} catch (error) {
if (this.processTimer) {
clearInterval(this.processTimer);
}
this.singlePartFileProgress = 0;
// console.log(this.utilsObj.fileList);
this.removeFailUpload();
break;
}
}
},
/**
* @Event 方法 当文件上传失败时,删除失败的文件
* @description: 文件上传失败,依旧会在界面显示失败的一个文件,会造成上传成功的假象
* */
removeFailUpload() {
let uid = this.chunkFile.file.uid; // 关键作用代码,去除文件列表失败文件
let idx = this.$refs.uploadFile.uploadFiles.findIndex(
item => item.uid === uid
); // 关键作用代码,去除文件列表失败文件(uploadFiles为el-upload中的ref值)
this.$refs.uploadFile.uploadFiles.splice(idx, 1); // 关键作用代码,去除文件列表失败文件
},
/**
* @Event 方法 实现文件上传逻辑,包括文件分片处理
* @description: 覆盖默认的上传行为,可以自定义上传的实现
* */
handleUpload(file) {
this.chunkFile = file;
//判断当前文件是否需要分块上传 默认 10mb以上
if (file.file.size > this.chunkSize * 1024 * 1024) {
this.uploadFileChunks(file.file, this.chunkSize * 1024 * 1024);
} else {
const formData = new FormData();
formData.append("file", file.file);
if (this.processTimer) {
clearInterval(this.processTimer);
}
this.processTimer = setInterval(() => {
if (this.singlePartFileProgress + 10 < 100) {
this.singlePartFileProgress = this.singlePartFileProgress + 10;
} //定时器,显示一个上传进度
}, 500);
upLoad(formData)
.then(res => {
this.handleSuccess(res);
})
.catch(err => {
this.removeFailUpload();
})
.finally(() => {
if (this.processTimer) {
this.singlePartFileProgress = 0;
clearInterval(this.processTimer);
}
});
}
},
/**
* @Event 方法
* @description: 点击文件列表中已上传的文件时的钩子
* */
handlePreview(file) {
let fileType = file?.suffix || file?.response?.data?.suffix;
if (file.response) {
// 上传文件的时候 查看
window.open(
file.response.data.url,
fileType === ".pdf" ? "_blank" : "_self"
);
} else {
// 文件上传成功之后返回值 查看
window.open(file.url, fileType === ".pdf" ? "_blank" : "_self");
}
},
/**
* @Event 方法
* @description: 文件上传成功时的钩子
* */
handleSuccess(file) {
this.singlePartFileProgress = 0;
console.log("文件上传成功时的钩子", file);
if (file.code === 1) {
this.resFileArr.push(file.data);
this.$emit("getFileUploadYt", this.resFileArr);
} else {
this.$message.warning(file.message);
}
},
/**
* @Event 方法
* @description: 文件列表移除文件时的钩子
* */
handleRemove(file) {
if (file.response) {
this.resFileArr.map((item, index) => {
if (
item === file.response.data ||
item.url === file.response.data.url
) {
this.resFileArr.splice(index, 1);
this.$emit("getFileUploadYt", this.resFileArr);
}
});
} else {
this.resFileArr.map((item, index) => {
if (item === file || item.url === file.url) {
this.resFileArr.splice(index, 1);
this.$emit("getFileUploadYt", this.resFileArr);
}
});
}
},
/**
* @Event 方法
* @description: 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
* */
handBeforeUpload(file) {
if (
[
"application/vnd.android.package-archive",
"application/x-zip-compressed",
"text/plain",
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
].indexOf(file.type) === -1
) {
this.$message.error(
"请上传后缀名为 apk、zip、pdf、txt、doc、docx、xls、xlsx的文件"
);
return false;
}
if (file.size > this.utilsObj.fileSize * 1024 * 1024) {
this.$message.error(`文件大小不能超过 ${this.utilsObj.fileSize}MB`);
return false;
}
},
/**
* @Event 方法
* @description: 文件超出个数限制时的钩子
* */
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 ${this.utilsObj.limitNum} 个文件,本次选择了 ${
files.length
} 个文件,共选择了 ${files.length + fileList.length} 个文件`
);
},
isPreviewable(file) {
const fileType = file.suffix;
const previewableTypes = [
".xls",
".xlsx",
".XLS",
".XLSX",
".doc",
".docx",
".DOC",
".DOCX",
".ppt",
".pptx",
".pdf",
".PPT",
".PPTX",
".PDF"
];
let fileView = false;
if (file && file.url) {
fileView = previewableTypes.includes(fileType);
}
return fileView;
},
filePreview(file) {
const suffix = file.suffix;
const typeMapper = {
docx: [".doc", ".docx", ".DOC", ".DOCX"],
excel: [".xls", ".xlsx", ".XLS", ".XLSX"],
pptx: [".ppt", ".pptx", ".PPT", ".PPTX"],
pdf: [".pdf", ".PDF"]
};
const fileType = Object.keys(typeMapper).find(key =>
typeMapper[key].includes(suffix)
);
window.open(
"/filePreviewer?fileSrc=" + file.url + "&fileType=" + fileType
);
}
}
};
</script>
<style lang="scss" scoped>
::v-deep .fileBox {
height: 36px;
background: rgba(255, 255, 255, 0);
border-radius: 4px;
display: flex;
align-items: center;
color: #1492ff !important;
font-weight: bold;
font-size: 16px;
i {
margin-right: 5px;
}
}
.disabledClass {
margin-top: -35px;
}
.file-slot {
padding: 2px 10px;
&-content {
display: flex;
flex-direction: row;
align-items: center;
&-name {
margin-left: 10px;
}
&-preview {
padding: 0 !important;
border: none;
margin-left: 10px;
}
&-remove {
padding: 0 !important;
border: none;
color: #fc5c5c !important;
}
}
}
::v-deep .el-upload {
display: block !important;
text-align: left !important;
}
.tips {
font-size: 14px;
margin-left: 8px;
display: flex;
.red {
color: #fc5c5c;
}
.yellow {
margin-left: 8px;
color: #f1924e;
}
}
</style>
4. 使用示例
html
<template>
<el-dialog
v-dialog-out
width="700px"
:title="title"
:visible.sync="dialogVisible"
:before-close="hideDialog"
:close-on-click-modal="false"
>
<div class="dialog-body">
<el-form
ref="form"
:model="formData"
:rules="formRules"
label-width="5.5rem"
>
<el-form-item label="考核标题 : " prop="title">
<el-input
:disabled="['详情'].includes(title)"
v-model="formData.title"
placeholder=""
/>
</el-form-item>
<!-- 1 区县 2 乡镇 -->
<el-form-item label="区域类型 : " prop="areaType">
<el-select
v-model="formData.areaType"
filterable
placeholder=""
:disabled="['详情'].includes(title)"
@change="changeAreaType"
>
<el-option
v-for="item in dict.type.situation_area_type"
:key="item.value"
:label="item.label"
:value="parseInt(item.value)"
/>
</el-select>
</el-form-item>
<el-form-item label="考核区域 : " prop="areaNames">
<el-input
v-model="formData.areaNames"
placeholder=""
readonly
:disabled="['详情'].includes(title)"
>
<template slot="append">
<div class="choose-class" @click="chooseDialogs">
<i class="iconfont if-sousuo" />
<span style="margin-left: 10px">{{
title === "详情" ? "查看" : "选择"
}}</span>
</div>
</template>
</el-input>
</el-form-item>
<el-form-item label="考核周期 : " prop="period">
<el-select
v-model="formData.period"
filterable
placeholder=""
:disabled="['详情'].includes(title)"
>
<el-option
v-for="item in quarterList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="考核类型 : " prop="checkType">
<el-input
:disabled="['详情'].includes(title)"
v-model="formData.checkType"
/>
</el-form-item> -->
<el-form-item label="备注 : " prop="remark">
<el-input
v-model="formData.remark"
placeholder=""
:disabled="['详情'].includes(title)"
type="textarea"
:rows="3"
maxlength="200"
show-word-limit
></el-input>
</el-form-item>
<el-form-item label="附件 : " prop="attachment">
<fileUploadYt
v-if="dialogVisible"
ref="fileUploadYt"
@getFileUploadYt="getAnnexUrl"
:utilsObj="fileUploadUtils"
/>
</el-form-item>
</el-form>
</div>
<lineH v-if="!['详情'].includes(title)" />
<div class="dialog-footer" v-if="!['详情'].includes(title)">
<el-button @click="hideDialog">取 消</el-button>
<el-button type="primary" @click="validateForm">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import {
areaAssessInsert,
areaAssessGetInfo,
areaAssessUpdate
} from "@/api/assessEvaluate/assessArea";
import { listByPage } from "@/api/system/dept";
import { areaList } from "@/api/system/deptArea";
import { generateQuarterList } from "@/utils/index";
export default {
name: "countyEvaluationDialog",
components: {},
props: {},
dicts: ["situation_area_type"],
provide() {
return {
requestName: areaList
};
},
data() {
return {
defaultParams: {
// areaType 1 区县 2 乡镇 nodeType 0 省市级 1 区县级 2公司/部门 3 乡镇
// nodeType: "1"
},
formLabel: [
{
label: "区域名称",
value: "areaName"
}
],
tableDataColumn: [
{
label: "区域名称",
prop: "areaName"
},
{
label: "创建时间",
prop: "createTime"
}
// {
// label: "管理单位",
// prop: "deptName"
// }
],
dialogVisible: false,
title: "",
formData: {},
formRules: {
title: [{ required: true, message: "请输入模版标题", trigger: "blur" }],
areaType: [
{ required: true, message: "请选择区域类型", trigger: "blur" }
],
areaNames: [
{ required: true, message: "请选择考核区域", trigger: "blur" }
],
period: [{ required: true, message: "请选择考核周期", trigger: "blur" }]
},
fileUploadUtils: {
isDisabled: false,
fileList: [],
limitNum: 4,
typeStyle: 1,
content: "考核文件"
},
selectList: [],
quarterList: generateQuarterList()
};
},
methods: {
changeAreaType(e) {
// areaType 1 区县 2 乡镇 nodeType 0 省市级 1 区县级 2公司/部门 3 乡镇
console.log("e", e);
this.defaultParams.areaType = e == 1 ? "1" : "3";
this.selectList = [];
this.$set(this.formData, "areaNames", "");
this.$set(this.formData, "areaIds", "");
},
getAnnexUrl(data) {
console.log(data);
this.$set(this.formData, "attachment", JSON.stringify(data));
},
chooseDialogs() {
if (!this.formData.areaType) {
this.$message.warning("请选择区域类型");
return;
}
let passData = {
data: this.selectList,
title: "选择考核区域"
};
this.$refs.chooseDialogs.showDialog(passData);
},
getListByDialog(data) {
this.$set(
this.formData,
"areaNames",
data.map(i => i.areaName).join(",")
);
this.$set(
this.formData,
"areaIdList",
data.map(i => i.id)
);
this.selectList = JSON.parse(JSON.stringify(data));
},
showDialog(data) {
console.log("data", data);
// areaType 1 区县 2 乡镇 nodeType 0 省市级 1 区县级 2公司/部门 3 乡镇
this.$set(this.defaultParams, "areaType", 1);
this.dialogVisible = true;
this.title = data.type;
if (data.data) {
this.getDetail(data.data.id);
}
if (data.type === "详情") {
this.fileUploadUtils.isDisabled = true;
}
},
hideDialog() {
this.dialogVisible = false;
// this.isDisable = false;
// this.$refs.form.resetFields();
this.formData = {};
this.fileUploadUtils.fileList = [];
this.fileUploadUtils.isDisabled = false;
this.selectList = [];
this.$parent.getTableData();
},
getDetail(id) {
areaAssessGetInfo({ id }).then(res => {
if (res.code === 1) {
this.formData = {
...res.data,
period: `${res.data.year}-${res.data.quarter}`
};
this.defaultParams.areaType = res.data.areaType == 1 ? "1" : "3";
this.selectList = res.data.areaIdList.map((id, index) => ({
id: id,
areaName: res.data.areaNames.split(",")[index]?.trim() || "未知区域"
}));
try {
if (this.formData.attachment) {
this.fileUploadUtils.fileList = JSON.parse(
this.formData.attachment
);
} else {
this.fileUploadUtils.fileList = [];
}
} catch (error) {
this.fileUploadUtils.fileList = [];
}
}
});
},
async validateForm() {
try {
if (await this.$refs.form.validate()) this.submitForm();
} catch (e) {}
},
submitForm() {
if (this.title === "新增") {
areaAssessInsert({
...this.formData,
year: this.formData.period.split("-")[0],
quarter: this.formData.period.split("-")[1]
}).then(res => {
if (res.code === 1) {
this.$message.success("新增成功");
this.hideDialog();
}
});
} else if (this.title === "编辑") {
areaAssessUpdate({
...this.formData,
year: this.formData.period.split("-")[0],
quarter: this.formData.period.split("-")[1]
}).then(res => {
if (res.code === 1) {
this.$message.success("编辑成功");
this.hideDialog();
}
});
}
}
},
created() {},
mounted() {}
};
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__body {
padding: 20px 0 0 !important;
}
.dialog-body {
padding: 0 20px;
max-height: 65vh;
overflow-y: auto;
}
.dialog-footer {
text-align: center;
padding: 10px 0 18px;
}
</style>