PC-questions-answersnuxt/app.vue
2023-12-20 15:48:26 +08:00

3896 lines
130 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<!--
新增的回答款需要输入图片
-->
<template>
<div 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>
</div>
</div>
<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>
</div>
</div>
</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>
<div
class="list"
id="list"
:style="[listStyle(), { height: listHeight + 'px' }]"
>
<template v-for="(item, index) in list" :key="index">
<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"
v-html="item['title']"
></div>
</div>
<template v-if="item['type'] == 'thread'">
<div
class="answer ellipsis"
v-if="item['message']"
v-html="item['message']"
></div>
</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"
v-html="item['title']"
></div>
</div>
<div
class="answer ellipsis"
v-if="item['content']"
v-html="item['content']"
></div>
<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>
<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>
</div>
<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"
></path>
</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"
/>
{{
detailsInfo["collectionnum"] > 0
? detailsInfo["collectionnum"]
: "收藏"
}}
</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="
copyText(detailsInfo['title'] + getCurrentUrl())
"
>
复制链接
</div>
</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>
</div>
<!-- 一共多少 -->
<div class="answer-total-amount">
共 {{ detailsInfo["answers"] }} 个回答
</div>
<!-- 回答-数据 -->
<div
class="answer-box-item"
v-for="(item, index) in answerList"
:key="index"
>
<!-- <div class="icon-circle-box">
<div class="icon-box flexcenter">A</div>
</div> -->
<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"
/>
{{
item["collectionnum"] == 0
? "收藏"
: item["collectionnum"]
}}
</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="
copyText(detailsInfo['title'] + getCurrentUrl())
"
>
复制链接
</div>
</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>
<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="
operateAnswerCommentsLike(it['token'], index, ind)
"
>
<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="
operateAnswerCommentsLike(
ite['token'],
index,
ind,
i
)
"
>
<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>
</div>
</div>
<!-- 回答-没有数据 -->
<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" />
</div>
<div class="empty-hint">我在等待你的回答</div>
</div>
<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>
</div>
</div>
</div>
<!-- 我的弹窗 -->
<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="
(myType == 'collect' && myCollectionList.length == 0) ||
(myType == 'answers' && myAnswerList.length == 0) ||
(myType == 'questions' && myQuestionsList.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">暂无内容</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">
{{
item["data"]["answers"] > 0
? "共" + item["data"]["answers"] + "个回答"
: "暂无回答"
}}
</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>
</div>
<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>
</div>
<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>
{{
item["answers"] == 0
? "暂无回答"
: "共" + item["answers"] + "个回答"
}}
</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="
changeAnonymousQuestions(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="
changeAnonymousQuestions(item['token'], 1, index)
"
>
<div class="">匿名发表</div>
<img
class="state-popup-icon"
src="./img/tick-orange.svg"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 我要提问 -->
<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>
<!-- 第二步 -->
<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>
</div>
<!-- 编辑回答 -->
<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>
</div>
<!-- 我来回答 -->
<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>
<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>
</div>
<!-- 提示框 -->
<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>
</div>
<!-- 举报 -->
<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>
</div>
</div>
</div>
</template>
<script>
import { onMounted, onUnmounted, ref, nextTick, watchEffect } from "vue";
import axios from "axios";
export default {
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);
});
});
};
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);
});
});
};
let isNeedLogin = ref(true); // 是否需要有登录
// 跳转登录
const goLogin = () => ajax_login();
const route = useRoute();
let detailsInfoDataVuex = useState("detailsInfoData", () => {});
let relatedlistDataVuex = useState("relatedlistData", () => {});
let listDataVuex = useState("listData", () => {});
const baseURL = "https://ask.gter.net";
let type = ref("list"); // list details
onMounted(() => {
// getUrlParams()
// getUserData()
if (process.env.NODE_ENV !== "production") isNeedLogin.value = false;
else determineIsLogin();
getListClass();
window.addEventListener("scroll", handleScroll);
getHistoricalSearchList();
if (isNeedScrollMiddle) scrollLeftInMiddle();
if (process.client) originUrl.value = window.location.origin;
listenPageBack();
if (listDataVuex.value) hanleServerListData();
if (detailsInfoDataVuex.value) hanleServerRequestData();
if (relatedlistDataVuex.value) hanleServerRelatedlistData();
});
// 列表的
const hanleServerListData = () => {
list.value = listDataVuex.value["list"];
backupsList = listDataVuex.value["backupsList"];
total.value = listDataVuex.value["total"];
keywordText.value = listDataVuex.value["keywordText"];
page = listDataVuex.value["page"];
inTheEndState.value = listDataVuex.value["inTheEndState"];
isListEmptyState.value = listDataVuex.value["isListEmptyState"];
isSearchMode.value = listDataVuex.value["isSearchMode"];
};
// 处理在服务端已经请求了详情接口的数据
const hanleServerRelatedlistData = () => {
recommendList = relatedlistDataVuex.value["list"];
recommendPage = relatedlistDataVuex.value["page"];
handleInsertRelatedlist();
};
// 处理在服务端已经请求了详情接口 数据
const hanleServerRequestData = () => {
const params = route.query;
type.value = "details";
let data = detailsInfoDataVuex.value;
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;
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);
});
// 获取当前url
const getCurrentUrl = () => {
return window.location.href;
};
// 我的 数据 数量
let myCount = ref({}); //
// 获取用户数据
const getUserData = (key) => {
$ajax("/api/user").then((res) => {
if (res.code != 200) return;
let data = res.data;
myCount.value = data.count;
handleMy(key);
});
};
// 是否是搜索模式
let isSearchMode = ref(false);
// 获取历史记录方法
const getHistoricalSearchList = () => {
const list = localStorage.getItem("historical-Search");
if (list) historicalSearchList.value = JSON.parse(list) || [];
else historicalSearchList.value = [];
};
// 存入历史记录 随便去重 和 限制长度 方法
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)
);
};
// 搜索点击事件
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(); // 列表是否为空的状态
// 获取列表数据
const getList = () => {
if (page == 0 || loading.value) return;
loading.value = true;
$ajax("/api/lists", {
page,
limit: 20,
keyword: keyword.value,
type: typePitch.value,
})
.then((res) => {
if (res.code == 401) goLogin();
if (res.code != 200) return;
let data = res.data;
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;
targetList.forEach((element, index) => {
if (element["uniqid"] == uniqid) {
cut(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";
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 = [];
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({});
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 (params["uniqid"] && process.server) {
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;
})
.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
// })
// }
}
if (process.server) {
await $ajax("/api/lists", {
page,
limit: 20,
keyword: keyword.value,
type: typePitch.value,
}).then((res) => {
if (res.code != 200) return;
let data = res.data;
list.value = list.value.concat(data.data || []);
backupsList = backupsList.concat(data.data || []);
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;
listDataVuex.value = {
list: list.value,
backupsList: backupsList,
total: total.value,
keywordText: keywordText.value,
page: page,
inTheEndState: inTheEndState.value,
isListEmptyState: isListEmptyState.value,
isSearchMode: isSearchMode.value,
};
// 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++;
relatedlistDataVuex.value = {
list: data,
page: 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));
}
}
);
}
} catch (error) {
console.error(error);
}
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);
};
return {
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,
};
},
};
</script>
<style>
@import url(./index.css);
</style>