feat: 复盘四周期手动上传,移除 AI 识别预填

固定 5m/15m/1h/4h 四槽截图上传与详情四宫格展示;自动 K 线默认关闭且与手动上传互斥。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-05 21:57:41 +08:00
parent eec57610dc
commit 88fe4bbe56
18 changed files with 644 additions and 621 deletions
+4
View File
@@ -89,6 +89,10 @@
const root = document.getElementById("embed-page-root") || document;
global.SymbolLivePrice.init(root);
}
if (global.JournalUploadSlots && typeof global.JournalUploadSlots.init === "function") {
const root = document.getElementById("embed-page-root") || document;
global.JournalUploadSlots.init(root);
}
}
function injectFragment(html) {
+105
View File
@@ -1659,3 +1659,108 @@ html[data-theme="light"] .symbol-live-price--ok {
border-color: #9ed4b8;
}
/* ── 复盘:四周期截图上传 / 详情四宫格 ── */
.journal-upload-slots {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
margin-top: 10px;
}
.journal-upload-slot {
display: flex;
flex-direction: column;
gap: 6px;
padding: 8px 10px;
border: 1px dashed rgba(130, 145, 190, 0.45);
border-radius: 8px;
background: rgba(12, 16, 32, 0.35);
font-size: 0.82rem;
}
.journal-upload-slot-label {
color: #9aa3c7;
font-weight: 600;
letter-spacing: 0.02em;
}
.journal-upload-slot-input {
font-size: 0.78rem;
max-width: 100%;
}
.journal-upload-slot-preview {
min-height: 72px;
border-radius: 6px;
background: rgba(0, 0, 0, 0.2);
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.journal-upload-slot-preview--filled {
min-height: 96px;
}
.journal-upload-slot-thumb {
width: 100%;
max-height: 140px;
object-fit: contain;
cursor: zoom-in;
border-radius: 4px;
}
.journal-upload-hint {
margin-top: 6px;
font-size: 0.72rem;
color: #8892b0;
}
.journal-detail-images {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
padding: 10px 14px 14px;
border-top: 1px solid rgba(130, 145, 190, 0.25);
}
.journal-detail-img-cell {
display: flex;
flex-direction: column;
gap: 4px;
min-width: 0;
}
.journal-detail-img-label {
font-size: 0.75rem;
color: #9aa3c7;
font-weight: 600;
}
.journal-detail-img-thumb {
width: 100%;
max-height: 220px;
object-fit: contain;
background: rgba(0, 0, 0, 0.25);
border-radius: 6px;
cursor: zoom-in;
}
html[data-theme="light"] .journal-upload-slot {
background: #f6f8fb;
border-color: #c5d0de;
}
html[data-theme="light"] .journal-upload-slot-preview {
background: #eef2f7;
}
html[data-theme="light"] .journal-detail-images {
border-top-color: #d0dae4;
}
html[data-theme="light"] .journal-detail-img-thumb {
background: #eef2f7;
}
+73 -10
View File
@@ -50,6 +50,76 @@
return lines.join("<br>");
}
function resolveJournalImages(o) {
if (Array.isArray(o.images) && o.images.length) return o.images;
if (o.image) return [{ tf: "", file: o.image }];
return [];
}
function setJournalDetailImages(o) {
const grid = document.getElementById("detailImages");
const legacyImg = document.getElementById("detailImage");
const images = resolveJournalImages(o || {});
if (grid) {
if (!images.length) {
grid.innerHTML = "";
grid.style.display = "none";
} else {
grid.innerHTML = images
.map(function (img) {
const tf = String(img.tf || "").trim();
const file = String(img.file || "").trim();
if (!file) return "";
const label = tf ? escapeHtml(tf) : "截图";
const src = "/static/images/" + encodeURIComponent(file).replace(/%2F/g, "/");
return (
'<div class="journal-detail-img-cell">' +
'<span class="journal-detail-img-label">' +
label +
"</span>" +
'<img class="journal-detail-img-thumb" src="' +
src +
'" alt="' +
label +
'" onclick="showImage(this.src)">' +
"</div>"
);
})
.join("");
grid.style.display = "grid";
}
if (legacyImg) {
legacyImg.src = "";
legacyImg.style.display = "none";
}
return;
}
if (legacyImg) {
if (images.length === 1) {
legacyImg.src = "/static/images/" + images[0].file;
legacyImg.style.display = "block";
} else {
legacyImg.src = "";
legacyImg.style.display = "none";
}
}
}
function clearJournalDetailImages() {
const grid = document.getElementById("detailImages");
if (grid) {
grid.innerHTML = "";
grid.style.display = "none";
}
const legacyImg = document.getElementById("detailImage");
if (legacyImg) {
legacyImg.src = "";
legacyImg.style.display = "none";
}
}
function setJournalDetailBody(o, formatExitLine) {
const body = document.getElementById("detailBody");
if (!body) return;
@@ -67,16 +137,7 @@
}
setJournalDetailBody(o, formatExitLine);
clearDetailActions();
const imgEl = document.getElementById("detailImage");
if (imgEl) {
if (o.image) {
imgEl.src = `/static/images/${o.image}`;
imgEl.style.display = "block";
} else {
imgEl.src = "";
imgEl.style.display = "none";
}
}
setJournalDetailImages(o);
if (typeof setDetailModalFullscreen === "function") {
setDetailModalFullscreen(false);
}
@@ -265,5 +326,7 @@
buildTradeRecordDetailHtml: buildTradeRecordDetailHtml,
openTradeRecordDetailModal: openTradeRecordDetailModal,
clearDetailActions: clearDetailActions,
clearJournalDetailImages: clearJournalDetailImages,
setJournalDetailImages: setJournalDetailImages,
};
})(typeof window !== "undefined" ? window : globalThis);
+69
View File
@@ -0,0 +1,69 @@
/**
* 复盘表单:四周期截图槽位本地预览。
*/
(function (global) {
"use strict";
const previewUrls = new WeakMap();
function clearPreview(cell) {
if (!cell) return;
const prev = previewUrls.get(cell);
if (prev) {
URL.revokeObjectURL(prev);
previewUrls.delete(cell);
}
cell.innerHTML = "";
cell.classList.remove("journal-upload-slot-preview--filled");
}
function renderPreview(cell, file, tf) {
clearPreview(cell);
if (!file || !cell) return;
const url = URL.createObjectURL(file);
previewUrls.set(cell, url);
const img = document.createElement("img");
img.src = url;
img.alt = tf + " 预览";
img.className = "journal-upload-slot-thumb";
img.addEventListener("click", function (e) {
e.preventDefault();
if (typeof global.showImage === "function") {
global.showImage(url);
}
});
cell.appendChild(img);
cell.classList.add("journal-upload-slot-preview--filled");
}
function bindInput(input) {
if (!input || input.dataset.journalSlotBound === "1") return;
input.dataset.journalSlotBound = "1";
const tf = input.getAttribute("data-tf") || "";
const cell = input.closest(".journal-upload-slot");
const preview = cell ? cell.querySelector(".journal-upload-slot-preview") : null;
input.addEventListener("change", function () {
const file = input.files && input.files[0];
if (!file) {
clearPreview(preview);
return;
}
renderPreview(preview, file, tf);
});
}
function init(root) {
const scope = root || document;
scope.querySelectorAll(".journal-upload-slot-input").forEach(bindInput);
}
global.JournalUploadSlots = { init: init };
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function () {
init(document);
});
} else {
init(document);
}
})(typeof window !== "undefined" ? window : globalThis);