SOURCE

console 命令行工具 X clear

                    
>
console
// let inp = document.querySelector('#inp')
// console.log(inp)

// 防抖函数
// function fn(val){
//     console.log(val)
// }

// function debounce(fn,time){
// let timer = null
// return function(arg){
//  clearTimeout(timer)
//     timer =  setTimeout(()=>fn.call(this,arg),time)
// }
// }

// 第二种实现
// function debounce(fn,time){
// return function(arg){
// clearTimeout(fn.id)
//     fn.id = setTimeout(()=>fn.call(this,arg),time)
// }
// }


// let s = debounce(fn,2000)
// inp.addEventListener('keyup',(e)=>{
// s(e.target.value)
// })

// 节流函数
// const fn = ()=>{
//     console.log(6)
// }

// function throttled(fn,gapTime){
//     let nowTime =null
//     let lastTime = null
//     return function(){
//         nowTime = new Date()
//         if(!lastTime || nowTime  -lastTime > gapTime){
//             fn()
//             lastTime = nowTime
//         }
//     }
// }

// 第二种实现方式  和上一种相似

// function throttled(fn,gapTime = 2000){
//     let lastTime = new Date()
//     return function(){
//         let nowTime = new Date()
//         if(nowTime - lastTime > gapTime){
//             fn()
//             lastTime = new Date()
//         }
//     }
// }


// let s = setInterval(throttled(fn,2000),100)
// let s = setInterval(throttled(fn),100)

const btn = document.querySelector('#btn')

btn.onclick = ()=>{
    console.log(1)
}

// 使用动画实现防抖
// button{
//   animation: throttle 2s step-end forwards;
// }
// button:active{
//   animation: none;
// }
// @keyframes throttle {
//   from {
//     pointer-events: none;
//   }
//   to {
//     pointer-events: all;
//   }
// }



// git
/**
 * git 常用命令
 * https://segmentfault.com/a/1190000042825498  //学习网址
 * git init //初始化本地仓库
 * git version  //查看git版本
 * git config --global user.name  'leitianshun'
 * git config --global user.email  johndoe@example.com
 * git config --global init.defaultbranch main # 默认分支名称,与GitHub兼容
 * mkdir project  //创建文件夹
 * cd project  //切换到文件夹
 * git inin  //初始化本地仓库
 * echo "Hello, Git " >> hello.txt  //往里面放文件
 * git status  //会看到新创建的未被追踪的文件。
 * cat hello.txt  //查看文件
 * git ssh-keygen   //创建秘钥
 * git clone url
 * git remote add origin url  //增加一个新的远程仓库,并命名
 * git remote remove origin
 * git remote -v //显示所有远程仓库
 * git add .
 * git commit -am 'fix:修复xxx'
 * git push origin master
 * git pull origign master
 * git merge [branch]  //  合并指定分支到当前分支
 * git branch -a  //列出所有本地分支和远程分支
 * git chenkout -b main //新建一个分支,并切换到该分支
 * git checkout main //切换到指定分支
 * git status //显示有变更的文件
 * git log  stat //显示commit历史,以及每次commit发生变更的文件
 *  git branch -r    列出所有远程分支
 * git branch main  //创建分支 但是依旧停留在此分支
 *  git branch --track [branch] [remote-branch]   // 新建一个分支,与指定的远程分支建立追踪关系
 * git branch -d [branch-name]  //删除分支
 * # 删除远程分支
* git push origin --delete [branch-name]
* git branch -dr [remote/branch]
 * git fetch [remote] //下载远程仓库的所有变动 
 * git remote show [remote]   // 显示某个远程仓库的信息
 * git push [remote] [branch] //上传本地指定分支到远程仓库
 * git push [remote] --force // 强行推送当前分支到远程仓库,即使有冲突
 * git push [remote] --all  //推送所有分支到远程仓库

git aliases  可以配置一个别名,只需在配置中设置它
设置一个别名是git tree,它以树的形式打印出一个漂亮的历史日志。
git config --global alias.tree 'log --graph --decorate --pretty=oneline --abbrev-commit'
然后使用  git tree  就可输出日志

另一个别名是删除所有合并的分支。
git config --global alias.clbr '!git branch --merged | grep -v \* | xargs git branch -D'

暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop

Git 全局设置:
git config --global user.name "leitianshun"
git config --global user.email "10109993+leitianshun@user.noreply.gitee.com"
创建 git 仓库:
mkdir yingxiangyun-source-code
cd yingxiangyun-source-code
git init 
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin git@gitee.com:leitianshun/yingxiangyun-source-code.git
git push -u origin "master"
已有仓库?
cd existing_git_repo
git remote add origin git@gitee.com:leitianshun/yingxiangyun-source-code.git
git push -u origin "master"


 */

