websocket 多聊天室功能
websocket 类也是在网上找到的。 修改后可以用来创建多房间聊天室。可以发送图片表情,图片,及文字。
分享的代码,已经测试。可正常运行
HTML 端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
<title>直播课程</title>
<link rel="stylesheet" href="css/base.css">
<link rel="stylesheet" href="css/zhibo.css">
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
</head>
<body class="scope">
<div style="width: 100%; height:250px;">
<script type="text/javascript" src="player/sewise.player.min.js"></script>
<script type="text/javascript">
var videourl='视屏播放地址不用写';
SewisePlayer.setup({
server: "vod",
type: "m3u8",
autostart: "true",
videourl: videourl,
skin: "vodWhite",
title: "三年级预备课程一",
claritybutton: "disable",
lang: "zh_CN"
});
</script>
</div> <div class="log comment" id="log">
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">我是用户1我是用是用户1我是用户1我是用户1我是用户1</span></div>
</div>
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">莫寒</span>:<span class="yuanwang"><img class="chat_pic" src="img/pic.jpg" alt=""></span></div>
</div>
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">我是用户1我是用是用户1我是用户1我是用户1我是用户1</span></div>
</div>
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">我是用户1我是用是用户1我是用户1我是用户1我是用户1</span></div>
</div>
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">莫寒</span>:<span class="yuanwang"><img class="chat_pic" src="img/150599173575244039.jpg" alt=""></span></div>
</div>
<div class="luck">
<div class="user"><img src="img/user.png"></div>
<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">我是用户1我是用是用户1我是用户1我是用户1我是用户1</span></div>
</div>
</div>
<div class="sendCon">
<p class="info">
<span class="emoji"> <input type="button" value=":)"></span>
<span class="placeholder"><img src="img/pic.jpg" alt=""><input type="file" id="file_img" onchange="preImg(this.id,'yulan_img')"></span>
<span class="text"><input type="text" id="text" placeholder=""></span>
<span class="send"><input type="button" class="btn" value="发送" onclick="sendText()"></span>
</p>
<ul class="emojiCon"></ul>
</div> <script>
var serverUrl="http://192.168.3.240"; //图片服务器的地址ip
var url="ws://你自已访问的ip:端口(8000)";
function link(){
socket=new WebSocket(url);
socket.onopen=function(){
// alert('连接成功')
};
socket.onerror=function(errorEvent){
// alert('error');
}
socket.onmessage=function(msg){
setMsg(msg.data);
console.log(msg);
}
// socket.onclose=function(){setMsg('断开连接')}
}
function closeScoket(){
socket.close();
socket=null;
}
//向页面中实时更新消息数据
function setMsg(var1){
var obj=JSON.parse(var1);
if(obj.type==1){
$('.log').append('<div class="luck">'
+'<div class="user"><img src="img/user.png"></div>'
+'<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">'+obj.msg+'</span></div></div>' );
add();
}else{
var img = new Image();
img.src=obj.msg;
img.onload=function(){
var isPic='';
//width>30 表示不是表情包图片
if(img.width>30){
isPic='<img class="chat_pic" src="'+obj.msg+'" alt="">';
}else{
isPic='<img class="chat_pic1" src="'+obj.msg+'" alt="">'
}
$('.log').append('<div class="luck">'
+'<div class="user"><img src="img/user.png"></div>'
+'<div class="content1"><span class="luckyP">奕佚奕佚</span>:<span class="yuanwang">'+isPic+'</span></div></div>' ); add();
}
}
} var arr=[1,2,3,4];
//发送文字
function sendText(id){
var json;
if($('#'+id).attr('src')==undefined){
json=JSON.stringify({'room':arr[1],'type':'1','msg':$('#text').val()});
if($('#text').val()==""){
$('body').append(pop("消息不能为空"));
return;
}
}else{
json=JSON.stringify({'room':arr[1],'type':'2','msg':$('#'+id).attr('src')});
$('.emojiCon').css('display','none');
}
socket.send(json);
$('#text').val('');
}
//发送图片
function sendPic(){
$.ajax({
url:''+serverUrl+'/test/Home/index/base64_decode',
type:'post',
data:{'msg':$('#yulan_img').attr('src')},
dataType:'html',
success:function(data){
console.log(data);
var json=JSON.stringify({'room':arr[3],'type':'2','msg':data});
socket.send(json);
$('.mask').remove();
},
error:function(event){
$('body').append(pop('服务器开小差啦~'))
}
})
}
//让讨论区的滚动条始终在底部 让用户立马看到自己的消息
function add(){
var div = document.getElementById('log');
div.scrollTop = div.scrollHeight;
}
//加载表情包
function afterLoad(){
var html='';
for(var i=0;i<91;i++){
html+='<li><img id="emoji_'+(i+1)+'" onclick="sendText(id)" src="'+serverUrl+'/test/Public/img/qq/'+(i+1)+'.gif" alt=""></li>';
}
$('.emojiCon').html(html);
}
//图片预览
function preImg(sourceId, targetId) {
if (typeof FileReader === 'undefined') {
alert('Your browser does not support FileReader...');
return;
}
var reader = new FileReader(); reader.onload = function(e) {
var img = document.getElementById(targetId);
img.src = this.result;
var w=img.width;
var h=img.height;
var winW=$(window).width();
var winH=$(window).height();
var marginTop=parseInt((winH-40-h)/2);
var marginLeft=parseInt((winW-w
)/2); if(w/h>1.2){
$(img).css('width',winW).css('margin-top',marginTop);
alert("marginTop:"+marginTop);
}else if(h/w>2){//超长图的时候 滚动条显示
$('.over_pic').css('height',winH-40).css('overflow','scroll');
$(img).css('width',winW);
}else{//竖图的时候
$(img).css('height',winH-40).css('margin-left',marginLeft);
alert("marginLeft:"+marginLeft);
}
}
reader.readAsDataURL(document.getElementById(sourceId).files[0]); $('body').append('<div class="mask scope"><div class="over_pic"><img id="yulan_img" src="" alt=""></div>'
+'<p><button class="sure" onclick="sendPic()">确认</button></p></div>');
} $(function(){
link();
afterLoad();
add();
$('.log').css('height',$(window).height()*0.65+'px');
$('.emoji').click(function(){
$('.emojiCon').show();
})
})
</script> </body> </html>
CSS 前端代码 bass
@charset "utf-8";
/* 禁用iPhone中Safari的字号自动调整 */
html {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
font-family:"微软雅黑",Arial,sans-serif;
}
/* 去除iPhone中默认的input样式 */
input{/* -webkit-appearance:none; */ resize: none;}
/* 取消链接高亮 */
body,div,ul,li,ol,h1,h2,h3,h4,h5,h6,input,textarea,select,p,dl,dt,dd,a,img,button,form,table,th,tr,td,tbody,article,
aside, details,figcaption,figure,footer,header,hgroup, menu,nav,section{
-webkit-tap-highlight-color:rgba(0, 0, 0, 0);
}
/* 设置HTML5元素为块 */
article, aside, details,figcaption,figure,footer,header,hgroup, menu,nav,section {
display: block;
}
/* 图片自适应 */
img {width: 100%;height: auto;width:auto\9; /* ie8 */
-ms-interpolation-mode:bicubic;/*为了照顾ie图片缩放失真*/}
*:focus {outline:none;}
/* 清零 */
body,div,ul,li,ol,h1,h2,h3,h4,h5,h6,input,textarea,select,p,dl,dt,dd,
a,img,button,form,table,th,tr,td,tbody,article,
aside, details,figcaption,figure,footer,header,hgroup, menu,nav,section
{
margin:;
padding:;
border:none;
}
em,i{font-style:normal;}
strong{font-weight: normal;}
.clearfix:after{content:""; display:block; visibility:hidden; height:; clear:both;}
.clearfix{zoom:;}
a{text-decoration:none; color:#969696;}
a:hover{ text-decoration:none;}
ul,ol,li{list-style:none;}
fieldset,img{border: none;}
q:before,q:after {content:"";}
input:password {ime-mode:disabled;}
*{box-sizing:border-box;}
.scope{min-width:320px; max-width:750px; margin: 0 auto;}
*{
margin:;
padding:;
}
@media screen and (max-width: 750px){
html{font-size:30px;}
}
@media screen and (min-width:640px) and (max-width:749px){
html{font-size:25px; }
}
@media screen and (min-width:480px) and (max-width:639px){
html{font-size:20px; }
}
@media screen and (min-width:320px) and (max-width:479px){
html{font-size:15px; }
} /*body{font-size:62.5%;}*/
fieldset,img{border:}
a{text-decoration:none;color:#000;outline:none}
li{list-style:none}
h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}
input,button,textarea,select,optgroup,option{
font-family:inherit;font-size:inherit;
font-style:inherit;font-weight:inherit}
input,button,textarea,select{*font-size:100%}
.clear:after{
display:block;
content:"clear";
height:;
clear:both;
visibility:hidden;
}
.clear{zoom:;}
CSS 前端代码 zhibo
.comment{
    overflow: scroll;
    border:1px solid red;
    padding:2%;
}
.luck{
    padding: 10px 0 0 0;
    overflow:hidden;
}
.luckyP{
    color:#44c6dd;
}
.chat_pic{
    width:40%;
    display:inline-block;
    vertical-align: top;
}
.chat_pic1{
    width:10%;
    vertical-align: middle;
}
.user img{
    width:40%;
}
.user,.content1{
    float:left;
}
.user{
    width:15%;
    text-align: center;
    vertical-align: middle;
}
.content1{
    width:85%;
    line-height:25px;
}
.sendCon{
    position:fixed;
    bottom:;
    left:;
    right:;
    padding:2%;
    background:#fff;
    border:1px solid #ddd;
    min-width:320px;
    max-width:750px;
    margin:0 auto;
}
.info span{
    display:inline-block;
}
.placeholder{
    width:15%;
    position:relative;
    text-align: center;
    vertical-align: middle;
}
    input[type="file"]{
        width:80%;
        position:absolute;
        left:2%;
        top:2%;
        opacity:;
    }
    .placeholder img{
        width:65%;
    }
.emoji{
    width:10%;
    text-align: center;
    /*vertical-align: middle;*/
    /*border:1px solid red;*/
}
    .emoji input{
        width:100%;
        padding:8% 2%;
        border:1px solid #ddd;
        background:#fff;
    }
    /*.emoji img{
        width:80%;
        border:1px solid blue;
        vertical-align: middle;
    }*/
.text{
    width:55%;
}
    #text{
        width:100%;
        border:1px solid #ddd;
        padding:2%;
    }
