feat(新增物模型模块及优化部门树): 新增物模型模块及优化其它模块代码
This commit is contained in:
parent
daf3f540a4
commit
1cbd436f73
@ -14,7 +14,7 @@ export default mergeConfig(
|
|||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
// target: 'http://8.134.75.234:8081',
|
// target: 'http://8.134.75.234:8081',
|
||||||
target: 'http://127.0.0.1:8081',
|
target: 'http://192.168.3.238:8081',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -11,6 +11,17 @@ export interface DeptRecord extends DeptCreateRecord {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取部门树
|
||||||
|
export function getAllDeptTree(id: number | string) {
|
||||||
|
return axios({
|
||||||
|
method: 'get',
|
||||||
|
url: '/api/rest/dept/tree',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 添加区域
|
// 添加区域
|
||||||
export function create(data: DeptCreateRecord) {
|
export function create(data: DeptCreateRecord) {
|
||||||
return axios.post(`/api/rest/dept`, data);
|
return axios.post(`/api/rest/dept`, data);
|
||||||
|
@ -24,8 +24,6 @@ export interface MessageCreateRecord {
|
|||||||
attachmentIds?: string[];
|
attachmentIds?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
export function queryMessage(userId: number, messageId: number) {
|
export function queryMessage(userId: number, messageId: number) {
|
||||||
return axios.get(`/api/rest/message/${userId}/${messageId}`);
|
return axios.get(`/api/rest/message/${userId}/${messageId}`);
|
||||||
|
75
src/api/tsl.ts
Normal file
75
src/api/tsl.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
export interface Record {
|
||||||
|
current: number;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServeRecord extends Record {
|
||||||
|
name?: string;
|
||||||
|
identifier?: string;
|
||||||
|
productId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PropertyRecord extends Record {
|
||||||
|
name?: string;
|
||||||
|
identifier?: string;
|
||||||
|
productId: number;
|
||||||
|
dataType?: string;
|
||||||
|
ioType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface eventRecord extends Record {
|
||||||
|
name?: string;
|
||||||
|
level?: string;
|
||||||
|
identifier?: string;
|
||||||
|
productId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryServeList(data: ServeRecord) {
|
||||||
|
return axios({
|
||||||
|
url: '/api/rest/tsl/serve',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryPropertyList(data: PropertyRecord) {
|
||||||
|
return axios({
|
||||||
|
url: '/api/rest/tsl/property',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryEventList(data: eventRecord) {
|
||||||
|
return axios({
|
||||||
|
url: '/api/rest/tsl/event',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createServe(data: any) {
|
||||||
|
return axios.post(`/api/rest/tsl/serve`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createProperty(data: any) {
|
||||||
|
return axios.post(`/api/rest/tsl/property`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createEvent(data: any) {
|
||||||
|
return axios.post(`/api/rest/tsl/event`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteServe(data: any) {
|
||||||
|
return axios.delete(`/api/rest/tsl/serve/${data}`, );
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteProperty(data: any) {
|
||||||
|
return axios.delete(`/api/rest/tsl/property/${data}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteEvent(data: any) {
|
||||||
|
return axios.delete(`/api/rest/tsl/event/${data}`);
|
||||||
|
}
|
BIN
src/assets/objectNetwork.png
Normal file
BIN
src/assets/objectNetwork.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.9 KiB |
34
src/mock/deptTree.ts
Normal file
34
src/mock/deptTree.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import Mock from 'mockjs';
|
||||||
|
import setupMock, { successResponseWrap } from '@/utils/setup-mock';
|
||||||
|
|
||||||
|
// 生成部门树数据
|
||||||
|
const deptTree = Mock.mock({
|
||||||
|
'totalDept': {
|
||||||
|
'dept': '总部门',
|
||||||
|
'children': [
|
||||||
|
{
|
||||||
|
'dept': '部门1',
|
||||||
|
'members': [
|
||||||
|
{'name': '@cname'},
|
||||||
|
{'name': '@cname'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'dept': '部门2',
|
||||||
|
'members': [
|
||||||
|
{'name': '@cname'},
|
||||||
|
{'name': '@cname'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setupMock({
|
||||||
|
setup: () => {
|
||||||
|
Mock.mock(new RegExp('/api/deptTree'), () => {
|
||||||
|
return successResponseWrap(deptTree);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 假设你需要将这个数据作为一个 API 的响应
|
@ -46,6 +46,29 @@ const IOT: AppRouteRecordRaw = {
|
|||||||
permissions: ['*'],
|
permissions: ['*'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'device/:id',
|
||||||
|
name: 'deviceDetail',
|
||||||
|
component: () => import('@/views/iot/device/components/device-detail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '设备详情',
|
||||||
|
requiresAuth: true,
|
||||||
|
showInMenu: false,
|
||||||
|
permissions: ['*'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'product/tsl/:id',
|
||||||
|
name: 'productTsl',
|
||||||
|
component: () => import('@/views/iot/product/components/product-tsl.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '物模型',
|
||||||
|
requiresAuth: true,
|
||||||
|
showInMenu: false,
|
||||||
|
permissions: ['*'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
94
src/views/dashboard/workplace/components/announcement.vue
Normal file
94
src/views/dashboard/workplace/components/announcement.vue
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<a-card
|
||||||
|
class="general-card"
|
||||||
|
title='公告'
|
||||||
|
:header-style="{ paddingBottom: '0' }"
|
||||||
|
:body-style="{ padding: '15px 20px 13px 20px' }"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<a-link @click="$router.push({ name: 'Bulletins' })">查看更多</a-link>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<div v-for="(item, idx) in renderData" :key="idx" class="item">
|
||||||
|
<a-tag color=blue size="small">通知</a-tag>
|
||||||
|
<span class="item-content" @click="$router.push({name:'Details',params:{id:item.id}})">
|
||||||
|
{{ item.title }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
// 获取公告列表
|
||||||
|
import { BulletinsRecord } from '@/api/bulletins';
|
||||||
|
import { useBulletinsStore } from '@/store';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const bulletinsStore = useBulletinsStore();
|
||||||
|
const renderData = ref<BulletinsRecord[]>([]);
|
||||||
|
|
||||||
|
// 获取公告列表
|
||||||
|
const fetchData = async (
|
||||||
|
params: BulletinsRecord = { current: 1 ,size: 5}
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const res = await bulletinsStore.getBulletinsList(params);
|
||||||
|
renderData.value = res.data.records;
|
||||||
|
} catch (err) {
|
||||||
|
// you can report use errorHandler or other
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchData();
|
||||||
|
|
||||||
|
|
||||||
|
const list = [
|
||||||
|
{
|
||||||
|
type: 'orangered',
|
||||||
|
label: '活动',
|
||||||
|
content: '内容最新优惠活动',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'cyan',
|
||||||
|
label: '消息',
|
||||||
|
content: '新增内容尚未通过审核,详情请点击查看。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'blue',
|
||||||
|
label: '通知',
|
||||||
|
content: '当前产品试用期即将结束,如需续费请点击查看。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'blue',
|
||||||
|
label: '通知',
|
||||||
|
content: '1月新系统升级计划通知',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'cyan',
|
||||||
|
label: '消息',
|
||||||
|
content: '新增内容已经通过审核,详情请点击查看。',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 4px;
|
||||||
|
color: var(--color-text-2);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
35
src/views/dashboard/workplace/components/quick-operation.vue
Normal file
35
src/views/dashboard/workplace/components/quick-operation.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<a-card
|
||||||
|
class="general-card"
|
||||||
|
:title="$t('workplace.quick.operation')"
|
||||||
|
:header-style="{ paddingBottom: '0' }"
|
||||||
|
:body-style="{ padding: '24px 20px 0 20px' }"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<a-link>{{ $t('workplace.quickOperation.setup') }}</a-link>
|
||||||
|
</template>
|
||||||
|
<a-row :gutter="8">
|
||||||
|
<a-col v-for="link in links" :key="link.text" :span="8" class="wrapper">
|
||||||
|
<div class="icon">
|
||||||
|
<component :is="link.icon" />
|
||||||
|
</div>
|
||||||
|
<a-typography-paragraph class="text">
|
||||||
|
{{ $t(link.text) }}
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-divider class="split-line" style="margin: 0" />
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const links = [
|
||||||
|
{ text: 'workplace.contentManagement', icon: 'icon-file' },
|
||||||
|
{ text: 'workplace.contentStatistical', icon: 'icon-storage' },
|
||||||
|
{ text: 'workplace.advanced', icon: 'icon-settings' },
|
||||||
|
{ text: 'workplace.onlinePromotion', icon: 'icon-mobile' },
|
||||||
|
{ text: 'workplace.contentPutIn', icon: 'icon-fire' },
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<a-card
|
||||||
|
class="general-card"
|
||||||
|
:title="$t('workplace.recently.visited')"
|
||||||
|
:header-style="{ paddingBottom: '0' }"
|
||||||
|
:body-style="{ paddingTop: '26px' }"
|
||||||
|
>
|
||||||
|
<div style="margin-bottom: -1rem">
|
||||||
|
<a-row :gutter="8">
|
||||||
|
<a-col v-for="link in links" :key="link.text" :span="8" class="wrapper">
|
||||||
|
<div class="icon">
|
||||||
|
<component :is="link.icon" />
|
||||||
|
</div>
|
||||||
|
<a-typography-paragraph class="text">
|
||||||
|
{{ $t(link.text) }}
|
||||||
|
</a-typography-paragraph>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const links = [
|
||||||
|
{
|
||||||
|
text: 'workplace.contentManagement',
|
||||||
|
icon: 'icon-storage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'workplace.contentStatistical',
|
||||||
|
icon: 'icon-file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'workplace.advanced',
|
||||||
|
icon: 'icon-settings',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
:deep(.arco-card-header-title) {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,70 +1,102 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-button
|
<div class="container">
|
||||||
type="outline"
|
<Breadcrumb :items="['物联网管理', '设备管理', '设备详情']" />
|
||||||
size="small"
|
<a-card class="general-card" title=" ">
|
||||||
status="success"
|
<a-descriptions v-model="renderData" size="large">
|
||||||
style="padding: 7px; margin-right: 10px"
|
<template #title><h3 style="margin-top: -15px">设备详情</h3></template>
|
||||||
@click="handleClick"
|
<a-descriptions-item label="设备名称">{{renderData.name }}</a-descriptions-item>
|
||||||
>
|
<a-descriptions-item label="硬件版本">{{renderData.hardwareVersion }}</a-descriptions-item>
|
||||||
<template #icon><icon-list /></template>
|
<a-descriptions-item label="固件版本">{{renderData.firmwareVersion }}</a-descriptions-item>
|
||||||
详情
|
<a-descriptions-item label="所属产品">{{renderData.productId }}</a-descriptions-item>
|
||||||
</a-button>
|
<!-- <a-descriptions-item label="备注">{{renderData.remark }}</a-descriptions-item>-->
|
||||||
|
<a-descriptions-item label="创建时间">{{dayjs(renderData.createTime).format('YYYY-MM-DD HH:mm:ss') }}</a-descriptions-item>
|
||||||
<a-modal
|
|
||||||
width="600px"
|
|
||||||
:visible="visible"
|
|
||||||
@cancel="handleCancel"
|
|
||||||
>
|
|
||||||
<template #title>设备详情</template>
|
|
||||||
<a-descriptions style="margin-top: 20px" :data="formData" size="large" :title=formData.name :column="1">
|
|
||||||
<a-descriptions-item label="产品名称">{{formData.productId}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="硬件版本">{{formData.hardwareVersion}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="固件版本">{{formData.firmwareVersion}}</a-descriptions-item>
|
|
||||||
<a-descriptions-item label="扩展属性">{{formData.extendParams}}</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
|
</a-card>
|
||||||
<template #footer>
|
<a-card class="general-card" style="margin-top: 10px">
|
||||||
<!-- <a-button class="editor-button" @click="handleCancel">取消</a-button>-->
|
<a-tabs :active-key="activeKey" @tab-click="handleMenuClick" style="padding-top: 20px">
|
||||||
<a-button class="editor-button" type="primary" @click="handleCancel">确定</a-button>
|
<a-tab-pane key="1" tab="参数" title="扩展属性">
|
||||||
</template>
|
<a-table :columns="columns" :data="renderData.extendParams" />
|
||||||
</a-modal>
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" tab="基本信息" title="基本信息">
|
||||||
|
基本信息
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="3" tab="执行服务" title="执行服务"> 执行服务内容 </a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import useVisible from '@/hooks/visible';
|
import dayjs from 'dayjs';
|
||||||
import { defineEmits, PropType, ref } from 'vue';
|
import { useRoute } from 'vue-router';
|
||||||
import { DeviceCreateRecord } from '@/api/device';
|
import { onMounted, ref } from 'vue';
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
import { queryDeviceDetail } from '@/api/device';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const props = defineProps({
|
const id = Number(route.params.id);
|
||||||
prem: {
|
const columns = [
|
||||||
type: Object as PropType<DeviceCreateRecord>,
|
{
|
||||||
|
title: '参数名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
},
|
},
|
||||||
isCreate: Boolean,
|
{
|
||||||
});
|
title: '参数标识',
|
||||||
const emit = defineEmits(['refresh']);
|
dataIndex: 'identifier',
|
||||||
const { visible, setVisible } = useVisible(false);
|
slotName: 'identifier',
|
||||||
|
},
|
||||||
const formData = ref<any>({
|
{
|
||||||
...props.prem,
|
title: '数据类型',
|
||||||
});
|
dataIndex: 'dataType',
|
||||||
|
slotName: 'dataType',
|
||||||
|
},
|
||||||
// 组件被点击
|
{
|
||||||
const handleClick = () => {
|
title: '参数类型',
|
||||||
setVisible(true);
|
dataIndex: 'type',
|
||||||
|
slotName: 'type',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const activeKey = ref('1');
|
||||||
|
const renderData = ref([]);
|
||||||
|
const fetchData = async (Id: number) => {
|
||||||
|
const res = await queryDeviceDetail(Id);
|
||||||
|
renderData.value = res.data;
|
||||||
};
|
};
|
||||||
|
const handleMenuClick = (e: any) => {
|
||||||
// 关闭
|
activeKey.value = e;
|
||||||
const handleCancel = async () => {
|
|
||||||
setVisible(false);
|
|
||||||
};
|
};
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData(id);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.editor-button{
|
.container {
|
||||||
position: static
|
padding: 0 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta span {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -82,13 +82,25 @@
|
|||||||
<a-form-item
|
<a-form-item
|
||||||
field="extendParams"
|
field="extendParams"
|
||||||
label="扩展属性"
|
label="扩展属性"
|
||||||
:rules="[{ required: true, message: '扩展属性不能为空' }]"
|
|
||||||
:validate-trigger="['change']"
|
|
||||||
>
|
>
|
||||||
<a-input
|
<!-- <a-input-->
|
||||||
v-model="formData.extendParams"
|
<!-- v-model="formData.extendParams"-->
|
||||||
placeholder='请输入扩展属性'
|
<!-- placeholder='请输入扩展属性'-->
|
||||||
/>
|
<!-- />-->
|
||||||
|
<div style="width: 100%">
|
||||||
|
<div style="width: 100%;margin-bottom: 5px; ">
|
||||||
|
<a-space v-for="(param,index) in paramsData" :key="index" style="margin-bottom: 5px">
|
||||||
|
<a-input v-model="param.name" placeholder="名称" allow-clear />
|
||||||
|
<a-input v-model="param.identifier" placeholder="标识" allow-clear />
|
||||||
|
<a-select v-model="param.dataType" :options="dataTypeOptions" allow-search />
|
||||||
|
<a-select v-model="param.type" :options="typeOptions" allow-search />
|
||||||
|
<a-button type="text" @click="handleDeleteParams(index)"><icon-minus-circle /></a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button @click="handleAddParams" style="width: 100%" >
|
||||||
|
<icon-plus />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
|
|
||||||
@ -108,6 +120,7 @@
|
|||||||
import { useMessageStore } from '@/store';
|
import { useMessageStore } from '@/store';
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
import '@wangeditor/editor/dist/css/style.css'
|
||||||
import { createDevice, updateDevice } from '@/api/device';
|
import { createDevice, updateDevice } from '@/api/device';
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prem: {
|
prem: {
|
||||||
@ -115,6 +128,58 @@
|
|||||||
},
|
},
|
||||||
isCreate: Boolean,
|
isCreate: Boolean,
|
||||||
});
|
});
|
||||||
|
const paramsData = ref([
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const dataTypeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '整型',
|
||||||
|
value: 'INT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '单精度浮点型',
|
||||||
|
value: 'FLOAT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '双精度浮点型',
|
||||||
|
value: 'DOUBLE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '布尔型',
|
||||||
|
value: 'BOOLEAN',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '字符串',
|
||||||
|
value: 'STRING',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '日期型',
|
||||||
|
value: 'DATE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '透传',
|
||||||
|
value: 'RAW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const typeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '物模型输入',
|
||||||
|
value: 'INPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '物模型输出',
|
||||||
|
value: 'OUTPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '读写属性',
|
||||||
|
value: 'RW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
const emit = defineEmits(['refresh']);
|
const emit = defineEmits(['refresh']);
|
||||||
const modalTitle = computed(() => {
|
const modalTitle = computed(() => {
|
||||||
return props.isCreate ? '创建设备' : '编辑设备';
|
return props.isCreate ? '创建设备' : '编辑设备';
|
||||||
@ -142,7 +207,22 @@
|
|||||||
options.value = []
|
options.value = []
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// 点击添加参数
|
||||||
|
const handleAddParams = () => {
|
||||||
|
// paramsVisible.value = true;
|
||||||
|
paramsData.value.push({
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 删除参数
|
||||||
|
const handleDeleteParams = (record: any) => {
|
||||||
|
if (record !== -1) {
|
||||||
|
paramsData.value.splice(record, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
// 组件被点击
|
// 组件被点击
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
@ -153,6 +233,7 @@
|
|||||||
const valid = await CreateRef.value?.validate();
|
const valid = await CreateRef.value?.validate();
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
// 新增
|
// 新增
|
||||||
|
formData.value.extendParams = paramsData.value;
|
||||||
if (props.isCreate) {
|
if (props.isCreate) {
|
||||||
// formData.value.username = formData.value.email;
|
// formData.value.username = formData.value.email;
|
||||||
const res = await createDevice(formData.value);
|
const res = await createDevice(formData.value);
|
||||||
|
@ -162,17 +162,16 @@
|
|||||||
{{ record.online == true? '是' : '否' }}
|
{{ record.online == true? '是' : '否' }}
|
||||||
</template>
|
</template>
|
||||||
<template #operations="{ record }">
|
<template #operations="{ record }">
|
||||||
<!-- <a-button-->
|
<a-button
|
||||||
<!-- type="outline"-->
|
type="outline"
|
||||||
<!-- size="small"-->
|
size="small"
|
||||||
<!-- status="success"-->
|
status="success"
|
||||||
<!-- style="padding: 7px; margin-right: 10px"-->
|
style="padding: 7px; margin-right: 10px"
|
||||||
<!-- @click="openDetail(record.id)"-->
|
@click="openDetail(record.id)"
|
||||||
<!-- >-->
|
>
|
||||||
<!-- <template #icon><icon-list /></template>-->
|
<template #icon><icon-list /></template>
|
||||||
<!-- 详情-->
|
详情
|
||||||
<!-- </a-button>-->
|
</a-button>
|
||||||
<DeviceDetail :prem="record" />
|
|
||||||
<DeviceEdit
|
<DeviceEdit
|
||||||
ref="editUserRef"
|
ref="editUserRef"
|
||||||
:prem="record"
|
:prem="record"
|
||||||
@ -338,7 +337,7 @@
|
|||||||
// 打开详情
|
// 打开详情
|
||||||
function openDetail(id:number): void{
|
function openDetail(id:number): void{
|
||||||
const url = router.resolve({
|
const url = router.resolve({
|
||||||
name: 'Detail',
|
name: 'deviceDetail',
|
||||||
params: {id}
|
params: {id}
|
||||||
}).href;
|
}).href;
|
||||||
router.push(url);
|
router.push(url);
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<Breadcrumb :items="['物联网管理', '产品管理','产品详情']" />
|
<Breadcrumb :items="['物联网管理', '产品管理', '产品详情']" />
|
||||||
<a-card class="general-card" title=" ">
|
<a-card class="general-card" title=" ">
|
||||||
<div class="announcement-detail">
|
<a-descriptions v-model="renderData" size="large">
|
||||||
<a-descriptions :data="renderData" size="large" title="产品详情" bordered >
|
<template #title><h3 style="margin-top: -15px">产品详情</h3></template>
|
||||||
<a-descriptions-item label="产品名称">{{renderData.name}}</a-descriptions-item>
|
<a-descriptions-item label="产品名称">{{renderData.name }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="产品类型">{{renderData.productType}}</a-descriptions-item>
|
<a-descriptions-item label="产品类型">{{renderData.productType }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="产品型号">{{renderData.model}}</a-descriptions-item>
|
<a-descriptions-item label="产品型号">{{renderData.model }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="通讯协议">{{renderData.link}}</a-descriptions-item>
|
<a-descriptions-item label="通讯协议">{{renderData.link }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="备注">{{renderData.remark}}</a-descriptions-item>
|
<a-descriptions-item label="备注">{{renderData.remark }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="创建时间">{{dayjs(renderData.createTime).format('YYYY-MM-DD HH:mm:ss')}}</a-descriptions-item>
|
<a-descriptions-item label="创建时间">{{dayjs(renderData.createTime).format('YYYY-MM-DD HH:mm:ss') }}</a-descriptions-item>
|
||||||
<a-descriptions-item label="扩展属性">
|
|
||||||
<a-table :columns="columns" :data="renderData.params" row-key="id" :pagination="false"/>
|
|
||||||
</a-descriptions-item>
|
|
||||||
</a-descriptions>
|
</a-descriptions>
|
||||||
</div>
|
</a-card>
|
||||||
|
<a-card class="general-card" style="margin-top: 10px">
|
||||||
|
<a-tabs :active-key="activeKey" @tab-click="handleMenuClick" style="padding-top: 20px">
|
||||||
|
<a-tab-pane key="1" tab="参数" title="参数">
|
||||||
|
<a-table :columns="columns" :data="renderData.params" />
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" tab="基本信息" title="基本信息">
|
||||||
|
基本信息
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="3" tab="执行服务" title="执行服务"> 执行服务内容 </a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -27,7 +34,7 @@
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = Number(route.params.id);
|
const id = Number(route.params.id);
|
||||||
const columns=[
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '参数名称',
|
title: '参数名称',
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
@ -49,72 +56,34 @@
|
|||||||
slotName: 'type',
|
slotName: 'type',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const renderData = ref<any>(
|
const activeKey = ref('1');
|
||||||
{
|
const renderData = ref([]);
|
||||||
name: '产品名称',
|
const fetchData = async (Id: number) => {
|
||||||
productType: '设备',
|
const res = await queryProductDetail(Id);
|
||||||
model: '123456',
|
renderData.value = res.data;
|
||||||
link: 'TCP',
|
};
|
||||||
remark: '123456',
|
const handleMenuClick = (e: any) => {
|
||||||
createTime: '2023-08-08 10:10:10',
|
activeKey.value = e;
|
||||||
params:[
|
};
|
||||||
{
|
onMounted(() => {
|
||||||
name:'设备名称',
|
fetchData(id);
|
||||||
identifier:'1.0.0',
|
});
|
||||||
dataType:'1.0.0',
|
|
||||||
type:'123456',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name:'设备名称',
|
|
||||||
identifier:'1.0.0',
|
|
||||||
dataType:'1.0.0',
|
|
||||||
type:'123456',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name:'设备名称',
|
|
||||||
identifier:'1.0.0',
|
|
||||||
dataType:'1.0.0',
|
|
||||||
type:'123456',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
);
|
|
||||||
// const fetchData = async (Id: number) => {
|
|
||||||
// const res = await queryProductDetail(Id);
|
|
||||||
// renderData.value = res.data;
|
|
||||||
// };
|
|
||||||
// onMounted(() => {
|
|
||||||
// fetchData(id);
|
|
||||||
// });
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.container {
|
.container {
|
||||||
padding: 0 20px 20px 20px;
|
padding: 0 20px 20px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.announcement-detail {
|
|
||||||
min-width: 800px;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: auto;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: #fff; /* 白色背景,与淡蓝色背景区分开来 */
|
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.meta span {
|
.meta span {
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.attachments li {
|
.attachments li {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
@ -131,5 +100,3 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
445
src/views/iot/product/components/product-edit.vue
Normal file
445
src/views/iot/product/components/product-edit.vue
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
<template>
|
||||||
|
<a-button v-if="props.isCreate" type="primary" @click="handleClick">
|
||||||
|
<template #icon><icon-plus /></template>
|
||||||
|
新建
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
v-if="!props.isCreate"
|
||||||
|
type="outline"
|
||||||
|
size="small"
|
||||||
|
:style="{ marginRight: '10px', padding: '7px' }"
|
||||||
|
@click="handleClick"
|
||||||
|
>
|
||||||
|
<template #icon><icon-edit /></template>
|
||||||
|
修改
|
||||||
|
</a-button>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="900px"
|
||||||
|
height="500px"
|
||||||
|
:visible="visible"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>{{ modalTitle }}</template>
|
||||||
|
<a-form
|
||||||
|
ref="CreateRef"
|
||||||
|
:model="formData"
|
||||||
|
:style="{ width: '800px',height: '420px' }"
|
||||||
|
>
|
||||||
|
<!-- 产品名称 -->
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
label='产品名称'
|
||||||
|
:rules="[{ required: true, message: '产品名称不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="formData.name"
|
||||||
|
placeholder='请输入产品名称'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 产品分类-->
|
||||||
|
<a-form-item
|
||||||
|
field="productType"
|
||||||
|
label="产品分类"
|
||||||
|
:rules="[{ required: true, message: '产品分类不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="formData.productType"
|
||||||
|
placeholder='请选择产品分类'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 产品类型 -->
|
||||||
|
<a-form-item
|
||||||
|
field="model"
|
||||||
|
label="类型"
|
||||||
|
:rules="[{ required: true, message: '产品类型不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="formData.model"
|
||||||
|
placeholder='请输入产品类型'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 接入方式 -->
|
||||||
|
<a-form-item
|
||||||
|
field="link"
|
||||||
|
label="接入"
|
||||||
|
:rules="[{ required: true, message: '接入方式不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="formData.link"
|
||||||
|
placeholder='请输入接入方式'
|
||||||
|
:options="linkOptions"
|
||||||
|
allow-search
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 备注 -->
|
||||||
|
<a-form-item
|
||||||
|
field="remark"
|
||||||
|
label="备注"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="formData.remark"
|
||||||
|
placeholder='请输入备注'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 参数 -->
|
||||||
|
<a-form-item
|
||||||
|
field="params"
|
||||||
|
label="参数"
|
||||||
|
>
|
||||||
|
<!-- <a-table-->
|
||||||
|
<!-- :columns="columns"-->
|
||||||
|
<!-- :data="paramsData"-->
|
||||||
|
<!-- :bordered="false"-->
|
||||||
|
<!-- :pagination="false"-->
|
||||||
|
<!-- :table-layout-fixed="true"-->
|
||||||
|
<!-- :show-header="false"-->
|
||||||
|
<!-- :hoverable="false"-->
|
||||||
|
<!-- :column-resizable="true"-->
|
||||||
|
<!-- :filter-icon-align-left="true"-->
|
||||||
|
<!-- :body-cell-class="{ padding: '0px',marginLeft: '-10px' }"-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- <template #name="{ record }">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- v-model="record.name"-->
|
||||||
|
<!-- placeholder="名称"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <template #identifier="{ record }">-->
|
||||||
|
<!-- <a-input-->
|
||||||
|
<!-- v-model="record.identifier"-->
|
||||||
|
<!-- placeholder="标识"-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <template #dataType="{ record }">-->
|
||||||
|
<!-- <a-select-->
|
||||||
|
<!-- v-model="record.dataType"-->
|
||||||
|
<!-- :options="dataTypeOptions"-->
|
||||||
|
<!-- allow-search-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <template #type="{ record }">-->
|
||||||
|
<!-- <a-select-->
|
||||||
|
<!-- v-model="record.type"-->
|
||||||
|
<!-- :options="typeOptions"-->
|
||||||
|
<!-- allow-search-->
|
||||||
|
<!-- />-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <template #operation="{ record }">-->
|
||||||
|
<!-- <a-button type="text" @click="handleDeleteParams(record)"><icon-minus-circle /></a-button>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <template #footer>-->
|
||||||
|
<!-- <a-button @click="handleAddParams" style="width: 100%" >-->
|
||||||
|
<!-- <icon-plus />-->
|
||||||
|
<!-- </a-button>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </a-table>-->
|
||||||
|
<div style="width: 100%">
|
||||||
|
<div style="width: 100%;margin-bottom: 5px; ">
|
||||||
|
<a-space v-for="(param,index) in paramsData" :key="index" style="margin-bottom: 5px">
|
||||||
|
<a-input v-model="param.name" placeholder="名称" allow-clear />
|
||||||
|
<a-input v-model="param.identifier" placeholder="标识" allow-clear />
|
||||||
|
<a-select v-model="param.dataType" :options="dataTypeOptions" allow-search />
|
||||||
|
<a-select v-model="param.type" :options="typeOptions" allow-search />
|
||||||
|
<a-button type="text" @click="handleDeleteParams(index)"><icon-minus-circle /></a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button @click="handleAddParams" style="width: 100%" type="outline">
|
||||||
|
<icon-plus />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<a-button class="editor-button" @click="handleCancel">取消</a-button>
|
||||||
|
<a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="900px"
|
||||||
|
:visible="paramsVisible"
|
||||||
|
@cancel="paramsCancel"
|
||||||
|
>
|
||||||
|
<template #title>添加参数</template>
|
||||||
|
<a-form
|
||||||
|
ref="CreateRef"
|
||||||
|
:model="paramsData"
|
||||||
|
:style="{ width: '650px' }"
|
||||||
|
>
|
||||||
|
<!-- 添加参数 -->
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
label="参数名称"
|
||||||
|
:rules="[{ required: true, message: '参数名称不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="paramsData.name"
|
||||||
|
placeholder='请选择参数名称'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 参数标识 -->
|
||||||
|
<a-form-item
|
||||||
|
field="identifier"
|
||||||
|
label="参数标识"
|
||||||
|
:rules="[{ required: true, message: '参数标识不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="paramsData.identifier"
|
||||||
|
placeholder='请选择参数标识'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item
|
||||||
|
field="dataType"
|
||||||
|
label="数据类型"
|
||||||
|
:rules="[{ required: true, message: '数据类型不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="paramsData.dataType"
|
||||||
|
placeholder='请输入数据类型'
|
||||||
|
:options="dataTypeOptions"
|
||||||
|
allow-search
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
field="type"
|
||||||
|
label="参数类型"
|
||||||
|
:rules="[{ required: true, message: '参数类型不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="paramsData.type"
|
||||||
|
placeholder='请输入参数类型'
|
||||||
|
:options="typeOptions"
|
||||||
|
allow-search
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<a-button class="editor-button" @click="paramsCancel">取消</a-button>
|
||||||
|
<a-button class="editor-button" type="primary" @click="paramsSubmit">确定</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import { computed, defineEmits, onMounted, PropType, ref } from 'vue';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
import '@wangeditor/editor/dist/css/style.css'
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
import { createProduct, ProductCreateRecord, queryProductDetail, updateProduct } from '@/api/product';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
prem: {
|
||||||
|
type: Object as PropType<ProductCreateRecord>,
|
||||||
|
},
|
||||||
|
isCreate: Boolean,
|
||||||
|
id: Number,
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
const modalTitle = computed(() => {
|
||||||
|
return props.isCreate ? '创建产品' : '编辑产品';
|
||||||
|
});
|
||||||
|
const { visible, setVisible } = useVisible(false);
|
||||||
|
const CreateRef = ref<FormInstance>();
|
||||||
|
const formData = ref<any>({
|
||||||
|
// params: [],
|
||||||
|
// ...props.prem,
|
||||||
|
});
|
||||||
|
const columns=[
|
||||||
|
{
|
||||||
|
title: '参数名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
width: '120',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '参数标识',
|
||||||
|
dataIndex: 'identifier',
|
||||||
|
slotName: 'identifier',
|
||||||
|
width: '120',
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数据类型',
|
||||||
|
dataIndex: 'dataType',
|
||||||
|
slotName: 'dataType',
|
||||||
|
width: '150',
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '参数类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
slotName: 'type',
|
||||||
|
width: '180',
|
||||||
|
align: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
align: 'left'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const paramsData = ref([
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const linkOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: 'TCP',
|
||||||
|
value: 'TCP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'HTTP',
|
||||||
|
value: 'HTTP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'MQTT',
|
||||||
|
value: 'MQTT',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const dataTypeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '整型',
|
||||||
|
value: 'INT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '单精度浮点型',
|
||||||
|
value: 'FLOAT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '双精度浮点型',
|
||||||
|
value: 'DOUBLE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '布尔型',
|
||||||
|
value: 'BOOLEAN',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '字符串',
|
||||||
|
value: 'STRING',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '日期型',
|
||||||
|
value: 'DATE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '透传',
|
||||||
|
value: 'RAW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const typeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '物模型输入',
|
||||||
|
value: 'INPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '物模型输出',
|
||||||
|
value: 'OUTPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '读写属性',
|
||||||
|
value: 'RW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const paramsVisible = ref(false);
|
||||||
|
const paramsName = ref([]);
|
||||||
|
const fetchData = async (Id: number | undefined) => {
|
||||||
|
const res = await queryProductDetail(Id);
|
||||||
|
formData.value = res.data;
|
||||||
|
};
|
||||||
|
// 组件被点击
|
||||||
|
const handleClick = () => {
|
||||||
|
setVisible(true);
|
||||||
|
if (!props.isCreate) {
|
||||||
|
fetchData(props.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 提交
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
const valid = await CreateRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
// 新增
|
||||||
|
if (props.isCreate) {
|
||||||
|
formData.value.params = paramsData.value;
|
||||||
|
// formData.value.username = formData.value.email;
|
||||||
|
const res = await createProduct(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '新建成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
emit('refresh');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
CreateRef.value?.resetFields();
|
||||||
|
} else {
|
||||||
|
// 编辑
|
||||||
|
const res = await updateProduct(formData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '修改成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
emit('refresh');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击添加参数
|
||||||
|
const handleAddParams = () => {
|
||||||
|
// paramsVisible.value = true;
|
||||||
|
paramsData.value.push({
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 删除参数
|
||||||
|
const handleDeleteParams = (record: any) => {
|
||||||
|
if (record !== -1) {
|
||||||
|
paramsData.value.splice(record, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 点击取消
|
||||||
|
const paramsCancel = () => {
|
||||||
|
paramsVisible.value = false;
|
||||||
|
};
|
||||||
|
// 参数模态框提交
|
||||||
|
const paramsSubmit = () => {
|
||||||
|
paramsVisible.value = false;
|
||||||
|
formData.value.params.push(paramsData.value);
|
||||||
|
paramsName.value.push(paramsData.value.name);
|
||||||
|
}
|
||||||
|
// 关闭
|
||||||
|
const handleCancel = async () => {
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.editor-button{
|
||||||
|
position: static
|
||||||
|
}
|
||||||
|
</style>
|
648
src/views/iot/product/components/product-tsl.vue
Normal file
648
src/views/iot/product/components/product-tsl.vue
Normal file
@ -0,0 +1,648 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<Breadcrumb :items="['物联网管理', '产品管理', '物模型']" />
|
||||||
|
<a-card class="general-card" title=" " style="height: 50px">
|
||||||
|
<h3 style="margin-top: -24px">物模型</h3>
|
||||||
|
</a-card>
|
||||||
|
<a-card class="general-card" style="margin-top: 10px;padding-top: 20px">
|
||||||
|
<a-tabs type="rounded" position="left" size="large" @change="changeKey" animation style="">
|
||||||
|
<a-tab-pane key="1" title="属性">
|
||||||
|
<a-button type="primary" style="margin-bottom: 10px" @click="handleClick">
|
||||||
|
<template #icon><icon-plus /></template>
|
||||||
|
新建
|
||||||
|
</a-button>
|
||||||
|
<a-table :columns="columns" :data="propertyData" >
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<a-button
|
||||||
|
type="outline"
|
||||||
|
status="danger"
|
||||||
|
size="small"
|
||||||
|
style="padding: 7px;margin-right: 10px"
|
||||||
|
@click="handleDeleteProperty(record)"
|
||||||
|
>
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" title="服务">
|
||||||
|
<a-button type="primary" style="margin-bottom: 10px" @click="handleClick">
|
||||||
|
<template #icon><icon-plus /></template>
|
||||||
|
新建
|
||||||
|
</a-button>
|
||||||
|
<a-table :columns="columns" :data="serveData" >
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<a-button
|
||||||
|
type="outline"
|
||||||
|
status="danger"
|
||||||
|
size="small"
|
||||||
|
style="padding: 7px;margin-right: 10px"
|
||||||
|
@click="handleDeleteServe(record)"
|
||||||
|
>
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="3" title="事件">
|
||||||
|
<a-button type="primary" style="margin-bottom: 10px" @click="handleClick">
|
||||||
|
<template #icon><icon-plus /></template>
|
||||||
|
新建
|
||||||
|
</a-button>
|
||||||
|
<a-table :columns="columns" :data="eventData" >
|
||||||
|
<template #operation="{ record }">
|
||||||
|
<a-button
|
||||||
|
type="outline"
|
||||||
|
status="danger"
|
||||||
|
size="small"
|
||||||
|
style="padding: 7px;margin-right: 10px"
|
||||||
|
@click="handleDeleteEvent(record)"
|
||||||
|
>
|
||||||
|
<template #icon><icon-delete /></template>
|
||||||
|
删除
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="900px"
|
||||||
|
height="500px"
|
||||||
|
:visible="visible && keyValue==='1'"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>新建属性</template>
|
||||||
|
<a-form
|
||||||
|
ref="propertyCreateRef"
|
||||||
|
:model="propertyAddData"
|
||||||
|
:style="{ width: '650px' }"
|
||||||
|
>
|
||||||
|
<!-- 设备名称 -->
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
label="属性名称"
|
||||||
|
:rules="[{ required: true, message: '设备名称不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="propertyAddData.name"
|
||||||
|
placeholder='请输入设备名称'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 标识 -->
|
||||||
|
<a-form-item
|
||||||
|
field="identifier"
|
||||||
|
label="标识"
|
||||||
|
:rules="[{ required: true, message: '标识不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="propertyAddData.identifier"
|
||||||
|
placeholder='请输入标识'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 数据类型 -->
|
||||||
|
<a-form-item
|
||||||
|
field="dataType"
|
||||||
|
label="数据类型"
|
||||||
|
:rules="[{ required: true, message: '数据类型不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-select v-model="propertyAddData.dataType" :options="dataTypeOptions" allow-search placeholder="请选择数据类型"/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 读写类型 -->
|
||||||
|
<a-form-item
|
||||||
|
field="ioType"
|
||||||
|
label="读写类型"
|
||||||
|
>
|
||||||
|
<a-radio-group v-model="propertyAddData.ioType">
|
||||||
|
<a-radio value="1">读写</a-radio>
|
||||||
|
<a-radio value="2">只读</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 备注 -->
|
||||||
|
<a-form-item
|
||||||
|
field="remark"
|
||||||
|
label="备注"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
v-model="propertyAddData.remark"
|
||||||
|
placeholder='请输入备注'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<a-button class="editor-button" @click="handleCancel">取消</a-button>
|
||||||
|
<a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="900px"
|
||||||
|
height="500px"
|
||||||
|
:visible="visible && keyValue==='2'"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>新建服务</template>
|
||||||
|
<a-form
|
||||||
|
ref="serveCreateRef"
|
||||||
|
:model="serveAddData"
|
||||||
|
:style="{ width: '650px' }"
|
||||||
|
>
|
||||||
|
<!-- 服务名称 -->
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
label="服务名称"
|
||||||
|
:rules="[{ required: true, message: '服务名称不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="serveAddData.name"
|
||||||
|
placeholder='请输入服务名称'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 标识 -->
|
||||||
|
<a-form-item
|
||||||
|
field="identifier"
|
||||||
|
label="标识"
|
||||||
|
:rules="[{ required: true, message: '标识不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="serveAddData.identifier"
|
||||||
|
placeholder='请输入标识'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 输入参数 -->
|
||||||
|
<a-form-item
|
||||||
|
field="inputs"
|
||||||
|
label="输入参数"
|
||||||
|
>
|
||||||
|
<div style="width: 100%">
|
||||||
|
<div style="width: 100%;margin-bottom: 5px; ">
|
||||||
|
<a-space v-for="(param,index) in serveInputData" :key="index" style="margin-bottom: 5px">
|
||||||
|
<a-input v-model="param.name" placeholder="名称" allow-clear />
|
||||||
|
<a-input v-model="param.identifier" placeholder="标识" allow-clear />
|
||||||
|
<a-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型" />
|
||||||
|
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型"/>
|
||||||
|
<a-button type="text" @click="handleDeleteParams(index,'serveInputData')"><icon-minus-circle /></a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button @click="handleAddParams('serveInputData')" style="width: 100%" type="outline">
|
||||||
|
<icon-plus />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 输出参数 -->
|
||||||
|
<a-form-item
|
||||||
|
field="outputs"
|
||||||
|
label="输出参数"
|
||||||
|
>
|
||||||
|
<div style="width: 100%">
|
||||||
|
<div style="width: 100%;margin-bottom: 5px; ">
|
||||||
|
<a-space v-for="(param,index) in serveOutputData" :key="index" style="margin-bottom: 5px">
|
||||||
|
<a-input v-model="param.name" placeholder="名称" allow-clear />
|
||||||
|
<a-input v-model="param.identifier" placeholder="标识" allow-clear />
|
||||||
|
<a-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型"/>
|
||||||
|
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型"/>
|
||||||
|
<a-button type="text" @click="handleDeleteParams(index,'serveOutputData')"><icon-minus-circle /></a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button @click="handleAddParams('serveOutputData')" style="width: 100%" type="outline">
|
||||||
|
<icon-plus />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 备注 -->
|
||||||
|
<a-form-item
|
||||||
|
field="remark"
|
||||||
|
label="备注"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
v-model="serveInputData.remark"
|
||||||
|
placeholder='请输入备注'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<a-button class="editor-button" @click="handleCancel">取消</a-button>
|
||||||
|
<a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<a-modal
|
||||||
|
width="900px"
|
||||||
|
height="500px"
|
||||||
|
:visible="visible && keyValue==='3'"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
>
|
||||||
|
<template #title>新建事件</template>
|
||||||
|
<a-form
|
||||||
|
ref="eventCreateRef"
|
||||||
|
:model="eventAddData"
|
||||||
|
:style="{ width: '650px' }"
|
||||||
|
>
|
||||||
|
<!-- 事件名称 -->
|
||||||
|
<a-form-item
|
||||||
|
field="name"
|
||||||
|
label="服务名称"
|
||||||
|
:rules="[{ required: true, message: '服务名称不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="eventAddData.name"
|
||||||
|
placeholder='请输入服务名称'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 标识 -->
|
||||||
|
<a-form-item
|
||||||
|
field="identifier"
|
||||||
|
label="标识"
|
||||||
|
:rules="[{ required: true, message: '标识不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="eventAddData.identifier"
|
||||||
|
placeholder='请输入标识'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 类型 -->
|
||||||
|
<a-form-item
|
||||||
|
field="type"
|
||||||
|
label="类型"
|
||||||
|
:rules="[{ required: true, message: '类型不能为空' }]"
|
||||||
|
:validate-trigger="['change']"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="eventAddData.type"
|
||||||
|
placeholder='请输入类型'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 输出参数 -->
|
||||||
|
<a-form-item
|
||||||
|
field="outputs"
|
||||||
|
label="输出参数"
|
||||||
|
>
|
||||||
|
<div style="width: 100%">
|
||||||
|
<div style="width: 100%;margin-bottom: 5px; ">
|
||||||
|
<a-space v-for="(param,index) in eventOutputData" :key="index" style="margin-bottom: 5px">
|
||||||
|
<a-input v-model="param.name" placeholder="名称" allow-clear />
|
||||||
|
<a-input v-model="param.identifier" placeholder="标识" allow-clear />
|
||||||
|
<a-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型"/>
|
||||||
|
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型"/>
|
||||||
|
<a-button type="text" @click="handleDeleteParams(index,'eventOutputData')"><icon-minus-circle /></a-button>
|
||||||
|
</a-space>
|
||||||
|
</div>
|
||||||
|
<a-button @click="handleAddParams('eventOutputData')" style="width: 100%" type="outline">
|
||||||
|
<icon-plus />
|
||||||
|
</a-button>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<!-- 备注 -->
|
||||||
|
<a-form-item
|
||||||
|
field="remark"
|
||||||
|
label="备注"
|
||||||
|
>
|
||||||
|
<a-textarea
|
||||||
|
v-model="eventAddData.remark"
|
||||||
|
placeholder='请输入备注'
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<template #footer>
|
||||||
|
<a-button class="editor-button" @click="handleCancel">取消</a-button>
|
||||||
|
<a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button>
|
||||||
|
</template>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
import useVisible from '@/hooks/visible';
|
||||||
|
import {
|
||||||
|
createEvent,
|
||||||
|
createProperty,
|
||||||
|
createServe,
|
||||||
|
deleteEvent,
|
||||||
|
deleteProperty,
|
||||||
|
deleteServe,
|
||||||
|
queryEventList,
|
||||||
|
queryPropertyList,
|
||||||
|
queryServeList
|
||||||
|
} from '@/api/tsl';
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
const { visible, setVisible } = useVisible();
|
||||||
|
const route = useRoute();
|
||||||
|
const id = Number(route.params.id);
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
slotName: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '标识',
|
||||||
|
dataIndex: 'identifier',
|
||||||
|
slotName: 'identifier',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remark',
|
||||||
|
slotName: 'remark',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'operation',
|
||||||
|
slotName: 'operation',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const serveData = ref([]);
|
||||||
|
const propertyData = ref([]);
|
||||||
|
const eventData = ref([]);
|
||||||
|
const keyValue = ref('1');
|
||||||
|
const paramsData = ref([]);
|
||||||
|
const dataTypeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '整型',
|
||||||
|
value: 'INT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '单精度浮点型',
|
||||||
|
value: 'FLOAT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '双精度浮点型',
|
||||||
|
value: 'DOUBLE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '布尔型',
|
||||||
|
value: 'BOOLEAN',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '字符串',
|
||||||
|
value: 'STRING',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '日期型',
|
||||||
|
value: 'DATE',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '透传',
|
||||||
|
value: 'RAW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const typeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: '物模型输入',
|
||||||
|
value: 'INPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '物模型输出',
|
||||||
|
value: 'OUTPUT',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '读写属性',
|
||||||
|
value: 'RW',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const propertyAddData = ref({
|
||||||
|
productId:id,
|
||||||
|
});
|
||||||
|
const eventAddData = ref({
|
||||||
|
productId:id,
|
||||||
|
outputs: [{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
const serveAddData = ref({
|
||||||
|
productId:id,
|
||||||
|
inputs: [{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}],
|
||||||
|
outputs: [{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
const serveInputData = ref([{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}]);
|
||||||
|
const serveOutputData = ref([{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}]);
|
||||||
|
const eventOutputData = ref([{
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
}]);
|
||||||
|
const propertyCreateRef = ref<FormInstance>();
|
||||||
|
const eventCreateRef = ref<FormInstance>();
|
||||||
|
const serveCreateRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
const fetchData = async (Id: number) => {
|
||||||
|
const params={
|
||||||
|
size:10,
|
||||||
|
current:1,
|
||||||
|
productId:Id,
|
||||||
|
}
|
||||||
|
const res1 = await queryServeList(params);
|
||||||
|
serveData.value = res1.data.records;
|
||||||
|
const res2 = await queryPropertyList(params);
|
||||||
|
propertyData.value = res2.data.records;
|
||||||
|
const res3 = await queryEventList(params);
|
||||||
|
eventData.value = res3.data.records;
|
||||||
|
};
|
||||||
|
const changeKey= (e:any) =>{
|
||||||
|
keyValue.value = e;
|
||||||
|
}
|
||||||
|
// 组件被点击
|
||||||
|
const handleClick = () => {
|
||||||
|
setVisible(true);
|
||||||
|
};
|
||||||
|
// 关闭
|
||||||
|
const handleCancel = async () => {
|
||||||
|
setVisible(false);
|
||||||
|
};
|
||||||
|
// 确定
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
|
||||||
|
if(keyValue.value==='1'){
|
||||||
|
const valid = await propertyCreateRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
const res = await createProperty(propertyAddData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '新建成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(keyValue.value==='2') {
|
||||||
|
const valid = await serveCreateRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
serveAddData.value.inputs = serveInputData.value;
|
||||||
|
serveAddData.value.outputs = serveOutputData.value;
|
||||||
|
const res = await createServe(serveAddData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '新建成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(keyValue.value==='3') {
|
||||||
|
const valid = await eventCreateRef.value?.validate();
|
||||||
|
if (!valid) {
|
||||||
|
eventAddData.value.outputs = eventOutputData.value;
|
||||||
|
const res = await createEvent(eventAddData.value);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '新建成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
// 删除参数
|
||||||
|
const handleDeleteParams = (record: any,data: string) => {
|
||||||
|
console.log(record);
|
||||||
|
if (record !== -1 && data==='serveInputData') {
|
||||||
|
serveInputData.value.splice(record, 1);
|
||||||
|
} else if (record!== -1 && data==='serveOutputData') {
|
||||||
|
serveOutputData.value.splice(record, 1);
|
||||||
|
} else if (record!== -1 && data==='eventOutputData') {
|
||||||
|
eventOutputData.value.splice(record, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 点击添加参数
|
||||||
|
const handleAddParams = (data:string) => {
|
||||||
|
console.log(data);
|
||||||
|
if(data==='serveInputData'){
|
||||||
|
serveInputData.value.push({
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
}else if(data==='serveOutputData') {
|
||||||
|
serveOutputData.value.push({
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
} else if(data==='eventOutputData') {
|
||||||
|
eventOutputData.value.push({
|
||||||
|
name: '',
|
||||||
|
identifier: '',
|
||||||
|
dataType: '',
|
||||||
|
type: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 删除属性
|
||||||
|
const handleDeleteProperty = async (record: any) => {
|
||||||
|
const res = await deleteProperty(record.id);
|
||||||
|
console.log(res);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '删除成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 删除服务
|
||||||
|
const handleDeleteServe = async (record: any) => {
|
||||||
|
console.log(record);
|
||||||
|
const res = await deleteServe(record.id);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '删除成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 删除事件
|
||||||
|
const handleDeleteEvent = async (record: any) => {
|
||||||
|
const res = await deleteEvent(record.id);
|
||||||
|
if (res.status === 200) {
|
||||||
|
Message.success({
|
||||||
|
content: '删除成功',
|
||||||
|
duration: 5 * 1000,
|
||||||
|
});
|
||||||
|
await fetchData(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchData(id);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
padding: 0 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta span {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments li {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #1890ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachments a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
@ -172,6 +172,16 @@
|
|||||||
<template #icon><icon-list /></template>
|
<template #icon><icon-list /></template>
|
||||||
详情
|
详情
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="outline"
|
||||||
|
size="small"
|
||||||
|
status="warning"
|
||||||
|
style="padding: 7px; margin-right: 10px"
|
||||||
|
@click="openTsl(record.id)"
|
||||||
|
>
|
||||||
|
<template #icon><icon-list /></template>
|
||||||
|
物模型
|
||||||
|
</a-button>
|
||||||
<ProductEdit
|
<ProductEdit
|
||||||
:id="record.id"
|
:id="record.id"
|
||||||
ref="editUserRef"
|
ref="editUserRef"
|
||||||
@ -339,6 +349,15 @@
|
|||||||
router.push(url);
|
router.push(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 打开物模型
|
||||||
|
function openTsl(id:number): void{
|
||||||
|
const url = router.resolve({
|
||||||
|
name: 'productTsl',
|
||||||
|
params: {id}
|
||||||
|
}).href;
|
||||||
|
router.push(url);
|
||||||
|
};
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
const res = await deleteProduct(id);
|
const res = await deleteProduct(id);
|
||||||
|
@ -134,11 +134,12 @@
|
|||||||
<a-card style="margin-right: 10px;width: 30%">
|
<a-card style="margin-right: 10px;width: 30%">
|
||||||
<a-tree
|
<a-tree
|
||||||
:data="deptTreeData"
|
:data="deptTreeData"
|
||||||
checkable="true"
|
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
||||||
style="margin-bottom: 8px; max-width: 240px"
|
style="margin-bottom: 8px; max-width: 240px"
|
||||||
@select="handleClickTree"
|
@select="handleClickTree"
|
||||||
@check="handleCheckTree"
|
@check="handleCheckTree"
|
||||||
/>
|
>
|
||||||
|
</a-tree>
|
||||||
</a-card>
|
</a-card>
|
||||||
<a-card style="flex: 1">
|
<a-card style="flex: 1">
|
||||||
<a-button type="primary" >全选</a-button>
|
<a-button type="primary" >全选</a-button>
|
||||||
@ -146,11 +147,11 @@
|
|||||||
:data="selectedDepartmentMembers"
|
:data="selectedDepartmentMembers"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
style="height: 520px">
|
style="height: 520px">
|
||||||
<template #key="{ record }">
|
<template #id="{ record }">
|
||||||
<a-checkbox v-model="selectedIds" :value="record.key"> </a-checkbox>
|
<a-checkbox v-model="selectedIds" :value="record.id"> </a-checkbox>
|
||||||
</template>
|
</template>
|
||||||
<template #title="{ record }">
|
<template #username="{ record }">
|
||||||
{{ record.title }}
|
{{ record.username }}
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
</a-card>
|
</a-card>
|
||||||
@ -165,7 +166,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import useVisible from '@/hooks/visible';
|
import useVisible from '@/hooks/visible';
|
||||||
import { computed, defineEmits, PropType, ref, shallowRef, onBeforeUnmount, reactive } from 'vue';
|
import { computed, defineEmits, PropType, ref, shallowRef, onBeforeUnmount, reactive, onMounted } from 'vue';
|
||||||
import { CreateRecord } from '@/api/user';
|
import { CreateRecord } from '@/api/user';
|
||||||
import { FormInstance } from '@arco-design/web-vue/es/form';
|
import { FormInstance } from '@arco-design/web-vue/es/form';
|
||||||
import { Message } from '@arco-design/web-vue';
|
import { Message } from '@arco-design/web-vue';
|
||||||
@ -174,6 +175,7 @@
|
|||||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||||
import { IEditorConfig } from '@wangeditor/editor'
|
import { IEditorConfig } from '@wangeditor/editor'
|
||||||
import '@wangeditor/editor/dist/css/style.css'
|
import '@wangeditor/editor/dist/css/style.css'
|
||||||
|
import { getAllDeptTree } from '@/api/dept';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
prem: {
|
prem: {
|
||||||
@ -205,12 +207,12 @@
|
|||||||
const columns = computed<any[]>(()=>[
|
const columns = computed<any[]>(()=>[
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
dataIndex: 'key',
|
dataIndex: 'id',
|
||||||
slotName: 'key',
|
slotName: 'id',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '用户',
|
title: '用户',
|
||||||
dataIndex: 'title',
|
dataIndex: 'username',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -253,33 +255,33 @@
|
|||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// );
|
// );
|
||||||
const deptTreeData = reactive([
|
const deptTreeData = ref([
|
||||||
{
|
{
|
||||||
key: '1',
|
id: '1',
|
||||||
title: '总部门',
|
name: '总部门',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
key: '2',
|
id: '2',
|
||||||
title: '部门1',
|
name: '部门1',
|
||||||
members: [
|
members: [
|
||||||
{ key: '101', title: '成员1' },
|
{ id: '101', username: '成员1' },
|
||||||
{ key: '102', title: '成员2' }
|
{ id: '102', username: '成员2' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '3',
|
id: '3',
|
||||||
title: '部门2',
|
name: '部门2',
|
||||||
members: [
|
members: [
|
||||||
{ key: '201', title: '成员3' },
|
{ id: '201', username: '成员3' },
|
||||||
{ key: '202', title: '成员4' }
|
{ id: '202', username: '成员4' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '4',
|
id: '4',
|
||||||
title: '部门3',
|
name: '部门3',
|
||||||
members: [
|
members: [
|
||||||
{ key: '203', title: '成员5' },
|
{ id: '203', username: '成员5' },
|
||||||
{ key: '204', title: '成员6' }
|
{ id: '204', username: '成员6' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -287,6 +289,13 @@
|
|||||||
]);
|
]);
|
||||||
const selectedDepartmentMembers: any = ref([]);
|
const selectedDepartmentMembers: any = ref([]);
|
||||||
const renderData = ref<any[]>([]);
|
const renderData = ref<any[]>([]);
|
||||||
|
// 获取部门树
|
||||||
|
const getDeptTree = async () => {
|
||||||
|
const res = await getAllDeptTree(1);
|
||||||
|
if (res.status === 200) {
|
||||||
|
deptTreeData.value = res.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
// 部门树查询
|
// 部门树查询
|
||||||
const queryDeptTree= async ()=>{
|
const queryDeptTree= async ()=>{
|
||||||
deptVisible.value = true;
|
deptVisible.value = true;
|
||||||
@ -299,7 +308,7 @@
|
|||||||
while (queue.length > 0) {
|
while (queue.length > 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const node = queue.shift()!;
|
const node = queue.shift()!;
|
||||||
if (selectedKeys.includes(node.key)) {
|
if (selectedKeys.includes(node.id)) {
|
||||||
if (node.members) {
|
if (node.members) {
|
||||||
selectedMembers.push(...node.members);
|
selectedMembers.push(...node.members);
|
||||||
}
|
}
|
||||||
@ -313,12 +322,12 @@
|
|||||||
|
|
||||||
|
|
||||||
// 部门树被点击
|
// 部门树被点击
|
||||||
const handleClickTree = (key: string[]) => {
|
const handleClickTree = (id: string[]) => {
|
||||||
// 假设 '1' 是总部门的键
|
// 假设 '1' 是总部门的键
|
||||||
if (key[0] === '1' || key.length === 0) {
|
if (id[0] === '1' || id.length === 0) {
|
||||||
// 广度优先遍历树,获取所有成员
|
// 广度优先遍历树,获取所有成员
|
||||||
const allMembers: any[] = [];
|
const allMembers: any[] = [];
|
||||||
const queue:any = [...deptTreeData];
|
const queue:any = [...deptTreeData.value];
|
||||||
while (queue.length > 0) {
|
while (queue.length > 0) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const node = queue.shift()!;
|
const node = queue.shift()!;
|
||||||
@ -333,17 +342,17 @@
|
|||||||
renderData.value = selectedDepartmentMembers.value;
|
renderData.value = selectedDepartmentMembers.value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const Members = getSelectedMembers(deptTreeData, key);
|
const Members = getSelectedMembers(deptTreeData.value, id);
|
||||||
selectedDepartmentMembers.value = Members;
|
selectedDepartmentMembers.value = Members;
|
||||||
}
|
}
|
||||||
// 部门树被选中
|
// 部门树被选中
|
||||||
const handleCheckTree = (key: string[]) => {
|
const handleCheckTree = (id: string[]) => {
|
||||||
if (key[0] === '1' ) { // 假设 '1' 是总部门的键
|
if (id[0] === '1' ) { // 假设 '1' 是总部门的键
|
||||||
const allKeys: string[] = [];
|
const allKeys: string[] = [];
|
||||||
const traverseTree = (node: any) => {
|
const traverseTree = (node: any) => {
|
||||||
if (node.members) {
|
if (node.members) {
|
||||||
node.members.forEach((member: any) => {
|
node.members.forEach((member: any) => {
|
||||||
allKeys.push(member.key);
|
allKeys.push(member.id);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
@ -352,14 +361,14 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
deptTreeData.forEach((node: any) => {
|
deptTreeData.value.forEach((node: any) => {
|
||||||
traverseTree(node);
|
traverseTree(node);
|
||||||
});
|
});
|
||||||
selectedIds.value = allKeys;
|
selectedIds.value = allKeys;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const selectedKeys = getSelectedMembers(deptTreeData, key);
|
const selectedKeys = getSelectedMembers(deptTreeData.value, id);
|
||||||
selectedIds.value = selectedKeys.map(item => item.key);
|
selectedIds.value = selectedKeys.map(item => item.id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -423,6 +432,9 @@
|
|||||||
const deptTreeCancel = () => {
|
const deptTreeCancel = () => {
|
||||||
deptVisible.value = false;
|
deptVisible.value = false;
|
||||||
};
|
};
|
||||||
|
onMounted(async () => {
|
||||||
|
await getDeptTree();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
Loading…
Reference in New Issue
Block a user