perf(物联网产品,设备,物模型模块): 优化物联网管理整个模块代码及其它模块bug

This commit is contained in:
Kven 2025-01-09 15:28:27 +08:00
parent 47f226e019
commit 803ce3dfa6
22 changed files with 293 additions and 177 deletions

View File

@ -1,4 +1,5 @@
import axios from 'axios';
import dashboard from '@/router/routes/modules/dashboard';
export interface DeviceRecord {
size: number;
@ -17,7 +18,7 @@ export interface DeviceCreateRecord {
name?: string;
hardwareVersion: string;
firmwareVersion: string;
extendParams: string;
extendParams: string[];
properties: string;
productId: number;
}
@ -46,6 +47,14 @@ export function queryDeviceList(data: DeviceRecord) {
export function queryDeviceDetail(id: number) {
return axios.get(`/api/rest/device/${id}`);
}
// 名称模糊查询
export function queryDeviceByName(data: any) {
return axios({
url: `/api/rest/product/fuzzy`,
method: 'get',
params: data,
});
}
// 新增
export function createDevice(data: DeviceCreateRecord) {
@ -54,7 +63,7 @@ export function createDevice(data: DeviceCreateRecord) {
// 修改
export function updateDevice(data:DeviceUpdateRecord) {
return axios.put(`/api/rest/device/${data.id}`, data);
return axios.patch(`/api/rest/device/${data.id}`, data);
}
// 删除
export function deleteDevice(id: number) {

View File

@ -26,25 +26,25 @@ export interface MessageCreateRecord {
// 查看详情
export function queryMessage(userId: number, messageId: number) {
return axios.get(`/api/rest/message/${userId}/${messageId}`);
return axios.get(`/api/rest/notice/${userId}/${messageId}`);
}
// 分页查询
export function queryMessageList(data: MessageRecord) {
return axios({
url: '/api/rest/message',
url: '/api/rest/notice',
method: 'get',
params: data,
});
}
// 创建消息
export function createMessage(data: MessageCreateRecord) {
return axios.post('/api/rest/message', data);
return axios.post('/api/rest/notice', data);
}
// 获取消息推送方式
export function getMessageTypes() {
return axios.get('/api/rest/message/setting');
return axios.get('/api/rest/notice/setting');
}
// 设置消息推送方式
export function setMessageTypes(data: string[]) {
return axios.patch('/api/rest/message/setting', data);
return axios.patch('/api/rest/notice/setting', data);
}

View File

@ -49,7 +49,7 @@ export interface MessagesRecord {
}
export interface MessageStatus {
ids: string[];
ids: number[];
}
export type MessageListType = MessagesList[];

View File

@ -6,7 +6,7 @@
<span> {{ item.title }}{{ formatUnreadLength(item.key) }} </span>
</template>
<a-result v-if="!renderList.length" status="404">
<template #subtitle> {{ $t('messageBox.noContent') }} </template>
<template #subtitle> 暂无内容 </template>
</a-result>
<List
:render-list="renderList"

View File

@ -150,9 +150,9 @@
</a-tooltip>
</li>
<li>
<a-button status="normal">{{ userStore.permissions }}</a-button>
</li>
<!-- <li>-->
<!-- <a-button status="normal">{{ userStore.permissions }}</a-button>-->
<!-- </li>-->
<li>
<a-dropdown trigger="click">
<a-avatar

View File

@ -12,6 +12,6 @@
"globalSettings": false,
"device": "desktop",
"tabBar": false,
"menuFromServer": true,
"menuFromServer": false,
"serverMenu": []
}

View File

@ -5,11 +5,11 @@ import { intersection } from 'lodash';
function checkPermission(el: HTMLElement, binding: DirectiveBinding) {
const { value } = binding;
const userStore = useUserStore();
const { authorities } = userStore;
const { permissions } = userStore;
if (Array.isArray(value)) {
if (value.length > 0) {
const hasPermission = intersection(value, authorities).length > 0;
const hasPermission = intersection(value, permissions).length > 0;
if (!hasPermission && el.parentNode) {
el.parentNode.removeChild(el);

View File

@ -7,6 +7,7 @@ const DASHBOARD: AppRouteRecordRaw = {
component: DEFAULT_LAYOUT,
meta: {
locale: 'menu.dashboard',
title: '首页',
requiresAuth: true,
icon: 'icon-dashboard', // 设置图标
order: 0, // 排序路由菜单项。如果设置该值,值越高,越靠前
@ -17,7 +18,8 @@ const DASHBOARD: AppRouteRecordRaw = {
name: 'Workplace',
component: () => import('@/views/dashboard/workplace/index.vue'),
meta: {
locale: 'menu.dashboard.workplace',
locale:'menu.dashboard.workplace',
title: '工作台',
requiresAuth: true,
permissions: ['*'],
},

View File

@ -18,7 +18,7 @@ const IOT: AppRouteRecordRaw = {
name: 'Product',
component: () => import('@/views/iot/product/index.vue'),
meta: {
// locale: 'menu.system.dept',
locale: 'menu.system.product',
title: '产品管理',
requiresAuth: true,
permissions: ['*'],
@ -29,7 +29,7 @@ const IOT: AppRouteRecordRaw = {
name: 'Device',
component: () => import('@/views/iot/device/index.vue'),
meta: {
// locale: 'menu.system.role',
locale: 'menu.system.device',
title: '设备管理',
requiresAuth: true,
permissions: ['*'],
@ -40,6 +40,7 @@ const IOT: AppRouteRecordRaw = {
name: 'productDetail',
component: () => import('@/views/iot/product/components/product-detail.vue'),
meta: {
locale:'menu.system.product',
title: '产品详情',
requiresAuth: true,
showInMenu: false,
@ -51,6 +52,7 @@ const IOT: AppRouteRecordRaw = {
name: 'deviceDetail',
component: () => import('@/views/iot/device/components/device-detail.vue'),
meta: {
locale: 'menu.system.deviceDetail',
title: '设备详情',
requiresAuth: true,
showInMenu: false,
@ -62,6 +64,7 @@ const IOT: AppRouteRecordRaw = {
name: 'productTsl',
component: () => import('@/views/iot/product/components/product-tsl.vue'),
meta: {
locale: 'menu.system.productTsl',
title: '物模型',
requiresAuth: true,
showInMenu: false,

View File

@ -7,6 +7,7 @@ const NOTIFICATION: AppRouteRecordRaw = {
component: DEFAULT_LAYOUT,
meta: {
locale: '通知管理',
title: '通知管理',
requiresAuth: true,
icon: 'icon-message', // 设置图标
order: 0, // 排序路由菜单项。如果设置该值,值越高,越靠前
@ -18,6 +19,7 @@ const NOTIFICATION: AppRouteRecordRaw = {
component: () => import('@/views/notification/notice/index.vue'),
meta: {
locale: '公告通知',
title: '公告通知',
requiresAuth: true,
permissions: ['*'],
},
@ -28,6 +30,7 @@ const NOTIFICATION: AppRouteRecordRaw = {
component: () => import('@/views/notification/noticeSet/index.vue'),
meta: {
locale: '公告管理',
title: '公告管理',
requiresAuth: true,
permissions: ['*'],
},

View File

@ -27,6 +27,7 @@ const SYSTEM: AppRouteRecordRaw = {
name: 'Role',
component: () => import('@/views/system/role/index.vue'),
meta: {
title: '角色管理',
requiresAuth: true,
permissions: ['*'],
},
@ -36,6 +37,7 @@ const SYSTEM: AppRouteRecordRaw = {
name: 'Dept',
component: () => import('@/views/system/dept/index.vue'),
meta: {
title: '部门管理',
requiresAuth: true,
permissions: ['*'],
},
@ -45,14 +47,17 @@ const SYSTEM: AppRouteRecordRaw = {
name: 'User',
component: () => import('@/views/system/user/index.vue'),
meta: {
title: '用户管理',
requiresAuth: true,
permissions: ['*'],
},
},
{
path: 'authority',
name: 'Authority',
component: () => import('@/views/system/authority/index.vue'),
meta: {
title: '权限管理',
requiresAuth: true,
permissions: ['*'],
},

View File

@ -6,6 +6,11 @@ import useTabBarStore from './modules/tab-bar';
import useRoleStore from './modules/role';
import useDeptStore from './modules/dept';
import useAuthStore from './modules/auth';
import useMessagesStore from './modules/messages';
import useBulletinsStore from './modules/bulletins';
import useMessageStore from './modules/message-mgmt';
import useBulletinStore from './modules/bulle-mgmt';
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
@ -17,5 +22,9 @@ export {
useDeptStore,
useRoleStore,
useAuthStore,
useMessagesStore,
useBulletinsStore,
useMessageStore,
useBulletinStore
};
export default pinia;

View File

@ -6,7 +6,7 @@ import {
queryDeptList,
enabled,
remove,
update,
update, getAllDeptTree
} from '@/api/dept';
import { deptStore } from './type';
@ -25,6 +25,11 @@ const useDeptStore = defineStore('dept', {
},
},
actions: {
// 获取所有部门树
async getAllDeptTree(id: number | string) {
return getAllDeptTree(id);
},
// 获取所有的角色列表
async getDeptList(data: DeptRecord) {
return queryDeptList(data);

View File

@ -49,7 +49,6 @@ const useUserStore = defineStore('user', {
setInfo(partial: Partial<UserState>) {
this.$patch(partial);
},
// Reset user's information
resetInfo() {
this.$reset();

View File

@ -1,68 +1,68 @@
// // 新建 @/utils/excel.ts
//
// import saveAs from 'file-saver'; // https://www.npmjs.com/package/file-saver
// import ExcelJS from 'exceljs'; // https://github.com/exceljs/exceljs/blob/master/README_zh.md
// import * as XLSX from 'xlsx'; // https://www.npmjs.com/package/xlsx
// import { Message } from '@arco-design/web-vue'; // https://arco.design/vue/component/message
// import { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; // arco类型
//
// export interface DownloadExcelPrams {
// columns: { title: string; key: string }[];
// rows: object[];
// name: string;
// }
//
// // 导出下载文件
// export function downloadExcel({
// columns,
// rows,
// name = '未命名文件',
// }: DownloadExcelPrams) {
// const workbook = new ExcelJS.Workbook();
// workbook.creator = 'Start-front';
// workbook.lastModifiedBy = 'Start-front';
// workbook.created = new Date(1985, 8, 30);
// workbook.modified = new Date();
// workbook.lastPrinted = new Date(2016, 9, 27);
//
// // 将工作簿添加一个sheet页sheet1
// const sheet1 = workbook.addWorksheet(name);
// // 表头数据添加
// sheet1.columns = columns.map((item) => ({
// header: item.title,
// key: item.key,
// width: 20,
// }));
// // 表格内容添加
// rows.map((item) => sheet1.addRow(item));
// workbook.xlsx.writeBuffer().then((buffer) => {
// saveAs(
// new Blob([buffer], { type: 'application/octet-stream' }),
// `${name}.xlsx`
// );
// });
// }
//
// // 读取文件为json格式
// export function readExcle(fileItem: FileItem) {
// return new Promise((resove, reject) => {
// try {
// let workbook: XLSX.Sheet;
// const reader = new FileReader();
// reader.readAsBinaryString(fileItem.file as File); // 发起异步请求
// reader.onload = function (ev) {
// const data = ev.target?.result;
// workbook = XLSX.read(data, { type: 'binary' });
// const sheetNames = workbook.SheetNames; // 工作表名称集合
// sheetNames.forEach((name: string) => {
// const worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表
// const jsonres = XLSX.utils.sheet_to_json(worksheet);
// resove(jsonres);
// });
// }; // onload
// } catch (error) {
// Message.error('读取失败,请选择正确文件');
// reject(error);
// }
// });
// }
// 新建 @/utils/excel.ts
import saveAs from 'file-saver'; // https://www.npmjs.com/package/file-saver
import ExcelJS from 'exceljs'; // https://github.com/exceljs/exceljs/blob/master/README_zh.md
import * as XLSX from 'xlsx'; // https://www.npmjs.com/package/xlsx
import { Message } from '@arco-design/web-vue'; // https://arco.design/vue/component/message
import { FileItem } from '@arco-design/web-vue/es/upload/interfaces'; // arco类型
export interface DownloadExcelPrams {
columns: { title: string; key: string }[];
rows: object[];
name: string;
}
// 导出下载文件
export function downloadExcel({
columns,
rows,
name = '未命名文件',
}: DownloadExcelPrams) {
const workbook = new ExcelJS.Workbook();
workbook.creator = 'Start-front';
workbook.lastModifiedBy = 'Start-front';
workbook.created = new Date(1985, 8, 30);
workbook.modified = new Date();
workbook.lastPrinted = new Date(2016, 9, 27);
// 将工作簿添加一个sheet页sheet1
const sheet1 = workbook.addWorksheet(name);
// 表头数据添加
sheet1.columns = columns.map((item) => ({
header: item.title,
key: item.key,
width: 20,
}));
// 表格内容添加
rows.map((item) => sheet1.addRow(item));
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(
new Blob([buffer], { type: 'application/octet-stream' }),
`${name}.xlsx`
);
});
}
// 读取文件为json格式
export function readExcle(fileItem: FileItem) {
return new Promise((resove, reject) => {
try {
let workbook: XLSX.Sheet;
const reader = new FileReader();
reader.readAsBinaryString(fileItem.file as File); // 发起异步请求
reader.onload = function (ev) {
const data = ev.target?.result;
workbook = XLSX.read(data, { type: 'binary' });
const sheetNames = workbook.SheetNames; // 工作表名称集合
sheetNames.forEach((name: string) => {
const worksheet = workbook.Sheets[name]; // 只能通过工作表名称来获取指定工作表
const jsonres = XLSX.utils.sheet_to_json(worksheet);
resove(jsonres);
});
}; // onload
} catch (error) {
Message.error('读取失败,请选择正确文件');
reject(error);
}
});
}

View File

@ -16,6 +16,7 @@
<a-modal
width="900px"
height="500px"
:visible="visible"
@cancel="handleCancel"
>
@ -23,23 +24,26 @@
<a-form
ref="CreateRef"
:model="formData"
:style="{ width: '650px' }"
:style="{ width: '800px', height: '420px' }"
>
<!-- 产品id -->
<a-form-item
field="productId"
field="productName"
label="产品名称"
:rules="[{ required: true, message: '产品名称不能为空' }]"
:validate-trigger="['change']"
>
<a-select
v-model="formData.productId"
v-model="formData.productName"
placeholder="请选择产品名称"
:loading="loading"
:filter-option="false"
allow-search
@search="handleSearch"
>
<a-option v-for="item of options" :key="item.id" :value="item">{{item}}</a-option>
<a-option v-for="item of options" :key="item.id" :value="item.name">{{
item.name
}}</a-option>
</a-select>
</a-form-item>
<!-- 设备名称 -->
@ -49,10 +53,7 @@
:rules="[{ required: true, message: '设备名称不能为空' }]"
:validate-trigger="['change']"
>
<a-input
v-model="formData.name"
placeholder='请输入设备名称'
/>
<a-input v-model="formData.name" placeholder="请输入设备名称" />
</a-form-item>
<!-- 硬件版本 -->
<a-form-item
@ -63,7 +64,7 @@
>
<a-input
v-model="formData.hardwareVersion"
placeholder='请输入硬件版本'
placeholder="请输入硬件版本"
/>
</a-form-item>
<!-- 固件版本 -->
@ -75,29 +76,57 @@
>
<a-input
v-model="formData.firmwareVersion"
placeholder='请输入固件版本'
placeholder="请输入固件版本"
/>
</a-form-item>
<a-form-item
field="remark"
label="备注"
>
<a-textarea
v-model="formData.remark"
placeholder="请输入描述"
/>
</a-form-item>
<!-- 扩展属性 -->
<a-form-item
field="extendParams"
label="扩展属性"
>
<!-- <a-input-->
<!-- v-model="formData.extendParams"-->
<!-- placeholder='请输入扩展属性'-->
<!-- />-->
<a-form-item field="extendParams" label="扩展属性">
<!-- <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">
<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-input
v-model="param.identifier"
placeholder="标识"
allow-clear
/>
<a-select
v-model="param.dataType"
:options="dataTypeOptions"
allow-search
placeholder="数据类型"
style="width: 140px"
/>
<a-select
v-model="param.type"
:options="typeOptions"
allow-search
placeholder="类型"
style="width: 140px"
/>
<a-button type="text" @click="handleDeleteParams(index)"
><icon-minus-circle
/></a-button>
</a-space>
</div>
<a-button @click="handleAddParams" style="width: 100%" >
<a-button type="outline" @click="handleAddParams" style="width: 100%">
<icon-plus />
</a-button>
</div>
@ -106,21 +135,30 @@
<template #footer>
<a-button class="editor-button" @click="handleCancel">取消</a-button>
<a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button>
<a-button class="editor-button" type="primary" @click="handleSubmit"
>确定</a-button
>
</template>
</a-modal>
</template>
<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,
} from 'vue';
import { CreateRecord } from '@/api/user';
import { FormInstance } from '@arco-design/web-vue/es/form';
import { Message } from '@arco-design/web-vue';
import { useMessageStore } from '@/store';
import '@wangeditor/editor/dist/css/style.css'
import { createDevice, updateDevice } from '@/api/device';
import '@wangeditor/editor/dist/css/style.css';
import { createDevice, queryDeviceByName, queryDeviceDetail, updateDevice } from '@/api/device';
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
import { queryProductDetail } from '@/api/product';
const props = defineProps({
prem: {
@ -168,11 +206,11 @@
]);
const typeOptions = computed<SelectOptionData[]>(() => [
{
label: '物模型输入',
label: '输入',
value: 'INPUT',
},
{
label: '物模型输出',
label: '输出',
value: 'OUTPUT',
},
{
@ -191,22 +229,34 @@
const formData = ref<any>({
...props.prem,
});
const editorRef = shallowRef()
const options = ref(['Option1', 'Option2', 'Option3']);
const editorRef = shallowRef();
const options = ref();
const loading = ref(false);
//
const handleSearch = (value: any) => {
if (value) {
loading.value = true;
window.setTimeout(() => {
options.value = [`${value}-Option1`, `${value}-Option2`, `${value}-Option3`]
options.value = [];
window.setTimeout(async () => {
const res = await queryDeviceByName({
name: value,
page:1,
size: 10,
});
options.value = res.data.records.map((item: any) => {
return {
id: item.id,
name: item.name,
};
});
loading.value = false;
}, 2000)
}, 2000);
} else {
options.value = []
options.value = [];
}
};
//
const handleAddParams = () => {
// paramsVisible.value = true;
@ -218,7 +268,7 @@
});
};
//
const handleDeleteParams = (record: any) => {
const handleDeleteParams = (record: number) => {
if (record !== -1) {
paramsData.value.splice(record, 1);
}
@ -226,14 +276,27 @@
//
const handleClick = () => {
setVisible(true);
if(!props.isCreate) {
const ID = formData.value.productId;
queryProductDetail(ID).then((res) => {
formData.value.productName = res.data.name;
});
queryDeviceDetail(formData.value.id).then((res) => {
paramsData.value = res.data.extendParams;
})
}
};
//
const handleSubmit = async () => {
const valid = await CreateRef.value?.validate();
// formData.value.productId = formData.value.productId.id;
if (!valid) {
//
formData.value.extendParams = paramsData.value;
const productId = await queryDeviceByName(formData.value.productName);
formData.value.productId = productId.data.records[0].id;
if (props.isCreate) {
// formData.value.username = formData.value.email;
const res = await createDevice(formData.value);
@ -263,21 +326,20 @@
//
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
//
const handleCancel = async () => {
checkKeys.value = [];
setVisible(false);
};
</script>
<style scoped>
.editor-button{
position: static
.editor-button {
position: static;
}
</style>

View File

@ -215,7 +215,6 @@
import usePagination from '@/hooks/pagination';
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import { useBulletinStore } from '@/store';
import useTableOption from '@/hooks/table-option';
import { Message } from '@arco-design/web-vue';
import { useRouter } from 'vue-router';
@ -248,7 +247,6 @@
deepClone,
} = useTableOption();
const bulletinStore = useBulletinStore();
const columns = computed<TableColumnData[]>(() => [
{

View File

@ -81,7 +81,7 @@
field="remark"
label="备注"
>
<a-input
<a-textarea
v-model="formData.remark"
placeholder='请输入备注'
/>
@ -143,8 +143,8 @@
<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-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型" style="width: 140px"/>
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型" style="width: 140px"/>
<a-button type="text" @click="handleDeleteParams(index)"><icon-minus-circle /></a-button>
</a-space>
</div>
@ -348,11 +348,11 @@
]);
const typeOptions = computed<SelectOptionData[]>(() => [
{
label: '物模型输入',
label: '输入',
value: 'INPUT',
},
{
label: '物模型输出',
label: '输出',
value: 'OUTPUT',
},
{
@ -365,6 +365,7 @@
const fetchData = async (Id: number | undefined) => {
const res = await queryProductDetail(Id);
formData.value = res.data;
paramsData.value = res.data.params;
};
//
const handleClick = () => {

View File

@ -80,7 +80,7 @@
<a-form
ref="propertyCreateRef"
:model="propertyAddData"
:style="{ width: '650px' }"
:style="{ width: '800px', height: '420px' }"
>
<!-- 设备名称 -->
<a-form-item
@ -152,7 +152,7 @@
<a-form
ref="serveCreateRef"
:model="serveAddData"
:style="{ width: '650px' }"
:style="{ width: '800px', height: '420px' }"
>
<!-- 服务名称 -->
<a-form-item
@ -188,8 +188,8 @@
<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-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型" style="width: 140px"/>
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型" style="width: 140px"/>
<a-button type="text" @click="handleDeleteParams(index,'serveInputData')"><icon-minus-circle /></a-button>
</a-space>
</div>
@ -208,8 +208,8 @@
<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-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型" style="width: 140px"/>
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型" style="width: 140px"/>
<a-button type="text" @click="handleDeleteParams(index,'serveOutputData')"><icon-minus-circle /></a-button>
</a-space>
</div>
@ -245,7 +245,7 @@
<a-form
ref="eventCreateRef"
:model="eventAddData"
:style="{ width: '650px' }"
:style="{ width: '800px', height: '420px' }"
>
<!-- 事件名称 -->
<a-form-item
@ -278,10 +278,7 @@
:rules="[{ required: true, message: '类型不能为空' }]"
:validate-trigger="['change']"
>
<a-input
v-model="eventAddData.type"
placeholder='请输入类型'
/>
<a-select v-model="eventAddData.type" :options="eventTypeOptions" allow-search placeholder="请选择类型"/>
</a-form-item>
<!-- 输出参数 -->
<a-form-item
@ -293,8 +290,8 @@
<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-select v-model="param.dataType" :options="dataTypeOptions" allow-search placeholder="数据类型" style="width: 140px"/>
<a-select v-model="param.type" :options="typeOptions" allow-search placeholder="类型" style="width: 140px"/>
<a-button type="text" @click="handleDeleteParams(index,'eventOutputData')"><icon-minus-circle /></a-button>
</a-space>
</div>
@ -404,11 +401,11 @@
]);
const typeOptions = computed<SelectOptionData[]>(() => [
{
label: '物模型输入',
label: '输入',
value: 'INPUT',
},
{
label: '物模型输出',
label: '输出',
value: 'OUTPUT',
},
{
@ -416,6 +413,16 @@
value: 'RW',
},
]);
const eventTypeOptions = computed<SelectOptionData[]>(() => [
{
label: '主动',
value: 'ACTIVE',
},
{
label: '被动',
value: 'PASSIVE',
},
]);
const propertyAddData = ref({
productId:id,
});

View File

@ -113,6 +113,7 @@
<a-table
row-key="id"
:default-expand-all-rows="true"
:default-expanded-keys="[1]"
:loading="loading"
:columns="(cloneColumns as TableColumnData[])"
:data="renderData"
@ -183,7 +184,7 @@ import { Pagination } from '@/types/global';
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
import dayjs from 'dayjs';
import { Message } from '@arco-design/web-vue';
import { DeptRecord } from '@/api/dept';
import { DeptRecord, getAllDeptTree } from '@/api/dept';
import { useDeptStore } from '@/store';
import DeptEdit from './components/dept-edit.vue';
@ -266,12 +267,12 @@ const columns = computed<TableColumnData[]>(() => [
const fetchData = async (params?: Partial<DeptRecord>) => {
setLoading(true);
try {
const res = await deptStore.getDeptList(params);
const res = await deptStore.getAllDeptTree(1);
renderData.value = res.data.records;
pagination.page = res.data.page;
pagination.current = res.data.current;
pagination.total = res.data.total;
renderData.value = res.data;
// pagination.page = res.data.page;
// pagination.current = res.data.current;
// pagination.total = res.data.total;
} catch (err) {
// you can report use errorHandler or other
} finally {

View File

@ -30,7 +30,7 @@
{ message: '请输入用戶' },
]"
>
<a-input
<a-input-tag
v-model="formData.userIds"
placeholder='请选择用戶'
:value=formData.userIds
@ -142,13 +142,13 @@
</a-tree>
</a-card>
<a-card style="flex: 1">
<a-button type="primary" >全选</a-button>
<a-button type="primary" style="margin-bottom: 10px" @click="handleCheckAllUsers">全选</a-button>
<a-table
:data="selectedDepartmentMembers"
:columns="columns"
style="height: 520px">
<template #id="{ record }">
<a-checkbox v-model="selectedIds" :value="record.id"> </a-checkbox>
<a-checkbox v-model="selectedIds" :value="record.userId"> </a-checkbox>
</template>
<template #username="{ record }">
{{ record.username }}
@ -176,6 +176,7 @@
import { IEditorConfig } from '@wangeditor/editor'
import '@wangeditor/editor/dist/css/style.css'
import { getAllDeptTree } from '@/api/dept';
import configArcoStyleImportPlugin from '../../../../../config/plugin/arcoStyleImport';
const props = defineProps({
prem: {
@ -202,7 +203,7 @@
const messageStore = useMessageStore();
const isFullScreen = ref(false);
const mode = 'default';
const selectedIds= ref<string[]>([]);
const selectedIds= ref<number[]>([]);
const toolbarConfig = { excludeKeys: ['uploadVideo', 'insertImage','insertVideo']}
const columns = computed<any[]>(()=>[
{
@ -302,7 +303,7 @@
}
// 广
const getSelectedMembers = (treeData: any[], selectedKeys: string[]) => {
const getSelectedMembers = (treeData: any[], selectedKeys: number[]) => {
const queue:any = [...treeData];
const selectedMembers: any[] = [];
while (queue.length > 0) {
@ -322,9 +323,9 @@
//
const handleClickTree = (id: string[]) => {
const handleClickTree = (id: number[]) => {
// '1'
if (id[0] === '1' || id.length === 0) {
if (id[0] === 1 && id.length === 1) {
// 广
const allMembers: any[] = [];
const queue:any = [...deptTreeData.value];
@ -346,13 +347,13 @@
selectedDepartmentMembers.value = Members;
}
//
const handleCheckTree = (id: string[]) => {
if (id[0] === '1' ) { // '1'
const allKeys: string[] = [];
const handleCheckTree = (id: number[]) => {
if (id[0] === 1 ) { // '1'
const allKeys: number[] = [];
const traverseTree = (node: any) => {
if (node.members) {
node.members.forEach((member: any) => {
allKeys.push(member.id);
allKeys.push(member.userId);
});
}
if (node.children) {
@ -368,7 +369,7 @@
} else {
const selectedKeys = getSelectedMembers(deptTreeData.value, id);
selectedIds.value = selectedKeys.map(item => item.id);
selectedIds.value = selectedKeys.map(item => item.userId);
}
};
@ -428,6 +429,17 @@
formData.value.userIds = selectedIds.value;
};
//
const handleCheckAllUsers = () => {
if(selectedIds.value.length ===0 ) {
handleCheckTree([1]);
} else {
selectedIds.value = [];
}
};
//
const deptTreeCancel = () => {
deptVisible.value = false;