fix: 修改bug

This commit is contained in:
100011797 2023-07-05 18:29:24 +08:00
parent 6651e75930
commit be0aeb9a0a
8 changed files with 557 additions and 380 deletions

View File

@ -35,6 +35,7 @@
<div class='info-body'>
<img
:src="
bindUser?.avatar ||
iconMap.get(
bindUser?.applicationProvider,
) || getImage('/apply/internal-standalone.png')
@ -62,7 +63,7 @@
:src="getImage('/bind/Vector.png')"
/>
<img
:src='iconMap.get(bindUser?.applicationProvider)'
:src='bindUser?.avatar || iconMap.get(bindUser?.applicationProvider)'
/>
</div>
<div class='desc'>

View File

@ -128,11 +128,14 @@ onMounted(() => {
}
.content-item-right {
button:hover {
:deep(button) {
&:hover {
background-color: @primary-color;
color: #fff;
}
}
}
}
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<ResizeObserver @resize="onResize">
<div class="tag-box" ref="box">
<div v-for="(item, i) in value" :key="item.id" ref="tags">
<div v-if="i != _index" class="tag">
{{ item.name }}
</div>
<div
v-else
class="tag-ellipsis"
:style="
i === _index
? {
width: `${offWidth}px`,
}
: {}
"
>
{{ item.name }}
</div>
</div>
</div>
</ResizeObserver>
</template>
<script lang="ts" setup>
import { default as ResizeObserver } from 'ant-design-vue/lib/vc-resize-observer';
const props = defineProps({
value: {
type: Array,
default: () => [],
},
});
const tags = ref<any>([]);
const box = ref<any>(null);
const _index = ref<number>(-1);
const offWidth = ref<number>(0);
const onResize = ({ width }: { width: number }) => {
let total = 0;
for (let i = 0; i < tags.value.length; i++) {
const item = tags.value[i];
total += item?.scrollWidth || 0;
const val = item?.offsetWidth - (total - width);
if (total >= width) {
_index.value = i;
offWidth.value = val;
break;
}
}
};
</script>
<style lang="less" scoped>
.tag-box {
margin-top: 15px;
display: flex;
width: 100%;
overflow: hidden;
.tag {
background-color: #f7f8fa;
border-radius: 32px;
margin-right: 8px;
padding: 0 14px;
color: #333333;
white-space: nowrap;
}
.tag-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
background-color: #f7f8fa;
border-radius: 32px;
margin-right: 8px;
padding: 0 14px;
color: #333333;
}
}
</style>

View File

