2023-11-25 00:40:09 +08:00
|
|
|
|
import csv
|
2023-11-28 21:30:56 +08:00
|
|
|
|
import html
|
2023-11-15 23:53:39 +08:00
|
|
|
|
import os
|
2023-12-10 18:55:17 +08:00
|
|
|
|
from re import findall
|
2023-11-16 22:39:59 +08:00
|
|
|
|
from PyQt5.QtCore import pyqtSignal, QThread
|
2023-12-07 20:35:51 +08:00
|
|
|
|
from PyQt5.QtWidgets import QFileDialog
|
2023-12-17 20:31:38 +08:00
|
|
|
|
# from eyed3 import load
|
2023-11-16 22:39:59 +08:00
|
|
|
|
|
2023-12-07 20:35:51 +08:00
|
|
|
|
from . import msg_db, micro_msg_db
|
2023-12-06 15:34:56 +08:00
|
|
|
|
from .package_msg import PackageMsg
|
2023-12-01 22:37:45 +08:00
|
|
|
|
from ..DataBase import hard_link_db
|
2023-12-12 01:17:21 +08:00
|
|
|
|
from ..DataBase import media_msg_db
|
2023-12-13 22:12:50 +08:00
|
|
|
|
from ..person import MePC
|
2023-12-06 20:50:32 +08:00
|
|
|
|
from ..util import path
|
2023-12-09 22:48:15 +08:00
|
|
|
|
import shutil
|
|
|
|
|
|
2023-12-11 22:49:17 +08:00
|
|
|
|
from ..util.compress_content import parser_reply
|
2023-12-09 22:48:15 +08:00
|
|
|
|
from ..util.emoji import get_emoji
|
2023-11-28 21:51:49 +08:00
|
|
|
|
|
2023-12-03 00:03:00 +08:00
|
|
|
|
os.makedirs('./data/聊天记录', exist_ok=True)
|
2023-11-20 22:30:31 +08:00
|
|
|
|
|
2023-11-15 23:53:39 +08:00
|
|
|
|
|
2023-12-06 20:50:32 +08:00
|
|
|
|
def makedirs(path):
|
2023-12-07 20:35:51 +08:00
|
|
|
|
os.makedirs(path, exist_ok=True)
|
2023-12-06 20:50:32 +08:00
|
|
|
|
os.makedirs(os.path.join(path, 'image'), exist_ok=True)
|
|
|
|
|
os.makedirs(os.path.join(path, 'emoji'), exist_ok=True)
|
|
|
|
|
os.makedirs(os.path.join(path, 'video'), exist_ok=True)
|
|
|
|
|
os.makedirs(os.path.join(path, 'voice'), exist_ok=True)
|
|
|
|
|
os.makedirs(os.path.join(path, 'file'), exist_ok=True)
|
2023-12-17 18:33:06 +08:00
|
|
|
|
os.makedirs(os.path.join(path, 'avatar'), exist_ok=True)
|
2023-12-06 20:50:32 +08:00
|
|
|
|
|
|
|
|
|
|
2023-11-28 21:30:56 +08:00
|
|
|
|
def escape_js_and_html(input_str):
|
|
|
|
|
# 转义HTML特殊字符
|
|
|
|
|
html_escaped = html.escape(input_str, quote=False)
|
|
|
|
|
|
|
|
|
|
# 手动处理JavaScript转义字符
|
|
|
|
|
js_escaped = (
|
|
|
|
|
html_escaped
|
|
|
|
|
.replace("\\", "\\\\")
|
|
|
|
|
.replace("'", r"\'")
|
|
|
|
|
.replace('"', r'\"')
|
|
|
|
|
.replace("\n", r'\n')
|
|
|
|
|
.replace("\r", r'\r')
|
|
|
|
|
.replace("\t", r'\t')
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return js_escaped
|
|
|
|
|
|
|
|
|
|
|
2023-11-15 23:53:39 +08:00
|
|
|
|
class Output(QThread):
|
|
|
|
|
"""
|
|
|
|
|
发送信息线程
|
|
|
|
|
"""
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
rangeSignal = pyqtSignal(int)
|
|
|
|
|
okSignal = pyqtSignal(int)
|
|
|
|
|
i = 1
|
|
|
|
|
CSV = 0
|
|
|
|
|
DOCX = 1
|
|
|
|
|
HTML = 2
|
2023-11-27 21:23:26 +08:00
|
|
|
|
CSV_ALL = 3
|
2023-12-07 20:35:51 +08:00
|
|
|
|
CONTACT_CSV = 4
|
2023-12-10 19:36:08 +08:00
|
|
|
|
TXT = 5
|
2023-11-15 23:53:39 +08:00
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
|
2023-11-15 23:53:39 +08:00
|
|
|
|
super().__init__(parent)
|
2023-11-27 21:23:26 +08:00
|
|
|
|
self.Child0 = None
|
2023-11-21 22:23:23 +08:00
|
|
|
|
self.last_timestamp = 0
|
2023-12-10 18:55:17 +08:00
|
|
|
|
self.message_types = message_types
|
2023-11-15 23:53:39 +08:00
|
|
|
|
self.sec = 2 # 默认1000秒
|
2023-11-16 22:39:59 +08:00
|
|
|
|
self.contact = contact
|
2023-11-27 21:23:26 +08:00
|
|
|
|
self.ta_username = contact.wxid if contact else ''
|
2023-11-15 23:53:39 +08:00
|
|
|
|
self.msg_id = 0
|
|
|
|
|
self.output_type = type_
|
|
|
|
|
self.total_num = 0
|
2023-11-16 22:39:59 +08:00
|
|
|
|
self.num = 0
|
2023-11-15 23:53:39 +08:00
|
|
|
|
|
2023-11-22 00:22:50 +08:00
|
|
|
|
def progress(self, value):
|
|
|
|
|
self.progressSignal.emit(value)
|
|
|
|
|
|
2023-11-27 21:23:26 +08:00
|
|
|
|
def to_csv_all(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/"
|
2023-12-03 00:03:00 +08:00
|
|
|
|
os.makedirs(origin_docx_path, exist_ok=True)
|
2023-12-09 22:48:15 +08:00
|
|
|
|
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'messages.csv'),
|
|
|
|
|
"csv files (*.csv);;all files(*.*)")
|
|
|
|
|
if not filename[0]:
|
2023-12-07 20:35:51 +08:00
|
|
|
|
return
|
|
|
|
|
filename = filename[0]
|
2023-11-27 21:23:26 +08:00
|
|
|
|
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
|
|
|
|
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
|
|
|
|
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
2023-12-06 15:34:56 +08:00
|
|
|
|
'StrTime', 'Remark', 'NickName', 'Sender']
|
2023-12-07 20:35:51 +08:00
|
|
|
|
|
2023-12-06 15:34:56 +08:00
|
|
|
|
packagemsg = PackageMsg()
|
|
|
|
|
messages = packagemsg.get_package_message_all()
|
2023-11-27 21:23:26 +08:00
|
|
|
|
# 写入CSV文件
|
|
|
|
|
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
|
|
|
|
writer = csv.writer(file)
|
|
|
|
|
writer.writerow(columns)
|
|
|
|
|
# 写入数据
|
|
|
|
|
writer.writerows(messages)
|
|
|
|
|
self.okSignal.emit(1)
|
|
|
|
|
|
2023-12-07 20:35:51 +08:00
|
|
|
|
def contact_to_csv(self):
|
2023-12-09 22:48:15 +08:00
|
|
|
|
filename = QFileDialog.getSaveFileName(None, "save file", os.path.join(os.getcwd(), 'contacts.csv'),
|
|
|
|
|
"csv files (*.csv);;all files(*.*)")
|
|
|
|
|
if not filename[0]:
|
2023-12-07 20:35:51 +08:00
|
|
|
|
return
|
|
|
|
|
filename = filename[0]
|
|
|
|
|
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
2023-12-09 22:48:15 +08:00
|
|
|
|
columns = ['UserName', 'Alias', 'Type', 'Remark', 'NickName', 'PYInitial', 'RemarkPYInitial', 'smallHeadImgUrl',
|
|
|
|
|
'bigHeadImgUrl']
|
2023-12-07 20:35:51 +08:00
|
|
|
|
contacts = micro_msg_db.get_contact()
|
|
|
|
|
# 写入CSV文件
|
|
|
|
|
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
|
|
|
|
writer = csv.writer(file)
|
|
|
|
|
writer.writerow(columns)
|
|
|
|
|
# 写入数据
|
|
|
|
|
writer.writerows(contacts)
|
|
|
|
|
self.okSignal.emit(1)
|
|
|
|
|
|
2023-11-22 00:22:50 +08:00
|
|
|
|
def run(self):
|
|
|
|
|
if self.output_type == self.DOCX:
|
|
|
|
|
return
|
2023-11-27 21:23:26 +08:00
|
|
|
|
elif self.output_type == self.CSV_ALL:
|
|
|
|
|
self.to_csv_all()
|
2023-12-07 20:35:51 +08:00
|
|
|
|
elif self.output_type == self.CONTACT_CSV:
|
|
|
|
|
self.contact_to_csv()
|
2023-11-27 21:23:26 +08:00
|
|
|
|
else:
|
2023-12-10 19:36:08 +08:00
|
|
|
|
self.Child = ChildThread(self.contact, type_=self.output_type, message_types=self.message_types)
|
2023-12-02 22:02:17 +08:00
|
|
|
|
self.Child.progressSignal.connect(self.progress)
|
|
|
|
|
self.Child.rangeSignal.connect(self.rangeSignal)
|
|
|
|
|
self.Child.okSignal.connect(self.okSignal)
|
|
|
|
|
self.Child.start()
|
2023-11-27 21:23:26 +08:00
|
|
|
|
|
|
|
|
|
def cancel(self):
|
|
|
|
|
self.requestInterruption()
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
|
|
|
|
|
2023-12-15 14:48:54 +08:00
|
|
|
|
def modify_audio_metadata(audiofile, new_artist): # 修改音频元数据中的“创作者”标签
|
2023-12-17 20:31:38 +08:00
|
|
|
|
return
|
2023-12-15 14:48:54 +08:00
|
|
|
|
audiofile = load(audiofile)
|
|
|
|
|
|
|
|
|
|
# 检查文件是否有标签
|
|
|
|
|
if audiofile.tag is None:
|
|
|
|
|
audiofile.initTag()
|
|
|
|
|
|
|
|
|
|
# 修改艺术家名称
|
|
|
|
|
audiofile.tag.artist = new_artist
|
|
|
|
|
audiofile.tag.save()
|
|
|
|
|
|
|
|
|
|
|
2023-11-22 00:22:50 +08:00
|
|
|
|
class ChildThread(QThread):
|
|
|
|
|
"""
|
|
|
|
|
子线程,用于导出部分聊天记录
|
|
|
|
|
"""
|
|
|
|
|
progressSignal = pyqtSignal(int)
|
|
|
|
|
rangeSignal = pyqtSignal(int)
|
|
|
|
|
okSignal = pyqtSignal(int)
|
|
|
|
|
i = 1
|
|
|
|
|
CSV = 0
|
|
|
|
|
DOCX = 1
|
|
|
|
|
HTML = 2
|
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def __init__(self, contact, type_=DOCX, message_types={}, parent=None):
|
2023-11-22 00:22:50 +08:00
|
|
|
|
super().__init__(parent)
|
|
|
|
|
self.contact = contact
|
2023-12-10 18:55:17 +08:00
|
|
|
|
self.message_types = message_types
|
2023-11-22 00:22:50 +08:00
|
|
|
|
self.last_timestamp = 0
|
|
|
|
|
self.sec = 2 # 默认1000秒
|
|
|
|
|
self.msg_id = 0
|
|
|
|
|
self.output_type = type_
|
|
|
|
|
|
|
|
|
|
def is_5_min(self, timestamp):
|
|
|
|
|
if abs(timestamp - self.last_timestamp) > 300:
|
|
|
|
|
self.last_timestamp = timestamp
|
|
|
|
|
return True
|
|
|
|
|
return False
|
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def text(self, doc, message):
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
emojiText = findall(r"(\[.+?\])", str_content)
|
|
|
|
|
for emoji_text in emojiText:
|
|
|
|
|
if emoji_text in emoji:
|
|
|
|
|
str_content = str_content.replace(emoji_text, emoji[emoji_text])
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:{1}, text: '{str_content}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
2023-12-10 18:55:17 +08:00
|
|
|
|
doc.write(
|
2023-12-10 19:36:08 +08:00
|
|
|
|
f'''{str_time} {name}\n{str_content}\n\n'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def image(self, doc, message):
|
2023-12-13 21:03:03 +08:00
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
2023-12-10 18:55:17 +08:00
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
BytesExtra = message[10]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
|
|
|
|
image_path = hard_link_db.get_image(str_content, BytesExtra, thumb=False)
|
|
|
|
|
image_thumb_path = hard_link_db.get_image(str_content, BytesExtra, thumb=True)
|
2023-12-12 10:32:16 +08:00
|
|
|
|
if not os.path.exists(os.path.join(MePC().wx_dir, image_path)):
|
|
|
|
|
image_path = None
|
|
|
|
|
if not os.path.exists(os.path.join(MePC().wx_dir, image_thumb_path)):
|
|
|
|
|
image_thumb_path = None
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if image_path is None and image_thumb_path is not None:
|
|
|
|
|
image_path = image_thumb_path
|
|
|
|
|
if image_path is None and image_thumb_path is None:
|
|
|
|
|
return
|
|
|
|
|
image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
|
2023-12-13 21:03:03 +08:00
|
|
|
|
image_path = image_path.replace('/', '\\')
|
2023-12-17 22:28:57 +08:00
|
|
|
|
try:
|
|
|
|
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
|
|
|
|
except:
|
|
|
|
|
print("网络图片",image_path)
|
|
|
|
|
pass
|
2023-12-10 19:36:08 +08:00
|
|
|
|
image_path = image_path.replace('\\', '/')
|
|
|
|
|
# print(f"tohtml:---{image_path}")
|
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
2023-12-10 18:55:17 +08:00
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:{type_}, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n[图片]\n\n'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-12 01:17:21 +08:00
|
|
|
|
def audio(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
msgSvrId = message[9]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-12 01:17:21 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
try:
|
|
|
|
|
audio_path = media_msg_db.get_audio(msgSvrId, output_path=origin_docx_path + "/voice")
|
2023-12-13 21:03:03 +08:00
|
|
|
|
audio_path = audio_path.replace('/', '\\')
|
2023-12-17 18:33:06 +08:00
|
|
|
|
modify_audio_metadata(audio_path, displayname)
|
2023-12-13 21:03:03 +08:00
|
|
|
|
os.utime(audio_path, (timestamp, timestamp))
|
2023-12-12 01:17:21 +08:00
|
|
|
|
audio_path = audio_path.replace('\\', '/')
|
2023-12-19 14:26:15 +08:00
|
|
|
|
audio_path = "./voice/" + os.path.basename(audio_path)
|
2023-12-16 12:58:29 +08:00
|
|
|
|
voice_to_text = escape_js_and_html(media_msg_db.get_audio_text(str_content))
|
2023-12-12 01:17:21 +08:00
|
|
|
|
except:
|
|
|
|
|
return
|
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-12 01:17:21 +08:00
|
|
|
|
)
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:34, text:'{audio_path}',is_send:{is_send},avatar_path:'{avatar}',voice_to_text:'{voice_to_text}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-12 01:17:21 +08:00
|
|
|
|
)
|
2023-12-13 21:23:43 +08:00
|
|
|
|
if self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n[语音]\n\n'''
|
|
|
|
|
)
|
2023-12-12 01:17:21 +08:00
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def emoji(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
timestamp = message[5]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
emoji_path = get_emoji(str_content, thumb=True, output_path=origin_docx_path + '/emoji')
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if emoji_path == "":
|
|
|
|
|
shutil.copy(f"{os.path.abspath('.')}/app/resources/icons/404.png", origin_docx_path + '/emoji/404.png')
|
|
|
|
|
emoji_path = "./emoji/404.png"
|
|
|
|
|
else:
|
|
|
|
|
emoji_path = './emoji/' + os.path.basename(emoji_path)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
2023-12-10 18:55:17 +08:00
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:{3}, text: '{emoji_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n[表情包]\n\n'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
|
|
|
|
def wx_file(self, doc, isSend, content, status):
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
def retract_message(self, doc, isSend, content, status):
|
|
|
|
|
return
|
|
|
|
|
|
2023-12-17 13:15:49 +08:00
|
|
|
|
def refermsg(self, doc, message):
|
2023-12-11 22:49:17 +08:00
|
|
|
|
"""
|
|
|
|
|
处理回复消息
|
|
|
|
|
@param doc:
|
|
|
|
|
@param message:
|
|
|
|
|
@return:
|
|
|
|
|
"""
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
avatar = 'myhead.png' if is_send else 'tahead.png'
|
|
|
|
|
content = parser_reply(message[11])
|
|
|
|
|
refer_msg = content.get('refer')
|
2023-12-17 18:33:06 +08:00
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-11 22:49:17 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
2023-12-20 18:19:17 +08:00
|
|
|
|
contentText = escape_js_and_html(content.get('title'))
|
2023-12-13 13:57:22 +08:00
|
|
|
|
emojiText = findall(r"(\[.+?\])", contentText)
|
|
|
|
|
for emoji_text in emojiText:
|
|
|
|
|
if emoji_text in emoji:
|
|
|
|
|
contentText = contentText.replace(emoji_text, emoji[emoji_text])
|
2023-12-13 13:19:31 +08:00
|
|
|
|
if refer_msg:
|
2023-12-20 18:19:17 +08:00
|
|
|
|
referText = f"{escape_js_and_html(refer_msg.get('displayname'))}:{escape_js_and_html(refer_msg.get('content'))}"
|
2023-12-13 13:57:22 +08:00
|
|
|
|
emojiText = findall(r"(\[.+?\])", referText)
|
|
|
|
|
for emoji_text in emojiText:
|
|
|
|
|
if emoji_text in emoji:
|
|
|
|
|
referText = referText.replace(emoji_text, emoji[emoji_text])
|
2023-12-13 13:19:31 +08:00
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},refer_text: '{referText}',avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-13 13:19:31 +08:00
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:49, text: '{contentText}',is_send:{is_send},sub_type:{content.get('type')},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-13 13:19:31 +08:00
|
|
|
|
)
|
2023-12-17 13:15:49 +08:00
|
|
|
|
elif self.output_type == Output.TXT:
|
2023-12-11 22:49:17 +08:00
|
|
|
|
name = '你' if is_send else self.contact.remark
|
2023-12-13 20:45:53 +08:00
|
|
|
|
if refer_msg:
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n{content.get('title')}\n引用:{refer_msg.get('displayname')}:{refer_msg.get('content')}\n\n'''
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n{content.get('title')}\n引用:未知\n\n'''
|
|
|
|
|
)
|
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def system_msg(self, doc, message):
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
is_send = message[4]
|
2023-12-10 19:36:08 +08:00
|
|
|
|
str_time = message[8]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
timestamp = message[5]
|
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
2023-12-17 22:09:44 +08:00
|
|
|
|
str_content = str_content.replace('<![CDATA[', "").replace(' <a href="weixin://revoke_edit_click">重新编辑</a>]]>', "")
|
|
|
|
|
res = findall('(</{0,1}(img|revo|_wc_cus|a).*?>)', str_content)
|
2023-12-17 21:52:44 +08:00
|
|
|
|
for xmlstr, b in res:
|
|
|
|
|
str_content = str_content.replace(xmlstr, "")
|
|
|
|
|
str_content = escape_js_and_html(str_content)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_content}',is_send:{is_send},avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:''}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
|
|
|
|
doc.write(
|
|
|
|
|
f'''{str_time} {name}\n{str_content}\n\n'''
|
|
|
|
|
)
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def video(self, doc, message):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
type_ = message[2]
|
|
|
|
|
str_content = message[7]
|
|
|
|
|
str_time = message[8]
|
|
|
|
|
is_send = message[4]
|
|
|
|
|
BytesExtra = message[10]
|
|
|
|
|
timestamp = message[5]
|
2023-12-17 18:33:06 +08:00
|
|
|
|
is_chatroom = 1 if self.contact.is_chatroom else 0
|
|
|
|
|
if is_chatroom:
|
|
|
|
|
avatar = f"./avatar/{message[12].wxid}.png"
|
|
|
|
|
else:
|
2023-12-17 19:37:16 +08:00
|
|
|
|
avatar = f"./avatar/{MePC().wxid if is_send else self.contact.wxid}.png"
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if is_chatroom:
|
|
|
|
|
if is_send:
|
|
|
|
|
displayname = MePC().name
|
|
|
|
|
else:
|
|
|
|
|
displayname = message[12].remark
|
|
|
|
|
else:
|
|
|
|
|
displayname = MePC().name if is_send else self.contact.remark
|
|
|
|
|
displayname = escape_js_and_html(displayname)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
if self.output_type == Output.HTML:
|
|
|
|
|
video_path = hard_link_db.get_video(str_content, BytesExtra, thumb=False)
|
|
|
|
|
image_path = hard_link_db.get_video(str_content, BytesExtra, thumb=True)
|
|
|
|
|
if video_path is None and image_path is not None:
|
|
|
|
|
image_path = path.get_relative_path(image_path, base_path=f'/data/聊天记录/{self.contact.remark}/image')
|
2023-12-16 18:00:44 +08:00
|
|
|
|
try:
|
2023-12-16 20:06:43 +08:00
|
|
|
|
# todo 网络图片问题
|
2023-12-16 18:00:44 +08:00
|
|
|
|
print(origin_docx_path + image_path[1:])
|
|
|
|
|
os.utime(origin_docx_path + image_path[1:], (timestamp, timestamp))
|
|
|
|
|
image_path = image_path.replace('\\', '/')
|
|
|
|
|
# print(f"tohtml:---{image_path}")
|
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-16 18:00:44 +08:00
|
|
|
|
)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:3, text: '{image_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-16 18:00:44 +08:00
|
|
|
|
)
|
|
|
|
|
except:
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:1, text: '视频丢失',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 19:36:08 +08:00
|
|
|
|
)
|
|
|
|
|
return
|
|
|
|
|
if video_path is None and image_path is None:
|
|
|
|
|
return
|
|
|
|
|
video_path = f'{MePC().wx_dir}/{video_path}'
|
|
|
|
|
if os.path.exists(video_path):
|
|
|
|
|
new_path = origin_docx_path + '/video/' + os.path.basename(video_path)
|
|
|
|
|
if not os.path.exists(new_path):
|
|
|
|
|
shutil.copy(video_path, os.path.join(origin_docx_path, 'video'))
|
2023-12-13 21:03:03 +08:00
|
|
|
|
os.utime(new_path, (timestamp, timestamp))
|
2023-12-10 19:36:08 +08:00
|
|
|
|
video_path = f'./video/{os.path.basename(video_path)}'
|
|
|
|
|
video_path = video_path.replace('\\', '/')
|
2023-12-10 18:55:17 +08:00
|
|
|
|
if self.is_5_min(timestamp):
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:0, text: '{str_time}',is_send:0,avatar_path:'',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
|
|
|
|
doc.write(
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f'''{{ type:{type_}, text: '{video_path}',is_send:{is_send},avatar_path:'{avatar}',timestamp:{timestamp},is_chatroom:{is_chatroom},displayname:'{displayname}'}},'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
name = '你' if is_send else self.contact.remark
|
2023-12-10 18:55:17 +08:00
|
|
|
|
doc.write(
|
2023-12-10 19:36:08 +08:00
|
|
|
|
f'''{str_time} {name}\n[视频]\n\n'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
)
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-11-25 00:40:09 +08:00
|
|
|
|
def to_csv(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
2023-12-03 00:03:00 +08:00
|
|
|
|
os.makedirs(origin_docx_path, exist_ok=True)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}_utf8.csv"
|
2023-11-25 00:40:09 +08:00
|
|
|
|
# columns = ["用户名", "消息内容", "发送时间", "发送状态", "消息类型", "isSend", "msgId"]
|
|
|
|
|
columns = ['localId', 'TalkerId', 'Type', 'SubType',
|
|
|
|
|
'IsSender', 'CreateTime', 'Status', 'StrContent',
|
|
|
|
|
'StrTime']
|
2023-12-01 22:37:45 +08:00
|
|
|
|
messages = msg_db.get_messages(self.contact.wxid)
|
2023-11-25 00:40:09 +08:00
|
|
|
|
# 写入CSV文件
|
|
|
|
|
with open(filename, mode='w', newline='', encoding='utf-8') as file:
|
|
|
|
|
writer = csv.writer(file)
|
|
|
|
|
writer.writerow(columns)
|
|
|
|
|
# 写入数据
|
|
|
|
|
writer.writerows(messages)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
# with open(filename, mode='r', newline='', encoding='utf-8') as file:
|
|
|
|
|
# content = file.read()
|
|
|
|
|
# filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}_gbk.csv"
|
|
|
|
|
# with open(filename, mode='w', newline='', encoding='gbk') as file:
|
|
|
|
|
# file.write(content.encode('utf-8', errors='ignore').decode('gbk', errors='ignore'))
|
2023-11-25 00:40:09 +08:00
|
|
|
|
self.okSignal.emit('ok')
|
|
|
|
|
|
2023-11-22 00:22:50 +08:00
|
|
|
|
def to_html_(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
2023-12-06 20:50:32 +08:00
|
|
|
|
makedirs(origin_docx_path)
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if self.contact.is_chatroom:
|
|
|
|
|
packagemsg = PackageMsg()
|
|
|
|
|
messages = packagemsg.get_package_message_by_wxid(self.contact.wxid)
|
|
|
|
|
else:
|
|
|
|
|
messages = msg_db.get_messages(self.contact.wxid)
|
2023-11-22 00:22:50 +08:00
|
|
|
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.html"
|
|
|
|
|
f = open(filename, 'w', encoding='utf-8')
|
2023-12-17 18:33:06 +08:00
|
|
|
|
f.write(html_head.replace("<title>Chat Records</title>", f"<title>{self.contact.remark}</title>"))
|
|
|
|
|
MePC().avatar.save(os.path.join(f"{origin_docx_path}/avatar/{MePC().wxid}.png"))
|
|
|
|
|
if self.contact.is_chatroom:
|
|
|
|
|
for message in messages:
|
|
|
|
|
if message[4]: # is_send
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
chatroom_avatar_path = f"{origin_docx_path}/avatar/{message[12].wxid}.png"
|
|
|
|
|
if not os.path.exists(chatroom_avatar_path):
|
|
|
|
|
message[12].avatar.save(chatroom_avatar_path)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
self.contact.avatar.save(os.path.join(f"{origin_docx_path}/avatar/{self.contact.wxid}.png"))
|
2023-12-10 18:55:17 +08:00
|
|
|
|
self.rangeSignal.emit(len(messages))
|
|
|
|
|
total_steps = len(messages)
|
|
|
|
|
for index, message in enumerate(messages):
|
|
|
|
|
type_ = message[2]
|
2023-12-11 22:49:17 +08:00
|
|
|
|
sub_type = message[3]
|
2023-12-10 19:36:08 +08:00
|
|
|
|
self.progressSignal.emit(int((index + 1) / total_steps * 100))
|
2023-12-10 18:55:17 +08:00
|
|
|
|
if type_ == 1 and self.message_types.get(type_):
|
|
|
|
|
self.text(f, message)
|
|
|
|
|
elif type_ == 3 and self.message_types.get(type_):
|
|
|
|
|
self.image(f, message)
|
2023-12-12 01:17:21 +08:00
|
|
|
|
elif type_ == 34 and self.message_types.get(type_):
|
|
|
|
|
self.audio(f, message)
|
2023-12-10 18:55:17 +08:00
|
|
|
|
elif type_ == 43 and self.message_types.get(type_):
|
|
|
|
|
self.video(f, message)
|
|
|
|
|
elif type_ == 47 and self.message_types.get(type_):
|
|
|
|
|
self.emoji(f, message)
|
|
|
|
|
elif type_ == 10000 and self.message_types.get(type_):
|
|
|
|
|
self.system_msg(f, message)
|
2023-12-17 18:48:22 +08:00
|
|
|
|
elif type_ == 49 and sub_type == 57 and self.message_types.get(1):
|
2023-12-17 13:15:49 +08:00
|
|
|
|
self.refermsg(f, message)
|
2023-12-10 18:55:17 +08:00
|
|
|
|
f.write(html_end)
|
|
|
|
|
f.close()
|
|
|
|
|
self.okSignal.emit(1)
|
|
|
|
|
|
2023-12-10 19:36:08 +08:00
|
|
|
|
def to_txt(self):
|
|
|
|
|
origin_docx_path = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}"
|
|
|
|
|
os.makedirs(origin_docx_path, exist_ok=True)
|
|
|
|
|
filename = f"{os.path.abspath('.')}/data/聊天记录/{self.contact.remark}/{self.contact.remark}.txt"
|
|
|
|
|
messages = msg_db.get_messages(self.contact.wxid)
|
|
|
|
|
total_steps = len(messages)
|
|
|
|
|
with open(filename, mode='w', newline='', encoding='utf-8') as f:
|
|
|
|
|
for index, message in enumerate(messages):
|
|
|
|
|
type_ = message[2]
|
2023-12-11 22:49:17 +08:00
|
|
|
|
sub_type = message[3]
|
2023-12-10 19:36:08 +08:00
|
|
|
|
self.progressSignal.emit(int((index + 1) / total_steps * 100))
|
|
|
|
|
if type_ == 1 and self.message_types.get(type_):
|
|
|
|
|
self.text(f, message)
|
|
|
|
|
elif type_ == 3 and self.message_types.get(type_):
|
|
|
|
|
self.image(f, message)
|
2023-12-13 21:23:43 +08:00
|
|
|
|
elif type_ == 34 and self.message_types.get(type_):
|
|
|
|
|
self.audio(f, message)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
elif type_ == 43 and self.message_types.get(type_):
|
|
|
|
|
self.video(f, message)
|
|
|
|
|
elif type_ == 47 and self.message_types.get(type_):
|
|
|
|
|
self.emoji(f, message)
|
|
|
|
|
elif type_ == 10000 and self.message_types.get(type_):
|
|
|
|
|
self.system_msg(f, message)
|
2023-12-11 22:49:17 +08:00
|
|
|
|
elif type_ == 49 and sub_type == 57:
|
|
|
|
|
self.refermsg(f, message)
|
2023-12-10 19:36:08 +08:00
|
|
|
|
self.okSignal.emit(1)
|
2023-12-17 13:15:49 +08:00
|
|
|
|
|
2023-12-10 18:55:17 +08:00
|
|
|
|
def run(self):
|
|
|
|
|
if self.output_type == Output.DOCX:
|
|
|
|
|
return
|
|
|
|
|
elif self.output_type == Output.CSV:
|
|
|
|
|
self.to_csv()
|
|
|
|
|
elif self.output_type == Output.HTML:
|
|
|
|
|
self.to_html_()
|
|
|
|
|
elif self.output_type == Output.CSV_ALL:
|
|
|
|
|
self.to_csv_all()
|
2023-12-10 19:36:08 +08:00
|
|
|
|
elif self.output_type == Output.TXT:
|
|
|
|
|
self.to_txt()
|
2023-12-10 18:55:17 +08:00
|
|
|
|
|
|
|
|
|
def cancel(self):
|
|
|
|
|
self.requestInterruption()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
emoji = {
|
|
|
|
|
'[微笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_1@2x.png" id="微笑" class="emoji_img">',
|
|
|
|
|
'[撇嘴]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_2@2x.png" id="撇嘴" class="emoji_img">',
|
|
|
|
|
'[色]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_3@2x.png" id="色" class="emoji_img">',
|
|
|
|
|
'[发呆]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_4@2x.png" id="发呆" class="emoji_img">',
|
|
|
|
|
'[得意]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_5@2x.png" id="得意" class="emoji_img">',
|
|
|
|
|
'[流泪]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_6@2x.png" id="流泪" class="emoji_img">',
|
|
|
|
|
'[害羞]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_7@2x.png" id="害羞" class="emoji_img">',
|
|
|
|
|
'[闭嘴]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_8@2x.png" id="闭嘴" class="emoji_img">',
|
|
|
|
|
'[睡]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_9@2x.png" id="睡" class="emoji_img">',
|
|
|
|
|
'[大哭]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_10@2x.png" id="大哭" class="emoji_img">',
|
|
|
|
|
'[尴尬]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_11@2x.png" id="尴尬" class="emoji_img">',
|
|
|
|
|
'[发怒]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_12@2x.png" id="发怒" class="emoji_img">',
|
|
|
|
|
'[调皮]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_13@2x.png" id="调皮" class="emoji_img">',
|
|
|
|
|
'[呲牙]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_14@2x.png" id="呲牙" class="emoji_img">',
|
|
|
|
|
'[惊讶]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_15@2x.png" id="惊讶" class="emoji_img">',
|
|
|
|
|
'[难过]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_16@2x.png" id="难过" class="emoji_img">',
|
|
|
|
|
'[抓狂]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_19@2x.png" id="抓狂" class="emoji_img">',
|
|
|
|
|
'[吐]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_20@2x.png" id="吐" class="emoji_img">',
|
|
|
|
|
'[偷笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_21@2x.png" id="偷笑" class="emoji_img">',
|
|
|
|
|
'[愉快]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_22@2x.png" id="愉快" class="emoji_img">',
|
|
|
|
|
'[白眼]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_23@2x.png" id="白 眼" class="emoji_img">',
|
|
|
|
|
'[傲慢]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_24@2x.png" id="傲慢" class="emoji_img">',
|
|
|
|
|
'[困]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_26@2x.png" id="困" class="emoji_img">',
|
|
|
|
|
'[惊恐]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_27@2x.png" id="惊恐" class="emoji_img">',
|
|
|
|
|
'[憨笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_29@2x.png" id="憨笑" class="emoji_img">',
|
|
|
|
|
'[悠闲]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_30@2x.png" id="悠闲" class="emoji_img">',
|
|
|
|
|
'[咒骂]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_32@2x.png" id="咒骂" class="emoji_img">',
|
|
|
|
|
'[疑问]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_33@2x.png" id="疑问" class="emoji_img">',
|
|
|
|
|
'[嘘]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_34@2x.png" id="嘘" class="emoji_img">',
|
|
|
|
|
'[晕]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_35@2x.png" id="晕" class="emoji_img">',
|
|
|
|
|
'[衰]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_37@2x.png" id="衰" class="emoji_img">',
|
|
|
|
|
'[骷髅]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_38@2x.png" id="骷髅" class="emoji_img">',
|
|
|
|
|
'[敲打]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_39@2x.png" id="敲打" class="emoji_img">',
|
|
|
|
|
'[再见]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_40@2x.png" id="再见" class="emoji_img">',
|
|
|
|
|
'[擦汗]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_41@2x.png" id="擦汗" class="emoji_img">',
|
|
|
|
|
'[抠鼻]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_42@2x.png" id="抠鼻" class="emoji_img">',
|
|
|
|
|
'[鼓掌]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_43@2x.png" id="鼓掌" class="emoji_img">',
|
|
|
|
|
'[坏笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_45@2x.png" id="坏笑" class="emoji_img">',
|
|
|
|
|
'[右哼哼]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_47@2x.png" id="右哼哼" class="emoji_img">',
|
|
|
|
|
'[鄙视]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_49@2x.png" id="鄙视" class="emoji_img">',
|
|
|
|
|
'[委屈]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_50@2x.png" id="委屈" class="emoji_img">',
|
|
|
|
|
'[快哭了]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_51@2x.png" id="快哭了" class="emoji_img">',
|
|
|
|
|
'[阴险]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_52@2x.png" id="阴险" class="emoji_img">',
|
|
|
|
|
'[亲亲]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_53@2x.png" id="亲亲" class="emoji_img">',
|
|
|
|
|
'[可怜]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_55@2x.png" id="可怜" class="emoji_img">',
|
2023-12-17 18:33:06 +08:00
|
|
|
|
'[Whimper]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_55@2x.png" id="可怜" class="emoji_img">',
|
2023-12-10 18:55:17 +08:00
|
|
|
|
'[笑脸]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Happy.png" id="笑脸" class="emoji_img">',
|
|
|
|
|
'[生病]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Sick.png" id="生病" class="emoji_img">',
|
|
|
|
|
'[脸红]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Flushed.png" id="脸红" class="emoji_img">',
|
|
|
|
|
'[破涕为笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Lol.png" id="破涕为笑" class="emoji_img">',
|
|
|
|
|
'[恐惧]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Terror.png" id="恐惧" class="emoji_img">',
|
|
|
|
|
'[失望]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/LetDown.png" id="失望" class="emoji_img">',
|
|
|
|
|
'[无语]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Duh.png" id="无语" class="emoji_img">',
|
|
|
|
|
'[嘿哈]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_04.png" id="嘿哈" class="emoji_img">',
|
|
|
|
|
'[捂脸]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_05.png" id="捂脸" class="emoji_img">',
|
|
|
|
|
'[奸笑]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_02.png" id="奸笑" class="emoji_img">',
|
|
|
|
|
'[机智]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_06.png" id="机智" class="emoji_img">',
|
|
|
|
|
'[皱眉]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_12.png" id="皱眉" class="emoji_img">',
|
|
|
|
|
'[耶]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_11.png" id="耶" class="emoji_img">',
|
|
|
|
|
'[吃瓜]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Watermelon.png" id="吃瓜" class="emoji_img">',
|
|
|
|
|
'[加油]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Addoil.png" id="加油" class="emoji_img">',
|
|
|
|
|
'[汗]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Sweat.png" id="汗" class="emoji_img">',
|
|
|
|
|
'[天啊]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Shocked.png" id="天啊" class="emoji_img">',
|
|
|
|
|
'[Emm]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Cold.png" id="Emm" class="emoji_img">',
|
|
|
|
|
'[社会社会]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Social.png" id="社会社会" class="emoji_img">',
|
|
|
|
|
'[旺柴]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Yellowdog.png" id="旺柴" class="emoji_img">',
|
|
|
|
|
'[好的]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/NoProb.png" id="好的" class="emoji_img">',
|
|
|
|
|
'[打脸]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Slap.png" id="打脸" class="emoji_img">',
|
|
|
|
|
'[哇]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Wow.png" id="哇" class="emoji_img">',
|
|
|
|
|
'[翻白眼]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Boring.png" id="翻白眼" class="emoji_img">',
|
|
|
|
|
'[666]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/666.png" id="666" class="emoji_img">',
|
|
|
|
|
'[让我看看]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/LetMeSee.png" id="让我看看" class="emoji_img">',
|
|
|
|
|
'[叹气]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Sigh.png" id="叹气" class="emoji_img">',
|
|
|
|
|
'[苦涩]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Hurt.png" id="苦涩" class="emoji_img">',
|
|
|
|
|
'[裂开]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Broken.png" id="裂开" class="emoji_img">',
|
|
|
|
|
'[嘴唇]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_66@2x.png" id="嘴唇" class="emoji_img">',
|
|
|
|
|
'[爱心]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_67@2x.png" id="爱心" class="emoji_img">',
|
|
|
|
|
'[心碎]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_68@2x.png" id="心碎" class="emoji_img">',
|
|
|
|
|
'[拥抱]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_79@2x.png" id="拥抱" class="emoji_img">',
|
|
|
|
|
'[强]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_80@2x.png" id="强" class="emoji_img">',
|
|
|
|
|
'[弱]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_81@2x.png" id="弱" class="emoji_img">',
|
|
|
|
|
'[握手]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_82@2x.png" id="握手" class="emoji_img">',
|
|
|
|
|
'[胜利]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_83@2x.png" id="胜利" class="emoji_img">',
|
|
|
|
|
'[抱拳]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_84@2x.png" id="抱拳" class="emoji_img">',
|
|
|
|
|
'[勾引]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_85@2x.png" id="勾引" class="emoji_img">',
|
|
|
|
|
'[拳头]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_86@2x.png" id="拳头" class="emoji_img">',
|
|
|
|
|
'[OK]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_90@2x.png" id="OK" class="emoji_img">',
|
|
|
|
|
'[合十]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Worship.png" id="合十" class="emoji_img">',
|
|
|
|
|
'[啤酒]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_58@2x.png" id="啤酒" class="emoji_img">',
|
|
|
|
|
'[咖啡]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_61@2x.png" id="咖啡" class="emoji_img">',
|
|
|
|
|
'[蛋糕]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_69@2x.png" id="蛋糕" class="emoji_img">',
|
|
|
|
|
'[玫瑰]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_64@2x.png" id="玫 瑰" class="emoji_img">',
|
|
|
|
|
'[凋谢]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_65@2x.png" id="凋谢" class="emoji_img">',
|
|
|
|
|
'[菜刀]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_56@2x.png" id="菜刀" class="emoji_img">',
|
|
|
|
|
'[炸弹]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_71@2x.png" id="炸弹" class="emoji_img">',
|
|
|
|
|
'[便便]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_75@2x.png" id="便便" class="emoji_img">',
|
|
|
|
|
'[月亮]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_76@2x.png" id="月亮" class="emoji_img">',
|
|
|
|
|
'[太阳]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_77@2x.png" id="太阳" class="emoji_img">',
|
|
|
|
|
'[庆 祝]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Party.png" id="庆祝" class="emoji_img">',
|
|
|
|
|
'[礼物]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_78@2x.png" id="礼物" class="emoji_img">',
|
|
|
|
|
'[红包]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_09.png" id="红包" class="emoji_img">',
|
|
|
|
|
'[發]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_16.png" id="發" class="emoji_img">',
|
|
|
|
|
'[福]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/2_15.png" id="福" class="emoji_img">',
|
|
|
|
|
'[烟花]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Fireworks.png" id="烟花" class="emoji_img">',
|
|
|
|
|
'[爆竹]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/newemoji/Firecracker.png" id="爆竹" class="emoji_img">',
|
|
|
|
|
'[猪头]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_63@2x.png" id="猪头" class="emoji_img">',
|
|
|
|
|
'[跳跳]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_93@2x.png" id="跳跳" class="emoji_img">',
|
|
|
|
|
'[发抖]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_94@2x.png" id="发抖" class="emoji_img">',
|
|
|
|
|
'[转圈]': '<img src="https://res.wx.qq.com/t/wx_fed/we-emoji/res/v1.2.8/assets/Expression/Expression_96@2x.png" id="转圈" class="emoji_img">'}
|
|
|
|
|
html_head = '''
|
2023-11-22 00:22:50 +08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>Chat Records</title>
|
|
|
|
|
<style>
|
2023-12-11 12:52:44 +08:00
|
|
|
|
*{
|
|
|
|
|
padding: 0;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
body{
|
|
|
|
|
height: 100vh;
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.modal {
|
|
|
|
|
display: none;
|
|
|
|
|
position: fixed;
|
|
|
|
|
z-index: 9999;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
background-color: rgba(0, 0, 0, 0.8);
|
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
.modal-image {
|
|
|
|
|
display: block;
|
|
|
|
|
max-width: 90%;
|
|
|
|
|
max-height: 90%;
|
2023-12-17 19:19:35 +08:00
|
|
|
|
position: absolute;
|
|
|
|
|
top: 50%;
|
|
|
|
|
left: 50%;
|
|
|
|
|
transform: translate(-50%, -50%);
|
2023-12-11 12:52:44 +08:00
|
|
|
|
}
|
|
|
|
|
.container{
|
2023-12-12 10:32:16 +08:00
|
|
|
|
height: 99%;
|
2023-12-11 12:52:44 +08:00
|
|
|
|
width: 900px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
border: 0.5px solid #e0e0e0;
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-flow: column;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
.content{
|
|
|
|
|
width: calc(100% - 40px);
|
|
|
|
|
padding: 20px;
|
|
|
|
|
overflow-y: scroll;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
.content:hover::-webkit-scrollbar-thumb{
|
|
|
|
|
background:rgba(0,0,0,0.1);
|
|
|
|
|
}
|
2023-12-17 18:59:03 +08:00
|
|
|
|
.bubble{
|
2023-12-11 12:52:44 +08:00
|
|
|
|
max-width: 400px;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
position: relative;
|
|
|
|
|
color: #000;
|
|
|
|
|
word-wrap:break-word;
|
|
|
|
|
word-break:normal;
|
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
.chat-refer {
|
|
|
|
|
margin-top: 5px;
|
2023-12-11 22:49:17 +08:00
|
|
|
|
max-width: 400px;
|
2023-12-17 18:43:37 +08:00
|
|
|
|
padding: 9px;
|
2023-12-11 22:49:17 +08:00
|
|
|
|
border-radius: 5px;
|
|
|
|
|
position: relative;
|
|
|
|
|
color: #000;
|
|
|
|
|
background-color: #e8e8e8;
|
|
|
|
|
word-wrap:break-word;
|
|
|
|
|
word-break:normal;
|
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
.chat-refer-right {
|
2023-12-17 19:37:16 +08:00
|
|
|
|
margin-right: 15px;
|
2023-12-11 22:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
.chat-refer-left{
|
2023-12-17 18:33:06 +08:00
|
|
|
|
margin-left: 15px;
|
2023-12-11 22:49:17 +08:00
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
.item-left .bubble{
|
|
|
|
|
margin-left: 15px;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
}
|
|
|
|
|
.item-left .bubble:before{
|
|
|
|
|
content: "";
|
|
|
|
|
position: absolute;
|
|
|
|
|
width: 0;
|
|
|
|
|
height: 0;
|
|
|
|
|
border-left: 10px solid transparent;
|
|
|
|
|
border-top: 10px solid transparent;
|
|
|
|
|
border-right: 10px solid #fff;
|
|
|
|
|
border-bottom: 10px solid transparent;
|
|
|
|
|
left: -20px;
|
|
|
|
|
}
|
|
|
|
|
.item-right .bubble{
|
|
|
|
|
margin-right: 15px;
|
|
|
|
|
background-color: #9eea6a;
|
|
|
|
|
}
|
|
|
|
|
.item-right .bubble:before{
|
|
|
|
|
content: "";
|
|
|
|
|
position: absolute;
|
|
|
|
|
width: 0;
|
|
|
|
|
height: 0;
|
|
|
|
|
border-left: 10px solid #9eea6a;
|
|
|
|
|
border-top: 10px solid transparent;
|
|
|
|
|
border-right: 10px solid transparent;
|
|
|
|
|
border-bottom: 10px solid transparent;
|
|
|
|
|
right: -20px;
|
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
.item {
|
|
|
|
|
white-space: pre-wrap;
|
2023-12-11 12:52:44 +08:00
|
|
|
|
margin-top: 15px;
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
2023-12-13 13:19:31 +08:00
|
|
|
|
.item-refer{
|
|
|
|
|
margin-top: 4px;
|
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
.item.item-right{
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
}
|
|
|
|
|
.item.item-center{
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
|
|
|
|
.item.item-center span{
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
padding: 2px 4px;
|
|
|
|
|
color: #fff;
|
|
|
|
|
background-color: #dadada;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
-moz-user-select:none; /*火狐*/
|
|
|
|
|
-webkit-user-select:none; /*webkit浏览器*/
|
|
|
|
|
-ms-user-select:none; /*IE10*/
|
|
|
|
|
-khtml-user-select:none; /*早期浏览器*/
|
|
|
|
|
user-select:none;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-17 18:33:06 +08:00
|
|
|
|
.content-wrapper {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
2023-12-17 19:37:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content-wrapper-left {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
align-items: baseline;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-17 19:37:16 +08:00
|
|
|
|
.content-wrapper-right {
|
|
|
|
|
align-items: flex-end;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-17 18:33:06 +08:00
|
|
|
|
.displayname {
|
|
|
|
|
margin-left: 13px;
|
|
|
|
|
margin-left: 13px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
color: darkgray;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
.chat-image img{
|
2023-11-27 19:26:31 +08:00
|
|
|
|
margin-right: 18px;
|
|
|
|
|
margin-left: 18px;
|
|
|
|
|
max-width: 300px;
|
|
|
|
|
max-height: auto;
|
2023-12-11 12:52:44 +08:00
|
|
|
|
}
|
|
|
|
|
.avatar img{
|
|
|
|
|
width: 42px;
|
|
|
|
|
height: 42px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
}
|
|
|
|
|
.chat-video video{
|
2023-12-07 23:23:55 +08:00
|
|
|
|
margin-right: 18px;
|
|
|
|
|
margin-left: 18px;
|
|
|
|
|
max-width: 350px;
|
2023-12-11 12:52:44 +08:00
|
|
|
|
}
|
2023-12-12 01:17:21 +08:00
|
|
|
|
.chat-audio{
|
2023-12-17 19:45:11 +08:00
|
|
|
|
max-width: 400px;
|
2023-12-12 01:17:21 +08:00
|
|
|
|
}
|
|
|
|
|
audio{
|
2023-12-17 19:45:11 +08:00
|
|
|
|
margin-left: 9px;
|
|
|
|
|
margin-right: 9px;
|
2023-12-12 01:17:21 +08:00
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
.input-area{
|
|
|
|
|
border-top:0.5px solid #e0e0e0;
|
|
|
|
|
height: 150px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-flow: column;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
}
|
|
|
|
|
textarea{
|
|
|
|
|
flex: 1;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
border: none;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
outline:none;
|
|
|
|
|
resize:none;
|
|
|
|
|
}
|
|
|
|
|
.button-area{
|
|
|
|
|
display: flex;
|
|
|
|
|
height: 40px;
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
line-height: 40px;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
}
|
|
|
|
|
.button-area button{
|
|
|
|
|
width: 80px;
|
|
|
|
|
border: none;
|
|
|
|
|
outline: none;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
float: right;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 设置滚动条的样式 */
|
|
|
|
|
::-webkit-scrollbar {
|
|
|
|
|
width:10px;
|
|
|
|
|
}
|
|
|
|
|
/* 滚动槽 */
|
|
|
|
|
::-webkit-scrollbar-track {
|
|
|
|
|
-webkit-box-shadow:inset006pxrgba(0,0,0,0.3);
|
|
|
|
|
border-radius:8px;
|
|
|
|
|
}
|
|
|
|
|
/* 滚动条滑块 */
|
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
|
|
|
border-radius:10px;
|
|
|
|
|
background:rgba(0,0,0,0);
|
|
|
|
|
-webkit-box-shadow:inset006pxrgba(0,0,0,0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pagination-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
2023-12-11 22:49:17 +08:00
|
|
|
|
align-items: center;
|
2023-12-11 12:52:44 +08:00
|
|
|
|
margin-top: 20px;
|
|
|
|
|
margin-left: 20px; /* 新增的左边距 */
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.button-row,
|
|
|
|
|
.jump-row,
|
|
|
|
|
#paginationInfo {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 10px;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
padding: 10px 25px;
|
|
|
|
|
background-color: #3498db;
|
|
|
|
|
color: white;
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
margin: 0 14px;
|
|
|
|
|
transition: background-color 0.3s;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button:hover {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
background-color: #2980b9;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
padding: 8px;
|
|
|
|
|
width: 120px;
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
margin-right: 0px;
|
|
|
|
|
margin-left: 15px;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
button,
|
|
|
|
|
input {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
font-size: 14px;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#paginationInfo {
|
2023-12-11 12:52:44 +08:00
|
|
|
|
color: #555;
|
|
|
|
|
font-size: 14px;
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-06 11:23:33 +08:00
|
|
|
|
.emoji_img {
|
2023-12-17 19:12:46 +08:00
|
|
|
|
width: 22px;
|
|
|
|
|
height: 22px;
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
margin-top: -4.4px;
|
2023-12-06 11:23:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 00:22:50 +08:00
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
2023-12-11 12:52:44 +08:00
|
|
|
|
<div class="container">
|
2023-11-22 00:22:50 +08:00
|
|
|
|
<div class="content" id="chat-container">
|
|
|
|
|
<div class="item item-center"><span>昨天 12:35</span></div>
|
|
|
|
|
<div class="item item-center"><span>你已添加了凡繁烦,现在可以开始聊天了。</span></div>
|
|
|
|
|
<div class="item item-left">
|
2023-11-21 22:23:23 +08:00
|
|
|
|
<div class="avatar">
|
2023-11-22 00:22:50 +08:00
|
|
|
|
<img src="https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=25668084,2889217189&fm=26&gp=0.jpg" />
|
2023-11-21 22:23:23 +08:00
|
|
|
|
</div>
|
2023-11-22 00:22:50 +08:00
|
|
|
|
<div class="bubble bubble-left">您好,我在武汉,你可以直接送过来吗,我有时间的话,可以自己过去拿<br/>!!!<br/>123
|
2023-11-21 22:23:23 +08:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
|
|
|
|
<div class="item item-right">
|
|
|
|
|
<div class="bubble bubble-right">hello<br/>你好呀</div>
|
|
|
|
|
<div class="avatar">
|
|
|
|
|
<img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3313909130,2406410525&fm=15&gp=0.jpg" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="item item-center">
|
|
|
|
|
<span>昨天 13:15</span>
|
|
|
|
|
</div>
|
2023-11-21 22:23:23 +08:00
|
|
|
|
</div>
|
2023-11-22 00:22:50 +08:00
|
|
|
|
</div>
|
|
|
|
|
<div></div>
|
2023-12-03 22:19:25 +08:00
|
|
|
|
<div id="modal" class="modal" onclick="hideModal()">
|
2023-12-11 12:52:44 +08:00
|
|
|
|
<img id="modal-image" class="modal-image">
|
2023-12-03 22:19:25 +08:00
|
|
|
|
</div>
|
2023-11-27 19:26:31 +08:00
|
|
|
|
<div class="pagination-container">
|
2023-12-11 12:52:44 +08:00
|
|
|
|
<div class="button-row">
|
|
|
|
|
<button onclick="prevPage()">上一页</button>
|
|
|
|
|
<button onclick="nextPage()">下一页</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="jump-row">
|
|
|
|
|
<input type="number" id="gotoPageInput" onkeydown="checkEnter(event)" placeholder="跳转到第几页">
|
|
|
|
|
<button onclick="gotoPage()">跳转</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="paginationInfo"></div>
|
2023-11-21 22:23:23 +08:00
|
|
|
|
</div>
|
2023-11-22 00:22:50 +08:00
|
|
|
|
<script>
|
2023-12-11 12:52:44 +08:00
|
|
|
|
const chatContainer = document.getElementById('chat-container');
|
|
|
|
|
// Sample chat messages (replace this with your actual data)
|
|
|
|
|
const chatMessages = [
|
2023-11-22 00:22:50 +08:00
|
|
|
|
'''
|
2023-12-10 18:55:17 +08:00
|
|
|
|
html_end = '''
|
2023-12-11 12:52:44 +08:00
|
|
|
|
];
|
|
|
|
|
function checkEnter(event) {
|
|
|
|
|
if (event.keyCode === 13) {
|
|
|
|
|
gotoPage();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
const itemsPerPage = 100; // 每页显示的元素个数
|
|
|
|
|
let currentPage = 1; // 当前页
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
function renderPage(page) {
|
|
|
|
|
const container = document.getElementById('chat-container');
|
|
|
|
|
container.innerHTML = ''; // 清空容器
|
2023-11-22 00:22:50 +08:00
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
// 计算当前页应该显示的元素范围
|
|
|
|
|
const startIndex = (page - 1) * itemsPerPage;
|
|
|
|
|
const endIndex = startIndex + itemsPerPage;
|
|
|
|
|
console.log(page);
|
2023-12-17 18:33:06 +08:00
|
|
|
|
|
|
|
|
|
// 生成各类标签的函数
|
|
|
|
|
function messageBubble(message, side) {
|
|
|
|
|
const messageBubbleTag = document.createElement('div');
|
|
|
|
|
messageBubbleTag.className = `bubble bubble-${side}`;
|
|
|
|
|
messageBubbleTag.innerHTML = message.text;
|
|
|
|
|
return messageBubbleTag;
|
|
|
|
|
}
|
|
|
|
|
function displayNameBox(message) {
|
|
|
|
|
const displayName = document.createElement('div');
|
|
|
|
|
displayName.className = "displayname";
|
|
|
|
|
displayName.innerHTML = message.displayname;
|
|
|
|
|
return displayName;
|
|
|
|
|
}
|
|
|
|
|
function avatarBox(message) {
|
|
|
|
|
const avatarTag = document.createElement('div');
|
|
|
|
|
avatarTag.className = "avatar";
|
|
|
|
|
avatarTag.innerHTML = `<img src="${message.avatar_path}" />`
|
|
|
|
|
return avatarTag;
|
|
|
|
|
}
|
|
|
|
|
function messageImgBox(message) {
|
|
|
|
|
const messageImgTag = document.createElement('div');
|
|
|
|
|
messageImgTag.className = `chat-image`;
|
|
|
|
|
messageImgTag.innerHTML = `<img src="${message.text}" onclick="showModal(this)"/>`;
|
|
|
|
|
return messageImgTag;
|
|
|
|
|
}
|
|
|
|
|
function messageVideoBox(message) {
|
|
|
|
|
const messageVideoTag = document.createElement('div');
|
|
|
|
|
messageVideoTag.className = `chat-video`;
|
|
|
|
|
messageVideoTag.innerHTML = `<video src="${message.text}" controls />`;
|
|
|
|
|
return messageVideoTag;
|
|
|
|
|
}
|
|
|
|
|
function messageElementReferText(message, side) {
|
|
|
|
|
const messageElementRefer = document.createElement('div');
|
|
|
|
|
messageElementRefer.className = `chat-refer chat-refer-${side}`;
|
|
|
|
|
messageElementRefer.innerHTML = message.refer_text;
|
|
|
|
|
return messageElementRefer;
|
|
|
|
|
}
|
|
|
|
|
function messageVoiceToTextBubble(message, side) {
|
|
|
|
|
const messageVoiceToTextTag = document.createElement('div');
|
|
|
|
|
messageVoiceToTextTag.className = `bubble bubble-${side}`;
|
|
|
|
|
messageVoiceToTextTag.innerHTML = message.voice_to_text;
|
|
|
|
|
return messageVoiceToTextTag;
|
|
|
|
|
}
|
|
|
|
|
function messageAudioBox(message) {
|
|
|
|
|
const messageAudioTag = document.createElement('div');
|
|
|
|
|
messageAudioTag.className = `chat-audio`;
|
|
|
|
|
messageAudioTag.innerHTML = `<audio src="${message.text}" controls></audio>`;
|
|
|
|
|
return messageAudioTag;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-19 00:13:39 +08:00
|
|
|
|
// 从数据列表中取出对应范围的元素并添加到容器中
|
2023-12-11 12:52:44 +08:00
|
|
|
|
for (let i = startIndex; i < endIndex && i < chatMessages.length; i++) {
|
|
|
|
|
const message = chatMessages[i];
|
2023-12-19 00:13:39 +08:00
|
|
|
|
if (i == startIndex) { // 判断一下在页面顶部多加一个时间
|
|
|
|
|
if (!/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(message.text)) {
|
|
|
|
|
// 时间戳转成时间
|
|
|
|
|
function timestampToTime(timestamp) {
|
|
|
|
|
let date = new Date(timestamp * 1000);
|
|
|
|
|
let year = date.getFullYear() + '-';
|
|
|
|
|
let month = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
|
|
|
|
|
let day = (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + ' ';
|
|
|
|
|
let hour = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
|
|
|
|
|
let minute = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
|
|
|
|
|
let second = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
|
|
|
|
|
return year + month + day + hour + minute + second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加div
|
|
|
|
|
const newTimeMessage = document.createElement('div');
|
|
|
|
|
newTimeMessage.className = "item item-center";
|
|
|
|
|
newTimeMessage.innerHTML = `<span>${timestampToTime(message.timestamp)}</span>`;
|
|
|
|
|
chatContainer.appendChild(newTimeMessage);
|
|
|
|
|
console.log("增加时间元素", timestampToTime(message.timestamp));
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
const messageElement = document.createElement('div'); // 下面那俩的合体
|
|
|
|
|
const avatarTag = avatarBox(message); // 头像
|
|
|
|
|
const messageContent = document.createElement('div'); // 除了avatar之外的所有
|
|
|
|
|
const side = message.is_send ? "right" : "left";
|
2023-12-11 12:52:44 +08:00
|
|
|
|
if (message.type == 1) {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
// displayname 和 bubble
|
2023-12-17 19:37:16 +08:00
|
|
|
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.is_chatroom && !message.is_send) {
|
|
|
|
|
messageContent.appendChild(displayNameBox(message));
|
2023-12-07 23:23:55 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
messageContent.appendChild(messageBubble(message, side));
|
2023-12-19 00:13:39 +08:00
|
|
|
|
|
2023-12-17 18:33:06 +08:00
|
|
|
|
// 整合
|
|
|
|
|
messageElement.className = `item item-${side}`;
|
|
|
|
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
|
|
|
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
else if (message.type == 0) {
|
2023-11-22 00:22:50 +08:00
|
|
|
|
messageElement.className = "item item-center";
|
2023-12-19 00:13:39 +08:00
|
|
|
|
messageElement.innerHTML = `<span>${message.text}</span>`;
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
else if (message.type == 3) {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
// displayname 和 img
|
2023-12-17 19:37:16 +08:00
|
|
|
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.is_chatroom && !message.is_send) {
|
|
|
|
|
messageContent.appendChild(displayNameBox(message));
|
2023-12-07 23:23:55 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
messageContent.appendChild(messageImgBox(message));
|
|
|
|
|
|
|
|
|
|
// 整合
|
|
|
|
|
messageElement.className = `item item-${side}`;
|
|
|
|
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
|
|
|
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
2023-12-07 23:23:55 +08:00
|
|
|
|
else if (message.type == 43) {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
// displayname 和 video
|
2023-12-17 19:37:16 +08:00
|
|
|
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.is_chatroom && !message.is_send) {
|
|
|
|
|
messageContent.appendChild(displayNameBox(message));
|
2023-12-07 23:23:55 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
messageContent.appendChild(messageVideoBox(message));
|
|
|
|
|
|
|
|
|
|
// 整合
|
|
|
|
|
messageElement.className = `item item-${side}`;
|
|
|
|
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
|
|
|
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
2023-11-27 19:26:31 +08:00
|
|
|
|
}
|
2023-12-11 22:49:17 +08:00
|
|
|
|
else if (message.type == 49) {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.sub_type == 57) {
|
|
|
|
|
// displayname 和 bubble 和 refer
|
2023-12-17 19:37:16 +08:00
|
|
|
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.is_chatroom && !message.is_send) {
|
|
|
|
|
messageContent.appendChild(displayNameBox(message));
|
2023-12-11 22:49:17 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
messageContent.appendChild(messageBubble(message, side));
|
|
|
|
|
if (message.refer_text) {
|
|
|
|
|
messageContent.appendChild(messageElementReferText(message, side));
|
2023-12-11 22:49:17 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
|
|
|
|
|
// 整合
|
|
|
|
|
messageElement.className = `item item-${side}`;
|
|
|
|
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
|
|
|
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
2023-12-11 22:49:17 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-12 01:17:21 +08:00
|
|
|
|
else if (message.type == 34) {
|
2023-12-17 18:33:06 +08:00
|
|
|
|
// displayname 和 转的文字 和 audio
|
2023-12-17 19:37:16 +08:00
|
|
|
|
messageContent.className = `content-wrapper content-wrapper-${side}`;
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.is_chatroom && !message.is_send) {
|
|
|
|
|
messageContent.appendChild(displayNameBox(message));
|
2023-12-12 01:17:21 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
if (message.voice_to_text) {
|
|
|
|
|
messageContent.appendChild(messageVoiceToTextBubble(message, side));
|
2023-12-12 01:17:21 +08:00
|
|
|
|
}
|
2023-12-17 18:33:06 +08:00
|
|
|
|
messageContent.appendChild(messageAudioBox(message));
|
|
|
|
|
|
|
|
|
|
// 整合
|
|
|
|
|
messageElement.className = `item item-${side}`;
|
|
|
|
|
messageElement.appendChild(message.is_send ? messageContent : avatarTag);
|
|
|
|
|
messageElement.appendChild(message.is_send ? avatarTag : messageContent);
|
2023-12-12 01:17:21 +08:00
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
chatContainer.appendChild(messageElement);
|
2023-12-11 12:52:44 +08:00
|
|
|
|
}
|
|
|
|
|
document.querySelector("#chat-container").scrollTop = 0;
|
|
|
|
|
updatePaginationInfo();
|
2023-12-17 20:19:29 +08:00
|
|
|
|
refreshMediaListener();
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
function prevPage() {
|
|
|
|
|
if (currentPage > 1) {
|
|
|
|
|
currentPage--;
|
|
|
|
|
renderPage(currentPage);
|
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
function nextPage() {
|
|
|
|
|
const totalPages = Math.ceil(chatMessages.length / itemsPerPage);
|
|
|
|
|
if (currentPage < totalPages) {
|
|
|
|
|
currentPage++;
|
|
|
|
|
renderPage(currentPage);
|
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
2023-12-11 12:52:44 +08:00
|
|
|
|
function updatePaginationInfo() {
|
|
|
|
|
const totalPages = Math.ceil(chatMessages.length / itemsPerPage);
|
|
|
|
|
const paginationInfo = document.getElementById('paginationInfo');
|
|
|
|
|
paginationInfo.textContent = `共 ${totalPages} 页,当前第 ${currentPage} 页`;
|
|
|
|
|
}
|
|
|
|
|
function gotoPage() {
|
|
|
|
|
const totalPages = Math.ceil(chatMessages.length / itemsPerPage);
|
|
|
|
|
const inputElement = document.getElementById('gotoPageInput');
|
|
|
|
|
const targetPage = parseInt(inputElement.value);
|
|
|
|
|
|
|
|
|
|
if (targetPage >= 1 && targetPage <= totalPages) {
|
|
|
|
|
currentPage = targetPage;
|
|
|
|
|
renderPage(currentPage);
|
|
|
|
|
} else {
|
|
|
|
|
alert('请输入有效的页码');
|
|
|
|
|
}
|
2023-11-22 00:22:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-11 12:52:44 +08:00
|
|
|
|
// 初始化页面
|
|
|
|
|
renderPage(currentPage);
|
2023-12-17 20:19:29 +08:00
|
|
|
|
|
|
|
|
|
function refreshMediaListener() {
|
|
|
|
|
const audioTags = document.querySelectorAll('audio');
|
|
|
|
|
const videoTags = document.querySelectorAll('video');
|
|
|
|
|
|
|
|
|
|
audioTags.forEach(audio => {
|
|
|
|
|
audio.addEventListener('play', function () {
|
|
|
|
|
pauseOtherMedia(audio);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
videoTags.forEach(video => {
|
|
|
|
|
video.addEventListener('play', function () {
|
|
|
|
|
pauseOtherMedia(video);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function pauseOtherMedia(currentMedia) {
|
|
|
|
|
const audioTags = document.querySelectorAll('audio');
|
|
|
|
|
const videoTags = document.querySelectorAll('video');
|
|
|
|
|
audioTags.forEach(media => {
|
|
|
|
|
if (media !== currentMedia && !media.paused) {
|
|
|
|
|
media.pause();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
videoTags.forEach(media => {
|
|
|
|
|
if (media !== currentMedia && !media.paused) {
|
|
|
|
|
media.pause();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
refreshMediaListener();
|
2023-11-22 00:22:50 +08:00
|
|
|
|
</script>
|
2023-12-03 22:19:25 +08:00
|
|
|
|
|
|
|
|
|
<script>
|
2023-12-11 12:52:44 +08:00
|
|
|
|
function showModal(image) {
|
|
|
|
|
var modal = document.getElementById("modal");
|
|
|
|
|
var modalImage = document.getElementById("modal-image");
|
|
|
|
|
modal.style.display = "block";
|
|
|
|
|
modalImage.src = image.src;
|
|
|
|
|
console.log(image.src);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hideModal() {
|
|
|
|
|
var modal = document.getElementById("modal");
|
|
|
|
|
modal.style.display = "none";
|
|
|
|
|
}
|
2023-12-03 22:19:25 +08:00
|
|
|
|
</script>
|
2023-11-21 22:23:23 +08:00
|
|
|
|
</body>
|
|
|
|
|
</html>
|
2023-11-22 00:22:50 +08:00
|
|
|
|
'''
|