添加投币和回应

This commit is contained in:
A1300399510
2024-07-26 18:49:40 +08:00
parent e7f6bbeaa4
commit 21ed7d94ef
8 changed files with 1241 additions and 89 deletions

363
app.vue
View File

@@ -205,11 +205,14 @@
<img class="operate-icon operate-collect-icon" style="width: 13px; height: 8px;" src="./img/view-icon.svg" />
{{ detailsInfo["viewnum"] || 0 }}
</div>
<div class="operate-item flexacenter" @click="operateCollect()">
<img class="operate-icon operate-collect-icon" v-if="detailsIscollection == 0" src="./img/collect-icon.png" />
<img class="operate-icon operate-collect-icon" v-else src="./img/collect-icon-colours.svg" />
{{ detailsInfo["collectionnum"] > 0 ? detailsInfo["collectionnum"] : "收藏" }}
</div>
<ClientOnly>
<div class="operate-item flexacenter" @click="operateCollect()">
<img class="operate-icon operate-collect-icon" v-if="detailsIscollection == 0" src="./img/collect-icon.png" />
<img class="operate-icon operate-collect-icon" v-else src="./img/collect-icon-colours.svg" />
{{ detailsInfo["collectionnum"] > 0 ? detailsInfo["collectionnum"] : "收藏" }}
</div>
</ClientOnly>
<div class="operate-item flexacenter operate-transmit" @mouseenter.stop="closeTransmitState()" @mouseleave.stop="closeAllTransmitState()">
<img class="operate-icon operate-transmit-icon" src="./img/transmit-icon.png" />
转发
@@ -246,6 +249,10 @@
<div class="answer-box-item" v-for="(item, index) in answerList" :key="index">
<img class="aa" src="@/img/A.png" />
<div class="edit-btn flexcenter" v-if="item['ismyself'] == 1" @click="openIAnswer(index)">
<img class="edit-icon" src="./img/edit-icon.png" />
</div>
<div class="answer-text" v-html="item['content']" @click="handleAnswerText"></div>
<div class="info-box flexacenter">
<div class="user-info flexacenter" @click="openUserInfo(index)">
@@ -269,23 +276,24 @@
</div>
<div class="operate-box flexacenter">
<div class="edit-box">
<div class="edit-btn flexcenter" v-if="item['ismyself'] == 1" @click="openIAnswer(index)">
<img class="edit-icon" src="./img/edit-icon.png" />
<div class="interaction-box flexacenter flex1">
<div class="interaction-item flexacenter pitch">
<template v-if="item.ripostecount?.total"> 回应 <span class="amount">{{ item.ripostecount?.total }}</span> </template>
<template v-else>添加回应</template>
</div>
<div class="interaction-item flexacenter">讨论 <span class="amount">19</span></div>
<div class="interaction-item flexacenter">投币 <span class="amount">19</span></div>
</div>
<div class="operate-list flexacenter">
<div class="operate-item flexacenter" @click="operateLike(item['token'], index)">
<!-- <div class="operate-item flexacenter" @click="operateLike(item['token'], index)">
<img class="operate-icon operate-like-icon" v-if="item['islike'] == 1" src="./img/like-icon-colours.png" />
<img class="operate-icon operate-like-icon" v-else src="./img/like-icon.png" />
{{ item["likenum"] }}
</div>
<!-- <div class="operate-item flexacenter" :class="{ commentnum: item['commentState'] }" @click="openCommentState(index)"> -->
<div class="operate-item flexacenter" :class="{ commentnum: item['commentState'] }">
<img class="operate-icon operate-comment-icon" src="./img/comment-icon.png" />
<!-- {{ item["commentnum"] }} -->
{{ item["commentnum"] }}
</div>
</div> -->
<div class="operate-item flexacenter" @click="operateCollect(item['token'], index)">
<img class="operate-icon operate-collect-icon" v-if="item['iscollection'] == 1" src="./img/collect-icon-colours.svg" />
<img class="operate-icon operate-collect-icon" v-else src="./img/collect-icon.png" />
@@ -319,6 +327,47 @@
</div>
</div>
<div class="answer-coins" v-if="false">
<div class="coins-show flexacenter">
<img class="coins-icon" src="@/img/bi-icon.png" />
<div class="coins-text flexacenter flex1">该回答已获 <span class="quantity">0</span> 个寄托币</div>
<div class="coins-btn flexcenter">给TA投币</div>
</div>
<div class="answer-coins-list">
<div class="answer-coins-item flexacenter" v-for="(item, index) in 9" :key="index">
<div class="ranking">{{ index + 1 }}</div>
<div class="coins-user flexacenter flex1">
<img class="coins-user-img" src="https://axure-file.lanhuapp.com/md5__1f472a5724af5648ff3ece07a2d77b36.svg" />
<div class="coins-user-name flex1">君语</div>
</div>
<div class="bi flexacenter">
<div class="bi-amount">12</div>
</div>
</div>
</div>
</div>
<div class="respond-area" v-if="true">
<div class="respond-already-item flexacenter" :class="{ 'pitch': it.selected }" v-for="(it, i) in item.ripostelist" :key="i" @click="selectEomji(it.item, index)">
<div class="code flexacenter" v-html="jointriposte(it.item)"></div>
{{ it.num }}
</div>
<div v-if="item.ripostelist?.length <= 3" class="respond-select flexacenter">
<template v-for="(it, i) in randomEmojis.slice(0, item.ripostelist?.length == 0 ? 8 : 5)" :key="i">
<div class="respond-select-item" v-html="jointriposte(it)" @click="selectEomji(it, index)"></div>
</template>
<RespondAdd :riposteoptions="riposteoptions" @selectEomji="selectEomji" :index="index"></RespondAdd>
</div>
<RespondAdd v-else :riposteoptions="riposteoptions" :index="index" @selectEomji="selectEomji"></RespondAdd>
</div>
<div class="respond-list-btn" v-if="item.ripostecount?.user > 0" @click="openRespondDetails(index)">
<span class="respond-list-btn-amount">{{ item.ripostecount?.user }}</span>
人回应
<img class="respond-list-btn-icon" src="@/img/arrowsRight.svg" />
</div>
<template v-if="item['commentState']">
<div class="post-comment flexacenter" :class="{ 'post-comment-radius': item.commentnum == 0 }">
<input class="post-input flex1" placeholder="说点什么…" v-model="item['commentInput']" />
@@ -439,18 +488,6 @@
<img class="more-comments-icon" src="@/img/arrow-circular-gray.png" />
</div>
</div>
<!-- 评论为空时 -->
<!-- <div class="comments-empty-box flexflex" v-else>
<div class="empty-box flexcenter">
<div class="dot-list flexacenter">
<img class="dot-item" src="./img/dot-yellow.svg" v-for="item in 3" :key="item" />
<img class="dot-item" src="./img/dot-gray.svg" v-for="item in 3" :key="item" />
</div>
<img class="empty-icon" src="./img/empty-icon.svg" />
</div>
<div class="empty-hint">和我说说你的想法或疑问吧</div>
</div> -->
</template>
</div>
@@ -727,7 +764,7 @@
<div class="form">
<div class="radio-area flexacenter">
<div class="radio-area-item flexacenter" :class="{ pitch: checkList.includes(s) }" v-for="(s, i) in reasonList" :key="i" @click="selectRadio(s)">
<div class="radio-area-frame"></div>
<div cdivlass="radio-area-frame"></div>
{{ s }}
</div>
</div>
@@ -742,6 +779,8 @@
</div>
</div>
</div>
<RespondPop v-if="respondPopState" :respondDetail="respondDetail" :respondPopObj="respondPopObj" @closePopList="closePopList" @selectEomji="selectEomji"></RespondPop>
</div>
</div>
</template>
@@ -757,9 +796,8 @@
// "todaysigned": 0
// }
import { onMounted, onUnmounted, ref, nextTick, watchEffect, watch } from "vue"
import { onMounted, onUnmounted, ref, nextTick, watchEffect, watch, provide } from "vue"
import axios from "axios"
export default {
name: "#answer-app",
async setup() {
@@ -771,8 +809,7 @@ export default {
emulateJSON: true,
withCredentials: true,
headers: {
authorization: process.env.NODE_ENV !== "production" && "223fe8a4ea0ede029244b3b01f0bdaad", // 头部标记 ada
// "7a89997c2ccd8cb5ed8cb20d843dafdd", // 头部标记 ada
authorization: process.env.NODE_ENV !== "production" && "c5438975031a43a61c13252623753fc5", // 头部标记
},
})
.then(function (res) {
@@ -806,8 +843,7 @@ export default {
emulateJSON: true,
withCredentials: true,
headers: {
authorization: process.env.NODE_ENV !== "production" && "223fe8a4ea0ede029244b3b01f0bdaad", // 头部标记
// "7a89997c2ccd8cb5ed8cb20d843dafdd", // 头部标记
authorization: process.env.NODE_ENV !== "production" && "c5438975031a43a61c13252623753fc5", // 头部标记
},
})
.then(function (res) {
@@ -884,6 +920,8 @@ export default {
const params = route.query
// console.log(params);
// getDetails(params.uniqid)
// 是否直接打开提问
setTimeout(() => {
if (params["ispublish"]) questionsInit()
@@ -1290,14 +1328,22 @@ export default {
let data = res.data
data.data.forEach((element, index) => {
element["commentList"] = []
if (element["commentnum"] > 0) {
element["showOneCommentState"] = true
console.log("element", element)
nextTick(() => {
openCommentState(index)
})
} else element["commentState"] = true
// element["commentList"] = []
// if (element["commentnum"] > 0) {
// element["showOneCommentState"] = true
// nextTick(() => {
// openCommentState(index)
// })
// } else element["commentState"] = true
if (element.ripostes > 0) {
nextTick(() => getRiposte(index))
} else {
element["ripostelist"] = []
element["ripostecount"] = {}
}
})
// console.log("data.data", data.data) showOneCommentState
@@ -1663,7 +1709,6 @@ export default {
targetAnswerList[index]["commentList"][ind]["child"] = merged1
answerList.value = targetAnswerList
})
}
@@ -2304,6 +2349,7 @@ export default {
// 用于发送某个URL的PV统计请求
if (window._czc) window._czc.push(["_trackPageview", contentUrl])
}
// 删除 url 参数的key
const deleteState = (keys = []) => {
if (typeof window === "undefined") return
@@ -2581,40 +2627,8 @@ export default {
replaceState({ uniqid: params["uniqid"] })
seo.value = data.seo
// handleInsertRelatedlist(params["uniqid"]);
})
.catch(error => console.error(error))
// if (process.server) {
// await $ajax("/api/details", {uniqid: params["uniqid"]})
// .then(res => {
// if (res.code != 200) return
// let data = res.data
// detailsInfo.value = data["info"] || {}
// detailsIsanswered.value = data["isanswered"] || 0
// detailsIscollection.value = data["iscollection"] || 0
// detailsIsmyself.value = data["ismyself"] || 0
// detailsToken = data["token"] || ""
// detailShare.value = data["share"] || {}
// type.value = "details"
// calculateListIndex(data.info, params["uniqid"])
// answerList.value = []
// answerPage.value = 1
// getAnswerList()
// closeAllTransmitState()
// replaceState({uniqid: params["uniqid"]})
// seo.value = data.seo
// })
// .finally(() => {
// detailLoading.value = false
// })
// }
}
await $ajax("/api/lists", {
@@ -2786,7 +2800,6 @@ export default {
// 点击发送信息
const sendMessage = uin => {
console.log("uin", uin)
if (uin && typeof messagePrivateItem == "function") {
messagePrivateItem({ uin: uin })
return
@@ -2836,7 +2849,211 @@ export default {
answerList.value[index]["showOneCommentState"] = false
}
return { handleLookOnly, zeroreply, replaceNumberObj, closeMyModel, myModelList, myModelState, listHeight, bottomTpsStyle, TAHomePage, sendMessage, avatarState, openUserInfo, isNeedLogin, handleInputYou, openListIAnswer, isListEmptyState, cutYourAnswerAnonymous, handleYourAnswer, yourAnswer, handleLogo, inTheEndState, setItemUrl, seo, originUrl, handleMenuState, reasonList, checkList, alertShow, alertText, selectRadio, alertSubmit, cutType, dialogSrc, answerPage, handleDetailsScroll, replaceState, copyText, boxClass, questionPlaceholderState, yourAnswerPlaceholderState, handleInput, handlePaste, itemStyle, listStyle, listBoxStyle, myType, type, pitchIndex, cut, list, keyword, keywordText, getList, total, typeList, typePitch, getDetails, detailsInfo, detailsIsanswered, detailsIscollection, detailsIsmyself, detailShare, detailLoading, answerList, operateLike, operateCollect, IAnswerState, IAnswerEditState, IAnswerInfo, amendIAnswer, openIAnswer, closeIAnswer, submitAnswer, openCommentState, submitAnswerComments, operateAnswerCommentsLike, openAnswerCommentsChild, closeAnswerCommentsChild, alsoCommentsData, handleAllComment, myCollectionList, myCollectionCount, myQuestionsList, myQuestionsCount, myAnswerList, myAnswerCount, cutAnswerPopupState, handleDate, handleCollectionScroll, handleAnswersScroll, handleQuestionsScroll, cancelCollection, getMyCollection, questionsSetp, questionsObj, cutAnonymous, cutQuestionsSetp, cutQuestionsPopupState, questionsTypeList, postingIssue, choosingTheme, handleMy, changeAnonymous, changeAnonymousQuestions, pageHeaderHeight, pageListHeight, questionsTransmitState, questionsTransmitMaskState, closeAllTransmitState, closeTransmitState, handleAnswerTransmitList, closeDetailMode, tabListFixeState, handleListScroll, historicalSearchState, historicalSearchList, searchFocus, searchBlur, searchClick, handleClickHistoricalItem, handleClickClear, isSearchMode, questionsInit, myCount, msg, myOpenDetails, handleAnswerText, getCurrentUrl, loading, showComments }
// 拼接 回应需要的 字符
const jointriposte = item => {
return `&#x${item};`
}
let ripostelist = ref([])
let ripostecount = ref({})
let riposteoptions = ref([
{
"name": "默认",
"baseUrl": "{@}riposte/img",
"data": {
"c150": "c150.png",
"c162": "c162.png",
"c126": "c126.png",
"c133": "c133.png",
"c157": "c157.png",
"c069": "c069.png",
"c005": "c005.png",
"c081": "c081.png",
"c026": "c026.png",
"c004": "c004.png",
"c011": "c011.png",
"c002": "c002.png",
"c059": "c059.png",
"c140": "c140.png",
"c167": "c167.png",
"c168": "c168.png",
"c169": "c169.png",
"c170": "c170.png",
"c171": "c171.png",
"c172": "c172.png",
"c173": "c173.png",
},
},
{
"name": "旗帜",
"baseUrl": "{@}riposte/img",
"data": {
"c093": "c093.png",
"c094": "c094.png",
"c095": "c095.png",
"c096": "c096.png",
"c097": "c097.png",
"c098": "c098.png",
"c099": "c099.png",
"c100": "c100.png",
"c101": "c101.png",
"c102": "c102.png",
"c103": "c103.png",
"c104": "c104.png",
"c105": "c105.png",
"c106": "c106.png",
"c107": "c107.png",
"c108": "c108.png",
"c109": "c109.png",
"c110": "c110.png",
"c111": "c111.png",
"c112": "c112.png",
"c113": "c113.png",
"c114": "c114.png",
"c115": "c115.png",
},
},
])
const getRiposte = index => {
let target = answerList.value[index]
$ajax("/api/riposte/riposteGet", { token: target.token }).then(res => {
console.log("res", res)
if (res.code != 200) return
let data = res.data
target.ripostecount = data.count || {}
target.ripostelist = data.list || []
answerList.value[index] = target
// if (ripostelist.value.length <= 3) randomEmoji()
})
}
let randomEmojis = ref(["c150", "c167", "c002", "c162", "c157", "c133", "c011", "c004"]) // 随机 五个 emoji
// 随机 7 个Emoji
const randomEmoji = () => {
let emojiList = ripostelist.value
// 需要排除的 Emoji
let exclude = []
emojiList.forEach(element => {
exclude.push(element.item)
})
let selectedList = [] // 待选择 Emoji To be selected
// 默认是有点赞的
for (const key in riposteoptions.value[0].data) {
if (key != "c150") selectedList.push(key)
}
const random = []
if (!exclude.includes("c150")) random.push("c150") // 添加第一个点赞 emoji
selectedList = selectedList.filter(itemB => !exclude.includes(itemB))
// 生成随机索引,确保不重复
let indexes = []
while (indexes.length < 7) {
let randomIndex = Math.floor(Math.random() * selectedList.length)
if (indexes.indexOf(randomIndex) === -1) {
indexes.push(randomIndex)
random.push(selectedList[randomIndex])
}
}
randomEmojis.value = random
}
const get = () => {
// /api/riposte/riposteGet
}
const selectEomji = (code, index, ispop = false, islist = false) => {
let target = answerList.value[index]
let ispitch = false
let isindex = target.ripostelist.findIndex(element => element.item === code)
if (isindex >= 0) ispitch = target.ripostelist[isindex].selected
if (ispitch && ispop) return
riposteSubmit(code, target.token).then(res => {
const data = res.data
target.ripostecount = data.count
if (isindex >= 0) {
target.ripostelist[isindex].num += ispitch ? -1 : 1
target.ripostelist[isindex].selected = !ispitch && target.ripostelist[isindex].num !== 0
if (target.ripostelist[isindex].num === 0) {
target.ripostelist.splice(isindex, 1)
}
} else {
target.ripostelist.push({
item: code,
num: 1,
selected: true,
})
}
if (islist) handleRiposteListData(code, data)
})
}
// 处理回应列表 数据
const handleRiposteListData = (code, data) => {
let target = respondDetail.value
// console.log("target", target)
if (target[code].selected) {
target[code].user = target[code].user.filter(item => item.uin != data.uin)
if (target[code].user.length == 0) delete target[code]
} else {
target[code].user.push({
avatar: data.avatar,
nickname: data.username,
uid: data.uid,
uin: data.uin,
})
}
target[code].selected = !target[code].selected
}
const riposteSubmit = (item, token) => {
return new Promise((resolve, reject) => {
$ajax("/api/riposte/riposteSubmit", { token, item }).then(res => {
if (res.code != 200) {
handleMsg("error", res["message"] || "报错了,请重试!!!")
reject(res)
} else {
handleMsg("success", res["message"] || "回应成功")
resolve(res)
}
})
})
}
let respondDetail = ref({})
let respondPopState = ref(false)
let respondPopObj = ref({})
// 打开回应详情
const openRespondDetails = index => {
let target = answerList.value[index]
respondPopObj.value.index = index
respondPopObj.value.user = target.ripostecount?.user
$ajax("/api/riposte/riposteDetail", { token: target.token }).then(res => {
console.log("res", res)
if (res.code != 200) return
respondDetail.value = res.data
respondPopState.value = true
})
}
const closePopList = () => {
respondPopState.value = false
}
return { handleLookOnly, zeroreply, replaceNumberObj, closeMyModel, myModelList, myModelState, listHeight, bottomTpsStyle, TAHomePage, sendMessage, avatarState, openUserInfo, isNeedLogin, handleInputYou, openListIAnswer, isListEmptyState, cutYourAnswerAnonymous, handleYourAnswer, yourAnswer, handleLogo, inTheEndState, setItemUrl, seo, originUrl, handleMenuState, reasonList, checkList, alertShow, alertText, selectRadio, alertSubmit, cutType, dialogSrc, answerPage, handleDetailsScroll, replaceState, copyText, boxClass, questionPlaceholderState, yourAnswerPlaceholderState, handleInput, handlePaste, itemStyle, listStyle, listBoxStyle, myType, type, pitchIndex, cut, list, keyword, keywordText, getList, total, typeList, typePitch, getDetails, detailsInfo, detailsIsanswered, detailsIscollection, detailsIsmyself, detailShare, detailLoading, answerList, operateLike, operateCollect, IAnswerState, IAnswerEditState, IAnswerInfo, amendIAnswer, openIAnswer, closeIAnswer, submitAnswer, openCommentState, submitAnswerComments, operateAnswerCommentsLike, openAnswerCommentsChild, closeAnswerCommentsChild, alsoCommentsData, handleAllComment, myCollectionList, myCollectionCount, myQuestionsList, myQuestionsCount, myAnswerList, myAnswerCount, cutAnswerPopupState, handleDate, handleCollectionScroll, handleAnswersScroll, handleQuestionsScroll, cancelCollection, getMyCollection, questionsSetp, questionsObj, cutAnonymous, cutQuestionsSetp, cutQuestionsPopupState, questionsTypeList, postingIssue, choosingTheme, handleMy, changeAnonymous, changeAnonymousQuestions, pageHeaderHeight, pageListHeight, questionsTransmitState, questionsTransmitMaskState, closeAllTransmitState, closeTransmitState, handleAnswerTransmitList, closeDetailMode, tabListFixeState, handleListScroll, historicalSearchState, historicalSearchList, searchFocus, searchBlur, searchClick, handleClickHistoricalItem, handleClickClear, isSearchMode, questionsInit, myCount, msg, myOpenDetails, handleAnswerText, getCurrentUrl, loading, showComments, jointriposte, ripostelist, ripostecount, riposteoptions, randomEmojis, selectEomji, openRespondDetails, respondPopState, respondDetail, respondPopObj, closePopList }
},
}
</script>