fix(bi): 添加投币数量必须大于0的校验

feat(item-bottom): 实现二维码弹窗自适应右侧边界
添加判断逻辑使二维码弹窗在靠近右侧边界时向左弹出

refactor(public.js): 优化ajax请求配置和登录跳转逻辑
统一设置axios默认配置,提取登录跳转函数

style(public.css): 调整QRcode-box.right的定位
修复二维码弹窗靠近右侧时的显示问题

fix(details.js): 修复粗体标记正则匹配多行内容
使用[\s\S]*?匹配可能的多行内容

refactor(index.js): 优化列表加载和滚动逻辑
移除模拟数据,添加加载状态,调整滚动加载阈值

chore: 更新html模板中的唯一标识和广告类名
This commit is contained in:
DESKTOP-RQ919RC\Pc
2025-11-19 19:27:43 +08:00
parent f49d937f19
commit c9e229a5cd
12 changed files with 211 additions and 217 deletions

View File

@@ -139,6 +139,10 @@ class BiCard extends HTMLElement {
coinSubmit() {
const num = Number(this.input.value || this.defaultcoinnum) || 0;
if (num <= 0) {
creationAlertBox("error", "投币数量必须大于0");
return;
}
this.fetchData(`https://api.gter.net/v2/api/forum/postTopicCoin`, {
token: this.token,
num,

View File

@@ -114,17 +114,36 @@ export const itemBottom = defineComponent({
});
};
let isright = ref(false);
const share = () => {
const token = item.value.token || "";
ajax(`/v2/api/forum/postTopicShare`, {token});
ajax(`/v2/api/forum/postTopicShare`, { token });
if (!shareBoxRef.value) return
// 1. 获取元素相对于可视窗口的位置信息
const rect = shareBoxRef.value.getBoundingClientRect();
// 2. 获取可视窗口宽度(不包含滚动条,更准确)
const clientWidth = document.documentElement.clientWidth;
// 3. 计算距离:可视窗口宽度 - 元素右边缘到左边缘的距离
const distance = clientWidth - rect.right;
console.log('distance', distance);
if (distance < 140) isright.value = true;
else isright.value = false;
};
return { share, QRcode, showQRcode, copyLinkClick, collectClick, item, likeClick, isLogin, isLikeGif };
const shareBoxRef = ref(null);
return { isright, shareBoxRef, share, QRcode, showQRcode, copyLinkClick, collectClick, item, likeClick, isLogin, isLikeGif };
},
components: {
like,
},
template: `<a class="comment flexacenter" v-if="item?.commentreviews && !Array.isArray(item?.commentreviews)" :href="item.url" target="_blank"> <img class="icon" :src="item?.commentreviews?.avatar" /> <div class="text one-line-display">{{ item?.commentreviews?.content || "[图]" }}</div></a><template v-if="item.comment_list?.length != 0"> <a class="comment flexacenter" style="margin-bottom: 15px" v-for="(item, index) in item.comment_list" :key="index" :href="item.url" target="_blank"> <img class="icon" :src="item.avatar" /> <div class="text one-line-display">{{ item.content || "[图]" }}</div> </a></template><div class="bottom flexacenter"> <div class="bottom-item like flexacenter" @click="likeClick()" v-if="item?.type != 'tenement'"> <img v-if="item.is_like" class="icon" src="/img/like-red-icon.png" /> <img v-else class="icon" src="/img/like-icon.png" /> <div class="text">{{ item.likes || "赞" }}</div> </div> <div class="bottom-item flexacenter" @click="collectClick()"> <img v-if="item.is_collect" class="icon" src="/img/collect-golden.svg" /> <img v-else class="icon" src="/img/collect-gray.png" /> <div class="text">{{ item.collections || "收藏" }}</div> </div> <a class="bottom-item flexacenter" v-if="item?.type != 'tenement'" :href="'/details/' + item.uniqid" target="_blank"> <img class="icon" src="/img/discuss-icon.png" /> <div class="text">{{ item.comments || "讨论" }}</div> </a> <a class="bottom-item flexacenter" v-if="item?.type != 'tenement'" :href="'/details/' + item.uniqid" target="_blank"> <img class="icon" src="/img/bi-copper-icon.png" /> <div class="text">{{ item.coins || "投币" }}</div> </a> <!-- 鼠标移入事件 --> <div class="bottom-item share flexacenter" @mouseenter="share"> <img class="icon" src="/img/share-gray.png" style="width: 19px; height: 19px;" /> <div class="text">{{ item.shares || '转发'}}</div> <div class="share-box flexcenter"> <div class="share-item flexcenter" @click="copyLinkClick()"> <img class="share-icon" src="/img/copy-black-icon.png" /> <div class="text">复制链接</div> </div> <!-- 鼠标移入 加载二维码 --> <div class="share-item wenxin flexcenter" @mouseenter="showQRcode"> <img class="share-icon" src="/img/weixin-icon.png" /> <div class="text">微信转发</div> <div class="QRcode-box flexcenter"> <img v-if="QRcode" class="QRcode" :src="QRcode" /> <div v-else class="QRcode flexcenter"> <img class="load" src="/img/load-icon.svg" /> </div> <div class="text">微信扫码</div> </div> </div> </div> </div></div><like v-if="isLikeGif"></like>`,
template: `<a class="comment flexacenter" v-if="item?.commentreviews && !Array.isArray(item?.commentreviews)" :href="item.url" target="_blank"> <img class="icon" :src="item?.commentreviews?.avatar" /> <div class="text one-line-display">{{ item?.commentreviews?.content || "[图]" }}</div></a><template v-if="item.comment_list?.length != 0"> <a class="comment flexacenter" style="margin-bottom: 15px" v-for="(item, index) in item.comment_list" :key="index" :href="item.url" target="_blank"> <img class="icon" :src="item.avatar" /> <div class="text one-line-display">{{ item.content || "[图]" }}</div> </a></template><div class="bottom flexacenter"> <div class="bottom-item like flexacenter" @click="likeClick()" v-if="item?.type != 'tenement'"> <img v-if="item.is_like" class="icon" src="/img/like-red-icon.png" /> <img v-else class="icon" src="/img/like-icon.png" /> <div class="text">{{ item.likes || "赞" }}</div> </div> <div class="bottom-item flexacenter" @click="collectClick()"> <img v-if="item.is_collect" class="icon" src="/img/collect-golden.svg" /> <img v-else class="icon" src="/img/collect-gray.png" /> <div class="text">{{ item.collections || "收藏" }}</div> </div> <a class="bottom-item flexacenter" v-if="item?.type != 'tenement'" :href="'/details/' + item.uniqid" target="_blank"> <img class="icon" src="/img/discuss-icon.png" /> <div class="text">{{ item.comments || "讨论" }}</div> </a> <a class="bottom-item flexacenter" v-if="item?.type != 'tenement'" :href="'/details/' + item.uniqid" target="_blank"> <img class="icon" src="/img/bi-copper-icon.png" /> <div class="text">{{ item.coins || "投币" }}</div> </a> <!-- 鼠标移入事件 --> <div class="bottom-item share flexacenter" @mouseenter="share"> <img class="icon" src="/img/share-gray.png" style="width: 19px; height: 19px;" /> <div class="text">{{ item.shares || '转发'}}</div> <div class="share-box flexcenter" ref="shareBoxRef"> <div class="share-item flexcenter" @click="copyLinkClick()"> <img class="share-icon" src="/img/copy-black-icon.png" /> <div class="text">复制链接</div> </div> <!-- 鼠标移入 加载二维码 --> <div class="share-item wenxin flexcenter" @mouseenter="showQRcode"> <img class="share-icon" src="/img/weixin-icon.png" /> <div class="text">微信转发</div> <div class="QRcode-box flexcenter" :class="{'right': isright}"> <img v-if="QRcode" class="QRcode" :src="QRcode" /> <div v-else class="QRcode flexcenter"> <img class="load" src="/img/load-icon.svg" /> </div> <div class="text">微信扫码</div> </div> </div> </div> </div></div><like v-if="isLikeGif"></like>`,
});