.send{
    width:15%;
}
    .btn{
        width:100%;
        background:#86e2fd;
        color:#fff;
        padding:9% 2%;
        vertical-align: middle;
    }
.mask{
    background:rgba(0,0,0,0.9);
    width:100%;
    height:100%;
    position:fixed;
    left:;
    top:;
    /*display:none;*/
}
.sure{
    background:#19ad17;
    color:#fff;
    padding:10px;
}
.mask p{
    text-align: right;
    position:absolute;
    bottom:;
    left:;
    right:;
    height:40px;
    vertical-align: middle;
}
.over_pic img{
    display:block;
}
/*表情包div*/
.emojiCon{
    position:absolute;
    bottom:;
    left:;
    display:none;
    background:#fff;
}
.emojiCon li{
    border:1px solid #ddd;
    float:left;
    width:8.33%;
}
php 服务端代码 server.php
<?php
    include 'websocket.class.php';
    $config=array(
    'address'=>'你自已ip地址',  //注意事 项 linux下云服务器,用ifconfig 查看自已的内网ip  外网访问的ip 是用写在html那块的
    'port'=>'8000',
    'event'=>'WSevent',//回调函数的函数名
    'log'=>true,
    );
    $websocket = new websocket($config);
    $websocket->run();
function WSevent($type,$event){
  global $websocket;
    if('in'==$type){
      $websocket->log('客户进入id:'.$event['k']);
    }elseif('out'==$type){
      $websocket->log('客户退出id:'.$event['k']);
    }elseif('msg'==$type){
      $websocket->log($event['k'].'消息:'.$event['msg']);
      roboot($event['sign'],$event['msg']);
    }
}
function roboot($sign,$t){
global $websocket;
    $msg_arr = json_decode($t,true);
    foreach($websocket->users as $k =>&$v){
        if(empty($v['room'])){
            $v['room']=$msg_arr['room'];
        }
        if($v['room'] ==$msg_arr['room']){
             $websocket->idwrite($k,$t);
        }
    }
}
    
