5 Commits
Author SHA1 Message Date
hz4th_coder b473ae7205 新增机器人分类: 4子分类(机械臂/AGV-AMR/人形/ROV)+91公共字段按8大类字段类别分组 (v2.4.0) 2026-09-14 12:27:58 +08:00
hz4th_coder dee20ca122 CPU公共参数字段升级为46字段+字段类别分组(物理参数/产品信息/核心配置/性能/缓存/架构/指令集) (v2.3.0) 2026-09-14 11:41:41 +08:00
hz4th_coder ea8165bbd8 修复启动脚本: 改用 openclaw conda 环境 python3 (系统 python3.10 无 flask 导致启动失败) (v2.2.2) 2026-09-12 12:33:51 +08:00
hz4th_coder 2d5abe5975 修复分类编辑弹窗内按钮触发表单提交导致跳转首页的问题 (v2.2.1)
- 根因: 编辑分类弹窗里的子类别/参数字段列表按钮渲染在 <form id=itemForm> 内且无 type=button,HTML 按钮默认 type=submit,点击时同时触发表单 GET 提交 → 页面刷新跳转到 /admin 首页
- 修复: 给 renderSubcategoriesList/renderFieldsList 的编辑/删除按钮、getImageUploadComponent 的图片操作按钮补 type=button
- 加固: 全局拦截 itemForm 原生 submit (preventDefault),保存统一走 saveItem,杜绝同类按钮再次引发页面跳转
2026-09-10 01:46:59 +08:00
hz4th_coder 9005a48bf3 GPU显卡公共参数字段全面升级为66字段+字段类别支持
- 按显卡规格9大类别整理66个公共参数字段(全部文本类型):
  图形处理器芯片基础信息(14)/显卡产品信息(12)/渲染硬件配置(8)/理论算力(5)/显存规格(5)/矩阵算力(8)/数值格式支持(2)/图形API与特性(6)/板卡设计(6)