View File

@@ -35,7 +35,7 @@
<div class="bottom-item share flexacenter" @mouseenter="share">
<img class="icon" src="/img/share-gray.png" style="width: 19px; height: 19px;" />
<div class="text">{{ item.shares || '转发'}}</div>
<div class="share-box flexcenter">
<div class="share-box flexcenter" ref="shareBoxRef">
<div class="share-item flexcenter" @click="copyLinkClick()">
<img class="share-icon" src="/img/copy-black-icon.png" />
<div class="text">复制链接</div>
@@ -45,7 +45,7 @@
<img class="share-icon" src="/img/weixin-icon.png" />
<div class="text">微信转发</div>
<div class="QRcode-box flexcenter">
<div class="QRcode-box flexcenter" :class="{'right': isright}">
<img v-if="QRcode" class="QRcode" :src="QRcode" />
<div v-else class="QRcode flexcenter">
<img class="load" src="/img/load-icon.svg" />

View File

@@ -88,5 +88,5 @@ export const latestList = defineComponent({
itemHead,
},
template: `<div class="posts-box box-newest " :class="['boxtype-' + boxtype]"> <div v-if="boxtype == 'newest'" class="box-newest-head flexacenter"> <img class="icon" src="/img/newest-icon.png" alt="" /> 最新 </div> <div v-else-if="boxtype == 'essence'" class="box-newest-head flexacenter"> <img class="icon" src="/img/essence.png" alt="" /> 精华阅读 </div> <div v-else class="slideshow-box"> <div class="tab-list flexacenter"> <div class="tab-item newest" :class="{'pitch': postsTab == 'newest'}" @click="tabPostsItem('newest')">最新</div> <div class="tab-item essence" :class="{'pitch': postsTab == 'essence'}" @click="tabPostsItem('essence')">精华</div> </div> </div> <div class="slideshow-content flexflex"> <!-- newest 最新 --> <div class="newest-side-box side-box"> <img class="bounding" src="/img/bounding-circle-green.svg" alt="" /> <div class="box"> <a v-for="(item, index) in latestList" :key="index" class="item flexacenter vuehide" :href="'/details/' + item.uniqid" target="_blank"> <div class="dot dot-green"></div> <div class="text one-line-display">{{ item.title || item.content }}</div> </a> </div> </div> <!-- essence 精选 --> <div class="essence-side-box side-box"> <img class="bounding" src="/img/bounding-circle-blue.svg" alt="" /> <div class="box"> <a v-for="(item, index) in topList" :key="index" class="item flexacenter vuehide" :href="'/details/' + item.uniqid" target="_blank"> <div class="dot"></div> <div class="text one-line-display">{{ item.title || item.content }}</div> </a> </div> </div> </div></div>`,
template: `<div class="posts-box box-newest " :class="['boxtype-' + boxtype]"> <div v-if="boxtype == 'newest'" class="box-newest-head flexacenter"> <img class="icon" src="/img/newest-icon.png" alt="" /> 最新 </div> <div v-else-if="boxtype == 'essence'" class="box-newest-head flexacenter"> <img class="icon" src="/img/essence.png" alt="" /> 精华阅读 </div> <div v-else class="slideshow-box"> <div class="tab-list flexacenter"> <div class="tab-item newest" :class="{'pitch': postsTab == 'newest'}" @click="tabPostsItem('newest')">最新 </div> <div class="tab-item essence" :class="{'pitch': postsTab == 'essence'}" @click="tabPostsItem('essence')">精华 </div> </div> </div> <div class="slideshow-content flexflex"> <!-- newest 最新 --> <div class="newest-side-box side-box"> <img class="bounding" src="/img/bounding-circle-green.svg" alt="" /> <div class="box"> <template v-for="(item, index) in latestList" :key="index"> <a v-if="item.title || item.content" class="item flexacenter vuehide" :href="'/details/' + item.uniqid" target="_blank"> <div class="dot dot-green"></div> <div class="text one-line-display">{{ item.title || item.content }}</div> </a> </template> </div> </div> <!-- essence 精选 --> <div class="essence-side-box side-box"> <img class="bounding" src="/img/bounding-circle-blue.svg" alt="" /> <div class="box"> <template v-for="(item, index) in topList" :key="index"> <a v-if="item.title || item.content" class="item flexacenter vuehide" :href="'/details/' + item.uniqid" target="_blank"> <div class="dot"></div> <div class="text one-line-display">{{ item.title || item.content }}</div> </a> </template> </div> </div> </div></div>`,
});

