Initial commit: MyBlog full stack blog
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/* =====================================================================
|
||||
* 好友模块(friend.js)
|
||||
* 好友申请 / 状态展示 / 博主审批弹窗。
|
||||
* ===================================================================== */
|
||||
|
||||
import { state } from "./state.js";
|
||||
import { escapeHtml, formatDate, openModal, showToast } from "./utils.js";
|
||||
import { api } from "./api.js";
|
||||
import { openLoginModal } from "./auth.js";
|
||||
import { renderAuthArea } from "./router.js";
|
||||
|
||||
export async function applyFriend() {
|
||||
if (!state.user) { openLoginModal(); showToast("请先登录后再申请好友", "info"); return; }
|
||||
try {
|
||||
await api("/api/friend/apply", { method: "POST" });
|
||||
state.friendStatus = "pending";
|
||||
renderAuthArea();
|
||||
showToast("好友申请已提交,等待博主审批", "success");
|
||||
} catch (err) {
|
||||
showToast(err.message, "error");
|
||||
}
|
||||
}
|
||||
|
||||
// 记录当前打开的审批弹窗引用,避免重复打开时弹窗叠加
|
||||
let manageModal = null;
|
||||
|
||||
export function openFriendManageModal() {
|
||||
// 先关闭上一次打开的审批弹窗
|
||||
if (manageModal) { try { manageModal.close(); } catch (e) { /* 忽略 */ } }
|
||||
const body = document.createElement("div");
|
||||
body.innerHTML = '<p class="muted">加载中…</p>';
|
||||
manageModal = openModal({ title: "好友申请管理", content: body });
|
||||
renderApplications(body);
|
||||
}
|
||||
|
||||
export async function openFriendListModal() {
|
||||
const body = document.createElement("div");
|
||||
body.innerHTML = '<p class="muted">加载中…</p>';
|
||||
const modal = openModal({ title: "好友列表", content: body });
|
||||
try {
|
||||
const friends = await api("/api/friend/list");
|
||||
if (!friends.length) { body.innerHTML = '<p class="empty">还没有好友</p>'; return; }
|
||||
body.innerHTML = friends.map((f) => `
|
||||
<div class="friend-row">
|
||||
${f.avatar ? `<img class="friend-avatar" src="${escapeHtml(f.avatar)}" alt="">` : '<span class="friend-avatar friend-avatar-empty"></span>'}
|
||||
<div class="friend-info">
|
||||
<strong>${escapeHtml(f.username)}</strong>
|
||||
<span class="muted">${escapeHtml(f.bio || `成为好友于 ${formatDate(f.friend_since)}`)}</span>
|
||||
</div>
|
||||
</div>`).join("");
|
||||
} catch (err) {
|
||||
body.innerHTML = "";
|
||||
showToast(err.message, "error");
|
||||
}
|
||||
}
|
||||
|
||||
export async function renderApplications(body) {
|
||||
try {
|
||||
const records = await api("/api/friend/applications");
|
||||
if (!records.length) { body.innerHTML = '<p class="empty">暂无申请记录</p>'; return; }
|
||||
body.innerHTML = "";
|
||||
const STATUS_TEXT = { pending: "待审批", accepted: "已通过", rejected: "已拒绝" };
|
||||
for (const record of records) {
|
||||
const row = document.createElement("div");
|
||||
row.className = "app-row";
|
||||
const statusText = STATUS_TEXT[record.status] || record.status;
|
||||
row.innerHTML = `
|
||||
<span class="app-user">${escapeHtml(record.username || "未知用户")}</span>
|
||||
<span class="app-email muted">${escapeHtml(record.email || "")}</span>
|
||||
<span class="app-time muted">${formatDate(record.created_time)}</span>
|
||||
<span class="app-status">${statusText}</span>`;
|
||||
if (record.status === "pending") {
|
||||
const approveBtn = document.createElement("button");
|
||||
approveBtn.className = "btn btn-primary btn-sm"; approveBtn.textContent = "通过";
|
||||
approveBtn.addEventListener("click", async () => {
|
||||
try {
|
||||
await api(`/api/friend/${record.id}/approve`, { method: "POST" });
|
||||
showToast("已通过好友申请", "success");
|
||||
await renderApplications(body); // 原地刷新当前弹窗内容,不再叠加新弹窗
|
||||
} catch (err) { showToast(err.message, "error"); }
|
||||
});
|
||||
const rejectBtn = document.createElement("button");
|
||||
rejectBtn.className = "btn btn-outline btn-sm"; rejectBtn.textContent = "拒绝";
|
||||
rejectBtn.addEventListener("click", async () => {
|
||||
try {
|
||||
await api(`/api/friend/${record.id}/reject`, { method: "POST" });
|
||||
showToast("已拒绝好友申请");
|
||||
await renderApplications(body); // 原地刷新当前弹窗内容,不再叠加新弹窗
|
||||
} catch (err) { showToast(err.message, "error"); }
|
||||
});
|
||||
row.appendChild(approveBtn);
|
||||
row.appendChild(rejectBtn);
|
||||
}
|
||||
body.appendChild(row);
|
||||
}
|
||||
} catch (err) {
|
||||
body.innerHTML = "";
|
||||
showToast(err.message, "error");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user