// CSS盒模型和IE盒模型的区别:

// 在 标准盒子模型中,width 和 height 指的是内容区域的宽度和高度。增加内边距、边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸。
// box-sizing:content-box;
// width = content


// IE盒子模型中,width 和 height 指的是内容区域+border+padding的宽度和高度。
// box-sizing:border-box;
// width = content + border + padding



// call apply  bind

// let obj = {name:'lei'}
// function fn(){
//     console.log(this.name)
// }
// function s(){
//     fn.call(obj)
// }
// s()


// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// var obj = {
//     name: 'jack',
//     getName: getName
// }
// var bar = {
//     name: 'rose'
// }
// obj.getName.call(bar) // rose
// obj.getName.apply(bar) // rose

// var bar = obj.getName.bind(bar)
// bar() // rose

// function getName() {
//     console.log(this)
// }
// var obj = {
//     getName: getName
// }
// obj.getName.call(1) // Number {1}
// obj.getName.call('winfar') // String {'winfar'}
// obj.getName.call(true) // Boolean {true}
// 当传入的是 null或者undefined,this绑定到全局对象。

// obj.getName.call(undefined) // Window
// obj.getName.call(null) // Window




// this 关键字    https://segmentfault.com/a/1190000042809553
// 2,
// let obj = {name:'12'}
// function fn(){
//     console.log(this.name)
// }
// fn.call(obj)
// // 12


// 3,
// let obj = {name:'1'}
// function fn(){
//     conosle.log(this.obj)
// }
// undifined  因为let 有暂时性死区 声明后不能立即调用  函数提升高于变量提升  

// 4,
// var obj = {name:'1'}
// function fn(){
//     conosle.log(this.obj)
// }
//{name:'1'}

// 默认绑定
// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// getName() // winfar

// 在严格模式下,全局对象无法使用默认绑定,this会绑定到 undefined。

// function getName() {
//   'use strict'
//     console.log(this)
// }
// getName() // undefined

// 如果对象属性嵌套有多层,被调用函数中的 this 只会指向最后一层对象,可以理解为指向直接调用它的对象。
// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// var obj = {
//     name: 'jack',
//     bar: {
//         name: 'rose',
//         getName: getName
//     }    
// }
// obj.bar.getName() // rose

// 隐式绑定
// 某个对象属性引用某个函数,在执行该函数时,this的绑定使用隐式绑定规则,该规则会把函数调用中的 this 绑定到上下文对象。

// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// var obj = {
//     name: 'jack',
//     getName: getName
// }
// obj.getName() // jack


// 值得注意,单独将对象中的函数提取出来赋值新变量,再执行这个引用变量,this 的隐式模式会丢失。

// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// var obj = {
//     name: 'jack',
//     getName: getName
// }
// var bar = obj.getName
// bar() // winfar


// 不管我们将回调函数传入自定义函数 emitFn,还是内置函数 setTimeout,都是应用默认绑定规则,回调函数中的 this都是指向全局对象。
// function getName() {
//     console.log(this.name)
// }
// var name = 'winfar'
// var obj = {
//     name: 'jack',
//     getName: getName
// }
// function emitFn(fn) {
//     fn()
// }
// emitFn(obj.getName) // winfar
// setTimeout(obj.getName) // winfar



// ajax的使用

// let username = document.querySelector('#inp')
// let password = document.querySelector('#pas')
// // console.log(inp,pas)
// username.addEventListener('keyup',(e)=>{
//     console.log(e.target.value)
// })


// const xhr = new XMLHttpRequest()
// xhr.open('post','https://note-server.hunger-valley.com/auth/login')
// xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// xhr.onreadystatechange = ()=>{
//     if(xhr.readyState == 4&&xhr.status==200){
//         console.log(JSON.parse(xhr.responseText))
//         alert('登录成功')
//     }
// }
// xhr.send('username=lts&password=123456')


