xg-project-library/html/subject.html

355 lines
17 KiB
HTML
Raw Normal View History

2024-10-29 11:14:25 +00:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
2024-10-31 04:27:27 +00:00
<link rel="stylesheet" href="/css/common.css" />
<link rel="stylesheet" href="/css/subject.css" />
2024-11-05 11:00:36 +00:00
<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>
2024-10-29 11:14:25 +00:00
</head>
<body>
2024-11-05 11:00:36 +00:00
<div class="main" id="app">
2024-10-29 11:14:25 +00:00
<img class="index-icon" src="/img/index-icon.png" />
2024-11-07 10:55:56 +00:00
<div class="boxbox">
2024-10-29 11:14:25 +00:00
<div class="tab flexacenter">
首页
<img class="img" src="/img/arrows.svg" />
按学科查看
<img class="img" src="/img/arrows.svg" />
2024-11-05 11:00:36 +00:00
<div class="current">{{ title }}</div>
2024-10-29 11:14:25 +00:00
</div>
<div class="info flexacenter">
<img class="img" src="/img/subject.png" />
<div class="flex1">
<div class="title">学科领域</div>
<div class="list flexflex">
2024-11-05 11:00:36 +00:00
<div class="item flexacenter" :class="{'pitch': item.value == id}" v-for="(item,index) in discipline" @click="cutDiscipline(item.value)">{{ item.label }}</div>
2024-10-29 11:14:25 +00:00
</div>
</div>
</div>
<div class="body flexflex">
<div class="left">
2024-11-05 11:00:36 +00:00
<div class="item flexacenter" :class="{'pitch': !sid}" @click="cutSid('')">
<img v-if="!sid" class="img" src="/img/side-all-pitch.png" />
<img v-else class="img" src="/img/side-all.png" />
全部项目
</div>
<div class="item flexacenter" :class="{'pitch': item.value == sid}" @click="cutSid(item.value)" v-for="(item,index) in university"><img class="img" :src="item.logo" />{{ item.name }}</div>
2024-10-29 11:14:25 +00:00
</div>
<div class="right flex1">
<div class="h flexacenter">
2024-11-05 11:00:36 +00:00
<div class="total">共 {{ count }} 个项目</div>
2024-11-11 06:28:21 +00:00
<div class="item flexacenter sort">
2024-10-29 11:14:25 +00:00
学费由低到高
<img class="img-sort" src="/img/sort-icon.png" />
2024-11-11 06:32:24 +00:00
<template v-if="!sortState">
2024-11-11 06:28:21 +00:00
<div class="sort-mask"></div>
<div class="sort-list">
<div class="sort-item pitch">排名由高到低</div>
<div class="sort-item">学费由低到高</div>
<div class="sort-item">学费由高到低</div>
</div>
</template>
2024-10-29 11:14:25 +00:00
</div>
2024-11-05 11:00:36 +00:00
<div class="item flexacenter" v-if="sid">
2024-10-29 11:14:25 +00:00
学校主页
2024-11-05 11:00:36 +00:00
<img class="img-school" src="/img/arrows-circle-black.svg" />
2024-10-29 11:14:25 +00:00
</div>
</div>
2024-11-05 11:00:36 +00:00
<div class="list flexflex" ref="dataListRef">
<div class="item" v-for="(item,index) in showList">
2024-10-29 11:14:25 +00:00
<div class="operate flexcenter">
2024-11-05 11:00:36 +00:00
<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>
已加入
2024-10-29 11:14:25 +00:00
</div>
2024-11-05 11:00:36 +00:00
<div v-else-if="item.contraststatus?.status === 0 || item.contraststatus?.ismanage === 0" @click="openMoreSelect(index)" class="circle flexcenter">
2024-10-29 11:14:25 +00:00
<img class="img-dot" src="/img/dot-dot-dot.png" />
</div>
2024-11-05 11:00:36 +00:00
<div v-else class="circle flexcenter" :class="'add' + item.random" @click="handleClick(item,index)">
<img class="img-add" src="/img/add-thick.svg" />
</div>
<div v-if="item.moreState" class="select-mask" @click="closeMoreSelectAll()"></div>
<div class="select flexflex" :class="{'show': item.moreState}">
2024-10-29 11:14:25 +00:00
<div class="title flexacenter">
<div class="dot"></div>
2024-11-05 11:00:36 +00:00
{{ item.contraststatus?.status == 1 ? '该项目已加入对比单,未加入项目管理' : '该项目已加入项目管理,未加入对比单' }}
2024-10-29 11:14:25 +00:00
</div>
2024-11-05 11:00:36 +00:00
<div class="btn flexcenter" @click="handleClick(item,index)"><img class="img" src="/img/add-circle.svg" />加入{{ item.contraststatus?.status == 1 ? '项目管理' : '对比单' }}</div>
2024-10-29 11:14:25 +00:00
</div>
</div>
2024-11-05 11:00:36 +00:00
<div class="name flexflex">{{ item.name_zh }}</div>
<div class="english">{{ item.name_en }}</div>
2024-10-29 11:14:25 +00:00
<div class="introduce flexacenter">
2024-11-05 11:00:36 +00:00
{{ item.department }}
<div class="flexacenter" v-if="item.rank">
2024-10-29 11:14:25 +00:00
<div class="line">|</div>
专业排名
2024-11-05 11:00:36 +00:00
<div class="quantity">{{ item.rank }}</div>
2024-10-29 11:14:25 +00:00
</div>
2024-11-05 11:00:36 +00:00
<div class="flexacenter" v-if="item.tuition_fee_text">
2024-10-29 11:14:25 +00:00
<div class="line">|</div>
2024-11-05 11:00:36 +00:00
学费HK$ <vie class="quantity">{{ item.tuition_fee_text }}</vie>
2024-10-29 11:14:25 +00:00
</div>
</div>
2024-11-05 11:00:36 +00:00
<div class="word" v-if="item.distinctive">{{ item.distinctive }}</div>
2024-10-29 11:14:25 +00:00
<div class="tag flexflex">
2024-11-05 11:00:36 +00:00
<div class="tag-item admissions" v-if="item.admissionsproject">招生官项目</div>
<div class="tag-item gray" :class="{'semester': item.semesterState}">{{ item.semester.text }}</div>
<div class="tag-item" v-for="item in item.tags">{{ item }}</div>
2024-10-29 11:14:25 +00:00
</div>
</div>
</div>
2024-11-05 11:00:36 +00:00
<div v-if="page == 0 && showList.length == 0" class="empty-box flexcenter">
<img class="icon" src="/img/empty-icon.png" />
<span class="text">暂无项目</span>
</div>
2024-10-29 11:14:25 +00:00
</div>
</div>
</div>
<!-- 底部 -->
2024-11-05 11:00:36 +00:00
<base-bottom ref="baseRef"></base-bottom>
2024-10-29 11:14:25 +00:00
</div>
<script>
2024-11-05 11:00:36 +00:00
const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue
const subject = createApp({
setup() {
const dataListRef = ref(null)
onMounted(() => {
window.addEventListener("scroll", handleScroll)
getBaseData().then(data => {
let list = JSON.parse(JSON.stringify(data.university)) || []
let obj = {}
data.discipline.forEach(element => {
obj[element.value] = element
})
title.value = obj[id.value].label
console.log("obj", obj)
discipline.value = obj
university.value = list
})
listMasonryInstance = new Masonry(dataListRef.value, {
itemSelector: ".item",
gutter: 10,
})
getData()
})
const handleScroll = () => {
const scrollHeight = document.documentElement.scrollHeight
const clientHeight = document.documentElement.clientHeight
const scrollTop = window.pageYOffset
if (scrollTop + clientHeight >= scrollHeight) {
calculateShowList()
}
}
let discipline = ref({})
let university = ref([])
let id = ref("3")
let title = ref("")
let sid = ref("")
const getData = () => {
$ajaxget("/api/project.lists", {
limit: 2000,
disciplineid: id.value,
sid: sid.value,
}).then(res => {
if (res.code != 200) return
const data = res.data
let list = data.data || []
const date = new Date()
const month = date.getMonth() + 1
const year = date.getFullYear()
list = list.map(element => ({
tuition_fee_text: formatNumberWithSpaces(element.tuition_fee),
...element,
rankk: convertRankToRankText(element.rank),
random: randomString(6),
semesterState: month > element.semester.month && year + 1 <= element.semester.year,
}))
function convertRankToRankText(rank) {
if (!rank) return 0
if (rank.indexOf("-")) {
const range = rank.split("-")
const start = parseInt(range[0]) * 1
const end = parseInt(range[1]) * 1
return start || end || 0
} else return rank || 0
}
listAll = list
screenList = list
count.value = data.count
page.value = 1
screenData()
})
}
let count = ref(0)
let listAll = []
let sortIndex = ref(1)
let screenList = []
let showList = ref([])
let page = ref(1)
// 筛选数据
const screenData = () => {
const sort = sortIndex.value
screenList = listAll
// 按排名由低到高排序
if (sort == 0) {
screenList.sort((a, b) => {
// a 排在后面
if (a.rankk == 0) return 1
// b 排在后面
if (b.rankk == 0) return -1
// 普通情况下的排序逻辑
return a.rankk - b.rankk
})
} else if (sort == 1) {
// 按学费由低到高排序
screenList.sort((a, b) => {
if (a.tuition_fee == null) return 1
if (b.tuition_fee == null) return -1
return a.tuition_fee - b.tuition_fee
})
} else if (sort == 2) {
// 按学费由高到低排序
screenList.sort((a, b) => {
if (a.tuition_fee == null) return 1
if (b.tuition_fee == null) return -1
return b.tuition_fee - a.tuition_fee
})
}
showList.value = []
count.value = screenList.length
calculateShowList()
}
let listMasonryInstance = null
// 在 screenList 数据截取要显示的数据
const calculateShowList = () => {
const limit = 20
if (page.value == 0) return
const startIndex = (page.value - 1) * limit
const endIndex = startIndex + limit
let list = screenList.slice(startIndex, endIndex)
showList.value = showList.value.concat(list)
page.value = endIndex >= screenList.length ? 0 : page.value + 1
nextTick(() => {
listMasonryInstance.reloadItems()
listMasonryInstance.layout()
})
}
const cutSid = value => {
sid.value = value
getData()
}
const cutDiscipline = value => {
id.value = value
getData()
}
const baseRef = ref(null)
// 点击事件
const handleClick = (item, index, i) => {
const random = item.random
if (item.status == 1) return
$ajax("/api/project.contrast/add", {
projectid: item.id,
}).then(res => {
console.log(baseRef.value)
baseRef.value.calculate(random, res.data.count)
const uniqid = item["uniqid"]
listAll.forEach(element => {
if (element.uniqid == uniqid) {
element["contraststatus"] = {
status: 1,
ismanage: 1,
}
}
})
showList.value[index]["contraststatus"] = {
status: 1,
ismanage: 1,
}
showList.value[index]["moreState"] = false
})
}
const openMoreSelect = index => {
closeMoreSelectAll()
showList.value[index]["moreState"] = true
}
// 关闭所有 状态 选择 弹出框
const closeMoreSelectAll = type => {
showList.value.forEach(element => {
element["moreState"] = false
})
}
return {
title,
discipline,
university,
id,
sid,
count,
sortIndex,
cutSid,
cutDiscipline,
showList,
dataListRef,
page,
handleClick,
openMoreSelect,
baseRef,
closeMoreSelectAll,
}
},
})
subject.component("base-bottom", base)
subject.mount("#app")
2024-10-29 11:14:25 +00:00
</script>
</body>
</html>