重构编辑器工具栏样式及功能,使用wangEditor替换原有实现 优化图片和视频上传逻辑,增加自定义校验和上传处理 调整编辑器样式,修复对齐功能及段落标题样式 更新表情选择器位置逻辑,支持上下方向显示 统一组件导入方式,添加版本控制参数防止缓存
92 lines
7.5 KiB
JavaScript
92 lines
7.5 KiB
JavaScript
// my-component.js
|
||
// 引入全局 Vue 对象(因在 HTML 中通过 script 引入,Vue 已挂载到 window)
|
||
const { defineComponent, ref, onMounted, nextTick } = Vue;
|
||
|
||
// 定义组件(直接使用模板)
|
||
export const slideshowBox = defineComponent({
|
||
name: "slideshowBox",
|
||
props: {
|
||
itemdata: {
|
||
type: Object,
|
||
default: () => {},
|
||
},
|
||
},
|
||
|
||
setup(props) {
|
||
let item = ref({ ...props.itemdata });
|
||
|
||
onMounted(() => getTopicLatest());
|
||
|
||
let tabPitch = ref(""); // thread offer vote interviewexperience
|
||
|
||
let latestList = ref({});
|
||
const getTopicLatest = () => {
|
||
ajaxGet(`/v2/api/forum/getTopicLatest?limit=4`).then((res) => {
|
||
const data = res.data || [];
|
||
(data.vote || []).forEach((item) => {
|
||
if (!item.title) {
|
||
// item.title = item.content;
|
||
// item.content = "";
|
||
}
|
||
});
|
||
|
||
latestList.value = data;
|
||
|
||
nextTick(() => {
|
||
tabItem(tabArr[Math.floor(Math.random() * tabArr.length)]);
|
||
});
|
||
});
|
||
};
|
||
|
||
const tabArr = ["offer", "vote", "interviewexperience"];
|
||
// const tabArr = ["thread", "offer", "vote", "interviewexperience"];
|
||
|
||
const tabItem = (key) => {
|
||
if (key == tabPitch.value) return;
|
||
|
||
const boxbox = document.querySelector(`.box-box`);
|
||
boxbox.classList.add(`box-${key}`);
|
||
let index = tabArr.indexOf(key);
|
||
|
||
// 修改 tab 状态的
|
||
if (tabPitch.value) {
|
||
let oldNode = boxbox.querySelector(`.slideshow-box .tab-item.${tabPitch.value}`);
|
||
oldNode.classList.toggle("pitch");
|
||
boxbox.classList.remove(`box-${tabPitch.value}`);
|
||
}
|
||
|
||
let targetTabNode = boxbox.querySelector(`.slideshow-box .tab-item.${key}`);
|
||
|
||
targetTabNode.classList.toggle("pitch");
|
||
let targetHeight = targetTabNode.offsetHeight;
|
||
|
||
// 修改全局背景状态的
|
||
let targetContentNode = boxbox.querySelector(`.slideshow-content .${key}-side-box`);
|
||
let targetContentHeight = targetContentNode.offsetHeight;
|
||
console.log("targetContentHeight", targetContentHeight);
|
||
|
||
boxbox.style.height = targetContentHeight + 66 + "px";
|
||
|
||
let slideshowContent = boxbox.querySelector(".slideshow-content");
|
||
|
||
slideshowContent.scrollTo({
|
||
left: 272 * index,
|
||
behavior: "smooth",
|
||
});
|
||
|
||
tabPitch.value = key;
|
||
};
|
||
|
||
const handleCheckAttest = (e) => {
|
||
if (realname.value === 0 && userInfoWin.value?.uin > 0) {
|
||
openAttest();
|
||
e.preventDefault(); // 阻止默认跳转(即使 href 为链接,也强制拦截)
|
||
}
|
||
};
|
||
|
||
return { handleCheckAttest, tabItem, tabPitch, tabPitch, latestList };
|
||
},
|
||
|
||
template: `<div class="box-box" :class="['box-' + tabPitch]"> <div class="slideshow-box"> <div class="tab-list flexacenter"> <!-- <div class="tab-item thread" :class="{'pitch': tabPitch == 'thread'}" @click="tabItem('thread')">帖子</div> --> <div class="tab-item offer" :class="{'pitch': tabPitch == 'offer'}" @click="tabItem('offer')">Offer</div> <div class="tab-item vote" :class="{'pitch': tabPitch == 'vote'}" @click="tabItem('vote')">投票</div> <div class="tab-item interviewexperience" :class="{'pitch': tabPitch == 'interviewexperience'}" @click="tabItem('interviewexperience')">面经</div> </div> </div> <div class="slideshow-content flexflex"> <!-- 问答 --> <!-- <div class="thread-side-box side-box"> <div class="box"> <a v-for="item in latestList.thread" :key="item.uniqid" class="item" target="_blank" :href="'/details/' + item.uniqid"> <div class="question flexacenter"> <div class="text flex1 ellipsis">{{ item.title }}</div> </div> <div class="answer flexacenter"> <div class="text flex1"> <div class="texttext">{{ item.content }}</div> </div> </div> </a> <a class="add-btn flexcenter" href="https://ask.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> --> <!-- offer --> <div class="offer-side-box side-box"> <div class="box"> <a v-for="item in latestList.offer" :key="item.uniqid" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <img class="school-img" :src="item.data.schoollogo" /> <div class="school-detail flex1 flexflex"> <div class="school-name one-line-display">{{ item.data.schoolname }}</div> <div class="school-brief one-line-display">{{ item.data.professional }}</div> <div class="school-offer flexacenter"> <span>{{ item.data.degree }}</span> <span class="long-string">|</span> <span>{{ item.data.semester }}</span> <span class="long-string">|</span> <span>{{ item.data.apply_results_text }}</span> </div> </div> </a> <a class="add-btn flexcenter" href="https://offer.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- 投票 --> <div class="vote-side-box side-box"> <div class="box"> <a v-for="item in latestList.vote" :key="item.uniqid" class="item flexflex vuehide" target="_blank" :href="'/details/' + item.uniqid"> <div class="name one-line-display">{{ item.title }}</div> <div class="brief">{{ item.content }}</div> </a> <a class="add-btn flexcenter" href="https://vote.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> <!-- mj --> <div class="interviewexperience-side-box side-box"> <div class="box"> <a v-for="item in latestList.interviewexperience" :key="item.thread_id" class="item flexflex" :href="'/details/' + item.uniqid" target="_blank"> <div class="school one-line-display">{{ item.data.schoolname }}</div> <div class="major one-line-display">{{ item.data.project }}</div> <div class="info"> <img class="icon" :src="item.user.avatar" /> <span class="text">{{ item.title || item.content }} </span> </div> </a> <a class="add-btn flexcenter" href="https://interviewexperience.gter.net" target="_blank"> <div>more</div> <img class="" style="margin-left: 8px;" src="/img/right-arrow-black.svg"> </a> </div> </div> </div></div>`,
|
||
});
|