GterForumWeB/src/views/detail/detailIndex.vue
2023-10-16 18:43:39 +08:00

1494 lines
57 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="container">
<div class="detail-head flexacenter">
<div class="detail-section" @click="toAllSection()">
版块<span class="section-name">{{ info.forum }}</span>
</div>
<div class="detail-data flexacenter">
<div class="detail-data-item flexacenter"><img class="detail-data-eye" src="@/assets/img/detail/eye.png" />{{ info.views }}</div>
<div class="detail-data-item flexacenter"><img class="detail-data-comment" src="@/assets/img/detail/comment.png" />{{ info.replies }}</div>
</div>
</div>
<div></div>
<div class="detail-title-box">
<div class="detail-title-item detail-title-jinghua flexcenter" v-if="info.digest > 0">精华</div>
<div class="detail-title-item detail-title-label flexcenter" v-if="info.typename">{{ info.typename }}</div>
{{ info.subject }}
</div>
<!-- -->
<div class="card flexcenter">
<div class="card-item shadow">
<div class="card-head flexacenter">
<img class="card-head-icon" :src="info.avatar" />
<div class="card-head-content flex1 flexflex">
<div class="card-head-name flexflex">{{ info.author || "匿名用户" }}</div>
<div class="card-head-time">{{ $formattedDate(info.dateline || "") }}</div>
</div>
<div class="card-head-fool">楼主</div>
<a class="edit-box flexcenter" v-if="info.isauthor == 1" :href="`https://www.gter.net/bbs/post/edit.html?tid=${tid}&pid=${info.pid}`">
<img class="edit-icom" src="@/assets/img/detail/edit.png" />
</a>
</div>
<template v-if="type == 5">
<div class="summary-content">
<div class="summary-content-item" v-for="(item, index) in collegelist" :key="index">
<div class="summary-offer-head flexacenter">
<span class="summary-offer-head-title">Offer {{ index + 1 }}</span>
<a class="flexacenter" :href="item.url">详情<svg-icon icon-class="arrowsBlackLeft" class-name="summary-offer-head-icon"></svg-icon></a>
</div>
<div class="summary-offer-box">
<template v-for="(it, i) in offerinfoKey">
<div class="summary-offer-item flexacenter" :key="i" v-if="item[it.key]">
<div class="summary-offer-key flexacenter">{{ it.name }}</div>
<div class="summary-offer-value flexacenter">{{ item[it.key] }}</div>
</div>
</template>
</div>
</div>
<div class="summary-content-item">
<div class="summary-offer-head flexacenter">
<span class="summary-offer-head-title">总结</span>
<a class="flexacenter" :href="info.url">详情<svg-icon icon-class="arrowsBlackLeft" class-name="summary-offer-head-icon"></svg-icon></a>
</div>
<div class="summary-wenzi" v-html="info.message"></div>
</div>
<a class="examine-btn flexcenter" :href="info.url">
查看当前总结详情
<div class="examine-btn-outside flexcenter">
<svg-icon icon-class="arrowsRoundBlackLeft" class-name="examine-btn-icon"></svg-icon>
</div>
</a>
</div>
</template>
<template v-else-if="type == 6">
<div class="offer-content">
<div class="offer-content-box">
<template v-for="(item, index) in offerinfoKey">
<div class="offer-content-item flexacenter" :key="index" v-if="offerinfo[item.key]">
<div class="offer-content-key" v-if="offerinfo[item.key]">{{ item.name }}</div>
<div class="offer-content-value">{{ offerinfo[item.key] }}</div>
</div>
</template>
</div>
<a class="examine-btn flexcenter" :href="offerinfo.url">
查看当前捷报详情
<div class="examine-btn-outside flexcenter">
<svg-icon icon-class="arrowsRoundBlackLeft" class-name="examine-btn-icon"></svg-icon>
</div>
</a>
</div>
</template>
<template v-else-if="type == 2">
<div class="offer-content">
<div class="offer-content-box">
<template v-for="(item, index) in interviewKey">
<div class="offer-content-item flexacenter" :key="index" v-if="info[item.key]">
<div class="offer-content-key" v-if="info[item.key]">{{ item.name }}</div>
<div class="offer-content-value" v-html="info[item.key]"></div>
</div>
</template>
</div>
</div>
</template>
<template v-else-if="type == 3">
<div class="offer-content">
<div class="offer-content-box">
<template v-for="(item, index) in tenementKey">
<div class="offer-content-item flexacenter" :key="index" v-if="info[item.key]">
<div class="offer-content-key" v-if="info[item.key]">{{ item.name }}</div>
<div class="offer-content-value" v-if="item.key != 'school'" v-html="info[item.key]"></div>
<div class="offer-content-value" v-else>
<template v-for="it in info[item.key]">{{ it.name }}</template>
</div>
</div>
</template>
</div>
<div v-html="info.message" class="vHtmlMessage" style="margin: 0.52rem 0;"></div>
<img class="tenement-img" v-for="(item, index) in info.images" :key="index" :src="item" />
</div>
</template>
<template v-else>
<div class="offer-content">
<div style="line-height: normal;" ref="vHtmlMessage" class="vHtmlMessage"></div>
</div>
</template>
</div>
<template v-if="postList.list.length != 0">
<div class="card-item shadow" v-for="(item, index) in postList.list" :key="index">
<div class="card-head flexacenter">
<img class="card-head-icon" :src="item.avatar" />
<div class="card-head-content flex1 flexflex">
<div class="card-head-name flexflex">
{{ item.author || "匿名用户" }}
<div class="landlord flexcenter" v-if="item.isauthor == 1">楼主</div>
</div>
<div class="card-head-time">{{ $formattedDate(item.dateline) }}</div>
</div>
<div class="card-head-fool" v-if="postList.page == 1">{{ `${(postList.page - 1) * postList.limit + index + 2}楼` }}</div>
<div class="card-head-fool" v-else>{{ `${(postList.page - 1) * postList.limit + index + 1}楼` }}</div>
<div class="edit-box flexcenter" v-if="item.ismyself == 1" @click.stop="openEditPop(item)">
<img class="edit-icom" src="@/assets/img/detail/edit.png" />
</div>
</div>
<div class="card-content flex1" @click.stop="handleReplyPop(item)" v-html="item.message"></div>
</div>
</template>
</div>
<!-- 分页 -->
<div class="paging flexcenter" v-if="postList.count > postList.limit">
<el-pagination small background layout="prev, pager, next" @current-change="currentChange" :current-page.sync="postList.page" :page-size="postList.limit" :total="postList.count"> </el-pagination>
</div>
<!-- 底部 -->
<div class="discuss-bottom flexflex flexacenter">
<!-- 底部的轮播 -->
<div class="swiper">
<div class="bottom-item flexacenter">
<div class="bottom-comment flexacenter" @click="setValue('popState', 'discussionSingle')">
<svg-icon icon-class="pen" class-name="bottom-comment-icom"></svg-icon>
想问啥,大胆问
<div class="loginBtn" v-if="!islogin" @click.stop="setValue('isloginBtnState', true, 'boolean')"></div>
</div>
</div>
</div>
<div class="bottom-item flex1 flexacenter">
<div class="bottom-operation-box flex1 flexacenter">
<div class="bottom-operation-item flex1 flexcolumn flexcenter" @click="info.islike == 0 ? tapOperate('like') : ''">
<div class="loginBtn" v-if="!islogin" @click.stop="setValue('isloginBtnState', true, 'boolean')"></div>
<img v-if="info.islike == 0" class="bottom-operation-icom" :class="{prepareLiskeAnimateState: prepareLiskeAnimateState}" src="@/assets/img/detail/like.png" />
<img v-else class="bottom-operation-icom" :class="{prepareLiskeAnimateState: prepareLiskeAnimateState}" src="@/assets/img/icon/like-o.png" />
<div class="bottom-operation-text">{{ info.recommend_add == 0 ? "" : info.recommend_add }}赞</div>
</div>
<div class="bottom-operation-item flex1 flexcolumn flexcenter" @click="tapOperate(info.isfav == 0 ? 'collect' : 'uncollect')">
<div class="loginBtn" v-if="!islogin" @click.stop="setValue('isloginBtnState', true, 'boolean')"></div>
<img v-if="info.isfav == 0" class="bottom-operation-icom" src="@/assets/img/detail/collect.png" />
<img v-else class="bottom-operation-icom" src="@/assets/img/detail/collect-c.png" />
<div class="bottom-operation-text">收藏</div>
</div>
<div class="bottom-operation-item flex1 flexcolumn flexcenter transmit" data-clipboard-text="Text to copy" @click="transmit()">
<img class="bottom-operation-icom bottom-transmit-icom" src="@/assets/img/detail/share.png" />
<div class="bottom-operation-text">转发</div>
</div>
</div>
</div>
</div>
<detail-reply :two-comment-data="twoCommentData" :comment-content="commentContent" :pop-state="popState"></detail-reply>
<coins :coin-config="coinConfig" :mybalance="mybalance" :pop-state="popState" :info="info"></coins>
<div class="alert" v-show="alert.state" :class="{alertState: alert.state}">
<el-alert :title="alert.message" type="info" center show-icon :closable="false"></el-alert>
</div>
</div>
</template>
<script>
import DetailReply from "@/components/DetailReply"
import Coins from "@/components/unlock/Coins"
import {coinNo} from "@/utils/bizarreUrl"
import emojiList from "@/assets/emojiList.json"
export default {
name: "detailIndex",
data() {
return {
twoCommentData: null,
editCommentPid: null, // 编辑回复的 id
popState: "", // discussionSingle discussionMulti
coinConfig: {
strategy: {
button: "攒币指南",
tips: "你的寄托币不够,快去发帖挣币吧",
url: coinNo,
},
},
islogin: true,
// prepareLiskeState: false,
prepareLiskeAnimateState: false,
stat: {
like: 0,
},
iscollect: 0,
ispostOfferLike: null, // 点击点赞提交状态
offerLikesumTimer: 0, // offer点赞累加定时器
offerLikesumAnimateTimer: 0, // offer点赞动画定时器
listlist: [],
tid: 0, // 帖子id
info: {},
type: 0, // 定位帖 1 面经 2 租房帖 3 总结 5 捷报 6
token: "",
offerinfo: {}, // offer捷报详情
offerinfoKey: [
{
// offer 字段汇总
key: "schoolname",
name: "申请学校",
},
{
key: "degree",
name: "学位",
},
{
key: "professional",
name: "专业",
},
{
key: "project",
name: "项目",
},
{
key: "apply_results",
name: "申请结果",
},
{
key: "semester",
name: "入学学期",
},
{
key: "noticedate",
name: "通知时间",
},
{
key: "useperformanceStr",
name: "使用成绩",
},
],
shareurl: "", // 分享链接
collegelist: [], // 总结里的 offer 列表数据
tenementKey: [
{
// 租房 字段汇总
key: "typeText",
name: "出租方式",
},
{
key: "rent",
name: "月租/",
},
{
key: "property",
name: "房屋类型",
},
{
key: "floor",
name: "所在楼层",
},
{
key: "acreage",
name: "面积(平方呎)",
},
{
key: "locationText",
name: "所在区域",
},
{
key: "addressText",
name: "地段/地址",
},
{
key: "school",
name: "附近学校",
},
{
key: "gender",
name: "性别要求",
},
{
key: "rentaldurationText",
name: "出租时长",
},
{
key: "introduction",
name: "房东或合租人介绍",
},
{
key: "intermediary_text",
name: "发布者身份",
},
{
key: "telText",
name: "电话",
},
{
key: "wechatText",
name: "微信",
},
],
interviewKey: [
{
// 面经 字段汇总
name: "学校",
key: "school",
},
{
name: "专业",
key: "profession",
},
{
name: "项目",
key: "project",
},
{
name: "毕业时间",
key: "interviewtime",
},
{
name: "面试过程及内容",
key: "message",
},
],
postList: {
// 回复列表数据
list: [],
page: 1,
limit: 20,
count: 0,
},
loading: null, // 加载中
commentContent: "", // 评论的文本
operateState: false, // 操作请求的状态
mybalance: 0, // 一共有多个寄托币
islogin: false, // 登录状态
alert: {
state: false,
message: "",
},
isloginBtnState: false,
}
},
watch: {
popState(newV, oldV) {
if (newV) this.$pageStop()
else this.$pageMove()
},
"$store.state.user": {
handler(newV, oldV) {
if (JSON.stringify(newV) != "{}") {
this.islogin = newV.uid > 0 ? true : false
this.tid = this.$route.query["tid"]
this.postList.page = this.$route.query["page"] || 1
this.getDetail()
}
},
immediate: true,
},
isloginBtnState(newV, oldV) {
if (newV) this.$goTologin()
},
},
mounted() {
window.scrollTo(0, 0)
},
methods: {
// 获取详细信息
getDetail() {
this.$startupUnderLoading(this)
this.$http
.post("/api/thread", {
tid: this.tid,
})
.then(res => {
if (res.code != 200) return
let data = res.data
let info = data.info
info["message"] = info["message"].trim()
const reg = new RegExp("\r\n", "g")
info["message"] = info["message"].replaceAll(reg, "<br/>")
info["message"] = info["message"].replace(/<img[^>]*>/g, match => {
return match.replace(/width="[^"]*"/g, "").replace(/height="[^"]*"/g, "")
})
// 回复和投币可见解锁前的html
// let replyVisibleHtml = `<div class="flexcenter content-unlock content-unlock-no replyVisible" @click="setValue('popState', 'discussionSingle')"><img class="unlock-icom" src="./img/unlock.png"/>作者设置了${this.islogin ? '回复' : '登录'}可见</div>`
let replyVisibleHtml = `<div class="flexcenter content-unlock content-unlock-no ${this.islogin ? "replyVisible" : "registerVisible"} " @click="setValue('popState', ${this.islogin ? "discussionSingle" : "isloginBtnState"})"><img class="unlock-icom" src="${this.$baseURL}/img/unlock.png"/>作者设置了${this.islogin ? "回复" : "登录"}可见</div>`
let coinVisibleHtml = `<div class="flexcenter content-unlock content-unlock-no coinVisible"><img class="unlock-icom" src="${this.$baseURL}/img/unlock.png"/>作者设置了投币可见</div>`
// 回复和投币可见解锁后的html
let replyVisibleHtmlAlready = `<div class="content-unlock content-already"><div class="content-already-header flexflex">- 本内容投币可见 -</div><div class="content-unlock-wenzi">标记</div></div>`
let ispost = data.info.ispost // 是否已经回复
let price = data.info.price // 是否需要投币
let isbuy = data.info.isbuy // 是否已经投币
let isauthor = data.info.isauthor // 是否是作者
if (price > 0 && isbuy == 0 && isauthor != 1) {
let message = info["message"]
// if (message.indexOf("[free]") != -1) {
info["message"] = ""
const regex = /\[(free|hide)\]([^[]+)\[\/(free|hide)\]/g
let result = message.match(regex) || []
for (let i = 0; i < result.length; i++) {
result[i] = result[i].replace("[free]", "")
result[i] = result[i].replace("[/free]", "")
info["message"] += result[i]
}
info["message"] += coinVisibleHtml
// }
}
if (isbuy == 1 || isauthor == 1) {
let message = info["message"]
let mubiao = "" // 目标 message
// const regex = /\[(free|hide|\/free|\/hide)\]/g;
// const regex = /\[(free|hide|\/free|\/hide)\]/g;
// const regex = /\[(free|hide(?:=[0-9]+)?|\/free|\/hide)\]/g;
// const regex = /\[(free|hide(?:=[0-9]+)?|\/free|\/hide)\]/g;
// const regex = /\[(free|hide=\d+\|\/free|\/hide)\]/g;
// (?:=[0-9]+)?\
// const regex = /\[(free|hide(?:=[0-9]+)?|\/free|\/hide)\]/g;
const regex = /\[free\]|\[\/free\]|\[hide\]|\[\/hide\]|\[hide=[^\]]+\]/g
const numericIndices = Array.from(message.matchAll(regex), match => match.index)
const result2D = []
for (let i = 0; i < numericIndices.length; i += 2) {
const pair = [numericIndices[i], numericIndices[i + 1]]
result2D.push(pair)
}
result2D.forEach((element, index) => {
if (index != 0) {
let temporary = message.slice(result2D[index - 1][1] + 7, element[0])
temporary = this.goEmpty(temporary)
if (temporary) mubiao += replyVisibleHtmlAlready.replace("标记", message.slice(result2D[index - 1][1] + 7, element[0]))
}
// 第一个
if (index == 0) {
let temporary = message.slice(0, element[0])
temporary = this.goEmpty(temporary)
// if (temporary) mubiao += replyVisibleHtmlAlready.replace('标记', message.slice(0, element[0]))
if (temporary) mubiao += message.slice(0, element[0])
}
// 最后一个
if (index == result2D.length - 1) {
let temporary = message.slice(element[1] + 7, message.length - 1)
temporary = this.goEmpty(temporary)
if (temporary) mubiao += replyVisibleHtmlAlready.replace("标记", message.slice(element[1] + 7, message.length - 1))
}
mubiao += message.slice(element[0], element[1] + 7)
})
mubiao = mubiao.replaceAll("[free]", "")
mubiao = mubiao.replaceAll("[/free]", "")
info["message"] = mubiao
}
const regex1 = /\[hide(?:=[0-9]+)?\]/
if (regex1.test(info["message"])) {
// if (info['message'].indexOf("[hide]") != -1) {
const regex = /\[hide\].*?\[\/hide\]/g // 获取所有[hide] 中间内容的正则
if (ispost == 0 && isauthor != 1) info["message"] = info["message"].replace(regex, replyVisibleHtml)
if (ispost == 1 || isauthor == 1) {
// info['message'] = info['message'].replaceAll("[hide]", `<div class="content-unlock content-already"><div class="content-already-header flexflex">- 本内容回复可见 -</div><div class="content-unlock-wenzi">`)
var pattern = /\[hide(=\d+)?\]/g
info["message"] = info["message"].replaceAll(pattern, `<div class="content-unlock content-already"><div class="content-already-header flexflex">- 本内容回复可见 -</div><div class="content-unlock-wenzi">`)
info["message"] = info["message"].replaceAll("[/hide]", `</div></div>`)
}
}
if (!this.islogin && isbuy == 0) {
info["message"] = info["message"].replaceAll("[free]", "")
info["message"] = info["message"].replaceAll("[/free]", "")
}
data.type == 0 ? (this.$refs["vHtmlMessage"] ? (this.$refs.vHtmlMessage.innerHTML = info["message"]) : "") : ""
let replyVisibleList = document.getElementsByClassName("replyVisible")
if (!Array.isArray(replyVisibleList)) {
for (let i = 0; i < replyVisibleList.length; i++) {
replyVisibleList[i].addEventListener("click", () => {
this.$emit("replyVisibleClick")
})
}
this.$on("replyVisibleClick", () => {
this.popState = "discussionSingle"
})
}
let coinVisibleList = document.getElementsByClassName("coinVisible")
if (!Array.isArray(coinVisibleList)) {
for (let i = 0; i < coinVisibleList.length; i++) {
coinVisibleList[i].addEventListener("click", () => {
this.$emit("coinVisibleClick")
})
}
this.$on("coinVisibleClick", () => {
this.popState = data.mybalance > price ? "coindisplayuser" : "coinNo"
})
}
let registerVisibleList = document.getElementsByClassName("registerVisible")
if (!Array.isArray(registerVisibleList)) {
for (let i = 0; i < registerVisibleList.length; i++) {
registerVisibleList[i].addEventListener("click", () => {
this.$emit("registerVisibleClick")
})
}
this.$on("registerVisibleClick", () => {
this.isloginBtnState = true
})
}
this.info = info
this.type = data.type
this.token = data.token
this.mybalance = data.mybalance
if (this.type == 6) this.getOfferDetail()
else if (this.type == 5) this.getsummaryDetails()
else if (this.type == 3) this.getTenementDetails()
else if (this.type == 2) this.getInterviewDetails()
info["replies"] != 0 ? this.getPostList() : ""
// this.getPostList()
})
.finally(() => {
this.$closeUnderLoading(this)
})
},
// 去 回车和去前后的空格
goEmpty(temporary) {
temporary = temporary.trim()
while (temporary.indexOf("<br/>") != -1) {
temporary = temporary.replace("<br/>", "")
}
return temporary
},
// 获取offer详情
getOfferDetail() {
this.$http
.get(
"/api/forum/details",
{
id: this.token,
},
"offer"
)
.then(res => {
let data = res.data
let offerinfo = data.collegelist[0]
let useperformanceStr = ""
offerinfo.useperformance &&
offerinfo.useperformance.forEach((el, index) => {
useperformanceStr += el + (offerinfo.useperformance.length - 1 == index ? "" : "、")
})
offerinfo["useperformanceStr"] = useperformanceStr
this.offerinfo = offerinfo
})
},
// 获取总结详情
getsummaryDetails() {
this.$http
.get(
`/api/forum/details`,
{
id: this.token,
},
"offer"
)
.then(res => {
let data = res.data
let collegelist = data.collegelist
collegelist.forEach((el, index) => {
let useperformanceStr = ""
el.useperformance &&
el.useperformance.forEach((element, i) => {
useperformanceStr += element + (el.useperformance.length - 1 == i ? "" : "、")
})
el["useperformanceStr"] = useperformanceStr
})
this.info = {...this.info, ...data.info}
this.collegelist = collegelist
this.shareurl = data.shareurl
})
},
// 租房
getTenementDetails() {
this.$http
.post(
"/tenement/forum/show",
{
token: this.token,
},
"tenement"
)
.then(res => {
if (res.code == 201) this.tenementInfoState = true
let tenementKey = this.tenementKey
let info = {...this.info, ...res.info}
info["typeText"] = info.gptype + ">>" + info.type
tenementKey[1].name += info["currency"] ? info["currency"] : "港元"
if (info.cityid == 1) info["locationText"] = info.location
else info["locationText"] = info.country + ">>" + info.city
info["addressText"] = info["address"] || "-"
info["rentaldurationText"] = info.rentalduration || "不限"
info["telText"] = info.tel || "-"
info["wechatText"] = info.wechat || "-"
const reg = new RegExp("\r\n", "g")
info["message"] = info["message"].replaceAll(reg, "<br/>")
info["message"] = info["message"].replace(/<img[^>]*>/g, match => {
return match.replace(/width="[^"]*"/g, "").replace(/height="[^"]*"/g, "")
})
this.info = info
})
},
// 获取面经详情
getInterviewDetails() {
this.$http
.post(
"/InterviewExperience/thread",
{
tid: this.tid,
token: this.token,
},
"tenement"
)
.then(res => {
if (res.code != 200) return
let data = res.data
this.info = {...this.info, ...data}
})
},
// 获取回复列表
getPostList() {
this.$startupUnderLoading(this)
let {page, limit} = this.postList
this.$http
.post("/api/thread/postList", {
token: this.token,
page,
limit,
})
.then(res => {
if (res.code != 200) return
let data = res.data
data.data.forEach(el => {
for (const key in emojiList) {
el.message = el.message.replaceAll(key, `<img class="gif" src="${emojiList[key]}" />`)
}
})
this.postList.list = data.data
this.postList.page = data.page
this.postList.limit = data.limit
this.postList.count = data.count
})
.finally(() => {
this.$closeUnderLoading(this)
})
},
// 打开编辑评论
openEditPop(item) {
let message = item.message
message = message.replace(/<div[^>]*>[\s\S]*?<\/div>/gi, "") // 清除掉引有的结构
// message = message.replace(/<[^>]*>/g, ''); // 清除掉引有的结构
message = message.trim()
this.commentContent = message
this.editCommentPid = item.pid
this.popState = "discussionMulti"
},
// 处理回复点击弹出弹窗
handleReplyPop(item) {
let message = item.message
// message = message.replace(/<(*?)[^>]*>[\s\S]*?<\/(*?)>/gi, ''); // 清除掉引有的结构
message = message.replace(/<[^>]*>/g, "") // 清除掉引有的结构
message = message.trim()
this.twoCommentData = {
avatar: item.avatar,
content: message,
pid: item.pid,
}
this.popState = "discussionSingle"
},
// 集中处理回复帖子
postComment(message) {
let url = ""
if (this.editCommentPid) url = "/api/operation/redactPost"
// 回复评论或者评论
else url = "/api/operation/reply" // 编辑评论
this.$http
.post(url, {
token: this.token,
message: this.commentContent,
pid: this.editCommentPid || (this.twoCommentData && this.twoCommentData.pid),
})
.then(res => {
if (res.code != 200) return
this.$Message.success("发布成功")
this.popState = ""
this.twoCommentData = null
if (this.editCommentPid) {
// 编辑 状态
setTimeout(() => {
this.$router.go(0)
}, 800)
return
}
this.editCommentPid = null
let {count, limit} = this.postList
let page = Math.ceil((count + 1) / limit)
setTimeout(() => {
if (page == this.postList.page) {
this.$router.go(0)
clearTimeout(timer)
return
}
let query = {
page,
tid: this.tid,
}
this.$router.push({path: `/detailIndex`, query})
}, 800)
})
},
// 点击改变页数
currentChange() {
let query = {
page: this.postList.page,
tid: this.tid,
}
this.getPostList()
this.$updateURLSearchParams(query)
},
// 点击点赞和收藏操作
tapOperate(key) {
// like collect uncollect
// this.openHintBox("dfl;kgjdfkljgklioj")
if (this.operateState) return
this.operateState = true
let url = ""
if (key == "like") url = "/api/operation/threadLike"
else if (key == "collect") url = "/api/operation/threadFav"
else if (key == "uncollect") url = "/api/operation/threadunFav"
this.$http
.post(url, {tid: this.tid})
.then(res => {
if (res.code != 200) return
if (key == "like") (this.info.islike = 1), this.info.recommends + 1
if (key == "collect") this.info.isfav = 1
if (key == "uncollect") this.info.isfav = 0
// this.$message(res.message)
this.openHintBox(res.message)
})
.finally(() => {
this.operateState = false
})
},
// 点击转发
transmit() {
let value = location.href
this.$copy(value, "已经复制链接,欢迎分享!")
},
setValue(key, value) {
this[key] = value
},
// 跳转全部板块的列表
toAllSection() {
this.$router.push({path: `/allSections`, query: {fid: this.info.fid}})
},
// 处理点击编辑自己的回复
handleIsmyself(item) {
this.popState = "discussionMulti"
this.commentContent = item.message
},
// 投币
postCoin() {
this.$http
.post("/api/operation/coinPurchase", {
token: this.token,
})
.then(res => {
if (res.code != 200) return
this.openHintBox(res.message)
this.popState = ""
this.$router.go(0)
})
},
// 提示框 自定义
openHintBox(message) {
this.alert.state = true
this.alert.message = message
setTimeout(() => {
this.alert.state = false
}, 1500)
},
},
components: {
DetailReply,
Coins,
},
}
</script>
<style lang="scss" scoped>
.alert {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #f4f4f5;
border: 1px solid #ebeef5;
border-radius: 0.2rem;
width: 50%;
opacity: 0;
transition: opacity 0.3s;
&.alertState {
opacity: 1;
}
}
.container {
margin-top: 1.3rem;
padding-bottom: 2.8rem;
.detail-head {
color: #7f7f7f;
padding: 0.191rem 0.2933rem 0;
justify-content: space-between;
.detail-section {
justify-content: space-between;
font-size: 0.32rem;
.section-name {
color: #333;
}
}
.detail-data {
color: rgb(127, 127, 127);
.detail-data-item {
color: rgb(127, 127, 127);
font-size: 0.28rem;
img {
margin-right: 0.12rem;
}
.detail-data-eye {
width: 0.36rem;
height: 0.36rem;
}
.detail-data-comment {
width: 0.32rem;
height: 0.32rem;
}
&:last-of-type {
margin-left: 0.32rem;
}
}
}
}
.detail-title-box {
padding: 0.72rem 0.2933rem 0;
color: #000;
font-size: 0.56rem;
font-weight: 650;
line-height: 0.86rem;
.detail-title-item {
font-size: 0.32rem;
color: #fff;
height: 0.64rem;
display: inline-flex;
margin-right: 0.16rem;
font-weight: 400;
line-height: 0.56rem;
&.detail-title-jinghua {
width: 1rem;
border-radius: 0.5rem 0.5rem 0;
background: linear-gradient(-57.3808deg, rgb(178, 152, 232) 0%, rgb(88, 70, 195) 100%);
vertical-align: middle;
}
&.detail-title-label {
background: rgb(51, 51, 51);
padding: 0 0.16rem;
display: inline-flex;
border-radius: 0.16rem;
vertical-align: middle;
// vertical-align: top;
}
}
}
.card {
margin-top: 0.48rem;
flex-direction: column;
.card-item {
width: 9.4rem;
border-radius: 0.4rem;
background: #fff;
margin-bottom: 0.4rem;
.card-head {
padding: 0.48rem 0.32rem;
border-bottom: 0.0133rem solid #ebebeb;
.card-head-icon {
width: 0.96rem;
height: 0.96rem;
border-radius: 50%;
margin-right: 0.28rem;
}
.card-head-content {
flex-direction: column;
.card-head-name {
color: #333;
font-size: 0.32rem;
margin-bottom: 0.08rem;
word-break: break-word;
margin-right: 0.2667rem;
.landlord {
color: rgb(127, 127, 127);
font-size: 0.26rem;
width: 0.64rem;
height: 0.44rem;
border: rgb(215, 215, 215) 0.0133rem solid;
background: rgb(240, 242, 245);
border-radius: 0.1rem;
margin-left: 0.16rem;
}
}
.card-head-time {
color: rgb(127, 127, 127);
font-size: 0.28rem;
}
}
.card-head-fool {
color: rgb(127, 127, 127);
font-size: 0.32rem;
}
.edit-box {
width: 0.64rem;
height: 0.64rem;
border-radius: 50%;
background: #f6f6f6;
margin-left: 0.32rem;
.edit-icom {
width: 0.4rem;
}
}
}
.card-content {
color: #333;
font-size: 0.36rem;
line-height: 0.6rem;
padding: 0.5rem 0.32rem;
word-break: break-word;
/deep/ {
img {
width: 100% !important;
height: auto !important;
&.gif {
width: auto !important;
}
}
.quote {
width: 100%;
color: #333;
font-size: 0.32rem;
border-radius: 0.16rem;
background: rgb(246, 246, 246) url(@/assets/img/detail/quotation-left.png) no-repeat 0.32rem 0.2666rem;
padding: 0.1333rem 0.1333rem 0.1333rem 1rem;
box-sizing: border-box;
margin-bottom: 0.48rem;
blockquote {
margin: 0;
padding: 0 0.8667rem 0.0667rem 0;
background: url(@/assets/img/detail/quotation-right.png) no-repeat 100% 100%;
line-height: 1.6;
zoom: 1;
display: inline;
}
.quotation-wenzi {
line-height: 0.52rem;
}
.quotation-icon {
width: 0.32rem;
height: 0.26rem;
}
.quotation-right {
flex-direction: column;
margin-left: 0.28rem;
.quotation-bottom {
color: #7f7f7f;
font-size: 0.28rem;
margin-top: 0.258rem;
.quotation-icon {
margin-left: 0.2rem;
}
}
}
}
.content-unlock {
&.content-unlock-no {
height: 3.2rem;
.unlock-icom {
width: 0.64rem;
height: 0.64rem;
margin-right: 0.2rem;
vertical-align: middle;
}
}
background: rgba(242, 242, 242, 0.7);
margin: 0.48rem 0;
color: #555555;
font-size: 0.32rem;
border-radius: 0.16rem;
&.content-already {
background: rgba(242, 242, 242, 0.7);
margin: 0.48rem 0;
padding: 0.32rem;
color: #555555;
font-size: 0.32rem;
border-radius: 0.16rem;
.content-already-header {
color: #7f7f7f;
font-size: 0.28rem;
justify-content: center;
}
.content-unlock-wenzi {
color: #333;
font-size: 0.36rem;
line-height: 0.6rem;
margin-top: 0.3rem;
}
}
}
}
}
.offer-content {
padding: 0.56rem 0.32rem;
.vHtmlMessage {
font-size: 0.36rem;
line-height: 0.6rem;
word-break: break-word;
/deep/ {
strong {
font-weight: bold;
}
img {
max-width: 100%;
}
.content-unlock {
&.content-unlock-no {
height: 3.2rem;
.unlock-icom {
width: 0.64rem;
height: 0.64rem;
margin-right: 0.2rem;
vertical-align: middle;
}
}
background: rgba(242, 242, 242, 0.7);
margin: 0.48rem 0;
color: #555555;
font-size: 0.32rem;
border-radius: 0.16rem;
&.content-already {
background: rgba(242, 242, 242, 0.7);
margin: 0.48rem 0;
padding: 0.32rem;
color: #555555;
font-size: 0.32rem;
border-radius: 0.16rem;
.content-already-header {
color: #7f7f7f;
font-size: 0.28rem;
justify-content: center;
}
.content-unlock-wenzi {
color: #333;
font-size: 0.36rem;
line-height: 0.6rem;
margin-top: 0.3rem;
}
}
}
}
}
.tenement-img {
width: 100%;
}
.offer-content-box {
.offer-content-item {
line-height: 0.6rem;
align-items: flex-start;
&:not(:last-of-type) {
margin-bottom: 0.52rem;
}
.offer-content-key {
font-size: 0.32rem;
color: #7f7f7f;
width: 2.04rem;
}
.offer-content-value {
font-size: 0.36rem;
color: #333;
width: 7.32rem;
white-space: break-spaces;
}
}
}
}
.examine-btn {
color: #333;
font-size: 0.3rem;
background: rgba(242, 242, 242, 1);
height: 0.96rem;
border-radius: 4.1rem;
margin-top: 0.52rem;
.examine-btn-outside {
width: 0.4rem;
height: 0.4rem;
margin-left: 0.24rem;
background: #fddf6d;
border-radius: 50%;
.examine-btn-icon {
width: 0.22rem;
height: 0.24rem;
}
}
}
.summary-content {
padding: 0.56rem 0.32rem;
.summary-content-item {
border-radius: 0.16rem;
border: 0.0133rem solid rgba(235, 235, 235, 1);
margin-bottom: 0.32rem;
.summary-offer-head {
justify-content: space-between;
height: 0.8rem;
background: rgba(246, 246, 246, 1);
color: #333;
padding: 0 0.24rem;
span,
a {
font-size: 0.32rem;
color: #333;
}
.summary-offer-head-title {
color: #000;
font-size: 0.4rem;
font-weight: 650;
}
.summary-offer-head-icon {
width: 0.14rem;
height: 0.36rem;
margin-left: 0.16rem;
}
}
.summary-offer-box {
padding-top: 0.28rem;
flex-direction: column;
justify-items: center;
.summary-offer-item {
line-height: 0.6rem;
padding: 0 0.24rem;
box-sizing: border-box;
margin-bottom: 0.2rem;
.summary-offer-key {
width: 1.3rem;
color: #7f7f7f;
font-size: 0.32rem;
margin-right: 0.74rem;
}
.summary-offer-value {
font-size: 0.36rem;
color: #333;
}
}
}
.summary-wenzi {
color: #333;
font-size: 0.32rem;
line-height: 0.6rem;
padding: 0.28rem 0.24rem;
}
}
}
}
}
.paging {
margin-top: 0.48rem;
::v-deep {
.el-pagination.is-background .el-pager li:not(.disabled).active {
background: rgba(98, 177, 255, 1);
border-radius: 50%;
}
.el-pagination .btn-next .el-icon,
.el-pagination .btn-prev .el-icon {
font-size: 0.4rem;
}
}
}
.discuss-bottom {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 100vw;
background-color: #fff;
padding: 0 0.4rem;
box-sizing: border-box;
z-index: 99;
border-top: 0.0133rem solid #dbdcdd;
padding-right: 0;
height: 2rem;
width: 10rem;
justify-content: space-between;
.swiper {
height: 2rem;
}
.bottom-item {
justify-content: space-between;
height: 100%;
.bottom-comment {
width: 4.6rem;
height: 0.8rem;
border-radius: 1rem;
padding: 0 0.28rem;
font-size: 0.32rem;
color: #aaaaaa;
background-color: #f2f2f2;
border: 0.0133rem solid #ebebeb;
box-sizing: border-box;
position: relative;
.bottom-comment-icom {
width: 0.4rem;
height: 0.4rem;
margin-right: 0.16rem;
}
}
.bottom-operation-box {
width: 3.8667rem;
justify-content: space-between;
}
.bottom-operation-icom {
width: 0.48rem;
height: 0.48rem;
margin-bottom: 0.1333rem;
}
.bottom-operation-item {
position: relative;
padding: 0 0.4rem;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.bottom-transmit-icom {
width: 0.4rem;
height: 0.4rem;
}
.bottom-operation-text {
font-size: 0.32rem;
color: #555555;
}
.bottom-information {
position: relative;
min-width: 4.6667rem;
max-width: 53.3333rem;
height: 0.8rem;
border-radius: 1rem;
background: linear-gradient(to right, #fff, #50e3c2, #50e3c2, #50e3c2);
}
.bottom-information-avatar {
width: 0.8rem;
height: 0.8rem;
border-radius: 50%;
}
.bottom-information-content {
color: #fff;
font-size: 0.2933rem;
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 0.1333rem;
.vertical {
height: 0.2933rem;
background-color: #fff;
width: 0.0133rem;
}
}
.bottom-information-item:not(:last-of-type) {
justify-content: center;
}
}
}
.loginBtn {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
// background: #50e3c2;
}
}
</style>