fix: 修改用户管理的类型展示问题;修改网络组件的集群控制;

* fix: 15017

* fix: 修改bug(13663、15022、13672)

* fix: 修改操作栏的距离

* fix: bug#15019

* fix: 修改菜单配置

* fix: 修改网络组件的集群控制

* fix: 修改用户管理的类型展示问题
This commit is contained in:
XieYongHong 2023-06-06 15:40:37 +08:00 committed by GitHub
parent 820ca7330e
commit 099c6fa32a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 156 additions and 139 deletions

View File

@ -219,7 +219,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 150, width: 60,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -189,7 +189,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 150, width: 60,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -191,7 +191,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 160,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -230,7 +230,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 160,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -166,7 +166,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 120,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -268,7 +268,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 200,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -588,7 +588,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 200,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -77,13 +77,14 @@
/> />
</template> </template>
</Guide> </Guide>
<LineChart <FullPage v-if="flowData.length !== 0">
v-if="flowData.length !== 0" <LineChart
:showX="true" :showX="true"
:showY="true" :showY="true"
style="min-height: 490px" style="min-height: 490px"
:chartData="flowData" :chartData="flowData"
/> />
</FullPage>
<div class="empty-body" v-else> <div class="empty-body" v-else>
<j-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /> <j-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" />
</div> </div>

View File

@ -142,7 +142,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 120,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -118,6 +118,7 @@ const columns = [
dataIndex: 'createTime', dataIndex: 'createTime',
key: 'createTime', key: 'createTime',
scopedSlots: true, scopedSlots: true,
width: 200,
search: { search: {
type: 'date', type: 'date',
}, },
@ -126,6 +127,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 60,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -114,7 +114,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 80,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -207,7 +207,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 100,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -41,7 +41,7 @@
/> />
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col :span="24"> <j-col :span="24" v-if="isNoCommunity">
<j-form-item <j-form-item
name="shareCluster" name="shareCluster"
:rules="Rules.shareCluster" :rules="Rules.shareCluster"
@ -1139,6 +1139,7 @@ import { cloneDeep } from 'lodash-es';
import type { FormData2Type, FormDataType } from '../type'; import type { FormData2Type, FormDataType } from '../type';
import { Store } from 'jetlinks-store'; import { Store } from 'jetlinks-store';
import LocalAddressSelect from './LocalAddressSelect.vue'; import LocalAddressSelect from './LocalAddressSelect.vue';
import { isNoCommunity } from '@/utils/utils';
const route = useRoute(); const route = useRoute();
const NetworkType = route.query.type as string; const NetworkType = route.query.type as string;
@ -1441,7 +1442,9 @@ onMounted(() => {
getSupports(); getSupports();
getCertificates(); getCertificates();
getResourcesCurrent(); getResourcesCurrent();
getResourcesClusters(); if(isNoCommunity){
getResourcesClusters();
}
getDetail(); getDetail();
}); });

View File

@ -263,7 +263,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 200, width: 120,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -279,7 +279,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 200,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -233,7 +233,7 @@ const columns = [
title: '配置名称', title: '配置名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
width: 100, ellipsis: true,
search: { search: {
type: 'string', type: 'string',
}, },
@ -280,7 +280,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 200,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -229,6 +229,7 @@ const columns = [
title: '模板名称', title: '模板名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
ellipsis: true,
search: { search: {
type: 'string', type: 'string',
}, },
@ -273,7 +274,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 200,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -327,7 +327,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 150, width: 120,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -226,7 +226,7 @@ const columns = [
title: '操作', title: '操作',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 250, width: 150,
scopedSlots: true, scopedSlots: true,
}, },
]; ];

View File

@ -244,7 +244,8 @@ const save = async (step?: number) => {
operation: typeData.data, operation: typeData.data,
selector: addModel.selector, selector: addModel.selector,
selectorValues: addModel.selectorValues, selectorValues: addModel.selectorValues,
productId: addModel.productId productId: addModel.productId,
source: 'fixed'
} }
emit('save', data, _options) emit('save', data, _options)
formItemContext.onFieldChange() formItemContext.onFieldChange()

