技术分享
技术分享

js实现列表转成树的一个有意思的方法

js实现列表转成树的一个有意思的方法

原本以为只完成了一层树,发现这样就能生成整棵树,原因可能与内存中的数据结构有关,没有详细考证,就是感觉很神奇,核心代码其实只有两句

const list2Tree = (list = [])=>{
    if(!list.length){
        return []
    }
    list.forEach(el=>{
        if(list.filter(item => item.pid == el.menuId).length){
            el.children = list.filter(item => item.pid == el.menuId)
        }
    })
    return list.filter(el=>el.menuId == 1)
}

koa2框架获取所有接口列表并通过接口暴露

koa2框架获取所有接口列表并通过接口暴露

router.get('/routesList', async(ctx, next)=>{
//这是唯一需要手动修改的,将路由文件的关键字放到这个数组中,再动态拼接路由文件名,之所以这样处理,是因为这样可以更加灵活地控制返回哪些接口数据
  let routerList = ['menu', 'role', 'user']
  let data = []
  routerList.forEach(el => {
      let filePath = '../routes/' + el + '.route'
      let li = {
        catogory: el,
        list:[]
      }
      li.list.push(...require(filePath).stack.map(i => {
        return {
           methods: i.methods,
           url: i.path
            }   
       }))
       data.push(li)
  });
  ctx.body={
    ...Res[0],
    data:data
  }
})

这样,只要请求 /routesList,便可以得到所有接口的列表,按照路由文件进行了分类,这样便于前端展示,是一个简易版的swagger(只有列表,没有参数信息,没有调试,也没有导出),调试接口的话,完全可以通过apifox等工具实现,又好功能又完善

{
    "status": 0,
    "msg": "成功",
    "data": [
        {
            "catogory": "menu",
            "list": [
                {
                    "methods": [
                        "HEAD",
                        "GET"
                    ],
                    "url": "/menu/getAll"
                },
                {
                    "methods": [
                        "HEAD",
                        "GET"
                    ],
                    "url": "/menu/getMenuTree"
                }
            ]
        },
        {
            "catogory": "role",
            "list": [
                {
                    "methods": [
                        "HEAD",
                        "GET"
                    ],
                    "url": "/role/getAll"
                }
            ]
        }
    ]
}

Koa路由中写一个钩子函数,用于萤石云消息触发钉钉机器人webhook

Koa路由中写一个钩子函数,用于萤石云消息触发钉钉机器人webhook

//钉钉机器人的地址
let webhook = 'https://oapi.dingtalk.com/robot/send?access_token=4dd5cd7xxxxxxxxxxxxxxxxxxxxxxxxxxx'
let whiteList = ['xxxx'] //摄像头序列号白名单,只有在白名单里的才促发报警消息,用于过滤
//获取webhook消息并转发到钉钉机器人
async function sendToDingtalk  (ctx,next) {
    await next()
    ctx.request.body = JSON.parse(ctx.request.body)
    console.log('debugger',ctx.request.body.header)
    console.log('debugger',ctx.request.body)
    let {deviceId, messageTime, channelNo, type, messageId} = ctx.request.body.header
    let {channelName, alarmTime, pictureList } = ctx.request.body.body
    console.log('萤石云消息ID:',messageId)
    let data = null
    if(type=='ys.alarm' &&  whiteList.includes(deviceId) ){
        data =  {
        "msgtype": "markdown",
        "markdown": {
            "title": `【告警消息】${channelName}`, 
            "text": `### 设备名称:${channelName} \n #### 设备序列号:${deviceId} \n #### 通道:${channelNo} \n #### 消息类型:${type} \n #### 时间:${alarmTime} \n ![](${pictureList[0].url})`
            }
        }
    }else if(type=='ys.onoffline'){
        data =  {
        "msgtype": "markdown",
        "markdown": {
            "title": `【上下线消息】${channelName}`, 
            "text": `### 设备名称:${channelName} \n #### 设备序列号:${deviceId} \n #### 通道:${channelNo} \n #### 消息类型:${type} \n #### 时间:${alarmTime}`
            }
        }
    }
    // 判断消息类型,然后发送到钉钉webhook
    if(data != null){
        axios.post(webhook,
           data
        ).then(res=>{
            console.log('钉钉调用成功')
            console.log(res.data)
        }).catch(err=>{
            console.error(err)
        })
    }
    
    ctx.body={
        messageId
    }
}

阿里云ddns ipv6解析程序

阿里云ddns ipv6解析程序

由于网上很多资源没有更新,一些接口阿里云方面已经调整,所以,结合这次自己部署经验,记录如下:
程序没有新增,如果没有记录,请手动添加一条。