@ -16,25 +16,12 @@
</div>
<div class="person-header-item-info-right">
<div class="person-header-item-info-right-top">
<j-ellipsis>
Hi, {{ user.userInfos?.name }}
</j-ellipsis>
</div>
<div class="person-header-item-info-right-info">
<!-- <div class="tag-box">
<div
v-for="i in user.userInfos?.orgList || []"
:key="i?.id"
class="tag"
>{{ i?.name }}</div
>
</div> -->
<div class="tag-box">
<div
v-for="i in user.userInfos?.roleList || []"
:key="i?.id"
class="tag"
><j-ellipsis>{{ i?.name }}</j-ellipsis></div
>
</div>
<RoleShow :value="user.userInfos?.roleList || []" />
</div>
</div>
</div>
@ -105,6 +92,7 @@ import {
USER_CENTER_MENU_CODE,
} from '@/utils/consts';
import { usePermissionStore } from '@/store/permission';
import RoleShow from './components/RoleShow/index.vue';
const imageTypes = reactive([
'image/jpeg',
@ -204,6 +192,7 @@ onUnmounted(() => {
height: 100%;
.person-header-item-info {
display: flex;
width: calc(100% - 380px);
.person-header-item-info-left {
margin-right: 30px;
}
@ -211,25 +200,16 @@ onUnmounted(() => {
.person-header-item-info-right {
display: flex;
flex-direction: column;
width: calc(100% - 126px);
.person-header-item-info-right-top {
display: flex;
font-size: 26px;
color: #1d2129;
font-weight: 500;
width: 100%;
}
.person-header-item-info-right-info {
.tag-box {
margin-top: 15px;
display: flex;
.tag {
background-color: #F7F8FA;
border-radius: 32px;
margin-right: 8px;
padding: 0 14px;
color: #333333;
}
}
width: 100%;
}
}
}

View File

@ -7,6 +7,8 @@
allowClear
@search="search"
/>
<div class="box">
<j-scrollbar height="100%">
<j-table
:columns="columns"
:data-source="dataSource"
@ -17,6 +19,7 @@
columnWidth: 0,
}"
rowKey="id"
:customRow="customRow"
>
<template #headerCell="{ column }">
<template v-if="column.dataIndex === 'original'">
@ -43,7 +46,9 @@
color="#87d068"
closable
@close="onClose"
><AIcon type="ArrowUpOutlined" /><span>{{
><AIcon
type="ArrowUpOutlined"
/><span>{{
filterValue ? '已映射' : '未映射'
}}</span></j-tag
>
@ -65,7 +70,7 @@
</template>
<template #bodyCell="{ column, text, record }">
<template v-if="column.dataIndex === 'name'">
<span class="metadata-title">
<span class="metadata-title" ref="title">
<j-ellipsis>
{{ text }} ({{ record.id }})
</j-ellipsis>
@ -84,7 +89,9 @@
:key="index + '_' + item.id"
:value="item.value"
:disabled="
selectedOriginalKeys.includes(item.id)
selectedOriginalKeys.includes(
item.id,
)
"
>
{{ item.label }} ({{
@ -95,6 +102,8 @@
</template>
</template>
</j-table>
</j-scrollbar>
</div>
</div>
<div class="right">
<j-scrollbar>
@ -140,6 +149,8 @@ const targetOptions = ref<any[]>([]);
const filterValue = ref<boolean | undefined>(undefined);
const originalData = ref([]);
const _value = ref<any>(undefined);
const columns = [
{
title: '序号',
@ -198,13 +209,22 @@ const getMetadataMapData = () => {
});
};
const customRow = (record: any) => {
return {
id: record.id,
class: _value.value === record.name ? 'metadata-search-row' : '',
};
};
const search = (value: string) => {
if (value) {
dataSource.value = dataSourceCache.value.filter((item: any) => {
return !!item.name?.includes(value);
const _item: any = dataSourceCache.value.find((item: any) => {
return value === item.name;
});
_value.value = _item.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
} else {
dataSource.value = dataSourceCache.value;
_value.value = undefined;
}
};
@ -276,7 +296,7 @@ const onChange = async (value: any, id: string) => {
};
const onFilter = ({ key }: any) => {
originalData.value = dataSource.value
originalData.value = dataSource.value;
const _dataSource = cloneDeep(dataSource.value).sort((a: any, b: any) => {
if (!key) {
return (a.original ? 1 : -1) - (b.original ? 1 : -1);
@ -301,14 +321,24 @@ onMounted(() => {
<style scoped lang='less'>
.metadata-map {
// position: relative;
min-height: 100%;
display: flex;
gap: 24px;
.left {
// margin-right: 44px;
flex: 1;
height: 100%;
.box {
height: calc(100vh - 388px);
overflow: hidden;
:deep(.metadata-search-row) {
td {
background: #ffff80 !important;
}
}
}
}
.right {

View File

@ -1,22 +1,25 @@
<template>
<div class='metadata-map'>
<div class='left'>
<div class="metadata-map">
<div class="left">
<j-input-search
style='width: 350px;margin-bottom:24px;'
placeholder='搜索平台属性名称'
style="width: 350px; margin-bottom: 24px"
placeholder="搜索平台属性名称"
allowClear
@search='search'
@search="search"
/>
<div class="box">
<j-scrollbar height="100%">
<j-table
:columns="columns"
:data-source="dataSource"
:pagination='false'
:rowSelection='{
:pagination="false"
:rowSelection="{
selectedRowKeys: selectedKeys,
hideSelectAll: true,
columnWidth: 0
}'
rowKey='id'
columnWidth: 0,
}"
rowKey="id"
:customRow="customRow"
>
<template #headerCell="{ column }">
<template v-if="column.dataIndex === 'plugin'">
@ -29,7 +32,9 @@
"
>
<span>
目标属性<j-tooltip title="插件中物模型下的属性">
目标属性<j-tooltip
title="插件中物模型下的属性"
>
<AIcon
style="margin-left: 10px"
type="QuestionCircleOutlined"
@ -41,7 +46,9 @@
color="#87d068"
closable
@close="onClose"
><AIcon type="ArrowUpOutlined" /><span>{{
><AIcon
type="ArrowUpOutlined"
/><span>{{
filterValue ? '已映射' : '未映射'
}}</span></j-tag
>
@ -62,44 +69,54 @@
</template>
</template>
<template #bodyCell="{ column, text, record }">
<template v-if='column.dataIndex === "name"'>
<span class='metadata-title'>
<template v-if="column.dataIndex === 'name'">
<span class="metadata-title">
<j-ellipsis>
{{ text }} ({{ record.id }})
</j-ellipsis>
</span>
</template>
<template v-if='column.dataIndex === "plugin"'>
<template v-if="column.dataIndex === 'plugin'">
<j-select
v-model:value='record.plugin'
style='width: 100%'
v-model:value="record.plugin"
style="width: 100%"
allowClear
@change='(id) => pluginChange(record, id)'
@change="(id) => pluginChange(record, id)"
>
<j-select-option
v-for='(item, index) in pluginOptions'
:key='index + "_" + item.id'
:value='item.value'
:disabled='selectedPluginKeys.includes(item.id)'
><j-tooltip :title="selectedPluginKeys.includes(item.id) ? '该属性已绑定平台属性' : ''">
{{ item.label }} ({{
item.id
}})
</j-tooltip></j-select-option>
v-for="(item, index) in pluginOptions"
:key="index + '_' + item.id"
:value="item.value"
:disabled="
selectedPluginKeys.includes(item.id)
"
><j-tooltip
:title="
selectedPluginKeys.includes(
item.id,
)
? '该属性已绑定平台属性'
: ''
"
>
{{ item.label }} ({{ item.id }})
</j-tooltip></j-select-option
>
</j-select>
</template>
</template>
</j-table>
</j-scrollbar>
</div>
<div class='right'>
</div>
<div class="right">
<j-scrollbar>
<div class='title'>
功能说明
</div>
<div class="title">功能说明</div>
<p>
该功能用于将插件中的
<b>物模型属性标识</b>
<b>平台物模型属性标识</b>进行映射,当两方属性标识不一致时可在当前页面直接修改映射管理系统将以映射后的物模型属性进行数据处理
<b>平台物模型属性标识</b
>进行映射,当两方属性标识不一致时可在当前页面直接修改映射管理系统将以映射后的物模型属性进行数据处理
</p>
<p>
未完成映射的属性标识目标属性列数据为空代表该属性值来源以在平台配置的来源为准
@ -107,11 +124,9 @@
<p>
数据条背景亮起代表<b>标识一致</b><b>已完成映射</b>的属性
</p>
<div class='title'>
功能图示
</div>
<div class="title">功能图示</div>
<div>
<img :src='getImage("/device/matadataMap.png")' />
<img :src="getImage('/device/matadataMap.png')" />
</div>
</j-scrollbar>
</div>
@ -119,19 +134,19 @@
</template>
<script setup lang='ts' name='MetadataMap'>
import { storeToRefs } from 'pinia'
import { storeToRefs } from 'pinia';
import { useProductStore } from '@/store/product';
import { detail as queryPluginAccessDetail } from '@/api/link/accessConfig'
import { getPluginData, getProductByPluginId } from '@/api/link/plugin'
import { getImage, onlyMessage } from '@/utils/comm'
import { getMetadataMapById, metadataMapById } from '@/api/device/instance'
import { detail as queryPluginAccessDetail } from '@/api/link/accessConfig';
import { getPluginData, getProductByPluginId } from '@/api/link/plugin';
import { getImage, onlyMessage } from '@/utils/comm';
import { getMetadataMapById, metadataMapById } from '@/api/device/instance';
import { cloneDeep } from 'lodash-es';
const productStore = useProductStore();
const { current: productDetail } = storeToRefs(productStore)
const dataSourceCache = ref([])
const dataSource = ref([])
const pluginOptions = ref<any[]>([])
const { current: productDetail } = storeToRefs(productStore);
const dataSourceCache = ref([]);
const dataSource = ref([]);
const pluginOptions = ref<any[]>([]);
const filterValue = ref<boolean | undefined>(undefined);
const originalData = ref([]);
@ -144,7 +159,7 @@ const columns = [
{
title: '序号',
dataIndex: 'index',
width: 100
width: 100,
},
{
title: '平台属性',
@ -155,49 +170,86 @@ const columns = [
dataIndex: 'plugin',
width: 250,
// sorter: tableFilter
}
]
},
];
const _value = ref<any>(undefined);
const selectedKeys = computed(() => {
return dataSource.value?.filter(item => !!item?.plugin).map(item => item.id) || []
})
return (
dataSource.value
?.filter((item) => !!item?.plugin)
.map((item) => item.id) || []
);
});
const selectedPluginKeys = computed(() => {
return dataSource.value?.filter(item => !!item?.plugin).map(item => item.plugin) || []
})
return (
dataSource.value
?.filter((item) => !!item?.plugin)
.map((item) => item.plugin) || []
);
});
const getMetadataMapData = () => {
return new Promise(resolve => {
getMetadataMapById('product', productDetail.value?.id).then(res => {
return new Promise((resolve) => {
getMetadataMapById('product', productDetail.value?.id).then((res) => {
if (res.success) {
resolve(res.result?.filter(item => item.customMapping)?.map(item => {
resolve(
res.result
?.filter((item) => item.customMapping)
?.map((item) => {
return {
id: item.metadataId,
pluginId: item.originalId
}
}) || [])
}
})
})
pluginId: item.originalId,
};
}) || [],
);
}
});
});
};
// const search = (value: string) => {
// if (value) {
// dataSource.value = dataSourceCache.value.filter((item: any) => {
// return !!item.name?.includes(value)
// })
// } else {
// dataSource.value = dataSourceCache.value
// }
// }
const customRow = (record: any) => {
return {
id: record.id,
class: _value.value === record.name ? 'metadata-search-row' : '',
};
};
const search = (value: string) => {
if (value) {
dataSource.value = dataSourceCache.value.filter((item: any) => {
return !!item.name?.includes(value)
})
const _item: any = dataSourceCache.value.find((item: any) => {
return value === item.name;
});
_value.value = _item.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
} else {
dataSource.value = dataSourceCache.value
}
_value.value = undefined;
}
};
const getDefaultMetadata = async () => {
const metadata = JSON.parse(productDetail.value?.metadata || '{}')
const properties = metadata.properties
const pluginMetadata = await getPluginMetadata()
const pluginProperties = pluginMetadata?.properties || []
const metadataMap: any = await getMetadataMapData()
pluginOptions.value = pluginProperties.map(item => ({...item, label: item.name, value: item.id}))
const metadata = JSON.parse(productDetail.value?.metadata || '{}');
const properties = metadata.properties;
const pluginMetadata = await getPluginMetadata();
const pluginProperties = pluginMetadata?.properties || [];
const metadataMap: any = await getMetadataMapData();
pluginOptions.value = pluginProperties.map((item) => ({
...item,
label: item.name,
value: item.id,
}));
// const concatProperties = [ ...pluginProperties.map(item => ({ id: item.id, pluginId: item.id})), ...metadataMap]
const concatProperties = [...metadataMap];
@ -211,50 +263,65 @@ const getDefaultMetadata = async () => {
}
});
dataSource.value = properties?.map((item: any, index: number) => {
const _m = concatProperties.find(p => p.id === item.id)
dataSource.value =
properties?.map((item: any, index: number) => {
const _m = concatProperties.find((p) => p.id === item.id);
return {
index: index + 1,
id: item.id, // id
name: item.name,
type: item.valueType?.type,
plugin: _m?.pluginId, // id
}
}) || []
dataSourceCache.value = dataSource.value
}
};
}) || [];
dataSourceCache.value = dataSource.value;
};
const getPluginMetadata = (): Promise<{ properties: any[] }> => {
return new Promise(resolve => {
queryPluginAccessDetail(productDetail.value?.accessId!).then(async res => {
return new Promise((resolve) => {
queryPluginAccessDetail(productDetail.value?.accessId!).then(
async (res) => {
if (res.success) {
const _channelId = (res.result as any)!.channelId
const pluginRes = await getPluginData('product', productDetail.value?.accessId || '', productDetail.value?.id).catch(() => ({ success: false, result: {}}))
const resp = await getProductByPluginId(_channelId).catch(() => ({ success: false, result: []}))
const _channelId = (res.result as any)!.channelId;
const pluginRes = await getPluginData(
'product',
productDetail.value?.accessId || '',
productDetail.value?.id,
).catch(() => ({ success: false, result: {} }));
const resp = await getProductByPluginId(_channelId).catch(
() => ({ success: false, result: [] }),
);
if (resp.success) {
const _item = (resp.result as any[])?.find((item: any) => item.id === (pluginRes?.result as any)?.externalId)
const _item = (resp.result as any[])?.find(
(item: any) =>
item.id ===
(pluginRes?.result as any)?.externalId,
);
resolve(_item ? _item.metadata : { properties: [] })
resolve(_item ? _item.metadata : { properties: [] });
}
}
resolve({ properties: [] })
})
})
}
resolve({ properties: [] });
},
);
});
};
const pluginChange = async (value: any, id: string) => {
const res = await metadataMapById('product', productDetail.value?.id, [{
const res = await metadataMapById('product', productDetail.value?.id, [
{
metadataType: 'property',
metadataId: value.id,
originalId: id
}])
originalId: id,
},
]);
if (res.success) {
onlyMessage('操作成功')
}
onlyMessage('操作成功');
}
};
const onFilter = ({ key }: any) => {
originalData.value = dataSource.value
originalData.value = dataSource.value;
const _dataSource = cloneDeep(dataSource.value).sort((a: any, b: any) => {
if (!key) {
return (a.plugin ? 1 : -1) - (b.plugin ? 1 : -1);
@ -273,9 +340,8 @@ const onClose = () => {
};
onMounted(() => {
getDefaultMetadata()
})
getDefaultMetadata();
});
</script>
<style scoped lang='less'>
@ -288,6 +354,17 @@ onMounted(() => {
.left {
// margin-right: 44px;
flex: 1;
.box {
height: calc(100vh - 392px);
overflow: hidden;
:deep(.metadata-search-row) {
td {
background: #ffff80 !important;
}
}
}
}
.right {
@ -302,7 +379,7 @@ onMounted(() => {
.title {
margin-bottom: 16px;
color: rgba(#000, .85);
color: rgba(#000, 0.85);
font-weight: bold;
p {

View File

@ -429,7 +429,12 @@ const formRules = ref({
'configuration.host': [{ required: true, message: '请输入服务器地址', trigger: 'blur' }],
'configuration.sender': [
{ required: true, message: '请输入发件人', trigger: 'blur' },
{ max: 64, message: '最多可输入64个字符' },
// { max: 64, message: '64' },
{
pattern:
/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
message: '请输入正确的邮箱',
},
],
'configuration.username': [
{ required: true, message: '请输入用户名', trigger: 'blur' },

View File

@ -71,7 +71,7 @@ const props = defineProps({
},
gridColumn: {
type: Number,
default: 2
default: 3
}
});