Add industry filter to recommendations and fix verify button width.
Show category, turnover, and per-industry counts; clarify volume is in lots. Prevent trade-save button from stretching full column width. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+99
-6
@@ -33,8 +33,11 @@
|
||||
var recRowsRaw = [];
|
||||
var recSortKey = 'trend';
|
||||
var recSortDesc = true;
|
||||
var REC_SORT_CACHE = 'qihuo_rec_sort_v1';
|
||||
var REC_COLSPAN = 14;
|
||||
var recIndustryFilter = '';
|
||||
var REC_SORT_CACHE = 'qihuo_rec_sort_v2';
|
||||
var REC_INDUSTRY_CACHE = 'qihuo_rec_industry_v1';
|
||||
var REC_COLSPAN = 16;
|
||||
var productCategories = window.PRODUCT_CATEGORIES || [];
|
||||
var POS_CACHE_KEY = 'qihuo_trading_live_v3';
|
||||
|
||||
function runWhenReady(fn) {
|
||||
@@ -1107,6 +1110,10 @@
|
||||
if (p.key) recSortKey = p.key;
|
||||
if (typeof p.desc === 'boolean') recSortDesc = p.desc;
|
||||
} catch (e) { /* ignore */ }
|
||||
try {
|
||||
var ind = sessionStorage.getItem(REC_INDUSTRY_CACHE);
|
||||
if (ind != null) recIndustryFilter = ind;
|
||||
} catch (e2) { /* ignore */ }
|
||||
}
|
||||
|
||||
function saveRecSortPrefs() {
|
||||
@@ -1115,11 +1122,62 @@
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function saveRecIndustryPref() {
|
||||
try {
|
||||
sessionStorage.setItem(REC_INDUSTRY_CACHE, recIndustryFilter || '');
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function syncRecSortUi() {
|
||||
var sel = document.getElementById('rec-sort-key');
|
||||
var btn = document.getElementById('rec-sort-dir');
|
||||
var indSel = document.getElementById('rec-industry-filter');
|
||||
if (sel) sel.value = recSortKey;
|
||||
if (btn) btn.textContent = recSortDesc ? '↓' : '↑';
|
||||
if (indSel) indSel.value = recIndustryFilter || '';
|
||||
}
|
||||
|
||||
function filterRecommendRows(rows) {
|
||||
if (!recIndustryFilter) return (rows || []).slice();
|
||||
return (rows || []).filter(function (r) {
|
||||
return (r.category || '') === recIndustryFilter;
|
||||
});
|
||||
}
|
||||
|
||||
function countByCategory(rows) {
|
||||
var counts = {};
|
||||
(rows || []).forEach(function (r) {
|
||||
var cat = r.category || '其他';
|
||||
counts[cat] = (counts[cat] || 0) + 1;
|
||||
});
|
||||
return counts;
|
||||
}
|
||||
|
||||
function updateRecStats(allRows, visibleRows) {
|
||||
var el = document.getElementById('rec-stats');
|
||||
if (!el) return;
|
||||
var total = (allRows || []).length;
|
||||
var shown = (visibleRows || []).length;
|
||||
if (!total) {
|
||||
el.textContent = '';
|
||||
return;
|
||||
}
|
||||
var parts = [];
|
||||
if (recIndustryFilter) {
|
||||
parts.push('筛选 <strong>' + shown + '</strong> / 共 ' + total + ' 个品种');
|
||||
} else {
|
||||
parts.push('共 <strong>' + total + '</strong> 个品种');
|
||||
}
|
||||
var order = productCategories.length ? productCategories.slice() : [];
|
||||
var counts = countByCategory(recIndustryFilter ? visibleRows : allRows);
|
||||
Object.keys(counts).forEach(function (k) {
|
||||
if (order.indexOf(k) < 0) order.push(k);
|
||||
});
|
||||
var breakdown = order.filter(function (cat) { return counts[cat]; }).map(function (cat) {
|
||||
return cat + ' ' + counts[cat];
|
||||
});
|
||||
if (breakdown.length) parts.push(breakdown.join(' · '));
|
||||
el.innerHTML = parts.join(' · ');
|
||||
}
|
||||
|
||||
var TREND_SORT_RANK = { break_long: 0, break_short: 0, long: 1, short: 2, range: 3, '': 9 };
|
||||
@@ -1165,6 +1223,15 @@
|
||||
return String(Math.round(n));
|
||||
}
|
||||
|
||||
function fmtRecTurnover(v) {
|
||||
if (v === null || v === undefined) return '—';
|
||||
var n = Number(v);
|
||||
if (!isFinite(n)) return '—';
|
||||
if (n >= 1e8) return (n / 1e8).toFixed(2) + '亿';
|
||||
if (n >= 1e4) return (n / 1e4).toFixed(1) + '万';
|
||||
return String(Math.round(n));
|
||||
}
|
||||
|
||||
function changeCellHtml(r) {
|
||||
if (r.yesterday_change == null) return '—';
|
||||
var ch = Number(r.yesterday_change);
|
||||
@@ -1206,7 +1273,10 @@
|
||||
function renderRecommendRows(rows) {
|
||||
if (!recommendList) return;
|
||||
if (!rows.length) {
|
||||
recommendList.innerHTML = '<tr><td colspan="' + REC_COLSPAN + '" class="empty-hint">当前资金下暂无推荐品种(每日后台刷新)</td></tr>';
|
||||
var emptyMsg = recIndustryFilter
|
||||
? '当前行业下暂无推荐品种'
|
||||
: '当前资金下暂无推荐品种(每日后台刷新)';
|
||||
recommendList.innerHTML = '<tr><td colspan="' + REC_COLSPAN + '" class="empty-hint">' + emptyMsg + '</td></tr>';
|
||||
return;
|
||||
}
|
||||
recommendList.innerHTML = rows.map(function (r) {
|
||||
@@ -1217,6 +1287,7 @@
|
||||
'<tr class="' + rowCls + '">' +
|
||||
'<td><strong' + nameCls + '>' + (r.name || '') + '</strong> <span class="text-accent">' + (r.main_code || r.ths || '') + '</span></td>' +
|
||||
'<td>' + (r.exchange || '') + '</td>' +
|
||||
'<td>' + (r.category || '—') + '</td>' +
|
||||
'<td>' + trendBadgeHtml(r) + '</td>' +
|
||||
'<td>' + gapBadgeHtml(r) + '</td>' +
|
||||
'<td>' + (r.price != null ? r.price : '—') + '</td>' +
|
||||
@@ -1225,6 +1296,7 @@
|
||||
'<td>' + changeCellHtml(r) + '</td>' +
|
||||
'<td>' + (r.yesterday_amplitude_pct != null ? r.yesterday_amplitude_pct + '%' : '—') + '</td>' +
|
||||
'<td>' + fmtRecVolume(r.volume) + '</td>' +
|
||||
'<td>' + fmtRecTurnover(r.turnover) + '</td>' +
|
||||
'<td>' + (r.margin_one_lot != null ? r.margin_one_lot + (r.margin_source === 'ctp' ? ' <span class="text-muted">(柜台)</span>' : '') : '—') + '</td>' +
|
||||
'<td>' + (r.open_fee_one_lot != null ? r.open_fee_one_lot : '—') + '</td>' +
|
||||
'<td>' + (r.max_lots != null && r.max_lots > 0 ? r.max_lots : '—') + '</td>' +
|
||||
@@ -1234,6 +1306,13 @@
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function renderRecommendTable() {
|
||||
var filtered = filterRecommendRows(recRowsRaw);
|
||||
var sorted = sortRecommendRows(filtered);
|
||||
updateRecStats(recRowsRaw, sorted);
|
||||
renderRecommendRows(sorted);
|
||||
}
|
||||
|
||||
function renderRecommendations(data) {
|
||||
if (!recommendList || !data) return;
|
||||
updateRecommendMaxMaps(data);
|
||||
@@ -1247,9 +1326,10 @@
|
||||
recRowsRaw = rows.slice();
|
||||
if (!rows.length) {
|
||||
recommendList.innerHTML = '<tr><td colspan="' + REC_COLSPAN + '" class="empty-hint">当前资金下暂无推荐品种(每日后台刷新)</td></tr>';
|
||||
updateRecStats([], []);
|
||||
return;
|
||||
}
|
||||
renderRecommendRows(sortRecommendRows(recRowsRaw));
|
||||
renderRecommendTable();
|
||||
}
|
||||
|
||||
function initRecommendSortControls() {
|
||||
@@ -1257,11 +1337,19 @@
|
||||
syncRecSortUi();
|
||||
var sel = document.getElementById('rec-sort-key');
|
||||
var btn = document.getElementById('rec-sort-dir');
|
||||
var indSel = document.getElementById('rec-industry-filter');
|
||||
if (indSel) {
|
||||
indSel.addEventListener('change', function () {
|
||||
recIndustryFilter = indSel.value || '';
|
||||
saveRecIndustryPref();
|
||||
renderRecommendTable();
|
||||
});
|
||||
}
|
||||
if (sel) {
|
||||
sel.addEventListener('change', function () {
|
||||
recSortKey = sel.value || 'trend';
|
||||
saveRecSortPrefs();
|
||||
renderRecommendRows(sortRecommendRows(recRowsRaw));
|
||||
renderRecommendTable();
|
||||
});
|
||||
}
|
||||
if (btn) {
|
||||
@@ -1269,9 +1357,10 @@
|
||||
recSortDesc = !recSortDesc;
|
||||
saveRecSortPrefs();
|
||||
syncRecSortUi();
|
||||
renderRecommendRows(sortRecommendRows(recRowsRaw));
|
||||
renderRecommendTable();
|
||||
});
|
||||
}
|
||||
if (recRowsRaw.length) updateRecStats(recRowsRaw, filterRecommendRows(recRowsRaw));
|
||||
}
|
||||
|
||||
function connectRecommendStream() {
|
||||
@@ -1373,6 +1462,10 @@
|
||||
initCtpOnLoad();
|
||||
connectRecommendStream();
|
||||
initRecommendSortControls();
|
||||
if (window.__RECOMMEND_ROWS__ && window.__RECOMMEND_ROWS__.length) {
|
||||
recRowsRaw = window.__RECOMMEND_ROWS__.slice();
|
||||
renderRecommendTable();
|
||||
}
|
||||
fetch('/api/recommend/list')
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) { if (data.ok) renderRecommendations(data); })
|
||||
|
||||
Reference in New Issue
Block a user