diff --git a/frontend/m/css/features.css b/frontend/m/css/features.css index 455d1a2..bb169e8 100644 --- a/frontend/m/css/features.css +++ b/frontend/m/css/features.css @@ -2765,6 +2765,40 @@ .m-num-strong { font-weight: 600; } .m-cell-text--empty { color: var(--text-tertiary); } +/* 详情 Sheet 内跟踪备注行 */ +.m-remark-row { + display: flex; + align-items: center; + gap: 10px; + margin: 12px 0 0; + padding: 10px 12px; + background: var(--surface); + border-radius: 8px; +} +.m-remark-label { flex: 0 0 auto; font-size: 12px; color: var(--text-secondary); } +.m-remark-text { + flex: 1 1 auto; + min-width: 0; + font-size: 13.5px; + color: var(--text-primary); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.m-remark-edit { + flex: 0 0 auto; + appearance: none; + border: none; + background: transparent; + color: var(--action); + font-size: 13px; + font-weight: 600; + cursor: pointer; + padding: 4px 2px; + -webkit-tap-highlight-color: transparent; +} +.m-remark-edit:active { opacity: 0.7; } + /* 自选股:颜色圆点标记 */ .m-stock--watch { flex-direction: row; align-items: center; gap: 8px; } .m-stock-copy { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; min-width: 0; } diff --git a/frontend/m/js/pages.js b/frontend/m/js/pages.js index 251a665..6ca154f 100644 --- a/frontend/m/js/pages.js +++ b/frontend/m/js/pages.js @@ -3392,6 +3392,63 @@ }); } + function openRemarkEditSheet() { + const detail = state.detail; + if (!detail || !detail.code) return; + const item = detail.watchItem || {}; + const current = item.remark || ""; + openSheet( + '

编辑跟踪备注

' + + '
" + + '
' + + '" + + '
' + + "
", + { detail: false } + ); + const input = document.getElementById("m-remark-input"); + if (input) { + input.addEventListener("input", function () { + const counter = document.querySelector('[data-counter-for="m-remark-input"]'); + if (counter) counter.textContent = input.value.length + "/240"; + }); + } + } + + function saveRemark() { + const detail = state.detail; + if (!detail || !detail.code) return; + const item = detail.watchItem || {}; + const code = detail.code; + const remark = document.getElementById("m-remark-input").value.trim(); + const payload = { + code: code, + name: item.name || detail.name || code, + sector: item.sector || detail.sector || "其他", + color: item.color || "red", + remark: remark + }; + global.MobileAPI.request("/api/watchlist", "POST", payload).then(function () { + const refresh = state.review && state.review.watchlist + ? global.MobileAPI.request("/api/watchlist?trade_date=" + encodeURIComponent(todayString())).then(function (res) { + state.review.watchlist = res || state.review.watchlist; + renderReviewWatchlist(); + }) + : Promise.resolve(); + return refresh; + }).then(function () { + closeSheet(); + openDetailSheet(code); + showToast("备注已保存"); + }).catch(function (error) { + showToast(error && error.message ? error.message : "保存失败"); + }); + } + function showToast(message) { const root = document.getElementById("m-sheet-root"); if (!root) return; @@ -3427,6 +3484,7 @@ name: name === "--" ? "" : name, sector: industry === "其他" ? "" : industry, watchlist: Boolean(stock.watchlist), + watchItem: stock.watchlist || null, tab: "intraday", payload: payload, }; @@ -3440,6 +3498,15 @@ const intradayOk = meta.intraday_status === "available"; const chartHtml = intradayOk ? intradayChart(payload) : emptyChart(meta.intraday_notice || "分时数据暂不可用"); + const watchItem = stock.watchlist || null; + const remarkRow = watchItem + ? '
' + + '跟踪备注' + + '' + escapeHtml(watchItem.remark || "未填写") + "" + + '' + + "
" + : ""; + body.innerHTML = '
' + '
' + @@ -3454,6 +3521,7 @@ '' + escapeHtml(chartCaptionHtml("intraday")) + "" + "
" + '
' + chartHtml + "
" + + remarkRow + '
点按图面可读数值 · 数据来源:本地行情
'; } @@ -4207,7 +4275,7 @@ '

' + escapeHtml(item.title) + "

" + '
' + escapeHtml(displayCompactDate(item.available_date)) + (upcoming ? "(未到期)" : "") + "
" + (item.content ? '
' + escapeHtml(item.content) + "
" : "") + - (item.code ? '" : "") + + (item.code ? '" : "") + "
" + '
' + (canRead ? '' : "") + @@ -4258,7 +4326,8 @@ /* ----- 全屏表单页 ----- */ function openForm(kind, opts) { - state.review.form = { kind: kind, opts: opts || {}, action: "buy", emotion: "calm", stock: null }; + const t = (opts && opts.trade) || {}; + state.review.form = { kind: kind, opts: opts || {}, action: t.action || "buy", emotion: t.emotion || "calm", stock: null }; state.review.dirty = false; const title = kind === "trade" ? ((opts && opts.trade) ? "编辑交易" : "新增交易") : kind === "daily" ? "写复盘" : "新增笔记"; global.MobileRouter.updateHeader({ title: title, back: true, actions: "" }); @@ -4946,12 +5015,12 @@ if (reviewDeleteNote) { deleteNote(reviewDeleteNote.dataset.noteId); return; } const noteCard = event.target.closest("[data-note-id]"); if (noteCard) { openNoteDetail(noteCard.dataset.noteId); return; } - const alertRow = event.target.closest("[data-alert-id]"); - if (alertRow) { openAlertDetail(alertRow.dataset.alertId); return; } const alertRead = event.target.closest("[data-review-alert-read]"); if (alertRead) { markAlertRead(alertRead.dataset.alertId); return; } const alertDelete = event.target.closest("[data-review-alert-delete]"); if (alertDelete) { deleteAlert(alertDelete.dataset.alertId); return; } + const alertRow = event.target.closest(".m-alert-row[data-alert-id]"); + if (alertRow) { openAlertDetail(alertRow.dataset.alertId); return; } const alertFilter = event.target.closest("[data-review-alert-filter]"); if (alertFilter) { state.review.alertStatus = alertFilter.dataset.reviewAlertFilter === "unread" ? "unread" : "all"; @@ -4964,6 +5033,10 @@ if (alertSave) { submitAlertAdd(); return; } const alertStock = event.target.closest("[data-alert-stock]"); if (alertStock) { openDetailSheet(alertStock.dataset.code); return; } + const remarkEdit = event.target.closest("[data-remark-edit]"); + if (remarkEdit) { openRemarkEditSheet(); return; } + const remarkSave = event.target.closest("[data-remark-save]"); + if (remarkSave) { saveRemark(); return; } const row = event.target.closest("[data-code]"); if (row) {