Browse Source

暂定终版,k线图需要优化

hxl
hongxilin 3 months ago
parent
commit
db6943750f
  1. 2
      .env.development
  2. 1
      index.html
  3. 9
      src/App.vue
  4. 65
      src/api/AIxiaocaishen.js
  5. 8
      src/assets/js/useAppBridge.js
  6. 26
      src/assets/js/useProjectTracking.js
  7. 5
      src/main.js
  8. 5
      src/router/index.js
  9. 4
      src/store/audio.js
  10. 24
      src/store/dataList.js
  11. 146
      src/views/AIchat.vue
  12. 12
      src/views/AIfind.vue
  13. 8
      src/views/Announcement.vue
  14. 124
      src/views/Echarts/KLine.vue
  15. 50
      src/views/homePage.vue

2
.env.development

@ -2,7 +2,7 @@
VITE_ENV = 'development'
VITE_OUTPUT_DIR = 'dev'
# public path
VITE_PUBLIC_PATH = /
VITE_PUBLIC_PATH = /AIxiaocaishen
#新数据接口
VITE_APP_API_BASE_URL = "http://39.101.133.168:8828/link"

1
index.html

@ -5,6 +5,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="src/assets/img/homePage/AIicon.png">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
<script type="text/javascript" src="https://lfjf.rzfwq.com/djt/soft/bogu2021/uni-app/webview.js"></script>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
<title>AI小财神</title>

9
src/App.vue

@ -1,7 +1,14 @@
<script setup>
import { useProjectTracking } from './assets/js/useProjectTracking.js'
const projectRoutes = [
'/homePage'
'/homePage',
'/AIchat',
'/AIfind',
'/Announcement'
]
//
useProjectTracking(projectRoutes)
</script>
<template>

65
src/api/AIxiaocaishen.js

