refactor(iot): 优化设备管理功能

- 修改设备编辑功能,将"修改"改为"编辑"
- 优化设备搜索功能,支持按产品名称搜索
-完善设备详情页面,显示设备状态
- 调整路由配置,增加设备详情路由
This commit is contained in:
Kven 2025-02-25 16:37:41 +08:00
parent 6f99833fe5
commit 2bc05aaea8
29 changed files with 106 additions and 63 deletions

View File

@ -61,7 +61,7 @@ export function createDevice(data: DeviceCreateRecord) {
return axios.post(`/api/rest/device`, data); return axios.post(`/api/rest/device`, data);
} }
// 修改 // 编辑
export function updateDevice(data: DeviceUpdateRecord) { export function updateDevice(data: DeviceUpdateRecord) {
return axios.patch(`/api/rest/device/${data.id}`, data); return axios.patch(`/api/rest/device/${data.id}`, data);
} }

View File

@ -57,7 +57,7 @@ export function createProduct(data: ProductCreateRecord) {
return axios.post(`/api/rest/product`, data); return axios.post(`/api/rest/product`, data);
} }
// 修改 // 编辑
export function updateProduct(data: ProductUpdateRecord) { export function updateProduct(data: ProductUpdateRecord) {
return axios.patch(`/api/rest/product/${data.id}`, data); return axios.patch(`/api/rest/product/${data.id}`, data);
} }

View File

@ -78,7 +78,7 @@
} }
} }
// //
async function readMessage(data: MessageListType) { async function readMessage(data: MessageListType) {
const ids = data.map((item) => item.messageId); const ids = data.map((item) => item.messageId);
await useMessageStore.setMessageStatus(ids); await useMessageStore.setMessageStatus(ids);
@ -104,7 +104,7 @@
const list = getUnreadList(type); const list = getUnreadList(type);
return list.length ? `(${list.length})` : ``; return list.length ? `(${list.length})` : ``;
}; };
// //
const handleItemClick = (items: MessageListType) => { const handleItemClick = (items: MessageListType) => {
if (renderList.value.length) readMessage([...items]); if (renderList.value.length) readMessage([...items]);
}; };

View File

