lvkun996 преди 2 години
родител
ревизия
acbeb77ff4
променени са 3 файла, в които са добавени 526 реда и са изтрити 525 реда
  1. 162 162
      src/components/TablePro/index.vue
  2. 344 343
      src/pages/Iot/device/index.vue
  3. 20 20
      src/utils/UsePro.ts

+ 162 - 162
src/components/TablePro/index.vue

@@ -1,162 +1,162 @@
-<template>
-    <a-row>
-      <!-- <a-col span="24" >
-        <a-row justify="end">
-            <a-col>
-              <a-space>
-                <a-button type="primary" @click="openModel('add')" >
-                  新增
-                  <template #icon>
-                    <plus-outlined />
-                  </template>
-                </a-button>
-                <a-button type="primary" >
-                  导出
-                  <template #icon>
-                    <download-outlined />
-                  </template>
-                </a-button>
-                <a-tooltip>
-                  <template #title >刷新</template>
-                  <reload-outlined v-if="!state.loading"  @click="reload"/>
-                  <loading-outlined v-else />
-                </a-tooltip>
-              </a-space>
-            </a-col>
-        </a-row>
-      </a-col> -->
-      <a-col span="24" style="overflow: hidden;overflow-x: scroll;">
-        <a-table
-          style="width: 100%;margin-top: 10px;"
-          v-bind="{...props}"
-          :data-source="state.data"
-          :loading="state.loading"
-          :pagination="state.pagination.total <= 10 ? false : state.pagination"
-          @change="handleTableChange"
-        >
-        <template #bodyCell="{ column, record }">
-          <template v-if="column.key === 'action'">
-            <a-space>
-              <span  v-for="item in column.list" :key="item.name" >
-                <a-popconfirm
-                  title="确实要删除吗?"
-                  ok-text="确定"
-                  cancel-text="取消"
-                  @confirm="confirmDel(item, record)"
-                  v-if="item.use == 'del'"
-                >
-                  <a>删除</a>
-                </a-popconfirm>
-                <a v-else @click="handleAction(item, record)" >{{item.name}}</a>
-              </span>
-            </a-space>
-          </template>
-        </template>
-        </a-table>
-      </a-col>
-    </a-row>
-</template>
-
-<script lang="ts" setup >
-import { useCopy } from '@/hooks/dom'
-import { ColumnsType } from 'ant-design-vue/lib/vc-table/interface'
-import { TableProps } from 'ant-design-vue/lib/vc-table/Table'
-import { reactive, ref, watch } from 'vue'
-import { PlusOutlined, DownloadOutlined, ReloadOutlined, LoadingOutlined } from '@ant-design/icons-vue'
-/**
- * formItemProps
- * rules 校验
- * request 需要请求的表单项 分别创建id key value name
- * type: input select radio check datepick
- */
-
-/**
-  * pro-able
-  * 'export' | 'add' | search
-*/
-
-export interface ColumnsChildren {
-  name: '',
-  use: string,
-  icon: '',
-  bindKey: string
-}
-
-export interface TablePropPorps extends TableProps {
-  request: (params: any) => any
-  del: (id: string) => void
-  params: any,
-  columns: ColumnsType & {children: ColumnsChildren},
-}
-
-const props = defineProps<TablePropPorps>()
-
-const formProRef = ref()
-
-const state = reactive({
-  loading: false,
-  data: [],
-  pagination: {
-    current: 1,
-    page: 1,
-    total: 0,
-    pageSize: 10
-  },
-  modelVisible: false,
-  opraState: 'add'
-})
-
-const handleTableChange = (pag: { pageSize: number; current: number }) => {
-  state.pagination = {
-    ...state.pagination,
-    pageSize: pag.pageSize,
-    current: pag.current
-  }
-}
-// 请求table 的data
-const request = async () => {
-  state.loading = true
-  const data = await props.request(props.params)
-  state.loading = false
-  console.log('table pro data:', data)
-  state.data = data
-}
-
-// 删除对应的table选项
-const confirmDel = async (item: ColumnsChildren, record: any) => {
-  await props.del(record[item.bindKey])
-  request()
-}
-
-const handleAction = (column: ColumnsChildren, record: any) => {
-  switch (column.use) {
-    case 'copy':
-      useCopy(record[column.bindKey])
-  }
-}
-
-// `const reload = () => request()` 正在定义一个名为 `reload` 的函数,该函数调用 `request` 函数。该函数用于在用户点击“刷新”按钮时重新加载表格数据。
-const reload = () => request()
-
-const openModel = (type: 'add' | 'update') => {
-  state.modelVisible = true
-  state.opraState = type
-}
-
-const closeModel = () => {
-  state.modelVisible = false
-}
-
-watch(
-  () => props.request,
-  () => request(),
-  {
-    deep: true,
-    immediate: true
-  }
-)
-
-</script>
-
-<style>
-</style>
+<template>
+    <a-row>
+      <!-- <a-col span="24" >
+        <a-row justify="end">
+            <a-col>
+              <a-space>
+                <a-button type="primary" @click="openModel('add')" >
+                  新增
+                  <template #icon>
+                    <plus-outlined />
+                  </template>
+                </a-button>
+                <a-button type="primary" >
+                  导出
+                  <template #icon>
+                    <download-outlined />
+                  </template>
+                </a-button>
+                <a-tooltip>
+                  <template #title >刷新</template>
+                  <reload-outlined v-if="!state.loading"  @click="reload"/>
+                  <loading-outlined v-else />
+                </a-tooltip>
+              </a-space>
+            </a-col>
+        </a-row>
+      </a-col> -->
+      <a-col span="24" style="overflow: hidden;overflow-x: scroll;">
+        <a-table
+          style="width: 100%;margin-top: 10px;"
+          v-bind="{...props}"
+          :data-source="state.data"
+          :loading="state.loading"
+          :pagination="state.pagination.total <= 10 ? false : state.pagination"
+          @change="handleTableChange"
+        >
+        <template #bodyCell="{ column, record }">
+          <template v-if="column.key === 'action'">
+            <a-space>
+              <span  v-for="item in column.list" :key="item.name" >
+                <a-popconfirm
+                  title="确实要删除吗?"
+                  ok-text="确定"
+                  cancel-text="取消"
+                  @confirm="confirmDel(item, record)"
+                  v-if="item.use == 'del'"
+                >
+                  <a>删除</a>
+                </a-popconfirm>
+                <a v-else @click="handleAction(item, record)" >{{item.name}}</a>
+              </span>
+            </a-space>
+          </template>
+        </template>
+        </a-table>
+      </a-col>
+    </a-row>
+</template>
+
+<script lang="ts" setup >
+import { useCopy } from '@/hooks/dom'
+import { ColumnsType } from 'ant-design-vue/lib/vc-table/interface'
+import { TableProps } from 'ant-design-vue/lib/vc-table/Table'
+import { reactive, ref, watch } from 'vue'
+import { PlusOutlined, DownloadOutlined, ReloadOutlined, LoadingOutlined } from '@ant-design/icons-vue'
+/**
+ * formItemProps
+ * rules 校验
+ * request 需要请求的表单项 分别创建id key value name
+ * type: input select radio check datepick
+ */
+
+/**
+  * pro-able
+  * 'export' | 'add' | search
+*/
+
+export interface ColumnsChildren {
+  name: '',
+  use: string,
+  icon: '',
+  bindKey: string
+}
+
+export interface TablePropPorps extends TableProps {
+  request: (params: any) => any
+  del: (id: string) => void
+  params: any,
+  columns: ColumnsType & {children: ColumnsChildren},
+}
+
+const props = defineProps<TablePropPorps>()
+
+const formProRef = ref()
+
+const state = reactive({
+  loading: false,
+  data: [],
+  pagination: {
+    current: 1,
+    page: 1,
+    total: 0,
+    pageSize: 10
+  },
+  modelVisible: false,
+  opraState: 'add'
+})
+
+const handleTableChange = (pag: { pageSize: number; current: number }) => {
+  state.pagination = {
+    ...state.pagination,
+    pageSize: pag.pageSize,
+    current: pag.current
+  }
+}
+// 请求table 的data
+const request = async () => {
+  state.loading = true
+  const data = await props.request(props.params)
+  state.loading = false
+  console.log('table pro data:', data)
+  state.data = data
+}
+
+// 删除对应的table选项
+const confirmDel = async (item: ColumnsChildren, record: any) => {
+  await props.del(record[item.bindKey])
+  request()
+}
+
+const handleAction = (column: ColumnsChildren, record: any) => {
+  switch (column.use) {
+    case 'copy':
+      useCopy(record[column.bindKey])
+  }
+}
+
+// `const reload = () => request()` 正在定义一个名为 `reload` 的函数,该函数调用 `request` 函数。该函数用于在用户点击“刷新”按钮时重新加载表格数据。
+const reload = () => request()
+
+const openModel = (type: 'add' | 'update') => {
+  state.modelVisible = true
+  state.opraState = type
+}
+
+const closeModel = () => {
+  state.modelVisible = false
+}
+
+watch(
+  () => props.request,
+  () => request(),
+  {
+    deep: true,
+    immediate: true
+  }
+)
+
+</script>
+
+<style>
+</style>