View File

@ -62,7 +62,8 @@ const check = async (): Promise<boolean> => {
let hasProperties = false let hasProperties = false
if (metadata.properties.length) { if (metadata.properties.length) {
if (deviceTrigger.operation?.readProperties && deviceTrigger.operation?.readProperties.length) { if (deviceTrigger.operation?.readProperties && deviceTrigger.operation?.readProperties.length) {
hasProperties = metadata.properties.every((item: any) => deviceTrigger.operation!.readProperties!.includes(item.id)) // hasProperties = metadata.properties.every((item: any) => deviceTrigger.operation!.readProperties!.includes(item.id))
hasProperties = deviceTrigger.operation!.readProperties.every(_id => metadata.properties.some((item: any) => item.id === _id))
} else if (deviceTrigger.operation?.writeProperties && Object.keys(deviceTrigger.operation?.writeProperties).length) { } else if (deviceTrigger.operation?.writeProperties && Object.keys(deviceTrigger.operation?.writeProperties).length) {
const key = Object.keys(deviceTrigger.operation?.writeProperties)[0] const key = Object.keys(deviceTrigger.operation?.writeProperties)[0]
hasProperties = metadata.properties.some((item: any) => key ===item.id) hasProperties = metadata.properties.some((item: any) => key ===item.id)

View File

@ -125,7 +125,8 @@ const checkDeviceDelete = async () => {
if (item!.selectorValues && metadata?.tags?.length) { if (item!.selectorValues && metadata?.tags?.length) {
const values = (item!.selectorValues?.[0]?.value as any).map((item: any) => item.column) const values = (item!.selectorValues?.[0]?.value as any).map((item: any) => item.column)
const tagKeys = new Set(values) const tagKeys = new Set(values)
hasAllTags = metadata?.tags?.every((item: any) => tagKeys.has(item.id)) hasAllTags = [...tagKeys.values()].every((_key) => metadata?.tags.some((item: any) => item.id === _key))
// hasAllTags = metadata?.tags?.every((item: any) => tagKeys.has(item.id))
} }
if (!hasAllTags) { if (!hasAllTags) {
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class='["actions-terms-warp", isFirst ? "first-children" : ""]'> <div :class='WarpClass'>
<div class='actions-terms-title'> <div class='actions-terms-title'>
{{ isFirst ? '当' : '否则' }} {{ isFirst ? '当' : '否则' }}
</div> </div>
@ -30,21 +30,28 @@
<div class='actions-terms-list-content'> <div class='actions-terms-list-content'>
<template v-if='showWhen'> <template v-if='showWhen'>
<WhenItem <j-scrollbar>
v-for='(item, index) in whenData' <div style="display: flex; padding-top: 10px;">
:key='item.key' <WhenItem
:name='index' v-for='(item, index) in whenData'
:showDeleteBtn='whenData.length !== 1' :key='item.key'
:isFirst='index === 0' :name='index'
:isLast='index === whenData.length -1' :showDeleteBtn='whenData.length !== 1'
:branchName='name' :isFirst='index === 0'
:data='item' :isLast='index === whenData.length -1'
/> :branchName='name'
:data='item'
/>
</div>
</j-scrollbar>
</template> </template>
<span v-else class='when-add' @click='addWhen' :style='{ padding: isFirst ? "16px 0" : 0 }'> <div v-else style="display: flex; padding-top: 10px;">
<AIcon type='PlusCircleOutlined' style='padding: 4px' /> <span class='when-add' @click='addWhen' :style='{ padding: isFirst ? "16px 0" : 0 }'>
添加过滤条件 <AIcon type='PlusCircleOutlined' style='padding: 4px' />
</span> 添加过滤条件
</span>
</div>
</div> </div>
</div> </div>
<div class='actions-branches'> <div class='actions-branches'>
@ -109,6 +116,14 @@ const whenData = computed(() => {
return props.data.when return props.data.when
}) })
const WarpClass = computed(() => {
return {
'actions-terms-warp': true,
'first-children': props.isFirst,
'terms-items': (FormModel.value.branches?.length || 0) > 0
}
})
const onDelete = () => { const onDelete = () => {
if (FormModel.value.branches?.length == 2) { if (FormModel.value.branches?.length == 2) {
FormModel.value.branches?.splice(props.name, 1, null) FormModel.value.branches?.splice(props.name, 1, null)

View File

@ -1,23 +1,9 @@
<template> <template>
<div <j-form-item
class='terms-params-content'
@mouseover='mouseover'
@mouseout='mouseout'
>
<j-popconfirm
title='确认删除?'
:overlayStyle='{minWidth: "180px"}'
@confirm='onDelete'
>
<div v-show='showDelete' class='terms-params-delete'>
<AIcon type='CloseOutlined' />
</div>
</j-popconfirm>
<j-form-item
:name='["branches", branchName, "when", whenName, "terms", props.name]' :name='["branches", branchName, "when", whenName, "terms", props.name]'
:rules='rules' :rules='rules'
> >
<ParamsItem <ParamsItem
v-model:value='formModel.branches[branchName].when[whenName].terms[props.name]' v-model:value='formModel.branches[branchName].when[whenName].terms[props.name]'
:isFirst='isFirst' :isFirst='isFirst'
:isLast='isLast' :isLast='isLast'
@ -25,9 +11,8 @@
:termsName='name' :termsName='name'
:whenName='whenName' :whenName='whenName'
:branchName='branchName' :branchName='branchName'
/> />
</j-form-item> </j-form-item>
</div>
</template> </template>
<script setup lang='ts' name='TermsItem'> <script setup lang='ts' name='TermsItem'>
@ -114,50 +99,6 @@ const rules = [
} }
] ]
const showDelete = ref(false)
const termsData = computed(() => {
return props.data.terms
})
const mouseover = () => {
if (props.showDeleteBtn){
showDelete.value = true
}
}
const mouseout = () => {
if (props.showDeleteBtn){
showDelete.value = false
}
}
const onDelete = () => {
formModel.value.branches?.[props.branchName]?.when?.splice(props.whenName, 1)
formModel.value.options!.when[props.branchName].terms.splice(props.whenName, 1)
}
const addTerms = () => {
const terms = {
type: 'and',
terms: [
{
column: undefined,
value: {
source: 'fixed',
value: undefined
},
termType: undefined,
key: `params_${randomString()}`,
type: 'and',
}
],
key: `terms_${randomString()}`
}
formModel.value.branches?.[props.branchName]?.when?.[props.whenName].terms?.push(terms)
formModel.value.options!.when[props.branchName].terms[props.whenName].terms.push(['','eq','','and'])
}
</script> </script>
<style scoped> <style scoped>

View File

@ -12,17 +12,32 @@
@select='typeChange' @select='typeChange'
/> />
</div> </div>
<TermsItem <div
v-for='(item, index) in termsData' class='terms-params-content'
:key='item.key' @mouseover='mouseover'
:branchName='branchName' @mouseout='mouseout'
:whenName='props.name' >
:name='index' <j-popconfirm
:showDeleteBtn='termsData.length > 1' title='确认删除?'
:isFirst='index === 0' :overlayStyle='{minWidth: "180px"}'
:isLast='index === termsData.length -1' @confirm='onDelete'
:data='item' >
/> <div v-show='showDelete' class='terms-params-delete'>
<AIcon type='CloseOutlined' />
</div>
</j-popconfirm>
<TermsItem
v-for='(item, index) in termsData'
:key='item.key'
:branchName='branchName'
:whenName='props.name'
:name='index'
:showDeleteBtn='termsData.length > 1'
:isFirst='index === 0'
:isLast='index === termsData.length -1'
:data='item'
/>
</div>
<div class='terms-group-add' @click='addWhen' v-if='isLast'> <div class='terms-group-add' @click='addWhen' v-if='isLast'>
<div class='terms-content'> <div class='terms-content'>
<AIcon type='PlusOutlined' /> <AIcon type='PlusOutlined' />
@ -80,6 +95,20 @@ const props = defineProps({
} }
}) })
const showDelete = ref(false)
const mouseover = () => {
if (props.showDeleteBtn){
showDelete.value = true
}
}
const mouseout = () => {
if (props.showDeleteBtn){
showDelete.value = false
}
}
const termsData = computed(() => { const termsData = computed(() => {
return props.data.terms return props.data.terms
}) })
@ -88,6 +117,11 @@ const typeChange = (e: any) => {
formModel.value.options!.when[props.name].terms[props.name].termType = e.label formModel.value.options!.when[props.name].terms[props.name].termType = e.label
} }
const onDelete = () => {
formModel.value.branches?.[props.branchName]?.when?.splice(props.name, 1)
formModel.value.options!.when[props.branchName].terms.splice(props.name, 1)
}
const addWhen = () => { const addWhen = () => {
const terms = { const terms = {
type: 'and', type: 'and',

View File

@ -56,6 +56,10 @@
margin-bottom: 0; margin-bottom: 0;
} }
&.terms-items:last-child {
margin-bottom: 24px;
}
.when-add-button { .when-add-button {
.add-button(); .add-button();
} }
@ -96,11 +100,7 @@
} }
.actions-terms-list-content { .actions-terms-list-content {
display: flex;
padding-top: 10px;
overflow-x: auto;
overflow-y: visible;
row-gap: 16px;
} }
} }

