Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
81590a0af3
|
@ -37,16 +37,15 @@
|
||||||
:name="['configuration', 'host']"
|
:name="['configuration', 'host']"
|
||||||
:rules="FormValidate.host"
|
:rules="FormValidate.host"
|
||||||
>
|
>
|
||||||
<div class="form-label">
|
<template #label>
|
||||||
Modbus主机IP
|
Modbus主机IP
|
||||||
<span class="form-label-required">*</span>
|
<j-tooltip title="支持ipv4、ipv6、域名">
|
||||||
<j-tooltip>
|
<AIcon
|
||||||
<template #title>
|
type="QuestionCircleOutlined"
|
||||||
<p>支持ipv4、ipv6、域名</p>
|
style="margin-left: 2px"
|
||||||
</template>
|
/>
|
||||||
<AIcon type="QuestionCircleOutlined" />
|
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</div>
|
</template>
|
||||||
<j-input
|
<j-input
|
||||||
placeholder="请输入Modbus主机IP"
|
placeholder="请输入Modbus主机IP"
|
||||||
v-model:value="formData.configuration.host"
|
v-model:value="formData.configuration.host"
|
||||||
|
@ -62,7 +61,7 @@
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入端口"
|
placeholder="请输入端口"
|
||||||
v-model:value="formData.configuration.port"
|
v-model:value="formData.configuration.port"
|
||||||
:min="1"
|
:min="0"
|
||||||
:max="65535"
|
:max="65535"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
@ -80,7 +79,7 @@
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.provider === 'OPC_UA'"
|
v-if="formData.provider === 'OPC_UA'"
|
||||||
label="安全策略"
|
label="安全策略"
|
||||||
:name="['configuration.securityPolicy']"
|
:name="['configuration', 'securityPolicy']"
|
||||||
:rules="FormValidate.securityPolicy"
|
:rules="FormValidate.securityPolicy"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
|
@ -96,7 +95,7 @@
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.provider === 'OPC_UA'"
|
v-if="formData.provider === 'OPC_UA'"
|
||||||
label="安全模式"
|
label="安全模式"
|
||||||
:name="['configuration.securityMode']"
|
:name="['configuration', 'securityMode']"
|
||||||
:rules="FormValidate.securityMode"
|
:rules="FormValidate.securityMode"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
|
@ -115,7 +114,7 @@
|
||||||
formData.configuration.securityMode === 'Sign'
|
formData.configuration.securityMode === 'Sign'
|
||||||
"
|
"
|
||||||
label="证书"
|
label="证书"
|
||||||
:name="['configuration.certificate']"
|
:name="['configuration', 'certificate']"
|
||||||
:rules="FormValidate.certificate"
|
:rules="FormValidate.certificate"
|
||||||
>
|
>
|
||||||
<j-select
|
<j-select
|
||||||
|
@ -131,20 +130,20 @@
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.provider === 'OPC_UA'"
|
v-if="formData.provider === 'OPC_UA'"
|
||||||
label="权限认证"
|
label="权限认证"
|
||||||
:name="['configuration.authType']"
|
:name="['configuration', 'authType']"
|
||||||
:rules="FormValidate.authType"
|
:rules="FormValidate.authType"
|
||||||
>
|
>
|
||||||
<RadioCard
|
<j-card-select
|
||||||
layout="horizontal"
|
:showImage="false"
|
||||||
:checkStyle="true"
|
v-model:value="formData.configuration.authType"
|
||||||
:options="Options['auth-types']"
|
:options="Options['auth-types']"
|
||||||
v-model="formData.configuration.authType"
|
@change="changeAuthType"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.configuration.authType === 'username'"
|
v-if="formData.configuration.authType === 'username'"
|
||||||
label="用户名"
|
label="用户名"
|
||||||
:name="['configuration.username']"
|
:name="['configuration', 'username']"
|
||||||
:rules="FormValidate.username"
|
:rules="FormValidate.username"
|
||||||
>
|
>
|
||||||
<j-input
|
<j-input
|
||||||
|
@ -153,9 +152,12 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="formData.configuration.authType === 'username'"
|
v-if="
|
||||||
|
formData.configuration.authType === 'username' ||
|
||||||
|
formData.configuration.authType === ['username']
|
||||||
|
"
|
||||||
label="密码"
|
label="密码"
|
||||||
:name="['configuration.password']"
|
:name="['configuration', 'password']"
|
||||||
:rules="FormValidate.password"
|
:rules="FormValidate.password"
|
||||||
>
|
>
|
||||||
<j-input-password
|
<j-input-password
|
||||||
|
@ -226,11 +228,9 @@ const handleOk = async () => {
|
||||||
const params = await formRef.value?.validate();
|
const params = await formRef.value?.validate();
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await save(params)
|
? await save(params).catch(() => {})
|
||||||
: await update(id, { ...props.data, ...params });
|
: await update(id, { ...props.data, ...params }).catch(() => {});
|
||||||
if (response.status === 200) {
|
emit('change', response?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
formRef.value?.resetFields();
|
formRef.value?.resetFields();
|
||||||
};
|
};
|
||||||
|
@ -240,29 +240,33 @@ const handleCancel = () => {
|
||||||
formRef.value?.resetFields();
|
formRef.value?.resetFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeAuthType = (value: Array<string>) => {
|
||||||
|
formData.value.configuration.authType = value[0];
|
||||||
|
};
|
||||||
|
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (input: string, option: any) => {
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOptionsList = async () => {
|
const getOptionsList = async () => {
|
||||||
for (let key in Options.value) {
|
for (let key in Options.value) {
|
||||||
const res = await queryOptionsList(key);
|
const res: any = await queryOptionsList(key);
|
||||||
Options.value[key] = res.result.map((item) => ({
|
Options.value[key] = res.result.map((item: any) => ({
|
||||||
label: item?.text || item,
|
label: item?.text || item,
|
||||||
value: item?.value || item,
|
value: item?.value || item,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const getCertificateList = async () => {
|
const getCertificateList = async () => {
|
||||||
const res = await queryCertificateList();
|
const res: any = await queryCertificateList();
|
||||||
certificateList.value = res.result.map((item) => ({
|
certificateList.value = res.result.map((item: any) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProvidersList = async () => {
|
const getProvidersList = async () => {
|
||||||
const resp = await getProviders();
|
const resp: any = await getProviders();
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const list = [
|
const list = [
|
||||||
{ label: 'OPC UA', value: 'OPC_UA' },
|
{ label: 'OPC UA', value: 'OPC_UA' },
|
||||||
|
@ -273,7 +277,9 @@ const getProvidersList = async () => {
|
||||||
(item: any) => item.id === 'modbus-tcp' || item.id === 'opc-ua',
|
(item: any) => item.id === 'modbus-tcp' || item.id === 'opc-ua',
|
||||||
)
|
)
|
||||||
.map((it: any) => (it?.id === 'opc-ua' ? 'OPC_UA' : 'MODBUS_TCP'));
|
.map((it: any) => (it?.id === 'opc-ua' ? 'OPC_UA' : 'MODBUS_TCP'));
|
||||||
const providers = list.filter((item: any) => arr.includes(item.value));
|
const providers: any = list.filter((item: any) =>
|
||||||
|
arr.includes(item.value),
|
||||||
|
);
|
||||||
providersList.value = providers;
|
providersList.value = providers;
|
||||||
if (arr.includes('OPC_UA')) {
|
if (arr.includes('OPC_UA')) {
|
||||||
getOptionsList();
|
getOptionsList();
|
||||||
|
@ -286,30 +292,10 @@ getCertificateList();
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id) formData.value = value;
|
if (value.id) formData.value = value as FormDataType;
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped></style>
|
||||||
.form {
|
|
||||||
.form-radio-button {
|
|
||||||
width: 148px;
|
|
||||||
height: 80px;
|
|
||||||
padding: 0;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.form-label {
|
|
||||||
height: 30px;
|
|
||||||
padding-bottom: 8px;
|
|
||||||
.form-label-required {
|
|
||||||
color: red;
|
|
||||||
margin: 0 4px 0 -2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { validateField } from '@/api/data-collect/channel';
|
import { validateField } from '@/api/data-collect/channel';
|
||||||
import { FormDataType } from './type.d';
|
import { FormDataType } from './type.d';
|
||||||
|
import type { Rule } from 'ant-design-vue/lib/form';
|
||||||
|
|
||||||
export const FormState: FormDataType = {
|
export const FormState: FormDataType = {
|
||||||
name: '',
|
name: '',
|
||||||
|
@ -44,7 +45,7 @@ export const TiTlePermissionButtonStyle = {
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
'text-overflow': 'ellipsis',
|
'text-overflow': 'ellipsis',
|
||||||
'white-space': 'nowrap',
|
'white-space': 'nowrap',
|
||||||
width: 'calc(100%-100px)',
|
width: 'calc(100%-150px)',
|
||||||
// width: '60%',
|
// width: '60%',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,10 +62,8 @@ export const regDomain = new RegExp(
|
||||||
);
|
);
|
||||||
export const checkEndpoint = (_rule: Rule, value: string): Promise<any> =>
|
export const checkEndpoint = (_rule: Rule, value: string): Promise<any> =>
|
||||||
new Promise(async (resolve, reject) => {
|
new Promise(async (resolve, reject) => {
|
||||||
if (value) {
|
const res = await validateField(value);
|
||||||
const res = await validateField(value);
|
return res.result.passed ? resolve('') : reject(res.result.reason);
|
||||||
return res.result.passed ? resolve('') : reject(res.result.reason);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
export const FormValidate = {
|
export const FormValidate = {
|
||||||
name: [
|
name: [
|
||||||
|
@ -89,7 +88,7 @@ export const FormValidate = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: regOnlyNumber,
|
pattern: regOnlyNumber,
|
||||||
message: '请输入1-65535之间的正整数',
|
message: '请输入0-65535之间的正整数',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -100,7 +99,7 @@ export const FormValidate = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
validator: checkEndpoint,
|
validator: checkEndpoint,
|
||||||
trigger: 'blur',
|
// trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -139,3 +138,70 @@ export const FormValidate = {
|
||||||
|
|
||||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
};
|
};
|
||||||
|
export const columns = [
|
||||||
|
{
|
||||||
|
title: '通道名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
fixed: 'left',
|
||||||
|
search: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '通讯协议',
|
||||||
|
dataIndex: 'provider',
|
||||||
|
key: 'provider',
|
||||||
|
ellipsis: true,
|
||||||
|
search: {
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: 'OPC_UA', value: 'OPC_UA' },
|
||||||
|
{ label: 'MODBUS_TCP', value: 'MODBUS_TCP' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'state',
|
||||||
|
key: 'state',
|
||||||
|
ellipsis: true,
|
||||||
|
scopedSlots: true,
|
||||||
|
search: {
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '正常', value: 'enabled' },
|
||||||
|
{ label: '禁用', value: 'disabled' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '运行状态',
|
||||||
|
dataIndex: 'runningState',
|
||||||
|
key: 'runningState',
|
||||||
|
ellipsis: true,
|
||||||
|
scopedSlots: true,
|
||||||
|
search: {
|
||||||
|
type: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '运行中', value: 'running' },
|
||||||
|
{ label: '部分错误', value: 'partialError' },
|
||||||
|
{ label: '错误', value: 'failed' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '说明',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
width: 200,
|
||||||
|
scopedSlots: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<div>
|
<div>
|
||||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
<pro-search
|
||||||
|
:columns="columns"
|
||||||
|
target="search"
|
||||||
|
@search="handleSearch"
|
||||||
|
/>
|
||||||
|
|
||||||
<j-pro-table
|
<j-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
|
@ -134,7 +138,6 @@ import _ from 'lodash';
|
||||||
const menuStory = useMenuStore();
|
const menuStory = useMenuStore();
|
||||||
const tableRef = ref<Record<string, any>>({});
|
const tableRef = ref<Record<string, any>>({});
|
||||||
const params = ref<Record<string, any>>({});
|
const params = ref<Record<string, any>>({});
|
||||||
const options = ref([]);
|
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const current = ref({});
|
const current = ref({});
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
allowClear
|
allowClear
|
||||||
show-search
|
show-search
|
||||||
:filter-option="filterOption"
|
:filter-option="filterOption"
|
||||||
|
@change="changeFunction"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
v-model:value="formData.configuration.parameter.quantity"
|
v-model:value="formData.configuration.parameter.quantity"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="255"
|
:max="255"
|
||||||
|
@blur="changeQuantity"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
@ -112,16 +114,9 @@
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="访问类型" name="accessModes">
|
<j-form-item label="访问类型" name="accessModes">
|
||||||
<!-- <RadioCard
|
<j-card-select
|
||||||
layout="horizontal"
|
multiple
|
||||||
:checkStyle="true"
|
:showImage="false"
|
||||||
:options="[
|
|
||||||
{ label: '读', value: 'read' },
|
|
||||||
{ label: '写', value: 'write' },
|
|
||||||
]"
|
|
||||||
v-model="formData.accessModes"
|
|
||||||
/> -->
|
|
||||||
<j-checkbox-group
|
|
||||||
v-model:value="formData.accessModes"
|
v-model:value="formData.accessModes"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '读', value: 'read' },
|
{ label: '读', value: 'read' },
|
||||||
|
@ -129,7 +124,6 @@
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<j-form-item
|
<j-form-item
|
||||||
:name="['nspwc']"
|
:name="['nspwc']"
|
||||||
v-if="
|
v-if="
|
||||||
|
@ -140,7 +134,6 @@
|
||||||
<span style="margin-right: 10px">非标准协议写入配置</span>
|
<span style="margin-right: 10px">非标准协议写入配置</span>
|
||||||
<j-switch v-model:checked="formData.nspwc" />
|
<j-switch v-model:checked="formData.nspwc" />
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-if="
|
v-if="
|
||||||
!!formData.nspwc &&
|
!!formData.nspwc &&
|
||||||
|
@ -151,14 +144,16 @@
|
||||||
:name="['configuration', 'parameter', 'writeByteCount']"
|
:name="['configuration', 'parameter', 'writeByteCount']"
|
||||||
:rules="ModBusRules.writeByteCount"
|
:rules="ModBusRules.writeByteCount"
|
||||||
>
|
>
|
||||||
<RadioCard
|
<j-card-select
|
||||||
layout="horizontal"
|
:showImage="false"
|
||||||
:checkStyle="true"
|
v-model:value="
|
||||||
|
formData.configuration.parameter.writeByteCount
|
||||||
|
"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '是', value: true },
|
{ label: '是', value: true },
|
||||||
{ label: '否', value: false },
|
{ label: '否', value: false },
|
||||||
]"
|
]"
|
||||||
v-model="formData.configuration.parameter.writeByteCount"
|
@change="changeWriteByteCount"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
|
@ -187,11 +182,10 @@
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入采集频率"
|
placeholder="请输入采集频率"
|
||||||
v-model:value="formData.configuration.interval"
|
v-model:value="formData.configuration.interval"
|
||||||
:min="1"
|
|
||||||
addon-after="ms"
|
addon-after="ms"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
@ -240,8 +234,8 @@ import {
|
||||||
} from '@/api/data-collect/collector';
|
} from '@/api/data-collect/collector';
|
||||||
import { ModBusRules, checkProviderData } from '../../data.ts';
|
import { ModBusRules, checkProviderData } from '../../data.ts';
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
import { Rule } from 'ant-design-vue/lib/form';
|
import type { Rule } from 'ant-design-vue/lib/form';
|
||||||
import { cloneDeep, isArray } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -285,9 +279,8 @@ const formData = ref({
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const handleOk = async () => {
|
||||||
const data = await formRef.value?.validate();
|
const data = await formRef.value?.validate();
|
||||||
|
|
||||||
delete data?.nspwc;
|
delete data?.nspwc;
|
||||||
const { codec } = data?.configuration;
|
const { codec } = data?.configuration;
|
||||||
|
|
||||||
|
@ -309,21 +302,29 @@ const onSubmit = async () => {
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await savePointBatch(params)
|
? await savePointBatch(params).catch(() => {})
|
||||||
: await updatePoint(id, { ...props.data, ...params });
|
: await updatePoint(id, { ...props.data, ...params }).catch(() => {});
|
||||||
if (response.status === 200) {
|
emit('change', response?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
onSubmit();
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeQuantity = () => {
|
||||||
|
if (formData.value.configuration.function === 'HoldingRegisters') {
|
||||||
|
formRef.value?.validate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const changeWriteByteCount = (value: Array<string>) => {
|
||||||
|
formData.value.configuration.parameter.writeByteCount = value[0];
|
||||||
|
};
|
||||||
|
const changeFunction = (value: string) => {
|
||||||
|
formData.value.accessModes =
|
||||||
|
value === 'DiscreteInputs' ? ['read'] : ['read', 'write'];
|
||||||
|
};
|
||||||
|
|
||||||
const checkLength = (_rule: Rule, value: string): Promise<any> =>
|
const checkLength = (_rule: Rule, value: string): Promise<any> =>
|
||||||
new Promise(async (resolve, reject) => {
|
new Promise(async (resolve, reject) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -347,10 +348,10 @@ const checkPointKey = (_rule: Rule, value: string): Promise<any> =>
|
||||||
new Promise(async (resolve, reject) => {
|
new Promise(async (resolve, reject) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
if (Number(oldPointKey) === Number(value)) return resolve('');
|
if (Number(oldPointKey) === Number(value)) return resolve('');
|
||||||
const res = await _validateField(collectorId, {
|
const res: any = await _validateField(collectorId, {
|
||||||
pointKey: value,
|
pointKey: value,
|
||||||
});
|
});
|
||||||
return res.result.passed ? resolve('') : reject(res.result.reason);
|
return res.result?.passed ? resolve('') : reject(res.result.reason);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -359,10 +360,10 @@ const filterOption = (input: string, option: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProviderList = async () => {
|
const getProviderList = async () => {
|
||||||
const res = await queryCodecProvider();
|
const res: any = await queryCodecProvider();
|
||||||
providerList.value = res.result
|
providerList.value = res.result
|
||||||
.filter((i) => i.id !== 'property')
|
.filter((i: any) => i.id !== 'property')
|
||||||
.map((item) => ({
|
.map((item: any) => ({
|
||||||
value: item.id,
|
value: item.id,
|
||||||
label: item.name,
|
label: item.name,
|
||||||
}));
|
}));
|
||||||
|
@ -386,11 +387,13 @@ watch(
|
||||||
formData.value = _value;
|
formData.value = _value;
|
||||||
if (!!_value.accessModes[0]?.value) {
|
if (!!_value.accessModes[0]?.value) {
|
||||||
formData.value.accessModes = value.accessModes.map(
|
formData.value.accessModes = value.accessModes.map(
|
||||||
(i) => i.value,
|
(i: any) => i.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!!_value.features[0]?.value) {
|
if (!!_value.features[0]?.value) {
|
||||||
formData.value.features = value.features.map((i) => i.value);
|
formData.value.features = value.features.map(
|
||||||
|
(i: any) => i.value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
formData.value.nspwc = !!writeByteCount || !!byteCount;
|
formData.value.nspwc = !!writeByteCount || !!byteCount;
|
||||||
}
|
}
|
||||||
|
@ -399,22 +402,4 @@ watch(
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped></style>
|
||||||
.form {
|
|
||||||
.form-radio-button {
|
|
||||||
width: 148px;
|
|
||||||
height: 80px;
|
|
||||||
padding: 0;
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.form-upload-button {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
.form-submit {
|
|
||||||
background-color: @primary-color !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<j-form-item label="访问类型" name="accessModes">
|
<j-form-item label="访问类型" name="accessModes">
|
||||||
<j-checkbox-group
|
<j-card-select
|
||||||
|
multiple
|
||||||
|
:showImage="false"
|
||||||
v-model:value="formData.accessModes"
|
v-model:value="formData.accessModes"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '读', value: 'read' },
|
{ label: '读', value: 'read' },
|
||||||
|
@ -54,15 +56,13 @@
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入采集频率"
|
placeholder="请输入采集频率"
|
||||||
v-model:value="formData.configuration.interval"
|
v-model:value="formData.configuration.interval"
|
||||||
:min="1"
|
|
||||||
addon-after="ms"
|
addon-after="ms"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
|
||||||
<a-form-item label="" :name="['features']">
|
<a-form-item label="" :name="['features']">
|
||||||
<a-checkbox-group v-model:value="formData.features">
|
<a-checkbox-group v-model:value="formData.features">
|
||||||
<a-checkbox value="changedOnly" name="type"
|
<a-checkbox value="changedOnly" name="type"
|
||||||
|
@ -70,7 +70,6 @@
|
||||||
>
|
>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|
||||||
<j-form-item label="说明" :name="['description']">
|
<j-form-item label="说明" :name="['description']">
|
||||||
<j-textarea
|
<j-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
|
@ -104,7 +103,7 @@ import {
|
||||||
updatePoint,
|
updatePoint,
|
||||||
_validateField,
|
_validateField,
|
||||||
} from '@/api/data-collect/collector';
|
} from '@/api/data-collect/collector';
|
||||||
import { OPCUARules, checkProviderData } from '../../data.ts';
|
import { OPCUARules } from '../../data.ts';
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
import { Rule } from 'ant-design-vue/lib/form';
|
import { Rule } from 'ant-design-vue/lib/form';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
@ -118,7 +117,6 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const providerList = ref([]);
|
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const id = props.data.id;
|
const id = props.data.id;
|
||||||
|
@ -136,9 +134,8 @@ const formData = ref({
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const handleOk = async () => {
|
||||||
const data = await formRef.value?.validate();
|
const data = await formRef.value?.validate();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
...props.data,
|
...props.data,
|
||||||
...data,
|
...data,
|
||||||
|
@ -148,17 +145,12 @@ const onSubmit = async () => {
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await savePoint(params)
|
? await savePoint(params).catch(() => {})
|
||||||
: await updatePoint(id, { ...props.data, ...params });
|
: await updatePoint(id, { ...props.data, ...params }).catch(() => {});
|
||||||
if (response.status === 200) {
|
emit('change', response?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
onSubmit();
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
@ -180,15 +172,17 @@ watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value.id && value.provider === 'OPC_UA') {
|
if (value.id && value.provider === 'OPC_UA') {
|
||||||
const _value = cloneDeep(value);
|
const _value: any = cloneDeep(value);
|
||||||
formData.value = _value;
|
formData.value = _value;
|
||||||
if (!!_value.accessModes[0]?.value) {
|
if (!!_value.accessModes[0]?.value) {
|
||||||
formData.value.accessModes = value.accessModes.map(
|
formData.value.accessModes = value.accessModes.map(
|
||||||
(i) => i.value,
|
(i: any) => i.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!!_value.features[0]?.value) {
|
if (!!_value.features[0]?.value) {
|
||||||
formData.value.features = value.features.map((i) => i.value);
|
formData.value.features = value.features.map(
|
||||||
|
(i: any) => i.value,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<j-form style="width: 80%" ref="formTableRef" :model="modelRef">
|
<j-form class="table" ref="formTableRef" :model="modelRef">
|
||||||
<j-table
|
<j-table
|
||||||
:dataSource="modelRef.dataSource"
|
:dataSource="modelRef.dataSource"
|
||||||
:columns="FormTableColumns"
|
:columns="FormTableColumns"
|
||||||
:scroll="{ x: 1100, y: 500 }"
|
:scroll="{ x: 1000, y: 550 }"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column: { dataIndex }, record, index }">
|
<template #bodyCell="{ column: { dataIndex }, record, index }">
|
||||||
<template v-if="dataIndex === 'name'">
|
<template v-if="dataIndex === 'name'">
|
||||||
|
@ -25,8 +25,11 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-if="dataIndex === 'id'">
|
<template v-if="dataIndex === 'id'">
|
||||||
<a-form-item :name="['dataSource', index, 'id']">
|
<a-form-item :name="['dataSource', index, 'id']">
|
||||||
<j-input v-model:value="record[dataIndex]" disabled>
|
<j-input
|
||||||
</j-input>
|
v-model:value="record[dataIndex]"
|
||||||
|
disabled
|
||||||
|
:bordered="false"
|
||||||
|
></j-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -78,8 +81,12 @@
|
||||||
]"
|
]"
|
||||||
:rules="[
|
:rules="[
|
||||||
{
|
{
|
||||||
required: true,
|
pattern: regOnlyNumber,
|
||||||
message: '请输入',
|
message: '请输入0或者正整数',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: checkLength,
|
||||||
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
|
@ -98,7 +105,7 @@
|
||||||
@blur="changeValue(index, dataIndex)"
|
@blur="changeValue(index, dataIndex)"
|
||||||
></j-input>
|
></j-input>
|
||||||
<j-checkbox
|
<j-checkbox
|
||||||
style="margin-left: 5px"
|
style="margin-left: 5px; margin-top: 5px"
|
||||||
v-show="index !== 0"
|
v-show="index !== 0"
|
||||||
v-model:checked="
|
v-model:checked="
|
||||||
record.configuration[dataIndex].check
|
record.configuration[dataIndex].check
|
||||||
|
@ -151,14 +158,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="dataIndex === 'action'">
|
<template v-if="dataIndex === 'action'">
|
||||||
<a-tooltip title="删除">
|
<j-tooltip title="删除">
|
||||||
<a-popconfirm
|
<j-popconfirm
|
||||||
title="确认删除"
|
title="确认删除"
|
||||||
@confirm="clickDelete(record.id)"
|
@confirm="clickDelete(record.id)"
|
||||||
>
|
>
|
||||||
<AIcon type="DeleteOutlined" />
|
<a><AIcon type="DeleteOutlined" /></a>
|
||||||
</a-popconfirm>
|
</j-popconfirm>
|
||||||
</a-tooltip>
|
</j-tooltip>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</j-table>
|
</j-table>
|
||||||
|
@ -166,7 +173,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { FormTableColumns } from '../../data';
|
import { FormTableColumns, regOnlyNumber } from '../../data';
|
||||||
|
import { Rule } from 'ant-design-vue/lib/form';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -177,10 +186,19 @@ const emits = defineEmits(['change']);
|
||||||
|
|
||||||
const formTableRef = ref();
|
const formTableRef = ref();
|
||||||
const defaultType = ['accessModes', 'interval', 'features'];
|
const defaultType = ['accessModes', 'interval', 'features'];
|
||||||
const modelRef = reactive({
|
const modelRef: any = reactive({
|
||||||
dataSource: [],
|
dataSource: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const checkLength = (_rule: Rule, value: string): Promise<any> =>
|
||||||
|
new Promise(async (resolve, reject) => {
|
||||||
|
if (value) {
|
||||||
|
return String(value).length > 64
|
||||||
|
? reject('最多可输入64个字符')
|
||||||
|
: resolve('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (input: string, option: any) => {
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||||
};
|
};
|
||||||
|
@ -268,6 +286,7 @@ watch(
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
.table {}
|
||||||
.form-item {
|
.form-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,14 @@
|
||||||
</div>
|
</div>
|
||||||
<j-spin :spinning="spinning">
|
<j-spin :spinning="spinning">
|
||||||
<a-tree
|
<a-tree
|
||||||
v-model:checkedKeys="checkedKeys"
|
v-if="!!treeData"
|
||||||
:tree-data="treeData"
|
|
||||||
default-expand-all
|
|
||||||
checkable
|
|
||||||
@check="onCheck"
|
|
||||||
:height="600"
|
|
||||||
>
|
|
||||||
<!-- <a-tree
|
|
||||||
:load-data="onLoadData"
|
:load-data="onLoadData"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
v-model:checkedKeys="checkedKeys"
|
v-model:checkedKeys="checkedKeys"
|
||||||
checkable
|
checkable
|
||||||
@check="onCheck"
|
@check="onCheck"
|
||||||
> -->
|
:height="600"
|
||||||
|
>
|
||||||
<template #title="{ name, key }">
|
<template #title="{ name, key }">
|
||||||
<span
|
<span
|
||||||
:class="[
|
:class="[
|
||||||
|
@ -32,6 +26,7 @@
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</a-tree>
|
</a-tree>
|
||||||
|
<j-empty v-else />
|
||||||
</j-spin>
|
</j-spin>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -56,7 +51,6 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
const emits = defineEmits(['change']);
|
const emits = defineEmits(['change']);
|
||||||
|
|
||||||
// const channelId = '1610517801347788800'; //测试
|
|
||||||
const channelId = props.data?.channelId;
|
const channelId = props.data?.channelId;
|
||||||
|
|
||||||
const checkedKeys = ref<string[]>([]);
|
const checkedKeys = ref<string[]>([]);
|
||||||
|
@ -73,12 +67,12 @@ const onLoadData = (node: any) =>
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const resp = await scanOpcUAList({
|
const resp: any = await scanOpcUAList({
|
||||||
id: channelId,
|
id: channelId,
|
||||||
nodeId: node.key,
|
nodeId: node.key,
|
||||||
});
|
});
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const list = resp.result.map((item: any) => {
|
const list: any = resp.result.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
key: item.id,
|
key: item.id,
|
||||||
|
@ -97,13 +91,13 @@ const onLoadData = (node: any) =>
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleData = (arr: any[]): any[] => {
|
const handleData = (arr: any): any[] => {
|
||||||
const data = arr.filter((item) => {
|
const data = arr.filter((item: any) => {
|
||||||
return (
|
return (
|
||||||
(isSelected && !selectKeys.value.includes(item.id)) || !isSelected
|
(isSelected && !selectKeys.value.includes(item.id)) || !isSelected
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return data.map((item) => {
|
return data.map((item: any) => {
|
||||||
if (item.children && item.children?.length) {
|
if (item.children && item.children?.length) {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
|
@ -115,7 +109,7 @@ const handleData = (arr: any[]): any[] => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onCheck = (checkedKeys, info) => {
|
const onCheck = (checkedKeys: any, info: any) => {
|
||||||
const one: any = { ...info.node };
|
const one: any = { ...info.node };
|
||||||
const list: any = [];
|
const list: any = [];
|
||||||
const last: any = list.length ? list[list.length - 1] : undefined;
|
const last: any = list.length ? list[list.length - 1] : undefined;
|
||||||
|
@ -149,8 +143,8 @@ const onCheck = (checkedKeys, info) => {
|
||||||
emits('change', item, info.checked);
|
emits('change', item, info.checked);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTreeData = (list: any[], key: string, children: any[]): any[] => {
|
const updateTreeData = (list: any, key: string, children: any[]): any[] => {
|
||||||
const arr = list.map((node) => {
|
const arr = list.map((node: any) => {
|
||||||
if (node.key === key) {
|
if (node.key === key) {
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
|
@ -170,44 +164,41 @@ const updateTreeData = (list: any[], key: string, children: any[]): any[] => {
|
||||||
|
|
||||||
const getPoint = async () => {
|
const getPoint = async () => {
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
const res = await queryPointNoPaging();
|
const res: any = await queryPointNoPaging();
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
selectKeys.value = res.result.map((item: any) => item.pointKey);
|
selectKeys.value = res.result.map((item: any) => item.pointKey);
|
||||||
}
|
}
|
||||||
|
getScanOpcUAList();
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
};
|
};
|
||||||
getPoint();
|
getPoint();
|
||||||
|
|
||||||
const getScanOpcUAList = async () => {
|
const getScanOpcUAList = async () => {
|
||||||
const res = await scanOpcUAList({ id: channelId });
|
spinning.value = true;
|
||||||
|
const res: any = await scanOpcUAList({ id: channelId });
|
||||||
treeAllData.value = res.result.map((item: any) => ({
|
treeAllData.value = res.result.map((item: any) => ({
|
||||||
...item,
|
...item,
|
||||||
key: item.id,
|
key: item.id,
|
||||||
title: item.name,
|
title: item.name,
|
||||||
disabled: item?.folder || false,
|
disabled: item?.folder || false,
|
||||||
}));
|
}));
|
||||||
|
spinning.value = false;
|
||||||
};
|
};
|
||||||
getScanOpcUAList();
|
// getScanOpcUAList();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => isSelected.value,
|
() => isSelected.value,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (value) {
|
treeData.value = value
|
||||||
treeData.value = handleData(treeAllData.value);
|
? handleData(treeAllData.value)
|
||||||
} else {
|
: treeAllData.value;
|
||||||
treeData.value = treeAllData.value;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
watch(
|
watch(
|
||||||
() => treeAllData.value,
|
() => treeAllData.value,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (isSelected.value) {
|
treeData.value = isSelected.value ? handleData(value) : value;
|
||||||
treeData.value = handleData(value);
|
|
||||||
} else {
|
|
||||||
treeData.value = value;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
);
|
);
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
import type { FormInstance } from 'ant-design-vue';
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
import { savePointBatch } from '@/api/data-collect/collector';
|
import { savePointBatch } from '@/api/data-collect/collector';
|
||||||
import { Rule } from 'ant-design-vue/lib/form';
|
import { Rule } from 'ant-design-vue/lib/form';
|
||||||
import { cloneDeep } from 'lodash';
|
|
||||||
|
|
||||||
import Table from './Table.vue';
|
import Table from './Table.vue';
|
||||||
import Tree from './Tree.vue';
|
import Tree from './Tree.vue';
|
||||||
|
@ -55,8 +54,8 @@ const tableDataMap = new Map();
|
||||||
const unSelectKeys = ref();
|
const unSelectKeys = ref();
|
||||||
|
|
||||||
const handleOk = async () => {
|
const handleOk = async () => {
|
||||||
loading.value = true;
|
const data: any = await formTableRef.value?.validate().catch(() => {});
|
||||||
const data = await formTableRef.value?.validate();
|
if (!data) return;
|
||||||
const list = data.map((item: any) => {
|
const list = data.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
@ -71,11 +70,9 @@ const handleOk = async () => {
|
||||||
accessModes: item.accessModes?.value || [],
|
accessModes: item.accessModes?.value || [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
console.log(1112, props.data, data, list);
|
loading.value = true;
|
||||||
const resp = await savePointBatch([...list]);
|
const resp = await savePointBatch([...list]).catch(() => {});
|
||||||
if (resp.status === 200) {
|
emit('change', resp?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
ref="formRef"
|
ref="formRef"
|
||||||
>
|
>
|
||||||
<j-form-item label="访问类型" name="accessModes">
|
<j-form-item label="访问类型" name="accessModes">
|
||||||
<j-checkbox-group
|
<j-card-select
|
||||||
|
multiple
|
||||||
|
:showImage="false"
|
||||||
v-model:value="formData.accessModes"
|
v-model:value="formData.accessModes"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '读', value: 'read' },
|
{ label: '读', value: 'read' },
|
||||||
|
@ -28,7 +30,19 @@
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item :name="['interval']">
|
<j-form-item
|
||||||
|
:name="['interval']"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
pattern: regOnlyNumber,
|
||||||
|
message: '请输入0或者正整数',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: checkLength,
|
||||||
|
trigger: 'change',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span>
|
<span>
|
||||||
采集频率
|
采集频率
|
||||||
|
@ -40,11 +54,10 @@
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<j-input-number
|
<j-input
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
placeholder="请输入采集频率"
|
placeholder="请输入采集频率"
|
||||||
v-model:value="formData.interval"
|
v-model:value="formData.interval"
|
||||||
:min="1"
|
|
||||||
addon-after="ms"
|
addon-after="ms"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
@ -77,6 +90,7 @@ import type { FormInstance } from 'ant-design-vue';
|
||||||
import { savePointBatch } from '@/api/data-collect/collector';
|
import { savePointBatch } from '@/api/data-collect/collector';
|
||||||
import { Rule } from 'ant-design-vue/lib/form';
|
import { Rule } from 'ant-design-vue/lib/form';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
|
import { regOnlyNumber } from '../../../data';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -104,8 +118,8 @@ const checkLength = (_rule: Rule, value: string): Promise<any> =>
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const handleOk = async () => {
|
||||||
const data = await formRef.value?.validate();
|
const data: any = await formRef.value?.validate();
|
||||||
const { accessModes, features, interval } = data;
|
const { accessModes, features, interval } = data;
|
||||||
const ischange =
|
const ischange =
|
||||||
accessModes.length !== 0 || features.length !== 0 || !!interval;
|
accessModes.length !== 0 || features.length !== 0 || !!interval;
|
||||||
|
@ -123,19 +137,14 @@ const onSubmit = async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = await savePointBatch(params);
|
const response = await savePointBatch(params).catch(() => {});
|
||||||
if (response.status === 200) {
|
emit('change', response?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
} else {
|
} else {
|
||||||
emit('change', true);
|
emit('change', true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
onSubmit();
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,8 +78,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BadgeStatus from '@/components/BadgeStatus/index.vue';
|
import type { ActionsType } from '@/components/Table/index';
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
type EmitProps = {
|
type EmitProps = {
|
||||||
|
@ -146,19 +145,20 @@ const handleClick = () => {
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background-color: red;
|
|
||||||
background-color: #2f54eb;
|
background-color: #2f54eb;
|
||||||
transform: rotate(-45deg);
|
transform: rotate(-45deg);
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
right: -2px;
|
||||||
|
bottom: -4px;
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
|
|
||||||
> span {
|
> span {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
// top: 6px;
|
||||||
left: 6px;
|
// left: 6px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,7 @@ const loading = ref(false);
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const collectorId = props.data.collectorId;
|
const collectorId = props.data.collectorId;
|
||||||
const pointId = props.data.id;
|
const pointId: string = props.data.id;
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
value: '',
|
value: '',
|
||||||
|
@ -140,23 +140,18 @@ const onChange = (value: Dayjs, dateString: string) => {
|
||||||
formData.value.value = dateString;
|
formData.value.value = dateString;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const handleOk = async () => {
|
||||||
const data = await formRef.value?.validate();
|
const data = await formRef.value?.validate();
|
||||||
const params = {
|
const params: any = {
|
||||||
...data,
|
...data,
|
||||||
pointId,
|
pointId,
|
||||||
};
|
};
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = await writePoint(collectorId, [params]);
|
const response = await writePoint(collectorId, [params]).catch(() => {});
|
||||||
if (response.status === 200) {
|
emit('change', response?.status === 200);
|
||||||
emit('change', true);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
onSubmit();
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<j-spin :spinning="spinning">
|
<j-spin :spinning="spinning">
|
||||||
<j-advanced-search
|
<pro-search :columns="columns" target="search" @search="handleSearch" />
|
||||||
:columns="columns"
|
|
||||||
target="search"
|
|
||||||
@search="handleSearch"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<j-pro-table
|
<j-pro-table
|
||||||
ref="tableRef"
|
ref="tableRef"
|
||||||
model="CARD"
|
model="CARD"
|
||||||
|
@ -77,6 +72,16 @@
|
||||||
</template>
|
</template>
|
||||||
</j-dropdown>
|
</j-dropdown>
|
||||||
</j-space>
|
</j-space>
|
||||||
|
<div
|
||||||
|
v-if="data?.provider === 'OPC_UA'"
|
||||||
|
style="margin-top: 15px"
|
||||||
|
>
|
||||||
|
<j-checkbox
|
||||||
|
v-model:checked="checkAll"
|
||||||
|
@change="onCheckAllChange"
|
||||||
|
>全选</j-checkbox
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #card="slotProps">
|
<template #card="slotProps">
|
||||||
<PointCardBox
|
<PointCardBox
|
||||||
|
@ -98,18 +103,14 @@
|
||||||
</template>
|
</template>
|
||||||
<template #action>
|
<template #action>
|
||||||
<div class="card-box-action">
|
<div class="card-box-action">
|
||||||
<a>
|
<j-popconfirm
|
||||||
<j-popconfirm
|
title="确定删除?"
|
||||||
title="确定删除?"
|
@confirm="handlDelete(slotProps.id)"
|
||||||
@confirm="handlDelete(slotProps.id)"
|
>
|
||||||
>
|
<a><AIcon type="DeleteOutlined" /></a>
|
||||||
<AIcon type="DeleteOutlined" />
|
</j-popconfirm>
|
||||||
</j-popconfirm>
|
<a @click="handlEdit(slotProps)"
|
||||||
</a>
|
><AIcon type="FormOutlined"
|
||||||
<a
|
|
||||||
><AIcon
|
|
||||||
@click="handlEdit(slotProps)"
|
|
||||||
type="FormOutlined"
|
|
||||||
/></a>
|
/></a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -125,28 +126,62 @@
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="card-box-content">
|
<div class="card-box-content">
|
||||||
<div class="card-box-content-left">
|
<div class="card-box-content-left">
|
||||||
<span>--</span>
|
<div class="card-box-content-left-1">
|
||||||
<a
|
<div
|
||||||
v-if="
|
class="ard-box-content-left-1-title"
|
||||||
getAccessModes(slotProps).includes(
|
v-if="propertyValue.has(slotProps.id)"
|
||||||
'write',
|
>
|
||||||
)
|
<j-ellipsis style="max-width: 150px">
|
||||||
"
|
{{
|
||||||
><AIcon
|
propertyValue.get(slotProps.id)
|
||||||
|
?.parseData[0] || 0
|
||||||
|
}}({{
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.dataType
|
||||||
|
}})
|
||||||
|
</j-ellipsis>
|
||||||
|
</div>
|
||||||
|
<span v-else>--</span>
|
||||||
|
<a
|
||||||
|
v-if="
|
||||||
|
getAccessModes(slotProps).includes(
|
||||||
|
'write',
|
||||||
|
)
|
||||||
|
"
|
||||||
@click.stop="clickEdit(slotProps)"
|
@click.stop="clickEdit(slotProps)"
|
||||||
type="EditOutlined"
|
><AIcon type="EditOutlined"
|
||||||
/></a>
|
/></a>
|
||||||
<a
|
<a
|
||||||
v-if="
|
v-if="
|
||||||
getAccessModes(slotProps).includes(
|
getAccessModes(slotProps).includes(
|
||||||
'read',
|
'read',
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
><AIcon
|
|
||||||
@click.stop="clickRedo(slotProps)"
|
@click.stop="clickRedo(slotProps)"
|
||||||
type="RedoOutlined"
|
><AIcon type="RedoOutlined"
|
||||||
/></a>
|
/></a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="propertyValue.has(slotProps.id)"
|
||||||
|
class="card-box-content-right-2"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.hex || ''
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{
|
||||||
|
moment(
|
||||||
|
propertyValue.get(slotProps.id)
|
||||||
|
?.timestamp,
|
||||||
|
).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-box-content-right">
|
<div class="card-box-content-right">
|
||||||
<div
|
<div
|
||||||
v-if="getRight1(slotProps)"
|
v-if="getRight1(slotProps)"
|
||||||
|
@ -198,7 +233,6 @@ import {
|
||||||
readPoint,
|
readPoint,
|
||||||
} from '@/api/data-collect/collector';
|
} from '@/api/data-collect/collector';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import { useMenuStore } from 'store/menu';
|
|
||||||
import PointCardBox from './components/PointCardBox/index.vue';
|
import PointCardBox from './components/PointCardBox/index.vue';
|
||||||
import WritePoint from './components/WritePoint/index.vue';
|
import WritePoint from './components/WritePoint/index.vue';
|
||||||
import BatchUpdate from './components/BatchUpdate/index.vue';
|
import BatchUpdate from './components/BatchUpdate/index.vue';
|
||||||
|
@ -207,6 +241,9 @@ import SaveOPCUA from './Save/SaveOPCUA.vue';
|
||||||
import Scan from './Scan/index.vue';
|
import Scan from './Scan/index.vue';
|
||||||
import { colorMap, getState } from '../data.ts';
|
import { colorMap, getState } from '../data.ts';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
|
import { getWebSocket } from '@/utils/websocket';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
|
@ -215,7 +252,6 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const menuStory = useMenuStore();
|
|
||||||
const tableRef = ref<Record<string, any>>({});
|
const tableRef = ref<Record<string, any>>({});
|
||||||
const params = ref<Record<string, any>>({});
|
const params = ref<Record<string, any>>({});
|
||||||
const opcImage = getImage('/DataCollect/device-opcua.png');
|
const opcImage = getImage('/DataCollect/device-opcua.png');
|
||||||
|
@ -227,10 +263,10 @@ const visible = reactive({
|
||||||
batchUpdate: false,
|
batchUpdate: false,
|
||||||
scan: false,
|
scan: false,
|
||||||
});
|
});
|
||||||
const current = ref({});
|
const current: any = ref({});
|
||||||
const accessModesOption = ref();
|
const accessModesOption = ref();
|
||||||
const _selectedRowKeys = ref<string[]>([]);
|
const _selectedRowKeys = ref<string[]>([]);
|
||||||
|
const checkAll = ref(false);
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
const collectorId = ref(props.data.id);
|
const collectorId = ref(props.data.id);
|
||||||
|
|
||||||
|
@ -242,7 +278,6 @@ const defaultParams = ref({
|
||||||
{
|
{
|
||||||
column: 'collectorId',
|
column: 'collectorId',
|
||||||
value: collectorId.value,
|
value: collectorId.value,
|
||||||
// value: '1610517928766550016', //测试
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -332,6 +367,9 @@ const columns = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const subRef = ref();
|
||||||
|
const propertyValue = ref(new Map());
|
||||||
|
|
||||||
const handlAdd = () => {
|
const handlAdd = () => {
|
||||||
visible.saveModBus = true;
|
visible.saveModBus = true;
|
||||||
current.value = {
|
current.value = {
|
||||||
|
@ -339,7 +377,7 @@ const handlAdd = () => {
|
||||||
provider: props.data?.provider || 'MODBUS_TCP',
|
provider: props.data?.provider || 'MODBUS_TCP',
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const handlEdit = (data: Object) => {
|
const handlEdit = (data: any) => {
|
||||||
if (data?.provider === 'OPC_UA') {
|
if (data?.provider === 'OPC_UA') {
|
||||||
visible.saveOPCUA = true;
|
visible.saveOPCUA = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -347,12 +385,12 @@ const handlEdit = (data: Object) => {
|
||||||
}
|
}
|
||||||
current.value = cloneDeep(data);
|
current.value = cloneDeep(data);
|
||||||
};
|
};
|
||||||
const handlDelete = async (data: string | undefined = undefined) => {
|
const handlDelete = async (id: string | undefined = undefined) => {
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
const res = !data
|
const res = !id
|
||||||
? await batchDeletePoint(_selectedRowKeys.value)
|
? await batchDeletePoint(_selectedRowKeys.value).catch(() => {})
|
||||||
: await removePoint(data as string);
|
: await removePoint(id as string).catch(() => {});
|
||||||
if (res.status === 200) {
|
if (res?.status === 200) {
|
||||||
cancelSelect();
|
cancelSelect();
|
||||||
tableRef.value?.reload();
|
tableRef.value?.reload();
|
||||||
message.success('操作成功');
|
message.success('操作成功');
|
||||||
|
@ -360,9 +398,13 @@ const handlDelete = async (data: string | undefined = undefined) => {
|
||||||
spinning.value = false;
|
spinning.value = false;
|
||||||
};
|
};
|
||||||
const handlBatchUpdate = () => {
|
const handlBatchUpdate = () => {
|
||||||
|
if (_selectedRowKeys.value.length === 0) {
|
||||||
|
message.warn('请先选择');
|
||||||
|
return;
|
||||||
|
}
|
||||||
const dataSet = new Set(_selectedRowKeys.value);
|
const dataSet = new Set(_selectedRowKeys.value);
|
||||||
const dataMap = new Map();
|
const dataMap = new Map();
|
||||||
tableRef?.value?._dataSource.forEach((i) => {
|
tableRef?.value?._dataSource.forEach((i: any) => {
|
||||||
dataSet.has(i.id) && dataMap.set(i.id, i);
|
dataSet.has(i.id) && dataMap.set(i.id, i);
|
||||||
});
|
});
|
||||||
current.value = [...dataMap.values()];
|
current.value = [...dataMap.values()];
|
||||||
|
@ -376,7 +418,7 @@ const clickEdit = async (data: object) => {
|
||||||
visible.writePoint = true;
|
visible.writePoint = true;
|
||||||
current.value = cloneDeep(data);
|
current.value = cloneDeep(data);
|
||||||
};
|
};
|
||||||
const clickRedo = async (data: object) => {
|
const clickRedo = async (data: any) => {
|
||||||
const res = await readPoint(data?.collectorId, [data?.id]);
|
const res = await readPoint(data?.collectorId, [data?.id]);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
cancelSelect();
|
cancelSelect();
|
||||||
|
@ -401,14 +443,14 @@ const getRight1 = (item: Partial<Record<string, any>>) => {
|
||||||
return !!getQuantity(item) || getAddress(item) || getScaleFactor(item);
|
return !!getQuantity(item) || getAddress(item) || getScaleFactor(item);
|
||||||
};
|
};
|
||||||
const getText = (item: Partial<Record<string, any>>) => {
|
const getText = (item: Partial<Record<string, any>>) => {
|
||||||
return (item?.accessModes || []).map((i) => i?.text).join(',');
|
return (item?.accessModes || []).map((i: any) => i?.text).join(',');
|
||||||
};
|
};
|
||||||
const getInterval = (item: Partial<Record<string, any>>) => {
|
const getInterval = (item: Partial<Record<string, any>>) => {
|
||||||
const { interval } = item.configuration || '';
|
const { interval } = item.configuration || '';
|
||||||
return !!interval ? '采集频率' + interval + 'ms' : '';
|
return !!interval ? '采集频率' + interval + 'ms' : '';
|
||||||
};
|
};
|
||||||
const getAccessModes = (item: Partial<Record<string, any>>) => {
|
const getAccessModes = (item: Partial<Record<string, any>>) => {
|
||||||
return item?.accessModes?.map((i) => i?.value);
|
return item?.accessModes?.map((i: any) => i?.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveChange = (value: object) => {
|
const saveChange = (value: object) => {
|
||||||
|
@ -431,33 +473,94 @@ const cancelSelect = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = (dt: any) => {
|
const handleClick = (dt: any) => {
|
||||||
|
if (props.data?.provider !== 'OPC_UA') return;
|
||||||
if (_selectedRowKeys.value.includes(dt.id)) {
|
if (_selectedRowKeys.value.includes(dt.id)) {
|
||||||
const _index = _selectedRowKeys.value.findIndex((i) => i === dt.id);
|
const _index = _selectedRowKeys.value.findIndex((i) => i === dt.id);
|
||||||
_selectedRowKeys.value.splice(_index, 1);
|
_selectedRowKeys.value.splice(_index, 1);
|
||||||
|
checkAll.value = false;
|
||||||
} else {
|
} else {
|
||||||
_selectedRowKeys.value = [..._selectedRowKeys.value, dt.id];
|
_selectedRowKeys.value = [..._selectedRowKeys.value, dt.id];
|
||||||
|
if (
|
||||||
|
_selectedRowKeys.value.length === tableRef.value?._dataSource.length
|
||||||
|
) {
|
||||||
|
checkAll.value = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const subscribeProperty = (value: any) => {
|
||||||
|
const list = value.map((item: any) => item.id);
|
||||||
|
const id = `collector-${props.data?.channelId || 'channel'}-${
|
||||||
|
props.data?.id || 'point'
|
||||||
|
}-data-${list.join('-')}`;
|
||||||
|
const topic = `/collector/${props.data?.channelId || '*'}/${
|
||||||
|
props.data?.id || '*'
|
||||||
|
}/data`;
|
||||||
|
subRef.value = getWebSocket(id, topic, {
|
||||||
|
pointId: list.join(','),
|
||||||
|
})
|
||||||
|
?.pipe(map((res: any) => res.payload))
|
||||||
|
.subscribe((payload: any) => {
|
||||||
|
propertyValue.value.set(payload.pointId, payload);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCheckAllChange = (e: any) => {
|
||||||
|
if (e.target.checked) {
|
||||||
|
_selectedRowKeys.value = [
|
||||||
|
...tableRef.value?._dataSource.map((i: any) => i.id),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
cancelSelect();
|
||||||
|
checkAll.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => tableRef?.value?._dataSource,
|
||||||
|
(value) => {
|
||||||
|
if (value.length !== 0) {
|
||||||
|
subscribeProperty(value);
|
||||||
|
}
|
||||||
|
cancelSelect();
|
||||||
|
checkAll.value = false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => _selectedRowKeys.value,
|
||||||
|
(value) => {
|
||||||
|
if (value.length === 0) {
|
||||||
|
checkAll.value = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.data,
|
() => props.data,
|
||||||
(value) => {
|
(value) => {
|
||||||
if (!!value) {
|
if (!!value) {
|
||||||
accessModesOption.value =
|
accessModesOption.value =
|
||||||
value.provider === 'MODBUS_TCP'
|
value?.provider === 'MODBUS_TCP'
|
||||||
? accessModesMODBUS_TCP
|
? accessModesMODBUS_TCP
|
||||||
: accessModesMODBUS_TCP.concat({
|
: accessModesMODBUS_TCP.concat({
|
||||||
label: '订阅',
|
label: '订阅',
|
||||||
value: 'subscribe',
|
value: 'subscribe',
|
||||||
});
|
});
|
||||||
defaultParams.value.terms[0].terms[0].value = value.id;
|
defaultParams.value.terms[0].terms[0].value = value.id;
|
||||||
// defaultParams.value.terms[0].terms[0].value = '1610517928766550016'; //测试
|
|
||||||
tableRef?.value?.reload && tableRef?.value?.reload();
|
tableRef?.value?.reload && tableRef?.value?.reload();
|
||||||
|
cancelSelect();
|
||||||
|
checkAll.value = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (subRef.value) {
|
||||||
|
subRef.value?.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索
|
* 搜索
|
||||||
* @param params
|
* @param params
|
||||||
|
@ -489,15 +592,22 @@ const handleSearch = (e: any) => {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
.card-box-content {
|
.card-box-content {
|
||||||
margin-top: 10px;
|
margin-top: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
.card-box-content-left {
|
.card-box-content-left {
|
||||||
flex: 0.2;
|
max-width: 220px;
|
||||||
border-right: 1px solid #e0e4e8;
|
border-right: 1px solid #e0e4e8;
|
||||||
height: 68px;
|
height: 68px;
|
||||||
padding-right: 20px;
|
padding-right: 10px;
|
||||||
display: flex;
|
.card-box-content-left-1 {
|
||||||
justify-content: flex-start;
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
.card-box-content-left-1-title {
|
||||||
|
color: #000;
|
||||||
|
font-size: 20px;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
a {
|
a {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,13 @@
|
||||||
:model="formData"
|
:model="formData"
|
||||||
name="basic"
|
name="basic"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
|
ref="formRef"
|
||||||
>
|
>
|
||||||
<j-form-item label="所属通道" v-bind="validateInfos.channelId">
|
<j-form-item
|
||||||
|
label="所属通道"
|
||||||
|
name="channelId"
|
||||||
|
:rules="LeftTreeRules.channelId"
|
||||||
|
>
|
||||||
<j-select
|
<j-select
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
v-model:value="formData.channelId"
|
v-model:value="formData.channelId"
|
||||||
|
@ -24,7 +29,11 @@
|
||||||
:disabled="!!id"
|
:disabled="!!id"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="采集器名称" v-bind="validateInfos.name">
|
<j-form-item
|
||||||
|
label="采集器名称"
|
||||||
|
name="name"
|
||||||
|
:rules="LeftTreeRules.name"
|
||||||
|
>
|
||||||
<j-input
|
<j-input
|
||||||
placeholder="请输入采集器名称"
|
placeholder="请输入采集器名称"
|
||||||
v-model:value="formData.name"
|
v-model:value="formData.name"
|
||||||
|
@ -32,8 +41,9 @@
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
label="从机地址"
|
label="从机地址"
|
||||||
v-bind="validateInfos['configuration.unitId']"
|
:name="['configuration', 'unitId']"
|
||||||
v-if="visibleUnitId"
|
v-if="visibleUnitId"
|
||||||
|
:rules="LeftTreeRules.unitId"
|
||||||
>
|
>
|
||||||
<j-input-number
|
<j-input-number
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@ -43,8 +53,10 @@
|
||||||
:max="255"
|
:max="255"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
<j-form-item v-bind="validateInfos['circuitBreaker.type']">
|
:name="['circuitBreaker', 'type']"
|
||||||
|
:rules="LeftTreeRules.type"
|
||||||
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span>
|
<span>
|
||||||
故障处理
|
故障处理
|
||||||
|
@ -60,20 +72,21 @@
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<RadioCard
|
<j-card-select
|
||||||
layout="horizontal"
|
:showImage="false"
|
||||||
:checkStyle="true"
|
v-model:value="formData.circuitBreaker.type"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '降频', value: 'LowerFrequency' },
|
{ label: '降频', value: 'LowerFrequency' },
|
||||||
{ label: '熔断', value: 'Break' },
|
{ label: '熔断', value: 'Break' },
|
||||||
{ label: '忽略', value: 'Ignore' },
|
{ label: '忽略', value: 'Ignore' },
|
||||||
]"
|
]"
|
||||||
v-model="formData.circuitBreaker.type"
|
@change="changeCardSelectType"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item
|
<j-form-item
|
||||||
v-bind="validateInfos['configuration.endian']"
|
:name="['configuration', 'endian']"
|
||||||
v-if="visibleEndian"
|
v-if="visibleEndian"
|
||||||
|
:rules="LeftTreeRules.endian"
|
||||||
>
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
<span>
|
<span>
|
||||||
|
@ -86,17 +99,17 @@
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<RadioCard
|
<j-card-select
|
||||||
layout="horizontal"
|
:showImage="false"
|
||||||
:checkStyle="true"
|
v-model:value="formData.configuration.endian"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: 'AB', value: 'BIG' },
|
{ label: 'AB', value: 'BIG' },
|
||||||
{ label: 'BA', value: 'LITTLE' },
|
{ label: 'BA', value: 'LITTLE' },
|
||||||
]"
|
]"
|
||||||
v-model="formData.configuration.endian"
|
@change="changeCardSelectEndian"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-form-item label="说明" v-bind="validateInfos.description">
|
<j-form-item label="说明" name="description">
|
||||||
<j-textarea
|
<j-textarea
|
||||||
placeholder="请输入说明"
|
placeholder="请输入说明"
|
||||||
v-model:value="formData.description"
|
v-model:value="formData.description"
|
||||||
|
@ -127,6 +140,9 @@
|
||||||
import { Form } from 'ant-design-vue';
|
import { Form } from 'ant-design-vue';
|
||||||
import { save, update } from '@/api/data-collect/collector';
|
import { save, update } from '@/api/data-collect/collector';
|
||||||
import { Store } from 'jetlinks-store';
|
import { Store } from 'jetlinks-store';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
import { LeftTreeRules } from '../../data';
|
||||||
|
import type { FormInstance } from 'ant-design-vue';
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const useForm = Form.useForm;
|
const useForm = Form.useForm;
|
||||||
|
@ -145,6 +161,7 @@ const props = defineProps({
|
||||||
const emit = defineEmits(['change']);
|
const emit = defineEmits(['change']);
|
||||||
|
|
||||||
const id = props.data.id;
|
const id = props.data.id;
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
channelId: undefined,
|
channelId: undefined,
|
||||||
|
@ -160,58 +177,26 @@ const formData = ref({
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const regOnlyNumber = new RegExp(/^\d+$/);
|
const handleOk = async () => {
|
||||||
|
const data = await formRef.value?.validate();
|
||||||
|
|
||||||
const { resetFields, validate, validateInfos } = useForm(
|
const { provider, name } = channelListAll.value.find(
|
||||||
formData,
|
(item: any) => item.id === formData.value.channelId,
|
||||||
reactive({
|
);
|
||||||
channelId: [
|
const params = {
|
||||||
{ required: true, message: '请选择所属通道', trigger: 'blur' },
|
...data,
|
||||||
],
|
provider,
|
||||||
name: [
|
channelName: name,
|
||||||
{ required: true, message: '请输入采集器名称', trigger: 'blur' },
|
};
|
||||||
{ max: 64, message: '最多可输入64个字符' },
|
|
||||||
],
|
|
||||||
'configuration.unitId': [
|
|
||||||
{ required: true, message: '请输入从机地址', trigger: 'blur' },
|
|
||||||
{
|
|
||||||
pattern: regOnlyNumber,
|
|
||||||
message: '请输入0-255之间的正整数',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'circuitBreaker.type': [
|
|
||||||
{ required: true, message: '请选择处理方式', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
'configuration.endian': [
|
|
||||||
{ required: true, message: '请选择高低位切换', trigger: 'blur' },
|
|
||||||
],
|
|
||||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const onSubmit = () => {
|
|
||||||
validate()
|
|
||||||
.then(async (res) => {
|
|
||||||
const { provider, name } = channelListAll.value.find(
|
|
||||||
(item) => item.id === formData.value.channelId,
|
|
||||||
);
|
|
||||||
const params = {
|
|
||||||
...toRaw(formData.value),
|
|
||||||
provider,
|
|
||||||
channelName: name,
|
|
||||||
};
|
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const response = !id
|
const response = !id
|
||||||
? await save(params)
|
? await save(params)
|
||||||
: await update(id, { ...props.data, ...params });
|
: await update(id, { ...props.data, ...params });
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
emit('change', true);
|
emit('change', true);
|
||||||
}
|
}
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
loading.value = false;
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTypeTooltip = (value: string) =>
|
const getTypeTooltip = (value: string) =>
|
||||||
|
@ -221,13 +206,16 @@ const getTypeTooltip = (value: string) =>
|
||||||
? '连续10分钟异常,停止采集数据进入熔断状态,设备重新启用后恢复采集状态'
|
? '连续10分钟异常,停止采集数据进入熔断状态,设备重新启用后恢复采集状态'
|
||||||
: '忽略异常,保持原采集频率超时时间为5s';
|
: '忽略异常,保持原采集频率超时时间为5s';
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
onSubmit();
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
const handleCancel = () => {
|
||||||
emit('change', false);
|
emit('change', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeCardSelectType = (value: Array<string>) => {
|
||||||
|
formData.value.circuitBreaker.type = value[0];
|
||||||
|
};
|
||||||
|
const changeCardSelectEndian = (value: Array<string>) => {
|
||||||
|
formData.value.configuration.endian = value[0];
|
||||||
|
};
|
||||||
const getChannelNoPaging = async () => {
|
const getChannelNoPaging = async () => {
|
||||||
channelListAll.value = Store.get('channelListAll');
|
channelListAll.value = Store.get('channelListAll');
|
||||||
channelList.value = channelListAll.value.map((item) => ({
|
channelList.value = channelListAll.value.map((item) => ({
|
||||||
|
|
|
@ -20,12 +20,13 @@
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</div>
|
</div>
|
||||||
<j-spin :spinning="spinning">
|
<j-spin :spinning="spinning">
|
||||||
<a-tree
|
<j-tree
|
||||||
:tree-data="defualtDataSource"
|
:tree-data="defualtDataSource"
|
||||||
v-model:selected-keys="selectedKeys"
|
v-model:selected-keys="selectedKeys"
|
||||||
:fieldNames="{ key: 'id' }"
|
:fieldNames="{ key: 'id' }"
|
||||||
v-if="defualtDataSource[0].children.length !== 0"
|
v-if="defualtDataSource[0].children.length !== 0"
|
||||||
:height="600"
|
:height="600"
|
||||||
|
defaultExpandAll
|
||||||
>
|
>
|
||||||
<template #title="{ name, data }">
|
<template #title="{ name, data }">
|
||||||
<Ellipsis class="tree-left-title">
|
<Ellipsis class="tree-left-title">
|
||||||
|
@ -90,7 +91,7 @@
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</a-tree>
|
</j-tree>
|
||||||
<j-empty v-else description="暂无数据" />
|
<j-empty v-else description="暂无数据" />
|
||||||
</j-spin>
|
</j-spin>
|
||||||
<Save v-if="visible" :data="current" @change="saveChange" />
|
<Save v-if="visible" :data="current" @change="saveChange" />
|
||||||
|
@ -121,13 +122,13 @@ const emits = defineEmits(['change']);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const channelId = route.query?.channelId;
|
const channelId = route.query?.channelId;
|
||||||
const spinning = ref(false);
|
const spinning = ref(false);
|
||||||
const selectedKeys = ref([]);
|
const selectedKeys: any = ref([]);
|
||||||
const searchValue = ref();
|
const searchValue = ref();
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const current = ref({});
|
const current = ref({});
|
||||||
const collectorAll = ref();
|
const collectorAll = ref();
|
||||||
|
|
||||||
const defualtDataSource = ref([
|
const defualtDataSource: any = ref([
|
||||||
{
|
{
|
||||||
id: '*',
|
id: '*',
|
||||||
name: '全部',
|
name: '全部',
|
||||||
|
@ -164,7 +165,7 @@ const handlEdit = (data: object) => {
|
||||||
visible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlUpdate = async (data: object) => {
|
const handlUpdate = async (data: any) => {
|
||||||
const state = data?.state?.value;
|
const state = data?.state?.value;
|
||||||
const resp = await update(data?.id, {
|
const resp = await update(data?.id, {
|
||||||
state: state !== 'disabled' ? 'disabled' : 'enabled',
|
state: state !== 'disabled' ? 'disabled' : 'enabled',
|
||||||
|
@ -210,7 +211,7 @@ const handleSearch = async (value: string) => {
|
||||||
!!value && (params.value = value);
|
!!value && (params.value = value);
|
||||||
}
|
}
|
||||||
spinning.value = true;
|
spinning.value = true;
|
||||||
const res = await queryCollector(params.value);
|
const res: any = await queryCollector(params.value);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
defualtDataSource.value[0].children = res.result;
|
defualtDataSource.value[0].children = res.result;
|
||||||
collectorAll.value = res.result;
|
collectorAll.value = res.result;
|
||||||
|
@ -232,11 +233,14 @@ onMounted(() => {
|
||||||
getChannelNoPaging();
|
getChannelNoPaging();
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(selectedKeys, (n) => {
|
watch(
|
||||||
const key = _.isArray(n) ? n[0] : n;
|
() => selectedKeys.value,
|
||||||
const row = collectorAll.value.find((i) => i.id === key);
|
(n) => {
|
||||||
emits('change', row);
|
const key = _.isArray(n) ? n[0] : n;
|
||||||
});
|
const row = collectorAll.value.find((i: any) => i.id === key);
|
||||||
|
emits('change', row);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => searchValue.value,
|
() => searchValue.value,
|
||||||
|
@ -249,7 +253,7 @@ watch(
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.tree-container {
|
.tree-container {
|
||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
|
width: 300px;
|
||||||
.add-btn {
|
.add-btn {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const getState = (record: any) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const regOnlyNumber = new RegExp(/^\d+$/);
|
export const regOnlyNumber = new RegExp(/^\d+$/);
|
||||||
|
|
||||||
export const checkProviderData = {
|
export const checkProviderData = {
|
||||||
int8: 1,
|
int8: 1,
|
||||||
|
@ -93,7 +93,7 @@ export const ModBusRules = {
|
||||||
byteCount: [
|
byteCount: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入自定义数据区长度(byte)',
|
message: '请输入自定义数据区长度(byte)',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
interval: [
|
interval: [
|
||||||
|
@ -101,6 +101,10 @@ export const ModBusRules = {
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入采集频率',
|
message: '请输入采集频率',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
pattern: regOnlyNumber,
|
||||||
|
message: '请输入0或者正整数',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
|
@ -134,10 +138,31 @@ export const OPCUARules = {
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入采集频率',
|
message: '请输入采集频率',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
pattern: regOnlyNumber,
|
||||||
|
message: '请输入0或者正整数',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LeftTreeRules = {
|
||||||
|
channelId: [{ required: true, message: '请选择所属通道', trigger: 'blur' }],
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入采集器名称', trigger: 'blur' },
|
||||||
|
{ max: 64, message: '最多可输入64个字符' },
|
||||||
|
],
|
||||||
|
unitId: [
|
||||||
|
{ required: true, message: '请输入从机地址', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
pattern: regOnlyNumber,
|
||||||
|
message: '请输入0-255之间的正整数',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
type: [{ required: true, message: '请选择处理方式', trigger: 'blur' }],
|
||||||
|
endian: [{ required: true, message: '请选择高低位切换', trigger: 'blur' }],
|
||||||
|
};
|
||||||
|
|
||||||
export const FormTableColumns = [
|
export const FormTableColumns = [
|
||||||
{
|
{
|
||||||
title: '名称',
|
title: '名称',
|
||||||
|
@ -162,7 +187,7 @@ export const FormTableColumns = [
|
||||||
title: '采集频率',
|
title: '采集频率',
|
||||||
key: 'interval',
|
key: 'interval',
|
||||||
dataIndex: 'interval',
|
dataIndex: 'interval',
|
||||||
width: 280,
|
width: 260,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '只推送变化的数据',
|
title: '只推送变化的数据',
|
||||||
|
@ -174,7 +199,6 @@ export const FormTableColumns = [
|
||||||
title: '操作',
|
title: '操作',
|
||||||
key: 'action',
|
key: 'action',
|
||||||
dataIndex: 'action',
|
dataIndex: 'action',
|
||||||
|
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
width: 80,
|
width: 80,
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
<Tree @change="changeTree" />
|
<Tree @change="changeTree" />
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<Point v-if="!!data" :data="data" />
|
<j-spin :spinning="spinning">
|
||||||
|
<Point v-if="!!data" :data="data" />
|
||||||
|
<j-empty style="margin-top: 20%" v-else />
|
||||||
|
</j-spin>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</page-container>
|
</page-container>
|
||||||
|
@ -16,9 +19,11 @@ import Tree from './Tree/index.vue';
|
||||||
import Point from './Point/index.vue';
|
import Point from './Point/index.vue';
|
||||||
|
|
||||||
const data = ref();
|
const data = ref();
|
||||||
|
const spinning = ref(true);
|
||||||
|
|
||||||
const changeTree = (row: any) => {
|
const changeTree = (row: any) => {
|
||||||
data.value = row;
|
data.value = row;
|
||||||
|
spinning.value = false;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -29,6 +34,7 @@ const changeTree = (row: any) => {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: calc(100vh - 180px);
|
min-height: calc(100vh - 180px);
|
||||||
|
width: 100%;
|
||||||
.left {
|
.left {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
border-right: 1px #eeeeee solid;
|
border-right: 1px #eeeeee solid;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<j-radio-group
|
<j-radio-group
|
||||||
default-value="a"
|
|
||||||
button-style="solid"
|
button-style="solid"
|
||||||
style="margin-right: 10px"
|
style="margin-right: 10px"
|
||||||
v-model:value="data.time.type"
|
v-model:value="data.time.type"
|
||||||
|
@ -31,9 +30,7 @@
|
||||||
</j-range-picker>
|
</j-range-picker>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div ref="chartRef" style="width: 100%; height: 350px"></div>
|
||||||
<div ref="chartRef" style="width: 100%; height: 350px"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</j-spin>
|
</j-spin>
|
||||||
</template>
|
</template>
|
||||||
|
@ -63,9 +60,9 @@ const pickerTimeChange = (
|
||||||
data.value.time.type = undefined;
|
data.value.time.type = undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getEcharts = async (val) => {
|
const getEcharts = async (val: any) => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const resp = await dashboard(pointParams(val));
|
const resp: any = await dashboard(pointParams(val));
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
const x = resp.result
|
const x = resp.result
|
||||||
.map((item: any) => item.data.timeString)
|
.map((item: any) => item.data.timeString)
|
||||||
|
@ -79,7 +76,7 @@ const getEcharts = async (val) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOptions = (x = [], y = []) => {
|
const handleOptions = (x = [], y = []) => {
|
||||||
const chart = chartRef.value;
|
const chart: any = chartRef.value;
|
||||||
if (chart) {
|
if (chart) {
|
||||||
const myChart = echarts.init(chart);
|
const myChart = echarts.init(chart);
|
||||||
const options = {
|
const options = {
|
||||||
|
@ -117,7 +114,7 @@ const handleOptions = (x = [], y = []) => {
|
||||||
watch(
|
watch(
|
||||||
() => data.value.time.type,
|
() => data.value.time.type,
|
||||||
(value) => {
|
(value) => {
|
||||||
data.value.time.end = Date.parse(new Date());
|
data.value.time.end = Date.parse(Date());
|
||||||
data.value.time.start = Date.parse(getTimeByType(value));
|
data.value.time.start = Date.parse(getTimeByType(value));
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
|
|
|
@ -44,7 +44,6 @@ const props = defineProps({
|
||||||
.top-card {
|
.top-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
// height: 200px;
|
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px solid #e0e4e8;
|
border: 1px solid #e0e4e8;
|
||||||
|
|
|
@ -28,11 +28,11 @@ import { queryCount } from '@/api/data-collect/dashboard';
|
||||||
import { defaultParams, statusData } from './tool';
|
import { defaultParams, statusData } from './tool';
|
||||||
|
|
||||||
const getNumberData = () => {
|
const getNumberData = () => {
|
||||||
statusData.value.forEach(async (item) => {
|
statusData.forEach(async (item: any) => {
|
||||||
const res = await queryCount(item[0].type, {});
|
const res = await queryCount(item[0].type, {});
|
||||||
const resp = await queryCount(item[0].type, defaultParams);
|
const resp = await queryCount(item[0].type, defaultParams);
|
||||||
item[0].total = res.result || 0;
|
item[0].total = res?.result || 0;
|
||||||
item[0].value = resp.result || 0;
|
item[0].value = resp?.result || 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
getNumberData();
|
getNumberData();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as echarts from 'echarts';
|
|
||||||
|
|
||||||
const getParams = (dt: any) => {
|
const getParams = (dt: any) => {
|
||||||
switch (dt.type) {
|
switch (dt.type) {
|
||||||
|
@ -54,7 +53,7 @@ const getParams = (dt: any) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTimeByType = (type) => {
|
export const getTimeByType = (type: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'hour':
|
case 'hour':
|
||||||
return moment().subtract(1, 'hours');
|
return moment().subtract(1, 'hours');
|
||||||
|
@ -69,7 +68,7 @@ export const getTimeByType = (type) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const pointParams = (data) => [
|
export const pointParams = (data: any) => [
|
||||||
{
|
{
|
||||||
dashboard: 'collector',
|
dashboard: 'collector',
|
||||||
object: 'pointData',
|
object: 'pointData',
|
||||||
|
@ -121,7 +120,7 @@ export const defaultParams = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const statusData = ref([
|
export const statusData = [
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
type: 'channel',
|
type: 'channel',
|
||||||
|
@ -152,4 +151,4 @@ export const statusData = ref([
|
||||||
total: 0,
|
total: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]);
|
];
|
||||||
|
|
|
@ -1,13 +1,3 @@
|
||||||
export type Agg = {
|
|
||||||
duration: number;
|
|
||||||
total: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AggPlaying = {
|
|
||||||
playerTotal: number;
|
|
||||||
playingTotal: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Footer = {
|
export type Footer = {
|
||||||
title: string;
|
title: string;
|
||||||
value: number | string;
|
value: number | string;
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<a-radio-group
|
<j-radio-group
|
||||||
v-if="quickBtn"
|
v-if="quickBtn"
|
||||||
default-value="today"
|
default-value="today"
|
||||||
button-style="solid"
|
button-style="solid"
|
||||||
v-model:value="radioValue"
|
v-model:value="radioValue"
|
||||||
@change="(e) => handleBtnChange(e.target.value)"
|
@change="(e) => handleBtnChange(e.target.value)"
|
||||||
>
|
>
|
||||||
<a-radio-button
|
<j-radio-button
|
||||||
v-for="item in quickBtnList"
|
v-for="item in quickBtnList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
>
|
>
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</a-radio-button>
|
</j-radio-button>
|
||||||
</a-radio-group>
|
</j-radio-group>
|
||||||
<a-range-picker
|
<j-range-picker
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
valueFormat="YYYY-MM-DD HH:mm:ss"
|
valueFormat="YYYY-MM-DD HH:mm:ss"
|
||||||
style="margin-left: 12px"
|
style="margin-left: 12px"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
v-model:value="rangeVal"
|
v-model:value="rangeVal"
|
||||||
:allowClear="false"
|
:allowClear="false"
|
||||||
>
|
>
|
||||||
</a-range-picker>
|
</j-range-picker>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
<div class="content-left">
|
<div class="content-left">
|
||||||
<div class="content-left-title">
|
<div class="content-left-title">
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
<a-tooltip placement="top" v-if="tooltip">
|
<j-tooltip placement="top" v-if="tooltip">
|
||||||
<template #title>
|
<template #title>
|
||||||
<span>{{ tooltip }}</span>
|
<span>{{ tooltip }}</span>
|
||||||
</template>
|
</template>
|
||||||
<AIcon type="QuestionCircleOutlined" />
|
<AIcon type="QuestionCircleOutlined" />
|
||||||
</a-tooltip>
|
</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-left-value">{{ value }}</div>
|
<div class="content-left-value">{{ value }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<div class="top-card-footer">
|
<div class="top-card-footer">
|
||||||
<template v-for="(item, index) in footer" :key="index">
|
<template v-for="(item, index) in footer" :key="index">
|
||||||
<span v-if="!item.status">{{ item.title }}</span>
|
<span v-if="!item.status">{{ item.title }}</span>
|
||||||
<a-badge v-else :text="item.title" :status="item.status" />
|
<j-badge v-else :text="item.title" :status="item.status" />
|
||||||
<div class="footer-item-value">{{ item.value }}</div>
|
<div class="footer-item-value">{{ item.value }}</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<div class="DashBoardBox">
|
<div class="DashBoardBox">
|
||||||
<a-row :gutter="24">
|
<j-row :gutter="24">
|
||||||
<a-col :span="6">
|
<j-col :span="6">
|
||||||
<TopCard
|
<TopCard
|
||||||
title="产品数量"
|
title="产品数量"
|
||||||
:img="getImage('/device/device-product.png')"
|
:img="getImage('/device/device-product.png')"
|
||||||
:footer="productFooter"
|
:footer="productFooter"
|
||||||
:value="productTotal"
|
:value="productTotal"
|
||||||
></TopCard>
|
></TopCard>
|
||||||
</a-col>
|
</j-col>
|
||||||
<a-col :span="6">
|
<j-col :span="6">
|
||||||
<TopCard
|
<TopCard
|
||||||
title="设备数量"
|
title="设备数量"
|
||||||
:img="getImage('/device/device-number.png')"
|
:img="getImage('/device/device-number.png')"
|
||||||
:footer="deviceFooter"
|
:footer="deviceFooter"
|
||||||
:value="deviceTotal"
|
:value="deviceTotal"
|
||||||
></TopCard
|
></TopCard
|
||||||
></a-col>
|
></j-col>
|
||||||
<a-col :span="6"
|
<j-col :span="6"
|
||||||
><TopCard
|
><TopCard
|
||||||
title="当前在线"
|
title="当前在线"
|
||||||
:footer="onlineFooter"
|
:footer="onlineFooter"
|
||||||
|
@ -29,18 +29,18 @@
|
||||||
:chartYData="barChartYData"
|
:chartYData="barChartYData"
|
||||||
></BarChart> -->
|
></BarChart> -->
|
||||||
<Charts :options="onlineOptions"></Charts> </TopCard
|
<Charts :options="onlineOptions"></Charts> </TopCard
|
||||||
></a-col>
|
></j-col>
|
||||||
<a-col :span="6"
|
<j-col :span="6"
|
||||||
><TopCard
|
><TopCard
|
||||||
title="今日设备信息量"
|
title="今日设备信息量"
|
||||||
:footer="messageFooter"
|
:footer="messageFooter"
|
||||||
:value="dayMessage"
|
:value="dayMessage"
|
||||||
>
|
>
|
||||||
<Charts :options="TodayDevOptions"></Charts> </TopCard
|
<Charts :options="TodayDevOptions"></Charts> </TopCard
|
||||||
></a-col>
|
></j-col>
|
||||||
</a-row>
|
</j-row>
|
||||||
<a-row :gutter="24">
|
<j-row :gutter="24">
|
||||||
<a-col :span="24">
|
<j-col :span="24">
|
||||||
<div class="message-card">
|
<div class="message-card">
|
||||||
<Guide title="设备消息">
|
<Guide title="设备消息">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
|
@ -56,18 +56,18 @@
|
||||||
<Charts :options="devMegOptions"></Charts>
|
<Charts :options="devMegOptions"></Charts>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</j-col>
|
||||||
</a-row>
|
</j-row>
|
||||||
<a-row :span="24">
|
<j-row :span="24">
|
||||||
<a-col :span="24">
|
<j-col :span="24">
|
||||||
<div class="device-position">
|
<div class="device-position">
|
||||||
<Guide title="设备分布"></Guide>
|
<Guide title="设备分布"></Guide>
|
||||||
<div class="device-map">
|
<div class="device-map">
|
||||||
<Amap></Amap>
|
<Amap></Amap>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</j-col>
|
||||||
</a-row>
|
</j-row>
|
||||||
</div>
|
</div>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="FirmwarePage">
|
<script lang="ts" setup name="FirmwarePage">
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
import type { ActionsType } from '@/components/Table/index';
|
||||||
import { query, queryProduct, remove } from '@/api/device/firmware';
|
import { query, queryProduct, remove } from '@/api/device/firmware';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
|
@ -6,18 +6,18 @@
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
>
|
>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<a-row :gutter="20">
|
<j-row :gutter="20">
|
||||||
<a-col :span="10">
|
<j-col :span="10">
|
||||||
<!-- 图片 -->
|
<!-- 图片 -->
|
||||||
<div class="card-item-avatar">
|
<div class="card-item-avatar">
|
||||||
<slot name="img"> </slot>
|
<slot name="img"> </slot>
|
||||||
</div>
|
</div>
|
||||||
</a-col>
|
</j-col>
|
||||||
<a-col :span="14">
|
<j-col :span="14">
|
||||||
<!-- 内容 -->
|
<!-- 内容 -->
|
||||||
<slot name="content"></slot>
|
<slot name="content"></slot>
|
||||||
</a-col>
|
</j-col>
|
||||||
</a-row>
|
</j-row>
|
||||||
|
|
||||||
<!-- 勾选 -->
|
<!-- 勾选 -->
|
||||||
<div v-if="active" class="checked-icon">
|
<div v-if="active" class="checked-icon">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- 配置信息 -->
|
<!-- 配置信息 -->
|
||||||
<template>
|
<template>
|
||||||
<a-card style="min-height: 100%">
|
<j-card style="min-height: 100%">
|
||||||
<a-descriptions bordered>
|
<j-descriptions bordered>
|
||||||
<template #title>
|
<template #title>
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<h3>配置信息</h3>
|
<h3>配置信息</h3>
|
||||||
|
@ -11,35 +11,35 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<a-descriptions-item label="ID">{{
|
<j-descriptions-item label="ID">{{
|
||||||
productStore.current.id
|
productStore.current.id
|
||||||
}}</a-descriptions-item>
|
}}</j-descriptions-item>
|
||||||
<a-descriptions-item label="产品分类">{{
|
<j-descriptions-item label="产品分类">{{
|
||||||
productStore.current.classifiedName
|
productStore.current.classifiedName
|
||||||
}}</a-descriptions-item>
|
}}</j-descriptions-item>
|
||||||
<a-descriptions-item label="设备类型">{{
|
<j-descriptions-item label="设备类型">{{
|
||||||
productStore.current.deviceType?.text
|
productStore.current.deviceType?.text
|
||||||
}}</a-descriptions-item>
|
}}</j-descriptions-item>
|
||||||
|
|
||||||
<a-descriptions-item label="接入方式">
|
<j-descriptions-item label="接入方式">
|
||||||
<a-button type="link" @click="changeTables">{{
|
<j-button type="link" @click="changeTables">{{
|
||||||
productStore.current.accessName
|
productStore.current.accessName
|
||||||
? productStore.current.accessName
|
? productStore.current.accessName
|
||||||
: '配置接入方式'
|
: '配置接入方式'
|
||||||
}}</a-button>
|
}}</j-button>
|
||||||
</a-descriptions-item>
|
</j-descriptions-item>
|
||||||
<a-descriptions-item label="创建时间">{{
|
<j-descriptions-item label="创建时间">{{
|
||||||
moment(productStore.current.createTime).format('YYYY-MM-DD HH:mm:ss')
|
moment(productStore.current.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||||
}}</a-descriptions-item>
|
}}</j-descriptions-item>
|
||||||
<a-descriptions-item label="更新时间">{{
|
<j-descriptions-item label="更新时间">{{
|
||||||
moment(productStore.current.modifyTime).format('YYYY-MM-DD HH:mm:ss')
|
moment(productStore.current.modifyTime).format('YYYY-MM-DD HH:mm:ss')
|
||||||
}}</a-descriptions-item>
|
}}</j-descriptions-item>
|
||||||
|
|
||||||
<a-descriptions-item label="说明" :span="3">
|
<j-descriptions-item label="说明" :span="3">
|
||||||
{{ productStore.current.describe }}
|
{{ productStore.current.describe }}
|
||||||
</a-descriptions-item>
|
</j-descriptions-item>
|
||||||
</a-descriptions>
|
</j-descriptions>
|
||||||
</a-card>
|
</j-card>
|
||||||
<!-- 编辑 -->
|
<!-- 编辑 -->
|
||||||
<Save ref="saveRef" :isAdd="isAdd" :title="title" />
|
<Save ref="saveRef" :isAdd="isAdd" :title="title" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<!-- 产品保存成功后的提示框 -->
|
<!-- 产品保存成功后的提示框 -->
|
||||||
<template>
|
<template>
|
||||||
<a-modal
|
<j-modal
|
||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
destroy-on-close
|
destroy-on-close
|
||||||
v-model:visible="visible"
|
v-model:visible="visible"
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<span>产品创建成功</span>
|
<span>产品创建成功</span>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<a-button @click="cancel">关闭</a-button>
|
<j-button @click="cancel">关闭</j-button>
|
||||||
</template>
|
</template>
|
||||||
<div class="product-tips">
|
<div class="product-tips">
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
进入设备列表页面,点击批量导入设备,批量添加同一产品下的设备
|
进入设备列表页面,点击批量导入设备,批量添加同一产品下的设备
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="DialogTips">
|
<script lang="ts" setup name="DialogTips">
|
||||||
import { getImage } from '@/utils/comm.ts';
|
import { getImage } from '@/utils/comm.ts';
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||||
新增
|
新增
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<a-upload
|
<j-upload
|
||||||
name="file"
|
name="file"
|
||||||
accept=".json"
|
accept=".json"
|
||||||
:showUploadList="false"
|
:showUploadList="false"
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<PermissionButton hasPermission="device/Product:import"
|
<PermissionButton hasPermission="device/Product:import"
|
||||||
>导入</PermissionButton
|
>导入</PermissionButton
|
||||||
>
|
>
|
||||||
</a-upload>
|
</j-upload>
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
<template #deviceType="slotProps">
|
<template #deviceType="slotProps">
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<j-form-item label="系统logo">
|
<j-form-item label="系统logo">
|
||||||
<div class="upload-image-warp-logo">
|
<div class="upload-image-warp-logo">
|
||||||
<div class="upload-image-border-logo">
|
<div class="upload-image-border-logo">
|
||||||
<a-upload
|
<j-upload
|
||||||
name="file"
|
name="file"
|
||||||
:action="FILE_UPLOAD"
|
:action="FILE_UPLOAD"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-upload>
|
</j-upload>
|
||||||
<div v-if="logoLoading">
|
<div v-if="logoLoading">
|
||||||
<div class="upload-loading-mask">
|
<div class="upload-loading-mask">
|
||||||
<LoadingOutlined
|
<LoadingOutlined
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="upload-image-warp-logo">
|
<div class="upload-image-warp-logo">
|
||||||
<div class="upload-image-border-logo">
|
<div class="upload-image-border-logo">
|
||||||
<a-upload
|
<j-upload
|
||||||
name="file"
|
name="file"
|
||||||
:action="FILE_UPLOAD"
|
:action="FILE_UPLOAD"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
|
@ -183,7 +183,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-upload>
|
</j-upload>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@
|
||||||
<j-form-item label="登录背景图">
|
<j-form-item label="登录背景图">
|
||||||
<div class="upload-image-warp-back">
|
<div class="upload-image-warp-back">
|
||||||
<div class="upload-image-border-back">
|
<div class="upload-image-border-back">
|
||||||
<a-upload
|
<j-upload
|
||||||
name="file"
|
name="file"
|
||||||
:action="FILE_UPLOAD"
|
:action="FILE_UPLOAD"
|
||||||
:headers="headers"
|
:headers="headers"
|
||||||
|
@ -242,7 +242,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-upload>
|
</j-upload>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload-tips">支持4M以内的图片:支持jpg、png</div>
|
<div class="upload-tips">支持4M以内的图片:支持jpg、png</div>
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="StreamPage">
|
<script lang="ts" setup name="StreamPage">
|
||||||
import type { ActionsType } from '@/components/Table/index.vue';
|
import type { ActionsType } from '@/components/Table/index';
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { query, remove, disable, enalbe } from '@/api/media/stream';
|
import { query, remove, disable, enalbe } from '@/api/media/stream';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
visible
|
visible
|
||||||
>
|
>
|
||||||
<h5 class="row">
|
<h5 class="row">
|
||||||
<exclamation-circle-outlined style="margin-right: 6px" />
|
<AIcon type="ExclamationCircleOutlined" style="margin-right: 6px" />
|
||||||
只能分配有“共享”权限的资产数据
|
只能分配有“共享”权限的资产数据
|
||||||
</h5>
|
</h5>
|
||||||
|
|
||||||
|
@ -132,7 +132,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { uniq, intersection } from 'lodash-es';
|
import { uniq, intersection } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
class="search-input"
|
class="search-input"
|
||||||
>
|
>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<search-outlined />
|
<AIcon type="SearchOutlined" />
|
||||||
</template>
|
</template>
|
||||||
</j-input>
|
</j-input>
|
||||||
<div class="add-btn">
|
<div class="add-btn">
|
||||||
|
@ -89,7 +89,6 @@ import { debounce, cloneDeep, omit } from 'lodash-es';
|
||||||
import { ArrayToTree } from '@/utils/utils';
|
import { ArrayToTree } from '@/utils/utils';
|
||||||
import EditDepartmentDialog from './EditDepartmentDialog.vue';
|
import EditDepartmentDialog from './EditDepartmentDialog.vue';
|
||||||
|
|
||||||
import { SearchOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
const permission = 'system/Department';
|
const permission = 'system/Department';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="setting-container">
|
<div class="setting-container">
|
||||||
<h5 class="top">
|
<h5 class="top">
|
||||||
<exclamation-circle-outlined />
|
<AIcon type="ExclamationCircleOutlined" />
|
||||||
<span style="padding-left: 12px"
|
<span style="padding-left: 12px"
|
||||||
>基于系统源代码中的菜单数据,配置系统菜单。</span
|
>基于系统源代码中的菜单数据,配置系统菜单。</span
|
||||||
>
|
>
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<template #title
|
<template #title
|
||||||
>根据系统代码自动读取的菜单数据</template
|
>根据系统代码自动读取的菜单数据</template
|
||||||
>
|
>
|
||||||
<question-circle-outlined />
|
<AIcon type="QuestionCircleOutlined" />
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="title-func">
|
<div class="title-func">
|
||||||
|
@ -36,7 +36,10 @@
|
||||||
placeholder="请输入菜单名称"
|
placeholder="请输入菜单名称"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<search-outlined style="color: #b3b3b3" />
|
<AIcon
|
||||||
|
type="SearchOutlined"
|
||||||
|
style="color: #b3b3b3"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</j-input>
|
</j-input>
|
||||||
<j-tree
|
<j-tree
|
||||||
|
@ -63,7 +66,7 @@
|
||||||
<template #title
|
<template #title
|
||||||
>菜单管理页面配置的菜单数据</template
|
>菜单管理页面配置的菜单数据</template
|
||||||
>
|
>
|
||||||
<question-circle-outlined />
|
<AIcon type="QuestionCircleOutlined" />
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,7 +77,10 @@
|
||||||
placeholder="请输入菜单名称"
|
placeholder="请输入菜单名称"
|
||||||
>
|
>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<search-outlined style="color: #b3b3b3" />
|
<AIcon
|
||||||
|
type="SearchOutlined"
|
||||||
|
style="color: #b3b3b3"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</j-input>
|
</j-input>
|
||||||
<j-tree
|
<j-tree
|
||||||
|
@ -103,7 +109,7 @@
|
||||||
style="padding: 0"
|
style="padding: 0"
|
||||||
type="link"
|
type="link"
|
||||||
>
|
>
|
||||||
<close-outlined />
|
<AIcon type="CloseOutlined" />
|
||||||
</j-button>
|
</j-button>
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
</j-popconfirm>
|
</j-popconfirm>
|
||||||
|
@ -114,7 +120,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<j-button type="primary" style="margin-top: 24px;">保存</j-button>
|
<j-button type="primary" style="margin-top: 24px">保存</j-button>
|
||||||
|
|
||||||
<div class="dialogs">
|
<div class="dialogs">
|
||||||
<j-modal
|
<j-modal
|
||||||
|
@ -131,13 +137,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="MenuSetting">
|
<script setup lang="ts" name="MenuSetting">
|
||||||
import {
|
|
||||||
ExclamationCircleOutlined,
|
|
||||||
QuestionCircleOutlined,
|
|
||||||
SearchOutlined,
|
|
||||||
CloseOutlined,
|
|
||||||
} from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
import { getMenuTree_api } from '@/api/system/menu';
|
import { getMenuTree_api } from '@/api/system/menu';
|
||||||
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
||||||
import { filterMenu, getKeys, loop } from './utils';
|
import { filterMenu, getKeys, loop } from './utils';
|
||||||
|
|
|
@ -64,8 +64,13 @@
|
||||||
onConfirm: () => table.changeStatus(slotProps),
|
onConfirm: () => table.changeStatus(slotProps),
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<stop-outlined v-if="slotProps.status" />
|
<AIcon
|
||||||
<play-circle-outlined v-else />
|
:type="
|
||||||
|
slotProps.status
|
||||||
|
? 'StopOutlined'
|
||||||
|
: 'PlayCircleOutlined'
|
||||||
|
"
|
||||||
|
/>
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:hasPermission="`${permission}:update`"
|
:hasPermission="`${permission}:update`"
|
||||||
|
@ -117,7 +122,6 @@ import {
|
||||||
changeUserStatus_api,
|
changeUserStatus_api,
|
||||||
deleteUser_api,
|
deleteUser_api,
|
||||||
} from '@/api/system/user';
|
} from '@/api/system/user';
|
||||||
import { StopOutlined, PlayCircleOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
|
|
||||||
const permission = 'system/User';
|
const permission = 'system/User';
|
||||||
|
|
Loading…
Reference in New Issue