fix(HEL-105): P3b总工返工四条整改——提醒详情已读/删除与关联股票失效、编辑交易动作情绪被重置、自选股跟踪备注编辑
- 提醒详情:委派先匹配 data-review-alert-read/delete,列表行收窄为 .m-alert-row[data-alert-id] - 提醒详情关联股票:按钮补 data-alert-stock 属性,接通 openDetailSheet - 编辑交易:openForm 从 opts.trade 带入 action/emotion,不再强制 buy/calm - 自选股:双图详情补「跟踪备注」展示+编辑抽屉(≤240),保存走 /api/watchlist upsert 并刷新列表 Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -3392,6 +3392,63 @@
|
||||
});
|
||||
}
|
||||
|
||||
function openRemarkEditSheet() {
|
||||
const detail = state.detail;
|
||||
if (!detail || !detail.code) return;
|
||||
const item = detail.watchItem || {};
|
||||
const current = item.remark || "";
|
||||
openSheet(
|
||||
'<div class="m-sheet-head"><h2>编辑跟踪备注</h2>' +
|
||||
'<button class="m-sheet-close" type="button" data-sheet-close aria-label="关闭">' + icon("close", 20) + "</button></div>" +
|
||||
'<div class="m-sheet-body">' +
|
||||
'<label class="m-form-field"><span>跟踪备注</span>' +
|
||||
'<div class="m-field-textarea">' +
|
||||
'<textarea id="m-remark-input" maxlength="240" rows="4" data-maxlength="240">' + escapeHtml(current) + "</textarea>" +
|
||||
'<span class="m-field-counter" data-counter-for="m-remark-input">' + String(current).length + "/240</span>" +
|
||||
"</div></label>" +
|
||||
'<div class="m-confirm-actions"><button class="m-btn-primary" type="button" data-remark-save>保存</button></div>' +
|
||||
"</div>",
|
||||
{ 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
|
||||
? '<div class="m-remark-row">' +
|
||||
'<span class="m-remark-label">跟踪备注</span>' +
|
||||
'<span class="m-remark-text">' + escapeHtml(watchItem.remark || "未填写") + "</span>" +
|
||||
'<button class="m-remark-edit" type="button" data-remark-edit>编辑</button>' +
|
||||
"</div>"
|
||||
: "";
|
||||
|
||||
body.innerHTML =
|
||||
'<div class="m-detail-top">' +
|
||||
'<div class="m-detail-quote">' +
|
||||
@@ -3454,6 +3521,7 @@
|
||||
'<span class="m-detail-chart-caption" id="m-detail-caption">' + escapeHtml(chartCaptionHtml("intraday")) + "</span>" +
|
||||
"</div>" +
|
||||
'<div class="m-detail-chart" id="m-detail-chart">' + chartHtml + "</div>" +
|
||||
remarkRow +
|
||||
'<div class="m-detail-note">点按图面可读数值 · 数据来源:本地行情</div>';
|
||||
}
|
||||
|
||||
@@ -4207,7 +4275,7 @@
|
||||
'<h3 class="m-alert-detail-title">' + escapeHtml(item.title) + "</h3>" +
|
||||
'<div class="m-alert-detail-meta">' + escapeHtml(displayCompactDate(item.available_date)) + (upcoming ? "(未到期)" : "") + "</div>" +
|
||||
(item.content ? '<div class="m-detail-text">' + escapeHtml(item.content) + "</div>" : "") +
|
||||
(item.code ? '<button class="m-alert-stock" type="button" data-code="' + escapeHtml(item.code) + '">' + escapeHtml(item.code) + "</button>" : "") +
|
||||
(item.code ? '<button class="m-alert-stock" type="button" data-alert-stock data-code="' + escapeHtml(item.code) + '">' + escapeHtml(item.code) + "</button>" : "") +
|
||||
"</div>" +
|
||||
'<div class="m-confirm-actions">' +
|
||||
(canRead ? '<button class="m-btn-primary" type="button" data-review-alert-read data-alert-id="' + escapeHtml(String(item.id)) + '">标为已读</button>' : "") +
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user