Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
d19f39a0ae
|
@ -107,7 +107,7 @@ export const deviceImport = (productId: string, fileUrl: string, autoDeploy: boo
|
|||
* @param type 文件类型
|
||||
* @returns
|
||||
*/
|
||||
export const deviceExport = (productId: string, type: string) => `${BASE_API_PATH}/device-instance${!!productId ? `/${productId}` : ''}/export.${type}`
|
||||
export const deviceExport = (productId: string, type: string, params?: any) => server.get(`/device-instance${!!productId ? `/${productId}` : ''}/export.${type}`, params, {responseType: 'blob'})
|
||||
|
||||
/**
|
||||
* 验证设备ID是否重复
|
||||
|
|
|
@ -97,7 +97,7 @@ export const _import = (configId: any, params: any) => server.get(`/network/card
|
|||
* @param format 类型 xlsx、csv
|
||||
* @param params
|
||||
*/
|
||||
export const _export = (format: string, data: any) => server.post(`/network/card/download.${format}/_query`, data, { responseType: 'blob' });
|
||||
export const _export = (format: string, data: any) => server.postStream(`/network/card/download.${format}/_query`, data);
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
|
|
|
@ -112,6 +112,12 @@ export const getStream = function(url: string, params = {}) {
|
|||
})
|
||||
}
|
||||
|
||||
export const postStream = function(url: string, data={}, params = {}) {
|
||||
return post<any>(url, data, params, {
|
||||
responseType: 'arraybuffer' // 设置请求数据类型,返回blob可解析类型
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常拦截处理器
|
||||
* @param {Object} error
|
||||
|
@ -208,7 +214,7 @@ request.interceptors.response.use(response => {
|
|||
}
|
||||
// 如果返回的的是文件流,那么return值则为response
|
||||
if (response.headers['content-type'] === 'application/octet-stream; charset=UTF-8' || response.headers['content-type'] === 'application/vnd.ms-excel;charset=UTF-8') {
|
||||
return response
|
||||
return response.data
|
||||
} else {
|
||||
return response.data
|
||||
}
|
||||
|
@ -222,5 +228,6 @@ export default {
|
|||
patch,
|
||||
put,
|
||||
remove,
|
||||
getStream
|
||||
getStream,
|
||||
postStream
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import moment from "moment";
|
||||
import { LocalStore } from "./comm";
|
||||
import { TOKEN_KEY } from "./variable";
|
||||
import {SystemConst} from './consts';
|
||||
import { SystemConst } from './consts';
|
||||
|
||||
/**
|
||||
* 把数据下载成JSON
|
||||
|
@ -30,7 +30,7 @@ export const downloadObject = (record: Record<string, any>, fileName: string, fo
|
|||
* @param url 下载链接
|
||||
* @param params 参数
|
||||
*/
|
||||
export const downloadFile = (url: string, params?: Record<string, any>) => {
|
||||
export const downloadFile = (url: string, params?: Record<string, any>) => {
|
||||
const formElement = document.createElement('form');
|
||||
formElement.style.display = 'display:none;';
|
||||
formElement.method = 'GET';
|
||||
|
@ -91,29 +91,29 @@ export const randomString = (length?: number) => {
|
|||
* @returns
|
||||
*/
|
||||
export const timestampFormat = (time: number) => {
|
||||
let hour = 0;
|
||||
let minute = 0;
|
||||
let second = 0;
|
||||
const timeStr = 'hh小时mm分钟ss秒';
|
||||
|
||||
if (time) {
|
||||
if (time >= 60 * 60 * 1000) {
|
||||
hour = Math.trunc(time / (60 * 60 * 1000));
|
||||
}
|
||||
let hour = 0;
|
||||
let minute = 0;
|
||||
let second = 0;
|
||||
const timeStr = 'hh小时mm分钟ss秒';
|
||||
|
||||
if (time >= 60 * 1000) {
|
||||
minute = Math.trunc((time - hour * 60 * 60 * 1000) / (60 * 1000));
|
||||
}
|
||||
|
||||
second = Math.trunc(
|
||||
(time - hour * (60 * 60 * 1000) - minute * 60 * 1000) / 1000,
|
||||
);
|
||||
if (time) {
|
||||
if (time >= 60 * 60 * 1000) {
|
||||
hour = Math.trunc(time / (60 * 60 * 1000));
|
||||
}
|
||||
|
||||
return timeStr
|
||||
.replace('hh', hour.toString())
|
||||
.replace('mm', minute.toString())
|
||||
.replace('ss', second.toString());
|
||||
if (time >= 60 * 1000) {
|
||||
minute = Math.trunc((time - hour * 60 * 60 * 1000) / (60 * 1000));
|
||||
}
|
||||
|
||||
second = Math.trunc(
|
||||
(time - hour * (60 * 60 * 1000) - minute * 60 * 1000) / 1000,
|
||||
);
|
||||
}
|
||||
|
||||
return timeStr
|
||||
.replace('hh', hour.toString())
|
||||
.replace('mm', minute.toString())
|
||||
.replace('ss', second.toString());
|
||||
};
|
||||
|
||||
export const ArrayToTree = (list: any[]): any[] => {
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { queryNoPagingPost } from '@/api/device/product';
|
||||
import { downloadFile } from '@/utils/utils';
|
||||
import { downloadFileByUrl } from '@/utils/utils';
|
||||
import encodeQuery from '@/utils/encodeQuery';
|
||||
import { deviceExport } from '@/api/device/instance';
|
||||
|
||||
|
@ -83,13 +83,23 @@ watch(
|
|||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
const handleOk = () => {
|
||||
const handleOk = async () => {
|
||||
const params = encodeQuery(props.data);
|
||||
downloadFile(
|
||||
deviceExport(modelRef.product || '', modelRef.fileType),
|
||||
params,
|
||||
// downloadFile(
|
||||
// deviceExport(modelRef.product || '', modelRef.fileType),
|
||||
// params,
|
||||
// );
|
||||
const res: any = await deviceExport(
|
||||
modelRef.product || '',
|
||||
modelRef.fileType,
|
||||
params
|
||||
);
|
||||
emit('close');
|
||||
if (res) {
|
||||
const blob = new Blob([res], { type: modelRef.fileType });
|
||||
const url = URL.createObjectURL(blob);
|
||||
downloadFileByUrl(url, `设备实例`, modelRef.fileType);
|
||||
emit('close');
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
|
|
|
@ -3,16 +3,22 @@
|
|||
:maskClosable="false"
|
||||
width="800px"
|
||||
:visible="true"
|
||||
title="当前进度"
|
||||
@ok="handleCancel"
|
||||
@cancel="handleCancel"
|
||||
:title="type === 'active' ? '启用' : '同步'"
|
||||
:closable="false"
|
||||
>
|
||||
<div>
|
||||
<j-badge v-if="flag" status="processing" text="进行中" />
|
||||
<j-badge v-else status="success" text="已完成" />
|
||||
<div style="margin: 10px 0px 20px 0px">
|
||||
<div v-if="flag">
|
||||
<div>{{ type === 'active' ? '正在启用全部设备' : '正在同步设备状态' }}</div>
|
||||
<j-progress :percent="50" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>{{ type === 'active' ? '启用' : '同步' }}成功:{{ count }}条</p>
|
||||
<p v-if="type === 'active'">启用失败:{{ errCount }}条<j-tooltip title="实例信息页面中的配置项未完善"><AIcon type="QuestionCircleOutlined" /></j-tooltip></p>
|
||||
</div>
|
||||
</div>
|
||||
<p>总数量:{{ count }}</p>
|
||||
<a style="color: red">{{ errMessage }}</a>
|
||||
<template #footer>
|
||||
<j-button v-if="!flag" type="primary" @click="handleCancel">完成</j-button>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
|
@ -32,8 +38,8 @@ const props = defineProps({
|
|||
});
|
||||
// const eventSource = ref<Record<string, any>>({})
|
||||
const count = ref<number>(0);
|
||||
const flag = ref<boolean>(false);
|
||||
const errMessage = ref<string>('');
|
||||
const flag = ref<boolean>(true);
|
||||
const errCount = ref<number>(0);
|
||||
const isSource = ref<boolean>(false);
|
||||
const id = ref<string>('');
|
||||
const source = ref<Record<string, any>>({});
|
||||
|
@ -43,30 +49,27 @@ const handleCancel = () => {
|
|||
emit('save');
|
||||
};
|
||||
|
||||
// const handleOk = () => {
|
||||
// emit('close');
|
||||
// emit('save');
|
||||
// };
|
||||
|
||||
const getData = (api: string) => {
|
||||
flag.value = true;
|
||||
let dt = 0;
|
||||
const _source = new EventSourcePolyfill(api);
|
||||
source.value = _source;
|
||||
_source.onmessage = (e: any) => {
|
||||
const res = JSON.parse(e.data);
|
||||
// console.log(res)
|
||||
switch (props.type) {
|
||||
case 'active':
|
||||
if (res.success) {
|
||||
_source.close();
|
||||
dt += res.total;
|
||||
count.value = dt;
|
||||
} else {
|
||||
if (res.source) {
|
||||
const msg = `${res.source.name}: ${res.message}`;
|
||||
errMessage.value = msg;
|
||||
errCount.value = 1
|
||||
id.value = res.source.id;
|
||||
isSource.value = true;
|
||||
} else {
|
||||
errMessage.value = res.message;
|
||||
errCount.value = 1
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -74,22 +77,13 @@ const getData = (api: string) => {
|
|||
dt += res;
|
||||
count.value = dt;
|
||||
break;
|
||||
case 'import':
|
||||
if (res.success) {
|
||||
const temp = res.result.total;
|
||||
dt += temp;
|
||||
count.value = dt;
|
||||
} else {
|
||||
errMessage.value = res.message;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
_source.onerror = () => {
|
||||
flag.value = false;
|
||||
_source.close();
|
||||
flag.value = false;
|
||||
};
|
||||
_source.onopen = () => {};
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
>选择</j-button
|
||||
>设备接入网关,用以提供设备接入能力
|
||||
</span>
|
||||
<span v-else>暂无权限,请联系管理员</span>
|
||||
<span v-else>请联系管理员配置产品接入方式</span>
|
||||
</template>
|
||||
</j-empty>
|
||||
</div>
|
||||
|
@ -337,20 +337,39 @@
|
|||
<div class="card-item-content-text">
|
||||
{{ slotProps.channelInfo?.name }}
|
||||
</div>
|
||||
<div>
|
||||
{{
|
||||
slotProps.channelInfo?.addresses
|
||||
? slotProps.channelInfo
|
||||
?.addresses[0].address
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
<Ellipsis style="width: calc(100% - 20px)">
|
||||
<div>
|
||||
{{
|
||||
slotProps.channelInfo?.addresses
|
||||
? slotProps.channelInfo
|
||||
?.addresses[0].address
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
</Ellipsis>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">协议</div>
|
||||
<div>{{ slotProps.protocolDetail?.name }}</div>
|
||||
</j-col>
|
||||
</j-row>
|
||||
<j-row>
|
||||
<j-col :span="24">
|
||||
<Ellipsis style="width: calc(100% - 50px)"
|
||||
><div class="context-access">
|
||||
{{
|
||||
!!slotProps?.description
|
||||
? slotProps?.description
|
||||
: dataSource.find(
|
||||
(item) =>
|
||||
item?.id ===
|
||||
slotProps?.provider,
|
||||
)?.description
|
||||
}}
|
||||
</div></Ellipsis
|
||||
>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
|
@ -482,6 +501,7 @@ const query = reactive({
|
|||
return new Promise((res) => {
|
||||
getProviders().then((resp: any) => {
|
||||
listData.value = [];
|
||||
console.log(description.value);
|
||||
if (isNoCommunity) {
|
||||
listData.value = (resp?.result || []).map(
|
||||
(item: any) => ({
|
||||
|
@ -1056,7 +1076,7 @@ const add = () => {
|
|||
console.log(value);
|
||||
if (value.status === 200) {
|
||||
tableRef.value.reload();
|
||||
handleClick(value.result)
|
||||
handleClick(value.result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1101,4 +1121,11 @@ nextTick(() => {
|
|||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.context-access {
|
||||
margin-right: 10px;
|
||||
color: #666;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
@back="onBack"
|
||||
:tabActiveKey="productStore.tabActiveKey"
|
||||
@tabChange="onTabChange"
|
||||
showBack="true"
|
||||
>
|
||||
<template #title>
|
||||
<div>
|
||||
|
|
|
@ -432,6 +432,7 @@ const query = reactive({
|
|||
key: 'id',
|
||||
search: {
|
||||
type: 'string',
|
||||
defaultTermType: 'eq'
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -43,11 +43,9 @@ const type = ref<string>('xlsx');
|
|||
|
||||
const handleOk = () => {
|
||||
_export(type.value, props.data).then((res: any) => {
|
||||
console.log(res)
|
||||
if (res) {
|
||||
const blob = new Blob([res], { type: type.value });
|
||||
const blob = new Blob([res.data], { type: type.value });
|
||||
const url = URL.createObjectURL(blob);
|
||||
console.log(url, 123);
|
||||
downloadFileByUrl(
|
||||
url,
|
||||
`物联卡管理-${moment(new Date()).format(
|
||||
|
|
Loading…
Reference in New Issue