Skip to content

Commit f2f414a

Browse files
committed
Merge branch 'feature/iot' of https://gitee.com/alwayssuper/yudao-ui-admin-vue3 into feature/iot
# Conflicts: # pnpm-lock.yaml
2 parents 7639f34 + 3c7521b commit f2f414a

File tree

6 files changed

+591
-2
lines changed

6 files changed

+591
-2
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@
8787
"source.fixAll.stylelint": "explicit"
8888
},
8989
"[vue]": {
90-
"editor.defaultFormatter": "esbenp.prettier-vscode"
90+
"editor.defaultFormatter": "octref.vetur"
9191
},
9292
"i18n-ally.localesPaths": ["src/locales"],
9393
"i18n-ally.keystyle": "nested",

src/api/iot/device/device/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ export enum DeviceStatusEnum {
6363
DISABLED = 3 // 已禁用
6464
}
6565

66+
// IoT 模拟设备数据
67+
export interface SimulatorDataVO {
68+
productKey: string
69+
deviceKey: string
70+
type: string
71+
subType: string
72+
reportTime: number // 时间戳
73+
content: string // 存储 JSON 字符串
74+
}
75+
6676
// 设备 API
6777
export const DeviceApi = {
6878
// 查询设备分页
@@ -136,5 +146,14 @@ export const DeviceApi = {
136146
// 获取导入模板
137147
importDeviceTemplate: async () => {
138148
return await request.download({ url: `/iot/device/get-import-template` })
149+
},
150+
151+
// 模拟设备
152+
simulatorDevice: async (data: SimulatorDataVO) => {
153+
return await request.post({ url: `/iot/device/data/simulator`, data })
154+
},
155+
//查询设备日志分页
156+
getDeviceLogPage: async (params: any) => {
157+
return await request.get({ url: `/iot/device/data/log/page`, params })
139158
}
140159
}

src/api/iot/thingmodel/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ export interface ThingModelData {
1717
service?: ThingModelService // 服务
1818
}
1919

20+
/**
21+
* IoT 模拟设备
22+
*/
23+
export interface SimulatorData extends ThingModelData {
24+
simulateValue?: string | number // 用于存储模拟值
25+
}
26+
2027
/**
2128
* ThingModelProperty 类型
2229
*/
@@ -45,6 +52,11 @@ export const ThingModelApi = {
4552
return await request.get({ url: `/iot/thing-model/page`, params })
4653
},
4754

55+
// 获得产品物模型列表
56+
getThingModelList: async (params: any) => {
57+
return await request.get({ url: `/iot/thing-model/list`, params })
58+
},
59+
4860
// 获得产品物模型
4961
getThingModelListByProductId: async (params: any) => {
5062
return await request.get({
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<template>
2+
<ContentWrap>
3+
<!-- 搜索区域 -->
4+
<el-form :model="queryParams" inline>
5+
<el-form-item>
6+
<el-select v-model="queryParams.type" placeholder="所有" class="!w-120px">
7+
<el-option label="所有" value="" />
8+
<el-option label="状态" value="state" />
9+
<el-option label="事件" value="event" />
10+
<el-option label="属性" value="property" />
11+
<el-option label="服务" value="service" />
12+
</el-select>
13+
</el-form-item>
14+
<el-form-item>
15+
<el-input v-model="queryParams.keyword" placeholder="日志识符" class="!w-200px" />
16+
</el-form-item>
17+
<el-form-item>
18+
<el-button type="primary" @click="handleQuery">
19+
<Icon icon="ep:search" class="mr-5px" /> 搜索
20+
</el-button>
21+
<el-switch v-model="autoRefresh" class="ml-10px" /> 定时刷新
22+
</el-form-item>
23+
</el-form>
24+
25+
<!-- 日志列表 -->
26+
<el-table v-loading="loading" :data="logList" :stripe="true" class="whitespace-nowrap">
27+
<el-table-column label="时间" align="center" prop="time" width="180">
28+
<template #default="scope">
29+
{{ formatDate(scope.row.time) }}
30+
</template>
31+
</el-table-column>
32+
<el-table-column label="类型" align="center" prop="type" width="120" />
33+
<el-table-column label="名称(标识符)" align="center" prop="subType" width="120" />
34+
<el-table-column label="内容" align="center" prop="content" :show-overflow-tooltip="true" />
35+
</el-table>
36+
37+
<!-- 分页 -->
38+
<div class="mt-10px flex justify-end">
39+
<Pagination
40+
:total="total"
41+
v-model:page="queryParams.pageNo"
42+
v-model:limit="queryParams.pageSize"
43+
@pagination="getLogList"
44+
/>
45+
</div>
46+
</ContentWrap>
47+
</template>
48+
49+
<script setup lang="ts">
50+
import { DeviceApi } from '@/api/iot/device/device'
51+
import { DICT_TYPE } from '@/utils/dict'
52+
import { formatDate } from '@/utils/formatTime'
53+
54+
const props = defineProps<{
55+
deviceKey: number
56+
}>()
57+
58+
//TODO:后续看看使用什么查询条件 目前后端是留了时间范围 type subType
59+
// 查询参数
60+
const queryParams = reactive({
61+
deviceKey: props.deviceKey,
62+
// type: '',
63+
// keyword: '',
64+
pageNo: 1,
65+
pageSize: 10
66+
})
67+
68+
// 列表数据
69+
const loading = ref(false)
70+
const total = ref(0)
71+
const logList = ref([])
72+
const autoRefresh = ref(false)
73+
let timer: any = null
74+
75+
// 类型映射
76+
const typeMap = {
77+
lifetime: '生命周期',
78+
state: '设备状态',
79+
property: '属性',
80+
event: '事件',
81+
service: '服务'
82+
}
83+
84+
/** 查询日志列表 */
85+
const getLogList = async () => {
86+
if (!props.deviceKey) return
87+
loading.value = true
88+
try {
89+
const res = await DeviceApi.getDeviceLogPage(queryParams)
90+
total.value = res.total
91+
logList.value = res.list.map((item: any) => {
92+
const log = {
93+
time: item.reportTime,
94+
type: item.type,
95+
subType: item.subType,
96+
content: item.content
97+
}
98+
return log
99+
})
100+
} finally {
101+
loading.value = false
102+
}
103+
}
104+
105+
/** 获取日志名称 */
106+
const getLogName = (log: any) => {
107+
const { type, identifier } = log
108+
let name = '未知'
109+
110+
if (type === 'property') {
111+
if (identifier === 'set_reply') name = '设置回复'
112+
else if (identifier === 'report') name = '上报'
113+
else if (identifier === 'set') name = '设置'
114+
} else if (type === 'state') {
115+
name = identifier === 'online' ? '上线' : '下线'
116+
} else if (type === 'lifetime') {
117+
name = identifier === 'register' ? '注册' : name
118+
}
119+
120+
return `${name}(${identifier})`
121+
}
122+
123+
/** 搜索操作 */
124+
const handleQuery = () => {
125+
queryParams.pageNo = 1
126+
getLogList()
127+
}
128+
129+
/** 监听自动刷新 */
130+
watch(autoRefresh, (newValue) => {
131+
if (newValue) {
132+
timer = setInterval(() => {
133+
getLogList()
134+
}, 5000)
135+
} else {
136+
clearInterval(timer)
137+
timer = null
138+
}
139+
})
140+
141+
/** 监听设备ID变化 */
142+
watch(
143+
() => props.deviceKey,
144+
(newValue) => {
145+
if (newValue) {
146+
handleQuery()
147+
}
148+
}
149+
)
150+
151+
/** 组件卸载时清除定时器 */
152+
onBeforeUnmount(() => {
153+
if (timer) {
154+
clearInterval(timer)
155+
}
156+
})
157+
158+
/** 初始化 */
159+
onMounted(() => {
160+
if (props.deviceKey) {
161+
getLogList()
162+
}
163+
})
164+
</script>

0 commit comments

Comments
 (0)