Merge branch 'dev' into dev-hub
This commit is contained in:
commit
140569c331
|
@ -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);
|
||||
|
||||
/**
|
||||
* 下载模板
|
||||
|
|
|
@ -18,6 +18,8 @@ export const getDeviceOrProductList_api = (data: object) => server.post(`/device
|
|||
export const getDeviceList_api = (data: object) => server.post(`/device/instance/_query`, data);
|
||||
// 根据产品的id获取产品的权限
|
||||
export const getPermission_api = (type: 'device' | 'product', ids: object, id: string) => server.post(`/assets/bindings/${type}/org/${id}/_query`, ids);
|
||||
// 获取绑定的权限
|
||||
export const getBindingsPermission = (type: 'device' | 'product', ids: string[]) => server.post(`/assets/bindings/${type}`, ids);
|
||||
// 获取产品的权限字典
|
||||
export const getPermissionDict_api = () => server.get(`/assets/bindings/product/permissions`);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<j-input
|
||||
v-else-if="typeMap.get(itemType) === 'file'"
|
||||
v-model:value="myValue"
|
||||
placeholder="请输入图片链接"
|
||||
placeholder="请输入链接"
|
||||
allowClear
|
||||
@change='inputChange'
|
||||
>
|
||||
|
|
|
@ -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[] => {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
placeholder="请选择指令类型"
|
||||
v-model:value="modelRef.messageType"
|
||||
show-search
|
||||
@change="onTypeChange"
|
||||
>
|
||||
<j-select-option value="READ_PROPERTY"
|
||||
>读取属性</j-select-option
|
||||
|
@ -108,7 +109,7 @@
|
|||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24" v-if="modelRef.messageType === 'INVOKE_FUNCTION'">
|
||||
<j-col :span="24" v-if="modelRef.messageType === 'INVOKE_FUNCTION'" class="inputs">
|
||||
<j-form-item
|
||||
:name="['message', 'functionId']"
|
||||
label="功能"
|
||||
|
@ -137,7 +138,8 @@
|
|||
:span="24"
|
||||
v-if="
|
||||
modelRef.messageType === 'INVOKE_FUNCTION' &&
|
||||
modelRef.message.functionId
|
||||
modelRef.message?.functionId &&
|
||||
modelRef.message?.inputs?.length
|
||||
"
|
||||
class="inputs"
|
||||
>
|
||||
|
@ -184,6 +186,8 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const editRef = ref();
|
||||
|
||||
const modelRef = reactive({
|
||||
|
@ -192,7 +196,7 @@ const modelRef = reactive({
|
|||
properties: undefined,
|
||||
functionId: undefined,
|
||||
inputs: [],
|
||||
value: undefined
|
||||
value: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -207,12 +211,21 @@ const onPropertyChange = (val: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
const onTypeChange = () => {
|
||||
modelRef.message = {
|
||||
properties: undefined,
|
||||
functionId: undefined,
|
||||
inputs: [],
|
||||
value: undefined,
|
||||
};
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
Object.assign(modelRef, newVal);
|
||||
if(newVal?.message?.properties){
|
||||
if (newVal?.message?.properties) {
|
||||
onPropertyChange(newVal?.message?.properties);
|
||||
}
|
||||
}
|
||||
|
@ -244,10 +257,13 @@ const saveBtn = () =>
|
|||
formRef.value
|
||||
.validate()
|
||||
.then(async (_data: any) => {
|
||||
await editRef.value.onSave().catch(() => {
|
||||
resolve(false)
|
||||
})
|
||||
resolve(_data)
|
||||
if (modelRef.message.inputs?.length) {
|
||||
await editRef.value?.onSave().catch(() => {
|
||||
resolve(false);
|
||||
});
|
||||
}
|
||||
emit('update:modelValue', _data)
|
||||
resolve(_data);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
resolve(err);
|
||||
|
|
|
@ -1,20 +1,48 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<div class="diagnose">
|
||||
<div class="diagnose-header" :style="{background: headerColorMap.get(topState)}">
|
||||
<div
|
||||
class="diagnose-header"
|
||||
:style="{ background: headerColorMap.get(topState) }"
|
||||
>
|
||||
<div class="diagnose-top">
|
||||
<div class="diagnose-img">
|
||||
<div v-if="topState === 'loading'" style="width: 100%; height: 100%; position: relative">
|
||||
<img :src="headerImgMap.get(topState)" style="height: 100%; position: absolute; z-index: 2" />
|
||||
<img :src="getImage('/diagnose/loading-1.png')" style="height: 100%" />
|
||||
<div
|
||||
v-if="topState === 'loading'"
|
||||
style="
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
"
|
||||
>
|
||||
<img
|
||||
:src="headerImgMap.get(topState)"
|
||||
style="
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
"
|
||||
/>
|
||||
<img
|
||||
:src="getImage('/diagnose/loading-1.png')"
|
||||
style="height: 100%"
|
||||
/>
|
||||
</div>
|
||||
<img v-else :src="headerImgMap.get(topState)" style="height: 100%" />
|
||||
<img
|
||||
v-else
|
||||
:src="headerImgMap.get(topState)"
|
||||
style="height: 100%"
|
||||
/>
|
||||
</div>
|
||||
<div class="diagnose-text">
|
||||
<div class="diagnose-title">{{headerTitleMap.get(topState)}}</div>
|
||||
<div class="diagnose-title">
|
||||
{{ headerTitleMap.get(topState) }}
|
||||
</div>
|
||||
<div class="diagnose-desc">
|
||||
<template v-if="topState !== 'loading'">{{headerDescMap.get(topState)}}</template>
|
||||
<template v-else>已诊断{{count}}个</template>
|
||||
<template v-if="topState !== 'loading'">{{
|
||||
headerDescMap.get(topState)
|
||||
}}</template>
|
||||
<template v-else>已诊断{{ count }}个</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -28,33 +56,60 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="diagnose-radio">
|
||||
<div class="diagnose-radio-item" :class="item.key === 'message' && topState !== 'success' ? 'disabled' : ''" v-for="item in tabList" :key="item.key" :style="activeKey === item.key ? {...activeStyle} : {}" @click="onTabChange(item.key)">
|
||||
{{item.text}}
|
||||
<div
|
||||
class="diagnose-radio-item"
|
||||
:class="
|
||||
item.key === 'message' && topState !== 'success'
|
||||
? 'disabled'
|
||||
: ''
|
||||
"
|
||||
v-for="item in tabList"
|
||||
:key="item.key"
|
||||
:style="
|
||||
activeKey === item.key ? { ...activeStyle } : {}
|
||||
"
|
||||
@click="onTabChange(item.key)"
|
||||
>
|
||||
{{ item.text }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Message v-show="activeKey === 'message'" />
|
||||
<Status v-show="activeKey !== 'message'" :providerType="providerType" @countChange="countChange" @percentChange="percentChange" @stateChange="stateChange" />
|
||||
<template v-if="!first">
|
||||
<Message v-show="activeKey === 'message'" />
|
||||
</template>
|
||||
<Status
|
||||
v-show="activeKey !== 'message'"
|
||||
:providerType="providerType"
|
||||
@countChange="countChange"
|
||||
@percentChange="percentChange"
|
||||
@stateChange="stateChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { headerImgMap, headerColorMap, headerTitleMap, headerDescMap, progressMap } from './util'
|
||||
import {
|
||||
headerImgMap,
|
||||
headerColorMap,
|
||||
headerTitleMap,
|
||||
headerDescMap,
|
||||
progressMap,
|
||||
} from './util';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import Status from './Status/index'
|
||||
import Message from './Message/index.vue'
|
||||
import Status from './Status/index';
|
||||
import Message from './Message/index.vue';
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
|
||||
type TypeProps = 'network' | 'child-device' | 'media' | 'cloud' | 'channel'
|
||||
type TypeProps = 'network' | 'child-device' | 'media' | 'cloud' | 'channel';
|
||||
|
||||
const instanceStore = useInstanceStore()
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
const tabList = [
|
||||
{ key: 'status', text: '连接状态' },
|
||||
{ key: 'message', text: '消息通信' },
|
||||
{ key: 'status', text: '连接状态' },
|
||||
{ key: 'message', text: '消息通信' },
|
||||
];
|
||||
|
||||
const activeStyle = {
|
||||
|
@ -64,139 +119,141 @@ const activeStyle = {
|
|||
color: '#000000BF',
|
||||
};
|
||||
|
||||
const topState = ref<'loading' | 'success' | 'error'>('loading')
|
||||
const count = ref<number>(0)
|
||||
const percent = ref<number>(0)
|
||||
const activeKey = ref<'status' | 'message'>('status')
|
||||
const providerType = ref()
|
||||
const topState = ref<'loading' | 'success' | 'error'>('loading');
|
||||
const count = ref<number>(0);
|
||||
const percent = ref<number>(0);
|
||||
const activeKey = ref<'status' | 'message'>('status');
|
||||
const providerType = ref();
|
||||
|
||||
provide('topState', topState)
|
||||
const first = ref<boolean>(true);
|
||||
|
||||
provide('topState', topState);
|
||||
|
||||
const onTabChange = (key: 'status' | 'message') => {
|
||||
if(topState.value === 'success'){
|
||||
activeKey.value = key
|
||||
if (topState.value === 'success') {
|
||||
activeKey.value = key;
|
||||
}
|
||||
}
|
||||
first.value = false
|
||||
};
|
||||
|
||||
const percentChange = (num: number) => {
|
||||
if(num === 0){
|
||||
percent.value = 0
|
||||
} else if( percent.value < 100 && !num) {
|
||||
percent.value += 20
|
||||
if (num === 0) {
|
||||
percent.value = 0;
|
||||
} else if (percent.value < 100 && !num) {
|
||||
percent.value += 20;
|
||||
} else {
|
||||
percent.value = num
|
||||
percent.value = num;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const stateChange = (_type: 'loading' | 'success' | 'error') => {
|
||||
topState.value = _type
|
||||
}
|
||||
topState.value = _type;
|
||||
};
|
||||
|
||||
const countChange = (num: number) => {
|
||||
count.value = num
|
||||
}
|
||||
count.value = num;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const provider = instanceStore.current?.accessProvider;
|
||||
if (provider === 'fixed-media' || provider === 'gb28181-2016') {
|
||||
providerType.value = 'media'
|
||||
providerType.value = 'media';
|
||||
} else if (provider === 'OneNet' || provider === 'Ctwing') {
|
||||
providerType.value = 'cloud'
|
||||
providerType.value = 'cloud';
|
||||
} else if (provider === 'modbus-tcp' || provider === 'opc-ua') {
|
||||
providerType.value = 'channel'
|
||||
providerType.value = 'channel';
|
||||
} else if (provider === 'child-device') {
|
||||
providerType.value = 'child-device'
|
||||
providerType.value = 'child-device';
|
||||
} else {
|
||||
providerType.value = 'network'
|
||||
providerType.value = 'network';
|
||||
}
|
||||
topState.value = 'loading';
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.diagnose {
|
||||
.diagnose-header {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px 25px;
|
||||
.diagnose-header {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px 25px;
|
||||
|
||||
.diagnose-top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
.diagnose-top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.diagnose-img {
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.diagnose-img {
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.diagnose-text {
|
||||
.diagnose-title {
|
||||
color: #000c;
|
||||
font-weight: 700;
|
||||
font-size: 25px;
|
||||
.diagnose-text {
|
||||
.diagnose-title {
|
||||
color: #000c;
|
||||
font-weight: 700;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.diagnose-desc {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.diagnose-desc {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
font-size: 14px;
|
||||
.diagnose-progress {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.diagnose-progress {
|
||||
width: 100%;
|
||||
}
|
||||
.diagnose-radio {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
|
||||
.diagnose-radio {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
|
||||
.diagnose-radio-item {
|
||||
width: 150px;
|
||||
height: 35px;
|
||||
margin-right: 8px;
|
||||
color: #00000073;
|
||||
line-height: 35px;
|
||||
text-align: center;
|
||||
background: #f2f2f2;
|
||||
border-radius: 2px 2px 0 0;
|
||||
cursor: pointer;
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
.diagnose-radio-item {
|
||||
width: 150px;
|
||||
height: 35px;
|
||||
margin-right: 8px;
|
||||
color: #00000073;
|
||||
line-height: 35px;
|
||||
text-align: center;
|
||||
background: #f2f2f2;
|
||||
border-radius: 2px 2px 0 0;
|
||||
cursor: pointer;
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.diagnose-loading {
|
||||
animation: diagnose-loading 2s linear infinite;
|
||||
animation: diagnose-loading 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes diagnose-loading {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
25% {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
75% {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -84,17 +84,55 @@
|
|||
<j-badge v-else status="error" text="未绑定" />
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<j-tooltip title="解绑">
|
||||
<j-popconfirm
|
||||
title="确认解绑"
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
:disabled="!record.id"
|
||||
@confirm="unbind(record.id)"
|
||||
:popConfirm="{
|
||||
title: '确认解绑?',
|
||||
onConfirm: unbind(record.id),
|
||||
}"
|
||||
style="padding: 0 5px"
|
||||
hasPermission="device/Instance:update"
|
||||
:tooltip="{
|
||||
title: '解绑',
|
||||
}"
|
||||
>
|
||||
<j-button type="link" :disabled="!record.id"
|
||||
><AIcon type="icon-jiebang"
|
||||
/></j-button>
|
||||
</j-popconfirm>
|
||||
</j-tooltip>
|
||||
<AIcon type="icon-jiebang" />
|
||||
</PermissionButton>
|
||||
<template v-if="record.id">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
:disabled="!record.id"
|
||||
style="padding: 0 5px"
|
||||
:popConfirm="{
|
||||
title:
|
||||
record.state.value === 'enabled'
|
||||
? '确认禁用?'
|
||||
: '确认启用?',
|
||||
onConfirm: onAction(record),
|
||||
}"
|
||||
hasPermission="device/Instance:update"
|
||||
:tooltip="{
|
||||
title:
|
||||
record.state.value === 'enabled'
|
||||
? '禁用'
|
||||
: '启用',
|
||||
}"
|
||||
>
|
||||
<AIcon
|
||||
v-if="
|
||||
record.state.value === 'enabled'
|
||||
"
|
||||
type="StopOutlined"
|
||||
/>
|
||||
<AIcon
|
||||
v-else
|
||||
type="PlayCircleOutlined"
|
||||
/>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</template>
|
||||
</j-table>
|
||||
|
@ -110,7 +148,7 @@
|
|||
/>
|
||||
</j-spin>
|
||||
<j-card v-else>
|
||||
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
||||
<JEmpty description="暂无数据,请配置物模型" style="margin: 10% 0" />
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
|
@ -171,7 +209,7 @@ const filterOption = (input: string, option: any) => {
|
|||
const instanceStore = useInstanceStore();
|
||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}');
|
||||
const loading = ref<boolean>(false);
|
||||
const channelList = ref([]);
|
||||
const channelList = ref<any[]>([]);
|
||||
|
||||
const modelRef = reactive({
|
||||
dataSource: [],
|
||||
|
@ -204,13 +242,16 @@ const handleSearch = async () => {
|
|||
}));
|
||||
console.log(metadata);
|
||||
if (_metadata && _metadata.length) {
|
||||
const resp: any = await getEdgeMap(instanceStore.current?.parentId || '', {
|
||||
deviceId: instanceStore.current.id,
|
||||
query: {},
|
||||
}).catch(() => {
|
||||
const resp: any = await getEdgeMap(
|
||||
instanceStore.current?.parentId || '',
|
||||
{
|
||||
deviceId: instanceStore.current.id,
|
||||
query: {},
|
||||
},
|
||||
).catch(() => {
|
||||
modelRef.dataSource = _metadata;
|
||||
loading.value = false;
|
||||
})
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
const array = resp.result?.[0].reduce((x: any, y: any) => {
|
||||
const metadataId = _metadata.find(
|
||||
|
@ -231,10 +272,13 @@ const handleSearch = async () => {
|
|||
|
||||
const unbind = async (id: string) => {
|
||||
if (id) {
|
||||
const resp = await removeEdgeMap(instanceStore.current?.parentId || '', {
|
||||
deviceId: instanceStore.current.id,
|
||||
idList: [id],
|
||||
});
|
||||
const resp = await removeEdgeMap(
|
||||
instanceStore.current?.parentId || '',
|
||||
{
|
||||
deviceId: instanceStore.current.id,
|
||||
idList: [id],
|
||||
},
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
handleSearch();
|
||||
|
@ -264,7 +308,10 @@ const onSave = () => {
|
|||
provider: (arr[0] as any)?.provider,
|
||||
requestList: arr,
|
||||
};
|
||||
const resp = await saveEdgeMap(instanceStore.current.parentId || '', submitData);
|
||||
const resp = await saveEdgeMap(
|
||||
instanceStore.current.parentId || '',
|
||||
submitData,
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
handleSearch();
|
||||
|
@ -275,6 +322,30 @@ const onSave = () => {
|
|||
console.log('error', err);
|
||||
});
|
||||
};
|
||||
|
||||
const onAction = async (record: any) => {
|
||||
const value = await formRef.value.validate();
|
||||
const array = value.filter((item: any) => item.channelId);
|
||||
const findArray = array.find((item: any) => item.id === record?.id);
|
||||
const arr = {
|
||||
...findArray,
|
||||
state: record?.state.value === 'enabled' ? 'disabled' : 'enabled',
|
||||
};
|
||||
const filterArray = array.filter((item: any) => item.id !== record?.id);
|
||||
const submitData = {
|
||||
deviceId: instanceStore.current.id,
|
||||
provider: array[0]?.provider,
|
||||
requestList: [...filterArray, arr],
|
||||
};
|
||||
const resp = await saveEdgeMap(
|
||||
instanceStore.current.parentId || '',
|
||||
submitData,
|
||||
);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
handleSearch();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
</j-space>
|
||||
</div>
|
||||
<j-tabs v-model="activeKey" tab-position="left">
|
||||
<j-tab-pane
|
||||
v-for="func in newFunctions"
|
||||
:key="func.id"
|
||||
:tab="func.name"
|
||||
>
|
||||
<j-tab-pane v-for="func in newFunctions" :key="func.id">
|
||||
<template #tab>
|
||||
<Ellipsis style="width: 100px; text-align: left">
|
||||
{{ func.name }}
|
||||
</Ellipsis>
|
||||
</template>
|
||||
<j-row :gutter="30">
|
||||
<j-col :span="15">
|
||||
<j-form :ref="`${func.id}Ref`" :model="func">
|
||||
|
@ -49,7 +50,7 @@
|
|||
:name="['table', index, 'value']"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '',
|
||||
message: '该字段为必填字段',
|
||||
}"
|
||||
has-feedback
|
||||
>
|
||||
|
@ -106,7 +107,7 @@
|
|||
</j-col>
|
||||
<j-col :span="9">
|
||||
<h6>执行结果:</h6>
|
||||
<span class="execute-result">
|
||||
<span :ref="`result${func.id}Ref`" class="execute-result">
|
||||
{{ func.executeResult }}
|
||||
</span>
|
||||
</j-col>
|
||||
|
|
|
@ -50,10 +50,14 @@
|
|||
:key="item.property"
|
||||
>
|
||||
<template #label>
|
||||
<span style="margin-right: 5px">{{ item.name }}</span>
|
||||
<j-tooltip v-if="item.description" :title="item.description"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></j-tooltip>
|
||||
<Ellipsis style="margin-right: 5px;">
|
||||
{{ item.name }}
|
||||
<j-tooltip
|
||||
v-if="item.description"
|
||||
:title="item.description"
|
||||
><AIcon type="QuestionCircleOutlined"
|
||||
/></j-tooltip>
|
||||
</Ellipsis>
|
||||
</template>
|
||||
<span
|
||||
v-if="
|
||||
|
@ -64,10 +68,10 @@
|
|||
>******</span
|
||||
>
|
||||
<span v-else>
|
||||
<span>{{
|
||||
<Ellipsis>{{
|
||||
instanceStore.current?.configuration?.[item.property] ||
|
||||
''
|
||||
}}</span>
|
||||
}}</Ellipsis>
|
||||
<j-tooltip
|
||||
v-if="isExit(item.property)"
|
||||
:title="`有效值:${
|
||||
|
|
|
@ -18,13 +18,18 @@
|
|||
:span="1"
|
||||
v-for="item in dataSource"
|
||||
:key="item.objectId"
|
||||
:label="item.relationName"
|
||||
>{{
|
||||
item?.related
|
||||
? (item?.related || []).map((i) => i.name).join(',')
|
||||
: ''
|
||||
}}</j-descriptions-item
|
||||
>
|
||||
<template #label>
|
||||
<Ellipsis>{{ item.relationName }}</Ellipsis>
|
||||
</template>
|
||||
<Ellipsis>
|
||||
{{
|
||||
item?.related
|
||||
? (item?.related || []).map((i) => i.name).join(',')
|
||||
: ''
|
||||
}}
|
||||
</Ellipsis>
|
||||
</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
<Save v-if="visible" @save="saveBtn" @close="visible = false" />
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<template #bodyCell="{ column, text, record }">
|
||||
<div style="width: 280px">
|
||||
<template v-if="['key', 'name'].includes(column.dataIndex)">
|
||||
<span>{{ text }}</span>
|
||||
<Ellipsis>{{ text }}</Ellipsis>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ValueItem
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
:span="1"
|
||||
v-for="item in dataSource"
|
||||
:key="item.key"
|
||||
:label="`${item.name}(${item.key})`"
|
||||
>{{ item?.value }}</j-descriptions-item
|
||||
>
|
||||
<template #label>
|
||||
<Ellipsis>{{ `${item.name}(${item.key})` }}</Ellipsis>
|
||||
</template>
|
||||
<Ellipsis>{{ item?.value }}</Ellipsis>
|
||||
</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
<Save v-if="visible" @close="visible = false" @save="saveBtn" />
|
||||
</div>
|
||||
|
|
|
@ -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 = () => {};
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<div style="display: flex">
|
||||
<h3>配置信息</h3>
|
||||
<div style="margin: 0 0px 0 15px; color: #1d39c4">
|
||||
<AIcon type="EditOutlined"/>
|
||||
<AIcon type="EditOutlined" @click="editConfig"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -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>
|
||||
|
@ -399,6 +418,7 @@ import { marked } from 'marked';
|
|||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import _ from 'lodash';
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const menuStore = useMenuStore();
|
||||
const permissionStore = usePermissionStore();
|
||||
|
@ -481,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) => ({
|
||||
|
@ -959,7 +980,11 @@ const getData = async (accessId?: string) => {
|
|||
if (metadata.value?.properties) {
|
||||
metadata.value?.properties.forEach((item) => {
|
||||
if (
|
||||
item.name === '流传输模式' && (!productStore.current?.configuration || !productStore.current?.configuration.hasOwnProperty(item.name))
|
||||
item.name === '流传输模式' &&
|
||||
(!productStore.current?.configuration ||
|
||||
!productStore.current?.configuration.hasOwnProperty(
|
||||
item.name,
|
||||
))
|
||||
) {
|
||||
formData.data[item.name] =
|
||||
item.type.expands?.defaultValue;
|
||||
|
@ -1046,7 +1071,14 @@ const getDetailInfo = () => {};
|
|||
const add = () => {
|
||||
const url = menuStore.hasMenu('link/AccessConfig/Detail');
|
||||
if (url) {
|
||||
window.open(`${origin}/#${url}`);
|
||||
const tab: any = window.open(`${origin}/#${url}?view=false`);
|
||||
tab.onTabSaveSuccess = (value: any) => {
|
||||
console.log(value);
|
||||
if (value.status === 200) {
|
||||
tableRef.value.reload();
|
||||
handleClick(value.result);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
/**
|
||||
|
@ -1089,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>
|
||||
|
@ -50,9 +51,7 @@
|
|||
</div>
|
||||
<div style="padding-top: 10px">
|
||||
<j-descriptions size="small" :column="4">
|
||||
<j-descriptions-item
|
||||
label="设备数量"
|
||||
style="cursor: pointer"
|
||||
<j-descriptions-item label="设备数量"
|
||||
><span @click="jumpDevice">{{
|
||||
productStore.current?.count
|
||||
? productStore.current?.count
|
||||
|
@ -116,8 +115,8 @@ import { message } from 'jetlinks-ui-components';
|
|||
import { getImage } from '@/utils/comm';
|
||||
import encodeQuery from '@/utils/encodeQuery';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const route = useRoute();
|
||||
const checked = ref<boolean>(true);
|
||||
const productStore = useProductStore();
|
||||
|
@ -141,7 +140,7 @@ const list = ref([
|
|||
{
|
||||
key: 'Metadata',
|
||||
tab: '物模型',
|
||||
class:'objectModel'
|
||||
class: 'objectModel',
|
||||
},
|
||||
{
|
||||
key: 'Device',
|
||||
|
@ -163,12 +162,16 @@ watch(
|
|||
productStore.reSet();
|
||||
productStore.tabActiveKey = 'Info';
|
||||
productStore.refresh(newId as string);
|
||||
console.log(productStore);
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => productStore.current,
|
||||
() => {
|
||||
getProtocol();
|
||||
},
|
||||
);
|
||||
const onBack = () => {};
|
||||
|
||||
const onTabChange = (e: string) => {
|
||||
|
@ -228,10 +231,40 @@ const getProtocol = async () => {
|
|||
(item: any) => item.id === 'transparentCodec',
|
||||
);
|
||||
if (paring) {
|
||||
list.value.push({
|
||||
key: 'DataAnalysis',
|
||||
tab: '数据解析',
|
||||
});
|
||||
list.value = [
|
||||
{
|
||||
key: 'Info',
|
||||
tab: '配置信息',
|
||||
},
|
||||
{
|
||||
key: 'Metadata',
|
||||
tab: '物模型',
|
||||
class: 'objectModel',
|
||||
},
|
||||
{
|
||||
key: 'Device',
|
||||
tab: '设备接入',
|
||||
},
|
||||
{
|
||||
key: 'DataAnalysis',
|
||||
tab: '数据解析',
|
||||
},
|
||||
];
|
||||
}else{
|
||||
list.value = [
|
||||
{
|
||||
key: 'Info',
|
||||
tab: '配置信息',
|
||||
},
|
||||
{
|
||||
key: 'Metadata',
|
||||
tab: '物模型',
|
||||
class: 'objectModel',
|
||||
},
|
||||
{
|
||||
key: 'Device',
|
||||
tab: '设备接入',
|
||||
},]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +289,6 @@ const jumpDevice = () => {
|
|||
);
|
||||
};
|
||||
onMounted(() => {
|
||||
getProtocol();
|
||||
if (history.state?.params?.tab) {
|
||||
productStore.tabActiveKey = history.state?.params?.tab;
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@
|
|||
<j-col flex="auto">
|
||||
<j-form-item name="id">
|
||||
<template #label>
|
||||
<span>ID</span>
|
||||
<j-tooltip
|
||||
title="若不填写,系统将自动生成唯一ID"
|
||||
>
|
||||
<span>ID</span>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
|
@ -77,56 +77,21 @@
|
|||
</j-tree-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="设备类型" name="deviceType">
|
||||
<j-radio-group
|
||||
v-model:value="form.deviceType"
|
||||
style="width: 100%"
|
||||
@change="changeValue"
|
||||
<j-card-select
|
||||
:value="form.deviceType"
|
||||
:options="deviceList"
|
||||
@change="changeDeviceType"
|
||||
>
|
||||
<j-row :span="24" :gutter="10">
|
||||
<j-col
|
||||
:span="8"
|
||||
v-for="item in deviceList"
|
||||
:key="item.value"
|
||||
>
|
||||
<div class="button-style">
|
||||
<j-radio-button
|
||||
:value="item.value"
|
||||
style="height: 100%; width: 100%"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<div class="card-content">
|
||||
<j-row :gutter="20">
|
||||
<j-col :span="10">
|
||||
<!-- 图片 -->
|
||||
<div class="img-style">
|
||||
<img :src="item.logo" />
|
||||
</div>
|
||||
</j-col>
|
||||
<j-col :span="14">
|
||||
<span class="card-style">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
</j-col>
|
||||
</j-row>
|
||||
|
||||
<!-- 勾选 -->
|
||||
<div
|
||||
v-if="
|
||||
form.deviceType ===
|
||||
item.value
|
||||
"
|
||||
class="checked-icon"
|
||||
>
|
||||
<div>
|
||||
<CheckOutlined />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</j-radio-button>
|
||||
</div>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</j-radio-group>
|
||||
<template #title="item">
|
||||
<span>{{ item.title }}</span>
|
||||
<a-tooltip :title="item"
|
||||
><AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</j-card-select>
|
||||
</j-form-item>
|
||||
<j-form-item label="说明" name="description">
|
||||
<j-textarea
|
||||
|
@ -195,17 +160,20 @@ const deviceList = ref([
|
|||
{
|
||||
label: '直连设备',
|
||||
value: 'device',
|
||||
logo: getImage('/device-type-1.png'),
|
||||
iconUrl: getImage('/device-type-1.png'),
|
||||
tooltip: '直连物联网平台的设备',
|
||||
},
|
||||
{
|
||||
label: '网关子设备',
|
||||
value: 'childrenDevice',
|
||||
logo: getImage('/device-type-2.png'),
|
||||
iconUrl: getImage('/device-type-2.png'),
|
||||
tooltip: '能挂载子设备与平台进行通信的设备',
|
||||
},
|
||||
{
|
||||
label: '网关设备',
|
||||
value: 'gateway',
|
||||
logo: getImage('/device/device-type-3.png'),
|
||||
iconUrl: getImage('/device/device-type-3.png'),
|
||||
tooltip: '作为网关的子设备,有网关代理连接到物联网平台',
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -356,6 +324,12 @@ const submitData = () => {
|
|||
}
|
||||
} else if (props.isAdd === 2) {
|
||||
// 编辑
|
||||
form.classifiedId
|
||||
? form.classifiedId
|
||||
: (form.classifiedId = ''); // 产品分类不选传空字符串
|
||||
form.classifiedName
|
||||
? form.classifiedName
|
||||
: (form.classifiedName = '');
|
||||
const res = await editProduct(form);
|
||||
if (res.status === 200) {
|
||||
message.success('保存成功!');
|
||||
|
@ -372,6 +346,10 @@ const submitData = () => {
|
|||
* 初始化
|
||||
*/
|
||||
queryProductTree();
|
||||
|
||||
const changeDeviceType = (value: Array<string>) => {
|
||||
form.deviceType = value[0];
|
||||
};
|
||||
defineExpose({
|
||||
show: show,
|
||||
});
|
||||
|
|
|
@ -432,6 +432,7 @@ const query = reactive({
|
|||
key: 'id',
|
||||
search: {
|
||||
type: 'string',
|
||||
defaultTermType: 'eq'
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -108,6 +108,9 @@ watchEffect(() => {
|
|||
_value.value = props.value || {
|
||||
expands: {}
|
||||
}
|
||||
if (props.onlyObject) {
|
||||
_value.value.type = 'object'
|
||||
}
|
||||
})
|
||||
|
||||
watch(_value,
|
||||
|
@ -116,14 +119,14 @@ watch(_value,
|
|||
},
|
||||
{ deep: true, immediate: true })
|
||||
|
||||
onMounted(() => {
|
||||
if (props.onlyObject) {
|
||||
_value.value = {
|
||||
type: 'object',
|
||||
expands: {}
|
||||
}
|
||||
}
|
||||
})
|
||||
// onMounted(() => {
|
||||
// if (props.onlyObject) {
|
||||
// _value.value = props.value || {
|
||||
// type: 'object',
|
||||
// expands: {}
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
const unit = reactive({
|
||||
unitOptions: [] as DefaultOptionType[],
|
||||
|
|
|
@ -206,14 +206,14 @@ const handleImport = async () => {
|
|||
loading.value = true
|
||||
const { id } = route.params || {}
|
||||
if (data.metadata === 'alink') {
|
||||
const res = await convertMetadata('from', 'alink', data.import)
|
||||
const res = await convertMetadata('from', 'alink', data.import).catch(err => err)
|
||||
if (res.status === 200) {
|
||||
const metadata = operateLimits(res.result)
|
||||
if (props?.type === 'device') {
|
||||
await saveMetadata(id as string, metadata)
|
||||
await saveMetadata(id as string, metadata).catch(err => err)
|
||||
// instanceStore.setCurrent(JSON.parse(metadata || '{}'))
|
||||
} else {
|
||||
await modify(id as string, { metadata: metadata })
|
||||
await modify(id as string, { metadata: metadata }).catch(err => err)
|
||||
// productStore.setCurrent(JSON.parse(metadata || '{}'))
|
||||
}
|
||||
loading.value = false
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -521,6 +521,13 @@ const saveData = () => {
|
|||
if (resp.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
history.back();
|
||||
if ((window as any).onTabSaveSuccess) {
|
||||
console.log(123);
|
||||
if (resp.result?.id) {
|
||||
(window as any).onTabSaveSuccess(resp);
|
||||
setTimeout(() => window.close(), 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
|
|
|
@ -140,7 +140,11 @@ const handleRecord = async () => {
|
|||
* 刷新
|
||||
*/
|
||||
const handleRefresh = () => {
|
||||
player.value.play();
|
||||
// player.value.play();
|
||||
url.value = '';
|
||||
setTimeout(() => {
|
||||
mediaStart();
|
||||
}, 500);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -303,7 +303,6 @@ const queryServiceRecords = async (date: Dayjs) => {
|
|||
const cloudView = (startTime: number, endTime: number) => {
|
||||
type.value = 'cloud';
|
||||
cloudTime.value = { startTime, endTime };
|
||||
queryServiceRecords(time.value!);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
:gridColumn="2"
|
||||
:gridColumn="4"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<PermissionButton
|
||||
|
@ -30,11 +30,9 @@
|
|||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:showStatus="true"
|
||||
:status="
|
||||
slotProps.state.value === 'online' ? 'success' : 'error'
|
||||
"
|
||||
:status="slotProps.state.value"
|
||||
:statusText="slotProps.state.text"
|
||||
:statusNames="{ success: 'success', error: 'error' }"
|
||||
:statusNames="{ online: 'processing', offline: 'error' }"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
|
|
|
@ -422,6 +422,7 @@ const formData = ref({
|
|||
userId: '',
|
||||
thirdPartyUserId: '',
|
||||
thirdPartyUserName: '',
|
||||
bindId: '',
|
||||
});
|
||||
const formRules = ref({
|
||||
userId: [{ required: true, message: '请选择用户', trigger: 'change' }],
|
||||
|
@ -463,6 +464,7 @@ const handleBindSubmit = () => {
|
|||
providerName: formData.value.thirdPartyUserName,
|
||||
thirdPartyUserId: formData.value.thirdPartyUserId,
|
||||
userId: formData.value.userId,
|
||||
id: formData.value.bindId,
|
||||
};
|
||||
confirmLoading.value = true;
|
||||
if (props.data.type === 'dingTalk') {
|
||||
|
|
|
@ -139,6 +139,7 @@ import {
|
|||
getDeviceList_api,
|
||||
getPermission_api,
|
||||
bindDeviceOrProductList_api,
|
||||
getBindingsPermission,
|
||||
} from '@/api/system/department';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { dictType } from '../typing';
|
||||
|
@ -295,22 +296,17 @@ const table: any = {
|
|||
const { pageIndex, pageSize, total, data } =
|
||||
resp.result as resultType;
|
||||
const ids = data.map((item) => item.id);
|
||||
getPermission_api(props.assetType, ids, parentId).then(
|
||||
// fix: bug#10706
|
||||
getBindingsPermission(props.assetType, ids).then(
|
||||
(perResp: any) => {
|
||||
const permissionObj = {};
|
||||
perResp.result.forEach((item: any) => {
|
||||
permissionObj[item.assetId] = props.allPermission
|
||||
.filter((permission) =>
|
||||
item.allPermissions.includes(permission.id),
|
||||
)
|
||||
.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
data.forEach((item) => {
|
||||
item.permissionList = perResp.result
|
||||
.find((f: any) => f.assetId === item.id)
|
||||
.permissionInfoList?.map((m: any) => ({
|
||||
label: m.name,
|
||||
value: m.id,
|
||||
disabled: true,
|
||||
}));
|
||||
});
|
||||
data.forEach((item) => {
|
||||
item.permissionList = permissionObj[item.id];
|
||||
item.selectPermissions = ['read'];
|
||||
|
||||
// 产品的状态进行转换处理
|
||||
|
@ -331,11 +327,10 @@ const table: any = {
|
|||
};
|
||||
}
|
||||
});
|
||||
|
||||
resolve({
|
||||
code: 200,
|
||||
result: {
|
||||
data: data,
|
||||
data: data.sort((a, b) => a.createTime - b.createTime),
|
||||
pageIndex,
|
||||
pageSize,
|
||||
total,
|
||||
|
@ -344,6 +339,57 @@ const table: any = {
|
|||
});
|
||||
},
|
||||
);
|
||||
// getPermission_api(props.assetType, ids, parentId).then(
|
||||
// (perResp: any) => {
|
||||
// console.log('perResp: ', perResp);
|
||||
// console.log('props.allPermission: ', props.allPermission);
|
||||
// const permissionObj = {};
|
||||
// perResp.result.forEach((item: any) => {
|
||||
// permissionObj[item.assetId] = props.allPermission
|
||||
// .filter((permission) =>
|
||||
// item.allPermissions.includes(permission.id),
|
||||
// )
|
||||
// .map((item) => ({
|
||||
// label: item.name,
|
||||
// value: item.id,
|
||||
// disabled: true,
|
||||
// }));
|
||||
// });
|
||||
// data.forEach((item) => {
|
||||
// item.permissionList = permissionObj[item.id];
|
||||
// item.selectPermissions = ['read'];
|
||||
|
||||
// // 产品的状态进行转换处理
|
||||
// if (props.assetType === 'product') {
|
||||
// item.state = {
|
||||
// value:
|
||||
// item.state === 1
|
||||
// ? 'online'
|
||||
// : item.state === 0
|
||||
// ? 'offline'
|
||||
// : '',
|
||||
// text:
|
||||
// item.state === 1
|
||||
// ? '正常'
|
||||
// : item.state === 0
|
||||
// ? '禁用'
|
||||
// : '',
|
||||
// };
|
||||
// }
|
||||
// });
|
||||
|
||||
// resolve({
|
||||
// code: 200,
|
||||
// result: {
|
||||
// data: data,
|
||||
// pageIndex,
|
||||
// pageSize,
|
||||
// total,
|
||||
// },
|
||||
// status: 200,
|
||||
// });
|
||||
// },
|
||||
// );
|
||||
});
|
||||
}),
|
||||
// 整理参数并获取数据
|
||||
|
@ -398,10 +444,15 @@ const table: any = {
|
|||
},
|
||||
};
|
||||
table.init();
|
||||
const selectRow = (keys:string[], rows:any[]) => {
|
||||
const okRows = rows.filter(item=>!!item.permissionList.find((permiss:any)=>permiss.value === 'share'));
|
||||
const selectRow = (keys: string[], rows: any[]) => {
|
||||
const okRows = rows.filter(
|
||||
(item) =>
|
||||
!!item.permissionList.find(
|
||||
(permiss: any) => permiss.value === 'share',
|
||||
),
|
||||
);
|
||||
table.selectedRows = okRows;
|
||||
table._selectedRowKeys.value = okRows.map(item=>item.id)
|
||||
table._selectedRowKeys.value = okRows.map((item) => item.id);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<pro-search
|
||||
:columns="columns"
|
||||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<j-pro-table
|
||||
|
@ -14,6 +14,7 @@
|
|||
model="TABLE"
|
||||
:params="queryParams"
|
||||
noPagination
|
||||
v-model:expandedRowKeys="expandedRowKeys"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<PermissionButton
|
||||
|
@ -152,6 +153,11 @@ const columns = [
|
|||
},
|
||||
];
|
||||
const queryParams = ref({ terms: [] });
|
||||
const expandedRowKeys = ref<string[]>([]);
|
||||
const handleSearch = (e: any) => {
|
||||
queryParams.value = e;
|
||||
if (!e.terms.length) expandedRowKeys.value = [];
|
||||
};
|
||||
|
||||
const tableRef = ref<Record<string, any>>({}); // 表格实例
|
||||
const table = reactive({
|
||||
|
|
Loading…
Reference in New Issue