Merge branch 'yongpxu-dev' into develop

This commit is contained in:
超级老白兔
2025-09-19 16:59:38 +08:00
262 changed files with 3240 additions and 2197 deletions

3
Cunkebao/.gitignore vendored
View File

@@ -3,4 +3,5 @@ dist/
build/ build/
yarn.lock yarn.lock
.env .env
.DS_Store .DS_Store
dist/*

View File

@@ -1,50 +1,50 @@
{ {
"_charts-DsEZaGAW.js": { "_charts-B449e2xS.js": {
"file": "assets/charts-DsEZaGAW.js", "file": "assets/charts-B449e2xS.js",
"name": "charts", "name": "charts",
"imports": [ "imports": [
"_ui-YC29IQHT.js", "_ui-DDu9FCjt.js",
"_vendor-Bq99rrm8.js" "_vendor-0WYR1k4q.js"
] ]
}, },
"_ui-D0C0OGrH.css": { "_ui-D0C0OGrH.css": {
"file": "assets/ui-D0C0OGrH.css", "file": "assets/ui-D0C0OGrH.css",
"src": "_ui-D0C0OGrH.css" "src": "_ui-D0C0OGrH.css"
}, },
"_ui-YC29IQHT.js": { "_ui-DDu9FCjt.js": {
"file": "assets/ui-YC29IQHT.js", "file": "assets/ui-DDu9FCjt.js",
"name": "ui", "name": "ui",
"imports": [ "imports": [
"_vendor-Bq99rrm8.js" "_vendor-0WYR1k4q.js"
], ],
"css": [ "css": [
"assets/ui-D0C0OGrH.css" "assets/ui-D0C0OGrH.css"
] ]
}, },
"_utils-Ft3ushmX.js": { "_utils-DC06x9DY.js": {
"file": "assets/utils-Ft3ushmX.js", "file": "assets/utils-DC06x9DY.js",
"name": "utils", "name": "utils",
"imports": [ "imports": [
"_vendor-Bq99rrm8.js" "_vendor-0WYR1k4q.js"
] ]
}, },
"_vendor-Bq99rrm8.js": { "_vendor-0WYR1k4q.js": {
"file": "assets/vendor-Bq99rrm8.js", "file": "assets/vendor-0WYR1k4q.js",
"name": "vendor" "name": "vendor"
}, },
"index.html": { "index.html": {
"file": "assets/index-d8oC2PBC.js", "file": "assets/index-Bx3nG52V.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
"imports": [ "imports": [
"_vendor-Bq99rrm8.js", "_vendor-0WYR1k4q.js",
"_ui-YC29IQHT.js", "_ui-DDu9FCjt.js",
"_utils-Ft3ushmX.js", "_utils-DC06x9DY.js",
"_charts-DsEZaGAW.js" "_charts-B449e2xS.js"
], ],
"css": [ "css": [
"assets/index-D8Ews0CA.css" "assets/index-QrS4Cvyc.css"
] ]
} }
} }

View File

@@ -11,13 +11,13 @@
</style> </style>
<!-- 引入 uni-app web-view SDK必须 --> <!-- 引入 uni-app web-view SDK必须 -->
<script type="text/javascript" src="/websdk.js"></script> <script type="text/javascript" src="/websdk.js"></script>
<script type="module" crossorigin src="/assets/index-d8oC2PBC.js"></script> <script type="module" crossorigin src="/assets/index-Bx3nG52V.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-Bq99rrm8.js"> <link rel="modulepreload" crossorigin href="/assets/vendor-0WYR1k4q.js">
<link rel="modulepreload" crossorigin href="/assets/ui-YC29IQHT.js"> <link rel="modulepreload" crossorigin href="/assets/ui-DDu9FCjt.js">
<link rel="modulepreload" crossorigin href="/assets/utils-Ft3ushmX.js"> <link rel="modulepreload" crossorigin href="/assets/utils-DC06x9DY.js">
<link rel="modulepreload" crossorigin href="/assets/charts-DsEZaGAW.js"> <link rel="modulepreload" crossorigin href="/assets/charts-B449e2xS.js">
<link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css"> <link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css">
<link rel="stylesheet" crossorigin href="/assets/index-D8Ews0CA.css"> <link rel="stylesheet" crossorigin href="/assets/index-QrS4Cvyc.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -161,273 +161,313 @@ const EMOJI_DATA: Record<EmojiName, EmojiInfo> = {
: { : {
name: "微笑", name: "微笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/微笑.png", path: "/assets/face/smile.png",
}, },
: { : {
name: "撇嘴", name: "撇嘴",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/撇嘴.png", path: "/assets/face/pout.png",
},
: {
name: "色",
category: EmojiCategory.FACE,
path: "/assets/face/lustful.png",
}, },
: { name: "色", category: EmojiCategory.FACE, path: "/assets/face/色.png" },
: { : {
name: "发呆", name: "发呆",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/发呆.png", path: "/assets/face/daze.png",
}, },
: { : {
name: "得意", name: "得意",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/得意.png", path: "/assets/face/smug.png",
}, },
: { : {
name: "流泪", name: "流泪",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/流泪.png", path: "/assets/face/crying.png",
}, },
: { : {
name: "害羞", name: "害羞",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/害羞.png", path: "/assets/face/shy.png",
}, },
: { : {
name: "闭嘴", name: "闭嘴",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/闭嘴.png", path: "/assets/face/shut-up.png",
},
: {
name: "睡",
category: EmojiCategory.FACE,
path: "/assets/face/sleep.png",
}, },
: { name: "睡", category: EmojiCategory.FACE, path: "/assets/face/睡.png" },
: { : {
name: "大哭", name: "大哭",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/大哭.png", path: "/assets/face/wail.png",
}, },
: { : {
name: "尴尬", name: "尴尬",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/尴尬.png", path: "/assets/face/awkward.png",
}, },
: { : {
name: "发怒", name: "发怒",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/发怒.png", path: "/assets/face/angry.png",
}, },
: { : {
name: "调皮", name: "调皮",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/调皮.png", path: "/assets/face/naughty.png",
}, },
: { : {
name: "呲牙", name: "呲牙",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/呲牙.png", path: "/assets/face/grin.png",
}, },
: { : {
name: "惊讶", name: "惊讶",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/惊讶.png", path: "/assets/face/surprised.png",
}, },
: { : {
name: "难过", name: "难过",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/难过.png", path: "/assets/face/sad.png",
},
: {
name: "囧",
category: EmojiCategory.FACE,
path: "/assets/face/embarrassed.png",
}, },
: { name: "囧", category: EmojiCategory.FACE, path: "/assets/face/囧.png" },
: { : {
name: "抓狂", name: "抓狂",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/抓狂.png", path: "/assets/face/crazy.png",
},
: {
name: "吐",
category: EmojiCategory.FACE,
path: "/assets/face/vomit.png",
}, },
: { name: "吐", category: EmojiCategory.FACE, path: "/assets/face/吐.png" },
: { : {
name: "偷笑", name: "偷笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/偷笑.png", path: "/assets/face/snicker.png",
}, },
: { : {
name: "愉快", name: "愉快",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/愉快.png", path: "/assets/face/happy.png",
}, },
: { : {
name: "白眼", name: "白眼",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/白眼.png", path: "/assets/face/roll-eyes.png",
}, },
: { : {
name: "傲慢", name: "傲慢",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/傲慢.png", path: "/assets/face/arrogant.png",
},
: {
name: "困",
category: EmojiCategory.FACE,
path: "/assets/face/sleepy.png",
}, },
: { name: "困", category: EmojiCategory.FACE, path: "/assets/face/困.png" },
: { : {
name: "惊恐", name: "惊恐",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/惊恐.png", path: "/assets/face/panic.png",
}, },
: { : {
name: "憨笑", name: "憨笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/憨笑.png", path: "/assets/face/silly-smile.png",
}, },
: { : {
name: "悠闲", name: "悠闲",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/悠闲.png", path: "/assets/face/leisurely.png",
}, },
: { : {
name: "咒骂", name: "咒骂",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/咒骂.png", path: "/assets/face/curse.png",
}, },
: { : {
name: "疑问", name: "疑问",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/疑问.png", path: "/assets/face/question.png",
},
: {
name: "嘘",
category: EmojiCategory.FACE,
path: "/assets/face/shush.png",
},
: {
name: "晕",
category: EmojiCategory.FACE,
path: "/assets/face/dizzy.png",
},
: {
name: "衰",
category: EmojiCategory.FACE,
path: "/assets/face/unlucky.png",
}, },
: { name: "嘘", category: EmojiCategory.FACE, path: "/assets/face/嘘.png" },
: { name: "晕", category: EmojiCategory.FACE, path: "/assets/face/晕.png" },
: { name: "衰", category: EmojiCategory.FACE, path: "/assets/face/衰.png" },
: { : {
name: "骷髅", name: "骷髅",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/骷髅.png", path: "/assets/face/skull.png",
}, },
: { : {
name: "敲打", name: "敲打",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/敲打.png", path: "/assets/face/knock.png",
}, },
: { : {
name: "再见", name: "再见",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/再见.png", path: "/assets/face/goodbye.png",
}, },
: { : {
name: "擦汗", name: "擦汗",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/擦汗.png", path: "/assets/face/wipe-sweat.png",
}, },
: { : {
name: "抠鼻", name: "抠鼻",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/抠鼻.png", path: "/assets/face/pick-nose.png",
}, },
: { : {
name: "鼓掌", name: "鼓掌",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/鼓掌.png", path: "/assets/face/clap.png",
}, },
: { : {
name: "坏笑", name: "坏笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/坏笑.png", path: "/assets/face/evil-smile.png",
}, },
: { : {
name: "右哼哼", name: "右哼哼",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/右哼哼.png", path: "/assets/face/right-hum.png",
}, },
: { : {
name: "鄙视", name: "鄙视",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/鄙视.png", path: "/assets/face/despise.png",
}, },
: { : {
name: "委屈", name: "委屈",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/委屈.png", path: "/assets/face/wronged.png",
}, },
: { : {
name: "快哭了", name: "快哭了",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/快哭了.png", path: "/assets/face/about-to-cry.png",
}, },
: { : {
name: "阴险", name: "阴险",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/阴险.png", path: "/assets/face/sinister.png",
}, },
: { : {
name: "亲亲", name: "亲亲",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/亲亲.png", path: "/assets/face/kiss.png",
}, },
: { : {
name: "可怜", name: "可怜",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/可怜.png", path: "/assets/face/pitiful.png",
}, },
: { : {
name: "笑脸", name: "笑脸",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/笑脸.png", path: "/assets/face/smiley.png",
}, },
: { : {
name: "生病", name: "生病",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/生病.png", path: "/assets/face/sick.png",
}, },
: { : {
name: "脸红", name: "脸红",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/脸红.png", path: "/assets/face/blush.png",
}, },
: { : {
name: "破涕为笑", name: "破涕为笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/破涕为笑.png", path: "/assets/face/tears-to-smile.png",
}, },
: { : {
name: "恐惧", name: "恐惧",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/恐惧.png", path: "/assets/face/fear.png",
}, },
: { : {
name: "失望", name: "失望",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/失望.png", path: "/assets/face/disappointed.png",
}, },
: { : {
name: "无语", name: "无语",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/无语.png", path: "/assets/face/speechless.png",
}, },
: { : {
name: "嘿哈", name: "嘿哈",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/嘿哈.png", path: "/assets/face/hey-ha.png",
}, },
: { : {
name: "捂脸", name: "捂脸",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/捂脸.png", path: "/assets/face/facepalm.png",
}, },
: { : {
name: "机智", name: "机智",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/机智.png", path: "/assets/face/smart.png",
}, },
: { : {
name: "皱眉", name: "皱眉",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/皱眉.png", path: "/assets/face/frown.png",
},
: {
name: "耶",
category: EmojiCategory.FACE,
path: "/assets/face/yeah.png",
}, },
: { name: "耶", category: EmojiCategory.FACE, path: "/assets/face/耶.png" },
: { : {
name: "吃瓜", name: "吃瓜",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/吃瓜.png", path: "/assets/face/eat-melon.png",
}, },
: { : {
name: "加油", name: "加油",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/加油.png", path: "/assets/face/cheer-up.png",
}, },
: { name: "汗", category: EmojiCategory.FACE, path: "/assets/face/汗.png" }, : {
name: "汗",
category: EmojiCategory.FACE,
path: "/assets/face/sweat.png",
},
: { : {
name: "天啊", name: "天啊",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/天啊.png", path: "/assets/face/oh-my.png",
}, },
Emm: { Emm: {
name: "Emm", name: "Emm",
@@ -437,28 +477,32 @@ const EMOJI_DATA: Record<EmojiName, EmojiInfo> = {
: { : {
name: "社会社会", name: "社会社会",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/社会社会.png", path: "/assets/face/social.png",
}, },
: { : {
name: "旺柴", name: "旺柴",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/旺柴.png", path: "/assets/face/doge.png",
}, },
: { : {
name: "好的", name: "好的",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/好的.png", path: "/assets/face/good.png",
}, },
: { : {
name: "打脸", name: "打脸",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/打脸.png", path: "/assets/face/slap-face.png",
},
: {
name: "哇",
category: EmojiCategory.FACE,
path: "/assets/face/wow.png",
}, },
: { name: "哇", category: EmojiCategory.FACE, path: "/assets/face/哇.png" },
: { : {
name: "翻白眼", name: "翻白眼",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/翻白眼.png", path: "/assets/face/eye-roll.png",
}, },
"666": { "666": {
name: "666", name: "666",
@@ -468,54 +512,54 @@ const EMOJI_DATA: Record<EmojiName, EmojiInfo> = {
: { : {
name: "让我看看", name: "让我看看",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/让我看看.png", path: "/assets/face/let-me-see.png",
}, },
: { : {
name: "叹气", name: "叹气",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/叹气.png", path: "/assets/face/sigh.png",
}, },
: { : {
name: "苦涩", name: "苦涩",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/苦涩.png", path: "/assets/face/bitter.png",
}, },
: { : {
name: "裂开", name: "裂开",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/裂开.png", path: "/assets/face/crack.png",
}, },
: { : {
name: "奸笑", name: "奸笑",
category: EmojiCategory.FACE, category: EmojiCategory.FACE,
path: "/assets/face/奸笑.png", path: "/assets/face/sly-smile.png",
}, },
// 手势表情 // 手势表情
: { : {
name: "握手", name: "握手",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/握手.png", path: "/assets/gesture/handshake.png",
}, },
: { : {
name: "胜利", name: "胜利",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/胜利.png", path: "/assets/gesture/victory.png",
}, },
: { : {
name: "抱拳", name: "抱拳",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/抱拳.png", path: "/assets/gesture/fist-salute.png",
}, },
: { : {
name: "勾引", name: "勾引",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/勾引.png", path: "/assets/gesture/beckon.png",
}, },
: { : {
name: "拳头", name: "拳头",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/拳头.png", path: "/assets/gesture/fist.png",
}, },
OK: { OK: {
name: "OK", name: "OK",
@@ -525,148 +569,148 @@ const EMOJI_DATA: Record<EmojiName, EmojiInfo> = {
: { : {
name: "合十", name: "合十",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/合十.png", path: "/assets/gesture/pray.png",
}, },
: { : {
name: "强", name: "强",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/.png", path: "/assets/gesture/strong.png",
}, },
: { : {
name: "拥抱", name: "拥抱",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/拥抱.png", path: "/assets/gesture/hug.png",
}, },
: { : {
name: "弱", name: "弱",
category: EmojiCategory.GESTURE, category: EmojiCategory.GESTURE,
path: "/assets/gesture/.png", path: "/assets/gesture/weak.png",
}, },
// 动物表情 // 动物表情
: { : {
name: "猪头", name: "猪头",
category: EmojiCategory.ANIMAL, category: EmojiCategory.ANIMAL,
path: "/assets/animal/猪头.png", path: "/assets/animal/pig.png",
}, },
: { : {
name: "跳跳", name: "跳跳",
category: EmojiCategory.ANIMAL, category: EmojiCategory.ANIMAL,
path: "/assets/animal/跳跳.png", path: "/assets/animal/jump.png",
}, },
: { : {
name: "发抖", name: "发抖",
category: EmojiCategory.ANIMAL, category: EmojiCategory.ANIMAL,
path: "/assets/animal/发抖.png", path: "/assets/animal/tremble.png",
}, },
: { : {
name: "转圈", name: "转圈",
category: EmojiCategory.ANIMAL, category: EmojiCategory.ANIMAL,
path: "/assets/animal/转圈.png", path: "/assets/animal/circle.png",
}, },
// 祝福表情 // 祝福表情
: { : {
name: "庆祝", name: "庆祝",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/庆祝.png", path: "/assets/blessing/celebrate.png",
}, },
: { : {
name: "礼物", name: "礼物",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/礼物.png", path: "/assets/blessing/gift.png",
}, },
: { : {
name: "红包", name: "红包",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/红包.png", path: "/assets/blessing/red-envelope.png",
}, },
: { : {
name: "發", name: "發",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/.png", path: "/assets/blessing/get-rich.png",
}, },
: { : {
name: "福", name: "福",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/.png", path: "/assets/blessing/fortune.png",
}, },
: { : {
name: "烟花", name: "烟花",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/烟花.png", path: "/assets/blessing/fireworks.png",
}, },
: { : {
name: "爆竹", name: "爆竹",
category: EmojiCategory.BLESSING, category: EmojiCategory.BLESSING,
path: "/assets/blessing/爆竹.png", path: "/assets/blessing/firecrackers.png",
}, },
// 其他表情 // 其他表情
: { : {
name: "嘴唇", name: "嘴唇",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/嘴唇.png", path: "/assets/other/lips.png",
}, },
: { : {
name: "爱心", name: "爱心",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/爱心.png", path: "/assets/other/heart.png",
}, },
: { : {
name: "心碎", name: "心碎",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/心碎.png", path: "/assets/other/broken-heart.png",
}, },
: { : {
name: "啤酒", name: "啤酒",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/啤酒.png", path: "/assets/other/beer.png",
}, },
: { : {
name: "咖啡", name: "咖啡",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/咖啡.png", path: "/assets/other/coffee.png",
}, },
: { : {
name: "蛋糕", name: "蛋糕",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/蛋糕.png", path: "/assets/other/cake.png",
}, },
: { : {
name: "凋谢", name: "凋谢",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/凋谢.png", path: "/assets/other/wither.png",
}, },
: { : {
name: "菜刀", name: "菜刀",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/菜刀.png", path: "/assets/other/knife.png",
}, },
: { : {
name: "炸弹", name: "炸弹",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/炸弹.png", path: "/assets/other/bomb.png",
}, },
便便: { 便便: {
name: "便便", name: "便便",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/便便.png", path: "/assets/other/poop.png",
}, },
: { : {
name: "太阳", name: "太阳",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/太阳.png", path: "/assets/other/sun.png",
}, },
: { : {
name: "月亮", name: "月亮",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/月亮.png", path: "/assets/other/moon.png",
}, },
: { : {
name: "玫瑰", name: "玫瑰",
category: EmojiCategory.OTHER, category: EmojiCategory.OTHER,
path: "/assets/other/玫瑰.png", path: "/assets/other/rose.png",
}, },
}; };

View File

@@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
import { Form, Input, Button, Toast, Checkbox } from "antd-mobile"; import { Form, Input, Button, Toast, Checkbox } from "antd-mobile";
import { import {
EyeInvisibleOutline, EyeInvisibleOutline,
@@ -7,7 +6,6 @@ import {
UserOutline, UserOutline,
} from "antd-mobile-icons"; } from "antd-mobile-icons";
import { useUserStore } from "@/store/module/user"; import { useUserStore } from "@/store/module/user";
import { useWebSocketStore } from "@/store/module/websocket/websocket";
import { loginWithPassword, loginWithCode, sendVerificationCode } from "./api"; import { loginWithPassword, loginWithCode, sendVerificationCode } from "./api";
import style from "./login.module.scss"; import style from "./login.module.scss";
@@ -19,7 +17,6 @@ const Login: React.FC = () => {
const [countdown, setCountdown] = useState(0); const [countdown, setCountdown] = useState(0);
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [agreeToTerms, setAgreeToTerms] = useState(false); const [agreeToTerms, setAgreeToTerms] = useState(false);
const { setUserInfo } = useCkChatStore.getState();
const { login, login2 } = useUserStore(); const { login, login2 } = useUserStore();
// 倒计时效果 // 倒计时效果
@@ -75,13 +72,9 @@ const Login: React.FC = () => {
: loginWithCode(loginParams); : loginWithCode(loginParams);
response.then(res => { response.then(res => {
const { member, kefuData, deviceTotal } = res; const { member, deviceTotal } = res;
// 清空WebSocket连接状态 // 清空WebSocket连接状态
useWebSocketStore.getState().clearConnectionState();
login(res.token, member, deviceTotal); login(res.token, member, deviceTotal);
const { self, token } = kefuData;
login2(token.access_token);
setUserInfo(self);
}); });
}; };

View File

@@ -84,16 +84,6 @@ const Mine: React.FC = () => {
bgColor: "#fff7e6", bgColor: "#fff7e6",
iconColor: "#fa8c16", iconColor: "#fa8c16",
}, },
{
id: "ckb",
title: "触客宝",
description: "触客宝",
icon: <PhoneOutlined />,
count: 0,
path: "/ckbox/weChat",
bgColor: "#fff7e6",
iconColor: "#fa8c16",
},
]; ];
// 加载统计数据 // 加载统计数据

View File

@@ -784,12 +784,6 @@ const TrafficPoolDetail: React.FC = () => {
</div> </div>
)} )}
</Card> </Card>
{/* 添加新标签按钮 */}
<Button block color="primary" className={styles.addTagBtn}>
<TagOutlined />
&nbsp;
</Button>
</div> </div>
)} )}
</div> </div>

