群控系统服务端开发模式-应用开发-业务架构逻辑开发BaseAPI继续开发二

        我思来想去,最后还是觉得先封装一下thinkphp6整体报错机制。要不然后期不好拓展。

一、封装报错机制

        1、修改thinkphp6报错文件路径

                在根目录下app文件夹下的provider.php文件中,注释thinkphp6自带报错文件类,自定义报错文件配置,代码如下:

<?php
use app\ExceptionHandle;
use app\Request;// 容器Provider定义文件
return ['think\Request'          => Request::class,//'think\exception\Handle' => ExceptionHandle::class,'think\exception\Handle' => '\\Error\\ExecptionHandle'
];

        2、在根目录下extend文件夹中创建Error文件夹,然后创建ExecptionHandle.php报错文件类,代码如下:

<?php
/*** json报错机制* User: 龙哥·三年风水* Date: 2024/10/29* Time: 14:21*/
namespace Error;
use think\exception\Handle;
use Throwable;
use think\facade\Env;
use think\Response;
class ExecptionHandle extends Handle
{private $msg = "未知错误";private $httpCode = 500;private $errorCode = 50000;public function render($request, Throwable $e): Response{//判断在`.env`里面是否开始了调试,开启了调试就原样返回,关闭了调试就返回自定义的json格式的错误信息//因我开启了强制路由,所以不管调试模式是否开启,都不需要检测是否开启路由模式/*if(Env::get("APP_DEBUG") == true){return parent::render($request,$e);}*/$this->msg = $e->getMessage() ?: $this->msg;//HttpExceptions是继承同级目录下HttpExceptions,代码在下方if ($e instanceof BaseError) {$this->httpCode = $e->getStatusCode() ?: $this->httpCode;}$this->errorCode = $e->getCode() ?: $this->errorCode;$result['code'] = $this->errorCode;$result['message'] = $this->msg;$result['time'] = time();return json($result, $this->httpCode);// 其他错误交给系统处理return parent::render($request, $e);}
}

        3、在同级目录下接着创建对外报错暴露接口BaseError.php类,代码如下:

<?php
/*** 总报错机制* User: 龙哥·三年风水* Date: 2024/10/29* Time: 14:56*/
namespace Error;
use Exception;
class BaseError extends \RuntimeException
{private $statusCode;private $headers;//主要是重构$code前提,$previous和 $headers在后面方便调用public function __construct(string $message = '',int $code = 50000,  int $statusCode = 404, Exception $previous = null, array $headers = []){$this->statusCode = $statusCode;$this->headers    = $headers;parent::__construct($message, $code, $previous);}public function getStatusCode(){return $this->statusCode;}public function getHeaders(){return $this->headers;}
}

二、总控开发

        1、在跟目录下的app文件夹下的controller文件夹中,创建Base.php文件类,代码如下:

<?php
/*** 总控制* User: 龙哥 三年风水* Date: 2024/10/27/0027* Time: 22:16*/
namespace app\controller;
use app\BaseController;
use Encipher\Encrypt;
use app\model\common\Token;
use Error\BaseError;
class Base extends BaseController
{protected $userId = 0;//用户编号,整个系统内部使用protected $avatar = '';//登录用户的头像protected $username = '';//登录用户的登录名称protected $realname = '';//登录用户的真实名称protected $email = '';//登录用户邮箱protected $ip = '';//登录用户授权组protected $departmentId = 0;//登录用户部门编号protected $gradeId = 0;//登录用户级别编号protected $isUnserialize = true;//Redis里面有按钮权限protected $token = '';//当前用户唯一编码protected $roleId = '';//登录用户的权限编号protected $key = '';//登录用户权限组标识protected $butts = [];//操作权限,整个系统内部使用protected $rules = [];//登录用户的权限组,内部使用//初始化方法public function initialize(){parent::initialize(); // TODO: Change the autogenerated stub$this->isLoginAuth();//判断是否登录}//token验证private function isLoginAuth(){$headInfo = $this->request->header();if(!isset($headInfo['authorization']))throw new BaseError('非法操作!');if(empty($headInfo['authorization']))throw new BaseError('操作异常!');$tokenValue = explode('|', Encrypt::encryptRsa($headInfo['authorization']));//解密 --转换tokenif(count($tokenValue) != 2)throw new BaseError('登录认证权限错误',50034,200);$token = sha1(sha1($tokenValue[0]).strtotime($tokenValue[1]));$res = Token::setToken($token, $headInfo['authorization'], $headInfo['x-real-ip']);if($res['status'] === false)throw new BaseError($res['info'],50034,200);//赋值错误信息$this->userId = $res['data']['admin_id'];$this->avatar = $res['data']['avatar'];$this->username = $res['data']['username'];$this->realname = $res['data']['realname'];$this->email = $res['data']['email'];$this->ip = $res['data']['ip'];$this->departmentId = $res['data']['department_id'];$this->gradeId = $res['data']['grade_id'];$this->roleId = $res['data']['role_id'];$this->token = $token;}
}

三、登录退出开发