@ -73,6 +73,19 @@ const IOT: AppRouteRecordRaw = {
permissions: ['iot:device:query'], permissions: ['iot:device:query'],
}, },
}, },
{
path: 'cardDevice/:id',
name: 'cardDeviceDetail',
component: () =>
import('@/views/iot/deviceCard/components/device-detail.vue'),
meta: {
locale: '设备详情',
title: '设备详情',
requiresAuth: true,
showInMenu: false,
permissions: ['iot:device:query'],
},
},
{ {
path: 'product/tsl/:id', path: 'product/tsl/:id',
name: 'productTsl', name: 'productTsl',

View File

@ -41,7 +41,7 @@
style="padding-top: 20px" style="padding-top: 20px"
> >
<a-tab-pane key="1" tab="参数" title="扩展属性"> <a-tab-pane key="1" tab="参数" title="扩展属性">
<a-table :columns="columns" :data="renderData.extendParams" /> <a-table :columns="columns" :data="renderData.params" />
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" tab="基本信息" title="基本信息"> <a-tab-pane key="2" tab="基本信息" title="基本信息">
基本信息 基本信息

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
@ -32,7 +32,7 @@
:model="formData" :model="formData"
:style="{ width: '800px', height: '420px' }" :style="{ width: '800px', height: '420px' }"
> >
<!-- 产品id --> <!-- 产品名称 -->
<a-form-item <a-form-item
field="productName" field="productName"
label="产品名称" label="产品名称"
@ -135,8 +135,7 @@
<template #footer> <template #footer>
<a-button class="editor-button" @click="handleCancel">取消</a-button> <a-button class="editor-button" @click="handleCancel">取消</a-button>
<a-button class="editor-button" type="primary" @click="handleSubmit" <a-button class="editor-button" type="primary" @click="handleSubmit">确定</a-button
>确定</a-button
> >
</template> </template>
</a-modal> </a-modal>
@ -319,7 +318,7 @@
const res = await updateDevice(formData.value); const res = await updateDevice(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
emit('refresh'); emit('refresh');

View File

@ -30,13 +30,20 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="9"> <a-col :span="9">
<a-form-item field="status" label="所属产品"> <a-form-item field="productName" label="所属产品">
<a-select <a-select
v-model="formModel.productName" v-model="formModel.productName"
:loading="loading"
:filter-option="false"
allow-search
style="width: 360px" style="width: 360px"
placeholder="请选择所属产品" placeholder="请选择所属产品"
:options="productOptions" @search="handleSearch"
/> >
<a-option v-for="item of options" :key="item.id" :value="item.name">{{
item.name
}}</a-option>
</a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="10"> <a-col :span="10">
@ -163,6 +170,9 @@
<template #id="{ record }"> <template #id="{ record }">
<span>{{ record.id }}</span> <span>{{ record.id }}</span>
</template> </template>
<template #state="{ record }">
{{ record.state == "UNACTIVATED" ? '未激活' : '激活'}}
</template>
<template #online="{ record }"> <template #online="{ record }">
{{ record.online == true ? '是' : '否' }} {{ record.online == true ? '是' : '否' }}
</template> </template>
@ -224,7 +234,7 @@
import useTableOption from '@/hooks/table-option'; import useTableOption from '@/hooks/table-option';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { deleteDevice, DeviceRecord, queryDeviceList } from '@/api/device'; import { deleteDevice, DeviceRecord, queryDeviceByName, queryDeviceList } from '@/api/device';
import DeviceEdit from '@/views/iot/device/components/device-edit.vue'; import DeviceEdit from '@/views/iot/device/components/device-edit.vue';
const generateFormModel = () => { const generateFormModel = () => {
@ -296,14 +306,7 @@
value: 'false', value: 'false',
}, },
]); ]);
const productOptions = computed(() => { const options = ref<any>([]);
return [
{
label: '全部',
value: '',
},
];
});
// //
const fetchData = async (params = { size: 10, current: 1 }) => { const fetchData = async (params = { size: 10, current: 1 }) => {
@ -327,6 +330,30 @@
} as unknown as DeviceRecord); } as unknown as DeviceRecord);
}; };
//
const handleSearch = (value: any) => {
if (value) {
loading.value = true;
options.value = [];
window.setTimeout(async () => {
const res = await queryDeviceByName({
name: value,
page: 1,
size: 5,
});
options.value = res.data.records.map((item: any) => {
return {
id: item.id,
name: item.name,
};
});
loading.value = false;
}, 1000);
} else {
options.value = [];
}
};
// //
const onPageChange = (current: number) => { const onPageChange = (current: number) => {
pagination.value.page = current; pagination.value.page = current;

View File

@ -81,10 +81,12 @@
default: '', default: '',
}, },
}); });
const emit = defineEmits(['search']);
// //
function openDetail(id: number): void { function openDetail(id: number): void {
const url = router.resolve({ const url = router.resolve({
name: 'deviceDetail', name: 'cardDeviceDetail',
params: { id }, params: { id },
}).href; }).href;
router.push(url); router.push(url);
@ -97,6 +99,7 @@
content: '删除成功', content: '删除成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
emit('search');
} }
}; };
</script> </script>

View File

@ -40,7 +40,7 @@
style="padding-top: 20px" style="padding-top: 20px"
> >
<a-tab-pane key="1" tab="参数" title="扩展属性"> <a-tab-pane key="1" tab="参数" title="扩展属性">
<a-table :columns="columns" :data="renderData.extendParams" /> <a-table :columns="columns" :data="renderData.params" />
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" tab="基本信息" title="基本信息"> <a-tab-pane key="2" tab="基本信息" title="基本信息">
基本信息 基本信息

View File

