// 评论的回答者 提问者 // 列表 hot标签 Object.assign(window, Vue) const forumApp = Vue.createApp({ setup() { const baseURL = "https://ask.gter.net" let type = ref('list') // list details onMounted(() => { getUrlParams() getUserData() getListClass() window.addEventListener('scroll', handleScroll); getHistoricalSearchList() }) onUnmounted(() => { window.removeEventListener('keydown', handleKeydown) window.removeEventListener('scroll', handleScroll); }); let initParams = {} // 获取url的参数 const getUrlParams = () => { const params = {}; const regex = /[?&]([^=#]+)=([^&#]*)/g; let match; while ((match = regex.exec(window.location.href))) { params[match[1]] = decodeURIComponent(match[2]); } initParams = params if (params['uniqid']) getDetails(params['uniqid']) if (params['keyword']) keyword.value = params['keyword'] if (params['tid']) typePitch.value = params['tid'] getList() } // 获取当前url const getCurrentUrl = () => { return window.location.href; } // 我的 数据 数量 let myCount = ref({}) // // 获取用户数据 const getUserData = () => { $ajax("/api/user").then(res => { if (res.code != 200) return let data = res.data myCount.value = data.count }) } // 是否是搜索模式 let isSearchMode = ref(false) // 获取历史记录方法 const getHistoricalSearchList = () => { const list = localStorage.getItem('historical-Search'); if (list) historicalSearchList.value = JSON.parse(list) || [] else historicalSearchList.value = [] } // 存入历史记录 随便去重 和 限制长度 方法 const setHistoricalSearchList = () => { 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 = [] type.value = 'list' pitchIndex.value = null 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 = [] type.value = 'list' 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; // 列表下 滑动到底部 获取新数据 // console.log("type.value == 'list'", type.value == 'list', scrollTop + clientHeight, scrollHeight); // if (scrollTop + clientHeight >= scrollHeight - 40 && type.value == 'list') getList() // 列表下 滚动到顶部 触发类型的固定状态 if (scrollTop > 115 && type.value == 'list') tabListFixeState.value = true else tabListFixeState.value = false } let keyword = ref('') // 搜索的值 let keywordText = ref('') // 搜索的文本 let list = ref([]) // 列表数据 let page = 1 let total = ref(0) // 回答总数 let loading = ref(false) // 获取列表数据 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 != 200) return let data = res.data list.value = list.value.concat(data.data || []) total.value = data.count || 0 keywordText.value = keyword.value || '' // page++ if (list.value.length != data['count']) page++ else page = 0 if (keyword.value) isSearchMode.value = true else isSearchMode.value = false }).finally(() => loading.value = false) } let typeList = ref([]) let typePitch = ref(null) // 获取分类数据 列表分类 const getListClass = () => { $ajax("/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") // 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 // uniqid = "fubm5CnD05qj" // 标记一下 8yr1m1fOH5CS detailsInfo.value = {} answerList.value = [] answerPage.value = 0 $ajax("/api/details", { 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' if (index !== null && index !== undefined) cut(index) else calculateListIndex(data.info, uniqid) answerList.value = [] answerPage.value = 1 getAnswerList() closeAllTransmitState() if (isOpenAnswer) openIAnswer() replaceState({ uniqid }) }).finally(() => { detailLoading.value = false }) } // const calculateListIndex = (info, uniqid) => { let targetList = [...list.value] if (targetList.length == 0 && isSearchMode.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(' { 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++ }).finally(() => answerLoading = false) } // 操作 - 点赞 const operateLike = (token, index) => { $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) => { $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'] 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({}) // 我来回答-弹窗的信息 // 开启我来回答 const openIAnswer = (index, type) => { 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 } // 修改我来回答的匿名状态 const amendIAnswer = () => { IAnswerInfo.value['anonymous'] = IAnswerInfo.value['anonymous'] == 0 ? 1 : 0 } let isNeedNewAnswersData = false // 是否需要获取新的我的回答数据 // 提交回答 const submitAnswer = () => { const questionTextarea = document.querySelector(".question-textarea") 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) { answerList.value = [] answerPage.value = 1 getAnswerList() closeIAnswer() isNeedNewAnswersData = true handleMsg('success', res['message'] || '操作成功') if (!IAnswerInfo.value['token']) myCount.value['answer']++ } }) } // 打开回答的评论 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).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).then(res => { if (res.code != 200) return let data = res.data let slice3 = data.data.slice(3) let merged = [...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'] = merged handleMsg('success', res['message'] || '操作成功') }) } // 获取评论数据的公共接口 const getAnswerCommentPublic = (index) => { return new Promise((resolve, reject) => { $ajax("/api/comment/lists", { token: answerList.value[index]['token'], limit: answerCommentLimit, childlimit: 1, }).then(res => { if (res.code != 200) return resolve(res) }) }) } // 提交回答-评论 const submitAnswerComments = (index, ind, i) => { // answerList.value[index]['commentState'] = true 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'].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']++ } else { let targetData = { id: data['commentid'], content, isauthor: 1, islike: 0, likenum: 0, ...data, child: [] } targetAnswerList[index]['commentList'].unshift(targetData) targetAnswerList[index]['commentCount']++ } closeAnswerCommentsChild() handleMsg('success', res['message'] || '操作成功') }) } // 回答-评论 点赞 const operateAnswerCommentsLike = (token, index, ind, i) => { $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) => { 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 merged = [...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'] = merged answerList.value = targetAnswerList }) } let myType = ref('') // collect answers questions // 专门处理 我的 弹窗数据 const handleMy = (key) => { // if ((key == 'collect' && isNeedNewColletData) || (key == 'collect' && myCollectionList.value.length == 0)) { if (key == 'collect') { myCollectionList.value = [] myCollectionPage = 1 getMyCollection() return } else if (key == 'answers') { myAnswerList.value = [] myAnswerPage = 1 getMyAnswer() return } else if (key == 'questions') { myQuestionsList.value = [] myQuestionsPage = 1 getMyQuestions() return } // myType.value = key } 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 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 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 }) myAnswerList.value = myAnswerList.value.concat(data.data) myAnswerCount.value = data.count if (myAnswerList.value.length != data['count']) myAnswerPage++ else myAnswerPage = 0 myType.value = 'answers' isNeedNewAnswersData = false }).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 = () => { $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 = () => { $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 => { // if (pitchIndex.value == null) type.value = type.value == 'list' ? 'details' : 'list' pitchIndex.value = index setTimeout(() => { scrollLeftInMiddle() }, 350) } // 滚动左边在中间 const scrollLeftInMiddle = () => { let list = document.querySelector(".list-box") list.scrollTo({ // top: 128 * pitchIndex.value - pageListHeight.value / 2 - 385, top: 128 * pitchIndex.value + 68 - pageListHeight.value / 2, behavior: 'smooth' }) } const listStyle = () => { const newtype = type.value let width = "" let margin = "" if (newtype == 'list') { width = '1200px' margin = '0 auto' } else { width = 'calc((100vw - 1200px) / 2 + 512px)' margin = 'initial' } return { width, margin } } const itemStyle = (index, content) => { const newtype = type.value // let itemHeight = content == "" ? 106 : 128 let obj = {} if (newtype == 'list') { let top = Math.floor(index / 2) * 128 + 'px' obj['top'] = top if (index % 2 == 0) obj['left'] = 0 else obj['left'] = 649 + 'px' } else { obj['top'] = index * 128 + 'px' obj['left'] = 0 obj['width'] = '100%' // obj['backgroundColor'] = '#fbfbfb' obj['paddingLeft'] = 'calc((100vw - 1200px) / 2)' } return obj }; // list-box const listBoxStyle = () => { const newtype = type.value let obj = {} if (newtype == 'list') { obj['overflow'] = 'visible' } else { // obj['height'] = 'calc(100vh - ' + pageHeaderHeight.value + 'px)' obj['height'] = pageListHeight.value + 'px' } return obj } const $ajax = (url, data) => { url = url.indexOf('//') > -1 ? url : baseURL + url; return new Promise(function (resolve, reject) { // var xhr = new XMLHttpRequest() // xhr.responseType = "json" // xhr.withCredentials = true // xhr.onreadystatechange = function () { // if (xhr.readyState === 4) { // if (xhr.status === 200) { // if (xhr.response.code != 200) handleMsg('error', xhr.response['message'] || '报错了,请重试!!!') // resolve(xhr.response) // } else { // if (xhr.response.status == 401) window.location.href = 'https://passport.gter.net'; // } // } // } // xhr.open("POST", url, true) // xhr.setRequestHeader("Content-Type", "application/json") // xhr.setRequestHeader("authorization", "63c9bef150557f9c90e93f98d2e2497e") // xhr.send(JSON.stringify(data)) axios.post(url, data, { emulateJSON: true, withCredentials: true, headers: { authorization: "017189d7d01fa8ccf649f36e82807937" // 头部标记 } }).then(function (res) { var data = null try { data = typeof res.data == 'string' ? JSON.parse(res.data) : res.data; 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'; }) }); } // 处理时间 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) => { $ajax("/api/operate/share", { token }).then() } // 关闭详情模式 const closeDetailMode = () => { type.value = 'list' pitchIndex.value = null replaceState() } // 全部的启动到底部 const handleListScroll = (e) => { const el = e.target; if (el.scrollHeight - el.scrollTop >= el.clientHeight + 40) return getList() } // 处理 回答弹窗的复制图片 const handlePaste = (event) => { 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 => { const questionTextarea = document.querySelector(".question-textarea") let imgNode = document.createElement('img'); imgNode.setAttribute('src', res.url); imgNode.setAttribute('data-aid', res.aid); questionTextarea.appendChild(imgNode); handleInput() handleMsg('warning', '上传成功') }) }; 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) // 回答的输入事件 判断是否显示 placeholder 用 const handleInput = (event) => { // IAnswerInfo.value['text'] = event.target.innerHTML; const questionTextarea = document.querySelector(".question-textarea") const html = questionTextarea.innerHTML if (html) questionPlaceholderState.value = false else questionPlaceholderState.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 = {}) => { // 获取当前URL参数 let params = new URLSearchParams(window.location.search); for (const key in obj) { params.set(key, obj[key]); } // 替换当前URL,但不刷新页面 window.history.replaceState({}, '', `${window.location.pathname}?${params}`); } // 删除 url 参数的key const deleteState = (keys = []) => { let params = new URLSearchParams(window.location.search); keys.forEach(key => { params.delete(key); }) window.history.replaceState({}, '', `${window.location.pathname}?${params}`); } // 我的打开 详情 const myOpenDetails = (value) => { getDetails(value.data['uniqid']) myType.value = "" } // 详情页滚动事件 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 = [] type.value = 'list' pitchIndex.value = null if (id != null) { replaceState({ tid: id }) deleteState(['uniqid']) } else deleteState(['tid', 'uniqid']) getList() } // 打开举报 const handleMenuState = (index, ind, i) => { 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', '举报成功') }) } watch(() => { if (questionsSetp.value || myType.value || IAnswerEditState.value || IAnswerState.value || dialogSrc.value) document.body.style.overflow = 'hidden' else document.body.style.overflow = 'auto' }) return { handleMenuState, reasonList, checkList, alertShow, alertText, selectRadio, alertSubmit, cutType, dialogSrc, answerPage, handleDetailsScroll, replaceState, copyText, boxClass, questionPlaceholderState, 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, }; } }) forumApp.mount("#answer-app"); //初始化