        1、在根目录下route文件夹中的app.php中添加路由地址。代码如下:

Route::get('login/get_code', 'common.Login/getCode');
Route::post('login/do_login', 'common.Login/doLogin');
Route::post('login/logout', 'common.Login/logout');

        2、在根目录下app文件夹下controller文件夹中创建common文件夹,然后在common文件夹中创建Login.php控制文件,代码如下:

                a、图片验证码获取

    //验证码展示public function getCode(){$re = app()->make(\Other\Captcha::class)->create();$base64 = 'data:image/png;base64,' . base64_encode($re->getData());return succ($base64);}

                b、登录

    //登录public function doLogin(){$param = $this->request->param();$validate = new \app\validate\common\Login;$result = $validate->check($param);//参数验证if (!$result) return err($validate->getError());//验证码的正确性if (!app()->make(\Other\Captcha::class)->check($param['captcha_code'])) return err('验证码错误');if (time() + 5 < strtotime($param['login_time'])) return err('非法登录');$resData = Admin::dataFind(['email' => trim($param['username'])], 'id,password,ip,status', true);//用户信息的正确性if (empty($resData) && empty($resData['id'])) return err('用户不存在');if ($resData['status'] !== 1) return err('该账号已被禁用');$systemParam = SystemModel::dataFind(['id' => 1],'security_password,platform_token_expira');if ($resData['password'] !== sha1($param['password'] . $systemParam['security_password'])) return err('账号对应的密码错误');if(!empty($resData['ip'])){if($resData['ip'] != $this->request->header('x-real-ip'))return err('禁止访问,不在IP白名单中');}//写入Token日志$data['token_type'] = 1;$data['menu_name'] = 'CommonLoginDoLogin';$data['admin_id'] = $resData['id'];$data['random_number'] = alnum();$data['create_time'] = date('Y-m-d',strtotime($param['login_time']));$data['login_time'] = $param['login_time'];$data['expire_time'] = strtotime($param['login_time']) + $systemParam['platform_token_expira'];$token = $data['admin_id'] . $data['random_number'];$data['token'] = sha1(sha1($token) . strtotime($data['login_time']));TokenModel::save($data,[]);//加入跨站攻击验证队列Redis::select(config('cache.stores.redis.token_db'))->setex('token_' . $data['token'],$systemParam['platform_token_expira'],$resData['id']);Redis::select(config('cache.stores.redis.token_db'))->setex('token_' . $resData['id'],$systemParam['platform_token_expira'],Encrypt::encryptRsa($data['token']));return succ('登录成功',Encrypt::encryptRsa($token));}

                c、退出

    //退出public function logout(){$info = $this->request->header();if(!isset($info['authorization']) || empty($info['authorization'])) return err('参数错误');$tokenn = Encrypt::decryptRsa($info['authorization']);$token = explode('|', $tokenn);$token = sha1(sha1($token[0]) . strtotime($token[1]));$redisToken = Redis::select(config('cache.stores.redis.token_db'))->get('token_' . $token);if(!empty($redisToken)){TokenModel::save(['expire_time' => time()], ['token' => $token]);Redis::select(config('cache.stores.redis.token_db'))->del('token_' . $redisToken);Redis::select(config('cache.stores.redis.token_db'))->del('token_' . $token);}return succ('退出成功');}

        3、验证码封装

               传统的验证码是采用session存储的哈,我这里封装成Redis存储的咯。

                a、安装官方提供的依赖

composer require topthink/think-captcha