View File

@@ -1,43 +0,0 @@
//构建联系人列表标签
import { weChatGroupService, contractService } from "@/utils/db";
import { request } from "@/api/request2";
import { ContactGroupByLabel } from "@/pages/pc/ckbox/data";
export function WechatGroup(params) {
return request("/api/WechatGroup/list", params, "GET");
}
export const createContractList = async (
kfSelected: number,
countLables: ContactGroupByLabel[],
) => {
// 根据 groupType 决定查询不同的服务
const dataByLabels = [];
for (const label of countLables) {
let data;
if (label.groupType === 1) {
// groupType: 1, 查询 contractService
data = await contractService.findWhere("groupId", label.id);
// 过滤出 kfSelected 对应的联系人
if (kfSelected && kfSelected != 0) {
data = data.filter(contact => contact.wechatAccountId === kfSelected);
}
// console.log(`标签 ${label.groupName} 对应的联系人数据:`, data);
} else if (label.groupType === 2) {
// groupType: 2, 查询 weChatGroupService
data = await weChatGroupService.findWhere("groupId", label.id);
if (kfSelected && kfSelected != 0) {
data = data.filter(contact => contact.wechatAccountId === kfSelected);
}
} else {
console.warn(`未知的 groupType: ${label.groupType}`);
data = [];
}
dataByLabels.push({
...label,
contacts: data,
});
}
return dataByLabels;
};

