476 lines
22 KiB
HTML
476 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Document</title>
|
|
<link rel="stylesheet" href="/css/common.css" />
|
|
<link rel="stylesheet" href="/css/index.css" />
|
|
<script src="/js/axios.min.js"></script>
|
|
<script src="/js/vue.global.js"></script>
|
|
<script src="/js/common.js"></script>
|
|
<script src="/js/base.js"></script>
|
|
<script src="/js/masonry.pkgd.min.js"></script>
|
|
<style>
|
|
[v-cloak] {
|
|
display: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="app" class="main" v-cloak>
|
|
<img class="index-icon" src="/img/index-icon.png" />
|
|
<div style="display: flex;" class="header-box flexacenter">
|
|
<img class="bj" src="/img/header-bj.svg" />
|
|
<div class="search flexacenter">
|
|
<div class="input flex1">搜索项目</div>
|
|
<img class="search-icon" src="/img/search-icon.svg" />
|
|
</div>
|
|
<div class="btn flexacenter">
|
|
<div class="item flexcenter">
|
|
<img class="icon" src="/img/contrast-icon.png" />
|
|
项目对比
|
|
</div>
|
|
<div class="item flexcenter">
|
|
<img class="icon" src="/img/contrast-icon.png" />
|
|
项目对比
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 筛选 -->
|
|
<div style="display: flex;" class="screen flexflex">
|
|
<div class="block school">
|
|
<div class="title flexacenter">
|
|
<div class="icon flexcenter">
|
|
<img class="img" src="/img/school-icon.png" />
|
|
</div>
|
|
按学校查看
|
|
</div>
|
|
<div class="list">
|
|
<div class="item flexcenter" v-for="(item,index) in university" :key="index">{{ item.label }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="block subject flex1">
|
|
<div class="title flexacenter">
|
|
<div class="icon flexcenter">
|
|
<img class="img" src="/img/school-icon.png" />
|
|
</div>
|
|
按学科查看
|
|
</div>
|
|
<div class="list flexflex">
|
|
<div class="item flexcenter" v-for="(item,index) in discipline">{{ item.label }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 缘分 -->
|
|
<div class="fate">
|
|
<div class="title flexacenter">
|
|
<div>今日缘分项目</div>
|
|
<div class="btn flexacenter" @click="getFate">
|
|
<img class="icon" src="/img/trade-icon.png" />
|
|
换一批
|
|
</div>
|
|
</div>
|
|
<div class="list flexflex">
|
|
<div class="item flexacenter" v-for="(item,index) in fateProject">
|
|
<div class="left">
|
|
<div class="name one-line-display">{{ item.name_zh }}</div>
|
|
<div class="message flexacenter">
|
|
<div class="project one-line-display">{{ item.name_en }}</div>
|
|
<span class="virgule">|</span>{{ item.schoolname }}
|
|
</div>
|
|
</div>
|
|
<div v-if="!item?.state" class="btn flexacenter" :class="'add' + item.random" @click="handleClick('fate',item,index)">
|
|
<div class="add flexcenter">
|
|
<img class="icon" src="/img/add-xiao.svg" />
|
|
</div>
|
|
加入对比单
|
|
</div>
|
|
<div v-else class="already flexacenter">
|
|
<div class="tick-box flexcenter">
|
|
<img class="img-tick" src="/img/tick-icon.svg" />
|
|
</div>
|
|
已加入
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 招生官 -->
|
|
<div class="recruit">
|
|
<div class="title flexacenter">
|
|
<img class="img" src="/img/admission-icon.png" />
|
|
<div class="btn flexacenter">
|
|
招生官频道
|
|
<img class="icon" src="/img/arrows-icon.png" />
|
|
</div>
|
|
</div>
|
|
<div class="list flexflex" ref="recruitListRef">
|
|
<div class="list-item" v-for="(item,index) in admissionList">
|
|
<div class="item flexflex" v-for="(item,i) in item">
|
|
<div class="operate flexcenter">
|
|
<div v-if="item.contraststatus?.status === 1 && item.contraststatus?.ismanage === 1" class="already flexacenter">
|
|
<div class="tick-box flexcenter">
|
|
<img class="img-tick" src="/img/tick-icon.svg" />
|
|
</div>
|
|
已加入
|
|
</div>
|
|
<div v-else-if="item.contraststatus?.status === 0 || item.contraststatus?.ismanage === 0" class="circle flexcenter" @click="openMoreSelect('admission',index,i)">
|
|
<img class="img-dot" src="/img/dot-dot-dot.png" />
|
|
</div>
|
|
<div v-else class="circle flexcenter" @click="handleClick('admission',item,index,i)" :class="'add' + item.random" >
|
|
<img class="img-add" src="/img/add-thick.svg" />
|
|
</div>
|
|
<div v-if="item.moreState" class="select-mask" @click="closeMoreSelectAll('admission')"></div>
|
|
<div class="select flexflex" :class="{'show': item.moreState}">
|
|
<div class="title flexacenter">
|
|
<div class="dot"></div>
|
|
{{ item.contraststatus?.status == 1 ? '该项目已加入对比单,未加入项目管理' : '该项目已加入项目管理,未加入对比单' }}
|
|
</div>
|
|
<div class="btn flexcenter" @click="handleClick('admission',item,index,i)"><img class="img" src="/img/add-circle.svg" />加入{{ item.contraststatus?.status == 1 ? '项目管理' : '对比单' }}</div>
|
|
</div>
|
|
</div>
|
|
<img class="avatar" :src="item.schoollogo" />
|
|
<div class="info">
|
|
<div class="school">{{ item.schoolname }}</div>
|
|
<div class="name one-line-display">{{ item.name_zh }}</div>
|
|
<div class="name-en one-line-display">{{ item.name_en }}</div>
|
|
<div class="aq flexacenter">
|
|
<div class="text">招生官答疑时间</div>
|
|
<div class="value flex1">长期答疑</div>
|
|
<img class="icon" src="/img/arrows-long-icon.png" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="indicate flexcenter">
|
|
<img class="icon" @click="cutAdmissionPage('left')" :src="reversedMessage('left')" />
|
|
<div class="text">{{ admissionPage }}/{{ admissionTotalPage }}</div>
|
|
<img class="icon btn-right" @click="cutAdmissionPage('right')" :src="reversedMessage('right')" />
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 列表 -->
|
|
<div class="data" ref="dataListRef">
|
|
<img class="data-item fall" @load="imageFallLoaded" src="/img/25fall.svg" />
|
|
<div class="data-item item" v-for="(item,index) in projectList">
|
|
<div class="school flexacenter"><img class="img" :src="item.schoollogo" />{{ item.schoolname }}</div>
|
|
<div class="name">{{ item.name_zh }}</div>
|
|
<div class="name-en">{{ item.name_en }}</div>
|
|
<div class="introduce flexacenter">
|
|
<div class="flexacenter" v-if="item.rank">
|
|
专业排名
|
|
<div class="quantity">{{ item.rank }}</div>
|
|
</div>
|
|
<div class="flexacenter" v-if="item.tuition_fee_text">
|
|
<div class="line" v-if="item.rank">|</div>
|
|
学费HK$
|
|
<div class="quantity">{{ item.tuition_fee_text }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="word" v-if="item.distinctive">{{ item.distinctive }}</div>
|
|
<div class="tag flexflex">
|
|
<!-- <div class="tag-item admissions">招生官项目</div> -->
|
|
<div class="tag-item gray" :class="{'semester': item.semesterState}">{{ item.semester.text }}</div>
|
|
<div class="tag-item" v-for="(item,index) in item.tags">{{ item }}</div>
|
|
</div>
|
|
<div class="operate flexcenter">
|
|
<div v-if="item.contraststatus?.status === 1 && item.contraststatus?.ismanage === 1" class="already flexacenter">
|
|
<div class="tick-box flexcenter">
|
|
<img class="img-tick" src="/img/tick-icon.svg" />
|
|
</div>
|
|
已加入
|
|
</div>
|
|
<div v-else-if="item.contraststatus?.status === 0 || item.contraststatus?.ismanage === 0" class="circle flexcenter" @click="openMoreSelect('list',index)">
|
|
<img class="img-dot" src="/img/dot-dot-dot.png" />
|
|
</div>
|
|
<div v-else class="circle flexcenter" :class="'add' + item.random" @click="handleClick('list',item,index)">
|
|
<img class="img-add" src="/img/add-thick.svg" />
|
|
</div>
|
|
<div v-if="item.moreState" class="select-mask" @click="closeMoreSelectAll('list')"></div>
|
|
<div class="select flexflex" :class="{'show': item.moreState}">
|
|
<div class="top flex1 flexcenter">
|
|
<div class="title flexacenter">
|
|
<div class="dot"></div>
|
|
{{ item.contraststatus?.status == 1 ? '该项目已加入对比单,未加入项目管理' : '该项目已加入项目管理,未加入对比单' }}
|
|
</div>
|
|
<div class="btn flexcenter" @click="handleClick('list',item,index)"><img class="img" src="/img/add-circle.svg" />加入{{ item.contraststatus?.status == 1 ? '项目管理' : '对比单' }}</div>
|
|
</div>
|
|
<div class="bottom"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 底部 -->
|
|
<base-bottom ref="baseRef"></base-bottom>
|
|
|
|
<div class="my-project">
|
|
dfgfdgdfgdfgfd
|
|
</div>
|
|
|
|
</div>
|
|
<script>
|
|
const { createApp, ref, onMounted, nextTick, onUnmounted } = Vue
|
|
const projectIndex = createApp({
|
|
setup() {
|
|
let dataListRef = ref(null)
|
|
|
|
onMounted(() => {
|
|
window.addEventListener("scroll", handleScroll)
|
|
|
|
listMasonryInstance = new Masonry(dataListRef.value, {
|
|
itemSelector: ".data-item",
|
|
gutter: 20,
|
|
})
|
|
init()
|
|
})
|
|
let user = ref({})
|
|
let university = ref([])
|
|
let discipline = ref([])
|
|
let contrastcount = ref({})
|
|
let encodekey = ref("")
|
|
|
|
// 初始化
|
|
const init = () => {
|
|
$ajaxget("/api/project.home/basicData").then(result => {
|
|
const data = result.data || {}
|
|
user.value = data.user
|
|
university.value = data.university
|
|
discipline.value = data.discipline
|
|
contrastcount.value = data.contrastcount
|
|
encodekey.value = data.encodekey
|
|
|
|
getFate()
|
|
getAdmission()
|
|
getProjectData()
|
|
})
|
|
}
|
|
|
|
// 今日缘分项目
|
|
let fateProject = ref([])
|
|
const getFate = () => {
|
|
$ajaxget("/api/project.home/todayFateProject").then(res => {
|
|
if (res.code != 200) return
|
|
const data = res.data || []
|
|
data.forEach(element => {
|
|
element["random"] = randomString(6)
|
|
})
|
|
|
|
fateProject.value = data
|
|
})
|
|
}
|
|
|
|
let admissionList = ref([])
|
|
let admissionTotalPage = ref(0) // 总页数
|
|
|
|
// 获取 招生官项目
|
|
const getAdmission = () => {
|
|
$ajaxget("/api/project.lists", {
|
|
limit: 20,
|
|
page: 1,
|
|
admissionsproject: 1,
|
|
}).then(res => {
|
|
if (res.code != 200) return
|
|
const data = res.data
|
|
const list = data.data || []
|
|
|
|
const targetList = (list || []).map(element => ({
|
|
...element,
|
|
random: randomString(6),
|
|
}))
|
|
|
|
const chunkArray = (array, size) => {
|
|
const result = []
|
|
for (let i = 0; i < array.length; i += size) {
|
|
result.push(array.slice(i, i + size))
|
|
}
|
|
return result
|
|
}
|
|
|
|
const groupedAdmissionList = chunkArray(targetList, 4)
|
|
|
|
admissionList.value = groupedAdmissionList
|
|
admissionTotalPage.value = groupedAdmissionList.length
|
|
})
|
|
}
|
|
|
|
let admissionPage = ref(1)
|
|
let recruitListRef = ref(null)
|
|
// 点击切换 招生官 轮播图 滚动
|
|
const cutAdmissionPage = type => {
|
|
if (type == "left") {
|
|
if (admissionPage.value > 1) admissionPage.value--
|
|
} else {
|
|
if (admissionPage.value < admissionTotalPage.value) admissionPage.value++
|
|
}
|
|
recruitListRef.value.scrollTo({
|
|
left: 1140 * (admissionPage.value - 1),
|
|
behavior: "smooth",
|
|
})
|
|
}
|
|
|
|
// 计算
|
|
const reversedMessage = type => {
|
|
if (type == "left") {
|
|
if (admissionPage.value == 1) return "/img/arrows-triangle-gray.svg"
|
|
else return "/img/arrows-triangle-blue.png"
|
|
} else {
|
|
if (admissionPage.value == admissionTotalPage.value) return "/img/arrows-triangle-gray.svg"
|
|
else return "/img/arrows-triangle-blue.png"
|
|
}
|
|
}
|
|
|
|
let projectList = ref([])
|
|
let projectPage = 1
|
|
// 获取项目数据
|
|
const getProjectData = () => {
|
|
if (projectPage == 0) return
|
|
$ajaxget("/api/project.lists", {
|
|
limit: 20,
|
|
page: projectPage,
|
|
}).then(res => {
|
|
if (res.code != 200) return
|
|
const data = res.data
|
|
|
|
const date = new Date()
|
|
const month = date.getMonth() + 1
|
|
const year = date.getFullYear()
|
|
|
|
let list = data.data || []
|
|
|
|
list = list.map(element => ({
|
|
...element,
|
|
random: randomString(6),
|
|
semesterState: month > element.semester.month && year + 1 <= element.semester.year,
|
|
tuition_fee_text: formatNumberWithSpaces(element.tuition_fee),
|
|
}))
|
|
projectList.value = projectList.value.concat(list)
|
|
projectPage = data.count > data.limit * data.page ? projectPage + 1 : 0
|
|
nextTick(() => {
|
|
listMasonryInstance.reloadItems()
|
|
listMasonryInstance.layout()
|
|
})
|
|
})
|
|
}
|
|
|
|
//瀑布实例
|
|
let listMasonryInstance = null
|
|
|
|
const imageFallLoaded = () => {
|
|
listMasonryInstance.reloadItems()
|
|
listMasonryInstance.layout()
|
|
}
|
|
|
|
const handleScroll = () => {
|
|
const scrollHeight = document.documentElement.scrollHeight
|
|
const clientHeight = document.documentElement.clientHeight
|
|
const scrollTop = window.pageYOffset
|
|
|
|
if (scrollTop + clientHeight >= scrollHeight) {
|
|
getProjectData()
|
|
}
|
|
}
|
|
|
|
const baseRef = ref(null)
|
|
|
|
// 点击事件
|
|
const handleClick = (type, item, index, i) => {
|
|
const random = item.random
|
|
|
|
if (item.status == 1) return
|
|
$ajax("/api/project.contrast/add", {
|
|
projectid: item.id,
|
|
}).then(res => {
|
|
baseRef.value.calculate(random)
|
|
|
|
if (type == "fate") fateProject.value[index]["state"] = 1
|
|
|
|
if (type == "admission") {
|
|
admissionList.value[index][i]["contraststatus"] = {
|
|
status: 1,
|
|
ismanage: 1,
|
|
}
|
|
admissionList.value[index][i]["moreState"] = false
|
|
}
|
|
|
|
if (type == "list") {
|
|
projectList.value[index]["contraststatus"] = {
|
|
status: 1,
|
|
ismanage: 1,
|
|
}
|
|
projectList.value[index]["moreState"] = false
|
|
}
|
|
})
|
|
}
|
|
|
|
const openMoreSelect = (type, index, i) => {
|
|
if (type == "admission") {
|
|
admissionList.value[index][i]["moreState"] = true
|
|
}
|
|
if (type == "list") {
|
|
console.log(222)
|
|
projectList.value[index]["moreState"] = true
|
|
}
|
|
}
|
|
|
|
// 关闭所有 状态 选择 弹出框
|
|
const closeMoreSelectAll = type => {
|
|
if (type == "admission") {
|
|
admissionList.value.forEach(element => {
|
|
element.forEach(ele => {
|
|
ele["moreState"] = false
|
|
})
|
|
})
|
|
}
|
|
|
|
if (type == "list") {
|
|
projectList.value.forEach(element => {
|
|
element["moreState"] = false
|
|
})
|
|
}
|
|
}
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener("scroll", handleScroll)
|
|
})
|
|
|
|
return {
|
|
user,
|
|
university,
|
|
discipline,
|
|
contrastcount,
|
|
encodekey,
|
|
fateProject,
|
|
getFate,
|
|
admissionList,
|
|
admissionPage,
|
|
admissionTotalPage,
|
|
cutAdmissionPage,
|
|
recruitListRef,
|
|
reversedMessage,
|
|
projectList,
|
|
dataListRef,
|
|
imageFallLoaded,
|
|
handleClick,
|
|
openMoreSelect,
|
|
closeMoreSelectAll,
|
|
baseRef,
|
|
}
|
|
},
|
|
})
|
|
|
|
projectIndex.component("base-bottom", base)
|
|
|
|
projectIndex.mount("#app")
|
|
</script>
|
|
</body>
|
|
</html>
|