# -*- coding: utf-8 -*-
# This file is auto-generated, don't edit it. Thanks.
import sys

from typing import List
from Tea.core import TeaCore
from alibabacloud_alidns20150109.client import Client as Alidns20150109Client
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_alidns20150109 import models as alidns_20150109_models
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient
from urllib.request import urlopen

class Sample:
    def __init__(self):
        pass

    @staticmethod
    def create_client(
        access_key_id: str,
        access_key_secret: str,
    ) -> Alidns20150109Client:
        """
        使用AK&SK初始化账号Client
        @param access_key_id:
        @param access_key_secret:
        @return: Client
        @throws Exception
        """
        config = open_api_models.Config(
            # 必填,您的 AccessKey ID,
            access_key_id=access_key_id,
            # 必填,您的 AccessKey Secret,
            access_key_secret=access_key_secret
        )
        # 访问的域名
        config.endpoint = f'alidns.cn-hangzhou.aliyuncs.com'
        return Alidns20150109Client(config)

    @staticmethod
    def main(
        args: List[str],
    ) -> None:
        client = Sample.create_client('key', 'scret') #填写自己的key和密钥,在阿里云申请ram调试账号
        runtime = util_models.RuntimeOptions()
        try:
            ip = urlopen('https://api-ipv6.ip.sb/ip').read()  # 使用IP.SB的接口获取ipv6地址
            ipv6 = str(ip, encoding='utf-8')
            
                    #获取子域名的id信息
            describe_sub_domain_records_request = alidns_20150109_models.DescribeSubDomainRecordsRequest(
                    sub_domain='ipv6.zhangdong.site',
                    type='AAAA'
                ) 
            # 复制代码运行请自行打印 API 的返回值
            resp = client.describe_sub_domain_records_with_options(describe_sub_domain_records_request, runtime)
            # res = UtilClient.to_jsonstring(TeaCore.to_map(resp))
            res = TeaCore.to_map(resp)
            print(res['statusCode'])
            if res['body']['TotalCount'] == 0:
                print("未查到AAAA记录,请新增")
            else:
                Record = res['body']['DomainRecords']['Record'][0]
                if Record['Value'] == ipv6.strip() :
                    print('IPv6地址没变无需更改')
                else:
                     #更新域名信息
                    update_domain_record_request = alidns_20150109_models.UpdateDomainRecordRequest( 
                        rr='ipv6',
                        type='AAAA',
                        value= ipv6,
                        record_id=Record['RecordId'])
                    resp= client.update_domain_record_with_options(update_domain_record_request, runtime)
                    res2 = TeaCore.to_map(resp)
                    if res2['statusCode'] == 200:
                        print("修改域名解析成功")
                    else:
                        print(res2)
        except Exception as error:
            # 如有需要,请打印 error
            UtilClient.assert_as_string(error.message)


if __name__ == '__main__':
    Sample.main(sys.argv[1:])

接着添加一个定时任务即可

特色

webdav服务

webdav服务

使用webdav,可以将网络硬盘加载到本地,用起来非常方便。

webdav服务来自hacdias/webdav,使用go编译的,各端程序都有,用法就是准备一个配置文件,然后启动,如果长久使用,就加入系统服务。

添加服务步骤:

  1. 创建一个webdav.service文件

/etc/systemd/system/下创建webdav.service文件

  1. 编辑文件
[Unit]
Description=WebDAV server
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/webdav --config /xxx/webdav.config
Restart=on-failure

[Install]
WantedBy=multi-user.target
  1. 重新加载

sudo systemctl daemon-reload

  1. 设置开机启动

sudo systemctl enable webdav

附:如果windows加载不了可以使用webdav客户端RailDrive


传图片时出现了一个问题,排查了很长时间,总算解决了。

主要本人的部署还是有些麻烦,转了两道,出问题排查起来比较麻烦

“你没有权限来执行此操作”

原因分析:

一是服务器上面没有写权限,但是除了图片,其它文件都可以上传,因此排除

二是raidrive设置了不能同步文件,因为有的nas系统会有这些限制,排查了一下,raidrive没有这些设置

三是服务器域名监听上有问题,因为本人是通过nginx转发代理的后端服务,因此,这一步容易出现图片类的请求被提前解析了,可能导致失败。因此,本人将配置文件中关于图片的路由全部注释,发现上传图片已经正常了。

这样就可以了

windows docker wsl模式更改镜像存储位置

由于默认位置在C盘,嘎嘎的都下载到C盘,一不小心C盘只剩1MB,紧急扩容。然后再想办法修改docker默认存储位置,通过查找资料,将步骤记录如下:

1.停止docker引擎

2.进入cmd模式

  • 停止服务
wsl --list -v

image-20221213084711712