View File

@@ -1,72 +0,0 @@
import {
ContractData,
KfUserListData,
CkAccount,
ContactGroupByLabel,
weChatGroup,
} from "@/pages/pc/ckbox/data";
// 权限片段接口
export interface PrivilegeFrag {
// 根据实际数据结构补充
[key: string]: any;
}
// 租户信息接口
export interface CkTenant {
id: number;
name: string;
guid: string;
thirdParty: string | null;
tenantType: number;
deployName: string;
}
// 触客宝用户信息接口
export interface CkUserInfo {
account: CkAccount;
privilegeFrags: PrivilegeFrag[];
tenant: CkTenant;
}
// 状态接口
export interface CkChatState {
userInfo: CkUserInfo | null;
isLoggedIn: boolean;
searchKeyword: string;
contractList: ContractData[];
chatSessions: any[];
kfUserList: KfUserListData[];
kfSelected: number;
getKfSelectedUser: () => KfUserListData | undefined;
countLables: ContactGroupByLabel[];
newContractList: ContactGroupByLabel[];
getContractList: () => ContractData[];
getSomeContractList: (kfSelected: number) => ContractData[];
getNewContractList: () => ContactGroupByLabel[];
setSearchKeyword: (keyword: string) => void;
clearSearchKeyword: () => void;
asyncKfSelected: (data: number) => void;
asyncWeChatGroup: (data: weChatGroup[]) => void;
asyncCountLables: (data: ContactGroupByLabel[]) => void;
getkfUserList: () => KfUserListData[];
asyncKfUserList: (data: KfUserListData[]) => void;
getKfUserInfo: (wechatAccountId: number) => KfUserListData | undefined;
asyncContractList: (data: ContractData[]) => void;
getChatSessions: () => any[];
asyncChatSessions: (data: any[]) => void;
updateChatSession: (session: ContractData | weChatGroup) => void;
deleteCtrlUser: (userId: number) => void;
updateCtrlUser: (user: KfUserListData) => void;
clearkfUserList: () => void;
addChatSession: (session: any) => void;
deleteChatSession: (sessionId: number) => void;
setUserInfo: (userInfo: CkUserInfo) => void;
clearUserInfo: () => void;
updateAccount: (account: Partial<CkAccount>) => void;
updateTenant: (tenant: Partial<CkTenant>) => void;
getAccountId: () => number | null;
getTenantId: () => number | null;
getAccountName: () => string | null;
getTenantName: () => string | null;
}

View File

