Ver código fonte

dashboard调整

moki 3 dias atrás
pai
commit
556ee27594
1 arquivos alterados com 195 adições e 209 exclusões
  1. 195 209
      src/views/ServerConfig.vue

+ 195 - 209
src/views/ServerConfig.vue

@@ -1,22 +1,11 @@
 <script lang="ts" setup>
 <script lang="ts" setup>
 import {onMounted, reactive, ref} from 'vue'
 import {onMounted, reactive, ref} from 'vue'
 import {message, Modal} from 'ant-design-vue'
 import {message, Modal} from 'ant-design-vue'
-import {DeleteOutlined, EditOutlined} from '@ant-design/icons-vue'
+import {DeleteOutlined, EditOutlined, PlusOutlined} from '@ant-design/icons-vue'
 import {createMqtt, deleteMqtt, getMqttList, updateMqtt} from '@/api/mqtt'
 import {createMqtt, deleteMqtt, getMqttList, updateMqtt} from '@/api/mqtt'
 import {createBle, deleteBle, getBleList, updateBle} from '@/api/ble'
 import {createBle, deleteBle, getBleList, updateBle} from '@/api/ble'
 import type {BleConfig, BleConfigForm, MqttConfig, MqttConfigForm} from '@/types'
 import type {BleConfig, BleConfigForm, MqttConfig, MqttConfigForm} from '@/types'
 
 
-const activeTab = ref('mqtt')
-
-const tabList = [
-  {key: 'mqtt', tab: '消息配置'},
-  {key: 'ble', tab: '蓝牙配置'},
-]
-
-function onTabChange(key: string) {
-  activeTab.value = key
-}
-
 // MQTT 相关
 // MQTT 相关
 const mqttLoading = ref(false)
 const mqttLoading = ref(false)
 const mqttList = ref<MqttConfig[]>([])
 const mqttList = ref<MqttConfig[]>([])
