精华内容
下载资源
问答
  • python实现可视化ftp客户端效果展示使用说明bug说明源码展示 效果展示 使用说明 1.先选择本地的一个目录进行文件展示 2.本地搜索是基于第一步选择本地目录的路径进行搜索的 3.ftp搜索是基于当前ftp显示这个页面进行...

    效果展示

    在这里插入图片描述

    使用说明

    1.先选择本地的一个目录进行文件展示
    2.本地搜索是基于第一步选择本地目录的路径进行搜索的
    3.ftp搜索是基于当前ftp显示这个页面进行搜索的
    4.左边本地展示框和右边ftp展示框支持拖拽上传,前提是先要选择一个目录。

    bug说明

    在这个项目中有两个最大的bug还未解决
    1.上传到ftp中文目录中会出现乱码
    2.上传和下载显示的进度条是一个假的进度条
    欢迎各位大佬对这两个bug进行修改

    gitee链接

    https://gitee.com/jaoyang520/ftpclient.git
    欢迎各位大佬修改bug

    源码展示

    import tkinter as tk
    from tkinter import ttk
    from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_center import BottomMenuBarCenter
    from ftp_client_alter_bug.seek.win_search import WinSearch
    from ftp_client_alter_bug.top_menu.top_menu_bar import TopMenuBar
    from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_left import BottomMenuBarleft
    from ftp_client_alter_bug.bottom_menu.bottom_menu_bar_right import BottomMenuBarRight
    from ftp_client_alter_bug.tree.win_tree import WinTree
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    from ftp_client_alter_bug.win_ftp_drag.ftpdrag import FtpDrag
    from ftp_client_alter_bug.win_ftp_drag.windrag import WinDrag
    
    win = tk.Tk()
    win.title("FTP客户端")
    win.geometry("1200x700")
    win.resizable(0, 0)
    
    
    xuanzhe_win_path = []
    win_path = []
    ftp_path = []
    win_search_name = []
    win_search_path = []
    ftp_search_path = []
    ftp_list = []
    ftp_tree_list = []
    win_xuanze_tree = []
    win_search_tree = []
    path = "初始化占位"
    
    top_frame = tk.Frame(win, width="1200", height="60")
    top_frame.place(x=0, y=5)
    top_menu = TopMenuBar(top_frame, path, win, win_search_path, ftp_list, xuanzhe_win_path)
    top_menu.logo()
    
    top_menu.open_wenjian()
    # top_menu.search_box()
    top_menu.name_ip("", "")
    top_menu.exit_login(ftp_tree_list, ftp_path, ftp_list)
    top_menu.login_in(ftp_path, ftp_list, ftp_tree_list)
    top_menu.lishi_login_in(ftp_path, ftp_list, ftp_tree_list)
    
    
    left_frame = tk.Frame(win, width="350", height="540")
    left_frame.place(x=10, y=90)
    tree = ttk.Treeview(left_frame, show="tree", height=26)
    tree.column("#0", width=350)
    st = ttk.Style()
    st.configure("Treeview", font=("宋体", 13))
    winftpdrag = WinDrag(left_frame, win_path, xuanzhe_win_path, tree)
    winftpdrag.execute()
    
    win_xuanze_tree.clear()
    win_xuanze_tree.append(tree)
    
    wintree = WinTree(path, win_path, tree)
    
    top_menu.local_mulu(win_path, tree)
    
    
    
    # 创建两个一模一样的frame实现一个注销一个加载
    win_center_frame = tk.Frame(win, width="420",bg="green", height="540")
    win_center_frame.place(x=350, y=90)
    search_path = r"D:\\python_daima"
    search_name = "9999"
    
    win_tree = ttk.Treeview(win_center_frame, show="tree", height=26)
    
    win_tree.column("#0", width=440)
    st = ttk.Style()
    st.configure("Treeview", font=("宋体", 12))
    win_search_tree.clear()
    win_search_tree.append(win_tree)
    
    winsearch = WinSearch(path, search_name, win_search_path, win_tree)
    
    top_menu.search_box(win_search_name, win_search_tree, ftp_search_path, ftp_list)
    
    
    
    right_frame = tk.Frame(win, width="420", height="540")
    right_frame.place(x=790, y=90)
    
    tree_ftp = ttk.Treeview(right_frame, show="tree", height=26, columns=("shijian", "wenjiantype"))
    tree_ftp.column("#0", width=250)
    tree_ftp.column("shijian", width=80)
    tree_ftp.column("wenjiantype", width=60)
    
    ftp_tree_list.append(tree_ftp)
    
    st = ttk.Style()
    st.configure("Treeview", font=("宋体", 13))
    
    
    bommot_frame_left = tk.Frame(win, width="350", height="60")
    bommot_frame_left.place(x=0, y=635)
    bommot_menu_left = BottomMenuBarleft(bommot_frame_left)
    bommot_menu_left.win_chuangjian_mulu(win_path, xuanzhe_win_path, tree)
    bommot_menu_left.win_chuangjian_wenjian(win_path, xuanzhe_win_path, tree)
    bommot_menu_left.win_delete_mulu(win_path, xuanzhe_win_path, tree)
    bommot_menu_left.win_delete_wenjian(win_path, xuanzhe_win_path, tree)
    
    # bommot_menu_left.shangchaung(win, ftp_path, ftp_list, ftp_frame, ftp_tree, win_path, bommot_frame_center)
    bommot_menu_left.open_wenjian(win_path)
    bommot_menu_left.gexian()
    
    
    bommot_frame_center = tk.Frame(win,  width="500", height="60")
    bommot_frame_center.place(x=350, y=635)
    bottom_menu_center = BottomMenuBarCenter(bommot_frame_center)
    bottom_menu_center.delete_mulu(win_search_path, xuanzhe_win_path, win_search_name, win_tree, win_path, tree)
    bottom_menu_center.open_weizhi(win_search_path)
    bottom_menu_center.delete_wenjian(ftp_list, tree_ftp, ftp_path, win_search_name, win_search_tree, ftp_search_path)
    bottom_menu_center.xiazai_wenjian(ftp_list, win_path, xuanzhe_win_path, bommot_frame_center, tree, ftp_search_path)
    bottom_menu_center.gexian()
    
    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
    ftpdrag = FtpDrag(right_frame, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp)
    ftpdrag.execute()
    
    
    bommot_menu_left.shangchaung(ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp)
    
    bommot_frame_right = tk.Frame(win, width="350", height="60")
    bommot_frame_right.place(x=850, y=635)
    bommot_menu_right = BottomMenuBarRight(bommot_frame_right)
    bommot_menu_right.geban()
    bommot_menu_right.ftp_chaungjian_mulu(ftp_path, ftp_list, tree_ftp)
    bommot_menu_right.ftp_jinru_xj(ftp_path, ftp_list, tree_ftp)
    bommot_menu_right.ftp_delete_mulu(ftp_path, ftp_list, tree_ftp)
    bommot_menu_right.ftp_delete_wenjian(ftp_path, ftp_list, tree_ftp)
    bommot_menu_right.xiazai(ftp_list, ftp_path, win_path, xuanzhe_win_path, bommot_frame_center, tree)
    bommot_menu_right.ftp_fh_sj(ftp_path, ftp_list, tree_ftp)
    
    
    tk.mainloop()
    
    import tkinter as tk
    import os
    from tkinter.messagebox import showinfo
    
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    from ftp_client_alter_bug.tree.win_tree import WinTree
    from ftp_client_alter_bug.seek.ftp_search import FtpSearch
    from ftp_client_alter_bug.seek.win_search import WinSearch
    
    
    class BottomMenuBarCenter:
        def __init__(self, bommot_frame_center):
            self.bommot_frame_center = bommot_frame_center
    
        # win删除文件
        def delete_mulu(self, win_search_path, xuanzhe_win_path, win_search_name, win_tree, win_path, tree):
            def delete_mulu_button():
                try:
                    # 也可以递归删除文件
                    def delAll(path):
                        if os.path.isdir(path):
                            files = os.listdir(path)
                            # 遍历并删除文件
                            for file in files:
                                p = os.path.join(path, file)
                                if os.path.isdir(p):
                                    # 递归
                                    delAll(p)
                                else:
                                    os.remove(p)
                            # 删除文件夹
                            os.rmdir(path)
                        else:
                            os.remove(path)
    
                    delAll(win_search_path[0])
    
                    table = win_tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    win_name = win_search_name[0]
                    winsearch = WinSearch(xuanzhe_win_path[0], win_name, win_search_path, win_tree)
                    winsearch.search()
    
                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()
                except:
                    showinfo("错误提示", "路径选择异常!")
    
    
            delete_mulu_but = tk.Button(self.bommot_frame_center, text="删除文件", command=delete_mulu_button, font=("宋体", 13), relief="flat")
            delete_mulu_but.place(x=15, y=2)
    
        # 打开window上文件所在的位置
        def open_weizhi(self, win_search_path):
            def open_weizhi_button():
                try:
                    os.startfile(rf"{win_search_path[0]}")
                except:
                    showinfo("错误提示", "未选择路径!")
            open_weizhi_but = tk.Button(self.bommot_frame_center, text="打开文件", command=open_weizhi_button, font=("宋体", 13), relief="flat")
            open_weizhi_but.place(x=15, y=35)
    
        # ftp删除文件
        def delete_wenjian(self, ftp_list, tree_ftp, ftp_path, win_search_name, win_search_tree, ftp_search_path):
            def delete_wenjian_button():
                try:
                    ftp_list[0].delete(ftp_search_path[0])
    
                    if str(ftp_list[0].pwd()) != "/":
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi(ftp_list[0].pwd())
                    else:
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi("/")
    
                    win_name = win_search_name[0]
                    table = win_search_tree[0]
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftpsearch = FtpSearch(ftp_list[0], win_name, ftp_search_path, table)
                    ftpsearch.show()
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
    
            delete_wenjian_but = tk.Button(self.bommot_frame_center, text="删除文件", command=delete_wenjian_button, font=("宋体", 13), relief="flat")
            delete_wenjian_but.place(x=415, y=2)
    
        # ftp下载文件
        def xiazai_wenjian(self, ftp_list, win_path, xuanzhe_win_path, bommot_frame_center, tree, ftp_search_path):
            def xiazai_wenjian_button():
                try:
                    print(ftp_list[0], ftp_search_path[0], win_path[0], "三个路径————————")
    
                    def downloadfile(ftp, remotepath, localpath):
                        bufsize = 1024  # 设置缓冲块大小
                        fp = open(localpath, 'wb')  # 以写模式在本地打开文件
                        ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)  # 接收服务器上文件并写入本地文件
                        ftp.set_debuglevel(0)  # 关闭调试
                        fp.close()  # 关闭文件
    
                    downloadfile(ftp_list[0], ftp_search_path[0], win_path[0]+"\\"+ftp_search_path[0].split("/")[-1])
    
                    # 更新进度条函数
                    def change_schedule(now_schedule, all_schedule):
                        canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                        bommot_frame_center.update()
                        x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                        if round(now_schedule / all_schedule * 100, 2) == 100.00:
                            x.set("完==成==了")
    
                    canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                    canvas.place(x=150, y=25)
                    x = tk.StringVar()
                    # 进度条以及完成程度
                    out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                    fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")
    
                    tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)
    
                    for i in range(100):
                        change_schedule(i, 99)
    
                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()
    
                    print(win_path[0]+ftp_search_path[0].split("\\")[-1],"============================")
                except:
                    showinfo("错误提示", "本地路径或服务器连接异常!")
    
            xiazai_wenjian_but = tk.Button(self.bommot_frame_center, text="下载文件", command=xiazai_wenjian_button, font=("宋体", 13), relief="flat")
            xiazai_wenjian_but.place(x=415, y=35)
    
        def gexian(self):
            tk.Label(self.bommot_frame_center, text="-------------进-------------度--------------条-------------").place(x=105, y=0)
    
    import tkinter as tk
    import os
    from tkinter.messagebox import showinfo
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    from ftp_client_alter_bug.tree.win_tree import WinTree
    
    
    class BottomMenuBarleft:
    
        def __init__(self, bommot_frame_left):
            self.bommot_frame_left = bommot_frame_left
    
        # 创建本地目录
        def win_chuangjian_mulu(self, win_path, xuanzhe_win_path, tree):
            def win_mulu_button():
                cj_mulu_win = tk.Tk()
                cj_mulu_win.geometry("300x170")
    
                tk.Label(cj_mulu_win, text="创建目录", font=("宋体", 17)).place(x=100, y=15)
                tk.Label(cj_mulu_win, text="目录名:", font=("宋体", 13)).place(x=30, y=60)
                mulu_entry = tk.Entry(cj_mulu_win, width=17, font=("宋体", 13))
                mulu_entry.place(x=100, y=60)
    
                def mulu_but():
                    try:
                        mulu_name = str(mulu_entry.get())
                        os.mkdir(win_path[0] + "\\" + mulu_name)
    
                        table = tree
                        items = table.get_children()
                        [table.delete(item) for item in items]
    
                        wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                        wintree.show_wenjian()
    
                        # cj_mulu_win.destroy()
                    except:
                        showinfo("错误提示", "未选择路径!")
                    finally:
                        cj_mulu_win.destroy()
    
                mulu_button = tk.Button(cj_mulu_win, text="确==========定", font=("宋体", 13), command=mulu_but)
                mulu_button.place(x=80, y=105)
    
    
                cj_mulu_win.mainloop()
            win_mulu_but = tk.Button(self.bommot_frame_left, text="创建目录", font=("宋体", 13), command=win_mulu_button, relief="flat")
            win_mulu_but.place(x=10, y=2)
    
        # 创建本地文件
        def win_chuangjian_wenjian(self, win_path, xuanzhe_win_path, tree):
    
            def win_wenjian_button():
                cj_wenjian_win = tk.Tk()
                cj_wenjian_win.geometry("300x170")
    
                tk.Label(cj_wenjian_win, text="创建文件", font=("宋体", 17)).place(x=100, y=15)
                tk.Label(cj_wenjian_win, text="文件名:", font=("宋体", 13)).place(x=30, y=60)
                wenjian_entry = tk.Entry(cj_wenjian_win, width=17, font=("宋体", 13))
                wenjian_entry.place(x=100, y=60)
    
                def wenjian_but():
                    try:
                        wenjian_name = str(wenjian_entry.get())
                        f = open(win_path[0] + "\\" + wenjian_name, "w")
                        f.close()
    
                        table = tree
                        items = table.get_children()
                        [table.delete(item) for item in items]
    
                        wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                        wintree.show_wenjian()
    
                        # cj_wenjian_win.destroy()
                    except:
                        showinfo("错误提示", "未选择路径!")
                    finally:
                        cj_wenjian_win.destroy()
    
                wenjian_button = tk.Button(cj_wenjian_win, text="确==========定", font=("宋体", 13), command=wenjian_but)
                wenjian_button.place(x=80, y=105)
    
            win_wenjian_but = tk.Button(self.bommot_frame_left, text="创建文件", font=("宋体", 13), command=win_wenjian_button, relief="flat")
            win_wenjian_but.place(x=10, y=35)
    
        # 删除目录
        def win_delete_mulu(self, win_path, xuanzhe_win_path, tree):
            def win_mulu_delete_button():
                try:
                    path = win_path[0]
                    # 也可以递归删除文件
                    def delAll(path):
                        if os.path.isdir(path):
                            files = os.listdir(path)
                            # 遍历并删除文件
                            for file in files:
                                p = os.path.join(path, file)
                                if os.path.isdir(p):
                                    # 递归
                                    delAll(p)
                                else:
                                    os.remove(p)
                            # 删除文件夹
                            os.rmdir(path)
                        else:
                            os.remove(path)
    
                    delAll(path)
                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()
                except:
                    showinfo("错误提示", "未选择路径!")
    
            win_delete_mu_but = tk.Button(self.bommot_frame_left, text="删除目录", font=("宋体", 13), command=win_mulu_delete_button, relief="flat")
            win_delete_mu_but.place(x=115, y=2)
    
        # 删除文件
        def win_delete_wenjian(self, win_path, xuanzhe_win_path, tree):
            def win_wenjian_delete_button():
                try:
                    path = win_path[0]
    
                    # 也可以递归删除文件
                    def delAll(path):
                        if os.path.isdir(path):
                            files = os.listdir(path)
                            # 遍历并删除文件
                            for file in files:
                                p = os.path.join(path, file)
                                if os.path.isdir(p):
                                    # 递归
                                    delAll(p)
                                else:
                                    os.remove(p)
                            # 删除文件夹
                            os.rmdir(path)
                        else:
                            os.remove(path)
    
                    delAll(path)
                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()
                except:
                    showinfo("错误提示", "未选择路径!")
    
            win_delete_wenjian_but = tk.Button(self.bommot_frame_left, text="删除文件", font=("宋体", 13), command=win_wenjian_delete_button, relief="flat")
            win_delete_wenjian_but.place(x=115, y=35)
    
        # 上传文件
        def shangchaung(self, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp):
            def shangchaung_button():
                try:
                    def uploadfile(ftp, remotepath, localpath):
                        bufsize = 1024
                        fp = open(localpath, 'rb')
                        ftp.storbinary(r'STOR ' + rf'{remotepath}', fp, bufsize)  # 上传文件
                        ftp.set_debuglevel(0)
                        fp.close()
                    print(ftp_list[0], ftp_list[0].pwd()+"\\"+win_path[0].split("\\")[-1], win_path[0], "----------==============-----------------==========")
    
                    uploadfile(ftp_list[0], ftp_list[0].pwd()+"\\"+win_path[0].split("\\")[-1], win_path[0])
    
                    # 更新进度条函数
                    def change_schedule(now_schedule, all_schedule):
                        canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                        bommot_frame_center.update()
                        x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                        if round(now_schedule / all_schedule * 100, 2) == 100.00:
                            x.set("完==成==了")
    
                    canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                    canvas.place(x=150, y=25)
                    x = tk.StringVar()
                    # 进度条以及完成程度
                    out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                    fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")
    
                    tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)
    
                    for i in range(100):
                        change_schedule(i, 99)
    
                    if str(ftp_list[0].pwd()) != "/":
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi(ftp_list[0].pwd())
                    else:
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi("/")
                except:
                    showinfo("错误提示", "本地路径或服务器连接异常!")
    
            shangchaung_but = tk.Button(self.bommot_frame_left, text="上传文件", font=("宋体", 13), command=shangchaung_button, relief="flat")
            shangchaung_but.place(x=220, y=2)
    
        # 打开文件
        def open_wenjian(self, win_path):
            def win_open_wenjian_button():
                try:
                    os.startfile(rf"{win_path[0]}")
                except:
                    showinfo("错误提示", "未选择路径!")
    
            win_open_wenjian_but = tk.Button(self.bommot_frame_left, text="打开文件", font=("宋体", 13), command=win_open_wenjian_button, relief="flat")
            win_open_wenjian_but.place(x=220, y=35)
    
        def gexian(self):
            tk.Label(self.bommot_frame_left, text="w|\ni|\nn|", font=("宋体", 13)).place(x=330, y=1)
    
    
    import tkinter as tk
    from tkinter.messagebox import showinfo
    
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    from ftp_client_alter_bug.tree.win_tree import WinTree
    
    
    class BottomMenuBarRight:
    
        def __init__(self, bommot_frame_right):
            self.bommot_frame_right = bommot_frame_right
    
        # 隔板
        def geban(self):
            tk.Label(self.bommot_frame_right, text="|f\n|t\n|p", font=("宋体", 13), relief="flat").place(x=-5, y=5)
    
        # 创建目录
        def ftp_chaungjian_mulu(self, ftp_path, ftp_list, tree_ftp):
    
            def ftp_cj_mulu_button():
                cj_win = tk.Tk()
                cj_win.geometry("300x200")
                titlte_lab = tk.Label(cj_win, text="创建目录", font=("宋体", 18))
                titlte_lab.place(x=105, y=25)
    
                titlte_lab = tk.Label(cj_win, text="目录名:", font=("宋体", 13))
                titlte_lab.place(x=30, y=80)
    
                cj_entry = tk.Entry(cj_win, width=21)
                cj_entry.place(x=100, y=80)
    
                def cj_button():
                    try:
                        muluzhi = str(cj_entry.get()).encode()
                        ftp_list[0].mkd(muluzhi.decode())
                        print(ftp_path)
                    except:
                        showinfo("错误提示", "路径选择或服务器连接异常!")
                    finally:
                        cj_win.destroy()
    
    
                    if str(ftp_list[0].pwd()) != "/":
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi(ftp_list[0].pwd())
                        # cj_win.destroy()
                    else:
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi("/")
                        # cj_win.destroy()
    
    
                cj_but = tk.Button(cj_win, text="确=======================认", font=("宋体", 13), command=cj_button)
                cj_but.place(x=20, y=130)
    
                cj_win.mainloop()
    
            ftp_cj_mulu_but = tk.Button(self.bommot_frame_right, text="创建目录", font=("宋体", 13), relief="flat", command=ftp_cj_mulu_button)
            ftp_cj_mulu_but.place(x=40, y=2)
    
    
        # 进入下级
        def ftp_jinru_xj(self, ftp_path, ftp_list, tree_ftp):
            def ftp_jinru_xj_button():
                try:
                    global path
                    path = ftp_path[0]
    
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi(ftp_path[0])
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
    
            global a
            a = ftp_jinru_xj_button
    
            ftp_jinru_xj_but = tk.Button(self.bommot_frame_right, text="进入下级", font=("宋体", 13), relief="flat", command=ftp_jinru_xj_button)
            ftp_jinru_xj_but.place(x=40, y=35)
    
        # 删除目录
        def ftp_delete_mulu(self, ftp_path, ftp_list, tree_ftp):
            def ftp_delete_mulu_button():
                try:
                    ftp_list[0].rmd(ftp_path[0])
    
                    if str(ftp_list[0].pwd()) != "/":
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi(ftp_list[0].pwd())
                    else:
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi("/")
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
    
    
            ftp_delete_mulu_but = tk.Button(self.bommot_frame_right, text="删除目录", font=("宋体", 13), relief="flat", command=ftp_delete_mulu_button)
            ftp_delete_mulu_but.place(x=150, y=2)
    
        # 删除文件
        def ftp_delete_wenjian(self, ftp_path, ftp_list, tree_ftp):
            def ftp_delete_wenjian_button():
                try:
    
                    ftp_list[0].delete(ftp_path[0])
    
                    if str(ftp_list[0].pwd()) != "/":
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi(ftp_list[0].pwd())
                    else:
                        table = tree_ftp
                        items = table.get_children()
                        [table.delete(item) for item in items]
                        ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                        ftptree.xianshi("/")
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
    
    
            ftp_delete_wenjian_but = tk.Button(self.bommot_frame_right, text="删除文件", font=("宋体", 13), relief="flat", command=ftp_delete_wenjian_button)
            ftp_delete_wenjian_but.place(x=150, y=35)
    
        # 下载文件
        def xiazai(self, ftp_list, ftp_path, win_path, xuanzhe_win_path, bommot_frame_center, tree):
    
            def xiazai_button():
                try:
                    print(ftp_list[0], ftp_path[0], win_path[0], "三个路径————————")
    
                    def downloadfile(ftp, remotepath, localpath):
                        bufsize = 1024  # 设置缓冲块大小
                        fp = open(localpath, 'wb')  # 以写模式在本地打开文件
                        ftp.retrbinary('RETR ' + remotepath, fp.write, bufsize)  # 接收服务器上文件并写入本地文件
                        ftp.set_debuglevel(0)  # 关闭调试
                        fp.close()  # 关闭文件
    
                    downloadfile(ftp_list[0], ftp_path[0], win_path[0]+"\\"+ftp_path[0].split("/")[-1])
    
                    # 更新进度条函数
                    def change_schedule(now_schedule, all_schedule):
                        canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                        bommot_frame_center.update()
                        x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                        if round(now_schedule / all_schedule * 100, 2) == 100.00:
                            x.set("完==成==了")
    
                    canvas = tk.Canvas(bommot_frame_center, width=110, height=30, bg="white")
                    canvas.place(x=150, y=25)
                    x = tk.StringVar()
                    # 进度条以及完成程度
                    out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                    fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")
    
                    tk.Label(bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)
    
                    for i in range(100):
                        change_schedule(i, 99)
    
                    table = tree
                    items = table.get_children()
                    [table.delete(item) for item in items]
    
                    wintree = WinTree(xuanzhe_win_path[0], win_path, tree)
                    wintree.show_wenjian()
    
                    print(win_path[0]+ftp_path[0].split("\\")[-1],"============================")
    
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
            xiazai_but = tk.Button(self.bommot_frame_right, text="下载文件", font=("宋体", 13), relief="flat", command=xiazai_button)
            xiazai_but.place(x=250, y=2)
    
        # 返回上级
        def ftp_fh_sj(self, ftp_path, ftp_list, tree_ftp):
    
            def ftp_fh_sj_button():
                try:
                    table = tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, tree_ftp)
                    ftptree.xianshi("..")
                except:
                    showinfo("错误提示", "路径选择或服务器连接异常!")
            global b
            b = ftp_fh_sj_button
    
    
            ftp_fh_sj_but = tk.Button(self.bommot_frame_right, text="返回上级", font=("宋体", 13), relief="flat", command=ftp_fh_sj_button)
            ftp_fh_sj_but.place(x=250, y=35)
    
    import os
    from tkinter import ttk
    import tkinter as tk
    
    class FtpSearch:
        def __init__(self, tree_ftp, search_name, ftp_search_path, win_tree):
            self.ftp = tree_ftp
            # 搜索框的内容
            self.search_name = search_name
            self.ftp_search_path = ftp_search_path
            self.tree = win_tree
    
            # # 滚动条
            # sy = tk.Scrollbar(self.center_frame)
            # sy.pack(side=tk.RIGHT, fill=tk.Y)
            # sy.config(command=self.tree.yview)
            # self.tree.config(yscrollcommand=sy.set)
    
            # 绑定事件
            self.tree.bind("<<TreeviewSelect>>", self.func)
            self.tree.pack(expand=True, fill=tk.BOTH)
            self.ev = tk.Variable()
    
    
        def show(self):
            dir_res = []
            self.ftp.dir('.', dir_res.append)
            for i in dir_res:
                print(i)
                if self.search_name in i.split()[3]:
                    self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[3]))
    
    
        def func(self, event):
            # widget触发事件的构建
            self.v = event.widget.selection()
            for sv in self.v:
                file = self.tree.item(sv)["text"]
                self.ev.set(file)
                apath = self.tree.item(sv)["values"][0]
    
                self.ftp_search_path.clear()
                self.ftp_search_path.append(apath)
                print(self.ftp_search_path)
                print(apath)
    
    import os
    from tkinter import ttk
    import tkinter as tk
    
    class WinSearch:
        def __init__(self, search_path, search_name, win_search_path, win_tree):
            self.search_path = search_path
            # 搜索框的内容
            self.search_name = search_name
            self.win_search_path = win_search_path
            self.tree = win_tree
    
            # # 滚动条
            # sy = tk.Scrollbar(self.center_frame)
            # sy.pack(side=tk.RIGHT, fill=tk.Y)
            # sy.config(command=self.tree.yview)
            # self.tree.config(yscrollcommand=sy.set)
    
            # 绑定事件
            self.tree.bind("<<TreeviewSelect>>", self.func)
            self.tree.pack(expand=True, fill=tk.BOTH)
            self.ev = tk.Variable()
    
    
        # 搜索关键词目录
        def search_keyword_dirs(self, root1, dirs):
            for _dir in dirs:
                if -1 != _dir.find(self.search_name) and _dir[0] != '$':
                    AllDir = os.path.join(root1, _dir)
                    self.tree.insert("", "end", text=AllDir, values=(AllDir,))
    
        # 搜索关键词文件
        def search_keyword_files(self, root, files):
            for file in files:
                if self.search_name in file:
                    AllFile = os.path.join(root, file)
    
                    self.tree.insert("", "end", text=AllFile, values=(AllFile,))
    
        # 搜索
        def search(self):
            curdisks = self.search_path
            # root 当前正在遍历的这个文件夹的本身的地址
            # dirs 是一个 list ,内容是该文件夹中所有的目录的名字
            # files 同样是 list , 内容是该文件夹中所有的文件
            for root, dirs, files in os.walk(curdisks):
                self.search_keyword_dirs(root, dirs)
                self.search_keyword_files(root,  files)
    
    
    
        def func(self, event):
            # widget触发事件的构建
            self.v = event.widget.selection()
            for sv in self.v:
                file = self.tree.item(sv)["text"]
                self.ev.set(file)
                apath = self.tree.item(sv)["values"][0]
    
                self.win_search_path.clear()
                self.win_search_path.append(apath)
                print(self.win_search_path)
                print(apath)
    
    
    
    import pickle
    import tkinter as tk
    from tkinter import ttk
    from tkinter.messagebox import showinfo
    
    from ftp_client_alter_bug.seek.ftp_search import FtpSearch
    from ftp_client_alter_bug.seek.win_search import WinSearch
    from ftplib import FTP
    import tkinter.filedialog as fi
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    from ftp_client_alter_bug.tree.win_tree import WinTree
    
    
    class TopMenuBar:
        def __init__(self, top_frame, path, win, win_search_path, ftp_list, xuanzhe_win_path):
            self.top_frame = top_frame
            self.path = path
            self.win = win
            self.win_search_path = win_search_path
            self.ftp_list = ftp_list
            self.xuanzhe_win_path = xuanzhe_win_path
    
    
        # logo
        def logo(self):
            logo_lable = tk.Label(self.top_frame, text="FTP客户端", font=("华文彩云", 29), fg="green")
            logo_lable.place(x=5, y=10)
    
        # window目录选择按钮
        def local_mulu(self, win_path, tree):
            # 目录选择按钮的回调函数
            def mulu_button():
                self.xuanzhe_win_path.clear()
                DEF_PATH = ""
                newDir = fi.askdirectory(initialdir=DEF_PATH, title="打开目录")
                print(newDir)
                DEF_PATH = newDir
                if len(newDir) == 0:
                    return
                print(DEF_PATH)
                self.xuanzhe_win_path.append(DEF_PATH)
                print(self.xuanzhe_win_path)
    
                table = tree
                items = table.get_children()
                [table.delete(item) for item in items]
    
                wintree = WinTree(self.xuanzhe_win_path[0], win_path, tree)
                wintree.show_wenjian()
    
            mulu_but = tk.Button(self.top_frame, text="选择本地目录", font=("宋体", 13), command=mulu_button, relief="flat")
            mulu_but.place(x=220, y=5)
    
        # 打开文件按钮
        def open_wenjian(self):
            def open_wenjian_button():
                pass
    
            open_wenjian_but = tk.Button(self.top_frame, text="选择本地文件", font=("宋体", 13), command=open_wenjian_button, relief="flat")
            open_wenjian_but.place(x=220, y=30)
    
    
        # 搜索框和其按钮
        def search_box(self, win_search_name, win_search_tree, ftp_search_path, ftp_list):
            # 本地搜索按钮的回调函数
            def local_search_button():
                try:
                    win_search_name.clear()
                    win_name = search_entry.get()
                    win_search_name.append(win_name)
    
                    table = win_search_tree[0]
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    winsearch = WinSearch(self.xuanzhe_win_path[0], win_name, self.win_search_path, win_search_tree[0])
                    winsearch.search()
                except:
                    showinfo("错误提示", "本地路径异常!")
    
            # ftp搜索按钮的回调函数
            def ftp_search_button():
                try:
                    win_search_name.clear()
                    win_name = search_entry.get()
                    win_search_name.append(win_name)
    
                    table = win_search_tree[0]
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftpsearch = FtpSearch(ftp_list[0], win_name, ftp_search_path, table)
                    ftpsearch.show()
                except:
                    showinfo("错误提示", "服务器连接异常!")
    
    
            search_entry = tk.Entry(self.top_frame, width="21",  font=("宋体", 15))
            search_entry.place(x=475, y=17)
    
            window_search = tk.Button(self.top_frame, text="本地搜索", font=("宋体", 15), command=local_search_button, relief="flat")
            window_search.place(x=350, y=17)
    
            ftp_search = tk.Button(self.top_frame, text="ftp搜索", font=("宋体", 15), command=ftp_search_button, relief="flat")
            ftp_search.place(x=730, y=17)
    
        # ip,port显示
        def name_ip(self, bieming, ip):
            name = bieming
            name_lable = tk.Label(self.top_frame, text=f"user: {name}", font=("宋体", 13))
            name_lable.place(x=850, y=5)
            ip = ip
            ip_lable = tk.Label(self.top_frame, text=f"ip: {ip}", font=("宋体", 13))
            ip_lable.place(x=1030, y=5)
    
        # 退出登录按钮
        def exit_login(self, ftp_tree_list, ftp_path, ftp_list):
            def exit_button():
                self.ftp_list[0].quit()
                table = ftp_tree_list[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
                ftptree.xianshi("/")
    
            exit_but = tk.Button(self.top_frame, text="退出登录", font=("宋体", 13), command=exit_button, relief="flat")
            exit_but.place(x=1100, y=30)
    
        # 登录按钮
        def login_in(self, ftp_path, ftp_list, ftp_tree_list):
            def login_in_button():
                wind = tk.Tk()
                wind.geometry("400x370")
                titile_lab = tk.Label(wind, text="ftp登录", font=("宋体", 19))
                titile_lab.place(x=150, y=30)
    
                self.ftp_list.clear()
    
                bieming_lab = tk.Label(wind, text="别名:", font=("宋体", 15))
                bieming_lab.place(x=60, y=90)
                bieming_entry = tk.Entry(wind, font=("宋体", 15))
                bieming_entry.place(x=130, y=90)
    
                user_name_lab = tk.Label(wind, text="用户名:", font=("宋体", 15))
                user_name_lab.place(x=40, y=130)
                user_name_entry = tk.Entry(wind, font=("宋体", 15))
                user_name_entry.place(x=130, y=130)
    
                pass_name_lab = tk.Label(wind, text="密码:", font=("宋体", 15))
                pass_name_lab.place(x=60, y=170)
                pass_name_entry = tk.Entry(wind, font=("宋体", 15))
                pass_name_entry.place(x=130, y=170)
    
                ip_name_lab = tk.Label(wind, text="ip:", font=("宋体", 15))
                ip_name_lab.place(x=80, y=210)
                ip_name_entry = tk.Entry(wind, font=("宋体", 15))
                ip_name_entry.place(x=130, y=210)
    
                port_name_lab = tk.Label(wind, text="port:", font=("宋体", 15))
                port_name_lab.place(x=60, y=250)
                port_name_entry = tk.Entry(wind, font=("宋体", 15))
                port_name_entry.place(x=130, y=250)
    
                def d_button():
                    self.ftp_list.clear()
                    bieming = str(bieming_entry.get())
                    user_name = str(user_name_entry.get())
                    pass_name = str(pass_name_entry.get())
                    ip_name = str(ip_name_entry.get())
                    port_name = int(port_name_entry.get())
    
                    try:
                        # 打开被序列化文件
                        with open("../data/usr_info.pickle", "wb") as usr_file:
                            # 用户数据
                            usr_info = [bieming, user_name, pass_name, ip_name, port_name]
                            # 存储(序列化)数据
                            pickle.dump(usr_info, usr_file)
                    except FileNotFoundError:
                            print("存储错误")
    
                    self.name_ip(bieming, ip_name)
    
                    self.ftp = FTP()  # 设置变量
                    self.ftp.connect(ip_name, port_name)  # 连接的ftp sever和端口
                    self.ftp.login(user_name, pass_name)  # 连接的用户名,密码
                    self.ftp.encoding = 'GB18030'
    
                    self.ftp_list.append(self.ftp)
    
                    table = ftp_tree_list[0]
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
                    ftptree.xianshi("/")
    
                    wind.destroy()
    
    
                d_but = tk.Button(wind, text="登=======================录", font=("宋体", 15), command=d_button)
                d_but.place(x=60, y=310)
    
    
                wind.mainloop()
    
    
    
            login_in_but = tk.Button(self.top_frame, text="登录", font=("宋体", 13), command=login_in_button, relief="flat")
            login_in_but.place(x=850, y=30)
    
        # 历史登录
        def lishi_login_in(self, ftp_path, ftp_list, ftp_tree_list):
            def lishi_login_button():
                self.ftp_list.clear()
                try:
                    # 打开被序列化文件,会自动创建此文件
                    with open("../data/usr_info.pickle", "rb+") as usr_file:
                        # 读取被序列化的文件
                        global usr_info
                        usr_info = pickle.load(usr_file)
                        print(usr_info)
                except FileNotFoundError:
                        print("读取错误")
    
                self.name_ip(usr_info[0], usr_info[3])
    
                self.ftp = FTP()  # 设置变量
                self.ftp.connect(usr_info[3], usr_info[4])  # 连接的ftp sever和端口
                self.ftp.login(usr_info[1], usr_info[2])  # 连接的用户名,密码
                self.ftp.encoding = 'GB18030'
    
                self.ftp_list.append(self.ftp)
    
                table = ftp_tree_list[0]
                items = table.get_children()
                [table.delete(item) for item in items]
                ftptree = FtpTree(ftp_path, ftp_list, ftp_tree_list[0])
                ftptree.xianshi("/")
    
            lishi_login_but = tk.Button(self.top_frame, text="历史登录", font=("宋体", 13), command=lishi_login_button, relief="flat")
            lishi_login_but.place(x=950, y=30)
    
    import os
    import tkinter as tk
    from tkinter import ttk
    from ftplib import FTP  # 加载ftp模块
    import sys
    
    class FtpTree:
    
        def __init__(self, ftp_path, ftp_list, tree_ftp):
    
            self.tree = tree_ftp
            self.num = 0
    
            self.ftp_list = ftp_list
            self.ftp_path = ftp_path
    
    
            # # 滚动条
            # sy = tk.Scrollbar(self.right_frame)
            # sy.pack(side=tk.LEFT, fill=tk.Y)
            # sy.config(command=self.tree.yview)
            # self.tree.config(yscrollcommand=sy.set)
    
            # 绑定事件
            self.tree.bind("<<TreeviewSelect>>", self.func)
            self.tree.pack(expand=True, fill=tk.BOTH)
            self.ev = tk.Variable()
            print(self.ev)
    
        def xianshi(self, path_ftp):
    
            self.ftp = self.ftp_list[0]
            self.ftp.cwd(path_ftp)
            self.num += 1
            dir_res = []
            self.ftp.dir('.', dir_res.append)
            for i in dir_res:
                if i.split()[2] == "<DIR>":
                    self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[0], i.split()[2]))
                else:
                    self.tree.insert("", "end", text=i.split()[3], open=True, values=(i.split()[0], "<file>"))
    
        def func(self, event):
            # widget触发事件的构建
            self.v = event.widget.selection()
            for sv in self.v:
                self.file = self.tree.item(sv)["text"]
                self.ev.set(self.file)
    
                self.ftp_path.clear()
                self.ftp_path.append(self.file)
                print(self.ftp_path)
                print(self.file)
    
    
    
    
    import os
    import tkinter as tk
    from tkinter import ttk
    
    class WinTree:
    
        def __init__(self, path, win_path, tree):
            self.path = path
            self.win_path = win_path
            self.tree = tree
    
            # # 滚动条
            # sy = tk.Scrollbar(self.left_frame)
            # sy.pack(side=tk.RIGHT, fill=tk.Y)
            # sy.config(command=self.tree.yview)
            # self.tree.config(yscrollcommand=sy.set)
    
            # 绑定事件
            self.tree.bind("<<TreeviewSelect>>", self.func)
            self.tree.pack(expand=True, fill=tk.BOTH)
            self.ev = tk.Variable()
            print(self.ev)
    
        def show_wenjian(self):
            self.root = self.tree.insert("", "end", text=self.getlastpath(self.path, ), open=True, values=(self.path,))
            self.loadtree(self.root, self.path)
    
        def func(self, event):
            # widget触发事件的构建
            self.v = event.widget.selection()
            for sv in self.v:
                file = self.tree.item(sv)["text"]
                self.ev.set(file)
                apath = self.tree.item(sv)["values"][0]
    
                self.win_path.clear()
                self.win_path.append(apath)
                print(self.win_path)
                print(apath)
    
        def loadtree(self, parent, parentPath):
            for FileName in os.listdir(parentPath):
                absPath = os.path.join(parentPath, FileName)
                if ("$" in absPath) == False:
                    # 插入树枝
                    treey = self.tree.insert(parent, "end", text=self.getlastpath(absPath), values=(absPath, ))
    
                    # 判断是否是目录
                    if os.path.isdir(absPath):
    
                        self.loadtree(treey, absPath)
    
        def getlastpath(self, path):
    
            pathList = os.path.split(path)
            return pathList[-1]
    
    
    from tkinter.messagebox import showinfo
    
    import windnd
    import tkinter as tk
    from ftp_client_alter_bug.tree.ftp_tree import FtpTree
    
    
    class FtpDrag():
        def __init__(self, right_frame, ftp_path, ftp_list, win_path, bommot_frame_center, tree_ftp):
            self.right_frame = right_frame
            self.ftp_path = ftp_path
            self.ftp_list = ftp_list
            self.win_path = win_path
            self.bommot_frame_center = bommot_frame_center
            self.tree_ftp = tree_ftp
    
        def win_file(self, files):
            msg = "\n".join((item.decode("gbk") for item in files))
            print(msg)
            # with open(msg, mode="rb+") as re:
            #     buffer = re.read()
            # with open(self.win_path[0] + "\\" + msg.split("\\")[-1], mode="wb+") as wr:
            #     wr.write(buffer)
            try:
                def uploadfile(ftp, remotepath, localpath):
                    bufsize = 1024
                    fp = open(localpath, 'rb')
                    ftp.storbinary(r'STOR ' + rf'{remotepath}', fp, bufsize)  # 上传文件
                    ftp.set_debuglevel(0)
                    fp.close()
    
    
                uploadfile(self.ftp_list[0], self.ftp_list[0].pwd() + "\\" + msg.split("\\")[-1], msg)
    
                # 更新进度条函数
                def change_schedule(now_schedule, all_schedule):
                    canvas.coords(fill_rec, (5, 5, 6 + (now_schedule / all_schedule) * 100, 25))
                    self.bommot_frame_center.update()
                    x.set(str(round(now_schedule / all_schedule * 100, 2)) + '%')
                    if round(now_schedule / all_schedule * 100, 2) == 100.00:
                        x.set("完==成==了")
    
                canvas = tk.Canvas(self.bommot_frame_center, width=110, height=30, bg="white")
                canvas.place(x=150, y=25)
                x = tk.StringVar()
                # 进度条以及完成程度
                out_rec = canvas.create_rectangle(5, 5, 105, 25, outline="blue", width=1)
                fill_rec = canvas.create_rectangle(5, 5, 5, 25, outline="", width=0, fill="blue")
    
                tk.Label(self.bommot_frame_center, textvariable=x, font=("宋体", 13)).place(x=280, y=30)
    
                for i in range(100):
                    change_schedule(i, 99)
    
                if str(self.ftp_list[0].pwd()) != "/":
                    table = self.tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(self.ftp_path, self.ftp_list, self.tree_ftp)
                    ftptree.xianshi(self.ftp_list[0].pwd())
                else:
                    table = self.tree_ftp
                    items = table.get_children()
                    [table.delete(item) for item in items]
                    ftptree = FtpTree(self.ftp_path, self.ftp_list, self.tree_ftp)
                    ftptree.xianshi("/")
            except:
                showinfo("错误提示", "服务器连接异常!")
    
        def execute(self):
            windnd.hook_dropfiles(self.right_frame, func=self.win_file)
    
    from tkinter.messagebox import showinfo
    
    import windnd
    from ftp_client_alter_bug.tree.win_tree import WinTree
    
    
    class WinDrag():
        def __init__(self, left_frame, win_path, xuanzhe_win_path, tree):
            self.left_frame = left_frame
            self.win_path = win_path
            self.xuanzhe_win_path = xuanzhe_win_path
            self.tree = tree
    
        def win_file(self, files):
            msg = "\n".join((item.decode("gbk") for item in files))
            print(msg)
            try:
                with open(msg, mode="rb+") as re:
                    buffer = re.read()
                with open(self.win_path[0] + "\\" + msg.split("\\")[-1], mode="wb+") as wr:
                    wr.write(buffer)
                table = self.tree
                items = table.get_children()
                [table.delete(item) for item in items]
    
                wintree = WinTree(self.xuanzhe_win_path[0], self.win_path, self.tree)
                wintree.show_wenjian()
            except:
                showinfo("错误提示", "未选择本地路径!")
    
        def execute(self):
            windnd.hook_dropfiles(self.left_frame, func=self.win_file)
    
    展开全文
  • 2019独角兽企业重金招聘Python工程师标准>>> ...

     

     

    今天,来为大家讲解一下无刷新页面(也称伪静态页面的操作方法)

    原理:

     伪静态通俗点说就是假的静态页面,也就是通过各种技术手段,让动态页面URL看上去和静态页面的一样。

     

    所使用工具:

    Microsoft Visual Studio 2010

    SQL Server Management Studio

     

     

    先建立一个数据库Table_4,方便我们一会的操作。

    Table_4:

    8311d4714c0ba13f99d96e7ecdfd9da4164.jpg

    然后继续我们的三层建立,项目结构图如下:

    aa1434d3344f1fb86dc9da025189dcf1491.jpg

    如果不会建立三层的同学可以去看我前面的文章

    https://my.oschina.net/u/3913001/blog/1858562

    然后就开始对各层实施代码了。

    上代码~

    Model层(user):
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Model
    {
        public class user
        {
            public string id { set; get; }
            public string username { set; get; }
            public string userpwd { set; get; }
            public string realname { set; get; }
        }
    }
    
    DAL层(dal):
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using System.Data.SqlClient;
    
    namespace DAL
    {
        public class dal
        {
            public List<Model.user> EModel(string where)
            {
                DataSet ds = DB.ToGetData(" select * from Table_4" + where);
                if (ds != null && ds.Tables[0] != null && ds.Tables[0].Rows.Count > 0)
                {
                    Model.user Myuserlist = null;
                    List<Model.user> MyList = new List<Model.user>();
                    foreach (DataRow item in ds.Tables[0].Rows)
                    {
                        Myuserlist = new Model.user();
                        Myuserlist.id = item["id"].ToString();
                        Myuserlist.username = item["username"].ToString();
                        Myuserlist.userpwd = item["userpwd"].ToString();
                        Myuserlist.realname = item["realname"].ToString();
                        MyList.Add(Myuserlist);
                    }
                    return MyList;
                }
                else
                {
                    return null;
                }
            }
    
             public class DB 
        {
      static string ConnStr = "Data Source=.;Initial Catalog=调用的数据库名;Persist Security Info=True;User ID=数据库用户名;Password=数据库密码";
           
            public static DataSet ToGetData(string Sql)
            {
                using (SqlConnection Conn = new SqlConnection(ConnStr))
                {
                    using (SqlDataAdapter da = new SqlDataAdapter(Sql, Conn))
                    {
                        DataSet ds = new DataSet();
                        Conn.Open();
                        da.Fill(ds);
                        da.Dispose();
                        return ds;
                    }
                }
            } 
        }
    }
        }
    
    
    UI层(前端):
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="fengye.aspx.cs" Inherits="UI.fengye" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
    
        <div>
         请输入用户ID:<asp:TextBox ID="TextBox1" runat="server">
            </asp:TextBox>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
            <asp:Button ID="Button1"
                runat="server" Text="查¨¦询¡¥" onclick="Button1_Click" /><br />
            
        <asp:DataList ID="DataList1" runat="server" 
               >
            <HeaderTemplate><table>
            <tr>
            <td>用户ID</td>
             <td>用户名字</td>
             <td>用户密码</td>
            <td>真实姓名</td>
            </tr>
            </HeaderTemplate>
            <ItemTemplate>
            <tr>
            <td> <%# Eval("id") %></td>
             <td> <%# Eval("username")%></td>
              <td> <%# Eval("userpwd")%></td>
               <td> <%# Eval("realname")%></td>
            </tr>
           </tr>
            </ItemTemplate>
            <FooterTemplate></table></FooterTemplate>
            </asp:DataList>
            </ContentTemplate> 
            </asp:UpdatePanel> 
        </div>
        </form>
    </body>
    </html>
    
    UI层(后端):
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    
    namespace UI
    {
        public partial class fengye : System.Web.UI.Page
        {
            BLL.bll Ebll = new BLL.bll();
            protected void Page_Load(object sender, EventArgs e)
            {
               
            }
            
    
            public void Button1_Click(object sender, EventArgs e)
            {
                string Byid = TextBox1.Text.Trim();
                if (!string.IsNullOrEmpty(Byid))
                {
    
                    DataList1.DataSource = Ebll.MyModel(Byid);
                    DataList1.DataBind();
    
    
                }
            }
        }
    }
    

    当完成以后执行,会发现查询改变的时候,页面没有刷新,是不是很神奇?

    09219b6229bc4b4c50e009804bd3c1f2da5.jpg

    转载于:https://my.oschina.net/aidaidai/blog/1863451

    展开全文
  • 登录页面模块功能实现生成验证码->显示验证码->检验验证码->保存会员登录状态会员退出功能:清空会话中的user_id和用户名 2.首页商品图片轮播展示,显示热销和推荐购买,搜索商品(张家豪) 显示商品热销(根据商品...
  • 提示:文章写完后,目录可以自动生成,如何生成可参考右边的...示例:在工具中,包含着本问所要实现功能,输入每一个功能前的数字,即可实现这个功能 二、使用步骤 1.引入库 代码如下: import os 2.执行函数 代码


    一、成果展示

    在这里插入图片描述

    示例:在工具框中,包含着本问所要实现的功能,输入每一个功能前的数字,即可实现这个功能

    二、使用步骤

    1.引入库

    代码如下:

    import os
    

    2.执行函数

    代码如下:

    if __name__ == '__main__':
        main()
    

    规定函数的执行次序

    3.主函数

    代码如下:

    def main():
        while True:
            menm()
            choice = int(input("请输入:"))
            if choice in [0,1,2,3,4,5,6,7]:
                if choice == 0:
                    answer = input("您确定退出系统吗?y/n:")
                    if answer == 'y' or answer == 'Y':
                        print("感谢您的使用")
                        break
                    if answer == 'n' or answer == 'N':
                        continue
                elif choice == 1:
                    insert()
    
                elif choice == 2:
                    search()
                elif choice == 3:
                    delete()
                elif choice == 4:
                    modify()
                elif choice == 5:
                    sort()
                elif choice == 6:
                    total()
                elif choice == 7:
                    show()
    
    
            else :
                print("输入有误,请重新输入")
    

    根据所输入的数字,调用所对应的函数

    4.显示主页面

    代码如下:

    def menm():
        print('''
        ==============================学生信息管理系统===================================
        ---------------------------------功能选择---------------------------------------
        \t\t\t\t 1.录入学生信息
        \t\t\t\t 2.查找学生信息
        \t\t\t\t 3.删除学生信息
        \t\t\t\t 4.修改学生信息
        \t\t\t\t 5.排序
        \t\t\t\t 6.统计学生总人数
        \t\t\t\t 7.显示所有学生信息
        \t\t\t\t 0.退出系统
        ------------------------------------------------------------------------------
        ==============================================================================
        ''')
    

    定义要显示主页面,列出所有的功能

    5.插入学生信息

    代码如下:

    def insert():
        student_list = []
        while True:
            id = input("请输入id(比如1001):")
            if not id:
                break
            name = input("请输入姓名:")
            if not name:
                break
            try:
                escore = int(input("请输入英语成绩:"))
                java = int(input("请输入java成绩:"))
                python = int(input("请输入python成绩:"))
            except:
                print("输入有误,请重新输入")
                continue
    
            student = {'id':id,'name':name,'escore':escore,'java':java,'python':python}
            student_list.append(student)
            answer = input("是否继续输入y/n:")
            if answer == 'y' or answer == 'Y':
                continue
            else:
                break
        save(student_list)
        print("学生信息录入完毕!!!")
    

    6.保存学生信息到文件

    代码如下:

    filename = 'student.txt'
    def save(lst):
        try:
            stu_txt = open(filename,'a',encoding = 'utf-8')
    
        except:
            stu_txt = open(filename,'w',encoding = 'utf-8')
        for item in lst:
            stu_txt.write(str(item)+'\n')
        stu_txt.close()
    

    save函数,把得到的信息写入到规定的文件里

    7.搜索学生信息并显示

    代码如下:

    def search():
        student_query = []
        while True:
            id = ''
            name = ''
            if os.path.exists(filename):
                mode = input('按ID查找请输入1,按名字查找请输入2:')
                if mode == '1':
                    id = input('请输入学生ID:')
                elif mode == '2':
                    name = input('请输入名字:')
                else:
                    print('输入信息有误')
                    search()
                with open(filename, 'r', encoding='utf-8') as rfile:
                    student = rfile.readlines()
                    for item in student:
                        d = dict(eval(item))
                        if id != '':
                            if d['id'] == id:
                                student_query.append(d)
                        if name != '':
                            if d['name'] == name:
                                student_query.append(d)
                # 显示查询结果
                show_student(student_query)
                student_query.clear()
                answer = input('是否继续查询学生信息:y/n: ')
                if answer == 'y':
                    continue
                else:
                    break
            else:
                print('尚未保存学生信息:')
                return
    

    查询已保存的学生信息,可根据ID或姓名查询

    8.显示搜索信息

    代码如下:

    def show_student(lst):
        if len(lst) == 0:
            print('没有查询到学生信息,无数据显示')
            return
        format_title = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}'
        print(format_title.format('id','姓名','英语成绩','java成绩','python成绩','总成绩'))
        format_data = '{:^6}\t{:^12}\t{:^8}\t{:^10}\t{:^10}\t{:^8}'
        for item in lst:
            print(format_data.format(
                                        item.get('id'),
                                        item.get('name'),
                                        item.get('escore'),
                                        item.get('java'),
                                        item.get('python'),
                                        int(item.get('escore'))+int(item.get('java'))+int(item.get('python'))
                                    ))
    

    展示搜索到的学生信息,并按照规定格式显示

    9.删除学生信息

    代码如下:

    def delete():
        while True:
            student_id = input('请输入想要删除的id:')
            if student_id != '':
                if os.path.exists(filename):
                    with open(filename,'r',encoding='utf-8') as file:
                        student_old = file.readlines()
                else:
                    student_old = []
                flag = False
                if student_old:
                    with open(filename,'w',encoding='utf-8') as wfile:
                        d = {}
                        for item in student_old:
                            d = dict(eval(item))
                            if d['id'] != student_id:
                                wfile.write(str(d)+'\n')
                            else:
                                flag = True
                        if flag:
                            print(f"ID为{student_id}的学生信息已经删除!")
    
                        else:
                            print(f'没有找到ID为{student_id}的学生信息')
                else:
                    print('无此学生信息')
                    break
                show()
                s = print('请选择是否继续删除学生信息 y/n:')
                if s == 'y' or s == 'Y':
                    continue
                else:
                    break
    
                                    ))
    

    把已保存的学生信息,按照输入的ID删除此学生信息

    10.修改学生信息

    代码如下:

    def modify():
        show()
        if os.path.exists(filename):
            with open(filename,'r',encoding='utf-8') as rfile:
                student_old = rfile.readlines()
        else:
            return
        student_id = input('请输入你想要修改的学生ID:')
        with open(filename,'w',encoding='utf-8') as wfile:
            for item in student_old:
                d = dict(eval(item))
                if d['id'] == student_id:
                    print(f'找到{student_id}的信息,可以修改')
                    while True:
                        try:
                            d['name'] = input('请输入名字:')
                            d['escore'] = int(input('请输入英语成绩:'))
                            d['java'] = input('请输入java成绩:')
                            d['python'] = input('请输入python成绩:')
                        except:
                            print('输入有误,请重新输入')
                            continue
                        else:
                            break
                    wfile.write(str(d)+'\n')
    
                else:
                    wfile.write(str(d)+'\n')
            wfile.close()
    
            answer = input('是否继续修改学生信息 y/n:')
            if answer == 'y' or answer == 'Y':
                modify()
            else:
                print("信息修改成功!!!")
    

    把已保存的学生信息,重新修改在保存

    11.对学生信息进行排序

    代码如下:

    def sort():
        show()
    
        if os.path.exists(filename):
            with open(filename,'r',encoding='utf-8') as rfile:
                students = rfile.readlines()
            student_new = []
            for item in students:
                d = dict(eval(item))
                student_new.append(d)
            asc = input('请选择(0.升序 1.降序):')
            if asc == '0':
                asc_bool = False
            elif asc == '1':
                asc_bool = True
            else:
                print('您的输入有误,请重新输入!!!')
                sort()
            mode = input('请选择排序方式(1.按英语成绩排序 2.按java成绩排序 3.按python成绩排序 0.按总成绩排序):')
            if mode == '1':
                student_new.sort(key=lambda x:int(x['escore']),reverse= asc_bool)
            elif mode == '2':
                student_new.sort(key=lambda x:int(x['java']),reverse= asc_bool)
            elif mode == '3':
                student_new.sort(key=lambda x:int(x['python']),reverse= asc_bool)
            elif mode == '0':
                student_new.sort(key=lambda x:int(x['escore'])+int(x['python'])+int(x['java']),reverse= asc_bool)
            else:
                print('输入有误,请重新输入!!!')
                sort()
            show_student(student_new)
        else :
            return
                                    ))
    

    根据各科的成绩,来进行升序或降序排列,并显示排序后得信息

    12.显示学生人数

    代码如下:

    def total():
        if os.path.exists(filename):
            with open(filename,'r',encoding='utf-8') as rfile:
                students = rfile.readlines()
                if students:
                    print(f'一共有{len(students)}名学生')
                else:
                    print('还未录入学生信息')
    
    
        else:
            print('还未保存学生信息')
                                    ))
    

    展示所有已保存的学生信息的数量

    13.展示所有学生信息

    代码如下:

    def show():
        student_list = []
        if os.path.exists(filename):
            with open(filename,'r',encoding='utf-8') as rfile:
                students = rfile.readlines()
            for item in students:
                student_list.append(eval(item))
            if student_list:
                show_student(student_list)
                                    ))
    

    展示所有已保存的学生信息

    三、目的

    提高对python基础的掌握

    展开全文
  • 本系列以可操作性为主,介绍如何通过django web框架来实现一些简单的功能。每一章都具有完整性和独立性。使用新手在动手做的过程中体会web开发的过程,过程中细节请参考相关文档。 本操作的环境: ================...
  • 实现文章的搜索功能 文章的标签及列表功能 文章的分类和列表功能 根据设置的相册显示配置的图片和链接 添加友情链接功能 初步实现个人简历页面 todo 文章推送到百度收录 新增分类时生成分类图片(文章列表显示) ...
  • Mistune:快速并且功能齐全的纯 Python 实现的 Markdown 解析器。 Python-Markdown:John Gruber’s Markdown 的 Python实现Python-Markdown2:纯 Python 实现的 Markdown 解析器,比 Python-Markdown 更快...
  • Python Cookbook

    2013-07-31 22:33:26
    3.14 用Python实现的简单加法器 133 3.15 检查信用卡校验和 136 3.16 查看汇率 137 第4章 Python技巧 139 引言 139 4.1 对象拷贝 140 4.2 通过列表推导构建列表 144 4.3 若列表中某元素存在则返回之 146 ...
  • ├─(124) 03 python全栈3 day56 基于BootStrap和FontAwesome制作页面.avi ├─(125) 04 python全栈3 day56 创建学生信息(一).avi ├─(126) 05 python全栈3 day56 创建学生信息(二).avi ├─(127) 06 python...
  • Python+Appium-6-class定位

    2019-06-04 08:25:04
    前言 基于前一篇的id和name定位的案例,本篇就针对class定位...第一个页面搜索框的class值:android.widget.TextView 点击后第二个页面的搜索框class值:android.widget.EditText 百度一下按钮的class值:androi...

    前言

    基于前一篇的id和name定位的案例,本篇就针对class定位来实现百度搜索功能

     

    class定位

    class定位就是通过UI Automator工具查看的class属性

    第一个页面搜索框的class值:android.widget.TextView

    点击后第二个页面的搜索框class值:android.widget.EditText

    百度一下按钮的class值:android.widget.TextView(这里用class定位死活不成功也不报错,class属性很多都是不唯一的,所以这里的我换了id定位)

     

    脚本编写

    from appium import webdriver
    import time
    # 配置信息
    desired_caps = {
        "platformName":"Android",
        "deviceName":"127.0.0.1:62001",
        "platformVersion":"6.0",
        "appPackage":"com.baidu.searchbox",
        "appActivity":"com.baidu.searchbox.SplashActivity",
        "unicodeKeyboard":True,  # 使unicode编码方式发送字符串
        "resetKeyboard":True   # 隐藏键盘
    }
    
    # 创建驱动
    driver = webdriver.Remote("127.0.0.1:4723/wd/hub", desired_caps)
    time.sleep(5)
    driver.find_element_by_class_name("android.widget.TextView").click()
    time.sleep(3)
    driver.find_element_by_class_name("android.widget.EditText").send_keys("appium class学习")
    time.sleep(5)
    # driver.find_element_by_class_name("android.widget.TextView").click()
    driver.find_element_by_id("com.baidu.searchbox:id/home_operation_enter").click()
    time.sleep(30)
    driver.quit()

     

    脚本运行

    展开全文
  • 阅览室是一个(虚拟的)书评“俱乐部”网站,提供...实现功能 响应式设计 拓扑结构 互动元素 未来功能 场地建设 页面布局 施工台 数据库设计 体裁合集 用户集合 隐私收集 terms_conditions集合 资料类型 搜索引擎优化
  • 各位好。 我想开发一个自己使用的网页版的写作工具,...<p>2、有哪些插件/扩展可以配合选择的技术/框架实现页面中各个区块的具体功能? <p>3、外包这样一个网站的大概价格和交付时间。</p>
  • 尹成Python27天入门到项目实战

    千人学习 2020-12-05 17:04:22
    面向对象数据搜索实战输入处理文本编辑器表格数据树状显示数据搜索可视化第一步实现查询窗体数据搜索可视化第二步实现搜索数据数据搜索可视化第三步实现显示窗体数据可视化第四步显示与搜索串联数据可视化终结作业...
  • 实例:搜索框.avi ├0047.复选框操作.avi ├0048.实例:多选和取消以及反选 ├0049.单选框以及下拉框.avi ├0050.属性操作 ├0051.实例:Tab菜单.avi ├0052.标签操作之创建并插入操作.avi ├0053.标签操作之创建并...
  • 13 自定制property实现延迟计算功能 14 property补充 15 元类介绍 16 自定义元类 17 函数复习 18 文件操作复习 第29章 01 上节课复习 02 什么是异常处理及异常处理的两种方式对比 03 多分支与万能异常 04 异常处理...
  • 使用装饰器实现页面缓存 为数据接口提供缓存服务 Day52 - 接入三方平台 文件上传表单控件和图片文件预览 服务器端如何处理上传的文件 Day53 - 异步任务和定时任务 网站优化第二定律 配置消息队列服务 在...
  • Python Scrapy 学习----自动爬取网页

    千次阅读 2016-04-24 17:41:43
    使用scrapy框架写爬虫时一般会在start_urls中指定我们需要爬虫去抓取的网页的url,但是如何让我们的爬虫像搜索引擎中使用的爬虫一样具备自动多网页爬取的功能呢?本文通过自动抓取个人csdn博客的所有文章标题、阅读...
  • 最新Python3.5零基础+高级+完整项目(28周全)培训视频学习资料;本资料仅用于学习。 【课程内容】 第1周 开课介绍 python发展介绍 第一个python程序 变量 字符编码与二进制 字符编码的区别与介绍 用户交互程序 if ...
  • 搜索功能 类别和过滤器 设置 注意 - 需要互联网连接 安装 Python3 克隆存储库 在项目中启动一个 Python 解释器 使用存储库中的 requirements.txt 文件将需求安装到环境中 开始 运行 app.py 文件 在浏览器中,输入 ...
  • 对于web开来说,用户登陆、注册、文件上传等是最基础的功能,针对不同的web框架,相关的文章非常多,但搜索之后发现大多都不具有完整性,对于web应用来说,包括数据库的创建,前端页面的开发,以及中间逻辑层的处理...
  • 这里要非常感谢 Xiaocong He (@xiaocong),他将这个想法实现了出来(见xiaocong/uiautomator),原理是在手机上运行了一个http rpc服务,将uiautomator中的功能开放出来,然后再将这些http接口封装成Python库。...
  • 查文档你能赶上我的SPEED吗?CSDN官方插件推荐!

    多人点赞 热门讨论 2021-05-27 10:02:57
    按下键盘的Ctrl+O,在浏览器呼出搜索框 输入doc+对应需要查询的文档名,如果不输入,会给你下拉提示,比如css、html、python、php 输入之后敲回车即可在当前页面打开文档页面,效果见下图 安装CSDN官方插件 那么,...
  • 从零开始写项目第五篇【评论功能、备忘录】 从零开始写项目终极【维护网站、修复Bug】 从零开始写项目【总结】 带你搭一个SpringBoot+SpringData JPA的Demo 【极简版】SpringBoot+SpringData JPA 管理系统 :jack_o...
  • 我们还有其他主题的页面:,, 维护人员:, 我们正在寻找更多的贡献者和维护者! 贡献 请随意 目录 代号 理查德·萨顿(Richard Sutton)和安德鲁·巴托(Andrew Barto)的《强化学习:入门》中的示例和练习代码 ...
  • 我们还有其他主题的页面:,, 维护人员:, 我们正在寻找更多的贡献者和维护者! 贡献 请随意 目录 代号 理查德·萨顿(Richard Sutton)和安德鲁·巴托(Andrew Barto)的《强化学习:入门》中的示例和练习代码 ...
  • matlab代码做游戏-RL:[R

    2021-05-21 12:26:39
    我们还有其他主题的页面:,, 维护人员:, 我们正在寻找更多的贡献者和维护者! 贡献 请随意 目录 代号 理查德·萨顿(Richard Sutton)和安德鲁·巴托(Andrew Barto)的《强化学习:入门》中的示例和练习代码 ...
  • 我们还有其他主题的页面:,, 维护人员:, 我们正在寻找更多的贡献者和维护者! 贡献 请随意 目录 代号 理查德·萨顿(Richard Sutton)和安德鲁·巴托(Andrew Barto)的《强化学习:入门》中的示例和练习代码 ...
  • 搜索小程序,如企鹅医典小程序,进入小程序页面 同样找控件的xpath,同上操作 初始化框架,进行相关 API 调用 关闭框架,执行用例 后期计划 改造FAutoTest,兼容QT4W,实现FAutoTest到QTA的无缝切换。 交流群 ...

空空如也

空空如也

1 2 3 4
收藏数 64
精华内容 25
关键字:

python实现页面搜索框功能

python 订阅