php 服务羰代码 websocket.class.php
<?php
/*
创建类websocket($config);
$config结构:
$config=array(
'address'=>'192.168.0.200',//绑定地址
'port'=>'8000',//绑定端口
'event'=>'WSevent',//回调函数的函数名
'log'=>true,//命令行显示记录
); 回调函数返回数据格式
function WSevent($type,$event) $type字符串 事件类型有以下三种
in 客户端进入
out 客户端断开
msg 客户端消息到达
均为小写 $event 数组
$event['k']内置用户列表的userid;
$event['sign']客户标示
$event['msg']收到的消息 $type='msg'时才有该信息 方法:
run()运行
search(标示)遍历取得该标示的id
close(标示)断开连接
write(标示,信息)推送信息
idwrite(id,信息)推送信息 属性:
$users 客户列表
结构:
$users=array(
[用户id]=>array('socket'=>[标示],'hand'=[是否握手-布尔值]),
[用户id]=>arr.....
)
*/ class websocket{
public $log;
public $event;
public $signets;
public $users;
public $master;
public function __construct($config){
if (substr(php_sapi_name(), 0, 3) !== 'cli') {
die("请通过命令行模式运行!");
}
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$this->event = $config['event'];
$this->log = $config['log'];
$this->master=$this->WebSocket($config['address'], $config['port']);
$this->sockets=array('s'=>$this->master);
}
function WebSocket($address,$port){
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, $address, $port);
socket_listen($server);
$this->log('开始监听: '.$address.' : '.$port);
return $server;
}
function run(){
while(true){
$changes=$this->sockets;
@socket_select($changes,$write=NULL,$except=NULL,NULL);
foreach($changes as $sign){
if($sign==$this->master){
$client=socket_accept($this->master);
$this->sockets[]=$client;
$user = array(
'socket'=>$client,
'hand'=>false,
);
$this->users[] = $user;
$k=$this->search($client);
$eventreturn = array('k'=>$k,'sign'=>$sign);
$this->eventoutput('in',$eventreturn);
}else{
$len=socket_recv($sign,$buffer,2048,0);
$k=$this->search($sign);
$user=$this->users[$k];
if($len<7){
$this->close($sign);
$eventreturn = array('k'=>$k,'sign'=>$sign);
$this->eventoutput('out',$eventreturn);
continue;
}
if(!$this->users[$k]['hand']){//没有握手进行握手
$this->handshake($k,$buffer);
}else{
$buffer = $this->uncode($buffer);
$eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer);
$this->eventoutput('msg',$eventreturn);
}
}
}
}
}
function search($sign){//通过标示遍历获取id
foreach ($this->users as $k=>$v){
if($sign==$v['socket'])
return $k;
}
return false;
}
function close($sign){//通过标示断开连接
$k=array_search($sign, $this->sockets);
socket_close($sign);
unset($this->sockets[$k]);
unset($this->users[$k]);
}
function handshake($k,$buffer){
$buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);
$key = trim(substr($buf,0,strpos($buf,"\r\n")));
$new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));
$new_message = "HTTP/1.1 101 Switching Protocols\r\n";
$new_message .= "Upgrade: websocket\r\n";
$new_message .= "Sec-WebSocket-Version: 13\r\n";
$new_message .= "Connection: Upgrade\r\n";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));
$this->users[$k]['hand']=true;
return true;
}
function uncode($str){
$mask = array();
$data = '';
$msg = unpack('H*',$str);
$head = substr($msg[1],0,2);
if (hexdec($head{1}) === 8) {
$data = false;
}else if (hexdec($head{1}) === 1){
$mask[] = hexdec(substr($msg[1],4,2));
$mask[] = hexdec(substr($msg[1],6,2));
$mask[] = hexdec(substr($msg[1],8,2));
$mask[] = hexdec(substr($msg[1],10,2));
$s = 12;
$e = strlen($msg[1])-2;
$n = 0;
for ($i=$s; $i<= $e; $i+= 2) {
$data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));
$n++;
}
}
return $data;
}
function code($msg){
$msg = preg_replace(array('/\r$/','/\n$/','/\r\n$/',), '', $msg);
$frame = array();
$frame[0] = '81';
$len = strlen($msg);
$frame[1] = $len<16?'0'.dechex($len):dechex($len);
$frame[2] = $this->ord_hex($msg);
$data = implode('',$frame);
return pack("H*", $data);
}
function ord_hex($data) {
$msg = '';
$l = strlen($data);
for ($i= 0; $i<$l; $i++) {
$msg .= dechex(ord($data{$i}));
}
return $msg;
} function idwrite($id,$t){//通过id推送信息
if(!$this->users[$id]['socket']){return false;}//没有这个标示
$t=$this->code($t);
return socket_write($this->users[$id]['socket'],$t,strlen($t));
}
function write($k,$t){//通过标示推送信息
$t=$this->code($t);
return socket_write($k,$t,strlen($t));
}
function eventoutput($type,$event){//事件回调
call_user_func($this->event,$type,$event);
}
function log($t){//控制台输出
if($this->log){
$t=$t."\r\n";
fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));
}
}
}
php 上传图片异步处理代码
$update_path = "Upload/";
$msg = $_POST['msg'];
$exe = str_replace('/', '.', strstr(strstr($msg, ';', TRUE), '/'));
$exe = $exe == '.jpeg' ? '.jpg' : $exe;
$tmp = base64_decode(substr(strstr($msg, ','), 1));
$path = $update_path . md5(time()) . $exe;
$res =file_put_contents($path, $tmp);
echo "http://".$_SERVER['SERVER_NAME']."/test/".$path;
window 下 打开dos 命令 找到php.exe 文件位置。用php.exe 执行 server.php 文件开启服务器监听。 php.exe server.php
打开html页面,点击链接,就可以链接websocket了。提示成功,便可以发送信息了。


