Files
PC-Light-Forum/js/public.js
DESKTOP-RQ919RC\Pc 43556292d2 fix(component): 修复组件名称错误和props类型定义
refactor(component): 重构组件模板结构,移除重复代码

feat(component): 添加可选props支持外部数据传入

style(css): 优化样式布局和响应式设计

fix(js): 修复URL路径处理逻辑和滚动加载问题

feat(search): 新增搜索页推荐内容和空状态处理

chore: 添加新图标资源文件
2025-12-22 19:01:00 +08:00

444 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const forumBaseURL = "https://api.gter.net";
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
const withVer = (p) => `${p}?v=${window.__ASSET_VERSION__}`;
const getScriptParameter = (paramName) => {
const currentScript = document.currentScript;
if (currentScript && currentScript.src) {
const url = new URL(currentScript.src, window.location.origin);
return url.searchParams.get(paramName);
}
return null;
};
// 判断是否已经创建了v参数
const vParam = getScriptParameter("v");
// 导出ajax函数
const ajax = (url, data) => {
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
url = url.indexOf("https://") > -1 ? url : forumBaseURL + url;
if (data) data["v"] = vParam || "v2";
return new Promise(function (resolve, reject) {
if (location.hostname == "127.0.0.1") axios.defaults.headers.common["Authorization"] = "n1pstcsmw6m6bcx49z705xhvduqviw29";
axios
.post(url, data, {
emulateJSON: true,
withCredentials: true,
})
.then(function (res) {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
if (data.code == 401) {
// 需要登录
go_ajax_Login();
reject();
}
resolve(data);
})
.catch((err) => {
reject();
if (err.response?.status == 401) go_ajax_Login();
});
});
};
const ajaxdelete = (url, data) => {
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
url = url.indexOf("https://") > -1 ? url : forumBaseURL + url;
return new Promise(function (resolve, reject) {
if (data) data["v"] = vParam || "v2";
axios
.delete(url, {
emulateJSON: true,
withCredentials: true,
data,
})
.then(function (res) {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
if (data.code == 401) {
// 需要登录
go_ajax_Login();
reject();
}
resolve(data);
})
.catch((err) => {
reject();
if (err.response?.status == 401) go_ajax_Login();
});
});
};
// 导出ajaxGet函数
const ajaxGet = (url) => {
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
url = url.indexOf("https://") > -1 ? url : forumBaseURL + url;
const paramSymbol = url.includes("?") ? "&" : "?";
url = `${url}${paramSymbol}v=${vParam || "v2"}`;
return new Promise(function (resolve, reject) {
if (location.hostname == "127.0.0.1") axios.defaults.headers.common["Authorization"] = "n1pstcsmw6m6bcx49z705xhvduqviw29";
axios
.get(
url,
{},
{
emulateJSON: true,
withCredentials: true,
}
)
.then(function (res) {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
if (data.code == 401) {
// 需要登录
go_ajax_Login();
reject();
}
resolve(data);
})
.catch((error) => {
if (error?.status == 401) go_ajax_Login();
reject(error);
});
});
};
const strtimeago = (dateStr, type = 1) => {
dateStr = dateStr + ""; // 反之传入的不是字符串
dateStr = dateStr.replaceAll("-", "/"); // 修改格式
var minute = 1000 * 60; // 把分,时,天,周,半个月,一个月用毫秒表示
var hour = minute * 60;
var day = hour * 24;
var now = new Date().getTime(); // 获取当前时间毫秒
let objectTime = new Date(dateStr).getTime();
var diffValue = now - objectTime; // 时间差
if (diffValue < 0) return "刚刚";
var minC = diffValue / minute; // 计算时间差的分,时,天,周,月
var hourC = diffValue / hour;
var dayC = diffValue / day;
const diffInMilliseconds = now - objectTime;
const diffInYears = diffInMilliseconds / (1000 * 60 * 60 * 24 * 365);
const diffInMonths = diffInYears * 12;
let result = "";
if (dayC >= 7) {
var datetime = new Date(dateStr);
var Nyear = datetime.getFullYear();
var Nmonth = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var Ndate = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
var Nhour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
var Nmin = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
if (type == 4) {
if (new Date().getFullYear() !== Nyear) result = `${Nyear}${Nmonth}${Ndate}`;
else result = `${Nmonth}${Ndate}${Nhour}:${Nmin}`;
}
if (type == 1) result = Nyear + "-" + Nmonth + "-" + Ndate;
if (type == 2) {
result = `${Nmonth}${Ndate}${Nhour}:${Nmin}`;
if (new Date().getFullYear() !== Nyear) result = `${Nyear}${result}`;
}
if (type == 3) {
if (diffInYears >= 1) result = Math.floor(diffInYears) + "年前";
else if (diffInMonths >= 1) result = Math.floor(diffInMonths) + "个月前";
else result = parseInt(dayC) + "天前";
}
} else if (dayC >= 1) result = parseInt(dayC) + "天前";
else if (hourC >= 1 && hourC <= 24) result = parseInt(hourC) + "小时前";
else if (minC >= 1 && minC <= 60) result = parseInt(minC) + "分钟前";
else result = "刚刚";
return result;
};
const timeago = (dateTimeStamp, type = 1) => {
if (!dateTimeStamp) return "刚刚";
// 判断位数
if (dateTimeStamp.toString().length !== 13) dateTimeStamp = dateTimeStamp * 1000;
var minute = 1000 * 60; //把分,时,天,周,半个月,一个月用毫秒表示
var hour = minute * 60;
var day = hour * 24;
var now = new Date().getTime(); //获取当前时间毫秒
var diffValue = now - dateTimeStamp; //时间差
if (diffValue < 0) return "刚刚";
var minC = diffValue / minute; //计算时间差的分,时,天,周,月
var hourC = diffValue / hour;
var dayC = diffValue / day;
let result = "";
if (dayC >= 7) {
var datetime = new Date(dateTimeStamp);
var Nyear = datetime.getFullYear();
var Nmonth = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var Ndate = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
var Nhour = datetime.getHours() < 10 ? "0" + datetime.getHours() : datetime.getHours();
var Nmin = datetime.getMinutes() < 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
if (type == 1) result = Nyear + "-" + Nmonth + "-" + Ndate;
if (type == 2) {
result = `${Nmonth}${Ndate}${Nhour}:${Nmin}`;
if (new Date().getFullYear() !== Nyear) result = `${Nyear}${result}`;
}
} else if (dayC >= 1) result = parseInt(dayC) + "天前";
else if (hourC >= 1 && hourC <= 24) result = parseInt(hourC) + "小时前";
else if (minC >= 1 && minC <= 60) result = parseInt(minC) + "分钟前";
else result = "刚刚";
return result;
};
const managerHide = (token, state, type = "offer") => {
return new Promise((resolve, reject) => {
const obj = {
offer: "Offer",
offer_summary: "总结",
interviewexperience: "面经",
thread: "帖子",
question: "帖子",
vote: "投票",
};
const isConfirmed = confirm(`确定要${state == 0 ? "隐藏" : "显示"}${obj[type]}吗?`);
if (isConfirmed) {
ajax(`/v2/api/forum/setTopicHide`, {
token,
hidden: Number(state !== 1),
}).then((res) => {
const data = res.data;
creationAlertBox("success", res.message || "");
resolve(data.hidden);
});
}
});
};
// 推荐
const managerRecommend = (token, state) => {
return new Promise((resolve, reject) => {
const post = () => {
ajax(`/v2/api/forum/setTopicRecommend`, {
token,
recommend: state == 1 ? 0 : 1,
}).then((res) => {
const data = res.data;
creationAlertBox("success", res.message || "");
resolve(data.recommend);
});
};
if (state == 1) {
const isConfirmed = confirm(`确定要取消推荐吗?`);
if (isConfirmed) post();
else resolve(state);
} else post();
});
};
// 精华
const managerEssence = (token, state) => {
return new Promise((resolve, reject) => {
const post = () => {
ajax(`/v2/api/forum/setTopicBest`, {
token,
best: state == 1 ? 0 : 1,
}).then((res) => {
const data = res.data;
creationAlertBox("success", res.message || "");
resolve(data.best);
});
};
if (state == 1) {
const isConfirmed = confirm(`确定要取消精华吗?`);
if (isConfirmed) post();
else resolve(state);
} else post();
});
};
// 删除
const managerDelete = (token) => {
return new Promise((resolve, reject) => {
const post = () => {
ajaxdelete(`/v2/api/forum/deleteTopic`, {
token,
}).then((res) => {
creationAlertBox("success", res.message || "");
resolve();
});
};
const isConfirmed = confirm(`确定要删除吗?`);
if (!isConfirmed) reject();
else post();
});
};
const getUrlParams = () => {
const params = {};
const queryString = window.location.search.slice(1);
if (queryString) {
queryString.split("&").forEach((pair) => {
const [key, value] = pair.split("=");
params[decodeURIComponent(key)] = decodeURIComponent(value || "");
});
}
return params;
};
const updateUrlParams = (params, replace = false) => {
// 解析当前URL
const url = new URL(window.location.href);
const searchParams = url.searchParams;
// 遍历参数对象更新URL参数
Object.entries(params).forEach(([key, value]) => {
if (value === null || value === undefined) {
// 删除参数
searchParams.delete(key);
} else {
// 添加或修改参数
searchParams.set(key, value);
}
});
// 生成新的URL保留协议、域名、路径等只修改参数
const newUrl = url.origin + url.pathname + (searchParams.toString() ? `?${searchParams.toString()}` : "");
// 修改URL不刷新页面
if (replace) {
history.replaceState(null, "", newUrl);
} else {
history.pushState(null, "", newUrl);
}
};
// 跳转 url
const redirectToExternalWebsite = (url, target = "_blank") => {
const link = document.createElement("a");
link.href = url;
link.target = target;
link.click();
};
// 点击ta的主页
const goHomePage = (token) => {
if (!token) return;
redirectToExternalWebsite(`/u/${token}`);
};
// 点击发送信息
const goSendMessage = (token) => {
if (typeof messagePrivateItem == "function") {
messagePrivateItem({ token });
return;
}
goHomePage(token);
};
const lang = {
money: { 1: "3000以下", 2: "3000-4000", 3: "4000-5000", 4: "5000-6500", 5: "6500-8000", 6: "8000-10000", 7: "10000-20000", 8: "20000-30000", 9: "30000-40000", 10: "40000-50000", 11: "50000以上" },
leaseterm: { 1: "长租", 2: "短租" },
intermediary: { 1: "中介", 2: "非中介", 3: "房东", 4: "有房招室友", 5: "其他", 6: "求房源" },
property: { 1: "唐楼", 2: "洋楼", 3: "酒店式公寓", 4: "村屋", 5: "其他", 6: "学生公寓", 7: "house", 8: "屋苑", 9: "酒店" },
elevator: { 1: "有电梯", 2: "无电梯", "-1": "不限" },
sunshinearea: { 1: "阳台", 2: "天台", "-1": "无" },
floor: { 1: "低层", 2: "中层", 3: "高层", 4: "地下", 5: "不要一楼", 6: "不要顶层" },
tenementtype: { 1: "合租", 2: "整租", 1.5: "独卫套房", 1.1: "房间", 1.2: "床位", 1.3: "客厅", 1.4: "其他", 2.1: "studio", 2.2: "一房", 2.3: "两房", 2.4: "三房", 2.5: "四房以上" },
gender: { 1: "女性", 2: "男性", 3: "男女皆可" },
location: { 1: "港岛", 2: "九龙", 3: "新界", 1.1: "上环/中环/金钟", 1.2: "湾仔/铜锣湾", 1.3: "天后/炮台山", 1.4: "北角/则鱼涌", 1.5: "太古/西湾河", 1.6: "筲箕湾/柴湾", 1.7: "西营盘/坚尼地城/石塘咀", 1.8: "薄扶林", 1.9: "赤柱/香港仔", 1.11: "半山/山顶", 1.12: "南区", 2.1: "九龙站/奥运/南昌", 2.2: "尖沙咀/佐敦", 2.3: "长沙湾/深水埗/荔枝角", 2.4: "美孚/荔景", 2.5: "红磡/黄埔", 2.6: "土瓜湾/何文田", 2.7: "九龙城/启德", 2.8: "石夹尾/九龙塘", 2.9: "乐富/黄大仙", 2.11: "钻石山/彩虹", 2.12: "牛头角/九龙湾/观塘", 2.13: "蓝田/油塘", 2.14: "调景岭", 2.15: "油麻地/旺角/太子", 3.1: "葵芳/葵兴", 3.2: "荃湾", 3.3: "将军澳/坑口/宝琳", 3.4: "大埔仔/西贡", 3.5: "康城", 3.6: "大围/沙田", 3.7: "马鞍山", 3.8: "大埔/火炭/太和", 3.9: "粉岭/上水", 3.11: "赤泥坪/大埔尾/樟树滩", 3.12: "元朗/天水围/屯门", 3.13: "青衣", 3.14: "东涌/马湾/愉景湾", 3.15: "长洲" },
apartmentschool: [
{ id: 1, name: "港大", sid: 309 },
{ id: 2, name: "城大", sid: 311 },
{ id: 3, name: "理工", sid: 312 },
{ id: 4, name: "浸会", sid: 313 },
{ id: 5, name: "中大", sid: 308 },
{ id: 6, name: "教大", sid: 453 },
{ id: 7, name: "科大", sid: 310 },
{ id: 8, name: "岭大", sid: 314 },
{ id: 9, name: "都大", sid: 315 },
],
rentalduration: { 1: "1个月", 2: "2个月", 3: "3个月", 4: "4个月", 5: "5个月", 6: "6个月", 7: "7个月", 8: "8个月", 9: "9个月", 10: "10个月", 11: "11个月", 12: "1年", 13: "1年1个月", 14: "1年2个月", 15: "1年3个月", 16: "1年4个月", 17: "1年5个月", 18: "1年6个月", 24: "2年", 36: "3年" },
};
let copyForumUid = (text) => {
if (navigator.clipboard)
copyForumUid = () => {
navigator.clipboard.writeText(text);
creationAlertBox("success", "复制成功");
};
else {
copyForumUid = () => {
var tempInput = document.createElement("input");
tempInput.value = text;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
creationAlertBox("success", "复制成功");
};
}
copyForumUid();
};
const updateUrlLastPath = (newLastPath, isReplace = false) => {
const raw = typeof newLastPath === "string" ? newLastPath : String(newLastPath);
const basePath = raw.split("?")[0];
let finalPathname = "";
if (basePath.startsWith("/")) {
finalPathname = basePath;
} else {
const oldPathSegments = window.location.pathname.split("/").filter(Boolean);
const newPathSegments = oldPathSegments.slice(0, -1); // 移除原最后一段
if (basePath) {
newPathSegments.push(basePath); // 添加新最后一段
}
finalPathname = "/" + newPathSegments.join("/");
}
// 拼接完整URL
const newSearch = window.location.search;
const newUrl = window.location.origin + finalPathname + newSearch;
// 管理历史栈 + 修改URL
if (isReplace) {
history.replaceState(null, document.title, newUrl);
} else {
history.pushState(null, document.title, newUrl);
}
};
const removeQueryQ = (isReplace = false) => {
const params = new URLSearchParams(window.location.search);
if (!params.has("q")) return;
params.delete("q");
const qs = params.toString();
const newUrl = window.location.origin + window.location.pathname + (qs ? "?" + qs : "") + window.location.hash;
if (isReplace) history.replaceState(null, document.title, newUrl);
else history.pushState(null, document.title, newUrl);
};
// 跳转登录
const go_ajax_Login = () => {
if (typeof ajax_login === "function") ajax_login();
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
};