Spaces:
Runtime error
Runtime error
update
#1
by
jjjjjjj1 - opened
- .env +3 -0
- .eslintrc.cjs +3 -0
- src/hooks/useChatTip/TipNode.vue +99 -0
- src/hooks/useChatTip/common.ts +6 -0
- src/hooks/useChatTip/qr-wx.png +0 -0
- src/hooks/useChatTip/qr-zfb.png +0 -0
- src/hooks/useChatTip/useChatTip.ts +34 -0
- src/views/chat/index.vue +12 -0
.env
CHANGED
|
@@ -8,3 +8,6 @@ VITE_GLOB_OPEN_LONG_REPLY=false
|
|
| 8 |
|
| 9 |
# When you want to use PWA
|
| 10 |
VITE_GLOB_APP_PWA=false
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
# When you want to use PWA
|
| 10 |
VITE_GLOB_APP_PWA=false
|
| 11 |
+
|
| 12 |
+
# 触发弹层提示所需聊天次数
|
| 13 |
+
VITE_GLOB_CHAT_TIP_THRESHOLD=6
|
.eslintrc.cjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
| 1 |
module.exports = {
|
| 2 |
root: true,
|
| 3 |
extends: ['@antfu'],
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
|
|
|
| 1 |
module.exports = {
|
| 2 |
root: true,
|
| 3 |
extends: ['@antfu'],
|
| 4 |
+
rules: {
|
| 5 |
+
"no-tabs": "off"
|
| 6 |
+
}
|
| 7 |
}
|
src/hooks/useChatTip/TipNode.vue
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<script setup lang="ts">
|
| 2 |
+
import { NButton, NModal } from 'naive-ui'
|
| 3 |
+
const { show } = defineProps<{
|
| 4 |
+
show: boolean
|
| 5 |
+
}>()
|
| 6 |
+
|
| 7 |
+
const emit = defineEmits<{
|
| 8 |
+
(event: 'increase'): void
|
| 9 |
+
}>()
|
| 10 |
+
</script>
|
| 11 |
+
|
| 12 |
+
<template>
|
| 13 |
+
<NModal :show="show">
|
| 14 |
+
<div class="card">
|
| 15 |
+
<div class="title">
|
| 16 |
+
❤️ ❤️️如果你觉得这个项目对你有帮助,并且情况允许的话,可以给我一点点支持,非常感谢支持~
|
| 17 |
+
</div>
|
| 18 |
+
<div class="pics">
|
| 19 |
+
<div class="item">
|
| 20 |
+
<img src="./qr-wx.png" alt="qr-img">
|
| 21 |
+
<div class="color-green">
|
| 22 |
+
微信
|
| 23 |
+
</div>
|
| 24 |
+
</div>
|
| 25 |
+
<div class="item">
|
| 26 |
+
<img src="./qr-zfb.png" alt="qr-img">
|
| 27 |
+
<div class="color-blue">
|
| 28 |
+
支付宝
|
| 29 |
+
</div>
|
| 30 |
+
</div>
|
| 31 |
+
</div>
|
| 32 |
+
<div class="foot">
|
| 33 |
+
<NButton type="success" size="large" block style="font-size: 18px;" @click="emit('increase')">
|
| 34 |
+
知道了🐶
|
| 35 |
+
</NButton>
|
| 36 |
+
</div>
|
| 37 |
+
</div>
|
| 38 |
+
</NModal>
|
| 39 |
+
</template>
|
| 40 |
+
|
| 41 |
+
<style scoped>
|
| 42 |
+
.card {
|
| 43 |
+
border-radius: 6px;
|
| 44 |
+
background-color: #fff;
|
| 45 |
+
text-align: center;
|
| 46 |
+
max-width: 660px;
|
| 47 |
+
padding: 32px;
|
| 48 |
+
max-height: 60vh;
|
| 49 |
+
overflow: auto;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.title {
|
| 53 |
+
font-size: 24px;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
.pics {
|
| 57 |
+
display: flex;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.item {
|
| 61 |
+
display: flex;
|
| 62 |
+
flex-direction: column;
|
| 63 |
+
align-items: center;
|
| 64 |
+
border: 1px solid #e5e5e5;
|
| 65 |
+
border-radius: 12px;
|
| 66 |
+
overflow: hidden;
|
| 67 |
+
margin: 12px 24px;
|
| 68 |
+
padding: 12px;
|
| 69 |
+
padding-bottom: 8px;
|
| 70 |
+
|
| 71 |
+
> img {
|
| 72 |
+
width: 300px;
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
.foot {
|
| 77 |
+
max-width: 320px;
|
| 78 |
+
margin: 0 auto;
|
| 79 |
+
margin-top: 32px;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
.color-green {
|
| 83 |
+
color: rgb(82, 158, 70);
|
| 84 |
+
font-size: 18px;
|
| 85 |
+
font-weight: bold;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
.color-blue {
|
| 89 |
+
color: rgb(70, 157, 225);
|
| 90 |
+
font-size: 18px;
|
| 91 |
+
font-weight: bold;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
@media screen and (max-width: 768px) {
|
| 95 |
+
.pics {
|
| 96 |
+
display: block;
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
</style>
|
src/hooks/useChatTip/common.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export const TIP_THRESHOLD = strNum2Num(import.meta.env.VITE_GLOB_CHAT_TIP_THRESHOLD) || 6
|
| 2 |
+
|
| 3 |
+
export function strNum2Num(str: string) {
|
| 4 |
+
const n = parseInt(str, 10)
|
| 5 |
+
return isNaN(n) ? 0 : n
|
| 6 |
+
}
|
src/hooks/useChatTip/qr-wx.png
ADDED
|
src/hooks/useChatTip/qr-zfb.png
ADDED
|
src/hooks/useChatTip/useChatTip.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { onMounted, ref } from 'vue'
|
| 2 |
+
import { TIP_THRESHOLD, strNum2Num } from './common.js'
|
| 3 |
+
|
| 4 |
+
const countCacheKey = '__chat_tip_count__'
|
| 5 |
+
|
| 6 |
+
export function useChatTip() {
|
| 7 |
+
const tipCount = ref(0)
|
| 8 |
+
|
| 9 |
+
onMounted(() => {
|
| 10 |
+
forceSyncCount()
|
| 11 |
+
})
|
| 12 |
+
|
| 13 |
+
/** 从localStorage中同步count */
|
| 14 |
+
function forceSyncCount() {
|
| 15 |
+
const cacheCount = strNum2Num(localStorage.getItem(countCacheKey) || '0')
|
| 16 |
+
|
| 17 |
+
if (cacheCount !== tipCount.value)
|
| 18 |
+
tipCount.value = cacheCount
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
function increase() {
|
| 22 |
+
tipCount.value++
|
| 23 |
+
|
| 24 |
+
if (tipCount.value > TIP_THRESHOLD)
|
| 25 |
+
tipCount.value = 0
|
| 26 |
+
|
| 27 |
+
localStorage.setItem(countCacheKey, String(tipCount.value))
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
return {
|
| 31 |
+
increase,
|
| 32 |
+
count: tipCount,
|
| 33 |
+
}
|
| 34 |
+
}
|
src/views/chat/index.vue
CHANGED
|
@@ -5,6 +5,9 @@ import { useRoute } from 'vue-router'
|
|
| 5 |
import { storeToRefs } from 'pinia'
|
| 6 |
import { NAutoComplete, NButton, NInput, useDialog, useMessage } from 'naive-ui'
|
| 7 |
import html2canvas from 'html2canvas'
|
|
|
|
|
|
|
|
|
|
| 8 |
import { Message } from './components'
|
| 9 |
import { useScroll } from './hooks/useScroll'
|
| 10 |
import { useChat } from './hooks/useChat'
|
|
@@ -27,6 +30,8 @@ const ms = useMessage()
|
|
| 27 |
|
| 28 |
const chatStore = useChatStore()
|
| 29 |
|
|
|
|
|
|
|
| 30 |
useCopyCode()
|
| 31 |
|
| 32 |
const { isMobile } = useBasicLayout()
|
|
@@ -155,6 +160,8 @@ async function onConversation() {
|
|
| 155 |
}
|
| 156 |
|
| 157 |
await fetchChatAPIOnce()
|
|
|
|
|
|
|
| 158 |
}
|
| 159 |
catch (error: any) {
|
| 160 |
const errorMessage = error?.message ?? t('common.wrong')
|
|
@@ -556,5 +563,10 @@ onUnmounted(() => {
|
|
| 556 |
</div>
|
| 557 |
</div>
|
| 558 |
</footer>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 559 |
</div>
|
| 560 |
</template>
|
|
|
|
| 5 |
import { storeToRefs } from 'pinia'
|
| 6 |
import { NAutoComplete, NButton, NInput, useDialog, useMessage } from 'naive-ui'
|
| 7 |
import html2canvas from 'html2canvas'
|
| 8 |
+
import { useChatTip } from '../../hooks/useChatTip/useChatTip.js'
|
| 9 |
+
import TipNode from '../../hooks/useChatTip/TipNode.vue'
|
| 10 |
+
import { TIP_THRESHOLD } from '../../hooks/useChatTip/common.js'
|
| 11 |
import { Message } from './components'
|
| 12 |
import { useScroll } from './hooks/useScroll'
|
| 13 |
import { useChat } from './hooks/useChat'
|
|
|
|
| 30 |
|
| 31 |
const chatStore = useChatStore()
|
| 32 |
|
| 33 |
+
const tipCount = useChatTip()
|
| 34 |
+
|
| 35 |
useCopyCode()
|
| 36 |
|
| 37 |
const { isMobile } = useBasicLayout()
|
|
|
|
| 160 |
}
|
| 161 |
|
| 162 |
await fetchChatAPIOnce()
|
| 163 |
+
|
| 164 |
+
tipCount.increase()
|
| 165 |
}
|
| 166 |
catch (error: any) {
|
| 167 |
const errorMessage = error?.message ?? t('common.wrong')
|
|
|
|
| 563 |
</div>
|
| 564 |
</div>
|
| 565 |
</footer>
|
| 566 |
+
|
| 567 |
+
<TipNode
|
| 568 |
+
:show="tipCount.count.value === TIP_THRESHOLD"
|
| 569 |
+
@increase="tipCount.increase"
|
| 570 |
+
/>
|
| 571 |
</div>
|
| 572 |
</template>
|