View File

@ -231,7 +231,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
scopedSlots: true, scopedSlots: true,
width: '200px', width: '160px',
fixed: 'right', fixed: 'right',
}, },
]; ];

View File

@ -173,7 +173,7 @@
}}</span> }}</span>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
<j-space :size="16"> <j-space>
<PermissionButton <PermissionButton
v-for="i in table.getActions(slotProps, 'table')" v-for="i in table.getActions(slotProps, 'table')"
:hasPermission="i.permission" :hasPermission="i.permission"
@ -338,6 +338,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 150,
scopedSlots: true, scopedSlots: true,
}, },
]; ];
@ -584,6 +585,7 @@ const table = {
refresh: () => { refresh: () => {
nextTick(() => { nextTick(() => {
tableRef.value.reload(); tableRef.value.reload();
table.cancelSelect()
}); });
}, },
}; };

View File

@ -192,6 +192,7 @@
v-for="i in table.getActions(slotProps, 'table')" v-for="i in table.getActions(slotProps, 'table')"
:hasPermission="i.permission" :hasPermission="i.permission"
type="link" type="link"
:key="i.key"
:tooltip="i?.tooltip" :tooltip="i?.tooltip"
:pop-confirm="i.popConfirm" :pop-confirm="i.popConfirm"
@click="i.onClick" @click="i.onClick"
@ -321,6 +322,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 100,
scopedSlots: true, scopedSlots: true,
}, },
]; ];
@ -576,6 +578,7 @@ const table = {
refresh: () => { refresh: () => {
nextTick(() => { nextTick(() => {
tableRef.value.reload(); tableRef.value.reload();
table.cancelSelect()
}); });
}, },
addConfirm: () => { addConfirm: () => {

View File

@ -147,7 +147,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
scopedSlots: true, scopedSlots: true,
width: '200px', width: 80,
}, },
]; ];
// //