@ -42,39 +42,86 @@ export const computedUsersAPI = function (params) {
}
})
}
// 首次进入小财神
export const useAiGodAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/useAiGod`,
method: 'post',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
// 停留时间
export const updateStayTimeAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/updateStayTime`,
method: 'post',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
// 获取新闻接口
export const getNewsAPI = function () {
return request({
url: `http://192.168.9.19:8080/api/ai_god/news`,
url: `${APIurl}/api/ai_god/news`,
method: 'POST'
})
}
// 获取引导搜索词接口
export const getQuestionAPI = function () {
return request({
url: `http://192.168.9.19:8080/api/ai_god/shows`,
url: `${APIurl}/api/ai_god/shows`,
method: 'POST',
data: new URLSearchParams({
"type": "1",
"num": "10"
"num": "10",
"state": "1"
})
})
}
// 获取公告接口
export const getAnnouncementAPI = function () {
return request({
url: `http://192.168.9.19:8080/api/ai_god/shows`,
url: `${APIurl}/api/ai_god/shows`,
method: 'POST',
data: new URLSearchParams({
"type": "3",
"num": "1"
"num": "1",
"state": "1"
})
})
}
// 获取用户次数接口
export const getUserCountAPI = function (params) {
return request({
url: `http://192.168.9.19:8080/api/ai_god/userUsageInfo`,
url: `${APIurl}/api/ai_god/userUsageInfo`,
method: 'POST',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
// 推荐问题/每日复盘/小财神简介点击事件接口
export const qsArpAamClickAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/shows/click`,
method: 'POST',
data: new URLSearchParams(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
// 财经新闻点击事件接口
export const newsClickAPI = function (params) {
return request({
url: `${APIurl}/api/ai_god/news/click`,
method: 'POST',
data: new URLSearchParams(params),
headers: {

8
src/assets/js/useAppBridge.js

@ -1,3 +1,5 @@
// import { platform } from "os"
//跳转app方法
export function useAppBridge() {
const fullClose = (n, m) => {
@ -8,7 +10,8 @@ export function useAppBridge() {
return Math.floor(result)
}
const packageFun = (funName, fun = () => {}, platform, data = {}) => {
const packageFun = (funName, fun = () => { }, platform, data = {}) => {
console.log('packageFun', funName, platform, data)
const JWrandom = fullClose(10000, 99999)
data.JWrandom = JWrandom
@ -37,7 +40,10 @@ export function useAppBridge() {
}
})
break
default:
console.log('未知平台', platform)
}
} catch (e) {
console.error('Error in packageFun:', e)
}

26
src/assets/js/useProjectTracking.js

@ -1,6 +1,6 @@
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { useRouter } from 'vue-router'
import { computedUsersAPI } from '@/api/sword'
import { computedUsersAPI, useAiGodAPI, updateStayTimeAPI } from '@/api/AIxiaocaishen'
export function useProjectTracking(projectRoutes) {
const router = useRouter()
@ -23,16 +23,24 @@ export function useProjectTracking(projectRoutes) {
const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1)
.toString()
.padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date
.getHours()
.toString()
.padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date
.getSeconds()
.toString()
.padStart(2, '0')}`
.getHours()
.toString()
.padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date
.getSeconds()
.toString()
.padStart(2, '0')}`
sessionStorage.setItem('projectEntryTime', formattedDate)
sessionStorage.setItem('hasRecordedEntry', 'true')
isInProject.value = true
hasRecordedEntry.value = true
const token = localStorage.getItem('localToken')
if (token) {
const result = useAiGodAPI({
token: token
})
console.log(result);
}
console.log('记录首次进入时间:', formattedDate)
}
@ -63,13 +71,13 @@ export function useProjectTracking(projectRoutes) {
const params = {
stayTime: duration,
loginTime: storedEntryTime,
// loginTime: storedEntryTime,
token: localToken
}
if (localToken) {
try {
const res = await computedUsersAPI(params)
const res = await updateStayTimeAPI(params)
console.log('跟踪数据已发送:', res)
sessionStorage.removeItem('projectEntryTime')
sessionStorage.removeItem('hasRecordedEntry')

5
src/main.js

@ -6,6 +6,9 @@ import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// import 'reset-css';
import { createPinia } from 'pinia'
import { useAppBridge } from './assets/js/useAppBridge.js'
const { packageFun, fullClose } = useAppBridge()
const app = createApp(App)
const pinia = createPinia()
@ -15,4 +18,6 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.use(router)
app.use(ElementPlus)
app.use(pinia)
app.provide('packageFun', packageFun)
app.provide('fullClose', fullClose)
app.mount('#app')

5
src/router/index.js

@ -20,6 +20,11 @@ const routes = [
name: 'AIfind',
component: () => import('@/views/AIfind.vue'),
meta: { title: '发现' }
},
{
path: '/Announcement',
name: 'Announcement',
component: () => import('@/views/Announcement.vue'),
}
]
// 创建路由实例

4
src/store/audio.js

@ -4,7 +4,9 @@ export const useAudioStore = defineStore('audio', {
state: () => ({
soundInstance: null, // Howl 实例
isPlaying: false, // 播放状态
isVoiceEnabled: true // 新增声音开关状态
isVoiceEnabled: true, // 新增声音开关状态
lastVoiceState: null,
ttsUrl:''
}),
actions: {
// 设置音频实例

24
src/store/dataList.js

@ -31,7 +31,9 @@ export const useDataStore = defineStore('data', () => {
const getQueryVariable = (variable) => {
const query = window.location.search.substring(1)
// console.log(query,'query')
const vars = query.split('&')
// console.log(vars,'vars')
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) {
@ -41,17 +43,17 @@ export const useDataStore = defineStore('data', () => {
return ''
}
const getAnswer = (result) => {
const data = result.data;
const vars = query.split('&')
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=')
if (pair[0] === variable) {
return pair[1]
}
}
return ''
}
// const getAnswer = (result) => {
// const data = result.data;
// const vars = query.split('&')
// for (let i = 0; i < vars.length; i++) {
// const pair = vars[i].split('=')
// if (pair[0] === variable) {
// return pair[1]
// }
// }
// return ''
// }
// 使用示例,获取地址栏参数
// const token = ref(getQueryVariable('token'))

146
src/views/AIchat.vue

@ -1,7 +1,7 @@
<script setup>
import { ref, onMounted, watch, nextTick } from "vue";
import { ElDialog } from "element-plus";
import { getReplyStreamAPI, getReplyAPI, TTSAPI, getQuestionAPI } from "../api/AIxiaocaishen";
import { getReplyStreamAPI, getReplyAPI, TTSAPI, getQuestionAPI, qsArpAamClickAPI } from "../api/AIxiaocaishen";
import { useUserStore } from '../store/userPessionCode'
import { useChatStore } from '../store/chat'
import { useAudioStore } from '../store/audio'
@ -31,7 +31,14 @@ const emit = defineEmits(["updateMessage", "sendMessage"]);
//
const dialogVisible = ref(false);
const currentQuestions = ref("");
const showQuestions = (questions) => {
const showQuestions = async (questions) => {
const click = await qsArpAamClickAPI({
token: localStorage.getItem('localToken'),
id: questions.id
})
console.log(click);
currentQuestions.value = questions;
//
emit("updateMessage", questions.title);
@ -40,37 +47,75 @@ const showQuestions = (questions) => {
//
const playAudio = (url) => {
if (audioStore.soundInstance) {
audioStore.soundInstance.stop()
//
if (!url) {
console.warn('音频URL为空,跳过播放');
audioStore.isPlaying = false;
return;
}
const newSound = new Howl({
src: [url],
html5: true, // HTML5 AudioiOS
format: ['mp3', 'wav'],
onplay: () => {
audioStore.isPlaying = true // store
newSound.volume(1) //
},
onend: () => audioStore.isPlaying = false,
onstop: () => audioStore.isPlaying = false,
onloaderror: (id, err) => {
console.error('音频加载失败:', err);
ElMessage.error('音频播放失败,请检查网络连接');
const handlePlay = () => {
if (audioStore.soundInstance) {
Howler.unload(); //
// audioStore.soundInstance.stop()
}
});
//
newSound.play()
audioStore.setAudioInstance(newSound);
const newSound = new Howl({
src: [url],
html5: true, // HTML5 AudioiOS
format: ['mp3', 'acc'],
onplay: () => {
audioStore.isPlaying = true // store
newSound.volume(1) //
},
onend: () => audioStore.isPlaying = false,
onstop: () => audioStore.isPlaying = false,
onloaderror: (id, err) => {
console.error('音频加载失败:', err);
ElMessage.error('音频播放失败,请检查网络连接');
}
});
//
newSound.play()
//
if (Howler.autoUnlock) {
Howler.autoUnlock();
audioStore.setAudioInstance(newSound);
Howler._howls.push(newSound); //
// //
// if (Howler.autoUnlock) {
// Howler.autoUnlock();
// }
}
Howler.volume(1.0) //
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
document.addEventListener('touchstart', handlePlay, { once: true });
ElMessage.info('请轻触屏幕以启用音频播放');
} else {
handlePlay();
}
// Howler.volume(1.0) //
};
//
const pauseAudio = () => {
if (audioStore.soundInstance) {
//
if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
Howler.stop(); // iOS
} else {
audioStore.soundInstance.pause();
}
audioStore.isPlaying = false;
//
nextTick(() => {
Howler.unload();
audioStore.soundInstance = null;
});
}
};
//
@ -180,9 +225,15 @@ watch(
const AIcontent = ref("");
// answer
const status = JSON.parse(ans.value.resp);
var status;
if (ans.value.resp !== "") {
status = JSON.parse(ans.value.resp);
} else {
status = null;
}
console.log(status, "status")
if (status.code == 200) {
if (status === null || status.code == 200) {
if (ans.value.answerG !== "") {
AIcontent.value = ans.value.answerG;
const code = ans.value.code;
@ -268,8 +319,10 @@ watch(
const ttsUrl = ref();
if (tts.value.tts_cn !== null) {
audioStore.ttsUrl = tts.value.tts_cn.url;
ttsUrl.value = tts.value.tts_cn.url;
} else if (tts.value.tts_en !== null) {
audioStore.ttsUrl = tts.value.tts_en.url;
ttsUrl.value = tts.value.tts_en.url;
}
@ -322,6 +375,7 @@ watch(
sender: "ai",
content: status.msg
});
chatStore.setLoading(false);
}
@ -329,6 +383,7 @@ watch(
}
catch (e) {
console.error('请求失败:', e);
chatStore.messages.pop();
chatStore.messages.push({
sender: "ai",
content: "AI思考失败,请稍后再试... ",
@ -362,7 +417,40 @@ watch(
// })
// }
watch(
() => audioStore.isVoiceEnabled,
(newVal) => {
//
if (newVal === audioStore.lastVoiceState) return;
audioStore.lastVoiceState = newVal;
if (newVal) {
console.log("开启语音播放");
//
const tryPlay = () => {
if (!audioStore.ttsUrl) return; //
if (audioStore.soundInstance?.playing()) return;
playAudio(audioStore.ttsUrl);
setTimeout(() => {
if (!audioStore.soundInstance?.playing()) {
Howler.unload();
}
}, 1000);
};
tryPlay();
} else {
console.log("关闭语音播放");
//
Howler.stop();
Howler.unload();
if (audioStore.soundInstance) {
audioStore.soundInstance.off(); //
audioStore.soundInstance = null;
}
}
},
{ immediate: true }
)
// GIF
onMounted(() => {
@ -429,7 +517,7 @@ onMounted(() => {
.chat-container {
display: flex;
flex-direction: column;
overflow-x: hidden;
overflow: hidden;
}
.gif-area {

12
src/views/AIfind.vue

@ -1,6 +1,6 @@
<script setup>
import { ref } from 'vue'
import { getNewsAPI } from "../api/AIxiaocaishen"
import { getNewsAPI,newsClickAPI } from "../api/AIxiaocaishen"
import { marked } from 'marked'; // marked
import katex from 'katex'; // KaTeX
@ -14,7 +14,15 @@ const getNewsList = async () => {
//
const dialogVisible = ref(false)
const currentNews = ref('')
const showNews = (news) => {
const showNews = async(news) => {
//
const result = await newsClickAPI({
token: localStorage.getItem('localToken'),
id: news.id
})
console.log(result)
currentNews.value = news
// 使markedMarkdownHTML
currentNews.value.description = marked(currentNews.value.description);

8
src/views/Announcement.vue

@ -1,6 +1,6 @@
<script setup>
import { ref, onMounted } from "vue";
import { getAnnouncementAPI } from "../api/AIxiaocaishen";
import { getAnnouncementAPI,qsArpAamClickAPI } from "../api/AIxiaocaishen";
const announcementVideo = ref({});
const getAnnouncement = async () => {
@ -9,6 +9,12 @@ const getAnnouncement = async () => {
announcementVideo.value.url = result.data[0].url;
announcementVideo.value.img = result.data[0].img;
const click=await qsArpAamClickAPI({
token: localStorage.getItem('localToken'),
id: result.data[0].id
})
console.log(click);
console.log(announcementVideo.value, "announcementVideo");
}

124
src/views/Echarts/KLine.vue

@ -1,6 +1,6 @@
<template>
<!-- 趋势研判K线图 -->
<div ref="KlineCanvs" class="KlineClass"></div>
<!-- <div ref="KlineCanvs" class="KlineClass"></div> -->
<div ref="chartContainer" class="KlineClass"></div>
</template>
<script setup>
@ -11,13 +11,76 @@ import { useDataStore } from '@/store/dataList'
const KlineCanvs = ref() // Echarts
const dataStore = useDataStore()
const klineData = computed(() => dataStore.klineData)
const chartContainer = ref() //
const chartInstances = ref([]) //
//
// watch(
// klineData,
// (newValue) => {
// console.log('K线', newValue) //
// const currentData = newValue //
// if (currentData) {
// nextTick(() => {
// //
// const newChartDiv = document.createElement('div')
// newChartDiv.className = 'dynamic-chart'
// chartContainer.value.appendChild(newChartDiv)
// //
// requestAnimationFrame(() => {
// //
// if (newChartDiv.offsetHeight === 0) {
// console.warn('')
// newChartDiv.style.height = '500px'
// }
// const newInstance = echarts.init(newChartDiv)
// chartInstances.value.push(newInstance)
// KlineCanvsEcharts(currentData, newInstance)
// })
// // KlineCanvsEcharts(currentData)
// console.log(':', newChartDiv.offsetWidth, 'x', newChartDiv.offsetHeight)
// })
// }
// },
// { immediate: true, deep: true }
// )
watch(
klineData,
(newValue) => {
const currentData = newValue //
console.log('收到K线数据:', newValue)
const currentData = newValue
if (currentData) {
nextTick(() => {
KlineCanvsEcharts(currentData)
//
const chartId = `chart-${Date.now()}`
const newChartDiv = document.createElement('div')
newChartDiv.className = 'dynamic-chart'
newChartDiv.id = chartId
chartContainer.value.appendChild(newChartDiv)
requestAnimationFrame(() => {
if (newChartDiv.offsetHeight === 0) {
newChartDiv.style.height = '500px'
}
//
const newInstance = echarts.init(newChartDiv)
const instanceData = JSON.parse(JSON.stringify(currentData))
//
chartInstances.value.push({
id: chartId,
instance: newInstance,
data: instanceData,
container: newChartDiv //
})
// 使
KlineCanvsEcharts(instanceData, newInstance)
})
})
}
},
@ -37,7 +100,7 @@ watch(
// },
// { immediate: true, deep: true }
// )
function KlineCanvsEcharts(datatok) {
function KlineCanvsEcharts(datatok, instance) {
// const textEcahrts = t.value //
const data = datatok.Kline
//
@ -51,6 +114,13 @@ function KlineCanvsEcharts(datatok) {
return { categoryData, value }
}
const dealData = spliteDate(data)
console.log('处理后的K线数据:', dealData)
if (dealData.value.length === 0 || dealData.categoryData.length === 0) {
console.error('空数据,无法渲染图表')
return
}
//
const KlineOption = {
title: {
@ -103,10 +173,11 @@ function KlineCanvsEcharts(datatok) {
},
//
grid: {
left: '12%',
right: '10%',
left: '3%',
right: '3%',
bottom: '10%',
top: '18%'
top: '15%',
containLabel: true //
},
yAxis: {
scale: !0, //true
@ -195,12 +266,22 @@ function KlineCanvsEcharts(datatok) {
]
}
// echarts
const KlineCanvsChart = echarts.init(KlineCanvs.value)
KlineCanvsChart.setOption(KlineOption)
// const KlineCanvsChart = echarts.init(KlineCanvs.value)
// KlineCanvsChart.setOption(KlineOption)
//
instance.setOption(KlineOption)
//
// window.addEventListener('resize', () => {
// KlineCanvsChart.resize()
// })
// resize
window.addEventListener('resize', () => {
KlineCanvsChart.resize()
instance.resize()
})
}
onMounted(() => {
@ -213,8 +294,25 @@ onMounted(() => {
.KlineClass {
position: relative;
width: 100%;
min-height: 600px;
/* 改为最小高度 */
display: flex;
flex-direction: column;
gap: 20px;
/* 添加间距 */
}
.chart-container {
position: relative;
width: 100%;
height: 100%;
left: 5%;
bottom: 8%;
}
.dynamic-chart {
width: 100%;
height: 500px !important;
/* 强制高度 */
flex-shrink: 0;
/* 禁止高度压缩 */
}
</style>

50
src/views/homePage.vue

@ -134,7 +134,7 @@ import Announcement from "./Announcement.vue";
//
const isAnnouncementVisible = ref(false);
const showAnnouncement = () => {
const showAnnouncement = async () => {
console.log("打开公告");
isScrolling.value = false; //
setActiveTab('', -1); //
@ -159,11 +159,11 @@ const tabContent = ref(null);
const isScrolling = ref(false); //
const smoothScrollToBottom = async () => {
console.log('调用滚动到底部的方法')
// console.log('')
// await nextTick();
const container = tabContent.value;
console.log(container, 'container')
console.log(isScrolling.value, 'isScrolling.value')
// console.log(container, 'container')
// console.log(isScrolling.value, 'isScrolling.value')
if (!container) return;
await nextTick(); // DOM
@ -173,7 +173,7 @@ const smoothScrollToBottom = async () => {
// container.scrollTop = container.scrollHeight;
// container.scrollTop = container.offsetHeight;
// container.scrollTop = container.scrollHeight + container.offsetHeight;
console.log(container.scrollHeight, container.offsetHeight,container.scrollHeight-container.offsetHeight, container.scrollTop, "总长度", "可视长度", "位置")
// console.log(container.scrollHeight, container.offsetHeight, container.scrollHeight - container.offsetHeight, container.scrollTop, "", "", "")
}
}
@ -183,7 +183,7 @@ const throttledSmoothScrollToBottom = _.throttle(smoothScrollToBottom, 500, { tr
watch(
() => chatStore.messages,
() => {
console.log('messages变化了')
// console.log('messages')
throttledSmoothScrollToBottom();
// setTimeout(throttledSmoothScrollToBottom, 100);
},
@ -194,7 +194,7 @@ watch(
watch(
activeTab,
async () => {
console.log('activeTab变化了', activeTab.value)
// console.log('activeTab', activeTab.value)
isScrolling.value = false; //
await nextTick(); // DOM
throttledSmoothScrollToBottom();
@ -203,16 +203,20 @@ watch(
{ deep: true, immediate: true }
);
// setTimeout
setTimeout(() => {
fnGetToken()
}, 800)
// token
const fnGetToken = () => {
// console.log('fnGetToken')
window.JWready = (ress) => {
// console.log('JWready')
try {
ress = JSON.parse(ress)
// console.log(ress, 'ress')
} catch (error) {
console.log(error, 'fnGetToken error')
} //platform5app
// platform.value = ress.data.platform
//
console.log(ress.data.platform, 'ress.data.platform')
if (!ress.data.platform) {
// AppURL
localStorage.setItem('localToken', decodeURIComponent(String(getQueryVariable('token'))))
@ -233,10 +237,16 @@ const fnGetToken = () => {
)
}
}
// console.log('')
// App
useAppBridge().packageFun('JWwebReady', () => { }, 5, {})
}
// setTimeout
setTimeout(() => {
fnGetToken()
}, 800)
// const tabContainer = tabContent.value
// let befortop = 0
// tabContainer.addEventListener('scroll', () => {
@ -263,23 +273,23 @@ const heightListener = () => {
if (activeTab.value === 'AIchat') {
if (aftertop - befortop > 0) {
console.log('向下滚动');
// console.log('');
isScrolling.value = true;
} else {
console.log('向上滚动');
// console.log('');
isScrolling.value = true;
}
//
if (isBottom) {
console.log('滚动到底部');
// console.log('');
isScrolling.value = false;
}
}
befortop = aftertop;
};
console.log(isScrolling.value, 'isScrolling.value')
// console.log(isScrolling.value, 'isScrolling.value')
tabContainer.addEventListener('scroll', scrollHandler);
};
@ -287,6 +297,12 @@ const heightListener = () => {
const throttledHeightListener = _.throttle(heightListener, 500, { trailing: false });
onMounted(async () => {
const isPhone =
/phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone/i.test(
navigator.userAgent
)
!isPhone &&
localStorage.setItem('localToken', decodeURIComponent(String(getQueryVariable('token'))))
setHeight(document.getElementById("testId")); //
await chatStore.getUserCount();
throttledSmoothScrollToBottom();

Loading…
Cancel
Save