const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provide } = Vue; import { itemForum } from "../component/item-forum/item-forum.js"; import { itemOffer } from "../component/item-offer/item-offer.js"; import { itemSummary } from "../component/item-summary/item-summary.js"; import { itemVote } from "../component/item-vote/item-vote.js"; import { itemMj } from "../component/item-mj/item-mj.js"; import { itemTenement } from "../component/item-tenement/item-tenement.js"; import { latestList } from "../component/latest-list/latest-list.js"; import { slideshowBox } from "../component/slideshow-box/slideshow-box.js"; import { like } from "../component/like/like.js"; const appSectionIndex = createApp({ setup() { onMounted(() => { getUserInfoWin(); setTimeout(() => (permissions.value = window["permissions"] || ["comment.edit", "comment.delete", "offercollege.hide", "offersummary.hide", "mj.hide", "topic:manager", "topic:hide"]), 1000); }); let isLogin = ref(true); let realname = ref(1); // 是否已经实名 let userInfoWin = ref({ authority: ["comment.edit", "comment.delete", "offercollege.hide", "offersummary.hide", "mj.hide", "topic:manager", "topic:hide"], avatar: "https://nas.gter.net:9008/avatar/97K4EWIMLrsbGTWXslC2WFVSEKWOikN42jDKLNjtax7HL4xtfMOJSdU9oWFhY2E~/middle?random=1761733169", groupid: 3, nickname: "肖荣豪", realname: 1, token: "01346a38444d71aaadb3adad52b52c39", uid: 500144, uin: 4238049, }); let permissions = ref([]); const getUserInfoWin = () => { const checkUser = () => { const user = window.userInfoWin; if (!user) return; document.removeEventListener("getUser", checkUser); realname.value = user.realname; userInfoWin.value = user; if (user?.uin > 0 || user?.uid > 0) isLogin.value = true; permissions.value = user?.authority || []; }; document.addEventListener("getUser", checkUser); }; const openAttest = () => { const handleAttestClose = () => { document.removeEventListener("closeAttest", handleAttestClose); realname.value = window.userInfoWin?.realname || 0; }; // 启动认证流程时添加监听 document.addEventListener("closeAttest", handleAttestClose); loadAttest(2); }; // 跳转登录 const goLogin = () => { if (typeof window === "undefined") return; if (window["userInfoWin"] && Object.keys(window["userInfoWin"]).length !== 0) { if (window["userInfoWin"]["uid"]) isNeedLogin.value = false; else ajax_login(); } else ajax_login(); }; provide("isLogin", isLogin); provide("userInfoWin", userInfoWin); provide("realname", realname); provide("openAttest", openAttest); provide("goLogin", goLogin); let authorInfo = ref({}); let info = ref({}); let ismyself = ref(false); let timestamp = ref(""); let updatedTime = ref(""); let token = ""; let uniqid = ""; let sectionn = ref([]); let tags = ref([]); onMounted(() => { const params = getUrlParams(); uniqid = params.uniqid || ""; init(); }); const init = () => { ajaxget(`/v2/api/forum/getTopicDetails?uniqid=${uniqid}`).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message || "主题不存在"); return; } const data = res.data; console.log(data, "data"); let targetInfo = data.info; if (!targetInfo.hidden) targetInfo.hidden = 0; // 替换换行 targetInfo.content = targetInfo.content?.replace(/\n/g, "
") || ""; if (!targetInfo.content) { targetInfo.content = targetInfo.title; targetInfo.title = ""; } authorInfo.value = Array.isArray(data.authorInfo) ? null : data.authorInfo; ismyself.value = data.ismyself || false; sectionn.value = targetInfo.sectionn; tags.value = targetInfo.tags; timestamp.value = strtimeago(targetInfo.release_at, 4); updatedTime.value = targetInfo.updated_at ? strtimeago(targetInfo.updated_at, 4) : null; info.value = targetInfo; token = data.token; getAuthorInfo(); getTopicOperation(); getCoinConfig(); getRelatedTopics(); getComment(); }); }; let count = ref(0); let medal = ref([]); const getAuthorInfo = () => { ajaxget(`/v2/api/forum/getSpaceDetail?uid=${authorInfo.value.uid || 0}&uin=${authorInfo.value.uin || 0}`).then((res) => { const data = res.data; const countList = data.count || []; count.value = countList.reduce((sum, item) => { const currentCount = Number(item.count) || 0; return sum + currentCount; }, 0); medal.value = data.medal || []; authorInfo.value = data.info; getCreationList(data.token); }); }; let recentlyList = ref([]); const getCreationList = (token) => { ajaxget(`/v2/api/forum/getSpaceTopicList?token=${token}&simple=1`).then((res) => { const data = res.data; recentlyList.value = data.data || []; recentlyList.value = recentlyList.value.slice(0, 8); }); }; let islike = ref(0); let iscollect = ref(0); const getTopicOperation = () => { ajax(`/v2/api/forum/getTopicOperation`, { token, actions: ["like", "collection"], }).then((res) => { const data = res.data; const like = data.like; const collection = data.collection; islike.value = like.status; iscollect.value = collection.status; }); }; let isLikeGif = ref(false); const likeClick = () => { ajax(`/v2/api/forum/postTopicLike`, { token, }).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message); return; } const data = res.data; islike.value = data.status; info.value.likes = data.likes; if (data.status) { isLikeGif.value = true; setTimeout(() => (isLikeGif.value = false), 2000); } }); }; const collectClick = () => { ajax(`/v2/api/forum/postTopicCollect`, { token, }).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message); return; } const data = res.data; iscollect.value = data.status; info.value.collections = data.collections; }); }; let strategy = ref(""); let mybalance = ref(0); let defaultcoinnum = 0; const getCoinConfig = () => { ajaxget(`/v2/api/forum/getCoinConfig`).then((res) => { const data = res.data; strategy.value = data.config.strategy.url || 0; mybalance.value = data.mybalance || 0; defaultcoinnum = data.defaultcoinnum || 0; }); }; let coinsState = ref(false); const openCoinBox = () => { coinsState.value = true; document.body.style.overflow = "hidden"; if (!coinListRequest) getCoinRankList(); }; const closeCoinBox = () => { coinsState.value = false; document.body.style.overflow = "auto"; }; let coinAmount = ref(""); const coinSubmit = () => { const num = Number(coinAmount.value || defaultcoinnum) || 0; ajax(`/v2/api/forum/postTopicCoin`, { token, num, }) .then((res) => { if (res.code == 200) creationAlertBox("success", res.message); else creationAlertBox("error", res.message); if (res.code != 200) return; let data = res.data; mybalance.value = mybalance.value - num || 0; coinAmount.value = ""; info.value.coins = data.coins || 0; coinNubmer.value = 0; coinList.value = []; getCoinRankList(); }) .finally(() => { // wx.hideLoading(); }); }; let coinNubmer = ref(0); let coinList = ref([]); let coinListRequest = false; // 控制请求次数 const getCoinRankList = () => { ajaxget(`/v2/api/forum/getCoinRankList?token=${token}&limit=1000`).then((res) => { const data = res.data; coinNubmer.value = data.nubmer; coinList.value = data.data; coinListRequest = true; }); }; let relatedList = ref([]); let relatedTime = ref(""); const getRelatedTopics = () => { ajaxget(`/v2/api/forum/getRelatedTopics?uniqid=${uniqid}&limit=8`).then((res) => { const data = res.data; relatedTime.value = data.updated_at || ""; relatedList.value = data.list || []; }); }; let alreadyCommentIdList = []; let commentPage = ref(1); let isgetCommentSate = false; let commentList = ref([]); let commentTotalCount = ref(0); const getComment = () => { if (commentPage.value == 0 || isgetCommentSate) return; isgetCommentSate = true; ajaxget(`/v2/api/forum/getCommentList?token=${token}&page=${commentPage.value}&limit=1500`) .then((res) => { if (res.code != 200) { creationAlertBox("error", res.message || ""); return; } let data = res.data; data.data.forEach((element, index) => { element.timestamp = strtimeago(element.created_at, 4); element["picture"] = []; element["isReplyBoxShow"] = 0; if (element.child.length > 0) { element.child.forEach((el) => { el["picture"] = []; el.timestamp = strtimeago(element.created_at, 4); el["isReplyBoxShow"] = 0; }); } }); if (commentPage.value > 1) { for (let index = 0; index < data.data.length; index++) { if (alreadyCommentIdList.includes(data.data[index].id)) { data.data.splice(index, 1); index--; } } } commentList.value = commentList.value.concat(data.data); commentTotalCount.value = data.count; commentPage.value = data.count > commentList.value.length ? commentPage.value + 1 : 0; }) .finally(() => { isgetCommentSate = false; }); }; let picture = ref([]); const openUserInfo = (index, i) => { if (i != undefined && commentList.value[index].child[i].user["uin"] > 0) commentList.value[index].child[i]["avatarState"] = true; if (i == undefined && index != undefined && commentList.value[index].user["uin"] > 0) commentList.value[index]["avatarState"] = true; }; const closeUserInfo = (index, i) => { if (i != undefined) commentList.value[index].child[i]["avatarState"] = false; else if (index != undefined) commentList.value[index]["avatarState"] = false; }; // 打开 回答-评论 的子评论 const openAnswerCommentsChild = (index, i) => { if (realname.value == 0 && userInfoWin.value?.uin > 0) { openAttest(); return; } if (!isLogin.value) { goLogin(); return; } closeAnswerCommentsChild(); if (i == null) commentList.value[index]["childState"] = true; else commentList.value[index].child[i]["childState"] = true; }; // 关闭 回答-评论 的子评论 const closeAnswerCommentsChild = () => { commentList.value.forEach((ele) => { ele["childState"] = false; ele["commentInput"] = ""; // 删除原本输入值 if (ele["child"] && ele["child"].length != 0) { ele["child"].forEach((el) => { el["childState"] = false; el["commentInput"] = ""; }); } }); }; let dialogSrc = ref(""); const handleAnswerText = (e) => { if (e.target.tagName === "IMG") { var src = e.target.getAttribute("src"); dialogSrc.value = src; window.addEventListener("keydown", handleKeydown); } }; const handleKeydown = (event) => { if (event.key !== "Escape") return; dialogSrc.value = ""; window.removeEventListener("keydown", handleKeydown); // 取消监听 }; // 回答-评论 点赞 const operateAnswerCommentsLike = (token, index, i) => { if (realname.value == 0 && userInfoWin.value?.uin > 0) { openAttest(); return; } if (!isLogin.value) { goLogin(); return; } ajax("https://api.gter.net/v2/api/forum/likeComment", { token, }).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message || "操作成功"); return; } let data = res.data; if (i != undefined) { commentList.value[index].child[i]["islike"] = data["status"]; commentList.value[index].child[i]["likenum"] = data["count"]; } else { commentList.value[index]["islike"] = data["status"]; commentList.value[index]["likenum"] = data["count"]; } creationAlertBox("success", res.message || "操作成功"); if (data["status"]) { isLikeGif.value = true; setTimeout(() => (isLikeGif.value = false), 2000); } }); }; let emojiState = ref(false); let emojiMaskState = ref(false); let inputTextarea = ref(""); // 打开 Emoji const openEmoji = (index, i) => { if (!isLogin.value) { goLogin(); return; } if (i != undefined) commentList.value[index].child[i]["emojiState"] = true; else if (index != undefined) commentList.value[index]["emojiState"] = true; else { closeEmoji(); closeAnswerCommentsChild(); emojiState.value = true; } emojiMaskState.value = true; }; // 关闭 Emoji const closeEmoji = (index, i) => { commentList.value.forEach((ele) => { ele["emojiState"] = false; if (ele["child"] && ele["child"].length != 0) { ele["child"].forEach((el) => { el["emojiState"] = false; }); } }); emojiState.value = false; emojiMaskState.value = false; editEmojiState.value = false; }; const TAHomePage = (uin) => goHomePage(uin); const sendMessage = (uin) => goSendMessage(uin); let emojiData = ref(["😀", "😁", "😆", "😅", "😂", "😉", "😍", "🥰", "😘", "🤥", "😪", "😵‍💫", "🤓", "🥺", "😋", "😜", "🤪", "😎", "🤩", "🥳", "😔", "🙁", "😭", "😡", "😳", "🤗", "🤔", "🤭", "🤫", "😯", "😵", "🙄", "🥴", "🤢", "🤑", "🤠", "👌", "✌️", "🤟", "🤘", "🤙", "👍", "👎", "✊", "👏", "🤝", "🙏", "💪", "❎️", "✳️", "✴️", "❇️", "#️⃣", "*️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟", "🆗", "🈶", "🉐", "🉑", "🌹", "🥀", "🌸", "🌺", "🌷", "🌲", "☘️", "🍀", "🍁", "🌙", "⭐", "🌍", "☀️", "⭐️", "🌟", "☁️", "🌈", "☂️", "❄️", "☃️", "☄️", "🔥", "💧", "🍎", "🍐", "🍊", "🍉", "🍓", "🍑", "🍔", "🍟", "🍕", "🥪", "🍜", "🍡", "🍨", "🍦", "🎂", "🍰", "🍭", "🍿", "🍩", "🧃", "🍹", "🍒", "🥝", "🥒", "🥦", "🥨", "🌭", "🥘", "🍱", "🍢", "🥮", "🍩", "🍪", "🧁", "🍵", "🍶", "🍻", "🥂", "🧋", "🎉", "🎁", "🧧", "🎃", "🎄", "🧨", "✨️", "🎈", "🎊", "🎋", "🎍", "🎀", "🎖️", "🏆️", "🏅", "💌", "📬", "🚗", "🚕", "🚲", "🛵", "🚀", "🚁", "⛵", "🚢", "🔮", "🧸", "🀄️"]); const handleEditFile = () => { editEmojiState.value = false; judgeLogin(); }; // 选择 Emoji const selectEmoji = (key, index, i) => { closeEmoji(); if (i != undefined) { if (!commentList.value[index]["child"][i]["commentInput"]) commentList.value[index]["child"][i]["commentInput"] = ""; commentList.value[index]["child"][i]["commentInput"] += key; } else if (index != undefined) { if (!commentList.value[index]["commentInput"]) commentList.value[index]["commentInput"] = ""; commentList.value[index]["commentInput"] += key; } else inputTextarea.value += key; }; const judgeLogin = () => { if (!isLogin.value) goLogin(); }; const maxPicture = 10; const handleFileUpload = (event, index, i) => { closeEmoji(); const file = event.target.files[0]; // 获取选择的文件 if (!file) return; if (file.size > maxSize) { creationAlertBox("error", "文件大小不能超过 20MB"); return; } let target = []; if (editCommentState.value) target = editPicture.value; else { if (i != undefined) target = commentList.value[index].child[i]["picture"]; else if (index != undefined) target = commentList.value[index]["picture"]; else target = picture.value; } if (target.length >= maxPicture) { creationAlertBox("error", `最多只能上传 ${maxPicture} 张图片`); return; } console.log("现有图片", target); const reader = new FileReader(); reader.onload = (e) => { const base64 = e.target.result; uploadImg(file).then((res) => { const obj = { aid: res.aid || "", url: res.url || "", }; target.push(obj); if (editCommentState.value) editPicture.value = target; else { if (i != undefined) commentList.value[index].child[i]["picture"] = target; else if (index != undefined) commentList.value[index]["picture"] = target; else picture.value = target; } creationAlertBox("success", "上传成功"); }); }; reader.readAsDataURL(file); }; let uploadConfig = null; const maxSize = 20 * 1024 * 1024; // 20MB // 上传图片 获取图片url const uploadImg = (file) => { return new Promise((resolve, reject) => { const upload = () => { let config = uploadConfig; const formData = new FormData(); formData.append(config.requestName, file); // 文件数据 formData.append("name", file.name); // 文件名 formData.append("type", "image"); // 文件名 formData.append("data", config.params.data); // 文件名 ajax(config.url, formData).then((res) => { if (res.code != 200) { creationAlertBox("error", "上传失败"); return; } let data = res.data; resolve(data); }); }; if (uploadConfig) upload(); else getUploadConfig().then(() => upload()); }); }; const getUploadConfig = () => { return new Promise((resolve, reject) => { ajax("https://api.gter.net/v1/config/upload?type=comment").then((res) => { let data = res.data; uploadConfig = data; resolve(); }); }); }; // 删除上传的图片 const closeFileUpload = (aid, index, i) => { let target = []; if (i != undefined) target = [...commentList.value[index].child[i]["picture"]]; else if (index != undefined) target = [...commentList.value[index]["picture"]]; else target = [...picture.value]; let sub = target.findIndex((item) => item.aid == aid); if (sub != -1) target.splice(sub, 1); if (i != undefined) commentList.value[index].child[i]["picture"] = target; else if (index != undefined) commentList.value[index]["picture"] = target; else picture.value = target; }; const closePictureUpload = (index) => picture.value.splice(index, 1); // 提交回答-评论 const submitAnswerComments = (index, i) => { if (realname.value == 0 && userInfoWin.value?.uin > 0) { openAttest(); return; } if (!isLogin.value) { goLogin(); return; } let content = ""; let parentid = null; // let token = this.token; let image = []; if (i != null) { content = commentList.value[index]["child"][i]["commentInput"]; parentid = commentList.value[index]["child"][i]["id"]; image = [...commentList.value[index]["child"][i]["picture"]]; } else if (index != null) { content = commentList.value[index]["commentInput"]; parentid = commentList.value[index]["id"]; image = [...commentList.value[index]["picture"]]; } else { content = inputTextarea.value; image = [...picture.value]; } // this.detailLoading = true; const attachments = { images: image, }; ajax("/v2/api/forum/postComment", { content, token, attachments, replyid: parentid, }) .then((res) => { if (res.code != 200) { creationAlertBox("error", res.message || "操作成功"); return; } let data = res.data; const timestamp = strtimeago(new Date()); if (i != null) { let targetData = { id: data["commentid"], content, isauthor: 1, islike: 0, likenum: 0, reply: { nickname: commentList.value[index]["child"][i]["nickname"], }, ...data, attachments, picture: [], timestamp, }; commentList.value[index]["child"].push(targetData); commentList.value[index]["childnum"]++; } else if (index != null) { let targetData = { id: data["commentid"], content, isauthor: 1, islike: 0, likenum: 0, reply: [], ...data, attachments, picture: [], timestamp, }; commentList.value[index]["child"].unshift(targetData); commentList.value[index]["childnum"]++; } else { let targetData = { id: data["commentid"], content, isauthor: 1, islike: 0, likenum: 0, ...data, child: [], attachments, picture: [], timestamp, }; commentList.value.unshift(targetData); inputTextarea.value = ""; picture.value = []; } commentTotalCount.value = data.count || 0; // if (!inputTextarea.value) { // const textarea = this.$refs["input-textarea"] // textarea.style.height = "80px" // } closeAnswerCommentsChild(); creationAlertBox("success", res.message || "操作成功"); }) .finally(() => { // this.detailLoading = false; }); }; let editCommentState = ref(false); let editToken = ref(""); let editPicture = ref([]); let editInput = ref(""); let editEmojiState = ref(false); const openEdit = (token, index, i) => { const list = JSON.parse(JSON.stringify(commentList.value)); let target = {}; if (i != null) target = list[index]["child"][i]; else target = list[index]; console.log("target", target); editToken.value = target.token || ""; editInput.value = target.content || ""; editPicture.value = target.attachments?.images || []; console.log("editCommentState", editPicture.value); editCommentState.value = true; }; const closeEdit = () => { editPicture.value = {}; editToken.value = ""; editInput.value = ""; editCommentState.value = false; }; // 打开 Emoji const openEditEmoji = (index, i) => { if (!isLogin.value) { goLogin(); return; } editEmojiState.value = true; }; const closeEditEmoji = () => { editEmojiState.value = false; }; const selectEditEmoji = (key) => { closeEmoji(); editInput.value += key; }; const postEditComment = () => { if (!isLogin.value) { goLogin(); return; } const image = editPicture.value; const attachments = { images: image, }; ajax("/v2/api/forum/postCommentEdit", { content: editInput.value, token: editToken.value, attachments, }).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message || "操作失败"); return; } commentList.value.forEach((element) => { if (element.token == editToken.value) { element["content"] = editInput.value; element["attachments"] = attachments; } element.child && element.child.forEach((ele) => { if (ele.token == editToken.value) { ele["content"] = editInput.value; ele["attachments"] = attachments; } }); }); editPicture.value = []; editToken.value = ""; editCommentState.value = false; editEmojiState.value = false; creationAlertBox("success", res.message || "操作成功"); }); }; const closeEditFileUpload = (aid) => { let target = [...editPicture.value]; let sub = target.findIndex((item) => item.aid == aid); if (sub != -1) target.splice(sub, 1); editPicture.value = target; }; const handleInputPaste = (event, index, ii) => { const items = event.clipboardData.items; // 获取粘贴的内容 for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.type.startsWith("image/")) { event.preventDefault(); const file = item.getAsFile(); // 获取文件 if (file.size > maxSize) { creationAlertBox("error", "文件大小不能超过 20MB"); return; } let target = []; if (editCommentState.value) target = editPicture.value; else { if (ii != undefined) target = commentList.value[index].child[ii]["picture"]; else if (index != undefined) target = commentList.value[index]["picture"]; else target = picture.value; } if (target.length >= maxPicture) { creationAlertBox("error", `最多只能上传 ${maxPicture} 张图片`); return; } const reader = new FileReader(); reader.onload = (e) => { const base64 = e.target.result; uploadImg(file).then((res) => { const obj = { aid: res.aid || "", url: res.url || "", }; target.push(obj); if (editCommentState.value) editPicture.value = target; else { if (ii != undefined) commentList.value[index].child[ii]["picture"] = target; else if (index != undefined) commentList.value[index]["picture"] = target; else picture.value = target; } creationAlertBox("success", "上传成功"); }); }; reader.readAsDataURL(file); } } }; // 自动输入框增高 const autoResize = (e) => { e.target.style.height = "auto"; // 重置高度 e.target.style.height = `${e.target.scrollHeight}px`; // 设置为内容高度 }; let commemtDelete = {}; // 点击删除 const commentDelete = (token, index, i) => { const post = () => { ajax("/v2/api/forum/deleteComment", { token, }).then((res) => { if (res.code != 200) { creationAlertBox("error", res.message); return; } if (i >= 0) { commentList.value[index].child.splice(i, 1); commentList.value[index].childnum -= 1; } else { commentList.value.splice(index, 1); } commentTotalCount.value -= 1; creationAlertBox("success", res.message || "操作成功"); }); }; const isConfirmed = confirm(`确定要删除讨论吗?`); if (isConfirmed) post(); }; const openDiscuss = () => { let dom = document.querySelector(".answer-discuss"); if (!dom) return; const rect = dom.getBoundingClientRect(); const scrollPosition = window.pageYOffset + rect.top - 50; window.scrollTo({ top: scrollPosition, behavior: "smooth", }); }; return { openDiscuss, commentDelete, handleInputPaste, autoResize, editCommentState, selectEditEmoji, closeEditEmoji, openEditEmoji, closeEdit, openEdit, closeEditFileUpload, postEditComment, submitAnswerComments, closePictureUpload, closeFileUpload, picture, editToken, editPicture, editInput, editEmojiState, handleFileUpload, inputTextarea, judgeLogin, handleEditFile, selectEmoji, emojiData, emojiMaskState, emojiState, closeEmoji, openEmoji, closeAnswerCommentsChild, openAnswerCommentsChild, dialogSrc, handleAnswerText, sendMessage, TAHomePage, operateAnswerCommentsLike, closeUserInfo, openUserInfo, permissions, commentList, commentPage, commentTotalCount, picture, userInfoWin, relatedList, relatedTime, coinNubmer, coinList, coinAmount, coinSubmit, strategy, mybalance, coinsState, openCoinBox, closeCoinBox, isLikeGif, likeClick, collectClick, islike, iscollect, recentlyList, medal, count, sectionn, tags, authorInfo, info, timestamp, updatedTime }; }, }); appSectionIndex.component("itemForum", itemForum); appSectionIndex.component("itemOffer", itemOffer); appSectionIndex.component("itemSummary", itemSummary); appSectionIndex.component("itemVote", itemVote); appSectionIndex.component("itemMj", itemMj); appSectionIndex.component("itemTenement", itemTenement); appSectionIndex.component("latestList", latestList); appSectionIndex.component("slideshowBox", slideshowBox); appSectionIndex.component("like", like); appSectionIndex.mount("#details");