Bläddra i källkod

feat(setting): 添加动态参数刷新功能并优化参数显示

- 添加单个参数刷新按钮和刷新功能实现
- 参数列表中显示参数地址和提示信息
- 优化参数卡片布局和样式调整
- 添加刷新和保存状态控制防止并发操作
- 统一参数状态管理字段命名
- 修复参数列表渲染的key值问题
- 临时禁用Python服务器创建功能
- 添加单参数获取接口映射配置
panqiuyao 3 veckor sedan
förälder
incheckning
8cde00eb3e
2 ändrade filer med 92 tillägg och 22 borttagningar
  1. 2 1
      electron/utils/socket.js
  2. 90 21
      frontend/src/views/Setting/components/AdvancedConfig.vue

+ 2 - 1
electron/utils/socket.js

@@ -24,7 +24,8 @@ const typeToMessage = {
   upload_goods_progress:"PhotographyDetail",
   detail_result_progress:"PhotographyDetail",
   "get_dynamic_config":"seeting",
-  "set_dynamic_config":"seeting"
+  "set_dynamic_config":"seeting",
+  "get_dynamic_config_signle":"seeting"
 }
 
 // MCU 错误日志配置(从 config 读取,默认100条)

+ 90 - 21
frontend/src/views/Setting/components/AdvancedConfig.vue

@@ -15,9 +15,9 @@
           <span>暂无可配置的动态参数</span>
         </div>
         <div class="param-grid" v-else>
-          <div v-for="(param, index) in dynamicParams" :key="index" class="param-card">
+          <div v-for="(param, index) in dynamicParams" :key="param.key || index" class="param-card">
             <div class="param-header">
-              <span class="param-name">{{ param.tips || `参数${param.addr}` }}</span>
+              <span class="param-name">{{param.addr}} : {{ param.tips || `参数${param.addr}` }}</span>
               <el-tag v-if="param.readonly" type="info" size="small" effect="plain">只读</el-tag>
             </div>
             <div class="param-body">
@@ -41,26 +41,36 @@
                 class="param-input"
               />
               <el-button
+                size="default"
+                :loading="refreshingIndex === index"
+                :disabled="refreshingIndex === index || savingIndex === index"
+                @click="refreshParam(param, index)"
+                class="param-action-btn"
+              >
+                <el-icon v-if="refreshingIndex !== index"><Refresh /></el-icon>
+                刷新
+              </el-button>
+              <el-button
                 type="primary"
                 size="default"
                 :loading="savingIndex === index"
-                :disabled="param.readonly"
+                :disabled="param.readonly || savingIndex === index || refreshingIndex === index"
                 @click="saveParam(param, index)"
-                class="param-save-btn"
+                class="param-action-btn"
               >
                 <el-icon v-if="savingIndex !== index"><Check /></el-icon>
                 保存
               </el-button>
             </div>
             <div
-              v-if="param.saveStatus"
+              v-if="param.statusType"
               class="param-status"
-              :class="`status-${param.saveStatus}`"
+              :class="`status-${param.statusType}`"
             >
               <el-icon>
-                <component :is="param.saveStatus === 'success' ? CircleCheck : CircleClose" />
+                <component :is="param.statusType === 'success' ? CircleCheck : CircleClose" />
               </el-icon>
-              <span>{{ param.saveStatus === 'success' ? '已保存' : '保存失败' }}</span>
+              <span>{{ param.statusText }}</span>
             </div>
           </div>
         </div>
@@ -86,6 +96,7 @@ const dynamicParams = ref<any[]>([]);
 // 加载状态
 const loading = ref(false);
 const savingIndex = ref<number>(-1);
+const refreshingIndex = ref<number>(-1);
 
 // 状态自动清除定时器
 const statusTimers = new Map<number, number>();
@@ -99,15 +110,19 @@ async function fetchDynamicConfig() {
     });
 
     const handler = (event: any, result: any) => {
+      console.log('get_dynamic_config')
+      console.log(result)
       if (result.code === 0 && result.data) {
         dynamicParams.value = Object.keys(result.data).map(key => ({
+          key,
           addr: result.data[key].addr,
           tips: result.data[key].tips,
           readonly: result.data[key].readonly,
           type: result.data[key].type,
           precision: result.data[key].precision,
           value: result.data[key].value,
-          saveStatus: ''
+          statusType: '',
+          statusText: ''
         }));
       } else if (result.msg) {
         ElMessage.error(result.msg);
@@ -125,14 +140,67 @@ async function fetchDynamicConfig() {
   });
 }
 
