Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
f9271d4f99
|
@ -1,21 +1,25 @@
|
|||
<template>
|
||||
<j-select allowClear v-model:value="_value" @change="onChange" placeholder="请选择" style="width: 100%">
|
||||
<j-select
|
||||
allowClear
|
||||
v-model:value="_value"
|
||||
@change="onChange"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in list"
|
||||
v-bind="item"
|
||||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
:filter-option="filterOption"
|
||||
showSearch
|
||||
>{{ item.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
edgeCollector,
|
||||
edgePoint,
|
||||
} from '@/api/device/instance';
|
||||
import queryDataList from './utils';
|
||||
|
||||
const _props = defineProps({
|
||||
modelValue: {
|
||||
|
@ -33,15 +37,17 @@ const _props = defineProps({
|
|||
edgeId: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
},
|
||||
provider: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:modelValue', data: string | undefined): void;
|
||||
(e: 'update:provider', data: string | undefined): void;
|
||||
(e: 'change', data: string | undefined): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
|
@ -52,64 +58,16 @@ watchEffect(() => {
|
|||
_value.value = _props.modelValue;
|
||||
});
|
||||
|
||||
const onChange = (_val: string) => {
|
||||
const onChange = (_val: string, _options: any) => {
|
||||
emit('update:modelValue', _val);
|
||||
};
|
||||
|
||||
const getCollector = async (_val: string) => {
|
||||
if (!_val) {
|
||||
return [];
|
||||
} else {
|
||||
const resp = await edgeCollector(_props.edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'channelId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
list.value = (resp.result as any[])?.[0] || []
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getPoint = async (_val: string) => {
|
||||
if (!_val) {
|
||||
return [];
|
||||
} else {
|
||||
const resp = await edgePoint(_props.edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'collectorId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
list.value = (resp.result as any[])?.[0] || []
|
||||
}
|
||||
}
|
||||
emit('update:provider', _options?.provider);
|
||||
emit('change', _val);
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
if (_props.id) {
|
||||
if (_props.type === 'POINT') {
|
||||
getPoint(_props.id);
|
||||
} else {
|
||||
getCollector(_props.id);
|
||||
}
|
||||
} else {
|
||||
list.value = [];
|
||||
}
|
||||
queryDataList(_props.id, _props.edgeId, _props.type).then((_data: any) => {
|
||||
list.value = _data;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
v-model:value="record[column.dataIndex]"
|
||||
placeholder="请选择"
|
||||
allowClear
|
||||
:filter-option="filterOption"
|
||||
@change="
|
||||
() => onChannelChange(index, 'channel')
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in channelList"
|
||||
|
@ -58,6 +60,10 @@
|
|||
:id="record.channelId"
|
||||
type="COLLECTOR"
|
||||
:edgeId="instanceStore.current.parentId"
|
||||
v-model:provider="record.provider"
|
||||
@change="
|
||||
onChannelChange(index, 'collector')
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</template>
|
||||
|
@ -80,61 +86,84 @@
|
|||
</j-form-item>
|
||||
</template>
|
||||
<template v-if="column.dataIndex === 'id'">
|
||||
<j-badge
|
||||
v-if="record[column.dataIndex]"
|
||||
status="success"
|
||||
text="已绑定"
|
||||
/>
|
||||
<template v-if="record[column.dataIndex]">
|
||||
<j-badge
|
||||
v-if="record.state.value === 'enabled'"
|
||||
status="success"
|
||||
text="在线"
|
||||
/>
|
||||
<j-badge
|
||||
v-else
|
||||
status="warning"
|
||||
text="离线"
|
||||
/>
|
||||
</template>
|
||||
<j-badge v-else status="error" text="未绑定" />
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="link"
|
||||
:disabled="!record.id"
|
||||
:popConfirm="{
|
||||
title: '确认解绑?',
|
||||
onConfirm: unbind(record.id),
|
||||
}"
|
||||
style="padding: 0 5px"
|
||||
hasPermission="device/Instance:update"
|
||||
:tooltip="{
|
||||
title: '解绑',
|
||||
}"
|
||||
<j-tooltip
|
||||
:title="
|
||||
isPermission
|
||||
? '解绑'
|
||||
: '暂无权限,请联系管理员'
|
||||
"
|
||||
>
|
||||
<AIcon type="icon-jiebang" />
|
||||
</PermissionButton>
|
||||
<j-popconfirm
|
||||
title="确认解绑?"
|
||||
:disabled="!record.id || !isPermission"
|
||||
@confirm="unbind(record.id)"
|
||||
>
|
||||
<j-button
|
||||
type="link"
|
||||
:disabled="
|
||||
!record.id || !isPermission
|
||||
"
|
||||
style="padding: 0 5px"
|
||||
>
|
||||
<AIcon type="icon-jiebang" />
|
||||
</j-button>
|
||||
</j-popconfirm>
|
||||
</j-tooltip>
|
||||
<template v-if="record.id">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
:disabled="!record.id"
|
||||
style="padding: 0 5px"
|
||||
:popConfirm="{
|
||||
title:
|
||||
<j-tooltip
|
||||
:title="
|
||||
isPermission
|
||||
? record.state.value ===
|
||||
'enabled'
|
||||
? '禁用'
|
||||
: '启用'
|
||||
: '暂无权限,请联系管理员'
|
||||
"
|
||||
>
|
||||
<j-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>
|
||||
:disabled="!isPermission"
|
||||
@confirm="onAction(record)"
|
||||
>
|
||||
<j-button
|
||||
type="link"
|
||||
style="padding: 0 5px"
|
||||
:disabled="!isPermission"
|
||||
>
|
||||
<AIcon
|
||||
v-if="
|
||||
record.state.value ===
|
||||
'enabled'
|
||||
"
|
||||
type="StopOutlined"
|
||||
/>
|
||||
<AIcon
|
||||
v-else
|
||||
type="PlayCircleOutlined"
|
||||
/>
|
||||
</j-button>
|
||||
</j-popconfirm>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
|
@ -142,10 +171,10 @@
|
|||
</j-table>
|
||||
<div class="pagination">
|
||||
<j-pagination
|
||||
@change="onPageChange"
|
||||
v-model:pageSize="pageSize"
|
||||
v-model:current="current"
|
||||
:total="metadata?.properties?.length || 0"
|
||||
@change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
</j-form>
|
||||
|
@ -175,6 +204,8 @@ import {
|
|||
import MSelect from './MSelect.vue';
|
||||
import PatchMapping from './PatchMapping.vue';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { usePermissionStore } from '@/store/permission';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -214,19 +245,22 @@ const columns = [
|
|||
},
|
||||
];
|
||||
|
||||
const current = ref<number>(1);
|
||||
const pageSize = ref<number>(10);
|
||||
const permissionStore = usePermissionStore();
|
||||
|
||||
const filterOption = (input: string, option: any) => {
|
||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
};
|
||||
const isPermission = permissionStore.hasPermission('device/Instance:update');
|
||||
|
||||
const current = ref<number>(0);
|
||||
const pageSize = ref<number>(10);
|
||||
|
||||
const instanceStore = useInstanceStore();
|
||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}');
|
||||
const loading = ref<boolean>(false);
|
||||
const channelList = ref<any[]>([]);
|
||||
|
||||
const _properties = ref<any[]>([]);
|
||||
const _properties = computed(() => {
|
||||
const _cur = current.value >= 1 ? current.value : 1;
|
||||
return metadata.properties.slice((_cur - 1) * 10, _cur * 10);
|
||||
});
|
||||
|
||||
const modelRef = reactive<{
|
||||
dataSource: any[];
|
||||
|
@ -250,18 +284,9 @@ const getChannel = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const queryData = (cur: number) => {
|
||||
_properties.value = metadata.properties.slice(
|
||||
(cur > 0 ? cur - 1 : 0) * 10,
|
||||
cur * 10,
|
||||
);
|
||||
handleSearch(_properties.value)
|
||||
};
|
||||
|
||||
const handleSearch = async (array: any[]) => {
|
||||
const handleSearch = async (_array: any[]) => {
|
||||
loading.value = true;
|
||||
getChannel();
|
||||
const _metadata: any[] = array.map((item: any) => ({
|
||||
const _metadata: any[] = _array.map((item: any) => ({
|
||||
metadataId: item.id,
|
||||
metadataName: `${item.name}(${item.id})`,
|
||||
metadataType: 'property',
|
||||
|
@ -297,11 +322,12 @@ const handleSearch = async (array: any[]) => {
|
|||
};
|
||||
|
||||
const unbind = async (id: string) => {
|
||||
if (id) {
|
||||
const _deviceId = instanceStore.current.id;
|
||||
if (id && _deviceId) {
|
||||
const resp = await removeEdgeMap(
|
||||
instanceStore.current?.parentId || '',
|
||||
{
|
||||
deviceId: instanceStore.current.id,
|
||||
deviceId: _deviceId,
|
||||
idList: [id],
|
||||
},
|
||||
);
|
||||
|
@ -314,22 +340,31 @@ const unbind = async (id: string) => {
|
|||
|
||||
const onPatchBind = () => {
|
||||
visible.value = false;
|
||||
handleSearch(_properties.value);
|
||||
onRefresh();
|
||||
};
|
||||
|
||||
const onPageChange = (page: any) => {
|
||||
queryData(page)
|
||||
const onChannelChange = (_index: number, type: 'collector' | 'channel') => {
|
||||
if (type === 'channel') {
|
||||
modelRef.dataSource[_index].collectorId = undefined;
|
||||
modelRef.dataSource[_index].pointId = undefined;
|
||||
} else {
|
||||
modelRef.dataSource[_index].pointId = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
_properties.value = metadata.properties.slice(0, 10);
|
||||
getChannel();
|
||||
handleSearch(_properties.value);
|
||||
});
|
||||
|
||||
const onPageChange = () => {
|
||||
handleSearch(_properties.value);
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
.then(async (_data: any) => {
|
||||
const arr = toRaw(modelRef).dataSource.filter(
|
||||
(i: any) => i.channelId,
|
||||
);
|
||||
|
@ -345,7 +380,7 @@ const onSave = () => {
|
|||
);
|
||||
if (resp.status === 200) {
|
||||
onlyMessage('操作成功!', 'success');
|
||||
handleSearch(_properties.value);
|
||||
onRefresh();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -355,8 +390,9 @@ const onSave = () => {
|
|||
};
|
||||
|
||||
const onAction = async (record: any) => {
|
||||
const value = await formRef.value.validate();
|
||||
const array = value.filter((item: any) => item.channelId);
|
||||
const array = (modelRef.dataSource || [])?.filter(
|
||||
(item: any) => item.channelId,
|
||||
);
|
||||
const findArray = array.find((item: any) => item.id === record?.id);
|
||||
const arr = {
|
||||
...findArray,
|
||||
|
@ -374,9 +410,42 @@ const onAction = async (record: any) => {
|
|||
);
|
||||
if (resp.status === 200) {
|
||||
onlyMessage('操作成功!', 'success');
|
||||
handleSearch(_properties.value);
|
||||
onRefresh();
|
||||
}
|
||||
};
|
||||
|
||||
const onRefresh = async () => {
|
||||
loading.value = true;
|
||||
if (modelRef.dataSource && modelRef.dataSource.length) {
|
||||
const resp: any = await getEdgeMap(
|
||||
instanceStore.current?.parentId || '',
|
||||
{
|
||||
deviceId: instanceStore.current.id,
|
||||
query: {},
|
||||
},
|
||||
).catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
const arr = cloneDeep(modelRef.dataSource);
|
||||
const array = resp.result?.[0].map((x: any) => {
|
||||
const _item = arr.find(
|
||||
(item: any) => item.metadataId === x.metadataId,
|
||||
);
|
||||
if (_item) {
|
||||
return {
|
||||
..._item,
|
||||
...x,
|
||||
};
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
});
|
||||
modelRef.dataSource = array;
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import { edgeCollector, edgePoint } from "@/api/device/instance";
|
||||
|
||||
const channelMap = new Map()
|
||||
const queryDataList = (_val: string, edgeId: string, type: string) => new Promise(async (resolve) => {
|
||||
if (!_val || !edgeId || !type) {
|
||||
resolve([])
|
||||
} else {
|
||||
if (channelMap.get(_val)) {
|
||||
resolve(channelMap.get(_val))
|
||||
} else {
|
||||
let resp = undefined
|
||||
if (type === 'POINT') {
|
||||
resp = await edgePoint(edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'collectorId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
} else {
|
||||
resp = await edgeCollector(edgeId, {
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'channelId',
|
||||
value: _val,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (resp && resp.status === 200) {
|
||||
const _data = (resp.result as any[])?.[0] || []
|
||||
channelMap.set(_val, _data)
|
||||
resolve(_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default queryDataList
|
|
@ -6,10 +6,10 @@
|
|||
:title="type === 'active' ? '启用' : '同步'"
|
||||
:closable="false"
|
||||
>
|
||||
<div style="margin: 10px 0px 20px 0px">
|
||||
<div style="margin: 10px 0px 20px 0px; padding-right: 10px;">
|
||||
<div v-if="flag">
|
||||
<div>{{ type === 'active' ? '正在启用全部设备' : '正在同步设备状态' }}</div>
|
||||
<j-progress :percent="50" />
|
||||
<j-progress :percent="_percent" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>{{ type === 'active' ? '启用' : '同步' }}成功:{{ count }}条</p>
|
||||
|
@ -23,6 +23,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDeviceNumber } from '@/api/device/product';
|
||||
import { EventSourcePolyfill } from 'event-source-polyfill';
|
||||
|
||||
const emit = defineEmits(['close', 'save']);
|
||||
|
@ -36,12 +37,11 @@ const props = defineProps({
|
|||
default: '',
|
||||
},
|
||||
});
|
||||
// const eventSource = ref<Record<string, any>>({})
|
||||
|
||||
const count = ref<number>(0);
|
||||
const total = ref<number>(0);
|
||||
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>>({});
|
||||
|
||||
const handleCancel = () => {
|
||||
|
@ -49,9 +49,14 @@ const handleCancel = () => {
|
|||
emit('save');
|
||||
};
|
||||
|
||||
const _percent = computed(() => {
|
||||
return ((errCount.value + count.value) / total.value * 100).toFixed(2)
|
||||
})
|
||||
|
||||
const getData = (api: string) => {
|
||||
flag.value = true;
|
||||
let dt = 0;
|
||||
let dt1 = 0;
|
||||
const _source = new EventSourcePolyfill(api);
|
||||
source.value = _source;
|
||||
_source.onmessage = (e: any) => {
|
||||
|
@ -59,24 +64,16 @@ const getData = (api: string) => {
|
|||
switch (props.type) {
|
||||
case 'active':
|
||||
if (res.success) {
|
||||
_source.close();
|
||||
dt += res.total;
|
||||
count.value = dt;
|
||||
flag.value = false;
|
||||
} else {
|
||||
if (res.source) {
|
||||
errCount.value = 1
|
||||
id.value = res.source.id;
|
||||
isSource.value = true;
|
||||
} else {
|
||||
errCount.value = 1
|
||||
}
|
||||
dt1 += res.total;
|
||||
errCount.value = dt1;
|
||||
}
|
||||
break;
|
||||
case 'sync':
|
||||
dt += res;
|
||||
count.value = dt;
|
||||
flag.value = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -93,7 +90,12 @@ watch(
|
|||
() => props.api,
|
||||
(newValue) => {
|
||||
if (newValue) {
|
||||
getData(newValue);
|
||||
getDeviceNumber({}).then(resp => {
|
||||
if(resp.status === 200){
|
||||
total.value = resp.result
|
||||
getData(newValue);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
|
|
|
@ -308,8 +308,8 @@ import dayjs from 'dayjs';
|
|||
import BadgeStatus from '@/components/BadgeStatus/index.vue';
|
||||
import BatchDropdown from '@/components/BatchDropdown/index.vue';
|
||||
import { BatchActionsType } from '@/components/BatchDropdown/types';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting';
|
||||
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
@ -322,22 +322,22 @@ const operationVisible = ref<boolean>(false);
|
|||
const api = ref<string>('');
|
||||
const type = ref<string>('');
|
||||
const isCheck = ref<boolean>(false);
|
||||
const routerParams = useRouterParams()
|
||||
const routerParams = useRouterParams();
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const transformData = (arr: any[]): any[] => {
|
||||
if(Array.isArray(arr) && arr.length){
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
return (arr || []).map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
id: `classifiedId is ${item.id}`,
|
||||
children: transformData(item.children)
|
||||
}
|
||||
})
|
||||
children: transformData(item.children),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -412,7 +412,7 @@ const columns = [
|
|||
hideInTable: true,
|
||||
search: {
|
||||
type: 'treeSelect',
|
||||
rename: 'productId$product-info',
|
||||
// rename: 'productId$product-info',
|
||||
options: () =>
|
||||
new Promise((resolve) => {
|
||||
queryTree({ paging: false }).then((resp: any) => {
|
||||
|
@ -429,22 +429,24 @@ const columns = [
|
|||
hideInTable: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
rename: 'productId$product-info',
|
||||
// rename: 'productId$product-info',
|
||||
options: () =>
|
||||
new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data).map(item => ({
|
||||
...item,
|
||||
value: `accessProvider is ${item.id}`
|
||||
})))
|
||||
const data = resp.result || [];
|
||||
resolve(
|
||||
accessConfigTypeFilter(data).map((item) => ({
|
||||
...item,
|
||||
value: `accessProvider is ${item.id}`,
|
||||
})),
|
||||
);
|
||||
});
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'productId$product-info',
|
||||
dataIndex: 'productId$product-info',
|
||||
key: 'accessId',
|
||||
dataIndex: 'accessId',
|
||||
title: '接入方式',
|
||||
hideInTable: true,
|
||||
search: {
|
||||
|
@ -728,9 +730,9 @@ const syncDeviceStatus = () => {
|
|||
};
|
||||
|
||||
const delSelectedDevice = async () => {
|
||||
if(!_selectedRowKeys.value.length){
|
||||
message.error('请选择设备')
|
||||
return
|
||||
if (!_selectedRowKeys.value.length) {
|
||||
message.error('请选择设备');
|
||||
return;
|
||||
}
|
||||
const resp = await batchDeleteDevice(_selectedRowKeys.value);
|
||||
if (resp.status === 200) {
|
||||
|
@ -754,9 +756,9 @@ const delSelectedDevice = async () => {
|
|||
// };
|
||||
|
||||
const disabledSelectedDevice = async () => {
|
||||
if(!_selectedRowKeys.value.length){
|
||||
message.error('请选择设备')
|
||||
return
|
||||
if (!_selectedRowKeys.value.length) {
|
||||
message.error('请选择设备');
|
||||
return;
|
||||
}
|
||||
const resp = await batchUndeployDevice(_selectedRowKeys.value);
|
||||
if (resp.status === 200) {
|
||||
|
@ -842,7 +844,7 @@ const batchActions: BatchActionsType[] = [
|
|||
popConfirm: {
|
||||
title: '确认禁用选中设备?',
|
||||
onConfirm: disabledSelectedDevice,
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
@ -853,7 +855,25 @@ const saveBtn = () => {
|
|||
};
|
||||
|
||||
const handleSearch = (_params: any) => {
|
||||
params.value = _params;
|
||||
// params.value = _params;
|
||||
const newParams = (_params?.terms as any[])?.map((item1) => {
|
||||
item1.terms = item1.terms.map((item2: any) => {
|
||||
if (
|
||||
item2.column &&
|
||||
['classifiedId', 'accessId', 'accessProvider'].includes(
|
||||
item2.column,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...item2,
|
||||
column: 'productId$product-info'
|
||||
};
|
||||
}
|
||||
return item2;
|
||||
});
|
||||
return item1;
|
||||
});
|
||||
params.value = { terms: newParams || [] };
|
||||
};
|
||||
|
||||
const onRefresh = () => {
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
v-if="
|
||||
permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
)
|
||||
"
|
||||
>
|
||||
|
@ -24,7 +30,7 @@
|
|||
<j-col :span="12">
|
||||
<Title data="接入方式">
|
||||
<template #extra>
|
||||
<j-tooltip
|
||||
<!-- <j-tooltip
|
||||
:title="
|
||||
productStore.current?.count &&
|
||||
productStore.current?.count > 0
|
||||
|
@ -44,7 +50,48 @@
|
|||
@click="showDevice"
|
||||
>更换</j-button
|
||||
>
|
||||
</j-tooltip>
|
||||
</j-tooltip> -->
|
||||
<PermissionButton
|
||||
style="margin: 0 0 0 20px"
|
||||
type="primary"
|
||||
size="small"
|
||||
:tooltip="{
|
||||
title:
|
||||
productStore.current?.count &&
|
||||
productStore.current?.count > 0
|
||||
? '产品下有设备实例时不能更换接入方式'
|
||||
: !(permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
))
|
||||
? '暂无权限,请联系管理员'
|
||||
: '',
|
||||
}"
|
||||
:disabled="
|
||||
(productStore.current?.count &&
|
||||
productStore.current?.count > 0) ||
|
||||
!(
|
||||
permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
)
|
||||
)
|
||||
"
|
||||
ghost
|
||||
@click="showDevice"
|
||||
>
|
||||
更换
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</Title>
|
||||
<div>
|
||||
|
@ -419,7 +466,7 @@ import { marked } from 'marked';
|
|||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import _ from 'lodash';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
import { accessConfigTypeFilter } from '@/utils/setting';
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
|
@ -502,8 +549,8 @@ const query = reactive({
|
|||
options: async () => {
|
||||
return new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data))
|
||||
const data = resp.result || [];
|
||||
resolve(accessConfigTypeFilter(data));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -935,7 +982,7 @@ const getData = async (accessId?: string) => {
|
|||
);
|
||||
getProviders().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
const data = resp.result || []
|
||||
const data = resp.result || [];
|
||||
dataSource.value = accessConfigTypeFilter(data as any[]);
|
||||
}
|
||||
});
|
||||
|
@ -1019,10 +1066,13 @@ watchEffect(() => {
|
|||
nextTick(() => {
|
||||
getData();
|
||||
});
|
||||
watch(()=>productStore.current,()=>{
|
||||
getData();
|
||||
formData.data = productStore.current?.configuration || {}
|
||||
})
|
||||
watch(
|
||||
() => productStore.current,
|
||||
() => {
|
||||
getData();
|
||||
formData.data = productStore.current?.configuration || {};
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
:deep(
|
||||
|
|
|
@ -85,7 +85,7 @@
|
|||
:value="form.deviceType"
|
||||
:options="deviceList"
|
||||
@change="changeDeviceType"
|
||||
:disabled="disabled"
|
||||
:disabled="productStore.detail?.accessId ? true : false"
|
||||
>
|
||||
<template #title="item">
|
||||
<span>{{ item.title }}</span>
|
||||
|
@ -142,12 +142,9 @@ const loading = ref<boolean>(false);
|
|||
const dialogRef = ref();
|
||||
const treeList = ref<Record<string, any>[]>([]);
|
||||
const visible = ref<boolean>(false);
|
||||
const logoLoading = ref<boolean>(false);
|
||||
const formRef = ref();
|
||||
const disabled = ref<boolean>(false);
|
||||
const idDisabled = ref<boolean>(false);
|
||||
const useForm = Form.useForm;
|
||||
const _selectedRowKeys = ref([]);
|
||||
const photoValue = ref('/images/device-product.png');
|
||||
const imageTypes = reactive([
|
||||
'image/jpeg',
|
||||
|
@ -258,12 +255,12 @@ const queryProductTree = async () => {
|
|||
* 处理产品分类key
|
||||
*/
|
||||
const dealProductTree = (arr: any) => {
|
||||
return arr.map((element: any) => {
|
||||
return arr.map((element: any) => {
|
||||
element.key = element.id;
|
||||
if (element.children) {
|
||||
element.children = dealProductTree(element.children);
|
||||
}
|
||||
return element
|
||||
return element;
|
||||
});
|
||||
};
|
||||
/**
|
||||
|
@ -279,9 +276,9 @@ const show = (data: any) => {
|
|||
form.deviceType = data.deviceType.value;
|
||||
form.describe = form.describe;
|
||||
form.id = data.id;
|
||||
disabled.value = productStore.current?.accessId ? true : false;
|
||||
idDisabled.value = true;
|
||||
} else if (props.isAdd === 1) {
|
||||
productStore.reSet();
|
||||
form.name = '';
|
||||
form.classifiedId = undefined;
|
||||
form.classifiedName = '';
|
||||
|
@ -289,8 +286,7 @@ const show = (data: any) => {
|
|||
form.deviceType = '';
|
||||
form.describe = undefined;
|
||||
form.id = undefined;
|
||||
disabled.value = false;
|
||||
disabled.vlaue = false;
|
||||
idDisabled.value = false;
|
||||
}
|
||||
visible.value = true;
|
||||
};
|
||||
|
|
|
@ -339,6 +339,7 @@ export default {
|
|||
granted: true,
|
||||
},
|
||||
{ id: 'add', name: '新增', enabled: true, granted: true },
|
||||
{ id: 'view', name: '查看', enabled: true, granted: true },
|
||||
],
|
||||
assetAccesses: [],
|
||||
options: {},
|
||||
|
@ -364,6 +365,12 @@ export default {
|
|||
granted: true,
|
||||
},
|
||||
{ id: 'update', name: '编辑', enabled: true, granted: true },
|
||||
{
|
||||
id: 'action',
|
||||
name: '启/禁用',
|
||||
enabled: true,
|
||||
granted: true,
|
||||
},
|
||||
{
|
||||
id: 'add',
|
||||
name: '新增',
|
||||
|
@ -451,6 +458,7 @@ export default {
|
|||
icon: 'icon-wangluozujian',
|
||||
url: '/iot/link/firmware',
|
||||
buttons: [
|
||||
{ id: 'view', name: '查看', enabled: true, granted: true },
|
||||
{ id: 'update', name: '编辑', enabled: true, granted: true },
|
||||
{
|
||||
id: 'action',
|
||||
|
@ -784,6 +792,7 @@ export default {
|
|||
granted: true,
|
||||
},
|
||||
{ id: 'add', name: '新增', enabled: true, granted: true },
|
||||
{ id: 'view', name: '查看', enabled: true, granted: true },
|
||||
],
|
||||
assetAccesses: [],
|
||||
options: {},
|
||||
|
@ -809,6 +818,12 @@ export default {
|
|||
granted: true,
|
||||
},
|
||||
{ id: 'update', name: '编辑', enabled: true, granted: true },
|
||||
{
|
||||
id: 'action',
|
||||
name: '启/禁用',
|
||||
enabled: true,
|
||||
granted: true,
|
||||
},
|
||||
{
|
||||
id: 'add',
|
||||
name: '新增',
|
||||
|
@ -896,6 +911,7 @@ export default {
|
|||
icon: 'icon-wangluozujian',
|
||||
url: '/iot/link/firmware',
|
||||
buttons: [
|
||||
{ id: 'view', name: '查看', enabled: true, granted: true },
|
||||
{ id: 'update', name: '编辑', enabled: true, granted: true },
|
||||
{
|
||||
id: 'action',
|
||||
|
|
|
@ -659,9 +659,8 @@ const saveData = () => {
|
|||
|
||||
const next = async () => {
|
||||
let data1: any = await formRef1.value?.validate();
|
||||
if (data1.hostPort?.port) {
|
||||
const port = JSON.parse(data1.hostPort.port).port;
|
||||
data1.hostPort.port = port;
|
||||
if (!isNumber(data1.hostPort.port)) {
|
||||
data1.hostPort.port = JSON.parse(data1.hostPort.port).port;
|
||||
}
|
||||
if (!data1?.shareCluster) {
|
||||
await formRef2.value
|
||||
|
|
|
@ -77,17 +77,14 @@ const columns = [
|
|||
width: 200,
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: '证书标准',
|
||||
value: 'common',
|
||||
},
|
||||
],
|
||||
},
|
||||
// search: {
|
||||
// type: 'select',
|
||||
// options: [
|
||||
// {
|
||||
// label: '证书标准',
|
||||
// value: 'common',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -161,6 +161,9 @@ import DeviceApi from '@/api/media/device';
|
|||
import { getImage } from '@/utils/comm';
|
||||
import { gatewayType } from '@/views/media/Device/typings';
|
||||
import { providerType } from '../const';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
|
@ -239,8 +242,8 @@ watch(
|
|||
if (val) {
|
||||
getGatewayList();
|
||||
} else {
|
||||
_selectedRowKeys.value = [];
|
||||
extendFormItem.value = [];
|
||||
_selectedRowKeys.value = [];;
|
||||
extendFormItem.value = [];;
|
||||
emit('close');
|
||||
}
|
||||
},
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
:multiple="true"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:value="relationData"
|
||||
showSearch
|
||||
treeNodeFilterProp="title"
|
||||
>
|
||||
<template #title="{ key, username, title }">
|
||||
<div
|
||||
|
@ -69,6 +71,8 @@
|
|||
:tree-data="treeData"
|
||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||
:value="relationData"
|
||||
showSearch
|
||||
treeNodeFilterProp="title"
|
||||
>
|
||||
<template #title="{ key, username, title }">
|
||||
<div
|
||||
|
@ -110,6 +114,7 @@
|
|||
placeholder="请输入收件人邮箱,多个收件人用换行分隔"
|
||||
:value="value?.value"
|
||||
mode="tags"
|
||||
max-tag-count="responsive"
|
||||
@change="
|
||||
(val) =>
|
||||
onChange(
|
||||
|
|
Loading…
Reference in New Issue