Files
PCAdmissionOfficer/H5/h5.html
DESKTOP-RQ919RC\Pc d638dade41 no message
2025-07-18 18:56:24 +08:00

474 lines
24 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="divport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./h5.css" />
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<script>
(function (window, document) {
var sizeUI = 750; // 定义设计图尺寸
var remBase = 75; // 定义基准值
var docEl = document.documentElement;
var bodyEl = document.querySelector("body");
setRemUnit();
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", function (e) {
if (e.persisted) setRemUnit();
});
function setRemUnit() {
var docFontSize = (docEl.clientWidth / sizeUI) * remBase;
docEl.style.fontSize = docFontSize + "px";
bodyEl.style.fontSize = 16 / docFontSize + "rem";
handleRemAdapt();
}
function handleRemAdapt() {
var currentFontSize = parseInt(docEl.style.fontSize);
var temp = currentFontSize;
for (var i = 0; i < 100; i++) {
var realFontSize = parseInt(window.getComputedStyle(docEl).fontSize);
var differ = realFontSize - currentFontSize;
if (Math.abs(differ) >= 1) {
if (differ > 0) temp--;
else temp++;
docEl.style.fontSize = temp + "px";
} else {
break;
}
}
}
})(window, document);
</script>
<div id="admission-officer" class="admission-officer" v-cloak class="container">
<div class="header-box">
<img class="header-bj" src="https://app.gter.net/image/miniApp/offer/admission-bj-blue.svg" />
<img class="bj-green" src="https://app.gter.net/image/miniApp/offer/admission-bj-green.svg" />
<img class="header-img" src="https://app.gter.net/image/miniApp/offer/admission-text.png" />
</div>
<div class="interview-box" v-if="interviewData" @click="getVideoUrl(interviewData.token)">
<div class="head">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/interview-icon.png" />
<img class="name" src="https://app.gter.net/image/miniApp/offer/interview-name.png" />
<img class="head-bj" src="https://app.gter.net/image/miniApp/offer/interview-other.svg" />
</div>
<img class="ok" src="https://app.gter.net/image/miniApp/offer/duck-ok.png" />
<img class="img" :src="interviewData.video_cover" />
<img class="play" src="https://app.gter.net/image/miniApp/offer/play-btn.svg" />
<div class="bottom">
<div class="title one-line-display">{{ interviewData.title }}</div>
<div class="subtitle one-line-display">{{ interviewData.subtitle }}</div>
</div>
</div>
<div class="interview-list" scroll-x v-if="interviewList.length > 0">
<div class="item" v-for="(item,index) in interviewList" :key="index" @click="getVideoUrl(item.token)">
<img class="img" :src="item.video_cover" />
<div class="title one-line-display">{{ item.title }}</div>
<div class="subtitle one-line-display">{{ item.subtitle }}</div>
</div>
</div>
<div class="preach-box" ref="swiperBox" v-if="preachList.length != 0" @touchstart="handleTouchStart" @touchend="handleTouchEnd">
<div class="head">
<img class="icon" src="https://app.gter.net/image/miniApp/offer/preach-icon.png" />
<img class="name" src="https://app.gter.net/image/miniApp/offer/preach-name.png" />
<img class="head-bj" src="https://app.gter.net/image/miniApp/offer/preach-other.svg" />
</div>
<div class="swiper flexflex" ref="swiperBoxSwiper" :style="{'height': preachList[0].length >= 3 ? '4.08rem' : preachList[0].length * 1.36 + 'rem'}">
<div class="swiper-item" v-for="(item,index) in preachList" :key="index">
<a class="item" v-for="(it,index) in item" :key="index" :href="it.link_url" target="_blank">
<div class="title flexacenter">
<div class="one-line-display text">{{ it.title }}</div>
<img class="arrow" src="https://app.gter.net/image/miniApp/offer/arrow-return.svg" />
</div>
<div class="time one-line-display">{{ it.lecture_time || '长期答疑' }}</div>
</a>
</div>
</div>
<div class="indicator flexcenter" v-if="preachList.length > 1">
<div class="item" :class="{'pitch': swiperCurrent == index}" v-for="(item,index) in preachList" :key="index"></div>
</div>
</div>
<div class="list" v-if="admissionList.length != 0">
<div class="item" v-for="(item,index) in admissionList" :key="item.id">
<div class="header">
<div class="abbreviation">
<img class="school-other" src="https://app.gter.net/image/miniApp/offer/school-other.svg" />
<div class="text" :style="{backgroundColor: item.color }">{{ item.abbreviation }}</div>
</div>
<img class="img" :src="item.banner" />
<div class="header-content flexacenter">
<img class="school-img" :src="item.logo" />
<div class="flex1">
<div class="school-name">
{{ item.name }}
<img class="arrow" src="https://app.gter.net/image/miniApp/offer/arrow-return.svg" />
</div>
<div class="school-english">{{ item.enname }}</div>
</div>
</div>
</div>
<div class="introduction">{{ item.introduction }}</div>
<div class="year flexacenter">
<div class="year-item flexcenter" v-for="(it,i) in item.yList" :key="i" :class="{'pitch': item.pitch == it}" :style="{backgroundColor: item.pitch == it ? item.color : '' }" @click.stop="cutSchoolYear(index,it)">{{ it }}季</div>
<div class="year-item more flexcenter" :class="[{'unfold': item.state,'pitch': item.isPitchMore}]" :style="{backgroundColor: item.state || item.isPitchMore ? item.color : '' }" @click="openSchoolYearState(index)" v-if="item.yListMore.length > 0">
<text>{{ item.isPitchMore ? item.pitch + '季' : '更多' }}</text>
<div class="triangle"></div>
<div class="more-mask" @click.stop="closeSchoolYearState(index)"></div>
<div class="more-box" :style="{backgroundColor: item.color }">
<div class="more-item" v-for="(it,i) in item.yListMore" :key="i" @click.stop="selectSchoolYearState(index,it)">{{ it }}季</div>
</div>
</div>
</div>
<div class="title-box">
<div class="title-item flexcenter" v-for="(it,index) in item.list[item.pitch]" :key="index">
<div class="name flexflex">
<div class="icon flexcenter">
<img class="img" src="https://app.gter.net/image/miniApp/offer/course-icon.png" />
</div>
<div class="text flex1">
{{ it.title }}
<div class="label" v-if="it.tag">
<img class="arrows" src="https://app.gter.net/image/miniApp/offer/arrows-triangle-blue.svg" />
{{ it.tag }}
</div>
</div>
</div>
<div class="bottom flexacenter">
<div class="time flexacenter">
<div class="icon flexcenter">
<img class="img" src="https://app.gter.net/image/miniApp/offer/time-icon.png" />
</div>
{{ it.date || '长期答疑' }}
</div>
<a class="btn flexcenter" :href="it.url" target="_blank" :style="{backgroundColor: item.color }">详情 <img class="arrows" src="https://app.gter.net/image/miniApp/offer/arrows-circle-white.svg" /></a>
</div>
</div>
</div>
</div>
</div>
<div class="end">- End -</div>
<div class="paly-box-mask flexcenter" v-if="palyState">
<div class="paly-box" @click.stop="">
<img class="close" src="../img/cross-white.svg" @click="closePalyState" />
<div class="paly-video"></div>
</div>
</div>
</div>
<!-- 引入了 vue3 js 创建 vue3 实例 -->
<script src="../js/vue.global.min.js"></script>
<script src="../js/artplayer.js"></script>
<script>
// 创建Vue3实例
const { createApp, onMounted, ref, onUnmounted, reactive } = Vue;
const admissionApp = createApp({
setup() {
onMounted(() => {
init();
getBannerList();
getAdmissionLists();
});
let interviewData = ref({}); // 模式一 的第一个访谈
let interviewList = ref({}); // 访谈 列表
const init = () => {
fetchData("/v1/admissionsOfficer/interview").then((res) => {
if (res.code != 200) return;
let data = res.data || [];
for (let i = 0; i < 20; i++) {
data.push({
title: "岭南大学保险",
subtitle: "香港商学院硕士都去卖保险了",
video_cover: "https://oss.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-Z0kdXrqqsgFptxhcq_cQnrlIKYkXFcXBq_D-81qNDQyOQ~~",
sid: 350 + i,
name: "岭南大学",
enname: "Lingnan University",
admission_officer_name: "施林佟",
admission_officer_rank: "副教授",
admission_officer_position: "数据科学学院助理院长",
focus_of_this_issue: "寄托建立了具有公信力的品牌评价系统\n致力打造一个华人区最专业的留学交流平台\n成为一个寄托或关于梦想的垂直门户网站",
istop: 1,
token: "D6zdTJ2cMaKd0g6nFqsa1JR5scupqIIg5Wuab33kATaY-myKGtBtHiygo4F5z8iY_Le6VEcmblBwOvlbiqvh1pyXKaET8hp8OsXbY1fFQwRKjq42OWQ3" + i,
});
}
let target = null;
const topItems = data.filter((item) => item.istop === 1);
if (topItems.length > 0) target = topItems[Math.floor(Math.random() * topItems.length)];
data = data.filter((item) => item.token !== target.token);
interviewData.value = target;
interviewList.value = data || [];
});
};
let palyState = ref(false); // 播放弹窗状态
let art = null; // 播放器实例
const getVideoUrl = (token) => {
fetchData(`/v1/admissionsOfficer/videoUrl?token=${token}`).then((res) => {
palyState.value = true;
setTimeout(() => {
art = new Artplayer({
container: ".paly-box-mask .paly-box .paly-video",
url: res.data.url,
autoplay: true,
fullscreen: true,
});
}, 500);
});
};
const closePalyState = () => {
art?.pause();
art?.destroy();
palyState.value = false;
};
let admissionList = ref([]); // 学校 招生官 列表
// 获取 院校 招生官 列表
const getAdmissionLists = () => {
fetchData(`/v1/admissionsOfficer/lists`).then((res) => {
if (res.code != 200) return;
const data = res.data;
let target = data.data || [];
target.forEach((item) => {
let year = [];
let obj = {};
item.articles.forEach((e) => {
year.push(e.year);
obj[e.year] = e.data;
});
item["pitch"] = year[0];
item["yList"] = year.slice(0, 4);
item["yListMore"] = year.slice(4);
item["list"] = obj;
});
admissionList.value = target;
});
};
// 切换招生官 院校 的 年份
const cutSchoolYear = (index, year) => {
admissionList.value[index]["pitch"] = year;
};
// 点击 招生官 年份 更多弹窗
const openSchoolYearState = (index) => (admissionList.value[index]["state"] = true);
// 选择 招生官 年份 更多弹窗
const selectSchoolYearState = (index, year) => {
admissionList.value[index]["pitch"] = year;
admissionList.value[index]["isPitchMore"] = true;
admissionList.value[index]["state"] = false;
};
// 关闭 招生官 年份 更多弹窗
const closeSchoolYearState = (index) => (admissionList.value[index]["state"] = false);
let moreSchoolSid = ref(0); // 选中 学校 sid
let moreSchoolData = ref({}); // 学校信息
let moreSchoolList = ref([]); // 年份下 列表 数据
let moreSchoolPitch = ref(0); // 选中年份
let moreSchoolYList = ref([]); // 年份 列表
let moreSchoolYMList = ref([]); // 年份 更多
const openMoreSchool = (sid) => {
fetchData(`/v1/admissionsOfficer/articles?sid=${sid}`).then((res) => {
if (res.code != 200) return;
const data = res.data || {};
moreSchoolData.value = data.school;
let target = data.data || [];
console.log("target", target);
let obj = {};
let yearList = [];
target.forEach((element) => {
obj[element.year] = element.data;
yearList.push(element.year);
});
moreSchoolYList.value = yearList.slice(0, 4);
moreSchoolYMList.value = yearList.slice(4);
moreSchoolPitch.value = yearList[0];
moreSchoolList.value = obj;
moreSchoolSid.value = sid;
document.body.style.overflow = "hidden";
});
};
let moreYearState = ref(false);
const openMoreYearState = () => {
moreYearState.value = true;
};
const closeMoreSchool = () => {
moreSchoolSid.value = 0;
document.body.style.overflow = "auto";
};
onUnmounted(() => {});
let preachList = ref([]); // 宣讲会 列表
let preachIndex = ref(0); // 宣讲会 下标
let preachI = ref(0); // 宣讲会 下标
let preachTimer = null;
let preachInterval = 3; // 每页 4 条
const getBannerList = () => {
fetchData(`/v1/admissionsOfficer/banner`).then((res) => {
if (res.code != 200) return;
let data = res.data;
for (let i = 0; i < 20; i++) {
data.push({
id: i + 20,
title: "香港中文大学 | 美国西北大学双硕士学位课程",
lecture_time: "2025-07-12 00:00:00",
image_url: "https://oss.x-php.com/Zvt57TuJSUvkyhw-xG7Y2l-c-Z0rfHjqqsgFptxhT66SWgrlI64uMxcfWaHf9cJWpdxZDnzZ5RLrizQ0Mjk~",
image_id: 977797,
sort: 1,
link_url: "https://www.baidu.com",
status: 1,
created_at: "2025-07-11 16:59:10",
updated_at: "2025-07-11 17:09:33",
});
}
// data.forEach((element, index) => (element["id"] = index + 1));
data.forEach((element) => (element["lecture_time"] = timeformat(element["lecture_time"])));
let target = [];
for (let i = 0; i < data.length; i += preachInterval) {
target.push(data.slice(i, i + preachInterval));
}
preachList.value = target;
preachListTimeout();
});
};
const timeformat = (time) => {
time = time.replaceAll("-", "/"); // 修改格式
let result = "";
var datetime = new Date(time);
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();
result = `${Nyear}${Nmonth}${Ndate}${Nhour}:${Nmin}`;
return result;
};
const swiperBox = ref(null);
const swiperBoxSwiper = ref(null);
let swiperCurrent = ref(0); // 宣讲会 下标
let preachListTimer = null; // 宣讲会 定时器
const preachListTimeout = () => {
preachListTimer = setTimeout(() => {
const width = swiperBox.value.scrollWidth;
swiperCurrent.value++;
if (swiperCurrent.value >= preachList.value.length) swiperCurrent.value = 0;
swiperBoxSwiper.value.scrollTo({
left: width * swiperCurrent.value,
behavior: "smooth",
});
preachListTimeout();
}, 3000);
};
// const touchStartX = ref(0);
// const touchStartY = ref(0);
const handleTouchStart = (e) => {
clearTimeout(preachListTimer);
// touchStartX.value = e.touches[0].clientX;
// touchStartY.value = e.touches[0].clientY;
};
const handleTouchEnd = (e) => {
preachListTimeout();
// const touchEndX = e.changedTouches[0].clientX;
// const touchEndY = e.changedTouches[0].clientY;
// const diffX = touchEndX - touchStartX.value;
// const diffY = touchEndY - touchStartY.value;
// console.log(`Touch moved X: ${diffX}, Y: ${diffY}`);
};
const fetchData = (url, data) => {
return new Promise((resolve, reject) => {
const baseUrl = "https://api.gter.net";
if (url.indexOf("http") == -1) url = baseUrl + url;
// 构建查询字符串
const queryString = Object.keys(data || {})
.map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
.join("&");
// 将查询字符串添加到URL
if (queryString) url += (url.indexOf("?") === -1 ? "?" : "&") + queryString;
var xhr = new XMLHttpRequest();
xhr.responseType = "json";
xhr.withCredentials = true;
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
let response = xhr.response;
resolve(response);
}
};
xhr.send();
});
};
return { swiperBoxSwiper, swiperBox, swiperCurrent, closePalyState, getVideoUrl, palyState, interviewList, closeSchoolYearState, selectSchoolYearState, openSchoolYearState, cutSchoolYear, admissionList, moreSchoolYMList, openMoreYearState, moreYearState, moreSchoolPitch, moreSchoolYList, moreSchoolList, moreSchoolData, moreSchoolSid, closeMoreSchool, openMoreSchool, interviewData, preachList, preachIndex, preachI, handleTouchStart, handleTouchEnd };
},
});
// 挂载到页面中的#app元素
admissionApp.mount("#admission-officer");
</script>
</body>
</html>