Explorar el Código

fix: 平台首页更新,展示平台设备列表数据信息

lihao16 hace 1 mes
padre
commit
ca10da03f8

+ 8 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/controller/SmsbDeviceController.java

@@ -48,6 +48,14 @@ public class SmsbDeviceController extends BaseController {
         return smsbDeviceService.queryPageList(bo, pageQuery);
     }
 
+    /**
+     * 首页-查询设备列表
+     */
+    @GetMapping("/indexList")
+    public R<List<SmsbDeviceVo>> indexList(SmsbDeviceBo bo) {
+        return smsbDeviceService.indexList(bo);
+    }
+
     /**
      * 查询设备列表
      */

+ 7 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/service/ISmsbDeviceService.java

@@ -158,4 +158,11 @@ public interface ISmsbDeviceService {
      * @return
      */
     boolean refreshCache();
+
+    /**
+     * 首页-获取设备列表
+     * @param bo
+     * @return
+     */
+    R<List<SmsbDeviceVo>> indexList(SmsbDeviceBo bo);
 }

+ 8 - 0
smsb-modules/smsb-device/src/main/java/com/inspur/device/service/impl/SmsbDeviceServiceImpl.java

@@ -525,4 +525,12 @@ public class SmsbDeviceServiceImpl implements ISmsbDeviceService {
         }
         return true;
     }
+
+    @Override
+    public R<List<SmsbDeviceVo>> indexList(SmsbDeviceBo bo) {
+        List<SmsbDeviceVo> result = baseMapper.selectVoList(new LambdaQueryWrapper<SmsbDevice>()
+            .eq(null!= bo.getOnlineStatus() ,SmsbDevice::getOnlineStatus, bo.getOnlineStatus())
+            .orderByDesc(SmsbDevice::getLastOnline));
+        return R.ok(result);
+    }
 }

+ 10 - 0
smsb-modules/smsb-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java

@@ -89,6 +89,16 @@ public class SysTenantController extends BaseController {
         return R.ok(tenantService.queryById(id));
     }
 
+    /**
+     * 首页 - 获取租户名称
+     *
+     * @param tenantId 租户ID
+     */
+    @GetMapping("/index/{tenantId}")
+    public R<SysTenantVo> indexGetInfo(@NotNull(message = "主键不能为空") @PathVariable String tenantId) {
+        return R.ok(tenantService.queryByTenantId(tenantId));
+    }
+
     /**
      * 新增租户
      */

+ 8 - 0
smsb-plus-ui/src/api/smsb/device/device.ts

@@ -16,6 +16,14 @@ export const listDevice = (query?: DeviceQuery): AxiosPromise<DeviceVO[]> => {
   });
 };
 