View File

@@ -701,6 +701,9 @@ body {
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.16862745);
flex-direction: column;
}
.item-box .bottom .bottom-item .share-box .share-item .QRcode-box.right {
left: -140px;
}
.item-box .bottom .bottom-item .share-box .share-item .QRcode-box .QRcode {
width: 100px;
height: 100px;
@@ -1681,7 +1684,6 @@ body {
line-height: 36px;
color: #333333;
font-size: 14px;
height: 32px;
line-height: 32px;
padding: 0 14px;
background-color: #f6f6f6;

View File

@@ -851,6 +851,10 @@ body {
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.16862745);
flex-direction: column;
&.right {
left: -140px;
}
.QRcode {
width: 100px;
height: 100px;
@@ -2024,7 +2028,6 @@ body {
line-height: 36px;
color: #333333;
font-size: 14px;
height: 32px;
line-height: 32px;
padding: 0 14px;
background-color: rgba(246, 246, 246, 1);

View File

@@ -17,7 +17,7 @@
<body>
<div class="container" id="details" v-cloak>
<div class="templateValue" ref="uniqidRef">i8aD88Xy1aK9</div>
<div class="templateValue" ref="uniqidRef">uzP1eSyPjvvD</div>
<div class="head-top flexacenter">
<img class="logo" src="https://oss.gter.net/logo" alt="" />

View File

@@ -171,10 +171,10 @@
<item-forum :itemdata="item" v-for="(item, index) in list" :key="index"></item-forum>
</div>
<div class="sidebar" :style="{'top': sidebarHeight + 'px'}" ref="sidebarRef">
<a class="adv" href="" target="_blank">
<a class="ad-item flexacenter" href="" target="_blank">
<img class="adv-icon" src="https://o.x-php.com/bbs/common/cf/1709075xdbbbvjd8cbxvdd.jpg" alt="26Fall祈福求offer得offer" />
</a>
<a class="adv" href="" target="_blank">
<a class="ad-item flexacenter" href="" target="_blank">
<img class="adv-icon" src="https://o.x-php.com/bbs/common/cf/1709075xdbbbvjd8cbxvdd.jpg" alt="26Fall祈福求offer得offer" />
</a>

View File

@@ -151,31 +151,6 @@ const appSectionIndex = createApp({
timestamp.value = strtimeago(targetInfo.release_at, 4);
updatedTime.value = targetInfo.updated_at ? strtimeago(targetInfo.updated_at, 4) : null;
// targetInfo.content = "[attach]976054[/attach]\n\n[attachimg]1008585[/attachimg]\n[attach]850105[/attach]";
// targetInfo.attachments = {
// images: [
// {
// aid: 1008585,
// url: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG_Y2l-U_pokcHeD1NFX9ddrB_WbUGy8P79gQxcXHOeQ4soV7NkzNDQyOQ~~",
// thumb: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG_Y2l-U_pokcHeD1NFX9ddrB_WbUWy8K_hyVFweFbPD7IZK4sVMAmnF5Vzp9Fkg0jQ0Mjk~",
// },
// ],
// files: [],
// videos: [
// {
// aid: 976054,
// posterurl: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG_Y2l-U_pokc36P1NFX9ddrB_WbUWy8K_hyVFweFrPD7IZK4sVMAm3Btwy-9Fkg0jQ0Mjk~",
// url: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-ZwscHvqqsgFptxhXa6RWi26P-BuTQFFE7SQttkb8LQ0NDI5",
// thumb: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-ZwscHvqqsgFptxhXa6QWi2uePJ5Bg8VFLPIqoYV7MtbCG2RtAz_-kVNNDQyOQ~~",
// },
// {
// aid: 850105,
// posterurl: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG_Y2l-U_pokc32G1NFX9ddrB_WbUWy8K_hyVFweFrPD7IZK4sVMA2eU5Vvl9Fkg0jQ0Mjk~",
// url: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-d-5otdXrqqsgFptxhXa6RWi26P-BuTQNAEuHBs9kb8LQ0NDI5",
// thumb: "https://o.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-d-5otdXrqqsgFptxhXa6QWi2uePJ5Bg8VFLPIqoYV7MsICzzBsFj_-kVNNDQyOQ~~",
// },
// ],
// };
if (targetInfo.content) targetInfo.content = restoreHtml(targetInfo.content, targetInfo.attachments);
info.value = targetInfo;
@@ -213,7 +188,7 @@ const appSectionIndex = createApp({
html = html.replace(/\[tag\]([^[]+)\[\/tag\]/gi, '<a class="blue" href="/tag/$1" target="_blank">#$1</a> <span class="fill"></span> ');
// 4. 还原粗体标记为h2标签
html = html.replace(/\[b\]([^[]+)\[\/b\]/gi, "<h2>$1</h2>");
html = html.replace(/\[b\]([\s\S]*?)\[\/b\]/gi, "<h2>$1</h2>");
// 5. 统一在单次遍历中按出现顺序替换 attach/attachimg
const byAid = new Map();

View File

@@ -160,7 +160,7 @@ const editApp = createApp({
html = html.replace(/\[tag\]([^[]+)\[\/tag\]/gi, '<span class="blue">#$1</span> <span class="fill"></span> ');
// 4. 还原粗体标记为h2标签
html = html.replace(/\[b\]([^[]+)\[\/b\]/gi, "<h2>$1</h2>");
html = html.replace(/\[b\]([\s\S]*?)\[\/b\]/gi, "<h2>$1</h2>");
// 5. 还原图片标记为img标签使用提供的imageList
html = html.replace(/\[attachimg\](\d+)\[\/attachimg\]/gi, (match, aid) => {
@@ -699,39 +699,50 @@ const editApp = createApp({
video.src = "";
};
video.addEventListener("error", () => {
cleanup();
reject(new Error("视频加载失败,请检查文件完整性"));
}, { once: true });
video.addEventListener(
"error",
() => {
cleanup();
reject(new Error("视频加载失败,请检查文件完整性"));
},
{ once: true }
);
video.addEventListener("loadeddata", () => {
const canvas = document.createElement("canvas");
const w = video.videoWidth || 320;
const h = video.videoHeight || 240;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
try {
ctx.drawImage(video, 0, 0, w, h);
} catch (e) {
cleanup();
reject(e);
return;
}
canvas.toBlob((blob) => {
cleanup();
if (!blob) {
reject(new Error("第一帧提取失败Blob 生成异常"));
video.addEventListener(
"loadeddata",
() => {
const canvas = document.createElement("canvas");
const w = video.videoWidth || 320;
const h = video.videoHeight || 240;
canvas.width = w;
canvas.height = h;
const ctx = canvas.getContext("2d");
try {
ctx.drawImage(video, 0, 0, w, h);
} catch (e) {
cleanup();
reject(e);
return;
}
const frameFile = new File([blob], `video_cover_${Date.now()}.png`, { type: "image/png" });
resolve(frameFile);
}, "image/png", 0.9);
}, { once: true });
canvas.toBlob(
(blob) => {
cleanup();
if (!blob) {
reject(new Error("第一帧提取失败Blob 生成异常"));
return;
}
const frameFile = new File([blob], `video_cover_${Date.now()}.png`, { type: "image/png" });
resolve(frameFile);
},
"image/png",
0.9
);
},
{ once: true }
);
});
};
const linkClick = () => {};
return { linkClick, insertVideo, insertLink, linkUrl, linkText, linkState, openLink, closeLink, handleClick, uniqid, userInfoWin, titleLength, submit, emojiState, openEmoji, closeEmoji, selectEmoji, optionEmoji, isPTitle, onEditorInput, onEditorFocus, onEditorBlur, paragraphTitle, info, tagList, token, cutAnonymity, editorRef, insertImage, judgeIsEmpty, isEmpty };

View File

@@ -2,13 +2,14 @@ const { createApp, ref, onMounted, nextTick, onUnmounted, computed, watch, provi
import { headTop } from "../component/head-top/head-top.js";
import { itemForum } from "../component/item-forum/item-forum.js";
import { latestList } from "../component/latest-list/latest-list.js";
import { loadBox } from "../component/load-box/load-box.js";
const appIndex = createApp({
setup() {
onMounted(() => getUserInfoWin());
let isLogin = ref(true);
let realname = ref(1); // 是否已经实名
let isLogin = ref(false);
let realname = ref(0); // 是否已经实名
let userInfoWin = ref({});
const getUserInfoWin = () => {
@@ -48,53 +49,7 @@ const appIndex = createApp({
provide("openAttest", openAttest);
provide("goLogin", goLogin);
let pastList = ref([
{
comments: 24,
created_at: "2025-04-14 16:08:52",
description: "''",
status: 0,
title: "25年4月美国无预警大量撤销留学生签证撤销原因是哪些我们的一些相关建议",
topicid: 253942,
uniqid: "uDqLzLTbK4Of",
},
{
comments: 24,
created_at: "2025-04-14 16:08:52",
description: "''",
status: 0,
title: "25年4月美国无预警大量撤销留学生签证撤销原因是哪些我们的一些相关建议",
topicid: 253942,
uniqid: "uDqLzLTbK4Of",
},
{
comments: 24,
created_at: "2025-04-14 16:08:52",
description: "''",
status: 0,
title: "25年4月美国无预警大量撤销留学生签证撤销原因是哪些我们的一些相关建议",
topicid: 253942,
uniqid: "uDqLzLTbK4Of",
},
{
comments: 24,
created_at: "2025-04-14 16:08:52",
description: "''",
status: 0,
title: "25年4月美国无预警大量撤销留学生签证撤销原因是哪些我们的一些相关建议",
topicid: 253942,
uniqid: "uDqLzLTbK4Of",
},
{
comments: 24,
created_at: "2025-04-14 16:08:52",
description: "''",
status: 0,
title: "25年4月美国无预警大量撤销留学生签证撤销原因是哪些我们的一些相关建议",
topicid: 253942,
uniqid: "uDqLzLTbK4Of",
},
]);
let pastList = ref([]);
onMounted(() => {
offerListScrolling();
@@ -107,10 +62,6 @@ const appIndex = createApp({
getTalkingRecommend();
getTopicHandpicked();
getTopicLatest();
setTimeout(() => {
BiComponent.initComponent('unlock');
}, 1000);
});
let ongoingbj = ref({}); // 话题数据
@@ -156,19 +107,28 @@ const appIndex = createApp({
offer.value = data.offer;
vote.value = data.vote;
interviewexperience.value = data.interviewexperience;
nextTick(() => {});
});
};
const sidebarFixed = ref(false);
const handleScroll = () => {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const scrollHeight = document.documentElement.scrollHeight;
const clientHeight = document.documentElement.clientHeight;
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
const clientHeight = window.innerHeight;
// 列表下 滑动到底部 获取新数据
if (scrollTop + clientHeight >= scrollHeight - 40) getList();
if (scrollTop + clientHeight >= scrollHeight - 200) getList();
// // 侧边栏滚动固定
// if (scrollTop >= matterRef.value.offsetTop + sidebarRef.value.offsetHeight - clientHeight) sidebarFixed.value = true;
// else sidebarFixed.value = false;
sidebarHeight.value = -(sidebarRef.value.offsetHeight - window.innerHeight);
if (sidebarHeight.value > 0) sidebarHeight.value = 12;
};
let offerlist = ref([]); // offer 列表滚动 数据
@@ -195,14 +155,20 @@ const appIndex = createApp({
let offerTimer = null;
let scrollup = null;
// offer list 滚动
const autoOfferListScroll = () => {
console.log("autoOfferListScroll");
if (typeof ScrollText !== "function") {
setTimeout(() => autoOfferListScroll(), 500);
return;
}
var scrollup = new ScrollText("offer-box");
scrollup.LineHeight = 56.5;
console.log("scrollup");
if (scrollup) return;
scrollup = new ScrollText("offer-box");
scrollup.LineHeight = 55;
scrollup.Amount = 1;
scrollup.Delay = 1;
scrollup.Start();
@@ -266,44 +232,40 @@ const appIndex = createApp({
return Object.values(groups);
};
let loading = false;
let loading = ref(false);
let page = ref(1);
let list = ref([]);
const getList = () => {
if (loading || page.value == 0) return;
loading = true;
// wx.showLoading();
if (loading.value || page.value == 0) return;
loading.value = true;
ajaxGet(`/v2/api/forum/topicLists?type=thread&page=${page.value || 1}`)
.then((res) => {
// wx.hideLoading();
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;
loading = false;
loading.value = false;
})
.catch((err) => {
// wx.hideLoading();
err = err.data;
if (err.code == 401) goLogin();
loading = false;
loading.value = false;
});
};
const clickbtn = () => {
BiComponent.initComponent();
};
const sidebarRef = ref(null);
const matterRef = ref(null);
let sidebarHeight = ref(0);
return { sidebarRef, sidebarHeight, clickbtn, interviewexperience, vote, offer, topicHandpickedList, list, sectionList, popList, custom_2AdvRef, ongoingbj, pastList, offerMouseover, offerMouseout, offerlist, offerListRef };
return { sidebarHeight, matterRef, sidebarFixed, sidebarRef, loading, interviewexperience, vote, offer, topicHandpickedList, list, sectionList, popList, custom_2AdvRef, ongoingbj, pastList, offerMouseover, offerMouseout, offerlist, offerListRef };
},
});
appIndex.component("headTop", headTop);
appIndex.component("itemForum", itemForum);
appIndex.component("latestList", latestList);
appIndex.component("load-box", loadBox);
appIndex.mount("#appIndex");

View File

@@ -1,9 +1,11 @@
const forumBaseURL = "https://api.gter.net";
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
// 导出ajax函数
const ajax = (url, data) => {
if (location.hostname == "127.0.0.1") axios.defaults.headers.common["Authorization"] = "erhvky91rk23vx7xiutj34db82kjb1vc";
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
url = url.indexOf("https://") > -1 ? url : forumBaseURL + url;
return new Promise(function (resolve, reject) {
@@ -17,26 +19,51 @@ const ajax = (url, data) => {
if (data.code == 401) {
// 需要登录
showWindow("login", "https://passport.gter.net/login/ajax", "get", -1, {
cover: true,
});
go_ajax_Login();
reject();
}
resolve(data);
})
.catch((err) => {
reject();
if (err.response?.status == 401)
showWindow("login", "https://passport.gter.net/login/ajax", "get", -1, {
cover: true,
});
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) {
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) => {
if (location.hostname == "127.0.0.1") axios.defaults.headers.common["Authorization"] = "erhvky91rk23vx7xiutj34db82kjb1vc";
axios.defaults.withCredentials = true;
axios.defaults.emulateJSON = true;
url = url.indexOf("https://") > -1 ? url : forumBaseURL + url;
return new Promise(function (resolve, reject) {
@@ -53,9 +80,7 @@ const ajaxGet = (url) => {
var data = typeof res.data == "string" ? JSON.parse(res.data) : res.data;
if (data.code == 401) {
// 需要登录
showWindow("login", "https://passport.gter.net/login/ajax", "get", -1, {
cover: true,
});
go_ajax_Login();
reject();
}
resolve(data);
@@ -153,61 +178,6 @@ const timeago = (dateTimeStamp, type = 1) => {
return result;
};
const creationAlertBox = (type = "success", text) => {
if (!text) return;
const pathObj = {
success: `<path fill="currentColor" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-55.808 536.384-99.52-99.584a38.4 38.4 0 1 0-54.336 54.336l126.72 126.72a38.272 38.272 0 0 0 54.336 0l262.4-262.464a38.4 38.4 0 1 0-54.272-54.336L456.192 600.384z"></path>`,
error: `<path fill="currentColor" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm0 393.664L407.936 353.6a38.4 38.4 0 1 0-54.336 54.336L457.664 512 353.6 616.064a38.4 38.4 0 1 0 54.336 54.336L512 566.336 616.064 670.4a38.4 38.4 0 1 0 54.336-54.336L566.336 512 670.4 407.936a38.4 38.4 0 1 0-54.336-54.336L512 457.664z"></path>`,
};
const colorObj = {
success: {
border: "#e1f3d8",
color: "#67c23a",
background: "#f0f9eb",
},
error: {
border: "#fde2e2",
color: "#f56c6c",
background: "#fef0f0",
},
};
if (!pathObj[type]) type = "success"; // 判断存不存在 给个默认值
const box = document.createElement("div");
box.style.position = "fixed";
box.style.zIndex = "10003";
box.style.top = "-51px";
box.style.left = "50%";
box.style.border = `${colorObj[type].border} 1px solid`;
box.style.color = colorObj[type].color;
box.style.background = colorObj[type].background;
box.style.display = "flex";
box.style.alignItems = "center";
box.style.fontSize = "14px";
box.style.padding = "15px 19px";
box.style.borderRadius = "4px";
box.style.transition = "0.5s";
box.style.transform = "translateX(-50%)";
const svg = `<svg style="width: 16px;height: 16px;margin-right: 10px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">${pathObj[type]}</svg>`;
box.innerHTML = `${svg}${text || "默认提示文本"}`;
document.body.appendChild(box);
setTimeout(() => {
box.style.top = 20 + "px";
setTimeout(() => {
box.style.top = -51 + "px";
setTimeout(() => {
box.remove();
}, 2000);
}, 2000);
}, 1);
};
const managerHide = (token, state, type = "offer") => {
return new Promise((resolve, reject) => {
const obj = {
@@ -277,6 +247,24 @@ const managerEssence = (token, state) => {
});
};
// 删除
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);
@@ -317,25 +305,27 @@ const updateUrlParams = (params, replace = false) => {
};
// 跳转 url
const redirectToExternalWebsite = (url) => {
const redirectToExternalWebsite = (url, target = "_blank") => {
const link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.target = target;
link.click();
};
// 点击ta的主页
const goHomePage = (uin) => {
redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&uid=${uin}`);
const goHomePage = (token) => {
if (!token) return;
redirectToExternalWebsite(`/u/${token}`);
};
// 点击发送信息
const goSendMessage = (uin) => {
if (uin && typeof messagePrivateItem == "function") {
messagePrivateItem({ uin: uin });
const goSendMessage = (token) => {
if (typeof messagePrivateItem == "function") {
messagePrivateItem({ token });
return;
}
redirectToExternalWebsite(`https://bbs.gter.net/home.php?mod=space&showmsg=1&uid=${uin}`);
goHomePage(token);
};
const lang = {
@@ -363,14 +353,14 @@ const lang = {
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 copyUid = (text) => {
let copyForumUid = (text) => {
if (navigator.clipboard)
copyUid = () => {
copyForumUid = () => {
navigator.clipboard.writeText(text);
creationAlertBox("success", "复制成功");
};
else {
copyUid = () => {
copyForumUid = () => {
var tempInput = document.createElement("input");
tempInput.value = text;
document.body.appendChild(tempInput);
@@ -380,5 +370,33 @@ let copyUid = (text) => {
creationAlertBox("success", "复制成功");
};
}
copyUid();
copyForumUid();
};
const updateUrlLastPath = (newLastPath, isReplace = false) => {
const raw = typeof newLastPath === "string" ? newLastPath : String(newLastPath);
const basePath = raw.split("?")[0];
const newPathname = basePath.startsWith("/") ? basePath : "/" + basePath;
const newSearch = window.location.search;
const newUrl = window.location.origin + newPathname + newSearch;
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 = () => {
console.log("go_ajax_Login");
if (typeof ajax_login === "function") ajax_login();
else window.open("https://passport.gter.net/?referer=" + escape(location.href), "_self");
};