const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provide } = Vue; (async function () { const { itemForum } = await import(withVer("../component/item-forum/item-forum.js")); const { itemOffer } = await import(withVer("../component/item-offer/item-offer.js")); const { itemSummary } = await import(withVer("../component/item-summary/item-summary.js")); const { itemVote } = await import(withVer("../component/item-vote/item-vote.js")); const { itemMj } = await import(withVer("../component/item-mj/item-mj.js")); const { itemTenement } = await import(withVer("../component/item-tenement/item-tenement.js")); const { itemProject } = await import(withVer("../component/item-project/item-project.js")); const { latestList } = await import(withVer("../component/latest-list/latest-list.js")); const { headTop } = await import(withVer("../component/head-top/head-top.js")); const { loadBox } = await import(withVer("../component/load-box/load-box.js")); const { huddleBox } = await import(withVer("../component/huddle-box/huddle-box.js")); const { helperPop } = await import(withVer("../component/helper-pop/helper-pop.js")); const appSectionIndex = createApp({ setup() { let uniValue = ref(null); let isMobile = ref(false); onMounted(() => { isMobile.value = window.isMobile; const urlObj = new URL(location.href); const pathParts = urlObj.pathname.split("/").filter((part) => part); const id = pathParts.pop(); section.value = uniValue.value.innerText; init(); getSectionList(); handpick(); getTags(); getList(); getTopicLatest(); window.addEventListener("scroll", handleScroll); // const preLoader = document.getElementById("pre-loader"); // if (preLoader) preLoader.style.display = "none"; document.querySelectorAll(".vuehide").forEach((item) => { item.style.display = "none"; }); }); const detailsRef = ref(null); const matterRef = ref(null); const sidebarRef = ref(null); const contentRef = ref(null); let sidebarHeight = ref(0); let matterHeight = ref(0); const sidebarFixed = ref(false); const handleScroll = () => { const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; const scrollHeight = document.documentElement.scrollHeight; const clientHeight = window.innerHeight; // 列表下 滑动到底部 获取新数据 if (scrollTop + clientHeight >= scrollHeight - 200) getList(); // 侧边栏滚动固定 // if (scrollTop >= detailsRef.value.offsetTop + sidebarRef.value.offsetHeight - clientHeight) sidebarFixed.value = true; // else sidebarFixed.value = false; matterHeight.value = -(contentRef.value.offsetHeight - window.innerHeight); sidebarHeight.value = -(sidebarRef.value.offsetHeight - window.innerHeight); if (matterHeight.value > 0) matterHeight.value = 12; if (sidebarHeight.value > 0) sidebarHeight.value = 12; }; let sectionList = ref([]); let section = ref(""); const getSectionList = () => { ajaxGet("/v2/api/forum/getSectionList").then((res) => { if (res.code != 200) return; const data = res.data || []; let obj = {}; data.forEach((element) => (obj[element.cid] = element)); const list = insertLineBetweenCategories(data, "cid"); sectionList.value = list; // if (!section.value) { // const uniqid = list[0].uniqid; // section.value = uniqid; // updateUrlParams({ section: uniqid }); // init(); // } }); }; // 将版块按 cid 分格开 const insertLineBetweenCategories = (arr) => { if (!arr.length) return []; const sortedArr = [...arr].sort((a, b) => { if (a["cid"] < b["cid"]) return -1; if (a["cid"] > b["cid"]) return 1; return 0; }); const result = [sortedArr[0]]; let prevCategory = sortedArr[0]["cid"]; for (let i = 1; i < sortedArr.length; i++) { const current = sortedArr[i]; const currentCategory = current["cid"]; if (currentCategory !== prevCategory) { result.push({ key: "line", }); prevCategory = currentCategory; } result.push(current); } return result; }; let info = ref({}); const init = () => { ajaxGet(`/v2/api/forum/getSectionDetails?sectionid=${section.value}`).then((res) => { if (res.code != 200) return; const data = res.data || {}; info.value = data; // 滚动到顶部 window.scrollTo({ top: 0, behavior: "smooth" }); }); }; let handpickList = ref([]); const handpick = () => { ajaxGet(`/v2/api/forum/topicHandpicked?sectionid=${section.value}`).then((res) => { let data = res.data || []; handpickList.value = data; }); }; let tagsList = ref([]); const getTags = () => { ajaxGet(`/v2/api/forum/sectionTags?sectionid=${section.value}`).then((res) => { if (res.code != 200) return; const data = res.data || {}; tagsList.value = data; }); }; let loading = ref(false); let page = ref(1); let count = ref(0); let list = ref([]); const getList = () => { if (loading.value || page.value == 0) return; loading.value = true; ajaxGet(`/v2/api/forum/topicLists?page=${page.value || 1}§ionid=${section.value}`) .then((res) => { if (res.code != 200) return; let data = res.data; list.value = list.value.concat(data.data); page.value = data.count > data.limit * data.page ? page.value + 1 : 0; count.value = data.count; loading.value = false; }) .catch((err) => { err = err.data; if (err.code == 401) openLoginBtnState(); loading.value = false; }); }; onMounted(() => getUserInfoWin()); let isLogin = ref(false); let realname = ref(0); // 是否已经实名 let userInfoWin = 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; }; 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"]) isLogin.value = true; else ajax_login(); } else ajax_login(); }; provide("isLogin", isLogin); provide("userInfoWin", userInfoWin); provide("realname", realname); provide("openAttest", openAttest); provide("goLogin", goLogin); const changeSection = (uniqid) => { section.value = uniqid; handpickList.value = []; info.value = {}; tagsList.value = []; count.value = 0; page.value = 1; list.value = []; init(); handpick(); getTags(); getList(); updateUrlLastPath(`/section/${uniqid}`); }; let offer = ref([]); // 面经列表 let vote = ref([]); // 面经列表 let interviewexperience = ref([]); // 面经列表 const getTopicLatest = () => { ajaxGet(`/v2/api/forum/getTopicLatest?limit=4`).then((res) => { const data = res.data || []; data.vote.forEach((item) => { if (!item.title) { item.title = item.content; item.content = ""; } }); offer.value = data.offer; vote.value = data.vote; interviewexperience.value = data.interviewexperience; }); }; let linkXg = ref([ { name: "申港超强资料包", url: "https://u.gter.net/ad/1043?x=gter", }, { name: "港校项目库", url: "http://program.gter.net/", }, { name: "26fall香港申请群", img: "/img/cong-ge.png", hint: "微信扫码添加", type: "cong", }, { name: "寄托香港租房", url: "https://fang.gter.net/", }, ]); // 链接列表 let linkOther = ref([ { name: "26fall申请群", img: "/img/cong-ge.png", title: "26fall申请群", hint: "微信扫码添加", type: "cong", }, { name: "申请求助", img: "/img/university-manager.png", title: "申请遇疑问可联系", hint: "寄托院校君", type: "university", }, ]); // 链接列表 const handleCheckAttest = (e) => { if (!isLogin.value) { goLogin(); e.preventDefault(); // 阻止默认跳转(即使 href 为链接,也强制拦截) return; } if (realname.value === 0 && userInfoWin.value?.uin > 0) { openAttest(); e.preventDefault(); // 阻止默认跳转(即使 href 为链接,也强制拦截) } }; let huddleBoxRef = ref(null); let helperPopRef = ref(null); const linkClick = (type) => { if (!isMobile.value) return; if (type == "cong") huddleBoxRef.value.open(); if (type == "university") helperPopRef.value.open(); }; return { helperPopRef, huddleBoxRef, linkClick, handleCheckAttest, sidebarHeight, matterHeight, page, sidebarFixed, detailsRef, contentRef, matterRef, sidebarRef, loading, linkOther, linkXg, uniValue, offer, vote, interviewexperience, changeSection, sectionList, section, info, handpickList, tagsList, list, count }; }, }); appSectionIndex.component("item-forum", itemForum); appSectionIndex.component("item-offer", itemOffer); appSectionIndex.component("item-summary", itemSummary); appSectionIndex.component("item-vote", itemVote); appSectionIndex.component("item-mj", itemMj); appSectionIndex.component("item-tenement", itemTenement); appSectionIndex.component("item-project", itemProject); appSectionIndex.component("latest-list", latestList); appSectionIndex.component("head-top", headTop); appSectionIndex.component("load-box", loadBox); appSectionIndex.component("huddle-box", huddleBox); appSectionIndex.component("helper-pop", helperPop); appSectionIndex.mount("#sectionIndex"); })();