iot-ui-vue/src/views/device/components/Metadata/Base/index.vue

233 lines
8.2 KiB
Vue

<template>
<div class="table-header">
<div>
<j-input-search v-model:value="searchValue" placeholder="请输入名称" @search="handleSearch" allowClear></j-input-search>
</div>
<div>
<PermissionButton type="primary" :hasPermission="`${permission}:update`" key="add" @click="handleAddClick"
:disabled="operateLimits('add', type)" :tooltip="{
title: operateLimits('add', type) ? '当前的存储方式不支持新增' : '新增',
}">
<template #icon>
<AIcon type="PlusOutlined" />
</template>
新增
</PermissionButton>
<Edit v-if="metadataStore.model.edit" :type="target" :tabs="type" @refresh="refreshMetadata"></Edit>
</div>
</div>
<j-table :loading="loading" :data-source="data" :columns="columns" row-key="id" model="TABLE" size="small"
:pagination="pagination">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'id'">
<div style="width: 100px"><Ellipsis>{{ record.id || '-' }}</Ellipsis></div>
</template>
<template v-if="column.dataIndex === 'name'">
<div style="width: 200px"><Ellipsis>{{ record.name || '-' }}</Ellipsis></div>
</template>
<template v-if="column.dataIndex === 'description'">
<div style="width: 200px"><Ellipsis>{{ record.description || '-' }}</Ellipsis></div>
</template>
<template v-if="column.dataIndex === 'level'">
{{ levelMap[record.expands?.level] || '-' }}
</template>
<template v-if="column.dataIndex === 'async'">
{{ record.async ? '是' : '否' }}
</template>
<template v-if="column.dataIndex === 'valueType'">
{{ record.valueType?.type }}
</template>
<template v-if="column.dataIndex === 'source'">
{{ sourceMap[record.expands?.source] }}
</template>
<template v-if="column.dataIndex === 'type'">
<j-tag v-for="item in (record.expands?.type || [])" :key="item">
{{ expandsType[item] }}
</j-tag>
</template>
<template v-if="column.dataIndex === 'action'">
<j-space>
<PermissionButton :has-permission="`${permission}:update`" type="link" key="edit" style="padding: 0"
:disabled="operateLimits('updata', type)" @click="handleEditClick(record)" :tooltip="{
title: operateLimits('updata', type) ? '当前的存储方式不支持编辑' : '编辑',
}">
<AIcon type="EditOutlined" />
</PermissionButton>
<PermissionButton :has-permission="`${permission}:delete`" type="link" key="delete" style="padding: 0" danger
:pop-confirm="{
title: '确认删除?', onConfirm: async () => {
await removeItem(record);
},
}" :tooltip="{
title: '删除',
}">
<AIcon type="DeleteOutlined" />
</PermissionButton>
</j-space>
</template>
</template>
</j-table>
</template>
<script setup lang="ts" name="BaseMetadata">
import type { MetadataItem, MetadataType } from '@/views/device/Product/typings'
import { useColumns } from './columns';
import { useInstanceStore } from '@/store/instance'
import { useProductStore } from '@/store/product'
import { useMetadataStore } from '@/store/metadata'
import PermissionButton from '@/components/PermissionButton/index.vue'
import { TablePaginationConfig } from 'ant-design-vue/es'
import { asyncUpdateMetadata, removeMetadata } from '../metadata'
import Edit from './Edit/index.vue'
import { ColumnProps } from 'ant-design-vue/es/table'
import { onlyMessage } from '@/utils/comm';
interface Props {
type: MetadataType;
target: 'product' | 'device';
permission: string | string[];
}
const props = defineProps<Props>()
const route = useRoute()
const instanceStore = useInstanceStore()
const productStore = useProductStore()
const loading = ref(false)
const data = ref<MetadataItem[]>([])
const { type, target = 'product' } = props
const levelMap = ref({
ordinary: '普通',
warn: '警告',
urgent: '紧急',
})
const sourceMap = ref({
device: '设备',
manual: '手动',
rule: '规则',
});
const expandsType = ref({
read: '读',
write: '写',
report: '上报',
});
const actions: ColumnProps[] = [
{
title: '操作',
align: 'left',
width: 80,
dataIndex: 'action',
},
];
const pagination = {
showTotal: (num: number, range: number[]) => {
return `第 ${range[0]} - ${range[1]} 条/总共 ${num} 条`;
},
showSizeChanger: true,
showQuickJumper: false,
defaultPageSize: 10,
size: 'small',
} as TablePaginationConfig
// const columns = computed(() => MetadataMapping.get(type)!.concat(actions))
const { columns } = useColumns(type)
const items = computed(() => JSON.parse((target === 'product' ? productStore.current?.metadata : instanceStore.current.metadata) || '{}'))
const searchValue = ref<string>()
const handleSearch = (searchValue: string) => {
if (searchValue) {
const arr = items.value[type].filter((item: MetadataItem) => item.name!.indexOf(searchValue) > -1).sort((a: MetadataItem, b: MetadataItem) => b?.sortsIndex - a?.sortsIndex)
data.value = arr
} else {
data.value = items.value[type]
}
}
const refreshMetadata = () => {
loading.value = true
// const res = target === 'product'
// ? await productDetail(route.params.id as string)
// : await detail(route.params.id as string);
const result = target === 'product' ? productStore.current?.metadata : instanceStore.current.metadata
const item = JSON.parse(result || '{}') as MetadataItem[]
console.log(item)
data.value = item[type]?.sort((a: any, b: any) => b?.sortsIndex - a?.sortsIndex)
loading.value = false
}
watch([route.params.id, type], refreshMetadata, { immediate: true })
const metadataStore = useMetadataStore()
watch(() => metadataStore.model.importMetadata,
(val: boolean) => {
if (!!val) {
refreshMetadata()
metadataStore.set('importMetadata', false)
}
})
const handleAddClick = () => {
metadataStore.set('edit', true)
metadataStore.set('item', undefined)
metadataStore.set('type', type)
metadataStore.set('action', 'add')
if (props.target === 'device' && !instanceStore.detail?.independentMetadata) {
onlyMessage('修改物模型后会脱离产品物模型', 'warning')
}
}
const limitsMap = new Map<string, any>();
limitsMap.set('events-add', 'eventNotInsertable');
limitsMap.set('events-updata', 'eventNotModifiable');
limitsMap.set('properties-add', 'propertyNotInsertable');
limitsMap.set('properties-updata', 'propertyNotModifiable');
const operateLimits = (action: 'add' | 'updata', types: MetadataType) => {
return (
target === 'device' &&
(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 (props.target === 'device' && !instanceStore.detail?.independentMetadata) {
onlyMessage('修改物模型后会脱离产品物模型', 'warning');
}
}
const resetMetadata = async () => {
// const { id } = route.params
// const resp = await detail(id as string);
// if (resp.status === 200) {
// instanceStore.setCurrent(resp?.result || []);
// }
const { id } = route.params
if (target === 'device') {
await instanceStore.refresh(id as string)
} else {
await productStore.getDetail(id as string)
}
metadataStore.set('importMetadata', true)
};
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) {
onlyMessage('操作成功!');
// Store.set(SystemConst.REFRESH_METADATA_TABLE, true);
metadataStore.model.edit = false;
metadataStore.model.item = {};
resetMetadata();
} else {
onlyMessage('操作失败!', 'error');
}
};
</script>
<style scoped lang="less">
.table-header {
display: flex;
justify-content: space-between;
padding: 16px;
}
</style>