Quellcode durchsuchen

feat: 消息通知

lvkun996 vor 2 Jahren
Ursprung
Commit
aeda46eaad

+ 88 - 0
src/api/iot/sys.ts

@@ -0,0 +1,88 @@
+import request from '@/service/request'
+
+/**
+ * 获取账户的系统配置
+ * @returns
+ */
+export const getSysConf = () => {
+  return request<IOT.API.SYS.Sys>({
+    url: '/sysConf',
+    method: 'GET'
+  })
+}
+
+/**
+ * 修改账户配置
+ * @returns
+ */
+export const updateSysConf = (data: IOT.API.SYS.Sys) => {
+  return request<string>({
+    url: '/sysConf',
+    method: 'PUT',
+    data
+  })
+}
+
+/**
+ * 查询通知方式列表
+ * @returns
+ */
+export const getNoticeMethod = (params: any) => {
+  return request<IOT.API.SYS.Notice[]>({
+    url: '/notificationMethod/page',
+    method: 'GET',
+    params
+  })
+}
+
+/**
+ * 新增通知方式
+ * @returns
+ */
+export const addNoticeMethod = (data: any) => {
+  return request<string>({
+    url: '/notificationMethod',
+    method: 'POST',
+    data
+  })
+}
+
+export const updateNoticeMethod = (data: any) => {
+  return request<string>({
+    url: '/notificationMethod',
+    method: 'PUT',
+    data
+  })
+}
+
+/**
+ * 通知方式 详情
+ * @returns
+ */
+export const getNoticeById = (id: string) => {
+  return request<IOT.API.SYS.Notice>({
+    url: `/notificationMethod/${id}`,
+    method: 'GET'
+  })
+}
+
+export const delNotice = (id: string) => {
+  return request<string>({
+    url: `/notificationMethod/${id}`,
+    method: 'DELETE'
+  })
+}
+
+export const updateNoticeStaus = ({ id, status }: {id: string, status: string}) => {
+  return request<string>({
+    url: `/notificationMethod/status?id=${id}&status=${status}`,
+    method: 'PUT'
+  })
+}
+
+export const updateNoticeLabel = ({ id, label }: {id: string, label: string}) => {
+  return request<string>({
+    url: `/notificationMethod/label?id=${id}&label=${label}`,
+    method: 'PUT'
+  })
+}

+ 1 - 0
src/controller/index.ts

@@ -6,3 +6,4 @@ export { ModelCmdController } from './iot/modelCmd'
 export { EventController } from './iot/event'
 export { DeviceContriller } from './iot/device'
 export { RuleController } from './iot/rule'
+export { SysController } from './iot/sys'

+ 46 - 0
src/controller/iot/sys.ts

@@ -0,0 +1,46 @@
+import { addNoticeMethod, getNoticeById, getNoticeMethod, getSysConf, updateNoticeLabel, updateNoticeMethod, updateNoticeStaus, updateSysConf } from '@/api/iot/sys'
+import { message } from 'ant-design-vue'
+
+export class SysController {
+  static async sysConf () {
+    return await getSysConf()
+  }
+
+  static async updateSysConf (data: IOT.API.SYS.Sys) {
+    await updateSysConf(data)
+    message.success('修改成功')
+  }
+
+  static async noticeMethodPage (params: any) {
+    return await getNoticeMethod(params)
+  }
+
+  static async addNoticeMethod (data: any) {
+    await addNoticeMethod(data)
+    message.success('新增成功')
+  }
+
+  static async updateNoticeMethod (data: any) {
+    await updateNoticeMethod(data)
+    message.success('修改成功')
+  }
+
+  static async noticeById (id: string) {
+    return await getNoticeById(id)
+  }
+
+  static async delNotice (id: string) {
+    await getNoticeById(id)
+    message.success('删除成功')
+  }
+
+  static async updateNoticeStaus (params: {id: string, status: string}) {
+    await updateNoticeStaus(params)
+    message.success('修改成功')
+  }
+
+  static async updateNoticeLabel (params: {id: string, label: string}) {
+    await updateNoticeLabel(params)
+    message.success('修改成功')
+  }
+}

+ 12 - 0
src/pages/Iot/sys/logo.vue

@@ -0,0 +1,12 @@
+<template>
+  <a-card>
+    logo
+  </a-card>
+</template>
+
+<script lang="ts" setup >
+
+</script>
+
+<style lang="less" scoped >
+</style>

+ 269 - 0
src/pages/Iot/sys/notice.vue

