diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..79cfd95 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,10 @@ +:4173 { + handle_path /prod-api/* { + reverse_proxy 192.168.1.201:1616 + } + handle { + root * /Users/ailanyin/WebstormProjects/qiaoba-ui/dist + file_server + try_files {path} / + } +} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..151aa68 --- /dev/null +++ b/env.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file diff --git a/package.json b/package.json index e35b4ef..119e3b7 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,11 @@ "@amap/amap-jsapi-loader": "^1.0.1", "@element-plus/icons-vue": "2.0.10", "@vueuse/core": "9.5.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", "axios": "0.27.2", + "chart.js": "^4.2.1", + "dayjs": "^1.11.7", "echarts": "5.4.0", "element-plus": "2.2.27", "file-saver": "2.0.5", @@ -29,9 +33,14 @@ "jsencrypt": "3.3.1", "lodash-es": "^4.17.21", "nprogress": "0.2.0", + "patternomaly": "^1.3.2", "pinia": "2.0.22", + "pinia-plugin-persistedstate": "^3.1.0", + "reconnecting-websocket": "^4.4.0", "uuid": "^9.0.0", + "v3-infinite-loading": "^1.2.2", "vue": "3.2.45", + "vue-chartjs": "^5.2.0", "vue-cropper": "1.0.3", "vue-router": "4.1.4", "vue3-json-viewer": "^2.2.2" @@ -39,8 +48,10 @@ "devDependencies": { "@vitejs/plugin-vue": "3.1.0", "@vue/compiler-sfc": "3.2.45", + "@vue/tsconfig": "^0.1.3", "prettier": "^2.8.4", "sass": "1.56.1", + "typescript": "^5.0.4", "unplugin-auto-import": "0.11.4", "vite": "3.2.3", "vite-plugin-compression": "0.5.1", diff --git a/src/api/alert/log.js b/src/api/alert/log.js new file mode 100644 index 0000000..9ece5dc --- /dev/null +++ b/src/api/alert/log.js @@ -0,0 +1,44 @@ +import request from "@/utils/request"; + +// 查询设备告警日志列表 +export function listLog(query) { + return request({ + url: "/alert/log/list", + method: "get", + params: query, + }); +} + +// 查询设备告警日志详细 +export function getLog(alertId) { + return request({ + url: "/alert/log/" + alertId, + method: "get", + }); +} + +// 新增设备告警日志 +export function addLog(data) { + return request({ + url: "/alert/log", + method: "post", + data: data, + }); +} + +// 修改设备告警日志 +export function updateLog(data) { + return request({ + url: "/alert/log", + method: "put", + data: data, + }); +} + +// 删除设备告警日志 +export function delLog(alertId) { + return request({ + url: "/alert/log/" + alertId, + method: "delete", + }); +} diff --git a/src/api/iot/device.js b/src/api/iot/device.js index 299e75e..26aba66 100644 --- a/src/api/iot/device.js +++ b/src/api/iot/device.js @@ -50,13 +50,77 @@ export function fetchOperatingStatus(deviceSn) { }); } +/** + * 查询设备物模型某一指标历史 + * @param params + * @return {*} + */ export function selectIdentifierHistory(params) { + let start_time = null; + let end_time = null; + if (params.startTime) start_time = new Date(params.startTime).getTime(); + if (params.endTime) end_time = new Date(params.endTime).getTime(); return request({ - url: `/iot/device/selectIdentifierHistory/${params.deviceSn}/${params.identifier}`, + url: `/iot/device/selectIdentifierHistory/${params.deviceSn}`, method: "GET", params: { pageNum: params.pageNum, pageSize: params.pageSize, + identifier: params.identifier, + type: params.type, + startTime: start_time, + endTime: end_time, + sort: params.sort, }, }); } + +export function setDeviceAttr(data) { + const { version, method, params } = data; + return request({ + url: `/iot/device/set/${data.productSn}/${data.deviceSn}`, + method: "post", + data: { + version, + method, + params, + }, + }); +} + +export function setDeviceInvoke(data) { + const { version, method, params } = data; + return request({ + url: `/iot/device/invoke/${data.productSn}/${data.deviceSn}`, + method: "post", + data: { + version, + method, + params, + }, + }); +} + +/** + * 属性设置日志列表 + * @param params + * @return {*} + */ +export function setPropertyLog(params) { + return request({ + url: `/device/setPropertyLog/list`, + params, + }); +} + +/** + * 服务调用日志列表 + * @return {*} + * @param params + */ +export function setFunctionLog(params) { + return request({ + url: `/device/setFunctionLog/list`, + params, + }); +} diff --git a/src/api/msg/msg.js b/src/api/msg/msg.js new file mode 100644 index 0000000..5e741ff --- /dev/null +++ b/src/api/msg/msg.js @@ -0,0 +1,29 @@ +import request from "@/utils/request"; + +// 查询消息列表 +export function listMsg(query) { + return request({ + url: "/msg/msg/list", + method: "get", + params: query, + }); +} + +// 修改消息 +export function updateMsg(msgIds, status) { + return request({ + url: `/msg/msg/${msgIds}/status`, + method: "put", + params: { + status, + }, + }); +} + +// 删除消息 +export function delMsg(msgIds) { + return request({ + url: "/msg/msg/" + msgIds, + method: "delete", + }); +} diff --git a/src/api/notice/config.js b/src/api/notice/config.js new file mode 100644 index 0000000..cd06e62 --- /dev/null +++ b/src/api/notice/config.js @@ -0,0 +1,14 @@ +import request from "@/utils/request"; + +export const msgConfig = () => + request({ + url: `/msg/config/getInfo`, + method: "GET", + }); + +export const saveConfig = (data) => + request({ + url: "/msg/config", + method: "POST", + data, + }); diff --git a/src/api/notice/template.js b/src/api/notice/template.js new file mode 100644 index 0000000..89f9c75 --- /dev/null +++ b/src/api/notice/template.js @@ -0,0 +1,44 @@ +import request from "@/utils/request"; + +// 查询通知模板列表 +export function listTemplate(query) { + return request({ + url: "/notice/template/list", + method: "get", + params: query, + }); +} + +// 查询通知模板详细 +export function getTemplate(templateId) { + return request({ + url: "/notice/template/" + templateId, + method: "get", + }); +} + +// 新增通知模板 +export function addTemplate(data) { + return request({ + url: "/notice/template", + method: "post", + data: data, + }); +} + +// 修改通知模板 +export function updateTemplate(data) { + return request({ + url: "/notice/template", + method: "put", + data: data, + }); +} + +// 删除通知模板 +export function delTemplate(templateId) { + return request({ + url: "/notice/template/" + templateId, + method: "delete", + }); +} diff --git a/src/api/product/noticeConfig.js b/src/api/product/noticeConfig.js new file mode 100644 index 0000000..8c1e257 --- /dev/null +++ b/src/api/product/noticeConfig.js @@ -0,0 +1,44 @@ +import request from "@/utils/request"; + +// 查询告警消息配置列表 +export function listNoticeConfig(query) { + return request({ + url: "/product/noticeConfig/list", + method: "get", + params: query, + }); +} + +// 查询告警消息配置详细 +export function getNoticeConfig(configId) { + return request({ + url: "/product/noticeConfig/" + configId, + method: "get", + }); +} + +// 新增告警消息配置 +export function addNoticeConfig(data) { + return request({ + url: "/product/noticeConfig", + method: "post", + data: data, + }); +} + +// 修改告警消息配置 +export function updateNoticeConfig(data) { + return request({ + url: "/product/noticeConfig", + method: "put", + data: data, + }); +} + +// 删除告警消息配置 +export function delNoticeConfig(configId) { + return request({ + url: "/product/noticeConfig/" + configId, + method: "delete", + }); +} diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss index 3ac74c2..d3109df 100644 --- a/src/assets/styles/element-ui.scss +++ b/src/assets/styles/element-ui.scss @@ -101,6 +101,12 @@ border-radius: 6px; .el-radio-button { + &:first-child { + } + + &:last-child { + } + .el-radio-button__inner { background-color: transparent; border: none; @@ -118,3 +124,29 @@ } } } + +.custom-table-style { + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + border-radius: 8px; + //border: 1px solid rgb(226 232 240); + border: none; + + .el-table__inner-wrapper { + //overflow: hidden; + //box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + + &::before { + display: none; + } + + .el-table__header-wrapper th { + background-color: #fbfbfb !important; + } + + .el-table__row:last-child { + td.el-table__cell { + border-bottom: none; + } + } + } +} diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss index c3d14a2..769e104 100644 --- a/src/assets/styles/sidebar.scss +++ b/src/assets/styles/sidebar.scss @@ -111,6 +111,7 @@ } } + /* rounded menu indicator */ & .router-link-active:not(.sidebar-logo-link) { position: relative; @@ -136,10 +137,8 @@ top: 50%; border-radius: 28px; box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), - 0 2px 4px -2px rgb(0 0 0 / 0.1), inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + 0 2px 4px -2px rgb(0 0 0 / 0.1); } - - //background-color: aliceblue; } } diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue new file mode 100644 index 0000000..29d2e01 --- /dev/null +++ b/src/components/Editor/index.vue @@ -0,0 +1,168 @@ + + + + + + + + + diff --git a/src/components/MapSelect/index.vue b/src/components/MapSelect/index.vue index a1993fe..0079bbe 100644 --- a/src/components/MapSelect/index.vue +++ b/src/components/MapSelect/index.vue @@ -1,5 +1,5 @@ - + + diff --git a/src/components/NotificationCenter/index.vue b/src/components/NotificationCenter/index.vue new file mode 100644 index 0000000..0874dc4 --- /dev/null +++ b/src/components/NotificationCenter/index.vue @@ -0,0 +1,465 @@ + + + + + + + + + + + + + + + + + + + 未读 + 已读 + + + + + {{ selectMulti ? "取消" : "选择" }} + + 删除 + + 标为已读 + + 刷新 + + + + + + + + + + + {{ "" }} + + + {{ + item.msgTitle + }} + {{ dayjs(item.sendTime).format("YYYY-MM-DD HH:mm:ss") }} + + + + + + + + 没有更多 + + + + + + + + + + + + + {{ msgDetail.msgContent }} + + + + + + + + diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue index 8200733..ffd46f0 100644 --- a/src/components/Pagination/index.vue +++ b/src/components/Pagination/index.vue @@ -1,12 +1,13 @@ props.total) { currentPage.value = 1; @@ -85,6 +90,7 @@ function handleSizeChange(val) { scrollTo(0, 800); } } + function handleCurrentChange(val) { emit("pagination", { page: val, limit: pageSize.value }); if (props.autoScroll) { @@ -98,6 +104,7 @@ function handleCurrentChange(val) { background: #fff; padding: 32px 16px; } + .pagination-container.hidden { display: none; } diff --git a/src/constant/dict.js b/src/constant/dict.js index 1a75237..4223c2d 100644 --- a/src/constant/dict.js +++ b/src/constant/dict.js @@ -58,7 +58,7 @@ export const modelTypeDict = [ elTagType: "success", }, { - label: "功能", + label: "服务", value: 2, elTagType: "warning", }, @@ -113,9 +113,9 @@ export const locationWayMap = [ // 1-未激活,2-禁用,3-在线,4-离线 export const deviceStatusMap = [ { - label: "未激活", + label: "启用", value: 1, - elTagType: "info", + elTagType: "success", }, { label: "禁用", @@ -210,8 +210,116 @@ export const setFunctionLogStatusDict = [ elTagType: "success", }, { - label: "未知", + label: "失败", value: "2", elTagType: "danger", }, ]; + +export const setPropertyLogStatusDict = [ + { + label: "未回复", + value: "0", + elTagType: "info", + }, + { + label: "成功", + value: "1", + elTagType: "success", + }, + { + label: "失败", + value: "2", + elTagType: "danger", + }, +]; + +export const deviceOnlineStatusDict = [ + { + label: "上线", + value: "4", + elTagType: "success", + }, + { + label: "下线", + value: "5", + elTagType: "danger", + }, +]; + +export const notificationTemplateState = [ + { + label: "停用", + value: "0", + elTagType: "danger", + }, + { + label: "正常", + value: "1", + elTagType: "success", + }, +]; + +export const noticeTypeDict = [ + { + label: "站内", + value: "1", + elTagType: "danger", + }, + { + label: "短信", + value: "2", + elTagType: "success", + }, + { + label: "邮件", + value: "3", + elTagType: "warning", + }, +]; + +export const msgTypeDict = [ + { + label: "阿里云", + value: "1", + fieldPrefix: "a", + elTagType: "danger", + }, + { + label: "腾讯云", + value: "2", + fieldPrefix: "b", + elTagType: "success", + }, +]; + +export const deviceAlertLogDict = [ + { + label: "待处理", + value: "0", + elTagType: "warning", + }, + { + label: "处理成功", + value: "1", + elTagType: "success", + }, + { + label: "处理失败", + value: "2", + elTagType: "danger", + }, +]; + +export const noticeStatusDict = [ + { + label: "停用", + value: "1", + elTagType: "danger", + }, + { + label: "正常", + value: "0", + elTagType: "success", + }, +]; diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index 59ac6bf..f7d7538 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -7,18 +7,19 @@ @toggleClick="toggleSideBar" /> + @@ -29,13 +30,15 @@ - + + + @@ -45,7 +48,7 @@ 布局设置 - + 退出登录 @@ -64,11 +67,10 @@ import Hamburger from "@/components/Hamburger"; import Screenfull from "@/components/Screenfull"; import SizeSelect from "@/components/SizeSelect"; import HeaderSearch from "@/components/HeaderSearch"; -import RuoYiGit from "@/components/RuoYi/Git"; -import RuoYiDoc from "@/components/RuoYi/Doc"; import useAppStore from "@/store/modules/app"; import useUserStore from "@/store/modules/user"; import useSettingsStore from "@/store/modules/settings"; +import NotificationCenter from "@/components/NotificationCenter"; const appStore = useAppStore(); const userStore = useUserStore(); @@ -106,6 +108,7 @@ function logout() { } const emits = defineEmits(["setLayout"]); + function setLayout() { emits("setLayout"); } diff --git a/src/main.js b/src/main.js index 6b60ea1..8f00b3b 100644 --- a/src/main.js +++ b/src/main.js @@ -46,6 +46,10 @@ import TreeSelect from "@/components/TreeSelect"; // 字典标签组件 import DictTag from "@/components/DictTag"; +// import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +// pinia.use(piniaPluginPersistedstate) + window._AMapSecurityConfig = { securityJsCode: "2b65e7751cb17e4605f4c4cdccf885f6", }; diff --git a/src/store/index.js b/src/store/index.js index 069d54e..f65df8b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,3 +1,6 @@ +import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; + const store = createPinia(); +store.use(piniaPluginPersistedstate); export default store; diff --git a/src/store/modules/notification.js b/src/store/modules/notification.js new file mode 100644 index 0000000..e7a5b51 --- /dev/null +++ b/src/store/modules/notification.js @@ -0,0 +1,46 @@ +import { defineStore } from "pinia"; +import { cloneDeep } from "lodash-es"; + +const useNotificationStore = defineStore("notification", { + state: () => ({ + unreadList: [], + }), + actions: { + pushItem(row) { + const _row = cloneDeep(row); + const isNotExisted = this.unreadList.every( + (el) => el.msgId !== _row.msgId + ); + if (isNotExisted) { + this.unreadList.unshift(_row); + } + }, + pushItems(rows) { + for (const row of rows) { + const _row = cloneDeep(row); + const isNotExisted = this.unreadList.every( + (el) => el.msgId !== _row.msgId + ); + if (isNotExisted) { + this.unreadList.push(_row); + } + } + }, + removeItem(id) { + this.unreadList = this.unreadList.filter((el) => el.msgId !== id); + }, + }, + getters: { + getList: (state) => { + return (params) => + state.unreadList.slice( + (params.pageNum - 1) * params.pageSize + 1, + (params.pageNum - 1) * params.pageSize + 1 + params.pageSize + ); + }, + unreadCount: (state) => state.unreadList.length, + }, + persist: true, +}); + +export default useNotificationStore; diff --git a/src/store/modules/user.js b/src/store/modules/user.js index 43a4e5d..58ecee4 100644 --- a/src/store/modules/user.js +++ b/src/store/modules/user.js @@ -1,6 +1,7 @@ -import { login, logout, getInfo } from "@/api/login"; -import { getToken, setToken, removeToken } from "@/utils/auth"; +import { getInfo, login, logout } from "@/api/login"; +import { getToken, removeToken, setToken } from "@/utils/auth"; import defAva from "@/assets/images/profile.jpg"; +import { v4 as uuidv4 } from "uuid"; const useUserStore = defineStore("user", { state: () => ({ @@ -8,7 +9,9 @@ const useUserStore = defineStore("user", { name: "", avatar: "", roles: [], + userId: null, permissions: [], + uniqueId: "" }), actions: { // 登录 @@ -47,8 +50,11 @@ const useUserStore = defineStore("user", { } else { this.roles = ["ROLE_DEFAULT"]; } + this.userId = user.userId; this.name = user.userName; this.avatar = avatar; + const uniqueId = uuidv4(); + this.uniqueId = uniqueId; resolve(res); }) .catch((error) => { @@ -71,8 +77,11 @@ const useUserStore = defineStore("user", { reject(error); }); }); - }, + } }, + persist: { + paths: ["uniqueId"] + } }); export default useUserStore; diff --git a/src/utils/index.js b/src/utils/index.js index 4490f41..c6812d3 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -392,3 +392,18 @@ export function camelCase(str) { export function isNumberStr(str) { return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str); } + +/** + * 生成随机字符串 + * @param length + * @return {string} + */ +export const generateRandomString = (length) => { + const characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +}; diff --git a/src/utils/test.js b/src/utils/test.js new file mode 100644 index 0000000..c9d2295 --- /dev/null +++ b/src/utils/test.js @@ -0,0 +1,6 @@ +const parseStr = (str) => + str.split(",").map((el) => ({ + type: el.split(":")[0], + template: el.split(":")[1], + user: el.split(":")[2], + })); diff --git a/src/views/alert/log/index.vue b/src/views/alert/log/index.vue new file mode 100644 index 0000000..d55d67a --- /dev/null +++ b/src/views/alert/log/index.vue @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + + + + + + + + + + + + + + + + + + + + + + + + + + 删除 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ row.happenTime }} + + + + + + + + + + + {{ row.handleTime }} + + + + + + 处理 + + 删除 + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/views/device/group/index.vue b/src/views/device/group/index.vue index e2caaac..cd32b10 100644 --- a/src/views/device/group/index.vue +++ b/src/views/device/group/index.vue @@ -92,6 +92,7 @@ diff --git a/src/views/iforgot.vue b/src/views/iforgot.vue index 7ba30eb..ff691a9 100644 --- a/src/views/iforgot.vue +++ b/src/views/iforgot.vue @@ -18,15 +18,15 @@ style="width: 50%; margin-top: 20px" type="primary" @click="activeIndex = 1" - >下一步 + >下一步 + 验证身份 第三部 - + + + diff --git a/src/views/iot/device/detail-panes/OperatingStatus.vue b/src/views/iot/device/detail-panes/OperatingStatus.vue index 55e2043..0639458 100644 --- a/src/views/iot/device/detail-panes/OperatingStatus.vue +++ b/src/views/iot/device/detail-panes/OperatingStatus.vue @@ -1,17 +1,27 @@ - + + 属性 + 事件 + 服务 + + + + + + - 属性 - 事件 - - 历史 - 下发 + 下发 + + 调用 + + 下发日志 + + + + + 调用日志 + + + + + + + + + + 图表 + 列表 + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + {{ row.msg ?? "-" }} + + + + + + {{ row.returnTime ?? "-" }} + + + + + + + + + + + + + + + + + + {{ row.msg ?? "-" }} + + + + + + {{ row.returnTime ?? "-" }} + + + + + @@ -71,52 +342,160 @@ import { reactive, ref, toRefs, watchEffect } from "vue"; import { fetchOperatingStatus, selectIdentifierHistory, + setDeviceAttr, + setDeviceInvoke, + setFunctionLog, + setPropertyLog, } from "@/api/iot/device"; -import { listModel } from "@/api/thingsmodel/model"; +import { ElMessage, ElMessageBox } from "element-plus"; +import { Line } from "vue-chartjs"; +import { + CategoryScale, + Chart as ChartJS, + Legend, + LinearScale, + LineElement, + PointElement, + Title, + Tooltip, +} from "chart.js"; +import DictTag from "@/components/DictTag/index.vue"; +import { + setFunctionLogStatusDict, + setPropertyLogStatusDict, +} from "@/constant/dict"; +import SvgIcon from "@/components/SvgIcon/index.vue"; +import { SemiSelect } from "@element-plus/icons-vue"; + +ChartJS.register( + Title, + Tooltip, + PointElement, + Legend, + LineElement, + CategoryScale, + LinearScale +); const props = defineProps({ deviceSn: { type: String, + required: true, }, - productId: { - type: Number, + productSn: { + type: String, + required: true, + }, + + modelList: { + type: Array, + required: true, }, }); -const { deviceSn, productId } = toRefs(props); +const { deviceSn, productSn, modelList } = toRefs(props); const modelType = ref(1); +const historyType = ref("chart"); // chart || list const dataList = ref([]); -const modelList = ref([]); +// const modelList = ref([]); const showHistoryDialog = ref(false); const historyList = ref([]); const historyLoading = ref(false); -const historyTotal = ref(0); +const historyTotal = ref(0); /*历史记录总数*/ +const loading = ref(false); +const activeRow = ref(); /*需要查看日志的行*/ + +const showPropertyLog = ref(false); /*显示设备属性设置日志*/ +const propertyLoading = ref(false); /*设备属性设置日志列表是否正在加载*/ +const propertyList = ref([]); /*设备属性设置日志列表*/ +const propertyLogTotal = ref(0); /*设备属性设置日志总数*/ + +const showInvokeLog = ref(false); /*是否显示调用日志*/ +const invokeLogLoading = ref(false); /*加载状态*/ +const invokeLogList = ref([]); /*服务调用日志列表*/ +const invokeLogTotal = ref(0); + const data = reactive({ - queryParams: { + historyQueryParams: { pageSize: 10, pageNum: 1, identifier: "", deviceSn: "", + sort: 2, + }, + propertyLogQueryParams: { + pageSize: 10, + pageNum: 1, + // setPropertyLog: { + deviceSn: deviceSn.value, + productSn: productSn.value, + setKey: null, + // } + }, + invokeLogQueryParams: { + pageSize: 10, + pageNum: 1, + // setFunctionLog: { + deviceSn: deviceSn.value, + productSn: productSn.value, + setKey: null, + // } }, }); -const { queryParams } = toRefs(data); +const { historyQueryParams, propertyLogQueryParams, invokeLogQueryParams } = + toRefs(data); +/** + * + * @param date + */ +const isAfterThanEndTime = (date) => { + const date_str = `${date.getFullYear()}-${ + date.getMonth() + 1 + }-${date.getDate()} 00:00:00`; + const _date = new Date(date_str).getTime(); + return ( + historyQueryParams.value.endTime && + _date > + new Date( + historyQueryParams.value.endTime.split(" ")[0] + " 00:00:00" + ).getTime() + ); +}; +const isBeforeThanStartTime = (date) => { + const date_str = `${date.getFullYear()}-${ + date.getMonth() + 1 + }-${date.getDate()} 00:00:00`; + const _date = new Date(date_str).getTime(); + return ( + historyQueryParams.value.startTime && + _date < + new Date( + historyQueryParams.value.startTime.split(" ")[0] + " 00:00:00" + ).getTime() + ); +}; const getHistoryList = () => { historyLoading.value = true; - selectIdentifierHistory(queryParams.value) + selectIdentifierHistory(historyQueryParams.value) .then((resp) => { historyList.value = resp.data.list; historyLoading.value = false; + historyTotal.value = resp.data.total; }) .catch(() => { historyLoading.value = false; }); }; -const handleShowHistory = (identifier) => { + +const handleShowHistory = (row) => { + activeRow.value = row; showHistoryDialog.value = true; - queryParams.value.identifier = identifier; - queryParams.value.deviceSn = deviceSn.value; + historyQueryParams.value.identifier = row.identifier; + historyQueryParams.value.deviceSn = deviceSn.value; + historyQueryParams.value.type = row.type; + getHistoryList(); }; // 获取运行状态 @@ -131,18 +510,148 @@ watchEffect(() => { getOperatingStatus(); }); // 获取物模型列表 -const getThingsModel = () => { - if (productId.value) { - listModel({ - productId: productId.value, - }).then((resp) => { - modelList.value = resp.rows?.filter((el) => el.type !== 2) ?? []; +// const getThingsModel = () => { +// if (productId.value) { +// loading.value = true; +// listModel({ +// productId: productId.value +// }).then((resp) => { +// modelList.value = resp.rows ?? []; +// loading.value = false; +// }); +// } +// }; + +/** + * 设置单个设备属性 + * @param identifier + */ +const handleSetDeviceAttr = (identifier) => { + ElMessageBox.prompt("请输入最新的值", "下发", { + confirmButtonText: "确认", + cancelButtonText: "取消", + inputPattern: /\S+/, + }).then(async ({ value }) => { + await setDeviceAttr({ + deviceSn: deviceSn.value, + productSn: productSn.value, + version: "1.0", + method: "thing.property.set", + params: { + [identifier]: value, + }, }); - } + getOperatingStatus(); + ElMessage.success("下发成功"); + }); }; + +/** + * 调用单个设备服务 + * @param identifier + */ +const handleSetDeviceInvoke = (identifier) => { + ElMessageBox.prompt("请输入最新的值", "下发", { + confirmButtonText: "确认", + cancelButtonText: "取消", + inputPattern: /\S+/, + }).then(async ({ value }) => { + await setDeviceInvoke({ + deviceSn: deviceSn.value, + productSn: productSn.value, + version: "1.0", + method: "thing.property.set", + params: { + [identifier]: value, + }, + }); + getOperatingStatus(); + ElMessage.success("下发成功"); + }); +}; + +/** + * 打开服务调用日志 + * @param row + */ +const openInvokeLog = (row) => { + activeRow.value = row; + invokeLogQueryParams.value.setKey = row.identifier; + showInvokeLog.value = true; +}; + +/** + * 打开属性设置日志 + * @param row + */ +const openPropertyLog = (row) => { + activeRow.value = row; + propertyLogQueryParams.value.setKey = row.identifier; + showPropertyLog.value = true; +}; + +/** + * 获取属性设置日志 + * @return {Promise} + */ +const getPropertyLogList = async () => { + propertyLoading.value = true; + const resp = await setPropertyLog(propertyLogQueryParams.value); + propertyList.value = resp.rows; + propertyLogTotal.value = resp.total; + propertyLoading.value = false; +}; + +/** + * 获取服务调用日志 + * @return {Promise} + */ +const getInvokeLogList = async () => { + invokeLogLoading.value = true; + const resp = await setFunctionLog(invokeLogQueryParams.value); + invokeLogList.value = resp.rows; + invokeLogTotal.value = resp.total; + invokeLogLoading.value = false; +}; + watchEffect(() => { - getThingsModel(); + // getThingsModel(); }); - + diff --git a/src/views/iot/device/detail-panes/UpgradeLog.vue b/src/views/iot/device/detail-panes/UpgradeLog.vue index fa6d8c8..92c00fd 100644 --- a/src/views/iot/device/detail-panes/UpgradeLog.vue +++ b/src/views/iot/device/detail-panes/UpgradeLog.vue @@ -1,7 +1,19 @@ - + + + + + - + diff --git a/src/views/iot/device/detail.vue b/src/views/iot/device/detail.vue index 59cf89c..d41bfc9 100644 --- a/src/views/iot/device/detail.vue +++ b/src/views/iot/device/detail.vue @@ -11,6 +11,22 @@ label-position="left" label-width="140px" > + + + + + 自动生成 + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + - - - - - - - - - + + - - + - - - 编辑 + + 编辑 + + - + @@ -153,7 +152,6 @@ diff --git a/src/views/iot/device/index.vue b/src/views/iot/device/index.vue index 0fa0f45..9a370b0 100644 --- a/src/views/iot/device/index.vue +++ b/src/views/iot/device/index.vue @@ -189,17 +189,17 @@ >删除 - - 导出 - - + + + + + + + + + + + @@ -218,7 +219,7 @@ - + - - - {{ locationWayMap.find((el) => el.value === row.locationWay)?.label }} - - + + + + + + + - - - {{ parseTime(scope.row.activeTime, "{y}-{m}-{d}") }} - - + + + + + + + + + + @@ -291,7 +302,7 @@ type="primary" @click="handleDetail(scope.row)" > - 修改 + 详情 + + + + 自动生成 + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + @@ -461,7 +412,13 @@ - + + + + - - - - - - - - - - - - - - --> + + + + + + + + + + + + + + + + + + + + + + + + +