diff --git a/component/item-head/item-head.js b/component/item-head/item-head.js index 330ae90..e0ea088 100644 --- a/component/item-head/item-head.js +++ b/component/item-head/item-head.js @@ -167,5 +167,5 @@ export const itemHead = defineComponent({ report, }, - template: `
{{ item?.user?.nickname || item.nickname || "匿名用户" }}
{{ timestamp }}
公开 匿名
{{ item.views }}
举报
删除
{{ item.name }} {{ item }}
`, + template: `
{{ item?.user?.nickname || item.nickname || "匿名用户" }}
{{ timestamp }}
公开 匿名
{{ item.views }}
举报
删除
{{ item.name }} {{ item }}
`, }); diff --git a/component/item-head/item-head.txt b/component/item-head/item-head.txt index 12f948b..042cc55 100644 --- a/component/item-head/item-head.txt +++ b/component/item-head/item-head.txt @@ -62,8 +62,12 @@
- - + + + + + + {{ item.name }} {{ item }}
diff --git a/js/best.js b/js/best.js new file mode 100644 index 0000000..d99fc64 --- /dev/null +++ b/js/best.js @@ -0,0 +1,266 @@ +const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provide } = Vue; + +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 { headTop } = await import(withVer("../component/head-top/head-top.js")); +const { hotTag } = await import(withVer("../component/hot-tag/hot-tag.js")); +const { hotSearch } = await import(withVer("../component/hot-search/hot-search.js")); +const { slideshowBox } = await import(withVer("../component/slideshow-box/slideshow-box.js")); +const { latestList } = await import(withVer("../component/latest-list/latest-list.js")); +const { loadBox } = await import(withVer("../component/load-box/load-box.js")); + +const appSearch = createApp({ + setup() { + let tag = ref(""); + let tagValue = ref(null); + let typeValue = ref(null); + onMounted(() => { + // const params = getUrlParams(); + // tag.value = params.tag || ""; + + // const urlObj = new URL(location.href); + // const pathParts = urlObj.pathname.split("/").filter((part) => part); + // tag.value = pathParts.pop(); + + tag.value = tagValue.value.innerText; + const type = typeValue.value.innerText; + if (type) tabValue.value = type; + + // init(); + getList(); + getUserInfoWin(); + + window.addEventListener("scroll", handleScroll); + + const preLoader = document.getElementById("pre-loader"); + if (preLoader) preLoader.style.display = "none"; + }); + + let isLogin = ref(false); + let realname = ref(0); // 是否已经实名 + let userInfoWin = ref({}); + 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"]) 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 cutTab = (type) => { + if (!uniqid) return; + if (tabValue.value == type) return; + page.value = 1; + list.value = []; + count.value = 0; + tabValue.value = type; + pagination.value = []; + + updateUrlParams({ type: type == "all" ? null : type }); + + getList(); + }; + + let tabList = ref({ + all: "全部", + thread: "论坛", + offer: "Offer", + offer_summary: "总结", + interviewexperience: "面经", + vote: "投票", + }); + + let tabValue = ref("all"); + + let uniqid = ""; + const init = () => { + ajaxGet(`/v2/api/forum/tagDetails?name=${tag.value}`).then((res) => { + if (res.code != 200) { + creationAlertBox("error", res.message); + page.value = null; + return; + } + const data = res.data; + uniqid = data.uniqid; + page.value = 1; + + console.log("data", data); + + getList(); + }); + }; + + let loading = ref(false); + let page = ref(1); + let maxPage = ref(0); + let count = ref(0); + let list = ref([]); + let pagination = ref([]); + const getList = () => { + console.log("page.value", page.value); + if (loading.value || page.value == 0) return; + loading.value = true; + // https://api.gter.net/v2/api/forum/topicLists?type=thread&page=1&limit=20&best=1 + const limit = 20; + window.scrollTo(0, 0); + console.log("getList"); + + ajaxGet(`/v2/api/forum/topicLists?type=${tabValue.value == "all" ? "" : tabValue.value}&page=${page.value}&limit=${limit}&best=1`) + .then((res) => { + if (res.code != 200) { + creationAlertBox("error", res.message); + return; + } + + let data = res.data; + list.value = data.data; + if (list.value.length == 0) page.value = null; + count.value = data.count; + loading.value = false; + maxPage.value = Math.ceil(count.value / limit); + pagination.value = calculatePagination(page.value, maxPage.value); + }) + .catch((err) => { + err = err.data; + if (err.code == 401) goLogin(); + loading.value = false; + }); + }; + + const calculatePagination = (currentPage, totalPages, visibleCount = 3) => { + // 处理特殊情况:总页数小于等于1时,无需显示分页 + if (totalPages <= 1) { + return []; + } + + const pages = []; + // 始终显示第一页 + pages.push(1); + + // 计算中间需要显示的页码范围 + let startPage = Math.max(2, currentPage - Math.floor(visibleCount / 2)); + let endPage = Math.min(totalPages - 1, startPage + visibleCount - 1); + + // 调整起始页码,确保显示足够数量的页码 + startPage = Math.max(2, endPage - visibleCount + 1); + + // 前面的省略号:如果第一页和起始页之间有间隔 + if (startPage > 2) { + pages.push("..."); + } + + // 添加中间的页码 + for (let i = startPage; i <= endPage; i++) { + pages.push(i); + } + + // 后面的省略号:如果最后一页和结束页之间有间隔 + if (endPage < totalPages - 1) { + pages.push("..."); + } + + // 始终显示最后一页(如果总页数大于1) + if (totalPages > 1) { + pages.push(totalPages); + } + + return pages; + }; + + const cutPage = (value) => { + if (value == "...") return; + if (value == page.value) return; + page.value = value; + list.value = []; + getList(); + }; + + const prevPage = () => { + page.value -= 1; + pagination.value = []; + list.value = []; + getList(); + }; + + const nextPage = () => { + page.value += 1; + pagination.value = []; + list.value = []; + getList(); + }; + + const sidebarFixed = ref(false); + + const handleScroll = () => { + // const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + // const clientHeight = window.innerHeight; + // // 侧边栏滚动固定 + // if (scrollTop >= matterRef.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; + }; + + const matterRef = ref(null); + const contentRef = ref(null); + const sidebarRef = ref(null); + + let sidebarHeight = ref(0); + let matterHeight = ref(0); + + return { sidebarHeight, matterHeight, sidebarFixed, contentRef, matterRef, sidebarRef, loading, tagValue, typeValue, maxPage, prevPage, nextPage, tag, tabValue, cutTab, tabList, count, list, page, pagination, cutPage }; + }, +}); +appSearch.component("item-forum", itemForum); +appSearch.component("itemOffer", itemOffer); +appSearch.component("itemSummary", itemSummary); +appSearch.component("itemVote", itemVote); +appSearch.component("itemMj", itemMj); +appSearch.component("itemTenement", itemTenement); +appSearch.component("head-top", headTop); +appSearch.component("hot-tag", hotTag); +appSearch.component("hot-search", hotSearch); +appSearch.component("slideshow-box", slideshowBox); +appSearch.component("latest-list", latestList); +appSearch.component("load-box", loadBox); +appSearch.mount("#search-tag");