@@ -0,0 +1,269 @@
+<template>
+  <a-card>
+    <a-row>
+      <a-col span="12">
+        <a-form layout="inline" >
+          <a-form-item label="通知名称" >
+            <a-input v-model:value="queryParamsState.label" placeholder="请输入通知名称"/>
+          </a-form-item>
+          <a-form-item  label='通知数据来源' >
+            <a-select
+              style="width: 170px"
+              v-model:value="queryParamsState.source"
+            >
+              <a-select-option
+                v-for="item in sourceList"
+                :key="item.key"
+                :value="item.key"
+              >
+                {{item.label}}
+              </a-select-option>
+            </a-select>
+          </a-form-item >
+          <a-form-item>
+            <a-button type="primary" @click="getNoticePage">搜索</a-button>
+          </a-form-item>
+      </a-form>
+      </a-col>
+      <a-col span="12" >
+        <a-row justify="end" >
+          <a-button type="primary" @click="openModal('add')" >新增</a-button>
+        </a-row>
+      </a-col>
+    </a-row>
+    <a-table
+      style="margin-top: 20px;"
+      :columns="columns"
+      :data-source="state.dataSource"
+      :loading="state.loading"
+      :pagination="queryParamsState"
+      @change="changePage"
+    >
+      <template #bodyCell="{column, record}">
+            <template v-if="column.key === 'status'" >
+              <a-switch
+                @click="changeStatus(record)"
+                v-model:checked="record.status"
+                checked-children="运行中"
+                un-checked-children="已关闭"
+              />
+            </template>
+            <template v-if="column.key === 'action'" >
+              <a-space>
+                <a @click="openModal('update', record.id)" >编辑</a>
+                <a-popconfirm
+                    title="确实要删除吗?"
+                    ok-text="确定"
+                    cancel-text="取消"
+                    @confirm="delNotice(record.id)"
+                  >
+                  <a>删除</a>
+                  </a-popconfirm>
+              </a-space>
+            </template>
+      </template>
+    </a-table>
+  </a-card>
+
+  <modal-pro
+    :label="modalTitle"
+    :visible="state.visible"
+    destroyOnClose
+    @cancel="state.visible = false"
+    @ok="ok"
+  >
+    <a-form :label-col="{span: 4}" :wrapper-col="{span: 14}">
+      <a-form-item label="任务名称" v-bind="validateInfos.taskLabel">
+        <a-input v-model:value="modalRef.taskLabel"  />
+      </a-form-item>
+      <a-form-item label="任务描述" >
+        <a-input v-model:value="modalRef.taskDescription" />
+      </a-form-item>
+      <a-form-item label="选择产品" >
+        <a-select
+          placeholder="请选择产品"
+          v-model:value="modalRef.taskConfig.modelId"
+        >
+          <a-select-option
+            v-for="model in state.modelList"
+            :key="model.id"
+            :value="model.id"
+          >
+            {{model.modelLabel}}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="选择设备" >
+        <a-select
+          placeholder="请选择产品"
+          v-model:value="modalRef.taskConfig.deviceId"
+        >
+          <a-select-option
+            v-for="device in state.deviceList"
+            :key="device.id"
+            :value="device.id"
+          >
+            {{device.deviceLabel}}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="任务类型" v-bind="validateInfos.taskType">
+        <a-select v-model:value="modalRef.taskConfig.taskType" >
+          <a-select-option
+            :value="item"
+            v-for="item in TaskController.taskTypeList"
+            :key="item"
+          >
+            {{TaskController.taskTypeMap.get(item)?.label }}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+      <span v-if="modalRef.taskConfig.taskType === 'DEVICE_CMD'" >
+        <a-form-item label="选择命令" >
+          <a-select
+            style="width: 170px;"
+            v-model:value="modalRef.taskConfig.cmdId"
+          >
+            <a-select-option
+              v-for="cmdItem in state.cmdList"
+              :key="cmdItem.id"
+              :value="cmdItem.id"
+            >
+            {{cmdItem.cmdLabel}}
+            </a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item label="命令参数" >
+          <div
+            v-for="(item, index) in modalRef.taskConfig.cmdParameters"
+            :key="index"
+            style="margin-bottom: 10px;"
+          >
+            <a-input-group compact  >
+              <a-input placeholder="key"  disabled v-model:value="item.paramLabel" style="width: 50%" />
+              <a-input placeholder="value" v-model:value="item.dataUnit" style="width: 50%" />
+            </a-input-group>
+          </div>
+        </a-form-item>
+      </span>
+      <span v-if="modalRef.taskConfig.taskType === 'DEVICE_MSG'" >
+        <a-form-item label="主题" >
+          <a-input v-model:value="modalRef.taskConfig.topic"  />
+        </a-form-item>
+        <a-form-item label="消息名称" >
+          <a-input v-model:value="modalRef.taskConfig.msgLabel"  />
+        </a-form-item>
+        <a-form-item label="消息内容" >
+          <a-textarea :auto-size="{ minRows: 2, maxRows: 5 }" v-model:value="modalRef.taskConfig.msgPayload"  />
+        </a-form-item>
+      </span>
+
+    </a-form>
+  </modal-pro>
+</template>
+
+<script lang="ts" setup >
+import { reactive, onMounted, computed } from 'vue'
+import { SysController } from '@/controller'
+import { Form } from 'ant-design-vue'
+
+const useForm = Form.useForm
+
+const columns = [
+  {
+    title: 'id',
+    dataIndex: 'id'
+  },
+  {
+    title: '通知名称',
+    dataIndex: 'label',
+    key: 'label'
+  },
+  {
+    title: '通知数据来源',
+    dataIndex: 'source',
+    key: 'source'
+  },
+  {
+    title: '状态',
+    dataIndex: 'status',
+    key: 'status'
+  },
+  {
+    title: '操作',
+    dataIndex: 'action',
+    key: 'action'
+  }
+]
+
+const sourceList = [{ key: 0, label: '通知' }, { key: 1, label: '告警' }]
+
+const queryParamsState = reactive({
+  page: 1,
+  pageSize: 10,
+  label: '',
+  source: ''
+})
+
+const state = reactive({
+  dataSource: [],
+  loading: false,
+  visible: false,
+  opraState: 'add',
+  noticeId: ''
+})
+
+const modalRef = reactive({
+  label: '',
+  source: 0,
+  status: false
+})
+
+const modalTitle = computed(() => state.opraState === 'add' ? '新增通知' : '编辑通知')
+
+const { resetFields, validate, validateInfos } = useForm(modalRef, reactive({
+  label: [{ required: true, message: '请填写通知名称' }]
+}))
+
+const ok = () => {
+
+}
+
+const openModal = (opraState: 'add' | 'update', id = '') => {
+  state.opraState = opraState
+  state.visible = true
+  state.noticeId = id
+  if (opraState === 'update') {
+    getNoticeById()
+  }
+}
+
+const changePage = ({ current }) => {
+  queryParamsState.page = current
+  getNoticePage()
+}
+
+const delNotice = (id: string) => SysController.delNotice(id)
+
+const changeStatus = async (record) => SysController.updateNoticeStaus({ id: record.id, status: record.status })
+
+const getNoticeById = async () => {
+  const { data } = await SysController.noticeById(state.noticeId)
+  resetFields(data)
+}
+
+const getNoticePage = async () => {
+  state.loading = true
+  const { data } = await SysController.noticeMethodPage(queryParamsState)
+  state.loading = false
+  state.dataSource = data
+}
+
+onMounted(() => {
+  getNoticePage()
+})
+
+</script>
+
+<style lang="less" scoped >
+</style>

