一、首先新建NewUpload.vue文件,
<template>
<div class="images-list1">
<el-upload
class="upload-demo"
:action="uploadUrl"
:before-upload="handleBeforeUpload"
:on-success="handleSuccess"
:on-error="handleUploadError"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:file-list="fileList"
:multiple="fileLimit > 1"
:data="paramsData"
:limit="fileLimit"
:list-type="listType"
drag
>
<i v-if="listType === 'picture-card'" class="el-icon-plus"></i>
<i v-else class="el-icon-upload uploIcon"></i>
<div class="uploName">点击或将文件拖拽到这里上传</div>
<div v-if="showTip" class="el-upload__tip">
支持扩展名:{{ fileTypeName || "jpg/png" }}
</div>
</el-upload>
</div>
</template>
<script>
import { imgPreview } from "@/utils/imgPreview.js";
export default {
name: 'NewUpload',
props: {
// 值
value: [String, Object, Array],
// 大小限制(MB)
fileSize: {
type: Number,
default: 5,
},
// 文件类型, 例如["doc", "xls", "ppt", "txt", "pdf"]
fileType: {
type: Array,
default: () => ['png', 'jpg', 'jpeg'],
},
// 文件列表类型 text/picture/picture-card
listType: {
type: String,
default: 'picture'
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
},
// 最大允许上传个数
fileLimit: {
type: Number,
default: 99
}
},
data() {
return {
uploadUrl: "/api/common/upload", // 上传的图片服务器地址
paramsData: {
// 'Authorization': 'Bearer token',
// 'output': 'json'
token: ''
}, // 上传携带的参数,看需求要不要
fileList: [],
tempFileList: [] // 因为 fileList为只读属性,所以用了一个中间变量来进行数据改变的交互。
}
},
watch: {
value: {
handler: function (newVal) {
this.tempFileList = newVal
},
immediate: true,
deep: true
},
},
computed: {
// 是否显示提示
showTip() {
return this.isShowTip && (this.fileType || this.fileSize);
},
fileTypeName() {
let typeName = ''
this.fileType.forEach(item => {
typeName += `${item},`
})
return typeName
},
fileAccept() {
let fileAccept = ''
this.fileType.forEach(element => {
fileAccept += `.${element},`
})
return fileAccept
}
},
created() {
if (this.value) {
this.fileList = JSON.parse(JSON.stringify(this.value))
}
var token = null
if (!JSON.parse(sessionStorage.getItem('tokenAll'))) {
token = null
} else {
token = JSON.parse(sessionStorage.getItem('tokenAll')).token
}
this.paramsData = {
token: token
}
},
methods: {
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件类型
if (this.fileType && file) {
const isTypeOk = this.fileType.some((item) => {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
}
// if (file.type.indexOf(item) > -1) return true;
if (fileExtension && fileExtension.indexOf(item) > -1) return true;
return false;
});
if (!isTypeOk && file) {
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
return false;
}
}
// 校检文件大小
// if (this.fileSize && file) {
// const isLt = file.size / 1024 / 1024 < this.fileSize;
// if (!isLt) {
// this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
// return false;
// }
// }
return new Promise((resolve) => {
imgPreview(file, (obj) => {
resolve(obj)
})
})
},
handleUploadError() {
this.$message.error("上传失败, 请重试");
},
// 文件个数超出
handleExceed() {
this.$message.error(`超出上传文件个数,请删除以后再上传!`);
},
// 文件上传成功的钩子
handleSuccess(res, file, fileList) {
if (res.code === 0) {
this.$message.success("上传成功")
this.changeFileList(fileList)
} else {
this.$message.error(res.response.errorMessage)
}
},
// 文件列表移除文件时的钩子
handleRemove(file, fileList) {
this.changeFileList(fileList)
},
// 文件列表改变的时候,更新组件的v-model的文的数据
changeFileList(fileList) {
const tempFileList = fileList.map(item => {
let tempItem = {
name: item.name,
url: item.response ? item.response.payload.imgUrl : item.url
}
return tempItem
})
this.$emit("input", tempFileList)
}
},
}
</script>
<style lang="less" scoped>
.images-list1 {
border-radius: 4px;
background: #fff;
::v-deep .el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
}
}
}
.uploName {
font-size: 16px;
color: #333752;
margin-bottom: 4px;
}
.el-upload__tip {
font-size: 14px;
color: #a2a5c4;
}
.uploIcon {
margin: 16px 0;
}
</style>
2、Pagenation.vue文件
<template>
<div class="paginaStly">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pages.currentPage"
:page-sizes="[10, 20, 50]"
:page-size="pages.pageSize"
:layout="layout"
:total="pages.total"
background
>
</el-pagination>
</div>
</template>
<script>
export default {
props: {
pages: {
type: Object,
default() {
return {
pageSize: 10,
currentPage: 1,
total: 0
}
}
},
layout: {
type: String,
default: "total, sizes, prev, pager, next, jumper",
},
},
data() {
return {
};
},
methods: {
//页面尺寸改变
handleSizeChange(val) {
this.$emit("sizeChange", val);
},
//页码改变
handleCurrentChange(val) {
this.$emit("currentChange", val);
},
},
};
</script>
<style lang="less" scoped>
.paginaStly {
display: flex;
justify-content: flex-end;
background: #fff;
padding: 32px 24px;
}
</style>
二、在src/utils下新建图片压缩文件imgPreview.js
// 图片压缩
export const imgPreview = (file, callback) => {
//将base64转换为文件
function dataURLtoFile(dataurl, file) {
var arr = dataurl.split(","),
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], file.name, {
type: file.type
});
}
// 压缩图片
function compress(img) {
let canvas = document.createElement("canvas");
let ctx = canvas.getContext("2d");
//瓦片canvas
let tCanvas = document.createElement("canvas");
let tctx = tCanvas.getContext("2d");
// let initSize = img.src.length;
let width = img.width;
let height = img.height;
//如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio;
if ((ratio = (width * height) / 4000000) > 1) {
// console.log("大于400万像素");
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// 铺底色
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
//如果图片像素大于100万则使用瓦片绘制
let count;
if ((count = (width * height) / 1000000) > 1) {
// console.log("超过100W像素");
count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
// 计算每块瓦片的宽和高
let nw = ~~(width / count);
let nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(
img,
i * nw * ratio,
j * nh * ratio,
nw * ratio,
nh * ratio,
0,
0,
nw,
nh
);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
//进行最小压缩
let ndata = canvas.toDataURL("image/jpeg", 0.3);
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
return ndata;
}
// 看支持不支持FileReader
if (!file || !window.FileReader) {
return;
}
if (/^image/.test(file.type)) {
// 创建一个reader
let reader = new FileReader();
// 将图片转成 base64 格式
reader.readAsDataURL(file);
// 读取成功后的回调
reader.onloadend = function () {
let result = this.result;
let img = new Image();
img.src = result;
//判断图片是否小于2M,是就直接上传,反之压缩图片
if (this.result.length <= 2000 * 1024) {
// 上传图片
let imageFile = dataURLtoFile(this.result, file);
callback(imageFile);
} else {
img.onload = function () {
let data = compress(img);
// 上传图片
let imageFile = dataURLtoFile(data, file);
callback(imageFile);
};
}
}
} else {
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function () {
let result = this.result;
let img = new Image();
img.src = result;
let imageFile = dataURLtoFile(this.result, file);
callback(imageFile);
}
}
};
三、在其他vue文件中引用封装的NewUpload组件,Pagenation组件
<template>
<div id="joinOrder">
<el-breadcrumb separator="/" style="margin-bottom: 12px">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>工单管理</el-breadcrumb-item>
<el-breadcrumb-item>文档管理</el-breadcrumb-item>
</el-breadcrumb>
<el-row class="tableRow">
<div class="tableTop">
<div class="tableText"><span class="bgInfo"></span>文档管理信息</div>
<div class="tableBtn">
<el-button
type="primary"
icon="el-icon-plus"
class="primBtn"
@click="addDocument"
>新增</el-button
>
<!-- <el-button plain class="plainBtn" @click="deleteClick('all')"
>删除</el-button
> -->
</div>
</div>
<div class="tableAllpa">
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
@selection-change="handleSelectionChange"
class="selecStyl"
v-loading="tableFlag"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="sort" label="序号"> </el-table-column>
<el-table-column prop="name" label="文档名称"> </el-table-column>
<el-table-column prop="fileTypeText" label="文档类型">
</el-table-column>
<el-table-column prop="orderTypeText" label="工单类型">
</el-table-column>
<el-table-column fixed="right" label="操作" width="130">
<template slot-scope="scope">
<el-button
@click="documEdit(scope.row)"
type="text"
size="small"
class="tableBtnStyl"
>编辑</el-button
>
<el-button
type="text"
size="small"
@click="deleteClick(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</el-row>
<Pagenation
:pages="pages"
@sizeChange="handleSizeChange"
@currentChange="handleCurrentChange"
/>
<el-dialog
:title="!editFlag ? '添加文档管理' : '编辑文档管理'"
:visible.sync="feedFlag"
:close-on-click-modal="false"
:append-to-body="true"
>
<el-form
:model="feedForm"
:rules="feedrules"
ref="feedForm"
label-width="120px"
label-position="left"
class="demo-ruleForm"
>
<el-row :gutter="16">
<el-col :md="24" :lg="24" :xl="24">
<el-form-item label="文档类型:" prop="docuType">
<el-select
v-model="feedForm.docuType"
placeholder="请选择"
clearable
>
<el-option value="">请选择</el-option>
<el-option
v-for="item in orginList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="工单类型:" prop="orderType">
<el-select
v-model="feedForm.orderType"
placeholder="请选择"
clearable
>
<el-option value="">请选择</el-option>
<el-option
v-for="item in orderList"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="文档路径:" prop="">
<NewUpload
v-model="docuList"
:fileSize="5"
:fileLimit="1"
listType="text"
:fileType="[
'pdf',
'doc',
'docx',
'xls',
'xlsx',
'png',
'jpg',
'jpeg',
]"
ref="refName"
/>
</el-form-item>
<el-form-item label="文档名称:" prop="docuName">
<el-input
v-model.trim="feedForm.docuName"
placeholder="请输入文档名称"
clearable
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<div>
<el-button @click="feedFlag = false" plain>取 消</el-button>
<el-button
type="primary"
@click="feedSubmit('feedForm')"
:loading="saveFlag"
>确认</el-button
>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { documentPage, documentSave, documentDel, documentDtl } from '@/api/orderApi/index.js'
import Pagenation from '@/components/comChild/Pagenation.vue'
import NewUpload from '@/components/comChild/NewUpload.vue'
export default {
data() {
return {
saveFlag: false,
editFlag: false,
feedFlag: false,
feedForm: {
docuName: '',
docuType: '',
orderType: ''
},
docuList: [],
docuListNew: [],
feedrules: {
docuName: [
{ required: true, message: '请输入文档名称', trigger: 'change' }
],
docuType: [
{ required: true, message: '请选择文档类型', trigger: 'change' }
],
orderType: [
{ required: true, message: '请选择工单类型', trigger: 'change' }
]
},
searchFlag: false,
tableFlag: false,
formLine: {
organName: '',
orginType: ''
},
orginList: [
{
value: 1,
label: '验收结果'
},
{
value: 2,
label: '现场验收'
},
{
value: 3,
label: '线上(远程)验收'
},
],
orderList: [
{
value: 1,
label: '验收申请工单'
}
],
tableData: [],
pages: {
pageSize: 10,
currentPage: 1,
total: 0,
},
id: '',
multipleId: []
}
},
components: {
Pagenation, NewUpload
},
watch: {
docuList: {
handler(newVal) {
if (newVal.length > 0 && !this.id) {
this.feedForm.docuName = newVal[0].name
}
}
}
},
mounted() {
this.getNewsList()
},
methods: {
addDocument() {
this.feedFlag = true
this.editFlag = false
this.id = ''
this.feedForm = {
docuName: '',
docuType: '',
orderType: ''
}
if (this.$refs.refName) {
this.$refs.refName.fileList = []
}
if (this.$refs['feedForm']) {
this.$refs['feedForm'].resetFields();
}
},
feedSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.docuListNew = []
this.docuList.forEach((item) => {
this.docuListNew.push(item.url)
})
this.getDocumSave()
} else {
return false;
}
});
},
async getDocumDtl() {
const data = {
id: this.id
}
await documentDtl(data).then(
(resp) => {
if (resp.code === 0) {
this.feedForm.docuType = resp.payload.fileType
this.feedForm.orderType = resp.payload.orderType
this.feedForm.docuName = resp.payload.name
let obj = {}
obj = {
name: resp.payload.name,
url: resp.payload.fileUrls
}
this.docuList = [obj]
this.$refs.refName.fileList = this.docuList
} else {
this.$message.error(resp.errorMessage)
}
},
(error) => {
this.$message.error(error)
}
)
},
getDocumSave() {
const data = {
fileType: this.feedForm.docuType,
orderType: this.feedForm.orderType,
fileUrls: this.docuListNew.join(','),
name: this.feedForm.docuName,
id: this.id
}
this.saveFlag = true
documentSave(data).then(
(resp) => {
if (resp.code === 0) {
if (!this.editFlag) {
this.$message({
message: '新增成功',
type: 'success'
})
} else {
this.$message({
message: '编辑成功',
type: 'success'
})
}
this.feedFlag = false
this.getNewsList()
} else {
this.$message.error(resp.errorMessage)
}
this.saveFlag = false
},
(error) => {
this.saveFlag = false
this.$message.error(error)
}
)
},
deleteClick(row) {
if (row == 'all') {
this.$message.error('该功能暂未开发')
return
}
this.$confirm('此操作将永久删除该条数据, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
cancelButtonClass: 'deleteBtn',
type: 'warning'
}).then(async () => {
await this.getDocumentDel(row)
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
getDocumentDel(item) {
let newUserId = ''
if (item == 'all') {
newUserId = this.multipleId.join(',')
} else {
newUserId = item.id
}
const data = {
data1: {
id: newUserId
}
}
documentDel(data).then(
(resp) => {
if (resp.code === 0) {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getNewsList()
} else {
this.$message.error(resp.errorMessage)
}
},
(error) => {
this.$message.error(error)
}
)
},
handleSelectionChange(val) {
this.multipleId = []
val.forEach((item) => {
this.multipleId.push(item.id)
})
},
clearTable() {
this.formLine = {
organName: '',
orginType: ''
}
this.pages = {
pageSize: 10,
currentPage: 1,
total: 0,
},
this.getNewsList()
},
searchTable() {
this.pages = {
pageSize: 10,
currentPage: 1,
total: 0,
},
this.getNewsList(true)
},
async documEdit(row) {
this.feedFlag = true
this.editFlag = true
this.id = row.id
await this.getDocumDtl()
},
getNewsList(isSearch) {
if (isSearch) {
this.searchFlag = true
}
this.tableFlag = true
const data = {
data1: {
pageNo: this.pages.currentPage,
pageSize: this.pages.pageSize
},
data2: {
name: this.formLine.organName,
fileType: this.formLine.orginType,
orderType: ''
}
}
documentPage(data).then(
(resp) => {
if (resp.code === 0) {
this.tableData = resp.payload.records
this.tableData.forEach((item) => {
switch (item.fileType) {
case 1:
item.fileTypeText = '验收结果'
break
case 2:
item.fileTypeText = '现场验收'
break
case 3:
item.fileTypeText = '线上(远程)验收'
break
default:
break
}
switch (item.orderType) {
case 1:
item.orderTypeText = '验收申请工单'
break
case 2:
item.orderTypeText = '网络接入工单'
break
default:
break
}
})
this.pages.total = resp.payload.total
if (isSearch) {
this.$message({
message: '查询成功',
type: 'success'
})
}
} else {
this.$message.error(resp.errorMessage)
}
this.searchFlag = false
this.tableFlag = false
},
(error) => {
this.searchFlag = false
this.tableFlag = false
this.$message.error(error)
}
)
},
handleSizeChange(newSize) {
this.pages.pageSize = newSize;
this.getNewsList();
},
//页码改变
handleCurrentChange(newPage) {
this.pages.currentPage = newPage;
this.getNewsList();
},
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
}
}
}
</script>
<style lang="less" scoped>
</style>