+export const listIndexDevice = (query?: DeviceQuery): AxiosPromise<DeviceVO[]> => {
+  return request({
+    url: '/smsb/device/indexList',
+    method: 'get',
+    params: query
+  });
+};
+
 export const listDeviceByTenantId = (query?: DeviceQuery): AxiosPromise<DeviceVO[]> => {
   return request({
     url: '/smsb/device/list/tenantId',

+ 8 - 0
smsb-plus-ui/src/api/system/tenant/index.ts

@@ -19,6 +19,14 @@ export function getTenant(id: string | number): AxiosPromise<TenantVO> {
   });
 }
 
+// 首页-查询租户详细
+export function indexGetTenant(id: string | number): AxiosPromise<TenantVO> {
+  return request({
+    url: '/system/tenant/index/' + id,
+    method: 'get'
+  });
+}
+
 // 新增租户
 export function addTenant(data: TenantForm) {
   return request({

+ 4 - 2
smsb-plus-ui/src/layout/components/Navbar.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="navbar">
-    <div class="navbar-left">
+    <div class="navbar-left" @click="gotoIndex">
       <img class="navbar-logo-img" src="@/assets/logo/logo.png" alt="logo" height="27" width="150px" />
 <!--      <span class="navbar-title">浪潮智能信发平台</span>-->
     </div>
@@ -220,7 +220,9 @@ const searchMenuRef = ref<InstanceType<typeof SearchMenu>>();
 const openSearchMenu = () => {
   searchMenuRef.value?.openSearch();
 };
-
+const gotoIndex = () => {
+  proxy.$router.push({ path: '/' });
+};
 // 动态切换
 const dynamicTenantEvent = async (tenantId: string) => {
   if (companyName.value != null && companyName.value !== '') {

+ 282 - 57
smsb-plus-ui/src/views/index.vue

@@ -1,83 +1,308 @@
 <template>
   <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>浪潮智能信发平台</h2>
-
-        <p><b>当前版本:</b> <span>v4.1.0</span></p>
-      </el-col>
-    </el-row>
+    <div class="index-content">
+      <el-row :gutter="20">
+        <el-col :sm="24" :lg="12" style="padding-left: 20px">
+          <!--          <h2>{{tenantName}}</h2>-->
+          <h2>
+            <el-icon style="cursor: pointer;" @click="refreshIndex">
+              <Refresh/>
+            </el-icon>
+              全局概览
+          </h2>
+        </el-col>
+      </el-row>
+      <el-divider style="margin: 5px"/>
+      <div class="statistic-card">
+        <el-row :gutter="20" justify="space-between">
+          <!-- 设备总数 -->
+          <el-col :span="6">
+            <el-statistic :value="totalNum" class="statistic-item" style="cursor: pointer;" @click="refreshDevice(1)">
+              <template #title>
+                <div class="statistic-title">
+                  <span style="color: #07549a;">设备总数</span>
+                </div>
+              </template>
+            </el-statistic>
+          </el-col>
+          <!-- 在线设备 -->
+          <el-col :span="6">
+            <el-statistic :value="onlineNum" class="statistic-item" style="cursor: pointer;" @click="refreshDevice(2)">
+              <template #title>
+                <div class="statistic-title">
+                  <span style="color: darkgreen">在线设备</span>
+                </div>
+              </template>
+            </el-statistic>
+          </el-col>
+          <!-- 离线设备 -->
+          <el-col :span="6">
+            <el-statistic :value="offlineNum" class="statistic-item" style="cursor: pointer;" @click="refreshDevice(3)">
+              <template #title>
+                <div class="statistic-title">
+                  <span style="color: red;">离线设备</span>
+                </div>
+              </template>
+            </el-statistic>
+          </el-col>
+          <!-- 待接入设备 -->
+          <el-col :span="6">
+            <el-statistic :value="initNum" class="statistic-item" style="cursor: pointer;" @click="refreshDevice(4)">
+              <template #title>
+                <div class="statistic-title">
+                  <span style="color: yellowgreen">待接入</span>
+                </div>
+              </template>
+            </el-statistic>
+          </el-col>
+        </el-row>
+      </div>
+      <div class="device-card">
+        <el-row :gutter="20">
+          <el-col
+            v-for="(device, index) in deviceList"
+            :key="device.id"
+            :span="6"
+            style="margin-bottom: 20px;"
+          >
+            <div class="device-item">
+              <div class="device-header">
+                <span class="device-name">{{ device.name }}</span>
+                <span :class="getStatusClass(device.onlineStatus)">
+              {{ getOnlineStatusText(device.onlineStatus) }}
+            </span>
+              </div>
+              <div class="device-info">
+                <p>分辨率: {{ device.resolution }}</p>
+                <p v-if="device.onlineStatus === 1">
+                  上次在线: {{ device.lastOnline }}
+                </p>
+                <p v-else-if="device.onlineStatus === 2">
+                  上次离线: {{ device.offlineTime }}
+                </p>
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </div>
   </div>
 </template>
 
 <script setup name="Index" lang="ts">
-const goTarget = (url: string) => {
-  window.open(url, '__blank');
-};
-</script>
+import useUserStore from "@/store/modules/user";
+import {indexGetTenant} from "@/api/system/tenant";
+import {ref} from "vue";
+import {DeviceStatisticsVo, DeviceVO} from "@/api/smsb/device/device_type";
+import {deviceStatistics, listIndexDevice} from "@/api/smsb/device/device";
+import {Refresh} from "@element-plus/icons-vue";
 
-<style scoped lang="scss">
-.home {
-  blockquote {
-    padding: 10px 20px;
-    margin: 0 0 20px;
-    font-size: 17.5px;
-    border-left: 5px solid #eee;
-  }
+const deviceStatisticsVo = ref<DeviceStatisticsVo>();
+const userStore = useUserStore();
+const tenantId = ref(userStore.tenantId);
+const tenantName = ref("");
+const totalNum = ref(0);
+const onlineNum = ref(0);
+const offlineNum = ref(0);
+const initNum = ref(0);
+const deviceList = ref<DeviceVO[]>([]);
 
-  hr {
-    margin-top: 20px;
-    margin-bottom: 20px;
-    border: 0;
-    border-top: 1px solid #eee;
-  }
+const getTenantName = async () => {
+  const res = await indexGetTenant(tenantId.value)
+  tenantName.value = res.data.companyName;
+}
 
-  .col-item {
-    margin-bottom: 20px;
+const getOnlineStatusText = (status) => {
+  switch (status) {
+    case 0:
+      return '未接入';
+    case 1:
+      return '在线';
+    case 2:
+      return '离线';
+    default:
+      return '未知';
   }
+};
 
-  ul {
-    padding: 0;
-    margin: 0;
+const getStatusClass = (status) => {
+  switch (status) {
+    case 0:
+      return 'status init';
+    case 1:
+      return 'status online';
+    case 2:
+      return 'status offline';
+    default:
+      return '';
+  }
+};
+const getDeviceStatistics = async () => {
+  const res = await deviceStatistics();
+  deviceStatisticsVo.value = res.data;
+  totalNum.value = deviceStatisticsVo.value.totalNum;
+  onlineNum.value = deviceStatisticsVo.value.onlineNum;
+  offlineNum.value = deviceStatisticsVo.value.offlineNum;
+  initNum.value = deviceStatisticsVo.value.initNum;
+};
+const getDeviceList = async () => {
+  const queryParams = {
+    pageNum: 1,
+    pageSize: 500
+  };
+  const res = await listIndexDevice(queryParams);
+  deviceList.value = res.data;
+  deviceList.value.forEach((data) => {
+    data.resolution = data.width + 'x' + data.height;
+  });
+};
+const refreshDevice = async (type: number) => {
+  const queryParams = {
+    pageNum: 1,
+    pageSize: 500,
+    onlineStatus: null
+  };
+  if (type === 2) {
+    queryParams.onlineStatus = 1;
+  }else if (type === 3) {
+    queryParams.onlineStatus = 2;
+  }else if (type === 4) {
+    queryParams.onlineStatus = 0;
   }
+  const res = await listIndexDevice(queryParams);
+  deviceList.value = res.data;
+  deviceList.value.forEach((data) => {
+    data.resolution = data.width + 'x' + data.height;
+  });
+}
+const refreshIndex = () => {
+  getDeviceStatistics()
+  getDeviceList();
+}
+onMounted(() => {
+  // 根据租户ID,获取租户名称
+  getTenantName();
+  getDeviceStatistics()
+  getDeviceList();
+});
+</script>
 
+<style scoped lang="scss">
+.home {
   font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
   font-size: 13px;
   color: #676a6c;
   overflow-x: hidden;
-
-  ul {
-    list-style-type: none;
-  }
-
-  h4 {
-    margin-top: 0px;
-  }
+  padding: 0;
+  margin-top: 10px;
 
   h2 {
     margin-top: 10px;
-    font-size: 26px;
-    font-weight: 100;
+    margin-bottom: 0px;
+    font-size: 22px;
+    font-weight: 600;
   }
+}
 
-  p {
-    margin-top: 10px;
+.index-content {
+  height: calc(100vh - 70px);
+  border-left: #e7eaec 1px solid;
+  width: 99%;
+}
 
-    b {
-      font-weight: 700;
-    }
-  }
+.statistic-card {
+  border-radius: 1px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+  border: 1px solid #ebeef5;
+  padding: 10px 0;
+  height: 80px;
+  background: #ffffff;
+  width: calc(100% - 3px);
+  margin-left: 10px;
+}
 
-  .update-log {
-    ol {
-      display: block;
-      list-style-type: decimal;
-      margin-block-start: 1em;
-      margin-block-end: 1em;
-      margin-inline-start: 0;
-      margin-inline-end: 0;
-      padding-inline-start: 40px;
-    }
-  }
+.statistic-item {
+  text-align: center;
+  padding: 10px 0;
+}
+
+.statistic-title {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+  font-size: 20px;
+  font-weight: 500;
+  margin-bottom: 8px;
+}
+
+.device-card {
+  height: calc(100vh - 210px);
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
+  border: 1px solid #ebeef5;
+  padding: 10px 10px;
+  margin: 10px;
+  width: calc(100% - 3px);
+  overflow-y: auto;
+}
+
+.device-item {
+  border: 1px solid #ebeef5;
+  border-radius: 4px;
+  padding: 15px;
+  height: 115px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  transition: box-shadow 0.3s ease;
+}
+
+.device-item:hover {
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+}
+
+.device-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 10px;
+  padding-bottom: 8px;
+  border-bottom: 1px solid #eee;
+}
+
+.device-name {
+  font-weight: bold;
+  font-size: 16px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.status {
+  font-size: 12px;
+  padding: 2px 6px;
+  border-radius: 4px;
+}
+
+.online {
+  background-color: #f0f9eb;
+  color: #67c23a;
+}
+
+.offline {
+  background-color: #fef0f0;
+  color: #f56c6c;
+}
+
+.init {
+  background-color: #f0f5ff;
+  color: #409eff;
+}
+
+.device-info p {
+  margin: 5px 0;
+  font-size: 13px;
+  color: #666;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 </style>

+ 2 - 2
smsb-plus-ui/src/views/login.vue

@@ -130,8 +130,8 @@ const handleLogin = () => {
       // 调用action的登录方法
       const [err] = await to(userStore.login(loginForm.value));
       if (!err) {
-        // const redirectUrl = redirect.value || '/';
-        const redirectUrl = '/dashboard/device';
+        const redirectUrl = redirect.value || '/';
+        // const redirectUrl = '/dashboard/device';
         await router.push(redirectUrl);
         loading.value = false;
       } else {