封装导出下载
This commit is contained in:
parent
4ab5a2eee3
commit
b32dee5886
@ -10,8 +10,8 @@ VUE_APP_API_BASEURL = https://xwapi.dev.dwoodauto.com/api/v1
|
||||
VUE_APP_API_DEV = https://xwapi.dev.dwoodauto.com
|
||||
|
||||
# WS地址
|
||||
VUE_APP_WS_URL = wss://api.dev.dwoodauto.com/wss
|
||||
VUE_APP_WSS_URL = wss://api.dev.dwoodauto.com/wss
|
||||
VUE_APP_WS_URL = wss://xwapi.dev.dwoodauto.com/wss
|
||||
VUE_APP_WSS_URL = wss://xwapi.dev.dwoodauto.com/wss
|
||||
|
||||
# 本地端口
|
||||
VUE_APP_PORT = 2801
|
||||
|
||||
@ -212,6 +212,13 @@ export default {
|
||||
post: async function (params) {
|
||||
return await http.post(this.url,params);
|
||||
}
|
||||
},
|
||||
export:{
|
||||
url: `${config.API_URL}/organization.export`,
|
||||
name: "公司资料导出",
|
||||
post: async function (params) {
|
||||
return await http.post(this.url,params);
|
||||
}
|
||||
}
|
||||
},
|
||||
dept: {
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<template>
|
||||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M554.666667 426.666667h213.333333l-256 256-256-256h213.333333V128h85.333334v298.666667z m-384 384h682.666666v-298.666667h85.333334v341.333333a42.666667 42.666667 0 0 1-42.666667 42.666667H128a42.666667 42.666667 0 0 1-42.666667-42.666667v-341.333333h85.333334v298.666667z" p-id="26056"></path></svg>
|
||||
<svg t="1720852160381" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3290" width="200" height="200"><path d="M519.64586667 75.09333333a36.40888889 36.40888889 0 0 1 36.40888888 36.40888889v501.49603556l182.04444445-177.96664889a36.40888889 36.40888889 0 1 1 50.97244445 52.06471111l-243.93955556 238.47822222a36.40888889 36.40888889 0 0 1-51.40935111-0.43690667L257.13777778 486.73223111a36.40888889 36.40888889 0 0 1 51.70062222-51.26371556l174.39857778 175.70929778V111.50222222a36.40888889 36.40888889 0 0 1 36.40888889-36.40888889z" fill="" p-id="3291"></path><path d="M111.50222222 584.67214222a36.40888889 36.40888889 0 0 1 36.40888889 36.40888889v218.45333334a36.40888889 36.40888889 0 0 0 36.40888889 36.40888888h655.36a36.40888889 36.40888889 0 0 0 36.40888889-36.40888888v-218.45333334a36.40888889 36.40888889 0 0 1 72.81777778 0v218.45333334a109.22666667 109.22666667 0 0 1-109.22666667 109.22666666h-655.36a109.22666667 109.22666667 0 0 1-109.22666667-109.22666666v-218.45333334a36.40888889 36.40888889 0 0 1 36.40888889-36.40888889z" fill="" p-id="3292"></path></svg>
|
||||
</template>
|
||||
13
src/assets/icons/Finish.vue
Normal file
13
src/assets/icons/Finish.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<svg t="1720855403788" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3434" width="200" height="200"><path d="M512.170667 6.144a504.917333 504.917333 0 0 0-504.32 504.32 504.917333 504.917333 0 0 0 504.32 504.405333 504.917333 504.917333 0 0 0 504.32-504.32 504.917333 504.917333 0 0 0-504.32-504.32zM794.453333 413.866667L466.432 750.08a42.069333 42.069333 0 0 1-29.866667 12.629333h-0.170666a42.069333 42.069333 0 0 1-29.696-12.288L230.314667 574.037333a41.984 41.984 0 1 1 59.392-59.392L436.053333 660.906667l298.24-305.834667a42.069333 42.069333 0 0 1 60.16 58.794667z" fill="#0DA525" p-id="3435"></path></svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Finish"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -21,6 +21,7 @@ export { default as Secure } from './Secure.vue'
|
||||
export { default as UserLog } from './Log.vue'
|
||||
export { default as WechartRound } from './WechartRound.vue'
|
||||
export { default as Cost } from './Cost.vue'
|
||||
export { default as Finish } from './Finish.vue'
|
||||
|
||||
// 列表按钮
|
||||
export { default as Delete } from './Delete.vue'
|
||||
|
||||
102
src/components/scExport/index.vue
Normal file
102
src/components/scExport/index.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<el-popover
|
||||
placement="bottom-start"
|
||||
title=""
|
||||
trigger="click"
|
||||
content=""
|
||||
width="280"
|
||||
:visible="exportVisible"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button v-bind="$attrs" :size="size" icon="sc-icon-Download" @click="exportClick">下载</el-button>
|
||||
</template>
|
||||
<template #default>
|
||||
<div class="exportHeader">
|
||||
<div class="name">{{info.type_desc}}</div>
|
||||
<div class="status" v-if="info.status==0">{{info.msg}}</div>
|
||||
<div class="finish" v-if="info.status==1"><i class="icon"><sc-icon-Finish/></i> 文件生成完成</div>
|
||||
</div>
|
||||
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="info.rate" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "index",
|
||||
props:{
|
||||
size:{ type: String, default: "small" },
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
exportVisible:false,
|
||||
info:{
|
||||
name:"",
|
||||
status:"",
|
||||
rate:0,
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 获取新消息
|
||||
this.$socketApi.getSock(this.getWsResult);
|
||||
},
|
||||
methods:{
|
||||
getWsResult(res){
|
||||
if(res.data && res.data.type == 6){
|
||||
if(res.data.status == 0){
|
||||
this.exportVisible = true;
|
||||
}
|
||||
this.info = res.data;
|
||||
if(res.data.status==1){
|
||||
this.exportVisible = false;
|
||||
this.info = {};
|
||||
this.down(res.data);
|
||||
}
|
||||
}
|
||||
},
|
||||
down(item){
|
||||
const blob = new Blob([item.file_url]);
|
||||
let fileName = item.type_desc+".xlsx";
|
||||
if ('download' in document.createElement('a')) { // 非IE下载
|
||||
let eLink = document.createElement('a');
|
||||
eLink.download = fileName
|
||||
eLink.style.display = 'none';
|
||||
eLink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(eLink);
|
||||
eLink.click();
|
||||
URL.revokeObjectURL(eLink.href); // 释放URL 对象
|
||||
document.body.removeChild(eLink);
|
||||
} else { // IE10+下载
|
||||
navigator.msSaveBlob(blob, fileName);
|
||||
}
|
||||
},
|
||||
exportClick(){
|
||||
if(this.exportVisible){
|
||||
this.exportVisible = false;
|
||||
return
|
||||
}
|
||||
this.$emit('exportData');
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.exportHeader{
|
||||
font-size: 12px;
|
||||
display: flex;align-items: center;justify-content: space-around;
|
||||
margin-bottom: 6px;
|
||||
.name{width: 60%;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;}
|
||||
.status{width: 40%;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;}
|
||||
.finish{
|
||||
display: flex;align-items: center;justify-content: flex-end;color: var(--el-color-success);
|
||||
.icon{width: 14px;height: 14px;margin-right: 4px;}
|
||||
}
|
||||
}
|
||||
.exportPopover :deep(.el-progress-bar__innerText){
|
||||
height: 100%;
|
||||
display: flex;align-items: center;justify-content: flex-end;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -242,9 +242,18 @@
|
||||
created() {
|
||||
this.onLayoutResize();
|
||||
window.addEventListener('resize', this.onLayoutResize);
|
||||
var menu = this.$router.sc_getMenu();
|
||||
const menu = this.$router.sc_getMenu();
|
||||
this.menu = this.filterUrl(menu);
|
||||
this.showThis()
|
||||
this.showThis();
|
||||
|
||||
let token = this.$TOOL.cookie.get('TOKEN');
|
||||
if (token && token != null) {
|
||||
let global_callback = function () {};
|
||||
this.$socketApi.createWebSocket(global_callback);
|
||||
|
||||
// 获取新消息
|
||||
// this.$socketApi.getSock(this.getWsResult);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
|
||||
@ -26,6 +26,7 @@ import scMultipleSelect from "./components/scMultipleSelect";
|
||||
import scInput from "./components/scInput";
|
||||
import scVgInput from "./components/scInput/inputVague";
|
||||
import scSearch from "./components/scSearch";
|
||||
import scExport from "./components/scExport";
|
||||
|
||||
import scStatusIndicator from './components/scMini/scStatusIndicator'
|
||||
import scTrend from './components/scMini/scTrend'
|
||||
@ -40,6 +41,7 @@ import errorHandler from './utils/errorHandler'
|
||||
|
||||
import * as elIcons from '@element-plus/icons-vue'
|
||||
import * as scIcons from './assets/icons'
|
||||
import * as socketApi from "@/utils/websocket";
|
||||
|
||||
export default {
|
||||
install(app) {
|
||||
@ -50,6 +52,7 @@ export default {
|
||||
app.config.globalProperties.$API = api;
|
||||
app.config.globalProperties.$AUTH = permission;
|
||||
app.config.globalProperties.$ROLE = rolePermission;
|
||||
app.config.globalProperties.$socketApi = socketApi;
|
||||
|
||||
//注册全局组件
|
||||
app.component('scTable', scTable);
|
||||
@ -76,6 +79,7 @@ export default {
|
||||
app.component('scInput', scInput);
|
||||
app.component('scVgInput', scVgInput);
|
||||
app.component('scSearch', scSearch);
|
||||
app.component('scExport', scExport);
|
||||
|
||||
//注册全局指令
|
||||
app.directive('auth', auth)
|
||||
|
||||
194
src/utils/websocket.js
Normal file
194
src/utils/websocket.js
Normal file
@ -0,0 +1,194 @@
|
||||
//@eslint-disable
|
||||
|
||||
import tool from '@/utils/tool';
|
||||
import systemConfig from '@/config';
|
||||
import api from '../api';
|
||||
import router from "@/router";
|
||||
import {ElNotification} from 'element-plus';
|
||||
// import store from "../store";
|
||||
|
||||
let websocket = null;
|
||||
let global_callback = function () {};
|
||||
let timeoutObj = null;
|
||||
let timeout = 28 * 1000; //30秒一次心跳
|
||||
let serverTimeoutObj = 60; //心跳倒计时
|
||||
let timeOutNum = 60; //断开 重连倒计时
|
||||
let lockReconnect = false; //是否真正建立连接
|
||||
const wsUri = systemConfig.WS_URL;
|
||||
let showNot = null;
|
||||
|
||||
function networkDes() {
|
||||
ElNotification.error({
|
||||
title: '网络已断开',
|
||||
message: '网络已断开,正在重连……'
|
||||
})
|
||||
}
|
||||
|
||||
function reConnect() {//重新连接
|
||||
if (lockReconnect) {
|
||||
return;
|
||||
}
|
||||
lockReconnect = true;
|
||||
//没连接上会一直重连,设置延迟避免请求过多
|
||||
timeOutNum && clearTimeout(timeOutNum);
|
||||
timeOutNum = setTimeout(function () {
|
||||
//新连接
|
||||
createWebSocket(global_callback);
|
||||
lockReconnect = false;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function startHeartbeat() {
|
||||
//清除时间
|
||||
clearTimeout(timeoutObj);
|
||||
clearTimeout(serverTimeoutObj);
|
||||
start();
|
||||
}
|
||||
|
||||
function start() {//开启心跳
|
||||
timeoutObj && clearTimeout(timeoutObj);
|
||||
serverTimeoutObj && clearTimeout(serverTimeoutObj);
|
||||
timeoutObj = setTimeout(function () {
|
||||
//这里发送一个心跳,后端收到后,返回一个心跳消息,
|
||||
if (websocket.readyState === 1) {//如果连接正常
|
||||
const heart = {type: "heart"}
|
||||
websocket.send(JSON.stringify(heart));
|
||||
} else {//否则重连
|
||||
reConnect();
|
||||
}
|
||||
serverTimeoutObj = setTimeout(function () {
|
||||
//超时关闭
|
||||
closeSock(false);
|
||||
}, timeout);
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
function createWebSocket(callback, token) {
|
||||
if (websocket == null || typeof websocket !== WebSocket) {
|
||||
initWebSocket(callback, token);
|
||||
}
|
||||
}
|
||||
|
||||
function initWebSocket(callback, token) {
|
||||
global_callback = callback;
|
||||
// 初始化websocket
|
||||
let reToken = token === undefined ? tool.cookie.get('TOKEN') : token;
|
||||
if(!reToken) return // 没有token 不执行ws创建
|
||||
websocket = new WebSocket(wsUri + "?token=Bearer " + reToken);
|
||||
websocket.onmessage = function (e) {
|
||||
webSocketOnMessage(e);
|
||||
};
|
||||
websocket.onclose = function (e) {
|
||||
webSocketClose(e);
|
||||
};
|
||||
websocket.onopen = function () {
|
||||
websocketOpen();
|
||||
};
|
||||
|
||||
// 连接发生错误的回调方法
|
||||
websocket.onerror = function () {
|
||||
networkDes()
|
||||
reConnect()
|
||||
};
|
||||
}
|
||||
|
||||
// 实际调用的方法
|
||||
function sendSock(agentData) {
|
||||
if (websocket.readyState === websocket.OPEN) {
|
||||
// 若是ws开启状态
|
||||
webSocketSend(agentData);
|
||||
} else if (websocket.readyState === websocket.CONNECTING) {
|
||||
// 若是 正在开启状态,则等待1s后重新调用
|
||||
setTimeout(function () {
|
||||
sendSock(agentData);
|
||||
}, 1000);
|
||||
} else {
|
||||
// 若未开启 ,则等待1s后重新调用
|
||||
setTimeout(function () {
|
||||
sendSock(agentData);
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function closeSock(active) {
|
||||
lockReconnect = active; // 主动断开时不重连
|
||||
websocket.close();
|
||||
}
|
||||
|
||||
// 数据接收
|
||||
function webSocketOnMessage(msg) {
|
||||
// 收到信息为Blob类型时
|
||||
let result = null;
|
||||
// debugger
|
||||
// 二进制文件
|
||||
if (msg.data instanceof Blob) {
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(msg.data, "UTF-8");
|
||||
reader.onload = () => {
|
||||
result = JSON.parse(reader.result);
|
||||
global_callback(result);
|
||||
};
|
||||
} else {
|
||||
if(msg.type === "") return
|
||||
result = JSON.parse(msg.data);
|
||||
// if(result.type == 13){
|
||||
// store.commit("SET_WS_Msg_NUM", result.data.todo_msg_count);
|
||||
// }
|
||||
if(global_callback){
|
||||
global_callback(result);
|
||||
}
|
||||
}
|
||||
if (result.type == -1 || result.type == 8 || result.type == 9) {
|
||||
if(result.type == -1){
|
||||
if(result.data && result.data.token){
|
||||
tool.cookie.set("TOKEN", result.data.token);
|
||||
}
|
||||
}else{
|
||||
showNot = ElNotification.error({
|
||||
title: '系统退出',
|
||||
message: result.msg,
|
||||
duration:0
|
||||
});
|
||||
handleError('系统退出', result.msg);
|
||||
}
|
||||
}
|
||||
|
||||
if(result.type == 'init'){
|
||||
if(showNot && showNot.close){
|
||||
showNot.close();
|
||||
}
|
||||
}
|
||||
startHeartbeat()
|
||||
}
|
||||
|
||||
function handleError() {
|
||||
api.system.user.logout.post().then();
|
||||
router.replace({ path: "/login" }).then();
|
||||
closeSock(true);
|
||||
}
|
||||
|
||||
function getSock(callback) {
|
||||
global_callback = callback
|
||||
}
|
||||
|
||||
// 数据发送
|
||||
function webSocketSend(agentData) {
|
||||
websocket.send(agentData);
|
||||
}
|
||||
|
||||
// 关闭
|
||||
function webSocketClose() {
|
||||
reConnect()
|
||||
}
|
||||
|
||||
function websocketOpen() {
|
||||
start()
|
||||
}
|
||||
|
||||
export {
|
||||
sendSock,
|
||||
createWebSocket,
|
||||
closeSock,
|
||||
getSock,
|
||||
reConnect,
|
||||
};
|
||||
@ -6,7 +6,7 @@
|
||||
<el-button type="primary" :size="size" plain>批量导入</el-button>
|
||||
</div>
|
||||
<div class="right-panel">
|
||||
<el-button :size="size" icon="sc-icon-Download">下载</el-button>
|
||||
<scExport :size="size" @exportData="exportData"></scExport>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
@ -206,6 +206,12 @@ export default {
|
||||
delete row.$switch_yx;
|
||||
}, 500);
|
||||
},
|
||||
async exportData() {
|
||||
const res = await this.$API.system.company.export.post();
|
||||
if(res.code == 200){
|
||||
this.$message.success('开始导出');
|
||||
}
|
||||
},
|
||||
upSearch(){
|
||||
this.$refs.table.upData(this.params);
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user