                b、在根目录下extend文件夹中创建Other文件夹,然后创建Captcha.php控制文件,代码如下:

<?php
/*** 自定义验证码* User: 龙哥·三年风水* Date: 2024/10/29* Time: 15:56*/
namespace Other;
use Redis\Redis;
use think\Config;
use think\Response;
class Captcha
{private $im = null; // 验证码图片实例private $color = null; // 验证码字体颜色// 配置文件定义private $config = null;// 验证码字符集合protected $codeSet = '234567890abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY';// 验证码过期时间(s)protected $expire = 1800;// 使用中文验证码protected $useZh = false;// 中文验证码字符串protected $zhSet = '们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借';// 使用背景图片protected $useImgBg = false;// 验证码字体大小(px)protected $fontSize = 25;// 是否画混淆曲线protected $useCurve = true;// 是否添加杂点protected $useNoise = true;// 验证码图片高度protected $imageH = 0;// 验证码图片宽度protected $imageW = 0;// 验证码位数protected $length = 5;// 验证码字体,不设置随机获取protected $fontttf = '';// 背景颜色protected $bg = [243, 251, 254];//算术验证码protected $math = false;/*** 架构方法 设置参数* @ access public* @ param Config $config* @ param Session $session*/public function __construct(Config $config){$this->config = $config;}/*** 配置验证码* @ param string|null $config*/protected function configure(string $config = null): void{if (is_null($config)) {$config = $this->config->get('captcha', []);} else {$config = $this->config->get('captcha.' . $config, []);}foreach ($config as $key => $val) {if (property_exists($this, $key)) {$this->{$key} = $val;}}}/*** 创建验证码* @ return array* @ throws Exception*/protected function generate(): array{$bag = '';if ($this->math) {$this->useZh = false;$this->length = 5;$x = random_int(10, 30);$y = random_int(1, 9);$bag = "{$x} + {$y} = ";$key = $x + $y;$key .= '';} else {if ($this->useZh) {$characters = preg_split('/(?<!^)(?!$)/u', $this->zhSet);} else {$characters = str_split($this->codeSet);}for ($i = 0; $i < $this->length; $i++) {$bag .= $characters[rand(0, count($characters) - 1)];}$key = mb_strtolower($bag, 'UTF-8');}$hash = password_hash($key, PASSWORD_BCRYPT, ['cost' => 10]);$generator = ['value' => $bag,'key' => $hash,];Redis::select(config('cache.stores.redis.other_db'))->setex('captcha_'.$key,$this->expire,serialize($generator));return $generator;}/*** 验证验证码是否正确* @ access public* @ param string $code 用户验证码* @ return bool 用户验证码是否正确*/public function check(string $code): bool{$code = mb_strtolower(trim($code), 'UTF-8');$generator = unserialize(Redis::select(config('cache.stores.redis.other_db'))->get('captcha_'.$code));if($generator === false)return false;$key = $generator['key'] ?? '';$res = password_verify($code, $key);if($res)Redis::select(config('cache.stores.redis.other_db'))->del('captcha_'.$code);return $res;}/*** 输出验证码并把验证码的值保存的session中* @ access public* @ param null|string $config* @ param bool $api* @ return Response*/public function create(string $config = null, bool $api = false): Response{$this->configure($config);$generator = $this->generate();// 图片宽(px)$this->imageW || $this->imageW = $this->length * $this->fontSize * 1.5 + $this->length * $this->fontSize / 2;// 图片高(px)$this->imageH || $this->imageH = $this->fontSize * 2.5;// 建立一幅 $this->imageW x $this->imageH 的图像$this->im = imagecreate($this->imageW, $this->imageH);// 设置背景imagecolorallocate($this->im, $this->bg[0], $this->bg[1], $this->bg[2]);// 验证码字体随机颜色$this->color = imagecolorallocate($this->im, mt_rand(1, 150), mt_rand(1, 150), mt_rand(1, 150));// 验证码使用随机字体$ttfPath = dirname(dirname(app()->getThinkPath())) . '/think-captcha' . '/assets/' . ($this->useZh ? 'zhttfs' : 'ttfs') . '/';if (empty($this->fontttf)) {$dir = dir($ttfPath);$ttfs = [];while (false !== ($file = $dir->read())) {if ('.' != $file[0] && substr($file, -4) == '.ttf') {$ttfs[] = $file;}}$dir->close();$this->fontttf = $ttfs[array_rand($ttfs)];}$fontttf = $ttfPath . $this->fontttf;if ($this->useImgBg) {$this->background();}if ($this->useNoise) {// 绘杂点$this->writeNoise();}if ($this->useCurve) {// 绘干扰线$this->writeCurve();}// 绘验证码$text = $this->useZh ? preg_split('/(?<!^)(?!$)/u', $generator['value']) : str_split($generator['value']); // 验证码foreach ($text as $index => $char) {$x = $this->fontSize * ($index + 1) * mt_rand(1.2, 1.6) * ($this->math ? 1 : 1.5);$y = $this->fontSize + mt_rand(10, 20);$angle = $this->math ? 0 : mt_rand(-40, 40);imagettftext($this->im, $this->fontSize, $angle, $x, $y, $this->color, $fontttf, $char);}ob_start();// 输出图像imagepng($this->im);$content = ob_get_clean();imagedestroy($this->im);return response($content, 200, ['Content-Length' => strlen($content)])->contentType('image/png');}/*** 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)**      高中的数学公式咋都忘了涅,写出来*        正弦型函数解析式:y=Asin(ωx+φ)+b*      各常数值对函数图像的影响:*        A:决定峰值(即纵向拉伸压缩的倍数)*        b:表示波形在Y轴的位置关系或纵向移动距离(上加下减)*        φ:决定波形与X轴位置关系或横向移动距离(左加右减)*        ω:决定周期(最小正周期T=2π/∣ω∣)**/protected function writeCurve(): void{$px = $py = 0;// 曲线前部分$A = mt_rand(1, $this->imageH / 2); // 振幅$b = mt_rand(-$this->imageH / 4, $this->imageH / 4); // Y轴方向偏移量$f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量$T = mt_rand($this->imageH, $this->imageW * 2); // 周期$w = (2 * M_PI) / $T;$px1 = 0; // 曲线横坐标起始位置$px2 = mt_rand($this->imageW / 2, $this->imageW * 0.8); // 曲线横坐标结束位置for ($px = $px1; $px <= $px2; $px = $px + 1) {if (0 != $w) {$py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b$i = (int)($this->fontSize / 5);while ($i > 0) {imagesetpixel($this->im, $px + $i, $py + $i, $this->color); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出(不用这while循环)性能要好很多$i--;}}}// 曲线后部分$A = mt_rand(1, $this->imageH / 2); // 振幅$f = mt_rand(-$this->imageH / 4, $this->imageH / 4); // X轴方向偏移量$T = mt_rand($this->imageH, $this->imageW * 2); // 周期$w = (2 * M_PI) / $T;$b = $py - $A * sin($w * $px + $f) - $this->imageH / 2;$px1 = $px2;$px2 = $this->imageW;for ($px = $px1; $px <= $px2; $px = $px + 1) {if (0 != $w) {$py = $A * sin($w * $px + $f) + $b + $this->imageH / 2; // y = Asin(ωx+φ) + b$i = (int)($this->fontSize / 5);while ($i > 0) {imagesetpixel($this->im, $px + $i, $py + $i, $this->color);$i--;}}}}/*** 画杂点* 往图片上写不同颜色的字母或数字*/protected function writeNoise(): void{$codeSet = '2345678abcdefhijkmnpqrstuvwxyz';for ($i = 0; $i < 10; $i++) {//杂点颜色$noiseColor = imagecolorallocate($this->im, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225));for ($j = 0; $j < 5; $j++) {// 绘杂点imagestring($this->im, 5, mt_rand(-10, $this->imageW), mt_rand(-10, $this->imageH), $codeSet[mt_rand(0, 29)], $noiseColor);}}}/*** 绘制背景图片* 注:如果验证码输出图片比较大,将占用比较多的系统资源*/protected function background(): void{$path = dirname(dirname(app()->getThinkPath())) . DS . 'think-captcha' . DS . '/assets/bgs/';$dir = dir($path);$bgs = [];while (false !== ($file = $dir->read())) {if ('.' != $file[0] && substr($file, -4) == '.jpg') {$bgs[] = $path . $file;}}$dir->close();$gb = $bgs[array_rand($bgs)];list($width, $height) = @getimagesize($gb);// Resample$bgImage = @imagecreatefromjpeg($gb);@imagecopyresampled($this->im, $bgImage, 0, 0, 0, 0, $this->imageW, $this->imageH, $width, $height);@imagedestroy($bgImage);}
}

