• 优酷系统 # 41-43


    优酷系统

    用户层(客户端)

    代码:

    bin

    1 import os
    2 import sys
    3 
    4 sys.path.append(os.path.dirname(os.path.dirname(__file__)))
    5 
    6 from core import src
    7 
    8 if __name__ == '__main__':
    9     src.run()
    start.py

    conf

    1 import os
    2 
    3 BEST_DIR = os.path.dirname(os.path.dirname(__file__))
    4 
    5 # 指定路径
    6 DB_PATH = os.path.join(BEST_DIR,'upload_movie')
    settings.py

    core

      1 from conf import settings
      2 from lib import common
      3 import os
      4 # 管理员
      5 admin_dic = {
      6     'cookie':None,
      7 }
      8 
      9 # 1.注册
     10 def register(client):
     11     while True:
     12         name = input('name>>>:').strip()
     13         send_dic = {
     14             'type':'select_name',
     15             'name':name,
     16             'user_type':'admin'
     17         }
     18         msg_dic = common.send_back(send_dic,client)
     19         if msg_dic['flag']:
     20             print(msg_dic['msg'])
     21             continue
     22         else:
     23             print(msg_dic['msg'])
     24             password = input('password>>>:').strip()
     25             re_password = input('re_password').strip()
     26             if password and re_password:
     27                 if re_password == password:
     28                     password = common.get_password(password)
     29                     user_dic = {
     30                         'type':'register',
     31                         'name':name,
     32                         'password':password,
     33                         'user_type':'admin'
     34                     }
     35                     back_dic = common.send_back(user_dic,client)
     36                     if back_dic['flag']:
     37                         print(back_dic['msg'])
     38                         break
     39                     else:
     40                         print(back_dic['msg'])
     41                 else:
     42                     print('pwd != re_pwd is False!!!')
     43             else:
     44                 print('password and re_password not null!!!')
     45 
     46 # 2.登陆
     47 def login(client):
     48     while True:
     49         name = input('name>>>:').strip()
     50         send_dic = {
     51             'type':'select_name',
     52             'name':name,
     53             'user_type':'admin'
     54         }
     55         msg_dic = common.send_back(send_dic,client)
     56         if msg_dic['flag']:
     57             print(msg_dic['msg'])
     58             password = input('password>>>:').strip()
     59             if password:
     60                 password = common.get_password(password)
     61                 user_dic = {
     62                     'type': 'login',
     63                     'name': name,
     64                     'password': password,
     65                     'user_type': 'admin'
     66                 }
     67                 back_dic = common.send_back(user_dic, client)
     68                 if back_dic['flag']:
     69                     print(back_dic['msg'])
     70                     admin_dic['cookie'] = back_dic['session']
     71 
     72                     print(admin_dic['cookie'])
     73                     break
     74                 else:
     75                     print(back_dic['msg'])
     76             else:
     77                 print('password not null!!!')
     78         else:
     79             print(msg_dic['msg'])
     80             continue
     81 
     82 # 3.上传视频
     83 def upload_movie(client):
     84     while True:
     85         # 打印所有的电影列表
     86         movie_list = common.get_movie_list()
     87         if movie_list:
     88             for k,v in enumerate(movie_list,start=1):
     89                 print(k,v)
     90 
     91             choose = input('choose movie >>>(q.quit):').strip()
     92             if choose == 'q':break
     93             if choose.isdigit():
     94                 choose = int(choose)
     95                 if choose in range(1,len(movie_list)+1):
     96                     file_name = movie_list[choose - 1]
     97                     path = os.path.join(settings.DB_PATH,file_name)
     98                     # 生成该文件的 md5 值 先去服务端 校验电影是否已存在,存在就不再上传了
     99                     file_md5 = common.get_file_md5(path)
    100                     print(file_md5,'file_md5')
    101                     send_dic = {
    102                         'type':'check_movie',
    103                         'session':admin_dic['cookie'],
    104                         'file_md5':file_md5
    105                     }
    106                     back_dic = common.send_back(send_dic,client)
    107 
    108                     if back_dic['flag']:
    109                         is_free = input('is free?(y/n)>>>:').strip()
    110                         is_free = 1 if is_free == 'y' else 0
    111                         print('is_free',is_free)
    112                         file_name = movie_list[choose-1]
    113                         print('file_name',file_name)
    114                         file_size = os.path.getsize(path)
    115                         print('file_size',file_size)
    116                         send_dic = {
    117                             'type':'upload_movie',
    118                             'session':admin_dic['cookie'],
    119                             'file_name':file_name,
    120                             'file_md5':file_md5,
    121                             'is_free':is_free,
    122                             'file_size':file_size,
    123                         }
    124 
    125                         back_dict = common.send_back(send_dic,client,path)
    126                         if back_dict['flag']:
    127                             print(back_dict['msg'])
    128                             break
    129                         else:
    130                             print(back_dict['msg'])
    131                     else:
    132                         print(back_dic['msg'])
    133 
    134                 else:
    135                     print('not in range')
    136             else:
    137                 print('must be a num')
    138         else:
    139             print('暂无可上传影片')
    140 # 4.删除视频
    141 def delete_movie(client):
    142     while True:
    143         user_dic = {
    144         'type':'get_movie_list',
    145             'session':admin_dic['cookie'],
    146             'movie_type':'all'
    147         }
    148         back_dic = common.send_back(user_dic,client)
    149         if back_dic['flag']:
    150             movie_list = back_dic['movie_list']
    151             for i,m in enumerate(movie_list,start=1):
    152                 print(i,m)
    153 
    154             choose = input('choose>>>:').strip()
    155             if choose == 'q': break
    156             if choose.isdigit():
    157                 choose = int(choose)
    158                 if choose in range(1,len(movie_list)+1):
    159                     delete_id = movie_list[choose-1][2]
    160                     send_dic = {
    161                         'type':'delete_movie_interface',
    162                         'session':admin_dic['cookie'],
    163                         'delete_id':delete_id,
    164                         }
    165                     back_dict = common.send_back(send_dic,client)
    166                     if back_dict['flag']:
    167                         print(back_dict['msg'])
    168                         break
    169                     else:
    170                         print(back_dict['msg'])
    171                 else:
    172                     print('not in range')
    173             else:
    174                 print('must be a number')
    175                 continue
    176         else:
    177             print(back_dic['msg'])
    178 # 5.发布公告
    179 def send_notice(client):
    180     while True:
    181         title = input('title>>>:').strip()
    182         content = input('content>>>:').strip()
    183         if title and content:
    184             user_dic = {
    185                 'type':'send_notice',
    186                 'session':admin_dic['cookie'],
    187                 'title':title,
    188                 'content':content,
    189             }
    190             back_dic = common.send_back(user_dic,client)
    191             if back_dic['flag']:
    192                 print(back_dic['msg'])
    193                 break
    194             else:
    195                 print(back_dic['msg'])
    196 
    197 func_dic = {
    198     "1":register,
    199     "2":login,
    200     "3":upload_movie,
    201     "4":delete_movie,
    202     "5":send_notice,
    203 }
    204 
    205 def run(client):
    206     print('welcome to youku admin view!!!')
    207     while True:
    208         print("""
    1.注册
    2.登陆
    3.上传视频
    4.删除视频
    5.发布公告
    q.quit
    """)
    209         choose = input("please choose>>>:").strip()
    210         if choose == 'q':break
    211         if choose in func_dic:
    212             func_dic[choose](client)
    213         else:
    214             print('choose not in func_dic')
    admin.py
     1 from core import admin,user
     2 from TCP_CLIENT import tcp_client
     3 
     4 func_dic = {
     5     '1':admin.run,
     6     '2':user.run,
     7 }
     8 
     9 def run():
    10     client = tcp_client.client()
    11     print('welcome to youku system!!!')
    12     while True:
    13         print("""
    1.管理员视图
    2.用户视图
    q.quit
    """)
    14         choose = input("please choose>>>:").strip()
    15         if choose == 'q':break
    16         if choose in func_dic:
    17             func_dic[choose](client)
    18         else:
    19             print('choose not in func_dic')
    src.py
      1 from lib import common
      2 import os
      3 from conf import settings
      4 # 用户
      5 admin_dic = {
      6     'cookie':None,
      7     'movie_type':'free',
      8 }
      9 
     10 
     11 # 1 注册
     12 def register(client):
     13     while True:
     14         name = input('name>>>:').strip()
     15         send_dic = {
     16             'type': 'select_name',
     17             'name': name,
     18             'user_type': 'user'
     19         }
     20         msg_dic = common.send_back(send_dic, client)
     21         if msg_dic['flag']:
     22             print(msg_dic['msg'])
     23             continue
     24         else:
     25             print(msg_dic['msg'])
     26             password = input('password>>>:').strip()
     27             re_password = input('re_password').strip()
     28             if password and re_password:
     29                 if re_password == password:
     30                     password = common.get_password(password)
     31                     user_dic = {
     32                         'type': 'register',
     33                         'name': name,
     34                         'password': password,
     35                         'user_type': 'user'
     36                     }
     37                     back_dic = common.send_back(user_dic, client)
     38                     if back_dic['flag']:
     39                         print(back_dic['msg'])
     40                         break
     41                     else:
     42                         print(back_dic['msg'])
     43                 else:
     44                     print('pwd != re_pwd is False!!!')
     45             else:
     46                 print('password and re_password not null!!!')
     47 
     48 # 2 登录
     49 def login(client):
     50     while True:
     51         name = input('name>>>:').strip()
     52         send_dic = {
     53             'type':'select_name',
     54             'name':name,
     55             'user_type':'user'
     56         }
     57         msg_dic = common.send_back(send_dic,client)
     58         if msg_dic['flag']:
     59             print(msg_dic['msg'])
     60             password = input('password>>>:').strip()
     61             if password:
     62                 password = common.get_password(password)
     63                 user_dic = {
     64                     'type': 'login',
     65                     'name': name,
     66                     'password': password,
     67                     'user_type': 'user'
     68                 }
     69                 back_dic = common.send_back(user_dic, client)
     70                 if back_dic['flag']:
     71                     print(back_dic['msg'])
     72                     admin_dic['cookie'] = back_dic['session']
     73 
     74                     print(admin_dic['cookie'])
     75                     break
     76                 else:
     77                     print(back_dic['msg'])
     78             else:
     79                 print('password not null!!!')
     80         else:
     81             print(msg_dic['msg'])
     82             continue
     83 
     84 # 3 冲会员
     85 def buy_vip(client):
     86     """
     87     會員:userinfo :is_vip:
     88     會員權益 is_free = 0 和 is_free = 1皆可查詢
     89     :return:
     90     """
     91     while True:
     92         is_vip = input('is_vip(y/n(n為下次再),q.quit)>>>:').strip()
     93         if is_vip == 'q': break
     94         if is_vip == 'n':
     95             print('下次再說,非會員')
     96             user_dic = {
     97                 'type': 'get_movie_list',
     98                 'session': admin_dic['cookie'],
     99                 'movie_type': 'free'  # is_free = 1
    100             }
    101             back_dic = common.send_back(user_dic, client)
    102             if back_dic['flag']:
    103                 movie_list = back_dic['movie_list']
    104                 for k, movie in enumerate(movie_list, start=1):
    105                     print('可播放免费视频', k, movie)
    106             else:
    107                 print(back_dic['msg'])
    108         else:
    109             user_dic = {
    110                 'type': 'get_movie_list',
    111                 'session': admin_dic['cookie'],
    112                 'movie_type': 'all'
    113             }
    114             back_dic = common.send_back(user_dic, client)
    115             if back_dic['flag']:
    116                 movie_list = back_dic['movie_list']
    117                 for k, movie in enumerate(movie_list, start=1):
    118                     print('收费免费视频都可播放', k, movie)
    119                 send_dic = {
    120                     'type': 'buy_vip',
    121                     'session': admin_dic['cookie'],
    122                     'user_type': 'user'
    123                 }
    124                 back_dict = common.send_back(send_dic,client)
    125                 if back_dict['flag']:
    126                     admin_dic['is_vip'] = 1
    127                     admin_dic['movie_type'] = 'all'
    128                     print(back_dict['msg'])
    129                 else:
    130                     print(back_dict['msg'])
    131 # 4 查看视频
    132 def select_movie(client):
    133     user_dic = {
    134         'type': 'get_movie_list',
    135         'session': admin_dic['cookie'],
    136         'movie_type': admin_dic['movie_type']
    137     }
    138     back_dic = common.send_back(user_dic, client)
    139     if back_dic['flag']:
    140         movie_list = back_dic['movie_list']
    141         for k, movie in enumerate(movie_list, start=1):
    142             print(f'{admin_dic["movie_type"]}', k, movie)
    143     else:
    144         print(back_dic['msg'])
    145 # 5 下载免费视频
    146 def download_free_movie(client):
    147     # 当前可查询电影
    148     user_dic = {
    149         'type': 'get_movie_list',
    150         'session': admin_dic['cookie'],
    151         'movie_type': 'free'
    152     }
    153 
    154     back_dic = common.send_back(user_dic, client)
    155     if back_dic['flag']:
    156         movie_list = back_dic['movie_list']
    157         for k, m in enumerate(movie_list, start=1):
    158             print(k, m)
    159         choose = input('choose>>>:').strip()
    160         if choose.isdigit():
    161             choose = int(choose)
    162             if choose in range(1, len(movie_list) + 1):
    163                 send_dic = {
    164                     'type': 'download_movie',
    165                     'session': admin_dic['cookie'],
    166                     'movie_type': admin_dic['movie_type'],
    167                     'movie_id': movie_list[choose - 1][2],
    168                 }
    169                 back_dict = common.send_back(send_dic, client)
    170                 if back_dict['flag']:
    171                     file_name = back_dict['file_name']
    172                     file_path = os.path.join(settings.DB_PATH, file_name)
    173                     file_size = back_dict['file_size']
    174                     # print(1111111111111111111)
    175                     recv_size = 0
    176                     with open(file_path, 'wb')as f:
    177                         while recv_size < file_size:
    178                             date = client.recv(1024)
    179                             # print(date)
    180                             if len(date) == 0: break
    181                             f.write(date)
    182                             recv_size += len(date)
    183                             print(recv_size/file_size)
    184                         print('下载完成')
    185                 else:
    186                     print(back_dict['msg'])
    187             else:
    188                 print('choose must in len(movie_list)')
    189         else:
    190             print('must input number')
    191     else:
    192         print(back_dic['msg'])
    193 # 6 下载收费视频
    194 def download_not_free_movie(client):
    195     user_dic = {
    196         'type': 'get_movie_list',
    197         'session': admin_dic['cookie'],
    198         'movie_type': 'not_free'
    199     }
    200 
    201     back_dic = common.send_back(user_dic, client)
    202     if back_dic['flag']:
    203         movie_list = back_dic['movie_list']
    204         for k, m in enumerate(movie_list, start=1):
    205             print(k, m)
    206         choose = input('choose>>>:').strip()
    207         if choose.isdigit():
    208             choose = int(choose)
    209             if choose in range(1, len(movie_list) + 1):
    210                 send_dic = {
    211                     'type': 'download_movie',
    212                     'session': admin_dic['cookie'],
    213                     'movie_type': admin_dic['movie_type'],
    214                     'movie_id': movie_list[choose - 1][2],
    215                 }
    216                 back_dict = common.send_back(send_dic, client)
    217                 if back_dict['flag']:
    218                     file_name = back_dict['file_name']
    219                     file_path = os.path.join(settings.DB_PATH, file_name)
    220                     file_size = back_dict['file_size']
    221                     # print(1111111111111111111)
    222                     recv_size = 0
    223                     with open(file_path, 'wb')as f:
    224                         while recv_size < file_size:
    225                             date = client.recv(1024)
    226                             # print(date)
    227                             if len(date) == 0: break
    228                             f.write(date)
    229                             recv_size += len(date)
    230                             print(recv_size / file_size)
    231                         print('下载完成')
    232                 else:
    233                     print(back_dict['msg'])
    234             else:
    235                 print('choose must in len(movie_list)')
    236         else:
    237             print('must input number')
    238     else:
    239         print(back_dic['msg'])
    240 # 7 查看观影记录
    241 def select_look_download_movie_long(client):
    242     user_dic = {
    243         'type':'look_movie_long',
    244         'session':admin_dic['cookie'],
    245     }
    246     back_dic = common.send_back(user_dic,client)
    247     if back_dic['flag']:
    248         print(back_dic)
    249     else:
    250         print(back_dic['msg'])
    251 # 8 查看公告
    252 def select_notice(client):
    253     user_dic = {
    254         'type': 'select_look_notice',
    255         'session': admin_dic['cookie'],
    256     }
    257     back_dic = common.send_back(user_dic, client)
    258     if back_dic['flag']:
    259         print(back_dic)
    260     else:
    261         print(back_dic['msg'])
    262 
    263 func_dic = {
    264     "1":register,
    265     "2":login,
    266     "3":buy_vip,
    267     "4":select_movie,
    268     "5":download_free_movie,
    269     "6":download_not_free_movie,
    270     "7":select_look_download_movie_long,
    271     "8":select_notice,
    272 }
    273 
    274 def run(client):
    275     print('welcome to youku user view!!!')
    276     while True:
    277         print("""
    1.注册
    2.登录
    3.冲会员
    4.查看视频
    5.下载免费视频
    6.下载收费视频
    7. 查看观影记录
    8.查看公告
    q.quit
    """)
    278         choose = input("please choose>>>:").strip()
    279         if choose == 'q':break
    280         if choose in func_dic:
    281             func_dic[choose](client)
    282         else:
    283             print('choose not in func_dic')
    user.py

    lib

     1 import struct
     2 import json
     3 import hashlib
     4 import os
     5 
     6 # 加密
     7 def get_password(password):
     8     md5 = hashlib.md5()
     9     md5.update(password.encode('utf-8'))
    10     return md5.hexdigest()
    11 
    12 
    13 # 收发
    14 def send_back(user_dic,client,file=None):
    15     # 发:
    16     json_user_dic = json.dumps(user_dic)
    17     headers = struct.pack('i',len(json_user_dic))
    18     client.send(headers)
    19     client.send(json_user_dic.encode('utf-8'))
    20     if file:
    21         with open(file,'rb')as f:
    22             for line in f:
    23                 client.send(line)
    24     # 收:
    25     header_dic = client.recv(4)
    26     # 解包
    27     dict_size = struct.unpack('i',header_dic)[0]
    28     dict_bytes = client.recv(dict_size)
    29     back_dic = json.loads(dict_bytes.decode('utf-8'))
    30     return back_dic
    31 
    32 # 电影列表
    33 from conf import settings
    34 def get_movie_list():
    35     return os.listdir(settings.DB_PATH)
    36 
    37 # 得到 file_md5
    38 def get_file_md5(path):
    39     if os.path.exists(path):
    40         file_size = os.path.getsize(path)
    41         # 取三段  开头 取3/1 中间 取三分之一结尾取3/1 空出10个字节
    42         file_list = [0,file_size//3,(file_size//3)*2,file_size-10]
    43         print(file_list,'file_list')
    44         md5 = hashlib.md5()
    45         with open(path,'rb') as f:
    46             for r in file_list:
    47                 f.seek(r)
    48                 data = f.read(10)
    49                 md5.update(data)
    50         return md5.hexdigest()
    51 
    52 
    53 if __name__ == '__main__':
    54     # ret = get_password('llx1546')
    55     # print(ret)  # 1bde94cfbc4f70608dc3de058f15e18b
    56     # res = get_movie_list()
    57     # print(res)
    58     pass
    common.py

    TCP_CLIENT

    1 import socket
    2 
    3 def client():
    4     client = socket.socket()
    5     client.connect(("127.0.0.1",9902))
    6     return client
    tcp_client.py

    upload_movie

    01 昨日内容回顾.mp4
    02 函数对象.mp4
    03 函数的嵌套调用.mp4
    04 函数的嵌套定义.mp4
    05 名称空间.mp4
    06 名字的查找顺序.mp4
    07 查找顺序练习题.mp4
    08 作用域.mp4

    接口层(服务器)

    代码

    server

    bin

    1 import os
    2 import sys
    3 
    4 sys.path.append(os.path.dirname(os.path.dirname(__file__)))
    5 
    6 from TCP_SERVER import tcp_server
    7 
    8 if __name__ == '__main__':
    9     tcp_server.server()
    start.py

    conf

    1 import os
    2 
    3 BASE_PATH = os.path.dirname(os.path.dirname(__file__))
    4 
    5 MOVIE_DIR = os.path.join(BASE_PATH,'movie_dir')
    settings.py

    interface

     1 from lib  import common
     2 from db import models
     3 from conf import settings
     4 import os
     5 from TCP_SERVER import tcp_server
     6 # 查看,文件有无重复
     7 @common.laugh_auth
     8 def check_movie(user_dic,conn):
     9     # 获取文件md5去数据库校验是否有电影
    10     movie_list = models.Movie.select(file_md5=user_dic['file_md5'])
    11     if movie_list:
    12         back_dic = {'flag':False,'msg':'电影已存在'}
    13     else:
    14         back_dic = {'flag':True,'msg':'电影不存在可上传'}
    15 
    16     common.send_msg(back_dic,conn)
    17 
    18 # 上传
    19 @common.laugh_auth
    20 def upload_movie(user_dic,conn):
    21     file_name = common.get_session(user_dic.get('file_name')) + user_dic.get('file_name')
    22     # print(file_name,'file_name')
    23     file_size = user_dic.get('file_size')
    24     # print(file_size,'file_size')
    25     is_free = user_dic.get('is_free')
    26     # print('is_free',is_free)
    27     user_id = user_dic.get('user_id')
    28     # print(user_id,'user_id')
    29 
    30     recv_size = 0
    31     path = os.path.join(settings.MOVIE_DIR,file_name)
    32     # print(path)
    33     with open(path,'wb')as f:
    34         # print(f)
    35         while recv_size < file_size:
    36             data = conn.recv(1024)
    37             f.write(data)
    38             recv_size += len(data)
    39             # print(recv_size/file_size)
    40 
    41     movie_obj = models.Movie(
    42         path=path,
    43         is_free=is_free,
    44         upload_time=common.get_nowtime(),
    45         user_id=user_id,
    46         file_md5=user_dic.get('file_md5'),
    47         is_delete=0,
    48         name=file_name,
    49     )
    50     movie_obj.save()
    51     back_dic = {'flag':True,'msg':'上传成功'}
    52     print(back_dic)
    53     common.send_msg(back_dic,conn)
    54 @common.laugh_auth
    55 def delete_movie_interface(user_dic,conn):
    56     movie_list = models.Movie.select(id=user_dic.get('delete_id'))
    57     if movie_list:
    58         movie_obj = movie_list[0]
    59         # 被删除的显示 is_delete = 1
    60         movie_obj.is_delete = 1
    61         movie_obj.update()
    62 
    63     back_dic = {'flag':True,'msg':'删除完成'}
    64     common.send_msg(back_dic,conn)
    65 
    66 # 發送公告
    67 @common.laugh_auth
    68 def send_notice_interface(user_dic,conn):
    69     user_id = user_dic.get('user_id')
    70     title = user_dic.get('title')
    71     content = user_dic.get('content')
    72     notice_obj = models.Notice(
    73         user_id=user_id,
    74         title=title,
    75         content=content,
    76     )
    77     notice_obj.save()
    78     back_dic = {'flag':True,'msg':'公告發送成功'}
    79     common.send_msg(back_dic,conn)
    admin_interface.py
      1 from db import models
      2 from lib import common
      3 # 导锁
      4 from TCP_SERVER import user_date
      5 # 查询
      6 def select_name_interface(user_dic,conn):
      7     print(user_dic)
      8     user_list = models.User.select(name=user_dic['name'])
      9     user_type = None
     10     k = None
     11     for k,v in enumerate(user_list):
     12         print(k,v)
     13         if v.user_type == user_dic['user_type']:
     14             user_type = v.user_type
     15             k = k
     16         else:
     17             continue
     18     if user_type and k:
     19         back_dic = {'flag': True, 'msg': '账号与类型已存在,可作登陆使用'}
     20     else:
     21         back_dic = {'flag': False, 'msg': '账号或类型不存在,可作注册使用'}
     22     common.send_msg(back_dic, conn)
     23 
     24 
     25 
     26     # print(user_list)
     27     # if user_list:
     28     #     back_dic = {'flag':True,'msg':'账号与类型已存在,可作登陆使用'}
     29     # else:
     30     #     back_dic = {'flag': False, 'msg': '账号或类型不存在,可作注册使用'}
     31     # common.send_msg(back_dic,conn)
     32 
     33     # user_list = models.User.select(name=user_dic['name'], user_type=user_dic['user_type'])
     34     # print('user_list', user_list)
     35     # if user_list:
     36     #     users_obj = user_list[0]
     37     #     print(users_obj, '11111111111111111111111111111111111111111111111')
     38     #     if users_obj.user_type == user_dic['user_type']:
     39     #         name = users_obj.name
     40     #         user_type = users_obj.user_type
     41     #
     42     #     else:
     43     #         useres_obj = user_list[1]
     44     #         print(useres_obj, '222222222222222222222222222222222222222222222')
     45     #         name = useres_obj.name
     46     #         user_type = users_obj.user_type
     47     #     back_dic = {'flag': True, 'msg': f'[{name}账户{user_type}]可用做登录'}
     48     # else:
     49     #     back_dic = {'flag': False, 'msg': '可用做注册'}
     50     # common.send_msg(back_dic, conn)
     51 # 注册
     52 def register_interface(user_dic,conn):
     53     name = user_dic['name']
     54     password = user_dic['password']
     55     is_locked = 0
     56     is_vip = 0
     57     user_type = user_dic['user_type']
     58     register_time = common.get_nowtime()
     59     user_obj = models.User(name=name,password=password,is_locked=is_locked,is_vip=is_vip,user_type=user_type,register_time=register_time)
     60     user_obj.save()
     61     back_dic = {'flag': True, 'msg': '注册成功'}
     62     common.send_msg(back_dic, conn)
     63 
     64 # 登录
     65 def login_interface(user_dic,conn):
     66     user_list = models.User.select(name=user_dic['name'], user_type=user_dic['user_type'],password=user_dic['password'])
     67     print('user_list',user_list)
     68     if user_list:
     69         users_obj = user_list[0]
     70         print(users_obj,'11111111111111111111111111111111111111111111111')
     71         if users_obj.user_type == user_dic['user_type']:
     72             name = users_obj.name
     73             id = users_obj.id
     74         else:
     75             useres_obj = user_list[1]
     76             print(useres_obj,'222222222222222222222222222222222222222222222')
     77             name = useres_obj.name
     78             id = useres_obj.id
     79             print(name,id)
     80         back_dic = {'flag': True, 'msg': '登录成功'}
     81         # print(2222222222222)
     82         session = common.get_session(name)
     83         # print(333333333333333333333)
     84         back_dic['session'] = session
     85         # print(44444444444444444444)
     86         user_date.lock.acquire()
     87         user_date.alive_user[user_dic['addr']] = [session,id]
     88         # print(55555555555555555555555555)
     89         user_date.lock.release()
     90         # print(6666666666666666666666666666)
     91 
     92     else:
     93         back_dic = {'flag': False, 'msg': '密码错误,请重试'}
     94     common.send_msg(back_dic, conn)
     95 
     96 def get_movie_list(user_dic,conn):
     97     # 先把所有没有删除的电影打印出来
     98     movie_list = models.Movie.select()
     99     print('未删除movie_list',movie_list)
    100     # 事先定义一个返回给客户端的电影列表
    101     back_movie_list = []
    102     if movie_list:
    103 
    104         for movie in movie_list:
    105             # 先判断电影是否被删除
    106             if not movie.is_delete:  # 有职为被删除,无值为未删除
    107                 # 1.收费免费都要
    108                 if user_dic['movie_type'] == 'all':
    109                     back_movie_list.append([movie.name,'免费' if movie.is_free else '收费',movie.id])   # movie_id,是为了标识是哪条数据的
    110 
    111                 # 2.只要免费的
    112                 elif user_dic['movie_type'] == 'free':
    113                     if movie.is_free:
    114                         back_movie_list.append([movie.name,'免费',movie.id])
    115                 # 3.只要收费的
    116                 else:
    117                     if not movie.is_free:
    118                         back_movie_list.append([movie.name,'收费',movie.id])
    119         if not back_movie_list:
    120             back_dic = {'flag':False,'msg':'暂无所需电影'}
    121         else:
    122             for movie in back_movie_list:
    123                 print('back_movie_list',movie)
    124             back_dic = {'flag':True,'msg':'','movie_list':back_movie_list}
    125     else:
    126         back_dic = {'flag':False,'msg':'没有电影'}
    127     common.send_msg(back_dic,conn)
    common_interface.py
      1 from lib import common
      2 from db import models
      3 import os
      4 
      5 # 买会员
      6 @common.laugh_auth
      7 def buy_vip_interface(user_dic,conn):
      8     user_list = models.User.select(id=user_dic.get('user_id'))
      9     user_type = user_dic.get('user_type')
     10     if user_list[0].get('user_type') == user_type:
     11         user_obj = user_list[0]
     12     else:
     13         user_obj = user_list[1]
     14     user_obj.is_vip = 1
     15     user_obj.update()
     16 
     17 
     18     back_dic = {'flag':True,'msg':'會員購買成功'}
     19     common.send_msg(back_dic,conn)
     20 
     21 # 下载视频
     22 @common.laugh_auth
     23 def download_movie_interface(user_dic,conn):
     24     # 指定下载电影
     25     movie_list = models.Movie.select(id=user_dic.get('movie_id'))
     26     # print(movie_list)
     27     if movie_list:
     28         movie_obj = movie_list[0]
     29         file_name = movie_obj.name
     30         # print('file_name',file_name)
     31         path = movie_obj.path
     32         # print('path',path)
     33         file_md5 = movie_obj.file_md5
     34         file_size = os.path.getsize(path)
     35 
     36         # 存放下载记录 id user_id movie_id download_time
     37         user_id = user_dic['user_id']
     38         # print(user_id,'user_id')
     39         movie_id = user_dic.get('movie_id')
     40         record_list = models.DownloadRecord.select()
     41         if record_list:
     42             for m in record_list:
     43                 print(m)
     44                 if m.movie_id == movie_id:
     45                     back_dic = {'flag':False,'msg':'电影已下载'}
     46                     path = None
     47                 else:
     48 
     49                     # print(movie_id,'movie_id')
     50                     download_time = common.get_nowtime()
     51                     # print(download_time,'download_time')
     52                     download_record = models.DownloadRecord(user_id=user_id, movie_id=movie_id, download_time=download_time)
     53                     download_record.save()
     54                     back_dic = {
     55                         'flag': True,
     56                         'file_name':file_name,
     57                         'file_size':file_size,
     58                         'file_md5':file_md5,
     59                         'path':path
     60                     }
     61 
     62 
     63 
     64                     # with open(path,'rb')as f:
     65                     #     for line in f:
     66                     #         conn.send(line)
     67 
     68         else:
     69             download_time = common.get_nowtime()
     70             # print(download_time,'download_time')
     71             download_record = models.DownloadRecord(user_id=user_id, movie_id=movie_id, download_time=download_time)
     72             download_record.save()
     73             back_dic = {
     74                 'flag': True,
     75                 'file_name': file_name,
     76                 'file_size': file_size,
     77                 'file_md5': file_md5,
     78                 'path': path
     79             }
     80             path = None
     81     else:
     82         back_dic = {'flag':False,'msg':'无所需电影'}
     83         path=None
     84     common.send_msg(back_dic,conn,path)
     85 
     86 # 查看观影记录
     87 @common.laugh_auth
     88 def select_lock_movie_long_interface(user_dic,conn):
     89     download_recrod_list = models.DownloadRecord.select(user_id = user_dic.get('user_id'))
     90     if download_recrod_list:
     91         download_recored = download_recrod_list[0]
     92         id = download_recored.id
     93         movie_id = download_recored.movie_id
     94         movie_list = models.Movie.select(id=movie_id)
     95         if movie_list:
     96             movie_obj = movie_list[0]
     97             # print(movie_obj)
     98             movie_name = movie_obj.name
     99             upload_time = str(movie_obj.upload_time)
    100             # print(upload_time)
    101             back_dic = {
    102                 'flag': True,
    103                 'id': id,
    104                 'movie_name': movie_name,
    105                 'download_time': upload_time,
    106             }
    107         else:
    108             back_dic = {'flag':False,'msg':'电影不存在'}
    109     else:
    110         back_dic = {'flag':False,'msg':'没有观影记录'}
    111     common.send_msg(back_dic, conn)
    112 
    113 # 查看公告
    114 @common.laugh_auth
    115 def select_notice_interface(user_dic,conn):
    116     notice_list = models.Notice.select()
    117     if notice_list:
    118         for notice_obj in notice_list:
    119             print(notice_obj)
    120             back_dic = {
    121                 'flag':True,
    122                 'id':notice_obj.id,
    123                 'title':notice_obj.title,
    124                 'content':notice_obj.content,
    125             }
    126     else:
    127         back_dic = {'flag':False,'msg':'没有公告'}
    128     common.send_msg(back_dic, conn)
    user_interface.py

    lib

     1 import hashlib
     2 import json
     3 import struct
     4 import time
     5 # 当前时间
     6 def get_nowtime():
     7     return time.strftime("%Y-%m-%d %X")
     8 
     9 # 收发
    10 def send_msg(back_dic,conn,file=None):
    11     # 发:
    12     json_user_dic = json.dumps(back_dic)
    13     headers = struct.pack('i',len(json_user_dic))
    14     conn.send(headers)
    15     conn.send(json_user_dic.encode('utf-8'))
    16     if file:
    17         with open(file,'rb')as f:
    18             for line in f:
    19                 conn.send(line)
    20 
    21 
    22 # session 内部封装的 name 和cpu处理时间
    23 
    24 def get_session(name):
    25     md5 = hashlib.md5()
    26     # cpu 处理时间
    27     md5.update(str(time.clock()).encode('utf-8'))
    28     md5.update(name.encode('utf-8'))
    29 
    30     return md5.hexdigest()
    31 
    32 
    33 # 装饰器:
    34 from TCP_SERVER import user_date
    35 from functools import wraps
    36 def laugh_auth(func):
    37     @wraps(func)
    38     def inner(*args,**kwargs):      # 位置传参  args = (user_dic ,conn)   kwargs = {}
    39         print('args',args,'kwargs',kwargs)
    40         # 从服务端 user_date 中 alive_user(需要把他进行遍历)中的数据与客户端数据作对比
    41         for v in user_date.alive_user.values():    # v = [session,user_id], [], []
    42             print(v)
    43             if args[0].get('session') == v[0]:     # 客户端:session args[0].get('session')   服务端session v[0]   对比,相同 则已经登录 ,反之请先登录
    44                 print('args[0]',args[0], '客户端session',args[0].get('session'),'服务端session',v[0])
    45                 args[0]['user_id'] = v[1]   # 通过v[1]  给它赋值
    46                 print('args[0]', args[0], '客户端user_id', args[0]['user_id'])
    47                 break
    48         if args[0].get('user_id'):
    49             print("args[0].get('user_id')",args[0].get('user_id'))
    50             res = func(*args, **kwargs)
    51             return res
    52         else:
    53             back_dic = {'flag':True,'msg':'请先登录'}
    54             send_msg(back_dic,args[1])
    55     return inner
    56 
    57 if __name__ == '__main__':
    58     pass
    59     # ret = get_nowtime()
    60     # print(ret)
    61     # res = get_session('llx')
    62     # print(res)  1b75a77a5778912f3731ece1170c6f61
    common.py

    TCP_SERVER

     1 import socket
     2 import struct
     3 import json
     4 from concurrent.futures import ThreadPoolExecutor
     5 from threading import Lock
     6 from TCP_SERVER import user_date
     7 from lib import common
     8 from interface import common_interface,user_interface,admin_interface
     9 #
    10 lock = Lock()
    11 
    12 user_date.lock = lock
    13 # 线程池
    14 pool = ThreadPoolExecutor(50)
    15 
    16 # 映射
    17 func_dic = {
    18     "select_name":common_interface.select_name_interface,
    19     "register":common_interface.register_interface,
    20     "login":common_interface.login_interface,
    21 'check_movie':admin_interface.check_movie,
    22     'upload_movie':admin_interface.upload_movie,
    23     'get_movie_list':common_interface.get_movie_list,
    24     'delete_movie_interface':admin_interface.delete_movie_interface,
    25     'send_notice':admin_interface.send_notice_interface,
    26     'buy_vip':user_interface.buy_vip_interface,
    27     'download_movie':user_interface.download_movie_interface,
    28     'look_movie_long':user_interface.select_lock_movie_long_interface,
    29     'select_look_notice':user_interface.select_notice_interface,
    30 }
    31 
    32 
    33 def server():
    34     server = socket.socket()
    35     server.bind(("127.0.0.1",9902))
    36     server.listen(5)
    37     while True:
    38         conn,addr = server.accept()
    39         pool.submit(working,conn,addr)
    40 # 分类映射接口
    41 def classes(user_dic,conn):
    42     if user_dic.get('type') in func_dic:
    43         print(user_dic.get('type'))
    44         func_dic[user_dic.get('type')](user_dic, conn)
    45 
    46     else:
    47         back_dic = {'flag':False,'msg':'类型不在范围内'}
    48         common.send_msg(back_dic,conn)
    49 
    50 
    51 #
    52 def working(conn,addr):
    53     while True:
    54         try:
    55             # 收:
    56             header_dic = conn.recv(4)
    57             if not header_dic:break
    58             # 解包
    59             dict_size = struct.unpack('i', header_dic)[0]
    60             dict_bytes = conn.recv(dict_size)
    61             user_dic = json.loads(dict_bytes.decode('utf-8'))
    62             # 分流
    63             print('user_dic',user_dic)
    64             user_dic['addr'] = addr
    65             classes(user_dic,conn)
    66         except Exception as e:
    67             print(e)
    68             user_date.lock.acquire()
    69             user_date.alive_user.pop(addr)
    70             user_date.lock.release()
    71             conn.close()
    72             break
    tcp_server.py
    1 alive_user = {}
    2 lock = None
    user_date.py
     1 管理员
     2                 1.注册
     3                 2.登陆
     4                 3.上传视频
     5                 4.删除视频
     6                 5.发布公告
     7 用户
     8                 1 注册
     9                 2 登录
    10                 3 冲会员
    11                 4 查看视频
    12                 5 下载免费视频
    13                 6 下载收费视频
    14                 7 查看观影记录
    15                 8 查看公告
    16 
    17 一个项目最最最重要的是数据库相关
    18 表设计
    19 
    20 1.用户表
    21     id  name password is_vip is_locked user_type register_time
    22 2.电影表
    23     id name path is_free is_delete file_md5 upload_time user_id
    24 3.公告表
    25     id title content user_id release_time
    26 4.观影记录表
    27     id user_id  movie_id  download_time
    readme

    movie_dir

    0db9e950ce4408ebe340dce170c8d27604 函数的嵌套定义.mp4
    6dfbbd942d20ea203b5a51ba2b3b548c06 名字的查找顺序.mp4
    11a3aad303d076c0081ac5f68a5cef0405 名称空间.mp4
    14dc865dab0e4535d5cdc4978b03119a02 函数对象.mp4
    392b2975a3c70dbebe55dd2f77de2c3f01 昨日内容回顾.mp4
    b509a0546e2b6d73f804b83002d5318707 查找顺序练习题.mp4
    bdbafa23ad5ae094b6f99eb3bfc4f0f608 作用域.mp4

    数据库(orm db)

     代码

    db

     1 from orm__pool.orm import Models,StringField,IntegerField
     2 class User(Models):
     3     table_name = 'userinfo'
     4     id = IntegerField('id',primary_key=True)
     5     name = StringField('name')
     6     password = StringField('password')
     7     is_locked = IntegerField('is_locked',default=0)
     8     is_vip = IntegerField('is_vip',default=0)
     9     user_type = StringField('user_type')
    10     register_time = StringField('register_time')
    11 
    12 class Movie(Models):
    13     table_name = 'movie'
    14     id = IntegerField('id',primary_key=True)
    15     name = StringField('name',column_type='varchar(255)')
    16     path = StringField('path')
    17     is_free = IntegerField('is_free',default=1)
    18     is_delete = IntegerField('is_delete',default=0)
    19     upload_time = StringField('upload_time')
    20     user_id = IntegerField('user_id')
    21     file_md5 = StringField('file_md5')
    22 
    23 class Notice(Models):
    24     table_name = 'notice'
    25     id = IntegerField('id',primary_key=True)
    26     title = StringField('title')
    27     content = StringField('content')
    28     user_id = IntegerField('user_id')
    29 
    30 class DownloadRecord(Models):
    31     table_name = 'download_record'
    32     id = IntegerField('id',primary_key=True)
    33     user_id =  IntegerField('user_id')
    34     movie_id = IntegerField('movie_id')
    35     download_time = StringField('download_time')
    models.py

    orm__pool

     1 from DBUtils.PooledDB import PooledDB
     2 import pymysql
     3 
     4 POOL = PooledDB(
     5     creator=pymysql,  # 使用链接数据库的模块
     6     maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
     7     mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
     8     maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
     9     maxshared=3,
    10     # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
    11     blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
    12     maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
    13     setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
    14     ping=0,
    15     # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
    16     host='127.0.0.1',
    17     port=3306,
    18     user='root',
    19     password='llx20190411',
    20     database='youku2',
    21     charset='utf8',
    22     autocommit='True'
    23 )
    db_pool.py
     1 import pymysql
     2 from orm__pool import db_pool
     3 
     4 class Mysql(object):
     5     def __init__(self):
     6         self.conn = db_pool.POOL.connection()
     7         self.cursor = self.conn.cursor(pymysql.cursors.DictCursor)
     8 
     9     def close(self):
    10         self.cursor.close()
    11         self.conn.close()
    12 
    13     def select(self,sql,args=None):
    14         self.cursor.execute(sql,args)
    15         res = self.cursor.fetchall()  # 列表套字典
    16         return res
    17 
    18     def execute(self,sql,args):
    19         try:
    20             self.cursor.execute(sql,args)
    21         except BaseException as e:
    22             print(e)
    mysql_singlenten.py
      1 """"""
      2 from orm__pool.mysql_singlenten import Mysql
      3 """
      4 定义字段类
      5 """
      6 class Field(object):
      7     def __init__(self,name,column_type,primary_key,default):
      8         self.name = name
      9         self.column_type = column_type
     10         self.primary_key = primary_key
     11         self.default = default
     12 
     13 
     14 # varcher
     15 class StringField(Field):
     16     def __init__(self,name,column_type='varchar(255)',primary_key = False,default=None):
     17         super().__init__(name,column_type,primary_key,default)
     18 
     19 # int
     20 class IntegerField(Field):
     21     def __init__(self,name,column_type='int',primary_key=False,default=None):
     22         super().__init__(name, column_type, primary_key, default)
     23 
     24 
     25 # 元类(自定义)
     26 class ModelMetaClass(type):
     27     def __new__(cls, class_name, class_bases,class_attrs):
     28         # 我仅仅只想拦截模型表的类的创建过程
     29         if class_name == 'Models':
     30             return type.__new__(cls,class_name,class_bases,class_attrs)
     31         # 给类放表名,主键字段,所有字段
     32         table_name = class_attrs.get('table_name',class_name)
     33         # 定义一个存储主键的变量
     34         primary_key = None
     35         # 定义一个字典用来存储自定义的表示"表"的所有字段信息
     36         mappings = {}
     37         for k,v in class_attrs.items():
     38             if isinstance(v,Field):
     39                 mappings[k] = v
     40                 if v.primary_key:
     41                     if primary_key:
     42                         raise TypeError("主键只能有一个")
     43                     primary_key = v.name
     44         # 将重复的键值对删除
     45         for k in mappings.keys():
     46             class_attrs.pop(k)
     47         if not primary_key:
     48             raise TypeError("必须要有一个主键")
     49         # 将处理好的数据放入class_attrs中
     50         class_attrs['table_name'] = table_name
     51         class_attrs['primary_key'] = primary_key
     52         class_attrs['mappings'] = mappings
     53         return type.__new__(cls,class_name,class_bases,class_attrs)
     54 
     55 #
     56 class Models(dict,metaclass=ModelMetaClass):
     57     def __init__(self,**kwargs):
     58         super().__init__(**kwargs)
     59     def __getattr__(self, item):
     60         return self.get(item,'没有该键值对')
     61     def __setattr__(self, key, value):
     62         self[key] = value
     63 
     64     # 查询方法:
     65     @classmethod
     66     def select(cls,**kwargs):
     67         ms = Mysql()
     68         # select * from userinfo
     69         if not kwargs:
     70             sql = 'select * from %s' % cls.table_name
     71             res = ms.select(sql)
     72         else:
     73             # select * from userinfo where id = 1
     74             k = list(kwargs.keys())[0]
     75             v = kwargs.get(k)
     76             sql = 'select * from %s where %s=?'%(cls.table_name,k)
     77             # select * from userinfo where id = ?
     78             sql = sql.replace('?','%s')  # select * from userinfo where id = %s
     79             res = ms.select(sql,v)
     80 
     81         if res:
     82             return [cls(**r) for r in res]  # 将数据库的一条数据映射为类的对象
     83 
     84     # 新增方法
     85     def save(self):
     86         ms = Mysql()
     87         # insert into userinfo (name,password) values('jason','123')
     88         # insert into %s(%s) values(?)
     89         fields = []   # [name,password]
     90         values = []
     91         args = []
     92         for k,v in self.mappings.items():
     93             if not v.primary_key:  # 将id 字段去除 因为新增一条数据 ,id是自增的不需要你传
     94                 fields.append(v.name)
     95                 args.append('?')
     96                 values.append(getattr(self,v.name))
     97                 print(k,v,'k,v')
     98         print(values,'values')
     99         # insert into user info userinfo(name,password) values(?,?)
    100         sql = 'insert into %s(%s) values(%s)'%(self.table_name,','.join(fields),','.join(args))
    101         print(sql,'sql')
    102         # insert into userinfo (name,password) values(?,?)
    103         sql = sql.replace('?','%s')
    104         print(sql,'sql完整')
    105         ms.execute(sql,values)
    106         # print(ms.cursor.fetchall(),'结果')
    107 
    108     # 修改方法:基本已经存在了的数据进行一个修改操作
    109     def update(self):
    110         ms = Mysql()
    111         # update userinfo set name = 'jason', password='123' where id = 1
    112         fields = []  # [name,password]
    113         values = []
    114         pr = None
    115         for k,v in self.mappings.items():
    116             if v.primary_key:
    117                 pr = getattr(self,v.name,v.default)
    118             else:
    119                 fields.append(v.name+'=?')
    120                 values.append(getattr(self,v.name,v.default))
    121         sql = 'update %s set %s where %s = %s'%(self.table_name,','.join(fields),self.primary_key,pr)
    122         # update userinfo set name='?',password='?' where id = 1
    123         sql = sql.replace('?','%s')
    124         ms.execute(sql,values)
    125 
    126 
    127 if __name__ == '__main__':
    128     pass
    129     # class Teacher(Models):
    130     #     table_name = 'teacher'
    131     #     tid = IntegerField(name='tid',primary_key=True)
    132     #     tname = StringField(name='tname')
    133     # obj = Teacher(tname='jason老师')
    134     # obj.save()
    135     # res = Teacher.select()
    136     # for r in res:
    137     #     print(r.tname)
    138     # print(res)
    139 
    140     # res = Teacher.select(tid=1)
    141     # teacher_obj = res[0]
    142     # teacher_obj.tname = 'jason老师'
    143     # teacher_obj.update()
    144     # res1 = Teacher.select()
    145     # print(res1)
    146 
    147     # class User(Models):
    148     #     table_name = 'User'
    149     #     id = IntegerField(name='id', primary_key=True)
    150     #     name = StringField(name='name')
    151     #     password = StringField(name='password')
    152     # print(User.primary_key)
    153     # print(User.mappings)
    154     # obj = User(name='jason')
    155     # print(obj.table_name)
    156     # print(obj.primary_key)
    157     # print(obj.mappings)
    orm.py

     

    navicat表

    观影记录表

    movie

    notice

    userinfo

  • 相关阅读:
    关于 php json float 出现很多位的问题
    做 Excel 的 XML schema.xsd
    笔记:Python 默认参数必须指向不变对象
    Bartender 使用 Excel xlsx 数据库时出现 0x800A0E7A
    Javascript 中 的 for ... in 和 for ... of 差别
    关于跨域资料收集 (2019-01-11)
    ThinkPHP3 和 ThinkPHP5 不是一个团队做的
    记录一下:给电推剪改锂电池
    为你的Web程序加个启动画面
    前端不为人知的一面--前端冷知识集锦 前端已经被玩儿坏了!像console.log()可以向控制台输出图片
  • 原文地址:https://www.cnblogs.com/llx--20190411/p/11448814.html
Copyright © 2020-2023  润新知