fix: 物模型开发

This commit is contained in:
wangshuaiswim 2023-02-02 18:29:23 +08:00
parent 519042d019
commit b46b71812d
8 changed files with 144 additions and 58 deletions

View File

@ -1,7 +1,7 @@
<template>
<template v-if="isPermission">
<template v-if="popConfirm">
<a-popconfirm v-bind="popConfirm" :disabled="!isPermission || props.disabled">
<a-popconfirm v-bind="popConfirm" @confirm="conform" :disabled="!isPermission || props.disabled">
<a-tooltip v-if="tooltip" v-bind="tooltip">
<slot v-if="noButton"></slot>
<a-button v-else v-bind="_buttonProps" :disabled="_isPermission" @click="handleClick">
@ -108,6 +108,10 @@ const _isPermission = computed(() =>
const handleClick = (e: MouseEvent) => {
emits('click', e)
}
const conform = (e: MouseEvent) => {
props.popConfirm?.onConfirm?.(e)
}
</script>
<style scoped lang="less">

View File

@ -5,12 +5,12 @@ import { detail } from '@/api/device/instance'
export const useInstanceStore = defineStore({
id: 'device',
state: () => ({
current: {} as Partial<DeviceInstance>,
detail: {} as Partial<DeviceInstance>,
current: {} as DeviceInstance,
detail: {} as DeviceInstance,
tabActiveKey: 'Info'
}),
actions: {
setCurrent(current: Partial<DeviceInstance>) {
setCurrent(current: DeviceInstance) {
this.current = current
this.detail = current
},

View File

@ -5,8 +5,8 @@ import { detail} from '@/api/device/product'
export const useProductStore = defineStore({
id: 'product',
state: () => ({
current: {} as ProductItem | undefined,
detail: {} as ProductItem | undefined,
current: {} as ProductItem,
detail: {} as ProductItem,
tabActiveKey: 'Info'
}),
actions: {

View File

@ -34,7 +34,7 @@
<template #extra>
<img @click="handleRefresh" :src="getImage('/device/button.png')" style="margin-right: 20px; cursor: pointer;" />
</template>
<component :is="tabs[instanceStore.tabActiveKey]" />
<component :is="tabs[instanceStore.tabActiveKey]" v-bind="{ type: 'device' }" />
</page-container>
</template>

View File

@ -18,6 +18,7 @@ import { updateMetadata, asyncUpdateMetadata } from '../../metadata'
import { Store } from 'jetlinks-store';
import { SystemConst } from '@/utils/consts';
import { detail } from '@/api/device/instance';
import { DeviceInstance } from '@/views/device/Instance/typings';
interface Props {
type: 'product' | 'device';
@ -50,7 +51,8 @@ const save = reactive({
save.loading = true
addFormRef.value?.validateFields().then(async (formValue) => {
const type = metadataStore.model.type
const _metadata = JSON.parse((props.type === 'device' ? instanceStore.detail.metadata : productStore.current?.metadata) || '{}')
const _detail: ProductItem | DeviceInstance = props.type === 'device' ? instanceStore.detail : productStore.current
const _metadata = JSON.parse(_detail?.metadata || '{}')
const list = _metadata[type] as any[]
if (formValue.id) {
if (metadataStore.model.action === 'add' && list.some(item => item.id === formValue.id)) {
@ -70,7 +72,7 @@ const save = reactive({
productStore.setCurrent(detail)
}
}
const _data = updateMetadata(type, [formValue], _metadata, updateStore)
const _data = updateMetadata(type, [formValue], _detail, updateStore)
const result = await asyncUpdateMetadata(props.type, _data)
if (result.status === 200) {
if ((window as any).onTabSaveSuccess) {

View File

@ -2,8 +2,8 @@
<JTable :loading="loading" :data-source="data" size="small" :columns="columns" row-key="id" model="TABLE">
<template #headerTitle>
<a-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch"></a-input-search>
<PermissionButton :has-permission="permission" key="add" @click="handleAddClick"
:disabled="operateLimits('add', type)" type="primary" :tooltip="{
<PermissionButton type="primary" :uhas-permission="`${permission}:update`" key="add" @click="handleAddClick"
:udisabled="operateLimits('add', type)" :tooltip="{
title: operateLimits('add', type) ? '当前的存储方式不支持新增' : '新增',
}">
<template #icon>
@ -30,6 +30,24 @@
{{ expandsType[item] }}
</a-tag>
</template>
<template #action="slotProps">
<PermissionButton :has-permission="`${permission}:update`" type="link" key="edit" style="padding: 0"
:disabled="operateLimits('updata', type)" @click="handleEditClick(slotProps)" :tooltip="{
title: operateLimits('updata', type) ? '当前的存储方式不支持编辑' : '编辑',
}">
<EditOutlined />
</PermissionButton>,
<PermissionButton :has-permission="`${permission}:delete`" type="link" key="delete" style="padding: 0"
:pop-confirm="{
title: '确认删除?', onConfirm: async () => {
await removeItem(slotProps);
},
}" :tooltip="{
title: '删除',
}">
<DeleteOutlined />
</PermissionButton>
</template>
</JTable>
</template>
<script setup lang="ts" name="BaseMetadata">
@ -40,6 +58,12 @@ import { useInstanceStore } from '@/store/instance'
import { useProductStore } from '@/store/product'
import { useMetadataStore } from '@/store/metadata'
import PermissionButton from '@/components/PermissionButton/index.vue'
import { PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue/es'
import { SystemConst } from '@/utils/consts'
import { Store } from 'jetlinks-store'
import { asyncUpdateMetadata, removeMetadata } from '../metadata'
import { detail } from '@/api/device/instance'
// import { detail } from '@/api/device/instance'
// import { detail as productDetail } from '@/api/device/product'
interface Props {
@ -75,6 +99,7 @@ const actions: JColumnProps[] = [
title: '操作',
align: 'left',
width: 200,
dataIndex: 'action',
scopedSlots: true,
},
];
@ -123,6 +148,41 @@ const operateLimits = (action: 'add' | 'updata', types: MetadataType) => {
(instanceStore.detail.features || []).find((item: { id: string; name: string }) => item.id === limitsMap.get(`${types}-${action}`))
);
};
const handleEditClick = (record: MetadataItem) => {
metadataStore.model.edit = true;
metadataStore.model.item = record;
metadataStore.model.type = type;
metadataStore.model.action = 'edit';
if (!instanceStore.detail?.independentMetadata && props.target === 'device') {
message.warning('修改物模型后会脱离产品物模型');
}
}
const resetMetadata = async () => {
const { id } = route.params
const resp = await detail(id as string);
if (resp.status === 200) {
instanceStore.setCurrent(resp?.result || []);
}
};
const removeItem = async (record: MetadataItem) => {
// const removeDB = () => {
// return DB.getDB().table(`${type}`).delete(record.id!);
// };
const _currentData = removeMetadata(type, [record], target === 'device' ? instanceStore.current : productStore.detail);
const result = await asyncUpdateMetadata(target, _currentData);
if (result.status === 200) {
message.success('操作成功!');
Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
metadataStore.model.edit = false;
metadataStore.model.item = {};
resetMetadata();
} else {
message.error('操作失败!');
}
};
</script>
<style scoped lang="less">

View File

@ -1,52 +1,50 @@
<template>
<div class='device-detail-metadata' style="position: relative;">
<div class="tips">
<a-tooltip :title="instanceStore.detail?.independentMetadata && type === 'device'
? '该设备已脱离产品物模型,修改产品物模型对该设备无影响'
: '设备会默认继承产品的物模型,修改设备物模型后将脱离产品物模型'">
<div class="ellipsis">
<info-circle-outlined style="margin-right: 3px" />
{{
instanceStore.detail?.independentMetadata && type === 'device'
? '该设备已脱离产品物模型,修改产品物模型对该设备无影响'
: '设备会默认继承产品的物模型,修改设备物模型后将脱离产品物模型'
}}
</div>
</a-tooltip>
</div>
<a-tabs class="metadataNav" destroyInactiveTabPane type="card">
<template #rightExtra>
<a-space>
<PermissionButton v-if="type === 'device' && instanceStore.detail?.independentMetadata"
:hasPermission="`${permission}:update`" :popConfirm="{ title: '确认重置?', onConfirm: resetMetadata, }"
:tooltip="{ title: '重置后将使用产品的物模型配置' }" key="reload">
重置操作
</PermissionButton>
<PermissionButton
:uhasPermission="`${permission}:update`"
@click="visible = true">快速导入</PermissionButton>
<PermissionButton
:uhasPermission="`${permission}:update`"
@click="cat = true">物模型TSL</PermissionButton>
</a-space>
</template>
<a-card>
<div class='device-detail-metadata' style="position: relative;">
<div class="tips">
<a-tooltip :title="instanceStore.detail?.independentMetadata && type === 'device'
? '该设备已脱离产品物模型,修改产品物模型对该设备无影响'
: '设备会默认继承产品的物模型,修改设备物模型后将脱离产品物模型'">
<div class="ellipsis">
<info-circle-outlined style="margin-right: 3px" />
{{
instanceStore.detail?.independentMetadata && type === 'device'
? '该设备已脱离产品物模型,修改产品物模型对该设备无影响'
: '设备会默认继承产品的物模型,修改设备物模型后将脱离产品物模型'
}}
</div>
</a-tooltip>
</div>
<a-tabs class="metadataNav" destroyInactiveTabPane type="card">
<template #rightExtra>
<a-space>
<PermissionButton v-if="type === 'device' && instanceStore.detail?.independentMetadata"
:hasPermission="`${permission}:update`" :popConfirm="{ title: '确认重置?', onConfirm: resetMetadata, }"
:tooltip="{ title: '重置后将使用产品的物模型配置' }" key="reload">
重置操作
</PermissionButton>
<PermissionButton :uhasPermission="`${permission}:update`" @click="visible = true">快速导入</PermissionButton>
<PermissionButton :uhasPermission="`${permission}:update`" @click="cat = true">物模型TSL</PermissionButton>
</a-space>
</template>
<a-tab-pane tab="属性定义" key="properties">
<BaseMetadata :target="type" type="properties" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="功能定义" key="functions">
<BaseMetadata :target="type" type="functions" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="事件定义" key="events">
<BaseMetadata :target="type" type="events" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="标签定义" key="tags">
<BaseMetadata :target="type" type="tags" :permission="permission" />
</a-tab-pane>
</a-tabs>
<Import v-model:visible="visible" :type="type" @close="visible = false" />
<Cat v-model:visible="cat" @close="cat = false" :type="type" />
</div>
<a-tab-pane tab="属性定义" key="properties">
<BaseMetadata :target="type" type="properties" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="功能定义" key="functions">
<BaseMetadata :target="type" type="functions" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="事件定义" key="events">
<BaseMetadata :target="type" type="events" :permission="permission" />
</a-tab-pane>
<a-tab-pane tab="标签定义" key="tags">
<BaseMetadata :target="type" type="tags" :permission="permission" />
</a-tab-pane>
</a-tabs>
<Import v-model:visible="visible" :type="type" @close="visible = false" />
<Cat v-model:visible="cat" @close="cat = false" :type="type" />
</div>
</a-card>
</template>
<script setup lang="ts" name="Metadata">
import { InfoCircleOutlined } from '@ant-design/icons-vue';

View File

@ -58,4 +58,26 @@ export const asyncUpdateMetadata = (
case 'device':
return saveMetadata(data.id, JSON.parse(data.metadata || '{}'));
}
};
/**
*
* @param type
* @param item
* @param data /
* @param onEvent
*/
export const removeMetadata = (
type: MetadataType,
item: MetadataItem[],
data: ProductItem | DeviceInstance,
onEvent?: (type: 'remove', item: MetadataItem) => void,
): ProductItem | DeviceInstance => {
const metadata = JSON.parse(data.metadata || '{}') as DeviceMetadata;
const config = (metadata[type] || []) as MetadataItem[];
// @ts-ignore
metadata[type] = config.filter((i) => !item.map((r) => r.id).includes(i.id));
onEvent?.('remove', item);
data.metadata = JSON.stringify(metadata);
return data;
};