                c、修改根目录下config文件夹中的captcha.php文件,代码如下:

<?php
// +----------------------------------------------------------------------
// | Captcha配置文件
// +----------------------------------------------------------------------return [//验证码位数'length'   => 4,// 验证码字符集合'codeSet'  => '23456789',// 验证码过期时间'expire'   => 1800,// 是否使用中文验证码'useZh'    => false,// 是否使用算术验证码'math'     => false,// 是否使用背景图'useImgBg' => false,//验证码字符大小'fontSize' => 16,// 是否使用混淆曲线'useCurve' => true,//是否添加杂点'useNoise' => true,// 验证码字体 不设置则随机'fontttf'  => '',//背景颜色'bg'       => [243, 251, 254],// 验证码图片高度'imageH'   => 40,// 验证码图片宽度'imageW'   => 120,// 验证码图片透明度'alpha'    => 0,// 是否采用API模式生成'api'      => false,// 添加额外的验证码设置// verify => [//     'length'=>4,//    ...//],
];

四、修改数据操作Tools工具里面的错误返回

        详细代码请查看前一章节文章

                        《群控系统服务端开发模式-应用开发-业务架构逻辑开发数据操作Tools工具封装》

五、提前说明

        到此BaseAPI开发第一阶段已经结束,明天将对api业务逻辑总结及测试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/459940.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速遍历包含合并单元格的Word表格

