2023-12-06 07:23:13 +00:00
|
|
|
|
<!--
|
2023-12-06 11:06:10 +00:00
|
|
|
|
新增的回答款需要输入图片
|
2023-12-06 07:23:13 +00:00
|
|
|
|
-->
|
|
|
|
|
<template>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div id="append_parent"></div>
|
|
|
|
|
<div id="ajaxwaitid"></div>
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
|
|
<Head>
|
|
|
|
|
<Title>{{ `${seo["title"] || "问答"} - 寄托天下出国留学网` }}</Title>
|
|
|
|
|
<Meta name="keyword" :content="seo['keyword']" />
|
|
|
|
|
<Meta name="description" :content="seo['description']" />
|
|
|
|
|
</Head>
|
|
|
|
|
|
|
|
|
|
<div class id="answer-app">
|
|
|
|
|
<header class="flexacenter" id="pageHeader">
|
|
|
|
|
<div class="flexacenter top">
|
|
|
|
|
<a href="./index.html">
|
|
|
|
|
<img class="logo" @click="handleLogo" alt="寄托问答" src="./img/logo.png" />
|
|
|
|
|
</a>
|
|
|
|
|
<div class="right flexacenter flex1">
|
|
|
|
|
<div class="searchInput flexacenter">
|
|
|
|
|
<input class="input flex1" placeholder="输入搜索关键词" v-model="keyword" @keydown.enter="searchClick()" @focus="searchFocus" @blur="searchBlur" />
|
|
|
|
|
<div class="clear-search flexacenter" v-if="isSearchMode">
|
|
|
|
|
<img class="cross-circle-black" @click="handleClickClear()" src="./img/cross-circle-black.png" />
|
|
|
|
|
<div class="halving-line"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="input-icon" src="./img/input-icon.png" @click="searchClick()" />
|
|
|
|
|
<div class="history-box" v-if="historicalSearchState" @click.stop>
|
|
|
|
|
<div class="history-title">历史搜索</div>
|
|
|
|
|
<div class="history-list">
|
|
|
|
|
<div class="history-item ellipsis" v-for="(item, index) in historicalSearchList" :key="index" @click.stop="handleClickHistoricalItem(item)">{{ item }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="btn-list flexacenter">
|
|
|
|
|
<div class="item flex1" @click="handleMy('collect')">我的收藏</div>
|
|
|
|
|
<div class="item flex1" @click="handleMy('questions')">我的提问</div>
|
|
|
|
|
<div class="item flex1" @click="handleMy('answers')">我的回答</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="add-btn flexcenter" @click="questionsInit()">
|
|
|
|
|
<img class="add-icon" src="./img/add-icon.svg" />
|
|
|
|
|
我要提问
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="tab-box flexcenter" :class="{ 'tab-list-fixed': tabListFixeState }">
|
|
|
|
|
<div class="tab-list flexacenter">
|
|
|
|
|
<div class="item flexcenter" :class="{ pitch: typePitch == null }" @click="cutType(null)">All</div>
|
|
|
|
|
<template v-for="(item, index) in typeList" :key="index">
|
|
|
|
|
<div class="halving-line">|</div>
|
|
|
|
|
<div class="item flexcenter" :class="{ pitch: typePitch == it['id'] }" v-for="it in item" :key="it" @click="cutType(it.id)">{{ it["name"] }}</div>
|
|
|
|
|
</template>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</header>
|
|
|
|
|
<div class="main flexflex" :class="{ 'mode-list': type == 'list' }">
|
|
|
|
|
<div class="list-box" @scroll="handleListScroll">
|
|
|
|
|
<div class="main-header" :style="{paddingLeft: type == 'list' ? 0 : 'calc((100vw - 1200px) / 2)',}">
|
|
|
|
|
<template v-if="myModelState">
|
|
|
|
|
<div class="search-keyword flexacenter" @click="closeMyModel()">
|
|
|
|
|
<div class="ellipsis">我的收藏/提问/回答</div>
|
|
|
|
|
<img class="search-keyword-cross" src="./img/cross-circle-icon.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else-if="isSearchMode">
|
|
|
|
|
<div class="search-keyword flexacenter" @click="handleClickClear()">
|
|
|
|
|
<div class="ellipsis">{{ keywordText }}</div>
|
|
|
|
|
<img class="search-keyword-cross" src="./img/cross-circle-icon.png" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="total grid-item" @click="cut">共 {{ total }} 条搜索结果</div>
|
|
|
|
|
</template>
|
|
|
|
|
<div v-else class="total grid-item" @click="cut">共 {{ total }} 条问答</div>
|
|
|
|
|
|
|
|
|
|
<div class="look-only flexcenter" v-if="type != 'details'" @click="handleLookOnly">
|
|
|
|
|
<img class="look-icon" v-if="zeroreply == 0" src="@/img/tick-no.svg">
|
|
|
|
|
<img class="look-icon" v-else src="@/img/tick-option.svg">
|
|
|
|
|
只看0回答
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="list" id="list" :style="[listStyle(), { height: listHeight + 'px' }]">
|
|
|
|
|
<template v-for="(item, index) in list" :key="item.uniqid">
|
|
|
|
|
<a v-if="item['isrecom']" class="item grid-item flexflex" :style="itemStyle(index, item['content'], item['type'])" :class="{pitch: index === pitchIndex,upLevel: index === pitchIndex - 1,}" target="_blank" :href="item['url']">
|
|
|
|
|
<img class="dot" src="./img/dot.svg" />
|
|
|
|
|
<div class="content" :style="{ width: type == 'list' ? '531px' : '430px' }">
|
|
|
|
|
<div class="issue-title flexcenter">
|
|
|
|
|
<div class="recommend flexcenter">推荐阅读</div>
|
|
|
|
|
<div class="issue ellipsis flex1">{{ item['title'] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<template v-if="item['type'] == 'thread'">
|
2023-12-21 02:53:20 +00:00
|
|
|
|
<div class="answer ellipsis" v-if="item['message']">{{ item['message'] }}</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</template>
|
|
|
|
|
<div class="answer" style="height: auto" v-else-if="item['type'] == 'vote'">
|
|
|
|
|
<div v-for="(ite, i) in item['option'].slice(0, 2)" :key="i">{{ replaceNumberObj[i] + ite }}</div>
|
|
|
|
|
<div>{{ replaceNumberObj[2] }} …</div>
|
|
|
|
|
</div>
|
|
|
|
|
<template v-else>
|
|
|
|
|
<div class="answer ellipsis flexacenter">
|
|
|
|
|
<div class="value-value" v-if="item['profession'] || item['professional']">{{ item["profession"] || item["professional"] }}</div>
|
|
|
|
|
<div class="value-value" v-if="item['project'] || item['degree']">{{ item["project"] || item["degree"] }}</div>
|
|
|
|
|
<div class="value-value" v-if="item['interviewtime'] || item['semester']">{{ item["interviewtime"] || item["semester"] }}</div>
|
|
|
|
|
<div class="value-value" v-if="item['apply_results']">{{ item["apply_results"] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<div class="bottom flexacenter">
|
|
|
|
|
<div class="typename flexcenter">{{ item["typename"] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</a>
|
|
|
|
|
<a v-else class="item grid-item flexflex" :style="itemStyle(index, item['content'])" :class="[{pitch: index === pitchIndex,upLevel: index === pitchIndex - 1,},`item${index}`,]" :href="setItemUrl(item['uniqid'])" @click.stop.prevent="getDetails(item['uniqid'], index)">
|
|
|
|
|
<img class="dot" src="./img/dot.svg" />
|
|
|
|
|
<div class="content" :style="{ width: type == 'list' ? '531px' : '430px' }">
|
|
|
|
|
<div class="issue-title flexcenter">
|
|
|
|
|
<img class="hot-icon" v-if="item['ishot'] == 1" src="./img/hot-icon.png" />
|
|
|
|
|
<div class="issue ellipsis flex1"> {{ item['title'] }}</div>
|
|
|
|
|
</div>
|
2023-12-21 02:53:20 +00:00
|
|
|
|
<div class="answer ellipsis" v-if="item['content']">{{ item['content'] }}</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="bottom flexacenter">
|
|
|
|
|
<div class="typename flexcenter" v-if="item['typename']">{{ item["typename"] }}</div>
|
|
|
|
|
<div v-else></div>
|
|
|
|
|
<div class="flexacenter">
|
|
|
|
|
<div class="quantity">{{ item["answers"] == 0 ? "暂无回答" : "共" + item["answers"] + "个回答" }}</div>
|
|
|
|
|
<template v-if="type == 'list'">
|
|
|
|
|
<div class="longString"></div>
|
|
|
|
|
<div class="answer-btn" @click.stop.prevent="openListIAnswer(index)">我来回答</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</a>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="bottom-tps" :style="bottomTpsStyle()" v-if="inTheEndState">- 到底了 -</div>
|
|
|
|
|
<div class="bottom-tps" :style="bottomTpsStyle()" v-if="myModelState"></div>
|
|
|
|
|
|
|
|
|
|
<div class="empty-box flexcenter" v-if="isListEmptyState && list.length == 0">
|
|
|
|
|
<div class="dot-list flexacenter">
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
<img class="empty-icon" src="./img/empty-icon.svg" />
|
|
|
|
|
<div class="empty-hint" v-if="isSearchMode">没有找到相关结果,请更换搜索关键词</div>
|
|
|
|
|
<div class="empty-hint" v-else>暂无数据</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
<div class="details-area-box flexflex" v-if="type == 'details'" @scroll="handleDetailsScroll">
|
|
|
|
|
<!-- 加载 -->
|
|
|
|
|
<div class="loading-bj flexcenter" v-if="detailLoading">
|
|
|
|
|
<svg t="1642133548066" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2597" width="200" height="200">
|
|
|
|
|
<path d="M512 249.5c-22.5 0-37.5-15-37.5-37.5V99.5c0-22.5 15-37.5 37.5-37.5s37.5 15 37.5 37.5V212c0 22.5-15 37.5-37.5 37.5z m0 712.5c-22.5 0-37.5-15-37.5-37.5V812c0-22.5 15-37.5 37.5-37.5s37.5 15 37.5 37.5v112.5c0 22.5-15 37.5-37.5 37.5zM212 549.5H99.5C77 549.5 62 534.5 62 512s15-37.5 37.5-37.5H212c22.5 0 37.5 15 37.5 37.5s-15 37.5-37.5 37.5z m712.5 0H812c-22.5 0-37.5-15-37.5-37.5s15-37.5 37.5-37.5h112.5c22.5 0 37.5 15 37.5 37.5s-15 37.5-37.5 37.5z m-153.75-150c-11.25 0-26.25-7.5-33.75-18.75-11.25-18.75-3.75-41.25 15-52.5L849.5 272c18.75-11.25 41.25-3.75 52.5 15s3.75 41.25-15 52.5l-97.5 56.25c-3.75 3.75-11.25 3.75-18.75 3.75z m-615 356.25c-11.25 0-26.25-7.5-33.75-18.75-11.25-18.75-3.75-41.25 15-52.5l97.5-56.25c18.75-11.25 41.25-3.75 52.5 15s3.75 41.25-15 52.5L174.5 752c-7.5 3.75-15 3.75-18.75 3.75z m506.25-465c-7.5 0-11.25 0-18.75-3.75-18.75-11.25-22.5-33.75-15-52.5L684.5 137c11.25-18.75 33.75-22.5 52.5-15 18.75 11.25 22.5 33.75 15 52.5L695.75 272c-7.5 11.25-22.5 18.75-33.75 18.75z m-356.25 615c-7.5 0-11.25 0-18.75-3.75-18.75-11.25-22.5-33.75-15-52.5l56.25-97.5c11.25-15 33.75-22.5 52.5-11.25s22.5 33.75 15 52.5L339.5 887c-7.5 11.25-22.5 18.75-33.75 18.75z m-52.5-506.25c-7.5 0-15 0-18.75-3.75L137 339.5c-18.75-11.25-26.25-33.75-15-52.5s33.75-22.5 52.5-15l97.5 56.25c18.75 11.25 22.5 33.75 11.25 52.5-3.75 11.25-18.75 18.75-30 18.75z m615 356.25c-7.5 0-11.25 0-18.75-3.75L752 695.75c-18.75-11.25-22.5-33.75-15-52.5 11.25-18.75 33.75-22.5 52.5-15L887 684.5c18.75 11.25 22.5 33.75 15 52.5-7.5 11.25-18.75 18.75-33.75 18.75zM362 290.75c-11.25 0-26.25-7.5-33.75-18.75L272 174.5c-7.5-18.75-3.75-41.25 15-52.5s41.25-3.75 52.5 15l56.25 97.5c7.5 18.75 3.75 41.25-15 48.75-7.5 3.75-11.25 7.5-18.75 7.5z m356.25 615c-11.25 0-26.25-7.5-33.75-18.75l-56.25-97.5c-11.25-18.75-3.75-41.25 15-52.5s41.25-3.75 52.5 15L752 849.5c11.25 18.75 3.75 41.25-15 52.5-7.5 3.75-11.25 3.75-18.75 3.75z" p-id="2598" fill="#26d79f" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="details-box flexflex">
|
|
|
|
|
<!-- 转发的蒙版 -->
|
|
|
|
|
|
|
|
|
|
<div class="close-box">
|
|
|
|
|
<div class="close-circle flexcenter" @click="closeDetailMode()">
|
|
|
|
|
<img class="close-icon" src="./img/close-icon.svg" />
|
|
|
|
|
<img class="details-cross-icon" src="./img/cross-icon.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- 提问信息 -->
|
|
|
|
|
<div class="details-issue">
|
|
|
|
|
<!-- <div class="icon q flexcenter">Q</div> -->
|
|
|
|
|
<img class="qq" src="@/img/Q.png" />
|
|
|
|
|
<div class="titletitle">{{ detailsInfo["title"] }}</div>
|
|
|
|
|
<div class="hint" @click="handleAnswerText" v-if="detailsInfo['content']" v-html="detailsInfo['content']"></div>
|
|
|
|
|
<div class="info-box flexacenter">
|
|
|
|
|
<div class="user-info flexacenter" @click="openUserInfo()">
|
|
|
|
|
<img class="avatar" v-if="detailsInfo['avatar']" :src="detailsInfo['avatar']" />
|
|
|
|
|
<div class="user-name">{{ detailsInfo["nickname"] }}</div>
|
|
|
|
|
<div class="avatar-box flexflex" v-if="avatarState">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(detailsInfo['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" />
|
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(detailsInfo['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
|
|
|
|
<div class="avatar-mask"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="time">{{ handleDate(detailsInfo["publicationdate"]) }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-box flexacenter">
|
|
|
|
|
<div class="answer-btn flexcenter" :class="{ white: detailsInfo['answers'] == 0 }" @click="openIAnswer()">
|
|
|
|
|
<img class="answer-btn-icon answer-icon-edit" src="./img/edit-icon.png" />
|
|
|
|
|
<img class="answer-btn-icon answer-icon-white" src="./img/edit-icon-white.svg" />
|
|
|
|
|
我来回答
|
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-list flexacenter">
|
|
|
|
|
<div class="operate-item flexacenter" style="cursor: auto">
|
|
|
|
|
<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" />
|
|
|
|
|
{{
|
2023-12-20 08:32:13 +00:00
|
|
|
|
detailsInfo["collectionnum"] > 0
|
|
|
|
|
? detailsInfo["collectionnum"]
|
|
|
|
|
: "收藏"
|
2023-12-20 07:48:26 +00:00
|
|
|
|
}}
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
<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" />
|
|
|
|
|
转发
|
|
|
|
|
<div class="transmit-box flexflex" v-if="questionsTransmitState" @click.stop style="z-index: 10">
|
|
|
|
|
<img class="cross-icon" @click.stop="closeAllTransmitState()" src="./img/cross-icon.png" />
|
|
|
|
|
<div class="transmit-left transmit-web">
|
|
|
|
|
<div class="transmit-title">转发网页版</div>
|
|
|
|
|
<div class="transmit-content">
|
|
|
|
|
<div class="transmit-headline">{{ detailsInfo["title"] }}</div>
|
|
|
|
|
<div class="transmit-url">{{ getCurrentUrl() }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="transmit-web-btn flexcenter" @click="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
copyText(detailsInfo['title'] + getCurrentUrl())
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">复制链接</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="transmit-right transmit-mini">
|
|
|
|
|
<div class="transmit-title">转发小程序版</div>
|
|
|
|
|
<div class="transmit-content flexcenter">
|
|
|
|
|
<img class="transmit-mini-img" :src="detailShare['qrcode']" />
|
|
|
|
|
<div class="flexcenter">
|
|
|
|
|
<img class="give-sweep" src="./img/give-sweep.png" />
|
|
|
|
|
扫码转发该问答
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-06 11:06:10 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 一共多少 -->
|
|
|
|
|
<div class="answer-total-amount">共 {{ detailsInfo["answers"] }} 个回答</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 回答-数据 -->
|
|
|
|
|
<div class="answer-box-item" v-for="(item, index) in answerList" :key="index">
|
|
|
|
|
<!-- <div class="icon-circle-box">
|
2023-12-06 07:23:13 +00:00
|
|
|
|
<div class="icon-box flexcenter">A</div>
|
2023-12-20 08:32:13 +00:00
|
|
|
|
</div>-->
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<img class="aa" src="@/img/A.png" />
|
|
|
|
|
|
|
|
|
|
<div class="answer-text" v-html="item['content']" @click="handleAnswerText"></div>
|
|
|
|
|
<div class="info-box flexacenter">
|
|
|
|
|
<div class="user-info flexacenter" @click="openUserInfo(index)">
|
|
|
|
|
<img class="avatar" :src="item['avatar']" />
|
|
|
|
|
<div class="user-name">{{ item["nickname"] }}</div>
|
|
|
|
|
<img class="homeShare" src="./img/title.png" v-if="item['groupid'] == 14" />
|
|
|
|
|
|
|
|
|
|
<div class="avatar-box flexflex" v-if="item['avatarState']">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(item['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" />
|
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(item['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
|
|
|
|
<div class="avatar-mask"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="time">{{ handleDate(item["publicationdate"]) }}</div>
|
|
|
|
|
</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>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-list flexacenter">
|
|
|
|
|
<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)">
|
|
|
|
|
<img class="operate-icon operate-comment-icon" src="./img/comment-icon.png" />
|
|
|
|
|
<!-- {{ item["commentnum"] }} -->
|
|
|
|
|
{{ item["commentnum"] }}
|
|
|
|
|
</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" />
|
|
|
|
|
{{
|
2023-12-20 08:32:13 +00:00
|
|
|
|
item["collectionnum"] == 0
|
|
|
|
|
? "收藏"
|
|
|
|
|
: item["collectionnum"]
|
2023-12-20 07:48:26 +00:00
|
|
|
|
}}
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-item operate-transmit flexacenter" @click="handleAnswerTransmitList(index)" @mouseenter.stop="handleAnswerTransmitList(index)" @mouseleave.stop="closeAllTransmitState()">
|
|
|
|
|
<img class="operate-icon operate-transmit-icon" src="./img/transmit-icon.png" />
|
|
|
|
|
转发
|
|
|
|
|
<div class="transmit-box flexflex" v-if="item['transmitState']" @click.stop>
|
|
|
|
|
<img class="cross-icon" @click.stop="closeAllTransmitState()" src="./img/cross-icon.png" />
|
|
|
|
|
<div class="transmit-left transmit-web">
|
|
|
|
|
<div class="transmit-title">转发网页版</div>
|
|
|
|
|
<div class="transmit-content">
|
|
|
|
|
<div class="transmit-headline">{{ detailsInfo["title"] }}</div>
|
|
|
|
|
<div class="transmit-url">{{ getCurrentUrl() }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="transmit-web-btn flexcenter" @click="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
copyText(detailsInfo['title'] + getCurrentUrl())
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">复制链接</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="transmit-right transmit-mini">
|
|
|
|
|
<div class="transmit-title">转发小程序版</div>
|
|
|
|
|
<div class="transmit-content flexcenter">
|
|
|
|
|
<img class="transmit-mini-img" :src="item['share']['qrcode']" />
|
|
|
|
|
<div class="flexcenter">
|
|
|
|
|
<img class="give-sweep" src="./img/give-sweep.png" />
|
|
|
|
|
扫码转发该问答
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<template v-if="item['commentState']">
|
|
|
|
|
<div class="post-comment flexacenter">
|
|
|
|
|
<input class="post-input flex1" placeholder="说点什么…" v-model="item['commentInput']" />
|
|
|
|
|
<div class="post-ok flexcenter" @click="submitAnswerComments(index)">OK</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 评论 -->
|
|
|
|
|
<div class="comments-box" v-if="item['commentList'] && item['commentList'].length != 0">
|
|
|
|
|
<div class="comments-item" v-for="(it, ind) in item['commentList']" :key="ind">
|
|
|
|
|
<div class="comments-header flexacenter">
|
|
|
|
|
<div class="comments-header-left flexacenter">
|
|
|
|
|
<img class="comments-avatar" :src="it['avatar']" @click="openUserInfo(index, ind)" />
|
|
|
|
|
<div class="comments-username" @click="openUserInfo(index, ind)">{{ it["nickname"] }}</div>
|
|
|
|
|
<div class="comments-time">{{ handleDate(it["timestamp"]) }}</div>
|
|
|
|
|
<div class="comments-identity" v-if="it['questioner'] == 1">提问者</div>
|
|
|
|
|
<div class="comments-identity" v-else-if="it['isauthor'] == 1">回答者</div>
|
|
|
|
|
<div class="avatar-box flexflex" v-if="it['avatarState']">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(it['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" />
|
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(it['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
|
|
|
|
<div class="avatar-mask" @click="openUserInfo(index, ind)"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-header-right flexacenter">
|
|
|
|
|
<div class="menu-box flexacenter" @click="handleMenuState(index, ind)">
|
|
|
|
|
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
|
|
|
|
<div class="report-box flexcenter">举报</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="comment-icon" @click="openAnswerCommentsChild(index, ind)" src="./img/comment-icon-gray.svg" />
|
|
|
|
|
<div class="flexacenter like-box" @click="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
operateAnswerCommentsLike(it['token'], index, ind)
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<img class="like-icon" v-if="it['islike'] == 0" src="./img/like-icon-gray.png" />
|
|
|
|
|
<img class="like-icon" v-else src="./img/like-icon-colours.png" />
|
|
|
|
|
<div class="like-quantity">{{ it["likenum"] || 0 }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-content">
|
|
|
|
|
<div class="comments-text">{{ it["content"] }}</div>
|
|
|
|
|
<div class="comments-input-box flexacenter" v-if="it['childState']">
|
|
|
|
|
<div class="comments-input flexflex">
|
|
|
|
|
<textarea class="flex1" placeholder="回复" v-model="it['commentInput']"></textarea>
|
|
|
|
|
<div class="comments-btn flexcenter" @click="submitAnswerComments(index, ind)">发送</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="forkfork" src="./img/cross-icon.png" @click="closeAnswerCommentsChild(index, ind)" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="child-comments" v-if="it['child'].length != 0">
|
|
|
|
|
<div class="comments-item" v-for="(ite, i) in it['child']" :key="i">
|
|
|
|
|
<div class="comments-header flexacenter">
|
|
|
|
|
<div class="comments-header-left flexacenter">
|
|
|
|
|
<img class="comments-avatar" @click="openUserInfo(index, ind, i)" :src="ite['avatar']" />
|
|
|
|
|
<div class="comments-username" @click="openUserInfo(index, ind, i)">{{ ite["nickname"] }}</div>
|
|
|
|
|
<div class="comments-time">{{ handleDate(ite["timestamp"]) }}</div>
|
|
|
|
|
<div class="comments-identity" v-if="ite['questioner'] == 1">提问者</div>
|
|
|
|
|
<div class="comments-identity" v-else-if="ite['isauthor'] == 1">回答者</div>
|
|
|
|
|
|
|
|
|
|
<div class="avatar-box flexflex" v-if="ite['avatarState']">
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="sendMessage(ite['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/send-messages-icon.png" />
|
|
|
|
|
发送信息
|
|
|
|
|
</a>
|
|
|
|
|
<a class="avatar-item flexcenter" target="_blank" @click.prevent="TAHomePage(ite['uin'])">
|
|
|
|
|
<img class="avatar-icon" src="@/img/homepage-icon.png" />
|
|
|
|
|
TA的主页
|
|
|
|
|
</a>
|
|
|
|
|
<div class="avatar-mask" @click="openUserInfo(index, ind, i)"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-header-right flexacenter">
|
|
|
|
|
<div class="menu-box flexacenter" @click="handleMenuState(index, ind, i)">
|
|
|
|
|
<img class="menu-icon" src="./img/menu-icon-gray.svg" />
|
|
|
|
|
<div class="report-box flexcenter">举报</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="comment-icon" @click="openAnswerCommentsChild(index, ind, i)" src="./img/comment-icon-gray.svg" />
|
|
|
|
|
<div class="flexacenter like-box" @click="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
operateAnswerCommentsLike(
|
|
|
|
|
ite['token'],
|
|
|
|
|
index,
|
|
|
|
|
ind,
|
|
|
|
|
i
|
|
|
|
|
)
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<img class="like-icon" v-if="ite['islike'] == 0" src="./img/like-icon-gray.png" />
|
|
|
|
|
<img class="like-icon" v-else src="./img/like-icon-colours.png" />
|
|
|
|
|
<div class="like-quantity">{{ ite["likenum"] || 0 }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-content">
|
|
|
|
|
<div class="comments-text">
|
|
|
|
|
<div class="comments-reply" v-if="JSON.stringify(ite['reply']) != '[]'">@{{ ite["reply"]["nickname"] }}</div>
|
|
|
|
|
{{ ite["content"] }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="comments-input-box flexacenter" v-if="ite['childState']">
|
|
|
|
|
<div class="comments-input flexflex">
|
|
|
|
|
<textarea class="flex1" placeholder="回复" v-model="ite['commentInput']"></textarea>
|
|
|
|
|
<div class="comments-btn flexcenter" @click="submitAnswerComments(index, ind, i)">发送</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="forkfork" src="./img/cross-icon.png" @click="closeAnswerCommentsChild(index, ind, i)" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="comments-also flexacenter" v-if="it['childnum'] > it['child'].length" @click="alsoCommentsData(index, ind)">
|
|
|
|
|
<div class>还有{{ it["childnum"] - 1 }}条回复</div>
|
|
|
|
|
<img class="also-icon" src="./img/arrow-circular-gray.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- {{ item["commentnum"] + ' ' + item["commentList"].length }} -->
|
|
|
|
|
<!-- <div class="reverl-all flexcenter" @click="handleAllComment(index)" v-if="item['commentnum'] != item['commentList'].length"> -->
|
|
|
|
|
<div class="reverl-all flexcenter" @click="handleAllComment(index)" v-if="item['commentCount'] != item['commentList'].length">
|
|
|
|
|
显示全部
|
|
|
|
|
<img class="arrow-circular" src="./img/arrow-circular-gray.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 评论为空时 -->
|
|
|
|
|
<!-- <div class="comments-empty-box flexflex" v-if="item['commentnum'] == 0"> -->
|
|
|
|
|
<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>
|
|
|
|
|
|
|
|
|
|
<!-- · 著作权归作者所有 · -->
|
|
|
|
|
<div class="copyright flexcenter" v-if="answerList.length > 0">· 著作权归作者所有 ·</div>
|
|
|
|
|
|
|
|
|
|
<!-- 你的答案 -->
|
|
|
|
|
<div class="your-answer-box" v-if="!isNeedLogin">
|
|
|
|
|
<div class="your-answer-header flexacenter">您的答案</div>
|
|
|
|
|
<div class="your-answer-textarea" :class="{ placeholder: yourAnswerPlaceholderState }" contenteditable="true" @paste="handlePaste($event, 'you')" v-html="yourAnswer['text']" @input="handleInputYou"></div>
|
|
|
|
|
|
|
|
|
|
<div class="flexacenter your-answer-bottom">
|
|
|
|
|
<div class="option-box flexacenter" @click="cutYourAnswerAnonymous()">
|
|
|
|
|
<img class="option-icon" v-if="yourAnswer['anonymous'] == 0" src="./img/tick-no.svg" />
|
|
|
|
|
<img class="option-icon" v-else src="./img/tick-option.svg" />
|
|
|
|
|
匿名发表
|
|
|
|
|
</div>
|
|
|
|
|
<div class="your-answer-submit flexcenter" @click="handleYourAnswer">提交回答</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 回答-没有数据 -->
|
|
|
|
|
<div class="answer-empty-box flexcenter" v-if="isNeedLogin && answerList.length == 0">
|
|
|
|
|
<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" />
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="empty-hint">我在等待你的回答</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="mobile-phone-check flexcenter">
|
|
|
|
|
<img class="QRCode-icon" src="./img/QRCode-icon.svg" alt />
|
|
|
|
|
手机查看该问答
|
|
|
|
|
<div class="QRCode-pop flexcenter">
|
|
|
|
|
<img class="offer-mini-QRcode" :src="detailShare['qrcode']" />
|
|
|
|
|
<div class="QRCode-hint flexacenter">
|
|
|
|
|
<img class="QRCode-img" src="./img/give-sweep.png" />
|
|
|
|
|
微信扫一扫
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 我的弹窗 -->
|
|
|
|
|
<div class="popover-mask my-popover flexcenter" v-if="myType">
|
|
|
|
|
<div class="popover-box flexflex">
|
|
|
|
|
<img class="cross-icon" src="./img/cross-icon.png" @click="myType = ''" />
|
|
|
|
|
<div class="tab-list flexcenter">
|
|
|
|
|
<div class="tab-item flexacenter" :class="{ pitch: myType == 'collect' }" @click="handleMy('collect')">
|
|
|
|
|
我的收藏
|
|
|
|
|
<div class="quantity">{{ myCollectionCount || myCount["collect"] || 0 }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="long-string"></div>
|
|
|
|
|
<div class="tab-item flexacenter" :class="{ pitch: myType == 'questions' }" @click="handleMy('questions')">
|
|
|
|
|
我的提问
|
|
|
|
|
<div class="quantity">{{ myQuestionsCount || myCount["questions"] || 0 }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="long-string"></div>
|
|
|
|
|
<div class="tab-item flexacenter" :class="{ pitch: myType == 'answers' }" @click="handleMy('answers')">
|
|
|
|
|
我的回答
|
|
|
|
|
<div class="quantity">{{ myAnswerCount || myCount["answer"] || 0 }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="empty-box flexcenter" v-if="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
(myType == 'collect' && myCollectionList.length == 0) ||
|
|
|
|
|
(myType == 'answers' && myAnswerList.length == 0) ||
|
|
|
|
|
(myType == 'questions' && myQuestionsList.length == 0)
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="dot-list flexacenter">
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-yellow.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
<img class="item" src="./img/dot-gray.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
<img class="empty-icon" src="./img/empty-icon.svg" />
|
|
|
|
|
<div class="empty-hint">暂无内容</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="content-box collect-list" v-if="myType == 'collect' && myCollectionList.length != 0" @scroll="handleCollectionScroll">
|
|
|
|
|
<div class="item flexflex" v-for="(item, index) in myCollectionList" :key="item" @click.stop="myOpenDetails(item.data['uniqid'])">
|
|
|
|
|
<template v-if="item.type == 'askanswercollection'">
|
|
|
|
|
<div class="icon a flexcenter">A</div>
|
|
|
|
|
<div class="centre flexflex flex1">
|
|
|
|
|
<div class="titletitle ellipsis" v-html="item['data']['content']"></div>
|
|
|
|
|
<div class="text ellipsis">提问:{{ item["data"]["title"] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="delete-box flexacenter">
|
|
|
|
|
<img class="delete-icon" @click.stop="cancelCollection(item['token'], index)" src="./img/delete-icon.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-else>
|
|
|
|
|
<div class="icon q flexcenter">Q</div>
|
|
|
|
|
<div class="centre flexflex flex1">
|
|
|
|
|
<div class="titletitle ellipsis">{{ item["data"]["title"] }}</div>
|
|
|
|
|
<div class="text ellipsis">
|
|
|
|
|
{{
|
2023-12-20 08:32:13 +00:00
|
|
|
|
item["data"]["answers"] > 0
|
|
|
|
|
? "共" + item["data"]["answers"] + "个回答"
|
|
|
|
|
: "暂无回答"
|
2023-12-20 07:48:26 +00:00
|
|
|
|
}}
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="delete-box flexacenter">
|
|
|
|
|
<img class="delete-icon" @click.stop="cancelCollection(item['token'], index)" src="./img/delete-icon.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="content-box answers-list" v-if="myType == 'answers' && myAnswerList.length != 0" @scroll="handleAnswersScroll">
|
|
|
|
|
<div class="item flexflex" v-for="(item, index) in myAnswerList" :key="item" @click.stop="myOpenDetails(item['uniqid'])">
|
|
|
|
|
<div class="icon a flexcenter">A</div>
|
|
|
|
|
<div class="centre flexflex flex1">
|
|
|
|
|
<div class="info flexacenter">
|
|
|
|
|
<div class="name">{{ item["nickname"] }}</div>
|
|
|
|
|
<div class="time">{{ handleDate(item["publicationdate"]) }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="titletitle ellipsis" v-html="item['content']"></div>
|
|
|
|
|
<div class="text ellipsis">提问:{{ item["title"] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-box flexacenter">
|
|
|
|
|
<div class="state-box flexacenter" @click.stop="cutAnswerPopupState(index)">
|
|
|
|
|
<div class="text">{{ item["anonymous"] == 0 ? "公开" : "匿名" }}</div>
|
|
|
|
|
<img class="arrows" src="./img/arrows-icon.svg" />
|
|
|
|
|
<div class="state-popup flexflex" v-if="item['popupState']">
|
|
|
|
|
<!-- <div class="state-popup-mask" @click.stop="cutAnswerPopupState(index)"></div> -->
|
|
|
|
|
<div class="state-popup-item flexacenter flex1" :class="{ pitch: item['anonymous'] == 0 }" @click.stop="changeAnonymous(item['token'], 0, index)">
|
|
|
|
|
<div class>公开发表</div>
|
|
|
|
|
<img class="state-popup-icon" src="./img/tick-orange.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="state-popup-item flexacenter flex1" :class="{ pitch: item['anonymous'] == 1 }" @click.stop="changeAnonymous(item['token'], 1, index)">
|
|
|
|
|
<div class>匿名发表</div>
|
|
|
|
|
<img class="state-popup-icon" src="./img/tick-orange.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<img class="edit-icon" @click.stop="openIAnswer(index, 'my')" src="./img/edit-icon.png" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="content-box questions-list" v-if="myType == 'questions' && myQuestionsList.length != 0" @scroll="handleQuestionsScroll">
|
|
|
|
|
<div class="item flexflex" v-for="(item, index) in myQuestionsList" :key="item" @click.stop="myOpenDetails(item['uniqid'])">
|
|
|
|
|
<div class="icon q flexcenter">Q</div>
|
|
|
|
|
<div class="centre flexflex flex1">
|
|
|
|
|
<div class="info flexacenter">
|
|
|
|
|
<div class="name">{{ item["nickname"] }}</div>
|
|
|
|
|
<div class="time">{{ handleDate(item["publicationdate"]) }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="titletitle ellipsis">{{ item["title"] }}</div>
|
|
|
|
|
<div class="text flexacenter">
|
|
|
|
|
<div class="new-answer flexacenter" v-if="item['authornewnum'] > 0">
|
|
|
|
|
有{{ item["authornewnum"] }}个新回答
|
|
|
|
|
<div class="long-string"></div>
|
|
|
|
|
</div>
|
|
|
|
|
{{
|
2023-12-20 08:32:13 +00:00
|
|
|
|
item["answers"] == 0
|
|
|
|
|
? "暂无回答"
|
|
|
|
|
: "共" + item["answers"] + "个回答"
|
2023-12-20 07:48:26 +00:00
|
|
|
|
}}
|
2023-12-20 11:11:08 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="operate-box flexacenter">
|
|
|
|
|
<div class="state-box flexacenter" @click.stop="cutQuestionsPopupState(index)">
|
|
|
|
|
<div class="text">{{ item["anonymous"] == 0 ? "公开" : "匿名" }}</div>
|
|
|
|
|
<img class="arrows" src="./img/arrows-icon.svg" />
|
|
|
|
|
<div class="state-popup flexflex" v-if="item['popupState']">
|
|
|
|
|
<div class="state-popup-item flexacenter flex1" :class="{ pitch: item['anonymous'] == 0 }" @click.stop="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
changeAnonymousQuestions(item['token'], 0, index)
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class>公开发表</div>
|
|
|
|
|
<img class="state-popup-icon" src="./img/tick-orange.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="state-popup-item flexacenter flex1" :class="{ pitch: item['anonymous'] == 1 }" @click.stop="
|
2023-12-20 07:48:26 +00:00
|
|
|
|
changeAnonymousQuestions(item['token'], 1, index)
|
2023-12-20 08:32:13 +00:00
|
|
|
|
">
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class>匿名发表</div>
|
|
|
|
|
<img class="state-popup-icon" src="./img/tick-orange.svg" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 我要提问 -->
|
|
|
|
|
<div class="popover-mask flexcenter issue-box" v-if="questionsSetp" @click="cutQuestionsSetp(0)">
|
|
|
|
|
<!-- 第一步 -->
|
|
|
|
|
<div class="choosing-theme" v-if="questionsSetp == 1" @click.stop>
|
|
|
|
|
<div class="titletitle">选择提问所属主题</div>
|
|
|
|
|
<div class="theme-list flexflex">
|
|
|
|
|
<div class="theme-stair-box flexflex" v-for="(item, index) in questionsTypeList" :key="index">
|
|
|
|
|
<div class="theme-item flexcenter" v-for="item in item" :key="item.id" @click="choosingTheme(item.id)">{{ item.name }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 第二步 -->
|
|
|
|
|
<div class="issue-form" v-else @click.stop>
|
|
|
|
|
<img class="issue-bj" src="./img/issue-bj.svg" />
|
|
|
|
|
<div class="flexcenter q">Q</div>
|
|
|
|
|
<img class="cross-icon" @click="cutQuestionsSetp(0)" src="./img/cross-icon.png" />
|
|
|
|
|
<div class="issue-input">
|
|
|
|
|
<textarea v-model="questionsObj.title" placeholder="一句话描述问题,以问号结尾"></textarea>
|
|
|
|
|
</div>
|
|
|
|
|
<textarea class="issue-replenish" v-model="questionsObj.content" placeholder="欢迎补充,清晰表达问题的关键点,可获得更有效的解答(非必填)"></textarea>
|
|
|
|
|
<div class="issue-bottom flexacenter">
|
|
|
|
|
<div class="option-box flexacenter" @click="cutAnonymous" style="color: #333">
|
|
|
|
|
<img class="option-icon" v-if="questionsObj.anonymous == 0" src="./img/tick-no.svg" />
|
|
|
|
|
<img class="option-icon" v-else src="./img/tick-option.svg" />
|
|
|
|
|
匿名发表
|
|
|
|
|
<div class style="color: #aaa">(发布后只能修改是否匿名)</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="issue-btn flexcenter" @click="postingIssue">发布问题</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
<!-- 编辑回答 -->
|
|
|
|
|
<div class="popover-mask flexcenter" v-if="IAnswerEditState">
|
|
|
|
|
<div class="edit-answers">
|
|
|
|
|
<img class="close-icon" src="./img/cross-icon.png" @click="closeIAnswer" />
|
|
|
|
|
<div class="titletitle">编辑回答</div>
|
|
|
|
|
<div class="question-textarea" :class="{ placeholder: questionPlaceholderState }" contenteditable="true" @paste="handlePaste($event)" v-html="IAnswerInfo['text']" @input="handleInput"></div>
|
|
|
|
|
<div class="issue-bottom flexacenter">
|
|
|
|
|
<div class="option-box flexacenter" @click="amendIAnswer">
|
|
|
|
|
<img class="option-icon" v-if="IAnswerInfo['anonymous'] == 0" src="./img/tick-no.svg" />
|
|
|
|
|
<img class="option-icon" v-else src="./img/tick-option.svg" />
|
|
|
|
|
匿名发表
|
|
|
|
|
</div>
|
|
|
|
|
<div class="issue-btn flexcenter" @click="submitAnswer">提交回答</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<!-- 我来回答 -->
|
|
|
|
|
<div class="popover-mask flexcenter" v-if="IAnswerState">
|
|
|
|
|
<div class="i-answer-box flexflex">
|
|
|
|
|
<img class="close-icon" src="./img/cross-icon.png" @click="closeIAnswer" />
|
|
|
|
|
<div class="question-header">
|
|
|
|
|
<div class="question-title flexflex">
|
|
|
|
|
<div class="question-icon flexcenter">Q</div>
|
|
|
|
|
<div class="flex1" v-html="IAnswerInfo['title']"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="question-replenish" v-if="IAnswerInfo['content']" v-html="IAnswerInfo['content']"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="question-middle flexflex">
|
|
|
|
|
<div class="question-icon flexcenter">A</div>
|
|
|
|
|
<div class="question-textarea" :class="{ placeholder: questionPlaceholderState }" contenteditable="true" @paste="handlePaste($event)" v-html="IAnswerInfo['text']" @input="handleInput"></div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
<div class="issue-bottom flexacenter">
|
|
|
|
|
<div class="option-box flexacenter" @click="amendIAnswer">
|
|
|
|
|
<img class="option-icon" v-if="IAnswerInfo['anonymous'] == 0" src="./img/tick-no.svg" />
|
|
|
|
|
<img class="option-icon" v-else src="./img/tick-option.svg" />
|
|
|
|
|
匿名发表
|
|
|
|
|
</div>
|
|
|
|
|
<div class="issue-btn flexcenter" @click="submitAnswer">提交回答</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
<!-- 提示框 -->
|
|
|
|
|
<transition name="msg" appear v-show="msg['state']">
|
|
|
|
|
<div class="box-item" :class="boxClass()" :style="{ top: 20 + 'px' }">
|
|
|
|
|
<div class="msg-container">{{ msg["text"] }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</transition>
|
|
|
|
|
|
|
|
|
|
<!-- 大图 -->
|
|
|
|
|
<div class="detail-image-mask flexcenter" v-if="dialogSrc" @click="dialogSrc = ''">
|
|
|
|
|
<div class="detail-image flexcenter">
|
|
|
|
|
<img class="detail-img" :src="dialogSrc" />
|
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
<!-- 举报 -->
|
|
|
|
|
<div class="alert-form" v-show="alertShow">
|
|
|
|
|
<div class="comments reports">
|
|
|
|
|
<div class="head">
|
|
|
|
|
<span style="display: flex; align-items: center">
|
|
|
|
|
<img style="width: 25px; margin-right: 7px" src="//app.gter.net/image/gter/offer/img/exclamationpoint.png?v=4.2.08_331040000" />举报投诉
|
|
|
|
|
</span>
|
|
|
|
|
<div class="close icon-close iconfont" @click="alertShow = false"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<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>
|
|
|
|
|
{{ s }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="text-box">
|
|
|
|
|
<textarea placeholder="请输入举报原因" v-model="alertText" maxlength="200"></textarea>
|
|
|
|
|
<div class="text-num">{{ 200 - alertText.length }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="footer">
|
|
|
|
|
<button type="button" @click="alertShow = false">取消</button>
|
|
|
|
|
<button type="submit" :disabled="checkList.length == 0" @click="alertSubmit">提交</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-12-20 07:48:26 +00:00
|
|
|
|
</div>
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
2023-12-07 07:11:20 +00:00
|
|
|
|
|
2023-12-06 07:23:13 +00:00
|
|
|
|
<script>
|
2023-12-20 11:11:08 +00:00
|
|
|
|
import { onMounted, onUnmounted, ref, nextTick, watchEffect, watch } from "vue";
|
2023-12-20 07:48:26 +00:00
|
|
|
|
import axios from "axios";
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
|
|
|
|
export default {
|
2023-12-20 11:11:08 +00:00
|
|
|
|
name: "#answer-app",
|
|
|
|
|
async setup() {
|
|
|
|
|
|
|
|
|
|
const $ajax = (url, data) => {
|
|
|
|
|
url = url.indexOf("//") > -1 ? url : baseURL + url;
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
|
axios
|
|
|
|
|
.post(url, data, {
|
|
|
|
|
emulateJSON: true,
|
|
|
|
|
withCredentials: true,
|
|
|
|
|
headers: {
|
|
|
|
|
// authorization: process.env.NODE_ENV !== "production" && "9c92af854f552bbd2aab43230bcf8438", // 头部标记
|
|
|
|
|
authorization:
|
|
|
|
|
process.env.NODE_ENV !== "production" &&
|
|
|
|
|
"7a89997c2ccd8cb5ed8cb20d843dafdd", // 头部标记 ada
|
|
|
|
|
// authorization: "2e25ccc21d5f86b670e7476f3b58ea5d", // 头部标记
|
|
|
|
|
// "Cache-Control": "no-cache",
|
|
|
|
|
// Pragma: "no-cache",
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
.then(function (res) {
|
|
|
|
|
var data = null;
|
|
|
|
|
try {
|
|
|
|
|
data =
|
|
|
|
|
typeof res.data == "string" ? JSON.parse(res.data) : res.data;
|
|
|
|
|
if (data["code"] == 401) isNeedLogin.value = true;
|
|
|
|
|
|
|
|
|
|
if (data["code"] != 200)
|
|
|
|
|
handleMsg("error", data["message"] || "报错了,请重试!!!");
|
|
|
|
|
// if (data["code"] == 401) window.location.href = "https://passport.gter.net"
|
|
|
|
|
} catch (error) { }
|
|
|
|
|
resolve(data);
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
// if (err.response.status == 401) window.location.href = "https://passport.gter.net"
|
|
|
|
|
if (err.response.status == 401) isNeedLogin.value = true;
|
|
|
|
|
resolve(err.response.data);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
const $ajaxGET = (url, data) => {
|
|
|
|
|
url = url.indexOf("//") > -1 ? url : baseURL + url;
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
|
axios
|
|
|
|
|
.get(url, data, {
|
|
|
|
|
emulateJSON: true,
|
|
|
|
|
withCredentials: true,
|
|
|
|
|
headers: {
|
|
|
|
|
authorization:
|
|
|
|
|
process.env.NODE_ENV !== "production" &&
|
|
|
|
|
"7a89997c2ccd8cb5ed8cb20d843dafdd", // 头部标记
|
|
|
|
|
// "Cache-Control": "no-cache",
|
|
|
|
|
// Pragma: "no-cache",
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
.then(function (res) {
|
|
|
|
|
var data = null;
|
|
|
|
|
try {
|
|
|
|
|
data =
|
|
|
|
|
typeof res.data == "string" ? JSON.parse(res.data) : res.data;
|
|
|
|
|
if (data["code"] == 401) isNeedLogin.value = true;
|
|
|
|
|
|
|
|
|
|
if (data["code"] != 200)
|
|
|
|
|
handleMsg("error", data["message"] || "报错了,请重试!!!");
|
|
|
|
|
// if (data["code"] == 401) window.location.href = "https://passport.gter.net"
|
|
|
|
|
} catch (error) { }
|
|
|
|
|
resolve(data);
|
|
|
|
|
})
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
// if (err.response.status == 401) window.location.href = "https://passport.gter.net"
|
|
|
|
|
if (err.response.status == 401) isNeedLogin.value = true;
|
|
|
|
|
resolve(err.response.data);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
let isNeedLogin = ref(true); // 是否需要有登录
|
|
|
|
|
// 跳转登录
|
|
|
|
|
const goLogin = () => ajax_login();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
const route = useRoute();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
let detailsInfoDataVuex = useState("detailsInfoData", () => { });
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
const baseURL = "https://ask.gter.net";
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
let type = ref("list"); // list details
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
// getUrlParams()
|
|
|
|
|
// getUserData()
|
|
|
|
|
if (process.env.NODE_ENV !== "production") isNeedLogin.value = false;
|
|
|
|
|
else determineIsLogin();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
getListClass();
|
|
|
|
|
window.addEventListener("scroll", handleScroll);
|
|
|
|
|
getHistoricalSearchList();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
if (isNeedScrollMiddle) scrollLeftInMiddle();
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
if (process.client) originUrl.value = window.location.origin;
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
listenPageBack();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
if (detailsInfoDataVuex.value) hanleServerRequestData();
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
initState.value++
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-21 02:53:20 +00:00
|
|
|
|
const params = route.query;
|
|
|
|
|
|
|
|
|
|
// console.log(params['ispublish']);
|
|
|
|
|
// 是否直接打开提问
|
|
|
|
|
if (params['ispublish']) questionsInit()
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
2023-12-07 07:11:20 +00:00
|
|
|
|
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 处理在服务端已经请求了详情接口 数据
|
|
|
|
|
const hanleServerRequestData = () => {
|
|
|
|
|
const params = route.query;
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
type.value = "details";
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
let data = detailsInfoDataVuex.value;
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
|
|
|
|
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";
|
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// calculateListIndex(data.info, params["uniqid"]);
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
|
|
|
|
answerList.value = [];
|
|
|
|
|
answerPage.value = 1;
|
|
|
|
|
getAnswerList();
|
|
|
|
|
|
|
|
|
|
closeAllTransmitState();
|
|
|
|
|
|
|
|
|
|
replaceState({ uniqid: params["uniqid"] });
|
|
|
|
|
seo.value = data.seo;
|
2023-12-20 11:11:08 +00:00
|
|
|
|
closeBottom();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 是否是后退 状态
|
|
|
|
|
let isBackState = false;
|
|
|
|
|
// 监听页面后退效果 重新获取 url 请求
|
|
|
|
|
const listenPageBack = () => {
|
|
|
|
|
window.addEventListener("popstate", function (event) {
|
|
|
|
|
const params = route.query;
|
|
|
|
|
if (params["keyword"]) keyword.value = params["keyword"];
|
|
|
|
|
if (params["tid"]) typePitch.value = params["tid"];
|
|
|
|
|
if (params["uniqid"]) {
|
|
|
|
|
isBackState = true;
|
|
|
|
|
getDetails(params["uniqid"]);
|
|
|
|
|
} else {
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
seo.value = {};
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 判断是否登录状态
|
|
|
|
|
const determineIsLogin = () => {
|
|
|
|
|
let count = 0;
|
|
|
|
|
let timer = setInterval(() => {
|
|
|
|
|
if (Object.keys(window["userInfoWin"]).length !== 0) {
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
if (window["userInfoWin"]["uid"]) isNeedLogin.value = false;
|
|
|
|
|
}
|
|
|
|
|
count++;
|
|
|
|
|
if (count >= 20) clearInterval(timer);
|
|
|
|
|
}, 100);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let originUrl = ref("");
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
window.removeEventListener("keydown", handleKeydown);
|
|
|
|
|
window.removeEventListener("scroll", handleScroll);
|
2023-12-20 07:48:26 +00:00
|
|
|
|
});
|
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 获取当前url
|
|
|
|
|
const getCurrentUrl = () => {
|
|
|
|
|
return window.location.href;
|
|
|
|
|
};
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 我的 数据 数量
|
|
|
|
|
let myCount = ref({}); //
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 获取用户数据
|
|
|
|
|
const getUserData = (key) => {
|
|
|
|
|
$ajax("/api/user").then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
myCount.value = data.count;
|
|
|
|
|
handleMy(key);
|
2023-12-20 07:48:26 +00:00
|
|
|
|
});
|
2023-12-20 11:11:08 +00:00
|
|
|
|
};
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 是否是搜索模式
|
|
|
|
|
let isSearchMode = ref(false);
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 获取历史记录方法
|
|
|
|
|
const getHistoricalSearchList = () => {
|
|
|
|
|
const list = localStorage.getItem("historical-Search");
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
if (list) historicalSearchList.value = JSON.parse(list) || [];
|
|
|
|
|
else historicalSearchList.value = [];
|
|
|
|
|
};
|
2023-12-20 07:48:26 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 存入历史记录 随便去重 和 限制长度 方法
|
|
|
|
|
const setHistoricalSearchList = () => {
|
|
|
|
|
if (!keyword.value) return;
|
|
|
|
|
historicalSearchList.value.unshift(keyword.value);
|
|
|
|
|
historicalSearchList.value = [...new Set(historicalSearchList.value)];
|
|
|
|
|
historicalSearchList.value = historicalSearchList.value.slice(0, 10);
|
|
|
|
|
|
|
|
|
|
localStorage.setItem(
|
|
|
|
|
"historical-Search",
|
|
|
|
|
JSON.stringify(historicalSearchList.value)
|
|
|
|
|
);
|
|
|
|
|
};
|
2023-12-06 07:23:13 +00:00
|
|
|
|
|
2023-12-20 11:11:08 +00:00
|
|
|
|
// 搜索点击事件
|
|
|
|
|
const searchClick = () => {
|
|
|
|
|
// if (keyword.value == "") return
|
|
|
|
|
setHistoricalSearchList();
|
|
|
|
|
page = 1;
|
|
|
|
|
list.value = [];
|
|
|
|
|
backupsList = [];
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
|
|
|
|
|
deleteState(["uniqid"]);
|
|
|
|
|
replaceState({
|
|
|
|
|
keyword: keyword.value,
|
|
|
|
|
});
|
|
|
|
|
searchBlur();
|
|
|
|
|
getList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 搜索获取焦点
|
|
|
|
|
const searchFocus = () => {
|
|
|
|
|
if (historicalSearchList.value.length == 0) return;
|
|
|
|
|
historicalSearchState.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 搜索失去焦点
|
|
|
|
|
const searchBlur = () => {
|
|
|
|
|
setTimeout(() => (historicalSearchState.value = false), 300);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击历史记录 item
|
|
|
|
|
const handleClickHistoricalItem = (value) => {
|
|
|
|
|
keyword.value = value;
|
|
|
|
|
searchClick();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击清除搜索
|
|
|
|
|
const handleClickClear = () => {
|
|
|
|
|
keyword.value = "";
|
|
|
|
|
page = 1;
|
|
|
|
|
list.value = [];
|
|
|
|
|
backupsList = [];
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
|
|
|
|
|
getList();
|
|
|
|
|
|
|
|
|
|
deleteState(["keyword"]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let historicalSearchState = ref(false); // 历史记录弹窗状态
|
|
|
|
|
let historicalSearchList = ref([]); // 历史记录数据
|
|
|
|
|
|
|
|
|
|
let tabListFixeState = ref(false); // 顶部 类型的 固定状态
|
|
|
|
|
const handleScroll = () => {
|
|
|
|
|
const scrollTop =
|
|
|
|
|
document.documentElement.scrollTop || document.body.scrollTop;
|
|
|
|
|
|
|
|
|
|
const scrollHeight = document.documentElement.scrollHeight;
|
|
|
|
|
const clientHeight = document.documentElement.clientHeight;
|
|
|
|
|
|
|
|
|
|
// 列表下 滑动到底部 获取新数据
|
|
|
|
|
if (scrollTop + clientHeight >= scrollHeight - 40 && type.value == "list")
|
|
|
|
|
getList();
|
|
|
|
|
|
|
|
|
|
// 列表下 滚动到顶部 触发类型的固定状态
|
|
|
|
|
// if (scrollTop > 115 && type.value == "list") tabListFixeState.value = true
|
|
|
|
|
if (scrollTop > 115) tabListFixeState.value = true;
|
|
|
|
|
else tabListFixeState.value = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let keyword = ref(""); // 搜索的值
|
|
|
|
|
let keywordText = ref(""); // 搜索的文本
|
|
|
|
|
|
|
|
|
|
let list = ref([]); // 列表数据
|
|
|
|
|
let backupsList = []; // 备份列表数据
|
|
|
|
|
let page = 1;
|
|
|
|
|
let total = ref(0); // 回答总数
|
|
|
|
|
let loading = ref(false);
|
|
|
|
|
let inTheEndState = ref(false); // 到底了状态
|
|
|
|
|
let isListEmptyState = ref(); // 列表是否为空的状态
|
|
|
|
|
let zeroreply = ref(0) // 只看0条回答状态
|
|
|
|
|
|
|
|
|
|
// 获取列表数据
|
|
|
|
|
const getList = () => {
|
|
|
|
|
if (page == 0 || loading.value) return;
|
|
|
|
|
loading.value = true;
|
|
|
|
|
|
|
|
|
|
$ajax("/api/lists", {
|
|
|
|
|
page,
|
|
|
|
|
limit: 20,
|
|
|
|
|
keyword: keyword.value,
|
|
|
|
|
type: typePitch.value,
|
|
|
|
|
zeroreply: zeroreply.value,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code == 401) goLogin();
|
|
|
|
|
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
|
|
|
|
|
let data = res.data;
|
2023-12-21 02:53:20 +00:00
|
|
|
|
data.data.forEach(element => {
|
|
|
|
|
element['content'] = element['content'].replace(/<[^>]*>/g, "");
|
|
|
|
|
})
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
list.value = list.value.concat(data.data || []);
|
|
|
|
|
backupsList = backupsList.concat(data.data || []);
|
|
|
|
|
|
|
|
|
|
total.value = data.count || 0;
|
|
|
|
|
|
|
|
|
|
keywordText.value = keyword.value || "";
|
|
|
|
|
|
|
|
|
|
// page++
|
|
|
|
|
if (list.value.length >= data["count"]) page = 0;
|
|
|
|
|
else page++;
|
|
|
|
|
|
|
|
|
|
if (page == 0 && list.value.length != 0) inTheEndState.value = true;
|
|
|
|
|
else inTheEndState.value = false;
|
|
|
|
|
|
|
|
|
|
if (list.value.length == 0) isListEmptyState.value = true;
|
|
|
|
|
else isListEmptyState.value = false;
|
|
|
|
|
|
|
|
|
|
if (keyword.value) isSearchMode.value = true;
|
|
|
|
|
else isSearchMode.value = false;
|
|
|
|
|
|
|
|
|
|
if (type.value == "details") handleInsertRelatedlist();
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (loading.value = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let typeList = ref([]);
|
|
|
|
|
let typePitch = ref(null);
|
|
|
|
|
|
|
|
|
|
// 获取分类数据 列表分类
|
|
|
|
|
const getListClass = () => {
|
|
|
|
|
$ajaxGET("/api/common/typeList").then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
typeList.value = data;
|
|
|
|
|
|
|
|
|
|
getPageHeight();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let pageHeaderHeight = ref(0); // 头部的高度
|
|
|
|
|
let pageListHeight = ref(0); // 底部列表的高度
|
|
|
|
|
|
|
|
|
|
const getPageHeight = () => {
|
|
|
|
|
let pageHeader = document.querySelector("#pageHeader");
|
|
|
|
|
pageHeaderHeight.value = pageHeader.clientHeight + 10;
|
|
|
|
|
pageListHeight.value = window.innerHeight - pageHeaderHeight.value;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let detailsInfo = ref({}); // 详情信息
|
|
|
|
|
let detailsIsanswered = ref(0); // 详情信息
|
|
|
|
|
let detailsIscollection = ref(0); // 详情信息
|
|
|
|
|
let detailsIsmyself = ref(0); // 详情信息
|
|
|
|
|
let detailsToken = ""; // 详情信息
|
|
|
|
|
let detailShare = ref({}); // 详情信息
|
|
|
|
|
let detailLoading = ref(false); // 详情加载
|
|
|
|
|
|
|
|
|
|
// 获取详情
|
|
|
|
|
const getDetails = (uniqid, index, isOpenAnswer) => {
|
|
|
|
|
if (detailLoading.value) return;
|
|
|
|
|
detailLoading.value = true;
|
|
|
|
|
// process.env.NODE_ENV !== "production" && (uniqid = "fCSyLDDa0r1q") // 标记1一下 8yr1m1fOH5CS fubm5CnD05qj fCSyLDDa0r1q
|
|
|
|
|
|
|
|
|
|
detailsInfo.value = {};
|
|
|
|
|
answerList.value = [];
|
|
|
|
|
answerPage.value = 0;
|
|
|
|
|
|
|
|
|
|
$ajax("/api/details", { uniqid })
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code != 200) {
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
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";
|
|
|
|
|
|
|
|
|
|
closeBottom();
|
|
|
|
|
|
|
|
|
|
if (index !== null && index !== undefined) cut(index);
|
|
|
|
|
else calculateListIndex(data.info, uniqid);
|
|
|
|
|
|
|
|
|
|
answerList.value = [];
|
|
|
|
|
answerPage.value = 1;
|
|
|
|
|
getAnswerList();
|
|
|
|
|
|
|
|
|
|
closeAllTransmitState();
|
|
|
|
|
|
|
|
|
|
if (isOpenAnswer) openIAnswer();
|
|
|
|
|
|
|
|
|
|
// 非后退状态才可以 修改 url
|
|
|
|
|
if (!isBackState) replaceState({ uniqid });
|
|
|
|
|
isBackState = false;
|
|
|
|
|
|
|
|
|
|
seo.value = data.seo;
|
|
|
|
|
|
|
|
|
|
// 初始化 我来回答的框
|
|
|
|
|
yourAnswer.value = {
|
|
|
|
|
text: "",
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 默认 详情 div 滚动到顶部
|
|
|
|
|
nextTick(() => detailsAreaScrollTop());
|
|
|
|
|
|
|
|
|
|
handleInsertRelatedlist(uniqid);
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (detailLoading.value = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 默认 详情 div 滚动到顶部 预防用户在 列表重复点击
|
|
|
|
|
const detailsAreaScrollTop = () => {
|
|
|
|
|
let detailsArea = document.querySelector(".details-area-box");
|
|
|
|
|
|
|
|
|
|
detailsArea.scrollTo({
|
|
|
|
|
top: 0,
|
|
|
|
|
behavior: "smooth",
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const calculateListIndex = (info, uniqid) => {
|
|
|
|
|
let targetList = [...list.value];
|
|
|
|
|
if (targetList.length == 0 && isSearchMode.value == false && myModelState.value == false) {
|
|
|
|
|
setTimeout(() => calculateListIndex(info, uniqid), 200);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let valve = false;
|
|
|
|
|
list.value.forEach((element, index) => {
|
|
|
|
|
if (element["uniqid"] == uniqid) {
|
|
|
|
|
cut(index);
|
|
|
|
|
pitchIndex.value = index;
|
|
|
|
|
valve = true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!valve) {
|
|
|
|
|
let content = "";
|
|
|
|
|
if (info["content"].indexOf("<img") == -1) content = info["content"];
|
|
|
|
|
const obj = {
|
|
|
|
|
answers: info["answers"],
|
|
|
|
|
content,
|
|
|
|
|
publicationdate: info["publicationdate"],
|
|
|
|
|
title: info["title"],
|
|
|
|
|
typename: info["typename"],
|
|
|
|
|
uniqid,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
list.value.unshift(obj);
|
|
|
|
|
if (!myModelState.value) backupsList.unshift(obj);
|
|
|
|
|
|
|
|
|
|
cut(0);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let answerList = ref([]); // 回答列表数据
|
|
|
|
|
let answerPage = ref(1); // 回答列表页数
|
|
|
|
|
let answerLoading = false; // 回答列表加载
|
|
|
|
|
|
|
|
|
|
// 获取详情的回答数据
|
|
|
|
|
const getAnswerList = () => {
|
|
|
|
|
if (answerLoading || answerPage.value == 0) return;
|
|
|
|
|
answerLoading = true;
|
|
|
|
|
|
|
|
|
|
$ajax("/api/details/answerList", {
|
|
|
|
|
token: detailsToken,
|
|
|
|
|
limit: 20,
|
|
|
|
|
page: answerPage.value,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
|
|
|
|
|
data.data.forEach((element) => {
|
|
|
|
|
element["commentList"] = [];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
answerList.value = answerList.value.concat(data.data);
|
|
|
|
|
|
|
|
|
|
if (answerList.value.length == data["count"]) answerPage.value = 0;
|
|
|
|
|
else answerPage.value++;
|
|
|
|
|
|
|
|
|
|
detailsInfo.value["answers"] = data["count"];
|
|
|
|
|
if (pitchIndex.value !== null)
|
|
|
|
|
list.value[pitchIndex.value]["answers"] = data["count"];
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (answerLoading = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 操作 - 点赞
|
|
|
|
|
const operateLike = (token, index) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/operate/like", { token }).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
answerList.value[index]["islike"] = data["status"];
|
|
|
|
|
answerList.value[index]["likenum"] = data["count"];
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let isNeedNewColletData = false; // 是否需要获取新的收藏数据 ,顶部的我的弹窗需要
|
|
|
|
|
|
|
|
|
|
// 操作 - 收藏
|
|
|
|
|
const operateCollect = (token = detailsToken, index) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/operate/collect", {
|
|
|
|
|
token,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
isNeedNewColletData = true;
|
|
|
|
|
myCollectionPage = 1;
|
|
|
|
|
myCollectionList.value = [];
|
|
|
|
|
if (data["type"] == "askquestioncollection") {
|
|
|
|
|
detailsIscollection.value = data["status"];
|
|
|
|
|
detailsInfo.value["collectionnum"] = data["count"];
|
|
|
|
|
} else {
|
|
|
|
|
answerList.value[index]["iscollection"] = data["status"];
|
|
|
|
|
answerList.value[index]["collectionnum"] = data["count"];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
|
|
|
|
|
if (data["status"]) myCount.value["collect"]++;
|
|
|
|
|
else myCount.value["collect"]--;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let IAnswerState = ref(false); // 我来回答-弹窗的状态
|
|
|
|
|
let IAnswerEditState = ref(false); // 编辑回答-弹窗的状态
|
|
|
|
|
|
|
|
|
|
let IAnswerInfo = ref({}); // 我来回答-弹窗的信息
|
|
|
|
|
// 开启我来回答 type: my 表示
|
|
|
|
|
const openIAnswer = (index, type) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index == null) {
|
|
|
|
|
IAnswerInfo.value = {
|
|
|
|
|
title: detailsInfo.value["title"],
|
|
|
|
|
content: detailsInfo.value["content"],
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
};
|
|
|
|
|
IAnswerState.value = true;
|
|
|
|
|
|
|
|
|
|
nextTick(() => handleInput());
|
|
|
|
|
} else {
|
|
|
|
|
// IAnswerInfo.value = answerList.value[index]
|
|
|
|
|
if (type == "my") {
|
|
|
|
|
IAnswerInfo.value = {
|
|
|
|
|
title: detailsInfo.value["title"],
|
|
|
|
|
...myAnswerList.value[index],
|
|
|
|
|
text: myAnswerList.value[index]["content"],
|
|
|
|
|
content: detailsInfo.value["content"],
|
|
|
|
|
};
|
|
|
|
|
myType.value = "";
|
|
|
|
|
} else {
|
|
|
|
|
IAnswerInfo.value = {
|
|
|
|
|
title: detailsInfo.value["title"],
|
|
|
|
|
...answerList.value[index],
|
|
|
|
|
text: answerList.value[index]["content"],
|
|
|
|
|
content: detailsInfo.value["content"],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IAnswerEditState.value = true;
|
|
|
|
|
|
|
|
|
|
nextTick(() => handleInput());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭我来回答
|
|
|
|
|
const closeIAnswer = () => {
|
|
|
|
|
IAnswerState.value = false;
|
|
|
|
|
IAnswerEditState.value = false;
|
|
|
|
|
isDirectlyListIAnswer = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 修改我来回答的匿名状态
|
|
|
|
|
const amendIAnswer = () => {
|
|
|
|
|
IAnswerInfo.value["anonymous"] =
|
|
|
|
|
IAnswerInfo.value["anonymous"] == 0 ? 1 : 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 提交回答
|
|
|
|
|
const submitAnswer = (type) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let questionTextarea = null;
|
|
|
|
|
|
|
|
|
|
if (type == "you")
|
|
|
|
|
questionTextarea = document.querySelector(".your-answer-textarea");
|
|
|
|
|
else questionTextarea = document.querySelector(".question-textarea");
|
|
|
|
|
|
|
|
|
|
if (questionTextarea)
|
|
|
|
|
IAnswerInfo.value["text"] = questionTextarea.innerHTML;
|
|
|
|
|
|
|
|
|
|
$ajax("/api/publish/answerSubmit", {
|
|
|
|
|
token: IAnswerInfo.value["token"] || detailsToken,
|
|
|
|
|
anonymous: IAnswerInfo.value["anonymous"] || 0,
|
|
|
|
|
content: IAnswerInfo.value["text"],
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
|
|
|
|
|
if (isDirectlyListIAnswer) {
|
|
|
|
|
getDetails(IAnswerInfo.value["uniqid"], IAnswerInfo.value["index"]);
|
|
|
|
|
IAnswerState.value = false;
|
|
|
|
|
} else {
|
|
|
|
|
answerList.value = [];
|
|
|
|
|
answerPage.value = 1;
|
|
|
|
|
getAnswerList();
|
|
|
|
|
closeIAnswer();
|
|
|
|
|
|
|
|
|
|
if (!IAnswerInfo.value["token"]) myCount.value["answer"]++;
|
|
|
|
|
|
|
|
|
|
if (type == "you") questionTextarea.innerHTML = "";
|
|
|
|
|
}
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 打开回答的评论
|
|
|
|
|
const openCommentState = (index) => {
|
|
|
|
|
if (answerList.value[index]["commentState"])
|
|
|
|
|
answerList.value[index]["commentState"] = false;
|
|
|
|
|
else answerList.value[index]["commentState"] = true;
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
answerList.value[index]["commentList"].length == 0 &&
|
|
|
|
|
answerList.value[index]["commentnum"] != 0
|
|
|
|
|
)
|
|
|
|
|
getAnswerCommentList(index);
|
|
|
|
|
|
|
|
|
|
// answerList.value[index]['commentState'] = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let answerCommentLimit = 3;
|
|
|
|
|
// 获取回答评论的数据
|
|
|
|
|
const getAnswerCommentList = (index) => {
|
|
|
|
|
getAnswerCommentPublic(index, 3).then((res) => {
|
|
|
|
|
let data = res.data;
|
|
|
|
|
answerList.value[index]["commentList"] = answerList.value[index][
|
|
|
|
|
"commentList"
|
|
|
|
|
].concat(data.data);
|
|
|
|
|
answerList.value[index]["commentCount"] = data["count"];
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取全部评论
|
|
|
|
|
const handleAllComment = (index) => {
|
|
|
|
|
answerCommentLimit = 1000;
|
|
|
|
|
getAnswerCommentPublic(index, 1000).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
let slice3 = data.data.slice(3);
|
|
|
|
|
let merged1 = [
|
|
|
|
|
...answerList.value[index]["commentList"],
|
|
|
|
|
...slice3.filter(
|
|
|
|
|
(item2) =>
|
|
|
|
|
!answerList.value[index]["commentList"].find(
|
|
|
|
|
(item1) => item1.id == item2.id
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// answerList.value[index]['commentList'] = answerList.value[index]['commentList'].concat(data.data.slice(3))
|
|
|
|
|
answerList.value[index]["commentList"] = merged1;
|
|
|
|
|
// handleMsg("success", res["message"] || "操作成功")
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取评论数据的公共接口
|
|
|
|
|
const getAnswerCommentPublic = (index, limit) => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
$ajax("/api/comment/lists", {
|
|
|
|
|
token: answerList.value[index]["token"],
|
|
|
|
|
// limit: answerCommentLimit,
|
|
|
|
|
limit,
|
|
|
|
|
childlimit: 1,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
resolve(res);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 提交回答-评论
|
|
|
|
|
const submitAnswerComments = (index, ind, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const targetAnswerList = [...answerList.value];
|
|
|
|
|
|
|
|
|
|
let content = "";
|
|
|
|
|
let parentid = null;
|
|
|
|
|
let token = targetAnswerList[index]["token"];
|
|
|
|
|
|
|
|
|
|
if (i != null) {
|
|
|
|
|
content =
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i][
|
|
|
|
|
"commentInput"
|
|
|
|
|
];
|
|
|
|
|
parentid =
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i]["id"];
|
|
|
|
|
} else if (ind != null) {
|
|
|
|
|
content = targetAnswerList[index]["commentList"][ind]["commentInput"];
|
|
|
|
|
parentid = targetAnswerList[index]["commentList"][ind]["id"];
|
|
|
|
|
} else content = targetAnswerList[index]["commentInput"];
|
|
|
|
|
|
|
|
|
|
$ajax("/api/comment/submit", {
|
|
|
|
|
content,
|
|
|
|
|
token,
|
|
|
|
|
parentid,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
|
|
|
|
|
if (i != null) {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
reply: {
|
|
|
|
|
nickname:
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i][
|
|
|
|
|
"nickname"
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
...data,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i][
|
|
|
|
|
"commentInput"
|
|
|
|
|
] = "";
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"].unshift(
|
|
|
|
|
targetData
|
|
|
|
|
);
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["childnum"]++;
|
|
|
|
|
} else if (ind != null) {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
reply: [],
|
|
|
|
|
...data,
|
|
|
|
|
};
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"].unshift(
|
|
|
|
|
targetData
|
|
|
|
|
);
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["childnum"]++;
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["commentInput"] = "";
|
|
|
|
|
} else {
|
|
|
|
|
let targetData = {
|
|
|
|
|
id: data["commentid"],
|
|
|
|
|
content,
|
|
|
|
|
isauthor: 1,
|
|
|
|
|
islike: 0,
|
|
|
|
|
likenum: 0,
|
|
|
|
|
...data,
|
|
|
|
|
child: [],
|
|
|
|
|
};
|
|
|
|
|
targetAnswerList[index]["commentList"].unshift(targetData);
|
|
|
|
|
targetAnswerList[index]["commentCount"]++;
|
|
|
|
|
targetAnswerList[index]["commentInput"] = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
targetAnswerList[index]["commentnum"] = data["count"];
|
|
|
|
|
|
|
|
|
|
// targetAnswerList[index]["commentcomments"] = data['count']
|
|
|
|
|
|
|
|
|
|
closeAnswerCommentsChild();
|
|
|
|
|
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 回答-评论 点赞
|
|
|
|
|
const operateAnswerCommentsLike = (token, index, ind, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/comment/like", {
|
|
|
|
|
token,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
|
|
|
|
|
let data = res.data;
|
|
|
|
|
const targetAnswerList = [...answerList.value];
|
|
|
|
|
|
|
|
|
|
if (i == null) {
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["islike"] =
|
|
|
|
|
data["status"];
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["likenum"] =
|
|
|
|
|
data["likenum"];
|
|
|
|
|
} else {
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i]["islike"] =
|
|
|
|
|
data["status"];
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"][i]["likenum"] =
|
|
|
|
|
data["likenum"];
|
|
|
|
|
}
|
|
|
|
|
answerList.value = targetAnswerList;
|
|
|
|
|
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 打开 回答-评论 的子评论
|
|
|
|
|
const openAnswerCommentsChild = (index, ind, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closeAnswerCommentsChild();
|
|
|
|
|
|
|
|
|
|
if (i == null)
|
|
|
|
|
answerList.value[index].commentList[ind]["childState"] = true;
|
|
|
|
|
else
|
|
|
|
|
answerList.value[index].commentList[ind]["child"][i][
|
|
|
|
|
"childState"
|
|
|
|
|
] = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭 回答-评论 的子评论
|
|
|
|
|
const closeAnswerCommentsChild = (index, ind, i) => {
|
|
|
|
|
const targetAnswerList = [...answerList.value];
|
|
|
|
|
|
|
|
|
|
targetAnswerList.forEach((element) => {
|
|
|
|
|
if (element["commentList"] && element["commentList"].length != 0) {
|
|
|
|
|
element["commentList"].forEach((ele) => {
|
|
|
|
|
ele["childState"] = false;
|
|
|
|
|
if (ele["child"] && ele["child"].length != 0) {
|
|
|
|
|
ele["child"].forEach((el) => {
|
|
|
|
|
el["childState"] = false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
answerList.value = targetAnswerList;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 获取剩下的子评论
|
|
|
|
|
const alsoCommentsData = (index, ind) => {
|
|
|
|
|
const targetAnswerList = [...answerList.value];
|
|
|
|
|
const parentid = targetAnswerList[index]["commentList"][ind]["id"];
|
|
|
|
|
const token = targetAnswerList[index]["token"];
|
|
|
|
|
|
|
|
|
|
$ajax("/api/comment/childrenList", {
|
|
|
|
|
token,
|
|
|
|
|
parentid,
|
|
|
|
|
limit: 20,
|
|
|
|
|
page: 1,
|
|
|
|
|
childlimit: 1,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
|
|
|
|
|
let merged1 = [
|
|
|
|
|
...targetAnswerList[index]["commentList"][ind]["child"],
|
|
|
|
|
...data.data.filter(
|
|
|
|
|
(item2) =>
|
|
|
|
|
!targetAnswerList[index]["commentList"][ind]["child"].find(
|
|
|
|
|
(item1) => item1.id == item2.id
|
|
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
targetAnswerList[index]["commentList"][ind]["child"] = merged1;
|
|
|
|
|
answerList.value = targetAnswerList;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let myType = ref(""); // collect answers questions
|
|
|
|
|
// 专门处理 我的 弹窗数据
|
|
|
|
|
const handleMy = (key) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Object.keys(myCount.value).length === 0) {
|
|
|
|
|
getUserData(key);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (key == "collect") {
|
|
|
|
|
myCollectionList.value = [];
|
|
|
|
|
myCollectionPage = 1;
|
|
|
|
|
getMyCollection();
|
|
|
|
|
} else if (key == "answers") {
|
|
|
|
|
myAnswerList.value = [];
|
|
|
|
|
myAnswerPage = 1;
|
|
|
|
|
getMyAnswer();
|
|
|
|
|
} else if (key == "questions") {
|
|
|
|
|
myQuestionsList.value = [];
|
|
|
|
|
myQuestionsPage = 1;
|
|
|
|
|
getMyQuestions();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let myCollectionList = ref([]); // 我的收藏列表
|
|
|
|
|
let myCollectionCount = ref(0); // 我的收藏数量
|
|
|
|
|
let myCollectionPage = 1; // 我的收藏页数
|
|
|
|
|
let myCollectionLading = false; // 我的收藏加载中
|
|
|
|
|
|
|
|
|
|
// 获取我的收藏
|
|
|
|
|
const getMyCollection = () => {
|
|
|
|
|
if (myCollectionPage == 0 || myCollectionLading) return;
|
|
|
|
|
myCollectionLading = true;
|
|
|
|
|
|
|
|
|
|
$ajax("/api/user/collect", {
|
|
|
|
|
limit: 20,
|
|
|
|
|
page: myCollectionPage,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
myType.value = "collect";
|
|
|
|
|
isNeedNewColletData = false;
|
|
|
|
|
|
|
|
|
|
data.data.forEach((element) => {
|
|
|
|
|
if (element["type"] == "askanswercollection") {
|
|
|
|
|
let content = element["data"]["content"];
|
|
|
|
|
element["data"]["content"] = processHtml(content);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
myCollectionList.value = myCollectionList.value.concat(data.data);
|
|
|
|
|
myCollectionCount.value = data.count;
|
|
|
|
|
|
|
|
|
|
if (myCollectionList.value.length != data["count"])
|
|
|
|
|
myCollectionPage++;
|
|
|
|
|
else myCollectionPage = 0;
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (myCollectionLading = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const processHtml = (html) => {
|
|
|
|
|
var parser = new DOMParser();
|
|
|
|
|
var doc = parser.parseFromString(html, "text/html");
|
|
|
|
|
var img = doc.querySelector("img");
|
|
|
|
|
if (img) {
|
|
|
|
|
return `<img src="${img.src}">`;
|
|
|
|
|
} else {
|
|
|
|
|
return doc.body.textContent;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 取消收藏
|
|
|
|
|
const cancelCollection = (token, index) => {
|
|
|
|
|
$ajax("/api/user/deleteCollect", {
|
|
|
|
|
token,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code == 200) {
|
|
|
|
|
myCollectionList.value.splice(index, 1);
|
|
|
|
|
myCollectionCount.value--;
|
|
|
|
|
myCount.value["collect"]--;
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 监听 我的收藏滚动到底部
|
|
|
|
|
const handleCollectionScroll = (e) => {
|
|
|
|
|
const el = e.target;
|
|
|
|
|
if (el.scrollHeight - el.scrollTop >= el.clientHeight + 10) return;
|
|
|
|
|
getMyCollection();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let myAnswerList = ref([]); // 我的回答数据
|
|
|
|
|
let myAnswerCount = ref(0); // 我的回答数量
|
|
|
|
|
let myAnswerPage = 1;
|
|
|
|
|
let myAnswerloadimg = false;
|
|
|
|
|
// 获取我的回答
|
|
|
|
|
const getMyAnswer = () => {
|
|
|
|
|
if (myAnswerPage == 0 || myAnswerloadimg) return;
|
|
|
|
|
myAnswerloadimg = true;
|
|
|
|
|
$ajax("/api/user/answer", {
|
|
|
|
|
limit: 20,
|
|
|
|
|
page: myAnswerPage,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
data.data.forEach((element) => {
|
|
|
|
|
element["popupState"] = false;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
data.data.forEach((element) => {
|
|
|
|
|
let content = element["content"];
|
|
|
|
|
element["content"] = processHtml(content);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
myAnswerList.value = myAnswerList.value.concat(data.data);
|
|
|
|
|
myAnswerCount.value = data.count;
|
|
|
|
|
|
|
|
|
|
if (myAnswerList.value.length != data["count"]) myAnswerPage++;
|
|
|
|
|
else myAnswerPage = 0;
|
|
|
|
|
|
|
|
|
|
myType.value = "answers";
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (myAnswerloadimg = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 我的回答 的滚动到底部事件
|
|
|
|
|
const handleAnswersScroll = (e) => {
|
|
|
|
|
const el = e.target;
|
|
|
|
|
// 判断滚动到底部
|
|
|
|
|
if (el.scrollHeight - el.scrollTop >= el.clientHeight + 10) return;
|
|
|
|
|
getMyAnswer();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let answerIndexOld = null;
|
|
|
|
|
// 切换 我的提问的公开匿名 弹窗状态
|
|
|
|
|
const cutAnswerPopupState = (index) => {
|
|
|
|
|
myAnswerList.value[index]["popupState"] = true;
|
|
|
|
|
|
|
|
|
|
if (answerIndexOld == index) {
|
|
|
|
|
myAnswerList.value[index]["popupState"] = false;
|
|
|
|
|
answerIndexOld = null;
|
|
|
|
|
} else {
|
|
|
|
|
myAnswerList.value[index]["popupState"] = true;
|
|
|
|
|
if (answerIndexOld != null)
|
|
|
|
|
myAnswerList.value[answerIndexOld]["popupState"] = false;
|
|
|
|
|
answerIndexOld = index;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更改匿名状态
|
|
|
|
|
const changeAnonymous = (token, anonymous, index) => {
|
|
|
|
|
$ajax("/api/publish/changeAnonymous", {
|
|
|
|
|
token,
|
|
|
|
|
anonymous,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
myAnswerList.value[index]["anonymous"] = anonymous;
|
|
|
|
|
cutAnswerPopupState(index);
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let myQuestionsList = ref([]); // 我的提问数据
|
|
|
|
|
let myQuestionsCount = ref(0); // 我的提问数量
|
|
|
|
|
let myQuestionsPage = 0; // 我的提问页数
|
|
|
|
|
let myQuestionsloading = false; // 我的提问页数
|
|
|
|
|
// 获取我的提问
|
|
|
|
|
const getMyQuestions = () => {
|
|
|
|
|
if (myQuestionsPage == 0 || myQuestionsloading) return;
|
|
|
|
|
myQuestionsloading = true;
|
|
|
|
|
$ajax("/api/user/questions", {
|
|
|
|
|
limit: 20,
|
|
|
|
|
page: myQuestionsPage,
|
|
|
|
|
})
|
|
|
|
|
.then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
myQuestionsList.value = myQuestionsList.value.concat(data.data);
|
|
|
|
|
myQuestionsCount.value = data.count;
|
|
|
|
|
myType.value = "questions";
|
|
|
|
|
|
|
|
|
|
if (myQuestionsList.value.length != data["count"]) myQuestionsPage++;
|
|
|
|
|
else myQuestionsPage = 0;
|
|
|
|
|
})
|
|
|
|
|
.finally(() => (myQuestionsloading = false));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 我的提问 的滚动到底部 事件
|
|
|
|
|
const handleQuestionsScroll = (e) => {
|
|
|
|
|
const el = e.target;
|
|
|
|
|
// 判断滚动到底部
|
|
|
|
|
if (el.scrollHeight - el.scrollTop >= el.clientHeight + 10) return;
|
|
|
|
|
getMyQuestions();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let questionsIndexOld = null;
|
|
|
|
|
// 切换 我的提问的公开匿名 弹窗状态
|
|
|
|
|
const cutQuestionsPopupState = (index) => {
|
|
|
|
|
myQuestionsList.value[index]["popupState"] = true;
|
|
|
|
|
|
|
|
|
|
if (questionsIndexOld == index) {
|
|
|
|
|
myQuestionsList.value[index]["popupState"] = false;
|
|
|
|
|
questionsIndexOld = null;
|
|
|
|
|
} else {
|
|
|
|
|
myQuestionsList.value[index]["popupState"] = true;
|
|
|
|
|
if (questionsIndexOld != null)
|
|
|
|
|
myQuestionsList.value[questionsIndexOld]["popupState"] = false;
|
|
|
|
|
questionsIndexOld = index;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 更改匿名状态
|
|
|
|
|
const changeAnonymousQuestions = (token, anonymous, index) => {
|
|
|
|
|
$ajax("/api/publish/changeAnonymous", {
|
|
|
|
|
token,
|
|
|
|
|
anonymous,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
myQuestionsList.value[index]["anonymous"] = anonymous;
|
|
|
|
|
cutQuestionsPopupState(index);
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let questionsSetp = ref(0); // 提问的步骤
|
|
|
|
|
|
|
|
|
|
// 切换提问步骤
|
|
|
|
|
const cutQuestionsSetp = (value) => (questionsSetp.value = value);
|
|
|
|
|
|
|
|
|
|
let questionsTypeList = ref([]); // 提问的类型主题
|
|
|
|
|
let questionsObj = ref({
|
|
|
|
|
// 提问的内容
|
|
|
|
|
token: "",
|
|
|
|
|
title: "",
|
|
|
|
|
content: "",
|
|
|
|
|
tags: "",
|
|
|
|
|
tid: "",
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 报 提问的初始化
|
|
|
|
|
const questionsInit = () => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/publish/questions").then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
questionsObj.value["token"] = data["token"];
|
|
|
|
|
|
|
|
|
|
questionsTypeList.value = data["typeList"] || [];
|
|
|
|
|
cutQuestionsSetp(1);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 选择提问主题
|
|
|
|
|
const choosingTheme = (id) => {
|
|
|
|
|
questionsObj.value.tid = id;
|
|
|
|
|
cutQuestionsSetp(2);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 切换匿名状态
|
|
|
|
|
const cutAnonymous = () => {
|
|
|
|
|
questionsObj.value.anonymous = questionsObj.value.anonymous == 0 ? 1 : 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 发布问题
|
|
|
|
|
const postingIssue = () => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$ajax("/api/publish/questionsSubmit", questionsObj.value).then((res) => {
|
|
|
|
|
if (res.code == 200) {
|
|
|
|
|
myCount.value["questions"]++;
|
|
|
|
|
questionsSetp.value = 0;
|
|
|
|
|
questionsObj.value = {
|
|
|
|
|
token: "",
|
|
|
|
|
title: "",
|
|
|
|
|
content: "",
|
|
|
|
|
tags: "",
|
|
|
|
|
tid: "",
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
};
|
|
|
|
|
handleMsg("success", res["message"] || "操作成功");
|
|
|
|
|
let data = res.data;
|
|
|
|
|
// calculateListIndex(res)
|
|
|
|
|
getDetails(data["uniqid"]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
handleMsg("error", res["message"] || "刷新重试!!!");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let pitchIndex = ref(null); // 选中的下标
|
|
|
|
|
// 切换 滚动列表
|
|
|
|
|
const cut = (index) => {
|
|
|
|
|
pitchIndex.value = index;
|
|
|
|
|
|
|
|
|
|
setTimeout(() => scrollLeftInMiddle(), 350);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 是否需要在 onMounted 滚动左边在中间
|
|
|
|
|
let isNeedScrollMiddle = false;
|
|
|
|
|
|
|
|
|
|
// 滚动左边在中间
|
|
|
|
|
const scrollLeftInMiddle = () => {
|
|
|
|
|
if (typeof document === "undefined") {
|
|
|
|
|
isNeedScrollMiddle = true;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let list = document.querySelector(".list-box");
|
|
|
|
|
let item = list.querySelector(`.item${pitchIndex.value}`);
|
|
|
|
|
// let prevNode = list.previousElementSibling; // 获取上一个节点
|
|
|
|
|
// var previousElement = item.previousElementSibling; // 你的元素的上一个元素
|
|
|
|
|
|
|
|
|
|
// 136 分为 两个68,一个是item高度的一半,另一个是列表顶部的 数量
|
|
|
|
|
let top = item.offsetTop - pageListHeight.value / 2 + 136;
|
|
|
|
|
list.scrollTo({
|
|
|
|
|
top,
|
|
|
|
|
behavior: "smooth",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
isNeedScrollMiddle = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const listStyle = () => {
|
|
|
|
|
const newtype = type.value;
|
|
|
|
|
let width = "";
|
|
|
|
|
let margin = "";
|
|
|
|
|
let height = "";
|
|
|
|
|
if (newtype == "list") {
|
|
|
|
|
width = "1200px";
|
|
|
|
|
margin = "0 auto";
|
|
|
|
|
// height = Math.ceil(list.value.length / 2) * 128 + "px"
|
|
|
|
|
} else {
|
|
|
|
|
width = "calc((100vw - 1200px) / 2 + 512px)";
|
|
|
|
|
margin = "initial";
|
|
|
|
|
// height = list.value.length * 128 + "px"
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
width,
|
|
|
|
|
margin,
|
|
|
|
|
height,
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let listHeight = ref(0);
|
|
|
|
|
let itemHeightLeft = 0;
|
|
|
|
|
let itemHeightRight = 0;
|
|
|
|
|
|
|
|
|
|
const itemStyle = (index, content, typetype) => {
|
|
|
|
|
if (index == 0) {
|
|
|
|
|
itemHeightLeft = 0;
|
|
|
|
|
itemHeightRight = 0;
|
|
|
|
|
}
|
|
|
|
|
const newtype = type.value;
|
|
|
|
|
// let itemHeight = content == "" ? 107 : 128
|
|
|
|
|
let obj = {};
|
|
|
|
|
if (newtype == "list") {
|
|
|
|
|
// let top = Math.floor(index / 2) * 128 + "px"
|
|
|
|
|
// obj["top"] = Math.floor(index / 2) * 128 + "px"
|
|
|
|
|
// obj["top"] = Math.floor(index / 2) * 128 + "px"
|
|
|
|
|
|
|
|
|
|
if (itemHeightLeft <= itemHeightRight) {
|
|
|
|
|
obj["top"] = itemHeightLeft + "px";
|
|
|
|
|
itemHeightLeft += content == "" ? 107 : 137;
|
|
|
|
|
obj["left"] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
obj["top"] = itemHeightRight + "px";
|
|
|
|
|
itemHeightRight += content == "" ? 107 : 137;
|
|
|
|
|
obj["left"] = 649 + "px";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// obj["top"] = itemHeightLeft + "px";
|
|
|
|
|
obj["position"] = "relative";
|
|
|
|
|
|
|
|
|
|
// position: static;
|
|
|
|
|
if (!typetype) {
|
|
|
|
|
itemHeightLeft += content == "" ? 107 : 137;
|
|
|
|
|
obj["height"] = content == "" ? 107 + "px" : 137 + "px";
|
|
|
|
|
} else {
|
|
|
|
|
itemHeightLeft += typetype == "vote" ? 170 : 137;
|
|
|
|
|
obj["height"] = typetype == "vote" ? 170 + "px" : 137 + "px";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// obj["left"] = 0;
|
|
|
|
|
obj["width"] = "100%";
|
|
|
|
|
obj["paddingLeft"] = "calc((100vw - 1200px) / 2)";
|
|
|
|
|
}
|
|
|
|
|
// 通过最后一个 算 列表的高度
|
|
|
|
|
if (index + 1 == list.value.length)
|
|
|
|
|
listHeight.value = Math.max(itemHeightLeft, itemHeightRight);
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const bottomTpsStyle = (index, content) => {
|
|
|
|
|
const newtype = type.value;
|
|
|
|
|
// let itemHeight = content == "" ? 106 : 128
|
|
|
|
|
let obj = {};
|
|
|
|
|
if (newtype == "list") {
|
|
|
|
|
} else {
|
|
|
|
|
obj["width"] = "calc(50vw - 88px)";
|
|
|
|
|
obj["height"] = `calc(100vh - ${list.value.length * 128}px - 268px)`;
|
|
|
|
|
obj["paddingLeft"] = "calc((100vw - 1200px) / 2)";
|
|
|
|
|
obj["borderRight"] = "1px solid #ebebeb";
|
|
|
|
|
obj["borderRight"] = "1px solid #ebebeb";
|
|
|
|
|
obj["background"] = "#fff";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// list-box
|
|
|
|
|
const listBoxStyle = () => {
|
|
|
|
|
const newtype = type.value;
|
|
|
|
|
let obj = {};
|
|
|
|
|
if (newtype == "list") obj["overflow"] = "visible";
|
|
|
|
|
else obj["height"] = pageListHeight.value + "px";
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理时间
|
|
|
|
|
const handleDate = (dateTimeStamp = new Date()) => {
|
|
|
|
|
dateTimeStamp = dateTimeStamp ? dateTimeStamp : null;
|
|
|
|
|
var timestamp = new Date(dateTimeStamp);
|
|
|
|
|
timestamp = timestamp.getTime();
|
|
|
|
|
var minute = 1000 * 60;
|
|
|
|
|
var hour = minute * 60;
|
|
|
|
|
var day = hour * 24;
|
|
|
|
|
var now = new Date().getTime();
|
|
|
|
|
var diffValue = now - timestamp;
|
|
|
|
|
var result;
|
|
|
|
|
if (diffValue < 0) return;
|
|
|
|
|
|
|
|
|
|
var dayC = diffValue / day;
|
|
|
|
|
var hourC = diffValue / (hour + 1);
|
|
|
|
|
var minC = diffValue / minute;
|
|
|
|
|
if (dayC >= 7) {
|
|
|
|
|
let date = new Date(timestamp);
|
|
|
|
|
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();
|
|
|
|
|
result = "" + Y + M + D + h + m;
|
|
|
|
|
} else if (dayC >= 1) result = "" + Math.round(dayC) + "天前";
|
|
|
|
|
else if (hourC >= 1) result = "" + Math.round(hourC) + "小时前";
|
|
|
|
|
else if (minC >= 1) result = "" + Math.round(minC) + "分钟前";
|
|
|
|
|
else result = "刚刚";
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let questionsTransmitState = ref(false); // 问题的转发 弹窗状态
|
|
|
|
|
let questionsTransmitMaskState = ref(false); // 问题的转发 弹窗蒙版状态状态
|
|
|
|
|
|
|
|
|
|
// 关闭转发状态
|
|
|
|
|
const closeTransmitState = () => {
|
|
|
|
|
questionsTransmitState.value = true;
|
|
|
|
|
questionsTransmitMaskState.value = true;
|
|
|
|
|
countForwardingTimes(detailsToken);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭全部转发状态
|
|
|
|
|
const closeAllTransmitState = () => {
|
|
|
|
|
answerList.value.forEach((element) => {
|
|
|
|
|
element["transmitState"] = false;
|
|
|
|
|
});
|
|
|
|
|
questionsTransmitState.value = false;
|
|
|
|
|
questionsTransmitMaskState.value = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 开启和关闭回答的转发状态 type open close
|
|
|
|
|
const handleAnswerTransmitList = (Iindex, type) => {
|
|
|
|
|
answerList.value[Iindex]["transmitState"] = true;
|
|
|
|
|
questionsTransmitMaskState.value = true;
|
|
|
|
|
countForwardingTimes(answerList.value[Iindex]["token"]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 统计转发次数
|
|
|
|
|
const countForwardingTimes = (token) => {
|
|
|
|
|
process.env.NODE_ENV === "production" &&
|
|
|
|
|
$ajaxGET("/api/operate/share?token=" + token);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭详情模式
|
|
|
|
|
const closeDetailMode = () => {
|
|
|
|
|
deleteState(["uniqid"]);
|
|
|
|
|
|
|
|
|
|
if (myModelState.value) {
|
|
|
|
|
closeMyModel();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
seo.value = {};
|
|
|
|
|
list.value = JSON.parse(JSON.stringify(backupsList));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 全部的启动到底部
|
|
|
|
|
const handleListScroll = (e) => {
|
|
|
|
|
const el = e.target;
|
|
|
|
|
if (
|
|
|
|
|
el.scrollHeight - el.scrollTop >= el.clientHeight + 40 ||
|
|
|
|
|
myModelState.value
|
|
|
|
|
)
|
|
|
|
|
return;
|
|
|
|
|
getList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理 回答弹窗的复制图片 type:you 为 您的答案
|
|
|
|
|
const handlePaste = (event, type) => {
|
|
|
|
|
const items = (event.clipboardData || event.originalEvent.clipboardData)
|
|
|
|
|
.items;
|
|
|
|
|
for (const item of items) {
|
|
|
|
|
if (item.type.indexOf("image") === 0) {
|
|
|
|
|
// 如果包含图片,阻止默认行为
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
handleMsg("warning", "上传图片中");
|
|
|
|
|
const file = item.getAsFile();
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
|
|
|
|
|
reader.onload = (e) => {
|
|
|
|
|
const base64 = e.target.result;
|
|
|
|
|
uploadImg(base64).then((res) => {
|
|
|
|
|
let questionTextarea = null;
|
|
|
|
|
if (type == "you")
|
|
|
|
|
questionTextarea = document.querySelector(
|
|
|
|
|
".your-answer-textarea"
|
|
|
|
|
);
|
|
|
|
|
else
|
|
|
|
|
questionTextarea = document.querySelector(".question-textarea");
|
|
|
|
|
|
|
|
|
|
let imgNode = document.createElement("img");
|
|
|
|
|
imgNode.setAttribute("src", res.url);
|
|
|
|
|
imgNode.setAttribute("data-aid", res.aid);
|
|
|
|
|
questionTextarea.appendChild(imgNode);
|
|
|
|
|
|
|
|
|
|
if (type == "you") handleInputYou();
|
|
|
|
|
else handleInput();
|
|
|
|
|
|
|
|
|
|
handleMsg("success", "上传成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
reader.readAsDataURL(file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// 上传图片 获取图片url
|
|
|
|
|
const uploadImg = (base64) => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
$ajax("/api/common/upload", {
|
|
|
|
|
data: base64,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
resolve(data);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 回答 的 placeholder 状态
|
|
|
|
|
let questionPlaceholderState = ref(false);
|
|
|
|
|
let yourAnswerPlaceholderState = ref(true); // 您的答案的 placeholder 状态
|
|
|
|
|
|
|
|
|
|
// 回答的输入事件 判断是否显示 placeholder 用
|
|
|
|
|
const handleInput = () => {
|
|
|
|
|
const questionTextarea = document.querySelector(".question-textarea");
|
|
|
|
|
const html = questionTextarea.innerHTML;
|
|
|
|
|
if (html) questionPlaceholderState.value = false;
|
|
|
|
|
else questionPlaceholderState.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleInputYou = () => {
|
|
|
|
|
const questionTextarea = document.querySelector(".your-answer-textarea");
|
|
|
|
|
const html = questionTextarea.innerHTML;
|
|
|
|
|
if (html) yourAnswerPlaceholderState.value = false;
|
|
|
|
|
else yourAnswerPlaceholderState.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let msg = ref({}); // 提示文本的对象 state 类型 type success warning error 显示状态 text 内容
|
|
|
|
|
|
|
|
|
|
// 调用 提示框方法
|
|
|
|
|
const handleMsg = (type, text) => {
|
|
|
|
|
msg.value["state"] = true;
|
|
|
|
|
msg.value["type"] = type;
|
|
|
|
|
msg.value["text"] = text;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 修改提示框类型
|
|
|
|
|
const boxClass = () => {
|
|
|
|
|
msgShowTimer();
|
|
|
|
|
return type ? `box-item-${msg.value["type"]}` : "";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let msgTimer = null;
|
|
|
|
|
const msgShowTimer = () => {
|
|
|
|
|
clearTimeout(msgTimer);
|
|
|
|
|
msgTimer = setTimeout(() => {
|
|
|
|
|
msg.value["state"] = false;
|
|
|
|
|
}, 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 复制
|
|
|
|
|
let copyText = (text) => {
|
|
|
|
|
if (navigator.clipboard) {
|
|
|
|
|
copyText = () => {
|
|
|
|
|
navigator.clipboard.writeText(text);
|
|
|
|
|
handleMsg("success", "复制成功");
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
copyText = () => {
|
|
|
|
|
var tempInput = document.createElement("input");
|
|
|
|
|
tempInput.value = text;
|
|
|
|
|
document.body.appendChild(tempInput);
|
|
|
|
|
tempInput.select();
|
|
|
|
|
document.execCommand("copy");
|
|
|
|
|
document.body.removeChild(tempInput);
|
|
|
|
|
handleMsg("success", "复制成功");
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
copyText();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 修改 url
|
|
|
|
|
const replaceState = (obj = {}) => {
|
|
|
|
|
if (typeof window === "undefined") return;
|
|
|
|
|
// 获取当前URL参数
|
|
|
|
|
let params = new URLSearchParams(window.location.search);
|
|
|
|
|
for (const key in obj) {
|
|
|
|
|
params.set(key, obj[key]);
|
|
|
|
|
}
|
|
|
|
|
// 替换当前URL,但不刷新页面
|
|
|
|
|
if (window.location.pathname.indexOf("index.html") == -1)
|
|
|
|
|
window.history.pushState(
|
|
|
|
|
{},
|
|
|
|
|
"",
|
|
|
|
|
`${window.location.pathname}index.html?${params}`
|
|
|
|
|
);
|
|
|
|
|
else
|
|
|
|
|
window.history.pushState(
|
|
|
|
|
{},
|
|
|
|
|
"",
|
|
|
|
|
`${window.location.pathname}?${params}`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let location = window.location;
|
|
|
|
|
let contentUrl = location.pathname + location.search;
|
|
|
|
|
if (window._hmt) window._hmt.push(["_trackPageview", contentUrl]);
|
|
|
|
|
|
|
|
|
|
// 用于发送某个URL的PV统计请求
|
|
|
|
|
if (window._czc) window._czc.push(["_trackPageview", contentUrl]);
|
|
|
|
|
};
|
|
|
|
|
// 删除 url 参数的key
|
|
|
|
|
const deleteState = (keys = []) => {
|
|
|
|
|
if (typeof window === "undefined") return;
|
|
|
|
|
|
|
|
|
|
let params = new URLSearchParams(window.location.search);
|
|
|
|
|
keys.forEach((key) => {
|
|
|
|
|
params.delete(key);
|
|
|
|
|
});
|
|
|
|
|
window.history.pushState({}, "", `${window.location.pathname}?${params}`);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let myModelState = ref(false); // 我的模式状态
|
|
|
|
|
let myModelList = ref([]); // 我的模式列表
|
|
|
|
|
let temporaryData = {}; // 临时存放
|
|
|
|
|
|
|
|
|
|
// 我的打开 详情
|
|
|
|
|
const myOpenDetails = (uniqid) => {
|
|
|
|
|
if (!uniqid) {
|
|
|
|
|
handleMsg("error", "没有找到相关提问");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
deleteState(["keyword"]);
|
|
|
|
|
|
|
|
|
|
if (!myModelState.value) {
|
|
|
|
|
temporaryData = {
|
|
|
|
|
total: total.value,
|
|
|
|
|
keywordText: keywordText.value,
|
|
|
|
|
isSearchMode: isSearchMode.value,
|
|
|
|
|
inTheEndState: inTheEndState.value,
|
|
|
|
|
type: type.value,
|
|
|
|
|
pitchIndex: pitchIndex.value,
|
|
|
|
|
listlist: JSON.parse(JSON.stringify(list.value)),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
isSearchMode.value = false;
|
|
|
|
|
inTheEndState.value = false;
|
|
|
|
|
keyword.value = "";
|
|
|
|
|
|
|
|
|
|
list.value = JSON.parse(JSON.stringify(myModelList.value));
|
|
|
|
|
|
|
|
|
|
myModelState.value = true;
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getDetails(uniqid);
|
|
|
|
|
|
|
|
|
|
myType.value = "";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 关闭我的模式
|
|
|
|
|
const closeMyModel = () => {
|
|
|
|
|
myModelList.value = JSON.parse(JSON.stringify(list.value));
|
|
|
|
|
isSearchMode.value = temporaryData["isSearchMode"];
|
|
|
|
|
keywordText.value = temporaryData["keywordText"];
|
|
|
|
|
keyword.value = temporaryData["keywordText"];
|
|
|
|
|
total.value = temporaryData["total"];
|
|
|
|
|
type.value = temporaryData["type"];
|
|
|
|
|
pitchIndex.value = temporaryData["pitchIndex"];
|
|
|
|
|
inTheEndState.value = temporaryData["inTheEndState"];
|
|
|
|
|
list.value = JSON.parse(JSON.stringify(temporaryData.listlist));
|
|
|
|
|
|
|
|
|
|
myModelState.value = false;
|
|
|
|
|
if (pitchIndex.value) {
|
|
|
|
|
let uniqid = list.value[pitchIndex.value]["uniqid"];
|
|
|
|
|
getDetails(uniqid);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 详情页滚动事件
|
|
|
|
|
const handleDetailsScroll = (e) => {
|
|
|
|
|
const el = e.target;
|
|
|
|
|
// 判断滚动到底部
|
|
|
|
|
if (el.scrollHeight - el.scrollTop !== el.clientHeight) return;
|
|
|
|
|
getAnswerList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let dialogSrc = ref(""); // 大图的src
|
|
|
|
|
|
|
|
|
|
// 处理点击答案图片 展开大图
|
|
|
|
|
const handleAnswerText = (e) => {
|
|
|
|
|
if (e.target.tagName === "IMG") {
|
|
|
|
|
var src = e.target.getAttribute("src");
|
|
|
|
|
dialogSrc.value = src;
|
|
|
|
|
window.addEventListener("keydown", handleKeydown);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 大图的监听 esc 键盘按钮
|
|
|
|
|
const handleKeydown = (event) => {
|
|
|
|
|
if (event.key !== "Escape") return;
|
|
|
|
|
dialogSrc.value = "";
|
|
|
|
|
window.removeEventListener("keydown", handleKeydown); // 取消监听
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 切换顶部的 type
|
|
|
|
|
const cutType = (id) => {
|
|
|
|
|
typePitch.value = id;
|
|
|
|
|
page = 1;
|
|
|
|
|
list.value = [];
|
|
|
|
|
backupsList = [];
|
|
|
|
|
myModelState.value = false
|
|
|
|
|
type.value = "list";
|
|
|
|
|
openBottom();
|
|
|
|
|
pitchIndex.value = null;
|
|
|
|
|
if (id != null) {
|
|
|
|
|
replaceState({
|
|
|
|
|
tid: id,
|
|
|
|
|
});
|
|
|
|
|
deleteState(["uniqid"]);
|
|
|
|
|
} else deleteState(["tid", "uniqid"]);
|
|
|
|
|
|
|
|
|
|
getList();
|
|
|
|
|
|
|
|
|
|
// 创新请求 设置列表的高度 为0
|
|
|
|
|
listHeight.value = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 打开举报
|
|
|
|
|
const handleMenuState = (index, ind, i) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (i === undefined)
|
|
|
|
|
reportToken = answerList.value[index].commentList[ind]["token"];
|
|
|
|
|
else
|
|
|
|
|
reportToken =
|
|
|
|
|
answerList.value[index].commentList[ind]["child"][i]["token"];
|
|
|
|
|
alertShow.value = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 举报 token
|
|
|
|
|
let reportToken = "";
|
|
|
|
|
const reasonList = ["广告", "辱骂", "重复发送", "不良信息", "其他"];
|
|
|
|
|
let checkList = ref([]);
|
|
|
|
|
let alertShow = ref(false);
|
|
|
|
|
let alertText = ref("");
|
|
|
|
|
const selectRadio = (value) => {
|
|
|
|
|
const index = checkList.value.indexOf(value);
|
|
|
|
|
if (index === -1) checkList.value.push(value);
|
|
|
|
|
else checkList.value.splice(index, 1);
|
|
|
|
|
};
|
|
|
|
|
// 举报提交
|
|
|
|
|
const alertSubmit = () => {
|
|
|
|
|
checkList.value.push(alertText.value);
|
|
|
|
|
$ajax("/api/operate/report", {
|
|
|
|
|
message: checkList.value,
|
|
|
|
|
token: reportToken,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
checkList.value = [];
|
|
|
|
|
reportToken = "";
|
|
|
|
|
alertShow.value = false;
|
|
|
|
|
handleMsg("success", "举报成功");
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
watchEffect(() => {
|
|
|
|
|
if (
|
|
|
|
|
questionsSetp.value ||
|
|
|
|
|
myType.value ||
|
|
|
|
|
IAnswerEditState.value ||
|
|
|
|
|
IAnswerState.value ||
|
|
|
|
|
dialogSrc.value
|
|
|
|
|
)
|
|
|
|
|
document.body.style.overflow = "hidden";
|
|
|
|
|
else document.body.style.overflow = "auto";
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let recommendList = []; // 推荐相关的数据
|
|
|
|
|
let recommendPage = 1;
|
|
|
|
|
|
|
|
|
|
// 获取推荐数据
|
|
|
|
|
const getRecommend = (uniqid) => {
|
|
|
|
|
$ajaxGET("/api/details/relatedlist", {
|
|
|
|
|
page: recommendPage,
|
|
|
|
|
limit: 20,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
|
|
|
|
|
let obj = {
|
|
|
|
|
offer: "Offer",
|
|
|
|
|
mj: "面经",
|
|
|
|
|
vote: "投票",
|
|
|
|
|
thread: "帖子",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let data = res.data;
|
|
|
|
|
// 替换 类名
|
|
|
|
|
data.forEach((element) => {
|
|
|
|
|
element["typename"] = obj[element["type"]];
|
|
|
|
|
element["isrecom"] = true;
|
|
|
|
|
});
|
|
|
|
|
recommendList = recommendList.concat(data);
|
|
|
|
|
recommendPage++;
|
|
|
|
|
handleInsertRelatedlist(uniqid);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理插入推荐数据
|
|
|
|
|
const handleInsertRelatedlist = (uniqid) => {
|
|
|
|
|
if (myModelState.value) return;
|
|
|
|
|
|
|
|
|
|
// 计算需要插入元素的数量
|
|
|
|
|
let insertCount = Math.ceil(backupsList.length / 5);
|
|
|
|
|
// 检查数组B的长度是否足够
|
|
|
|
|
if (recommendList.length < insertCount) {
|
|
|
|
|
getRecommend(uniqid);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let target = JSON.parse(JSON.stringify(backupsList));
|
|
|
|
|
let result = [];
|
|
|
|
|
|
|
|
|
|
let j = 0;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < target.length; i++) {
|
|
|
|
|
result.push(target[i]);
|
|
|
|
|
if ((i + 1) % 4 === 0 && j < recommendList.length) {
|
|
|
|
|
result.push(recommendList[j]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list.value = JSON.parse(JSON.stringify(result));
|
|
|
|
|
|
|
|
|
|
// 加入 推荐阅读后 重新计算下标 和 滚动
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
if (uniqid) {
|
|
|
|
|
result.forEach((element, index) => {
|
|
|
|
|
if (element["uniqid"] == uniqid) {
|
|
|
|
|
pitchIndex.value = index;
|
|
|
|
|
scrollLeftInMiddle();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const replaceNumberObj = {
|
|
|
|
|
0: "①",
|
|
|
|
|
1: "②",
|
|
|
|
|
2: "③",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let seo = ref({});
|
|
|
|
|
|
|
|
|
|
let initState = ref(0)
|
|
|
|
|
let arrr = []
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 这是一个 等待的方法 如果复制后 会 多次等待
|
|
|
|
|
// await new Promise(resolve => setTimeout(resolve, 2000))
|
|
|
|
|
|
|
|
|
|
const params = route.query;
|
|
|
|
|
if (params["keyword"]) keyword.value = params["keyword"];
|
|
|
|
|
if (params["tid"]) typePitch.value = params["tid"];
|
|
|
|
|
if (process.server && params["uniqid"]) {
|
|
|
|
|
await axios
|
|
|
|
|
.post(baseURL + "/api/details", { uniqid: params["uniqid"] })
|
|
|
|
|
.then((response) => {
|
|
|
|
|
let res = response.data;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
detailsInfoDataVuex.value = 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;
|
|
|
|
|
// 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", {
|
|
|
|
|
page,
|
|
|
|
|
limit: 20,
|
|
|
|
|
keyword: keyword.value,
|
|
|
|
|
type: typePitch.value,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let data = res.data;
|
|
|
|
|
|
2023-12-21 02:53:20 +00:00
|
|
|
|
data.data.forEach(element => {
|
|
|
|
|
element['content'] = element['content'].replace(/<[^>]*>/g, "");
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
list.value = data.data
|
|
|
|
|
backupsList = data.data
|
2023-12-20 11:11:08 +00:00
|
|
|
|
|
|
|
|
|
total.value = data.count || 0;
|
|
|
|
|
|
|
|
|
|
keywordText.value = keyword.value || "";
|
|
|
|
|
|
|
|
|
|
if (list.value.length != data["count"]) page++;
|
|
|
|
|
else page = 0;
|
|
|
|
|
|
|
|
|
|
if (page == 0 && list.value.length != 0) inTheEndState.value = true;
|
|
|
|
|
else inTheEndState.value = false;
|
|
|
|
|
|
|
|
|
|
if (list.value.length == 0) isListEmptyState.value = true;
|
|
|
|
|
else isListEmptyState.value = false;
|
|
|
|
|
|
|
|
|
|
if (keyword.value) isSearchMode.value = true;
|
|
|
|
|
else isSearchMode.value = false;
|
|
|
|
|
|
|
|
|
|
// if (!process.server && params["uniqid"]) handleInsertRelatedlist()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
await $ajaxGET("/api/details/relatedlist", { page: 1, limit: 20 }).then((res) => {
|
|
|
|
|
if (res.code != 200) return;
|
|
|
|
|
let obj = {
|
|
|
|
|
offer: "Offer",
|
|
|
|
|
mj: "面经",
|
|
|
|
|
vote: "投票",
|
|
|
|
|
thread: "帖子",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let data = res.data;
|
|
|
|
|
// // 替换 类名
|
|
|
|
|
data.forEach((element) => {
|
|
|
|
|
element["typename"] = obj[element["type"]];
|
|
|
|
|
element["isrecom"] = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
recommendList = recommendList.concat(data);
|
|
|
|
|
recommendPage++;
|
|
|
|
|
|
|
|
|
|
if (params["uniqid"]) {
|
|
|
|
|
let target = JSON.parse(JSON.stringify(backupsList));
|
|
|
|
|
let result = [];
|
|
|
|
|
let j = 0;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < target.length; i++) {
|
|
|
|
|
result.push(target[i]);
|
|
|
|
|
if ((i + 1) % 4 === 0 && j < recommendList.length) {
|
|
|
|
|
result.push(recommendList[j]);
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list.value = JSON.parse(JSON.stringify(result));
|
|
|
|
|
|
|
|
|
|
initState.value++
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 这个是监听 初始化的 推荐接口 和 onmount 都运行完成后 滚动 item ,不让冲突
|
|
|
|
|
watch(initState, (newValue, oldValue) => {
|
|
|
|
|
if (newValue === 2) {
|
|
|
|
|
const params = route.query;
|
|
|
|
|
calculateListIndex(detailsInfo.value, params["uniqid"]);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const setItemUrl = (uniqid) => {
|
|
|
|
|
let url = `./index.html?uniqid=${uniqid}`;
|
|
|
|
|
let query = route.query;
|
|
|
|
|
for (const key in query) {
|
|
|
|
|
if (key != "uniqid") url += `&${key}=${query[key]}`;
|
|
|
|
|
}
|
|
|
|
|
return url;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理点击 logo
|
|
|
|
|
const handleLogo = () => {
|
|
|
|
|
window.location.href = window.location.origin + window.location.pathname;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 您的答案
|
|
|
|
|
let yourAnswer = ref({
|
|
|
|
|
text: "",
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 切换您的答案 匿名状态
|
|
|
|
|
const cutYourAnswerAnonymous = () => {
|
|
|
|
|
yourAnswer.value["anonymous"] = yourAnswer.value["anonymous"] ? 0 : 1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理 您的答案的点击提交
|
|
|
|
|
const handleYourAnswer = () => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IAnswerInfo.value = { ...yourAnswer.value };
|
|
|
|
|
submitAnswer("you");
|
|
|
|
|
|
|
|
|
|
yourAnswer.value = {
|
|
|
|
|
text: "",
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let isDirectlyListIAnswer = false; // 是否是直接打开列表的我来回答
|
|
|
|
|
// 专门处理列表状态的 我来回答
|
|
|
|
|
const openListIAnswer = (index) => {
|
|
|
|
|
if (isNeedLogin.value) {
|
|
|
|
|
goLogin();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let targetData = list.value[index];
|
|
|
|
|
IAnswerInfo.value = {
|
|
|
|
|
title: targetData["title"],
|
|
|
|
|
content: targetData["content"],
|
|
|
|
|
token: targetData["token"],
|
|
|
|
|
uniqid: targetData["uniqid"],
|
|
|
|
|
anonymous: 0,
|
|
|
|
|
index,
|
|
|
|
|
};
|
|
|
|
|
isDirectlyListIAnswer = true;
|
|
|
|
|
IAnswerState.value = true;
|
|
|
|
|
nextTick(() => handleInput());
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 头像框的状态
|
|
|
|
|
let avatarState = ref(false);
|
|
|
|
|
// 开启头像框
|
|
|
|
|
const openUserInfo = (index, ind, i) => {
|
|
|
|
|
if (i != null) {
|
|
|
|
|
if (answerList.value[index].commentList[ind]["child"][i]["uin"] > 0)
|
|
|
|
|
answerList.value[index].commentList[ind]["child"][i]["avatarState"] =
|
|
|
|
|
!answerList.value[index].commentList[ind]["child"][i][
|
|
|
|
|
"avatarState"
|
|
|
|
|
];
|
|
|
|
|
} else if (ind != null) {
|
|
|
|
|
if (answerList.value[index].commentList[ind]["uin"] > 0)
|
|
|
|
|
answerList.value[index].commentList[ind]["avatarState"] =
|
|
|
|
|
!answerList.value[index].commentList[ind]["avatarState"];
|
|
|
|
|
} else if (index != null) {
|
|
|
|
|
if (answerList.value[index]["uin"] > 0)
|
|
|
|
|
answerList.value[index]["avatarState"] =
|
|
|
|
|
!answerList.value[index]["avatarState"];
|
|
|
|
|
} else {
|
|
|
|
|
if (detailsInfo.value["uin"] > 0)
|
|
|
|
|
avatarState.value = !avatarState.value;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击发送信息
|
|
|
|
|
const sendMessage = (uin) => {
|
|
|
|
|
redirectToExternalWebsite(
|
|
|
|
|
`https://bbs.gter.net/home.php?mod=space&showmsg=1&uid=${uin}`
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 点击ta的主页
|
|
|
|
|
const TAHomePage = (uin) => {
|
|
|
|
|
redirectToExternalWebsite(
|
|
|
|
|
`https://bbs.gter.net/home.php?mod=space&uid=${uin}`
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 跳转 url
|
|
|
|
|
const redirectToExternalWebsite = (url) => {
|
|
|
|
|
const link = document.createElement("a");
|
|
|
|
|
link.href = url;
|
|
|
|
|
link.target = "_blank";
|
|
|
|
|
link.click();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 详情模式下关闭底部
|
|
|
|
|
const closeBottom = () => {
|
|
|
|
|
if (process.server) return;
|
|
|
|
|
|
|
|
|
|
const footer = document.querySelector("body .index-footer");
|
|
|
|
|
if (footer) footer.style.display = "none";
|
|
|
|
|
else setTimeout(() => closeBottom(), 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const openBottom = () => {
|
|
|
|
|
const footer = document.querySelector("body .index-footer");
|
|
|
|
|
if (footer) footer.style.display = "block";
|
|
|
|
|
else setTimeout(() => openBottom(), 1000);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理点击 只看
|
|
|
|
|
const handleLookOnly = () => {
|
|
|
|
|
zeroreply.value = (zeroreply.value == 0 ? 1 : 0)
|
|
|
|
|
page = 1;
|
|
|
|
|
list.value = []
|
|
|
|
|
backupsList = [];
|
|
|
|
|
getList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
};
|
|
|
|
|
},
|
2023-12-20 07:48:26 +00:00
|
|
|
|
};
|
2023-12-06 07:23:13 +00:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
@import url(./index.css);
|
|
|
|
|
</style>
|