// blog  使用ajax
// const xhr = new XMLHttpRequest()
// xhr.open('post','https://blog-server.hunger-valley.com/auth/login')
// xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// xhr.onreadystatechange=()=>{
//     if(xhr.readyState==4&&xhr.status == 200){
//         console.log(xhr.responseText) 
//     }
// }


// xhr.send('username=lts&password=123456')  




// axios  请求配置

// 第一种全局默认配置  小云笔记配置
// axios.defaults.baseURL= 'https://note-server.hunger-valley.com'
// axios.defaults.timeout = 3000
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'  //或者application/json;charset=utf-8 
// axios.defaults.withcredentials = true //跨域请求携带凭证
// axios.defaults.validateStatus = (status)=>{
//     return status >=200 && status < 500
// }

// const request = (url,method,data)=>{
// return new Promise((resolve,reject)=>{
//     let options = {
//         url,
//         data
//     }
//     if(method == 'get'){
// options.params = data
//     }else {
//         options.data = data
//     }
//     axios(options).then(res=>{
//         if(res.status == 200){
// resolve(res.data)
//         }else{
//             reject(res)
//             Message({
//                 type:'error',
//                 message:res.data.msg
//             })
//         }
//         }).catch(err=>{
// reject(err)
//         })
// })
// }

// // 请求配置

// export default {
//     request,
//       getInfo: () => {
//     return request('/auth', 'get')
//   },
//   login: (data) => {
//     return request('/auth/login', 'POST', data)
//   },
//   logout() {
//     return request('/auth/logout', 'get')
//   },
//   register: (data) => {
//     return request(
//       '/auth/register', 'POST', data
//     )
//   },
//   getAllNoteBook: () => {
//     return request('/notebooks')
//   },
//   addNoteBook(data) {
//     return request('/notebooks', 'POST', data)
//   },
//   deleteNoteBook: (id) => {
//     return request('/notebooks/' + id, 'DELETE',)
//   },
//   editNoteBook: (id, data) => {
//     return request('/notebooks/' + id, 'PATCH', data)
//   },
//   getNoteFromNoteBook: (id) => {
//     return request('/notes/from/' + id, 'get')
//   },
//   addNote(id, data = '') {
//     return request(`/notes/to/${id}`, 'POST', data)
//   },
//   updateNote: (id, data) => {
//     return request('/notes/' + id, 'PATCH', data)
//   },
//   delNOte: (id) => {
//     return request(`/notes/${id}`, 'DELETE')
//   }
// }

// 第二种  小云笔记配置

// const options = {
//     baseURL:'http://121.40.245.252:88',
//     method:'post',
//     header:{
//        ' Content-Type':'application/x-www-form-urlencoded'
//     },
//     timeout:3000,
//     withcredentials:true
// }

// const servince = axios.create(options)

// servince.intercepials.request.use(config=>{
//     return config
// },error=>{
//     return Promise.reject(error)
// })

// servince.intercepials.response.use(res=>{
// if(res.status==200){
//     return res.data
// }
// },error=>{
//     return Promise.reject(error)
// })

// // 接口配置
// export default {
//     servince,
//     login:()=>{
//         return servince({
//             url:'xxx',
//             method:'get'
//         })
//     },
//      login: (data) => {
//     return servince.request({
//       url: '/auth/login',
//       method: 'POST',
//       data: data
//     })
//   },
//   register: (data) => {
//     return servince({
//       url: '/auth/register',
//       method: 'POST',
//       data: data
//     })
//   },
//   logout: () => {
//     return servince.request({
//       url: '/auth/logout',
//       method: 'get'
//     })
//   }
// }


// uniapp 请求配置