Word中的合并表格如下&#xff0c;现在需要根据子类&#xff08;例如&#xff1a;果汁&#xff09;查找对应的品类&#xff0c;如果这是Excel表格&#xff0c;那么即使包含合并单元格&#xff0c;也很容易处理&#xff0c;但是使用Word VBA进行查找&#xff0c;就需要一些技巧。…

智慧园区 | 数智引领,让智慧触手可及

随着科技的飞速发展&#xff0c;智慧园区正成为现代城市发展的重要方向之一。在智慧园区中&#xff0c;各种高科技手段被应用于园区的管理和服务&#xff0c;为园区的运营和居民的生活带来无限可能。 智慧园区管理平台是智慧园区建设的核心。它集聚了大数据、物联网、云计算等技…

基于uniapp微信小程序的旅游系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【分布式知识】分布式对象存储组件-Minio

文章目录 什么是minio核心特点&#xff1a;使用场景&#xff1a;开发者工具&#xff1a;社区和支持&#xff1a; 核心概念什么是对象存储&#xff1f;MinIO 如何确定对对象的访问权限&#xff1f;我可以在存储桶内按文件夹结构组织对象吗&#xff1f;如何备份和恢复 MinIO 上的…

iQOO手机怎样将屏幕投射到MacBook?可以同步音频吗?

众所周知&#xff0c;苹果品牌的设备自己有AirPlay的投屏功能&#xff0c;iPhone要投屏到MacBook只要连接同一网络&#xff0c;然后开启AirPlay就可以投屏。但其他品牌的手机没有AirPlay&#xff0c;怎么将手机屏幕投射到MacBook呢&#xff1f; 安卓系统的手机可以使用无线投屏…

2. 从服务器的主接口入手

Webserver 的主函数 main.cpp&#xff0c;完成了哪些功能&#xff1f; #include "config.h"int main(int argc, char *argv[]) {string user "";string passwd "";string databasename "";Config config;config.parse_arg(argc, a…

四、Prompt工程——简单应用

Prompt工程——简单应用 一、提示工程&#xff08;Prompt Engineering&#xff09;二、Prompt基本法则三、Prompt 调优四、简单的例子文本总结文本判断文本提取文本转化——翻译文本转化——语气 更多结语 一、提示工程&#xff08;Prompt Engineering&#xff09; 提示工程也…

5G RedCap工业路由器赋能电力物联网应用

随着5G轻量化技术应用的推进&#xff0c;5G RedCap旨在提供低功耗、低成本、广覆盖等功能特点赋能电力智能化升级。特别适用于工业物联网、低空经济、车联网、消费电子和轻量级5G的需求。 5G RedCap工业路由器的特点 低功耗&#xff1a;5G RedCap工业路由器通过节能技术&#…

Flume采集Kafka数据到Hive

版本&#xff1a; Kafka&#xff1a;2.4.1 Flume&#xff1a;1.9.0 Hive&#xff1a;3.1.0 Kafka主题准备&#xff1a; Hive表准备&#xff1a;确保hive表为&#xff1a;分区分桶、orc存储、开启事务 Flume准备&#xff1a; 配置flume文件&#xff1a; /opt/datasophon/flume-1…