@ -35,7 +35,7 @@
@click="handleClick" @click="handleClick"
> >
<!-- <template #icon><icon-edit /></template>--> <!-- <template #icon><icon-edit /></template>-->
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
@ -344,7 +344,7 @@
const res = await updateDevice(formData.value); const res = await updateDevice(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
emit('refresh'); emit('refresh');

View File

@ -90,6 +90,7 @@
:title="item.name" :title="item.name"
:productName="item.productName" :productName="item.productName"
:createTime="item.createTime" :createTime="item.createTime"
@search="search"
open-txt="详情" open-txt="详情"
> >
<template #skeleton> <template #skeleton>

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
@ -328,7 +328,7 @@
const res = await updateProduct(formData.value); const res = await updateProduct(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
emit('refresh'); emit('refresh');

View File

@ -41,7 +41,7 @@
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" title="服务"> <a-tab-pane key="2" title="服务">
<a-button <a-button
v-permission="['iot:serve:create']" v-permission="['iot:server:create']"
type="primary" type="primary"
style="margin-bottom: 10px" style="margin-bottom: 10px"
@click="handleClick" @click="handleClick"
@ -52,7 +52,7 @@
<a-table :columns="columns" :data="serveData"> <a-table :columns="columns" :data="serveData">
<template #operation="{ record }"> <template #operation="{ record }">
<a-button <a-button
v-permission="['iot:serve:delete']" v-permission="['iot:server:delete']"
type="outline" type="outline"
status="danger" status="danger"
size="small" size="small"

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
@ -237,7 +237,7 @@
const res = await bulletinStore.updateBulletin(formData.value); const res = await bulletinStore.updateBulletin(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
emit('refresh'); emit('refresh');

View File

@ -404,12 +404,12 @@
const res = await bulletinStore.toggleBulletin(record.id); const res = await bulletinStore.toggleBulletin(record.id);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改置顶成功', content: '编辑置顶成功',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} else { } else {
Message.error({ Message.error({
content: '修改置顶失败', content: '编辑置顶失败',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} }

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal

View File

@ -11,7 +11,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
width="700px" width="700px"

View File

@ -283,13 +283,13 @@
const res = await authStore.enabledAuth(record.id); const res = await authStore.enabledAuth(record.id);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 3 * 1000, duration: 3 * 1000,
}); });
search(); search();
} else { } else {
Message.error({ Message.error({
content: '修改失败', content: '编辑失败',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} }

View File

@ -28,10 +28,10 @@ export default {
'Confirm the deletion of this role': '确认删除此角色?', 'Confirm the deletion of this role': '确认删除此角色?',
'modify.status.sucess': '修改状态成功', 'modify.status.sucess': '编辑状态成功',
'modify.status.fail': '修改状态失败', 'modify.status.fail': '编辑状态失败',
// modalTitle // modalTitle
'createRole': '新增角色', 'createRole': '新增角色',
'editRole': '修改角色信息', 'editRole': '编辑角色信息',
}; };

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
width="700px" width="700px"

View File

@ -25,5 +25,5 @@ export default {
// modalTitle // modalTitle
'createDept': '新增部门', 'createDept': '新增部门',
'editDept': '修改部门信息', 'editDept': '编辑部门信息',
}; };

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
width="700px" width="700px"
@ -198,7 +198,7 @@
const res = await updateMenu(formData.value); const res = await updateMenu(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
} }

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
width="700px" width="700px"

View File

