恢复聊天室第二代
@ -0,0 +1,9 @@
|
||||
import wx
|
||||
|
||||
class voice_frame(wx.Frame):
|
||||
def __init__(self,Id):
|
||||
super().__init__()
|
||||
panel = wx.Panel(self)
|
||||
box = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
|
299
python/code/chat_room/Chat_Room_Second/Client/Page/Chat_main.py
Normal file
@ -0,0 +1,299 @@
|
||||
import wx.richtext as rt
|
||||
import os
|
||||
import wx
|
||||
import time
|
||||
import multiprocessing
|
||||
|
||||
from Client.Transmission.Process_Client import ProcessClient
|
||||
|
||||
|
||||
class ChatFrame(wx.Frame, ProcessClient):
|
||||
def __init__(self, Id):
|
||||
wx.Frame.__init__(self, None, size=(800, 600), title="账号: " + str(Id))
|
||||
ProcessClient.__init__(self)
|
||||
self.userid = Id
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
ChatMain_Panel = wx.Panel(self, style=wx.BORDER_SUNKEN)
|
||||
ChatMain_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
ChatMain_Panel.SetSizer(ChatMain_box)
|
||||
|
||||
Function_Panel = wx.Panel(ChatMain_Panel, style=wx.BORDER_RAISED)
|
||||
Function_box = wx.BoxSizer(wx.VERTICAL)
|
||||
Function_Panel.SetSizer(Function_box)
|
||||
Function_Panel.SetBackgroundColour(wx.Colour(240, 240, 240))
|
||||
|
||||
image_chat = r'./Client/image/chat.png'
|
||||
Chat_bitmap = wx.Bitmap(image_chat, wx.BITMAP_TYPE_PNG)
|
||||
Chat_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=Chat_bitmap, style=wx.BORDER_RAISED)
|
||||
Chat_bitmap_static.SetToolTip("聊天")
|
||||
Function_box.Add(Chat_bitmap_static, 1, wx.EXPAND, 0)
|
||||
Chat_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_chat_button)
|
||||
|
||||
Function_box.AddSpacer(20) # 调整这个数字以改变间距大小
|
||||
|
||||
image_connect = r'./Client/image/connect.png'
|
||||
connect_bitmap = wx.Bitmap(image_connect, wx.BITMAP_TYPE_PNG)
|
||||
connect_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=connect_bitmap, style=wx.BORDER_RAISED)
|
||||
connect_bitmap_static.SetToolTip("通讯录")
|
||||
Function_box.Add(connect_bitmap_static, 1, wx.EXPAND, 0)
|
||||
connect_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_connect_button)
|
||||
|
||||
Function_box.AddSpacer(20) # 调整这个数字以改变间距大小
|
||||
|
||||
image_find = r'./Client/image/find.png'
|
||||
find_bitmap = wx.Bitmap(image_find, wx.BITMAP_TYPE_PNG)
|
||||
find_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=find_bitmap, style=wx.BORDER_RAISED)
|
||||
find_bitmap_static.SetToolTip("查找")
|
||||
Function_box.Add(find_bitmap_static, 1, wx.EXPAND, 0)
|
||||
find_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_find_button)
|
||||
|
||||
Function_box.AddSpacer(280) # 调整这个数字以改变间距大小
|
||||
|
||||
image_site = r'./Client/image/site.png'
|
||||
site_bitmap = wx.Bitmap(image_site, wx.BITMAP_TYPE_PNG)
|
||||
site_bitmap_static = wx.StaticBitmap(Function_Panel, bitmap=site_bitmap, style=wx.BORDER_RAISED)
|
||||
site_bitmap_static.SetToolTip("设置")
|
||||
Function_box.Add(site_bitmap_static, 1, wx.EXPAND, 0)
|
||||
site_bitmap_static.Bind(wx.EVT_LEFT_DOWN, self.click_site_button)
|
||||
|
||||
Function_box.Fit(Function_Panel) # 调整面板大小以适应图像
|
||||
|
||||
ChatMain_box.Add(Function_Panel, 0, wx.EXPAND | wx.ALL, 5)
|
||||
|
||||
operate_box = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.chat_page = self.ChatPage(ChatMain_Panel) # 将 ChatMain_Panel 作为 ChatPage 的 parent
|
||||
operate_box.Add(self.chat_page, 1, wx.EXPAND, 5)
|
||||
self.chat_page.Hide()
|
||||
|
||||
self.Process_client_send("File_operate", "read_data", None)
|
||||
|
||||
self.connect_page = self.ConnectPage(ChatMain_Panel)
|
||||
operate_box.Add(self.connect_page, 1, wx.EXPAND, 5)
|
||||
self.connect_page.Hide()
|
||||
|
||||
self.site_page = self.SitePage(ChatMain_Panel)
|
||||
operate_box.Add(self.site_page, 1, wx.EXPAND, 5)
|
||||
self.site_page.Hide()
|
||||
|
||||
self.find_page = self.FindPage(ChatMain_Panel)
|
||||
operate_box.Add(self.find_page, 1, wx.EXPAND, 5)
|
||||
self.find_page.Hide()
|
||||
|
||||
ChatMain_box.Add(operate_box, 1, wx.EXPAND, 5)
|
||||
|
||||
self.chat_page.Show()
|
||||
|
||||
ChatMain_Panel.SetSizer(ChatMain_box)
|
||||
|
||||
def click_chat_button(self, event):
|
||||
self.chat_page.Hide()
|
||||
self.connect_page.Hide()
|
||||
self.site_page.Hide()
|
||||
self.find_page.Hide()
|
||||
self.chat_page.Show()
|
||||
self.Layout()
|
||||
|
||||
def click_connect_button(self, event):
|
||||
self.chat_page.Hide()
|
||||
self.connect_page.Hide()
|
||||
self.site_page.Hide()
|
||||
self.find_page.Hide()
|
||||
self.connect_page.Show()
|
||||
self.Layout()
|
||||
|
||||
def click_site_button(self, event):
|
||||
self.chat_page.Hide()
|
||||
self.connect_page.Hide()
|
||||
self.site_page.Hide()
|
||||
self.find_page.Hide()
|
||||
self.site_page.Show()
|
||||
self.Layout()
|
||||
|
||||
def click_find_button(self, event):
|
||||
self.chat_page.Hide()
|
||||
self.connect_page.Hide()
|
||||
self.site_page.Hide()
|
||||
self.find_page.Hide()
|
||||
self.find_page.Show()
|
||||
self.Layout()
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'Chat_main']:
|
||||
match data['function']:
|
||||
case 'ChatPage_add_Contact_person':
|
||||
data = data['content']
|
||||
Contact = data['Contact']
|
||||
Remark = data['Remark']
|
||||
Time = data['UpDataTime']
|
||||
state = data['state']
|
||||
if state:
|
||||
wx.CallAfter(self.chat_page.ChatPage_add_Contact_person, Contact, Remark)
|
||||
case 'Chat_screen_show':
|
||||
Contact = None
|
||||
data = data['content']
|
||||
send = data['Send']
|
||||
receive = data['Receive']
|
||||
Type = data['Type']
|
||||
content = data['Content']
|
||||
UpDataTime = data['Time']
|
||||
if send == str(self.userid):
|
||||
Contact = receive
|
||||
elif receive == str(self.userid):
|
||||
Contact = send
|
||||
wx.CallAfter(self.chat_page.Chat_screen_show, Contact, send, receive, Type, content, UpDataTime)
|
||||
|
||||
class ChatPage(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent, style=wx.BORDER_SUNKEN)
|
||||
|
||||
ChatPage_main_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.chat_page_map = {}
|
||||
self.chat_page_ids = []
|
||||
self.current_chat_page = None # 新增的属性用于跟踪当前显示的聊天面板
|
||||
|
||||
self.ChatPage_Listbook = wx.Listbook(self, style=wx.LB_LEFT)
|
||||
self.ChatPage_Listbook.Bind(wx.EVT_LISTBOOK_PAGE_CHANGED, self.on_page_changed)
|
||||
|
||||
ChatPage_main_box.Add(self.ChatPage_Listbook, 1, wx.EXPAND, 0)
|
||||
self.SetSizer(ChatPage_main_box)
|
||||
|
||||
def ChatPage_add_Contact_person(self, Id, Remark):
|
||||
contact_page = wx.Panel(self.ChatPage_Listbook)
|
||||
self.ChatPage_Listbook.AddPage(contact_page, Remark)
|
||||
chat_page = self.ChatPage_add_Contact_tab(Id)
|
||||
|
||||
self.chat_page_map[Id] = chat_page
|
||||
self.chat_page_ids.append(Id)
|
||||
# 隐藏当前的聊天面板
|
||||
if self.current_chat_page:
|
||||
self.current_chat_page.Hide()
|
||||
# 将新的聊天面板添加到ChatPage_main_box中
|
||||
self.GetSizer().Add(chat_page, 5, wx.EXPAND)
|
||||
# 显示新的聊天面板
|
||||
chat_page.Show()
|
||||
# 更新当前显示的聊天面板
|
||||
self.current_chat_page = chat_page
|
||||
chat_page.Show()
|
||||
# 重新布局
|
||||
self.Layout()
|
||||
|
||||
def ChatPage_add_Contact_tab(self, Id):
|
||||
chat_panel = wx.Panel(self)
|
||||
chat_box = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
chat_panel.contact_id = Id
|
||||
|
||||
chat_receive_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
chat_panel.chat_receive_text = rt.RichTextCtrl(chat_panel,
|
||||
style=wx.VSCROLL | wx.HSCROLL | wx.NO_BORDER | wx.WANTS_CHARS)
|
||||
chat_receive_box.Add(chat_panel.chat_receive_text, 1, wx.EXPAND, 0)
|
||||
chat_box.Add(chat_receive_box, 2, wx.EXPAND, 0)
|
||||
|
||||
toolbar = wx.ToolBar(chat_panel)
|
||||
toolbar.SetToolBitmapSize((16, 16)) # Set the size of the toolbar icons
|
||||
toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/picture.png')))
|
||||
toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/file.png')))
|
||||
toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/speech.png')))
|
||||
toolbar.AddTool(wx.ID_ANY, "Tool", wx.Bitmap(wx.Bitmap(r'./Client/image/video.png')))
|
||||
toolbar.Realize()
|
||||
toolbar.SetSize((-1, 30)) # Set the size of the toolbar
|
||||
chat_box.Add(toolbar, 0, wx.EXPAND)
|
||||
|
||||
chat_send_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
chat_panel.chat_send_text = wx.TextCtrl(chat_panel, style=wx.TE_MULTILINE)
|
||||
chat_send_box.Add(chat_panel.chat_send_text, 1, wx.EXPAND, 0)
|
||||
chat_box.Add(chat_send_box, 1, wx.EXPAND, 0)
|
||||
|
||||
send_button = wx.Button(chat_panel, label='发送') # Create a send button
|
||||
send_button.Bind(wx.EVT_BUTTON, self.on_send_button_click)
|
||||
chat_send_box.Add(send_button, 0, wx.EXPAND | wx.LEFT, 5) # Add the button to the send box
|
||||
|
||||
chat_panel.SetSizer(chat_box)
|
||||
|
||||
return chat_panel
|
||||
|
||||
def Chat_screen_show(self, Contact, send, receive, Type, data, UpDataTime):
|
||||
chat_panel = self.chat_page_map[Contact]
|
||||
if Type == 'text':
|
||||
# 确定对齐方式
|
||||
if Contact == receive:
|
||||
alignment = wx.TEXT_ALIGNMENT_RIGHT
|
||||
else:
|
||||
alignment = wx.TEXT_ALIGNMENT_LEFT
|
||||
# 开始设置对齐
|
||||
chat_panel.chat_receive_text.BeginAlignment(alignment)
|
||||
# 按每30个字符分割消息内容并写入
|
||||
contents = [data[i:i + 30] for i in range(0, len(data), 30)]
|
||||
contents.append(UpDataTime) # 添加时间戳
|
||||
for content in contents:
|
||||
chat_panel.chat_receive_text.WriteText(content + '\n') # WriteText处理换行
|
||||
# 结束对齐设置
|
||||
chat_panel.chat_receive_text.EndAlignment()
|
||||
# 添加额外的新行(如果需要)
|
||||
chat_panel.chat_receive_text.Newline()
|
||||
|
||||
# 在添加完所有消息后
|
||||
chat_panel.chat_receive_text.ShowPosition(chat_panel.chat_receive_text.GetLastPosition())
|
||||
chat_panel.Refresh()
|
||||
chat_panel.Update()
|
||||
self.Layout()
|
||||
|
||||
def on_send_button_click(self, event):
|
||||
button = event.GetEventObject()
|
||||
chat_panel = button.GetParent()
|
||||
send_text = chat_panel.chat_send_text.GetValue() # 正确获取输入框内容
|
||||
contact_id = str(chat_panel.contact_id) # 获取联系人ID
|
||||
if send_text == '':
|
||||
return
|
||||
|
||||
self.Chat_screen_show(contact_id, None, contact_id, 'text', send_text,
|
||||
time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
|
||||
|
||||
data = {"Type": "text", "content": send_text}
|
||||
|
||||
content = {"genre": '聊天记录', "target": contact_id, "content": data}
|
||||
|
||||
top_frame = self.GetTopLevelParent()
|
||||
|
||||
top_frame.Process_client_send('Session_server', 'send_server', content)
|
||||
chat_panel.chat_send_text.SetValue('') # 清空输入框
|
||||
event.Skip()
|
||||
|
||||
def on_page_changed(self, event):
|
||||
# 获取当前选定的页面的索引
|
||||
current_page_index = self.ChatPage_Listbook.GetSelection()
|
||||
# 通过索引从chat_page_ids列表中获取对应的Id
|
||||
current_page_id = self.chat_page_ids[current_page_index]
|
||||
# 从chat_page_map中找到对应的聊天面板
|
||||
new_chat_page = self.chat_page_map[current_page_id]
|
||||
# 隐藏旧的聊天面板
|
||||
if self.current_chat_page:
|
||||
self.current_chat_page.Hide()
|
||||
# 显示新的聊天面板
|
||||
new_chat_page.Show()
|
||||
# 更新当前显示的聊天面板
|
||||
self.current_chat_page = new_chat_page
|
||||
# 重新布局
|
||||
self.Layout()
|
||||
# 处理完事件后,不要忘记调用event.Skip(),以便事件可以继续传播到其他处理器
|
||||
event.Skip()
|
||||
|
||||
class ConnectPage(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent)
|
||||
print("联系人")
|
||||
|
||||
class SitePage(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent)
|
||||
print("设置")
|
||||
|
||||
class FindPage(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent)
|
||||
print("查找")
|
270
python/code/chat_room/Chat_Room_Second/Client/Page/Login.py
Normal file
@ -0,0 +1,270 @@
|
||||
import json
|
||||
import multiprocessing
|
||||
import os
|
||||
|
||||
import wx
|
||||
import threading
|
||||
import time
|
||||
from Client.Transmission.Process_Client import ProcessClient
|
||||
from .Chat_main import ChatFrame
|
||||
|
||||
|
||||
def open_chat_window(Id):
|
||||
app = wx.App()
|
||||
ChatFrame(Id).Show()
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
class LoginFrame(wx.Frame, ProcessClient):
|
||||
def __init__(self):
|
||||
wx.Frame.__init__(self, None, id=-1, title='登录', pos=wx.DefaultPosition, size=(380, 300))
|
||||
ProcessClient.__init__(self)
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
# 创建菜单栏
|
||||
menu_bar = wx.MenuBar()
|
||||
|
||||
# 登录菜单
|
||||
login_menu = wx.Menu()
|
||||
menu_bar.Append(login_menu, "登录")
|
||||
|
||||
# 更多菜单
|
||||
more_menu = wx.Menu()
|
||||
self.register_id = wx.NewId()
|
||||
self.set_server_id = wx.NewId()
|
||||
more_menu.Append(self.register_id, "注册账号")
|
||||
more_menu.Append(self.set_server_id, "服务器设置")
|
||||
menu_bar.Append(more_menu, "更多")
|
||||
|
||||
self.SetMenuBar(menu_bar)
|
||||
|
||||
# 创建状态栏
|
||||
self.status_bar = self.CreateStatusBar(2)
|
||||
self.server_status = False # 服务器状态
|
||||
status_thread = threading.Thread(target=self.update_status_bar(None), daemon=True)
|
||||
status_thread.start()
|
||||
|
||||
# 启动定时器,每秒钟触发一次
|
||||
self.timer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.update_status_bar, self.timer)
|
||||
self.timer.Start(1000) # 设置定时器间隔为1000毫秒(1秒
|
||||
|
||||
# 获取菜单点击事件
|
||||
self.Bind(wx.EVT_MENU, self.click_menu, id=self.register_id)
|
||||
self.Bind(wx.EVT_MENU, self.click_menu, id=self.set_server_id)
|
||||
self.Bind(wx.EVT_MENU_OPEN, self.click_menu_title)
|
||||
|
||||
# 创建注册面板
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.login_panel = LoginPanel(self)
|
||||
self.register_panel = RegisterPanel(self)
|
||||
self.sizer.Add(self.login_panel, 1, wx.EXPAND)
|
||||
self.sizer.Add(self.register_panel, 1, wx.EXPAND)
|
||||
|
||||
self.login_panel.Hide()
|
||||
self.register_panel.Hide()
|
||||
|
||||
self.login_panel.Show()
|
||||
|
||||
# 主页按钮绑定
|
||||
self.Bind(wx.EVT_BUTTON, self.send_login_button, self.login_panel.LoginPanel_login_label)
|
||||
self.Bind(wx.EVT_BUTTON, self.send_register_button, self.register_panel.RegisterPanel_login_label)
|
||||
|
||||
self.SetSizer(self.sizer)
|
||||
|
||||
def update_status_bar(self, event):
|
||||
if self.server_status:
|
||||
self.status_bar.SetStatusText("服务器\t已连接", 0)
|
||||
else:
|
||||
self.status_bar.SetStatusText("服务器\t未连接", 0)
|
||||
|
||||
self.status_bar.SetStatusText("时间\t" + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 1)
|
||||
|
||||
def click_menu_title(self, event):
|
||||
menu = event.GetMenu()
|
||||
menu_title = menu.GetTitle()
|
||||
if menu_title == "登录":
|
||||
self.login_panel.Hide()
|
||||
self.register_panel.Hide()
|
||||
self.login_panel.Show()
|
||||
self.Layout()
|
||||
|
||||
# 点击菜单检测
|
||||
def click_menu(self, event):
|
||||
menu_id = event.GetId()
|
||||
if menu_id == self.register_id:
|
||||
self.login_panel.Hide()
|
||||
self.register_panel.Hide()
|
||||
self.register_panel.Show()
|
||||
self.Layout()
|
||||
elif menu_id == self.set_server_id:
|
||||
self.login_panel.Hide()
|
||||
self.register_panel.Hide()
|
||||
self.Layout()
|
||||
|
||||
def login_page_receive(self, receive_content):
|
||||
if receive_content["genre"] == '登录':
|
||||
match receive_content["data"]['status']:
|
||||
case 0:
|
||||
self.Process_client_send("File_operate", "detection_data", receive_content["data"]['account'])
|
||||
wx.MessageBox('登录成功正在获取数据', '登录', wx.OK | wx.ICON_INFORMATION)
|
||||
case -1:
|
||||
wx.MessageBox('重复登录', '登录', wx.OK | wx.ICON_INFORMATION)
|
||||
case 1:
|
||||
wx.MessageBox('密码错误', '登录', wx.OK | wx.ICON_INFORMATION)
|
||||
case 2:
|
||||
wx.MessageBox('未找到该账号', '登录', wx.OK | wx.ICON_INFORMATION)
|
||||
elif receive_content["genre"] == '注册':
|
||||
wx.MessageBox(
|
||||
f'注册成功\n网名 : {receive_content["data"]['NetName']} \n账号 : {receive_content["data"]['Id']} \n密码 : {receive_content["data"]['Password']}',
|
||||
'注册', wx.OK | wx.ICON_INFORMATION)
|
||||
|
||||
def send_login_button(self, event):
|
||||
if self.server_status:
|
||||
account = self.login_panel.LoginPanel_account_text.GetValue().strip()
|
||||
password = self.login_panel.LoginPanel_password_text.GetValue().strip()
|
||||
content = {'account': account, 'password': password}
|
||||
target = "服务器"
|
||||
genre = "登录"
|
||||
data = {"genre": genre, "target": target, "content": content}
|
||||
if account and password:
|
||||
self.Process_client_send("Session_server", "send_server", data)
|
||||
|
||||
|
||||
def send_register_button(self, event):
|
||||
if self.server_status:
|
||||
account = self.register_panel.RegisterPanel_account_text.GetValue().strip()
|
||||
password = self.register_panel.RegisterPanel_password_text.GetValue().strip()
|
||||
content = {'account': account, 'password': password}
|
||||
target = "服务器"
|
||||
genre = "注册"
|
||||
data = {"genre": genre, "target": target, "content": content}
|
||||
if account and password:
|
||||
self.Process_client_send("Session_server", "send_server", data)
|
||||
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'Login']:
|
||||
match data['function']:
|
||||
case 'server_status':
|
||||
self.server_status = data['content']
|
||||
case 'login_page_receive':
|
||||
self.login_page_receive(data['content'])
|
||||
case '更新完成':
|
||||
multiprocessing.Process(target=open_chat_window, args=(data['content'],)).start()
|
||||
self.Destroy()
|
||||
|
||||
|
||||
|
||||
class LoginPanel(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
# 主盒子
|
||||
LoginPanel_main_box = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
# 顶部盒子,目前只放了软件名
|
||||
LoginPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子
|
||||
LoginPanel_show_title = wx.StaticText(self, label='登录')
|
||||
LoginPanel_show_title.SetFont(wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
LoginPanel_top_box.Add(LoginPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10)
|
||||
LoginPanel_main_box.Add(LoginPanel_top_box, 0, wx.EXPAND)
|
||||
|
||||
# 中部盒子,放账号和密码
|
||||
LoginPanel_content_box = wx.BoxSizer(wx.VERTICAL)
|
||||
# 账号
|
||||
LoginPanel_account_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
LoginPanel_account_label = wx.StaticText(self, label=' 账号:')
|
||||
LoginPanel_account_label.SetFont(
|
||||
wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
LoginPanel_account_box.Add(LoginPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.LoginPanel_account_text = wx.TextCtrl(self, size=(300, 30))
|
||||
self.LoginPanel_account_text.SetHint('请输入账号')
|
||||
LoginPanel_account_box.Add(self.LoginPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL)
|
||||
LoginPanel_content_box.Add(LoginPanel_account_box)
|
||||
# 添加空白控件来增加间距
|
||||
LoginPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5)
|
||||
# 密码
|
||||
LoginPanel_password_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
LoginPanel_password_label = wx.StaticText(self, label=' 密码:')
|
||||
LoginPanel_password_label.SetFont(
|
||||
wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
LoginPanel_password_box.Add(LoginPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.LoginPanel_password_text = wx.TextCtrl(self, size=(300, 30))
|
||||
self.LoginPanel_password_text.SetHint('请输入密码')
|
||||
LoginPanel_password_box.Add(self.LoginPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL)
|
||||
LoginPanel_content_box.Add(LoginPanel_password_box)
|
||||
LoginPanel_main_box.Add(LoginPanel_content_box, 0, wx.EXPAND)
|
||||
|
||||
# 底部盒子
|
||||
LoginPanel_bottom_box = wx.BoxSizer(wx.VERTICAL)
|
||||
# 登录按钮
|
||||
LoginPanel_login_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局
|
||||
self.LoginPanel_login_label = wx.Button(self, size=(200, 50), label='登录')
|
||||
LoginPanel_login_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间
|
||||
LoginPanel_login_box.Add(self.LoginPanel_login_label, 0, wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中
|
||||
LoginPanel_login_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间
|
||||
LoginPanel_bottom_box.Add(LoginPanel_login_box, 1,
|
||||
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐
|
||||
LoginPanel_main_box.Add(LoginPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间
|
||||
|
||||
self.SetSizer(LoginPanel_main_box)
|
||||
|
||||
|
||||
class RegisterPanel(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
|
||||
# 主盒子
|
||||
RegisterPanel_main_box = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
# 顶部盒子,目前只放了软件名
|
||||
RegisterPanel_top_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子
|
||||
RegisterPanel_show_title = wx.StaticText(self, label='注册')
|
||||
RegisterPanel_show_title.SetFont(
|
||||
wx.Font(30, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
RegisterPanel_top_box.Add(RegisterPanel_show_title, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10)
|
||||
RegisterPanel_main_box.Add(RegisterPanel_top_box, 0, wx.EXPAND)
|
||||
|
||||
# 中部盒子,放账号和密码
|
||||
RegisterPanel_content_box = wx.BoxSizer(wx.VERTICAL)
|
||||
# 账号
|
||||
RegisterPanel_account_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
RegisterPanel_account_label = wx.StaticText(self, label=' 用户名:')
|
||||
RegisterPanel_account_label.SetFont(
|
||||
wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
RegisterPanel_account_box.Add(RegisterPanel_account_label, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.RegisterPanel_account_text = wx.TextCtrl(self, size=(300, 30))
|
||||
self.RegisterPanel_account_text.SetHint('请输入用户名')
|
||||
RegisterPanel_account_box.Add(self.RegisterPanel_account_text, 1, wx.ALIGN_CENTER_VERTICAL)
|
||||
RegisterPanel_content_box.Add(RegisterPanel_account_box)
|
||||
# 添加空白控件来增加间距
|
||||
RegisterPanel_content_box.Add(wx.StaticText(self, label=''), 0, wx.ALL, 5)
|
||||
# 密码
|
||||
RegisterPanel_password_box = wx.BoxSizer(wx.HORIZONTAL)
|
||||
RegisterPanel_password_label = wx.StaticText(self, label=' 密码: ')
|
||||
RegisterPanel_password_label.SetFont(
|
||||
wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
|
||||
RegisterPanel_password_box.Add(RegisterPanel_password_label, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
self.RegisterPanel_password_text = wx.TextCtrl(self, size=(300, 30))
|
||||
self.RegisterPanel_password_text.SetHint('请输入密码')
|
||||
RegisterPanel_password_box.Add(self.RegisterPanel_password_text, 1, wx.ALIGN_CENTER_VERTICAL)
|
||||
RegisterPanel_content_box.Add(RegisterPanel_password_box)
|
||||
RegisterPanel_main_box.Add(RegisterPanel_content_box, 0, wx.EXPAND)
|
||||
|
||||
# 底部盒子
|
||||
RegisterPanel_bottom_box = wx.BoxSizer(wx.VERTICAL)
|
||||
# 登录按钮
|
||||
RegisterPanel_register_box = wx.BoxSizer(wx.VERTICAL) # 使用垂直盒子布局
|
||||
self.RegisterPanel_login_label = wx.Button(self, size=(200, 50), label='确认')
|
||||
RegisterPanel_register_box.AddStretchSpacer() # 添加一个可伸缩的空间,将登录按钮推到垂直中间
|
||||
RegisterPanel_register_box.Add(self.RegisterPanel_login_label, 0,
|
||||
wx.ALIGN_CENTER_HORIZONTAL) # 将登录按钮添加到垂直盒子中
|
||||
RegisterPanel_register_box.AddStretchSpacer() # 再次添加一个可伸缩的空间,将登录按钮推到垂直中间
|
||||
RegisterPanel_bottom_box.Add(RegisterPanel_register_box, 1,
|
||||
wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER_HORIZONTAL) # 将垂直盒子添加到底部盒子中,设置垂直和水平居中对齐
|
||||
RegisterPanel_main_box.Add(RegisterPanel_bottom_box, 1, wx.EXPAND) # 将底部盒子添加到主盒子中,使其填满剩余空间
|
||||
|
||||
self.SetSizer(RegisterPanel_main_box)
|
@ -0,0 +1,2 @@
|
||||
from .Chat_main import *
|
||||
from .Login import *
|
@ -0,0 +1,103 @@
|
||||
import os
|
||||
import csv
|
||||
import time
|
||||
|
||||
from .Process_Client import ProcessClient
|
||||
|
||||
|
||||
class FileOperate(ProcessClient):
|
||||
def __init__(self, user_id):
|
||||
ProcessClient.__init__(self)
|
||||
|
||||
self.user_id = user_id
|
||||
|
||||
self.root_path = None
|
||||
self.Account_path = None
|
||||
self.Contacts_path = None
|
||||
self.History_path = None
|
||||
self.file_root_path = None
|
||||
self.other_file_path = None
|
||||
self.image_file_path = None
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
def detection_data(self, Id):
|
||||
self.user_id = Id
|
||||
self.root_path = rf'.\{Id}'
|
||||
self.Account_path = self.root_path + r'\Account.csv'
|
||||
self.Contacts_path = self.root_path + r'\Contacts.csv'
|
||||
self.History_path = self.root_path + r'\History.csv'
|
||||
self.file_root_path = self.root_path + r'\file'
|
||||
self.other_file_path = self.file_root_path + r'\other'
|
||||
self.image_file_path = self.file_root_path + r'\image'
|
||||
if not os.path.isdir(self.root_path):
|
||||
os.mkdir(self.root_path)
|
||||
if not os.path.isdir(self.file_root_path):
|
||||
os.mkdir(self.file_root_path)
|
||||
os.mkdir(self.other_file_path)
|
||||
os.mkdir(self.image_file_path)
|
||||
if not os.path.exists(self.Account_path):
|
||||
with open(self.Account_path, 'w', encoding='utf-8') as f:
|
||||
pass
|
||||
with open(self.Account_path, 'r+', encoding='utf-8') as info:
|
||||
data = csv.DictReader(info)
|
||||
if os.path.getsize(self.Account_path) == 0: # 检查文件大小是否为0
|
||||
date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(0))
|
||||
else:
|
||||
for d in data:
|
||||
date = d['UpDataTime']
|
||||
|
||||
target = "服务器"
|
||||
genre = "数据更新"
|
||||
data = {"genre": genre, "target": target, "content": date}
|
||||
self.Process_client_send("Session_server", "send_server", data)
|
||||
|
||||
def read_data(self):
|
||||
with open(self.Contacts_path, 'r', encoding='utf-8') as Contacts:
|
||||
data = csv.reader(Contacts)
|
||||
next(data)
|
||||
for i in data:
|
||||
content = {'Contact': i[0], 'Remark': i[1], 'state': i[2], 'UpDataTime': i[3]}
|
||||
self.Process_client_send("Chat_main", "ChatPage_add_Contact_person", content)
|
||||
with open(self.History_path, 'r', encoding='utf-8') as History_path:
|
||||
data = csv.reader(History_path)
|
||||
next(data)
|
||||
for i in data:
|
||||
content = {'Send': i[0], 'Receive': i[1], 'Type': i[2], 'Content': i[3], 'Time': i[4]}
|
||||
self.Process_client_send("Chat_main", "Chat_screen_show", content)
|
||||
|
||||
def save_data(self, data):
|
||||
target = list(data.keys())[0]
|
||||
data = list(data.values())[0]
|
||||
match target:
|
||||
case 'Account':
|
||||
with open(self.Account_path, 'w+', encoding='utf-8', newline='') as file:
|
||||
csv_file = csv.writer(file)
|
||||
csv_file.writerow(list(data.keys()))
|
||||
csv_file.writerow(list(data.values()))
|
||||
case 'Contacts':
|
||||
with open(self.Contacts_path, 'a+', encoding='utf-8', newline='') as file:
|
||||
csv_file = csv.writer(file)
|
||||
if os.path.getsize(self.Contacts_path) == 0: # 检查文件大小是否为0
|
||||
csv_file.writerow(list(data.keys()))
|
||||
csv_file.writerow(list(data.values()))
|
||||
case 'History':
|
||||
with open(self.History_path, 'a+', encoding='utf-8', newline='') as file:
|
||||
csv_file = csv.writer(file)
|
||||
if os.path.getsize(self.History_path) == 0: # 检查文件大小是否为0
|
||||
csv_file.writerow(list(data.keys()))
|
||||
csv_file.writerow(list(data.values()))
|
||||
case '更新完成':
|
||||
self.Process_client_send("ALL", "更新完成", eval(data))
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'File_operate']:
|
||||
match data['function']:
|
||||
case 'detection_data':
|
||||
self.detection_data(data['content'])
|
||||
case 'save_data':
|
||||
self.save_data(data['content'])
|
||||
case 'read_data':
|
||||
self.read_data()
|
@ -0,0 +1,31 @@
|
||||
import json
|
||||
import threading
|
||||
from multiprocessing.connection import Client
|
||||
|
||||
|
||||
class ProcessClient:
|
||||
def __init__(self):
|
||||
self.Process_port = 8727
|
||||
self.Process_server = 'localhost'
|
||||
self.Process_client_Client = Client((self.Process_server, self.Process_port))
|
||||
Process_client_recv = threading.Thread(target=self.Process_client_recv)
|
||||
Process_client_recv.start()
|
||||
|
||||
def Process_client_send(self, target, function, content):
|
||||
data = {"target": target, "function": function, "content": content}
|
||||
data_json = json.dumps(data)
|
||||
self.Process_client_Client.send(data_json)
|
||||
|
||||
def Process_client_recv(self):
|
||||
while True:
|
||||
try:
|
||||
data_json = self.Process_client_Client.recv()
|
||||
data = json.loads(data_json)
|
||||
self.Process_client_pick(data)
|
||||
|
||||
except ConnectionResetError as e:
|
||||
print("连接已关闭: " + str(e))
|
||||
break
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
pass
|
@ -0,0 +1,52 @@
|
||||
import json
|
||||
import multiprocessing
|
||||
from multiprocessing.connection import Listener
|
||||
import threading
|
||||
|
||||
|
||||
class ProcessServer:
|
||||
def __init__(self):
|
||||
try:
|
||||
self.Process_port = 8727
|
||||
self.Process_server = 'localhost'
|
||||
self.Process_server_listener = Listener((self.Process_server, self.Process_port))
|
||||
self.Process_client_link_dick = {}
|
||||
Process_client_link_Thread = threading.Thread(target=self.Process_client_link)
|
||||
Process_client_link_Thread.start()
|
||||
except:
|
||||
print("进程通信端口绑定失败")
|
||||
|
||||
def Process_client_link(self):
|
||||
while True:
|
||||
client_connect = self.Process_server_listener.accept()
|
||||
client_Thread_recv = threading.Thread(target=self.Process_client_recv, args=(client_connect,))
|
||||
client_Thread_recv.start()
|
||||
|
||||
def Process_client_recv(self, client_Thread_recv):
|
||||
while True:
|
||||
try:
|
||||
data_json = client_Thread_recv.recv()
|
||||
data = json.loads(data_json)
|
||||
if data['target'] == 'Server':
|
||||
if data['function'] == 'Name':
|
||||
self.Process_client_link_dick[data['content']] = client_Thread_recv
|
||||
else:
|
||||
self.Process_client_pick(data)
|
||||
except ConnectionResetError as e:
|
||||
print("进程关闭" + str(e))
|
||||
|
||||
def Process_client_send(self, target, function, content):
|
||||
connect = self.Process_client_link_dick[target]
|
||||
data = {"target": target, "function": function, "content": content}
|
||||
data_json = json.dumps(data)
|
||||
connect.send(data_json)
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] == 'ALL':
|
||||
for value in self.Process_client_link_dick.values():
|
||||
data_json = json.dumps(data)
|
||||
value.send(data_json)
|
||||
else:
|
||||
if data['target'] in self.Process_client_link_dick.keys():
|
||||
data_json = json.dumps(data)
|
||||
self.Process_client_link_dick[data['target']].send(data_json)
|
@ -0,0 +1,85 @@
|
||||
import multiprocessing
|
||||
import os
|
||||
import time
|
||||
import socket
|
||||
import json
|
||||
import threading
|
||||
from .Process_Client import ProcessClient
|
||||
|
||||
|
||||
class Session_server(ProcessClient):
|
||||
def __init__(self):
|
||||
ProcessClient.__init__(self)
|
||||
self.socker_ip = "127.0.0.1"
|
||||
self.socker_port = 7868
|
||||
self.server_socket = None
|
||||
self.server_status = False # 服务器状态
|
||||
self.link_server_Thread = threading.Thread(target=self.link_server)
|
||||
self.link_server_Thread.start()
|
||||
self.receive_server_Thread = threading.Thread(target=self.receive_server)
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
def link_server(self):
|
||||
while True:
|
||||
if not self.server_status:
|
||||
time.sleep(1)
|
||||
if self.server_socket is not None:
|
||||
self.server_socket = None
|
||||
try:
|
||||
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.server_socket.connect((self.socker_ip, self.socker_port))
|
||||
self.server_status = True
|
||||
if not self.receive_server_Thread.is_alive():
|
||||
self.receive_server_Thread.start()
|
||||
except Exception as a:
|
||||
self.server_status = False
|
||||
print("连接错误:" + str(a))
|
||||
finally:
|
||||
self.Process_client_send("ALL", "server_status", self.server_status)
|
||||
pass
|
||||
|
||||
def receive_server(self):
|
||||
while self.server_status:
|
||||
try:
|
||||
receive_content_json = self.server_socket.recv(1024).decode('utf-8')
|
||||
receive_content = json.loads(receive_content_json)
|
||||
self.content_pick(receive_content)
|
||||
except Exception as a:
|
||||
print("客户端接收错误:" + str(a))
|
||||
self.server_status = False
|
||||
self.Process_client_send("ALL", "server_status", self.server_status)
|
||||
|
||||
def send_server(self, genre, target, content):
|
||||
if self.server_status:
|
||||
try:
|
||||
data = {"genre": genre, "target": target, "data": content,
|
||||
"datetime": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}
|
||||
data_json = json.dumps(data) + '\n'
|
||||
self.server_socket.send(data_json.encode("utf-8"))
|
||||
except Exception as a:
|
||||
print("发送错误:" + str(a))
|
||||
self.server_status = False
|
||||
self.Process_client_send("ALL", "server_status", self.server_status)
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'Session_server']:
|
||||
match data['function']:
|
||||
case 'server_status':
|
||||
self.server_status = data['content']
|
||||
case 'send_server':
|
||||
self.send_server(data['content']['genre'], data['content']['target'], data['content']['content'])
|
||||
|
||||
def content_pick(self, data):
|
||||
match data['genre']:
|
||||
case '注册' | '登录':
|
||||
self.Process_client_send("Login", "login_page_receive", data)
|
||||
case '数据更新':
|
||||
self.Process_client_send("File_operate", "save_data", data['data'])
|
||||
case '聊天记录':
|
||||
if data['data']['Type'] == 'text':
|
||||
self.Process_client_send("File_operate", "save_data", {"History": data['data']})
|
||||
if data['target'] == '接收':
|
||||
self.Process_client_send("Chat_main", "Chat_screen_show", data['data'])
|
@ -0,0 +1,4 @@
|
||||
from .Process_Server import *
|
||||
from .Process_Client import *
|
||||
from .Session_server import *
|
||||
from .File_operate import *
|
16
python/code/chat_room/Chat_Room_Second/Client/__init__.py
Normal file
@ -0,0 +1,16 @@
|
||||
from .Page import *
|
||||
from .Transmission import *
|
||||
|
||||
|
||||
class start_all:
|
||||
def __init__(self):
|
||||
ProcessServer()
|
||||
|
||||
Session_server()
|
||||
|
||||
FileOperate(None)
|
||||
|
||||
app = wx.App()
|
||||
LoginFrame().Show()
|
||||
app.MainLoop()
|
||||
|
BIN
python/code/chat_room/Chat_Room_Second/Client/image/chat.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/connect.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/file.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/find.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/picture.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/site.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/speech.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
python/code/chat_room/Chat_Room_Second/Client/image/video.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
@ -0,0 +1,181 @@
|
||||
import os
|
||||
|
||||
import pymssql
|
||||
import threading
|
||||
import time
|
||||
from .Process_Client import *
|
||||
|
||||
|
||||
class database(ProcessClient):
|
||||
def __init__(self):
|
||||
ProcessClient.__init__(self)
|
||||
self.database_server = 'localhost'
|
||||
self.database_user = 'Chat'
|
||||
self.database_password = '123456'
|
||||
self.database_port = 8972
|
||||
self.database_name = 'Chat'
|
||||
self.database_state = False
|
||||
self.database_conn = None
|
||||
self.database_cursor = None
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
self.link_database_thread = threading.Thread(target=self.link_database)
|
||||
self.link_database_thread.start()
|
||||
|
||||
# 创建一个互斥锁对象
|
||||
self.lock = threading.Lock()
|
||||
|
||||
def link_database(self):
|
||||
while not self.database_state:
|
||||
time.sleep(1)
|
||||
try:
|
||||
self.database_conn = pymssql.connect(server=self.database_server,
|
||||
user=self.database_user,
|
||||
password=self.database_password,
|
||||
port=self.database_port,
|
||||
database=self.database_name)
|
||||
self.database_cursor = self.database_conn.cursor()
|
||||
self.database_state = True
|
||||
except pymssql.Error as a:
|
||||
print(a)
|
||||
|
||||
def check_account_state(self, client_id, Id: int, password):
|
||||
if self.database_state:
|
||||
try:
|
||||
state = 2
|
||||
self.database_cursor.execute(f"select Id,Password from Account where Id = {Id}")
|
||||
request_data = self.database_cursor.fetchall()
|
||||
if len(request_data) != 0:
|
||||
if request_data[0][1] == password:
|
||||
state = 0
|
||||
else:
|
||||
state = 1
|
||||
|
||||
content = {"account": Id, "status": state}
|
||||
data = {"client_id": client_id, "target": "客户端", "genre": "登录", "data": content}
|
||||
self.Process_client_send('Session_client', 'send_client', data)
|
||||
|
||||
except pymssql as a:
|
||||
self.database_state = False
|
||||
print(a)
|
||||
|
||||
def sign_account(self, client_id, NetName, Password):
|
||||
if self.database_state:
|
||||
# 获取锁
|
||||
self.lock.acquire()
|
||||
try:
|
||||
self.database_cursor.execute("insert into Account(NetName, Password)"
|
||||
f"values ('{NetName}','{Password}')")
|
||||
self.database_conn.commit()
|
||||
self.database_cursor.execute(f"SELECT SCOPE_IDENTITY() AS LastInsertedId;")
|
||||
Id = self.database_cursor.fetchone()[0]
|
||||
# 释放锁
|
||||
self.lock.release()
|
||||
info = {"Id": int(Id), "NetName": NetName, "Password": Password}
|
||||
|
||||
content = {"client_id": client_id, "target": "客户端", "genre": "注册", "data": info}
|
||||
self.Process_client_send('Session_client', 'send_client', content)
|
||||
|
||||
except pymssql as a:
|
||||
self.lock.release()
|
||||
self.database_state = False
|
||||
return False
|
||||
|
||||
def alter_state_database(self, Id: int, sate):
|
||||
if self.database_state:
|
||||
try:
|
||||
self.database_cursor.execute(f"update Account set State = N'{sate}' where Id = {Id}")
|
||||
self.database_conn.commit()
|
||||
except pymssql as a:
|
||||
self.database_state = False
|
||||
print(a)
|
||||
|
||||
def detection_data(self, Id, date):
|
||||
datas = []
|
||||
|
||||
self.database_cursor.execute(f"select Id,Password,NetName,UpDataTime from Account where Id = {Id}")
|
||||
Account_database = self.database_cursor.fetchall()
|
||||
Account_content = {'Id': Account_database[0][0],
|
||||
'Password': Account_database[0][1],
|
||||
'NetName': Account_database[0][2],
|
||||
'UpDataTime': Account_database[0][3].strftime('%Y-%m-%d %H:%M:%S')}
|
||||
if Account_content['UpDataTime'] == date:
|
||||
content = {"client_id": Id, "target": "客户端", "genre": "数据更新", "data": {"更新完成": Id}}
|
||||
self.Process_client_send('Session_client', 'send_client', content)
|
||||
return
|
||||
|
||||
Account_data = {"Account": Account_content}
|
||||
datas.append(Account_data)
|
||||
|
||||
self.database_cursor.execute(
|
||||
f"select ContactsId,Remark,State,UpDataTime from Contacts where UserId = {Id} and UpDataTime > '{date}'")
|
||||
Contacts_database = self.database_cursor.fetchall()
|
||||
for Contact in Contacts_database:
|
||||
Contacts_content = {'Contact': Contact[0],
|
||||
'Remark': Contact[1],
|
||||
'State': Contact[2],
|
||||
'UpDataTime': Contact[3].strftime('%Y-%m-%d %H:%M:%S')}
|
||||
Contacts_data = {"Contacts": Contacts_content}
|
||||
datas.append(Contacts_data)
|
||||
|
||||
self.database_cursor.execute(f"select * from History where Send = {Id} or Receive = {Id} and Time > '{date}'")
|
||||
History_database = self.database_cursor.fetchall()
|
||||
for History in History_database:
|
||||
content = {
|
||||
'Send': History[0],
|
||||
'Receive': History[1],
|
||||
'Type': History[2],
|
||||
'Content': History[3],
|
||||
'Time': History[4].strftime('%Y-%m-%d %H:%M:%S')}
|
||||
History_data = {"History": content}
|
||||
datas.append(History_data)
|
||||
|
||||
datas.append({"更新完成": Id})
|
||||
|
||||
for data in datas:
|
||||
time.sleep(0.1)
|
||||
content = {"client_id": Id, "target": "客户端", "genre": "数据更新", "data": data}
|
||||
self.Process_client_send('Session_client', 'send_client', content)
|
||||
|
||||
def update_History(self, Send, Receive, Type, Content, Time):
|
||||
if self.database_state:
|
||||
try:
|
||||
self.database_cursor.execute(f"insert into History(Send, Receive, Type, Content,Time)"
|
||||
f"select {Send},{Receive},'{Type}',N'{Content}','{Time}'")
|
||||
self.database_conn.commit()
|
||||
except pymssql as a:
|
||||
self.database_state = False
|
||||
print(a)
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'Database_formula']:
|
||||
match data['function']:
|
||||
case 'check_account_state':
|
||||
|
||||
self.check_account_state(data['content']['client_id'],
|
||||
data['content']['account'],
|
||||
data['content']['password'])
|
||||
|
||||
case 'sign_account':
|
||||
|
||||
self.sign_account(data['content']['client_id'],
|
||||
data['content']['account'],
|
||||
data['content']['password'])
|
||||
|
||||
case 'alter_state_database':
|
||||
self.alter_state_database(data['content']['Id'],
|
||||
data['content']['sate'])
|
||||
|
||||
case 'detection_data':
|
||||
self.detection_data(data['content']['client_id'],
|
||||
data['content']['date'])
|
||||
|
||||
case 'update_History':
|
||||
self.update_History(data['content']['Send'],
|
||||
data['content']['Receive'],
|
||||
data['content']['Type'],
|
||||
data['content']['Content'],
|
||||
data['content']['Time'])
|
@ -0,0 +1,30 @@
|
||||
import json
|
||||
import threading
|
||||
from multiprocessing.connection import Client
|
||||
|
||||
|
||||
class ProcessClient:
|
||||
def __init__(self):
|
||||
self.Process_port = 3244
|
||||
self.Process_server = 'localhost'
|
||||
self.Process_client_Client = Client((self.Process_server, self.Process_port))
|
||||
Process_client_recv = threading.Thread(target=self.Process_client_recv)
|
||||
Process_client_recv.start()
|
||||
|
||||
def Process_client_send(self, target, function, content):
|
||||
data = {"target": target, "function": function, "content": content}
|
||||
data_json = json.dumps(data)
|
||||
self.Process_client_Client.send(data_json)
|
||||
|
||||
def Process_client_recv(self):
|
||||
while True:
|
||||
try:
|
||||
data_json = self.Process_client_Client.recv()
|
||||
data = json.loads(data_json)
|
||||
self.Process_client_pick(data)
|
||||
except EOFError:
|
||||
print("连接已关闭")
|
||||
break
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
pass
|
@ -0,0 +1,49 @@
|
||||
import json
|
||||
import multiprocessing
|
||||
from multiprocessing.connection import Listener
|
||||
import threading
|
||||
|
||||
|
||||
class ProcessServer:
|
||||
def __init__(self):
|
||||
try:
|
||||
self.Process_port = 3244
|
||||
self.Process_server = 'localhost'
|
||||
self.Process_server_listener = Listener((self.Process_server, self.Process_port))
|
||||
self.Process_client_link_dick = {}
|
||||
Process_client_link_Thread = threading.Thread(target=self.Process_client_link)
|
||||
Process_client_link_Thread.start()
|
||||
except:
|
||||
print("进程通信端口绑定失败")
|
||||
|
||||
def Process_client_link(self):
|
||||
while True:
|
||||
client_connect = self.Process_server_listener.accept()
|
||||
client_Thread_recv = threading.Thread(target=self.Process_client_recv, args=(client_connect,))
|
||||
client_Thread_recv.start()
|
||||
|
||||
def Process_client_recv(self, client_Thread_recv):
|
||||
while True:
|
||||
data_json = client_Thread_recv.recv()
|
||||
data = json.loads(data_json)
|
||||
if data['target'] == 'Server':
|
||||
if data['function'] == 'Name':
|
||||
self.Process_client_link_dick[data['content']] = client_Thread_recv
|
||||
else:
|
||||
self.Process_client_pick(data)
|
||||
|
||||
def Process_client_send(self, target, function, content):
|
||||
connect = self.Process_client_link_dick[target]
|
||||
data = {"target": target, "function": function, "content": content}
|
||||
data_json = json.dumps(data)
|
||||
connect.send(data_json)
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] == 'ALL':
|
||||
for value in self.Process_client_link_dick.values():
|
||||
data_json = json.dumps(data)
|
||||
value.send(data_json)
|
||||
else:
|
||||
if data['target'] in self.Process_client_link_dick.keys():
|
||||
data_json = json.dumps(data)
|
||||
self.Process_client_link_dick[data['target']].send(data_json)
|
@ -0,0 +1,127 @@
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
import socket
|
||||
import json
|
||||
import threading
|
||||
from .Process_Client import *
|
||||
|
||||
|
||||
class link_client(ProcessClient):
|
||||
def __init__(self):
|
||||
ProcessClient.__init__(self)
|
||||
self.server_host = "127.0.0.1"
|
||||
self.server_port = 7868
|
||||
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.server_socket.bind((self.server_host, self.server_port))
|
||||
self.server_socket.listen()
|
||||
self.client_socket_dict = {}
|
||||
self.client_max_id = 0
|
||||
|
||||
current_file_path = __file__
|
||||
current_file_name = os.path.basename(current_file_path).split('.')[0]
|
||||
self.Process_client_send("Server", "Name", current_file_name)
|
||||
|
||||
self.link_client_Thread = threading.Thread(target=self.link_client)
|
||||
self.link_client_Thread.start()
|
||||
|
||||
def link_client(self):
|
||||
while True:
|
||||
try:
|
||||
client_socket, client_address = self.server_socket.accept()
|
||||
self.client_max_id += 1
|
||||
client_id = ''.join(random.choice(string.ascii_letters) for _ in range(10)) + str(self.client_max_id)
|
||||
self.client_socket_dict[client_id] = client_socket
|
||||
recv_client_Thread = threading.Thread(target=self.recv_client, args=(client_socket,), daemon=True)
|
||||
recv_client_Thread.start()
|
||||
except:
|
||||
pass
|
||||
|
||||
def send_client(self, client_id, genre, target, content):
|
||||
client_socket = self.client_socket_dict[client_id]
|
||||
try:
|
||||
data = {"genre": genre, "target": target, "data": content,
|
||||
"datetime": time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}
|
||||
data_json = json.dumps(data) + '\n'
|
||||
client_socket.send(data_json.encode("utf-8"))
|
||||
except:
|
||||
client_socket.close()
|
||||
|
||||
def pick_data(self, client_id, data):
|
||||
match data['genre']:
|
||||
case '登录':
|
||||
content = {'client_id': client_id, 'account': data['data']['account'],
|
||||
'password': data['data']['password']}
|
||||
self.Process_client_send("Database_formula", "check_account_state", content)
|
||||
case '注册':
|
||||
content = {'client_id': client_id, 'account': data['data']['account'],
|
||||
'password': data['data']['password']}
|
||||
self.Process_client_send("Database_formula", "sign_account", content)
|
||||
case '数据更新':
|
||||
content = {'client_id': client_id, 'date': data['data']}
|
||||
self.Process_client_send("Database_formula", "detection_data", content)
|
||||
case '聊天记录':
|
||||
Send = client_id
|
||||
Receive = data['target']
|
||||
Time = data['datetime']
|
||||
data = data['data']
|
||||
Type = data['Type']
|
||||
Content = data['content']
|
||||
content = {'Send': Send, 'Receive': Receive, 'Time': Time, 'Type': Type, 'Content': Content}
|
||||
self.Process_client_send("Database_formula", "update_History", content)
|
||||
self.send_client(Send, "聊天记录", "发送", content)
|
||||
if Receive in self.client_socket_dict:
|
||||
self.send_client(Receive, "聊天记录", "接收", content)
|
||||
|
||||
def recv_client(self, client_socket):
|
||||
state = True
|
||||
while state:
|
||||
try:
|
||||
data_json = client_socket.recv(1024).decode('utf-8')
|
||||
data = json.loads(data_json)
|
||||
client_Id = self.find_client(client_socket, None)
|
||||
self.pick_data(client_Id, data)
|
||||
except:
|
||||
try:
|
||||
client_socket.close()
|
||||
finally:
|
||||
state = False
|
||||
self.find_client(client_socket, None)
|
||||
client_id = self.find_client(client_socket, None)
|
||||
del self.client_socket_dict[client_id]
|
||||
if client_id.isdigit():
|
||||
self.Process_client_send("Database_formula", "alter_state_database",
|
||||
{"Id": client_id, "sate": 0})
|
||||
|
||||
def Process_client_pick(self, data):
|
||||
if data['target'] in ['ALL', 'Session_client']:
|
||||
match data['function']:
|
||||
case 'send_client':
|
||||
client_id = data['content']['client_id']
|
||||
genre = data['content']['genre']
|
||||
target = data['content']['target']
|
||||
content = data['content']['data']
|
||||
if data['content']['genre'] == '登录':
|
||||
if content['account'] not in self.client_socket_dict:
|
||||
if content['status'] == 0:
|
||||
client_socket = self.find_client(None, client_id)
|
||||
del self.client_socket_dict[client_id]
|
||||
client_id = content['account']
|
||||
self.client_socket_dict[client_id] = client_socket
|
||||
if client_id.isdigit():
|
||||
self.Process_client_send("Database_formula", "alter_state_database",
|
||||
{"Id": client_id, "sate": 1})
|
||||
else:
|
||||
return
|
||||
self.send_client(client_id, genre, target, content)
|
||||
|
||||
def find_client(self, client_socket, client_id):
|
||||
if client_id is None:
|
||||
for key, value in self.client_socket_dict.items():
|
||||
if value == client_socket:
|
||||
return key
|
||||
elif client_socket is None:
|
||||
for key, value in self.client_socket_dict.items():
|
||||
if key == client_id:
|
||||
return value
|
@ -0,0 +1,4 @@
|
||||
from .Process_Server import *
|
||||
from .Process_Client import *
|
||||
from .Session_client import *
|
||||
from .Database_formula import *
|
11
python/code/chat_room/Chat_Room_Second/Server/__init__.py
Normal file
@ -0,0 +1,11 @@
|
||||
from .Transmission import *
|
||||
|
||||
|
||||
class Server_main:
|
||||
def __init__(self):
|
||||
ProcessServer()
|
||||
database()
|
||||
link_client()
|
||||
|
||||
|
||||
|
4
python/code/chat_room/Chat_Room_Second/StartClient.py
Normal file
@ -0,0 +1,4 @@
|
||||
from Client import start_all
|
||||
|
||||
if __name__ == '__main__':
|
||||
start_all()
|
4
python/code/chat_room/Chat_Room_Second/StartServer.py
Normal file
@ -0,0 +1,4 @@
|
||||
from Server import Server_main
|
||||
|
||||
if __name__ == '__main__':
|
||||
Server_main()
|
6
python/code/chat_room/Chat_Room_Second/start_all.py
Normal file
@ -0,0 +1,6 @@
|
||||
from Client import start_all
|
||||
from Server import Server_main
|
||||
|
||||
if __name__ == '__main__':
|
||||
Server_main()
|
||||
start_all()
|
@ -1,70 +0,0 @@
|
||||
from selenium import webdriver # 驱动
|
||||
from selenium.webdriver.common.by import By # 解析方式
|
||||
from selenium.webdriver import Keys # 模拟按键
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
|
||||
import time
|
||||
|
||||
# 开启无头浏览器
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
options.add_argument("--disable-gpu")
|
||||
|
||||
driver = webdriver.Chrome() # 创建浏览器对象
|
||||
|
||||
driver.get(
|
||||
"https://www.google.com/maps/search/%E6%B1%BD%E4%BF%AE/@22.2354762,113.7531542,11z/data=!4m6!2m5!3m4!2s22.2492,+113.8819!4m2!1d113.8819137!2d22.2492291?entry=ttu")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
scrollable_element = driver.find_element(By.XPATH,
|
||||
'//*[@id="QA0Szd"]/div/div/div[1]/div[2]/div/div[1]/div/div/div[1]/div[1]')
|
||||
|
||||
for i in range(10):
|
||||
scrollable_element.send_keys(Keys.PAGE_DOWN)
|
||||
time.sleep(1)
|
||||
|
||||
divs = driver.find_elements(By.XPATH,
|
||||
'//div/div/div[1]/div[2]/div/div[1]/div/div/div[1]/div[1]/div[not(@class)]')
|
||||
for div in divs:
|
||||
info_dict = {"店名": "", "地址": "", "电话": "", "网站": "", "Plus Code": "", "星期一": "", "星期二": "", "星期三": "",
|
||||
"星期四": "", "星期五": "", "星期六": "", "星期日": ""}
|
||||
info_content = []
|
||||
div.click()
|
||||
time.sleep(1)
|
||||
info_path_1 = "//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[7]"
|
||||
info_path_2 = "//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[8]"
|
||||
title = driver.find_element(By.XPATH,
|
||||
'//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[2]/div/div[1]/div[1]/h1').text
|
||||
info_dict["店名"] = title
|
||||
info_divs = driver.find_element(By.XPATH, info_path_1)
|
||||
|
||||
role_test = info_divs.get_attribute("role")
|
||||
if role_test == "presentation":
|
||||
info_divs = driver.find_element(By.XPATH, info_path_2)
|
||||
|
||||
a_s = info_divs.find_elements(By.XPATH, './/a')
|
||||
button_s = info_divs.find_elements(By.XPATH, './/button')
|
||||
|
||||
for a in a_s:
|
||||
a_info = a.get_attribute("aria-label")
|
||||
if a is not None:
|
||||
info_content.append(a_info)
|
||||
|
||||
for button in button_s:
|
||||
button_info = button.get_attribute("aria-label")
|
||||
if button_info is not None:
|
||||
info_content.append(button_info)
|
||||
|
||||
for info in info_content:
|
||||
tmp_content = info.split(":", 1)
|
||||
if tmp_content[0] in ["地址", "电话", "Plus Code", "网站"]:
|
||||
info_dict[tmp_content[0]] = tmp_content[1].strip()
|
||||
tmp_content = info.split(",", 1)
|
||||
if tmp_content[0] in ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]:
|
||||
tmp_time = tmp_content[1].split("、", -1)
|
||||
info_dict[tmp_content[0]] = tmp_time[0].strip()
|
||||
|
||||
print(info_dict)
|
77
python/test/script.py
Normal file
@ -0,0 +1,77 @@
|
||||
from selenium import webdriver # 驱动
|
||||
from selenium.webdriver.common.by import By # 解析方式
|
||||
from selenium.webdriver import Keys # 模拟按键
|
||||
from selenium.webdriver.common.action_chains import ActionChains
|
||||
import time
|
||||
# 开启无头浏览器
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
|
||||
|
||||
class google_map_script:
|
||||
def __init__(self, url, head, frequency):
|
||||
self.url = url
|
||||
self.head = head
|
||||
self.frequency = frequency
|
||||
|
||||
def start(self):
|
||||
if self.head:
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
options.add_argument("--disable-gpu")
|
||||
driver = webdriver.Chrome(options=options) # 创建浏览器对象
|
||||
else:
|
||||
driver = webdriver.Chrome()
|
||||
|
||||
def work(self, driver):
|
||||
driver.get(self.url)
|
||||
time.sleep(3)
|
||||
scrollable_element = driver.find_element(By.XPATH,
|
||||
'//*[@id="QA0Szd"]/div/div/div[1]/div[2]/div/div[1]/div/div/div[1]/div[1]')
|
||||
|
||||
for i in range(10):
|
||||
scrollable_element.send_keys(Keys.PAGE_DOWN)
|
||||
time.sleep(1)
|
||||
|
||||
divs = driver.find_elements(By.XPATH,
|
||||
'//div/div/div[1]/div[2]/div/div[1]/div/div/div[1]/div[1]/div[not(@class)]')
|
||||
for div in divs:
|
||||
info_dict = {"店名": "", "地址": "", "电话": "", "网站": "", "Plus Code": "", "星期一": "", "星期二": "",
|
||||
"星期三": "",
|
||||
"星期四": "", "星期五": "", "星期六": "", "星期日": ""}
|
||||
info_content = []
|
||||
div.click()
|
||||
time.sleep(1)
|
||||
info_path_1 = "//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[7]"
|
||||
info_path_2 = "//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[8]"
|
||||
title = driver.find_element(By.XPATH,
|
||||
'//div/div/div[1]/div[3]/div/div[1]/div/div/div[2]/div[2]/div/div[1]/div[1]/h1').text
|
||||
info_dict["店名"] = title
|
||||
info_divs = driver.find_element(By.XPATH, info_path_1)
|
||||
|
||||
role_test = info_divs.get_attribute("role")
|
||||
if role_test == "presentation":
|
||||
info_divs = driver.find_element(By.XPATH, info_path_2)
|
||||
|
||||
a_s = info_divs.find_elements(By.XPATH, './/a')
|
||||
button_s = info_divs.find_elements(By.XPATH, './/button')
|
||||
|
||||
for a in a_s:
|
||||
a_info = a.get_attribute("aria-label")
|
||||
if a is not None:
|
||||
info_content.append(a_info)
|
||||
|
||||
for button in button_s:
|
||||
button_info = button.get_attribute("aria-label")
|
||||
if button_info is not None:
|
||||
info_content.append(button_info)
|
||||
|
||||
for info in info_content:
|
||||
tmp_content = info.split(":", 1)
|
||||
if tmp_content[0] in ["地址", "电话", "Plus Code", "网站"]:
|
||||
info_dict[tmp_content[0]] = tmp_content[1].strip()
|
||||
tmp_content = info.split(",", 1)
|
||||
if tmp_content[0] in ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]:
|
||||
tmp_time = tmp_content[1].split("、", -1)
|
||||
info_dict[tmp_content[0]] = tmp_time[0].strip()
|
||||
|
||||
print(info_dict)
|