完成10%
This commit is contained in:
+160
-36
@@ -20,6 +20,24 @@
|
||||
return root.GenealogyApi && root.GenealogyApi.defaultClient;
|
||||
}
|
||||
|
||||
function shouldRedirectToLogin(api, error) {
|
||||
var status = error && (error.status || error.code);
|
||||
|
||||
return !api || !api.getToken || !api.getToken() || Number(status) === 401;
|
||||
}
|
||||
|
||||
function redirectUnauthorized(api, error) {
|
||||
if (!shouldRedirectToLogin(api, error)) return false;
|
||||
if (api && api.clearToken) api.clearToken();
|
||||
if (!root.location) return true;
|
||||
if (typeof root.location.replace === 'function') {
|
||||
root.location.replace('login.html');
|
||||
return true;
|
||||
}
|
||||
root.location.href = 'login.html';
|
||||
return true;
|
||||
}
|
||||
|
||||
function query(selector, rootNode) {
|
||||
return documentRef ? (rootNode || documentRef).querySelector(selector) : null;
|
||||
}
|
||||
@@ -62,7 +80,7 @@
|
||||
return text || undefined;
|
||||
}
|
||||
|
||||
function toNumberOrUndefined(value) {
|
||||
function toIntegerOrUndefined(value) {
|
||||
var text = trimOrUndefined(value);
|
||||
var number;
|
||||
|
||||
@@ -80,23 +98,21 @@
|
||||
mediaOssIds: trimOrUndefined(source.mediaOssIds),
|
||||
status: trimOrUndefined(source.status)
|
||||
};
|
||||
var sortOrder = toNumberOrUndefined(source.sortOrder);
|
||||
var sortOrder = toIntegerOrUndefined(source.sortOrder);
|
||||
|
||||
if (sortOrder !== undefined) body.sortOrder = sortOrder;
|
||||
return body;
|
||||
}
|
||||
|
||||
function buildCommentBody(values) {
|
||||
// FamilyFeedCommentBody 的 content 是唯一必填字段,其余字段按需携带。
|
||||
// FamilyFeedCommentBody 仅接受 commentContent 和可选的 parentCommentId。
|
||||
var source = values || {};
|
||||
var body = {
|
||||
content: String(source.content || '').trim()
|
||||
commentContent: String(source.commentContent || '').trim()
|
||||
};
|
||||
var parentCommentId = toNumberOrUndefined(source.parentCommentId);
|
||||
var replyUserId = toNumberOrUndefined(source.replyUserId);
|
||||
var parentCommentId = trimOrUndefined(source.parentCommentId);
|
||||
|
||||
if (parentCommentId !== undefined) body.parentCommentId = parentCommentId;
|
||||
if (replyUserId !== undefined) body.replyUserId = replyUserId;
|
||||
return body;
|
||||
}
|
||||
|
||||
@@ -136,12 +152,17 @@
|
||||
|
||||
function normalizeComment(item) {
|
||||
var commentId = getCommentId(item);
|
||||
var content = item && item.content;
|
||||
var commentContent = item && item.commentContent;
|
||||
var userDeleted;
|
||||
|
||||
if (!commentId || content === undefined || content === null) return null;
|
||||
if (!commentId || commentContent === undefined) return null;
|
||||
userDeleted = String(item && item.userDeleted || '') === '1';
|
||||
return {
|
||||
commentId: commentId,
|
||||
content: String(content)
|
||||
commentContent: commentContent === null ? '该评论已删除' : String(commentContent),
|
||||
appUserNickName: trimOrUndefined(item && item.appUserNickName),
|
||||
replyCount: item && item.replyCount,
|
||||
userDeleted: userDeleted || commentContent === null
|
||||
};
|
||||
}
|
||||
|
||||
@@ -203,17 +224,46 @@
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function hasReplies(comment) {
|
||||
var count = comment && comment.replyCount;
|
||||
|
||||
return count !== undefined && count !== null && String(count) !== '' && String(count) !== '0';
|
||||
}
|
||||
|
||||
function renderCommentRow(feedId, comment) {
|
||||
var author = comment.appUserNickName ? '<strong>' + escapeHtml(comment.appUserNickName) + '</strong> ' : '';
|
||||
var actions = '';
|
||||
|
||||
if (!comment.userDeleted) {
|
||||
actions += '<button class="pill" type="button" data-feed-comment-reply="' + escapeHtml(comment.commentId) + '" data-feed-id="' + escapeHtml(feedId) + '">回复</button>';
|
||||
actions += '<button class="pill" type="button" data-feed-comment-delete="' + escapeHtml(comment.commentId) + '" data-feed-id="' + escapeHtml(feedId) + '">删除评论</button>';
|
||||
}
|
||||
if (hasReplies(comment)) {
|
||||
actions += '<button class="pill" type="button" data-feed-comment-replies="' + escapeHtml(comment.commentId) + '" data-feed-id="' + escapeHtml(feedId) + '">查看回复</button>';
|
||||
}
|
||||
|
||||
return '<div class="module-row" data-feed-comment-node="' + escapeHtml(comment.commentId) + '"><p>' + author + escapeHtml(comment.commentContent) + '</p>' + actions + '</div>';
|
||||
}
|
||||
|
||||
function normalizeComments(data) {
|
||||
var comments = normalizeList(data).map(normalizeComment);
|
||||
|
||||
return {
|
||||
invalidCount: comments.filter(function (item) { return !item; }).length,
|
||||
comments: comments.filter(Boolean)
|
||||
};
|
||||
}
|
||||
|
||||
function renderComments(feedId, data) {
|
||||
var row = query('[data-feed-id="' + feedId + '"]');
|
||||
var comments = normalizeList(data).map(normalizeComment);
|
||||
var invalidCount = comments.filter(function (item) { return !item; }).length;
|
||||
var list = comments.filter(Boolean);
|
||||
var result = normalizeComments(data);
|
||||
var list = result.comments;
|
||||
var previous = row && row.nextElementSibling;
|
||||
|
||||
if (!row) return;
|
||||
if (previous && previous.getAttribute('data-feed-comment-list') === feedId) previous.remove();
|
||||
if (invalidCount) {
|
||||
row.insertAdjacentHTML('afterend', '<div class="api-empty" data-feed-comment-list="' + escapeHtml(feedId) + '">评论响应缺少 commentId 或 content,请联系后端补充 DTO。</div>');
|
||||
if (result.invalidCount) {
|
||||
row.insertAdjacentHTML('afterend', '<div class="api-empty" data-feed-comment-list="' + escapeHtml(feedId) + '">评论响应缺少 commentId 或 commentContent,请联系后端补充 DTO。</div>');
|
||||
return;
|
||||
}
|
||||
if (!list.length) {
|
||||
@@ -222,7 +272,28 @@
|
||||
}
|
||||
|
||||
row.insertAdjacentHTML('afterend', '<div class="module-list" data-feed-comment-list="' + escapeHtml(feedId) + '">' + list.map(function (comment) {
|
||||
return '<div class="module-row"><p>' + escapeHtml(comment.content) + '</p><button class="pill" type="button" data-feed-comment-delete="' + escapeHtml(comment.commentId) + '" data-feed-id="' + escapeHtml(feedId) + '">删除评论</button></div>';
|
||||
return renderCommentRow(feedId, comment);
|
||||
}).join('') + '</div>');
|
||||
}
|
||||
|
||||
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>');
|
||||
return;
|
||||
}
|
||||
if (!result.comments.length) {
|
||||
row.insertAdjacentHTML('afterend', '<div class="api-empty" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">暂无直接回复</div>');
|
||||
return;
|
||||
}
|
||||
|
||||
row.insertAdjacentHTML('afterend', '<div class="module-list" data-feed-reply-list="' + escapeHtml(parentCommentId) + '">' + result.comments.map(function (comment) {
|
||||
return renderCommentRow(feedId, comment);
|
||||
}).join('') + '</div>');
|
||||
}
|
||||
|
||||
@@ -264,39 +335,47 @@
|
||||
|
||||
async function loadFeeds() {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (!api || !genealogyId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId) return;
|
||||
syncGenealogyLinks(genealogyId);
|
||||
try {
|
||||
renderFeeds(await api.feedsPage(genealogyId, { pageNum: 1, pageSize: 20 }), genealogyId);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '家族动态加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFeedForEdit() {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
var feedId = getCurrentFeedId();
|
||||
|
||||
if (!api || !genealogyId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId) return;
|
||||
syncGenealogyLinks(genealogyId);
|
||||
if (!feedId) return;
|
||||
try {
|
||||
fillFeedForm(await api.feedDetail(genealogyId, feedId));
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '动态详情加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function submitFeed(form) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
var feedId = getCurrentFeedId();
|
||||
var body;
|
||||
|
||||
if (!api || !genealogyId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId) return;
|
||||
// 富文本编辑器在提交前同步回 textarea,保证发送的是用户当前输入。
|
||||
if (root.KindEditor && root.KindEditor.sync) root.KindEditor.sync('#feedContent');
|
||||
body = buildFeedBody(getFormValues(form));
|
||||
@@ -313,15 +392,18 @@
|
||||
showMessage('动态已保存');
|
||||
root.location.href = getListUrl(genealogyId);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '动态保存失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function likeFeed(feedId, shouldLike) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (!api || !genealogyId || !feedId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
try {
|
||||
if (shouldLike) {
|
||||
await api.likeFeed(genealogyId, feedId);
|
||||
@@ -330,64 +412,92 @@
|
||||
}
|
||||
await loadFeeds();
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || (shouldLike ? '点赞失败' : '取消点赞失败'));
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteFeed(feedId) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (!api || !genealogyId || !feedId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
if (root.confirm && !root.confirm('确认删除这条动态吗?')) return;
|
||||
try {
|
||||
await api.deleteFeed(genealogyId, feedId);
|
||||
await loadFeeds();
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '删除动态失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function showComments(feedId) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (!api || !genealogyId || !feedId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
try {
|
||||
renderComments(feedId, await api.feedComments(genealogyId, feedId));
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '评论加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function createComment(feedId) {
|
||||
async function showCommentReplies(feedId, commentId) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId || !commentId) return;
|
||||
try {
|
||||
renderCommentReplies(feedId, commentId, await api.feedCommentReplies(genealogyId, feedId, commentId));
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '回复加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function createComment(feedId, parentCommentId) {
|
||||
var api = getApi();
|
||||
var genealogyId;
|
||||
var content;
|
||||
var body;
|
||||
|
||||
if (!api || !genealogyId || !feedId) return;
|
||||
content = root.prompt ? root.prompt('请输入评论内容', '') : '';
|
||||
body = buildCommentBody({ content: content });
|
||||
if (!body.content) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId) return;
|
||||
content = root.prompt ? root.prompt(parentCommentId ? '请输入回复内容' : '请输入评论内容', '') : '';
|
||||
body = buildCommentBody({ commentContent: content, parentCommentId: parentCommentId });
|
||||
if (!body.commentContent) return;
|
||||
try {
|
||||
await api.createFeedComment(genealogyId, feedId, body);
|
||||
await showComments(feedId);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '评论发布失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteComment(feedId, commentId) {
|
||||
var api = getApi();
|
||||
var genealogyId = requireGenealogyId();
|
||||
var genealogyId;
|
||||
|
||||
if (!api || !genealogyId || !feedId || !commentId) return;
|
||||
if (redirectUnauthorized(api)) return;
|
||||
genealogyId = requireGenealogyId();
|
||||
if (!genealogyId || !feedId || !commentId) return;
|
||||
if (root.confirm && !root.confirm('确认删除这条评论吗?')) return;
|
||||
try {
|
||||
await api.deleteFeedComment(genealogyId, feedId, commentId);
|
||||
await showComments(feedId);
|
||||
} catch (error) {
|
||||
if (redirectUnauthorized(api, error)) return;
|
||||
showMessage(error.message || '删除评论失败');
|
||||
}
|
||||
}
|
||||
@@ -424,6 +534,18 @@
|
||||
feedId = target.closest('[data-feed-comment]').getAttribute('data-feed-comment');
|
||||
createComment(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);
|
||||
}
|
||||
if (target.closest('[data-feed-comment-replies]')) {
|
||||
event.preventDefault();
|
||||
commentId = target.closest('[data-feed-comment-replies]').getAttribute('data-feed-comment-replies');
|
||||
feedId = target.closest('[data-feed-comment-replies]').getAttribute('data-feed-id');
|
||||
showCommentReplies(feedId, commentId);
|
||||
}
|
||||
if (target.closest('[data-feed-delete]')) {
|
||||
event.preventDefault();
|
||||
deleteFeed(target.closest('[data-feed-delete]').getAttribute('data-feed-delete'));
|
||||
@@ -451,7 +573,9 @@
|
||||
buildCommentBody: buildCommentBody,
|
||||
normalizeFeed: normalizeFeed,
|
||||
normalizeComment: normalizeComment,
|
||||
normalizeComments: normalizeComments,
|
||||
normalizeList: normalizeList,
|
||||
shouldRedirectToLogin: shouldRedirectToLogin,
|
||||
init: init
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user