- 每个字段新增 category 字段类别属性(对应#开头的参数类别中文名)
- 保留平台必备结构字段: name/manufacturer/official_urls/reference_urls/description
- 后台字段编辑弹框新增「字段类别」输入,字段列表显示📁类别徽标
- 子类别关键特性映射到新字段(显存容量/着色单元/首发价/FP32等)
- 修复重复FP16: 理论算力=fp16, 矩阵算力=fp16_matrix
2026-09-10 01:32:21 +08:00
3 changed files with 2079 additions and 231 deletions
+2042 -224
View File
File diff suppressed because it is too large Load Diff
Executable
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
# param-hub 启动脚本(setsid 完全脱离终端,确保持久运行)
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
PID_FILE="$APP_DIR/app.pid"
PYTHON="/home/hz1/miniconda3/envs/openclaw/bin/python3"
cd "$APP_DIR"
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if ps -p $PID > /dev/null 2>&1; then
echo "param-hub 已在运行 (PID: $PID)"
exit 0
fi
fi
setsid nohup "$PYTHON" app.py > logs/app.log 2>&1 &
echo $! > "$PID_FILE"
sleep 2
echo "param-hub 已启动 (PID: $(cat $PID_FILE))"
+20 -7
View File
@@ -507,6 +507,7 @@
<div class="space-y-4"> <div class="space-y-4">
<div><label class="text-sm text-gray-600 mb-1 block">字段名 *</label><input type="text" id="field_key" class="w-full px-3 py-2 border rounded-lg" placeholder="如:context_length"></div> <div><label class="text-sm text-gray-600 mb-1 block">字段名 *</label><input type="text" id="field_key" class="w-full px-3 py-2 border rounded-lg" placeholder="如:context_length"></div>
<div><label class="text-sm text-gray-600 mb-1 block">显示名 *</label><input type="text" id="field_label" class="w-full px-3 py-2 border rounded-lg" placeholder="如:上下文长度"></div> <div><label class="text-sm text-gray-600 mb-1 block">显示名 *</label><input type="text" id="field_label" class="w-full px-3 py-2 border rounded-lg" placeholder="如:上下文长度"></div>
<div><label class="text-sm text-gray-600 mb-1 block">字段类别</label><input type="text" id="field_category" class="w-full px-3 py-2 border rounded-lg" placeholder="如:图形处理器芯片基础信息(参数分组,可为空)"></div>
<div><label class="text-sm text-gray-600 mb-1 block">字段类型</label><select id="field_type" class="w-full px-3 py-2 border rounded-lg"> <div><label class="text-sm text-gray-600 mb-1 block">字段类型</label><select id="field_type" class="w-full px-3 py-2 border rounded-lg">
<option value="text">文本</option> <option value="text">文本</option>
<option value="number">数字</option> <option value="number">数字</option>
@@ -1585,7 +1586,7 @@
${imageUrls.map((url, idx) => ` ${imageUrls.map((url, idx) => `
<div class="relative w-24 h-24 border rounded-lg overflow-hidden group"> <div class="relative w-24 h-24 border rounded-lg overflow-hidden group">
<img src="${url}" class="w-full h-full object-cover"> <img src="${url}" class="w-full h-full object-cover">
<button onclick="removeImage(${idx})" class="absolute top-1 right-1 w-6 h-6 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition flex items-center justify-center"> <button type="button" onclick="removeImage(${idx})" class="absolute top-1 right-1 w-6 h-6 bg-red-500 text-white rounded-full opacity-0 group-hover:opacity-100 transition flex items-center justify-center">
<i class="ri-close-line"></i> <i class="ri-close-line"></i>
</button> </button>
</div> </div>
@@ -1593,10 +1594,10 @@
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<input type="file" id="imageInput" accept="image/*" multiple class="hidden" onchange="handleImageUpload(event, '${type}')"> <input type="file" id="imageInput" accept="image/*" multiple class="hidden" onchange="handleImageUpload(event, '${type}')">
<button onclick="document.getElementById('imageInput').click()" class="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 text-sm"> <button type="button" onclick="document.getElementById('imageInput').click()" class="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 text-sm">
<i class="ri-image-add-line mr-1"></i>选择图片 <i class="ri-image-add-line mr-1"></i>选择图片
</button> </button>
<button onclick="pasteImageFromClipboard('${type}')'" class="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 text-sm"> <button type="button" onclick="pasteImageFromClipboard('${type}')'" class="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 text-sm">
<i class="ri-clipboard-line mr-1"></i>粘贴图片 <i class="ri-clipboard-line mr-1"></i>粘贴图片
</button> </button>
</div> </div>
@@ -1842,10 +1843,10 @@
</div> </div>
</div> </div>
<div class="flex gap-2 opacity-0 group-hover:opacity-100 transition"> <div class="flex gap-2 opacity-0 group-hover:opacity-100 transition">
<button onclick="editSubcategory(${index})" class="px-2 py-1 text-blue-600 hover:bg-blue-50 rounded text-sm"> <button type="button" onclick="editSubcategory(${index})" class="px-2 py-1 text-blue-600 hover:bg-blue-50 rounded text-sm">
<i class="ri-edit-line"></i> <i class="ri-edit-line"></i>
</button> </button>
<button onclick="deleteSubcategory(${index})" class="px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm"> <button type="button" onclick="deleteSubcategory(${index})" class="px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm">
<i class="ri-delete-bin-line"></i> <i class="ri-delete-bin-line"></i>
</button> </button>
</div> </div>
@@ -1879,13 +1880,14 @@
${field.required ? '<span class="text-red-500">必填</span>' : '可选'} ${field.required ? '<span class="text-red-500">必填</span>' : '可选'}
${field.description ? ` | ${field.description}` : ''} ${field.description ? ` | ${field.description}` : ''}
</div> </div>
${field.category ? `<div class="mt-1"><span class="inline-block px-2 py-0.5 bg-indigo-50 text-indigo-600 border border-indigo-100 rounded text-xs">📁 ${field.category}</span></div>` : ''}
</div> </div>
</div> </div>
<div class="flex gap-2 opacity-0 group-hover:opacity-100 transition"> <div class="flex gap-2 opacity-0 group-hover:opacity-100 transition">
<button onclick="editField(${index})" class="px-2 py-1 text-blue-600 hover:bg-blue-50 rounded text-sm"> <button type="button" onclick="editField(${index})" class="px-2 py-1 text-blue-600 hover:bg-blue-50 rounded text-sm">
<i class="ri-edit-line"></i> <i class="ri-edit-line"></i>
</button> </button>
<button onclick="deleteField(${index})" class="px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm"> <button type="button" onclick="deleteField(${index})" class="px-2 py-1 text-red-600 hover:bg-red-50 rounded text-sm">
<i class="ri-delete-bin-line"></i> <i class="ri-delete-bin-line"></i>
</button> </button>
</div> </div>
@@ -1900,6 +1902,7 @@
document.getElementById('fieldModalTitle').textContent = '添加参数字段'; document.getElementById('fieldModalTitle').textContent = '添加参数字段';
document.getElementById('field_key').value = ''; document.getElementById('field_key').value = '';
document.getElementById('field_label').value = ''; document.getElementById('field_label').value = '';
document.getElementById('field_category').value = '';
document.getElementById('field_type').value = 'text'; document.getElementById('field_type').value = 'text';
document.getElementById('field_desc').value = ''; document.getElementById('field_desc').value = '';
document.getElementById('field_required').checked = false; document.getElementById('field_required').checked = false;
@@ -1915,6 +1918,7 @@
document.getElementById('fieldModalTitle').textContent = '编辑参数字段'; document.getElementById('fieldModalTitle').textContent = '编辑参数字段';
document.getElementById('field_key').value = field.key || ''; document.getElementById('field_key').value = field.key || '';
document.getElementById('field_label').value = field.label || ''; document.getElementById('field_label').value = field.label || '';
document.getElementById('field_category').value = field.category || '';
document.getElementById('field_type').value = field.type || 'text'; document.getElementById('field_type').value = field.type || 'text';
document.getElementById('field_desc').value = field.description || ''; document.getElementById('field_desc').value = field.description || '';
document.getElementById('field_required').checked = field.required || false; document.getElementById('field_required').checked = field.required || false;
@@ -1938,6 +1942,7 @@
function saveField() { function saveField() {
const key = document.getElementById('field_key').value.trim(); const key = document.getElementById('field_key').value.trim();
const label = document.getElementById('field_label').value.trim(); const label = document.getElementById('field_label').value.trim();
const category = document.getElementById('field_category').value.trim();
const type = document.getElementById('field_type').value; const type = document.getElementById('field_type').value;
const description = document.getElementById('field_desc').value.trim(); const description = document.getElementById('field_desc').value.trim();
const required = document.getElementById('field_required').checked; const required = document.getElementById('field_required').checked;
@@ -1948,6 +1953,7 @@
} }
const field = { key, label, type, description, required }; const field = { key, label, type, description, required };
if (category) field.category = category;
if (currentFieldTarget === 'subcategory') { if (currentFieldTarget === 'subcategory') {
// 子类别额外字段 // 子类别额外字段
@@ -2233,6 +2239,13 @@
document.getElementById('smartUpdateModal').addEventListener('click', function(e) { if (e.target === this) closeSmartUpdateModal(); }); document.getElementById('smartUpdateModal').addEventListener('click', function(e) { if (e.target === this) closeSmartUpdateModal(); });
document.getElementById('fieldModal').addEventListener('click', function(e) { if (e.target === this) closeFieldModal(); }); document.getElementById('fieldModal').addEventListener('click', function(e) { if (e.target === this) closeFieldModal(); });
// 防止 itemForm 原生提交(保存统一走 saveItem,避免表单 GET 提交导致页面跳转/刷新)
document.addEventListener('submit', function(e) {
if (e.target && e.target.id === 'itemForm') {
e.preventDefault();
}
});
// ============ 智能添加功能 ============ // ============ 智能添加功能 ============
let smartAddType = ''; let smartAddType = '';