no message
This commit is contained in:
parent
292412033f
commit
bc9734adfa
@ -49,7 +49,7 @@ body {
|
||||
bottom: 15px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 2;
|
||||
z-index: 100;
|
||||
}
|
||||
.base .left {
|
||||
width: 450px;
|
||||
@ -129,6 +129,11 @@ body {
|
||||
background-color: #f95d5d;
|
||||
border: none;
|
||||
}
|
||||
.tag .tag-item.admissions {
|
||||
background-color: #73d1e5;
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
.red-dot {
|
||||
position: fixed;
|
||||
width: 10px;
|
||||
|
@ -59,7 +59,7 @@ body {
|
||||
bottom: 15px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 2;
|
||||
z-index: 100;
|
||||
.left {
|
||||
width: 450px;
|
||||
height: 50px;
|
||||
@ -145,6 +145,12 @@ body {
|
||||
background-color: rgba(249, 93, 93, 1);
|
||||
border: none;
|
||||
}
|
||||
|
||||
&.admissions {
|
||||
background-color: rgba(115, 209, 229, 1);
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,7 @@
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.hot .list .list-item .item {
|
||||
padding: 22px 0;
|
||||
padding: 22px 5px 22px 0;
|
||||
width: 510px;
|
||||
height: 90px;
|
||||
margin-left: 33px;
|
||||
@ -376,7 +376,6 @@
|
||||
margin: 0 12px;
|
||||
}
|
||||
.content {
|
||||
height: 1214px;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #f2f2f2;
|
||||
border-radius: 12px;
|
||||
@ -399,12 +398,16 @@
|
||||
.content .body .left .item {
|
||||
height: 56px;
|
||||
padding-left: 34px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.content .body .left .item .img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.content .body .left .item .img.img-pitch {
|
||||
display: none;
|
||||
}
|
||||
.content .body .left .item.pitch {
|
||||
background-color: #fbfbfb;
|
||||
border-top: 1px solid #ebebeb;
|
||||
@ -414,6 +417,12 @@
|
||||
color: #000000;
|
||||
font-weight: 650;
|
||||
}
|
||||
.content .body .left .item.pitch .img {
|
||||
display: none;
|
||||
}
|
||||
.content .body .left .item.pitch .img.img-pitch {
|
||||
display: block;
|
||||
}
|
||||
.content .body .left .item.pitch::after {
|
||||
content: "";
|
||||
width: 5px;
|
||||
@ -450,6 +459,7 @@
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.content .body .right .screen .list .item.pitch {
|
||||
background-color: #7b8cd3;
|
||||
@ -534,7 +544,7 @@
|
||||
}
|
||||
.content .body .right .list .item .operate .circle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@ -562,7 +572,6 @@
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: -24px;
|
||||
width: 285px;
|
||||
background-color: #fbfbfb;
|
||||
border-radius: 8px;
|
||||
-moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.18039216);
|
||||
@ -572,11 +581,14 @@
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
align-items: center;
|
||||
padding-top: 68px;
|
||||
z-index: 2;
|
||||
}
|
||||
.content .body .right .list .item .operate .select.show {
|
||||
width: 285px;
|
||||
height: 171px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -235,7 +235,7 @@
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
.item {
|
||||
padding: 22px 0;
|
||||
padding: 22px 5px 22px 0;
|
||||
width: 510px;
|
||||
height: 90px;
|
||||
margin-left: 33px;
|
||||
@ -424,7 +424,6 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
height: 1214px;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border: 1px solid rgba(242, 242, 242, 1);
|
||||
border-radius: 12px;
|
||||
@ -447,10 +446,15 @@
|
||||
.item {
|
||||
height: 56px;
|
||||
padding-left: 34px;
|
||||
cursor: pointer;
|
||||
.img {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 12px;
|
||||
|
||||
&.img-pitch {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.pitch {
|
||||
@ -461,6 +465,12 @@
|
||||
position: relative;
|
||||
color: #000000;
|
||||
font-weight: 650;
|
||||
.img {
|
||||
display: none;
|
||||
&.img-pitch {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
content: "";
|
||||
width: 5px;
|
||||
@ -502,6 +512,7 @@
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&.pitch {
|
||||
background-color: rgba(123, 140, 211, 1);
|
||||
@ -593,7 +604,7 @@
|
||||
right: 24px;
|
||||
.circle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
cursor: pointer;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@ -621,7 +632,6 @@
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: -24px;
|
||||
width: 285px;
|
||||
background-color: rgba(251, 251, 251, 1);
|
||||
border-radius: 8px;
|
||||
-moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.180392156862745);
|
||||
@ -631,10 +641,13 @@
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
align-items: center;
|
||||
padding-top: 68px;
|
||||
z-index: 2;
|
||||
&.show {
|
||||
width: 285px;
|
||||
height: 171px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.box .info .list .item.pitch {
|
||||
background-color: #7b8cd3;
|
||||
@ -89,6 +90,7 @@
|
||||
.body .left .item {
|
||||
height: 56px;
|
||||
padding-left: 34px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.body .left .item .img {
|
||||
width: 18px;
|
||||
@ -161,6 +163,7 @@
|
||||
font-size: 16px;
|
||||
color: #000000;
|
||||
margin-bottom: 12px;
|
||||
width: 345px;
|
||||
}
|
||||
.body .right .list .item .english {
|
||||
font-family: "PingFangSC-Regular", "PingFang SC", sans-serif;
|
||||
@ -200,7 +203,7 @@
|
||||
}
|
||||
.body .right .list .item .operate .circle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 4;
|
||||
cursor: pointer;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@ -216,11 +219,18 @@
|
||||
width: 18px;
|
||||
height: 8px;
|
||||
}
|
||||
.body .right .list .item .operate .select-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.body .right .list .item .operate .select {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: -24px;
|
||||
width: 285px;
|
||||
background-color: #fbfbfb;
|
||||
border-radius: 8px;
|
||||
-moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.18039216);
|
||||
@ -230,11 +240,14 @@
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
align-items: center;
|
||||
padding-top: 68px;
|
||||
z-index: 2;
|
||||
}
|
||||
.body .right .list .item .operate .select.show {
|
||||
width: 285px;
|
||||
height: 171px;
|
||||
opacity: 1;
|
||||
}
|
||||
@ -283,3 +296,6 @@
|
||||
width: 10px;
|
||||
height: 8px;
|
||||
}
|
||||
.empty-box {
|
||||
height: 500px;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
|
||||
&.pitch {
|
||||
background-color: rgba(123, 140, 211, 1);
|
||||
@ -95,6 +96,7 @@
|
||||
.item {
|
||||
height: 56px;
|
||||
padding-left: 34px;
|
||||
cursor: pointer;
|
||||
.img {
|
||||
width: 18px;
|
||||
margin-right: 12px;
|
||||
@ -173,6 +175,7 @@
|
||||
font-size: 16px;
|
||||
color: #000000;
|
||||
margin-bottom: 12px;
|
||||
width: 345px;
|
||||
}
|
||||
|
||||
.english {
|
||||
@ -212,7 +215,7 @@
|
||||
right: 24px;
|
||||
.circle {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
z-index: 4;
|
||||
cursor: pointer;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
@ -228,11 +231,18 @@
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
.select-mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.select {
|
||||
position: absolute;
|
||||
top: -18px;
|
||||
right: -24px;
|
||||
width: 285px;
|
||||
background-color: rgba(251, 251, 251, 1);
|
||||
border-radius: 8px;
|
||||
-moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.180392156862745);
|
||||
@ -242,10 +252,13 @@
|
||||
transition: all 0.3s;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
align-items: center;
|
||||
padding-top: 68px;
|
||||
z-index: 2;
|
||||
&.show {
|
||||
width: 285px;
|
||||
height: 171px;
|
||||
opacity: 1;
|
||||
}
|
||||
@ -307,3 +320,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty-box {
|
||||
height: 500px;
|
||||
}
|
||||
|
302
html/school.html
302
html/school.html
@ -11,6 +11,7 @@
|
||||
<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;
|
||||
@ -115,69 +116,76 @@
|
||||
<div class="header flexcenter">项目筛选</div>
|
||||
<div class="body flexflex">
|
||||
<div class="left">
|
||||
<div class="item flexacenter"><img class="img" src="/img/side-all.png" />全部项目</div>
|
||||
<div class="item flexacenter pitch"><img class="img" src="/img/side-subject.png" />按学科</div>
|
||||
<div class="item flexacenter"><img class="img" src="/img/side-school.png" />按学院</div>
|
||||
<div class="item flexacenter" :class="{'pitch': screen.pitch == 'all'}" @click="selectScreen('all')"><img class="img" src="/img/side-all.png" /><img class="img img-pitch" src="/img/side-all-pitch.png" />全部项目</div>
|
||||
<div class="item flexacenter" :class="{'pitch': screen.pitch == 'subject'}" @click="selectScreen('subject')"><img class="img" src="/img/side-subject.png" /><img class="img img-pitch" src="/img/side-subject-pitch.png" />按学科</div>
|
||||
<div class="item flexacenter" :class="{'pitch': screen.pitch == 'school'}" @click="selectScreen('school')"><img class="img" src="/img/side-school.png" /><img class="img img-pitch" src="/img/side-school-pitch.png" />按学院</div>
|
||||
</div>
|
||||
<div class="right flex1">
|
||||
<div class="screen">
|
||||
<div class="screen" v-if="screen.pitch == 'subject'">
|
||||
<div class="title">按学科查看:</div>
|
||||
<div class="list flexflex">
|
||||
<div class="item pitch">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item flexcenter" :class="{'pitch': screen.disciplineid == item.disciplineid }" v-for="item in screen.list" @click="selectScreenItem(item)">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="screen" v-if="screen.pitch == 'school'">
|
||||
<div class="title">按学院查看:</div>
|
||||
<div class="list flexflex">
|
||||
<div class="item flexcenter" :class="{'pitch': screen.university == item.value }" v-for="item in screen.list" @click="selectScreenItem(item)">{{ item.value }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="h flexacenter">
|
||||
<div class="total">共 113 个项目</div>
|
||||
<div class="total">共 {{ count }} 个项目</div>
|
||||
<div class="sort flexacenter">
|
||||
学费由低到高
|
||||
<img class="img" src="/img/sort-icon.png" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list flexflex">
|
||||
<div class="item">
|
||||
<div class="list flexflex" ref="dataListRef">
|
||||
<div class="item" v-for="(item ,index) in showList">
|
||||
<div class="operate flexcenter">
|
||||
<div style="display: none;" class="circle flexcenter">
|
||||
<img class="img-add" src="/img/add-thick.svg" />
|
||||
</div>
|
||||
<div class="circle flexcenter">
|
||||
<img class="img-dot" src="/img/dot-dot-dot.png" />
|
||||
</div>
|
||||
<div class="select flexflex show">
|
||||
<div class="title flexacenter">
|
||||
<div class="dot"></div>
|
||||
该项目已加入对比单,未加入项目管理
|
||||
</div>
|
||||
<div class="btn flexcenter"><img class="img" src="/img/add-circle.svg" />加入项目管理</div>
|
||||
</div>
|
||||
<div style="display: none;" class="already flexacenter">
|
||||
<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" @click="openMoreSelect(index)" class="circle flexcenter">
|
||||
<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()"></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('list',item,index)"><img class="img" src="/img/add-circle.svg" />加入{{ item.contraststatus?.status == 1 ? '项目管理' : '对比单' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name flexflex">建筑硕士</div>
|
||||
<div class="english">Master of Architecture</div>
|
||||
<div class="name flexflex">{{ item.name_zh }}</div>
|
||||
<div class="english">{{ item.name_en }}</div>
|
||||
<div class="introduce flexacenter">
|
||||
建筑学院
|
||||
<div class="flexacenter">
|
||||
{{ item.department }}
|
||||
<div class="flexacenter" v-if="item.rank">
|
||||
<div class="line">|</div>
|
||||
专业排名
|
||||
<div class="quantity">52</div>
|
||||
<div class="quantity">{{ item.rank }}</div>
|
||||
</div>
|
||||
<div class="flexacenter">
|
||||
<div class="flexacenter" v-if="item.tuition_fee_text">
|
||||
<div class="line">|</div>
|
||||
学费HK$ <vie class="quantity">281,000</vie>
|
||||
学费HK$
|
||||
<div class="quantity">{{ item.tuition_fee_text }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word">一句话描述独特之处,一句话描述独特之处。</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 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -193,14 +201,32 @@
|
||||
const { createApp, ref, onMounted, nextTick, onUnmounted, computed } = Vue
|
||||
const projectSchool = createApp({
|
||||
setup() {
|
||||
const dataListRef = ref(null)
|
||||
onMounted(() => {
|
||||
console.log("onMounted")
|
||||
|
||||
window.addEventListener("scroll", handleScroll)
|
||||
getBaseData().then(data => {
|
||||
console.log("data", data)
|
||||
})
|
||||
getinit()
|
||||
getProjectData()
|
||||
|
||||
listMasonryInstance = new Masonry(dataListRef.value, {
|
||||
itemSelector: ".item",
|
||||
gutter: 10,
|
||||
})
|
||||
})
|
||||
|
||||
let id = 309
|
||||
const handleScroll = () => {
|
||||
const scrollHeight = document.documentElement.scrollHeight
|
||||
const clientHeight = document.documentElement.clientHeight
|
||||
const scrollTop = window.pageYOffset
|
||||
|
||||
if (scrollTop + clientHeight >= scrollHeight) {
|
||||
calculateShowList()
|
||||
}
|
||||
}
|
||||
|
||||
let id = 309
|
||||
let info = ref({})
|
||||
let hotList = ref([])
|
||||
let discipline = ref([])
|
||||
@ -223,7 +249,6 @@
|
||||
twoDimensionalArray.push(list.slice(i, i + 4))
|
||||
}
|
||||
|
||||
console.log("twoDimensionalArray", twoDimensionalArray)
|
||||
info.value = data.info
|
||||
hotList.value = twoDimensionalArray
|
||||
hotListTotalPage.value = twoDimensionalArray.length
|
||||
@ -261,7 +286,7 @@
|
||||
if (hotListPage.value < hotListTotalPage.value) hotListPage.value++
|
||||
}
|
||||
hotListRef.value.scrollTo({
|
||||
left: 1152 * (hotListPage.value - 1),
|
||||
left: 1153.2 * (hotListPage.value - 1),
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
@ -288,10 +313,196 @@
|
||||
projectid: item.id,
|
||||
}).then(res => {
|
||||
baseRef.value.calculate(random, res.data.count)
|
||||
|
||||
if (type == "hot") hotList.value[index][i]["contraststatus"] = 1
|
||||
if (type == "list") {
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let count = ref(0)
|
||||
let listAll = []
|
||||
let screenList = []
|
||||
let showList = ref([])
|
||||
let page = ref(1)
|
||||
let screen = ref({
|
||||
pitch: "all",
|
||||
name: "",
|
||||
state: "",
|
||||
})
|
||||
|
||||
const getProjectData = () => {
|
||||
$ajaxget("/api/project.lists", {
|
||||
limit: 2000,
|
||||
page: 1,
|
||||
sid: id,
|
||||
}).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.forEach(element => {
|
||||
const semester = element.semester || {}
|
||||
|
||||
if (month > semester.month && year + 1 <= semester.year) element["semesterState"] = true
|
||||
|
||||
element["tuition_fee_text"] = formatNumberWithSpaces(element.tuition_fee)
|
||||
element["random"] = randomString(6)
|
||||
element["rankk"] = convertRankToRankText(element.rank)
|
||||
})
|
||||
|
||||
listAll = list
|
||||
// screenList = list
|
||||
count.value = data.count
|
||||
|
||||
screenData()
|
||||
})
|
||||
}
|
||||
|
||||
const 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
|
||||
}
|
||||
|
||||
let sortIndex = ref(0) // 排名由高到低 0 学费由低到高 1 学费由高到低 2
|
||||
|
||||
// 筛选数据
|
||||
const screenData = () => {
|
||||
const sort = sortIndex.value
|
||||
const disciplineid = screen.value["disciplineid"]
|
||||
const university = screen.value["university"]
|
||||
let list = []
|
||||
if (disciplineid > 0) {
|
||||
screenList = listAll.filter(item => item.disciplineid === disciplineid)
|
||||
} else if (university) {
|
||||
screenList = listAll.filter(item => item.department === university)
|
||||
} else {
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
count.value = screenList.length
|
||||
showList.value = []
|
||||
page.value = 1
|
||||
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)
|
||||
|
||||
// console.log(showList.value)
|
||||
page.value = endIndex >= screenList.length ? 0 : page.value + 1
|
||||
nextTick(() => {
|
||||
listMasonryInstance.reloadItems()
|
||||
listMasonryInstance.layout()
|
||||
})
|
||||
}
|
||||
|
||||
const openMoreSelect = (index) => {
|
||||
closeMoreSelectAll()
|
||||
showList.value[index]["moreState"] = true
|
||||
}
|
||||
|
||||
// 点击选择 中间 的 筛选
|
||||
const selectScreen = type => {
|
||||
screen.value["pitch"] = type
|
||||
if (type == "all") {
|
||||
screen.value["disciplineid"] = ""
|
||||
screen.value["university"] = ""
|
||||
screen.value["list"] = []
|
||||
page.value = 1
|
||||
sortIndex.value = 0
|
||||
screenData()
|
||||
return
|
||||
}
|
||||
|
||||
if (type == "subject") {
|
||||
console.log(discipline.value)
|
||||
screen.value["university"] = ""
|
||||
screen.value["disciplineid"] = discipline.value[0].disciplineid
|
||||
screen.value["list"] = discipline.value
|
||||
} else if (type == "school") {
|
||||
screen.value["disciplineid"] = ""
|
||||
screen.value["university"] = universitydepartment.value[0].value
|
||||
screen.value["list"] = universitydepartment.value
|
||||
}
|
||||
sortIndex.value = 1
|
||||
screenData()
|
||||
}
|
||||
|
||||
const selectScreenItem = item => {
|
||||
const pitch = screen.value["pitch"]
|
||||
if (pitch == "subject") {
|
||||
screen.value["disciplineid"] = item.disciplineid
|
||||
screen.value["university"] = ""
|
||||
} else if (pitch == "school") {
|
||||
screen.value["disciplineid"] = ""
|
||||
screen.value["university"] = item.value
|
||||
}
|
||||
|
||||
screenData()
|
||||
}
|
||||
|
||||
// 关闭所有 状态 选择 弹出框
|
||||
const closeMoreSelectAll = type => {
|
||||
showList.value.forEach(element => {
|
||||
element["moreState"] = false
|
||||
})
|
||||
}
|
||||
|
||||
@ -313,6 +524,15 @@
|
||||
handleClick,
|
||||
|
||||
baseRef,
|
||||
count,
|
||||
|
||||
showList,
|
||||
openMoreSelect,
|
||||
screen,
|
||||
selectScreen,
|
||||
selectScreenItem,
|
||||
dataListRef,
|
||||
closeMoreSelectAll,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
@ -6,9 +6,15 @@
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="/css/common.css" />
|
||||
<link rel="stylesheet" href="/css/subject.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>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
<div class="main" id="app">
|
||||
<img class="index-icon" src="/img/index-icon.png" />
|
||||
|
||||
<div class="box">
|
||||
@ -17,108 +23,325 @@
|
||||
<img class="img" src="/img/arrows.svg" />
|
||||
按学科查看
|
||||
<img class="img" src="/img/arrows.svg" />
|
||||
<div class="current">建筑及城市规划</div>
|
||||
<div class="current">{{ title }}</div>
|
||||
</div>
|
||||
<div class="info flexacenter">
|
||||
<img class="img" src="/img/subject.png" />
|
||||
<div class="flex1">
|
||||
<div class="title">学科领域</div>
|
||||
<div class="list flexflex">
|
||||
<div class="item pitch">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item">建筑及城市规划</div>
|
||||
<div class="item flexacenter" :class="{'pitch': item.value == id}" v-for="(item,index) in discipline" @click="cutDiscipline(item.value)">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="body flexflex">
|
||||
<div class="left">
|
||||
<div class="item flexacenter pitch"><img class="img" src="/img/side-all-pitch.png" />全部项目</div>
|
||||
<div class="item flexacenter"><img class="img" src="https://axure-file.lanhuapp.com/md5__226be23041eb582c15651be885eb13cd.png" />香港大学</div>
|
||||
<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>
|
||||
</div>
|
||||
<div class="right flex1">
|
||||
<div class="h flexacenter">
|
||||
<div class="total">共 113 个项目</div>
|
||||
<div class="total">共 {{ count }} 个项目</div>
|
||||
<div class="item flexacenter">
|
||||
学费由低到高
|
||||
<img class="img-sort" src="/img/sort-icon.png" />
|
||||
</div>
|
||||
|
||||
<div class="item flexacenter">
|
||||
<div class="item flexacenter" v-if="sid">
|
||||
学校主页
|
||||
<img class="img-school" src="/img/sort-icon.png" />
|
||||
<img class="img-school" src="/img/arrows-circle-black.svg" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list flexflex">
|
||||
<div class="item">
|
||||
<div class="list flexflex" ref="dataListRef">
|
||||
<div class="item" v-for="(item,index) in showList">
|
||||
<div class="operate flexcenter">
|
||||
<div style="display: none;" class="circle flexcenter">
|
||||
<img class="img-add" src="/img/add-thick.svg" />
|
||||
</div>
|
||||
<div class="circle flexcenter">
|
||||
<img class="img-dot" src="/img/dot-dot-dot.png" />
|
||||
</div>
|
||||
<div class="select flexflex show">
|
||||
<div class="title flexacenter">
|
||||
<div class="dot"></div>
|
||||
该项目已加入对比单,未加入项目管理
|
||||
</div>
|
||||
<div class="btn flexcenter"><img class="img" src="/img/add-circle.svg" />加入项目管理</div>
|
||||
</div>
|
||||
<div style="display: none;" class="already flexacenter">
|
||||
<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" @click="openMoreSelect(index)" class="circle flexcenter">
|
||||
<img class="img-dot" src="/img/dot-dot-dot.png" />
|
||||
</div>
|
||||
<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}">
|
||||
<div class="title flexacenter">
|
||||
<div class="dot"></div>
|
||||
{{ item.contraststatus?.status == 1 ? '该项目已加入对比单,未加入项目管理' : '该项目已加入项目管理,未加入对比单' }}
|
||||
</div>
|
||||
<div class="btn flexcenter" @click="handleClick(item,index)"><img class="img" src="/img/add-circle.svg" />加入{{ item.contraststatus?.status == 1 ? '项目管理' : '对比单' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name flexflex">建筑硕士</div>
|
||||
<div class="english">Master of Architecture</div>
|
||||
<div class="name flexflex">{{ item.name_zh }}</div>
|
||||
<div class="english">{{ item.name_en }}</div>
|
||||
<div class="introduce flexacenter">
|
||||
建筑学院
|
||||
<div class="flexacenter">
|
||||
{{ item.department }}
|
||||
<div class="flexacenter" v-if="item.rank">
|
||||
<div class="line">|</div>
|
||||
专业排名
|
||||
<div class="quantity">52</div>
|
||||
<div class="quantity">{{ item.rank }}</div>
|
||||
</div>
|
||||
<div class="flexacenter">
|
||||
<div class="flexacenter" v-if="item.tuition_fee_text">
|
||||
<div class="line">|</div>
|
||||
学费HK$ <vie class="quantity">281,000</vie>
|
||||
学费HK$ <vie class="quantity">{{ item.tuition_fee_text }}</vie>
|
||||
</div>
|
||||
</div>
|
||||
<div class="word">一句话描述独特之处,一句话描述独特之处。</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 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部 -->
|
||||
<div class="base flexcenter">
|
||||
<div class="left flexacenter">
|
||||
<div class="text flex1">搜索项目</div>
|
||||
<img class="img" src="/img/search-black-icon.svg" />
|
||||
</div>
|
||||
<div class="rigth flexacenter">
|
||||
<img class="img" src="/img/contrast-icon.png" />
|
||||
<div class="text">项目对比</div>
|
||||
<div class="number">16</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-bottom ref="baseRef"></base-bottom>
|
||||
</div>
|
||||
<script>
|
||||
function name() {
|
||||
return "123"
|
||||
}
|
||||
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
|
||||
console.log("page", page.value)
|
||||
|
||||
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")
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -29,6 +29,8 @@ const base = {
|
||||
this.count = count
|
||||
|
||||
const dom = document.querySelector(".add" + random)
|
||||
if (!dom) return
|
||||
|
||||
const rect = dom.getBoundingClientRect()
|
||||
const top = rect.top + rect.height / 2 - 5
|
||||
const left = rect.left + rect.width / 2 - 5
|
||||
|
52
js/common.js
52
js/common.js
@ -79,7 +79,6 @@ function objectToQueryString(obj = {}) {
|
||||
return queryString ? "?" + queryString : ""
|
||||
}
|
||||
|
||||
|
||||
function decodeKey(encrypted, key) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
@ -87,12 +86,16 @@ function decodeKey(encrypted, key) {
|
||||
|
||||
const encryptedData = CryptoJS.enc.Base64.parse(encrypted)
|
||||
|
||||
const decrypted = CryptoJS.AES.decrypt({
|
||||
ciphertext: encryptedData
|
||||
}, CryptoJS.enc.Utf8.parse(decodekey), {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
})
|
||||
const decrypted = CryptoJS.AES.decrypt(
|
||||
{
|
||||
ciphertext: encryptedData,
|
||||
},
|
||||
CryptoJS.enc.Utf8.parse(decodekey),
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
}
|
||||
)
|
||||
|
||||
const text = JSON.parse(decrypted.toString(CryptoJS.enc.Utf8))
|
||||
resolve(text)
|
||||
@ -100,4 +103,37 @@ function decodeKey(encrypted, key) {
|
||||
reject()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getBaseData() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const storedTime = localStorage.getItem("dataTimestamp")
|
||||
const storedData = localStorage.getItem("basicData")
|
||||
|
||||
const currentTime = new Date().getTime()
|
||||
const timeDiff = currentTime - parseInt(storedTime)
|
||||
if (storedTime && storedData && timeDiff <= 5 * 60 * 1000) {
|
||||
// 在5分钟内,使用本地存储的数据
|
||||
const basicData = JSON.parse(storedData)
|
||||
// 处理数据
|
||||
resolve(basicData)
|
||||
}
|
||||
|
||||
$ajaxget("/api/project.home/basicData").then(res => {
|
||||
if (res.code != 200) return
|
||||
const data = res.data
|
||||
const basicData = {
|
||||
contrastcount: data.contrastcount || 0,
|
||||
university: data.university,
|
||||
discipline: data.discipline,
|
||||
rankings: data.rankings,
|
||||
encodekey: data.encodekey,
|
||||
}
|
||||
|
||||
// 更新本地存储的时间戳和数据
|
||||
localStorage.setItem("dataTimestamp", new Date().getTime())
|
||||
localStorage.setItem("basicData", JSON.stringify(basicData))
|
||||
resolve(basicData)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user