react18中react-thunk实现公共数据仓库的异步操作

redux及react-redux都只能实现数据的同步修改更新&#xff0c;有点类似于vue中的mutation&#xff0c;只能做同步操作&#xff0c;异步的话不用actions来实现。由于在项目始终不可避免要实现的异步数据的更新&#xff0c;这明显不够用了。是时候引入我们的异步中间件redux-thun…

开源一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码

大家好&#xff0c;我是一颗甜苞谷&#xff0c;今天分享一款前后端分离的企业级网站内容管理系统&#xff0c;支持站群管理、多平台静态化&#xff0c;多语言、全文检索的源码。 前言 在当今的数字化时代&#xff0c;企业网站和个人博客已成为信息传播和品牌建设的重要渠道。…

Docker-常用命令大全(附命令详解)

文章目录 Docker 基础命令查看docker 运行状态关闭docker启动docker重启dockerdocker设置随服务启动而自启动查看docker 版本号信息docker 帮助命令 docker 镜像命令查看自己服务器中docker 镜像列表搜索镜像拉取镜像运行镜像保存镜像删除镜像加载镜像镜像标签 Docker 容器命令…

【ComfyUI】手动安装部署ComfyUI的运行环境

如果不喜欢已有的一键启动包&#xff0c;我们可以手动的安装和部署ComfyUI的运行环境&#xff0c;相比一键安装包&#xff0c;自己部署ComfyUI 环境具有相当大的灵活性&#xff0c;其实部署ComfyUI 环境非常简单&#xff0c;不像网上说的那么复杂。下面我们就按照顺序给大家分享…

Golang | Leetcode Golang题解之第520题检测大写字母

题目&#xff1a; 题解&#xff1a; func detectCapitalUse(word string) bool {// 若第 1 个字母为小写&#xff0c;则需额外判断第 2 个字母是否为小写if len(word) > 2 && unicode.IsLower(rune(word[0])) && unicode.IsUpper(rune(word[1])) {return f…

【Cri-Dockerd】安装cri-dockerd

cri-dockerd的作用&#xff1a; 在k8s1.24之前。k8s会通过dockershim来调用docker进行容器运行时containerd&#xff0c;并且会自动安装dockershim&#xff0c;但是从1.24版本之前k8s为了降低容器运行时的调用的复杂度和效率&#xff0c;直接调用containerd了&#xff0c;并且…

git下载和配置

git是什么&#xff1f; Git是一种分布式版本控制系统&#xff0c;用于跟踪文件的变化&#xff0c;尤其是源代码。它允许多个开发者在同一项目上进行协作&#xff0c;同时保持代码的历史记录。Git的主要特点包括&#xff1a; 分布式&#xff1a;每个开发者都有项目的完整副本&a…

GPT避坑指南:如何辨别逆向、AZ、OpenAI官转

市面上有些说自己是官转&#xff0c;一刀只需要1块甚至几毛钱&#xff0c;并声称官方倍率的&#xff0c;很大可能就是使用的是 逆向或Azure。 如何鉴别逆向 逆向的种类很多&#xff0c;主要分为3类 逆向不知名A| 镜像站或偷的 key。成本约等于0&#xff0c;调用聊天数据可能在…

postgresql增量备份系列一

简介 在一些大容量得数据库应用中&#xff0c;采用全量备份得方式&#xff0c;会带来大量时间浪费和开销&#xff0c;此时定期的增量备份可以使得数据存储周期变长。本文讲解几个增量备份工具 pg_basebackup pg_receivewal&#xff08;异地归档模式&#xff09; 使用pg_bas…

arcgis pro 3.3.1安装教程

一、获取方式&#xff1a; http://dt4.8tupian.net/2/29913a61b1500.pg3二、软件目录&#xff1a; 三、安装步骤&#xff1a; &#xff08;1&#xff09;安装软件运行环境windowsdesktop-runtime 8.0.4; &#xff08;2&#xff09;选中安装文件arcgispro_33zh_cn_190127.exe&…

LabVIEW汽车状态监测系统

LabVIEW汽车状态监测系统通过模拟车辆运行状态&#xff0c;有效地辅助工程师进行故障预测和维护计划优化&#xff0c;从而提高汽车的可靠性和安全性。 项目背景&#xff1a; 现代汽车工业面临着日益增长的安全要求和客户对于车辆性能的高期望。汽车状态监测系统旨在实时监控汽…