pm2 部署nuxt3项目
1、静态部署//pnpm打包 pnpm run generate代码传到(或Jenkins构建)到linux服务器,用常用的Nginx静态部署就可以2、build 打包 pm2部署pnpm run build在根目录新建pm2配置文件:ecosystem.config.jsmodule.exports = { apps: [ { name: 'blog', exec_mode: 'cluster', instances: 'max', script: '.output/server/index.mjs', env: { NITRO_PORT: 3000, NITRO_HOST: '127.0.0.1', }, }, ], }启用pm2pm2 restart ecosystem.config.js pm2 save pm2 list到此结束就可以访问了。
查看详情点赞1评论收藏浏览902023-02-27 16:17:54导弹制造流程
导弹制造流程主要分为研制和生产两个阶段,每个阶段都包含了多个步骤,如下所示:研制阶段: 设计阶段:根据任务需求和技术要求,进行导弹的总体设计和方案确定。* 技术研究阶段:包括弹体外形设计、材料选型、动力系统研制、制导系统研制、试验测试等。 试验验证阶段:对导弹进行多项试验验证,包括静态试验、动态试验、环境适应性试验、系统一体性试验等。生产阶段: 毛坯制造:将所需材料加工成相应的毛坯。 零件加工:对毛坯进行加工,制造出各个零部件。 部件组装:将各个零部件组装成部件。 全弹总装:将所有部件组装成完整的导弹。 试验测试:对导弹进行各项试验测试,如静态试验、动态试验、全弹试验等。 导弹制造厂主要负责弹体的制造和全弹的总装,弹上安装的发动机、控制仪器及各种装置均由专业厂所提供。不同类型的导弹可能有不同的制导方式,常见的制导方式包括: 激光制导:需要激光指示器照射目标。* 雷达制导:通过雷达头持续照射目标。 红外制导:通过红外引导头照射辐射源。* 电视制导:通过摄像头观察目标校准。 GPS制导:将目标坐标预先输入导弹电脑中规划路线有发射后不管的能力。 有线制导:多用于反坦克导弹后面拖着一根线。 惯性制导:多用于弹道弹道速度较快。弹道导弹的制造主要分为三步:造弹头、造弹身、造弹尾。其中,造弹头和造弹身相对简单,而造弹尾则是重点。弹尾需要喷,因此需要先做一个药柱箱,然后将药装进去。弹头、弹身、弹尾装在一起,就可以制造出一枚地道的弹道导弹了。
查看详情点赞1评论1收藏1浏览1262023-03-02 11:13:55go 发送邮件功能
上一篇 go-zero 数字图形验证码功能 之后,接下来我们要开发一个发送邮件的功能。框架还是go-zero,好吧,我们开始撸!1、引包:我们用到的是这个包(github.com/jordan-wright/email)github.com/jordan-wright/email2、新建一个邮件发送的工具:新建一个utils文件加,然后创建mail.go文件直接撸代码:我用的是163邮箱,开干之前。需要在邮箱进行配置。具体步骤百度一下或者联系我沟通。package utils import ( "crypto/tls" "fmt" "net/smtp" "strings" "github.com/jordan-wright/email" ) func Email(To, subject string, body string) error { to := strings.Split(To, ",") return send(to, subject, body) } func send(to []string, subject string, body string) error { from := "这里是发件人邮箱地址,需要自己配置" nickname := "这里是名称" secret := "秘钥" host := "smtp.163.com" port := 465 isSSL := true auth := smtp.PlainAuth("", from, secret, host) e := email.NewEmail() if nickname != "" { e.From = fmt.Sprintf("%s <%s>", nickname, from) } else { e.From = from } e.To = to e.Subject = subject e.HTML = []byte(body) var err error hostAddr := fmt.Sprintf("%s:%d", host, port) if isSSL { err = e.SendWithTLS(hostAddr, auth, &tls.Config{ServerName: host}) } else { err = e.Send(hostAddr, auth) } return err } OK,工具方法已经好了。我们开始引用:utils.Email(in.Email, "xxx", "您好,欢迎加入xxxxx!邮箱已发送,祝您使用愉快!")
查看详情点赞1评论收藏1浏览1072023-03-03 16:22:48three学习路线(一)
安装three官网包引入three.js<script type="module"> // 现在浏览器支持ES6语法,自然包括import方式引入js文件 import * as THREE from './build/three.module.js'; </script>three.js三个基本概念:场景Scene、相机Camera、渲染器Renderer1.三维场景Scene你可以把三维场景Scene (opens new window)对象理解为虚拟的3D场景,用来表示模拟生活中的真实三维场景,或者说三维世界。创建3D场景对象Sceneconst scene = new THREE.Scene();2.物体形状:几何体Geometry Three.js提供了各种各样的几何体API,用来表示三维物体的几何形状{ 长方体(BoxGeomentry) 圆柱体(CylinderGeometry) 球体(SphereGeometry) 圆锥(ConeGeometry) 矩形平面(PlaneGeometry) 圆面图(CircleGeometry)}//创建一个长方体几何对象Geometryconst geometry = new THREE.BoxGeometry(100, 100, 100); 3.物体外观:材质Material如果你想定义物体的外观效果,比如颜色,就需要通过材质Material相关的API实现。threejs不同材质渲染效果不同,下面就以threejs最简单的网格基础材质MeshBasicMaterial (opens new window)为例给大家实现一个红色材质效果。{ 网格基础材质(MeshBasicMaterial) 网格漫反射材质(MeshLamberMaterial) 网格高光材质(MeshPhongMaterial) 物理材质(MeshStanderMaterial)(MeshPhysicalMaterial) 点材质(PointsMaterial) 线基础材质(LineBasicMaterial) 精灵材质(SpriteMaterial)}//创建一个材质对象Materialconst material = new THREE.MeshBasicMaterial({ color: 0xff0000,//0xff0000设置材质颜色为红色 }); 4.物体:网格模型Mesh实际生活中有各种各样的物体,在threejs中可以通过网格模型Mesh (opens new window)表示一个虚拟的物体,比如一个箱子、一个鼠标。// 两个参数分别为几何体geometry、材质materialconst mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh5.模型位置:position实际生活中,一个物体往往是有位置的,对于threejs而言也是一样的,你可以通过位置属性position定义网格模型Mesh在三维场景Scene中的位置。const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh //设置网格模型在三维空间中的位置坐标,默认是坐标原点 mesh.position.set(0,10,0);6.add()方法在threejs中你创建了一个表示物体的虚拟对象Mesh,需要通过.add()方法,把网格模型mesh添加到三维场景scene中。scene.add(mesh); 代码小结<script type="module"> // es6引入three.js import * as THREE from "../build/three.module.js"; // 创建场景 const scene = new THREE.Scene(); // 创建物体形状(几何体) const geomeyry = new THREE.BoxGeometry(100, 100, 100); // 添加物体外观(材质) const material = new THREE.MeshBasicMaterial({ color: 0xff0000, }); // 创建网格模型 把形状外观放入模型中 const mesh = new THREE.Mesh(geomeyry, material); // 设置模型所在场景(Scene)中的位置 mesh.position.set(0, 10, 0); // 把模型添加到场景(Scene)中 scene.add(mesh); </script>
查看详情点赞1评论1收藏浏览882023-03-07 15:11:28VirtualBox虚拟机安装Centos系统,并安装宝塔环境
今天在新公司,需要安装Linux系统进行开发项目。以前是外包出去的项目,不知道为啥必须用Linux系统,也不知道有多少坑。 一步一来呗。首先,我们先安装虚拟机,我用的是VirtualBox,其他虚拟机同样的道理。然后安装Linux环境,我用的是centos系统,有兴趣的同学用其他系统也一样的。最后简简单单用宝塔部署了一个环境。简单的来。1、安装VirtualBox虚拟机VirtualBox官网地址: https://www.virtualbox.org/然后傻瓜式安装,直接下一步到头。安装完成之后如图:2、开始安装Centos系统首先下载centos系统,随便哪里下载都行,我这里用的是: https://www.centos.org/download/选择的是阿里云好,这里然后就开始安装系统然后一步一步进行操作,安装完成后,网络选择桥接好了,安装完成。接下来,我们用xshell链接虚拟机进行操作。这个地方要先查虚拟机IPifconfig如果提示没有这个命令需要安装工具1、新安装centos需要启动网卡,运行nmcli dev status查看设备状态2、查看网卡为ens33 ,执行命令nmcli con up ens333、开启启动网络 切换到网络配置目录 cd /etc/sysconfig/network-scripts/ 编辑 vi ifcfg-ens33首先找到ONBOOT=no修改为ONBOOT=yes然后保存退出 执行systemctl start network 或service network restart #重启网络服务 4、运行ifconfig,查看ip(最小安装会出现没有ifconfig命令需要安装,执行yum install net-tools -y)nmcli dev status nmcli con up ens33 cd /etc/sysconfig/network-scripts/ vi ifcfg-ens33 ONBOOT=yes 执行systemctl start network 或service network restart #重启网络服务 yum install net-tools -y5、查找到ip,后台运行虚拟机,使用xshell或phpstorm里带的ssh链接centosOK,xshell链接成功了接下来就安装宝塔 https://www.bt.cn/new/download.html 到这里所有的东西都准备好了,接下来就是部署站点了。
查看详情点赞1评论收藏浏览682023-03-23 16:35:06input输入框限制正则
只能输入数字:<el-input v-model.number="num" oninput="value=value.replace(/[^\d]/g,'')" />禁止输入空格:<el-input v-model="name" @input="name = name.replace(/[ ]/g, '')" />禁止输入中文空格:<el-input v-model="code" @input="code = code.replace(/[\u4e00-\u9fa5]|[ ]/g, '')" />1.限制input输入框只能输入大小写字母、数字、下划线的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/[^\w_]/g,'');"> 2.限制input输入框只能输入小写字母、数字、下划线的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/[^a-z0-9_]/g,'');"> 3…限制input输入框只能输入数字和点的正则表达式:<el-input type="text" onkeyup="value=value.replace(/[^\d.]/g,'')">4.限制input输入框只能输入中文的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/[^\u4e00-\u9fa5]/g,'')"> 5.限制input输入框只能输入数字的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/\D/g,'')"> 6.限制input输入框只能输入英文的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/[^a-zA-Z]/g,'')">7.限制input输入框只能输入中文、数字、英文的正则表达式:<el-input onkeyup="value=value.replace(/[^\w\u4E00-\u9FA5]/g, '')"> 8.限制input输入框只能输入数字和字母的正则表达式:<el-inputt onKeyUp="value=value.replace(/[\W]/g,'')"> 9.限制input输入框除了英文的标点符号以外,其他的都可以中文,英文字母,数字,中文标点的正则表达式:<el-input type="text" onkeyup="this.value=this.value.replace(/^[^!@#$%^&*()-=+]/g,'')">10.限制input输入框只能输入数字代码(小数点也不能输入)的正则表达式:<el-input onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')">11.限制input输入框只能输入数字,能输小数点.的正则表达式:<el-input onkeyup="if(isNaN(value))execCommand('undo')" onafterpaste="if(isNaN(value))execCommand('undo')"><el-input name=txt1 onchange="if(/\D/.test(this.value)){alert('只能输入数字');this.value='';}">或者<el-input type=text t_value="" o_value="" onkeypress="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onkeyup="if(!this.value.match(/^[\+\-]?\d*?\.?\d*?$/))this.value=this.t_value;else this.t_value=this.value;if(this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?)?$/))this.o_value=this.value" onblur="if(!this.value.match(/^(?:[\+\-]?\d+(?:\.\d+)?|\.\d*?)?$/))this.value=this.o_value;else{if(this.value.match(/^\.\d+$/))this.value=0+this.value;if(this.value.match(/^\.$/))this.value=0;this.o_value=this.value}">12限制input输入框只能输入字母和汉字的正则表达式:<el-input onkeyup="value=value.replace(/[\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[\d]/g,''))" maxlength=10 name="Numbers">13.限制input输入框只能输入英文字母和数字,不能输入中文的正则表达式:<el-input onkeyup="value=value.replace(/[^\w\.\/]/ig,'')">14限制input输入框只能输入数字和英文的正则表达式:<el-input onKeyUp="value=value.replace(/[^\d|chun]/g,'')">15限制input输入框小数点后只能有最多两位(数字,中文都可输入),不能输入字母和运算符号的正则表达式:<el-input onKeyPress="if((event.keyCode<48 || event.keyCode>57) && event.keyCode!=46 || /\.\d\d$/.test(value))event.returnValue=false">16.限制input输入框小数点后只能有最多两位(数字,字母,中文都可输入),可以输入运算符号:的正则表达式:<el-input onkeyup="this.value=this.value.replace(/^(\-)*(\d+)\.(\d\d).*$/,'$1$2.$3')">17.不可输入中文<el-input onkeyup="this.value=this.value.replace(/[\u4E00-\u9FA5]/g,'')">18.不可输入空格<el-input onkeyup="onkeyup="value = value.replace(/\s+/g, '')">
查看详情点赞1评论收藏1浏览662023-03-27 11:33:07Laravel 缓存类原子锁
在后端开发中,关于锁的问题,也是经常能遇到的。为了防止程序并行所导致的数据破坏,或者系统故障,在开发中合理的运用锁,可以带来更好的效果。Cache::lock用法:if (Cache::lock('foo', 10)->get()) { // 锁住这个key 10秒的时间 // 然后我们可以接着自己实际项目中的相关操作 Cache::lock('foo')->release();//一定要在结尾处释放锁,不然会导致别的并行或后续请求一直无法获取锁而停滞 }例如最常见我们在处理用户余额的时候需要用到锁utils工具中封装方法: /** * 获取一个原子锁 * @param string $name * @param int $seconds * @return Lock */ public static function acquireLock(string $name, int $seconds = 60): Lock { return Cache::lock($name, $seconds); } /** * 释放一个原子锁 * @param Lock $lock * @return void */ public static function releaseLock(Lock $lock): void { $released = optional($lock)->release(); if (!$released) { optional($lock)->forceRelease(); } }调用:/** * 增加用户余额 * @param int $userId * @param int $amountInCents * @param int $changeType * @param string $description * @return UserAccountBalance|null */ public function increaseUserBalance( int $userId, int $amountInCents, int $changeType, string $description = '', ): ?UserAccountBalance { $lock = Utils::acquireLock('user_balance_' . $userId); try { $lock->block(10); $balance = $this->getBalance($userId); if (empty($balance)) { $balance = $this->createBalance([ 'user_id' => $userId, 'total_balance_in_cents' => 0, 'withdrawn_balance_in_cents' => 0, 'remaining_balance_in_cents' => 0, ]); } if (empty($balance)) { throw new Exception('创建用户余额失败'); } if ($amountInCents == 0) { return $balance; } $change = $this->createBalanceChange([ 'user_id' => $userId, 'changed_amount_in_cents' => $amountInCents, 'change_type' => $changeType, 'change_detail' => ['description' => $description], ]); if (empty($change)) { throw new Exception('余额变更记录保存失败'); } $this->updateBalance($balance, [ 'total_balance_in_cents' => $balance->total_balance_in_cents + $amountInCents, 'remaining_balance_in_cents' => $balance->remaining_balance_in_cents + $amountInCents, ]); return $balance; } catch (Exception $error) { Log::error('用户余额更新失败', [ 'userId' => $userId, 'amount_in_cents' => $amountInCents, 'code' => $error->getCode(), 'message' => $error->getMessage(), 'file' => $error->getFile(), 'line' => $error->getLine(), ]); return null; } finally { Utils::releaseLock($lock); } }
查看详情点赞1评论收藏浏览522023-03-29 11:09:41JS屏蔽UC浏览器网页垃圾广告问题
在前端开发中,特别是手机端网页时候。经常会在手机网页底部自动加上类似于上面这种垃圾广告。这样会应该我们的站点,让人误以为是广告,所以我们要在代码中进行处理。这种情况基本上UC浏览器向我们页面插入了一段iframe代码。处理的方式有很多,下面是我们常用的一种方式,亲测可用。// 清除广告 var del_times = 0, deTimer = null; function adGo() { var iframe = document.getElementsByTagName("iframe")[0]; if (iframe) { var bodyNode = { tagName: "" }, iframeParent, targetNode = iframe.parentNode; while (bodyNode.tagName != "BODY") { bodyNode = targetNode; if (bodyNode.tagName != "BODY") { iframeParent = targetNode; targetNode = targetNode.parentNode; } } if (iframeParent) //如果iframe有父类 bodyNode.removeChild(iframeParent); else bodyNode.removeChild(iframe); } del_times++; if (del_times > 10) window.clearInterval(deTimer); } //抢先 删除 嵌入广告 (function () { adGo(); })(); deTimer = self.setInterval(adGo, 200); ///新版 首先需要在body结束之前插入一行HTML代码: <div id="lastOne"></div> 使用这个代码的目的是为了找到页面的最后一行标识。这行代码以后出现的代码都会被jQury删除掉。 UC广告使用了滚动触发的,所以我们需要这个写: $(document).scroll(function () { $("#lastOne").nextAll().remove(); });
查看详情点赞1评论收藏浏览782023-03-30 13:54:54JS阻止用户重复点击(防抖&节流)
如图所示:我们在前端研发过程中,在表单提交或者用户其他点击行为过程中,为了避免用户重复点击,我们有必要在这些可点击地方加上防抖操作 。一方面阻止用户重复请求后端接口,另一方面也提高了用户的体验性。let clickNum = 0; // 表单提交 $('.submit_btn').on('click', function () { if (clickNum == 0) { clickNum = 1; setTimeout(function () { clickNum = 0 }, 3000); //这里写需要执行的函数 }else{ layer.msg('请勿频繁操作!'); } })
查看详情点赞1评论收藏浏览762023-03-30 14:02:56一些分享生活的文案
1.我们总以为生活欠我们一个“满意”,其实我们欠生活一个努力!2.性命中最值得欣慰的,莫过于一觉醒来,你发现太阳还在,你还活着,周围的一切依旧完美。3.愿你放下执着,放下不甘心,从今以后,只负责精彩自己的人生。往事不回头,未来不将就,你若盛开,清风自来;人生虽有终点,生命却是无涯,生活可以自然,生命却要认真。4.不要过于执着什么,终究你会发现很多你为之所动的东西,最后都辜负了你。最难的也是最重要的,并非是放下过去,而是学会重新开始。5.我们可以输在人生起跑点,但绝不能输在人生转折点。6.忙碌是幸福的,令我们没时间体会痛苦,奔波是快乐,使我们真实的感受生活,疲惫是享受,让我们无暇空虚,愿你的生活多姿多彩,永远开心!7.远方也好,附近也好,只要牵挂就好;平淡也好富贵也好,只要健康就好;电话也好,信息也好,经常记得骚扰就好!一条信息,愿你生活安好。8.无论是生活还是工作,如果你想得到对手的好感,或是希望他为你做事,最好的方法就是对他施以攻心术。给予他恩泽,让他百分百地信任你,这样他就会与你化干戈为玉帛,并忠心耿耿地跟着你。9.生活再不如人意,都要学会自我温暖和慰藉,给自己多一点欣赏和鼓励。我们的生存背景大多是冷色的,逼迫着我们在危机中奋进,在两难中抉择,在困惑中放弃。那些斑斑血泪与伤痕,部分是自我赋予的,本来活着就很难,何必在意那些身外的阻挠与非议?要懂得对自己好些,让自己的精神有一方暖色的栖息地。10.做一个简单的人,不为利益毁掉情谊,不因钱财坏了人品,对长辈尊重,对弱小爱护,实实在在,本本分分,上对得起天地,下对得起良心。做一个简单的人,心地善良,懂得感恩,用乐观的心态去生活,不抱怨不消极,爱惜自己的身体,注意自己的言行。11.人一生中会遇到不顺心的事,会碰到不顺眼的人,如果你不学会原谅,就会活得痛苦,活得累。原谅是一种风度,是一种情怀,它像一把伞,帮助你在雨季里行路。学会原谅,快乐至上。12.随缘,首先要知道世间一切都在因缘聚散无常变化中,爱恨顺逆荣辱皆不会长久,无可执持。苦乐齐受,悉从缘生,与其为结果大喜大悲,不如在前谨慎用心地取舍善恶。随缘是一方面尽心竭力,另一方面得失从缘。13.世无特立独行之蚁方方正正之沙。14.种自己的花,爱自己的宇宙。15.所有美好的事情都是值得等待的。 我是泰戈尔,与你一起,分享生活。
查看详情点赞1评论4收藏10644浏览1132023-03-30 20:59:06