// const request = (url,method,data,isShowLoading,authorization=false)=>{
// let _url = url
// //#ifndef H5
// _url = config.basePath + url
// //#enddef 
// //#ifdef H5
// _url = '/api' + url
// //#endif
//     cosnt accessToken = uni.getSotrageSync('access_token')
//     const expires_in = uni.getSotrageSync('expires_in')
// return new Promise((resolve,reject) =>{
//     if(isShowLoading){
//         uni.showLoading()
//     }
//     uni.reqeust({
//         url:url,
//         method:method,
//         data:data,
//         withcredentilas:true,
//         header:{
//             tenant-id:config.tenantId,
//             app-id:config.appId,
//             authorization:'basic' + Base64.encode('MA:MA_Secret'),
//             blade-auth:'bearer' +  accessToken ? accessToken : '',
//             client-type:'MA'
//         },
//         success(res){
//             if(res.statusCode==200){
//                 resolve(res)
//             }
//         },fial(res){
//             reject(res)
//         },complete(res){
//             if(isShowLoading){
//                 uni.hidenLoading()
//             }
//         }
//     })
// })
// }

// // 接口封装
// export default {
//     request,
//     couponIndoPage:(data)=>{
//         return reqeust('/blade-mall-api/bargaininfo/page','get',data,false)
//     },
//     	bargainUserGet: id => {
// 		//砍价记录详情
// 		return request('/blade-mall-api/bargainuser/' + id, 'get', null, false);
// 	},
//     	grouponUserPageGrouponing: data => {
// 		//拼团中分页列表
// 		return request('/blade-mall-api/grouponuser/page/grouponing', 'get', data, true);
// 	},
//     userwithdrawRecordSave: data => {
// 		//分销 申请提现
// 		return request('/blade-mall-api/userwithdrawrecord', 'post', data, true);
// 	},
// }


// 发送验证码实现 

// let  sendBtn = document.querySelector('#sendCode')
// sendBtn.style.cursor = 'pointer'
// sendBtn.style.color = 'red'
// var msgKey = false,time = 10,successMsg = '${time}秒后可发送',initMsg = '发送验证码',initTime=10
// sendBtn.onclick = ()=>{
// if(msgKey) return
//  sendBtn.innerHTML = successMsg.replace('${time}',time)
//  msgKey = true
//  let timer = setInterval(()=>{
//      time--
//  sendBtn.innerHTML = successMsg.replace('${time}',time)
//  if(time==0){
//  sendBtn.innerHTML = initMsg
//  time = initTime
//      msgKey = false
//  clearInterval(timer)
//  }
//  },1000)
// }



// 时间计算  时间戳 1668597442360 2022 11.16 19.17
// function formDate(str){
//     let diff = new Date().getTime - new Date(str).getTime()
//     // let diff = new Date().getTime() - str
//     if(!str){
//         return
//     }
//     if(diff<0){
//         return
//     }
//     if((diff / 1000 ) < 30){
//         return '刚刚'
//     }else if((diff  / 1000 ) < 60){
//         return parseInt(diff / 1000) + '秒前'
//     }else if((diff /60/ 1000) < 60){
//         return parseInt(diff / 60000) + '分钟前'
//     }else if((diff / 60 / 60 / 1000)< 24){
//         return parseInt(diff / 3600000) + '小时前'
//     }else if((diff / 24 / 60 / 60 / 1000 < 31)){
//         parseInt(diff / 24/360000) + '天前'
//     } else if ((diff / 2592000000) < 12) {
//     return parseInt(diff / 2592000000) + '月前'
//   } else {
//     return parseInt(diff / 31536000000) + '年前'
//   }
// }
//  let a =  formDate(1668597442360)
// let as = formDate('2022-11-15T02:02:57.443Z')
//  console.log(as)


 // Vue.filter('formatDate', function (str) {   //把时间作为参数传进来
//   if (!str) return ''   //如果没有就返回空
//   var date = new Date(str)
//   var time = new Date().getTime() - date.getTime() //现在的时间-传入的时间 = 相差的时间(单位 = 毫秒)
//   if (time < 0) {
//     return ''
//   } else if ((time / 1000 < 30)) {
//     return '刚刚'
//   } else if (time / 1000 < 60) {
//     return parseInt((time / 1000)) + '秒前'
//   } else if ((time / 60000) < 60) {
//     return parseInt((time / 60000)) + '分钟前'
//   } else if ((time / 3600000) < 24) {
//     return parseInt(time / 3600000) + '小时前'
//   } else if ((time / 86400000) < 31) {
//     return parseInt(time / 86400000) + '天前'
//   } else if ((time / 2592000000) < 12) {
//     return parseInt(time / 2592000000) + '月前'
//   } else {
//     return parseInt(time / 31536000000) + '年前'
//   }
// }
// ) 