+ 344 - 343
src/pages/Iot/device/index.vue

@@ -1,343 +1,344 @@
-<template>
-
-  <a-card title="设备统计" >
-    <a-row justify="center">
-      <a-col
-        v-for="item in state.deviceCount"
-        :key="item.key"
-        :xs="12"  :sm="12"  :md="6"  :lg="8"  :xl="4"
-      >
-        <div class="statistic" >
-          <span class="count" :style="{color: item.color}" >{{item.value}}</span>
-          <span>台</span>
-        </div>
-        <div class="label" >
-          {{item.label}}
-        </div>
-      </a-col>
-    </a-row>
-  </a-card>
-
-  <a-card style="margin-top: 20px;">
-    <a-row justify="space-between" >
-      <a-col :span="20"  >
-        <a-form layout="inline" >
-          <a-form-item  >
-            <a-select  allowClear style="width: 176px;"  v-model:value="searchState.deviceStatus" placeholder="请输入设备状态">
-              <a-select-option
-                v-for="item in DeviceContriller.deviceStatus"
-                :key="item.key"
-                :value="item.key"
-              >{{item.name}}</a-select-option>
-            </a-select>
-          </a-form-item>
-          <a-form-item style="width: 400px;">
-            <a-input-group compact >
-              <a-select allowClear v-model:value="searchState.searchKey" style="width: 150px;" >
-                <a-select-option v-for="item in searchList" :key="item.key" :value="item.key">{{item.name}}</a-select-option>
-              </a-select>
-              <a-input allowClear v-model:value="searchState.searchValue" style="width: 176px" placeholder="请输入查询值"/>
-            </a-input-group>
-          </a-form-item>
-          <a-form-item><a-button @click="resetFields([])">重置</a-button></a-form-item>
-          <a-form-item><a-button type="primary" @click="getDevicePage">搜索</a-button> </a-form-item>
-        </a-form>
-      </a-col>
-      <a-col :span="2" >
-        <a-button type="primary" @click="openModal('add', {})"> + 新增设备</a-button>
-      </a-col>
-    </a-row>
-
-    <a-table
-      style="margin-top: 20px;width: 100%;"
-      :columns="columns"
-      :data-source="state.dataSource"
-      :loading="state.loading"
-      :pagination="searchState"
-      @change="changePage"
-    >
-      <template #bodyCell="{column, record}">
-        <template v-if="column.key === 'id'" >
-          <a @click="goDetailPage(record.id)">{{record.id}}</a>
-        </template>
-        <template v-if="column.key === 'deviceStatus'" >
-          <a-tag :color="record.deviceStatus.color" >{{record.deviceStatus.name}}</a-tag>
-        </template>
-        <template v-if="column.key === 'deviceNodeType'" >
-          <a-tag>{{record.deviceNodeType == 'GATEWAY'?'直连类型':'非直连类型'}}</a-tag>
-        </template>
-        <template v-if="column.key === 'rtsUrl'" >
-          {{record.rtsUrl ? '支持': '否'}}
-        </template>
-        <template v-if="column.key === 'action'">
-            <a-space>
-              <a @click="goDetailPage(record.id)">查看</a>
-              <a @click="goDebugPage(record.id)" >调试</a>
-              <a @click="goAnalysisPage(record.id)">分析</a>
-              <a-popconfirm
-                  title="确实要删除吗?"
-                  ok-text="确定"
-                  cancel-text="取消"
-                  @confirm="delDevice(record.id)"
-                >
-                  <a href="#">删除</a>
-              </a-popconfirm>
-            </a-space>
-        </template>
-      </template>
-    </a-table>
-  </a-card>
-
-  <a-modal
-    title="单设备注册"
-    :open="state.visible"
-    @cancel="state.visible = false"
-    @ok="ok"
-  >
-    <a-form  :labelCol="{span: 6}" :wrapperCol="{span: 14}" >
-      <a-form-item label="所属产品" v-bind="validateInfosDeviceState.modelId" >
-        <a-select allowClear v-model:value="deviceState.modelId" >
-          <a-select-option
-            v-for="item in state.modelList"
-            :key="item.id"
-            :value="item.id"
-          >
-            {{item.modelLabel}}
-          </a-select-option>
-        </a-select>
-      </a-form-item>
-      <a-form-item label="设备标识码" v-bind="validateInfosDeviceState.deviceCode"  >
-        <a-input allowClear v-model:value="deviceState.deviceCode" />
-      </a-form-item>
-      <a-form-item label="设备名称" >
-        <a-input allowClear v-model:value="deviceState.deviceLabel" />
-      </a-form-item>
-      <a-form-item label="设备认证类型" >
-        <a-radio-group v-model:value="deviceState.deviceAuthType">
-          <a-radio value="SECRET">密钥认证</a-radio>
-          <a-radio value="X509CERT">x509证书</a-radio>
-        </a-radio-group>
-      </a-form-item>
-      <a-form-item label="密匙" v-if="deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET " >
-        <a-input-password allowClear v-model:value="deviceState.deviceSecret" />
-      </a-form-item>
-      <a-form-item label="确认密匙"  v-if="deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET ">
-        <a-input-password allowClear v-model:value="deviceState.confirmSecret" />
-      </a-form-item>
-    </a-form>
-  </a-modal>
-
-</template>
-
-<script lang="ts" setup >
-
-import { DeviceContriller, ModelController } from '@/controller/index'
-import { onMounted, reactive, ref, toRefs, nextTick, computed, watch } from 'vue'
-import { Form, message } from 'ant-design-vue'
-import { DeviceAuthTypeEnum } from '@/enum/common'
-import { useRoute, useRouter } from 'vue-router'
-import { DownOutlined } from '@ant-design/icons-vue'
-
-const useForm = Form.useForm
-const router = useRouter()
-
-const modelId = (useRoute().query.modelId || '') as string
-
-console.log('modelId:', modelId)
-
-const columns = [
-  {
-    title: '设备ID',
-    dataIndex: 'id',
-    key: 'id',
-    ellipsis: true
-  },
-  {
-    title: '设备名称',
-    dataIndex: 'deviceLabel',
-    ellipsis: true
-  },
-  {
-    title: '设备标识码',
-    dataIndex: 'deviceCode',
-    ellipsis: true
-  },
-  {
-    title: '设备描述',
-    dataIndex: 'deviceDescription',
-    ellipsis: true
-  },
-  {
-    title: '节点类型',
-    dataIndex: 'deviceNodeType',
-    key: 'deviceNodeType',
-    width: 100
-  },
-  {
-    title: '所属产品',
-    dataIndex: 'modelLabel',
-    ellipsis: true
-  },
-  {
-    title: '支持live',
-    dataIndex: 'rtsUrl',
-    key: 'rtsUrl',
-    width: 100
-  },
-  {
-    title: '状态',
-    dataIndex: 'deviceStatus',
-    key: 'deviceStatus',
-    ellipsis: true,
-    width: 80
-  },
-  {
-    title: '操作',
-    key: 'action'
-  }
-]
-
-const searchList = [
-  { name: '设备id', key: 'deviceId' },
-  { name: '设备名称', key: 'deviceLabel' },
-  { name: '设备标识码', key: 'deviceCode' }
-]
-
-const analysisList = [
-  { label: '上下线分析', key: 'session' },
-  { label: '属性分析', key: 'attr' }
-]
-
-const state = reactive<{
-  modelId: string,
-  deviceCount: any,
-  dataSource: IOT.API.DEVICE.Device[],
-  loading: boolean,
-  visible: boolean,
-  opraState: 'add' | 'update',
-  modelList: IOT.API.MODEL.ModelDot[]
-  analysisVisible: boolean
-  analysisType: 'session' | 'attr' | ''
-}>({
-  modelId: modelId,
-  deviceCount: [],
-  dataSource: [],
-  modelList: [],
-  loading: false,
-  visible: false,
-  analysisVisible: false,
-  analysisType: '',
-  opraState: 'add'
-})
-
-const searchState = reactive({
-  page: 1,
-  pageSize: 10,
-  total: 0,
-  deviceStatus: null,
-  modelId: modelId,
-  searchKey: 'deviceId',
-  searchValue: '',
-  showSizeChanger: false
-})
-
-const deviceState = reactive({
-  id: '',
-  modelId: '',
-  deviceLabel: '',
-  deviceCode: '',
-  deviceDescription: '',
-  deviceAuthType: DeviceAuthTypeEnum.SECRET,
-  modelLabel: '',
-  deviceSecret: '',
-  confirmSecret: ''
-})
-
-const { resetFields, validate, validateInfos } = useForm(searchState, {})
-
-const { resetFields: resetFieldsDevice, validate: validateDevice, validateInfos: validateInfosDeviceState } = useForm(deviceState, reactive({
-  modelId: [{ required: true, message: '请选择所属产品' }],
-  deviceCode: [{ required: true, message: '请填写设备码' }]
-}))
-
-const changePage = ({ current }) => {
-  searchState.page = current
-  getDevicePage()
-}
-
-const goDebugPage = (id: string) => {
-  router.push({ path: '/devOps/onlineTest', query: { id } })
-}
-
-const goDetailPage = (id: string) => {
-  router.push({ path: '/device/detail', query: { id } })
-}
-
-const delDevice = async (id: string) => {
-  await DeviceContriller.del(id)
-  getDevicePage()
-}
-
-const goAnalysisPage = (id: string) => {
-  router.push({ path: '/device/analysis', query: { id } })
-}
-
-const ok = () => {
-  if (deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET && deviceState.deviceSecret !== deviceState.confirmSecret) {
-    message.warn('两次密匙输入不同')
-    return
-  }
-  validateDevice().then(async (r) => {
-    await DeviceContriller.post(deviceState)
-    state.visible = false
-    getDevicePage()
-  })
-}
-
-const getModelList = async () => {
-  const { data } = await ModelController.list()
-  state.modelList = data
-}
-
-const openModal = (opraState: 'add' | 'update', record:Partial<IOT.API.DEVICE.Device> = {}) => {
-  state.visible = true
-  state.opraState = opraState
-  getModelList()
-  resetFieldsDevice({})
-}
-
-const getDevicePage = async () => {
-  state.loading = true
-  const { data, sum } = await DeviceContriller.page(searchState)
-  state.loading = false
-  state.dataSource = data
-  searchState.total = sum
-}
-
-const getDeviceStatistics = async () => {
-  const data = await DeviceContriller.statistics({ modelId: state.modelId })
-  state.deviceCount = data as any
-}
-
-onMounted(() => {
-  getDeviceStatistics()
-  getDevicePage()
-})
-
-</script>
-
-<style lang="less" scoped >
-@import '~@/styles/theme.less';
-.statistic {
-  color: @sublabel-color;
-  .count {
-    font-size: 48px;
-    margin-right: 10px;
-  }
-}
-.label {
-  font-size: 18px;
-  color: @sublabel-color;
-}
-
-</style>
+<template>
+
+  <a-card title="设备统计" >
+    <a-row justify="center">
+      <a-col
+        v-for="item in state.deviceCount"
+        :key="item.key"
+        :xs="12"  :sm="12"  :md="6"  :lg="8"  :xl="4"
+      >
+        <div class="statistic" >
+          <span class="count" :style="{color: item.color}" >{{item.value}}</span>
+          <span>台</span>
+        </div>
+        <div class="label" >
+          {{item.label}}
+        </div>
+      </a-col>
+    </a-row>
+  </a-card>
+
+  <a-card style="margin-top: 20px;">
+    <a-row justify="space-between" >
+      <a-col :span="20"  >
+        <a-form layout="inline" >
+          <a-form-item  >
+            <a-select  allowClear style="width: 176px;"  v-model:value="searchState.deviceStatus" placeholder="请输入设备状态">
+              <a-select-option
+                v-for="item in DeviceContriller.deviceStatus"
+                :key="item.key"
+                :value="item.key"
+              >{{item.name}}</a-select-option>
+            </a-select>
+          </a-form-item>
+          <a-form-item style="width: 400px;">
+            <a-input-group compact >
+              <a-select allowClear v-model:value="searchState.searchKey" style="width: 150px;" >
+                <a-select-option v-for="item in searchList" :key="item.key" :value="item.key">{{item.name}}</a-select-option>
+              </a-select>
+              <a-input allowClear v-model:value="searchState.searchValue" style="width: 176px" placeholder="请输入查询值"/>
+            </a-input-group>
+          </a-form-item>
+          <a-form-item><a-button @click="resetFields([])">重置</a-button></a-form-item>
+          <a-form-item><a-button type="primary" @click="getDevicePage">搜索</a-button> </a-form-item>
+        </a-form>
+      </a-col>
+      <a-col :span="2" >
+        <a-button type="primary" @click="openModal('add', {})"> + 新增设备</a-button>
+      </a-col>
+    </a-row>
+
+    <a-table
+      style="margin-top: 20px;width: 100%;"
+      :columns="columns"
+      :data-source="state.dataSource"
+      :loading="state.loading"
+      :pagination="searchState"
+      @change="changePage"
+    >
+      <template #bodyCell="{column, record}">
+        <template v-if="column.key === 'id'" >
+          <a @click="goDetailPage(record.id)">{{record.id}}</a>
+        </template>
+        <template v-if="column.key === 'deviceStatus'" >
+          <a-tag :color="record.deviceStatus.color" >{{record.deviceStatus.name}}</a-tag>
+        </template>
+        <template v-if="column.key === 'deviceNodeType'" >
+          <a-tag>{{record.deviceNodeType == 'GATEWAY'?'直连类型':'非直连类型'}}</a-tag>
+        </template>
+        <template v-if="column.key === 'rtsUrl'" >
+          {{record.rtsUrl ? '支持': '否'}}
+        </template>
+        <template v-if="column.key === 'action'">
+            <a-space>
+              <a @click="goDetailPage(record.id)">查看</a>
+              <a @click="goDebugPage(record.id)" >调试</a>
+              <a @click="goAnalysisPage(record.id)">分析</a>
+              <a-popconfirm
+                  title="确实要删除吗?"
+                  ok-text="确定"
+                  cancel-text="取消"
+                  @confirm="delDevice(record.id)"
+                >
+                  <a href="#">删除</a>
+              </a-popconfirm>
+            </a-space>
+        </template>
+      </template>
+    </a-table>
+  </a-card>
+
+  <a-modal
+    title="单设备注册"
+    :open="state.visible"
+    @cancel="state.visible = false"
+    @ok="ok"
+  >
+    <a-form  :labelCol="{span: 6}" :wrapperCol="{span: 14}" >
+      <a-form-item label="所属产品" v-bind="validateInfosDeviceState.modelId" >
+        <a-select allowClear v-model:value="deviceState.modelId" >
+          <a-select-option
+            v-for="item in state.modelList"
+            :key="item.id"
+            :value="item.id"
+          >
+            {{item.modelLabel}}
+          </a-select-option>
+        </a-select>
+      </a-form-item>
+      <a-form-item label="设备标识码" v-bind="validateInfosDeviceState.deviceCode"  >
+        <a-input allowClear v-model:value="deviceState.deviceCode" />
+      </a-form-item>
+      <a-form-item label="设备名称" >
+        <a-input allowClear v-model:value="deviceState.deviceLabel" />
+      </a-form-item>
+      <a-form-item label="设备认证类型" >
+        <a-radio-group v-model:value="deviceState.deviceAuthType">
+          <a-radio value="SECRET">密钥认证</a-radio>
+          <a-radio value="X509CERT">x509证书</a-radio>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item label="密匙" v-if="deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET " >
+        <a-input-password allowClear v-model:value="deviceState.deviceSecret" />
+      </a-form-item>
+      <a-form-item label="确认密匙"  v-if="deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET ">
+        <a-input-password allowClear v-model:value="deviceState.confirmSecret" />
+      </a-form-item>
+    </a-form>
+  </a-modal>
+
+</template>
+
+<script lang="ts" setup >
+
+import { DeviceContriller, ModelController } from '@/controller/index'
+import { onMounted, reactive, ref, toRefs, nextTick, computed, watch } from 'vue'
+import { Form, message } from 'ant-design-vue'
+import { DeviceAuthTypeEnum } from '@/enum/common'
+import { useRoute, useRouter } from 'vue-router'
+import { DownOutlined } from '@ant-design/icons-vue'
+
+const useForm = Form.useForm
+
+const router = useRouter()
+
+const modelId = (useRoute().query.modelId || '') as string
+
+console.log('modelId:', modelId)
+
+const columns = [
+  {
+    title: '设备ID',
+    dataIndex: 'id',
+    key: 'id',
+    ellipsis: true
+  },
+  {
+    title: '设备名称',
+    dataIndex: 'deviceLabel',
+    ellipsis: true
+  },
+  {
+    title: '设备标识码',
+    dataIndex: 'deviceCode',
+    ellipsis: true
+  },
+  {
+    title: '设备描述',
+    dataIndex: 'deviceDescription',
+    ellipsis: true
+  },
+  {
+    title: '节点类型',
+    dataIndex: 'deviceNodeType',
+    key: 'deviceNodeType',
+    width: 100
+  },
+  {
+    title: '所属产品',
+    dataIndex: 'modelLabel',
+    ellipsis: true
+  },
+  {
+    title: '支持live',
+    dataIndex: 'rtsUrl',
+    key: 'rtsUrl',
+    width: 100
+  },
+  {
+    title: '状态',
+    dataIndex: 'deviceStatus',
+    key: 'deviceStatus',
+    ellipsis: true,
+    width: 80
+  },
+  {
+    title: '操作',
+    key: 'action'
+  }
+]
+
+const searchList = [
+  { name: '设备id', key: 'deviceId' },
+  { name: '设备名称', key: 'deviceLabel' },
+  { name: '设备标识码', key: 'deviceCode' }
+]
+
+const analysisList = [
+  { label: '上下线分析', key: 'session' },
+  { label: '属性分析', key: 'attr' }
+]
+
+const state = reactive<{
+  modelId: string,
+  deviceCount: any,
+  dataSource: IOT.API.DEVICE.Device[],
+  loading: boolean,
+  visible: boolean,
+  opraState: 'add' | 'update',
+  modelList: IOT.API.MODEL.ModelDot[]
+  analysisVisible: boolean
+  analysisType: 'session' | 'attr' | ''
+}>({
+  modelId: modelId,
+  deviceCount: [],
+  dataSource: [],
+  modelList: [],
+  loading: false,
+  visible: false,
+  analysisVisible: false,
+  analysisType: '',
+  opraState: 'add'
+})
+
+const searchState = reactive({
+  page: 1,
+  pageSize: 10,
+  total: 0,
+  deviceStatus: null,
+  modelId: modelId,
+  searchKey: 'deviceId',
+  searchValue: '',
+  showSizeChanger: false
+})
+
+const deviceState = reactive({
+  id: '',
+  modelId: '',
+  deviceLabel: '',
+  deviceCode: '',
+  deviceDescription: '',
+  deviceAuthType: DeviceAuthTypeEnum.SECRET,
+  modelLabel: '',
+  deviceSecret: '',
+  confirmSecret: ''
+})
+
+const { resetFields, validate, validateInfos } = useForm(searchState, {})
+
+const { resetFields: resetFieldsDevice, validate: validateDevice, validateInfos: validateInfosDeviceState } = useForm(deviceState, reactive({
+  modelId: [{ required: true, message: '请选择所属产品' }],
+  deviceCode: [{ required: true, message: '请填写设备码' }]
+}))
+
+const changePage = ({ current }) => {
+  searchState.page = current
+  getDevicePage()
+}
+
+const goDebugPage = (id: string) => {
+  router.push({ path: '/devOps/onlineTest', query: { id } })
+}
+
+const goDetailPage = (id: string) => {
+  router.push({ path: '/device/detail', query: { id } })
+}
+
+const delDevice = async (id: string) => {
+  await DeviceContriller.del(id)
+  getDevicePage()
+}
+
+const goAnalysisPage = (id: string) => {
+  router.push({ path: '/device/analysis', query: { id } })
+}
+
+const ok = () => {
+  if (deviceState.deviceAuthType === DeviceAuthTypeEnum.SECRET && deviceState.deviceSecret !== deviceState.confirmSecret) {
+    message.warn('两次密匙输入不同')
+    return
+  }
+  validateDevice().then(async (r) => {
+    await DeviceContriller.post(deviceState)
+    state.visible = false
+    getDevicePage()
+  })
+}
+
+const getModelList = async () => {
+  const { data } = await ModelController.list()
+  state.modelList = data
+}
+
+const openModal = (opraState: 'add' | 'update', record:Partial<IOT.API.DEVICE.Device> = {}) => {
+  state.visible = true
+  state.opraState = opraState
+  getModelList()
+  resetFieldsDevice({})
+}
+
+const getDevicePage = async () => {
+  state.loading = true
+  const { data, sum } = await DeviceContriller.page(searchState)
+  state.loading = false
+  state.dataSource = data
+  searchState.total = sum
+}
+
+const getDeviceStatistics = async () => {
+  const data = await DeviceContriller.statistics({ modelId: state.modelId })
+  state.deviceCount = data as any
+}
+
+onMounted(() => {
+  getDeviceStatistics()
+  getDevicePage()
+})
+
+</script>
+
+<style lang="less" scoped >
+@import '~@/styles/theme.less';
+.statistic {
+  color: @sublabel-color;
+  .count {
+    font-size: 48px;
+    margin-right: 10px;
+  }
+}
+.label {
+  font-size: 18px;
+  color: @sublabel-color;
+}
+
+</style>

