diff --git a/app/static/index.html b/app/static/index.html
index b104e83..195337a 100644
--- a/app/static/index.html
+++ b/app/static/index.html
@@ -365,6 +365,15 @@
font-size: 12px;
}
+ .symbol-table .symbol-category-row td {
+ background: var(--primary-light);
+ color: white;
+ font-weight: 600;
+ font-size: 13px;
+ padding: 8px 16px;
+ border-bottom: none;
+ }
+
.add-symbol-form {
background: var(--gray-50);
border: 2px dashed var(--gray-300);
@@ -1357,6 +1366,38 @@
let taskSymbolsData = [];
let selectedTaskSymbols = [];
let currentTaskId = null;
+
+ // 品种分类映射表
+ const SYMBOL_CATEGORIES = {
+ // 贵金属
+ '沪金': '贵金属', '沪银': '贵金属', '铂金': '贵金属', '钯金': '贵金属',
+ // 有色金属
+ '沪铜': '有色金属', '沪铝': '有色金属', '沪锌': '有色金属', '沪铅': '有色金属',
+ '沪镍': '有色金属', '沪锡': '有色金属', '氧化铝': '有色金属', '国际铜': '有色金属',
+ // 黑色系
+ '螺纹钢': '黑色系', '热卷': '黑色系', '铁矿石': '黑色系', '焦炭': '黑色系',
+ '焦煤': '黑色系', '锰硅': '黑色系', '硅铁': '黑色系',
+ // 能源化工
+ '原油': '能源化工', '燃料油': '能源化工', '沥青': '能源化工', '低硫燃料油': '能源化工',
+ 'PTA': '能源化工', 'PVC': '能源化工', '聚乙烯': '能源化工', '聚丙烯': '能源化工',
+ '苯乙烯': '能源化工', '乙二醇': '能源化工', '甲醇': '能源化工', '纯碱': '能源化工',
+ '玻璃': '能源化工', '橡胶': '能源化工', '20号胶': '能源化工', '丁二烯橡胶': '能源化工',
+ '尿素': '能源化工', '烧碱': '能源化工',
+ // 农产品
+ '豆粕': '农产品', '豆油': '农产品', '棕榈油': '农产品', '菜籽': '农产品',
+ '菜粕': '农产品', '菜油': '农产品', '玉米': '农产品', '玉米淀粉': '农产品',
+ '白糖': '农产品', '棉花': '农产品', '棉纱': '农产品', '苹果': '农产品',
+ '红枣': '农产品', '花生': '农产品', '粳米': '农产品',
+ // 金融期货
+ '中证1000': '金融期货', '中证500': '金融期货', '沪深300': '金融期货', '上证50': '金融期货',
+ '中证2000': '金融期货', '十年国债': '金融期货', '五年国债': '金融期货', '三十年国债': '金融期货',
+ // 其他
+ '集运指数': '其他', '碳酸锂': '其他', '工业硅': '其他', '多晶硅': '其他',
+ '欧线': '其他', '铝合金': '其他'
+ };
+
+ // 分类显示顺序
+ const CATEGORY_ORDER = ['贵金属', '有色金属', '黑色系', '能源化工', '农产品', '金融期货', '其他'];
let allTasks = [];
// Navigation
@@ -1506,17 +1547,46 @@
const regex = new RegExp(`(${currentSearchTerm})`, 'gi');
return text.replace(regex, '$1');
};
-
- const rows = Object.entries(filteredItems).map(([name, code]) =>
- `
- | ${highlightText(name)} |
- |
-
-
-
- |
-
`
- ).join('');
+
+ // 按分类分组
+ const grouped = {};
+ for (const [name, code] of Object.entries(filteredItems)) {
+ const category = SYMBOL_CATEGORIES[name] || '其他';
+ if (!grouped[category]) grouped[category] = [];
+ grouped[category].push({ name, code });
+ }
+
+ // 按分类顺序渲染
+ let tbodyHtml = '';
+ for (const category of CATEGORY_ORDER) {
+ if (!grouped[category] || grouped[category].length === 0) continue;
+ tbodyHtml += `| ${category} |
`;
+ for (const { name, code } of grouped[category]) {
+ tbodyHtml += `
+ | ${highlightText(name)} |
+ |
+
+
+
+ |
+
`;
+ }
+ }
+ // 处理未在映射表中的分类
+ for (const [category, symbols] of Object.entries(grouped)) {
+ if (CATEGORY_ORDER.includes(category)) continue;
+ tbodyHtml += `| ${category} |
`;
+ for (const { name, code } of symbols) {
+ tbodyHtml += `
+ | ${highlightText(name)} |
+ |
+
+
+
+ |
+
`;
+ }
+ }
return `
@@ -1526,7 +1596,7 @@
| 操作 |
- ${rows}
+ ${tbodyHtml}
`;
};
diff --git a/openspec/changes/symbol-config-category-group/.comet.yaml b/openspec/changes/symbol-config-category-group/.comet.yaml
new file mode 100644
index 0000000..b10dbbb
--- /dev/null
+++ b/openspec/changes/symbol-config-category-group/.comet.yaml
@@ -0,0 +1,8 @@
+name: symbol-config-category-group
+phase: build
+workflow: tweak
+created_at: "2026-07-07T23:15:00+08:00"
+updated_at: "2026-07-07T23:15:00+08:00"
+build_mode: direct
+verify_result: null
+archived: false
diff --git a/openspec/changes/symbol-config-category-group/design.md b/openspec/changes/symbol-config-category-group/design.md
new file mode 100644
index 0000000..95abe94
--- /dev/null
+++ b/openspec/changes/symbol-config-category-group/design.md
@@ -0,0 +1,31 @@
+# 设计文档
+
+## 实现方案
+
+### 1. 品种分类映射表
+在前端定义 `SYMBOL_CATEGORIES` 对象,将品种名称映射到类别:
+```javascript
+const SYMBOL_CATEGORIES = {
+ // 贵金属
+ '沪金': '贵金属', '沪银': '贵金属', '铂金': '贵金属', '钯金': '贵金属',
+ // 有色金属
+ '沪铜': '有色金属', '沪铝': '有色金属', ...
+ // 黑色系
+ '螺纹钢': '黑色系', '热卷': '黑色系', ...
+ // 能源化工
+ '原油': '能源化工', 'PTA': '能源化工', ...
+ // 农产品
+ '豆粕': '农产品', '豆油': '农产品', ...
+ // 金融期货
+ '中证1000': '金融期货', ...
+};
+```
+
+### 2. 分组渲染逻辑
+修改 `renderTable` 函数:
+1. 将品种按类别分组
+2. 未分类的品种归入"其他"组
+3. 按类别顺序渲染,每组显示标题行
+
+### 3. CSS 样式
+新增 `.symbol-category-header` 样式,用于分组标题行
diff --git a/openspec/changes/symbol-config-category-group/proposal.md b/openspec/changes/symbol-config-category-group/proposal.md
new file mode 100644
index 0000000..31006a7
--- /dev/null
+++ b/openspec/changes/symbol-config-category-group/proposal.md
@@ -0,0 +1,14 @@
+# 品种配置按类别分组显示
+
+## 动机
+当前品种配置列表按添加顺序显示,品种较多时不易查找。需要按品种类别(贵金属、有色金属、黑色系等)分组显示。
+
+## 目标
+1. 在前端定义品种分类映射表
+2. 列表按分类分组显示,每组有标题
+3. 保持现有功能(修改合约、删除)不变
+
+## 范围
+- 修改 `app/static/index.html` 中的 `renderTable` 函数
+- 新增品种分类映射表
+- 新增分组标题样式
diff --git a/openspec/changes/symbol-config-category-group/tasks.md b/openspec/changes/symbol-config-category-group/tasks.md
new file mode 100644
index 0000000..ea603ad
--- /dev/null
+++ b/openspec/changes/symbol-config-category-group/tasks.md
@@ -0,0 +1,5 @@
+# 任务列表
+
+- [x] 1. 新增品种分类映射表 `SYMBOL_CATEGORIES`
+- [x] 2. 修改 `renderTable` 函数,按分类分组渲染
+- [x] 3. 新增分组标题行 CSS 样式