由于目前class只支持static方法,static属性目前还处于试验性功能(stage-3)阶段,如果不装babel,无法兼容chrome https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Class_elements
Class A {
static a = 1;
}
// 改为
A.a = 1;
兼容性相关 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
onchange事件只有失去焦点时才会触发,oninput值改变了会触发
如果watch监听对象属性值的改变,需要用到deep: true, 这种情况对象内部的变化虽然可以监听到,但不能监听到具体改动,watch的newval 和val 一致,有些情况可以考虑使用computed属性
vue watch监听数据,新老值一样?(opens new window)
在本地 pc-v2 分支基础上,新建一个分支 pc-v2-zuo,没有推送的远程。
git branch —set-upstream-to=origin/pc-v2-zuo pc-v2-zuo
# 提示如下
#if you are planning on basing your work on an upstream branch that already exists at the remote, you may need to run "git feach" to retrieve it
# 如果您打算基于远程已经存在的上游分支工作,则可能需要运行“ git feach”来检索它
# if you are planning to push out a new local branch that will track its remote counterpart, you may want to use "git push -u" to set the upstream config as you push
# 如果您打算推出一个新的本地分支来跟踪其远程副本,则可能需要在推送时使用“ git push -u”设置上游配置
# 先push
git push origin pc-v2-zuo:pc-v2-zuo
# 再将当前分支关联到远程分支
git branch —set-upstream-to=origin/pc-v2-zuo pc-v2-zuo
问题:如果我从 pc-v2 的基础上创建的新分支,并创建了远程分支。当 pc-v2 改动时,在新的分支 pc-v2-zuo 上 git pull 是否可以拉取到 pc-v2 的最新改动,是否只能在本地 pc-v2 上 git pull 然后在本地 pc-v2-zuo 上 git merge pc-v2 才行 ?
任何更新 node_modules 和 / 或 package.json 依赖的命令npm install,npm rm,npm update都会自动同步现有的package-lock.json文件。
自npm 5.0版本发布以来,npm i的规则发生了三次变化。
1、npm 5.0.x 版本,不管package.json怎么变,npm i 时都会根据lock文件下载package-lock.json file not updated after package.json file is changed · Issue #16866 · npm/npm 这个 issue 控诉了这个问题,明明手动改了package.json,为啥不给我升级包!然后就导致了5.1.0的问题…
2、5.1.0版本后 npm install 会无视lock文件 去下载最新的npm 然后有人提了这个issue why is package-lock being ignored? · Issue #17979 · npm/npm 控诉这个问题,最后演变成5.4.2版本后的规则。
3、5.4.2版本后 如果改了package.json,且package.json和lock文件不同,那么执行
npm i
时npm会根据package中的版本号以及语义含义去下载最新的包,并更新至lock。如果两者是同一状态,那么执行npm i
都会根据lock下载,不会理会package实际包的版本是否有新。
参考:
npm install 生成的package-lock.json是什么文件?有什么用?(opens new window)
package-lock.json的作用(opens new window)
NPM package-locks 中文(opens new window)
NPM package-locks 英文(opens new window)
过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。
一般使用transform缩小0.5倍来实现,如果是border先将元素放大2倍,再缩小0.5倍,放大缩小后还是以放大的空间来占位,使用positon:absolute脱离标准文档流,就不会有两倍的占位了。
/* 比1px还细的线 */
.thinline {
height: 1px;width:100%;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
background:#ccc;
}
解决方法是将样式用style写在内联样式里,刚开始不相信写成内联样式就可以解决这个问题,但实践后发现确实可以解决这个问题。
一般flex布局后,item子项某一个高度比较高,其他子项的高度也会是高度最高的子项高度。设置border时会特别明显。如果需要让item高度适应内容,就可以使用 align-self: flex-start。
https://www.yuque.com/guoqzuo/piylht/kg7660#45717a91
AJAX 进度信息progressEvent.lengthComputable false
let {loaded = 0, total = 0, lengthComputable } = this.progressEvent
// 对于 progressEvent.lengthComputable 为false的接口,total属性会无效
// 参考:https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/lengthComputable
if (lengthComputable) {
if (total === 0) return ''
this.progressText = `下载中: ${this.formatFileSize(loaded)} / ${this.formatFileSize(total)}`
// 数据百分比,进度 1 - pendingPercent
this.percentage = this.pendingPercent * 100 + Math.ceil((loaded / total)*(1 - this.pendingPercent) * 100)
} else {
// 资源无法计算size, total无效的情况
this.progressText = '下载中: ${this.formatFileSize(loaded)}'
// 进度无法精准计算,只能模拟,没触发一次onprogress时间,进度增加10%,加到90%就停止
if (this.percentage <= 80) {
this.percentage += 10
}
}
formatFileSize(value) {
let sizeArr = [
{ sizeStr: 'B', index: 10 },
{ sizeStr: 'KB', index: 20 },
{ sizeStr: 'MB', index: 30 },
{ sizeStr: 'GB', index: 40 },
{ sizeStr: 'TB', index: 50 },
]
for (let i = 0, len = sizeArr.length; i < len; i++) {
if (value < 2 ** sizeArr[i].index) {
let newVal = value / 2 ** (sizeArr[i].index - 10)
newVal = Number.isInteger(newVal) ? newVal : newVal.toFixed(2)
return `${newVal}${sizeArr[i].sizeStr}`
}
}
return 'too large > 1025 T'
}
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/submissions/
https://leetcode-cn.com/problems/merge-sorted-array/submissions/
解题demo
https://github.com/zuoxiaobai/fenote/tree/master/src/leetcode/task
flex布局justify-content属性值区别
Bootstrap 编码规范:编写灵活、稳定、高质量的 HTML 和 CSS 代码的规范。https://codeguide.bootcss.com/
不管有多少人共同参与同一项目,一定要确保每一行代码都像是同一个人编写的。
参考: https://www.jianshu.com/p/46519b0499c3
https://yarn.bootcss.com/
Yarn 是一个快速、可靠、安全的依赖管理工具。是 NPM 的替代品。
今天看看了ts实战指南这本书,里面是这样介绍Yarn的:
Yarn [jɑːn] 是facebook,google等公司共同开发的一款新的js包管理工具,并没有试图完全取代npm,Yarn同样是从npm获取包。存在的目的是:解决团队使用npm面临的少数问题,如版本锁定,并行安装、文案输出等
macos安装Yarn方法
brew install yarn
Yarn基本用法
# 初始化一个新项目
yarn init
# 添加依赖包
yarn add [package]
yarn add [package]@[version]
yarn add [package]@[tag]
# 添加到不同依赖类别
yarn add [package] --dev
yarn add [package] --peer
yarn add [package] --optional
# 更新依赖包
yarn upgrade [package]
yarn upgrade [package]@[version]
yarn upgrade [package]@[tag]
# 移除依赖包
yarn remove [package]
# 安装项目的全部依赖
yarn 或者 yarn install
返回千分位逗号分隔的字符串.
// MDN文档: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
var number = 12123
number.toLocaleString() // "12,123"
number.toLocaleString('en', {style:'currency', currency:'USD'}) // "$12,123.00"
number.toLocaleString('cn', {style:'currency', currency:'CNY'}) // "¥12,123.00"
之前可能是很少写非常复杂的联动逻辑,发现如果多组件需要取很多公共数据做检验联动时,状态管理是非常有必要的。这是一个很好的使用场景。如果场景不是很复杂,那就没必要使用状态管理。想到之前看vuex官方文档时的一句话: Flux libraries are like glasses: you’ll know when you need them.(Flux 架构就像眼镜:您自会知道什么时候需要它。) https://vuex.vuejs.org/
zip -e 目标文件名.zip 需要加密的zip文件
# 输入上面的命令后,会提示输入两次密码
更多zip命令相关用法,可以在控制台使用 man zip 查看文档
vscode插件名称: “GitLens – Git supercharged”,安装后点击某一行代码,都会显示最近的git提交记录,非常好的一个git插件
/**
* Number.prototype.toFixed()
* The toFixed() method formats a number using fixed-point notation.
* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
*
* 使用方法:
* numObj.toFixed(digits)
* @params { Integer } digits 可选 保留精度,为空时,默认为0,即取整
* @returns { String } 返回转换后的字符串
*/
var a = 1.235
a.toFixed() // "1"
typeof a.toFixed() // "string"
a.toFixed(2) // "1.23"
重点来了,tofixed()需要注意的地方:
var a = 0.15
var b = 0.25
a.toFixed(1) // "0.1" 注意这里四舍五入异常
b.toFixed(1) // "0.3" 这里四舍五入又是成功的
// 如果希望精准的保留1位小数可以 Math.round(a*10) / 10, 如果是两位 100,n位 Math.pow(10, n)
Number.prototype.myToFixed = function (num) {
// 在原型方法注入 myToFixed函数,这里怎么获取当前的值呢?可以使用this
// 注意 this 是一个Number对象
// var a = Number(2) // 2 typeof a 为 "number"
// var b = new Number(2) // Number{2} typeof b 为 "object"
// 获取值需要使用 b.valueOf() // 2
// 如果没有传参数
if (num === undefined) {
return Math.round(this.valueOf())
}
// 如果有传参,且为整数
if (Number.isInteger(num)) {
var tempCount = Math.pow(10, num)
var tempNum = Math.round(this.valueOf() * tempCount) / tempCount
// 这一步其实已经就可以了。但对于保留整数后面两位小数来说,会有bug
// var a = 2
// a.myToFixed(2) => 2 而不是 2.00
// 需要再转换下
return tempNum.toFixed(num)
} else {
throw new Error('参数必须是number类型,且必须是整数')
}
}
-2.12.toFixed(1) // -2.1 注意返回的字符串,被 - 操作后就是number了
(-2.12).toFixed(1) // "-2.1"
参考: https://www.zhihu.com/question/58702398/answer/235777073
DevOps 是 Development(开发)和 Operations(运维) 的组合词
目前学术界和从业人员还没有为 “DevOps” 建立唯一的定义
DevOps可以改变 运营、开发、测试人员在开发和交付过程中协作的方式。
网易云认为:DevOps 强调的是高效组织团队之间如何通过自动化的工具协作和沟通来完成软件的生命周期管理,从而更快、更频繁地交付更稳定的软件
DevOps 的出现是由于软件行业日益清晰地认识到,为了按时交付软件产品和服务,开发部门和运维部门必须紧密合作。
企业为什么需要DevOps,DevOps有什么依赖?网易云认为:
DevOps 希望做到的是软件产品交付过程中IT工具链的打通,使得各个团队减少时间损耗,更加高效地协同工作。
字面意思是无服务器,小程序云开发就是一种
CI持续集成 => CD持续交付 => CO持续运营
参考: 干货满满!10分钟看懂Docker和K8S(opens new window)
容器是虚拟机的一个发展,相对传统的虚拟机,容器的优点:
特性 | 虚拟机 | 容器 |
---|---|---|
隔离级别 | 操作系统级 | 进程级 |
隔离策略 | Hypervisor | CGroups |
系统资源 | 5-15% | 0-5% |
启动时间 | 分钟级 | 秒级 |
镜像存储 | GB-TB | KB-MB |
集群规模 | 上百 | 上万 |
高可用策略 | 备份、容灾、迁移 | 弹性、负载、动态 |
K8S是基于容器的集群管理平台,它的全称,是kubernetes。
旧的jsp项目,需要用到prompt功能,但需要优化下UI,整体导入elementUI不合适,就自己用原生JS写了个。样式、div结构,直接从elementUI message-box审查元素里面抽离,相关点击事件,校验,自己封装,具体代码位置: https://github.com/zuoxiaobai/fedemo/blob/master/src/DebugDemo/prompt/index.html
/**
* 向window挂载 elcustomPrompt 函数,代替系统的prompt
* window.elCustomPrompt IE9+
* 从 element UI中抽出messagebox样式结构
*/
(function() {
/**
* @description elementUI风格自定义propmt封装
* @param { String } title 标题propmt第一个参数
* @param { String } placeholder input的placeholder
* @param { Function } validateFunc 动态校验值函数
* - 点击确认后,执行的函数,参数为当前值,
* - return格式:
* { result: true, msg: '成功'}
* { result: false, msg: '自定义错误信息' }
* 考虑到阻塞程序向下执行,兼容性问题,不使用promise,使用回调函数。
* @param { Function } callback 获取到值后的回调
*/
function elCustomPrompt(title, placeholder, validateFunc, callback) {
console.log('show elCustomPrompt')
var deleteImgUrl = 'delete.png' // 16 * 16
var errMsg = '' // 错误信息
// 创建dom并挂载
var domStr = '
'
var div = document.createElement('div')
div.setAttribute('id', 'elCustomPromptDiv')
div.innerHTML = domStr
document.body.appendChild(div)
// 移除弹窗框
function removeDiv() {
document.body.removeChild(div)
}
// 绑定事件
var elCustomPromptErrMsgDiv = document.getElementById('elCustomPromptErrMsgDiv'),
elCustomPromptCloseBtn = document.getElementById('elCustomPromptCloseBtn'),
elCustomPromptCancelBtn = document.getElementById('elCustomPromptCancelBtn'),
elCustomPromptOkBtn = document.getElementById('elCustomPromptOkBtn'),
elCustomPromptInput = document.getElementById('elCustomPromptInput'),
elCustomPromptMain = document.getElementById('elCustomPromptMain')
elCustomPromptMessageBox = document.getElementById('elCustomPromptMessageBox')
// 关闭弹窗、取消事件
elCustomPromptCloseBtn.onclick = function() {
removeDiv()
}
elCustomPromptCancelBtn.onclick = function() {
removeDiv()
}
// 点击确定后的操作
elCustomPromptOkBtn.onclick = function() {
console.log('点击了确定')
// 再次校验
let tempResult = validateFunc(elCustomPromptInput.value)
if (!tempResult.result) {
elCustomPromptErrMsgDiv.style.visibility = 'visible'
elCustomPromptErrMsgDiv.innerHTML = tempResult.msg
elCustomPromptOkBtn.setAttribute('disabled', 'disabled')
return
}
// 关闭 弹窗,调用callback
removeDiv()
callback(elCustomPromptInput.value)
}
// 输入事件
elCustomPromptInput.oninput = function(e) {
console.log(elCustomPromptInput.value)
// 校验并显示信息
var tempResult = validateFunc(elCustomPromptInput.value)
console.log(tempResult)
if (tempResult.result) {
console.log('成功')
// 校验成功
elCustomPromptErrMsgDiv.style.visibility = 'hidden'
elCustomPromptErrMsgDiv.innerHTML = ''
elCustomPromptOkBtn.removeAttribute('disabled')
} else {
// 校验失败
console.log('失败')
elCustomPromptErrMsgDiv.style.visibility = 'visible'
elCustomPromptErrMsgDiv.innerHTML = tempResult.msg
elCustomPromptOkBtn.setAttribute('disabled', 'disabled')
}
}
// 空白位置点击关闭弹窗
elCustomPromptMain.onclick = function() {
removeDiv()
}
elCustomPromptMessageBox.onclick = function(e) {
event.stopPropagation()
}
}
window.elCustomPrompt = elCustomPrompt
})()
一句话总结:用一个父元素(铺满屏幕,绝对布局)包裹该div(绝对布局,水平垂直居中,固定宽高),父元素监听点击事件后移除div,子元素div监听点击后阻止事件冒泡。这样就实现了,点击外部关闭div,点击内部区域不关不div。测试代码:
复习下JS高程3里面将的函数做参数时this的问题,除了bind,也可以使用闭包
var a = 5
function callback() {
console.log('-- callback this', this, this.a, '--')
}
function validate() {
console.log('-- validate this', this, this.a, '--')
}
function showPrompt(title, validate, callback) {
validate()
callback()
}
showPrompt('1', validate, callback) // 5 5
showPrompt('1', validate.bind({a: 2}), callback.bind({a: 1})) // 2 1
或者
var a = 5
var callback = {
a: 1,
handler() {
console.log(this, this.a)
}
}
var validate = {
a: 2,
handler() {
console.log(this, this.a)
}
}
function showPrompt(title, validate, callback) {
validate()
callback()
}
showPrompt('1', validate.handler, callback.handler) // 5 5
showPrompt('1', validate.handler.bind(validate), callback.handler.bind(callback)) // 2 1
使用箭头函数
var a = 5
var callback = {
a: 1,
handler: () => {
console.log(this, this.a)
}
}
var validate = {
a: 2,
handler: () => {
console.log(this, this.a)
}
}
function showPrompt(title, validate, callback) {
validate()
callback()
}
showPrompt('1', validate.handler, callback.handler) // 5 5
showPrompt('1', validate.handler.bind(validate), callback.handler.bind(callback)) // 5 5
一句话总结:如果不想用!important,那最前面加id,来提高优先级
这复习下之前看HTML权威指南css部分及CSS权威指南里css优先级的问题 https://www.yuque.com/guoqzuo/piylht/dg9u82#4944cc9c
如果两条定义于同一层次的样式都能应用于同一个元素。且都包含同样的属性值,就需要根据特殊性来决定到底使用哪种。 a. 样式的选择器中id值的数目(#) b. 选择器中其他属性和伪类的数目(.class等属性) c. 选择器中元素名和伪元素数目(元素名等)
a的特殊性最高,b其次,c最低。按a-b-c来表示。比如如果a值相等,才会去比较b。1-0-0的特殊性比0-5-5高。在 CSS权特威指南 中,有4位,最高位为内嵌(Inline)样式设置的样式。关于特殊性,建议看CSS权威指南,个人认为比这里要好理解一点。如果层级一样,谁后定义的,优先级就越高。
参考: https://zhidao.baidu.com/question/486470512.html
当设置是background-repeat在y轴重复背景时,background-position设置的顶部开始具体会无效
业务场景:
我是标题
产品信息
最开始的思路:直接将main-title 设置margin-top: -20px,但这样会导致中间主内容整体上移,覆盖顶部部分内容,然后想到使用background-position属性将中间部分内容背景顶部开始位置设置20px左右,这样margin上去后,部分内容使用的就会是顶部的背景。但中间部分内容又设置了backgroud-repeat属性,导致background-position设置失效。
换个思路,将main-title再用一层div包裹,外层div position设置为relative, main-title设置为position:absolute,这样 top:-20px 即可实现需求,但问题来了。标题如果过长,会分行显示(可能是2行,3行,4行),这样会覆盖下面的产品信息。所以需要知道标题的高度。但标题是position:absolute的,已经脱离的文档流,无法对现有文档布局造成影响。
貌似没有css的解决方法,只能通过dom,计算title高度,然后将产品信息设置对应的margin-top
document.getElementById('autoMarginTop').style.marginTop = document.getElementById('autoHeightTitle').clientHeight - relatvie包裹元素高度 + 'px'
刚了解到了一个解决方法:标题使用 position:relative; top:-10px 就可以了
svn update
git与svn常用命令对比: https://blog.csdn.net/scythe666/article/details/51941622
svnadmin create ------------------------------> git init
svn co ------------------------------> git clone
svn update ------------------------------> git pull
svn add ------------------------------> git add
svn commit ------------------------------> git add, git commit
svn status ------------------------------> git status
svn switch ------------------------> git checkout
svn merge ------------------------> git merge
svn revert ------------------------------> git checkout
如果需要看别人的代码,运行异常,业务逻辑复杂的情况,可以加个console.log,打印的log位置,点击文件,进入,就可以在对应的文件下断点了。然后一步步执行,就可以确定问题所在。调试其他人写的复杂逻辑必备,这种情况靠console.log看太麻烦,特别是改动不方便实时更新调试的情况效果更好。
之前用eclipse build ant ,将war deploy到tomcat的webapps会很慢,后面换成 idea后会很快。
测试demo地址: https://github.com/zuoxiaobai/fedemo/blob/master/src/DebugDemo/html2canvas/index.html
Document
邀请函
你好,邀请你xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
--- guoqzuo
参考:https://www.cnblogs.com/qlqwjy/p/7681035.html
<%-- JSP中的注释,这里面的内容在查看页面源代码时,看不到这里面注释书写的内容 --%>
所以涉及业务的建议使用<%-- --%>注释,文字描述性的建议使用注释。
修改了某个js,重新编译到tomcat的webapps目录下,发现改动一直没有生效。以为改错了,进入编译后的文件目录,检查文件是有改动的,就想到应该是有缓存,浏览器加载过该js文件就缓存了。清下浏览器缓存,改动生效
jpg、png、bmp、gif图片格式区别,什么是webp?
参考:https://baijiahao.baidu.com/s?id=1599728202992947939&wfr=spider&for=pc
参考:https://baike.baidu.com/item/webp%E6%A0%BC%E5%BC%8F/4077671?fr=aladdin,https://www.jianshu.com/p/73ca9e8b986a
在html文件编辑区域,右键 => open With live server,可以开启http服务,不需要自己搭建node服务或nginx
参考:什么是 Alpha、Beta、RC、Release版 https://www.cnblogs.com/lanmiao/articles/2184282.html
// html2canvas Releases note
v1.0.0-rc.5
v1.0.0-rc.4
…
v1.0.0-rc.0
v1.0.0-alpha.12
…
v1.0.0-alpha.1
v0.5.0-beta4
v0.5.0-beta3
0.5.0-alpha1
v0.4.1 - 7.9.2013
v0.3.3 - 2.3.2012
v0.3.2 - 20.2.2012
0.3.1
v0.3.0 - 7.9.2011
let routes = []
// 路由信息仅开发环境可见
if (process.env.NODE_ENV === 'development') {
routes = [
{
path: ‘/xxxx’,
component: () => import(‘xxx’)
}
]
}
export default routes
点击屏幕下方第一个图标:访达(Finder) => 屏幕左上方苹果logo右侧 点击 访达(Finder) => 偏好设置 => 高级 => 勾选显示所有文件扩展名
// 没有下载进度,页面不会跳转,没什么反应
var a = ''
$("html").append(a)
document.getElementById('download').click()
$('#download').remove()
文件下载进度里会有一个total, loaded字段,total字段依赖于后端response响应头里的Content-length
写的逻辑或项目搭建情况,遇到的坑,思路,一定要有markdown,这样后面他人维护会很好维护。不至于耗费大量时间去整理业务逻辑(搬砖),建议存到当前目录的readme.md或者统一存放到docs目录里
macOS 安装nginx
解决方法:brew install nginx, 需要注意xcode不要随意卸载,不然会出各种奇怪的问题: 包括svn问题、nginx安装问题等。
# brew install nginx 安装后部分log
==> nginx
Docroot is: /usr/local/var/www
The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.
nginx will load all files in /usr/local/etc/nginx/servers/.
To have launchd start nginx now and restart at login:
brew services start nginx
Or, if you do not want or need a background service you can just run: nginx
brew install nginx
# 运行nginx,出现端口占用的情况,可能已经启动过nginx了
kevindeMacBook-Air:~ kevin$ sudo nginx
Password:
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:8080 failed (48: Address already in use)
# 如果出现上面端口被占用的情况,也可以查看端口占用情况
kevindeMacBook-Air:~ kevin$ lsof -i :8080
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 42869 kevin 6u IPv4 0x97257f79dc0dbd3 0t0 TCP *:http-alt (LISTEN)
nginx 42870 kevin 6u IPv4 0x97257f79dc0dbd3 0t0 TCP *:http-alt (LISTEN)
# 解除端口占用
kevindeMacBook-Air:~ kevin$ sudo kill -9 42869
kevindeMacBook-Air:~ kevin$ sudo kill -9 42870
# 修改端口为81
# 我本地的80端口之前调试过php,开启了apache服务占用了,127.0.0.1/1.php可以正常访问php项目
kevindeMacBook-Air:~ kevin$ vi /usr/local/etc/nginx/nginx.conf
# http://127.0.0.1:81/ 修改为81后,可正常访问