Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
4e8c6dfe9d
|
@ -4,7 +4,10 @@ export const queryCollector = (data: any) =>
|
|||
server.post(`/data-collect/collector/_query/no-paging?paging=false`, data);
|
||||
|
||||
export const queryChannelNoPaging = () =>
|
||||
server.post(`/data-collect/channel/_query/no-paging`, { paging: false });
|
||||
server.post(`/data-collect/channel/_query/no-paging`, {
|
||||
paging: false,
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
});
|
||||
|
||||
export const save = (data: any) => server.post(`/data-collect/collector`, data);
|
||||
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
<template>
|
||||
<Tooltip ref="tooltipRef" placement="top" v-bind="props.tooltip">
|
||||
<template v-if="props.tooltip" #title>
|
||||
<slot></slot>
|
||||
<slot name="tooltip"></slot>
|
||||
</template>
|
||||
<span
|
||||
ref="triggerRef"
|
||||
v-bind="triggerAttrs()"
|
||||
@click="handleClickRef"
|
||||
@mouseenter="
|
||||
[
|
||||
props.expandTrigger === 'click'
|
||||
? getTooltipDisabled()
|
||||
: undefined,
|
||||
]
|
||||
"
|
||||
>
|
||||
<slot></slot>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Tooltip, TooltipProps } from 'ant-design-vue';
|
||||
|
||||
import { computed, mergeProps, PropType, ref, useAttrs } from 'vue';
|
||||
|
||||
// define class name
|
||||
const jEllipsis = 'j-ellipsis';
|
||||
const jEllipsisCursorClass = 'j-ellipsis-cursor';
|
||||
const jEllipsisLineClampClass = 'j-ellipsis-line-clamp';
|
||||
|
||||
const props = defineProps({
|
||||
/** expand by */
|
||||
expandTrigger: {
|
||||
type: String as PropType<'click'>,
|
||||
default: undefined,
|
||||
},
|
||||
/** multiline ellipsis */
|
||||
lineClamp: {
|
||||
type: [Number, String] as PropType<string | number>,
|
||||
default: 1,
|
||||
},
|
||||
/** a-tooltip props */
|
||||
tooltip: {
|
||||
type: [Boolean, Object] as PropType<TooltipProps | boolean>,
|
||||
default: true,
|
||||
},
|
||||
});
|
||||
|
||||
const attrs = useAttrs();
|
||||
|
||||
function triggerAttrs() {
|
||||
return {
|
||||
...mergeProps(attrs, {
|
||||
class: [
|
||||
jEllipsis,
|
||||
props.lineClamp !== undefined
|
||||
? jEllipsisLineClampClass
|
||||
: undefined,
|
||||
props.expandTrigger === 'click'
|
||||
? jEllipsisCursorClass
|
||||
: undefined,
|
||||
],
|
||||
style: ellipsisStyleRef.value,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const expandedRef = ref(false);
|
||||
const tooltipRef = ref<HTMLElement | null>(null);
|
||||
const triggerRef = ref<HTMLElement | null>(null);
|
||||
|
||||
const ellipsisStyleRef = computed(() => {
|
||||
const { lineClamp } = props;
|
||||
const { value: expanded } = expandedRef;
|
||||
if (lineClamp !== undefined) {
|
||||
return {
|
||||
textOverflow: '',
|
||||
'-webkit-line-clamp': expanded ? '' : lineClamp,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
textOverflow: expanded ? '' : 'ellipsis',
|
||||
'-webkit-line-clamp': '',
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function syncCursorStyle(trigger: HTMLElement, tooltipDisabled: boolean): void {
|
||||
if (props.expandTrigger === 'click' && !tooltipDisabled) {
|
||||
syncTriggerClass(trigger, jEllipsisCursorClass, 'add');
|
||||
} else {
|
||||
syncTriggerClass(trigger, jEllipsisCursorClass, 'remove');
|
||||
}
|
||||
}
|
||||
|
||||
function getTooltipDisabled(): boolean {
|
||||
let tooltipDisabled = false;
|
||||
const { value: expanded } = expandedRef;
|
||||
if (expanded) return true;
|
||||
const { value: trigger } = triggerRef;
|
||||
if (trigger) {
|
||||
syncEllipsisStyle(trigger);
|
||||
tooltipDisabled = trigger.scrollHeight <= trigger.offsetHeight;
|
||||
|
||||
syncCursorStyle(trigger, tooltipDisabled);
|
||||
}
|
||||
return tooltipDisabled;
|
||||
}
|
||||
|
||||
const handleClickRef = computed(() => {
|
||||
return props.expandTrigger === 'click'
|
||||
? () => {
|
||||
const { value: expanded } = expandedRef;
|
||||
expandedRef.value = !expanded;
|
||||
}
|
||||
: undefined;
|
||||
});
|
||||
|
||||
function syncEllipsisStyle(trigger: HTMLElement): void {
|
||||
if (!trigger) return;
|
||||
const latestStyle = ellipsisStyleRef.value;
|
||||
const lineClampClass = jEllipsisLineClampClass;
|
||||
if (props.lineClamp !== undefined) {
|
||||
syncTriggerClass(trigger, lineClampClass, 'add');
|
||||
} else {
|
||||
syncTriggerClass(trigger, lineClampClass, 'remove');
|
||||
}
|
||||
for (const key in latestStyle) {
|
||||
if ((trigger.style as any)[key] !== (latestStyle as any)[key]) {
|
||||
(trigger.style as any)[key] = (latestStyle as any)[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function syncTriggerClass(
|
||||
trigger: HTMLElement,
|
||||
styleClass: string,
|
||||
action: 'add' | 'remove',
|
||||
): void {
|
||||
if (action === 'add') {
|
||||
if (!trigger.classList.contains(styleClass)) {
|
||||
trigger.classList.add(styleClass);
|
||||
}
|
||||
} else {
|
||||
if (trigger.classList.contains(styleClass)) {
|
||||
trigger.classList.remove(styleClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang='less'>
|
||||
.j-ellipsis {
|
||||
overflow: hidden;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.j-ellipsis-cursor {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.j-ellipsis-line-clamp {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,7 @@
|
|||
<template>
|
||||
<j-form-item :name="name.concat(['type'])" v-show="false">
|
||||
<j-input v-model:value="value.type" disabled/>
|
||||
</j-form-item>
|
||||
<j-form-item :name="name.concat(['script'])">
|
||||
<f-rule-editor v-model:value="value.script" :id="id" :virtualRule="value"></f-rule-editor>
|
||||
</j-form-item>
|
||||
|
@ -60,10 +63,12 @@ interface Emits {
|
|||
const emit = defineEmits<Emits>()
|
||||
|
||||
onMounted(() => {
|
||||
emit('update:value', {
|
||||
...props.value,
|
||||
type: 'script'
|
||||
})
|
||||
if (!props.value.type) {
|
||||
emit('update:value', {
|
||||
...props.value,
|
||||
type: 'script'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const aggTypeOptions = ref()
|
||||
|
|
|
@ -9,8 +9,8 @@ import NormalUpload from './NormalUpload/index.vue'
|
|||
import FileFormat from './FileFormat/index.vue'
|
||||
import JProUpload from './Upload/index.vue'
|
||||
import { BasicLayoutPage, BlankLayoutPage } from './Layout'
|
||||
import { PageContainer, AIcon } from 'jetlinks-ui-components'
|
||||
import Ellipsis from './Ellipsis/index.vue'
|
||||
import { PageContainer, AIcon, Ellipsis } from 'jetlinks-ui-components'
|
||||
// import Ellipsis from './Ellipsis/index.vue'
|
||||
import JEmpty from './Empty/index.vue'
|
||||
import AMapComponent from './AMapComponent/index.vue'
|
||||
import PathSimplifier from './AMapComponent/PathSimplifier.vue'
|
||||
|
|
|
@ -3,6 +3,8 @@ import { systemVersion } from '@/api/comm'
|
|||
import { useMenuStore } from './menu'
|
||||
import { getDetails_api } from '@/api/system/basis';
|
||||
import type { ConfigInfoType } from '@/views/system/Basis/typing';
|
||||
import { LocalStore } from '@/utils/comm'
|
||||
import { SystemConst } from '@/utils/consts'
|
||||
|
||||
type SystemStateType = {
|
||||
isCommunity: boolean;
|
||||
|
@ -22,6 +24,7 @@ export const useSystem = defineStore('system', {
|
|||
const resp = await systemVersion()
|
||||
if (resp.success && resp.result) {
|
||||
const isCommunity = resp.result.edition === 'community'
|
||||
LocalStore.set(SystemConst.VERSION_CODE, resp.result.edition)
|
||||
this.isCommunity = isCommunity
|
||||
// 获取菜单
|
||||
const menu = useMenuStore()
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import { isNoCommunity } from '@/utils/utils';
|
||||
|
||||
// 过滤网关类型
|
||||
export const accessConfigTypeFilter = (data: any[], filterKey: string = 'id'): any[] => {
|
||||
if (!data) return []
|
||||
const filterKeys = !isNoCommunity ?
|
||||
[
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
'plugin_gateway'
|
||||
] : ['plugin_gateway']
|
||||
return data.filter(item => !filterKeys.includes(item[filterKey])).map( item => ({ ...item, label: item.name, value: item.id}))
|
||||
}
|
|
@ -16,4 +16,12 @@ export const phoneRegEx = (value: string) => {
|
|||
export const passwordRegEx = (value: string) => {
|
||||
const password = new RegExp(/^\S*(?=\S{8,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])\S*$/)
|
||||
return password.test(value)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 判断是否为正确的IP地址
|
||||
*/
|
||||
export const testIP = (value: string) => {
|
||||
const ip =
|
||||
/^([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.([0-9]|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])$/;
|
||||
return ip.test(value);
|
||||
};
|
|
@ -301,7 +301,13 @@ const formData = ref({
|
|||
});
|
||||
|
||||
const handleOk = async () => {
|
||||
const data = await formRef.value?.validate();
|
||||
console.log(2, formRef.value, formRef.value?.validate());
|
||||
|
||||
const data = await formRef.value?.validate().catch((err) => {
|
||||
console.log(23, err);
|
||||
});
|
||||
console.log(3, data);
|
||||
|
||||
delete data?.nspwc;
|
||||
const { codec } = data?.configuration;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<template #headerTitle>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
v-if="data?.provider !== 'OPC_UA'"
|
||||
v-if="data?.provider == 'MODBUS_TCP'"
|
||||
type="primary"
|
||||
@click="handlAdd"
|
||||
hasPermission="DataCollect/Collector:add"
|
||||
|
|
|
@ -56,22 +56,8 @@
|
|||
<j-form-item
|
||||
:name="['circuitBreaker', 'type']"
|
||||
:rules="LeftTreeRules.type"
|
||||
label="故障处理"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
故障处理
|
||||
<j-tooltip
|
||||
:title="
|
||||
getTypeTooltip(formData.circuitBreaker.type)
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<j-card-select
|
||||
:showImage="false"
|
||||
v-model:value="formData.circuitBreaker.type"
|
||||
|
@ -83,6 +69,9 @@
|
|||
@change="changeCardSelectType"
|
||||
/>
|
||||
</j-form-item>
|
||||
<p style="color: #616161">
|
||||
{{ getTypeTooltip(formData.circuitBreaker.type) }}
|
||||
</p>
|
||||
<j-form-item
|
||||
:name="['configuration', 'endian']"
|
||||
v-if="visibleEndian"
|
||||
|
@ -137,15 +126,12 @@
|
|||
</j-modal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { save, update } from '@/api/data-collect/collector';
|
||||
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 useForm = Form.useForm;
|
||||
const channelListAll = ref();
|
||||
const channelList = ref();
|
||||
const visibleEndian = ref(false);
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
:tree-data="defualtDataSource"
|
||||
v-model:selected-keys="selectedKeys"
|
||||
:fieldNames="{ key: 'id' }"
|
||||
v-if="defualtDataSource[0].children.length !== 0"
|
||||
v-if="
|
||||
defualtDataSource.length !== 0 ||
|
||||
defualtDataSource?.[0]?.children?.length !== 0
|
||||
"
|
||||
:height="600"
|
||||
defaultExpandAll
|
||||
>
|
||||
|
@ -129,13 +132,15 @@ const visible = ref(false);
|
|||
const current = ref({});
|
||||
const collectorAll = ref();
|
||||
|
||||
const defualtDataSource: any = ref([
|
||||
const root = [
|
||||
{
|
||||
id: '*',
|
||||
name: '全部',
|
||||
children: [],
|
||||
},
|
||||
]);
|
||||
];
|
||||
|
||||
const defualtDataSource: any = ref(_.cloneDeep(root));
|
||||
|
||||
const defualtParams = {
|
||||
paging: false,
|
||||
|
@ -195,9 +200,11 @@ const saveChange = (value: object) => {
|
|||
};
|
||||
|
||||
const handleSearch = async (value: any) => {
|
||||
let clickSearch = false;
|
||||
if (!searchValue.value && !value) {
|
||||
params.value = _.cloneDeep(defualtParams);
|
||||
} else if (!!searchValue.value) {
|
||||
clickSearch = true;
|
||||
params.value = { ..._.cloneDeep(defualtParams) };
|
||||
params.value.terms[1] = {
|
||||
terms: [
|
||||
|
@ -214,12 +221,24 @@ const handleSearch = async (value: any) => {
|
|||
spinning.value = true;
|
||||
const res: any = await queryCollector(params.value);
|
||||
if (res.status === 200) {
|
||||
defualtDataSource.value[0].children = res.result;
|
||||
collectorAll.value = res.result;
|
||||
if (selectedKeys.value.length === 0) {
|
||||
selectedKeys.value = [res?.result[0]?.id] || [];
|
||||
emits('change', res?.result[0]);
|
||||
if (clickSearch) {
|
||||
defualtDataSource.value = res.result;
|
||||
} else {
|
||||
defualtDataSource.value = _.cloneDeep(root);
|
||||
defualtDataSource.value[0].children = res.result;
|
||||
}
|
||||
collectorAll.value = res.result;
|
||||
|
||||
if (selectedKeys.value.length === 0) {
|
||||
selectedKeys.value = ['*'];
|
||||
}
|
||||
|
||||
//激活change事件
|
||||
setTimeout(() => {
|
||||
const _selectedKeys = _.cloneDeep(selectedKeys.value);
|
||||
selectedKeys.value = [];
|
||||
selectedKeys.value = _selectedKeys;
|
||||
}, 0);
|
||||
}
|
||||
spinning.value = false;
|
||||
};
|
||||
|
@ -238,8 +257,10 @@ watch(
|
|||
() => selectedKeys.value,
|
||||
(n) => {
|
||||
const key = _.isArray(n) ? n[0] : n;
|
||||
const row = collectorAll.value.find((i: any) => i.id === key);
|
||||
emits('change', row);
|
||||
if (key) {
|
||||
const row = collectorAll.value.find((i: any) => i.id === key);
|
||||
emits('change', row);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</div>
|
||||
<div class="right">
|
||||
<j-spin :spinning="spinning">
|
||||
<Point v-if="!!data" :data="data" />
|
||||
<Point v-if="data || data === undefined" :data="data" />
|
||||
<j-empty style="margin-top: 20%" v-else />
|
||||
</j-spin>
|
||||
</div>
|
||||
|
|
|
@ -208,6 +208,7 @@ const onPropertyChange = (val: string) => {
|
|||
(item: any) => item.id === val,
|
||||
);
|
||||
property.value = _item || {};
|
||||
modelRef.message.value = undefined
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -214,6 +214,12 @@
|
|||
item.actionType
|
||||
"
|
||||
show-search
|
||||
@change="
|
||||
() =>
|
||||
onActionTypeChange(
|
||||
index,
|
||||
)
|
||||
"
|
||||
>
|
||||
<j-select-option
|
||||
value="command"
|
||||
|
@ -491,6 +497,18 @@ const onActionCollChange = (_key: string[]) => {
|
|||
actionActiveKey.value = _key;
|
||||
};
|
||||
|
||||
const onActionTypeChange = (_index: number) => {
|
||||
modelRef.actionMappings[_index].command = {
|
||||
messageType: undefined,
|
||||
message: {
|
||||
properties: undefined,
|
||||
functionId: undefined,
|
||||
inputs: [],
|
||||
value: undefined
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const addItem = () => {
|
||||
actionActiveKey.value.push(String(modelRef.actionMappings.length));
|
||||
modelRef.actionMappings.push({
|
||||
|
@ -527,6 +545,20 @@ const productChange = (value: string) => {
|
|||
modelRef.propertyMappings = modelRef.propertyMappings.map((item) => {
|
||||
return { source: item.source, target: [] };
|
||||
});
|
||||
modelRef.actionMappings = modelRef.actionMappings.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
command: {
|
||||
messageType: undefined,
|
||||
message: {
|
||||
properties: undefined,
|
||||
functionId: undefined,
|
||||
inputs: [],
|
||||
value: undefined,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
const item = productList.value.find((item) => item.id === value);
|
||||
if (item) {
|
||||
modelRef.productName = item.name;
|
||||
|
@ -571,7 +603,7 @@ const getTypes = async () => {
|
|||
};
|
||||
|
||||
const getDuerOSProperties = (val: string) => {
|
||||
console.log(val)
|
||||
console.log(val);
|
||||
const arr = modelRef.propertyMappings.map((item) => item?.source) || [];
|
||||
const checked = _.cloneDeep(arr);
|
||||
const _index = checked.findIndex((i) => i === val);
|
||||
|
@ -673,7 +705,7 @@ watch(
|
|||
_data.applianceType = _data?.applianceType?.value;
|
||||
}
|
||||
Object.assign(modelRef, _data);
|
||||
console.log(modelRef.propertyMappings)
|
||||
console.log(modelRef.propertyMappings);
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<pro-search class="search" type="simple" :columns="columns" target="device-instance-running-events" @search="handleSearch" />
|
||||
<pro-search class="device-search" type="simple" :columns="columns" target="device-instance-running-events" @search="handleSearch" />
|
||||
<JProTable
|
||||
ref="eventsRef"
|
||||
:columns="columns"
|
||||
|
@ -62,14 +62,14 @@ const _getEventList = (_params: any) =>
|
|||
|
||||
watchEffect(() => {
|
||||
if (events.data?.valueType?.type === 'object') {
|
||||
(events.data.valueType?.properties || []).map((i: any) => {
|
||||
(events.data.valueType?.properties || []).reverse().map((i: any) => {
|
||||
columns.value.splice(0, 0, {
|
||||
key: i.id,
|
||||
title: i.name,
|
||||
dataIndex: `${i.id}_format`,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
type: i?.valueType?.type || 'string',
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
@ -97,8 +97,8 @@ const detail = (_info: any) => {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.search {
|
||||
padding: 0 0 0 24px;
|
||||
<style lang="less">
|
||||
.device-search {
|
||||
margin: 0 0 24px 0 ;
|
||||
}
|
||||
</style>
|
|
@ -33,8 +33,10 @@
|
|||
}指标值`,
|
||||
}"
|
||||
:name="['metrics', index, 'value', 0]"
|
||||
:label="item?.name || '指标值'"
|
||||
>
|
||||
<template #label>
|
||||
<Ellipsis>{{ item?.name || '指标值' }}</Ellipsis>
|
||||
</template>
|
||||
<ValueItem
|
||||
v-model:modelValue="item.value[0]"
|
||||
:itemType="data.valueType?.type"
|
||||
|
@ -95,6 +97,7 @@
|
|||
import { queryMetric, saveMetric } from '@/api/device/instance';
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isNumber } from 'lodash-es';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
|
@ -110,7 +113,7 @@ const instanceStore = useInstanceStore();
|
|||
const formRef = ref();
|
||||
|
||||
const modelRef = reactive<{
|
||||
metrics: any[]
|
||||
metrics: any[];
|
||||
}>({
|
||||
metrics: [],
|
||||
});
|
||||
|
@ -132,8 +135,8 @@ watch(
|
|||
) {
|
||||
const list = resp?.result.map((item: any) => {
|
||||
const val = Array.isArray(item?.value)
|
||||
? [item?.value]
|
||||
: item?.value?.split(',');
|
||||
? item?.value
|
||||
: (isNumber(item?.value) ? [item.value] : item?.value?.split(','))
|
||||
return {
|
||||
...item,
|
||||
value: val,
|
||||
|
@ -172,7 +175,7 @@ watch(
|
|||
const handleSave = () => {
|
||||
formRef.value
|
||||
.validate()
|
||||
.then(async () => {
|
||||
.then(async (_data: any) => {
|
||||
loading.value = true;
|
||||
const list = (toRaw(modelRef)?.metrics || []).map((item: any) => {
|
||||
return {
|
||||
|
|
|
@ -309,6 +309,7 @@ import BadgeStatus from '@/components/BadgeStatus/index.vue';
|
|||
import BatchDropdown from '@/components/BatchDropdown/index.vue';
|
||||
import { BatchActionsType } from '@/components/BatchDropdown/types';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
const instanceRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
@ -417,12 +418,17 @@ const columns = [
|
|||
options: () =>
|
||||
new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
resolve(
|
||||
resp.result.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: `accessProvider is ${item.id}`,
|
||||
})),
|
||||
);
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data).map(item => ({
|
||||
...item,
|
||||
value: `accessProvider is ${item.id}`
|
||||
})))
|
||||
// resolve(
|
||||
// resp.result.map((item: any) => ({
|
||||
// label: item.name,
|
||||
// value: `accessProvider is ${item.id}`,
|
||||
// })),
|
||||
// );
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
|
|
@ -419,6 +419,7 @@ import { marked } from 'marked';
|
|||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import _ from 'lodash';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
|
@ -433,7 +434,6 @@ marked.setOptions({
|
|||
});
|
||||
const simpleImage = ref(Empty.PRESENTED_IMAGE_SIMPLE);
|
||||
const visible = ref<boolean>(false);
|
||||
const listData = ref<string[]>([]);
|
||||
const access = ref({});
|
||||
const config = ref<any>({});
|
||||
const metadata = ref<ConfigMetadata>({ properties: [] });
|
||||
|
@ -500,35 +500,10 @@ const query = reactive({
|
|||
search: {
|
||||
type: 'select',
|
||||
options: async () => {
|
||||
return new Promise((res) => {
|
||||
return new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
listData.value = [];
|
||||
if (isNoCommunity) {
|
||||
(resp?.result || []).map((item: any) => {
|
||||
if (item.id != 'plugin_gateway') {
|
||||
listData.value.push({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listData.value = (resp?.result || [])
|
||||
.filter((i: any) =>
|
||||
[
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(i.id),
|
||||
)
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
// }
|
||||
}
|
||||
res(listData.value);
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data))
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -960,7 +935,8 @@ const getData = async (accessId?: string) => {
|
|||
);
|
||||
getProviders().then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
dataSource.value = resp.result;
|
||||
const data = resp.result || []
|
||||
dataSource.value = accessConfigTypeFilter(data as any[]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ import Save from './Save/index.vue';
|
|||
import { useMenuStore } from 'store/menu';
|
||||
import { useRoute } from 'vue-router';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
/**
|
||||
* 表格数据
|
||||
*/
|
||||
|
@ -442,37 +443,11 @@ const query = reactive({
|
|||
dataIndex: 'accessProvider',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: async () => {
|
||||
return new Promise((res) => {
|
||||
options: () => {
|
||||
return new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
listData.value = [];
|
||||
// const list = () => {
|
||||
if (isNoCommunity) {
|
||||
(resp?.result || []).map((item: any) => {
|
||||
if (item.id != 'plugin_gateway') {
|
||||
listData.value.push({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listData.value = (resp?.result || [])
|
||||
.filter((i: any) =>
|
||||
[
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(i.id),
|
||||
)
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
// }
|
||||
}
|
||||
res(listData.value);
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data))
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<j-select v-model:value="_value.source" :options="PropertySource" size="small"
|
||||
:disabled="metadataStore.model.action === 'edit'" @change="changeSource"></j-select>
|
||||
</j-form-item>
|
||||
<virtual-rule-param v-if="_value.source === 'rule'" v-model:value="_value.virtualRule"
|
||||
<virtual-rule-param v-if="type === 'product' && _value.source === 'rule'" v-model:value="_value.virtualRule"
|
||||
:name="name.concat(['virtualRule'])" :id="id" :showWindow="_value.source === 'rule'"></virtual-rule-param>
|
||||
<j-form-item label="读写类型" :name="name.concat(['type'])" :rules="[
|
||||
{ required: true, message: '请选择读写类型' },
|
||||
|
|
|
@ -42,6 +42,8 @@ export default [
|
|||
actions: ['query'],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'notice',
|
||||
|
@ -182,6 +184,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'notice/Template',
|
||||
|
@ -301,6 +305,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -344,6 +350,8 @@ export default [
|
|||
actions: ['find-geo'],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'device/Product',
|
||||
|
@ -354,7 +362,6 @@ export default [
|
|||
url: '/iot/device/Product',
|
||||
icon: 'icon-chanpin',
|
||||
sortIndex: 2,
|
||||
accessSupport: 'support',
|
||||
assetType: 'product',
|
||||
showPage: ['device-product'],
|
||||
permissions: [
|
||||
|
@ -535,6 +542,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'device/Instance',
|
||||
|
@ -545,7 +554,8 @@ export default [
|
|||
url: '/iot/device/Instance',
|
||||
icon: 'icon-shebei',
|
||||
sortIndex: 3,
|
||||
accessSupport: 'support',
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true,
|
||||
assetType: 'device',
|
||||
showPage: ['device-instance'],
|
||||
permissions: [
|
||||
|
@ -752,7 +762,8 @@ export default [
|
|||
sortIndex: 4,
|
||||
url: '/iot/device/Category',
|
||||
icon: 'icon-chanpinfenlei',
|
||||
accessSupport: 'support',
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true,
|
||||
assetType: 'deviceCategory',
|
||||
showPage: ['device-category'],
|
||||
permissions: [],
|
||||
|
@ -832,6 +843,8 @@ export default [
|
|||
actions: ['query'],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'link/AccessConfig',
|
||||
|
@ -956,6 +969,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'link/Protocol',
|
||||
|
@ -1026,6 +1041,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'Log',
|
||||
|
@ -1048,6 +1065,8 @@ export default [
|
|||
},
|
||||
],
|
||||
buttons: [],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'link/Type',
|
||||
|
@ -1124,6 +1143,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'link/Certificate',
|
||||
|
@ -1178,6 +1199,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'media/Stream',
|
||||
|
@ -1242,125 +1265,9 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
// {
|
||||
// code: 'link/Channel',
|
||||
// name: '通道配置',
|
||||
// owner: 'iot',
|
||||
// //parentId: '1-4',
|
||||
// //id: '1-4-8',
|
||||
// sortIndex: 8,
|
||||
// url: '/iot/link/Channel',
|
||||
// icon: 'icon-zidingyiguize',
|
||||
// showPage: ['media-server'],
|
||||
// permissions: [],
|
||||
// children: [
|
||||
// {
|
||||
// code: 'link/Channel/Opcua',
|
||||
// name: 'OPC UA',
|
||||
// owner: 'iot',
|
||||
// //parentId: '1-4-8',
|
||||
// //id: '1-4-8-1',
|
||||
// sortIndex: 1,
|
||||
// url: '/iot/link/Channel/Opcua',
|
||||
// icon: 'icon-zhilianshebei',
|
||||
// showPage: ['opc-client'],
|
||||
// permissions: [
|
||||
// { permission: 'opc-device-bind', actions: ['query'] },
|
||||
// { permission: 'opc-point', actions: ['query'] },
|
||||
// { permission: 'opc-client', actions: ['query'] },
|
||||
// ],
|
||||
// buttons: [
|
||||
// {
|
||||
// id: 'view',
|
||||
// name: '设备接入',
|
||||
// permissions: [
|
||||
// { permission: 'opc-point', actions: ['query'] },
|
||||
// { permission: 'opc-device-bind', actions: ['query'] },
|
||||
// { permission: 'opc-client', actions: ['query'] },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'action',
|
||||
// name: '启/禁用',
|
||||
// permissions: [
|
||||
// { permission: 'opc-point', actions: ['query', 'save'] },
|
||||
// { permission: 'opc-client', actions: ['query', 'save'] },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'update',
|
||||
// name: '编辑',
|
||||
// permissions: [
|
||||
// { permission: 'opc-point', actions: ['query', 'save'] },
|
||||
// { permission: 'opc-device-bind', actions: ['query', 'save'] },
|
||||
// { permission: 'opc-client', actions: ['query', 'save'] },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'delete',
|
||||
// name: '删除',
|
||||
// permissions: [
|
||||
// { permission: 'opc-point', actions: ['query', 'delete'] },
|
||||
// { permission: 'opc-device-bind', actions: ['query', 'delete'] },
|
||||
// { permission: 'opc-client', actions: ['query', 'delete'] },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'add',
|
||||
// name: '新增',
|
||||
// permissions: [
|
||||
// { permission: 'opc-point', actions: ['query', 'save'] },
|
||||
// { permission: 'opc-device-bind', actions: ['query', 'save'] },
|
||||
// { permission: 'opc-client', actions: ['query', 'save'] },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// code: 'link/Channel/Modbus',
|
||||
// name: 'Modbus',
|
||||
// owner: 'iot',
|
||||
// //parentId: '1-4-8',
|
||||
// //id: '1-4-8-2',
|
||||
// sortIndex: 2,
|
||||
// url: '/iot/link/Channel/Modbus',
|
||||
// icon: 'icon-changjingliandong',
|
||||
// showPage: ['modbus-master'],
|
||||
// permissions: [
|
||||
// { permission: 'modbus-point', actions: ['query', 'save', 'delete'] },
|
||||
// { permission: 'modbus-master', actions: ['query', 'save', 'delete'] },
|
||||
// ],
|
||||
// buttons: [
|
||||
// {
|
||||
// id: 'update',
|
||||
// name: '编辑',
|
||||
// permissions: [{ permission: 'modbus-master', actions: ['query', 'save'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'action',
|
||||
// name: '启/禁用',
|
||||
// permissions: [{ permission: 'modbus-master', actions: ['query', 'save'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'view',
|
||||
// name: '设备接入',
|
||||
// permissions: [{ permission: 'modbus-master', actions: ['query', 'save'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'delete',
|
||||
// name: '删除',
|
||||
// permissions: [{ permission: 'modbus-master', actions: ['query', 'delete'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'add',
|
||||
// name: '新增',
|
||||
// permissions: [{ permission: 'modbus-master', actions: ['query', 'save'] }],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
code: 'device/Firmware',
|
||||
name: '远程升级',
|
||||
|
@ -1458,6 +1365,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -1493,6 +1402,8 @@ export default [
|
|||
{ permission: 'things-collector', actions: ['query'] },
|
||||
],
|
||||
buttons: [],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'DataCollect/Channel',
|
||||
|
@ -1624,6 +1535,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'DataCollect/Collector',
|
||||
|
@ -1755,6 +1668,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -1787,6 +1702,8 @@ export default [
|
|||
{ permission: 'alarm-record', actions: ['query'] },
|
||||
],
|
||||
buttons: [],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'rule-engine/Alarm/Config',
|
||||
|
@ -1809,6 +1726,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'rule-engine/Alarm/Configuration',
|
||||
|
@ -1920,6 +1839,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'rule-engine/Alarm/Log',
|
||||
|
@ -1970,6 +1891,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -2061,6 +1984,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'Northbound/AliCloud',
|
||||
|
@ -2137,6 +2062,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -2295,6 +2222,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'rule-engine/Scene',
|
||||
|
@ -2445,6 +2374,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -2566,6 +2497,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'edge/Resource',
|
||||
|
@ -2641,6 +2574,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -2656,8 +2591,6 @@ export default [
|
|||
url: '/media',
|
||||
icon: 'icon-shipinwangguan',
|
||||
sortIndex: 2,
|
||||
accessSupport: 'indirect',
|
||||
indirectMenus: ['1-3-3'],
|
||||
permissions: [],
|
||||
buttons: [],
|
||||
children: [
|
||||
|
@ -2673,6 +2606,8 @@ export default [
|
|||
permissions: [],
|
||||
buttons: [],
|
||||
showPage: ['media-device'],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'media/DashBoard',
|
||||
|
@ -2691,6 +2626,8 @@ export default [
|
|||
],
|
||||
buttons: [],
|
||||
showPage: ['dashboard', 'media-device'],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'media/Device',
|
||||
|
@ -2811,6 +2748,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'media/SplitScreen',
|
||||
|
@ -2845,6 +2784,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'media/Cascade',
|
||||
|
@ -2954,6 +2895,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -3007,6 +2950,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'system/User',
|
||||
|
@ -3095,6 +3040,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'system/Department',
|
||||
|
@ -3291,6 +3238,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'system/Role',
|
||||
|
@ -3366,6 +3315,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'system/Menu',
|
||||
|
@ -3393,17 +3344,6 @@ export default [
|
|||
},
|
||||
],
|
||||
},
|
||||
// 超管才具备该权限
|
||||
// {
|
||||
// id: 'setting',
|
||||
// name: '配置',
|
||||
// permissions: [
|
||||
// {
|
||||
// permission: 'menu',
|
||||
// actions: ['query', 'save', 'grant'],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
id: 'update',
|
||||
name: '编辑',
|
||||
|
@ -3459,6 +3399,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'system/Permission',
|
||||
|
@ -3547,44 +3489,9 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
// {
|
||||
// code: 'system/Platforms',
|
||||
// name: '第三方平台',
|
||||
// owner: 'iot',
|
||||
// //parentId: '3',
|
||||
// //id: '3-7',
|
||||
// sortIndex: 7,
|
||||
// url: '/system/platforms',
|
||||
// icon: 'icon-xitongguanli1',
|
||||
// permissions: [{ permission: 'open-api', actions: ['query', 'save', 'delete'] }],
|
||||
// buttons: [
|
||||
// {
|
||||
// id: 'empowerment',
|
||||
// name: '赋权',
|
||||
// permissions: [
|
||||
// { permission: 'user-third-party-manager', actions: ['save'] },
|
||||
// { permission: 'open-api', actions: ['save'] },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// id: 'password',
|
||||
// name: '重置密码',
|
||||
// permissions: [{ permission: 'open-api', actions: ['save'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'delete',
|
||||
// name: '删除',
|
||||
// permissions: [{ permission: 'open-api', actions: ['delete'] }],
|
||||
// },
|
||||
// {
|
||||
// id: 'update',
|
||||
// name: '编辑',
|
||||
// permissions: [{ permission: 'open-api', actions: ['save'] }],
|
||||
// },
|
||||
// { id: 'add', name: '新增', permissions: [{ permission: 'open-api', actions: ['save'] }] },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
code: 'system/Relationship',
|
||||
name: '关系配置',
|
||||
|
@ -3638,6 +3545,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'system/DataSource',
|
||||
|
@ -3720,6 +3629,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "支持", value: "support" },
|
||||
supportDataAccess: true
|
||||
},
|
||||
{
|
||||
code: 'system/Platforms/Setting',
|
||||
|
@ -3767,6 +3678,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'system/Apply',
|
||||
|
@ -3859,6 +3772,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
code: 'system/License',
|
||||
|
@ -3955,6 +3870,8 @@ export default [
|
|||
icon: 'icon-keshihua',
|
||||
showPage: ['network-flow'],
|
||||
permissions: [{ permission: 'network-flow', actions: ['query'] }],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
path: '5Hpl-O2m8',
|
||||
|
@ -4115,6 +4032,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
path: '5Hpl-ZjAG',
|
||||
|
@ -4159,6 +4078,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
path: '5Hpl-eS9h',
|
||||
|
@ -4229,6 +4150,8 @@ export default [
|
|||
],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
{
|
||||
path: '5Hpl-cL34',
|
||||
|
@ -4247,6 +4170,8 @@ export default [
|
|||
actions: ['query'],
|
||||
},
|
||||
],
|
||||
accessSupport: { text: "不支持", value: "unsupported" },
|
||||
supportDataAccess: false
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -51,6 +51,7 @@ import Channel from '../components/Channel/index.vue';
|
|||
import Edge from '../components/Edge/index.vue';
|
||||
import Cloud from '../components/Cloud/index.vue';
|
||||
import { getProviders, detail } from '@/api/link/accessConfig';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
const route = useRoute();
|
||||
const id = route.params.id as string;
|
||||
|
@ -140,7 +141,8 @@ const getTypeList = (result: Record<string, any>) => {
|
|||
const queryProviders = async () => {
|
||||
const resp: any = await getProviders();
|
||||
if (resp.status === 200) {
|
||||
dataSource.value = getTypeList(resp.result);
|
||||
const data = resp.result || []
|
||||
dataSource.value = getTypeList(accessConfigTypeFilter(data as any[]));
|
||||
// dataSource.value = getTypeList(resp.result)[0].list.filter(
|
||||
// (item) => item.name !== '插件设备接入',
|
||||
// );
|
||||
|
@ -151,7 +153,8 @@ const getProvidersData = async () => {
|
|||
if (id !== ':id') {
|
||||
getProviders().then((response: any) => {
|
||||
if (response.status === 200) {
|
||||
const list = getTypeList(response.result);
|
||||
const data = response.result || []
|
||||
const list = getTypeList(accessConfigTypeFilter(data as any[]));
|
||||
dataSource.value = list.filter(
|
||||
(item: any) =>
|
||||
item.channel === 'network' ||
|
||||
|
|
|
@ -188,6 +188,7 @@ import {
|
|||
} from '@/api/link/accessConfig';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
|
@ -318,12 +319,7 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
const getProvidersList = async () => {
|
||||
const res: any = await getProviders();
|
||||
providersList.value = res.result;
|
||||
providersOptions.value = (res?.result || [])
|
||||
?.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))
|
||||
.filter((item: any) => item.value !== 'plugin_gateway'); // todo 暂时不做插件接入
|
||||
providersOptions.value = accessConfigTypeFilter(res.result || [])
|
||||
};
|
||||
getProvidersList();
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ import { queryTree } from '@/api/device/category'
|
|||
import { getTreeData_api } from '@/api/system/department'
|
||||
import { isNoCommunity } from '@/utils/utils'
|
||||
import { getImage } from '@/utils/comm'
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void
|
||||
|
@ -115,23 +116,7 @@ const columns = [
|
|||
search: {
|
||||
type: 'select',
|
||||
options: () => getProviders().then((resp: any) => {
|
||||
if (isNoCommunity) {
|
||||
return (resp?.result || []).map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id
|
||||
}))
|
||||
} else {
|
||||
return (resp?.result || []).filter((item: any) => [
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(item.id))
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}))
|
||||
}
|
||||
return accessConfigTypeFilter(resp.result || [])
|
||||
})
|
||||
}
|
||||
},
|
||||
|
|
|
@ -74,6 +74,7 @@ import { queryTree } from '@/api/device/category';
|
|||
import { getTreeData_api } from '@/api/system/department';
|
||||
import { isNoCommunity } from '@/utils/utils';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
|
||||
type Emit = {
|
||||
(e: 'update:rowKey', data: string): void;
|
||||
|
@ -127,26 +128,8 @@ const columns = [
|
|||
type: 'select',
|
||||
options: () =>
|
||||
getProviders().then((resp: any) => {
|
||||
if (isNoCommunity) {
|
||||
return (resp?.result || []).map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
} else {
|
||||
return (resp?.result || [])
|
||||
.filter((item: any) =>
|
||||
[
|
||||
'mqtt-server-gateway',
|
||||
'http-server-gateway',
|
||||
'mqtt-client-gateway',
|
||||
'tcp-server-gateway',
|
||||
].includes(item.id),
|
||||
)
|
||||
.map((item: any) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
const data = resp.result || []
|
||||
return accessConfigTypeFilter(data)
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
@select="onChange"
|
||||
>
|
||||
<template v-slot="{ label }">
|
||||
<j-input :value="label" />
|
||||
<j-input :value="label" readonly />
|
||||
</template>
|
||||
</ParamsDropdown>
|
||||
</template>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
@select="onValueChange"
|
||||
>
|
||||
<template v-slot="{ label }">
|
||||
<j-input :value="label" placeholder="请选择" />
|
||||
<j-input readonly :value="label" placeholder="请选择" />
|
||||
</template>
|
||||
</ParamsDropdown>
|
||||
</j-form-item>
|
||||
|
@ -112,7 +112,6 @@ const filterParamsData = (type?: string, data?: any[]): any[] => {
|
|||
item.children = _children;
|
||||
return _children.length ? true : false;
|
||||
} else if (item.type === type) {
|
||||
// optionMap.current.set(item.id, item);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -132,12 +131,12 @@ const handleOptions = computed(() => {
|
|||
if (_type === 'boolean') {
|
||||
return [
|
||||
{
|
||||
label: _item.trueText,
|
||||
value: _item.trueValue,
|
||||
label: _item.trueText || true,
|
||||
value: _item.trueValue || true,
|
||||
},
|
||||
{
|
||||
label: _item.falseText,
|
||||
value: _item.falseValue,
|
||||
label: _item.falseText || false,
|
||||
value: _item.falseValue || false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
|
@ -22,18 +22,19 @@
|
|||
showSearch
|
||||
placeholder="请选择功能"
|
||||
v-model:value="modelRef.message.functionId"
|
||||
@select="functionSelect"
|
||||
@change="functionSelect"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in metadata?.functions || []"
|
||||
:value="item?.id"
|
||||
:key="item?.id"
|
||||
:label="item?.name"
|
||||
>{{ item?.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
<j-form-item
|
||||
v-if="modelRef.message.functionId"
|
||||
v-if="modelRef.message.functionId && functions.length"
|
||||
:name="['message', 'inputs']"
|
||||
:rules="functionRules"
|
||||
>
|
||||
|
@ -54,6 +55,7 @@
|
|||
showSearch
|
||||
placeholder="请选择属性"
|
||||
v-model:value="modelRef.message.properties[0]"
|
||||
@change="propertySelect"
|
||||
>
|
||||
<j-select-option
|
||||
v-for="item in metadata?.properties.filter((i) =>
|
||||
|
@ -61,6 +63,7 @@
|
|||
) || []"
|
||||
:value="item?.id"
|
||||
:key="item?.id"
|
||||
:label="item?.name"
|
||||
>{{ item?.name }}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
|
@ -130,8 +133,14 @@ const props = defineProps({
|
|||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
productDetail: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const modelRef = reactive({
|
||||
|
@ -146,8 +155,19 @@ const modelRef = reactive({
|
|||
|
||||
const writeFormRef = ref();
|
||||
|
||||
const functionSelect = () => {
|
||||
const functionSelect = (val: any, options?: any) => {
|
||||
modelRef.message.inputs = [];
|
||||
emit('change', {
|
||||
propertiesName: options?.label,
|
||||
propertiesValue: modelRef.propertiesValue,
|
||||
});
|
||||
};
|
||||
|
||||
const propertySelect = (val: any, options?: any) => {
|
||||
emit('change', {
|
||||
propertiesName: options?.label,
|
||||
propertiesValue: modelRef.propertiesValue,
|
||||
});
|
||||
};
|
||||
|
||||
const functionRules = [
|
||||
|
@ -156,11 +176,11 @@ const functionRules = [
|
|||
if (!value?.length && functions.value.length) {
|
||||
return Promise.reject('请输入功能值');
|
||||
} else {
|
||||
const hasValue = value.find(
|
||||
const hasValue = value?.find(
|
||||
(item: { name: string; value: any }) => !item.value,
|
||||
);
|
||||
if (hasValue) {
|
||||
const functionItem = functions.value.find(
|
||||
const functionItem = functions.value?.find(
|
||||
(item: any) => item.id === hasValue.name,
|
||||
);
|
||||
return Promise.reject(
|
||||
|
@ -239,11 +259,11 @@ const onMessageTypeChange = (val: string) => {
|
|||
};
|
||||
|
||||
watch(
|
||||
() => props.values,
|
||||
() => props.productDetail,
|
||||
(newVal) => {
|
||||
if (newVal?.productDetail?.id) {
|
||||
if (newVal?.selector === 'fixed') {
|
||||
const id = newVal?.selectorValues?.[0]?.value;
|
||||
if (newVal?.id) {
|
||||
if (props.values?.selector === 'fixed') {
|
||||
const id = props.values?.selectorValues?.[0]?.value;
|
||||
if (id) {
|
||||
detail(id).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
|
@ -254,9 +274,7 @@ watch(
|
|||
});
|
||||
}
|
||||
} else {
|
||||
metadata.value = JSON.parse(
|
||||
newVal?.productDetail?.metadata || '{}',
|
||||
);
|
||||
metadata.value = JSON.parse(newVal?.metadata || '{}');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -282,6 +300,13 @@ watch(
|
|||
|
||||
const onWriteChange = (val: string) => {
|
||||
modelRef.propertiesValue = val;
|
||||
emit('change', {
|
||||
propertiesName:
|
||||
deviceMessageType.value === 'INVOKE_FUNCTION'
|
||||
? _function.value?.name
|
||||
: _property.value?.name,
|
||||
propertiesValue: modelRef.propertiesValue,
|
||||
});
|
||||
};
|
||||
|
||||
const onFormSave = () => {
|
||||
|
@ -295,19 +320,19 @@ const onFormSave = () => {
|
|||
reject(false);
|
||||
}
|
||||
}
|
||||
// 处理三种情况的值的格式
|
||||
const obj = {
|
||||
resolve({
|
||||
message: {
|
||||
...modelRef.message,
|
||||
..._data.message,
|
||||
propertiesName:
|
||||
deviceMessageType.value === 'INVOKE_FUNCTION'
|
||||
? _function.value?.name
|
||||
: _property.value?.name,
|
||||
propertiesValue: modelRef.propertiesValue,
|
||||
},
|
||||
};
|
||||
resolve(obj);
|
||||
});
|
||||
emit('change', {
|
||||
propertiesName:
|
||||
deviceMessageType.value === 'INVOKE_FUNCTION'
|
||||
? _function.value?.name
|
||||
: _property.value?.name,
|
||||
propertiesValue: modelRef.propertiesValue,
|
||||
});
|
||||
})
|
||||
.catch((err: any) => {
|
||||
reject(err);
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang='ts' name='Product'>
|
||||
import { query } from '@/api/device/instance';
|
||||
import { query, detail } from '@/api/device/instance';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { PropType } from 'vue';
|
||||
|
||||
|
@ -161,16 +161,27 @@ const deviceQuery = (p: any) => {
|
|||
return query(p);
|
||||
};
|
||||
|
||||
const handleClick = (detail: any) => {
|
||||
if (props.value?.[0]?.value === detail.id) {
|
||||
const handleClick = (_detail: any) => {
|
||||
if (props.value?.[0]?.value === _detail.id) {
|
||||
emit('update:value', undefined);
|
||||
emit('change', {});
|
||||
} else {
|
||||
emit('update:value', [{ value: detail.id, name: detail.name }]);
|
||||
emit('change', detail);
|
||||
emit('update:value', [{ value: _detail.id, name: _detail.name }]);
|
||||
emit('change', _detail);
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => props.value, async (newVal) => {
|
||||
if(newVal[0]?.value){
|
||||
const { result } = await detail(newVal[0]?.value)
|
||||
emit('update:value', [{ value: result?.id, name: result?.name }]);
|
||||
emit('change', result);
|
||||
}
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
params.value = {
|
||||
...params.value,
|
||||
|
|
|
@ -177,15 +177,8 @@ const onValueChange = () => {
|
|||
value: item.value,
|
||||
};
|
||||
});
|
||||
const arr = _data.map((item: any) => {
|
||||
return {
|
||||
column: item.name,
|
||||
type: item.type,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
||||
emits('update:value', [{ value: newValue, name: '标签' }]);
|
||||
emits('change', [{ value: newValue, name: '标签' }], arr);
|
||||
emits('change', [{ value: newValue, name: '标签' }], _data);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -13,18 +13,12 @@
|
|||
@change="onSelectorChange"
|
||||
/>
|
||||
</j-form-item>
|
||||
<!-- <j-form-item
|
||||
v-if="modelRef.selector === 'fixed'"
|
||||
name="selectorValues"
|
||||
:rules="[{ required: true, message: '请选择设备' }]"
|
||||
> -->
|
||||
<Device
|
||||
v-if="modelRef.selector === 'fixed'"
|
||||
:productId="values.productDetail.id"
|
||||
:productId="productDetail.id"
|
||||
v-model:value="modelRef.selectorValues"
|
||||
@change="onDeviceChange"
|
||||
/>
|
||||
<!-- </j-form-item> -->
|
||||
<j-form-item
|
||||
v-else-if="modelRef.selector === 'relation'"
|
||||
label="关系"
|
||||
|
@ -107,6 +101,10 @@ const props = defineProps({
|
|||
parallel: {
|
||||
type: Boolean,
|
||||
},
|
||||
productDetail: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
// save保存deviceDetail
|
||||
|
@ -122,9 +120,7 @@ const modelRef = reactive({
|
|||
selectorValues: undefined,
|
||||
deviceId: '',
|
||||
source: '',
|
||||
relationName: '',
|
||||
upperKey: '',
|
||||
message: undefined,
|
||||
});
|
||||
|
||||
const list = ref<any[]>([]);
|
||||
|
@ -166,10 +162,11 @@ const filterTree = (nodes: any[]) => {
|
|||
if (
|
||||
it.children.find(
|
||||
(item: any) =>
|
||||
item.id.indexOf('deviceId' || 'device_id' || 'device_Id') >
|
||||
-1,
|
||||
item?.id?.indexOf(
|
||||
'deviceId' || 'device_id' || 'device_Id',
|
||||
) > -1,
|
||||
) &&
|
||||
!it.children.find((item: any) => item.id.indexOf('boolean') > -1)
|
||||
!it.children.find((item: any) => item?.id.indexOf('boolean') > -1)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
@ -197,7 +194,7 @@ const sourceChangeEvent = async () => {
|
|||
const productId =
|
||||
data.value?.branches?.[props.branchesName].then?.[props.thenName]
|
||||
?.actions?.[props.name > 0 ? props.name - 1 : 0]?.device?.productId;
|
||||
if (productId === props.values?.productDetail?.id) {
|
||||
if (productId === props?.productDetail?.id) {
|
||||
const _data = await getParams(_params, unref(data));
|
||||
builtInList.value = handleParamsData(filterTree(_data), 'id');
|
||||
} else {
|
||||
|
@ -205,7 +202,7 @@ const sourceChangeEvent = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const filterType = async () => {
|
||||
const filterType = async (newVal: any) => {
|
||||
const _list = TypeList.filter((item) => item.value === 'fixed');
|
||||
if (unref(data)?.trigger?.type === 'device') {
|
||||
//关系
|
||||
|
@ -221,10 +218,9 @@ const filterType = async () => {
|
|||
_list.push(...array);
|
||||
}
|
||||
//标签
|
||||
const tag = JSON.parse(
|
||||
props.values.productDetail?.metadata || '{}',
|
||||
)?.tags;
|
||||
const tag = JSON.parse(newVal?.metadata || '{}')?.tags;
|
||||
if (tag && tag.length !== 0) {
|
||||
tagList.value = tag || [];
|
||||
const array = TypeList.filter((item) => item.value === 'tag');
|
||||
_list.push(...array);
|
||||
}
|
||||
|
@ -251,23 +247,23 @@ const filterType = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const onSelectorChange = () => {
|
||||
const onSelectorChange = (val: string) => {
|
||||
modelRef.selectorValues = undefined;
|
||||
modelRef.selector = val;
|
||||
};
|
||||
|
||||
const onDeviceChange = (_detail: any) => {
|
||||
if (_detail) {
|
||||
if (_detail.id) {
|
||||
modelRef.deviceId = _detail.id;
|
||||
modelRef.deviceId = _detail?.id;
|
||||
modelRef.selectorValues = [
|
||||
{ value: _detail.id, name: _detail.name },
|
||||
] as any;
|
||||
modelRef.message = {} as any;
|
||||
} else {
|
||||
modelRef.deviceId = '';
|
||||
modelRef.selectorValues = [] as any;
|
||||
}
|
||||
emits('save', unref(modelRef), _detail);
|
||||
emits('save', unref(modelRef), { name: _detail.name });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -276,8 +272,7 @@ const onRelationChange = (val: any, options: any) => {
|
|||
modelRef.source = 'upper';
|
||||
modelRef.selectorValues = val;
|
||||
modelRef.upperKey = 'scene.deviceId';
|
||||
modelRef.relationName = options.label;
|
||||
emits('save', unref(modelRef), {});
|
||||
emits('save', unref(modelRef), { relationName: options.label });
|
||||
};
|
||||
|
||||
const onTagChange = (val: any[], arr: any[]) => {
|
||||
|
@ -285,27 +280,61 @@ const onTagChange = (val: any[], arr: any[]) => {
|
|||
modelRef.deviceId = 'deviceId';
|
||||
modelRef.source = 'fixed';
|
||||
}
|
||||
emits('save', unref(modelRef), {}, arr ? { tagList: arr } : {});
|
||||
const tagName = arr.map((i, _index) => {
|
||||
return `${_index !== 0 && _index !== (arr || []).length && i.type}${
|
||||
i.name
|
||||
}为${i.value}`;
|
||||
});
|
||||
emits(
|
||||
'save',
|
||||
unref(modelRef),
|
||||
{},
|
||||
arr ? { tagName: tagName.join('') } : {},
|
||||
);
|
||||
};
|
||||
|
||||
const onVariableChange = (val: any, node: any) => {
|
||||
modelRef.deviceId = val;
|
||||
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
||||
emits('save', unref(modelRef), node);
|
||||
emits('save', unref(modelRef), { name: node.description });
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
Object.assign(modelRef, props.values);
|
||||
});
|
||||
watch(
|
||||
() => props.values,
|
||||
(newVal) => {
|
||||
Object.assign(modelRef, newVal);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.values.productDetail,
|
||||
() => props.productDetail,
|
||||
async (newVal) => {
|
||||
await sourceChangeEvent();
|
||||
if (newVal) {
|
||||
const metadata = JSON.parse(newVal?.metadata || '{}');
|
||||
tagList.value = metadata?.tags || [];
|
||||
filterType();
|
||||
filterType(newVal);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true,
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => [props.values, builtInList.value],
|
||||
([newVal1, newVal2]) => {
|
||||
if (newVal2 && newVal2.length) {
|
||||
const param = newVal1?.selectorValues?.[0]?.value;
|
||||
const isVariable = (newVal2 || [])?.find((item: any) => {
|
||||
return item.children.find((i: any) => i.id === param);
|
||||
});
|
||||
if (isVariable) {
|
||||
modelRef.selector = 'variable';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -319,14 +348,14 @@ const onFormSave = () => {
|
|||
formRef.value
|
||||
.validate()
|
||||
.then(async (_data: any) => {
|
||||
if(modelRef.selector === 'fixed'){
|
||||
if(!modelRef?.selectorValues?.[0]?.value){
|
||||
onlyMessage('请选择设备', 'error')
|
||||
if (modelRef.selector === 'fixed') {
|
||||
if (!modelRef?.selectorValues?.[0]?.value) {
|
||||
onlyMessage('请选择设备', 'error');
|
||||
reject(false);
|
||||
} else {
|
||||
resolve({
|
||||
..._data,
|
||||
selectorValues: modelRef.selectorValues
|
||||
selectorValues: modelRef.selectorValues,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<Product
|
||||
v-if="current === 0"
|
||||
v-model:rowKey="DeviceModel.productId"
|
||||
v-model:detail="DeviceModel.productDetail"
|
||||
v-model:detail="productDetail"
|
||||
@change="onProductChange"
|
||||
/>
|
||||
<Device
|
||||
|
@ -34,6 +34,7 @@
|
|||
:thenName="thenName"
|
||||
:values="DeviceModel"
|
||||
@save="onDeviceSave"
|
||||
:productDetail="productDetail"
|
||||
ref="deviceRef"
|
||||
/>
|
||||
<Action
|
||||
|
@ -42,7 +43,9 @@
|
|||
:branchesName="branchesName"
|
||||
:thenName="thenName"
|
||||
:values="DeviceModel"
|
||||
:productDetail="productDetail"
|
||||
ref="actionRef"
|
||||
@change="onActionsChange"
|
||||
/>
|
||||
</div>
|
||||
<template #footer>
|
||||
|
@ -61,7 +64,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DeviceModelType } from './typings';
|
||||
import { DeviceModelType, DeviceOptionType } from './typings';
|
||||
import Product from './Product.vue';
|
||||
import Device from './device/index.vue';
|
||||
import Action from './actions/index.vue';
|
||||
|
@ -105,26 +108,22 @@ const current = ref<number>(0);
|
|||
const deviceRef = ref<any>();
|
||||
const actionRef = ref<any>();
|
||||
|
||||
const productDetail = ref<any>({});
|
||||
|
||||
const DeviceModel = reactive<DeviceModelType>({
|
||||
productId: '',
|
||||
deviceId: '',
|
||||
productDetail: {},
|
||||
device: {},
|
||||
deviceDetail: {},
|
||||
options: {},
|
||||
selector: 'fixed',
|
||||
selectorValues: [],
|
||||
upperKey: '',
|
||||
source: 'fixed',
|
||||
relationName: '',
|
||||
message: {},
|
||||
propertiesName: '',
|
||||
propertiesValue: '',
|
||||
columns: [],
|
||||
actionName: '',
|
||||
tagList: [],
|
||||
message: {
|
||||
messageType: 'INVOKE_FUNCTION',
|
||||
},
|
||||
});
|
||||
|
||||
const DeviceOptions = ref<DeviceOptionType>({});
|
||||
|
||||
const emit = defineEmits<Emit>();
|
||||
|
||||
const onCancel = () => {
|
||||
|
@ -139,7 +138,6 @@ const onSave = (_data: any) => {
|
|||
productId: DeviceModel.productId,
|
||||
message: _data.message,
|
||||
};
|
||||
//处理按变量
|
||||
if (DeviceModel.selector === 'variable') {
|
||||
item.selector = 'fixed';
|
||||
}
|
||||
|
@ -152,55 +150,46 @@ const onSave = (_data: any) => {
|
|||
properties: '', //属性功能
|
||||
propertiesValue: '', //设置功能
|
||||
selector: DeviceModel.selector, //选择器标识
|
||||
productName: DeviceModel.productDetail.name,
|
||||
relationName: DeviceModel.relationName,
|
||||
triggerName: data.value.options?.trigger?.name || '触发设备',
|
||||
tagList: [],
|
||||
columns: [],
|
||||
otherColumns: [],
|
||||
...DeviceOptions.value,
|
||||
};
|
||||
_options.name =
|
||||
DeviceModel.deviceDetail?.name || DeviceModel.selectorValues?.[0]?.name;
|
||||
const _type = _data.message.messageType;
|
||||
if (_type === 'INVOKE_FUNCTION') {
|
||||
_options.type = '执行';
|
||||
_options.properties = _data.message.propertiesName;
|
||||
}
|
||||
if (_type === 'READ_PROPERTY') {
|
||||
_options.type = '读取';
|
||||
_options.properties = _data.message.propertiesName;
|
||||
}
|
||||
if (_type === 'WRITE_PROPERTY') {
|
||||
_options.type = '设置';
|
||||
_options.properties = _data.message.propertiesName;
|
||||
_options.propertiesValue =
|
||||
typeof _data.message.propertiesValue === 'object'
|
||||
? JSON.stringify(_data.message.propertiesValue)
|
||||
: `${_data.message.propertiesValue}`;
|
||||
_options.columns = DeviceModel.columns;
|
||||
_options.otherColumns = DeviceModel.columns;
|
||||
const cur: any = Object.values(_data.message.properties)?.[0];
|
||||
if (cur?.source === 'upper') {
|
||||
_options.propertiesValue = DeviceModel.actionName;
|
||||
}
|
||||
}
|
||||
if (_options.selector === 'tag') {
|
||||
_options.taglist = DeviceModel.tagList.map((it) => ({
|
||||
name: it.column || it.name,
|
||||
type: it.type ? (it.type === 'and' ? '并且' : '或者') : '',
|
||||
value: it.value,
|
||||
}));
|
||||
}
|
||||
if (_options.selector === 'variable') {
|
||||
_options.name = DeviceModel.selectorValues?.[0]?.name;
|
||||
(typeof _options?.propertiesValue === 'object'
|
||||
? JSON.stringify(_options?.propertiesValue)
|
||||
: `${_options?.propertiesValue}`) || DeviceModel?.selectorValues?.[0]?.value;
|
||||
}
|
||||
emit('save', item, _options);
|
||||
};
|
||||
|
||||
const onProductChange = () => {
|
||||
DeviceModel.selectorValues = undefined
|
||||
DeviceModel.message = {}
|
||||
}
|
||||
const onProductChange = (_val: any) => {
|
||||
DeviceModel.selectorValues = undefined;
|
||||
DeviceModel.message = {
|
||||
messageType: 'INVOKE_FUNCTION',
|
||||
};
|
||||
DeviceOptions.value.productName = _val?.name;
|
||||
};
|
||||
|
||||
const onDeviceSave = (_data: any, obj?: any) => {
|
||||
Object.assign(DeviceModel, { ..._data });
|
||||
DeviceOptions.value = { ...unref(DeviceOptions), ...obj };
|
||||
};
|
||||
|
||||
const onActionsChange = (options?: any) => {
|
||||
const obj = {
|
||||
...DeviceOptions.value,
|
||||
...options,
|
||||
};
|
||||
DeviceOptions.value = obj;
|
||||
};
|
||||
|
||||
const save = async (step?: number) => {
|
||||
let _step = step !== undefined ? step : current.value;
|
||||
|
@ -215,7 +204,7 @@ const save = async (step?: number) => {
|
|||
} else if (DeviceModel.selectorValues?.length) {
|
||||
current.value = 2;
|
||||
} else {
|
||||
onlyMessage('请选择设备', 'error')
|
||||
onlyMessage('请选择设备', 'error');
|
||||
}
|
||||
} else {
|
||||
if (actionRef.value) {
|
||||
|
@ -239,41 +228,14 @@ const prev = () => {
|
|||
|
||||
const saveClick = () => save();
|
||||
|
||||
const onDeviceSave = (_data: any, _detail: any, obj?: any) => {
|
||||
Object.assign(DeviceModel, { ..._data, ...obj });
|
||||
DeviceModel.deviceDetail = _detail;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newValue) => {
|
||||
Object.assign(DeviceModel, newValue);
|
||||
Object.assign(DeviceModel, {...newValue});
|
||||
if (newValue?.productId) {
|
||||
detail(newValue.productId).then((resp) => {
|
||||
if (resp.status === 200) {
|
||||
DeviceModel.productDetail = resp.result;
|
||||
if (
|
||||
DeviceModel.selector === 'tag' &&
|
||||
DeviceModel.selectorValues[0]?.value
|
||||
) {
|
||||
const metadata = JSON.parse(
|
||||
DeviceModel.productDetail?.metadata || '{}',
|
||||
);
|
||||
const tags = metadata.tags || [];
|
||||
const arr = DeviceModel.selectorValues[0]?.value
|
||||
.filter((item: any) => !!item.value)
|
||||
.map((item: any) => {
|
||||
return {
|
||||
column:
|
||||
tags.find(
|
||||
(i: any) => i.id === item.column,
|
||||
)?.name || item.column,
|
||||
type: item.type,
|
||||
value: item.value,
|
||||
};
|
||||
});
|
||||
DeviceModel.tagList = arr;
|
||||
}
|
||||
productDetail.value = resp.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,27 +2,27 @@ import { ProductItem } from '@/views/device/Product/typings';
|
|||
import { ActionsDeviceProps } from '../../../typings';
|
||||
|
||||
type DeviceModelType = {
|
||||
// steps: {
|
||||
// key: string;
|
||||
// title: string;
|
||||
// content: React.ReactNode;
|
||||
// }[];
|
||||
// current: number;
|
||||
productId: string;
|
||||
deviceId: string;
|
||||
productDetail: ProductItem | any;
|
||||
device: Partial<ActionsDeviceProps>;
|
||||
deviceDetail: any;
|
||||
options: any;
|
||||
source: string;
|
||||
selector: string;
|
||||
selectorValues: any;
|
||||
upperKey: string;
|
||||
source: string;
|
||||
relationName: string;
|
||||
message: any;
|
||||
propertiesName: string;
|
||||
propertiesValue: string | any;
|
||||
columns: string[];
|
||||
actionName: string;
|
||||
tagList: any[];
|
||||
}
|
||||
upperKey: string;
|
||||
deviceId: string;
|
||||
message: {
|
||||
properties?: any;
|
||||
messageType: string;
|
||||
inputs?: any[]
|
||||
}
|
||||
}
|
||||
|
||||
type DeviceOptionType = {
|
||||
name?: string;
|
||||
productName?: string;
|
||||
propertiesValue?: string;
|
||||
propertiesName?: any;
|
||||
tagName?: string;
|
||||
relationName?: string;
|
||||
actionName?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,12 +58,14 @@ const checkDeviceDelete = async () => {
|
|||
formTouchOff()
|
||||
return
|
||||
}
|
||||
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
||||
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
|
||||
if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { // 某一个设备被删除
|
||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||
formTouchOff()
|
||||
return
|
||||
if (item?.selector === 'fixed') {
|
||||
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
||||
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
|
||||
if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { // 某一个设备被删除
|
||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||
formTouchOff()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -107,9 +107,11 @@ const onKeys: string[] = EventSubscribeKeys({
|
|||
action: props.actionName
|
||||
})
|
||||
|
||||
EventEmitter.subscribe(onKeys, (d: any) => {
|
||||
const handleRequest = () => {
|
||||
columnRequest()
|
||||
})
|
||||
}
|
||||
|
||||
EventEmitter.subscribe(onKeys, handleRequest)
|
||||
|
||||
provide('filter-params', columnOptions)
|
||||
|
||||
|
@ -241,6 +243,10 @@ nextTick(() => {
|
|||
columnRequest()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
EventEmitter.unSubscribe(onKeys, handleRequest)
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -263,7 +263,7 @@
|
|||
{{data?.options?.name}}
|
||||
</Ellipsis>
|
||||
<Ellipsis style='max-width: 400px;'>
|
||||
{{data?.options?.properties}}
|
||||
{{data?.options?.propertiesName}}
|
||||
</Ellipsis>
|
||||
|
||||
<Ellipsis style='max-width: 200px;'>
|
||||
|
@ -295,21 +295,9 @@
|
|||
"
|
||||
/>
|
||||
{{ data?.options?.type }}
|
||||
<span
|
||||
v-for="(i, _index) in data?.options?.taglist ||
|
||||
[]"
|
||||
:key="i.value"
|
||||
>
|
||||
{{
|
||||
_index !== 0 &&
|
||||
_index !==
|
||||
(data?.options?.taglist || []).length &&
|
||||
i.type
|
||||
}}
|
||||
{{ i.name }}为{{ i.value }}
|
||||
</span>
|
||||
<span>{{ data?.options?.tagName }}</span>
|
||||
的{{ data?.options?.productName }}
|
||||
{{ data?.options?.properties }}
|
||||
{{ data?.options?.propertiesName }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="data?.device?.selector === 'relation'">
|
||||
|
@ -328,7 +316,7 @@
|
|||
>具有相同 {{ data?.options?.relationName }}的{{
|
||||
data?.options?.productName
|
||||
}}设备的
|
||||
{{ data?.options?.properties }}
|
||||
{{ data?.options?.propertiesName }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -572,44 +560,6 @@ const rules = [{
|
|||
}
|
||||
}]
|
||||
|
||||
const formTouchOff = () => {
|
||||
console.log('formTouchOff')
|
||||
formItemContext.onFieldChange()
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前执行动作的设备或者产品是否删除
|
||||
*/
|
||||
const checkDeviceDelete = async () => {
|
||||
const item = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device
|
||||
const proResp = await queryProductList({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.productId }]}]})
|
||||
if (proResp.success && (proResp.result as any)?.total === 0) { // 产品已删除
|
||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.productId = undefined
|
||||
formTouchOff()
|
||||
return
|
||||
}
|
||||
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
||||
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
|
||||
if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { // 某一个设备被删除
|
||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||
formTouchOff()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前执行动作的通知配置、消息模板是否删除
|
||||
*/
|
||||
const checkNoticeDelete = () => {
|
||||
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
if (_data.value.branches![props.branchesName].then[props.thenName].actions[props.name]?.executor === 'device') {
|
||||
checkDeviceDelete()
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -221,7 +221,7 @@ const showDouble = computed(() => {
|
|||
} else {
|
||||
metricOption.value = []
|
||||
}
|
||||
return isRange && !isMetric
|
||||
return isRange && !isMetric.value
|
||||
})
|
||||
|
||||
const mouseover = () => {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { BranchesThen } from '@/views/rule-engine/Scene/typings'
|
||||
|
||||
export const ContextKey = 'columnOptions'
|
||||
|
||||
export const handleParamsData = (data: any[], key: string = 'column'): any[] => {
|
||||
|
@ -12,7 +14,7 @@ export const handleParamsData = (data: any[], key: string = 'column'): any[] =>
|
|||
}
|
||||
|
||||
export const thenRules = [{
|
||||
validator(_: string, value: any) {
|
||||
validator(_: string, value: BranchesThen[]) {
|
||||
if (!value || (value && !value.length) || !value.some(item => item.actions && item.actions.length)) {
|
||||
return Promise.reject('至少配置一个执行动作')
|
||||
}
|
||||
|
|
|
@ -540,7 +540,7 @@
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '该字段是必填字段',
|
||||
message: '请输入用户名',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
|
@ -567,7 +567,7 @@
|
|||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '该字段是必填字段',
|
||||
message: '请输入密码',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
|
@ -824,7 +824,15 @@
|
|||
placeholder="请输入redirectUrl"
|
||||
/>
|
||||
</j-form-item>
|
||||
<j-form-item label="IP白名单">
|
||||
<j-form-item
|
||||
label="IP白名单"
|
||||
:name="['apiServer', 'ipWhiteList']"
|
||||
:rules="[
|
||||
{
|
||||
validator: validateIP,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<j-textarea
|
||||
v-model:value="form.data.apiServer.ipWhiteList"
|
||||
placeholder="请输入IP白名单,多个地址回车分隔,不填默认均可访问"
|
||||
|
@ -1197,12 +1205,7 @@
|
|||
<j-form-item
|
||||
v-if="form.data.provider !== 'dingtalk-ent-app'"
|
||||
class="resetLabel"
|
||||
:name="[
|
||||
'sso',
|
||||
'configuration',
|
||||
'oauth2',
|
||||
'clientId',
|
||||
]"
|
||||
:name="['sso', 'configuration', 'appId']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
|
@ -1223,7 +1226,7 @@
|
|||
</template>
|
||||
<j-input
|
||||
v-model:value="
|
||||
form.data.sso.configuration.oauth2.clientId
|
||||
form.data.sso.configuration.appId
|
||||
"
|
||||
placeholder="请输入appId"
|
||||
/>
|
||||
|
@ -1232,12 +1235,7 @@
|
|||
<j-form-item
|
||||
v-if="form.data.provider !== 'wechat-webapp'"
|
||||
class="resetLabel"
|
||||
:name="[
|
||||
'sso',
|
||||
'configuration',
|
||||
'oauth2',
|
||||
'clientSecret',
|
||||
]"
|
||||
:name="['sso', 'configuration', 'appKey']"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
|
@ -1258,8 +1256,7 @@
|
|||
</template>
|
||||
<j-input
|
||||
v-model:value="
|
||||
form.data.sso.configuration.oauth2
|
||||
.clientSecret
|
||||
form.data.sso.configuration.appKey
|
||||
"
|
||||
placeholder="请输入appKey"
|
||||
/>
|
||||
|
@ -1443,6 +1440,7 @@
|
|||
<script setup lang="ts">
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
import { LocalStore, filterSelectNode } from '@/utils/comm';
|
||||
import { testIP } from '@/utils/validate';
|
||||
|
||||
import {
|
||||
getDepartmentList_api,
|
||||
|
@ -1465,6 +1463,7 @@ import {
|
|||
import { randomString } from '@/utils/utils';
|
||||
import { cloneDeep, difference } from 'lodash';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import { Rule } from 'ant-design-vue/lib/form';
|
||||
|
||||
const emit = defineEmits(['changeApplyType']);
|
||||
const routeQuery = useRoute().query;
|
||||
|
@ -1673,6 +1672,10 @@ function init() {
|
|||
watch(
|
||||
() => form.data.provider,
|
||||
(n) => {
|
||||
form.data.page.baseUrl = '';
|
||||
form.data.page.parameters = [];
|
||||
form.data.apiClient.baseUrl = '';
|
||||
form.data.apiClient.parameters = [];
|
||||
emit('changeApplyType', n);
|
||||
if (routeQuery.id) return;
|
||||
if (n === 'wechat-webapp' || n === 'dingtalk-ent-app') {
|
||||
|
@ -1697,19 +1700,21 @@ function init() {
|
|||
function getInfo(id: string) {
|
||||
getAppInfo_api(id).then((resp: any) => {
|
||||
// 后端返回的headers和parameters中, key转为label
|
||||
resp.result.apiClient.headers = resp.result.apiClient.headers.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
label: m.key,
|
||||
}),
|
||||
);
|
||||
resp.result.apiClient.parameters = resp.result.apiClient.parameters.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
label: m.key,
|
||||
}),
|
||||
);
|
||||
if (resp.result.apiClient) {
|
||||
resp.result.apiClient.headers = resp.result.apiClient.headers.map(
|
||||
(m: any) => ({
|
||||
...m,
|
||||
label: m.key,
|
||||
}),
|
||||
);
|
||||
resp.result.apiClient.parameters =
|
||||
resp.result.apiClient.parameters.map((m: any) => ({
|
||||
...m,
|
||||
label: m.key,
|
||||
}));
|
||||
}
|
||||
form.data = {
|
||||
...initForm, // 查询详情, 赋值初始字段. 解决编辑改变接入方式报错的问题: bug#10892
|
||||
...resp.result,
|
||||
integrationModes: resp.result.integrationModes.map(
|
||||
(item: any) => item.value,
|
||||
|
@ -1749,7 +1754,6 @@ function clickAddItem(data: string[], target: string) {
|
|||
}
|
||||
// 保存
|
||||
function clickSave() {
|
||||
console.log('headers: ', form.data.apiClient.headers);
|
||||
formRef.value?.validate().then(() => {
|
||||
const params = cloneDeep(form.data);
|
||||
// 删除多余的参数
|
||||
|
@ -1813,7 +1817,7 @@ function clickSave() {
|
|||
if (resp.status === 200) {
|
||||
const isPage = params.integrationModes.includes('page');
|
||||
if (isPage) {
|
||||
form.data = params;
|
||||
// form.data = params;
|
||||
dialog.selectId = routeQuery.id || resp.result.id;
|
||||
dialog.selectProvider = form.data.provider;
|
||||
dialog.visible = true;
|
||||
|
@ -1842,7 +1846,7 @@ function getErrorNum(
|
|||
}
|
||||
}
|
||||
|
||||
const imageTypes = ref(['image/jpg', 'image/png']);
|
||||
const imageTypes = ref(['image/jpg', 'image/png', 'image/jpeg']);
|
||||
const beforeLogoUpload = (file: any) => {
|
||||
const isType: any = imageTypes.value.includes(file.type);
|
||||
if (!isType) {
|
||||
|
@ -1863,7 +1867,6 @@ function changeBackUpload(info: UploadChangeParam<UploadFile<any>>) {
|
|||
form.uploadLoading = false;
|
||||
form.data.sso.configuration.oauth2.logoUrl = info.file.response?.result;
|
||||
} else if (info.file.status === 'error') {
|
||||
console.log(info.file);
|
||||
form.uploadLoading = false;
|
||||
message.error('logo上传失败,请稍后再试');
|
||||
}
|
||||
|
@ -1878,6 +1881,23 @@ function clearNullProp(obj: object) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证IP合法性
|
||||
* @param _rule
|
||||
* @param value
|
||||
*/
|
||||
const validateIP = (_rule: Rule, value: string) => {
|
||||
const ipList = value?.split(/[\n,]/g).filter((i: string) => i && i.trim());
|
||||
const errorIPList = ipList.filter(
|
||||
(f: string) => !testIP(f.replace(/\s*/g, '')),
|
||||
);
|
||||
return new Promise((resolve, reject) => {
|
||||
!errorIPList.length
|
||||
? resolve('')
|
||||
: reject(`[${errorIPList}]不是正确的IP地址`);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -117,9 +117,7 @@
|
|||
</j-form-item>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'notnull'">
|
||||
<j-form-item
|
||||
:name="['data', index, 'notnull']"
|
||||
>
|
||||
<j-form-item :name="['data', index, 'notnull']">
|
||||
<j-radio-group
|
||||
v-model:value="record.notnull"
|
||||
button-style="solid"
|
||||
|
@ -134,9 +132,7 @@
|
|||
</j-form-item>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'comment'">
|
||||
<j-form-item
|
||||
:name="['data', index, 'notnull']"
|
||||
>
|
||||
<j-form-item :name="['data', index, 'notnull']">
|
||||
<j-input
|
||||
v-model:value="record.comment"
|
||||
placeholder="请输入说明"
|
||||
|
@ -167,20 +163,27 @@
|
|||
</j-button>
|
||||
</div>
|
||||
</div>
|
||||
<j-modal v-model:visible="dialog.visible" title="新增" @ok="handleOk">
|
||||
<j-form :model="dialog.form" ref="addFormRef">
|
||||
<j-modal
|
||||
:visible="true"
|
||||
v-if="dialog.visible"
|
||||
title="新增"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<j-form :model="dialog.form" ref="addFormRef" :layout="'vertical'">
|
||||
<j-form-item
|
||||
label="名称"
|
||||
name="name"
|
||||
:required="true"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入名称',
|
||||
},
|
||||
// {
|
||||
// required: true,
|
||||
// message: '请输入名称',
|
||||
// },
|
||||
{
|
||||
max: 64,
|
||||
message: '最多可输入64个字符',
|
||||
trigger: 'blur',
|
||||
trigger: 'change',
|
||||
},
|
||||
{
|
||||
// pattern: /^[0-9].*$/,
|
||||
|
@ -191,7 +194,7 @@
|
|||
{
|
||||
pattern: /^\w+$/,
|
||||
message: '名称只能由数字、字母、下划线、中划线组成',
|
||||
trigger: 'blur',
|
||||
trigger: 'change',
|
||||
},
|
||||
]"
|
||||
>
|
||||
|
@ -410,6 +413,11 @@ const handleOk = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
dialog.visible = false;
|
||||
addFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
watch(
|
||||
[() => leftData.searchValue, () => leftData.sourceTree],
|
||||
([m, n]) => {
|
||||
|
@ -458,6 +466,8 @@ const checkName = (_: any, value: any) =>
|
|||
} else {
|
||||
resolve('');
|
||||
}
|
||||
} else {
|
||||
reject('请输入名称');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,388 +0,0 @@
|
|||
<template>
|
||||
<div class="setting-container">
|
||||
<h5 class="top">
|
||||
<AIcon type="ExclamationCircleOutlined" />
|
||||
<span style="padding-left: 12px"
|
||||
>基于系统源代码中的菜单数据,配置系统菜单。</span
|
||||
>
|
||||
</h5>
|
||||
|
||||
<div class="transfer">
|
||||
<!-- 左侧树 -->
|
||||
<div class="basic-tree left">
|
||||
<div class="title">
|
||||
<div class="title-label">
|
||||
<span>源菜单</span>
|
||||
<j-tooltip>
|
||||
<template #title
|
||||
>根据系统代码自动读取的菜单数据</template
|
||||
>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<div class="title-func">
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="dialogShow = true"
|
||||
ghost
|
||||
>一键拷贝</j-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<j-input
|
||||
v-model:value="transfer.data.leftSearchValue"
|
||||
style="margin-bottom: 8px"
|
||||
placeholder="请输入菜单名称"
|
||||
@change="transfer.changeTreeLeft"
|
||||
>
|
||||
<template #prefix>
|
||||
<AIcon
|
||||
type="SearchOutlined"
|
||||
style="color: #b3b3b3"
|
||||
/>
|
||||
</template>
|
||||
</j-input>
|
||||
<j-tree
|
||||
v-if="transfer.data.leftTreeData.length !== 0"
|
||||
:tree-data="transfer.data.leftTreeData"
|
||||
draggable
|
||||
defaultExpandAll
|
||||
:height="550"
|
||||
>
|
||||
<template #title="row">
|
||||
<div>{{ row.name }}</div>
|
||||
</template>
|
||||
</j-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="center">
|
||||
<j-button>请拖动至右侧</j-button>
|
||||
</div>
|
||||
<!-- 右侧树 -->
|
||||
<div class="basic-tree right">
|
||||
<div class="title">
|
||||
<div class="title-label">
|
||||
<span>系统菜单</span>
|
||||
<j-tooltip>
|
||||
<template #title
|
||||
>菜单管理页面配置的菜单数据</template
|
||||
>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</j-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<j-input
|
||||
v-model:value="transfer.data.rightSearchValue"
|
||||
style="margin-bottom: 8px"
|
||||
placeholder="请输入菜单名称"
|
||||
@change="transfer.changeTreeRight"
|
||||
>
|
||||
<template #prefix>
|
||||
<AIcon
|
||||
type="SearchOutlined"
|
||||
style="color: #b3b3b3"
|
||||
/>
|
||||
</template>
|
||||
</j-input>
|
||||
|
||||
<j-tree
|
||||
v-if="transfer.data.rightTreeData.length !== 0"
|
||||
draggable
|
||||
defaultExpandAll
|
||||
:tree-data="transfer.data.rightTreeData"
|
||||
@drop="transfer.onRightDrop"
|
||||
:height="550"
|
||||
>
|
||||
<template #title="row">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
"
|
||||
>
|
||||
<span>{{ row.name }}</span>
|
||||
<j-popconfirm
|
||||
title="确认删除?"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="transfer.removeItem(row)"
|
||||
placement="topRight"
|
||||
>
|
||||
<j-tooltip>
|
||||
<template #title>删除</template>
|
||||
<j-button
|
||||
style="
|
||||
padding: 0;
|
||||
margin-right: 12px;
|
||||
"
|
||||
type="link"
|
||||
>
|
||||
<AIcon type="CloseOutlined" />
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
</j-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
</j-tree>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<j-button type="primary" style="margin-top: 24px">保存</j-button>
|
||||
|
||||
<div class="dialogs">
|
||||
<j-modal
|
||||
v-model:visible="dialogShow"
|
||||
title="一键拷贝"
|
||||
@ok="transfer.copy"
|
||||
cancelText="取消"
|
||||
okText="确认"
|
||||
>
|
||||
<p>源数据将会覆盖当前的系统菜单数据,确定要一键拷贝吗?</p>
|
||||
</j-modal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="MenuSetting">
|
||||
import { getMenuTree_api } from '@/api/system/menu';
|
||||
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
||||
import { filterMenu, getKeys, loop } from './utils';
|
||||
import BaseTreeData from './baseMenu';
|
||||
import type {
|
||||
AntTreeNodeDropEvent,
|
||||
TreeDataItem,
|
||||
TreeProps,
|
||||
} from 'ant-design-vue/es/tree';
|
||||
import { treeFilter } from '@/utils/tree';
|
||||
import { cloneDeep } from 'lodash';
|
||||
|
||||
const transfer = {
|
||||
data: reactive({
|
||||
// 左侧树
|
||||
leftSearchValue: '',
|
||||
leftTreeData: [] as any[],
|
||||
|
||||
// 右侧树
|
||||
rightSearchValue: '',
|
||||
rightTreeData: [] as any[],
|
||||
}),
|
||||
leftSourceData: [] as any[],
|
||||
rightSourceData: [] as any[],
|
||||
|
||||
init: () => {
|
||||
// 源菜单
|
||||
const sourceMenu = getSystemPermission_api().then((resp: any) => {
|
||||
const newTree = filterMenu(
|
||||
resp.result.map((item: any) => JSON.parse(item).id),
|
||||
BaseTreeData,
|
||||
);
|
||||
transfer.leftSourceData = [...newTree];
|
||||
transfer.data.leftTreeData = newTree;
|
||||
});
|
||||
const params = {
|
||||
paging: false,
|
||||
terms: [
|
||||
{
|
||||
terms: [
|
||||
{
|
||||
column: 'owner',
|
||||
termType: 'eq',
|
||||
value: 'iot',
|
||||
},
|
||||
{
|
||||
column: 'owner',
|
||||
termType: 'isnull',
|
||||
value: '1',
|
||||
type: 'or',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
// 系统菜单
|
||||
const systemMenu = getMenuTree_api(params).then((resp: any) => {
|
||||
transfer.data.rightTreeData = resp.result;
|
||||
transfer.rightSourceData = [...resp.result];
|
||||
});
|
||||
// 当两个菜单的源数据都获取到之后,对左侧菜单进行更新,更新每项是否需要禁用
|
||||
Promise.all([sourceMenu, systemMenu]).then(() => transfer.updateTree());
|
||||
},
|
||||
copy: () => {
|
||||
transfer.data.rightTreeData = [...toRaw(transfer.data.leftTreeData)];
|
||||
dialogShow.value = false;
|
||||
},
|
||||
removeItem: (row: any) => {
|
||||
loop(
|
||||
transfer.data.rightTreeData,
|
||||
row.id,
|
||||
(item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
||||
arr?.splice(index, 1);
|
||||
},
|
||||
);
|
||||
transfer.updateTree();
|
||||
},
|
||||
onRightDrop: (info: AntTreeNodeDropEvent) => {
|
||||
const dropKey = info.node.id;
|
||||
const dragKey = info.dragNode.id;
|
||||
const dropPos = (info.node.pos && info.node.pos.split('-')) || [];
|
||||
const dropPosition =
|
||||
info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
||||
const data = [...transfer.data.rightTreeData];
|
||||
let dragObj: TreeDataItem = { key: '' };
|
||||
loop(
|
||||
data,
|
||||
dragKey,
|
||||
(item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
||||
arr?.splice(index, 1);
|
||||
dragObj = item;
|
||||
},
|
||||
);
|
||||
|
||||
if (!info.dropToGap) {
|
||||
// Drop on the content
|
||||
loop(data, dropKey, (item: TreeDataItem) => {
|
||||
item.children = item.children || [];
|
||||
/// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else if (
|
||||
(info.node.children || []).length > 0 && // Has children
|
||||
info.node.expanded && // Is expanded
|
||||
dropPosition === 1 // On the bottom gap
|
||||
) {
|
||||
loop(data, dropKey, (item: TreeDataItem) => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else {
|
||||
let ar: TreeProps['treeData'] = [];
|
||||
let i = 0;
|
||||
loop(
|
||||
data,
|
||||
dropKey,
|
||||
(
|
||||
_item: TreeDataItem,
|
||||
index: number,
|
||||
arr: TreeProps['treeData'],
|
||||
) => {
|
||||
ar = arr;
|
||||
i = index;
|
||||
},
|
||||
);
|
||||
if (dropPosition === -1) {
|
||||
ar.splice(i, 0, dragObj);
|
||||
} else {
|
||||
ar.splice(i + 1, 0, dragObj);
|
||||
}
|
||||
}
|
||||
transfer.data.rightTreeData = data;
|
||||
},
|
||||
updateTree: () => {
|
||||
console.log(getKeys(transfer.data.rightTreeData));
|
||||
},
|
||||
changeTreeLeft: (val: any) => {
|
||||
const value = val.target.value;
|
||||
if (value) {
|
||||
transfer.data.leftTreeData = treeFilter(
|
||||
transfer.leftSourceData,
|
||||
value,
|
||||
'name',
|
||||
);
|
||||
} else {
|
||||
transfer.data.leftTreeData = cloneDeep(transfer.rightSourceData);
|
||||
}
|
||||
},
|
||||
changeTreeRight: (val: any) => {
|
||||
const value = val.target.value;
|
||||
if (value) {
|
||||
transfer.data.rightTreeData = treeFilter(
|
||||
transfer.rightSourceData,
|
||||
value,
|
||||
'name',
|
||||
);
|
||||
} else {
|
||||
transfer.data.rightTreeData = cloneDeep(transfer.rightSourceData);
|
||||
}
|
||||
},
|
||||
};
|
||||
transfer.init();
|
||||
|
||||
const dialogShow = ref<boolean>(false);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.setting-container {
|
||||
padding: 24px;
|
||||
margin: 24px;
|
||||
background-color: #fff;
|
||||
|
||||
.top {
|
||||
font-size: inherit;
|
||||
margin-bottom: 24px;
|
||||
padding: 10px 24px;
|
||||
color: rgba(0, 0, 0, 0.55);
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.transfer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.basic-tree {
|
||||
flex: 1;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
padding: 14px 16px;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
background-color: #f3f4f4;
|
||||
|
||||
.title-label {
|
||||
span {
|
||||
padding-right: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 12px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
:deep(.ant-tree) {
|
||||
height: 550px;
|
||||
overflow: auto;
|
||||
.ant-tree-list-holder-inner {
|
||||
> .ant-tree-treenode {
|
||||
width: 100%;
|
||||
}
|
||||
.ant-tree-node-content-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
flex-basis: 120px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -3,84 +3,84 @@
|
|||
<j-card>
|
||||
<div class="top">
|
||||
<AIcon style="padding: 12px" type="ExclamationCircleOutlined" />
|
||||
<span>基于系统源代码中的菜单数据,配置系统菜单。</span>
|
||||
<span
|
||||
>单击可切换菜单未选中/选中状态;操作父级菜单时,对应子菜单状态将默认与其同步,可以单独操作调整;支持拖拽菜单调整展示顺序。
|
||||
</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">
|
||||
系统菜单
|
||||
<j-tooltip>
|
||||
<template #title
|
||||
>根据系统代码自动读取的菜单数据</template
|
||||
<j-card title="菜单配置" style="width: 80%">
|
||||
<div class="tree">
|
||||
<j-tree
|
||||
v-if="treeData.length !== 0"
|
||||
show-line
|
||||
defaultExpandAll
|
||||
multiple
|
||||
draggable
|
||||
:tree-data="treeData"
|
||||
:height="520"
|
||||
@select="onSelect"
|
||||
:selectedKeys="selectedKeys"
|
||||
@drop="onDrop"
|
||||
>
|
||||
<AIcon type="QuestionCircleOutlined" />
|
||||
</j-tooltip>
|
||||
</div>
|
||||
<div class="tree">
|
||||
<j-input
|
||||
v-model="filterText"
|
||||
placeholder="请输入"
|
||||
@change="change"
|
||||
style="margin-bottom: 12px"
|
||||
/>
|
||||
<j-tree
|
||||
v-if="treeData.length !== 0"
|
||||
show-line
|
||||
defaultExpandAll
|
||||
multiple
|
||||
draggable
|
||||
:tree-data="treeData"
|
||||
:height="500"
|
||||
@select="onSelect"
|
||||
:selectedKeys="selectedKeys"
|
||||
@drop="onDrop"
|
||||
>
|
||||
<template #title="row">
|
||||
<div class="tree-content">
|
||||
<div class="tree-content-title">
|
||||
<AIcon type="HolderOutlined" />
|
||||
<div style="margin-left: 8px">
|
||||
{{ row.name }}
|
||||
<template #title="row">
|
||||
<div class="tree-content">
|
||||
<div class="tree-content-title">
|
||||
<AIcon type="HolderOutlined" />
|
||||
<div style="margin-left: 8px">
|
||||
{{ row.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</j-tree>
|
||||
</div>
|
||||
<j-button type="primary">保存</j-button>
|
||||
</template>
|
||||
</j-tree>
|
||||
</div>
|
||||
</j-card>
|
||||
</div>
|
||||
<j-button
|
||||
type="primary"
|
||||
@click="() => (visible = true)"
|
||||
style="margin-left: 10%"
|
||||
>保存</j-button
|
||||
>
|
||||
</j-card>
|
||||
<j-modal
|
||||
:visible="visible"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
modalType="message"
|
||||
:confirmLoading="loading"
|
||||
>
|
||||
保存后当前系统菜单数据将被覆盖,确认操作?
|
||||
</j-modal>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="MenuSetting">
|
||||
import { getMenuTree_api } from '@/api/system/menu';
|
||||
import { getSystemPermission as getSystemPermission_api } from '@/api/initHome';
|
||||
import {
|
||||
getSystemPermission as getSystemPermission_api,
|
||||
updateMenus,
|
||||
} from '@/api/initHome';
|
||||
import {
|
||||
filterMenu,
|
||||
mergeMapToArr,
|
||||
developArrToMap,
|
||||
drop,
|
||||
select,
|
||||
getMaxDepth,
|
||||
} from './utils';
|
||||
import BaseMenu from './baseMenu';
|
||||
import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree';
|
||||
import { treeFilter } from '@/utils/tree';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { onlyMessage } from '@/utils/comm';
|
||||
|
||||
const selectedKeys: any = ref([]);
|
||||
const treeData = ref<any>([]);
|
||||
const filterText = ref('');
|
||||
const systemMenu: any = ref([]);
|
||||
const baseMenu: any = ref([]);
|
||||
const AllMenu = ref([]);
|
||||
|
||||
const onSelect = (selecteds: Array<string>, e: any) => {
|
||||
selectedKeys.value = select(selecteds, e);
|
||||
};
|
||||
|
||||
const onDrop = (info: AntTreeNodeDropEvent) => {
|
||||
treeData.value = drop(info, treeData.value);
|
||||
};
|
||||
const visible = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const params = {
|
||||
paging: false,
|
||||
|
@ -103,8 +103,33 @@ const params = {
|
|||
],
|
||||
};
|
||||
|
||||
const change = (val: any) => {
|
||||
treeData.value = treeFilter(AllMenu.value, val.target.value, 'name');
|
||||
const handleOk = async () => {
|
||||
loading.value = true;
|
||||
const res = await updateMenus(treeData.value);
|
||||
if (res.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
}
|
||||
loading.value = false;
|
||||
visible.value = false;
|
||||
};
|
||||
const handleCancel = () => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const onSelect = (selecteds: Array<string>, e: any) => {
|
||||
selectedKeys.value = select(selecteds, e);
|
||||
};
|
||||
|
||||
const onDrop = (info: AntTreeNodeDropEvent) => {
|
||||
const TreeData = cloneDeep(treeData.value);
|
||||
const newTreeData = drop(info, treeData.value);
|
||||
const maxDepth = getMaxDepth(newTreeData);
|
||||
if (maxDepth > 3) {
|
||||
onlyMessage('仅支持3级菜单', 'error');
|
||||
treeData.value = TreeData;
|
||||
} else {
|
||||
treeData.value = newTreeData;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -116,6 +141,7 @@ onMounted(() => {
|
|||
getMenuTree_api(params).then((resp: any) => {
|
||||
if (resp.status == 200) {
|
||||
systemMenu.value = resp.result;
|
||||
//初始化菜单
|
||||
const baseMenuData = developArrToMap(baseMenu.value);
|
||||
const systemMenuData = developArrToMap(systemMenu.value, true);
|
||||
selectedKeys.value = systemMenuData.checkedKeys;
|
||||
|
@ -136,19 +162,14 @@ onMounted(() => {
|
|||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: rgba(0, 0, 0, 0.55);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.content {
|
||||
width: 50%;
|
||||
margin-top: 24px;
|
||||
.title {
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
padding: 12px;
|
||||
background: #f3f4f4;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
width: 100%;
|
||||
margin: 12px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
// flex-direction: row;
|
||||
:deep(.ant-tree) {
|
||||
.ant-tree-switcher {
|
||||
display: flex;
|
||||
|
@ -165,12 +186,16 @@ onMounted(() => {
|
|||
width: 100%;
|
||||
}
|
||||
}
|
||||
:deep(.ant-card-body) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tree {
|
||||
height: 580px;
|
||||
// flex: 1;
|
||||
height: 540px;
|
||||
margin: 16px 0;
|
||||
padding: 12px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
@ -178,6 +203,8 @@ onMounted(() => {
|
|||
&-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 5px 0;
|
||||
|
||||
&-title {
|
||||
flex: 1;
|
||||
font-weight: 800;
|
||||
|
|
|
@ -61,20 +61,20 @@ export const developArrToMap = (Menu: any, checked = false) => {
|
|||
const rootSet = new Set();
|
||||
const arrMap = new Map();
|
||||
const checkedKeys: any = [];
|
||||
const getMap = (arr: any, parentCode = 'root', preKey = '0') => {
|
||||
arr.forEach((item: any, index: number) => {
|
||||
const key = preKey + `-${index}`; //初始化key
|
||||
const getMap = (arr: any, parentCode = 'root') => {
|
||||
arr.forEach((item: any) => {
|
||||
item.title = item.code;
|
||||
item.key = key;
|
||||
if (checked) {
|
||||
checkedKeys.push(key);
|
||||
item.key = item.code;
|
||||
if (checked || item?.checked) {
|
||||
item.checked = item?.checked || checked;
|
||||
checkedKeys.push(item.code);
|
||||
}
|
||||
arrMap.set(item.code, item);
|
||||
if (parentCode === 'root') {
|
||||
rootSet.add(item.code); //处理根菜单
|
||||
}
|
||||
if (item?.children) {
|
||||
getMap(item?.children, item.code, key);
|
||||
getMap(item?.children, item.code);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -91,17 +91,16 @@ export const developArrToMap = (Menu: any, checked = false) => {
|
|||
export const select = (selecteds: Array<string>, e: any) => {
|
||||
const { node } = e;
|
||||
const childKeys: Array<string> = [];
|
||||
const getChildKeys = (data: any, preKey = '0') => {
|
||||
data.forEach((item: any, index: number) => {
|
||||
const checkedKey = preKey + `-${index}`;
|
||||
childKeys.push(checkedKey);
|
||||
const getChildKeys = (data: any) => {
|
||||
data.forEach((item: any) => {
|
||||
childKeys.push(item.code);
|
||||
if (item?.children) {
|
||||
getChildKeys(item?.children, checkedKey);
|
||||
getChildKeys(item?.children);
|
||||
}
|
||||
});
|
||||
};
|
||||
if (node?.children) {
|
||||
getChildKeys(node.children, node.key);
|
||||
getChildKeys(node.children);
|
||||
}
|
||||
|
||||
const Keys = new Set(selecteds);
|
||||
|
@ -185,4 +184,28 @@ export const drop = (info: AntTreeNodeDropEvent, treeData: any) => {
|
|||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
};
|
||||
|
||||
// 查找最深层级
|
||||
export const getMaxDepth = (data: any) => {
|
||||
let maxDepth = 0;
|
||||
data.forEach((node: any) => {
|
||||
const depth = getNodeDepth(node);
|
||||
if (depth > maxDepth) {
|
||||
maxDepth = depth;
|
||||
}
|
||||
});
|
||||
return maxDepth;
|
||||
};
|
||||
export const getNodeDepth = (node: any) => {
|
||||
let depth = 1;
|
||||
if (node.children) {
|
||||
node.children.forEach((child: any) => {
|
||||
const childDepth = getNodeDepth(child) + 1;
|
||||
if (childDepth > depth) {
|
||||
depth = childDepth;
|
||||
}
|
||||
});
|
||||
}
|
||||
return depth;
|
||||
};
|
||||
|
|
|
@ -3700,8 +3700,8 @@ jetlinks-store@^0.0.3:
|
|||
|
||||
jetlinks-ui-components@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#593185f6313895485b59e9a79bc920c63374d84d"
|
||||
integrity sha512-dkSOmatSPLHlV91YdTcHWO2wfwriUIZKEuLd5bJF2GsO9SvDMyJ2YJ4n/3fkklOoL5albhY37iX2Ot3A+7QYwA==
|
||||
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#27312836506c4833dcaaef075e1d3c694d75ae4d"
|
||||
integrity sha512-oum7zipoDUVkm/tPd7yu+mw9mR5NmfBcvBf49ebf55s+nz4zyArFOITzldQJ3Wx6BwaUUH/BiDwskHH+KgBVyg==
|
||||
dependencies:
|
||||
"@vueuse/core" "^9.12.0"
|
||||
ant-design-vue "^3.2.15"
|
||||
|
|
Loading…
Reference in New Issue