From 40d06c180fc398c02145b9a45c88313aae216436 Mon Sep 17 00:00:00 2001 From: "DESKTOP-RQ919RC\\Pc" <1300399510@qq.com> Date: Thu, 20 Nov 2025 19:11:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E5=BA=93=E7=BB=84=E4=BB=B6=E5=B9=B6=E4=BC=98=E5=8C=96=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E9=A1=B5=E9=9D=A2=E6=A0=B7=E5=BC=8F=E5=92=8C=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增项目库组件item-project,包含学校、专业、学费等信息的展示 优化搜索页面样式,调整分类项宽度和间距 修复搜索页面滚动定位问题,完善分页和URL参数处理 添加本地开发服务器脚本serve.ps1 更新public.css和public.less样式文件 --- component/item-project/item-project.js | 91 ++++++++++++++ component/item-project/item-project.txt | 30 +++++ css/homepage-me.css | 2 + css/homepage-me.less | 5 +- css/homepage-other.css | 2 + css/homepage-other.less | 2 + css/public.css | 101 ++++++++++++++- css/public.less | 120 +++++++++++++++++- css/search.css | 3 +- css/search.less | 3 +- js/save.js | 2 + js/search.js | 106 ++++++++++------ search.html | 159 ++++++++++++------------ serve.ps1 | 56 +++++++++ 14 files changed, 558 insertions(+), 124 deletions(-) create mode 100644 component/item-project/item-project.js create mode 100644 component/item-project/item-project.txt create mode 100644 serve.ps1 diff --git a/component/item-project/item-project.js b/component/item-project/item-project.js new file mode 100644 index 0000000..79afab9 --- /dev/null +++ b/component/item-project/item-project.js @@ -0,0 +1,91 @@ +const { defineComponent, ref, onMounted } = Vue; + +export const itemProject = defineComponent({ + name: "item-project", + props: { + itemdata: { + type: Object, + default: () => ({}), + }, + }, + setup(props) { + const formatNumberWithSpaces = (number) => { + if (Number(number) != number) return; + return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); + }; + + const judgmentClass = (name) => { + const redtag = redtagArr.value || ["26Fall", "26Spring"]; + let classname = ""; + if (redtag.includes(name)) classname = "gray semester"; + else { + // 判断 字符串 是以 25/26/27... + Fall/Spring/Summer + const regex = /^(2[0-9]|3\d)(Fall|Spring|Summer)$/; + classname = regex.test(name) ? "gray" : ""; + } + return { + name, + class: classname, + }; + }; + + onMounted(() => { + checkWConfig(); + }); + + let redtagArr = ref([]); + + const checkWConfig = () => { + const wConfig = JSON.parse(localStorage.getItem("wConfig")) || {}; + if (wConfig.time) { + const time = new Date(wConfig.time); + const now = new Date(); + if (now - time > 24 * 60 * 60 * 1000) { + getWConfig(); + monitorGetRedTag(); + } else { + const config = wConfig.config || {}; + redtagArr.value = config.redtag || []; + } + } else { + getWConfig(); + monitorGetRedTag(); + } + }; + + const monitorGetRedTag = () => { + let timer = setInterval(() => { + const wConfig = JSON.parse(localStorage.getItem("wConfig")) || {}; + if (wConfig.time) { + const config = wConfig.config || {}; + redtagArr.value = config.redtag; + clearInterval(timer); + } + }, 1000); + }; + + const getWConfig = () => { + if (window.wConfigloading) return; + window.wConfigloading = true; + ajaxGet("/v2/api/config/website").then((res) => { + if (res.code == 200) { + let data = res["data"] || {}; + const config = data.config || {}; + redtagArr.value = config.redtag; + data.time = new Date().toISOString(); + localStorage.setItem("wConfig", JSON.stringify(data)); + } + window.wConfigloading = false; + }); + }; + + let item = ref({ ...props.itemdata }); + + item.value["tuition_fee_text"] = formatNumberWithSpaces(item.value.tuition_fee || ""); + + item.value["url"] = "https://program.gter.net/details/" + item.value.uniqid; + + return { item }; + }, + template: `
港校项目库
{{ tag.name || tag }}
{{ item.schoolname }} {{ item.name_zh || item.program_zh }} {{ item.name_en || item.program_en }} {{ item.department }}
|
专业排名
{{ item.rank }}
|
学费HK$
{{ item.tuition_fee_text }}
{{ item.distinctive }}
`, +}); diff --git a/component/item-project/item-project.txt b/component/item-project/item-project.txt new file mode 100644 index 0000000..672dfbc --- /dev/null +++ b/component/item-project/item-project.txt @@ -0,0 +1,30 @@ +
+
+ + 港校项目库 +
{{ tag.name || tag }} +
+
+ + + + {{ item.schoolname }} + + + {{ item.name_zh || item.program_zh }} + {{ item.name_en || item.program_en }} + + {{ item.department }} +
+
|
+ 专业排名
{{ item.rank }}
+
+
+
|
+ 学费HK$
{{ item.tuition_fee_text }}
+
+
+ + {{ + item.distinctive }} +
\ No newline at end of file diff --git a/css/homepage-me.css b/css/homepage-me.css index cc6e801..fb96fcf 100644 --- a/css/homepage-me.css +++ b/css/homepage-me.css @@ -17,6 +17,8 @@ padding-top: 39px; padding-bottom: 38px; margin-right: 20px; + position: sticky; + top: 10px; } #homepage-me .matter .card-user .avatar-box { position: relative; diff --git a/css/homepage-me.less b/css/homepage-me.less index 7b80c47..c4e111e 100644 --- a/css/homepage-me.less +++ b/css/homepage-me.less @@ -16,6 +16,9 @@ padding-top: 39px; padding-bottom: 38px; margin-right: 20px; + position: sticky; + top: 10px; + .avatar-box { position: relative; margin-bottom: 20px; @@ -165,7 +168,7 @@ a { text-decoration: none; } - + .bi-url { text-decoration: underline; color: #04b0d5; diff --git a/css/homepage-other.css b/css/homepage-other.css index 4017d69..a99d61f 100644 --- a/css/homepage-other.css +++ b/css/homepage-other.css @@ -38,6 +38,8 @@ padding-top: 39px; padding-bottom: 40px; margin-right: 20px; + position: sticky; + top: 10px; } #homepage-other .matter .card-user .avatar { width: 120px; diff --git a/css/homepage-other.less b/css/homepage-other.less index ae17d5f..a76e99f 100644 --- a/css/homepage-other.less +++ b/css/homepage-other.less @@ -40,6 +40,8 @@ padding-top: 39px; padding-bottom: 40px; margin-right: 20px; + position: sticky; + top: 10px; .avatar { width: 120px; diff --git a/css/public.css b/css/public.css index 64f0079..5759dbe 100644 --- a/css/public.css +++ b/css/public.css @@ -600,6 +600,103 @@ body { .item-box.item-tenement .picture .picture-item:not(:last-child) { margin-right: 10px; } +.item-box.item-project { + padding-bottom: 18px; +} +.item-box.item-project .school { + color: #333333; + font-size: 14px; + margin-top: 2px; + margin-bottom: 5px; +} +.item-box.item-project .school .icon { + width: 18px; + height: 20px; + margin-right: 8px; +} +.item-box.item-project .name { + word-break: break-word; + font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; + font-weight: 650; + font-style: normal; + font-size: 20px; + color: #000000; + line-height: 36px; +} +.item-box.item-project .en { + font-size: 14px; + color: #7f7f7f; + margin-top: 4px; + word-break: break-all; +} +.item-box.item-project .introduce { + font-size: 14px; + color: #555555; + margin-top: 8px; + flex-wrap: wrap; +} +.item-box.item-project .introduce .line { + color: #d7d7d7; + margin: 0 8px; +} +.item-box.item-project .introduce .q { + font-family: "Arial", "Arial-Black", "Arial Black", sans-serif; + font-weight: 900; + color: #000000; + margin-left: 8px; +} +.item-box.item-project .word { + font-size: 14px; + color: #7f7f7f; + padding: 0 10px; + height: 46px; + line-height: 46px; + background-color: #f6f6f6; + border-radius: 10px; + margin-top: 10px; + word-break: break-all; + display: inherit; +} +.item-box.item-project .tag { + flex-wrap: wrap; +} +.item-box.item-project .tag .tag-item { + font-size: 14px; + color: #555555; + padding: 0 8px; + width: fit-content; + height: 24px; + line-height: 24px; + background-color: #f2f2f2; + border-radius: 6px; + margin-bottom: 10px; +} +.item-box.item-project .tag .tag-item.admissions { + background-color: #04b0d5; + border: none; + color: #fff; +} +.item-box.item-project .tag .tag-item.gray { + border: none; + color: #fff; + background-color: #333333; +} +.item-box.item-project .tag .tag-item.gray.semester { + background-color: #f95d5d; +} +.item-box.item-project .tag .tag-item:not(:last-child) { + margin-right: 10px; +} +.item-box.item-project .tag .tag-item.blue { + color: #ffffff; + background-color: #04b0d5; +} +.item-box.item-project .tag .tag-item.icon { + height: 24px; + width: 94px; + padding: 0; + margin-right: 10px; +} .item-box .comment { height: 40px; background-color: #f6f6f6; @@ -1123,7 +1220,7 @@ body { margin-right: 10px; } .side-box.newest-side-box .box .item .dot.dot-green { - background-image: url(/img/dot-green.svg); + background-image: url(../img/dot-green.svg); background-repeat: no-repeat; } .side-box.newest-side-box .box .item .text { @@ -1158,7 +1255,7 @@ body { width: 6px; height: 6px; margin-right: 10px; - background-image: url(/img/dot-blue.svg); + background-image: url(../img/dot-blue.svg); background-repeat: no-repeat; } .side-box.essence-side-box .box .item .text { diff --git a/css/public.less b/css/public.less index f4eb389..838a817 100644 --- a/css/public.less +++ b/css/public.less @@ -728,6 +728,119 @@ body { } } + &.item-project { + padding-bottom: 18px; + .school { + .icon { + width: 18px; + height: 20px; + margin-right: 8px; + } + + color: #333333; + font-size: 14px; + margin-top: 2px; + margin-bottom: 5px; + } + + .name { + word-break: break-word; + font-family: "PingFangSC-Semibold", "PingFang SC Semibold", "PingFang SC", sans-serif; + font-weight: 650; + font-style: normal; + font-size: 20px; + color: #000000; + line-height: 36px; + } + + .en { + font-size: 14px; + color: #7f7f7f; + margin-top: 4px; + word-break: break-all; + } + + .introduce { + font-size: 14px; + color: #555555; + margin-top: 8px; + flex-wrap: wrap; + + .line { + color: #d7d7d7; + margin: 0 8px; + } + + .q { + font-family: "Arial", "Arial-Black", "Arial Black", sans-serif; + font-weight: 900; + color: #000000; + margin-left: 8px; + } + } + + .word { + font-size: 14px; + color: #7f7f7f; + padding: 0 10px; + height: 46px; + line-height: 46px; + background-color: #f6f6f6; + border-radius: 10px; + margin-top: 10px; + word-break: break-all; + display: inherit; + } + + .tag { + flex-wrap: wrap; + + .tag-item { + &.admissions { + background-color: #04b0d5; + border: none; + color: #fff; + } + + &.gray { + border: none; + color: #fff; + background-color: rgba(51, 51, 51, 1); + + &.semester { + background-color: #f95d5d; + } + } + + font-size: 14px; + color: #555555; + padding: 0 8px; + width: fit-content; + height: 24px; + line-height: 24px; + background-color: #f2f2f2; + border-radius: 6px; + margin-bottom: 10px; + + &:not(:last-child) { + margin-right: 10px; + } + + &.blue { + color: #ffffff; + background-color: #04b0d5; + } + + &.icon { + height: 24px; + width: 94px; + padding: 0; + margin-right: 10px; + } + } + } + } + .comment { height: 40px; background-color: rgba(246, 246, 246, 1); @@ -1360,7 +1473,7 @@ body { } .side-box.newest-side-box .box .item .dot.dot-green { - background-image: url(/img/dot-green.svg); + background-image: url(../img/dot-green.svg); background-repeat: no-repeat; } @@ -1403,7 +1516,7 @@ body { width: 6px; height: 6px; margin-right: 10px; - background-image: url(/img/dot-blue.svg); + background-image: url(../img/dot-blue.svg); background-repeat: no-repeat; } @@ -1831,7 +1944,6 @@ body { } } - .input { border: none; outline: none; @@ -2160,4 +2272,4 @@ td { 100% { transform: rotate(360deg); } -} \ No newline at end of file +} diff --git a/css/search.css b/css/search.css index c40eae3..a3407e3 100644 --- a/css/search.css +++ b/css/search.css @@ -25,7 +25,8 @@ margin-bottom: 16px; } #search .classify .item { - width: 50px; + min-width: 50px; + padding: 0 8px; height: 32px; line-height: 32px; text-align: center; diff --git a/css/search.less b/css/search.less index 92e1922..55a378b 100644 --- a/css/search.less +++ b/css/search.less @@ -27,7 +27,8 @@ .classify { margin-bottom: 16px; .item { - width: 50px; + min-width: 50px; + padding: 0 8px; height: 32px; line-height: 32px; text-align: center; diff --git a/js/save.js b/js/save.js index 91ce106..3ca5e83 100644 --- a/js/save.js +++ b/js/save.js @@ -29,6 +29,8 @@ const watchList = { "../component/hot-tag/hot-tag.txt": "../component/hot-tag/hot-tag.js", // 监听 hot-search.txt,同步到 hot-search.js "../component/hot-search/hot-search.txt": "../component/hot-search/hot-search.js", + // 监听 item-project.txt,同步到 item-project.js + "../component/item-project/item-project.txt": "../component/item-project/item-project.js", // 监听 bi.txt,同步到 bi.js "../component/bi/bi.txt": "../component/bi/bi.js", diff --git a/js/search.js b/js/search.js index 6c6d6de..180be59 100644 --- a/js/search.js +++ b/js/search.js @@ -1,16 +1,17 @@ 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 { headTop } from "/component/head-top/head-top.js"; -import { hotTag } from "/component/hot-tag/hot-tag.js"; -import { hotSearch } from "/component/hot-search/hot-search.js"; -import { slideshowBox } from "/component/slideshow-box/slideshow-box.js"; -import { latestList } from "/component/latest-list/latest-list.js"; -import { loadBox } from "/component/load-box/load-box.js"; +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 { itemProject } from "../component/item-project/item-project.js"; +import { headTop } from "../component/head-top/head-top.js"; +import { hotTag } from "../component/hot-tag/hot-tag.js"; +import { hotSearch } from "../component/hot-search/hot-search.js"; +import { slideshowBox } from "../component/slideshow-box/slideshow-box.js"; +import { latestList } from "../component/latest-list/latest-list.js"; +import { loadBox } from "../component/load-box/load-box.js"; const appSearch = createApp({ setup() { @@ -18,7 +19,8 @@ const appSearch = createApp({ let typeValue = ref(null); let kw = ref(""); onMounted(() => { - // const params = getUrlParams(); + const params = getUrlParams(); + console.log("params", params); // kw.value = params.kw || ""; // const urlObj = new URL(location.href); // const pathParts = urlObj.pathname.split("/").filter((part) => part); @@ -26,9 +28,11 @@ const appSearch = createApp({ kw.value = kwValue.value.innerText; const tab = typeValue.value.innerText; if (tab) tabValue.value = tab; + if (params.page) page.value = params.page; + else page.value = 1; - page.value = 1; - getList(); + if (kw.value) getList(); + else page.value = null; getUserInfoWin(); @@ -125,6 +129,8 @@ const appSearch = createApp({ if (loading.value || page.value == null) return; loading.value = true; const limit = 20; + window.scrollTo(0, 0); + updateUrlParams({ page: page.value }); ajaxGet(`/v2/api/forum/topicLists?type=${tabValue.value == "all" ? "" : tabValue.value}&page=${page.value}&limit=${limit}&keyword=${kw.value}`) .then((res) => { if (res.code != 200) { @@ -133,6 +139,38 @@ const appSearch = createApp({ } let data = res.data; + data.data.unshift({ + id: 20, + program_en: "Master of Laws in Arbitration and Dispute Resolution", + program_zh: "法学硕士(仲裁及争议解决学)", + program_abbr: "LLMARBDR", + program_code: "P41", + award_en: "Master of Laws in Arbitration and Dispute Resolution", + award_zh: "法学硕士(仲裁及争议解决学)", + subject_area_id: 9, + subject_area_name: "Law", + primary_university: "City University of Hong Kong", + primary_university_id: 3, + status: "ACTIVE", + intake_year: 2026, + disciplineid: 9, + distinctive: "毕业生可参与:当事人、辩护人、专家、仲裁员和调解员", + rank: "42", + department: "法律学院", + admissionsproject: "1", + departmentid: 26, + schoolalias: "城大", + schoolname: "香港城市大学", + tags: ["有奖学金", "论文课程", "26fall 提前批", "Top 50", "专业资格认证"], + schoolenname: "City University of Hong Kong", + intake_month: 9, + schoolid: 311, + tuition_fee: null, + uniqid: "tf1yFYMER8-1bY1t5oLbKaNc2FVhOWM0", + type: "programs", + schoollogo: "https://oss.x-php.com/school/J6BSwE-VfCFkCb1SBaR7ec6NYmTA4pRcOalNHJRfNzUxNg~~", + }); + list.value = data.data; if (list.value.length == 0) page.value = null; @@ -141,7 +179,14 @@ const appSearch = createApp({ maxPage.value = Math.ceil(count.value / limit); pagination.value = calculatePagination(page.value, maxPage.value); - updateUrlLastPath(kw.value); + let url = `/search/${kw.value}`; + + const hostname = location.hostname; + const localHostReg = /^(localhost|127\.0\.0\.1|\[::1\])$/; + if (localHostReg.test(hostname)) url = `/search.html`; + + updateUrlLastPath(url); + removeQueryQ(); }) .catch((err) => { err = err.data; @@ -227,29 +272,13 @@ const appSearch = createApp({ const sidebarFixed = ref(false); const matterFixed = ref(false); + const matterBottom = ref(false); const handleScroll = () => { - - matterHeight.value = -(document.querySelector(".matter-content").offsetHeight - window.innerHeight); - sidebarHeight.value = -(document.querySelector(".sidebar-box").offsetHeight - window.innerHeight); - - // const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - // const clientHeight = window.innerHeight; - - // const sideHeight = sidebarRef.value.offsetHeight; - // const matterTop = matterRef.value.offsetTop; - // const matterHeight = matterContentRef.value.offsetHeight; - - // console.log("sideHeight", sideHeight); - // console.log("matterHeight", matterHeight); - // if (sideHeight < matterHeight) { - // // 侧边栏滚动固定 - // if (scrollTop >= matterTop + sideHeight - clientHeight) sidebarFixed.value = true; - // else sidebarFixed.value = false; - // } else { - // if (scrollTop >= matterTop + matterHeight - clientHeight) matterFixed.value = true; - // else matterFixed.value = false; - // } + matterHeight.value = -(matterContentRef.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); @@ -259,7 +288,7 @@ const appSearch = createApp({ let sidebarHeight = ref(0); let matterHeight = ref(0); - return { matterHeight, sidebarHeight, matterFixed, matterContentRef, sidebarFixed, matterRef, sidebarRef, loading, typeValue, kwValue, startSearch, kw, maxPage, prevPage, nextPage, tabValue, cutTab, tabList, count, list, page, pagination, cutPage }; + return { matterHeight, sidebarHeight, matterBottom, matterFixed, matterContentRef, sidebarFixed, matterRef, sidebarRef, loading, typeValue, kwValue, startSearch, kw, maxPage, prevPage, nextPage, tabValue, cutTab, tabList, count, list, page, pagination, cutPage }; }, }); appSearch.component("item-forum", itemForum); @@ -268,6 +297,7 @@ appSearch.component("itemSummary", itemSummary); appSearch.component("itemVote", itemVote); appSearch.component("itemMj", itemMj); appSearch.component("itemTenement", itemTenement); +appSearch.component("itemProject", itemProject); appSearch.component("head-top", headTop); appSearch.component("hot-tag", hotTag); appSearch.component("hot-search", hotSearch); diff --git a/search.html b/search.html index 8dd078a..1b5831c 100644 --- a/search.html +++ b/search.html @@ -1,84 +1,89 @@ - - - - 搜索 - - - - - - -