@@ -1,527 +0,0 @@
import { createPersistStore } from "@/store/createPersistStore";
import { CkChatState, CkUserInfo, CkTenant } from "./ckchat.data";
import {
ContractData,
weChatGroup,
CkAccount,
KfUserListData,
ContactGroupByLabel,
} from "@/pages/pc/ckbox/data";
import { weChatGroupService, contractService } from "@/utils/db";
import { createContractList } from "@/store/module/ckchat/api";
import { useWeChatStore } from "@/store/module/weChat/weChat";
// 从weChat store获取clearCurrentContact方法
const getClearCurrentContact = () =>
useWeChatStore.getState().clearCurrentContact;
export const useCkChatStore = createPersistStore<CkChatState>(
set => ({
userInfo: null,
isLoggedIn: false,
contractList: [], //联系人列表
chatSessions: [], //聊天会话
kfUserList: [], //客服列表
countLables: [], //标签列表
newContractList: [], //联系人分组
kfSelected: 0, //选中的客服
searchKeyword: "", //搜索关键词
//客服列表
asyncKfUserList: async data => {
set({ kfUserList: data });
// await kfUserService.createManyWithServerId(data);
},
// 获取客服列表
getkfUserList: async () => {
const state = useCkChatStore.getState();
return state.kfUserList;
// return await kfUserService.findAll();
},
// 异步设置标签列表
asyncCountLables: async (data: ContactGroupByLabel[]) => {
set({ countLables: data });
// 清除getNewContractList缓存
const state = useCkChatStore.getState();
if (
state.getNewContractList &&
typeof state.getNewContractList === "function"
) {
// 触发缓存重新计算
await state.getNewContractList();
}
},
// 设置搜索关键词
setSearchKeyword: (keyword: string) => {
set({ searchKeyword: keyword });
},
// 清除搜索关键词
clearSearchKeyword: () => {
set({ searchKeyword: "" });
},
asyncKfSelected: async (data: number) => {
set({ kfSelected: data });
// 清除getChatSessions、getContractList和getNewContractList缓存
const state = useCkChatStore.getState();
if (
state.getChatSessions &&
typeof state.getChatSessions === "function"
) {
// 触发缓存重新计算
state.getChatSessions();
}
if (
state.getContractList &&
typeof state.getContractList === "function"
) {
// 触发缓存重新计算
state.getContractList();
}
if (
state.getNewContractList &&
typeof state.getNewContractList === "function"
) {
// 触发缓存重新计算
await state.getNewContractList();
}
},
// 获取联系人分组列表 - 使用缓存避免无限循环
getNewContractList: (() => {
let cachedResult: any = null;
let lastKfSelected: number | null = null;
let lastCountLablesLength: number = 0;
let lastSearchKeyword: string = "";
return async () => {
const state = useCkChatStore.getState();
// 检查是否需要重新计算缓存
const shouldRecalculate =
cachedResult === null ||
lastKfSelected !== state.kfSelected ||
lastCountLablesLength !== (state.countLables?.length || 0) ||
lastSearchKeyword !== state.searchKeyword;
if (shouldRecalculate) {
// 使用createContractList构建联系人分组数据
let contractList = await createContractList(
state.kfSelected,
state.countLables,
);
// 根据搜索关键词筛选联系人分组
if (state.searchKeyword.trim()) {
const keyword = state.searchKeyword.toLowerCase();
contractList = contractList
.map(group => ({
...group,
contracts:
group.contracts?.filter(item => {
const nickname = (item.nickname || "").toLowerCase();
const conRemark = (item.conRemark || "").toLowerCase();
return (
nickname.includes(keyword) || conRemark.includes(keyword)
);
}) || [],
}))
.filter(group => group.contracts.length > 0);
}
cachedResult = contractList;
lastKfSelected = state.kfSelected;
lastCountLablesLength = state.countLables?.length || 0;
lastSearchKeyword = state.searchKeyword;
}
return cachedResult;
};
})(),
// 搜索好友和群组的新方法 - 从本地数据库查询并返回扁平化的搜索结果
searchContactsAndGroups: (() => {
let cachedResult: (ContractData | weChatGroup)[] = [];
let lastKfSelected: number | null = null;
let lastSearchKeyword: string = "";
return async () => {
const state = useCkChatStore.getState();
// 检查是否需要重新计算缓存
const shouldRecalculate =
lastKfSelected !== state.kfSelected ||
lastSearchKeyword !== state.searchKeyword;
if (shouldRecalculate) {
if (state.searchKeyword.trim()) {
const keyword = state.searchKeyword.toLowerCase();
// 从本地数据库查询联系人数据
let allContacts: any[] = await contractService.findAll();
// 从本地数据库查询群组数据
let allGroups: any[] = await weChatGroupService.findAll();
// 根据选中的客服筛选联系人
if (state.kfSelected !== 0) {
allContacts = allContacts.filter(
item => item.wechatAccountId === state.kfSelected,
);
}
// 根据选中的客服筛选群组
if (state.kfSelected !== 0) {
allGroups = allGroups.filter(
item => item.wechatAccountId === state.kfSelected,
);
}
// 搜索匹配的联系人
const matchedContacts = allContacts.filter(item => {
const nickname = (item.nickname || "").toLowerCase();
const conRemark = (item.conRemark || "").toLowerCase();
return nickname.includes(keyword) || conRemark.includes(keyword);
});
// 搜索匹配的群组
const matchedGroups = allGroups.filter(item => {
const nickname = (item.nickname || "").toLowerCase();
const conRemark = (item.conRemark || "").toLowerCase();
return nickname.includes(keyword) || conRemark.includes(keyword);
});
// 合并搜索结果
cachedResult = [...matchedContacts, ...matchedGroups];
} else {
cachedResult = [];
}
lastKfSelected = state.kfSelected;
lastSearchKeyword = state.searchKeyword;
}
return cachedResult;
};
})(),
// 异步设置联系人分组列表
asyncNewContractList: async (data: any[]) => {
set({ newContractList: data });
// 清除getNewContractList缓存
const state = useCkChatStore.getState();
if (
state.getNewContractList &&
typeof state.getNewContractList === "function"
) {
// 触发缓存重新计算
await state.getNewContractList();
}
},
// 异步设置会话列表
asyncChatSessions: data => {
set({ chatSessions: data });
// 清除getChatSessions缓存
const state = useCkChatStore.getState();
if (
state.getChatSessions &&
typeof state.getChatSessions === "function"
) {
// 触发缓存重新计算
state.getChatSessions();
}
},
// 异步设置联系人列表
asyncContractList: async (data: ContractData[]) => {
set({ contractList: data });
await contractService.createManyWithServerId(data);
// 清除getContractList缓存
const state = useCkChatStore.getState();
if (
state.getContractList &&
typeof state.getContractList === "function"
) {
// 触发缓存重新计算
state.getContractList();
}
},
//获取特定联系人
getSomeContractList: (kfSelected: number) => {
const state = useCkChatStore.getState();
return state.contractList.filter(
item => item.wechatAccountId === kfSelected,
);
},
// 获取联系人列表 - 使用缓存避免无限循环
getContractList: (() => {
let cachedResult: any = null;
let lastKfSelected: number | null = null;
let lastContractListLength: number = 0;
let lastSearchKeyword: string = "";
return () => {
const state = useCkChatStore.getState();
// 检查是否需要重新计算缓存
const shouldRecalculate =
cachedResult === null ||
lastKfSelected !== state.kfSelected ||
lastContractListLength !== state.contractList.length ||
lastSearchKeyword !== state.searchKeyword;
if (shouldRecalculate) {
let filteredContracts = state.contractList;
// 根据客服筛选
if (state.kfSelected !== 0) {
filteredContracts = filteredContracts.filter(
item => item.wechatAccountId === state.kfSelected,
);
}
// 根据搜索关键词筛选
if (state.searchKeyword.trim()) {
const keyword = state.searchKeyword.toLowerCase();
filteredContracts = filteredContracts.filter(item => {
const nickname = (item.nickname || "").toLowerCase();
const conRemark = (item.conRemark || "").toLowerCase();
return nickname.includes(keyword) || conRemark.includes(keyword);
});
}
cachedResult = filteredContracts;
lastKfSelected = state.kfSelected;
lastContractListLength = state.contractList.length;
lastSearchKeyword = state.searchKeyword;
}
return cachedResult;
};
})(),
//异步设置联系人分组
asyncWeChatGroup: async (data: weChatGroup[]) => {
await weChatGroupService.createManyWithServerId(data);
},
//获取选中的客服信息
getKfSelectedUser: () => {
const state = useCkChatStore.getState();
return state.kfUserList.find(item => item.id === state.kfSelected);
},
getKfUserInfo: (wechatAccountId: number) => {
const state = useCkChatStore.getState();
return state.kfUserList.find(item => item.id === wechatAccountId);
},
// 删除控制终端用户
deleteCtrlUser: (userId: number) => {
set(state => ({
kfUserList: state.kfUserList.filter(item => item.id !== userId),
}));
},
// 更新控制终端用户
updateCtrlUser: (user: KfUserListData) => {
set(state => ({
kfUserList: state.kfUserList.map(item =>
item.id === user.id ? user : item,
),
}));
},
// 清空控制终端用户列表
clearkfUserList: () => {
set({ kfUserList: [] });
},
// 获取聊天会话 - 使用缓存避免无限循环
getChatSessions: (() => {
let cachedResult: any = null;
let lastKfSelected: number | null = null;
let lastChatSessionsLength: number = 0;
let lastSearchKeyword: string = "";
return () => {
const state = useCkChatStore.getState();
// 检查是否需要重新计算缓存
const shouldRecalculate =
cachedResult === null ||
lastKfSelected !== state.kfSelected ||
lastChatSessionsLength !== state.chatSessions.length ||
lastSearchKeyword !== state.searchKeyword;
if (shouldRecalculate) {
let filteredSessions = state.chatSessions;
// 根据客服筛选
if (state.kfSelected !== 0) {
filteredSessions = filteredSessions.filter(
item => item.wechatAccountId === state.kfSelected,
);
}
// 根据搜索关键词筛选
if (state.searchKeyword.trim()) {
const keyword = state.searchKeyword.toLowerCase();
filteredSessions = filteredSessions.filter(item => {
const nickname = (item.nickname || "").toLowerCase();
const conRemark = (item.conRemark || "").toLowerCase();
return nickname.includes(keyword) || conRemark.includes(keyword);
});
}
cachedResult = filteredSessions;
lastKfSelected = state.kfSelected;
lastChatSessionsLength = state.chatSessions.length;
lastSearchKeyword = state.searchKeyword;
}
return cachedResult;
};
})(),
// 添加聊天会话
addChatSession: (session: ContractData | weChatGroup) => {
set(state => {
// 检查是否已存在相同id的会话
const exists = state.chatSessions.some(item => item.id === session.id);
// 如果已存在则不添加,否则添加到列表中
return {
chatSessions: exists
? state.chatSessions
: [...state.chatSessions, session as ContractData | weChatGroup],
};
});
},
// 更新聊天会话
updateChatSession: (session: ContractData | weChatGroup) => {
set(state => ({
chatSessions: state.chatSessions.map(item =>
item.id === session.id ? { ...item, ...session } : item,
),
}));
},
// 删除聊天会话
deleteChatSession: (sessionId: number) => {
set(state => ({
chatSessions: state.chatSessions.filter(item => item.id !== sessionId),
}));
//当前选中的客户清空
getClearCurrentContact();
},
// 设置用户信息
setUserInfo: (userInfo: CkUserInfo) => {
set({ userInfo, isLoggedIn: true });
},
// 清除用户信息
clearUserInfo: () => {
set({ userInfo: null, isLoggedIn: false });
},
// 更新账户信息
updateAccount: (account: Partial<CkAccount>) => {
set(state => ({
userInfo: state.userInfo
? {
...state.userInfo,
account: { ...state.userInfo.account, ...account },
}
: null,
}));
},
// 更新租户信息
updateTenant: (tenant: Partial<CkTenant>) => {
set(state => ({
userInfo: state.userInfo
? {
...state.userInfo,
tenant: { ...state.userInfo.tenant, ...tenant },
}
: null,
}));
},
// 获取账户ID
getAccountId: () => {
const state = useCkChatStore.getState();
return Number(state.userInfo?.account?.id) || null;
},
// 获取租户ID
getTenantId: () => {
const state = useCkChatStore.getState();
return state.userInfo?.tenant?.id || null;
},
// 获取账户名称
getAccountName: () => {
const state = useCkChatStore.getState();
return (
state.userInfo?.account?.realName ||
state.userInfo?.account?.userName ||
null
);
},
// 获取租户名称
getTenantName: () => {
const state = useCkChatStore.getState();
return state.userInfo?.tenant?.name || null;
},
}),
{
name: "ckchat-store",
partialize: state => ({
userInfo: state.userInfo,
isLoggedIn: state.isLoggedIn,
kfUserList: state.kfUserList,
}),
onRehydrateStorage: () => state => {
// console.log("CkChat store hydrated:", state);
},
},
);
// 导出便捷的获取方法
export const getCkAccountId = () => useCkChatStore.getState().getAccountId();
export const getCkTenantId = () => useCkChatStore.getState().getTenantId();
export const getCkAccountName = () =>
useCkChatStore.getState().getAccountName();
export const getCkTenantName = () => useCkChatStore.getState().getTenantName();
export const getChatSessions = () =>
useCkChatStore.getState().getChatSessions();
export const addChatSession = (session: ContractData | weChatGroup) =>
useCkChatStore.getState().addChatSession(session);
export const updateChatSession = (session: ContractData | weChatGroup) =>
useCkChatStore.getState().updateChatSession(session);
export const deleteChatSession = (sessionId: string) =>
useCkChatStore.getState().deleteChatSession(sessionId);
export const getkfUserList = () => useCkChatStore.getState().kfUserList;
export const addCtrlUser = (user: KfUserListData) =>
useCkChatStore.getState().addCtrlUser(user);
export const deleteCtrlUser = (userId: number) =>
useCkChatStore.getState().deleteCtrlUser(userId);
export const updateCtrlUser = (user: KfUserListData) =>
useCkChatStore.getState().updateCtrlUser(user);
export const asyncKfUserList = (data: KfUserListData[]) =>
useCkChatStore.getState().asyncKfUserList(data);
export const asyncContractList = (data: ContractData[]) =>
useCkChatStore.getState().asyncContractList(data);
export const asyncChatSessions = (data: ContractData[]) =>
useCkChatStore.getState().asyncChatSessions(data);
export const asyncKfSelected = (data: number) =>
useCkChatStore.getState().asyncKfSelected(data);
export const asyncWeChatGroup = (data: weChatGroup[]) =>
useCkChatStore.getState().asyncWeChatGroup(data);
export const getKfSelectedUser = () =>
useCkChatStore.getState().getKfSelectedUser();
export const getKfUserInfo = (wechatAccountId: number) =>
useCkChatStore.getState().getKfUserInfo(wechatAccountId);
export const getContractList = () =>
useCkChatStore.getState().getContractList();
export const getNewContractList = () =>
useCkChatStore.getState().getNewContractList();
export const asyncCountLables = (data: ContactGroupByLabel[]) =>
useCkChatStore.getState().asyncCountLables(data);
export const asyncNewContractList = (data: any[]) =>
useCkChatStore.getState().asyncNewContractList(data);
export const getCountLables = () => useCkChatStore.getState().countLables;
export const setSearchKeyword = (keyword: string) =>
useCkChatStore.getState().setSearchKeyword(keyword);
export const clearSearchKeyword = () =>
useCkChatStore.getState().clearSearchKeyword();
export const searchContactsAndGroups = () =>
useCkChatStore.getState().searchContactsAndGroups();
useCkChatStore.getState().getKfSelectedUser();