@@ -205,181 +194,213 @@ onMounted(() => {
 
 
 <template>
 <template>
   <div class="server-config-page">
   <div class="server-config-page">
-    <a-card
-        :active-tab-key="activeTab"
-        :tab-list="tabList"
-        :body-style="{ padding: '10px' }"
-        style="width: 100%; height: 100%;"
-        @tabChange="onTabChange"
-    >
-      <!-- 消息配置 -->
-      <template v-if="activeTab === 'mqtt'">
-        <a-spin :spinning="mqttLoading">
-          <div class="card-grid">
-            <a-card v-for="item in mqttList" :key="item.id" class="config-card" size="small">
-              <template #title>
-                <div class="card-title">服务器 {{ item.id }}</div>
-              </template>
-              <div class="card-content">
-                <a-row :gutter="[0, 4]">
-                  <a-col :span="8" class="label">地址:</a-col>
-                  <a-col :span="16" class="value">{{ item.broker }}</a-col>
-                  <a-col :span="8" class="label">状态:</a-col>
-                  <a-col :span="16">
-                    <a-tag :color="item.enabled ? 'success' : 'default'" size="small">{{
-                        item.enabled ? '启用' : '禁用'
-                      }}
-                    </a-tag>
-                  </a-col>
-                  <a-col :span="8" class="label">客户端ID:</a-col>
-                  <a-col :span="16" class="value">{{ item.client_id }}</a-col>
-                  <a-col :span="8" class="label">主题:</a-col>
-                  <a-col :span="16" class="value">{{ item.topic }}</a-col>
-                </a-row>
-              </div>
-              <template #actions>
-                <a-button class="action-btn" size="small" type="link" @click="openMqttModal(item)">
-                  <EditOutlined/>
-                  编辑
-                </a-button>
-                <a-button class="action-btn" danger size="small" type="link" @click="onMqttDelete(item)">
-                  <DeleteOutlined/>
-                  删除
-                </a-button>
-              </template>
-            </a-card>
-
-            <a-card class="config-card add-card" size="small" @click="openMqttModal()">
-              <div class="add-card-content">
-                <img alt="add" class="add-icon" src="/plus.svg"/>
-              </div>
-            </a-card>
-          </div>
-        </a-spin>
-
-        <a-modal
-            :ok-text="mqttEditingId !== null ? '更新' : '创建'"
-            :open="mqttModalVisible"
-            :title="mqttEditingId !== null ? '编辑消息配置' : '新建消息配置'"
-            :width="480"
-            cancel-text="取消"
-            @cancel="mqttModalVisible = false"
-            @ok="onMqttSubmit"
-        >
-          <a-form layout="vertical">
-            <a-form-item label="Broker 地址" required>
-              <a-input v-model:value="mqttForm.broker" placeholder="tcp://127.0.0.1:1883"/>
-            </a-form-item>
-            <a-form-item label="客户端ID">
-              <a-input v-model:value="mqttForm.client_id" placeholder="agent-monitor"/>
-            </a-form-item>
-            <a-form-item label="用户名">
-              <a-input v-model:value="mqttForm.username" placeholder="可选"/>
-            </a-form-item>
-            <a-form-item label="密码">
-              <a-input-password v-model:value="mqttForm.password" placeholder="可选"/>
-            </a-form-item>
-            <a-form-item label="主题">
-              <a-input v-model:value="mqttForm.topic" placeholder="agent/status"/>
-            </a-form-item>
-            <a-form-item label="启用">
-              <a-switch v-model:checked="mqttForm.enabled"/>
-            </a-form-item>
-          </a-form>
-        </a-modal>
-      </template>
-
-      <!-- 蓝牙配置 -->
-      <template v-if="activeTab === 'ble'">
-        <a-spin :spinning="bleLoading">
-          <div class="card-grid">
-            <a-card v-for="item in bleList" :key="item.id" class="config-card" size="small">
-              <template #title>
-                <div class="card-title">蓝牙 {{ item.id }}</div>
-              </template>
-              <div class="card-content">
-                <a-row :gutter="[0, 4]">
-                  <a-col :span="8" class="label">设备名称:</a-col>
-                  <a-col :span="16" class="value">{{ item.device_name }}</a-col>
-                  <a-col :span="8" class="label">状态:</a-col>
-                  <a-col :span="16">
-                    <a-tag :color="item.enabled ? 'success' : 'default'" size="small">{{
-                        item.enabled ? '启用' : '禁用'
-                      }}
-                    </a-tag>
-                  </a-col>
-                  <a-col :span="8" class="label">服务码:</a-col>
-                  <a-col :span="16" :title="item.service_uuid" class="value">{{
-                      truncate(item.service_uuid, 20)
+    <!-- MQTT 配置 -->
+    <div class="section-card">
+      <div class="section-header">
+        <span class="section-title">消息配置 (MQTT)</span>
+        <a-button size="small" type="primary" @click="openMqttModal()">
+          <template #icon>
+            <PlusOutlined/>
+          </template>
+          新建
+        </a-button>
+      </div>
+      <a-spin :spinning="mqttLoading">
+        <div v-if="mqttList.length === 0" class="empty-text">暂无配置</div>
+        <div v-else class="card-grid">
+          <a-card v-for="item in mqttList" :key="item.id" class="config-card" size="small">
+            <template #title>
+              <div class="card-title">服务器 {{ item.id }}</div>
+            </template>
+            <div class="card-content">
+              <a-row :gutter="[0, 4]">
+                <a-col :span="8" class="label">地址:</a-col>
+                <a-col :span="16" class="value">{{ item.broker }}</a-col>
+                <a-col :span="8" class="label">状态:</a-col>
+                <a-col :span="16">
+                  <a-tag :color="item.enabled ? 'success' : 'default'" size="small">{{
+                      item.enabled ? '启用' : '禁用'
                     }}
                     }}
-                  </a-col>
-                  <a-col :span="8" class="label">模式码:</a-col>
-                  <a-col :span="16" :title="item.mode_char_uuid" class="value">{{
-                      truncate(item.mode_char_uuid, 20)
+                  </a-tag>
+                </a-col>
+                <a-col :span="8" class="label">客户端ID:</a-col>
+                <a-col :span="16" class="value">{{ item.client_id }}</a-col>
+                <a-col :span="8" class="label">主题:</a-col>
+                <a-col :span="16" class="value">{{ item.topic }}</a-col>
+              </a-row>
+            </div>
+            <template #actions>
+              <a-button class="action-btn" size="small" type="link" @click="openMqttModal(item)">
+                <EditOutlined/>
+                编辑
+              </a-button>
+              <a-button class="action-btn" danger size="small" type="link" @click="onMqttDelete(item)">
+                <DeleteOutlined/>
+                删除
+              </a-button>
+            </template>
+          </a-card>
+        </div>
+      </a-spin>
+    </div>
+
+    <!-- BLE 配置 -->
+    <div class="section-card">
+      <div class="section-header">
+        <span class="section-title">蓝牙配置 (BLE)</span>
+        <a-button size="small" type="primary" @click="openBleModal()">
+          <template #icon>
+            <PlusOutlined/>
+          </template>
+          新建
+        </a-button>
+      </div>
+      <a-spin :spinning="bleLoading">
+        <div v-if="bleList.length === 0" class="empty-text">暂无配置</div>
+        <div v-else class="card-grid">
+          <a-card v-for="item in bleList" :key="item.id" class="config-card" size="small">
+            <template #title>
+              <div class="card-title">蓝牙 {{ item.id }}</div>
+            </template>
+            <div class="card-content">
+              <a-row :gutter="[0, 4]">
+                <a-col :span="8" class="label">设备名称:</a-col>
+                <a-col :span="16" class="value">{{ item.device_name }}</a-col>
+                <a-col :span="8" class="label">状态:</a-col>
+                <a-col :span="16">
+                  <a-tag :color="item.enabled ? 'success' : 'default'" size="small">{{
+                      item.enabled ? '启用' : '禁用'
                     }}
                     }}
-                  </a-col>
-                </a-row>
-              </div>
-              <template #actions>
-                <a-button class="action-btn" size="small" type="link" @click="openBleModal(item)">
-                  <EditOutlined/>
-                  编辑
-                </a-button>
-                <a-button class="action-btn" danger size="small" type="link" @click="onBleDelete(item)">
-                  <DeleteOutlined/>
-                  删除
-                </a-button>
-              </template>
-            </a-card>
-
-            <a-card class="config-card add-card" size="small" @click="openBleModal()">
-              <div class="add-card-content">
-                <img alt="add" class="add-icon" src="/plus.svg"/>
-              </div>
-            </a-card>
-          </div>
-        </a-spin>
-
-        <a-modal
-            :ok-text="bleEditingId !== null ? '更新' : '创建'"
-            :open="bleModalVisible"
-            :title="bleEditingId !== null ? '编辑蓝牙配置' : '新建蓝牙配置'"
-            :width="520"
-            cancel-text="取消"
-            @cancel="bleModalVisible = false"
-            @ok="onBleSubmit"
-        >
-          <a-form layout="vertical">
-            <a-form-item label="设备名称" required>
-              <a-input v-model:value="bleForm.device_name" placeholder="AI-Light"/>
-            </a-form-item>
-            <a-form-item label="服务码" required>
-              <a-input v-model:value="bleForm.service_uuid" :placeholder="DEFAULT_SERVICE_UUID"/>
-            </a-form-item>
-            <a-form-item label="模式码" required>
-              <a-input v-model:value="bleForm.mode_char_uuid" :placeholder="DEFAULT_MODE_CHAR_UUID"/>
-              <div class="form-hint">读写/通知 - 灯效模式控制</div>
-            </a-form-item>
-            <a-form-item label="启用">
-              <a-switch v-model:checked="bleForm.enabled"/>
-            </a-form-item>
-          </a-form>
-        </a-modal>
-      </template>
-    </a-card>
+                  </a-tag>
+                </a-col>
+                <a-col :span="8" class="label">服务码:</a-col>
+                <a-col :span="16" :title="item.service_uuid" class="value">{{
+                    truncate(item.service_uuid, 20)
+                  }}
+                </a-col>
+                <a-col :span="8" class="label">模式码:</a-col>
+                <a-col :span="16" :title="item.mode_char_uuid" class="value">{{
+                    truncate(item.mode_char_uuid, 20)
+                  }}
+                </a-col>
+              </a-row>
+            </div>
+            <template #actions>
+              <a-button class="action-btn" size="small" type="link" @click="openBleModal(item)">
+                <EditOutlined/>
+                编辑
+              </a-button>
+              <a-button class="action-btn" danger size="small" type="link" @click="onBleDelete(item)">
+                <DeleteOutlined/>
+                删除
+              </a-button>
+            </template>
+          </a-card>
+        </div>
+      </a-spin>
+    </div>
+
+    <!-- MQTT 弹窗 -->
+    <a-modal
+        :ok-text="mqttEditingId !== null ? '更新' : '创建'"
+        :open="mqttModalVisible"
+        :title="mqttEditingId !== null ? '编辑消息配置' : '新建消息配置'"
+        :width="480"
+        cancel-text="取消"
+        @cancel="mqttModalVisible = false"
+        @ok="onMqttSubmit"
+    >
+      <a-form layout="vertical">
+        <a-form-item label="Broker 地址" required>
+          <a-input v-model:value="mqttForm.broker" placeholder="tcp://127.0.0.1:1883"/>
+        </a-form-item>
+        <a-form-item label="客户端ID">
+          <a-input v-model:value="mqttForm.client_id" placeholder="agent-monitor"/>
+        </a-form-item>
+        <a-form-item label="用户名">
+          <a-input v-model:value="mqttForm.username" placeholder="可选"/>
+        </a-form-item>
+        <a-form-item label="密码">
+          <a-input-password v-model:value="mqttForm.password" placeholder="可选"/>
+        </a-form-item>
+        <a-form-item label="主题">
+          <a-input v-model:value="mqttForm.topic" placeholder="agent/status"/>
+        </a-form-item>
+        <a-form-item label="启用">
+          <a-switch v-model:checked="mqttForm.enabled"/>
+        </a-form-item>
+      </a-form>
+    </a-modal>
+
+    <!-- BLE 弹窗 -->
+    <a-modal
+        :ok-text="bleEditingId !== null ? '更新' : '创建'"
+        :open="bleModalVisible"
+        :title="bleEditingId !== null ? '编辑蓝牙配置' : '新建蓝牙配置'"
+        :width="520"
+        cancel-text="取消"
+        @cancel="bleModalVisible = false"
+        @ok="onBleSubmit"
+    >
+      <a-form layout="vertical">
+        <a-form-item label="设备名称" required>
+          <a-input v-model:value="bleForm.device_name" placeholder="AI-Light"/>
+        </a-form-item>
+        <a-form-item label="服务码" required>
+          <a-input v-model:value="bleForm.service_uuid" :placeholder="DEFAULT_SERVICE_UUID"/>
+        </a-form-item>
+        <a-form-item label="模式码" required>
+          <a-input v-model:value="bleForm.mode_char_uuid" :placeholder="DEFAULT_MODE_CHAR_UUID"/>
+          <div class="form-hint">读写/通知 - 灯效模式控制</div>
+        </a-form-item>
+        <a-form-item label="启用">
+          <a-switch v-model:checked="bleForm.enabled"/>
+        </a-form-item>
+      </a-form>
+    </a-modal>
   </div>
   </div>
 </template>
 </template>
 
 
 <style scoped>
 <style scoped>
 .server-config-page {
 .server-config-page {
   color: var(--text-color);
   color: var(--text-color);
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
   height: 100%;
   height: 100%;
+}
+
+.section-card {
+  flex: 1;
+  min-height: 0;
+  background: var(--card-bg);
+  border: 1px solid var(--border-color);
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+  padding: 16px 20px;
   display: flex;
   display: flex;
   flex-direction: column;
   flex-direction: column;
+  overflow: auto;
 }
 }
 
 
-.server-config-page :deep(.ant-card-head) {
-  padding: 0 15px;
+.section-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 12px;
+}
+
+.section-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--text-secondary);
+}
+
+.empty-text {
+  color: var(--text-secondary);
+  font-size: 13px;
+  text-align: center;
+  padding: 24px 0;
 }
 }
 
 
 .card-grid {
 .card-grid {
@@ -479,39 +500,4 @@ onMounted(() => {
   font-size: 12px;
   font-size: 12px;
   margin-top: 4px;
   margin-top: 4px;
 }
 }
-
-.add-card {
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  background: transparent;
-  border: 1px dashed var(--border-color);
-  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px 0 rgba(0, 0, 0, 0.02);
-  transition: all 0.3s;
-}
-
-.add-card:hover {
-  border-color: #1890ff;
-  box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.06), 0 6px 16px 0 rgba(0, 0, 0, 0.04), 0 9px 28px 8px rgba(0, 0, 0, 0.03);
-}
-
-.add-card-content {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 100%;
-  height: 100%;
-}
-
-.add-icon {
-  width: 48px;
-  height: 48px;
-  opacity: 0.3;
-  transition: opacity 0.3s;
-}
-
-.add-card:hover .add-icon {
-  opacity: 0.6;
-}
 </style>
 </style>