等待后端更新接口
This commit is contained in:
+307
-59
@@ -65,6 +65,125 @@
|
||||
if (root.alert) root.alert(message);
|
||||
}
|
||||
|
||||
function getApiStateType(error) {
|
||||
return Number(error && (error.status || error.code)) === 403 ? 'forbidden' : 'error';
|
||||
}
|
||||
|
||||
function setFeedFormStatus(message, type) {
|
||||
var target = query('[data-feed-form-status]');
|
||||
|
||||
if (!target) return;
|
||||
if (!message) {
|
||||
target.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
if (root.ProfileUI && root.ProfileUI.setApiState) {
|
||||
root.ProfileUI.setApiState(target, type || 'error', message);
|
||||
return;
|
||||
}
|
||||
target.textContent = message;
|
||||
}
|
||||
|
||||
function setFeedContainerState(selector, type, message) {
|
||||
var target = query(selector);
|
||||
|
||||
if (!target) return;
|
||||
if (root.ProfileUI && root.ProfileUI.setApiState) {
|
||||
root.ProfileUI.setApiState(target, type, message);
|
||||
return;
|
||||
}
|
||||
target.innerHTML = '<div class="api-state api-state--' + type + '" data-api-state="' + type + '">' +
|
||||
escapeHtml(message) + '</div>';
|
||||
}
|
||||
|
||||
function setFeedFormEnabled(enabled) {
|
||||
var form = query('[data-feed-form]');
|
||||
|
||||
if (form) {
|
||||
queryAll('input, textarea, select, button', form).forEach(function (field) {
|
||||
field.disabled = !enabled;
|
||||
});
|
||||
}
|
||||
queryAll('[data-feed-editor-action]').forEach(function (action) {
|
||||
action.hidden = !enabled;
|
||||
action.disabled = !enabled;
|
||||
});
|
||||
}
|
||||
|
||||
function setFeedSubmitPending(pending) {
|
||||
var selectors = '[data-feed-form] [type="submit"], [type="submit"][form="feed-edit-form"]';
|
||||
|
||||
queryAll(selectors).forEach(function (button) {
|
||||
if (!button.dataset.defaultLabel) button.dataset.defaultLabel = button.textContent;
|
||||
button.disabled = Boolean(pending);
|
||||
button.textContent = pending ? '正在保存…' : button.dataset.defaultLabel;
|
||||
button.setAttribute('aria-busy', pending ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function setFeedCommentFormStatus(message, type) {
|
||||
var target = query('[data-feed-comment-form-status]');
|
||||
|
||||
if (!target) return;
|
||||
if (!message) {
|
||||
target.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
if (root.ProfileUI && root.ProfileUI.setApiState) {
|
||||
root.ProfileUI.setApiState(target, type || 'error', message);
|
||||
return;
|
||||
}
|
||||
target.textContent = message;
|
||||
}
|
||||
|
||||
function setFeedCommentFormEnabled(enabled) {
|
||||
var form = query('[data-feed-comment-form]');
|
||||
|
||||
if (!form) return;
|
||||
queryAll('input, textarea, button', form).forEach(function (field) {
|
||||
field.disabled = !enabled;
|
||||
});
|
||||
}
|
||||
|
||||
function setFeedCommentSubmitPending(pending) {
|
||||
queryAll('[data-feed-comment-form] [type="submit"]').forEach(function (button) {
|
||||
if (!button.dataset.defaultLabel) button.dataset.defaultLabel = button.textContent;
|
||||
button.textContent = pending ? '正在发布…' : button.dataset.defaultLabel;
|
||||
button.setAttribute('aria-busy', pending ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function setFeedCommentTarget(parentCommentId) {
|
||||
var form = query('[data-feed-comment-form]');
|
||||
var target = query('[data-feed-comment-form-target]');
|
||||
var parent = parentCommentId ? toId(parentCommentId) : '';
|
||||
|
||||
if (!form) return;
|
||||
if (query('[name="parentCommentId"]', form)) query('[name="parentCommentId"]', form).value = parent;
|
||||
if (target) target.textContent = parent ? '正在回复这条评论' : '发表公开评论';
|
||||
}
|
||||
|
||||
function openFeedCommentForm(feedId, parentCommentId) {
|
||||
var genealogyId = getCurrentGenealogyId();
|
||||
var form;
|
||||
var submitButton;
|
||||
|
||||
if (!feedId || !genealogyId) return;
|
||||
if (!query('[data-feed-detail-page]')) {
|
||||
if (root.location) root.location.href = buildFeedUrl('detail', genealogyId, feedId);
|
||||
return;
|
||||
}
|
||||
if (getCurrentFeedId() !== toId(feedId)) return;
|
||||
form = query('[data-feed-comment-form]');
|
||||
submitButton = form && query('[type="submit"]', form);
|
||||
if (!form || !submitButton || submitButton.disabled) return;
|
||||
setFeedCommentTarget(parentCommentId);
|
||||
setFeedCommentFormStatus('');
|
||||
if (query('[name="commentContent"]', form) && query('[name="commentContent"]', form).focus) {
|
||||
query('[name="commentContent"]', form).focus();
|
||||
}
|
||||
}
|
||||
|
||||
function getQueryParam(search, name) {
|
||||
var params = new URLSearchParams(String(search || '').replace(/^\?/, ''));
|
||||
|
||||
@@ -280,6 +399,39 @@
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function renderFeedState(type, message) {
|
||||
if (root.ProfileUI && root.ProfileUI.renderApiState) {
|
||||
return root.ProfileUI.renderApiState(type, message);
|
||||
}
|
||||
return '<div class="api-state api-state--' + escapeHtml(type) + '" data-api-state="' +
|
||||
escapeHtml(type) + '">' + escapeHtml(message) + '</div>';
|
||||
}
|
||||
|
||||
function replaceInlineCommentList(feedId, content) {
|
||||
var row = query('[data-feed-id="' + feedId + '"]');
|
||||
var previous = row && row.nextElementSibling;
|
||||
|
||||
if (!row) return;
|
||||
if (previous && previous.getAttribute('data-feed-comment-list') === feedId) previous.remove();
|
||||
row.insertAdjacentHTML('afterend', '<div data-feed-comment-list="' + escapeHtml(feedId) + '">' + content + '</div>');
|
||||
}
|
||||
|
||||
function replaceReplyList(parentCommentId, content) {
|
||||
var row = query('[data-feed-comment-node="' + parentCommentId + '"]');
|
||||
var previous = row && row.nextElementSibling;
|
||||
|
||||
if (!row) return;
|
||||
if (previous && previous.getAttribute('data-feed-reply-list') === parentCommentId) previous.remove();
|
||||
row.insertAdjacentHTML('afterend', content);
|
||||
}
|
||||
|
||||
function setReplyState(parentCommentId, type, message) {
|
||||
replaceReplyList(
|
||||
parentCommentId,
|
||||
'<div data-feed-reply-list="' + escapeHtml(parentCommentId) + '">' + renderFeedState(type, message) + '</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function getListUrl(genealogyId, feedId) {
|
||||
return buildFeedUrl(feedId ? 'edit' : 'list', genealogyId, feedId);
|
||||
}
|
||||
@@ -323,11 +475,11 @@
|
||||
|
||||
if (!container) return;
|
||||
if (invalidCount) {
|
||||
container.innerHTML = '<div class="api-empty">动态响应缺少 feedId 或 feedContent,请联系后端补充 DTO。</div>';
|
||||
setFeedContainerState('[data-feed-list]', 'error', '动态响应缺少 feedId 或 feedContent,请联系后端补充 DTO。');
|
||||
return;
|
||||
}
|
||||
if (!feeds.length) {
|
||||
container.innerHTML = '<div class="api-empty">暂无家族动态</div>';
|
||||
setFeedContainerState('[data-feed-list]', 'empty', '暂无家族动态');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,21 +545,19 @@
|
||||
var row = query('[data-feed-id="' + feedId + '"]');
|
||||
var result = normalizeComments(data);
|
||||
var list = result.comments;
|
||||
var previous = row && row.nextElementSibling;
|
||||
var content;
|
||||
|
||||
if (!row && !detailContainer) return;
|
||||
if (previous && previous.getAttribute('data-feed-comment-list') === feedId) previous.remove();
|
||||
if (result.invalidCount) {
|
||||
content = '<div class="api-empty">评论响应缺少 commentId 或 commentContent,请联系后端补充 DTO。</div>';
|
||||
if (detailContainer) detailContainer.innerHTML = content;
|
||||
else row.insertAdjacentHTML('afterend', '<div data-feed-comment-list="' + escapeHtml(feedId) + '">' + content + '</div>');
|
||||
content = renderFeedState('error', '评论响应缺少 commentId 或 commentContent,请联系后端补充 DTO。');
|
||||
if (detailContainer) setFeedContainerState('[data-feed-detail-comments]', 'error', '评论响应缺少 commentId 或 commentContent,请联系后端补充 DTO。');
|
||||
else replaceInlineCommentList(feedId, content);
|
||||
return;
|
||||
}
|
||||
if (!list.length) {
|
||||
content = '<div class="api-empty">暂无评论</div>';
|
||||
if (detailContainer) detailContainer.innerHTML = content;
|
||||
else row.insertAdjacentHTML('afterend', '<div data-feed-comment-list="' + escapeHtml(feedId) + '">' + content + '</div>');
|
||||
content = renderFeedState('empty', '暂无评论');
|
||||
if (detailContainer) setFeedContainerState('[data-feed-detail-comments]', 'empty', '暂无评论');
|
||||
else replaceInlineCommentList(feedId, content);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -415,26 +565,24 @@
|
||||
return renderCommentRow(feedId, comment);
|
||||
}).join('') + '</div>' + renderPageControls('comments', feedId, '', currentCommentPages[feedId] || 1, getPageTotal(data));
|
||||
if (detailContainer) detailContainer.innerHTML = content;
|
||||
else row.insertAdjacentHTML('afterend', '<div data-feed-comment-list="' + escapeHtml(feedId) + '">' + content + '</div>');
|
||||
else replaceInlineCommentList(feedId, content);
|
||||
}
|
||||
|
||||
function renderCommentReplies(feedId, parentCommentId, data) {
|
||||
var row = query('[data-feed-comment-node="' + parentCommentId + '"]');
|
||||
var result = normalizeComments(data);
|
||||
var previous = row && row.nextElementSibling;
|
||||
|
||||
if (!row) return;
|
||||
if (previous && previous.getAttribute('data-feed-reply-list') === parentCommentId) previous.remove();
|
||||
if (result.invalidCount) {
|
||||
row.insertAdjacentHTML('afterend', '<div class="api-empty" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">回复响应缺少 commentId 或 commentContent,请联系后端补充 DTO。</div>');
|
||||
setReplyState(parentCommentId, 'error', '回复响应缺少 commentId 或 commentContent,请联系后端补充 DTO。');
|
||||
return;
|
||||
}
|
||||
if (!result.comments.length) {
|
||||
row.insertAdjacentHTML('afterend', '<div class="api-empty" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">暂无直接回复</div>');
|
||||
setReplyState(parentCommentId, 'empty', '暂无直接回复');
|
||||
return;
|
||||
}
|
||||
|
||||
row.insertAdjacentHTML('afterend', '<div class="module-list" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">' + result.comments.map(function (comment) {
|
||||
replaceReplyList(parentCommentId, '<div class="module-list" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">' + result.comments.map(function (comment) {
|
||||
return renderCommentRow(feedId, comment);
|
||||
}).join('') + renderPageControls('replies', feedId, parentCommentId, currentReplyPages[parentCommentId] || 1, getPageTotal(data)) + '</div>');
|
||||
}
|
||||
@@ -471,11 +619,21 @@
|
||||
});
|
||||
}
|
||||
|
||||
function canEditFeeds(genealogy) {
|
||||
return Boolean(genealogy && (genealogy.canEditContent === true || genealogy.canManage === true));
|
||||
}
|
||||
|
||||
function setFeedContentEditingEnabled(enabled) {
|
||||
queryAll('[data-feed-create-link]').forEach(function (link) {
|
||||
link.hidden = !enabled;
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeViewerContext(genealogy, profile) {
|
||||
return {
|
||||
userId: toId(profile && profile.userId),
|
||||
canEditContent: genealogy && genealogy.canEditContent === true,
|
||||
canManage: genealogy && genealogy.canManage === true
|
||||
canEditContent: canEditFeeds(genealogy),
|
||||
canManage: Boolean(genealogy && genealogy.canManage === true)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -494,6 +652,7 @@
|
||||
profile = null;
|
||||
}
|
||||
viewerContext = normalizeViewerContext(genealogy, profile);
|
||||
setFeedContentEditingEnabled(viewerContext.canEditContent);
|
||||
return viewerContext;
|
||||
}
|
||||
|
||||
@@ -544,7 +703,11 @@
|
||||
|
||||
if (!genealogyId) {
|
||||
container = query('[data-feed-list]');
|
||||
if (container) container.innerHTML = '<div class="api-empty">请从具体家谱进入家族圈动态</div>';
|
||||
if (container) setFeedContainerState('[data-feed-list]', 'forbidden', '请从具体家谱进入家族圈动态。');
|
||||
setFeedFormEnabled(false);
|
||||
setFeedFormStatus('请从具体家谱进入动态发布。', 'forbidden');
|
||||
setFeedCommentFormEnabled(false);
|
||||
setFeedCommentFormStatus('请从具体家谱进入动态详情后发表评论。', 'forbidden');
|
||||
showMessage('请从具体家谱进入家族圈动态');
|
||||
}
|
||||
return genealogyId;
|
||||
@@ -560,6 +723,7 @@
|
||||
if (!genealogyId) return;
|
||||
syncGenealogyLinks(genealogyId);
|
||||
currentFeedPage = buildPageQuery(pageNum || getQueryParam(root.location && root.location.search, 'pageNum')).pageNum;
|
||||
setFeedContainerState('[data-feed-list]', 'loading', '正在加载家族动态…');
|
||||
try {
|
||||
await loadViewerContext(api, genealogyId);
|
||||
data = await api.feedsPage(genealogyId, buildPageQuery(currentFeedPage));
|
||||
@@ -567,7 +731,11 @@
|
||||
updateListPager(data);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
if (query('[data-feed-list]')) query('[data-feed-list]').innerHTML = '<div class="api-empty">家族动态加载失败,请稍后重试。</div>';
|
||||
setFeedContainerState(
|
||||
'[data-feed-list]',
|
||||
getApiStateType(error),
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权查看该家谱的动态。' : '家族动态加载失败,请稍后重试。'
|
||||
);
|
||||
showMessage(error.message || '家族动态加载失败');
|
||||
}
|
||||
}
|
||||
@@ -581,19 +749,33 @@
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId) return;
|
||||
syncGenealogyLinks(genealogyId);
|
||||
setFeedFormEnabled(false);
|
||||
setFeedFormStatus('正在读取家谱权限…', 'loading');
|
||||
try {
|
||||
await loadViewerContext(api, genealogyId);
|
||||
if (!viewerContext.canEditContent) {
|
||||
setFeedFormStatus('当前账号无权发布或编辑该家谱的动态。', 'forbidden');
|
||||
return;
|
||||
}
|
||||
setFeedFormEnabled(true);
|
||||
if (query('[data-feed-advanced]')) {
|
||||
query('[data-feed-advanced]').hidden = !viewerContext.canManage;
|
||||
queryAll('[name]', query('[data-feed-advanced]')).forEach(function (field) {
|
||||
field.disabled = !viewerContext.canManage;
|
||||
});
|
||||
}
|
||||
if (!feedId) return;
|
||||
if (!feedId) {
|
||||
setFeedFormStatus('');
|
||||
return;
|
||||
}
|
||||
fillFeedForm(await api.feedDetail(genealogyId, feedId));
|
||||
setFeedFormStatus('');
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '动态详情加载失败');
|
||||
setFeedFormStatus(
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权维护该家谱的动态。' : (error.message || '动态详情加载失败'),
|
||||
getApiStateType(error)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,21 +786,35 @@
|
||||
var feed;
|
||||
|
||||
if (redirectUnauthorized(api)) return;
|
||||
setFeedCommentFormEnabled(false);
|
||||
setFeedCommentFormStatus('正在读取动态评论权限…', 'loading');
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) {
|
||||
if (query('[data-feed-detail]')) query('[data-feed-detail]').innerHTML = '<div class="api-empty">动态链接缺少有效编号</div>';
|
||||
setFeedContainerState('[data-feed-detail]', 'error', '动态链接缺少有效编号。');
|
||||
setFeedCommentFormStatus('动态链接缺少有效编号。', 'error');
|
||||
return;
|
||||
}
|
||||
syncGenealogyLinks(genealogyId);
|
||||
setFeedContainerState('[data-feed-detail]', 'loading', '正在加载动态详情…');
|
||||
try {
|
||||
await loadViewerContext(api, genealogyId);
|
||||
feed = normalizeFeed(await api.feedDetail(genealogyId, feedId));
|
||||
if (!feed) throw new Error('动态响应缺少 feedId 或 feedContent,请联系后端补充 DTO。');
|
||||
renderFeedDetail(feed, genealogyId);
|
||||
setFeedCommentFormEnabled(true);
|
||||
setFeedCommentFormStatus('');
|
||||
await showComments(feedId, currentCommentPages[feedId] || 1);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
if (query('[data-feed-detail]')) query('[data-feed-detail]').innerHTML = '<div class="api-empty">动态详情加载失败,请返回列表重试。</div>';
|
||||
setFeedContainerState(
|
||||
'[data-feed-detail]',
|
||||
getApiStateType(error),
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权查看该动态。' : '动态详情加载失败,请返回列表重试。'
|
||||
);
|
||||
setFeedCommentFormStatus(
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权评论该动态。' : '动态详情加载失败,暂不能发表评论。',
|
||||
getApiStateType(error)
|
||||
);
|
||||
showMessage(error.message || '动态详情加载失败');
|
||||
}
|
||||
}
|
||||
@@ -632,24 +828,28 @@
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId) return;
|
||||
if (!viewerContext.canEditContent) {
|
||||
setFeedFormStatus('当前账号无权发布或编辑该家谱的动态。', 'forbidden');
|
||||
return;
|
||||
}
|
||||
// 富文本编辑器在提交前同步回 textarea,保证发送的是用户当前输入。
|
||||
if (root.AppRichEditor && root.AppRichEditor.syncAll) root.AppRichEditor.syncAll();
|
||||
try {
|
||||
body = buildFeedBody(getFormValues(form));
|
||||
} catch (error) {
|
||||
showMessage(error.message || '动态表单校验失败');
|
||||
setFeedFormStatus(error.message || '动态表单校验失败', 'error');
|
||||
return;
|
||||
}
|
||||
if (!body.feedContent) {
|
||||
showMessage('请填写动态内容');
|
||||
setFeedFormStatus('请填写动态内容', 'error');
|
||||
return;
|
||||
}
|
||||
return withActionLock('save:' + (feedId || 'new'), async function () {
|
||||
var saved;
|
||||
var savedFeedId;
|
||||
var buttons = queryAll('[type="submit"]', form);
|
||||
|
||||
buttons.forEach(function (button) { button.disabled = true; });
|
||||
setFeedSubmitPending(true);
|
||||
setFeedFormStatus('正在保存动态…', 'loading');
|
||||
try {
|
||||
if (feedId) {
|
||||
saved = await api.updateFeed(genealogyId, feedId, body);
|
||||
@@ -665,9 +865,12 @@
|
||||
root.location.href = buildPostSaveUrl(genealogyId, savedFeedId, body.status);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '动态保存失败');
|
||||
setFeedFormStatus(
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权保存该家谱的动态。' : (error.message || '动态保存失败'),
|
||||
getApiStateType(error)
|
||||
);
|
||||
} finally {
|
||||
buttons.forEach(function (button) { button.disabled = false; });
|
||||
setFeedSubmitPending(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -723,6 +926,11 @@
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
currentCommentPages[feedId] = buildPageQuery(pageNum).pageNum;
|
||||
if (query('[data-feed-detail-comments]')) {
|
||||
setFeedContainerState('[data-feed-detail-comments]', 'loading', '正在加载评论…');
|
||||
} else {
|
||||
replaceInlineCommentList(feedId, renderFeedState('loading', '正在加载评论…'));
|
||||
}
|
||||
try {
|
||||
renderComments(
|
||||
feedId,
|
||||
@@ -731,7 +939,19 @@
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
if (query('[data-feed-detail-comments]')) {
|
||||
query('[data-feed-detail-comments]').innerHTML = '<div class="api-empty">评论加载失败,请稍后重试。</div>';
|
||||
setFeedContainerState(
|
||||
'[data-feed-detail-comments]',
|
||||
getApiStateType(error),
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权查看评论。' : '评论加载失败,请稍后重试。'
|
||||
);
|
||||
} else {
|
||||
replaceInlineCommentList(
|
||||
feedId,
|
||||
renderFeedState(
|
||||
getApiStateType(error),
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权查看评论。' : '评论加载失败,请稍后重试。'
|
||||
)
|
||||
);
|
||||
}
|
||||
showMessage(error.message || '评论加载失败');
|
||||
}
|
||||
@@ -745,6 +965,7 @@
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId || !commentId) return;
|
||||
currentReplyPages[commentId] = buildPageQuery(pageNum).pageNum;
|
||||
setReplyState(commentId, 'loading', '正在加载回复…');
|
||||
try {
|
||||
renderCommentReplies(
|
||||
feedId,
|
||||
@@ -758,46 +979,60 @@
|
||||
);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
if (query('[data-feed-comment-node="' + commentId + '"]')) {
|
||||
query('[data-feed-comment-node="' + commentId + '"]').insertAdjacentHTML(
|
||||
'afterend',
|
||||
'<div class="api-empty">回复加载失败,请稍后重试。</div>'
|
||||
);
|
||||
}
|
||||
setReplyState(
|
||||
commentId,
|
||||
getApiStateType(error),
|
||||
getApiStateType(error) === 'forbidden' ? '当前账号无权查看回复。' : '回复加载失败,请稍后重试。'
|
||||
);
|
||||
showMessage(error.message || '回复加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function createComment(feedId, parentCommentId) {
|
||||
async function submitComment(form) {
|
||||
var api = getApi();
|
||||
var genealogyId;
|
||||
var content;
|
||||
var feedId = getCurrentFeedId();
|
||||
var body;
|
||||
var values;
|
||||
var forbidden = false;
|
||||
|
||||
if (redirectUnauthorized(api)) return;
|
||||
if (redirectUnauthorized(api) || !form) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
content = root.prompt ? root.prompt(parentCommentId ? '请输入回复内容' : '请输入评论内容', '') : '';
|
||||
body = buildCommentBody({ commentContent: content, parentCommentId: parentCommentId });
|
||||
if (!body.commentContent) return;
|
||||
if (body.commentContent.length > 1000) {
|
||||
showMessage('评论不能超过 1000 字');
|
||||
values = getFormValues(form);
|
||||
body = buildCommentBody(values);
|
||||
if (!body.commentContent) {
|
||||
setFeedCommentFormStatus('请填写评论内容。', 'error');
|
||||
return;
|
||||
}
|
||||
return withActionLock('comment:' + feedId + ':' + (parentCommentId || 'root'), async function () {
|
||||
if (body.commentContent.length > 1000) {
|
||||
setFeedCommentFormStatus('评论不能超过 1000 字。', 'error');
|
||||
return;
|
||||
}
|
||||
return withActionLock('comment:' + feedId + ':' + (body.parentCommentId || 'root'), async function () {
|
||||
setFeedCommentFormEnabled(false);
|
||||
setFeedCommentSubmitPending(true);
|
||||
setFeedCommentFormStatus('正在发布评论…', 'loading');
|
||||
try {
|
||||
await api.createFeedComment(genealogyId, feedId, body);
|
||||
await showComments(feedId, currentCommentPages[feedId] || 1);
|
||||
if (parentCommentId) await showCommentReplies(feedId, parentCommentId, currentReplyPages[parentCommentId] || 1);
|
||||
if (query('[data-feed-detail-page]')) {
|
||||
var feed = normalizeFeed(await api.feedDetail(genealogyId, feedId));
|
||||
if (feed) renderFeedDetail(feed, genealogyId);
|
||||
} else {
|
||||
await loadFeeds(currentFeedPage);
|
||||
}
|
||||
if (body.parentCommentId) await showCommentReplies(feedId, body.parentCommentId, currentReplyPages[body.parentCommentId] || 1);
|
||||
form.reset();
|
||||
setFeedCommentTarget('');
|
||||
setFeedCommentFormStatus('');
|
||||
var feed = normalizeFeed(await api.feedDetail(genealogyId, feedId));
|
||||
if (feed) renderFeedDetail(feed, genealogyId);
|
||||
showMessage('评论已发布');
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '评论发布失败');
|
||||
forbidden = getApiStateType(error) === 'forbidden';
|
||||
setFeedCommentFormStatus(
|
||||
forbidden ? '当前账号无权评论该动态。' : (error.message || '评论发布失败,请稍后重试。'),
|
||||
getApiStateType(error)
|
||||
);
|
||||
} finally {
|
||||
setFeedCommentSubmitPending(false);
|
||||
if (!forbidden) setFeedCommentFormEnabled(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -832,9 +1067,16 @@
|
||||
documentRef.addEventListener('submit', function (event) {
|
||||
var form = event.target.closest('[data-feed-form]');
|
||||
|
||||
if (!form) return;
|
||||
event.preventDefault();
|
||||
submitFeed(form);
|
||||
if (form) {
|
||||
event.preventDefault();
|
||||
submitFeed(form);
|
||||
return;
|
||||
}
|
||||
form = event.target.closest('[data-feed-comment-form]');
|
||||
if (form) {
|
||||
event.preventDefault();
|
||||
submitComment(form);
|
||||
}
|
||||
});
|
||||
documentRef.addEventListener('click', function (event) {
|
||||
var target = event.target;
|
||||
@@ -858,13 +1100,18 @@
|
||||
if (target.closest('[data-feed-comment]')) {
|
||||
event.preventDefault();
|
||||
feedId = target.closest('[data-feed-comment]').getAttribute('data-feed-comment');
|
||||
createComment(feedId);
|
||||
openFeedCommentForm(feedId);
|
||||
}
|
||||
if (target.closest('[data-feed-comment-reply]')) {
|
||||
event.preventDefault();
|
||||
commentId = target.closest('[data-feed-comment-reply]').getAttribute('data-feed-comment-reply');
|
||||
feedId = target.closest('[data-feed-comment-reply]').getAttribute('data-feed-id');
|
||||
createComment(feedId, commentId);
|
||||
openFeedCommentForm(feedId, commentId);
|
||||
}
|
||||
if (target.closest('[data-feed-comment-cancel]')) {
|
||||
event.preventDefault();
|
||||
setFeedCommentTarget('');
|
||||
setFeedCommentFormStatus('');
|
||||
}
|
||||
if (target.closest('[data-feed-comment-replies]')) {
|
||||
event.preventDefault();
|
||||
@@ -937,6 +1184,7 @@
|
||||
withActionLock: withActionLock,
|
||||
normalizeFeed: normalizeFeed,
|
||||
normalizeComment: normalizeComment,
|
||||
canEditFeeds: canEditFeeds,
|
||||
normalizeViewerContext: normalizeViewerContext,
|
||||
normalizeComments: normalizeComments,
|
||||
normalizeList: normalizeList,
|
||||
|
||||
Reference in New Issue
Block a user