注意事项目:linux 下 滥听端口时,注意服务器防火墙是否开启端口过滤。 Linux 有iptables firewall 两个防火墙软件件
websocket 多聊天室功能的更多相关文章
- PHP 之websocket实现聊天室功能
		
一.功能界面 具体的详细代码:https://github.com/yangsphp/websocket-master/tree/master 二.具体代码实现 1.前端代码如下 <!DOCTY ...
 - 基于WebSocket实现聊天室(Node)
		
基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...
 - Ext JS学习第十六天 事件机制event(一)  DotNet进阶系列(持续更新)  第一节:.Net版基于WebSocket的聊天室样例  第十五节:深入理解async和await的作用及各种适用场景和用法  第十五节:深入理解async和await的作用及各种适用场景和用法  前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G
		
code&monkey Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...
 - 关于websocket制作聊天室的的一些总结
		
websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...
 - Netty学习笔记(四) 简单的聊天室功能之服务端开发
		
前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...
 - 使用epoll实现聊天室功能,同时比较epoll和select的异同
		
1.首先介绍一下select和epoll的异同,如下(摘抄自https://www.cnblogs.com/Anker/p/3265058.html) select的几大缺点: (1)每次调用sele ...
 - websocket+golang聊天室
		
原文地址: http://www.niu12.com/article/3 websocket+golang聊天室 main.go和index.html放在同一目录下 main.go package m ...
 - [Python] socket发送UDP广播实现聊天室功能
		
一.说明 本文主要使用socket.socket发送UDP广播来实现聊天室功能. 重点难点:理解UDP通讯流程.多线程.UDP广播收发等. 测试环境:Win10\Python3.5. 程序基本流程:创 ...
 - WebSocket 网页聊天室
		
先给大家开一个原始的websocket的连接使用范例 <?php /* * recv是从套接口接收数据,也就是拿过来,但是不知道是什么 * read是读取拿过来的数据,就是要知道recv过来的是 ...
 
随机推荐
- redis开启持久化、redis 数据备份与恢复
			
redis持久化介绍 https://segmentfault.com/a/1190000015897415 1. 开启aof持久化.以守护进程启动.远程访问先把配置文件拷贝一份到/etc/redi ...
 - Java内部类(4):静态内部类&接口内部类
			
使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类.静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向 ...
 - MongoDB集群-主从复制(副本集)、failover
			
1.概念 主从复制的目的:数据冗余.备份.读写分离 主从方式:一主一从(不推荐,只能实现复制,主节点挂掉且未重新启动的时候,无法提升从节点为master),一主一从一裁判,一主多从 复制方式:主节点记 ...
 - jbolt插件创建jfinal项目
			
Jfina官方文档:https://www.jfinal.com/doc JFinal由Handler.Interceptor.Controller.Render.Plugin五大部分组成,且JFin ...
 - DRF视图-基类
			
2个视图基类 REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写. 为了区分上面请求和响应的代码,我们再次创建一个新的子应用: python manage.py star ...
 - android#定制ListView的界面
			
内容摘自<第一行代码>——郭霖 只能显示一段文本的ListView实在是太单调了,我们现在就来对ListView的界面进行定制,让它可以显示更加丰富的内容.首先需要准备好一组图片,分别对应 ...
 - Git速成学习第一课:创建版本库与版本回退
			
Git速成学习笔记整理于廖雪峰老师的官网网站:https://www.liaoxuefeng.com/ 我太困了0.0精神点再写...... /*我来啦!以后会陆续更新自己的学习笔记*/ Git是分布 ...
 - SolidWorks学习笔记8 包覆,圆顶
			
包覆 在该平面上创建草图,点击A,创建文字 在左侧取消勾选“使用文档字体”,点击字体,重新设置高度,字体. 在草图上点击来放置. 点击特征->包覆, 在模型树中选择有文字的草图 这里面 选择圆柱 ...
 - [bzoj3162]独钓寒江雪_树hash_树形dp
			
独钓寒江雪 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3162 题解: 首先,如果没有那个本质相同的限制这就是个傻逼题. 直接树形dp ...
 - Vue.js学习笔记-script标签在head和body的区别
			
初学JavaScript,项目需要没有系统学习,只能边查资料边码代码,埋下的坑不知道有多少,还是建议时间充足的情况下系统的将Javascript学习一遍 ,涉及的HTML知识也务必了解. 问题 最开始 ...