// Promise 的简单使用   all  race  then  finally  resolve reject

function a(s){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            // console.log(1)
            resolve(s)
        },2000)
    })
}

function b(){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            // console.log(1)
            resolve(2)
        },4000)
    })
}

function c(){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            // console.log(1)
            resolve(66)
        },1000)
    })
}

// 同时执行多个请求 等两个请求执行完成后在执行另一个请求

// Promise.all([a(6),b()]).then(res=>{
//     console.log(res)
// }).then(res=>{
//     c().then(res=>{
//         console.log(res)
//     }).finally(res=>{
//         console.log('不管结果如何我都会执行')
//     })
// })

// 同时发送多个请求 那个请求最先得到结果就返回最先得到结果的
// Promise.race([a(),b()]).then(res=>{
//     console.log(res)
// })

// async  await 异步请求同步执行

// (async function async(){
// let res = await a(3),res2 = await c()
// console.log(res,res2)
// })()




// 时间计算    1668590794116
// function formDate(str){
//     // let diff = new Date().getTime - new Date(str).getTime()
//     let diff = new Date().getTime() - str
//     if(!str){
//         return
//     }
//     if(diff<0){
//         return
//     }
//     if((diff / 1000 ) < 30){
//         return '刚刚'
//     }else if((diff / 1000 ) < 60){
//         return parseInt(diff / 1000) + '秒前'
//     }else if((diff / 60 / 1000) <60){
//         return parseInt(diff / 60000) + '分钟前'
//     }else if((diff /60 / 60 / 1000) <24){
//         return parseInt(diff / 3600000) + '小时前'
//     }else if((diff / 24 / 60 / 60 / 1000)<31){
//         return parseInt(diff /24/ 3600000) + '天前'
//     }else if((diff / 30 / 24 /60 / 60 / 1000) <12){
//         return parseInt(diff /24/30/ 3600000) + '月前'        
//     }
// }

// let s = formDate(1668590794116)
// console.log(s)



// uniapp 实现小程序定位

// getUserLocation(){
// const qqmapSdk = new qqmapSdk({
//     key:'xxx'
// })
// uni.getLocation({
//     type:'wgs84',
//     geocode:true,
//     success(res){
// this.longitude = res.longitude
// this.latitude = res.latitude
// qqmapSdk.reverseGeocoder({
//     location:{
//         longitude:this.longitude,
//         latitude:this.latitude,
//     },
//         success(res){
// let province = res.result.ad_info.province
// let city = res.result.ad_info.city
// let district = res.result.ad_info.district
//         },fial(err){

//         },complete(res){
//             conosle.log(res)
//         }
// })
//     },fial(err){

//     }
// })
// }


// 数组遍历
// let arr = new Array(5)  //创建5个空数组
// let arr2 = [1,2,3]
// arr2.map((item,index)=>{
//     arr[index] = item
// })
// // console.log(arr)



// 数组去重

let arr = [1,2,4,2,4,3,3]

// let arr2 = [...new Set(arr)]  //第一种

// let arr2 = []    //第二种
// arr.forEach(item=>{
// if(!arr2.includes(item)){
//     arr2.push(item)
// }
// })

//  let arr2= arr.filter((item,index)=> arr.indexOf(item) === index)  //第三种
// console.log(arr2)



// 水平居中
// position:absolute;
// left:50%;
// transform:translateX(-50%);
//  background: linear-gradient(to bottom, red, pink);  //渐变色  从上往下渐变


/**
 * 数组去重
 * let arr = [1,2,3,1,2,4,3]
 * 1,  let arr2 = [...new Set(arr)]
 * 
 * 2,let arr2 = [] 
 * arr.forEach(item=>{
 * if(!arr2.includes(item)){
 * arr2.push(item)
 * }
 * })
 * 
 * 3,  arr.filter((item,index)=>arr.indexOf(item) == index)
 * 
 */


