feat(新增物模型模块及优化部门树): 新增物模型模块及优化其它模块代码
This commit is contained in:
parent
daf3f540a4
commit
1cbd436f73
@ -14,7 +14,7 @@ export default mergeConfig(
|
||||
proxy: {
|
||||
'/api': {
|
||||
// target: 'http://8.134.75.234:8081',
|
||||
target: 'http://127.0.0.1:8081',
|
||||
target: 'http://192.168.3.238:8081',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
|
@ -11,6 +11,17 @@ export interface DeptRecord extends DeptCreateRecord {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// 获取部门树
|
||||
export function getAllDeptTree(id: number | string) {
|
||||
return axios({
|
||||
method: 'get',
|
||||
url: '/api/rest/dept/tree',
|
||||
params: {
|
||||
id,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 添加区域
|
||||
export function create(data: DeptCreateRecord) {
|
||||
return axios.post(`/api/rest/dept`, data);
|
||||
|
@ -24,8 +24,6 @@ export interface MessageCreateRecord {
|
||||
attachmentIds?: string[];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 查看详情
|
||||
export function queryMessage(userId: number, messageId: number) {
|
||||
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: ['*'],
|
||||
},
|
||||
},
|
||||
{
|
||||
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>
|
||||
<a-button
|
||||
type="outline"
|
||||
size="small"
|
||||
status="success"
|
||||
style="padding: 7px; margin-right: 10px"
|
||||
@click="handleClick"
|
||||
>
|
||||
<template #icon><icon-list /></template>
|
||||
详情
|
||||
</a-button>
|
||||
|
||||
<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>
|
||||
|
||||
<template #footer>
|
||||
<!-- <a-button class="editor-button" @click="handleCancel">取消</a-button>-->
|
||||
<a-button class="editor-button" type="primary" @click="handleCancel">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['物联网管理', '设备管理', '设备详情']" />
|
||||
<a-card class="general-card" title=" ">
|
||||
<a-descriptions v-model="renderData" size="large">
|
||||
<template #title><h3 style="margin-top: -15px">设备详情</h3></template>
|
||||
<a-descriptions-item label="设备名称">{{renderData.name }}</a-descriptions-item>
|
||||
<a-descriptions-item label="硬件版本">{{renderData.hardwareVersion }}</a-descriptions-item>
|
||||
<a-descriptions-item label="固件版本">{{renderData.firmwareVersion }}</a-descriptions-item>
|
||||
<a-descriptions-item label="所属产品">{{renderData.productId }}</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>
|
||||
</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.extendParams" />
|
||||
</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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useVisible from '@/hooks/visible';
|
||||
import { defineEmits, PropType, ref } from 'vue';
|
||||
import { DeviceCreateRecord } from '@/api/device';
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import dayjs from 'dayjs';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { queryDeviceDetail } from '@/api/device';
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
prem: {
|
||||
type: Object as PropType<DeviceCreateRecord>,
|
||||
const route = useRoute();
|
||||
const id = Number(route.params.id);
|
||||
const columns = [
|
||||
{
|
||||
title: '参数名称',
|
||||
dataIndex: 'name',
|
||||
slotName: 'name',
|
||||
},
|
||||
isCreate: Boolean,
|
||||
});
|
||||
const emit = defineEmits(['refresh']);
|
||||
const { visible, setVisible } = useVisible(false);
|
||||
|
||||
const formData = ref<any>({
|
||||
...props.prem,
|
||||
});
|
||||
|
||||
|
||||
// 组件被点击
|
||||
const handleClick = () => {
|
||||
setVisible(true);
|
||||
{
|
||||
title: '参数标识',
|
||||
dataIndex: 'identifier',
|
||||
slotName: 'identifier',
|
||||
},
|
||||
{
|
||||
title: '数据类型',
|
||||
dataIndex: 'dataType',
|
||||
slotName: 'dataType',
|
||||
},
|
||||
{
|
||||
title: '参数类型',
|
||||
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 handleCancel = async () => {
|
||||
setVisible(false);
|
||||
const handleMenuClick = (e: any) => {
|
||||
activeKey.value = e;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchData(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.editor-button{
|
||||
position: static
|
||||
.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>
|
||||
|
@ -82,13 +82,25 @@
|
||||
<a-form-item
|
||||
field="extendParams"
|
||||
label="扩展属性"
|
||||
:rules="[{ required: true, message: '扩展属性不能为空' }]"
|
||||
:validate-trigger="['change']"
|
||||
>
|
||||
<a-input
|
||||
v-model="formData.extendParams"
|
||||
placeholder='请输入扩展属性'
|
||||
/>
|
||||
<!-- <a-input-->
|
||||
<!-- v-model="formData.extendParams"-->
|
||||
<!-- 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>
|
||||
|
||||
@ -108,6 +120,7 @@
|
||||
import { useMessageStore } from '@/store';
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import { createDevice, updateDevice } from '@/api/device';
|
||||
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||
|
||||
const props = defineProps({
|
||||
prem: {
|
||||
@ -115,6 +128,58 @@
|
||||
},
|
||||
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 modalTitle = computed(() => {
|
||||
return props.isCreate ? '创建设备' : '编辑设备';
|
||||
@ -142,7 +207,22 @@
|
||||
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 = () => {
|
||||
setVisible(true);
|
||||
@ -153,6 +233,7 @@
|
||||
const valid = await CreateRef.value?.validate();
|
||||
if (!valid) {
|
||||
// 新增
|
||||
formData.value.extendParams = paramsData.value;
|
||||
if (props.isCreate) {
|
||||
// formData.value.username = formData.value.email;
|
||||
const res = await createDevice(formData.value);
|
||||
|
@ -162,17 +162,16 @@
|
||||
{{ record.online == true? '是' : '否' }}
|
||||
</template>
|
||||
<template #operations="{ record }">
|
||||
<!-- <a-button-->
|
||||
<!-- type="outline"-->
|
||||
<!-- size="small"-->
|
||||
<!-- status="success"-->
|
||||
<!-- style="padding: 7px; margin-right: 10px"-->
|
||||
<!-- @click="openDetail(record.id)"-->
|
||||
<!-- >-->
|
||||
<!-- <template #icon><icon-list /></template>-->
|
||||
<!-- 详情-->
|
||||
<!-- </a-button>-->
|
||||
<DeviceDetail :prem="record" />
|
||||
<a-button
|
||||
type="outline"
|
||||
size="small"
|
||||
status="success"
|
||||
style="padding: 7px; margin-right: 10px"
|
||||
@click="openDetail(record.id)"
|
||||
>
|
||||
<template #icon><icon-list /></template>
|
||||
详情
|
||||
</a-button>
|
||||
<DeviceEdit
|
||||
ref="editUserRef"
|
||||
:prem="record"
|
||||
@ -338,7 +337,7 @@
|
||||
// 打开详情
|
||||
function openDetail(id:number): void{
|
||||
const url = router.resolve({
|
||||
name: 'Detail',
|
||||
name: 'deviceDetail',
|
||||
params: {id}
|
||||
}).href;
|
||||
router.push(url);
|
||||
|
@ -1,20 +1,27 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<Breadcrumb :items="['物联网管理', '产品管理','产品详情']" />
|
||||
<Breadcrumb :items="['物联网管理', '产品管理', '产品详情']" />
|
||||
<a-card class="general-card" title=" ">
|
||||
<div class="announcement-detail">
|
||||
<a-descriptions :data="renderData" size="large" title="产品详情" bordered >
|
||||
<a-descriptions-item label="产品名称">{{renderData.name}}</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.link}}</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="扩展属性">
|
||||
<a-table :columns="columns" :data="renderData.params" row-key="id" :pagination="false"/>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<a-descriptions v-model="renderData" size="large">
|
||||
<template #title><h3 style="margin-top: -15px">产品详情</h3></template>
|
||||
<a-descriptions-item label="产品名称">{{renderData.name }}</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.link }}</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>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
@ -27,7 +34,7 @@
|
||||
|
||||
const route = useRoute();
|
||||
const id = Number(route.params.id);
|
||||
const columns=[
|
||||
const columns = [
|
||||
{
|
||||
title: '参数名称',
|
||||
dataIndex: 'name',
|
||||
@ -49,72 +56,34 @@
|
||||
slotName: 'type',
|
||||
},
|
||||
];
|
||||
const renderData = ref<any>(
|
||||
{
|
||||
name: '产品名称',
|
||||
productType: '设备',
|
||||
model: '123456',
|
||||
link: 'TCP',
|
||||
remark: '123456',
|
||||
createTime: '2023-08-08 10:10:10',
|
||||
params:[
|
||||
{
|
||||
name:'设备名称',
|
||||
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);
|
||||
// });
|
||||
const activeKey = ref('1');
|
||||
const renderData = ref([]);
|
||||
const fetchData = async (Id: number) => {
|
||||
const res = await queryProductDetail(Id);
|
||||
renderData.value = res.data;
|
||||
};
|
||||
const handleMenuClick = (e: any) => {
|
||||
activeKey.value = e;
|
||||
};
|
||||
onMounted(() => {
|
||||
fetchData(id);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
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 {
|
||||
font-size: 24px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
.meta span {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
|
||||
.attachments li {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -131,5 +100,3 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
</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>
|
||||
详情
|
||||
</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
|
||||
:id="record.id"
|
||||
ref="editUserRef"
|
||||
@ -339,6 +349,15 @@
|
||||
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 res = await deleteProduct(id);
|
||||
|
@ -134,11 +134,12 @@
|
||||
<a-card style="margin-right: 10px;width: 30%">
|
||||
<a-tree
|
||||
:data="deptTreeData"
|
||||
checkable="true"
|
||||
:field-names="{ title: 'name', key: 'id', children: 'children' }"
|
||||
style="margin-bottom: 8px; max-width: 240px"
|
||||
@select="handleClickTree"
|
||||
@check="handleCheckTree"
|
||||
/>
|
||||
>
|
||||
</a-tree>
|
||||
</a-card>
|
||||
<a-card style="flex: 1">
|
||||
<a-button type="primary" >全选</a-button>
|
||||
@ -146,11 +147,11 @@
|
||||
:data="selectedDepartmentMembers"
|
||||
:columns="columns"
|
||||
style="height: 520px">
|
||||
<template #key="{ record }">
|
||||
<a-checkbox v-model="selectedIds" :value="record.key"> </a-checkbox>
|
||||
<template #id="{ record }">
|
||||
<a-checkbox v-model="selectedIds" :value="record.id"> </a-checkbox>
|
||||
</template>
|
||||
<template #title="{ record }">
|
||||
{{ record.title }}
|
||||
<template #username="{ record }">
|
||||
{{ record.username }}
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
@ -165,7 +166,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
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 { FormInstance } from '@arco-design/web-vue/es/form';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
@ -174,6 +175,7 @@
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||
import { IEditorConfig } from '@wangeditor/editor'
|
||||
import '@wangeditor/editor/dist/css/style.css'
|
||||
import { getAllDeptTree } from '@/api/dept';
|
||||
|
||||
const props = defineProps({
|
||||
prem: {
|
||||
@ -205,12 +207,12 @@
|
||||
const columns = computed<any[]>(()=>[
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'key',
|
||||
slotName: 'key',
|
||||
dataIndex: 'id',
|
||||
slotName: 'id',
|
||||
},
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'title',
|
||||
dataIndex: 'username',
|
||||
},
|
||||
])
|
||||
|
||||
@ -253,33 +255,33 @@
|
||||
// },
|
||||
// },
|
||||
// );
|
||||
const deptTreeData = reactive([
|
||||
const deptTreeData = ref([
|
||||
{
|
||||
key: '1',
|
||||
title: '总部门',
|
||||
id: '1',
|
||||
name: '总部门',
|
||||
children: [
|
||||
{
|
||||
key: '2',
|
||||
title: '部门1',
|
||||
id: '2',
|
||||
name: '部门1',
|
||||
members: [
|
||||
{ key: '101', title: '成员1' },
|
||||
{ key: '102', title: '成员2' }
|
||||
{ id: '101', username: '成员1' },
|
||||
{ id: '102', username: '成员2' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
title: '部门2',
|
||||
id: '3',
|
||||
name: '部门2',
|
||||
members: [
|
||||
{ key: '201', title: '成员3' },
|
||||
{ key: '202', title: '成员4' }
|
||||
{ id: '201', username: '成员3' },
|
||||
{ id: '202', username: '成员4' }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
title: '部门3',
|
||||
id: '4',
|
||||
name: '部门3',
|
||||
members: [
|
||||
{ key: '203', title: '成员5' },
|
||||
{ key: '204', title: '成员6' }
|
||||
{ id: '203', username: '成员5' },
|
||||
{ id: '204', username: '成员6' }
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -287,6 +289,13 @@
|
||||
]);
|
||||
const selectedDepartmentMembers: any = ref([]);
|
||||
const renderData = ref<any[]>([]);
|
||||
// 获取部门树
|
||||
const getDeptTree = async () => {
|
||||
const res = await getAllDeptTree(1);
|
||||
if (res.status === 200) {
|
||||
deptTreeData.value = res.data;
|
||||
}
|
||||
}
|
||||
// 部门树查询
|
||||
const queryDeptTree= async ()=>{
|
||||
deptVisible.value = true;
|
||||
@ -299,7 +308,7 @@
|
||||
while (queue.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const node = queue.shift()!;
|
||||
if (selectedKeys.includes(node.key)) {
|
||||
if (selectedKeys.includes(node.id)) {
|
||||
if (node.members) {
|
||||
selectedMembers.push(...node.members);
|
||||
}
|
||||
@ -313,12 +322,12 @@
|
||||
|
||||
|
||||
// 部门树被点击
|
||||
const handleClickTree = (key: string[]) => {
|
||||
const handleClickTree = (id: string[]) => {
|
||||
// 假设 '1' 是总部门的键
|
||||
if (key[0] === '1' || key.length === 0) {
|
||||
if (id[0] === '1' || id.length === 0) {
|
||||
// 广度优先遍历树,获取所有成员
|
||||
const allMembers: any[] = [];
|
||||
const queue:any = [...deptTreeData];
|
||||
const queue:any = [...deptTreeData.value];
|
||||
while (queue.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const node = queue.shift()!;
|
||||
@ -333,17 +342,17 @@
|
||||
renderData.value = selectedDepartmentMembers.value;
|
||||
return;
|
||||
}
|
||||
const Members = getSelectedMembers(deptTreeData, key);
|
||||
const Members = getSelectedMembers(deptTreeData.value, id);
|
||||
selectedDepartmentMembers.value = Members;
|
||||
}
|
||||
// 部门树被选中
|
||||
const handleCheckTree = (key: string[]) => {
|
||||
if (key[0] === '1' ) { // 假设 '1' 是总部门的键
|
||||
const handleCheckTree = (id: string[]) => {
|
||||
if (id[0] === '1' ) { // 假设 '1' 是总部门的键
|
||||
const allKeys: string[] = [];
|
||||
const traverseTree = (node: any) => {
|
||||
if (node.members) {
|
||||
node.members.forEach((member: any) => {
|
||||
allKeys.push(member.key);
|
||||
allKeys.push(member.id);
|
||||
});
|
||||
}
|
||||
if (node.children) {
|
||||
@ -352,14 +361,14 @@
|
||||
});
|
||||
}
|
||||
};
|
||||
deptTreeData.forEach((node: any) => {
|
||||
deptTreeData.value.forEach((node: any) => {
|
||||
traverseTree(node);
|
||||
});
|
||||
selectedIds.value = allKeys;
|
||||
|
||||
} else {
|
||||
const selectedKeys = getSelectedMembers(deptTreeData, key);
|
||||
selectedIds.value = selectedKeys.map(item => item.key);
|
||||
const selectedKeys = getSelectedMembers(deptTreeData.value, id);
|
||||
selectedIds.value = selectedKeys.map(item => item.id);
|
||||
}
|
||||
};
|
||||
|
||||
@ -423,6 +432,9 @@
|
||||
const deptTreeCancel = () => {
|
||||
deptVisible.value = false;
|
||||
};
|
||||
onMounted(async () => {
|
||||
await getDeptTree();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
Loading…
Reference in New Issue
Block a user