View File

@@ -1,33 +0,0 @@
import { ChatRecord, ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
// 微信聊天相关的类型定义
export interface WeChatState {
// 当前选中的联系人/群组
currentContract: ContractData | weChatGroup | null;
// 当前聊天用户的消息列表(只存储当前聊天用户的消息)
currentMessages: ChatRecord[];
// 清空当前联系人
clearCurrentContact: () => void;
// 消息加载状态
messagesLoading: boolean;
isLoadingData: boolean;
currentGroupMembers: any[];
// Actions
setCurrentContact: (
contract: ContractData | weChatGroup,
isExist?: boolean,
) => void;
loadChatMessages: (Init: boolean, To?: number) => Promise<void>;
SearchMessage: (params: {
From: number;
To: number;
keyword: string;
Count?: number;
}) => Promise<void>;
// 视频消息处理方法
setVideoLoading: (messageId: number, isLoading: boolean) => void;
setVideoUrl: (messageId: number, videoUrl: string) => void;
addMessage: (message: ChatRecord) => void;
receivedMsg: (message: ChatRecord) => void;
}

View File

@@ -1,287 +0,0 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
import {
getChatMessages,
getChatroomMessages,
getGroupMembers,
} from "@/pages/pc/ckbox/api";
import { WeChatState } from "./weChat.data";
import { clearUnreadCount, updateConfig } from "@/pages/pc/ckbox/api";
import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
import { weChatGroupService, contractService } from "@/utils/db";
import {
addChatSession,
updateChatSession,
useCkChatStore,
} from "@/store/module/ckchat/ckchat";
export const useWeChatStore = create<WeChatState>()(
persist(
(set, get) => ({
// 初始状态
currentContract: null,
currentMessages: [],
messagesLoading: false,
isLoadingData: false,
currentGroupMembers: [],
//清空当前联系人
clearCurrentContact: () => {
set({ currentContract: null, currentMessages: [] });
},
// Actions
setCurrentContact: (
contract: ContractData | weChatGroup,
isExist?: boolean,
) => {
const state = useWeChatStore.getState();
// 切换联系人时清空当前消息,等待重新加载
set({ currentMessages: [] });
clearUnreadCount([contract.id]).then(() => {
if (isExist) {
updateChatSession({ ...contract, unreadCount: 0 });
} else {
addChatSession(contract);
}
set({ currentContract: contract });
updateConfig({
id: contract.id,
config: { chat: true },
});
state.loadChatMessages(true, 4704624000000);
});
},
loadChatMessages: async (Init: boolean, To?: number) => {
const state = useWeChatStore.getState();
const contact = state.currentContract;
set({ messagesLoading: true });
set({ isLoadingData: Init });
try {
const params: any = {
wechatAccountId: contact.wechatAccountId,
From: 1,
To: To || +new Date(),
Count: 5,
olderData: true,
};
if ("chatroomId" in contact && contact.chatroomId) {
params.wechatChatroomId = contact.id;
const messages = await getChatroomMessages(params);
const currentGroupMembers = await getGroupMembers({
id: contact.id,
});
if (Init) {
set({ currentMessages: messages || [], currentGroupMembers });
} else {
set({
currentMessages: [
...(messages || []),
...state.currentMessages,
],
});
}
} else {
params.wechatFriendId = contact.id;
const messages = await getChatMessages(params);
if (Init) {
set({ currentMessages: messages || [] });
} else {
set({
currentMessages: [
...(messages || []),
...state.currentMessages,
],
});
}
}
set({ messagesLoading: false });
} catch (error) {
console.error("获取聊天消息失败:", error);
} finally {
set({ messagesLoading: false });
}
},
SearchMessage: async ({
From = 1,
To = 4704624000000,
keyword = "",
Count = 20,
}: {
From: number;
To: number;
keyword: string;
Count?: number;
}) => {
const state = useWeChatStore.getState();
const contact = state.currentContract;
set({ messagesLoading: true });
try {
const params: any = {
wechatAccountId: contact.wechatAccountId,
From,
To,
keyword,
Count,
olderData: true,
};
if ("chatroomId" in contact && contact.chatroomId) {
params.wechatChatroomId = contact.id;
const messages = await getChatroomMessages(params);
const currentGroupMembers = await getGroupMembers({
id: contact.id,
});
set({ currentMessages: messages || [], currentGroupMembers });
} else {
params.wechatFriendId = contact.id;
const messages = await getChatMessages(params);
set({ currentMessages: messages || [] });
}
set({ messagesLoading: false });
} catch (error) {
console.error("获取聊天消息失败:", error);
} finally {
set({ messagesLoading: false });
}
},
setMessageLoading: loading => {
set({ messagesLoading: Boolean(loading) });
},
addMessage: message => {
set(state => ({
currentMessages: [...state.currentMessages, message],
}));
},
receivedMsg: async message => {
const currentContract = useWeChatStore.getState().currentContract;
//判断群还是好友
const getMessageId =
message?.wechatChatroomId || message.wechatFriendId;
const isWechatGroup = message?.wechatChatroomId;
//当前选中聊天的群或好友
if (currentContract && currentContract.id == getMessageId) {
set(state => ({
currentMessages: [...state.currentMessages, message],
}));
} else {
//更新消息列表unread数值根据接收的++1 这样
const chatSessions = useCkChatStore.getState().chatSessions;
const session = chatSessions.find(item => item.id == getMessageId);
if (session) {
session.unreadCount = Number(session.unreadCount) + 1;
updateChatSession(session);
} else {
if (isWechatGroup) {
const [group] = await weChatGroupService.findByIds(getMessageId);
if (group) {
addChatSession({
...group,
unreadCount: 1,
});
}
} else {
const [user] = await contractService.findByIds(getMessageId);
addChatSession({
...user,
unreadCount: 1,
});
}
}
}
},
updateMessage: (messageId, updates) => {
set(state => ({
currentMessages: state.currentMessages.map(msg =>
msg.id === messageId ? { ...msg, ...updates } : msg,
),
}));
},
// 便捷选择器
getCurrentContact: () => get().currentContract,
getCurrentMessages: () => get().currentMessages,
getMessagesLoading: () => get().messagesLoading,
// 视频消息处理方法
setVideoLoading: (messageId: number, isLoading: boolean) => {
set(state => ({
currentMessages: state.currentMessages.map(msg => {
if (msg.id === messageId) {
try {
const content = JSON.parse(msg.content);
// 更新加载状态
const updatedContent = { ...content, isLoading };
return {
...msg,
content: JSON.stringify(updatedContent),
};
} catch (e) {
console.error("更新视频加载状态失败:", e);
return msg;
}
}
return msg;
}),
}));
},
setVideoUrl: (messageId: number, videoUrl: string) => {
set(state => ({
currentMessages: state.currentMessages.map(msg => {
if (msg.id === messageId) {
try {
const content = JSON.parse(msg.content);
// 检查视频是否已经下载完毕,避免重复更新
if (content.videoUrl && content.videoUrl === videoUrl) {
console.log("视频已下载,跳过重复更新:", messageId);
return msg;
}
// 设置视频URL并清除加载状态
const updatedContent = {
...content,
videoUrl,
isLoading: false,
};
return {
...msg,
content: JSON.stringify(updatedContent),
};
} catch (e) {
console.error("更新视频URL失败:", e);
return msg;
}
}
return msg;
}),
}));
},
clearAllData: () => {
set({
currentContract: null,
currentMessages: [],
messagesLoading: false,
});
},
}),
{
name: "wechat-storage",
partialize: state => ({
// currentContract 不做持久化,登录和页面刷新时直接清空
}),
},
),
);
// 导出便捷的选择器函数
export const useCurrentContact = () =>
useWeChatStore(state => state.currentContract);
export const useCurrentMessages = () =>
useWeChatStore(state => state.currentMessages);
export const useMessagesLoading = () =>
useWeChatStore(state => state.messagesLoading);

View File

@@ -1,7 +0,0 @@
import { ChatRecord } from "@/pages/pc/ckbox/data";
export interface Messages {
friendMessage?: ChatRecord | null;
chatroomMessage?: ChatRecord | null;
seq: number;
cmdType: string;
}

View File

@@ -1,117 +0,0 @@
//消息管理器
import { deepCopy } from "@/utils/common";
import { WebSocketMessage } from "./websocket";
import { getkfUserList, asyncKfUserList } from "@/store/module/ckchat/ckchat";
import { Messages } from "./msg.data";
import { useWeChatStore } from "@/store/module/weChat/weChat";
// 消息处理器类型定义
type MessageHandler = (message: WebSocketMessage) => void;
const setVideoUrl = useWeChatStore.getState().setVideoUrl;
const addMessage = useWeChatStore.getState().addMessage;
const receivedMsg = useWeChatStore.getState().receivedMsg;
// 消息处理器映射
const messageHandlers: Record<string, MessageHandler> = {
// 微信账号存活状态响应
CmdRequestWechatAccountsAliveStatusResp: message => {
// console.log("微信账号存活状态响应", message);
// 获取客服列表
const kfUserList = deepCopy(getkfUserList());
const wechatAccountsAliveStatus = message.wechatAccountsAliveStatus || {};
// 遍历客服列表,更新存活状态
kfUserList.forEach(kfUser => {
kfUser.isOnline = wechatAccountsAliveStatus[kfUser.id];
});
asyncKfUserList(kfUserList);
},
// 发送消息响应
CmdSendMessageResp: message => {
console.log("发送消息响应", message);
addMessage(message.friendMessage || message.chatroomMessage);
// 在这里添加具体的处理逻辑
},
CmdSendMessageResult: message => {
console.log("发送消息结果", message);
// 在这里添加具体的处理逻辑
},
// 接收消息响应
CmdReceiveMessageResp: message => {
console.log("接收消息响应", message);
addMessage(message.friendMessage || message.chatroomMessage);
// 在这里添加具体的处理逻辑
},
//收到消息
CmdNewMessage: (message: Messages) => {
// 在这里添加具体的处理逻辑
receivedMsg(message.friendMessage || message.chatroomMessage);
},
CmdFriendInfoChanged: message => {
// console.log("好友信息变更", message);
// 在这里添加具体的处理逻辑
},
// 登录响应
CmdSignInResp: message => {
console.log("登录响应", message);
// 在这里添加具体的处理逻辑
},
// 通知消息
CmdNotify: message => {
console.log("通知消息", message);
// 在这里添加具体的处理逻辑
if (message.notify == "Kicked out") {
// 被踢出时直接跳转到登录页面
window.location.href = "/login";
}
},
CmdDownloadVideoResult: message => {
// 在这里添加具体的处理逻辑
setVideoUrl(message.friendMessageId, message.url);
},
// 可以继续添加更多处理器...
};
// 默认处理器
const defaultHandler: MessageHandler = message => {
console.log("未知消息类型", message.cmdType, message);
};
// 注册新的消息处理器
export const registerMessageHandler = (
cmdType: string,
handler: MessageHandler,
) => {
messageHandlers[cmdType] = handler;
};
// 移除消息处理器
export const unregisterMessageHandler = (cmdType: string) => {
delete messageHandlers[cmdType];
};
// 获取所有已注册的消息类型
export const getRegisteredMessageTypes = (): string[] => {
return Object.keys(messageHandlers);
};
// 消息管理核心函数
export const msgManageCore = (message: WebSocketMessage) => {
const cmdType = message.cmdType;
if (!cmdType) {
console.warn("消息缺少cmdType字段", message);
return;
}
// 获取对应的处理器,如果没有则使用默认处理器
const handler = messageHandlers[cmdType] || defaultHandler;
try {
handler(message);
} catch (error) {
console.error(`处理消息类型 ${cmdType} 时发生错误:`, error);
}
};

View File

@@ -1,586 +0,0 @@
import { createPersistStore } from "@/store/createPersistStore";
import { Toast } from "antd-mobile";
import { useUserStore } from "../user";
import { useCkChatStore } from "@/store/module/ckchat/ckchat";
const { getAccountId } = useCkChatStore.getState();
import { msgManageCore } from "./msgManage";
// WebSocket消息类型
export interface WebSocketMessage {
cmdType?: string;
seq?: number;
wechatAccountIds?: string[];
content?: any;
[key: string]: any;
}
// WebSocket连接状态
export enum WebSocketStatus {
DISCONNECTED = "disconnected",
CONNECTING = "connecting",
CONNECTED = "connected",
RECONNECTING = "reconnecting",
ERROR = "error",
}
// WebSocket配置
interface WebSocketConfig {
url: string;
client: string;
accountId: number;
accessToken: string;
autoReconnect: boolean;
cmdType: string;
seq: number;
reconnectInterval: number;
maxReconnectAttempts: number;
[key: string]: any;
}
interface WebSocketState {
// 连接状态
status: WebSocketStatus;
ws: WebSocket | null;
// 配置信息
config: WebSocketConfig | null;
// 消息相关
messages: WebSocketMessage[];
unreadCount: number;
// 重连相关
reconnectAttempts: number;
reconnectTimer: NodeJS.Timeout | null;
aliveStatusTimer: NodeJS.Timeout | null; // 客服用户状态查询定时器
// 方法
connect: (config: Partial<WebSocketConfig>) => void;
disconnect: () => void;
sendMessage: (message: Omit<WebSocketMessage, "id" | "timestamp">) => void;
sendCommand: (cmdType: string, data?: any) => void;
clearMessages: () => void;
markAsRead: () => void;
reconnect: () => void;
clearConnectionState: () => void; // 清空连接状态
// 内部方法
_handleOpen: () => void;
_handleMessage: (event: MessageEvent) => void;
_handleClose: (event: CloseEvent) => void;
_handleError: (event: Event) => void;
_startReconnectTimer: () => void;
_stopReconnectTimer: () => void;
_startAliveStatusTimer: () => void; // 启动客服状态查询定时器
_stopAliveStatusTimer: () => void; // 停止客服状态查询定时器
}
// 默认配置
const DEFAULT_CONFIG: WebSocketConfig = {
url: "wss://kf.quwanzhi.com:9993",
client: "kefu-client",
accountId: 0,
accessToken: "",
autoReconnect: true,
cmdType: "", // 添加默认的命令类型
seq: +new Date(), // 添加默认的序列号
reconnectInterval: 3000,
maxReconnectAttempts: 5,
};
export const useWebSocketStore = createPersistStore<WebSocketState>(
(set, get) => ({
status: WebSocketStatus.DISCONNECTED,
ws: null,
config: null,
messages: [],
unreadCount: 0,
reconnectAttempts: 0,
reconnectTimer: null,
aliveStatusTimer: null,
// 连接WebSocket
connect: (config: Partial<WebSocketConfig>) => {
const currentState = get();
// 检查当前连接状态,避免重复连接
if (
currentState.status === WebSocketStatus.CONNECTED ||
currentState.status === WebSocketStatus.CONNECTING
) {
// console.log("WebSocket已连接或正在连接跳过重复连接", {
// currentStatus: currentState.status,
// hasWebSocket: !!currentState.ws,
// });
return;
}
// 如果已经有WebSocket实例先断开
if (currentState.ws) {
// console.log("断开现有WebSocket连接");
currentState.disconnect();
}
// 合并配置
const fullConfig: WebSocketConfig = {
...DEFAULT_CONFIG,
...config,
};
// 获取用户信息
const { token2 } = useUserStore.getState();
if (!token2) {
Toast.show({ content: "未找到有效的访问令牌", position: "top" });
return;
}
// 构建WebSocket URL
const params = new URLSearchParams({
client: fullConfig.client.toString(),
accountId: getAccountId().toString(),
accessToken: token2,
t: Date.now().toString(),
});
const wsUrl = fullConfig.url + "?" + params;
// 检查URL是否为localhost如果是则不连接
if (wsUrl.includes("localhost") || wsUrl.includes("127.0.0.1")) {
// console.error("WebSocket连接被拦截不允许连接到本地地址", wsUrl);
Toast.show({
content: "WebSocket连接被拦截不允许连接到本地地址",
position: "top",
});
set({ status: WebSocketStatus.ERROR });
return;
}
set({
status: WebSocketStatus.CONNECTING,
config: fullConfig,
});
try {
const ws = new WebSocket(wsUrl);
// 绑定事件处理器
ws.onopen = () => get()._handleOpen();
ws.onmessage = event => get()._handleMessage(event);
ws.onclose = event => get()._handleClose(event);
ws.onerror = event => get()._handleError(event);
set({ ws });
// console.log("WebSocket连接创建成功", wsUrl);
} catch (error) {
// console.error("WebSocket连接失败:", error);
set({ status: WebSocketStatus.ERROR });
Toast.show({ content: "WebSocket连接失败", position: "top" });
}
},
// 断开连接
disconnect: () => {
const currentState = get();
if (currentState.ws) {
currentState.ws.close();
}
currentState._stopReconnectTimer();
currentState._stopAliveStatusTimer();
set({
status: WebSocketStatus.DISCONNECTED,
ws: null,
reconnectAttempts: 0,
});
// console.log("WebSocket连接已断开");
},
// 发送消息
sendMessage: message => {
const currentState = get();
if (
currentState.status !== WebSocketStatus.CONNECTED ||
!currentState.ws
) {
Toast.show({ content: "WebSocket未连接", position: "top" });
return;
}
const fullMessage: WebSocketMessage = {
...message,
};
try {
currentState.ws.send(JSON.stringify(fullMessage));
// console.log("消息发送成功:", fullMessage);
} catch (error) {
// console.error("消息发送失败:", error);
Toast.show({ content: "消息发送失败", position: "top" });
}
},
// 发送命令
sendCommand: (cmdType: string, data?: any) => {
const currentState = get();
if (
currentState.status !== WebSocketStatus.CONNECTED ||
!currentState.ws
) {
Toast.show({
content: "WebSocket未连接正在重新连接...",
position: "top",
});
// 重置连接状态并发起重新连接
set({ status: WebSocketStatus.DISCONNECTED });
if (currentState.config) {
currentState.connect(currentState.config);
}
return;
}
const command = {
cmdType,
...data,
seq: +new Date(),
};
try {
currentState.ws.send(JSON.stringify(command));
// console.log("命令发送成功:", command);
} catch (error) {
// console.error("命令发送失败:", error);
Toast.show({ content: "命令发送失败", position: "top" });
// 发送失败时也尝试重新连接
set({ status: WebSocketStatus.DISCONNECTED });
if (currentState.config) {
currentState.connect(currentState.config);
}
}
},
// 清除消息
clearMessages: () => {
set({ messages: [], unreadCount: 0 });
},
// 标记为已读
markAsRead: () => {
set({ unreadCount: 0 });
},
// 重连
reconnect: () => {
const currentState = get();
if (currentState.config) {
// 检查是否允许重连
if (!currentState.config.autoReconnect) {
// console.log("自动重连已禁用,不再尝试重连");
return;
}
currentState.connect(currentState.config);
}
},
// 清空连接状态(用于退出登录时)
clearConnectionState: () => {
const currentState = get();
// 断开现有连接
if (currentState.ws) {
currentState.ws.close();
}
// 停止所有定时器
currentState._stopReconnectTimer();
currentState._stopAliveStatusTimer();
// 重置所有状态
set({
status: WebSocketStatus.DISCONNECTED,
ws: null,
config: null,
messages: [],
unreadCount: 0,
reconnectAttempts: 0,
reconnectTimer: null,
aliveStatusTimer: null,
});
// console.log("WebSocket连接状态已清空");
},
// 内部方法:处理连接打开
_handleOpen: () => {
const currentState = get();
set({
status: WebSocketStatus.CONNECTED,
reconnectAttempts: 0,
});
// console.log("WebSocket连接成功");
const { token2 } = useUserStore.getState();
// 发送登录命令
if (currentState.config) {
currentState.sendCommand("CmdSignIn", {
accessToken: token2,
accountId: Number(getAccountId()),
client: currentState.config?.client || "kefu-client",
seq: +new Date(),
});
}
Toast.show({ content: "WebSocket连接成功", position: "top" });
// 启动客服状态查询定时器
currentState._startAliveStatusTimer();
},
// 内部方法:处理消息接收
_handleMessage: (event: MessageEvent) => {
try {
const data = JSON.parse(event.data);
// console.log("收到WebSocket消息:", data);
// 处理特定的通知消息
if (data.cmdType === "CmdNotify") {
// 处理Auth failed通知
if (data.notify === "Auth failed" || data.notify === "Kicked out") {
// console.error(`WebSocket ${data.notify},断开连接`);
Toast.show({
content: `WebSocket ${data.notify},断开连接`,
position: "top",
});
// 禁用自动重连
if (get().config) {
set({
config: {
...get().config!,
autoReconnect: false,
},
});
}
// 停止客服状态查询定时器
get()._stopAliveStatusTimer();
// 断开连接
get().disconnect();
return;
}
}
const currentState = get();
const newMessage: WebSocketMessage = {
id: Date.now().toString(),
type: data.type || "message",
content: data,
timestamp: Date.now(),
sender: data.sender,
receiver: data.receiver,
};
set({
messages: [...currentState.messages, newMessage],
unreadCount: currentState.unreadCount + 1,
});
//消息处理器
msgManageCore(data);
// 可以在这里添加消息处理逻辑
// 比如播放提示音、显示通知等
} catch (error) {
// console.error("解析WebSocket消息失败:", error);
}
},
// 内部方法:处理连接关闭
_handleClose: (event: CloseEvent) => {
const currentState = get();
// console.log("WebSocket连接关闭:", event.code, event.reason);
set({
status: WebSocketStatus.DISCONNECTED,
ws: null,
});
// 自动重连逻辑
if (
currentState.config?.autoReconnect &&
currentState.reconnectAttempts <
(currentState.config?.maxReconnectAttempts || 5)
) {
// console.log("尝试自动重连...");
currentState._startReconnectTimer();
} else if (!currentState.config?.autoReconnect) {
// console.log("自动重连已禁用,不再尝试重连");
// 重置重连计数
set({ reconnectAttempts: 0 });
}
},
// 内部方法:处理连接错误
_handleError: (event: Event) => {
// console.error("WebSocket连接错误:", event);
set({ status: WebSocketStatus.ERROR });
Toast.show({ content: "WebSocket连接错误", position: "top" });
},
// 内部方法:启动重连定时器
_startReconnectTimer: () => {
const currentState = get();
currentState._stopReconnectTimer();
set({
status: WebSocketStatus.RECONNECTING,
reconnectAttempts: currentState.reconnectAttempts + 1,
});
const timer = setTimeout(() => {
// console.log(
// `尝试重连 (${currentState.reconnectAttempts + 1}/${currentState.config?.maxReconnectAttempts})`,
// );
currentState.reconnect();
}, currentState.config?.reconnectInterval || 3000);
set({ reconnectTimer: timer });
},
// 内部方法:停止重连定时器
_stopReconnectTimer: () => {
const currentState = get();
if (currentState.reconnectTimer) {
clearTimeout(currentState.reconnectTimer);
set({ reconnectTimer: null });
}
},
// 内部方法:启动客服状态查询定时器
_startAliveStatusTimer: () => {
const currentState = get();
// 先停止现有定时器
currentState._stopAliveStatusTimer();
// 获取客服用户列表
const { kfUserList } = useCkChatStore.getState();
// 如果没有客服用户,不启动定时器
if (!kfUserList || kfUserList.length === 0) {
return;
}
// 启动定时器每5秒查询一次
const timer = setInterval(() => {
const state = get();
// 检查连接状态
if (state.status === WebSocketStatus.CONNECTED) {
const { kfUserList: currentKfUserList } = useCkChatStore.getState();
if (currentKfUserList && currentKfUserList.length > 0) {
state.sendCommand("CmdRequestWechatAccountsAliveStatus", {
wechatAccountIds: currentKfUserList.map(v => v.id),
});
}
} else {
// 如果连接断开,停止定时器
state._stopAliveStatusTimer();
}
}, 5 * 1000);
set({ aliveStatusTimer: timer });
},
// 内部方法:停止客服状态查询定时器
_stopAliveStatusTimer: () => {
const currentState = get();
if (currentState.aliveStatusTimer) {
clearInterval(currentState.aliveStatusTimer);
set({ aliveStatusTimer: null });
}
},
}),
{
name: "websocket-store",
partialize: state => ({
// 只持久化必要的状态不持久化WebSocket实例
status: state.status,
config: state.config,
messages: state.messages.slice(-100), // 只保留最近100条消息
unreadCount: state.unreadCount,
reconnectAttempts: state.reconnectAttempts,
// 注意:定时器不需要持久化,重新连接时会重新创建
}),
onRehydrateStorage: () => state => {
// 页面刷新后,如果之前是连接状态,尝试重新连接
if (state && state.status === WebSocketStatus.CONNECTED && state.config) {
// console.log("页面刷新后恢复WebSocket连接", {
// persistedConfig: state.config,
// currentDefaultConfig: DEFAULT_CONFIG,
// });
// 使用最新的默认配置,而不是持久化的配置
const freshConfig = {
...DEFAULT_CONFIG,
client: state.config.client,
accountId: state.config.accountId,
accessToken: state.config.accessToken,
autoReconnect: state.config.autoReconnect,
};
// console.log("使用刷新后的配置重连:", freshConfig);
// 延迟一下再重连,确保页面完全加载
// 同时检查当前状态,避免重复连接
setTimeout(() => {
// 重新获取最新的状态而不是使用闭包中的state
const currentState = useWebSocketStore.getState();
// console.log("页面刷新后检查状态", {
// status: currentState.status,
// hasWs: !!currentState.ws,
// });
// 强制重置状态为disconnected因为页面刷新后WebSocket实例已失效
if (
currentState.status === WebSocketStatus.CONNECTED &&
!currentState.ws
) {
// console.log("检测到状态不一致重置为disconnected");
useWebSocketStore.setState({
status: WebSocketStatus.DISCONNECTED,
});
}
// 重新获取状态进行连接
const latestState = useWebSocketStore.getState();
if (
latestState.status === WebSocketStatus.DISCONNECTED ||
latestState.status === WebSocketStatus.ERROR
) {
// console.log("页面刷新后开始重连");
latestState.connect(freshConfig);
} else {
// console.log("WebSocket已连接或正在连接跳过页面刷新重连", {
// status: latestState.status,
// });
}
}, 1000);
}
},
},
);

View File

@@ -0,0 +1,121 @@
{
"face": {
"微笑": "smile",
"撇嘴": "pout",
"色": "lust",
"发呆": "daze",
"得意": "proud",
"流泪": "cry",
"害羞": "shy",
"闭嘴": "shut-up",
"睡": "sleep",
"大哭": "sob",
"尴尬": "awkward",
"发怒": "angry",
"调皮": "naughty",
"呲牙": "grin",
"惊讶": "surprised",
"难过": "sad",
"囧": "embarrassed",
"抓狂": "crazy",
"吐": "vomit",
"偷笑": "snicker",
"愉快": "happy",
"白眼": "roll-eyes",
"傲慢": "arrogant",
"困": "sleepy",
"惊恐": "panic",
"憨笑": "silly-smile",
"悠闲": "relaxed",
"咒骂": "curse",
"疑问": "question",
"嘘": "shush",
"晕": "dizzy",
"衰": "unlucky",
"骷髅": "skull",
"敲打": "knock",
"再见": "goodbye",
"擦汗": "wipe-sweat",
"抠鼻": "pick-nose",
"鼓掌": "clap",
"坏笑": "evil-smile",
"右哼哼": "right-hum",
"鄙视": "despise",
"委屈": "wronged",
"快哭了": "about-to-cry",
"阴险": "sinister",
"亲亲": "kiss",
"可怜": "pitiful",
"笑脸": "smiley",
"生病": "sick",
"脸红": "blush",
"破涕为笑": "smile-through-tears",
"恐惧": "fear",
"失望": "disappointed",
"无语": "speechless",
"嘿哈": "hey-ha",
"捂脸": "facepalm",
"机智": "smart",
"皱眉": "frown",
"耶": "yeah",
"吃瓜": "eat-melon",
"加油": "cheer-up",
"汗": "sweat",
"天啊": "oh-my-god",
"Emm": "emm",
"社会社会": "social",
"旺柴": "doge",
"好的": "ok",
"打脸": "slap-face",
"哇": "wow",
"翻白眼": "eye-roll",
"666": "666",
"让我看看": "let-me-see",
"叹气": "sigh",
"苦涩": "bitter",
"裂开": "crack",
"奸笑": "wicked-smile"
},
"gesture": {
"握手": "handshake",
"胜利": "victory",
"抱拳": "fist-salute",
"勾引": "beckon",
"拳头": "fist",
"OK": "ok",
"合十": "pray",
"强": "strong",
"拥抱": "hug",
"弱": "weak"
},
"animal": {
"猪头": "pig-head",
"跳跳": "jump",
"发抖": "shiver",
"转圈": "spin"
},
"blessing": {
"庆祝": "celebrate",
"礼物": "gift",
"红包": "red-envelope",
"發": "fortune",
"福": "blessing",
"烟花": "fireworks",
"爆竹": "firecrackers"
},
"other": {
"嘴唇": "lips",
"爱心": "heart",
"心碎": "broken-heart",
"啤酒": "beer",
"咖啡": "coffee",
"蛋糕": "cake",
"凋谢": "wither",
"菜刀": "knife",
"炸弹": "bomb",
"便便": "poop",
"太阳": "sun",
"月亮": "moon",
"玫瑰": "rose"
}
}

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Some files were not shown because too many files have changed in this diff Show More