+ 18 - 0
src/router/index.ts

@@ -162,6 +162,24 @@ export const routes: Array<ROUTER.RoutesProps> = [
         name: '数据服务文档',
         component: () => import('@/pages/iot/doc/dataDoc.vue'),
         icon: 'CoffeeOutlined'
+      },
+      {
+        path: '/sys',
+        name: '系统设置',
+        redirect: '/task/manage',
+        icon: 'DatabaseOutlined',
+        children: [
+          {
+            path: '/task/manage',
+            name: '任务管理',
+            component: () => import('@/pages/iot/task/manage.vue')
+          },
+          {
+            path: '/task/track',
+            name: '任务追踪',
+            component: () => import('@/pages/iot/task/track.vue')
+          }
+        ]
       }
     ]
   },

+ 24 - 0
src/type/iot.d.ts

@@ -339,6 +339,30 @@ declare namespace IOT {
         'ENABLE': number
       }
     }
+
+    namespace SYS {
+      interface Sys {
+        'id': string,
+        'sysLabel': string,
+        'sysIcon': string, // 系统图片,上传时候限制大小为3M 并且base64 编码
+        'sysTheme': string,
+        'mailConf': {
+          'host': string,
+          'port': number,
+          'protocol': string,
+          'username': string,
+          'password': string
+        }
+      }
+
+      interface Notice {
+        'id': string,
+        'source': 0 | 1, // 通知数据来源 0 通知 1 告警
+        'label': string, // 通知方式名称
+        'notification': null, // 通知配置
+        'status': boolean // 状态 true 是启用 false 是停用
+      }
+    }
 }
 
 }