// https://blog.csdn.net/CodingNoob/article/details/80879208
// const request = (url, method, data) => {
//   return new Promise((resolve, reject) => {
//     const xhr = new XMLHttpRequest()
//     xhr.open(`${method}`, `//blog-server.hunger-valley.com${url}`)
//     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
//     xhr.send(data)
//     xhr.onreadystatechange = () => {
//       if (xhr.readyState == 4 && xhr.status == 200) {
//         console.log(xhr.responseText)
//         resolve(xhr.response)
//       }
//     }
//   })
// }

// request('/auth/login', 'POST', 'username=lts&password=123456')


// <script type="text/javascript">

//         //post请求
//         document.querySelector(".postbtn").onclick= function(){
//             var xmlhttp = new XMLHttpRequest();
//             var obj = {
//                 name: 'zhansgan',
//                 age: 18
//             };
//             xmlhttp.open("POST", "http://192.168.1.200:8080/php/test.php", true);
//             xmlhttp.setRequestHeader("token","header-token-value"); // 可以定义请求头带给后端
//             xmlhttp.setRequestHeader("dingyi","header-dingyi-value");
//             xmlhttp.send(JSON.stringify(obj));  // 要发送的参数,要转化为json字符串发送给后端,后端就会接受到json对象
//             // readyState == 4 为请求完成,status == 200为请求陈宫返回的状态
//             xmlhttp.onreadystatechange = function(){
//                 if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
//                     console.log(xmlhttp.responseText);
//                 }
//             }
//         };

//         //get请求
//         document.querySelector(".getbtn").onclick= function(){
//             var xmlhttp = new XMLHttpRequest();
//             // get方法带参数是将参数写在url里面传过去给后端
//             xmlhttp.open("GET", "http://192.168.1.200:8080/php/test.php?name='zhansgang'&age=12", true);
//             xmlhttp.setRequestHeader("token","header-token-value");
//             xmlhttp.setRequestHeader("dingyi","header-dingyi-value");
//             xmlhttp.send();
//             // readyState == 4 为请求完成,status == 200为请求陈宫返回的状态
//             xmlhttp.onreadystatechange = function(){
//                 if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
//                     console.log(xmlhttp.responseText);
//                 }
//             }
//         };
//     </script>

// console.log(1)


/**
 * 使用动画
 * @keyframes animation {
 * from {
 * transform:rotate(0deg)
 * }
 * to {
 * transform:rotate(359deg) 
 * }
 * }
 * 
 * xxx{
 * animation:animation  2s linear  infinite;
 * }
 * 
 */





 
 <div class="box">
 <div>
 <lable> 用户名
  <input type="" id='inp'>
     </lable> 
 </div>
  <div>

 <lable> 密码
  <input type="" id='pas'>
     </lable> 
 </div>
 <div>
     <button >提交</button>
 </div>
 </div>

 <div>
     <button id="btn">节流按钮</button>
 </div>
 <hr/>
 <table class="tab">
     <tr >
         <th>name</th>
         <th>age</th>
         <th>gender</th>
     </tr>
     <tr >
         <td>1</td>
         <td>2</td>
         <td>3</td>
     </tr>
       <tr >
         <td rowspan="2">1</td>
         <td>2</td>
         <td>3</td>
     </tr>
       <tr >
         <!-- <td>1</td> -->
         <td>2</td>
         <td>3</td>
     </tr>
       <tr >
         <td>1</td>
         <td colspan="2">2</td>
         <!-- <td>3</td> -->
     </tr>

 </table>
 <hr>
<div>
    <button id='sendCode'>发送验证码</button>
</div>
<hr>
<!-- <div class="keybords">

</div> -->
.box{
    width: 230px;
    height: 100px;
    border: 1px solid gray;
    padding: 10px;
    text-align: center;
    /* box-sizing: content-box; */
}
.box #inp{
    margin: 10px 0;
}
.box button{
margin: 10px 0;
}


  #btn{
   animation: throttle 2s step-end forwards;
 }
  #btn:active{
   animation: none;
 }
 @keyframes throttle {
   from {
       color: red;
     pointer-events: none;
   }
   to {
       color: green;
     pointer-events: all;
   }
 }
 
.tab{
    border: 1px solid red;
    text-align: center;
}
.tab th{
    border: 1px solid black;    
}
.tab td{
    border: 1px solid black;
    cursor: pointer;

}