Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
30c1a1813d
|
@ -13,3 +13,5 @@ export const postInitSet = (data) => server.post(`/user/settings/init`, data)
|
||||||
export const systemVersion = () => server.get(`/system/version`)
|
export const systemVersion = () => server.get(`/system/version`)
|
||||||
|
|
||||||
export const bindInfo = () => server.get(`/application/sso/_all`)
|
export const bindInfo = () => server.get(`/application/sso/_all`)
|
||||||
|
|
||||||
|
export const settingDetail = (scopes) => server.get(`/system/config/${scopes}`)
|
|
@ -297,7 +297,7 @@ const JTable = defineComponent<JTableProps>({
|
||||||
</div>
|
</div>
|
||||||
{/* 分页 */}
|
{/* 分页 */}
|
||||||
{
|
{
|
||||||
(!!_dataSource.value.length) && !props.noPagination &&
|
(!!_dataSource.value.length) && !props.noPagination && props.type === 'PAGE' &&
|
||||||
<div class={styles['jtable-pagination']}>
|
<div class={styles['jtable-pagination']}>
|
||||||
<Pagination
|
<Pagination
|
||||||
size="small"
|
size="small"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
@cancelSelect="cancelSelect"
|
@cancelSelect="cancelSelect"
|
||||||
>
|
>
|
||||||
<template #headerTitle>
|
<template #headerTitle>
|
||||||
<a-button type="primary">新增</a-button>
|
<a-button type="primary" @click="add">新增</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #card="slotProps">
|
<template #card="slotProps">
|
||||||
<CardBox
|
<CardBox
|
||||||
|
@ -83,8 +83,10 @@ import server from "@/utils/request";
|
||||||
import type { ActionsType } from '@/components/Table/index.vue'
|
import type { ActionsType } from '@/components/Table/index.vue'
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { DeleteOutlined } from '@ant-design/icons-vue'
|
import { DeleteOutlined } from '@ant-design/icons-vue'
|
||||||
|
import { message } from "ant-design-vue";
|
||||||
|
|
||||||
const request = (data: any) => server.post(`/device-product/_query`, data)
|
const request = (data: any) => server.post(`/device-product/_query`, data)
|
||||||
|
// const request = (data: any) => server.post(`/device/category/_tree`, {paging: false})
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
@ -169,6 +171,10 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const add = () => {
|
||||||
|
message.warn('123')
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
<template>
|
||||||
|
<a-drawer :mask-closable="false" title="查看物模型" width="700" v-model:visible="_visible" destroy-on-close @close="close">
|
||||||
|
<template #extra>
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="handleExport">
|
||||||
|
导出
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<a-spin :spinning="loading">
|
||||||
|
<div class="cat-content">
|
||||||
|
<p class="cat-tip">
|
||||||
|
物模型是对设备在云端的功能描述,包括设备的属性、服务和事件。物联网平台通过定义一种物的描述语言来描述物模型,称之为
|
||||||
|
TSL(即 Thing Specification Language),采用 JSON 格式,您可以根据 TSL
|
||||||
|
组装上报设备的数据。您可以导出完整物模型,用于云端应用开发。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<a-tabs @change="handleConvertMetadata">
|
||||||
|
<a-tab-pane v-for="item in codecs" :tab-key="item.id" :key="item.id">
|
||||||
|
<div class="cat-panel">
|
||||||
|
<!-- TODO 代码编辑器 -->
|
||||||
|
</div>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-spin>
|
||||||
|
</a-drawer>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts" name="Cat">
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { downloadObject } from '@/utils/utils'
|
||||||
|
import { useInstanceStore } from '@/store/instance';
|
||||||
|
import { useProductStore } from '@/store/product';
|
||||||
|
import type { Key } from 'ant-design-vue/es/_util/type';
|
||||||
|
import { convertMetadata, getCodecs, detail as productDetail } from '@/api/device/product';
|
||||||
|
import { detail } from '@/api/device/instance'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean;
|
||||||
|
type: 'product' | 'device';
|
||||||
|
}
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:visible', data: boolean): void;
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
const emits = defineEmits<Emits>()
|
||||||
|
const route = useRoute()
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const _visible = computed({
|
||||||
|
get: () => {
|
||||||
|
return props.visible;
|
||||||
|
},
|
||||||
|
set: (val: any) => {
|
||||||
|
emits('update:visible', val);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
emits('update:visible', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instanceStore = useInstanceStore()
|
||||||
|
const productStore = useProductStore()
|
||||||
|
const metadataMap = {
|
||||||
|
product: productStore.current?.metadata as string,
|
||||||
|
device: instanceStore.current?.metadata as string,
|
||||||
|
};
|
||||||
|
const metadata = metadataMap[props.type];
|
||||||
|
const value = ref(metadata)
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
downloadObject(
|
||||||
|
JSON.parse(value.value),
|
||||||
|
`${props.type === 'device'
|
||||||
|
? instanceStore.current?.name
|
||||||
|
: productStore.current?.name
|
||||||
|
}-物模型`,
|
||||||
|
'YYYY/MM/DD',
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
message.error('请先配置物模型');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConvertMetadata = (key: Key) => {
|
||||||
|
if (key === 'alink') {
|
||||||
|
value.value = '';
|
||||||
|
if (metadata) {
|
||||||
|
convertMetadata('to', 'alink', JSON.parse(metadata)).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
value.value = JSON.stringify(res.result)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value.value = metadata;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const codecs = ref<{ id: string; name: string }[]>()
|
||||||
|
|
||||||
|
const routeChange = async (id: string) => {
|
||||||
|
const res = await getCodecs()
|
||||||
|
if (res.status === 200) {
|
||||||
|
codecs.value = [{ id: 'jetlinks', name: 'jetlinks' }].concat(res.result)
|
||||||
|
}
|
||||||
|
if (props.type === 'device' && id) {
|
||||||
|
detail(id as string).then((resp) => {
|
||||||
|
if (resp.status === 200) {
|
||||||
|
instanceStore.setCurrent(resp.result);
|
||||||
|
const _metadata = resp.result?.metadata;
|
||||||
|
value.value = _metadata;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => route.params.id,
|
||||||
|
(id) => routeChange(id as string),
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (props.visible) {
|
||||||
|
loading.value = true
|
||||||
|
const { id } = route.params
|
||||||
|
if (props.type === 'device') {
|
||||||
|
detail(id as string).then((resp) => {
|
||||||
|
loading.value = false
|
||||||
|
instanceStore.setCurrent(resp.result)
|
||||||
|
value.value = resp.result.metadata
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
productDetail(id as string).then((resp) => {
|
||||||
|
loading.value = false
|
||||||
|
// productStore.setCurrent(resp.result)
|
||||||
|
value.value = resp.result.metadata
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.cat-content {
|
||||||
|
background: #F6F6F6;
|
||||||
|
|
||||||
|
.cat-tip {
|
||||||
|
padding: 10px;
|
||||||
|
color: rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cat-panel {
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
height: 670px;
|
||||||
|
width: 650px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,262 @@
|
||||||
|
<template>
|
||||||
|
<a-modal :mask-closable="false" title="导入物模型" destroy-on-close v-model:visible="_visible" @cancel="close"
|
||||||
|
@ok="handleImport" :confirm-loading="loading">
|
||||||
|
<div class="import-content">
|
||||||
|
<p class="import-tip">
|
||||||
|
<exclamation-circle-outlined style="margin-right: 5px" />
|
||||||
|
导入的物模型会覆盖原来的属性、功能、事件、标签,请谨慎操作。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<a-form layout="vertical" v-model="formModel">
|
||||||
|
<a-form-item label="导入方式" v-bind="validateInfos.type">
|
||||||
|
<a-select v-if="type === 'product'" v-model:value="formModel.type">
|
||||||
|
<a-select-option value="copy">拷贝产品</a-select-option>
|
||||||
|
<a-select-option value="import">导入物模型</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="选择产品" v-bind="validateInfos.copy" v-if="formModel.type === 'copy'">
|
||||||
|
<a-select :options="productList" v-model:value="formModel.copy" option-filter-prop="label"></a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="物模型类型" v-bind="validateInfos.metadata"
|
||||||
|
v-if="type === 'device' || formModel.type === 'import'">
|
||||||
|
<a-select v-model:value="formModel.metadata">
|
||||||
|
<a-select-option value="jetlinks">Jetlinks物模型</a-select-option>
|
||||||
|
<a-select-option value="alink">阿里云物模型TSL</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="导入类型" v-bind="validateInfos.metadataType"
|
||||||
|
v-if="type === 'device' || formModel.type === 'import'">
|
||||||
|
<a-select v-model:value="formModel.metadataType">
|
||||||
|
<a-select-option value="file">文件上传</a-select-option>
|
||||||
|
<a-select-option value="script">脚本</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="文件上传" v-bind="validateInfos.upload" v-if="formModel.metadataType === 'file'">
|
||||||
|
<a-upload v-model:file-list="formModel.upload" name="files" :before-upload="beforeUpload" accept=".json"
|
||||||
|
:show-upload-list="false"></a-upload>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="物模型" v-bind="validateInfos.import" v-if="formModel.metadataType === 'script'">
|
||||||
|
<!-- TODO代码编辑器 -->
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts" name="Import">
|
||||||
|
import { useForm } from 'ant-design-vue/es/form';
|
||||||
|
import { saveMetadata } from '@/api/device/instance'
|
||||||
|
import { queryNoPagingPost, convertMetadata, modify } from '@/api/device/product'
|
||||||
|
import type { DefaultOptionType } from 'ant-design-vue/es/select';
|
||||||
|
import { UploadProps } from 'ant-design-vue/es';
|
||||||
|
import type { DeviceMetadata } from '@/views/device/Product/typings'
|
||||||
|
import { message } from 'ant-design-vue/es';
|
||||||
|
import { Store } from 'jetlinks-store';
|
||||||
|
import { SystemConst } from '@/utils/consts';
|
||||||
|
import { useInstanceStore } from '@/store/instance'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const instanceStore = useInstanceStore()
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
visible: boolean,
|
||||||
|
type: 'device' | 'product',
|
||||||
|
}
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:visible', data: boolean): void;
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
const emits = defineEmits<Emits>()
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const _visible = computed({
|
||||||
|
get: () => {
|
||||||
|
return props.visible;
|
||||||
|
},
|
||||||
|
set: (val: any) => {
|
||||||
|
emits('update:visible', val);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
emits('update:visible', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** form表单 */
|
||||||
|
const formModel = reactive<Record<string, any>>({
|
||||||
|
type: 'import',
|
||||||
|
metadata: 'jetlinks',
|
||||||
|
metadataType: 'script',
|
||||||
|
})
|
||||||
|
const rules = reactive({
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择导入方式',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
copy: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择产品',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
metadata: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择物模型类型',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
metadataType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择导入类型',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
upload: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传文件',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
import: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入物模型',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
const { validate, validateInfos } = useForm(formModel, rules);
|
||||||
|
const onSubmit = () => {
|
||||||
|
validate().then(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const productList = ref<DefaultOptionType[]>([])
|
||||||
|
|
||||||
|
const loadData = async () => {
|
||||||
|
const { id } = route.params || {}
|
||||||
|
const product = await queryNoPagingPost({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
|
terms: [{ column: 'id$not', value: id }],
|
||||||
|
}) as any
|
||||||
|
productList.value = product.result.filter((i: any) => i?.metadata).map((item: any) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.metadata,
|
||||||
|
key: item.id
|
||||||
|
})) as DefaultOptionType[]
|
||||||
|
}
|
||||||
|
loadData()
|
||||||
|
|
||||||
|
const beforeUpload: UploadProps['beforeUpload'] = file => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsText(file);
|
||||||
|
reader.onload = (json) => {
|
||||||
|
formModel.import = json.target?.result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const operateLimits = (mdata: DeviceMetadata) => {
|
||||||
|
const obj: DeviceMetadata = { ...mdata };
|
||||||
|
const old = JSON.parse(instanceStore.detail?.metadata || '{}');
|
||||||
|
const fid = instanceStore.detail?.features?.map(item => item.id);
|
||||||
|
if (fid?.includes('eventNotModifiable')) {
|
||||||
|
obj.events = old?.events || [];
|
||||||
|
}
|
||||||
|
if (fid?.includes('propertyNotModifiable')) {
|
||||||
|
obj.properties = old?.properties || [];
|
||||||
|
}
|
||||||
|
(obj?.events || []).map((item, index) => {
|
||||||
|
return { ...item, sortsIndex: index };
|
||||||
|
});
|
||||||
|
(obj?.properties || []).map((item, index) => {
|
||||||
|
return { ...item, sortsIndex: index };
|
||||||
|
});
|
||||||
|
(obj?.functions || []).map((item, index) => {
|
||||||
|
return { ...item, sortsIndex: index };
|
||||||
|
});
|
||||||
|
(obj?.tags || []).map((item, index) => {
|
||||||
|
return { ...item, sortsIndex: index };
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImport = async () => {
|
||||||
|
validate().then(async (data) => {
|
||||||
|
loading.value = true
|
||||||
|
if (data.metadata === 'alink') {
|
||||||
|
const res = await convertMetadata('from', 'alink', data.import)
|
||||||
|
if (res.status === 200) {
|
||||||
|
const metadata = JSON.stringify(operateLimits(res.result))
|
||||||
|
const { id } = route.params || {}
|
||||||
|
if (props?.type === 'device') {
|
||||||
|
await saveMetadata(id as string, metadata)
|
||||||
|
} else {
|
||||||
|
await modify(id as string, { metadata: metadata })
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
// MetadataAction.insert(JSON.parse(metadata || '{}'));
|
||||||
|
message.success('导入成功')
|
||||||
|
} else {
|
||||||
|
loading.value = false
|
||||||
|
message.error('发生错误!')
|
||||||
|
}
|
||||||
|
Store.set(SystemConst.GET_METADATA, true)
|
||||||
|
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||||
|
close()
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const _object = JSON.parse(data[props?.type === 'device' ? 'import' : data?.type] || '{}')
|
||||||
|
if (
|
||||||
|
!(!!_object?.properties || !!_object?.events || !!_object?.functions || !!_object?.tags)
|
||||||
|
) {
|
||||||
|
message.error('物模型数据不正确')
|
||||||
|
loading.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { id } = route.params || {}
|
||||||
|
const params = {
|
||||||
|
id,
|
||||||
|
metadata: JSON.stringify(operateLimits(_object as DeviceMetadata)),
|
||||||
|
};
|
||||||
|
const paramsDevice = JSON.stringify(operateLimits(_object as DeviceMetadata))
|
||||||
|
let resp = undefined
|
||||||
|
if (props?.type === 'device') {
|
||||||
|
resp = await saveMetadata(id as string, paramsDevice)
|
||||||
|
} else {
|
||||||
|
resp = await modify(id as string, params)
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
if (resp.status === 200) {
|
||||||
|
if (props?.type === 'device') {
|
||||||
|
const metadata: DeviceMetadata = JSON.parse(paramsDevice || '{}')
|
||||||
|
// MetadataAction.insert(metadata);
|
||||||
|
message.success('导入成功')
|
||||||
|
} else {
|
||||||
|
const metadata: DeviceMetadata = JSON.parse(params?.metadata || '{}')
|
||||||
|
// MetadataAction.insert(metadata);
|
||||||
|
message.success('导入成功')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Store.set(SystemConst.GET_METADATA, true)
|
||||||
|
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||||
|
close();
|
||||||
|
} catch (e) {
|
||||||
|
loading.value = false
|
||||||
|
message.error(e === 'error' ? '物模型数据不正确' : '上传json格式的物模型文件')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// const showProduct = computed(() => formModel.type === 'copy')
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.import-content {
|
||||||
|
background: rgb(236, 237, 238);
|
||||||
|
|
||||||
|
.import-tip {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<div class='device-detail-metadata' style="position: relative;">
|
||||||
|
<div class="tips" style="width: 40%">
|
||||||
|
<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>
|
||||||
|
<template #rightExtra>
|
||||||
|
<a-space>
|
||||||
|
<PermissionButton v-if="type === 'device'" :hasPermission="`${permission}:update`"
|
||||||
|
:popConfirm="{ title: '确认重置?', onConfirm: resetMetadata, }" :tooltip="{ title: '重置后将使用产品的物模型配置' }"
|
||||||
|
key="reload">
|
||||||
|
重置操作
|
||||||
|
</PermissionButton>
|
||||||
|
<PermissionButton :isPermission="`${permission}:update`" @click="visible = true">快速导入</PermissionButton>
|
||||||
|
<PermissionButton :isPermission="`${permission}:update`" @click="cat = true">物模型TSL</PermissionButton>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<a-tab-pane tab="属性定义" key="properties">
|
||||||
|
<BaseMetadata target={props.type} type="properties" :permission="permission" />
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane tab="功能定义" key="functions">
|
||||||
|
<BaseMetadata target={props.type} type="functions" :permission="permission" />
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane tab="事件定义" key="events">
|
||||||
|
<BaseMetadata target={props.type} type="events" :permission="permission" />
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane tab="标签定义" key="tags">
|
||||||
|
<BaseMetadata target={props.type} type="tags" :permission="permission" />
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
<Import :visible="visible" :type="type" @close="visible = false" />
|
||||||
|
<Cat :visible="cat" @close="cat = false" :type="type" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts" name="Metadata">
|
||||||
|
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||||
|
import { deleteMetadata } from '@/api/device/instance.js'
|
||||||
|
import { message } from 'ant-design-vue'
|
||||||
|
import { Store } from 'jetlinks-store'
|
||||||
|
import { SystemConst } from '@/utils/consts'
|
||||||
|
import { useInstanceStore } from '@/store/instance'
|
||||||
|
import Import from './Import/index.vue'
|
||||||
|
import Cat from './Cat/index.vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const instanceStore = useInstanceStore()
|
||||||
|
interface Props {
|
||||||
|
type: 'product' | 'device';
|
||||||
|
independentMetadata?: boolean;
|
||||||
|
}
|
||||||
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const permission = computed(() => props.type === 'device' ? 'device/Instance' : 'device/Product')
|
||||||
|
const visible = ref(false)
|
||||||
|
const cat = ref(false)
|
||||||
|
|
||||||
|
// 重置物模型
|
||||||
|
const resetMetadata = async () => {
|
||||||
|
const { id } = route.params
|
||||||
|
const resp = await deleteMetadata(id as string)
|
||||||
|
if (resp.status === 200) {
|
||||||
|
message.info('操作成功')
|
||||||
|
|
||||||
|
Store.set(SystemConst.REFRESH_DEVICE, true)
|
||||||
|
setTimeout(() => {
|
||||||
|
Store.set(SystemConst.REFRESH_METADATA_TABLE, true)
|
||||||
|
}, 400)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.device-detail-metadata {
|
||||||
|
.tips {
|
||||||
|
position: absolute;
|
||||||
|
top: 12px;
|
||||||
|
z-index: 1;
|
||||||
|
margin-left: 330px;
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metadataNav {
|
||||||
|
:global {
|
||||||
|
.ant-card-body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,8 +5,16 @@
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<img
|
<img
|
||||||
style="width: 100%; height: 100%"
|
style="width: 100%; height: 100%"
|
||||||
:src="getImage('/login.png')"
|
:src="basis.backgroud || getImage('/login.png')"
|
||||||
/>
|
/>
|
||||||
|
<a
|
||||||
|
href="https://beian.miit.gov.cn/#/Integrated/index"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="records"
|
||||||
|
>
|
||||||
|
备案:渝ICP备19017719号-1
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -16,11 +24,13 @@
|
||||||
<img
|
<img
|
||||||
alt="logo"
|
alt="logo"
|
||||||
class="logo"
|
class="logo"
|
||||||
:src="getImage('/logo.png')"
|
:src="basis.logo || getImage('/logo.png')"
|
||||||
/>
|
/>
|
||||||
<!-- </link> -->
|
<!-- </link> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="desc">物联网平台</div>
|
<div class="desc">
|
||||||
|
{{ basis.title || SystemConst.SYSTEM_NAME }}
|
||||||
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<a-form
|
<a-form
|
||||||
layout="vertical"
|
layout="vertical"
|
||||||
|
@ -168,11 +178,13 @@ import {
|
||||||
getInitSet,
|
getInitSet,
|
||||||
systemVersion,
|
systemVersion,
|
||||||
bindInfo,
|
bindInfo,
|
||||||
|
settingDetail,
|
||||||
} from '@/api/login';
|
} from '@/api/login';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import { useUserInfo } from '@/store/userInfo';
|
import { useUserInfo } from '@/store/userInfo';
|
||||||
import { LocalStore } from '@/utils/comm';
|
import { LocalStore } from '@/utils/comm';
|
||||||
import { BASE_API_PATH, TOKEN_KEY, Version_Code } from '@/utils/variable';
|
import { BASE_API_PATH, TOKEN_KEY, Version_Code } from '@/utils/variable';
|
||||||
|
import { SystemConst } from '@/utils/consts';
|
||||||
|
|
||||||
const store = useUserInfo();
|
const store = useUserInfo();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@ -200,6 +212,7 @@ const codeConfig = ref(false);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const bindings = ref<any[]>();
|
const bindings = ref<any[]>();
|
||||||
|
const basis = ref<any>({});
|
||||||
|
|
||||||
const defaultImg = getImage('/apply/provider1.png');
|
const defaultImg = getImage('/apply/provider1.png');
|
||||||
const iconMap = new Map();
|
const iconMap = new Map();
|
||||||
|
@ -222,6 +235,15 @@ const onFinish = async () => {
|
||||||
username: form.username,
|
username: form.username,
|
||||||
});
|
});
|
||||||
LocalStore.set(TOKEN_KEY, res?.result.token);
|
LocalStore.set(TOKEN_KEY, res?.result.token);
|
||||||
|
// if (res.result.username === 'admin') {
|
||||||
|
// const resp: any = await getInitSet();
|
||||||
|
// if (resp.status === 200 && !resp.result.length) {
|
||||||
|
// window.location.href = '/#/init-home';
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// window.location.href = '/';
|
||||||
|
|
||||||
const resp: any = await getInitSet();
|
const resp: any = await getInitSet();
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
router.push('/demo');
|
router.push('/demo');
|
||||||
|
@ -257,6 +279,7 @@ const getCookie = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOpen = () => {
|
const getOpen = () => {
|
||||||
|
LocalStore.removeAll();
|
||||||
systemVersion().then((res: any) => {
|
systemVersion().then((res: any) => {
|
||||||
if (res.success && res.result) {
|
if (res.success && res.result) {
|
||||||
LocalStore.set(Version_Code, res.result.edition);
|
LocalStore.set(Version_Code, res.result.edition);
|
||||||
|
@ -269,6 +292,18 @@ const getOpen = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
settingDetail('front').then((res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
const ico: any = document.querySelector('link[rel="icon"]');
|
||||||
|
ico.href = res.result.ico;
|
||||||
|
basis.value = res.result;
|
||||||
|
if (res.result.title) {
|
||||||
|
document.title = res.result.title;
|
||||||
|
} else {
|
||||||
|
document.title = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleClickOther = (item: any) => {
|
const handleClickOther = (item: any) => {
|
||||||
|
@ -316,6 +351,14 @@ screenRotation(screenWidth.value, screenHeight.value);
|
||||||
.left {
|
.left {
|
||||||
width: 73%;
|
width: 73%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
.records {
|
||||||
|
position: absolute;
|
||||||
|
top: 96%;
|
||||||
|
left: 35%;
|
||||||
|
color: rgba(0, 0, 0, 0.35);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.right {
|
||||||
|
|
Loading…
Reference in New Issue