+// 刷新单个参数
+function refreshParam(param: any, index: number) {
+  if (refreshingIndex.value !== -1 || savingIndex.value !== -1) {
+    return;
+  }
+
+  refreshingIndex.value = index;
+  param.statusType = '';
+  param.statusText = '';
+
+  socketStore.sendMessage({
+    type: 'get_dynamic_config_signle',
+    data: {
+      name: param.addr
+    }
+  });
+
+  const handler = (event: any, result: any) => {
+    clientStore.ipc.removeAllListeners(icpList.socket.message + '_get_dynamic_config_signle');
+    console.log('get_dynamic_config_signle')
+    console.log(result)
+    refreshingIndex.value = -1;
+
+    const name = param.tips || `参数${param.addr}`;
+    if (result.code === 0 && result.data) {
+      if (result.data.value !== undefined && result.data.value !== null) {
+        param.value = result.data.value;
+      }
+      param.statusType = 'success';
+      param.statusText = '已刷新到最新值';
+    } else {
+      param.statusType = 'fail';
+      param.statusText = result.msg || `${name} 刷新失败`;
+    }
+
+    scheduleClearStatus(index);
+  };
+
+  clientStore.ipc.once(icpList.socket.message + '_get_dynamic_config_signle', handler);
+
+  setTimeout(() => {
+    clientStore.ipc.removeAllListeners(icpList.socket.message + '_get_dynamic_config_signle');
+
+    if (refreshingIndex.value === index) {
+      refreshingIndex.value = -1;
+      param.statusType = 'fail';
+      param.statusText = '刷新超时';
+      scheduleClearStatus(index);
+    }
+  }, 5000);
+}
+
 // 保存单个参数
 function saveParam(param: any, index: number) {
-  if (param.readonly || savingIndex.value !== -1) {
+  if (param.readonly || savingIndex.value !== -1 || refreshingIndex.value !== -1) {
     return;
   }
 
   savingIndex.value = index;
-  param.saveStatus = '';
+  param.statusType = '';
+  param.statusText = '';
 
   socketStore.sendMessage({
     type: 'set_dynamic_config',
@@ -152,11 +220,11 @@ function saveParam(param: any, index: number) {
 
     const name = param.tips || `参数${param.addr}`;
     if (result.code === 0) {
-      param.saveStatus = 'success';
-      ElMessage.success(`${name} 保存成功`);
+      param.statusType = 'success';
+      param.statusText = '已保存';
     } else {
-      param.saveStatus = 'fail';
-      ElMessage.error(result.msg || `${name} 保存失败`);
+      param.statusType = 'fail';
+      param.statusText = result.msg || `${name} 保存失败`;
     }
 
     scheduleClearStatus(index);
@@ -168,8 +236,8 @@ function saveParam(param: any, index: number) {
     clientStore.ipc.removeAllListeners(icpList.socket.message + '_set_dynamic_config');
     if (savingIndex.value === index) {
       savingIndex.value = -1;
-      param.saveStatus = 'fail';
-      ElMessage.error('保存超时');
+      param.statusType = 'fail';
+      param.statusText = '保存超时';
       scheduleClearStatus(index);
     }
   }, 5000);
@@ -183,7 +251,8 @@ function scheduleClearStatus(index: number) {
   }
   const timer = window.setTimeout(() => {
     if (dynamicParams.value[index]) {
-      dynamicParams.value[index].saveStatus = '';
+      dynamicParams.value[index].statusType = '';
+      dynamicParams.value[index].statusText = '';
     }
     statusTimers.delete(index);
   }, 3000);
@@ -254,7 +323,7 @@ $text-secondary: #909399;
 
 .param-grid {
   display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
+  grid-template-columns: repeat(auto-fill, minmax(440px, 1fr));
   gap: 16px;
 }
 
@@ -293,9 +362,9 @@ $text-secondary: #909399;
       min-width: 0;
     }
 
-    .param-save-btn {
+    .param-action-btn {
       flex-shrink: 0;
-      min-width: 80px;
+      min-width: 72px;
     }
 
     :deep(.el-input-number) {