+ 20 - 20
src/utils/UsePro.ts

@@ -1,20 +1,20 @@
-import ModalPro from '@/components/ModalPro/index.vue'
-import SiderPro from '@/components/SiderPro/index.vue'
-import TablePro from '@/components/TableProV2/index'
-import FormPro from '@/components/FormPro/index.vue'
-import RowPro from '@/components/RowPro/index.vue'
-import ColPro from '@/components/ColPro/index.vue'
-import UploadPro from '@/components/UploadPro/index'
-import PageHeader from '@/layout/pageHeader.vue'
-import { App } from 'vue'
-
-export default function (app: App) {
-  app.component('modal-pro', ModalPro)
-  app.component('sider-pro', SiderPro)
-  app.component('table-pro', TablePro)
-  app.component('form-pro', FormPro) // 别问问什么是oo, 问就是这样比较帅
-  app.component('l-row', RowPro)
-  app.component('l-col', ColPro)
-  app.component('upload-pro', UploadPro)
-  app.component('page-header', PageHeader)
-}
+import ModalPro from '@/components/ModalPro/index.vue'
+import SiderPro from '@/components/SiderPro/index.vue'
+import TablePro from '@/components/TableProV2/index'
+import FormPro from '@/components/FormPro/index.vue'
+import RowPro from '@/components/RowPro/index.vue'
+import ColPro from '@/components/ColPro/index.vue'
+import UploadPro from '@/components/UploadPro/index'
+import PageHeader from '@/layout/pageHeader.vue'
+import { App } from 'vue'
+
+export default function (app: App) {
+  app.component('modal-pro', ModalPro)
+  app.component('sider-pro', SiderPro)
+  app.component('table-pro', TablePro)
+  app.component('form-pro', FormPro) // 别问问什么是oo, 问就是这样比较帅
+  app.component('l-row', RowPro)
+  app.component('l-col', ColPro)
+  app.component('upload-pro', UploadPro)
+  app.component('page-header', PageHeader)
+}