View File

@ -71,7 +71,8 @@ import {
getMaxDepth, getMaxDepth,
mergeArr, mergeArr,
findAllParentsAndChildren, findAllParentsAndChildren,
handleSorts handleSorts,
handleSortsArr
} from './utils'; } from './utils';
import BaseMenu from '@/views/init-home/data/baseMenu'; import BaseMenu from '@/views/init-home/data/baseMenu';
import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree'; import type { AntTreeNodeDropEvent } from 'ant-design-vue/es/tree';
@ -214,7 +215,7 @@ onMounted(() => {
); );
// //
treeData.value = handleSorts(AllMenu); treeData.value = handleSortsArr(AllMenu);
} }
}); });
}); });

View File

@ -60,9 +60,7 @@ export const mergeArr = (oldData: Array<any>, newData: Array<any>) => {
(child) => child.code === oldChild.code, (child) => child.code === oldChild.code,
); );
if (index !== -1) { if (index !== -1) {
mergedChildren.push( mergedChildren.push(mergeItem(oldChild, newChildren[index]));
mergeItem(oldChild, newChildren[index]),
);
newChildren.splice(index, 1); newChildren.splice(index, 1);
} else { } else {
//防止重复code系统已经选中的code不能再从old中添加 //防止重复code系统已经选中的code不能再从old中添加
@ -71,15 +69,16 @@ export const mergeArr = (oldData: Array<any>, newData: Array<any>) => {
} }
} }
} }
return { return {
...oldItem, ...oldItem,
children: mergedChildren.concat(newChildren), children: mergedChildren.concat(newChildren),
}; };
} }
return oldItem; return oldItem
}; };
for (const newItem of newData) { for (const newItem of newData) {
const oldItem = oldData.find((item) => item.code === newItem.code); const oldItem = oldData.find((item) => item.code === newItem.code);
mergedData.push(mergeItem(oldItem, newItem)); mergedData.push(mergeItem(oldItem, newItem));
@ -102,7 +101,7 @@ export const mergeArr = (oldData: Array<any>, newData: Array<any>) => {
} }
} }
return mergedData; return mergedData
}; };
/** /**
@ -321,4 +320,14 @@ export const handleSorts = (node: any[]) => {
} }
return item return item
}) })
}
export const handleSortsArr = (node: any[]) => {
if (!node) return []
return node.sort((a, b) => a.sortIndex - b.sortIndex).map((item) => {
if (item.children) {
item.children = handleSortsArr(item.children)
}
return item
})
} }

View File

@ -162,7 +162,7 @@ const columns = [
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
scopedSlots: true, scopedSlots: true,
width: 200, width: 150,
}, },
]; ];
const queryParams = ref({ terms: [] }); const queryParams = ref({ terms: [] });

View File

@ -204,7 +204,7 @@ const columns = [
title: '操作', title: '操作',
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
width: '200px', width: 120,
fixed: 'right', fixed: 'right',
scopedSlots: true, scopedSlots: true,
}, },

View File

@ -146,6 +146,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
scopedSlots: true, scopedSlots: true,
width: 100,
}, },
]; ];
const queryParams = ref({}); const queryParams = ref({});

View File

@ -117,7 +117,7 @@ const columns = [
title: '操作', title: '操作',
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
width: 200, width: 120,
fixed: 'right', fixed: 'right',
scopedSlots: true, scopedSlots: true,
}, },

View File

@ -32,7 +32,7 @@
</PermissionButton> </PermissionButton>
</template> </template>
<template #type="slotProps"> <template #type="slotProps">
{{ slotProps.type.name }} {{ slotProps.type?.name }}
</template> </template>
<template #status="slotProps"> <template #status="slotProps">
<BadgeStatus <BadgeStatus
@ -220,6 +220,7 @@ const columns = [
dataIndex: 'action', dataIndex: 'action',
key: 'action', key: 'action',
fixed: 'right', fixed: 'right',
width: 150,
scopedSlots: true, scopedSlots: true,
}, },
]; ];