@ -301,12 +301,12 @@
const res = await roleStore.enabledRole(record.id); const res = await roleStore.enabledRole(record.id);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} else { } else {
Message.error({ Message.error({
content: '修改失败', content: '编辑失败',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} }

View File

@ -28,10 +28,10 @@ export default {
'Confirm the deletion of this role': '确认删除此角色?', 'Confirm the deletion of this role': '确认删除此角色?',
'modify.status.sucess': '修改状态成功', 'modify.status.sucess': '编辑状态成功',
'modify.status.fail': '修改状态失败', 'modify.status.fail': '编辑状态失败',
// modalTitle // modalTitle
'createRole': '新增角色', 'createRole': '新增角色',
'editRole': '修改角色信息', 'editRole': '编辑角色信息',
}; };

View File

@ -17,7 +17,7 @@
@click="handleClick" @click="handleClick"
> >
<template #icon><icon-edit /></template> <template #icon><icon-edit /></template>
修改 编辑
</a-button> </a-button>
<a-modal <a-modal
@ -201,9 +201,9 @@
setVisible(true); setVisible(true);
}; };
// //
const diffDataForm = (newData: any, oldData: any) => { const diffDataForm = (newData: any, oldData: any) => {
const result = {}; // const result = {}; //
Object.keys(oldData).forEach((key) => { Object.keys(oldData).forEach((key) => {
if (oldData[key] !== newData[key]) { if (oldData[key] !== newData[key]) {
result[key] = newData[key]; result[key] = newData[key];
@ -241,7 +241,7 @@
// const res = await userStore.updateUser(formData.value); // const res = await userStore.updateUser(formData.value);
// if (res.status === 200) { // if (res.status === 200) {
// Message.success({ // Message.success({
// content: '', // content: '',
// duration: 5 * 1000, // duration: 5 * 1000,
// }); // });
// } // }
@ -249,7 +249,7 @@
const res = await userStore.updateUser(formData.value); const res = await userStore.updateUser(formData.value);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改成功', content: '编辑成功',
duration: 5 * 1000, duration: 5 * 1000,
}); });
} }

View File

@ -405,12 +405,12 @@
const res = await userStore.enabledUser(record.id); const res = await userStore.enabledUser(record.id);
if (res.status === 200) { if (res.status === 200) {
Message.success({ Message.success({
content: '修改状态成功', content: '编辑状态成功',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} else { } else {
Message.error({ Message.error({
content: '修改状态失败', content: '编辑状态失败',
duration: 3 * 1000, duration: 3 * 1000,
}); });
} }

View File

@ -37,8 +37,8 @@ export default {
'searchTable.actions.columnSetting': '列设置', 'searchTable.actions.columnSetting': '列设置',
// modify // modify
'modify.user.info.sucess': '修改成功', 'modify.user.info.sucess': '编辑成功',
'modify.user.info.fail': '修改失败', 'modify.user.info.fail': '编辑失败',
'user.info.username': '用户名', 'user.info.username': '用户名',
'user.info.username.placeholder': '请输入用户名', 'user.info.username.placeholder': '请输入用户名',
@ -69,5 +69,5 @@ export default {
// modalTitle // modalTitle
'createUser': '新增用户', 'createUser': '新增用户',
'editUser': '修改用户信息', 'editUser': '编辑用户信息',
}; };

View File

@ -58,9 +58,9 @@ export default {
'userSetting.SecuritySettings.placeholder.email': 'userSetting.SecuritySettings.placeholder.email':
'您暂未设置邮箱,绑定邮箱可以用来找回密码、接收通知等。', '您暂未设置邮箱,绑定邮箱可以用来找回密码、接收通知等。',
'userSetting.SecuritySettings.button.settings': '设置', 'userSetting.SecuritySettings.button.settings': '设置',
'userSetting.SecuritySettings.button.update': '修改', 'userSetting.SecuritySettings.button.update': '编辑',
'userSetting.certification.title.enterprise': '企业实名认证', 'userSetting.certification.title.enterprise': '企业实名认证',
'userSetting.certification.extra.enterprise': '修改认证主体', 'userSetting.certification.extra.enterprise': '编辑认证主体',
'userSetting.certification.label.accountType': '账号类型', 'userSetting.certification.label.accountType': '账号类型',
'userSetting.certification.label.status': '认证状态', 'userSetting.certification.label.status': '认证状态',
'userSetting.certification.label.time': '认证时间', 'userSetting.certification.label.time': '认证时间',