1、实现效果

和element ui 选择月份同样的效果,也支持键盘上下左右控制选择季度。
2、页面调用
<ElQuarterPicker v-model="value" placeholder="选择季度"></ElQuarterPicker>
3、组件代码: ElQuarterPicker.vue
<template>
<div class="evaluationform">
<div class="loadingBox" v-loading="loading" element-loading-text="数据加载中..." v-if="loading"></div><!-- 加载效果 -->
<el-date-picker v-if="activeName =='1'" v-model="selectTime" type="daterange" range-separator="-"
start-placeholder="开始日期" end-placeholder="结束日期" placeholder="选择日期" value-format="yyyy-MM-dd"
@change="handleChange">
</el-date-picker>
<el-button type="primary" style="margin-left:15px" class="btn-def" @click="handleUpload">成果上传</el-button>
<el-button type="primary" style="margin-left:15px" class="btn-def" @click="exportsExcel"
:loading="excelLoading">刷新</el-button>
<el-button type="primary" style="margin-left:15px" class="btn-def" @click="handleUpload('pdf')">发布离线成果</el-button>
<el-tabs v-model="activeName" class="margin-top20" type="card" @tab-click="handleClick">
<el-tab-pane label="日报" name="1">
<el-table :data="tableData" v-loading="tableLoading" style="width: 100%;margin-top: 15px;"
:header-cell-style="headerCellStyle" :cell-style="cellStyle" :height="tableHeight">
<el-table-column type="index" width="80" label="序号" align="center">
</el-table-column>
<el-table-column prop="curDate" label="日期" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.curDate.replace(/\./g, '-') }}</span>
</template>
</el-table-column>
<el-table-column prop="bgmc" label="文件名" align="center" min-width="300">
</el-table-column>
<el-table-column prop="status" label="状态" align="center" min-width="100">
<template slot-scope="scope">
<div v-if="scope.row.status == 1">
待确认
<span class="progress" @click="onProgress(scope.row)">{{ scope.row.confirmationNumber }}</span>
</div>
<div v-else :style="{ color: scope.row.status == '3' ? '#409eff' : '#85ce61' }">{{ scope.row.status == 2 ?
'已确认' : scope.row.status == 3 ? '已发布' : '' }}</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="140">
<template slot-scope="scope">
<span v-if="scope.row.isWord=='1'">
<el-button @click="handlePreview(scope.row)" type="text" size="small">预览</el-button>
<el-button v-if="scope.row.status == 1" @click="handleEdit(scope.row)" type="text"
size="small">编辑</el-button>
<el-button v-if="scope.row.status == 1 && scope.row.isQr == '待确认'" @click="handleConfirm(scope.row)"
type="text" size="small">确认</el-button>
<el-button v-if="scope.row.status == 2 || scope.row.isQr == '已确认'"
@click="handleCancelConfirmation(scope.row)" type="text" size="small">取消确认</el-button>
<el-button v-if="scope.row.status == 2" @click="handleRelease(scope.row)" type="text"
size="small">发布</el-button>
<el-button v-if="scope.row.status == 3" @click="handleCancelPublishing(scope.row)" type="text"
size="small">取消发布</el-button>
<el-button @click="handleDownload(scope.row)" type="text" size="small">下载</el-button>
</span>
<el-button v-if="scope.row.status == 1 || scope.row.isWord=='0' " @click="handleDelete(scope.row)" type="text"
size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style="text-align: right;padding: 10px 0px;">
<el-pagination :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</el-tab-pane>
<el-tab-pane label="季报" name="2">
<el-table :data="tableData" v-loading="tableLoading" style="width: 100%;margin-top: 15px;"
:header-cell-style="headerCellStyle" :cell-style="cellStyle" :height="tableHeight">
<el-table-column type="index" width="80" label="序号" align="center">
</el-table-column>
<el-table-column prop="curDate" label="日期" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.curDate.split('-')[0] }}年{{ scope.row.curDate.split('-')[1] }}季度</span>
</template>
</el-table-column>
<el-table-column prop="bgmc" label="文件名" align="center" min-width="300">
</el-table-column>
<el-table-column prop="status" label="状态" align="center" min-width="100">
<template slot-scope="scope">
<div v-if="scope.row.status == 1">
待确认
<span class="progress" @click="onProgress(scope.row)">{{ scope.row.confirmationNumber }}</span>
</div>
<div v-else :style="{ color: scope.row.status == '3' ? '#409eff' : '#85ce61' }">{{ scope.row.status == 2 ?
'已确认' : scope.row.status == 3 ? '已发布' : '' }}</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="140">
<template slot-scope="scope">
<span v-if="scope.row.isWord =='1'">
<el-button @click="handlePreview(scope.row)" type="text" size="small">预览</el-button>
<el-button v-if="scope.row.status == 1" @click="handleEdit(scope.row)" type="text"
size="small">编辑</el-button>
<el-button v-if="scope.row.status == 1 && scope.row.isQr == '待确认'" @click="handleConfirm(scope.row)"
type="text" size="small">确认</el-button>
<el-button v-if="scope.row.status == 2 || scope.row.isQr == '已确认'"
@click="handleCancelConfirmation(scope.row)" type="text" size="small">取消确认</el-button>
<el-button v-if="scope.row.status == 2" @click="handleRelease(scope.row)" type="text"
size="small">发布</el-button>
<el-button v-if="scope.row.status == 3" @click="handleCancelPublishing(scope.row)" type="text"
size="small">取消发布</el-button>
<el-button @click="handleDownload(scope.row)" type="text" size="small">下载</el-button>
</span>
<el-button v-if="scope.row.status == 1 || scope.row.isWord =='0' " @click="handleDelete(scope.row)" type="text"
size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div style="text-align: right;padding: 10px 0px;">
<el-pagination :current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</el-tab-pane>
</el-tabs>
<el-dialog :title="uploadType == 'pdf' ? '发布离线成果(pdf)':'成果上传(word)'" :visible.sync="dialogVisible" width="450px"
class="centerDialog">
<div>
<label for="">简报类型:</label>
<el-radio v-model="radio" :label="1">日报</el-radio>
<el-radio v-model="radio" :label="2">季报</el-radio>
</div>
<label for="">选择日期:</label>
<ElQuarterPicker v-show="radio == 2" v-model="value" placeholder="选择季度"></ElQuarterPicker>
<el-date-picker v-show="radio == 1" v-model="fileTime" type="date" placeholder="选择日期" value-format="yyyy-MM-dd">
</el-date-picker>
<el-upload class="upload-demo" ref="enclosureUpload" :accept="uploadType == 'pdf'? '.pdf':'.docx'"
:file-list="fileList" action multiple :limit="1" :show-file-list="false" :auto-upload="false"
:on-change="handleFileChange" :on-exceed="handleExceed" :disabled="fileBtn">
<el-button type="info" size="small" class="filebtns" plain round @click="uploadmore2">
上传
</el-button>
</el-upload>
</el-dialog>
<el-dialog title="确认信息" :visible.sync="progressdialogVisible" width="600px" class="centerDialog">
<el-table :data="progressTableData" v-loading="progressTableLoading" style="width: 100%;margin-top: 15px;"
:header-cell-style="headerCellStyle" :cell-style="cellStyle">
<el-table-column type="index" width="80" label="序号" align="center">
</el-table-column>
<el-table-column prop="date" label="确认日期" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.curDate.replace(/\./g, '-') }}</span>
</template>
</el-table-column>
<el-table-column prop="userName" label="确认人" min-width="100" align="center">
<template slot-scope="scope">
<span>{{ scope.row.curDate.replace(/\./g, '-') }}</span>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import {
getcgFile,
idxDlgxjbDelFile,
importXlsx,
postUpload,
postUploadPdf,
idxDlgxjbDownloadFile,
idxDlgxjbDlgXjbUpdateByDlgXjbId,
idxDlgxjbDlgXjbUserListByDlgXjbId,
exportExcel
} from '@/api/upload.js'
import { getDate, getBeforeDate } from '@/utils/index'
import ElQuarterPicker from '@/components/Quarter/index.vue'
export default {
components: { ElQuarterPicker },
data() {
return {
loading: false,//更新汇总表加载
excelLoading: false,//更新汇总表加载
selectTime: [],//成果列表查询时间
tableData: [],//成果列表 status 1 待确认 2 已确认 3已发布
tableHeight: this.initHeight(),//成果列表 高度
tableLoading: false,//成果列表加载
currentPage: 1,
pageSize: 10,
total: 0,
dialogVisible: false, // 上传成果弹窗
fileTime: '',//上传成果的时间 默认当前时间
fileBtn: true,//上传按钮是否禁用
fileList: [],//上传的成果
timer: null, //上传成果计时器
progressdialogVisible: false,//确认信息 弹框
progressTableData: [],//确认信息 表格数据
progressTableLoading: false,//确认信息 表格数据 弹框
radio: 1,//1 日报 2 季报
value: '',//季度
activeName:'1',
uploadType: 'pdf',//上传类型 pdf word
};
},
mounted() {
window.onresize = () => {
return (() => {
this.tableheight = this.initHeight();
})()
}
this.selectTime = [getBeforeDate(30), getBeforeDate(0)]
this.getList()
},
watch: {
value(val) {
// this.getList()
}
},
methods: {
// tab切换
handleClick(tab, event) {
this.getList()
},
// 表格的高度
initHeight() {
// return 'calc(100vh - 220px)'
return "620px";
},
// 时间切换
handleChange() {
this.getList()
this.timer = new Date().getTime()
},
// 获取成果列表
getList() {
this.tableLoading = true
var obj = {}
if (this.selectTime && this.selectTime.length) {
obj = {
startDate: this.selectTime[0],
endDate: this.selectTime[1],
current: this.currentPage,
size: this.pageSize,
type: this.activeName
}
} else {
obj = {
startDate: '',
endDate: '',
current: this.currentPage,
size: this.pageSize,
type: this.activeName
}
}
getcgFile(obj).then(res => {
this.tableData = res.content
this.total = res.totalElements
this.tableLoading = false
this.excelLoading = false
}).catch(() => {
this.tableData = []
this.total = 0
this.tableLoading = false
this.excelLoading = false
})
},
// 更新汇总表
exportsExcel() {
this.excelLoading = true
this.getList()
// this.loading = true
// const obj = {
// date: sessionStorage.getItem('da')
// };
// exportExcel(obj)
// .then(res => {
// this.$message.success(res)
// this.getList()
// this.excelLoading = false
// this.loading = false
// })
// .catch((err) => {
// this.$message.error(err + '文件导出失败,数据不全!')
// this.getList()
// this.excelLoading = false
// this.loading = false
// });
},
// 分页 每页多少条
handleSizeChange(val) {
this.pageSize = val;
this.getList();
},
// 分页 多少页
handleCurrentChange(val) {
this.currentPage = val;
this.getList();
},
// 查看 确认信息
onProgress(row) {
this.progressdialogVisible = true
idxDlgxjbDlgXjbUserListByDlgXjbId({
dlgXjbId: row.id
}).then(res => {
if (!res || !res[0]) return
this.progressTableData = res
this.progressdialogVisible = false
}).catch(() => {
this.progressTableData = []
this.progressdialogVisible = false
})
},
// 预览
handlePreview(row) {
this.$router.push({
path: '/data/word',
query: {
isEdit: 0,
id: row.id
}
})
},
// 编辑
handleEdit(row) {
this.$router.push({
path: '/data/word',
query: {
isEdit: 1,
id: row.id
}
})
},
// 确认
handleConfirm(row) {
this.$confirm('请确认该文件内容是否正确!', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
idxDlgxjbDlgXjbUpdateByDlgXjbId({
dlgXjbId: row.id,
status: 1,//status 1.确认2.重置确认3.发布4.取消发布
}).then(res => {
this.$message.success('确认成功')
this.getList()
})
})
},
// 取消确认
handleCancelConfirmation(row) {
this.$confirm('请确认是否要取消确认!', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
idxDlgxjbDlgXjbUpdateByDlgXjbId({
dlgXjbId: row.id,
status: 2,//status 1.确认2.重置确认3.发布4.取消发布
}).then(res => {
this.$message.success('取消确认成功')
this.getList()
})
})
},
// 发布
handleRelease(row) {
this.$confirm('请确认是否要发布该文件!', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
idxDlgxjbDlgXjbUpdateByDlgXjbId({
dlgXjbId: row.id,
status: 3,//status 1.确认2.重置确认3.发布4.取消发布
}).then(res => {
this.$message.success('发布成功')
this.getList()
})
})
},
// 取消发布
handleCancelPublishing(row) {
this.$confirm('请确认是否要取消发布该文件!', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
idxDlgxjbDlgXjbUpdateByDlgXjbId({
dlgXjbId: row.id,
status: 4,//status 1.确认2.重置确认3.发布4.取消发布
}).then(res => {
this.$message.success('取消发布成功')
this.getList()
})
})
},
//删除
handleDelete(row) {
this.$confirm('请确认是否删除该文件!', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
idxDlgxjbDelFile({
id: row.id
}).then(res => {
this.$message.success('删除成功')
this.getList()
})
})
},
// 下载
handleDownload(row) {
const loading = this.$loading({
lock: true,
text: "下载中,请稍后",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.5)"
});
idxDlgxjbDownloadFile({
id: row.id,
type:'word'
}).then(res => {
let url = window.URL.createObjectURL(new Blob([res]));
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.setAttribute("download", row.bgmc + '.docx');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
loading.close();
}).catch(() => {
loading.close();
});
},
// 表头样式
headerCellStyle() {
return {
background: 'rgb(233, 237, 242)',
color: 'rgb(75, 84, 104)',
fontWeight: '700',
fontSize: '18px',
borderColor: 'rgb(211, 214, 220)'
};
},
// 表格单元格样式
cellStyle() {
return {
fontSize: '16px',
color: 'rgb(96, 98, 102)',
fontWeight: '400',
marginBottom: '20px',
boxShadow: '0px 2px 4px 0px rgba(0, 0, 0, 0.08)'
};
},
// 成果上传
handleUpload(v) {
this.fileList = []
this.fileTime =''
this.value =''
this.radio =1
this.uploadType = v
this.dialogVisible = true
// this.fileTime = getDate(new Date()).replace(/\./g, '-')
this.fileBtn = true
},
// 上传按钮点击
uploadmore2() {
if (!this.fileTime && this.radio ==1) {
this.$message.warning('请先选择日期在进行上传!')
return
}
if (!this.value && this.radio ==2) {
this.$message.warning('请先选择季度在进行上传!')
return
}
this.fileList =[]
this.fileBtn = false
},
// 文件超出个数限制时的钩子
handleExceed(files, fileList) {
this.$message.warning(`限制选择7个文件,本次选择了 ${files.length} 个文件`);
},
// 上传附件 过滤重复
filterRepetition(arr) {
let arr1 = []; //存id
let newArr = []; //存新数组
for (let i in arr) {
if (arr1.indexOf(arr[i].name) == -1) {
arr1.push(arr[i].name);
newArr.push(arr[i]);
}
}
return newArr;
},
// 修改 存放要上传的文件列表
handleFileChange(file, fileList) {
let arr = this.filterRepetition(fileList);
if (arr.length !== fileList.length) {
this.$message("上传重复文件,已过滤重复文件");
}
this.fileList = arr;
// 上传文件后,自动把文件传给后台,这里做了一个防抖,等待500ms后在传给后台
this.debounce(this.submitUpload, 500);
},
// element上传多个文件时,会把每个文件做个单独请求
// 这里的方法是请求最后一次
debounce(fn, waits) {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
this.timer = setTimeout(() => {
fn.apply(this, arguments); // 把参数传进去
}, waits);
},
// 确定
async submitUpload() {
if (this.fileList.length === 0) {
this.$message.success("请上传文件");
return;
}
let formData = new FormData(); // 用FormData存放上传文件
this.fileList.forEach((file) => {
formData.append("file", file.raw);
});
formData.append("date", this.radio ==1 ? this.fileTime: this.value);
formData.append("bglx", this.radio);
// formData.append("status", 1);
// 确定上传 把在上传列表里的文件 合并到formData里面传给后台
if(this.uploadType =='pdf'){
let res = await postUploadPdf(formData);
this.fileList = []
this.$message.success('上传成功')
this.getList()
this.fileBtn = true
this.fileTime = null
this.dialogVisible = false
}else{
let res = await postUpload(formData);
this.fileList = []
this.$message.success('上传成功')
this.getList()
this.fileBtn = true
this.fileTime = null
this.dialogVisible = false
}
}
}
};
</script>
<style lang="scss" scoped>
.evaluationform {
padding: 15px;
// margin-top: 2px;
width: 100%;
height: 100%;
.progress {
color: #4d85ff;
margin-left: 10px;
cursor: pointer;
}
::v-deep .centerDialog {
.el-dialog {
position: relative;
.el-dialog__header {
position: absolute;
top: -10px;
right: -6px;
}
.el-dialog__body {
padding: 20px;
}
}
}
::v-deep .el-date-editor {
box-sizing: border-box;
border: 1px solid rgb(187, 202, 227);
border-radius: 2px;
background: rgb(241, 249, 255);
.el-range-input {
background: rgb(241, 249, 255);
color: rgb(51, 51, 51);
font-family: 微软雅黑;
font-size: 16px;
font-weight: 700;
}
}
.upload-demo {
margin-top: 15px;
display: inline-block;
margin-left: 15px;
margin-bottom: 15px;
}
.el-button--info {
background: #66b1ff;
border-color: #66b1ff;
color: #FFF;
}
.filebtns {
width: 97px;
height: 38px;
background: #409EFF !important;
border-color: #409EFF !important;
font-size: 14px;
font-weight: 500;
}
.loadingBox {
width: calc(100vw);
height: calc(100vh);
position: fixed;
bottom: 0px;
right: 20px;
z-index: 999999999;
}
.btn-def {
background: #1059b5;
border: solid 1px #1059b5;
height: 32px;
color: #fff;
font-family: 微软雅黑;
font-size: 14px;
font-weight: 700
}
::v-deep .el-dialog__header {
position: relative !important;
top: 0;
left: 0;
padding: 20px !important;
}
.margin-top20{
margin-top: 20px;
}
}
</style>