This commit is contained in:
A1300399510
2024-01-05 18:20:39 +08:00
parent 8fac6121c2
commit bb91a032e9
75 changed files with 2121 additions and 1204 deletions

View File

@@ -23,28 +23,60 @@
个面经
</div>
<div class="mj-list" @scroll="handleListScroll">
<a class="mj-item flexflex" :class="{ pitch: pitchIndex == index }" v-for="(item, index) in relatedlist" :key="index" @click.stop.prevent="handleItem(item['uniqid'])" :href="`./details/${item['uniqid']}`">
<div class="mj-header flexacenter">
<img class="mj-avatar" :src="item['avatar']" />
<div class="user-name">{{ item["username"] || "匿名用户" }}</div>
<div class="time">{{ handleDate(item["releasetime"]) }}发布</div>
</div>
<template v-for="(item, index) in relatedlist" :key="index">
<a v-if="item['type']" class="mj-item flexflex recommend" :href="item?.url" target="_blank">
<div class="mj-header flexacenter">
<div class="label flexcenter">推荐阅读</div>
<h1>{{ item["title"] }}</h1>
</div>
<div class="info-list flexflex">
<div class="info-item flexacenter" v-if="item['profession']">
<div class="info-name">专业</div>
<div class="info-value flex1 ellipsis">{{ item["profession"] }}</div>
<div class="info-list flexflex" v-if="item['type'] == 'offer'">
<div class="info-item flexacenter">
<div class="info-name">专业</div>
<div class="info-value flex1 ellipsis">{{ item["professional"] }}</div>
</div>
<div class="info-item flexacenter">
<div class="info-name">学位</div>
<div class="info-value flex1 ellipsis">{{ item["degree"] }}</div>
</div>
<div class="info-item flexacenter">
<div class="info-name">结果</div>
<div class="info-value flex1 ellipsis">{{ item["apply_results"] }}</div>
</div>
</div>
<div class="info-item flexacenter" v-if="item['project']">
<div class="info-name">项目</div>
<div class="info-value flex1 ellipsis">{{ item["project"] }}</div>
<div class="thread-text ellipsis flexflex" v-if="item['type'] == 'thread' || item['type'] == 'ask'">
<div class="ask-label" v-if="item['type'] == 'ask'">回答</div>
<div class="flex1 ellipsis">{{ item["message"] }}</div>
</div>
<div class="info-item flexacenter" v-if="item['interviewtime']">
<div class="info-name">时间</div>
<div class="info-value flex1 ellipsis">{{ item["interviewtime"] }}</div>
<div class="vote-list" v-if="item['type'] == 'vote'">
<div class="vote-item" v-for="(ite, i) in item['option'].slice(0, 2)" :key="i">{{ numberToEnclosed(i) }} &nbsp; {{ ite }}</div>
<div class="vote-item">{{ numberToEnclosed(3) }} &nbsp; </div>
</div>
</div>
</a>
</a>
<a v-else class="mj-item flexflex" :class="{ pitch: pitchIndex == index }" @click.stop.prevent="handleItem(item['uniqid'])" :href="`./details/${item['uniqid']}`">
<div class="mj-header flexacenter">
<img class="mj-avatar" :src="item['avatar']" />
<div class="user-name">{{ item["username"] || "匿名用户" }}</div>
<div class="time">{{ handleDate(item["releasetime"]) }}发布</div>
</div>
<div class="info-list flexflex">
<div class="info-item flexacenter" v-if="item['profession']">
<div class="info-name">专业</div>
<div class="info-value flex1 ellipsis">{{ item["profession"] }}</div>
</div>
<div class="info-item flexacenter" v-if="item['project']">
<div class="info-name">项目</div>
<div class="info-value flex1 ellipsis">{{ item["project"] }}</div>
</div>
<div class="info-item flexacenter" v-if="item['interviewtime']">
<div class="info-name">时间</div>
<div class="info-value flex1 ellipsis">{{ item["interviewtime"] }}</div>
</div>
</div>
</a>
</template>
</div>
</div>
<!-- <div class="right flex1" @scroll="handleCommentsScroll" v-loading="detailsLoading"> -->
@@ -75,10 +107,12 @@
<div class="user-name">{{ info["nickname"] || "匿名用户" }}</div>
<div class="time">{{ handleDate(info["releasetime"]) }}发布</div>
</div>
<div class="mj-header-right flexacenter" v-if="isBrowser">
<img class="eye-icon" src="@/assets/img/eye-icon.svg" />
{{ info["views"] }}
</div>
<a class="mj-header-right flexacenter" target="_blank" :href="info['threadurl']">
<img class="original-icon" src="@/assets/img/original-icon.png" />
论坛原帖
<!-- <img class="eye-icon" src="@/assets/img/eye-icon.svg" /> -->
<!-- {{ info["views"] }} -->
</a>
</div>
</div>
<div class="details-box">
@@ -263,6 +297,10 @@
<div class="floor-area flexacenter">
<div class="floor-content flexacenter">
<div class="floor-left flexacenter">
<div class="item flexacenter" v-if="isBrowser" style="cursor: auto;">
<img class="icon" src="@/assets/img/eye-icon-black.svg" />
{{ info["views"] }}
</div>
<div class="item flexacenter" @click="handleLike">
<img class="icon" v-if="islike == 1" src="@/assets/img/like-icon-colours.png" />
<img class="icon" v-else src="@/assets/img/like-icon.png" />
@@ -278,7 +316,7 @@
<ClientOnly>
<el-popover placement="bottom" width="628px" trigger="click" popper-style="padding: 0;border-radius: 10px;" v-model:visible="transmitBoxState">
<template #reference>
<div class="item flexacenter"><img class="icon" src="@/assets/img/transmit-icon.png" />转发</div>
<div class="item flexacenter" @click="handleShare"><img class="icon" src="@/assets/img/transmit-icon.png" />转发</div>
</template>
<div class="transmit-box flexflex">
@@ -306,6 +344,18 @@
</ClientOnly>
</div>
<div class="floor-middle flexacenter coin-box">
<div class="coin-content flexacenter flex1" @click="openCoinRankList">
<img class="coin-icon" src="@/assets/img/coin-icon.png" />
<div class="coin-text flex1 flexacenter">
已获
<div class="coin-value">{{ info.coins }}</div>
个寄托币
</div>
</div>
<div class="coin-btn flexcenter" @click="openCoinOperation()">给TA投币</div>
</div>
<div class="floor-right flexacenter" @mouseenter="handleFloorRight(true)" @mouseleave="handleFloorRight(false)">
手机查看该面经
<img class="arrows-icon" src="@/assets/img/arrows-icon.png" />
@@ -323,6 +373,58 @@
</div>
<Report v-if="reportAlertShow" :reportToken="reportToken"></Report>
</div>
<!-- 投币操作 弹窗 -->
<div class="pop-masking flexcenter" v-if="isInsertCoinsOperationShow">
<div class="slit-pop-box" v-if="coinMybalance > 0" style="border-radius: 11px;">
<div class="slit-left" style="width: 50px;">
<img class="slit-left-icon" src="//app.gter.net/image/gter/offer/imgdetails/u620.png" style="margin-top: -8px;" />
</div>
<div class="slit-box">
<div class="slit-head" style="flex: 1; flex-direction: column; align-items: flex-start;">
<div class="slit-head-title flexflex" style="width: 100%; justify-content: space-between;">
<span>投币</span>
<div class="in-all">
你共有 <span>{{ coinMybalance }}</span> 寄托币
</div>
<!-- <a target="_blank" :href="coinConfig.strategy.url" style="font-weight: 100; font-size: 13px; text-decoration: underline;">{{ coinConfig.strategy.button }}</a> -->
</div>
</div>
<div class="coin-quantity flexacenter">
<div class="coin-quantity-item" :class="{ 'coin-pitch': coinAmount == item }" v-for="(item, index) in coinConfig.list" :key="index" @click="coinSelectAmountDispose(item)">
{{ item }} <span>{{ coinConfig.unit }}</span>
</div>
</div>
<el-input class="slit-input" v-model="coinAmount" placeholder="自定义投币金额" show-word-limit="false"> </el-input>
<div class="message-box">
<div class="message-hint">顺便说点什么</div>
<el-input class="slit-input" style="font-size: 15px;" v-model="coinMessage" placeholder="请输入" maxlength="500" show-word-limit> </el-input>
</div>
<div class="operation">
<div class="operation-item flexcenter" @click="isInsertCoinsOperationShow = !isInsertCoinsOperationShow">取消</div>
<div class="operation-item flexcenter greenBj" @click="postCoinSbmit()">确定</div>
</div>
</div>
</div>
<div class="no-jituobi-pop-box" v-else>
<img class="no-jituobi-close" @click="isInsertCoinsOperationShow = !isInsertCoinsOperationShow" src="@/assets/img/cross-icon.png" />
<div class="no-jituobi-head flexacenter">
<img class="bi-icon" src="//app.gter.net/image/gter/offer/imgdetails/u620.png" style="margin-right: 12px;" />
<span style="margin-top: 10px;">
{{ coinConfig?.strategy?.tips }}
</span>
</div>
<a :href="coinConfig?.strategy?.url" target="_blank">
<div class="strategy-btn greenBj flexcenter">{{ coinConfig?.strategy?.button }}<img class="strategy-icon" src="@/assets/img/strategy-icon.svg" /></div>
</a>
</div>
</div>
<!-- 投币 排行榜 -->
<RankingBox v-if="coinrankingState" :coinrankingList="coinrankingList"></RankingBox>
</template>
<script setup>
@@ -482,6 +584,8 @@ const getDetails = () => {
if (relatedlist.value.length == 0) getRelatedlistHttp()
else CalculateSelectedList()
if (JSON.stringify(coinConfig.value) == "{}") getCoinInfo()
detailsLoading.value = false
getCommentListHttp()
})
@@ -530,9 +634,7 @@ const getRelatedlistHttp = () => {
relatedlist.value = relatedlist.value.concat(data.data)
relatedcount.value = data.count
// if (data.count > re) relatedpage
// page++
if (relatedlist.value.length >= data["count"]) relatedpage.value = 0
else relatedpage.value++
@@ -645,10 +747,7 @@ const commentLike = (index, i) => {
targetCommentList[index].likenum = data["likenum"]
}
ElMessage({
message: res.message,
type: "success",
})
ElMessage.success(res.message)
})
}
@@ -1046,6 +1145,129 @@ const openAvatarPopover = (index, i) => {
if (i != null) commentList.value[index]["child"][i]["popoverState"] = true
else commentList.value[index]["popoverState"] = true
}
let isInsertCoinsOperationShow = ref(false) // 投票弹窗
let coinMybalance = ref({}) // 我的寄托币数量
let coinConfig = ref({}) // 投币的配置
let coinConnum = ref(0) // 寄托币数量
let coinRanklist = ref({}) // 投币排行榜
let coinAmount = ref(null) // 投币选择的金额
let coinCustomAmount = ref(null) // 投币自定义的金额
let defaultcoinnum = ref(0) // 投币金额默认寄托币数
let coinMessage = ref("") // 投币时的说点什么
let postCoinSbmitState = false // 投币中
// 获取寄托币
const getCoinInfo = () => {
coinHttp({ token }).then(res => {
if (res.code != 200) return
let data = res.data
coinConfig.value = data.config
coinMybalance.value = data.mybalance
coinRanklist.value = data.ranklist
defaultcoinnum.value = data.defaultcoinnum
})
}
// 打开寄托币弹窗
const openCoinOperation = () => {
isInsertCoinsOperationShow.value = true
}
// 处理投币的选择选项
const coinSelectAmountDispose = amount => {
coinAmount.value = amount
}
// 提交寄托币
const postCoinSbmit = () => {
if (postCoinSbmitState) return
postCoinSbmitState = true
coinsubmitHttp({
token,
coinnum: coinAmount.value,
message: coinMessage.value,
})
.then(res => {
if (res.code != 200) {
ElMessage.error(res.message)
return
}
let data = res.data
info.value.coins = info.value.coins + data["coinnum"]
coinMybalance.value = coinMybalance.value - data["coinnum"]
coinAmount.value = null
isInsertCoinsOperationShow.value = false
ElMessage.success(res.message)
if (data.comment) {
const userInfoWin = window.userInfoWin || {}
commentComments.value = data.comment.count
let newComment = {
avatar: userInfoWin["avatar"],
child: [],
childnum: 0,
content: coinMessage.value,
id: parseInt(data.comment.commentid),
...data.comment,
islike: 0,
likenum: 0,
nickname: userInfoWin["nickname"] || "匿名用户",
parentid: 0,
reply: [],
timestamp: generateTime(),
}
commentList.value.unshift(newComment)
}
coinMessage.value = ""
coinrankingList.value = []
})
.finally(() => (postCoinSbmitState = false))
}
let coinrankingList = ref([]) // 投币排行榜数据
let coinrankingState = ref(false) // 投币排行榜 弹窗状态
let coinrankingLoading = false // 投币排行榜加载中
const getCoinranking = () => {
if (coinrankingLoading) return
coinrankingLoading = true
coinrankingHttp({ token })
.then(res => {
if (res.code != 200) return
const data = res.data
coinrankingList.value = data
coinrankingState.value = true
})
.finally(() => (coinrankingLoading = false))
}
// 打开寄托币排行榜
const openCoinRankList = () => {
if (info.value.coins == 0) return
if (coinrankingList.value.length == 0) getCoinranking()
else coinrankingState.value = true
}
// 生成时间
const generateTime = () => {
let date = new Date()
let Y = date.getFullYear() + "-"
let M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-"
let D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " "
let h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":"
let m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()
return "" + Y + M + D + h + m
}
provide("coinrankingState", coinrankingState)
// 处理点击转发统计
const handleShare = () => shareHttp({ token })
</script>
<style lang="less" scoped>
@@ -1112,11 +1334,19 @@ const openAvatarPopover = (index, i) => {
}
.mj-list {
// &::-webkit-scrollbar {
// width: 6px !important;
// }
&::-webkit-scrollbar {
width: 6px !important;
width: 0 !important;
}
scrollbar-width: none;
-ms-overflow-style: none;
margin-right: 9px;
padding: 0 25px 15px 30px;
padding: 0 30px 15px;
flex: 1;
overflow: auto;
@@ -1129,6 +1359,62 @@ const openAvatarPopover = (index, i) => {
cursor: pointer;
position: relative;
&.recommend {
.mj-header {
display: inline-block;
.label {
background: rgba(114, 219, 134, 0.117647);
font-size: 12px;
color: #72db86;
padding: 0 5px;
display: inline-flex;
margin-right: 10px;
}
h1 {
display: inline;
font-weight: 650;
font-size: 14px;
color: #000000;
line-height: 26px;
// display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
.thread-text {
color: #555555;
font-size: 13px;
.ask-label {
color: #7f7f7f;
}
}
.vote-list {
color: #555555;
font-size: 13px;
.vote-item {
&:not(:last-of-type) {
margin-bottom: 6px;
}
}
}
}
&:hover::after {
content: "";
position: absolute;
background: #f6f6f6;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 10px;
z-index: -1;
}
&.pitch {
&::before,
&::after {
@@ -1140,7 +1426,7 @@ const openAvatarPopover = (index, i) => {
&::after {
top: 0;
left: 0;
width: 280px;
width: 100%;
height: 100%;
border-radius: 10px;
z-index: -1;
@@ -1148,7 +1434,7 @@ const openAvatarPopover = (index, i) => {
&::before {
top: 50%;
left: 280px;
left: 100%;
width: 10px;
height: 10px;
transform: translate(-64%, -50%) rotate(45deg);
@@ -1276,13 +1562,22 @@ const openAvatarPopover = (index, i) => {
}
.mj-header-right {
.eye-icon {
width: 13px;
height: 8px;
margin-right: 5px;
color: #333;
font-size: 14px;
cursor: pointer;
.original-icon {
width: 18px;
height: 16px;
margin-right: 7px;
}
font-size: 12px;
color: #aaaaaa;
// .eye-icon {
// width: 13px;
// height: 8px;
// margin-right: 5px;
// }
// font-size: 12px;
// color: #aaaaaa;
}
}
}
@@ -1726,6 +2021,45 @@ const openAvatarPopover = (index, i) => {
}
}
.floor-middle {
min-width: 300px;
height: 40px;
background-color: rgba(246, 246, 246, 1);
border-radius: 150px;
.coin-content {
padding: 0 13px;
height: 100%;
cursor: pointer;
.coin-icon {
width: 20px;
height: 24px;
margin-right: 5px;
margin-top: -2px;
}
.coin-text {
font-size: 13px;
color: #333333;
.coin-value {
font-family: "Arial-Black", "Arial Black", sans-serif;
font-weight: 900;
margin: 0 5px;
}
}
}
.coin-btn {
width: 97px;
height: 40px;
background-color: rgba(114, 219, 134, 1);
border-radius: 150px;
color: #ffffff;
font-size: 13px;
cursor: pointer;
}
}
.floor-right {
color: #7f7f7f;
font-size: 13px;
@@ -1837,4 +2171,204 @@ const openAvatarPopover = (index, i) => {
width: 113px;
height: 113px;
}
.pop-masking {
* {
box-sizing: content-box;
}
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.6);
z-index: 10;
.slit-pop-box {
width: 433px;
border: 1px solid #e5e5e5;
background-color: #fff;
border-radius: 20px;
padding: 60px 50px 48px 38px;
display: flex;
-webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.21);
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.21);
.slit-left-icon {
width: 50px;
height: 60px;
}
.slit-box {
flex: 1;
margin-left: 15px;
.slit-head {
display: flex;
align-items: center;
justify-content: space-between;
height: 54px;
.slit-head-title {
font-weight: 650;
font-size: 20px;
color: #333;
}
.in-all {
font-size: 13px;
color: #7f7f7f;
font-weight: 400;
& > span {
color: #000;
font-weight: 650;
}
}
}
.coin-quantity {
display: flex;
align-items: center;
margin-bottom: 27px;
margin-top: 20px;
}
.coin-quantity-item {
width: 78px;
height: 46px;
border: 1px solid #d7d7d7;
background-color: #f0f2f5;
border-radius: 5px;
font-size: 20px;
color: #000;
font-weight: 650;
line-height: 46px;
text-align: center;
cursor: pointer;
user-select: none;
& > span {
color: #555;
font-weight: 400;
font-size: 14px;
}
&:not(:last-of-type) {
margin-right: 16px;
}
&.coin-pitch {
background-color: #333333;
border-color: #333333;
color: #fff;
& > span {
color: #fff;
}
}
}
.slit-input {
width: 360px;
height: 38px;
padding-left: 8px;
border: 1px solid #d7d7d7;
outline: none;
border-radius: 8px;
/* 去掉number类型自带的加减按钮 */
overflow: hidden;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
}
&[type="number"] {
-moz-appearance: textfield;
}
/deep/ .el-input__wrapper {
box-shadow: none;
}
}
.message-box {
display: flex;
flex-direction: column;
.message-hint {
color: #000;
font-size: 14px;
margin-top: 29px;
margin-bottom: 12px;
}
}
.operation {
display: flex;
justify-content: flex-end;
margin-top: 48px;
.operation-item {
width: 120px;
height: 41px;
margin-left: 16px;
font-size: 16px;
color: #000;
border: 1px solid #797979;
border-radius: 45px;
cursor: pointer;
&.greenBj {
color: #fff;
}
}
}
}
}
}
.no-jituobi-pop-box {
width: 520px;
flex-direction: column;
border: 1px solid #e5e5e5;
background-color: #fff;
border-radius: 11px;
display: flex;
-webkit-box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.21);
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.21);
padding-bottom: 55px;
position: relative;
.no-jituobi-close {
width: 16px;
height: 16px;
cursor: pointer;
position: absolute;
top: 10px;
right: 10px;
}
.no-jituobi-head {
font-size: 15px;
color: #333;
margin: 38px auto 44px;
.bi-icon {
width: 50px;
height: 60px;
}
}
.strategy-btn {
width: 198px;
height: 43px;
color: #fff;
font-size: 16px;
border-radius: 100px;
margin: 0 auto;
cursor: pointer;
.strategy-icon {
width: 16px;
height: 16px;
margin-left: 8px;
}
}
}
.greenBj {
background-color: rgba(114, 219, 134, 1);
border-color: rgba(114, 219, 134, 1) !important;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<Head>
<Title>寄托天下 - 面经分享 </Title>
<Title>寄托天下 - 面经分享</Title>
<Meta name="keyword" content="留学资讯,留学交流论坛,留学面经,面试经验,寄托天下" />
</Head>
<TopHead></TopHead>