要确保两个状态都是stopped,上面就是有个还在running,就要查找到相关进程并停止掉。

  • 备份相关文件
    wsl --export docker-desktop-data "E:\\docker-desktop-data.tar"
    
  • wsl取消注册docker-desktop-data,这样C盘下的C:\Users\用户\AppData\Local\Docker\wsl \data\ext4.vhdx将会被自动删除
    wsl --unregister docker-desktop-data
    
  • 设置新的挂载路径,并导入data
    wsl --import docker-desktop-data "E:\\docker\\wsl" "E:\\docker-desktop-data.tar" --version 2
    

结束。

使用ollama软件实现本地gpt使用

  • 官网下载ollama软件并安装
  • 根据需要设置环境变量,尤其是代理,不然网速非常慢
环境变量

OLLAMA_MODELS F:\xxx 
存放模型目录,如果没有指定,就会默认放C盘,C盘空间大那就随意

OLLAMA_ORIGINS *
来源限制,设置为*表示可以任意源访问,没限制

OLLAMA_HOST 0.0.0.0
访问主机限制,如果想要网络上任意主机访问的话,就设置0.0.0.0

set HTTP_PROXY=http://127.0.0.1:xxxx

  • 运行 ollama run llama2:2b,首次将自动下载模型
  • 下载安装chatbox并添加ollama服务地址 127.0.0.1:11434

大工告成!体验GPT吧!

nginx添加网站密码访问

放在互联网上的应用没法避免的有乱七八糟的病毒或者恶意用户来攻击,每天每时每刻都有,为了减少不必要的骚扰,可以对代理网站做一个密码防护,主要是一些测试页面和一些不对外公开的应用,在宝塔应用中其实就包含密码访问的功能,但是有缺陷,经过反复测试,还是没法对代理网站做密码防护,即便是路径确定为/也不行。

后面尝试使用nginx的密码认证模块,发现很好用,使用也比较简单,作一记录,方便以后查阅。

  1. apt install apache2-utils
  2. htpassed -c /www/server/nginx/.htpasswd username 此处username为你自定义的用户名
  3. 连续两次输入密码后,会生成.htpasswd文件
  4. 在nginx配置文件中添加以下代码:
    location ^~ / {
      auth_basic "Restricted Content";
      auth_basic_user_file /www/server/nginx/.htpasswd;
      proxy_pass http://localhost:8080;#替换你要代理的地址
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  • 如果需要ws连接的代理网站,还需要添加如下字段:
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_cache_bypass $http_upgrade;

这样就大工告成了!打开网站后显示如下:

ubuntu安装xrdp时遇到的问题记录

手上有一台jstson orin的机器,装了ubuntu系统,因为之前别的机器上装过,没有遇到什么问题,没想到还是出了问题,特此记录!

安装:sudo apt-get install xrdp

在windows 上打开远程连接工具,发现连接不上,一点登陆就闪退,于是找问题

先是服务器上在设置里面打开屏幕共享和远程控制功能,然后还是不行,切换到home目录,有一个隐藏文件,.xsession-errors ,cat 命令打开,发现有错误,如下

网上一搜,说是sh命令在ubuntu上面默认是dash而不是bash,所以无法不兼容,卧槽塔猴,之前为啥没问题!

解决办法,要么就是修改脚本,但是这里没法改,只能将dash改为bash

方法: sudo dpkg -reconfigure dash

选择no即可

然后重启xrdp服务。systemctl restart xrdp

这下终于可以连上了,但是屏幕除了背景,啥也没有

这又是啥问题!

一搜原来是ubuntu 开启了3d桌面

这其实也没用,因为图中的帖子是2012年针对老版本的,新版本不适用,又找到一篇帖子,

这一次竟然解决了

成功出现了画面

特此记录

pip源的修改和使用-备忘

pip修改默认镜像源_pip恢复默认源_H.S.T不想卷的博客-CSDN博客

国内的几个源:

地址归属
http://mirrors.aliyun.com/pypi/simple/阿里云
http://pypi.douban.com/simple/豆瓣
http://pypi.mirrors.ustc.edu.cn/simple/中国科学技术大学
https://pypi.mirrors.ustc.edu.cn/simple/中国科技大学
https://pypi.tuna.tsinghua.edu.cn/simple/清华大学

永久修改

一种方案是修改配置文件,可以找到配置文件修改,也可以使用命令修改,配置文件windows系统在\User{本机用户名称}\AppData\Roaming\pip\pip.ini,修改命令参考:

pip config setglobal.index-url https://pypi.tuna.tsinghua.edu.cn/simple

临时使用:

pip install [模块] -i http://mirrors.aliyun.com/pypi/simple/

诺提示http连接不安全,还要加上一个参数

pip install [模块] -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com