- 添加默认头像图片资源 - 扩展监听文件同步配置 - 重构头像展示样式,增加背景和尺寸控制 - 完善签到功能逻辑和样式交互 - 新增头部组件HTML模板和JS实现 - 调整搜索框和历史记录显示逻辑 - 优化页面布局和响应式设计
152 lines
8.4 KiB
JavaScript
152 lines
8.4 KiB
JavaScript
// my-component.js
|
||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||
const { defineComponent, ref, onMounted, onUnmounted, nextTick } = Vue;
|
||
|
||
// 定义组件(直接使用模板)
|
||
export const headTop = defineComponent({
|
||
name: "headTop",
|
||
props: {
|
||
page: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
},
|
||
|
||
setup(props) {
|
||
// 轮播相关状态
|
||
let currentIndex = ref(0); // 当前显示的关键词索引
|
||
let carouselTimer = ref(null); // 轮播定时器
|
||
let isPaused = ref(false); // 是否暂停轮播
|
||
|
||
onMounted(() => {
|
||
getHistorySearch();
|
||
// 写一个函数 ,判断本地缓存有没有 wConfig 并判断 是否过一天 如果过了一天 则更新 wConfig
|
||
checkWConfig();
|
||
|
||
// 启动轮播
|
||
startCarousel();
|
||
});
|
||
|
||
// 启动轮播函数
|
||
const startCarousel = () => {
|
||
// 清除已有的定时器
|
||
if (carouselTimer.value) {
|
||
clearInterval(carouselTimer.value);
|
||
}
|
||
|
||
// 设置新的定时器,每秒滚动一次
|
||
carouselTimer.value = setInterval(() => {
|
||
if (!searchInputState.value && hotSearchWords.value.length > 1) {
|
||
if (currentIndex.value >= hotSearchWords.value.length - 1) {
|
||
currentIndex.value++;
|
||
setTimeout(() => {
|
||
if (!searchInputState.value) currentIndex.value = 0;
|
||
}, 2300);
|
||
} else currentIndex.value++;
|
||
}
|
||
}, 2300);
|
||
};
|
||
|
||
// 暂停轮播
|
||
const pauseCarousel = () => {
|
||
isPaused.value = true;
|
||
};
|
||
|
||
// 恢复轮播
|
||
const resumeCarousel = () => {
|
||
isPaused.value = false;
|
||
};
|
||
|
||
let hotSearchWords = 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();
|
||
else {
|
||
hotSearchWords.value = wConfig.hotSearchWords || [];
|
||
}
|
||
} else {
|
||
getWConfig();
|
||
}
|
||
};
|
||
|
||
const getWConfig = () => {
|
||
ajaxGet("/v2/api/config/website").then((res) => {
|
||
if (res.code == 200) {
|
||
let data = res["data"] || {};
|
||
hotSearchWords.value = data.hotSearchWords || {};
|
||
data.time = new Date().toISOString();
|
||
localStorage.setItem("wConfig", JSON.stringify(data));
|
||
}
|
||
});
|
||
};
|
||
|
||
let state = ref(0); // 是否已经签到
|
||
|
||
let userInfoWinTimerCount = 0;
|
||
const userInfoWinTimer = setInterval(() => {
|
||
if (location.host == "127.0.0.1:5501") return;
|
||
if (todaysignedState) {
|
||
state.value = todaysigned;
|
||
clearInterval(userInfoWinTimer);
|
||
}
|
||
userInfoWinTimerCount++;
|
||
if (userInfoWinTimerCount >= 3000) clearInterval(userInfoWinTimer);
|
||
}, 50);
|
||
|
||
const signIn = () => {
|
||
SignInComponent.initComponent();
|
||
};
|
||
|
||
let pitchState = ref(false);
|
||
|
||
let page = ref(props.page);
|
||
|
||
console.log("page", page.value, props.page);
|
||
|
||
let input = ref("");
|
||
|
||
let historySearchList = ref([]); // 历史搜索数据
|
||
// 获取历史搜索
|
||
const getHistorySearch = () => {
|
||
const data = JSON.parse(localStorage.getItem("history-search")) || [];
|
||
historySearchList.value = data;
|
||
};
|
||
|
||
// 跳转搜索
|
||
const searchEvent = (value) => {
|
||
const kw = value || input.value || hotSearchWords.value[currentIndex.value]?.keyword || "";
|
||
if (!kw) return;
|
||
historySearchList.value.unshift(kw);
|
||
historySearchList.value = [...new Set(historySearchList.value)];
|
||
if (historySearchList.value.length > 10) historySearchList.value = historySearchList.value.splice(0, 10);
|
||
localStorage.setItem("history-search", JSON.stringify(historySearchList.value));
|
||
|
||
redirectToExternalWebsite("/search/" + kw);
|
||
searchInputBlur();
|
||
};
|
||
|
||
let searchHistoryShowState = ref(false); // 历史记录的展开状态
|
||
let searchInputState = ref(false); // 搜索框的状态
|
||
// 切换历史记录展示状态
|
||
const searchInputFocus = () => {
|
||
searchInputState.value = true;
|
||
if (historySearchList.value.length == 0) return;
|
||
searchHistoryShowState.value = true;
|
||
};
|
||
const searchInputBlur = () => {
|
||
setTimeout(() => {
|
||
searchInputState.value = false;
|
||
searchHistoryShowState.value = false;
|
||
}, 200);
|
||
};
|
||
|
||
return { hotSearchWords, historySearchList, searchEvent, searchInputState, searchHistoryShowState, searchInputFocus, searchInputBlur, page, pitchState, state, signIn, input, currentIndex, pauseCarousel, resumeCarousel };
|
||
},
|
||
|
||
template: `<div class="head-top flexacenter"> <a href="/" class="flexacenter" target="_blank"> <img class="logo" src="https://oss.gter.net/logo" alt="" /> </a> <div class="flex1"></div> <div class="input-box flexacenter" :class="{'pitch': searchInputState}"> <div class="placeholder" v-if="!searchInputState && !input"> <div class="placeholder-box" :style="{transform: 'translateY(-' + currentIndex * 36 + 'px)', transition: 'transform .3s ease'}"> <div class="item one-line-display" v-for="(item,index) in hotSearchWords" :key="index">大家都在搜:{{ item.keyword }}</div> <div class="item one-line-display" v-for="(item,index) in hotSearchWords.slice(0, 2)" :key="'copy-' + index">大家都在搜:{{ item.keyword }}</div> </div> </div> <input class="input flex1" type="text" @keyup.enter="searchEvent()" v-model="input" @focus="searchInputFocus" @blur="searchInputBlur" maxlength="140" /> <img class="icon" src="/img/search-icon.svg" @click="searchEvent()" /> <div class="search-box-history" v-if="searchHistoryShowState"> <div class="search-box-history-title">历史搜索</div> <div class="search-box-history-list"> <div class="search-box-history-item one-line-display" v-for="(item,index) in historySearchList " :key="index" @click="searchEvent(item)">{{ item }}</div> </div> </div> </div> <div class="post-list flexacenter" v-if="page == 'details'"><a href="/publish" target="_blank" style="margin-right: 10px"> <img class="post-item" src="/img/post-thread.png" /> </a> <a href="https://offer.gter.net/post" target="_blank" style="margin-right: 10px"> <img class="post-item" src="/img/post-offer.png" /> </a> <a href="https://offer.gter.net/post/summary" target="_blank" style="margin-right: 10px"> <img class="post-item" src="/img/post-summary.png" /> </a> <a href="https://interviewexperience.gter.net/publish" target="_blank" style="margin-right: 10px"> <img class="post-item" src="/img/post-mj.png" /> </a> <a href="https://vote.gter.net/publish" target="_blank" style="margin-right: 10px"> <img class="post-item" src="/img/post-vote.png" /> </a> </div> <template v-else> <div class="sign-in flexacenter" :class="{'sign-in-already': state == 1, 'sign-in-no': state == 0}" @click="signIn()" v-cloak> <div class="sign-in-no-box"> <img class="sign-in-bj" src="/img/sign-in-bj.svg" /> <img class="coin-bj" src="/img/coin-bj.svg" /> <img class="coin-icon" src="/img/coin-icon.png" /> <span class="text flex1">签到领寄托币</span> <div class="sign-go flexcenter"> <img class="sign-go-bj" src="/img/sign-go.svg" /> GO </div> <img class="petal1" src="/img/petal1.png" /> <img class="petal2" src="/img/petal2.png" /> <img class="petal3" src="/img/petal3.png" /> </div> <div class="sign-in-already-box"> <img class="sign-icon" src="/img/sign-icon.png" /> <span>已签到,明天再来</span> </div> </div> </template></div>`,
|
||
});
|