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:
@@ -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,
|
||||
|
||||
@@ -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>`,
|
||||
});
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>`,
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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="" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
27
js/edit.js
27
js/edit.js
@@ -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,12 +699,18 @@ const editApp = createApp({
|
||||
video.src = "";
|
||||
};
|
||||
|
||||
video.addEventListener("error", () => {
|
||||
video.addEventListener(
|
||||
"error",
|
||||
() => {
|
||||
cleanup();
|
||||
reject(new Error("视频加载失败,请检查文件完整性"));
|
||||
}, { once: true });
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
|
||||
video.addEventListener("loadeddata", () => {
|
||||
video.addEventListener(
|
||||
"loadeddata",
|
||||
() => {
|
||||
const canvas = document.createElement("canvas");
|
||||
const w = video.videoWidth || 320;
|
||||
const h = video.videoHeight || 240;
|
||||
@@ -718,7 +724,8 @@ const editApp = createApp({
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
canvas.toBlob((blob) => {
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
cleanup();
|
||||
if (!blob) {
|
||||
reject(new Error("第一帧提取失败,Blob 生成异常"));
|
||||
@@ -726,12 +733,16 @@ const editApp = createApp({
|
||||
}
|
||||
const frameFile = new File([blob], `video_cover_${Date.now()}.png`, { type: "image/png" });
|
||||
resolve(frameFile);
|
||||
}, "image/png", 0.9);
|
||||
}, { once: true });
|
||||
},
|
||||
"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 };
|
||||
|
||||
106
js/index.js
106
js/index.js
@@ -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");
|
||||
|
||||
174
js/public.js
174
js/public.js
@@ -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,
|
||||
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");
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user